162e87e88Sbostic /*-
2*a71d9ce2Sbostic * Copyright (c) 1988, 1993
3*a71d9ce2Sbostic * The Regents of the University of California. All rights reserved.
462e87e88Sbostic *
562e87e88Sbostic * %sccs.include.proprietary.c%
662e87e88Sbostic */
762e87e88Sbostic
870468683Srrh #ifndef lint
9*a71d9ce2Sbostic static char copyright[] =
10*a71d9ce2Sbostic "@(#) Copyright (c) 1988, 1993\n\
11*a71d9ce2Sbostic The Regents of the University of California. All rights reserved.\n";
1262e87e88Sbostic #endif /* not lint */
1362e87e88Sbostic
1462e87e88Sbostic #ifndef lint
15*a71d9ce2Sbostic static char sccsid[] = "@(#)deroff.c 8.1 (Berkeley) 06/06/93";
1662e87e88Sbostic #endif /* not lint */
1770468683Srrh
1870468683Srrh #include <stdio.h>
1970468683Srrh
20b43b9614Srrh /*
21b43b9614Srrh * Deroff command -- strip troff, eqn, and Tbl sequences from
22b43b9614Srrh * a file. Has two flags argument, -w, to cause output one word per line
23b43b9614Srrh * rather than in the original format.
24b43b9614Srrh * -mm (or -ms) causes the corresponding macro's to be interpreted
25b43b9614Srrh * so that just sentences are output
26b43b9614Srrh * -ml also gets rid of lists.
27b43b9614Srrh * Deroff follows .so and .nx commands, removes contents of macro
28b43b9614Srrh * definitions, equations (both .EQ ... .EN and $...$),
29b43b9614Srrh * Tbl command sequences, and Troff backslash constructions.
30b43b9614Srrh *
31b43b9614Srrh * All input is through the Cget macro;
32b43b9614Srrh * the most recently read character is in c.
33b43b9614Srrh *
34b43b9614Srrh * Modified by Robert Henry to process -me and -man macros.
3570468683Srrh */
3670468683Srrh
37b43b9614Srrh #define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
38b43b9614Srrh #define C1get ( (c=getc(infile)) == EOF ? eof() : c)
39b43b9614Srrh
40b43b9614Srrh #ifdef DEBUG
41b43b9614Srrh # define C _C()
42b43b9614Srrh # define C1 _C1()
43b43b9614Srrh #else not DEBUG
44b43b9614Srrh # define C Cget
45b43b9614Srrh # define C1 C1get
46b43b9614Srrh #endif not DEBUG
47b43b9614Srrh
4870468683Srrh #define SKIP while(C != '\n')
4970468683Srrh #define SKIP_TO_COM SKIP; SKIP; pc=c; while(C != '.' || pc != '\n' || C > 'Z')pc=c
5070468683Srrh
5170468683Srrh #define YES 1
5270468683Srrh #define NO 0
53b43b9614Srrh #define MS 0 /* -ms */
54b43b9614Srrh #define MM 1 /* -mm */
55b43b9614Srrh #define ME 2 /* -me */
56b43b9614Srrh #define MA 3 /* -man */
57b43b9614Srrh
58b43b9614Srrh #ifdef DEBUG
59b43b9614Srrh char *mactab[] = {"-ms", "-mm", "-me", "-ma"};
60b43b9614Srrh #endif DEBUG
61b43b9614Srrh
6270468683Srrh #define ONE 1
6370468683Srrh #define TWO 2
6470468683Srrh
6570468683Srrh #define NOCHAR -2
6670468683Srrh #define SPECIAL 0
6770468683Srrh #define APOS 1
68af085800Srrh #define PUNCT 2
69af085800Srrh #define DIGIT 3
70af085800Srrh #define LETTER 4
7170468683Srrh
72b43b9614Srrh int wordflag;
73b43b9614Srrh int msflag; /* processing a source written using a mac package */
74b43b9614Srrh int mac; /* which package */
75b43b9614Srrh int disp;
76b43b9614Srrh int parag;
77b43b9614Srrh int inmacro;
78b43b9614Srrh int intable;
79b43b9614Srrh int keepblock; /* keep blocks of text; normally false when msflag */
8070468683Srrh
81af085800Srrh char chars[128]; /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
8270468683Srrh
8370468683Srrh char line[512];
8470468683Srrh char *lp;
8570468683Srrh
8670468683Srrh int c;
8770468683Srrh int pc;
88b43b9614Srrh int ldelim;
89b43b9614Srrh int rdelim;
9070468683Srrh
9170468683Srrh
9270468683Srrh int argc;
9370468683Srrh char **argv;
9470468683Srrh
9570468683Srrh char fname[50];
9670468683Srrh FILE *files[15];
9770468683Srrh FILE **filesp;
9870468683Srrh FILE *infile;
99b43b9614Srrh FILE *opn();
100b43b9614Srrh /*
101b43b9614Srrh * Flags for matching conditions other than
102b43b9614Srrh * the macro name
103b43b9614Srrh */
104b43b9614Srrh #define NONE 0
105b43b9614Srrh #define FNEST 1 /* no nested files */
106b43b9614Srrh #define NOMAC 2 /* no macro */
107b43b9614Srrh #define MAC 3 /* macro */
108b43b9614Srrh #define PARAG 4 /* in a paragraph */
109b43b9614Srrh #define MSF 5 /* msflag is on */
110b43b9614Srrh #define NBLK 6 /* set if no blocks to be kept */
11170468683Srrh
112b43b9614Srrh /*
113b43b9614Srrh * Return codes from macro minions, determine where to jump,
114b43b9614Srrh * how to repeat/reprocess text
115b43b9614Srrh */
116b43b9614Srrh #define COMX 1 /* goto comx */
117b43b9614Srrh #define COM 2 /* goto com */
118b43b9614Srrh
main(ac,av)11970468683Srrh main(ac, av)
12070468683Srrh int ac;
12170468683Srrh char **av;
12270468683Srrh {
12370468683Srrh register int i;
124af085800Srrh int errflg = 0;
125af085800Srrh register optchar;
12670468683Srrh FILE *opn();
127b43b9614Srrh int kflag = NO;
128b43b9614Srrh char *p;
12970468683Srrh
130b43b9614Srrh wordflag = NO;
131b43b9614Srrh msflag = NO;
132b43b9614Srrh mac = ME;
133b43b9614Srrh disp = NO;
134b43b9614Srrh parag = NO;
135b43b9614Srrh inmacro = NO;
136b43b9614Srrh intable = NO;
137b43b9614Srrh ldelim = NOCHAR;
138b43b9614Srrh rdelim = NOCHAR;
139b43b9614Srrh keepblock = YES;
140b43b9614Srrh
141b43b9614Srrh for(argc = ac - 1, argv = av + 1;
142b43b9614Srrh ( (argc > 0)
143b43b9614Srrh && (argv[0][0] == '-')
144b43b9614Srrh && (argv[0][1] != '\0') );
145b43b9614Srrh --argc, ++argv
146b43b9614Srrh ){
147b43b9614Srrh for(p = argv[0]+1; *p; ++p) {
148b43b9614Srrh switch(*p) {
149af085800Srrh case 'p':
150af085800Srrh parag=YES;
151af085800Srrh break;
152b43b9614Srrh case 'k':
153b43b9614Srrh kflag = YES;
154b43b9614Srrh break;
155b43b9614Srrh case 'w':
156b43b9614Srrh wordflag = YES;
157b43b9614Srrh kflag = YES;
158b43b9614Srrh break;
159b43b9614Srrh case 'm':
160b43b9614Srrh msflag = YES;
161b43b9614Srrh keepblock = NO;
162b43b9614Srrh switch(p[1]){
163b43b9614Srrh case 'm': mac = MM; p++; break;
164b43b9614Srrh case 's': mac = MS; p++; break;
165b43b9614Srrh case 'e': mac = ME; p++; break;
166b43b9614Srrh case 'a': mac = MA; p++; break;
167b43b9614Srrh case 'l': disp = YES; p++; break;
168b43b9614Srrh default: errflg++; break;
169b43b9614Srrh }
170b43b9614Srrh break;
171b43b9614Srrh default:
172af085800Srrh errflg++;
17370468683Srrh }
174b43b9614Srrh }
175b43b9614Srrh }
176b43b9614Srrh
177b43b9614Srrh if (kflag)
178b43b9614Srrh keepblock = YES;
179af085800Srrh if (errflg)
180b43b9614Srrh fatal("usage: deroff [ -w ] [ -k] [ -m (a e m s l) ] [ file ] ... \n",
181b43b9614Srrh (char *) NULL);
182b43b9614Srrh
183b43b9614Srrh #ifdef DEBUG
184b43b9614Srrh printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n",
185b43b9614Srrh msflag, mactab[mac], keepblock, disp);
186b43b9614Srrh #endif DEBUG
187b43b9614Srrh if (argc == 0){
18870468683Srrh infile = stdin;
189b43b9614Srrh } else {
190b43b9614Srrh infile = opn(argv[0]);
191b43b9614Srrh --argc;
192b43b9614Srrh ++argv;
193b43b9614Srrh }
194b43b9614Srrh
195b43b9614Srrh
19670468683Srrh files[0] = infile;
19770468683Srrh filesp = &files[0];
19870468683Srrh
19970468683Srrh for(i='a'; i<='z' ; ++i)
20070468683Srrh chars[i] = LETTER;
20170468683Srrh for(i='A'; i<='Z'; ++i)
20270468683Srrh chars[i] = LETTER;
20370468683Srrh for(i='0'; i<='9'; ++i)
20470468683Srrh chars[i] = DIGIT;
20570468683Srrh chars['\''] = APOS;
20670468683Srrh chars['&'] = APOS;
207af085800Srrh chars['.'] = PUNCT;
208af085800Srrh chars[','] = PUNCT;
209af085800Srrh chars[';'] = PUNCT;
210af085800Srrh chars['?'] = PUNCT;
211af085800Srrh chars[':'] = PUNCT;
21270468683Srrh work();
21370468683Srrh }
214af085800Srrh char *calloc();
215af085800Srrh
skeqn()21670468683Srrh skeqn()
21770468683Srrh {
21870468683Srrh while((c = getc(infile)) != rdelim)
21970468683Srrh if(c == EOF)
22070468683Srrh c = eof();
22170468683Srrh else if(c == '"')
22270468683Srrh while( (c = getc(infile)) != '"')
22370468683Srrh if(c == EOF)
22470468683Srrh c = eof();
22570468683Srrh else if(c == '\\')
22670468683Srrh if((c = getc(infile)) == EOF)
22770468683Srrh c = eof();
22870468683Srrh if(msflag)return(c='x');
22970468683Srrh return(c = ' ');
23070468683Srrh }
23170468683Srrh
opn(p)23270468683Srrh FILE *opn(p)
23370468683Srrh register char *p;
23470468683Srrh {
23570468683Srrh FILE *fd;
23670468683Srrh
237ba10b4eeSmckusick if( (fd = fopen(p, "r")) == NULL) {
238ba10b4eeSmckusick fprintf(stderr, "Deroff: ");
239ba10b4eeSmckusick perror(p);
240ba10b4eeSmckusick exit(1);
241ba10b4eeSmckusick }
24270468683Srrh
24370468683Srrh return(fd);
24470468683Srrh }
24570468683Srrh
eof()24670468683Srrh eof()
24770468683Srrh {
24870468683Srrh if(infile != stdin)
24970468683Srrh fclose(infile);
25070468683Srrh if(filesp > files)
25170468683Srrh infile = *--filesp;
252b43b9614Srrh else if (argc > 0) {
253b43b9614Srrh infile = opn(argv[0]);
254b43b9614Srrh --argc;
255b43b9614Srrh ++argv;
256b43b9614Srrh } else
25770468683Srrh exit(0);
25870468683Srrh return(C);
25970468683Srrh }
26070468683Srrh
getfname()26170468683Srrh getfname()
26270468683Srrh {
26370468683Srrh register char *p;
264af085800Srrh struct chain {
265af085800Srrh struct chain *nextp;
266af085800Srrh char *datap;
267af085800Srrh } *chainblock;
26870468683Srrh register struct chain *q;
26970468683Srrh static struct chain *namechain = NULL;
27070468683Srrh char *copys();
27170468683Srrh
27270468683Srrh while(C == ' ') ;
27370468683Srrh
27470468683Srrh for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p)
27570468683Srrh C;
27670468683Srrh *p = '\0';
27770468683Srrh while(c != '\n')
27870468683Srrh C;
27970468683Srrh
28070468683Srrh /* see if this name has already been used */
28170468683Srrh
28270468683Srrh for(q = namechain ; q; q = q->nextp)
28370468683Srrh if( ! strcmp(fname, q->datap))
28470468683Srrh {
28570468683Srrh fname[0] = '\0';
28670468683Srrh return;
28770468683Srrh }
28870468683Srrh
28970468683Srrh q = (struct chain *) calloc(1, sizeof(*chainblock));
29070468683Srrh q->nextp = namechain;
29170468683Srrh q->datap = copys(fname);
29270468683Srrh namechain = q;
29370468683Srrh }
29470468683Srrh
fatal(s,p)29570468683Srrh fatal(s,p)
29670468683Srrh char *s, *p;
29770468683Srrh {
29870468683Srrh fprintf(stderr, "Deroff: ");
29970468683Srrh fprintf(stderr, s, p);
30070468683Srrh exit(1);
30170468683Srrh }
302af085800Srrh
303b43b9614Srrh /*ARGSUSED*/
textline(str,constant)3048baa3d18Sbostic textline(str, constant)
305b43b9614Srrh char *str;
3068baa3d18Sbostic int constant;
307b43b9614Srrh {
308b43b9614Srrh if (wordflag) {
309b43b9614Srrh msputwords(0);
310b43b9614Srrh return;
311b43b9614Srrh }
312b43b9614Srrh puts(str);
313b43b9614Srrh }
314b43b9614Srrh
work()31570468683Srrh work()
31670468683Srrh {
31770468683Srrh for( ;; )
31870468683Srrh {
319b43b9614Srrh C;
320b43b9614Srrh #ifdef FULLDEBUG
321b43b9614Srrh printf("Starting work with `%c'\n", c);
322b43b9614Srrh #endif FULLDEBUG
323b43b9614Srrh if(c == '.' || c == '\'')
32470468683Srrh comline();
32570468683Srrh else
326b43b9614Srrh regline(textline, TWO);
32770468683Srrh }
32870468683Srrh }
32970468683Srrh
3308baa3d18Sbostic regline(pfunc, constant)
331b43b9614Srrh int (*pfunc)();
3328baa3d18Sbostic int constant;
33370468683Srrh {
33470468683Srrh line[0] = c;
33570468683Srrh lp = line;
33670468683Srrh for( ; ; )
33770468683Srrh {
338b43b9614Srrh if(c == '\\') {
33970468683Srrh *lp = ' ';
34070468683Srrh backsl();
34170468683Srrh }
342b43b9614Srrh if(c == '\n')
343b43b9614Srrh break;
344b43b9614Srrh if(intable && c=='T') {
34570468683Srrh *++lp = C;
346b43b9614Srrh if(c=='{' || c=='}') {
34770468683Srrh lp[-1] = ' ';
34870468683Srrh *lp = C;
34970468683Srrh }
350b43b9614Srrh } else {
351b43b9614Srrh *++lp = C;
35270468683Srrh }
35370468683Srrh }
35470468683Srrh
35570468683Srrh *lp = '\0';
35670468683Srrh
35770468683Srrh if(line[0] != '\0')
3588baa3d18Sbostic (*pfunc)(line, constant);
35970468683Srrh }
36070468683Srrh
macro()36170468683Srrh macro()
36270468683Srrh {
36370468683Srrh if(msflag){
364af085800Srrh do {
365af085800Srrh SKIP;
366af085800Srrh } while(C!='.' || C!='.' || C=='.'); /* look for .. */
36770468683Srrh if(c != '\n')SKIP;
36870468683Srrh return;
36970468683Srrh }
37070468683Srrh SKIP;
37170468683Srrh inmacro = YES;
37270468683Srrh }
37370468683Srrh
tbl()37470468683Srrh tbl()
37570468683Srrh {
37670468683Srrh while(C != '.');
37770468683Srrh SKIP;
37870468683Srrh intable = YES;
37970468683Srrh }
stbl()38070468683Srrh stbl()
38170468683Srrh {
38270468683Srrh while(C != '.');
38370468683Srrh SKIP_TO_COM;
38470468683Srrh if(c != 'T' || C != 'E'){
38570468683Srrh SKIP;
38670468683Srrh pc=c;
38770468683Srrh while(C != '.' || pc != '\n' || C != 'T' || C != 'E')pc=c;
38870468683Srrh }
38970468683Srrh }
39070468683Srrh
eqn()39170468683Srrh eqn()
39270468683Srrh {
39370468683Srrh register int c1, c2;
39470468683Srrh register int dflg;
395af085800Srrh char last;
39670468683Srrh
39770468683Srrh last=0;
39870468683Srrh dflg = 1;
39970468683Srrh SKIP;
40070468683Srrh
40170468683Srrh for( ;;)
40270468683Srrh {
403af085800Srrh if(C1 == '.' || c == '\'')
40470468683Srrh {
405af085800Srrh while(C1==' ' || c=='\t')
40670468683Srrh ;
407af085800Srrh if(c=='E' && C1=='N')
40870468683Srrh {
40970468683Srrh SKIP;
41070468683Srrh if(msflag && dflg){
41170468683Srrh putchar('x');
41270468683Srrh putchar(' ');
413af085800Srrh if(last){
414af085800Srrh putchar(last);
415af085800Srrh putchar('\n');
416af085800Srrh }
41770468683Srrh }
41870468683Srrh return;
41970468683Srrh }
42070468683Srrh }
42170468683Srrh else if(c == 'd') /* look for delim */
42270468683Srrh {
423af085800Srrh if(C1=='e' && C1=='l')
424af085800Srrh if( C1=='i' && C1=='m')
42570468683Srrh {
42670468683Srrh while(C1 == ' ');
42770468683Srrh if((c1=c)=='\n' || (c2=C1)=='\n'
42870468683Srrh || (c1=='o' && c2=='f' && C1=='f') )
42970468683Srrh {
43070468683Srrh ldelim = NOCHAR;
43170468683Srrh rdelim = NOCHAR;
43270468683Srrh }
43370468683Srrh else {
43470468683Srrh ldelim = c1;
43570468683Srrh rdelim = c2;
43670468683Srrh }
43770468683Srrh }
43870468683Srrh dflg = 0;
43970468683Srrh }
44070468683Srrh
441af085800Srrh if(c != '\n') while(C1 != '\n'){
442af085800Srrh if(chars[c] == PUNCT)last = c;
443af085800Srrh else if(c != ' ')last = 0;
444af085800Srrh }
44570468683Srrh }
44670468683Srrh }
44770468683Srrh
backsl()44870468683Srrh backsl() /* skip over a complete backslash construction */
44970468683Srrh {
45070468683Srrh int bdelim;
45170468683Srrh
452af085800Srrh sw:
453af085800Srrh switch(C)
45470468683Srrh {
45570468683Srrh case '"':
45670468683Srrh SKIP;
45770468683Srrh return;
45870468683Srrh case 's':
45970468683Srrh if(C == '\\') backsl();
46070468683Srrh else {
46170468683Srrh while(C>='0' && c<='9') ;
46270468683Srrh ungetc(c,infile);
46370468683Srrh c = '0';
46470468683Srrh }
46570468683Srrh --lp;
46670468683Srrh return;
46770468683Srrh
46870468683Srrh case 'f':
46970468683Srrh case 'n':
47070468683Srrh case '*':
47170468683Srrh if(C != '(')
47270468683Srrh return;
47370468683Srrh
47470468683Srrh case '(':
475af085800Srrh if(msflag){
476af085800Srrh if(C == 'e'){
477af085800Srrh if(C == 'm'){
478af085800Srrh *lp = '-';
479af085800Srrh return;
480af085800Srrh }
481af085800Srrh }
482af085800Srrh else if(c != '\n')C;
483af085800Srrh return;
484af085800Srrh }
48570468683Srrh if(C != '\n') C;
48670468683Srrh return;
48770468683Srrh
48870468683Srrh case '$':
48970468683Srrh C; /* discard argument number */
49070468683Srrh return;
49170468683Srrh
49270468683Srrh case 'b':
49370468683Srrh case 'x':
49470468683Srrh case 'v':
49570468683Srrh case 'h':
49670468683Srrh case 'w':
49770468683Srrh case 'o':
49870468683Srrh case 'l':
49970468683Srrh case 'L':
50070468683Srrh if( (bdelim=C) == '\n')
50170468683Srrh return;
50270468683Srrh while(C!='\n' && c!=bdelim)
50370468683Srrh if(c == '\\') backsl();
50470468683Srrh return;
50570468683Srrh
50670468683Srrh case '\\':
50770468683Srrh if(inmacro)
50870468683Srrh goto sw;
50970468683Srrh default:
51070468683Srrh return;
51170468683Srrh }
51270468683Srrh }
51370468683Srrh
copys(s)51470468683Srrh char *copys(s)
51570468683Srrh register char *s;
51670468683Srrh {
51770468683Srrh register char *t, *t0;
51870468683Srrh
519af085800Srrh if( (t0 = t = calloc( (unsigned)(strlen(s)+1), sizeof(*t) ) ) == NULL)
52070468683Srrh fatal("Cannot allocate memory", (char *) NULL);
52170468683Srrh
52270468683Srrh while( *t++ = *s++ )
52370468683Srrh ;
52470468683Srrh return(t0);
52570468683Srrh }
526b43b9614Srrh
sce()527b43b9614Srrh sce()
528b43b9614Srrh {
52970468683Srrh register char *ap;
53070468683Srrh register int n, i;
53170468683Srrh char a[10];
53270468683Srrh for(ap=a;C != '\n';ap++){
53370468683Srrh *ap = c;
53470468683Srrh if(ap == &a[9]){
53570468683Srrh SKIP;
53670468683Srrh ap=a;
53770468683Srrh break;
53870468683Srrh }
53970468683Srrh }
54070468683Srrh if(ap != a)n = atoi(a);
54170468683Srrh else n = 1;
54270468683Srrh for(i=0;i<n;){
54370468683Srrh if(C == '.'){
54470468683Srrh if(C == 'c'){
54570468683Srrh if(C == 'e'){
54670468683Srrh while(C == ' ');
547af085800Srrh if(c == '0'){
548af085800Srrh SKIP;
549af085800Srrh break;
55070468683Srrh }
55170468683Srrh else SKIP;
55270468683Srrh }
55370468683Srrh else SKIP;
55470468683Srrh }
555af085800Srrh else if(c == 'P' || C == 'P'){
556af085800Srrh if(c != '\n')SKIP;
557af085800Srrh break;
558af085800Srrh }
559af085800Srrh else if(c != '\n')SKIP;
560af085800Srrh }
56170468683Srrh else {
56270468683Srrh SKIP;
56370468683Srrh i++;
56470468683Srrh }
56570468683Srrh }
56670468683Srrh }
567b43b9614Srrh
refer(c1)568af085800Srrh refer(c1)
569af085800Srrh {
570af085800Srrh register int c2;
571af085800Srrh if(c1 != '\n')
572af085800Srrh SKIP;
573af085800Srrh while(1){
574af085800Srrh if(C != '.')
575af085800Srrh SKIP;
576af085800Srrh else {
577af085800Srrh if(C != ']')
578af085800Srrh SKIP;
579af085800Srrh else {
580af085800Srrh while(C != '\n')
581af085800Srrh c2=c;
582af085800Srrh if(chars[c2] == PUNCT)putchar(c2);
583af085800Srrh return;
584af085800Srrh }
585af085800Srrh }
586af085800Srrh }
587af085800Srrh }
588b43b9614Srrh
inpic()589b43b9614Srrh inpic()
590b43b9614Srrh {
591af085800Srrh register int c1;
592af085800Srrh register char *p1;
593af085800Srrh SKIP;
594af085800Srrh p1 = line;
595af085800Srrh c = '\n';
596af085800Srrh while(1){
597af085800Srrh c1 = c;
598af085800Srrh if(C == '.' && c1 == '\n'){
599af085800Srrh if(C != 'P'){
600af085800Srrh if(c == '\n')continue;
601af085800Srrh else { SKIP; c='\n'; continue;}
602af085800Srrh }
603af085800Srrh if(C != 'E'){
604af085800Srrh if(c == '\n')continue;
605af085800Srrh else { SKIP; c='\n';continue; }
606af085800Srrh }
607af085800Srrh SKIP;
608af085800Srrh return;
609af085800Srrh }
610af085800Srrh else if(c == '\"'){
611af085800Srrh while(C != '\"'){
612af085800Srrh if(c == '\\'){
613af085800Srrh if(C == '\"')continue;
614af085800Srrh ungetc(c,infile);
615af085800Srrh backsl();
616af085800Srrh }
617af085800Srrh else *p1++ = c;
618af085800Srrh }
619af085800Srrh *p1++ = ' ';
620af085800Srrh }
621af085800Srrh else if(c == '\n' && p1 != line){
622af085800Srrh *p1 = '\0';
623b43b9614Srrh if(wordflag)msputwords(NO);
624af085800Srrh else {
625af085800Srrh puts(line);
626af085800Srrh putchar('\n');
627af085800Srrh }
628af085800Srrh p1 = line;
629af085800Srrh }
630af085800Srrh }
631af085800Srrh }
632b43b9614Srrh
633b43b9614Srrh #ifdef DEBUG
_C1()634b43b9614Srrh _C1()
635b43b9614Srrh {
636b43b9614Srrh return(C1get);
637b43b9614Srrh }
_C()638b43b9614Srrh _C()
639b43b9614Srrh {
640b43b9614Srrh return(Cget);
641b43b9614Srrh }
642b43b9614Srrh #endif DEBUG
643b43b9614Srrh
644b43b9614Srrh /*
645b43b9614Srrh * Macro processing
646b43b9614Srrh *
647b43b9614Srrh * Macro table definitions
648b43b9614Srrh */
649b43b9614Srrh #define reg register
650b43b9614Srrh typedef int pacmac; /* compressed macro name */
651b43b9614Srrh int argconcat = 0; /* concat arguments together (-me only) */
652b43b9614Srrh
653b43b9614Srrh #define tomac(c1, c2) ((((c1) & 0xFF) << 8) | ((c2) & 0xFF))
654b43b9614Srrh #define frommac(src, c1, c2) (((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF))
655b43b9614Srrh
656b43b9614Srrh struct mactab{
657b43b9614Srrh int condition;
658b43b9614Srrh pacmac macname;
659b43b9614Srrh int (*func)();
660b43b9614Srrh };
661b43b9614Srrh struct mactab troffmactab[];
662b43b9614Srrh struct mactab ppmactab[];
663b43b9614Srrh struct mactab msmactab[];
664b43b9614Srrh struct mactab mmmactab[];
665b43b9614Srrh struct mactab memactab[];
666b43b9614Srrh struct mactab manmactab[];
667b43b9614Srrh /*
668b43b9614Srrh * macro table initialization
669b43b9614Srrh */
670b43b9614Srrh #define M(cond, c1, c2, func) {cond, tomac(c1, c2), func}
671b43b9614Srrh
672b43b9614Srrh /*
673b43b9614Srrh * Put out a macro line, using ms and mm conventions.
674b43b9614Srrh */
msputmac(s,constant)6758baa3d18Sbostic msputmac(s, constant)
676b43b9614Srrh register char *s;
6778baa3d18Sbostic int constant;
678b43b9614Srrh {
679b43b9614Srrh register char *t;
680b43b9614Srrh register found;
681b43b9614Srrh int last;
682b43b9614Srrh found = 0;
683b43b9614Srrh
684b43b9614Srrh if (wordflag) {
685b43b9614Srrh msputwords(YES);
686b43b9614Srrh return;
687b43b9614Srrh }
688b43b9614Srrh while(*s)
689b43b9614Srrh {
690b43b9614Srrh while(*s==' ' || *s=='\t')
691b43b9614Srrh putchar(*s++);
692b43b9614Srrh for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t)
693b43b9614Srrh ;
694b43b9614Srrh if(*s == '\"')s++;
6958baa3d18Sbostic if(t>s+constant && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER){
696b43b9614Srrh while(s < t)
697b43b9614Srrh if(*s == '\"')s++;
698b43b9614Srrh else
699b43b9614Srrh putchar(*s++);
700b43b9614Srrh last = *(t-1);
701b43b9614Srrh found++;
702b43b9614Srrh }
703b43b9614Srrh else if(found && chars[ s[0] ] == PUNCT && s[1] == '\0')
704b43b9614Srrh putchar(*s++);
705b43b9614Srrh else{
706b43b9614Srrh last = *(t-1);
707b43b9614Srrh s = t;
708b43b9614Srrh }
709b43b9614Srrh }
710b43b9614Srrh putchar('\n');
711b43b9614Srrh if(msflag && chars[last] == PUNCT){
712b43b9614Srrh putchar(last);
713b43b9614Srrh putchar('\n');
714b43b9614Srrh }
715b43b9614Srrh }
716b43b9614Srrh /*
717b43b9614Srrh * put out words (for the -w option) with ms and mm conventions
718b43b9614Srrh */
msputwords(macline)719b43b9614Srrh msputwords(macline)
720b43b9614Srrh int macline; /* is this is a macro line */
721b43b9614Srrh {
722b43b9614Srrh register char *p, *p1;
723b43b9614Srrh int i, nlet;
724b43b9614Srrh
725b43b9614Srrh for(p1 = line ; ;) {
726b43b9614Srrh /*
727b43b9614Srrh * skip initial specials ampersands and apostrophes
728b43b9614Srrh */
729b43b9614Srrh while( chars[*p1] < DIGIT)
730b43b9614Srrh if(*p1++ == '\0') return;
731b43b9614Srrh nlet = 0;
732b43b9614Srrh for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p)
733b43b9614Srrh if(i == LETTER) ++nlet;
734b43b9614Srrh
735ffcb7197Sralph if (nlet > 1 && chars[p1[0]] == LETTER) {
736b43b9614Srrh /*
737b43b9614Srrh * delete trailing ampersands and apostrophes
738b43b9614Srrh */
739ffcb7197Sralph while( (i=chars[p[-1]]) == PUNCT || i == APOS )
740b43b9614Srrh --p;
741b43b9614Srrh while(p1 < p)
742b43b9614Srrh putchar(*p1++);
743b43b9614Srrh putchar('\n');
744b43b9614Srrh } else {
745b43b9614Srrh p1 = p;
746b43b9614Srrh }
747b43b9614Srrh }
748b43b9614Srrh }
749b43b9614Srrh /*
750b43b9614Srrh * put out a macro using the me conventions
751b43b9614Srrh */
752b43b9614Srrh #define SKIPBLANK(cp) while(*cp == ' ' || *cp == '\t') { cp++; }
753b43b9614Srrh #define SKIPNONBLANK(cp) while(*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
754b43b9614Srrh
meputmac(cp,constant)7558baa3d18Sbostic meputmac(cp, constant)
756b43b9614Srrh reg char *cp;
7578baa3d18Sbostic int constant;
758b43b9614Srrh {
759b43b9614Srrh reg char *np;
760b43b9614Srrh int found;
761b43b9614Srrh int argno;
762b43b9614Srrh int last;
763b43b9614Srrh int inquote;
764b43b9614Srrh
765b43b9614Srrh if (wordflag) {
766b43b9614Srrh meputwords(YES);
767b43b9614Srrh return;
768b43b9614Srrh }
769b43b9614Srrh for (argno = 0; *cp; argno++){
770b43b9614Srrh SKIPBLANK(cp);
771b43b9614Srrh inquote = (*cp == '"');
772b43b9614Srrh if (inquote)
773b43b9614Srrh cp++;
774b43b9614Srrh for (np = cp; *np; np++){
775b43b9614Srrh switch(*np){
776b43b9614Srrh case '\n':
777b43b9614Srrh case '\0': break;
778b43b9614Srrh case '\t':
779b43b9614Srrh case ' ': if (inquote) {
780b43b9614Srrh continue;
781b43b9614Srrh } else {
782b43b9614Srrh goto endarg;
783b43b9614Srrh }
784b43b9614Srrh case '"': if(inquote && np[1] == '"'){
785b43b9614Srrh strcpy(np, np + 1);
786b43b9614Srrh np++;
787b43b9614Srrh continue;
788b43b9614Srrh } else {
789b43b9614Srrh *np = ' '; /* bye bye " */
790b43b9614Srrh goto endarg;
791b43b9614Srrh }
792b43b9614Srrh default: continue;
793b43b9614Srrh }
794b43b9614Srrh }
795b43b9614Srrh endarg: ;
796b43b9614Srrh /*
797b43b9614Srrh * cp points at the first char in the arg
798b43b9614Srrh * np points one beyond the last char in the arg
799b43b9614Srrh */
800b43b9614Srrh if ((argconcat == 0) || (argconcat != argno)) {
801b43b9614Srrh putchar(' ');
802b43b9614Srrh }
803b43b9614Srrh #ifdef FULLDEBUG
804b43b9614Srrh {
805b43b9614Srrh char *p;
806b43b9614Srrh printf("[%d,%d: ", argno, np - cp);
807b43b9614Srrh for (p = cp; p < np; p++) {
808b43b9614Srrh putchar(*p);
809b43b9614Srrh }
810b43b9614Srrh printf("]");
811b43b9614Srrh }
812b43b9614Srrh #endif FULLDEBUG
813b43b9614Srrh /*
814b43b9614Srrh * Determine if the argument merits being printed
815b43b9614Srrh *
8168baa3d18Sbostic * constant is the cut off point below which something
817b43b9614Srrh * is not a word.
818b43b9614Srrh */
8198baa3d18Sbostic if ( ( (np - cp) > constant)
820b43b9614Srrh && ( inquote
821b43b9614Srrh || (chars[cp[0]] == LETTER)) ){
822b43b9614Srrh for (cp = cp; cp < np; cp++){
823b43b9614Srrh putchar(*cp);
824b43b9614Srrh }
825b43b9614Srrh last = np[-1];
826b43b9614Srrh found++;
827b43b9614Srrh } else
828b43b9614Srrh if(found && (np - cp == 1) && chars[*cp] == PUNCT){
829b43b9614Srrh putchar(*cp);
830b43b9614Srrh } else {
831b43b9614Srrh last = np[-1];
832b43b9614Srrh }
833b43b9614Srrh cp = np;
834b43b9614Srrh }
835b43b9614Srrh if(msflag && chars[last] == PUNCT)
836b43b9614Srrh putchar(last);
837b43b9614Srrh putchar('\n');
838b43b9614Srrh }
839b43b9614Srrh /*
840b43b9614Srrh * put out words (for the -w option) with ms and mm conventions
841b43b9614Srrh */
meputwords(macline)842b43b9614Srrh meputwords(macline)
843b43b9614Srrh int macline;
844b43b9614Srrh {
845b43b9614Srrh msputwords(macline);
846b43b9614Srrh }
847b43b9614Srrh /*
848b43b9614Srrh *
849b43b9614Srrh * Skip over a nested set of macros
850b43b9614Srrh *
851b43b9614Srrh * Possible arguments to noblock are:
852b43b9614Srrh *
853b43b9614Srrh * fi end of unfilled text
854b43b9614Srrh * PE pic ending
855b43b9614Srrh * DE display ending
856b43b9614Srrh *
857b43b9614Srrh * for ms and mm only:
858b43b9614Srrh * KE keep ending
859b43b9614Srrh *
860b43b9614Srrh * NE undocumented match to NS (for mm?)
861b43b9614Srrh * LE mm only: matches RL or *L (for lists)
862b43b9614Srrh *
863b43b9614Srrh * for me:
864b43b9614Srrh * ([lqbzcdf]
865b43b9614Srrh */
866b43b9614Srrh
noblock(a1,a2)867b43b9614Srrh noblock(a1, a2)
868b43b9614Srrh char a1, a2;
869b43b9614Srrh {
870b43b9614Srrh register int c1,c2;
871b43b9614Srrh register int eqnf;
872b43b9614Srrh int lct;
873b43b9614Srrh lct = 0;
874b43b9614Srrh eqnf = 1;
875b43b9614Srrh SKIP;
876b43b9614Srrh while(1){
877b43b9614Srrh while(C != '.')
878b43b9614Srrh if(c == '\n')
879b43b9614Srrh continue;
880b43b9614Srrh else
881b43b9614Srrh SKIP;
882b43b9614Srrh if((c1=C) == '\n')
883b43b9614Srrh continue;
884b43b9614Srrh if((c2=C) == '\n')
885b43b9614Srrh continue;
886b43b9614Srrh if(c1==a1 && c2 == a2){
887b43b9614Srrh SKIP;
888b43b9614Srrh if(lct != 0){
889b43b9614Srrh lct--;
890b43b9614Srrh continue;
891b43b9614Srrh }
892b43b9614Srrh if(eqnf)
893b43b9614Srrh putchar('.');
894b43b9614Srrh putchar('\n');
895b43b9614Srrh return;
896b43b9614Srrh } else if(a1 == 'L' && c2 == 'L'){
897b43b9614Srrh lct++;
898b43b9614Srrh SKIP;
899b43b9614Srrh }
900b43b9614Srrh /*
901b43b9614Srrh * equations (EQ) nested within a display
902b43b9614Srrh */
903b43b9614Srrh else if(c1 == 'E' && c2 == 'Q'){
904b43b9614Srrh if ( (mac == ME && a1 == ')')
905b43b9614Srrh || (mac != ME && a1 == 'D') ) {
906b43b9614Srrh eqn();
907b43b9614Srrh eqnf=0;
908b43b9614Srrh }
909b43b9614Srrh }
910b43b9614Srrh /*
911b43b9614Srrh * turning on filling is done by the paragraphing
912b43b9614Srrh * macros
913b43b9614Srrh */
914b43b9614Srrh else if(a1 == 'f') { /* .fi */
915b43b9614Srrh if ( (mac == ME && (c2 == 'h' || c2 == 'p'))
916b43b9614Srrh ||(mac != ME && (c1 == 'P' || c2 == 'P')) ) {
917b43b9614Srrh SKIP;
918b43b9614Srrh return;
919b43b9614Srrh }
920b43b9614Srrh } else {
921b43b9614Srrh SKIP;
922b43b9614Srrh }
923b43b9614Srrh }
924b43b9614Srrh }
925b43b9614Srrh
EQ()926b43b9614Srrh EQ()
927b43b9614Srrh {
928b43b9614Srrh eqn();
929b43b9614Srrh return(0);
930b43b9614Srrh }
domacro()931b43b9614Srrh domacro()
932b43b9614Srrh {
933b43b9614Srrh macro();
934b43b9614Srrh return(0);
935b43b9614Srrh }
PS()936b43b9614Srrh PS()
937b43b9614Srrh {
9380ce649f8Sbostic for (C; c == ' ' || c == '\t'; C);
9390ce649f8Sbostic if (c == '<') { /* ".PS < file" -- don't expect a .PE */
9400ce649f8Sbostic SKIP;
9410ce649f8Sbostic return(0);
9420ce649f8Sbostic }
943b43b9614Srrh if (!msflag) {
944b43b9614Srrh inpic();
945b43b9614Srrh } else {
946b43b9614Srrh noblock('P', 'E');
947b43b9614Srrh }
948b43b9614Srrh return(0);
949b43b9614Srrh }
950b43b9614Srrh
skip()951b43b9614Srrh skip()
952b43b9614Srrh {
953b43b9614Srrh SKIP;
954b43b9614Srrh return(0);
955b43b9614Srrh }
956b43b9614Srrh
intbl()957b43b9614Srrh intbl()
958b43b9614Srrh {
959b43b9614Srrh if(msflag){
960b43b9614Srrh stbl();
961b43b9614Srrh }
962b43b9614Srrh else tbl();
963b43b9614Srrh return(0);
964b43b9614Srrh }
965b43b9614Srrh
outtbl()966b43b9614Srrh outtbl(){ intable = NO; }
967b43b9614Srrh
so()968b43b9614Srrh so()
969b43b9614Srrh {
970b43b9614Srrh getfname();
971b43b9614Srrh if( fname[0] )
972b43b9614Srrh infile = *++filesp = opn( fname );
973b43b9614Srrh return(0);
974b43b9614Srrh }
nx()975b43b9614Srrh nx()
976b43b9614Srrh {
977b43b9614Srrh getfname();
978b43b9614Srrh if(fname[0] == '\0') exit(0);
979b43b9614Srrh if(infile != stdin)
980b43b9614Srrh fclose(infile);
981b43b9614Srrh infile = *filesp = opn(fname);
982b43b9614Srrh return(0);
983b43b9614Srrh }
skiptocom()984b43b9614Srrh skiptocom(){ SKIP_TO_COM; return(COMX); }
985b43b9614Srrh
PP(c12)986b43b9614Srrh PP(c12)
987b43b9614Srrh pacmac c12;
988b43b9614Srrh {
989b43b9614Srrh int c1, c2;
990b43b9614Srrh
991b43b9614Srrh frommac(c12, c1, c2);
992b43b9614Srrh printf(".%c%c",c1,c2);
993b43b9614Srrh while(C != '\n')putchar(c);
994b43b9614Srrh putchar('\n');
995b43b9614Srrh return(0);
996b43b9614Srrh }
AU()997b43b9614Srrh AU()
998b43b9614Srrh {
999b43b9614Srrh if(mac==MM) {
1000b43b9614Srrh return(0);
1001b43b9614Srrh } else {
1002b43b9614Srrh SKIP_TO_COM;
1003b43b9614Srrh return(COMX);
1004b43b9614Srrh }
1005b43b9614Srrh }
1006b43b9614Srrh
SH(c12)1007b43b9614Srrh SH(c12)
1008b43b9614Srrh pacmac c12;
1009b43b9614Srrh {
1010b43b9614Srrh int c1, c2;
1011b43b9614Srrh
1012b43b9614Srrh frommac(c12, c1, c2);
1013b43b9614Srrh
1014b43b9614Srrh if(parag){
1015b43b9614Srrh printf(".%c%c",c1,c2);
1016b43b9614Srrh while(C != '\n')putchar(c);
1017b43b9614Srrh putchar(c);
1018b43b9614Srrh putchar('!');
1019b43b9614Srrh while(1){
1020b43b9614Srrh while(C != '\n')putchar(c);
1021b43b9614Srrh putchar('\n');
1022b43b9614Srrh if(C == '.')
1023b43b9614Srrh return(COM);
1024b43b9614Srrh putchar('!');
1025b43b9614Srrh putchar(c);
1026b43b9614Srrh }
1027b43b9614Srrh /*NOTREACHED*/
1028b43b9614Srrh } else {
1029b43b9614Srrh SKIP_TO_COM;
1030b43b9614Srrh return(COMX);
1031b43b9614Srrh }
1032b43b9614Srrh }
1033b43b9614Srrh
UX()1034b43b9614Srrh UX()
1035b43b9614Srrh {
1036b43b9614Srrh if(wordflag)
1037b43b9614Srrh printf("UNIX\n");
1038b43b9614Srrh else
1039b43b9614Srrh printf("UNIX ");
1040b43b9614Srrh return(0);
1041b43b9614Srrh }
1042b43b9614Srrh
MMHU(c12)1043b43b9614Srrh MMHU(c12)
1044b43b9614Srrh pacmac c12;
1045b43b9614Srrh {
1046b43b9614Srrh int c1, c2;
1047b43b9614Srrh
1048b43b9614Srrh frommac(c12, c1, c2);
1049b43b9614Srrh if(parag){
1050b43b9614Srrh printf(".%c%c",c1,c2);
1051b43b9614Srrh while(C != '\n')putchar(c);
1052b43b9614Srrh putchar('\n');
1053b43b9614Srrh } else {
1054b43b9614Srrh SKIP;
1055b43b9614Srrh }
1056b43b9614Srrh return(0);
1057b43b9614Srrh }
1058b43b9614Srrh
mesnblock(c12)1059b43b9614Srrh mesnblock(c12)
1060b43b9614Srrh pacmac c12;
1061b43b9614Srrh {
1062b43b9614Srrh int c1, c2;
1063b43b9614Srrh
1064b43b9614Srrh frommac(c12, c1, c2);
1065b43b9614Srrh noblock(')',c2);
1066b43b9614Srrh return(0);
1067b43b9614Srrh }
mssnblock(c12)1068b43b9614Srrh mssnblock(c12)
1069b43b9614Srrh pacmac c12;
1070b43b9614Srrh {
1071b43b9614Srrh int c1, c2;
1072b43b9614Srrh
1073b43b9614Srrh frommac(c12, c1, c2);
1074b43b9614Srrh noblock(c1,'E');
1075b43b9614Srrh return(0);
1076b43b9614Srrh }
nf()1077b43b9614Srrh nf()
1078b43b9614Srrh {
1079b43b9614Srrh noblock('f','i');
1080b43b9614Srrh return(0);
1081b43b9614Srrh }
1082b43b9614Srrh
ce()1083b43b9614Srrh ce()
1084b43b9614Srrh {
1085b43b9614Srrh sce();
1086b43b9614Srrh return(0);
1087b43b9614Srrh }
1088b43b9614Srrh
meip(c12)1089b43b9614Srrh meip(c12)
1090b43b9614Srrh pacmac c12;
1091b43b9614Srrh {
1092b43b9614Srrh if(parag)
1093b43b9614Srrh mepp(c12);
1094b43b9614Srrh else if (wordflag) /* save the tag */
1095b43b9614Srrh regline(meputmac, ONE);
1096b43b9614Srrh else {
1097b43b9614Srrh SKIP;
1098b43b9614Srrh }
1099b43b9614Srrh return(0);
1100b43b9614Srrh }
1101b43b9614Srrh /*
1102b43b9614Srrh * only called for -me .pp or .sh, when parag is on
1103b43b9614Srrh */
mepp(c12)1104b43b9614Srrh mepp(c12)
1105b43b9614Srrh pacmac c12;
1106b43b9614Srrh {
1107b43b9614Srrh PP(c12); /* eats the line */
1108b43b9614Srrh return(0);
1109b43b9614Srrh }
1110b43b9614Srrh /*
1111b43b9614Srrh * Start of a section heading; output the section name if doing words
1112b43b9614Srrh */
mesh(c12)1113b43b9614Srrh mesh(c12)
1114b43b9614Srrh pacmac c12;
1115b43b9614Srrh {
1116b43b9614Srrh if (parag)
1117b43b9614Srrh mepp(c12);
1118b43b9614Srrh else if (wordflag)
1119b43b9614Srrh defcomline(c12);
1120b43b9614Srrh else {
1121b43b9614Srrh SKIP;
1122b43b9614Srrh }
1123b43b9614Srrh return(0);
1124b43b9614Srrh }
1125b43b9614Srrh /*
1126b43b9614Srrh * process a font setting
1127b43b9614Srrh */
mefont(c12)1128b43b9614Srrh mefont(c12)
1129b43b9614Srrh pacmac c12;
1130b43b9614Srrh {
1131b43b9614Srrh argconcat = 1;
1132b43b9614Srrh defcomline(c12);
1133b43b9614Srrh argconcat = 0;
1134b43b9614Srrh return(0);
1135b43b9614Srrh }
manfont(c12)1136b43b9614Srrh manfont(c12)
1137b43b9614Srrh pacmac c12;
1138b43b9614Srrh {
1139b43b9614Srrh return(mefont(c12));
1140b43b9614Srrh }
manpp(c12)1141b43b9614Srrh manpp(c12)
1142b43b9614Srrh pacmac c12;
1143b43b9614Srrh {
1144b43b9614Srrh return(mepp(c12));
1145b43b9614Srrh }
1146b43b9614Srrh
defcomline(c12)1147b43b9614Srrh defcomline(c12)
1148b43b9614Srrh pacmac c12;
1149b43b9614Srrh {
1150b43b9614Srrh int c1, c2;
1151b43b9614Srrh
1152b43b9614Srrh frommac(c12, c1, c2);
1153b43b9614Srrh if(msflag && mac==MM && c2=='L'){
1154b43b9614Srrh if(disp || c1 == 'R') {
1155b43b9614Srrh noblock('L','E');
1156b43b9614Srrh } else {
1157b43b9614Srrh SKIP;
1158b43b9614Srrh putchar('.');
1159b43b9614Srrh }
1160b43b9614Srrh }
1161b43b9614Srrh else if(c1=='.' && c2=='.'){
1162b43b9614Srrh if(msflag){
1163b43b9614Srrh SKIP;
1164b43b9614Srrh return;
1165b43b9614Srrh }
1166b43b9614Srrh while(C == '.')
1167b43b9614Srrh /*VOID*/;
1168b43b9614Srrh }
1169b43b9614Srrh ++inmacro;
1170b43b9614Srrh /*
1171b43b9614Srrh * Process the arguments to the macro
1172b43b9614Srrh */
1173b43b9614Srrh switch(mac){
1174b43b9614Srrh default:
1175b43b9614Srrh case MM:
1176b43b9614Srrh case MS:
1177b43b9614Srrh if(c1 <= 'Z' && msflag)
1178b43b9614Srrh regline(msputmac, ONE);
1179b43b9614Srrh else
1180b43b9614Srrh regline(msputmac, TWO);
1181b43b9614Srrh break;
1182b43b9614Srrh case ME:
1183b43b9614Srrh regline(meputmac, ONE);
1184b43b9614Srrh break;
1185b43b9614Srrh }
1186b43b9614Srrh --inmacro;
1187b43b9614Srrh }
1188b43b9614Srrh
comline()1189b43b9614Srrh comline()
1190b43b9614Srrh {
1191b43b9614Srrh reg int c1;
1192b43b9614Srrh reg int c2;
1193b43b9614Srrh pacmac c12;
1194b43b9614Srrh reg int mid;
1195b43b9614Srrh int lb, ub;
1196b43b9614Srrh int hit;
1197b43b9614Srrh static int tabsize = 0;
1198b43b9614Srrh static struct mactab *mactab = (struct mactab *)0;
1199b43b9614Srrh reg struct mactab *mp;
1200b43b9614Srrh
1201b43b9614Srrh if (mactab == 0){
1202b43b9614Srrh buildtab(&mactab, &tabsize);
1203b43b9614Srrh }
1204b43b9614Srrh com:
1205b43b9614Srrh while(C==' ' || c=='\t')
1206b43b9614Srrh ;
1207b43b9614Srrh comx:
1208b43b9614Srrh if( (c1=c) == '\n')
1209b43b9614Srrh return;
1210b43b9614Srrh c2 = C;
1211b43b9614Srrh if(c1=='.' && c2 !='.')
1212b43b9614Srrh inmacro = NO;
1213b43b9614Srrh if(msflag && c1 == '['){
1214b43b9614Srrh refer(c2);
1215b43b9614Srrh return;
1216b43b9614Srrh }
1217b43b9614Srrh if(parag && mac==MM && c1 == 'P' && c2 == '\n'){
1218b43b9614Srrh printf(".P\n");
1219b43b9614Srrh return;
1220b43b9614Srrh }
1221b43b9614Srrh if(c2 == '\n')
1222b43b9614Srrh return;
1223b43b9614Srrh /*
1224b43b9614Srrh * Single letter macro
1225b43b9614Srrh */
1226b43b9614Srrh if (mac == ME && (c2 == ' ' || c2 == '\t') )
1227b43b9614Srrh c2 = ' ';
1228b43b9614Srrh c12 = tomac(c1, c2);
1229b43b9614Srrh /*
1230b43b9614Srrh * binary search through the table of macros
1231b43b9614Srrh */
1232b43b9614Srrh lb = 0;
1233b43b9614Srrh ub = tabsize - 1;
1234b43b9614Srrh while(lb <= ub){
1235b43b9614Srrh mid = (ub + lb) / 2;
1236b43b9614Srrh mp = &mactab[mid];
1237b43b9614Srrh if (mp->macname < c12)
1238b43b9614Srrh lb = mid + 1;
1239b43b9614Srrh else if (mp->macname > c12)
1240b43b9614Srrh ub = mid - 1;
1241b43b9614Srrh else {
1242b43b9614Srrh hit = 1;
1243b43b9614Srrh #ifdef FULLDEBUG
1244b43b9614Srrh printf("preliminary hit macro %c%c ", c1, c2);
1245b43b9614Srrh #endif FULLDEBUG
1246b43b9614Srrh switch(mp->condition){
1247b43b9614Srrh case NONE: hit = YES; break;
1248b43b9614Srrh case FNEST: hit = (filesp == files); break;
1249b43b9614Srrh case NOMAC: hit = !inmacro; break;
1250b43b9614Srrh case MAC: hit = inmacro; break;
1251b43b9614Srrh case PARAG: hit = parag; break;
1252b43b9614Srrh case NBLK: hit = !keepblock; break;
1253b43b9614Srrh default: hit = 0;
1254b43b9614Srrh }
1255b43b9614Srrh if (hit) {
1256b43b9614Srrh #ifdef FULLDEBUG
1257b43b9614Srrh printf("MATCH\n");
1258b43b9614Srrh #endif FULLDEBUG
1259b43b9614Srrh switch( (*(mp->func))(c12) ) {
1260b43b9614Srrh default: return;
1261b43b9614Srrh case COMX: goto comx;
1262b43b9614Srrh case COM: goto com;
1263b43b9614Srrh }
1264b43b9614Srrh }
1265b43b9614Srrh #ifdef FULLDEBUG
1266b43b9614Srrh printf("FAIL\n");
1267b43b9614Srrh #endif FULLDEBUG
1268b43b9614Srrh break;
1269b43b9614Srrh }
1270b43b9614Srrh }
1271b43b9614Srrh defcomline(c12);
1272b43b9614Srrh }
1273b43b9614Srrh
macsort(p1,p2)1274b43b9614Srrh int macsort(p1, p2)
1275b43b9614Srrh struct mactab *p1, *p2;
1276b43b9614Srrh {
1277b43b9614Srrh return(p1->macname - p2->macname);
1278b43b9614Srrh }
1279b43b9614Srrh
sizetab(mp)1280b43b9614Srrh int sizetab(mp)
1281b43b9614Srrh reg struct mactab *mp;
1282b43b9614Srrh {
1283b43b9614Srrh reg int i;
1284b43b9614Srrh i = 0;
1285b43b9614Srrh if (mp){
1286b43b9614Srrh for (; mp->macname; mp++, i++)
1287b43b9614Srrh /*VOID*/ ;
1288b43b9614Srrh }
1289b43b9614Srrh return(i);
1290b43b9614Srrh }
1291b43b9614Srrh
macfill(dst,src)1292b43b9614Srrh struct mactab *macfill(dst, src)
1293b43b9614Srrh reg struct mactab *dst;
1294b43b9614Srrh reg struct mactab *src;
1295b43b9614Srrh {
1296b43b9614Srrh if (src) {
1297b43b9614Srrh while(src->macname){
1298b43b9614Srrh *dst++ = *src++;
1299b43b9614Srrh }
1300b43b9614Srrh }
1301b43b9614Srrh return(dst);
1302b43b9614Srrh }
1303b43b9614Srrh
1304b43b9614Srrh buildtab(r_back, r_size)
1305b43b9614Srrh struct mactab **r_back;
1306b43b9614Srrh int *r_size;
1307b43b9614Srrh {
1308b43b9614Srrh int size;
1309b43b9614Srrh
1310b43b9614Srrh struct mactab *p, *p1, *p2;
1311b43b9614Srrh struct mactab *back;
1312b43b9614Srrh
1313b43b9614Srrh size = sizetab(troffmactab);
1314b43b9614Srrh size += sizetab(ppmactab);
1315b43b9614Srrh p1 = p2 = (struct mactab *)0;
1316b43b9614Srrh if (msflag){
1317b43b9614Srrh switch(mac){
1318b43b9614Srrh case ME: p1 = memactab; break;
1319b43b9614Srrh case MM: p1 = msmactab;
1320b43b9614Srrh p2 = mmmactab; break;
1321b43b9614Srrh
1322b43b9614Srrh case MS: p1 = msmactab; break;
1323b43b9614Srrh case MA: p1 = manmactab; break;
1324b43b9614Srrh default: break;
1325b43b9614Srrh }
1326b43b9614Srrh }
1327b43b9614Srrh size += sizetab(p1);
1328b43b9614Srrh size += sizetab(p2);
1329b43b9614Srrh back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
1330b43b9614Srrh
1331b43b9614Srrh p = macfill(back, troffmactab);
1332b43b9614Srrh p = macfill(p, ppmactab);
1333b43b9614Srrh p = macfill(p, p1);
1334b43b9614Srrh p = macfill(p, p2);
1335b43b9614Srrh
1336b43b9614Srrh qsort(back, size, sizeof(struct mactab), macsort);
1337b43b9614Srrh *r_size = size;
1338b43b9614Srrh *r_back = back;
1339b43b9614Srrh }
1340b43b9614Srrh
1341b43b9614Srrh /*
1342b43b9614Srrh * troff commands
1343b43b9614Srrh */
1344b43b9614Srrh struct mactab troffmactab[] = {
1345b43b9614Srrh M(NONE, '\\','"', skip), /* comment */
1346b43b9614Srrh M(NOMAC, 'd','e', domacro), /* define */
1347b43b9614Srrh M(NOMAC, 'i','g', domacro), /* ignore till .. */
1348b43b9614Srrh M(NOMAC, 'a','m', domacro), /* append macro */
1349b43b9614Srrh M(NBLK, 'n','f', nf), /* filled */
1350b43b9614Srrh M(NBLK, 'c','e', ce), /* centered */
1351b43b9614Srrh
1352b43b9614Srrh M(NONE, 's','o', so), /* source a file */
1353b43b9614Srrh M(NONE, 'n','x', nx), /* go to next file */
1354b43b9614Srrh
1355b43b9614Srrh M(NONE, 't','m', skip), /* print string on tty */
1356b43b9614Srrh M(NONE, 'h','w', skip), /* exception hyphen words */
1357b43b9614Srrh M(NONE, 0,0, 0)
1358b43b9614Srrh };
1359b43b9614Srrh /*
1360b43b9614Srrh * Preprocessor output
1361b43b9614Srrh */
1362b43b9614Srrh struct mactab ppmactab[] = {
1363b43b9614Srrh M(FNEST, 'E','Q', EQ), /* equation starting */
1364b43b9614Srrh M(FNEST, 'T','S', intbl), /* table starting */
1365b43b9614Srrh M(FNEST, 'T','C', intbl), /* alternative table? */
1366b43b9614Srrh M(FNEST, 'T','&', intbl), /* table reformatting */
1367b43b9614Srrh M(NONE, 'T','E', outtbl),/* table ending */
1368b43b9614Srrh M(NONE, 'P','S', PS), /* picture starting */
1369b43b9614Srrh M(NONE, 0,0, 0)
1370b43b9614Srrh };
1371b43b9614Srrh /*
1372b43b9614Srrh * Particular to ms and mm
1373b43b9614Srrh */
1374b43b9614Srrh struct mactab msmactab[] = {
1375b43b9614Srrh M(NONE, 'T','L', skiptocom), /* title follows */
1376b43b9614Srrh M(NONE, 'F','S', skiptocom), /* start footnote */
1377b43b9614Srrh M(NONE, 'O','K', skiptocom), /* Other kws */
1378b43b9614Srrh
1379b43b9614Srrh M(NONE, 'N','R', skip), /* undocumented */
1380b43b9614Srrh M(NONE, 'N','D', skip), /* use supplied date */
1381b43b9614Srrh
1382b43b9614Srrh M(PARAG, 'P','P', PP), /* begin parag */
1383b43b9614Srrh M(PARAG, 'I','P', PP), /* begin indent parag, tag x */
1384b43b9614Srrh M(PARAG, 'L','P', PP), /* left blocked parag */
1385b43b9614Srrh
1386b43b9614Srrh M(NONE, 'A','U', AU), /* author */
1387b43b9614Srrh M(NONE, 'A','I', AU), /* authors institution */
1388b43b9614Srrh
1389b43b9614Srrh M(NONE, 'S','H', SH), /* section heading */
1390b43b9614Srrh M(NONE, 'S','N', SH), /* undocumented */
1391b43b9614Srrh M(NONE, 'U','X', UX), /* unix */
1392b43b9614Srrh
1393b43b9614Srrh M(NBLK, 'D','S', mssnblock), /* start display text */
1394b43b9614Srrh M(NBLK, 'K','S', mssnblock), /* start keep */
1395b43b9614Srrh M(NBLK, 'K','F', mssnblock), /* start float keep */
1396b43b9614Srrh M(NONE, 0,0, 0)
1397b43b9614Srrh };
1398b43b9614Srrh
1399b43b9614Srrh struct mactab mmmactab[] = {
1400b43b9614Srrh M(NONE, 'H',' ', MMHU), /* -mm ? */
1401b43b9614Srrh M(NONE, 'H','U', MMHU), /* -mm ? */
1402b43b9614Srrh M(PARAG, 'P',' ', PP), /* paragraph for -mm */
1403b43b9614Srrh M(NBLK, 'N','S', mssnblock), /* undocumented */
1404b43b9614Srrh M(NONE, 0,0, 0)
1405b43b9614Srrh };
1406b43b9614Srrh
1407b43b9614Srrh struct mactab memactab[] = {
1408b43b9614Srrh M(PARAG, 'p','p', mepp),
1409b43b9614Srrh M(PARAG, 'l','p', mepp),
1410b43b9614Srrh M(PARAG, 'n','p', mepp),
1411b43b9614Srrh M(NONE, 'i','p', meip),
1412b43b9614Srrh
1413b43b9614Srrh M(NONE, 's','h', mesh),
1414b43b9614Srrh M(NONE, 'u','h', mesh),
1415b43b9614Srrh
1416b43b9614Srrh M(NBLK, '(','l', mesnblock),
1417b43b9614Srrh M(NBLK, '(','q', mesnblock),
1418b43b9614Srrh M(NBLK, '(','b', mesnblock),
1419b43b9614Srrh M(NBLK, '(','z', mesnblock),
1420b43b9614Srrh M(NBLK, '(','c', mesnblock),
1421b43b9614Srrh
1422b43b9614Srrh M(NBLK, '(','d', mesnblock),
1423b43b9614Srrh M(NBLK, '(','f', mesnblock),
1424b43b9614Srrh M(NBLK, '(','x', mesnblock),
1425b43b9614Srrh
1426b43b9614Srrh M(NONE, 'r',' ', mefont),
1427b43b9614Srrh M(NONE, 'i',' ', mefont),
1428b43b9614Srrh M(NONE, 'b',' ', mefont),
1429b43b9614Srrh M(NONE, 'u',' ', mefont),
1430b43b9614Srrh M(NONE, 'q',' ', mefont),
1431b43b9614Srrh M(NONE, 'r','b', mefont),
1432b43b9614Srrh M(NONE, 'b','i', mefont),
1433b43b9614Srrh M(NONE, 'b','x', mefont),
1434b43b9614Srrh M(NONE, 0,0, 0)
1435b43b9614Srrh };
1436b43b9614Srrh
1437b43b9614Srrh
1438b43b9614Srrh struct mactab manmactab[] = {
1439b43b9614Srrh M(PARAG, 'B','I', manfont),
1440b43b9614Srrh M(PARAG, 'B','R', manfont),
1441b43b9614Srrh M(PARAG, 'I','B', manfont),
1442b43b9614Srrh M(PARAG, 'I','R', manfont),
1443b43b9614Srrh M(PARAG, 'R','B', manfont),
1444b43b9614Srrh M(PARAG, 'R','I', manfont),
1445b43b9614Srrh
1446b43b9614Srrh M(PARAG, 'P','P', manpp),
1447b43b9614Srrh M(PARAG, 'L','P', manpp),
1448b43b9614Srrh M(PARAG, 'H','P', manpp),
1449b43b9614Srrh M(NONE, 0,0, 0)
1450b43b9614Srrh };
1451