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