1 #ifndef lint
RCSid()2 static char *RCSid() { return RCSid("$Id: doc2ms.c,v 1.21 2015/05/30 12:21:08 broeker Exp $"); }
3 #endif
4 
5 /* GNUPLOT - doc2ms.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  * doc2ms.c  -- program to convert Gnuplot .DOC format to *roff -ms document
39  * From hlp2ms by Thomas Williams
40  *
41  * Modified by Russell Lang, 2nd October 1989
42  * to make vms help level 1 and 2 create the same ms section level.
43  *
44  * Modified to become doc2ms by David Kotz (David.Kotz@Dartmouth.edu) 12/89
45  * Added table and backquote support.
46  *
47  * usage:  doc2ms [file.doc [file.ms]]
48  *
49  *   where file.doc is a VMS .DOC file, and file.ms will be a [nt]roff
50  *     document suitable for printing with nroff -ms or troff -ms
51  *
52  * typical usage for GNUPLOT:
53  *
54  *   doc2ms gnuplot.doc | tbl | eqn | troff -ms
55  *
56  * or
57  *
58  *   doc2ms gnuplot.doc | groff -ms -et >gnuplot.ps
59  */
60 
61 #ifdef HAVE_CONFIG_H
62 # include "config.h"
63 #endif
64 
65 #include "syscfg.h"
66 #include "stdfn.h"
67 #include "doc2x.h"
68 
69 #define LINE_SKIP		3
70 
71 void init __PROTO((FILE *, char *));
72 void convert __PROTO((FILE *, FILE *));
73 void process_line __PROTO((char *, FILE *));
74 void section __PROTO((char *, FILE *));
75 void putms __PROTO((char *, FILE *));
76 void putms_verb __PROTO((char *, FILE *));
77 void finish __PROTO((FILE *));
78 
79 static TBOOLEAN intable = FALSE;
80 
81 int
main(int argc,char ** argv)82 main (int argc, char **argv)
83 {
84     char *titlepage_filename = "titlepag.ms";
85     FILE *infile;
86     FILE *outfile;
87     infile = stdin;
88     outfile = stdout;
89 
90     if (argc > 4) {
91 	fprintf(stderr, "Usage: %s [infile [outfile [titlefile]]]\n", argv[0]);
92 	exit(EXIT_FAILURE);
93     }
94     if (argc >= 2) {
95 	if ((infile = fopen(argv[1], "r")) == (FILE *) NULL) {
96 	    fprintf(stderr, "%s: Can't open %s for reading\n",
97 		    argv[0], argv[1]);
98 	    exit(EXIT_FAILURE);
99 	}
100     }
101     if (argc >= 3) {
102 	if ((outfile = fopen(argv[2], "w")) == (FILE *) NULL) {
103 	    fprintf(stderr, "%s: Can't open %s for writing\n",
104 		    argv[0], argv[2]);
105 	    exit(EXIT_FAILURE);
106 	}
107     }
108     if (argc == 4) {
109 	FILE *check_titlepage;
110 	if (! (check_titlepage = fopen(argv[3], "r"))) {
111 	    fprintf(stderr, "%s: Can't open %s for reading\n",
112 		    argv[0], argv[3]);
113 	    exit(EXIT_FAILURE);
114 	}
115 	titlepage_filename = argv[3];
116 	fclose(check_titlepage);
117     }
118     init(outfile, titlepage_filename);
119     convert(infile, outfile);
120     finish(outfile);
121     return EXIT_SUCCESS;
122 }
123 
124 
125 void
init(FILE * b,char * t)126 init(FILE *b, char *t)
127 {
128     /* in nroff, increase line length by 8 and don't adjust lines */
129     (void) fprintf(b, "\
130 .if n \\{.nr LL +8m\n.na \\}\n\
131 .nr PO +0.3i\n\
132 .so %s\n\
133 .pn 1\n\
134 .bp\n\
135 .ta 1.5i 3.0i 4.5i 6.0i 7.5i\n\
136 \\&\n.sp 3\n.PP\n", t);
137 
138     /* following line commented out by rjl
139        (void) fputs(".so intro\n",b);
140      */
141 }
142 
143 
144 void
convert(FILE * a,FILE * b)145 convert( FILE *a, FILE *b)
146 {
147     static char line[MAX_LINE_LEN+1];
148 
149     while (get_line(line, sizeof(line), a)) {
150 	process_line(line, b);
151     }
152 }
153 
154 void
process_line(char * line,FILE * b)155 process_line( char *line, FILE *b)
156 {
157     switch (line[0]) {		/* control character */
158     case '?':{			/* interactive help entry */
159 	    break;		/* ignore */
160 	}
161     case '@':{			/* start/end table */
162 	    if (intable) {
163 		(void) fputs(".TE\n.KE\n", b);
164 		(void) fputs(".EQ\ndelim off\n.EN\n\n", b);
165 		intable = FALSE;
166 	    } else {
167 		(void) fputs("\n.EQ\ndelim $$\n.EN\n", b);
168 		(void) fputs(".KS\n.TS\ncenter box tab (@) ;\n", b);
169 		/* moved to gnuplot.doc by RCC
170 		   (void) fputs("c c l .\n", b);
171 		 */
172 		intable = TRUE;
173 	    }
174 	    /* ignore rest of line */
175 	    break;
176 	}
177     case '^':{			/* html table entry */
178 	    break;		/* ignore */
179 	}
180     case '=':			/* latex index entry */
181     case 'F':			/* latex embedded figure */
182     case '#':{			/* latex table entry */
183 	    break;		/* ignore */
184 	}
185     case '%':{			/* troff table entry */
186 	    if (intable)
187 		(void) fputs(line + 1, b);	/* copy directly */
188 	    else
189 		fprintf(stderr, "error: %% line found outside of table\n");
190 	    break;
191 	}
192     case '\n':			/* empty text line */
193     case ' ':{			/* normal text line */
194 	    if (intable)
195 		break;		/* ignore while in table */
196 	    switch (line[1]) {
197 	    case ' ':{
198 		    /* verbatim mode */
199 		    fputs(".br\n", b);
200 		    putms_verb(line + 1, b);
201 		    fputs(".br\n", b);
202 		    break;
203 		}
204 	    case '\'':{
205 		    fputs("\\&", b);
206 		    putms(line + 1, b);
207 		    break;
208 		}
209 	    case '.':{		/* hide leading . from ms */
210 		    fputs("\\&", b);
211 		    putms(line + 1, b);
212 		    break;
213 		}
214 	    default:{
215 		    if (line[0] == '\n')
216 			putms(line, b);		/* handle totally blank line */
217 		    else
218 			putms(line + 1, b);
219 		    break;
220 		}
221 		break;
222 	    }
223 	    break;
224 	}
225     default:{
226 	    if (isdigit((int)line[0])) {	/* start of section */
227 		if (!intable)	/* ignore while in table */
228 		    section(line, b);
229 	    } else
230 		fprintf(stderr, "unknown control code '%c' in column 1\n",
231 			line[0]);
232 	    break;
233 	}
234     }
235 }
236 
237 
238 /* process a line with a digit control char */
239 /* starts a new [sub]section */
240 
241 void
section(char * line,FILE * b)242 section( char *line, FILE *b)
243 {
244     static char string[MAX_LINE_LEN+1];
245     int sh_i;
246     static int old = 1;
247 
248 
249     (void) sscanf(line, "%d %[^\n]s", &sh_i, string);
250 
251     (void) fprintf(b, ".sp %d\n", (sh_i == 1) ? LINE_SKIP : LINE_SKIP - 1);
252 
253     if (sh_i > old) {
254 	do
255 	    if (old != 1)	/* this line added by rjl */
256 		(void) fputs(".RS\n.IP\n", b);
257 	while (++old < sh_i);
258     } else if (sh_i < old) {
259 	do
260 	    if (sh_i != 1)	/* this line added by rjl */
261 		(void) fputs(".RE\n.br\n", b);
262 	while (--old > sh_i);
263     }
264     /* added by dfk to capitalize section headers */
265     if (islower((unsigned char)string[0]))
266 	string[0] = toupper((unsigned char)string[0]);
267 
268     /* next 3 lines added by rjl */
269     if (sh_i != 1)
270 	(void) fprintf(b, ".NH %d\n%s\n.sp 1\n.LP\n", sh_i - 1, string);
271     else
272 	(void) fprintf(b, ".NH %d\n%s\n.sp 1\n.LP\n", sh_i, string);
273     old = sh_i;
274 
275     (void) fputs(".XS\n", b);
276     (void) fputs(string, b);
277     (void) fputs("\n.XE\n", b);
278 }
279 
280 void
putms(char * s,FILE * file)281 putms( char *s, FILE *file)
282 {
283     static TBOOLEAN inquote = FALSE;
284 
285     while (*s != NUL) {
286 	switch (*s) {
287 	case '`':{		/* backquote -> boldface */
288 		if (inquote) {
289 		    fputs("\\fR", file);
290 		    inquote = FALSE;
291 		} else {
292 		    fputs("\\fB", file);
293 		    inquote = TRUE;
294 		}
295 		break;
296 	    }
297 	case '\\':{		/* backslash */
298 		fputs("\\\\", file);
299 		break;
300 	    }
301 	case '\'':{		/* single quote */
302 		fputs("\\&'", file);
303 		break;
304 	    }
305 	default:{
306 		fputc(*s, file);
307 		break;
308 	    }
309 	}
310 	s++;
311     }
312 }
313 
314 /*
315  * convert a verbatim line to troff input style, i.e. convert "\" to "\\"
316  * (added by Alexander Lehmann 01/30/93)
317  */
318 
319 void
putms_verb(char * s,FILE * file)320 putms_verb( char *s, FILE *file)
321 {
322     while (*s != '\0') {
323 	if (*s == '\\') {
324 	    fputc('\\', file);
325 	}
326 	fputc(*s, file);
327 	s++;
328     }
329 }
330 
331 /* spit out table of contents */
332 void
finish(FILE * b)333 finish(FILE *b)
334 {
335     fputs("\
336 .pn 1\n\
337 .ds RH %\n\
338 .af % i\n\
339 .bp\n.PX\n", b);
340 }
341