Initial release of Maemo 5 port of gnuplot
[gnuplot] / docs / doc2tex.c
1 #ifndef lint
2 static char *RCSid() { return RCSid("$Id: doc2tex.c,v 1.21 2006/08/13 17:23:23 mikulik Exp $"); }
3 #endif
4
5 /* GNUPLOT - doc2tex.c */
6
7 /*[
8  * Copyright 1986 - 1993, 1998, 2004   Thomas Williams, Colin Kelley
9  *
10  * Permission to use, copy, and distribute this software and its
11  * documentation for any purpose with or without fee is hereby granted,
12  * provided that the above copyright notice appear in all copies and
13  * that both that copyright notice and this permission notice appear
14  * in supporting documentation.
15  *
16  * Permission to modify the software is granted, but not the right to
17  * distribute the complete modified source code.  Modifications are to
18  * be distributed as patches to the released version.  Permission to
19  * distribute binaries produced by compiling modified sources is granted,
20  * provided you
21  *   1. distribute the corresponding source modifications from the
22  *    released version in the form of a patch file along with the binaries,
23  *   2. add special version identification to distinguish your version
24  *    in addition to the base release version number,
25  *   3. provide your name and address as the primary contact for the
26  *    support of your modified version, and
27  *   4. retain our contact information in regard to use of the base
28  *    software.
29  * Permission to distribute the released version of the source code along
30  * with corresponding source modifications in the form of a patch file is
31  * granted with same provisions 2 through 4 for binary distributions.
32  *
33  * This software is provided "as is" without express or implied warranty
34  * to the extent permitted by applicable law.
35 ]*/
36
37 /*
38  * doc2tex.c  -- program to convert Gnuplot .DOC format to LaTeX document
39  * Also will work for VMS .HLP files.
40  * Modified by Russell Lang from hlp2ms.c by Thomas Williams
41  * Extended by David Kotz to support quotes ("), backquotes, tables.
42  * Extended by Jens Emmerich to handle '_', '---', paired single
43  * quotes. Changed "-handling. Added pre/post-verbatim hooks.
44  *
45  *
46  * usage:  doc2tex [file.doc [file.tex]]
47  *
48  *   where file.doc is a Gnuplot .DOC file, and file.tex will be an
49  *     article document suitable for printing with LaTeX.
50  *
51  * typical usage for GNUPLOT:
52  *
53  *   doc2tex gnuplot.doc gnuplot.tex
54  *   latex gnuplot.tex ; latex gnuplot.tex
55  */
56
57 #ifdef HAVE_CONFIG_H
58 # include "config.h"
59 #endif
60
61 #include "syscfg.h"
62 #include "stdfn.h"
63 #include "doc2x.h"
64
65 void init __PROTO((FILE *));
66 void convert __PROTO((FILE *, FILE *));
67 void process_line __PROTO((char *, FILE *));
68 void section __PROTO((char *, FILE *));
69 void puttex __PROTO((char *, FILE *));
70 void finish __PROTO((FILE *));
71
72 static TBOOLEAN intable = FALSE;
73 static TBOOLEAN verb = FALSE;
74 static TBOOLEAN see = FALSE;
75 static TBOOLEAN inhref = FALSE;
76
77 int
78 main (int argc, char **argv)
79 {
80     FILE *infile;
81     FILE *outfile;
82
83     infile = stdin;
84     outfile = stdout;
85
86     if (argc > 3) {
87         fprintf(stderr, "Usage: %s [infile [outfile]]\n", argv[0]);
88         exit(EXIT_FAILURE);
89     }
90     if (argc >= 2) {
91         if ((infile = fopen(argv[1], "r")) == (FILE *) NULL) {
92             fprintf(stderr, "%s: Can't open %s for reading\n",
93                     argv[0], argv[1]);
94             exit(EXIT_FAILURE);
95         }
96     }
97     if (argc == 3) {
98         if ((outfile = fopen(argv[2], "w")) == (FILE *) NULL) {
99             fprintf(stderr, "%s: Can't open %s for writing\n",
100                     argv[0], argv[2]);
101             exit(EXIT_FAILURE);
102         }
103     }
104     init(outfile);
105     convert(infile, outfile);
106     finish(outfile);
107     return EXIT_SUCCESS;
108 }
109
110
111 void
112 init(FILE *b)
113 {
114     (void) fputs("\\input{titlepag.tex}\n", b);
115 }
116
117
118 void
119 convert(FILE *a, FILE *b)
120 {
121     static char line[MAX_LINE_LEN+1];
122
123     while (get_line(line, sizeof(line), a))
124         process_line(line, b);
125
126 }
127
128 void
129 process_line( char *line, FILE *b)
130 {
131     char string[MAX_LINE_LEN+1], c;
132     int i, initlen;
133     char *ind;
134     static TBOOLEAN parsed = FALSE;
135
136     initlen = strlen(line);
137     switch (line[0]) {          /* control character */
138     case '?':                   /* interactive help entry */
139                                 /* convert '?xxx' to '\label{xxx}' */
140             line[strlen(line)-1]=NUL;
141             (void) fputs("\\label{",b);
142             fputs(line+1, b);
143             (void) fputs("}\n",b);
144             if (!strpbrk(line+1," ")) { /* Make an index entry also */
145                 (void) fputs("\\index{",b);
146                 while ((ind = strpbrk(line+1,"-_")))
147                     *ind = ' ';
148                 fputs(line+1, b);
149                 (void) fputs("}\n",b);
150             }
151             break;              /* ignore */ /* <- don't ignore */
152
153     case '=':                   /* explicit index entry */
154             line[strlen(line)-1]=NUL;
155             (void) fputs("\\index{",b);
156             while ((ind = strpbrk(line+1,"-_")))
157                 *ind = ' ';
158             fputs(line+1, b);
159             (void) fputs("}\n",b);
160             break;
161
162     case '@':{                  /* start/end table */
163             if (intable) {
164                 (void) fputs("\\hline\n\\end{tabular}\n", b);
165                 (void) fputs("\\end{center}\n", b);
166                 intable = FALSE;
167             } else {
168                 if (verb) {
169                     (void) fputs("\\end{verbatim}\n", b);
170                     (void) fputs("\\postverbatim\n", b);
171                     verb = FALSE;
172                 }
173                 (void) fputs("\n\\begin{center}\n", b);
174                 /* moved to gnuplot.doc by RCC
175                    (void) fputs("\\begin{tabular}{|ccl|} \\hline\n", b);
176                  */
177                 intable = TRUE;
178             }
179             /* ignore rest of line */
180             break;
181         }
182     case '#':{                  /* latex table entry */
183             if (intable)
184                 (void) fputs(line + 1, b);      /* copy directly */
185             else {
186                 fprintf(stderr, "warning: # line found outside of table\n");
187                 fprintf(stderr, "%s\n", line + 11);
188             }
189
190             break;
191         }
192     case '^':{                  /* external link escape */
193                                 /* internal link escape */
194              /* convert '^ <a href="xxx">yyy</a>' to '\href{xxx}{yyy}' */
195              /* convert '^ <a href="#xxx"></a> to '\ref{xxx}' */
196              /* convert '^ <a name="xxx"></a> to '\label{xxx}' */
197             switch (line[3]) {
198             case 'a':{
199                     switch (line[5]) {
200                     case 'h':{
201                             if (line[11] == '#') {
202                                 fputs("{\\bf ",b);
203                                 parsed = 0;
204                                 for (i = 12; (c = line[i]) != '"'; i++) {
205                                     string[i-12] = c;
206                                 }
207                                 string[i-12]= NUL;
208                                 i++;i++;
209                                 for ( ; i < initlen-5; i++) {
210                                      fputc(line[i],b);
211                                 }
212                                 fputs(" (p.~\\pageref{",b);
213                                 fputs(string,b);
214                                 fputs("})}} ",b);
215                                 inhref = FALSE;
216                             } else {
217                                 inhref = TRUE;
218                                 if (strstr(line,"</a>") == NULL){
219                                    fputs("\\par\\hskip2.7em\\href{",b);
220                                 } else {
221                                    fputs("\\href{",b);
222                                 }
223                                 parsed = 0;
224                                 for (i = 11; i < initlen-1 ; i++){
225                                     c = line[i];
226                                     if (c == '"') {
227                                          ;
228                                     } else if ( c == '>' && parsed == 0) {
229                                         fputs("}{\\tt ",b); parsed = 1;
230                                     } else if ( c == '~') {
231                                         fputs("\\~",b);
232                                     } else if ( c == '_' && parsed == 1) {
233                                         fputs("\\_",b);
234                                     } else if ( c == '<' && parsed == 1) {
235                                         fputs("}{\n",b);
236                                         i += 5;
237                                         inhref = FALSE;
238                                     } else {
239                                         fputc(c,b);
240                                     }
241                                 }
242                             }
243                             break;
244                     }
245                     case 'n': {
246                             fputs("\\label{",b);
247                             for (i = 11; (c = *(line +i)) != '"'; i++) {
248                                  fputc(c,b);
249                             }
250                             fputs("}\n",b);
251                             break;
252                        }
253                     default:
254                             break;
255                     }
256                     break;
257                }
258             case '/':
259                     if ( line[4] == 'a') {
260                         fputs("}\n\n",b);
261                         inhref = FALSE;
262                     }
263                     break;
264             default:
265                     break;              /* ignore */
266             }
267             break;
268         }
269     case '%':{                  /* troff table entry */
270             break;              /* ignore */
271         }
272     case '\n':                  /* empty text line */
273     case ' ':{                  /* normal text line */
274             if (intable)
275                 break;          /* ignore while in table */
276             if ( inhref == TRUE){
277                  puttex(line+1,b);
278                  break;
279             }
280             if (line[1] == ' ') {
281                 /* verbatim mode */
282                 if (!verb) {
283                     (void) fputs("\\preverbatim\n", b);
284                     (void) fputs("\\begin{verbatim}\n", b);
285                     verb = TRUE;
286                 }
287                 (void) fputs(line + 2, b);
288             } else {
289                 if (verb) {
290                     (void) fputs("\\end{verbatim}\n", b);
291                     (void) fputs("\\postverbatim\n", b);
292                     verb = FALSE;
293                 }
294                 if (line[0] == '\n')
295                     puttex(line, b);    /* handle totally blank line */
296                 else
297                     puttex(line + 1, b);
298             }
299             break;
300         }
301     default:{
302             if (isdigit((int) line[0])) {       /* start of section */
303                 if (!intable)   /* ignore while in table */
304                     section(line, b);
305             } else
306                 fprintf(stderr, "unknown control code '%c' in column 1\n",
307                         line[0]);
308             break;
309         }
310     }
311 }
312
313 /* process a line with a digit control char */
314 /* starts a new [sub]section */
315
316 void
317 section(char *line, FILE *b)
318 {
319     static char string[MAX_LINE_LEN+1];
320     int sh_i;
321
322     if (verb) {
323         (void) fputs("\\end{verbatim}\n", b);
324         (void) fputs("\\postverbatim\n", b);
325         verb = FALSE;
326     }
327     (void) sscanf(line, "%d %[^\n]s", &sh_i, string);
328     switch (sh_i) {
329     case 1:
330         (void) fprintf(b, "\\part{");
331         break;
332     case 2:
333         (void) fprintf(b, "\\section{");
334         break;
335     case 3:
336         (void) fprintf(b, "\\subsection{");
337         break;
338     case 4:
339         (void) fprintf(b, "\\subsubsection{");
340         break;
341     case 5:
342         (void) fprintf(b, "\\paragraph{");
343         break;
344     case 6:
345         (void) fprintf(b, "\\subparagraph{");
346         break;
347     default:
348         break;
349
350     }
351     if (islower((int) string[0]))
352         string[0] = toupper(string[0]);
353     puttex(string, b);
354     (void) fprintf(b, "}\n");
355 }
356
357 /* put text in string str to file while buffering special TeX characters */
358 void
359 puttex( char *str, FILE *file)
360 {
361     register char ch;
362     char string[MAX_LINE_LEN+1], c;
363     static TBOOLEAN inquote = FALSE;
364     int i;
365
366     while ((ch = *str++) != NUL) {
367         switch (ch) {
368         case '#':
369         case '$':
370         case '%':
371         case '&':
372         case '{':
373         case '}':
374             (void) fputc('\\', file);
375             (void) fputc(ch, file);
376             break;
377         case '\\':
378             (void) fputs("$\\backslash$", file);
379             break;
380         case '~':
381             (void) fputs("\\~{\\ }", file);
382             break;
383         case '^':
384             (void) fputs("\\verb+^+", file);
385             break;
386         case '>':
387         case '<':
388         case '|':
389             (void) fputc('$', file);
390             (void) fputc(ch, file);
391             (void) fputc('$', file);
392             break;
393         case '"':
394             (void) fputs("{\\tt\"}", file);
395             break;
396         case '\'':
397             if (*str == '\'') {
398                 (void) fputs("{'\\,'}", file);
399                 str++;
400             } else {
401                 (void) fputc(ch, file);
402             }
403             break;
404         case '-':
405             if ((*str == '-') && (*(str + 1) == '-')) {
406                 (void) fputs(" --- ", file);
407                 str += 2;
408             } else {
409                 (void) fputc(ch, file);
410             }
411             break;
412         case '`':    /* backquotes mean boldface */
413             if (inquote) {
414                 if (see){
415                     char *index = string;
416                     char *s;
417                     (void) fputs(" (p.~\\pageref{", file);
418                     (void) fputs(string, file);
419                     (void) fputs("})", file);
420 #ifndef NO_CROSSREFS
421                     /* Make the final word an index entry also */
422                     fputs("\\index{",file);
423 #if 0
424                     /* Aug 2006: no need to split index words at - or _ */
425                     if (strrchr(index,'-'))
426                         index = strrchr(index,'-')+1;
427                     if (strrchr(index,'_'))
428                         index = strrchr(index,'_')+1;
429 #endif
430                     if (strrchr(index,' '))
431                         index = strrchr(index,' ')+1;
432                     while ((s = strchr(index,'_')) != NULL) /* replace _ by space */
433                         *s = ' ';
434                     fputs(index,file);
435                     fputs("}",file);
436 #endif
437                     /* see = FALSE; */
438                 }
439                 (void) fputs("}", file);
440                 inquote = FALSE;
441             } else {
442                 (void) fputs("{\\bf ", file);
443                 for (i=0; i<MAX_LINE_LEN && ((c=str[i]) != '`') ; i++){
444                     string[i] = c;
445                 }
446                 string[i] = NUL;
447                 inquote = TRUE;
448             }
449             break;
450         case '_':               /* emphasised text ? */
451             for (i = 0; isalpha((int) (*(str + i))); i++);
452             if ((i > 0) && (*(str + i) == '_') &&
453                            isspace((int) (*(str + i + 1)))) {
454                 (void) fputs("{\\em ", file);
455                 for (; *str != '_'; str++) {
456                     (void) fputc(*str, file);
457                 }
458                 str++;
459                 (void) fputs("\\/}", file);
460             } else {
461                 (void) fputs("\\_", file);
462             }
463             break;
464         case 's':    /* find backquote after 'see' {see `} */
465         case 'S':
466             (void) fputc(ch, file);
467             if ( str[0] == 'e' && str[1] == 'e' && isspace(str[2])){
468                 see = TRUE;
469             }
470             break;
471         case ')':
472         case '.':
473             see = FALSE;
474         default:
475             (void) fputc(ch, file);
476             break;
477         }
478     }
479 }
480
481
482 void finish(FILE *b)
483 {
484     (void) fputs("\\part{Index}\n", b);
485     (void) fputs("\\printindex\n", b);
486     (void) fputs("\\end{document}\n", b);
487 }
488