xref: /original-bsd/usr.bin/deroff/deroff.c (revision a71d9ce2)
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