deroff.c revision 1.1 1 1.1 perry /* $NetBSD: deroff.c,v 1.1 2005/06/29 20:58:50 perry Exp $ */
2 1.1 perry
3 1.1 perry /* taken from: OpenBSD: deroff.c,v 1.6 2004/06/02 14:58:46 tom Exp */
4 1.1 perry
5 1.1 perry /*-
6 1.1 perry * Copyright (c) 1988, 1993
7 1.1 perry * The Regents of the University of California. All rights reserved.
8 1.1 perry *
9 1.1 perry * Redistribution and use in source and binary forms, with or without
10 1.1 perry * modification, are permitted provided that the following conditions
11 1.1 perry * are met:
12 1.1 perry * 1. Redistributions of source code must retain the above copyright
13 1.1 perry * notice, this list of conditions and the following disclaimer.
14 1.1 perry * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 perry * notice, this list of conditions and the following disclaimer in the
16 1.1 perry * documentation and/or other materials provided with the distribution.
17 1.1 perry * 3. Neither the name of the University nor the names of its contributors
18 1.1 perry * may be used to endorse or promote products derived from this software
19 1.1 perry * without specific prior written permission.
20 1.1 perry *
21 1.1 perry * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1 perry * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1 perry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1 perry * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1 perry * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1 perry * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1 perry * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1 perry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1 perry * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1 perry * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1 perry * SUCH DAMAGE.
32 1.1 perry */
33 1.1 perry /*
34 1.1 perry * Copyright (C) Caldera International Inc. 2001-2002.
35 1.1 perry * All rights reserved.
36 1.1 perry *
37 1.1 perry * Redistribution and use in source and binary forms, with or without
38 1.1 perry * modification, are permitted provided that the following conditions
39 1.1 perry * are met:
40 1.1 perry * 1. Redistributions of source code and documentation must retain the above
41 1.1 perry * copyright notice, this list of conditions and the following disclaimer.
42 1.1 perry * 2. Redistributions in binary form must reproduce the above copyright
43 1.1 perry * notice, this list of conditions and the following disclaimer in the
44 1.1 perry * documentation and/or other materials provided with the distribution.
45 1.1 perry * 3. All advertising materials mentioning features or use of this software
46 1.1 perry * must display the following acknowledgement:
47 1.1 perry * This product includes software developed or owned by Caldera
48 1.1 perry * International, Inc.
49 1.1 perry * 4. Neither the name of Caldera International, Inc. nor the names of other
50 1.1 perry * contributors may be used to endorse or promote products derived from
51 1.1 perry * this software without specific prior written permission.
52 1.1 perry *
53 1.1 perry * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
54 1.1 perry * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
55 1.1 perry * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56 1.1 perry * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57 1.1 perry * IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
58 1.1 perry * INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
59 1.1 perry * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
60 1.1 perry * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 1.1 perry * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62 1.1 perry * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
63 1.1 perry * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 1.1 perry * POSSIBILITY OF SUCH DAMAGE.
65 1.1 perry */
66 1.1 perry
67 1.1 perry #ifndef lint
68 1.1 perry static const char copyright[] =
69 1.1 perry "@(#) Copyright (c) 1988, 1993\n\
70 1.1 perry The Regents of the University of California. All rights reserved.\n";
71 1.1 perry #endif /* not lint */
72 1.1 perry
73 1.1 perry #ifndef lint
74 1.1 perry #if 0
75 1.1 perry static const char sccsid[] = "@(#)deroff.c 8.1 (Berkeley) 6/6/93";
76 1.1 perry #else
77 1.1 perry static const char rcsid[] = "$NetBSD: deroff.c,v 1.1 2005/06/29 20:58:50 perry Exp $";
78 1.1 perry #endif
79 1.1 perry #endif /* not lint */
80 1.1 perry
81 1.1 perry #include <err.h>
82 1.1 perry #include <limits.h>
83 1.1 perry #include <stdio.h>
84 1.1 perry #include <stdlib.h>
85 1.1 perry #include <string.h>
86 1.1 perry #include <unistd.h>
87 1.1 perry
88 1.1 perry /*
89 1.1 perry * Deroff command -- strip troff, eqn, and Tbl sequences from
90 1.1 perry * a file. Has two flags argument, -w, to cause output one word per line
91 1.1 perry * rather than in the original format.
92 1.1 perry * -mm (or -ms) causes the corresponding macro's to be interpreted
93 1.1 perry * so that just sentences are output
94 1.1 perry * -ml also gets rid of lists.
95 1.1 perry * Deroff follows .so and .nx commands, removes contents of macro
96 1.1 perry * definitions, equations (both .EQ ... .EN and $...$),
97 1.1 perry * Tbl command sequences, and Troff backslash constructions.
98 1.1 perry *
99 1.1 perry * All input is through the Cget macro;
100 1.1 perry * the most recently read character is in c.
101 1.1 perry *
102 1.1 perry * Modified by Robert Henry to process -me and -man macros.
103 1.1 perry */
104 1.1 perry
105 1.1 perry #define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
106 1.1 perry #define C1get ( (c=getc(infile)) == EOF ? eof() : c)
107 1.1 perry
108 1.1 perry #ifdef DEBUG
109 1.1 perry # define C _C()
110 1.1 perry # define C1 _C1()
111 1.1 perry #else /* not DEBUG */
112 1.1 perry # define C Cget
113 1.1 perry # define C1 C1get
114 1.1 perry #endif /* not DEBUG */
115 1.1 perry
116 1.1 perry #define SKIP while (C != '\n')
117 1.1 perry #define SKIP_TO_COM SKIP; SKIP; pc=c; while (C != '.' || pc != '\n' || C > 'Z')pc=c
118 1.1 perry
119 1.1 perry #define YES 1
120 1.1 perry #define NO 0
121 1.1 perry #define MS 0 /* -ms */
122 1.1 perry #define MM 1 /* -mm */
123 1.1 perry #define ME 2 /* -me */
124 1.1 perry #define MA 3 /* -man */
125 1.1 perry
126 1.1 perry #ifdef DEBUG
127 1.1 perry char *mactab[] = { "-ms", "-mm", "-me", "-ma" };
128 1.1 perry #endif /* DEBUG */
129 1.1 perry
130 1.1 perry #define ONE 1
131 1.1 perry #define TWO 2
132 1.1 perry
133 1.1 perry #define NOCHAR -2
134 1.1 perry #define SPECIAL 0
135 1.1 perry #define APOS 1
136 1.1 perry #define PUNCT 2
137 1.1 perry #define DIGIT 3
138 1.1 perry #define LETTER 4
139 1.1 perry
140 1.1 perry #define MAXFILES 20
141 1.1 perry
142 1.1 perry int iflag;
143 1.1 perry int wordflag;
144 1.1 perry int msflag; /* processing a source written using a mac package */
145 1.1 perry int mac; /* which package */
146 1.1 perry int disp;
147 1.1 perry int parag;
148 1.1 perry int inmacro;
149 1.1 perry int intable;
150 1.1 perry int keepblock; /* keep blocks of text; normally false when msflag */
151 1.1 perry
152 1.1 perry char chars[128]; /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
153 1.1 perry
154 1.1 perry char line[LINE_MAX];
155 1.1 perry char *lp;
156 1.1 perry
157 1.1 perry int c;
158 1.1 perry int pc;
159 1.1 perry int ldelim;
160 1.1 perry int rdelim;
161 1.1 perry
162 1.1 perry char fname[PATH_MAX];
163 1.1 perry FILE *files[MAXFILES];
164 1.1 perry FILE **filesp;
165 1.1 perry FILE *infile;
166 1.1 perry
167 1.1 perry int argc;
168 1.1 perry char **argv;
169 1.1 perry
170 1.1 perry /*
171 1.1 perry * Macro processing
172 1.1 perry *
173 1.1 perry * Macro table definitions
174 1.1 perry */
175 1.1 perry typedef int pacmac; /* compressed macro name */
176 1.1 perry int argconcat = 0; /* concat arguments together (-me only) */
177 1.1 perry
178 1.1 perry #define tomac(c1, c2) ((((c1) & 0xFF) << 8) | ((c2) & 0xFF))
179 1.1 perry #define frommac(src, c1, c2) (((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF))
180 1.1 perry
181 1.1 perry struct mactab{
182 1.1 perry int condition;
183 1.1 perry pacmac macname;
184 1.1 perry int (*func)(); /* XXX - args */
185 1.1 perry };
186 1.1 perry
187 1.1 perry struct mactab troffmactab[];
188 1.1 perry struct mactab ppmactab[];
189 1.1 perry struct mactab msmactab[];
190 1.1 perry struct mactab mmmactab[];
191 1.1 perry struct mactab memactab[];
192 1.1 perry struct mactab manmactab[];
193 1.1 perry
194 1.1 perry /*
195 1.1 perry * Macro table initialization
196 1.1 perry */
197 1.1 perry #define M(cond, c1, c2, func) {cond, tomac(c1, c2), func}
198 1.1 perry
199 1.1 perry /*
200 1.1 perry * Flags for matching conditions other than
201 1.1 perry * the macro name
202 1.1 perry */
203 1.1 perry #define NONE 0
204 1.1 perry #define FNEST 1 /* no nested files */
205 1.1 perry #define NOMAC 2 /* no macro */
206 1.1 perry #define MAC 3 /* macro */
207 1.1 perry #define PARAG 4 /* in a paragraph */
208 1.1 perry #define MSF 5 /* msflag is on */
209 1.1 perry #define NBLK 6 /* set if no blocks to be kept */
210 1.1 perry
211 1.1 perry /*
212 1.1 perry * Return codes from macro minions, determine where to jump,
213 1.1 perry * how to repeat/reprocess text
214 1.1 perry */
215 1.1 perry #define COMX 1 /* goto comx */
216 1.1 perry #define COM 2 /* goto com */
217 1.1 perry
218 1.1 perry int skeqn(void);
219 1.1 perry int eof(void);
220 1.1 perry int _C1(void);
221 1.1 perry int _C(void);
222 1.1 perry int EQ(void);
223 1.1 perry int domacro(void);
224 1.1 perry int PS(void);
225 1.1 perry int skip(void);
226 1.1 perry int intbl(void);
227 1.1 perry int outtbl(void);
228 1.1 perry int so(void);
229 1.1 perry int nx(void);
230 1.1 perry int skiptocom(void);
231 1.1 perry int PP(pacmac);
232 1.1 perry int AU(void);
233 1.1 perry int SH(pacmac);
234 1.1 perry int UX(void);
235 1.1 perry int MMHU(pacmac);
236 1.1 perry int mesnblock(pacmac);
237 1.1 perry int mssnblock(pacmac);
238 1.1 perry int nf(void);
239 1.1 perry int ce(void);
240 1.1 perry int meip(pacmac);
241 1.1 perry int mepp(pacmac);
242 1.1 perry int mesh(pacmac);
243 1.1 perry int mefont(pacmac);
244 1.1 perry int manfont(pacmac);
245 1.1 perry int manpp(pacmac);
246 1.1 perry int macsort(const void *, const void *);
247 1.1 perry int sizetab(struct mactab *);
248 1.1 perry void getfname(void);
249 1.1 perry void textline(char *, int);
250 1.1 perry void work(void);
251 1.1 perry void regline(void (*)(char *, int), int);
252 1.1 perry void macro(void);
253 1.1 perry void tbl(void);
254 1.1 perry void stbl(void);
255 1.1 perry void eqn(void);
256 1.1 perry void backsl(void);
257 1.1 perry void sce(void);
258 1.1 perry void refer(int);
259 1.1 perry void inpic(void);
260 1.1 perry void msputmac(char *, int);
261 1.1 perry void msputwords(int);
262 1.1 perry void meputmac(char *, int);
263 1.1 perry void meputwords(int);
264 1.1 perry void noblock(char, char);
265 1.1 perry void defcomline(pacmac);
266 1.1 perry void comline(void);
267 1.1 perry void buildtab(struct mactab **, int *);
268 1.1 perry FILE *opn(char *);
269 1.1 perry struct mactab *macfill(struct mactab *, struct mactab *);
270 1.1 perry __dead void usage(void);
271 1.1 perry
272 1.1 perry int
273 1.1 perry main(int ac, char **av)
274 1.1 perry {
275 1.1 perry int i, ch;
276 1.1 perry int errflg = 0;
277 1.1 perry int kflag = NO;
278 1.1 perry
279 1.1 perry iflag = NO;
280 1.1 perry wordflag = NO;
281 1.1 perry msflag = NO;
282 1.1 perry mac = ME;
283 1.1 perry disp = NO;
284 1.1 perry parag = NO;
285 1.1 perry inmacro = NO;
286 1.1 perry intable = NO;
287 1.1 perry ldelim = NOCHAR;
288 1.1 perry rdelim = NOCHAR;
289 1.1 perry keepblock = YES;
290 1.1 perry
291 1.1 perry while ((ch = getopt(ac, av, "ikpwm:")) != -1) {
292 1.1 perry switch (ch) {
293 1.1 perry case 'i':
294 1.1 perry iflag = YES;
295 1.1 perry break;
296 1.1 perry case 'k':
297 1.1 perry kflag = YES;
298 1.1 perry break;
299 1.1 perry case 'm':
300 1.1 perry msflag = YES;
301 1.1 perry keepblock = NO;
302 1.1 perry switch (optarg[0]) {
303 1.1 perry case 'm':
304 1.1 perry mac = MM;
305 1.1 perry break;
306 1.1 perry case 's':
307 1.1 perry mac = MS;
308 1.1 perry break;
309 1.1 perry case 'e':
310 1.1 perry mac = ME;
311 1.1 perry break;
312 1.1 perry case 'a':
313 1.1 perry mac = MA;
314 1.1 perry break;
315 1.1 perry case 'l':
316 1.1 perry disp = YES;
317 1.1 perry break;
318 1.1 perry default:
319 1.1 perry errflg++;
320 1.1 perry break;
321 1.1 perry }
322 1.1 perry if (errflg == 0 && optarg[1] != '\0')
323 1.1 perry errflg++;
324 1.1 perry break;
325 1.1 perry case 'p':
326 1.1 perry parag = YES;
327 1.1 perry break;
328 1.1 perry case 'w':
329 1.1 perry wordflag = YES;
330 1.1 perry kflag = YES;
331 1.1 perry break;
332 1.1 perry default:
333 1.1 perry errflg++;
334 1.1 perry }
335 1.1 perry }
336 1.1 perry argc = ac - optind;
337 1.1 perry argv = av + optind;
338 1.1 perry
339 1.1 perry if (kflag)
340 1.1 perry keepblock = YES;
341 1.1 perry if (errflg)
342 1.1 perry usage();
343 1.1 perry
344 1.1 perry #ifdef DEBUG
345 1.1 perry printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n",
346 1.1 perry msflag, mactab[mac], keepblock, disp);
347 1.1 perry #endif /* DEBUG */
348 1.1 perry if (argc == 0) {
349 1.1 perry infile = stdin;
350 1.1 perry } else {
351 1.1 perry infile = opn(argv[0]);
352 1.1 perry --argc;
353 1.1 perry ++argv;
354 1.1 perry }
355 1.1 perry files[0] = infile;
356 1.1 perry filesp = &files[0];
357 1.1 perry
358 1.1 perry for (i = 'a'; i <= 'z' ; ++i)
359 1.1 perry chars[i] = LETTER;
360 1.1 perry for (i = 'A'; i <= 'Z'; ++i)
361 1.1 perry chars[i] = LETTER;
362 1.1 perry for (i = '0'; i <= '9'; ++i)
363 1.1 perry chars[i] = DIGIT;
364 1.1 perry chars['\''] = APOS;
365 1.1 perry chars['&'] = APOS;
366 1.1 perry chars['.'] = PUNCT;
367 1.1 perry chars[','] = PUNCT;
368 1.1 perry chars[';'] = PUNCT;
369 1.1 perry chars['?'] = PUNCT;
370 1.1 perry chars[':'] = PUNCT;
371 1.1 perry work();
372 1.1 perry exit(0);
373 1.1 perry }
374 1.1 perry
375 1.1 perry int
376 1.1 perry skeqn(void)
377 1.1 perry {
378 1.1 perry
379 1.1 perry while ((c = getc(infile)) != rdelim) {
380 1.1 perry if (c == EOF)
381 1.1 perry c = eof();
382 1.1 perry else if (c == '"') {
383 1.1 perry while ((c = getc(infile)) != '"') {
384 1.1 perry if (c == EOF ||
385 1.1 perry (c == '\\' && (c = getc(infile)) == EOF))
386 1.1 perry c = eof();
387 1.1 perry }
388 1.1 perry }
389 1.1 perry }
390 1.1 perry if (msflag)
391 1.1 perry return((c = 'x'));
392 1.1 perry return((c = ' '));
393 1.1 perry }
394 1.1 perry
395 1.1 perry FILE *
396 1.1 perry opn(char *p)
397 1.1 perry {
398 1.1 perry FILE *fd;
399 1.1 perry
400 1.1 perry if ((fd = fopen(p, "r")) == NULL)
401 1.1 perry err(1, "fopen %s", p);
402 1.1 perry
403 1.1 perry return(fd);
404 1.1 perry }
405 1.1 perry
406 1.1 perry int
407 1.1 perry eof(void)
408 1.1 perry {
409 1.1 perry
410 1.1 perry if (infile != stdin)
411 1.1 perry fclose(infile);
412 1.1 perry if (filesp > files)
413 1.1 perry infile = *--filesp;
414 1.1 perry else if (argc > 0) {
415 1.1 perry infile = opn(argv[0]);
416 1.1 perry --argc;
417 1.1 perry ++argv;
418 1.1 perry } else
419 1.1 perry exit(0);
420 1.1 perry return(C);
421 1.1 perry }
422 1.1 perry
423 1.1 perry void
424 1.1 perry getfname(void)
425 1.1 perry {
426 1.1 perry char *p;
427 1.1 perry struct chain {
428 1.1 perry struct chain *nextp;
429 1.1 perry char *datap;
430 1.1 perry } *q;
431 1.1 perry static struct chain *namechain= NULL;
432 1.1 perry
433 1.1 perry while (C == ' ')
434 1.1 perry ; /* nothing */
435 1.1 perry
436 1.1 perry for (p = fname ; p - fname < sizeof(fname) && (*p = c) != '\n' &&
437 1.1 perry c != ' ' && c != '\t' && c != '\\'; ++p)
438 1.1 perry C;
439 1.1 perry *p = '\0';
440 1.1 perry while (c != '\n')
441 1.1 perry C;
442 1.1 perry
443 1.1 perry /* see if this name has already been used */
444 1.1 perry for (q = namechain ; q; q = q->nextp)
445 1.1 perry if (strcmp(fname, q->datap) == 0) {
446 1.1 perry fname[0] = '\0';
447 1.1 perry return;
448 1.1 perry }
449 1.1 perry
450 1.1 perry q = (struct chain *) malloc(sizeof(struct chain));
451 1.1 perry if (q == NULL)
452 1.1 perry err(1, NULL);
453 1.1 perry q->nextp = namechain;
454 1.1 perry q->datap = strdup(fname);
455 1.1 perry if (q->datap == NULL)
456 1.1 perry err(1, NULL);
457 1.1 perry namechain = q;
458 1.1 perry }
459 1.1 perry
460 1.1 perry /*ARGSUSED*/
461 1.1 perry void
462 1.1 perry textline(char *str, int constant)
463 1.1 perry {
464 1.1 perry
465 1.1 perry if (wordflag) {
466 1.1 perry msputwords(0);
467 1.1 perry return;
468 1.1 perry }
469 1.1 perry puts(str);
470 1.1 perry }
471 1.1 perry
472 1.1 perry void
473 1.1 perry work(void)
474 1.1 perry {
475 1.1 perry
476 1.1 perry for (;;) {
477 1.1 perry C;
478 1.1 perry #ifdef FULLDEBUG
479 1.1 perry printf("Starting work with `%c'\n", c);
480 1.1 perry #endif /* FULLDEBUG */
481 1.1 perry if (c == '.' || c == '\'')
482 1.1 perry comline();
483 1.1 perry else
484 1.1 perry regline(textline, TWO);
485 1.1 perry }
486 1.1 perry }
487 1.1 perry
488 1.1 perry void
489 1.1 perry regline(void (*pfunc)(char *, int), int constant)
490 1.1 perry {
491 1.1 perry
492 1.1 perry line[0] = c;
493 1.1 perry lp = line;
494 1.1 perry while (lp - line < sizeof(line)) {
495 1.1 perry if (c == '\\') {
496 1.1 perry *lp = ' ';
497 1.1 perry backsl();
498 1.1 perry }
499 1.1 perry if (c == '\n')
500 1.1 perry break;
501 1.1 perry if (intable && c == 'T') {
502 1.1 perry *++lp = C;
503 1.1 perry if (c == '{' || c == '}') {
504 1.1 perry lp[-1] = ' ';
505 1.1 perry *lp = C;
506 1.1 perry }
507 1.1 perry } else {
508 1.1 perry *++lp = C;
509 1.1 perry }
510 1.1 perry }
511 1.1 perry *lp = '\0';
512 1.1 perry
513 1.1 perry if (line[0] != '\0')
514 1.1 perry (*pfunc)(line, constant);
515 1.1 perry }
516 1.1 perry
517 1.1 perry void
518 1.1 perry macro(void)
519 1.1 perry {
520 1.1 perry
521 1.1 perry if (msflag) {
522 1.1 perry do {
523 1.1 perry SKIP;
524 1.1 perry } while (C!='.' || C!='.' || C=='.'); /* look for .. */
525 1.1 perry if (c != '\n')
526 1.1 perry SKIP;
527 1.1 perry return;
528 1.1 perry }
529 1.1 perry SKIP;
530 1.1 perry inmacro = YES;
531 1.1 perry }
532 1.1 perry
533 1.1 perry void
534 1.1 perry tbl(void)
535 1.1 perry {
536 1.1 perry
537 1.1 perry while (C != '.')
538 1.1 perry ; /* nothing */
539 1.1 perry SKIP;
540 1.1 perry intable = YES;
541 1.1 perry }
542 1.1 perry
543 1.1 perry void
544 1.1 perry stbl(void)
545 1.1 perry {
546 1.1 perry
547 1.1 perry while (C != '.')
548 1.1 perry ; /* nothing */
549 1.1 perry SKIP_TO_COM;
550 1.1 perry if (c != 'T' || C != 'E') {
551 1.1 perry SKIP;
552 1.1 perry pc = c;
553 1.1 perry while (C != '.' || pc != '\n' || C != 'T' || C != 'E')
554 1.1 perry pc = c;
555 1.1 perry }
556 1.1 perry }
557 1.1 perry
558 1.1 perry void
559 1.1 perry eqn(void)
560 1.1 perry {
561 1.1 perry int c1, c2;
562 1.1 perry int dflg;
563 1.1 perry char last;
564 1.1 perry
565 1.1 perry last=0;
566 1.1 perry dflg = 1;
567 1.1 perry SKIP;
568 1.1 perry
569 1.1 perry for (;;) {
570 1.1 perry if (C1 == '.' || c == '\'') {
571 1.1 perry while (C1 == ' ' || c == '\t')
572 1.1 perry ;
573 1.1 perry if (c == 'E' && C1 == 'N') {
574 1.1 perry SKIP;
575 1.1 perry if (msflag && dflg) {
576 1.1 perry putchar('x');
577 1.1 perry putchar(' ');
578 1.1 perry if (last) {
579 1.1 perry putchar(last);
580 1.1 perry putchar('\n');
581 1.1 perry }
582 1.1 perry }
583 1.1 perry return;
584 1.1 perry }
585 1.1 perry } else if (c == 'd') {
586 1.1 perry /* look for delim */
587 1.1 perry if (C1 == 'e' && C1 == 'l')
588 1.1 perry if (C1 == 'i' && C1 == 'm') {
589 1.1 perry while (C1 == ' ')
590 1.1 perry ; /* nothing */
591 1.1 perry
592 1.1 perry if ((c1 = c) == '\n' ||
593 1.1 perry (c2 = C1) == '\n' ||
594 1.1 perry (c1 == 'o' && c2 == 'f' && C1=='f')) {
595 1.1 perry ldelim = NOCHAR;
596 1.1 perry rdelim = NOCHAR;
597 1.1 perry } else {
598 1.1 perry ldelim = c1;
599 1.1 perry rdelim = c2;
600 1.1 perry }
601 1.1 perry }
602 1.1 perry dflg = 0;
603 1.1 perry }
604 1.1 perry
605 1.1 perry if (c != '\n')
606 1.1 perry while (C1 != '\n') {
607 1.1 perry if (chars[c] == PUNCT)
608 1.1 perry last = c;
609 1.1 perry else if (c != ' ')
610 1.1 perry last = 0;
611 1.1 perry }
612 1.1 perry }
613 1.1 perry }
614 1.1 perry
615 1.1 perry /* skip over a complete backslash construction */
616 1.1 perry void
617 1.1 perry backsl(void)
618 1.1 perry {
619 1.1 perry int bdelim;
620 1.1 perry
621 1.1 perry sw:
622 1.1 perry switch (C) {
623 1.1 perry case '"':
624 1.1 perry SKIP;
625 1.1 perry return;
626 1.1 perry
627 1.1 perry case 's':
628 1.1 perry if (C == '\\')
629 1.1 perry backsl();
630 1.1 perry else {
631 1.1 perry while (C >= '0' && c <= '9')
632 1.1 perry ; /* nothing */
633 1.1 perry ungetc(c, infile);
634 1.1 perry c = '0';
635 1.1 perry }
636 1.1 perry --lp;
637 1.1 perry return;
638 1.1 perry
639 1.1 perry case 'f':
640 1.1 perry case 'n':
641 1.1 perry case '*':
642 1.1 perry if (C != '(')
643 1.1 perry return;
644 1.1 perry
645 1.1 perry case '(':
646 1.1 perry if (msflag) {
647 1.1 perry if (C == 'e') {
648 1.1 perry if (C == 'm') {
649 1.1 perry *lp = '-';
650 1.1 perry return;
651 1.1 perry }
652 1.1 perry }
653 1.1 perry else if (c != '\n')
654 1.1 perry C;
655 1.1 perry return;
656 1.1 perry }
657 1.1 perry if (C != '\n')
658 1.1 perry C;
659 1.1 perry return;
660 1.1 perry
661 1.1 perry case '$':
662 1.1 perry C; /* discard argument number */
663 1.1 perry return;
664 1.1 perry
665 1.1 perry case 'b':
666 1.1 perry case 'x':
667 1.1 perry case 'v':
668 1.1 perry case 'h':
669 1.1 perry case 'w':
670 1.1 perry case 'o':
671 1.1 perry case 'l':
672 1.1 perry case 'L':
673 1.1 perry if ((bdelim = C) == '\n')
674 1.1 perry return;
675 1.1 perry while (C != '\n' && c != bdelim)
676 1.1 perry if (c == '\\')
677 1.1 perry backsl();
678 1.1 perry return;
679 1.1 perry
680 1.1 perry case '\\':
681 1.1 perry if (inmacro)
682 1.1 perry goto sw;
683 1.1 perry
684 1.1 perry default:
685 1.1 perry return;
686 1.1 perry }
687 1.1 perry }
688 1.1 perry
689 1.1 perry void
690 1.1 perry sce(void)
691 1.1 perry {
692 1.1 perry char *ap;
693 1.1 perry int n, i;
694 1.1 perry char a[10];
695 1.1 perry
696 1.1 perry for (ap = a; C != '\n'; ap++) {
697 1.1 perry *ap = c;
698 1.1 perry if (ap == &a[9]) {
699 1.1 perry SKIP;
700 1.1 perry ap = a;
701 1.1 perry break;
702 1.1 perry }
703 1.1 perry }
704 1.1 perry if (ap != a)
705 1.1 perry n = atoi(a);
706 1.1 perry else
707 1.1 perry n = 1;
708 1.1 perry for (i = 0; i < n;) {
709 1.1 perry if (C == '.') {
710 1.1 perry if (C == 'c') {
711 1.1 perry if (C == 'e') {
712 1.1 perry while (C == ' ')
713 1.1 perry ; /* nothing */
714 1.1 perry if (c == '0') {
715 1.1 perry SKIP;
716 1.1 perry break;
717 1.1 perry } else
718 1.1 perry SKIP;
719 1.1 perry }
720 1.1 perry else
721 1.1 perry SKIP;
722 1.1 perry } else if (c == 'P' || C == 'P') {
723 1.1 perry if (c != '\n')
724 1.1 perry SKIP;
725 1.1 perry break;
726 1.1 perry } else if (c != '\n')
727 1.1 perry SKIP;
728 1.1 perry } else {
729 1.1 perry SKIP;
730 1.1 perry i++;
731 1.1 perry }
732 1.1 perry }
733 1.1 perry }
734 1.1 perry
735 1.1 perry void
736 1.1 perry refer(int c1)
737 1.1 perry {
738 1.1 perry int c2;
739 1.1 perry
740 1.1 perry if (c1 != '\n')
741 1.1 perry SKIP;
742 1.1 perry
743 1.1 perry for (c2 = -1;;) {
744 1.1 perry if (C != '.')
745 1.1 perry SKIP;
746 1.1 perry else {
747 1.1 perry if (C != ']')
748 1.1 perry SKIP;
749 1.1 perry else {
750 1.1 perry while (C != '\n')
751 1.1 perry c2 = c;
752 1.1 perry if (c2 != -1 && chars[c2] == PUNCT)
753 1.1 perry putchar(c2);
754 1.1 perry return;
755 1.1 perry }
756 1.1 perry }
757 1.1 perry }
758 1.1 perry }
759 1.1 perry
760 1.1 perry void
761 1.1 perry inpic(void)
762 1.1 perry {
763 1.1 perry int c1;
764 1.1 perry char *p1;
765 1.1 perry
766 1.1 perry SKIP;
767 1.1 perry p1 = line;
768 1.1 perry c = '\n';
769 1.1 perry for (;;) {
770 1.1 perry c1 = c;
771 1.1 perry if (C == '.' && c1 == '\n') {
772 1.1 perry if (C != 'P') {
773 1.1 perry if (c == '\n')
774 1.1 perry continue;
775 1.1 perry else {
776 1.1 perry SKIP;
777 1.1 perry c = '\n';
778 1.1 perry continue;
779 1.1 perry }
780 1.1 perry }
781 1.1 perry if (C != 'E') {
782 1.1 perry if (c == '\n')
783 1.1 perry continue;
784 1.1 perry else {
785 1.1 perry SKIP;
786 1.1 perry c = '\n';
787 1.1 perry continue;
788 1.1 perry }
789 1.1 perry }
790 1.1 perry SKIP;
791 1.1 perry return;
792 1.1 perry }
793 1.1 perry else if (c == '\"') {
794 1.1 perry while (C != '\"') {
795 1.1 perry if (c == '\\') {
796 1.1 perry if (C == '\"')
797 1.1 perry continue;
798 1.1 perry ungetc(c, infile);
799 1.1 perry backsl();
800 1.1 perry } else
801 1.1 perry *p1++ = c;
802 1.1 perry }
803 1.1 perry *p1++ = ' ';
804 1.1 perry }
805 1.1 perry else if (c == '\n' && p1 != line) {
806 1.1 perry *p1 = '\0';
807 1.1 perry if (wordflag)
808 1.1 perry msputwords(NO);
809 1.1 perry else {
810 1.1 perry puts(line);
811 1.1 perry putchar('\n');
812 1.1 perry }
813 1.1 perry p1 = line;
814 1.1 perry }
815 1.1 perry }
816 1.1 perry }
817 1.1 perry
818 1.1 perry #ifdef DEBUG
819 1.1 perry int
820 1.1 perry _C1(void)
821 1.1 perry {
822 1.1 perry
823 1.1 perry return(C1get);
824 1.1 perry }
825 1.1 perry
826 1.1 perry int
827 1.1 perry _C(void)
828 1.1 perry {
829 1.1 perry
830 1.1 perry return(Cget);
831 1.1 perry }
832 1.1 perry #endif /* DEBUG */
833 1.1 perry
834 1.1 perry /*
835 1.1 perry * Put out a macro line, using ms and mm conventions.
836 1.1 perry */
837 1.1 perry void
838 1.1 perry msputmac(char *s, int constant)
839 1.1 perry {
840 1.1 perry char *t;
841 1.1 perry int found;
842 1.1 perry int last;
843 1.1 perry
844 1.1 perry last = 0;
845 1.1 perry found = 0;
846 1.1 perry if (wordflag) {
847 1.1 perry msputwords(YES);
848 1.1 perry return;
849 1.1 perry }
850 1.1 perry while (*s) {
851 1.1 perry while (*s == ' ' || *s == '\t')
852 1.1 perry putchar(*s++);
853 1.1 perry for (t = s ; *t != ' ' && *t != '\t' && *t != '\0' ; ++t)
854 1.1 perry ; /* nothing */
855 1.1 perry if (*s == '\"')
856 1.1 perry s++;
857 1.1 perry if (t > s + constant && chars[(unsigned char)s[0]] == LETTER &&
858 1.1 perry chars[(unsigned char)s[1]] == LETTER) {
859 1.1 perry while (s < t)
860 1.1 perry if (*s == '\"')
861 1.1 perry s++;
862 1.1 perry else
863 1.1 perry putchar(*s++);
864 1.1 perry last = *(t-1);
865 1.1 perry found++;
866 1.1 perry } else if (found && chars[(unsigned char)s[0]] == PUNCT &&
867 1.1 perry s[1] == '\0') {
868 1.1 perry putchar(*s++);
869 1.1 perry } else {
870 1.1 perry last = *(t - 1);
871 1.1 perry s = t;
872 1.1 perry }
873 1.1 perry }
874 1.1 perry putchar('\n');
875 1.1 perry if (msflag && chars[last] == PUNCT) {
876 1.1 perry putchar(last);
877 1.1 perry putchar('\n');
878 1.1 perry }
879 1.1 perry }
880 1.1 perry
881 1.1 perry /*
882 1.1 perry * put out words (for the -w option) with ms and mm conventions
883 1.1 perry */
884 1.1 perry void
885 1.1 perry msputwords(int macline)
886 1.1 perry {
887 1.1 perry char *p, *p1;
888 1.1 perry int i, nlet;
889 1.1 perry
890 1.1 perry for (p1 = line;;) {
891 1.1 perry /*
892 1.1 perry * skip initial specials ampersands and apostrophes
893 1.1 perry */
894 1.1 perry while (chars[(unsigned char)*p1] < DIGIT)
895 1.1 perry if (*p1++ == '\0')
896 1.1 perry return;
897 1.1 perry nlet = 0;
898 1.1 perry for (p = p1 ; (i = chars[(unsigned char)*p]) != SPECIAL ; ++p)
899 1.1 perry if (i == LETTER)
900 1.1 perry ++nlet;
901 1.1 perry
902 1.1 perry if (nlet > 1 && chars[(unsigned char)p1[0]] == LETTER) {
903 1.1 perry /*
904 1.1 perry * delete trailing ampersands and apostrophes
905 1.1 perry */
906 1.1 perry while ((i = chars[(unsigned char)p[-1]]) == PUNCT ||
907 1.1 perry i == APOS )
908 1.1 perry --p;
909 1.1 perry while (p1 < p)
910 1.1 perry putchar(*p1++);
911 1.1 perry putchar('\n');
912 1.1 perry } else {
913 1.1 perry p1 = p;
914 1.1 perry }
915 1.1 perry }
916 1.1 perry }
917 1.1 perry
918 1.1 perry /*
919 1.1 perry * put out a macro using the me conventions
920 1.1 perry */
921 1.1 perry #define SKIPBLANK(cp) while (*cp == ' ' || *cp == '\t') { cp++; }
922 1.1 perry #define SKIPNONBLANK(cp) while (*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
923 1.1 perry
924 1.1 perry void
925 1.1 perry meputmac(char *cp, int constant)
926 1.1 perry {
927 1.1 perry char *np;
928 1.1 perry int found;
929 1.1 perry int argno;
930 1.1 perry int last;
931 1.1 perry int inquote;
932 1.1 perry
933 1.1 perry last = 0;
934 1.1 perry found = 0;
935 1.1 perry if (wordflag) {
936 1.1 perry meputwords(YES);
937 1.1 perry return;
938 1.1 perry }
939 1.1 perry for (argno = 0; *cp; argno++) {
940 1.1 perry SKIPBLANK(cp);
941 1.1 perry inquote = (*cp == '"');
942 1.1 perry if (inquote)
943 1.1 perry cp++;
944 1.1 perry for (np = cp; *np; np++) {
945 1.1 perry switch (*np) {
946 1.1 perry case '\n':
947 1.1 perry case '\0':
948 1.1 perry break;
949 1.1 perry
950 1.1 perry case '\t':
951 1.1 perry case ' ':
952 1.1 perry if (inquote)
953 1.1 perry continue;
954 1.1 perry else
955 1.1 perry goto endarg;
956 1.1 perry
957 1.1 perry case '"':
958 1.1 perry if (inquote && np[1] == '"') {
959 1.1 perry memmove(np, np + 1, strlen(np));
960 1.1 perry np++;
961 1.1 perry continue;
962 1.1 perry } else {
963 1.1 perry *np = ' '; /* bye bye " */
964 1.1 perry goto endarg;
965 1.1 perry }
966 1.1 perry
967 1.1 perry default:
968 1.1 perry continue;
969 1.1 perry }
970 1.1 perry }
971 1.1 perry endarg: ;
972 1.1 perry /*
973 1.1 perry * cp points at the first char in the arg
974 1.1 perry * np points one beyond the last char in the arg
975 1.1 perry */
976 1.1 perry if ((argconcat == 0) || (argconcat != argno))
977 1.1 perry putchar(' ');
978 1.1 perry #ifdef FULLDEBUG
979 1.1 perry {
980 1.1 perry char *p;
981 1.1 perry printf("[%d,%d: ", argno, np - cp);
982 1.1 perry for (p = cp; p < np; p++) {
983 1.1 perry putchar(*p);
984 1.1 perry }
985 1.1 perry printf("]");
986 1.1 perry }
987 1.1 perry #endif /* FULLDEBUG */
988 1.1 perry /*
989 1.1 perry * Determine if the argument merits being printed
990 1.1 perry *
991 1.1 perry * constant is the cut off point below which something
992 1.1 perry * is not a word.
993 1.1 perry */
994 1.1 perry if (((np - cp) > constant) &&
995 1.1 perry (inquote || (chars[(unsigned char)cp[0]] == LETTER))) {
996 1.1 perry for (cp = cp; cp < np; cp++)
997 1.1 perry putchar(*cp);
998 1.1 perry last = np[-1];
999 1.1 perry found++;
1000 1.1 perry } else if (found && (np - cp == 1) &&
1001 1.1 perry chars[(unsigned char)*cp] == PUNCT) {
1002 1.1 perry putchar(*cp);
1003 1.1 perry } else {
1004 1.1 perry last = np[-1];
1005 1.1 perry }
1006 1.1 perry cp = np;
1007 1.1 perry }
1008 1.1 perry if (msflag && chars[last] == PUNCT)
1009 1.1 perry putchar(last);
1010 1.1 perry putchar('\n');
1011 1.1 perry }
1012 1.1 perry
1013 1.1 perry /*
1014 1.1 perry * put out words (for the -w option) with ms and mm conventions
1015 1.1 perry */
1016 1.1 perry void
1017 1.1 perry meputwords(int macline)
1018 1.1 perry {
1019 1.1 perry
1020 1.1 perry msputwords(macline);
1021 1.1 perry }
1022 1.1 perry
1023 1.1 perry /*
1024 1.1 perry *
1025 1.1 perry * Skip over a nested set of macros
1026 1.1 perry *
1027 1.1 perry * Possible arguments to noblock are:
1028 1.1 perry *
1029 1.1 perry * fi end of unfilled text
1030 1.1 perry * PE pic ending
1031 1.1 perry * DE display ending
1032 1.1 perry *
1033 1.1 perry * for ms and mm only:
1034 1.1 perry * KE keep ending
1035 1.1 perry *
1036 1.1 perry * NE undocumented match to NS (for mm?)
1037 1.1 perry * LE mm only: matches RL or *L (for lists)
1038 1.1 perry *
1039 1.1 perry * for me:
1040 1.1 perry * ([lqbzcdf]
1041 1.1 perry */
1042 1.1 perry void
1043 1.1 perry noblock(char a1, char a2)
1044 1.1 perry {
1045 1.1 perry int c1,c2;
1046 1.1 perry int eqnf;
1047 1.1 perry int lct;
1048 1.1 perry
1049 1.1 perry lct = 0;
1050 1.1 perry eqnf = 1;
1051 1.1 perry SKIP;
1052 1.1 perry for (;;) {
1053 1.1 perry while (C != '.')
1054 1.1 perry if (c == '\n')
1055 1.1 perry continue;
1056 1.1 perry else
1057 1.1 perry SKIP;
1058 1.1 perry if ((c1 = C) == '\n')
1059 1.1 perry continue;
1060 1.1 perry if ((c2 = C) == '\n')
1061 1.1 perry continue;
1062 1.1 perry if (c1 == a1 && c2 == a2) {
1063 1.1 perry SKIP;
1064 1.1 perry if (lct != 0) {
1065 1.1 perry lct--;
1066 1.1 perry continue;
1067 1.1 perry }
1068 1.1 perry if (eqnf)
1069 1.1 perry putchar('.');
1070 1.1 perry putchar('\n');
1071 1.1 perry return;
1072 1.1 perry } else if (a1 == 'L' && c2 == 'L') {
1073 1.1 perry lct++;
1074 1.1 perry SKIP;
1075 1.1 perry }
1076 1.1 perry /*
1077 1.1 perry * equations (EQ) nested within a display
1078 1.1 perry */
1079 1.1 perry else if (c1 == 'E' && c2 == 'Q') {
1080 1.1 perry if ((mac == ME && a1 == ')')
1081 1.1 perry || (mac != ME && a1 == 'D')) {
1082 1.1 perry eqn();
1083 1.1 perry eqnf=0;
1084 1.1 perry }
1085 1.1 perry }
1086 1.1 perry /*
1087 1.1 perry * turning on filling is done by the paragraphing
1088 1.1 perry * macros
1089 1.1 perry */
1090 1.1 perry else if (a1 == 'f') { /* .fi */
1091 1.1 perry if ((mac == ME && (c2 == 'h' || c2 == 'p'))
1092 1.1 perry || (mac != ME && (c1 == 'P' || c2 == 'P'))) {
1093 1.1 perry SKIP;
1094 1.1 perry return;
1095 1.1 perry }
1096 1.1 perry } else {
1097 1.1 perry SKIP;
1098 1.1 perry }
1099 1.1 perry }
1100 1.1 perry }
1101 1.1 perry
1102 1.1 perry int
1103 1.1 perry EQ(void)
1104 1.1 perry {
1105 1.1 perry
1106 1.1 perry eqn();
1107 1.1 perry return(0);
1108 1.1 perry }
1109 1.1 perry
1110 1.1 perry int
1111 1.1 perry domacro(void)
1112 1.1 perry {
1113 1.1 perry
1114 1.1 perry macro();
1115 1.1 perry return(0);
1116 1.1 perry }
1117 1.1 perry
1118 1.1 perry int
1119 1.1 perry PS(void)
1120 1.1 perry {
1121 1.1 perry
1122 1.1 perry for (C; c == ' ' || c == '\t'; C)
1123 1.1 perry ; /* nothing */
1124 1.1 perry
1125 1.1 perry if (c == '<') { /* ".PS < file" -- don't expect a .PE */
1126 1.1 perry SKIP;
1127 1.1 perry return(0);
1128 1.1 perry }
1129 1.1 perry if (!msflag)
1130 1.1 perry inpic();
1131 1.1 perry else
1132 1.1 perry noblock('P', 'E');
1133 1.1 perry return(0);
1134 1.1 perry }
1135 1.1 perry
1136 1.1 perry int
1137 1.1 perry skip(void)
1138 1.1 perry {
1139 1.1 perry
1140 1.1 perry SKIP;
1141 1.1 perry return(0);
1142 1.1 perry }
1143 1.1 perry
1144 1.1 perry int
1145 1.1 perry intbl(void)
1146 1.1 perry {
1147 1.1 perry
1148 1.1 perry if (msflag)
1149 1.1 perry stbl();
1150 1.1 perry else
1151 1.1 perry tbl();
1152 1.1 perry return(0);
1153 1.1 perry }
1154 1.1 perry
1155 1.1 perry int
1156 1.1 perry outtbl(void)
1157 1.1 perry {
1158 1.1 perry
1159 1.1 perry intable = NO;
1160 1.1 perry return(0);
1161 1.1 perry }
1162 1.1 perry
1163 1.1 perry int
1164 1.1 perry so(void)
1165 1.1 perry {
1166 1.1 perry
1167 1.1 perry if (!iflag) {
1168 1.1 perry getfname();
1169 1.1 perry if (fname[0]) {
1170 1.1 perry if (++filesp - &files[0] > MAXFILES)
1171 1.1 perry err(1, "too many nested files (max %d)",
1172 1.1 perry MAXFILES);
1173 1.1 perry infile = *filesp = opn(fname);
1174 1.1 perry }
1175 1.1 perry }
1176 1.1 perry return(0);
1177 1.1 perry }
1178 1.1 perry
1179 1.1 perry int
1180 1.1 perry nx(void)
1181 1.1 perry {
1182 1.1 perry
1183 1.1 perry if (!iflag) {
1184 1.1 perry getfname();
1185 1.1 perry if (fname[0] == '\0')
1186 1.1 perry exit(0);
1187 1.1 perry if (infile != stdin)
1188 1.1 perry fclose(infile);
1189 1.1 perry infile = *filesp = opn(fname);
1190 1.1 perry }
1191 1.1 perry return(0);
1192 1.1 perry }
1193 1.1 perry
1194 1.1 perry int
1195 1.1 perry skiptocom(void)
1196 1.1 perry {
1197 1.1 perry
1198 1.1 perry SKIP_TO_COM;
1199 1.1 perry return(COMX);
1200 1.1 perry }
1201 1.1 perry
1202 1.1 perry int
1203 1.1 perry PP(pacmac c12)
1204 1.1 perry {
1205 1.1 perry int c1, c2;
1206 1.1 perry
1207 1.1 perry frommac(c12, c1, c2);
1208 1.1 perry printf(".%c%c", c1, c2);
1209 1.1 perry while (C != '\n')
1210 1.1 perry putchar(c);
1211 1.1 perry putchar('\n');
1212 1.1 perry return(0);
1213 1.1 perry }
1214 1.1 perry
1215 1.1 perry int
1216 1.1 perry AU(void)
1217 1.1 perry {
1218 1.1 perry
1219 1.1 perry if (mac == MM)
1220 1.1 perry return(0);
1221 1.1 perry SKIP_TO_COM;
1222 1.1 perry return(COMX);
1223 1.1 perry }
1224 1.1 perry
1225 1.1 perry int
1226 1.1 perry SH(pacmac c12)
1227 1.1 perry {
1228 1.1 perry int c1, c2;
1229 1.1 perry
1230 1.1 perry frommac(c12, c1, c2);
1231 1.1 perry
1232 1.1 perry if (parag) {
1233 1.1 perry printf(".%c%c", c1, c2);
1234 1.1 perry while (C != '\n')
1235 1.1 perry putchar(c);
1236 1.1 perry putchar(c);
1237 1.1 perry putchar('!');
1238 1.1 perry for (;;) {
1239 1.1 perry while (C != '\n')
1240 1.1 perry putchar(c);
1241 1.1 perry putchar('\n');
1242 1.1 perry if (C == '.')
1243 1.1 perry return(COM);
1244 1.1 perry putchar('!');
1245 1.1 perry putchar(c);
1246 1.1 perry }
1247 1.1 perry /*NOTREACHED*/
1248 1.1 perry } else {
1249 1.1 perry SKIP_TO_COM;
1250 1.1 perry return(COMX);
1251 1.1 perry }
1252 1.1 perry }
1253 1.1 perry
1254 1.1 perry int
1255 1.1 perry UX(void)
1256 1.1 perry {
1257 1.1 perry
1258 1.1 perry if (wordflag)
1259 1.1 perry printf("UNIX\n");
1260 1.1 perry else
1261 1.1 perry printf("UNIX ");
1262 1.1 perry return(0);
1263 1.1 perry }
1264 1.1 perry
1265 1.1 perry int
1266 1.1 perry MMHU(pacmac c12)
1267 1.1 perry {
1268 1.1 perry int c1, c2;
1269 1.1 perry
1270 1.1 perry frommac(c12, c1, c2);
1271 1.1 perry if (parag) {
1272 1.1 perry printf(".%c%c", c1, c2);
1273 1.1 perry while (C != '\n')
1274 1.1 perry putchar(c);
1275 1.1 perry putchar('\n');
1276 1.1 perry } else {
1277 1.1 perry SKIP;
1278 1.1 perry }
1279 1.1 perry return(0);
1280 1.1 perry }
1281 1.1 perry
1282 1.1 perry int
1283 1.1 perry mesnblock(pacmac c12)
1284 1.1 perry {
1285 1.1 perry int c1, c2;
1286 1.1 perry
1287 1.1 perry frommac(c12, c1, c2);
1288 1.1 perry noblock(')', c2);
1289 1.1 perry return(0);
1290 1.1 perry }
1291 1.1 perry
1292 1.1 perry int
1293 1.1 perry mssnblock(pacmac c12)
1294 1.1 perry {
1295 1.1 perry int c1, c2;
1296 1.1 perry
1297 1.1 perry frommac(c12, c1, c2);
1298 1.1 perry noblock(c1, 'E');
1299 1.1 perry return(0);
1300 1.1 perry }
1301 1.1 perry
1302 1.1 perry int
1303 1.1 perry nf(void)
1304 1.1 perry {
1305 1.1 perry
1306 1.1 perry noblock('f', 'i');
1307 1.1 perry return(0);
1308 1.1 perry }
1309 1.1 perry
1310 1.1 perry int
1311 1.1 perry ce(void)
1312 1.1 perry {
1313 1.1 perry
1314 1.1 perry sce();
1315 1.1 perry return(0);
1316 1.1 perry }
1317 1.1 perry
1318 1.1 perry int
1319 1.1 perry meip(pacmac c12)
1320 1.1 perry {
1321 1.1 perry
1322 1.1 perry if (parag)
1323 1.1 perry mepp(c12);
1324 1.1 perry else if (wordflag) /* save the tag */
1325 1.1 perry regline(meputmac, ONE);
1326 1.1 perry else
1327 1.1 perry SKIP;
1328 1.1 perry return(0);
1329 1.1 perry }
1330 1.1 perry
1331 1.1 perry /*
1332 1.1 perry * only called for -me .pp or .sh, when parag is on
1333 1.1 perry */
1334 1.1 perry int
1335 1.1 perry mepp(pacmac c12)
1336 1.1 perry {
1337 1.1 perry
1338 1.1 perry PP(c12); /* eats the line */
1339 1.1 perry return(0);
1340 1.1 perry }
1341 1.1 perry
1342 1.1 perry /*
1343 1.1 perry * Start of a section heading; output the section name if doing words
1344 1.1 perry */
1345 1.1 perry int
1346 1.1 perry mesh(pacmac c12)
1347 1.1 perry {
1348 1.1 perry
1349 1.1 perry if (parag)
1350 1.1 perry mepp(c12);
1351 1.1 perry else if (wordflag)
1352 1.1 perry defcomline(c12);
1353 1.1 perry else
1354 1.1 perry SKIP;
1355 1.1 perry return(0);
1356 1.1 perry }
1357 1.1 perry
1358 1.1 perry /*
1359 1.1 perry * process a font setting
1360 1.1 perry */
1361 1.1 perry int
1362 1.1 perry mefont(pacmac c12)
1363 1.1 perry {
1364 1.1 perry
1365 1.1 perry argconcat = 1;
1366 1.1 perry defcomline(c12);
1367 1.1 perry argconcat = 0;
1368 1.1 perry return(0);
1369 1.1 perry }
1370 1.1 perry
1371 1.1 perry int
1372 1.1 perry manfont(pacmac c12)
1373 1.1 perry {
1374 1.1 perry
1375 1.1 perry return(mefont(c12));
1376 1.1 perry }
1377 1.1 perry
1378 1.1 perry int
1379 1.1 perry manpp(pacmac c12)
1380 1.1 perry {
1381 1.1 perry
1382 1.1 perry return(mepp(c12));
1383 1.1 perry }
1384 1.1 perry
1385 1.1 perry void
1386 1.1 perry defcomline(pacmac c12)
1387 1.1 perry {
1388 1.1 perry int c1, c2;
1389 1.1 perry
1390 1.1 perry frommac(c12, c1, c2);
1391 1.1 perry if (msflag && mac == MM && c2 == 'L') {
1392 1.1 perry if (disp || c1 == 'R') {
1393 1.1 perry noblock('L', 'E');
1394 1.1 perry } else {
1395 1.1 perry SKIP;
1396 1.1 perry putchar('.');
1397 1.1 perry }
1398 1.1 perry }
1399 1.1 perry else if (c1 == '.' && c2 == '.') {
1400 1.1 perry if (msflag) {
1401 1.1 perry SKIP;
1402 1.1 perry return;
1403 1.1 perry }
1404 1.1 perry while (C == '.')
1405 1.1 perry /*VOID*/;
1406 1.1 perry }
1407 1.1 perry ++inmacro;
1408 1.1 perry /*
1409 1.1 perry * Process the arguments to the macro
1410 1.1 perry */
1411 1.1 perry switch (mac) {
1412 1.1 perry default:
1413 1.1 perry case MM:
1414 1.1 perry case MS:
1415 1.1 perry if (c1 <= 'Z' && msflag)
1416 1.1 perry regline(msputmac, ONE);
1417 1.1 perry else
1418 1.1 perry regline(msputmac, TWO);
1419 1.1 perry break;
1420 1.1 perry case ME:
1421 1.1 perry regline(meputmac, ONE);
1422 1.1 perry break;
1423 1.1 perry }
1424 1.1 perry --inmacro;
1425 1.1 perry }
1426 1.1 perry
1427 1.1 perry void
1428 1.1 perry comline(void)
1429 1.1 perry {
1430 1.1 perry int c1;
1431 1.1 perry int c2;
1432 1.1 perry pacmac c12;
1433 1.1 perry int mid;
1434 1.1 perry int lb, ub;
1435 1.1 perry int hit;
1436 1.1 perry static int tabsize = 0;
1437 1.1 perry static struct mactab *mactab = (struct mactab *)0;
1438 1.1 perry struct mactab *mp;
1439 1.1 perry
1440 1.1 perry if (mactab == 0)
1441 1.1 perry buildtab(&mactab, &tabsize);
1442 1.1 perry com:
1443 1.1 perry while (C == ' ' || c == '\t')
1444 1.1 perry ;
1445 1.1 perry comx:
1446 1.1 perry if ((c1 = c) == '\n')
1447 1.1 perry return;
1448 1.1 perry c2 = C;
1449 1.1 perry if (c1 == '.' && c2 != '.')
1450 1.1 perry inmacro = NO;
1451 1.1 perry if (msflag && c1 == '[') {
1452 1.1 perry refer(c2);
1453 1.1 perry return;
1454 1.1 perry }
1455 1.1 perry if (parag && mac==MM && c1 == 'P' && c2 == '\n') {
1456 1.1 perry printf(".P\n");
1457 1.1 perry return;
1458 1.1 perry }
1459 1.1 perry if (c2 == '\n')
1460 1.1 perry return;
1461 1.1 perry /*
1462 1.1 perry * Single letter macro
1463 1.1 perry */
1464 1.1 perry if (mac == ME && (c2 == ' ' || c2 == '\t') )
1465 1.1 perry c2 = ' ';
1466 1.1 perry c12 = tomac(c1, c2);
1467 1.1 perry /*
1468 1.1 perry * binary search through the table of macros
1469 1.1 perry */
1470 1.1 perry lb = 0;
1471 1.1 perry ub = tabsize - 1;
1472 1.1 perry while (lb <= ub) {
1473 1.1 perry mid = (ub + lb) / 2;
1474 1.1 perry mp = &mactab[mid];
1475 1.1 perry if (mp->macname < c12)
1476 1.1 perry lb = mid + 1;
1477 1.1 perry else if (mp->macname > c12)
1478 1.1 perry ub = mid - 1;
1479 1.1 perry else {
1480 1.1 perry hit = 1;
1481 1.1 perry #ifdef FULLDEBUG
1482 1.1 perry printf("preliminary hit macro %c%c ", c1, c2);
1483 1.1 perry #endif /* FULLDEBUG */
1484 1.1 perry switch (mp->condition) {
1485 1.1 perry case NONE:
1486 1.1 perry hit = YES;
1487 1.1 perry break;
1488 1.1 perry case FNEST:
1489 1.1 perry hit = (filesp == files);
1490 1.1 perry break;
1491 1.1 perry case NOMAC:
1492 1.1 perry hit = !inmacro;
1493 1.1 perry break;
1494 1.1 perry case MAC:
1495 1.1 perry hit = inmacro;
1496 1.1 perry break;
1497 1.1 perry case PARAG:
1498 1.1 perry hit = parag;
1499 1.1 perry break;
1500 1.1 perry case NBLK:
1501 1.1 perry hit = !keepblock;
1502 1.1 perry break;
1503 1.1 perry default:
1504 1.1 perry hit = 0;
1505 1.1 perry }
1506 1.1 perry
1507 1.1 perry if (hit) {
1508 1.1 perry #ifdef FULLDEBUG
1509 1.1 perry printf("MATCH\n");
1510 1.1 perry #endif /* FULLDEBUG */
1511 1.1 perry switch ((*(mp->func))(c12)) {
1512 1.1 perry default:
1513 1.1 perry return;
1514 1.1 perry case COMX:
1515 1.1 perry goto comx;
1516 1.1 perry case COM:
1517 1.1 perry goto com;
1518 1.1 perry }
1519 1.1 perry }
1520 1.1 perry #ifdef FULLDEBUG
1521 1.1 perry printf("FAIL\n");
1522 1.1 perry #endif /* FULLDEBUG */
1523 1.1 perry break;
1524 1.1 perry }
1525 1.1 perry }
1526 1.1 perry defcomline(c12);
1527 1.1 perry }
1528 1.1 perry
1529 1.1 perry int
1530 1.1 perry macsort(const void *p1, const void *p2)
1531 1.1 perry {
1532 1.1 perry struct mactab *t1 = (struct mactab *)p1;
1533 1.1 perry struct mactab *t2 = (struct mactab *)p2;
1534 1.1 perry
1535 1.1 perry return(t1->macname - t2->macname);
1536 1.1 perry }
1537 1.1 perry
1538 1.1 perry int
1539 1.1 perry sizetab(struct mactab *mp)
1540 1.1 perry {
1541 1.1 perry int i;
1542 1.1 perry
1543 1.1 perry i = 0;
1544 1.1 perry if (mp) {
1545 1.1 perry for (; mp->macname; mp++, i++)
1546 1.1 perry /*VOID*/ ;
1547 1.1 perry }
1548 1.1 perry return(i);
1549 1.1 perry }
1550 1.1 perry
1551 1.1 perry struct mactab *
1552 1.1 perry macfill(struct mactab *dst, struct mactab *src)
1553 1.1 perry {
1554 1.1 perry
1555 1.1 perry if (src) {
1556 1.1 perry while (src->macname)
1557 1.1 perry *dst++ = *src++;
1558 1.1 perry }
1559 1.1 perry return(dst);
1560 1.1 perry }
1561 1.1 perry
1562 1.1 perry __dead void
1563 1.1 perry usage(void)
1564 1.1 perry {
1565 1.1 perry extern char *__progname;
1566 1.1 perry
1567 1.1 perry fprintf(stderr, "usage: %s [-ikpw ] [ -m ( a | e | m | s | l ) ] [ filename ] ... \n", __progname);
1568 1.1 perry exit(1);
1569 1.1 perry }
1570 1.1 perry
1571 1.1 perry void
1572 1.1 perry buildtab(struct mactab **r_back, int *r_size)
1573 1.1 perry {
1574 1.1 perry int size;
1575 1.1 perry struct mactab *p, *p1, *p2;
1576 1.1 perry struct mactab *back;
1577 1.1 perry
1578 1.1 perry size = sizetab(troffmactab) + sizetab(ppmactab);
1579 1.1 perry p1 = p2 = NULL;
1580 1.1 perry if (msflag) {
1581 1.1 perry switch (mac) {
1582 1.1 perry case ME:
1583 1.1 perry p1 = memactab;
1584 1.1 perry break;
1585 1.1 perry case MM:
1586 1.1 perry p1 = msmactab;
1587 1.1 perry p2 = mmmactab;
1588 1.1 perry break;
1589 1.1 perry case MS:
1590 1.1 perry p1 = msmactab;
1591 1.1 perry break;
1592 1.1 perry case MA:
1593 1.1 perry p1 = manmactab;
1594 1.1 perry break;
1595 1.1 perry default:
1596 1.1 perry break;
1597 1.1 perry }
1598 1.1 perry }
1599 1.1 perry size += sizetab(p1);
1600 1.1 perry size += sizetab(p2);
1601 1.1 perry back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
1602 1.1 perry if (back == NULL)
1603 1.1 perry err(1, NULL);
1604 1.1 perry
1605 1.1 perry p = macfill(back, troffmactab);
1606 1.1 perry p = macfill(p, ppmactab);
1607 1.1 perry p = macfill(p, p1);
1608 1.1 perry p = macfill(p, p2);
1609 1.1 perry
1610 1.1 perry qsort(back, size, sizeof(struct mactab), macsort);
1611 1.1 perry *r_size = size;
1612 1.1 perry *r_back = back;
1613 1.1 perry }
1614 1.1 perry
1615 1.1 perry /*
1616 1.1 perry * troff commands
1617 1.1 perry */
1618 1.1 perry struct mactab troffmactab[] = {
1619 1.1 perry M(NONE, '\\','"', skip), /* comment */
1620 1.1 perry M(NOMAC, 'd','e', domacro), /* define */
1621 1.1 perry M(NOMAC, 'i','g', domacro), /* ignore till .. */
1622 1.1 perry M(NOMAC, 'a','m', domacro), /* append macro */
1623 1.1 perry M(NBLK, 'n','f', nf), /* filled */
1624 1.1 perry M(NBLK, 'c','e', ce), /* centered */
1625 1.1 perry
1626 1.1 perry M(NONE, 's','o', so), /* source a file */
1627 1.1 perry M(NONE, 'n','x', nx), /* go to next file */
1628 1.1 perry
1629 1.1 perry M(NONE, 't','m', skip), /* print string on tty */
1630 1.1 perry M(NONE, 'h','w', skip), /* exception hyphen words */
1631 1.1 perry M(NONE, 0,0, 0)
1632 1.1 perry };
1633 1.1 perry
1634 1.1 perry /*
1635 1.1 perry * Preprocessor output
1636 1.1 perry */
1637 1.1 perry struct mactab ppmactab[] = {
1638 1.1 perry M(FNEST, 'E','Q', EQ), /* equation starting */
1639 1.1 perry M(FNEST, 'T','S', intbl), /* table starting */
1640 1.1 perry M(FNEST, 'T','C', intbl), /* alternative table? */
1641 1.1 perry M(FNEST, 'T','&', intbl), /* table reformatting */
1642 1.1 perry M(NONE, 'T','E', outtbl),/* table ending */
1643 1.1 perry M(NONE, 'P','S', PS), /* picture starting */
1644 1.1 perry M(NONE, 0,0, 0)
1645 1.1 perry };
1646 1.1 perry
1647 1.1 perry /*
1648 1.1 perry * Particular to ms and mm
1649 1.1 perry */
1650 1.1 perry struct mactab msmactab[] = {
1651 1.1 perry M(NONE, 'T','L', skiptocom), /* title follows */
1652 1.1 perry M(NONE, 'F','S', skiptocom), /* start footnote */
1653 1.1 perry M(NONE, 'O','K', skiptocom), /* Other kws */
1654 1.1 perry
1655 1.1 perry M(NONE, 'N','R', skip), /* undocumented */
1656 1.1 perry M(NONE, 'N','D', skip), /* use supplied date */
1657 1.1 perry
1658 1.1 perry M(PARAG, 'P','P', PP), /* begin parag */
1659 1.1 perry M(PARAG, 'I','P', PP), /* begin indent parag, tag x */
1660 1.1 perry M(PARAG, 'L','P', PP), /* left blocked parag */
1661 1.1 perry
1662 1.1 perry M(NONE, 'A','U', AU), /* author */
1663 1.1 perry M(NONE, 'A','I', AU), /* authors institution */
1664 1.1 perry
1665 1.1 perry M(NONE, 'S','H', SH), /* section heading */
1666 1.1 perry M(NONE, 'S','N', SH), /* undocumented */
1667 1.1 perry M(NONE, 'U','X', UX), /* unix */
1668 1.1 perry
1669 1.1 perry M(NBLK, 'D','S', mssnblock), /* start display text */
1670 1.1 perry M(NBLK, 'K','S', mssnblock), /* start keep */
1671 1.1 perry M(NBLK, 'K','F', mssnblock), /* start float keep */
1672 1.1 perry M(NONE, 0,0, 0)
1673 1.1 perry };
1674 1.1 perry
1675 1.1 perry struct mactab mmmactab[] = {
1676 1.1 perry M(NONE, 'H',' ', MMHU), /* -mm ? */
1677 1.1 perry M(NONE, 'H','U', MMHU), /* -mm ? */
1678 1.1 perry M(PARAG, 'P',' ', PP), /* paragraph for -mm */
1679 1.1 perry M(NBLK, 'N','S', mssnblock), /* undocumented */
1680 1.1 perry M(NONE, 0,0, 0)
1681 1.1 perry };
1682 1.1 perry
1683 1.1 perry struct mactab memactab[] = {
1684 1.1 perry M(PARAG, 'p','p', mepp),
1685 1.1 perry M(PARAG, 'l','p', mepp),
1686 1.1 perry M(PARAG, 'n','p', mepp),
1687 1.1 perry M(NONE, 'i','p', meip),
1688 1.1 perry
1689 1.1 perry M(NONE, 's','h', mesh),
1690 1.1 perry M(NONE, 'u','h', mesh),
1691 1.1 perry
1692 1.1 perry M(NBLK, '(','l', mesnblock),
1693 1.1 perry M(NBLK, '(','q', mesnblock),
1694 1.1 perry M(NBLK, '(','b', mesnblock),
1695 1.1 perry M(NBLK, '(','z', mesnblock),
1696 1.1 perry M(NBLK, '(','c', mesnblock),
1697 1.1 perry
1698 1.1 perry M(NBLK, '(','d', mesnblock),
1699 1.1 perry M(NBLK, '(','f', mesnblock),
1700 1.1 perry M(NBLK, '(','x', mesnblock),
1701 1.1 perry
1702 1.1 perry M(NONE, 'r',' ', mefont),
1703 1.1 perry M(NONE, 'i',' ', mefont),
1704 1.1 perry M(NONE, 'b',' ', mefont),
1705 1.1 perry M(NONE, 'u',' ', mefont),
1706 1.1 perry M(NONE, 'q',' ', mefont),
1707 1.1 perry M(NONE, 'r','b', mefont),
1708 1.1 perry M(NONE, 'b','i', mefont),
1709 1.1 perry M(NONE, 'b','x', mefont),
1710 1.1 perry M(NONE, 0,0, 0)
1711 1.1 perry };
1712 1.1 perry
1713 1.1 perry struct mactab manmactab[] = {
1714 1.1 perry M(PARAG, 'B','I', manfont),
1715 1.1 perry M(PARAG, 'B','R', manfont),
1716 1.1 perry M(PARAG, 'I','B', manfont),
1717 1.1 perry M(PARAG, 'I','R', manfont),
1718 1.1 perry M(PARAG, 'R','B', manfont),
1719 1.1 perry M(PARAG, 'R','I', manfont),
1720 1.1 perry
1721 1.1 perry M(PARAG, 'P','P', manpp),
1722 1.1 perry M(PARAG, 'L','P', manpp),
1723 1.1 perry M(PARAG, 'H','P', manpp),
1724 1.1 perry M(NONE, 0,0, 0)
1725 1.1 perry };
1726