xref: /csrg-svn/usr.bin/deroff/deroff.c (revision 9079)
19075Srrh #ifndef lint
2*9079Srrh static char sccsid[] = "@(#)deroff.c	4.2	(Berkeley)	82/11/06";
39075Srrh #endif not lint
49075Srrh 
5*9079Srrh char *xxxvers = "\nDeroff Version 1.02 (Bell Labs)    24 July 1978\n";
69075Srrh 
79075Srrh 
89075Srrh #include <stdio.h>
99075Srrh 
109075Srrh /* Deroff command -- strip troff, eqn, and Tbl sequences from
119075Srrh a file.  Has two flags argument, -w, to cause output one word per line
129075Srrh rather than in the original format.
13*9079Srrh -mm (or -ms) causes the corresponding macro's to be interpreted
14*9079Srrh so that just sentences are output
15*9079Srrh -ml  also gets rid of lists.
169075Srrh Deroff follows .so and .nx commands, removes contents of macro
179075Srrh definitions, equations (both .EQ ... .EN and $...$),
189075Srrh Tbl command sequences, and Troff backslash constructions.
199075Srrh 
209075Srrh All input is through the C macro; the most recently read character is in c.
219075Srrh */
229075Srrh 
239075Srrh #define C ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
249075Srrh #define C1 ( (c=getc(infile)) == EOF ? eof() :  c)
259075Srrh #define SKIP while(C != '\n')
269075Srrh #define SKIP_TO_COM SKIP; SKIP; pc=c; while(C != '.' || pc != '\n' || C > 'Z')pc=c
279075Srrh 
289075Srrh #define YES 1
299075Srrh #define NO 0
309075Srrh #define MS 0
319075Srrh #define MM 1
329075Srrh #define ONE 1
339075Srrh #define TWO 2
349075Srrh 
359075Srrh #define NOCHAR -2
369075Srrh #define SPECIAL 0
379075Srrh #define APOS 1
38*9079Srrh #define PUNCT 2
39*9079Srrh #define DIGIT 3
40*9079Srrh #define LETTER 4
419075Srrh 
429075Srrh int wordflag = NO;
439075Srrh int msflag = NO;
44*9079Srrh int mac = MM;
459075Srrh int disp = 0;
46*9079Srrh int parag = 0;
479075Srrh int inmacro = NO;
489075Srrh int intable = NO;
499075Srrh 
50*9079Srrh char chars[128];  /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
519075Srrh 
529075Srrh char line[512];
539075Srrh char *lp;
549075Srrh 
559075Srrh int c;
569075Srrh int pc;
579075Srrh int ldelim	= NOCHAR;
589075Srrh int rdelim	= NOCHAR;
599075Srrh 
609075Srrh 
619075Srrh int argc;
629075Srrh char **argv;
639075Srrh 
64*9079Srrh extern int optind;
65*9079Srrh extern char*optarg;
669075Srrh char fname[50];
679075Srrh FILE *files[15];
689075Srrh FILE **filesp;
699075Srrh FILE *infile;
709075Srrh 
719075Srrh main(ac, av)
729075Srrh int ac;
739075Srrh char **av;
749075Srrh {
75*9079Srrh 	register int i;
76*9079Srrh 	int errflg = 0;
77*9079Srrh 	register optchar;
78*9079Srrh 	FILE *opn();
799075Srrh 
80*9079Srrh 	argc = ac;
81*9079Srrh 	argv = av;
82*9079Srrh 	while ((optchar = getopt(argc, argv, "wpm:")) != EOF) switch(optchar) {
83*9079Srrh 	case 'w':
84*9079Srrh 		wordflag = YES;
85*9079Srrh 		break;
86*9079Srrh 	case 'm':
87*9079Srrh 		msflag = YES;
88*9079Srrh 		if (*optarg == 'm')
89*9079Srrh 			mac = MM;
90*9079Srrh 		else if (*optarg == 's')
91*9079Srrh 			mac = MS;
92*9079Srrh 		else if (*optarg == 'l')
93*9079Srrh 			disp = 1;
94*9079Srrh 		else errflg++;
95*9079Srrh 		break;
96*9079Srrh 	case 'p':
97*9079Srrh 		parag=YES;
98*9079Srrh 		break;
99*9079Srrh 	case '?':
100*9079Srrh 		errflg++;
1019075Srrh 	}
102*9079Srrh 	if (errflg)
103*9079Srrh 		fatal("usage: deroff [ -w ] [ -m (m s l) ] [ file ] ... \n", (char *) NULL);
104*9079Srrh 	if ( optind == argc )
105*9079Srrh 		infile = stdin;
106*9079Srrh 	else
107*9079Srrh 		infile = opn(argv[optind++]);
108*9079Srrh 	files[0] = infile;
109*9079Srrh 	filesp = &files[0];
1109075Srrh 
111*9079Srrh 	for(i='a'; i<='z' ; ++i)
112*9079Srrh 		chars[i] = LETTER;
113*9079Srrh 	for(i='A'; i<='Z'; ++i)
114*9079Srrh 		chars[i] = LETTER;
115*9079Srrh 	for(i='0'; i<='9'; ++i)
116*9079Srrh 		chars[i] = DIGIT;
117*9079Srrh 	chars['\''] = APOS;
118*9079Srrh 	chars['&'] = APOS;
119*9079Srrh 	chars['.'] = PUNCT;
120*9079Srrh 	chars[','] = PUNCT;
121*9079Srrh 	chars[';'] = PUNCT;
122*9079Srrh 	chars['?'] = PUNCT;
123*9079Srrh 	chars[':'] = PUNCT;
124*9079Srrh 	work();
125*9079Srrh }
126*9079Srrh char *calloc();
1279075Srrh 
1289075Srrh 
1299075Srrh 
1309075Srrh 
1319075Srrh 
1329075Srrh 
1339075Srrh skeqn()
1349075Srrh {
135*9079Srrh 	while((c = getc(infile)) != rdelim)
136*9079Srrh 		if(c == EOF)
137*9079Srrh 			c = eof();
138*9079Srrh 		else if(c == '"')
139*9079Srrh 			while( (c = getc(infile)) != '"')
140*9079Srrh 				if(c == EOF)
1419075Srrh 					c = eof();
142*9079Srrh 				else if(c == '\\')
143*9079Srrh 					if((c = getc(infile)) == EOF)
144*9079Srrh 						c = eof();
145*9079Srrh 	if(msflag)return(c='x');
146*9079Srrh 	return(c = ' ');
1479075Srrh }
1489075Srrh 
1499075Srrh 
1509075Srrh FILE *opn(p)
1519075Srrh register char *p;
1529075Srrh {
153*9079Srrh 	FILE *fd;
1549075Srrh 
155*9079Srrh 	if( (fd = fopen(p, "r")) == NULL)
156*9079Srrh 		fatal("Cannot open file %s\n", p);
1579075Srrh 
158*9079Srrh 	return(fd);
1599075Srrh }
1609075Srrh 
1619075Srrh 
1629075Srrh 
1639075Srrh eof()
1649075Srrh {
165*9079Srrh 	if(infile != stdin)
166*9079Srrh 		fclose(infile);
167*9079Srrh 	if(filesp > files)
168*9079Srrh 		infile = *--filesp;
169*9079Srrh 	else if(optind < argc)
1709075Srrh 	{
171*9079Srrh 		infile = opn(argv[optind++]);
1729075Srrh 	}
173*9079Srrh 	else
174*9079Srrh 		exit(0);
1759075Srrh 
176*9079Srrh 	return(C);
1779075Srrh }
1789075Srrh 
1799075Srrh 
1809075Srrh 
1819075Srrh getfname()
1829075Srrh {
183*9079Srrh 	register char *p;
184*9079Srrh 	struct chain {
185*9079Srrh 		struct chain *nextp;
186*9079Srrh 		char *datap;
187*9079Srrh 	} *chainblock;
188*9079Srrh 	register struct chain *q;
189*9079Srrh 	static struct chain *namechain	= NULL;
190*9079Srrh 	char *copys();
1919075Srrh 
192*9079Srrh 	while(C == ' ') ;
1939075Srrh 
194*9079Srrh 	for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p)
195*9079Srrh 		C;
196*9079Srrh 	*p = '\0';
197*9079Srrh 	while(c != '\n')
198*9079Srrh 		C;
1999075Srrh 
200*9079Srrh 	/* see if this name has already been used */
2019075Srrh 
202*9079Srrh 	for(q = namechain ; q; q = q->nextp)
203*9079Srrh 		if( ! strcmp(fname, q->datap))
2049075Srrh 		{
205*9079Srrh 			fname[0] = '\0';
206*9079Srrh 			return;
2079075Srrh 		}
2089075Srrh 
209*9079Srrh 	q = (struct chain *) calloc(1, sizeof(*chainblock));
210*9079Srrh 	q->nextp = namechain;
211*9079Srrh 	q->datap = copys(fname);
212*9079Srrh 	namechain = q;
2139075Srrh }
2149075Srrh 
2159075Srrh 
2169075Srrh 
2179075Srrh 
2189075Srrh fatal(s,p)
2199075Srrh char *s, *p;
2209075Srrh {
221*9079Srrh 	fprintf(stderr, "Deroff: ");
222*9079Srrh 	fprintf(stderr, s, p);
223*9079Srrh 	exit(1);
2249075Srrh }
225*9079Srrh 
2269075Srrh work()
2279075Srrh {
2289075Srrh 
229*9079Srrh 	for( ;; )
2309075Srrh 	{
231*9079Srrh 		if(C == '.'  ||  c == '\'')
232*9079Srrh 			comline();
233*9079Srrh 		else
234*9079Srrh 			regline(NO,TWO);
2359075Srrh 	}
2369075Srrh }
2379075Srrh 
2389075Srrh 
2399075Srrh 
2409075Srrh 
2419075Srrh regline(macline,const)
2429075Srrh int macline;
2439075Srrh int const;
2449075Srrh {
245*9079Srrh 	line[0] = c;
246*9079Srrh 	lp = line;
247*9079Srrh 	for( ; ; )
2489075Srrh 	{
249*9079Srrh 		if(c == '\\')
2509075Srrh 		{
251*9079Srrh 			*lp = ' ';
252*9079Srrh 			backsl();
2539075Srrh 		}
254*9079Srrh 		if(c == '\n') break;
255*9079Srrh 		if(intable && c=='T')
2569075Srrh 		{
257*9079Srrh 			*++lp = C;
258*9079Srrh 			if(c=='{' || c=='}')
2599075Srrh 			{
260*9079Srrh 				lp[-1] = ' ';
261*9079Srrh 				*lp = C;
2629075Srrh 			}
2639075Srrh 		}
264*9079Srrh 		else	*++lp = C;
2659075Srrh 	}
2669075Srrh 
267*9079Srrh 	*lp = '\0';
2689075Srrh 
269*9079Srrh 	if(line[0] != '\0')
270*9079Srrh 		if(wordflag)
271*9079Srrh 			putwords(macline);
272*9079Srrh 		else if(macline)
273*9079Srrh 			putmac(line,const);
274*9079Srrh 		else
275*9079Srrh 			puts(line);
2769075Srrh }
2779075Srrh 
2789075Srrh 
2799075Srrh 
2809075Srrh 
2819075Srrh putmac(s,const)
2829075Srrh register char *s;
2839075Srrh int const;
2849075Srrh {
285*9079Srrh 	register char *t;
286*9079Srrh 	register found;
287*9079Srrh 	int last;
288*9079Srrh 	found = 0;
2899075Srrh 
290*9079Srrh 	while(*s)
2919075Srrh 	{
292*9079Srrh 		while(*s==' ' || *s=='\t')
293*9079Srrh 			putchar(*s++);
294*9079Srrh 		for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t)
295*9079Srrh 			;
296*9079Srrh 		if(*s == '\"')s++;
297*9079Srrh 		if(t>s+const && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER){
298*9079Srrh 			while(s < t)
299*9079Srrh 				if(*s == '\"')s++;
300*9079Srrh 				else
301*9079Srrh 					putchar(*s++);
302*9079Srrh 			last = *(t-1);
303*9079Srrh 			found++;
304*9079Srrh 		}
305*9079Srrh 		else if(found && chars[ s[0] ] == PUNCT && s[1] == '\0')
306*9079Srrh 			putchar(*s++);
307*9079Srrh 		else{
308*9079Srrh 			last = *(t-1);
309*9079Srrh 			s = t;
310*9079Srrh 		}
3119075Srrh 	}
312*9079Srrh 	putchar('\n');
313*9079Srrh 	if(msflag && chars[last] == PUNCT){
314*9079Srrh 		putchar(last);
315*9079Srrh 		putchar('\n');
316*9079Srrh 	}
3179075Srrh }
3189075Srrh 
3199075Srrh 
3209075Srrh 
3219075Srrh putwords(macline)	/* break into words for -w option */
3229075Srrh int macline;
3239075Srrh {
324*9079Srrh 	register char *p, *p1;
325*9079Srrh 	int i, nlet;
3269075Srrh 
3279075Srrh 
328*9079Srrh 	for(p1 = line ; ;)
3299075Srrh 	{
330*9079Srrh 		/* skip initial specials ampersands and apostrophes */
331*9079Srrh 		while( chars[*p1] < DIGIT)
332*9079Srrh 			if(*p1++ == '\0') return;
333*9079Srrh 		nlet = 0;
334*9079Srrh 		for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p)
335*9079Srrh 			if(i == LETTER) ++nlet;
3369075Srrh 
337*9079Srrh 		if( (!macline && nlet>1)   /* MDM definition of word */
338*9079Srrh 		    || (macline && nlet>2 && chars[ p1[0] ]==LETTER && chars[ p1[1] ]==LETTER) )
3399075Srrh 		{
340*9079Srrh 			/* delete trailing ampersands and apostrophes */
341*9079Srrh 			while(p[-1]=='\'' || p[-1]=='&'|| chars[ p[-1] ] == PUNCT)
342*9079Srrh 				--p;
343*9079Srrh 			while(p1 < p) putchar(*p1++);
344*9079Srrh 			putchar('\n');
3459075Srrh 		}
346*9079Srrh 		else
347*9079Srrh 			p1 = p;
3489075Srrh 	}
3499075Srrh }
3509075Srrh 
3519075Srrh 
3529075Srrh comline()
3539075Srrh {
354*9079Srrh 	register int c1, c2;
3559075Srrh 
3569075Srrh com:
357*9079Srrh 	while(C==' ' || c=='\t')
358*9079Srrh 		;
3599075Srrh comx:
360*9079Srrh 	if( (c1=c) == '\n')
361*9079Srrh 		return;
362*9079Srrh 	c2 = C;
363*9079Srrh 	if(c1=='.' && c2!='.')
364*9079Srrh 		inmacro = NO;
365*9079Srrh 	if(msflag && c1 == '['){
366*9079Srrh 		refer(c2);
367*9079Srrh 		return;
368*9079Srrh 	}
369*9079Srrh 	if(parag && mac==MM && c1 == 'P' && c2 == '\n'){
370*9079Srrh 		printf(".P\n");
371*9079Srrh 		return;
372*9079Srrh 	}
373*9079Srrh 	if(c2 == '\n')
374*9079Srrh 		return;
3759075Srrh 
376*9079Srrh 	if(c1 == '\\' && c2 == '\"')
377*9079Srrh 		SKIP;
378*9079Srrh 	else if(c1=='E' && c2=='Q' && filesp==files)
379*9079Srrh 		eqn();
380*9079Srrh 	else if(c1=='T' && (c2=='S' || c2=='C' || c2=='&') && filesp==files){
381*9079Srrh 		if(msflag){
382*9079Srrh 			stbl();
383*9079Srrh 		}
384*9079Srrh 		else tbl();
385*9079Srrh 	}
386*9079Srrh 	else if(c1=='T' && c2=='E')
387*9079Srrh 		intable = NO;
388*9079Srrh 	else if(!inmacro && c1=='d' && c2=='e')
389*9079Srrh 		macro();
390*9079Srrh 	else if(!inmacro && c1=='i' && c2=='g')
391*9079Srrh 		macro();
392*9079Srrh 	else if(!inmacro && c1=='a' && c2 == 'm')
393*9079Srrh 		macro();
394*9079Srrh 	else if(c1=='s' && c2=='o')
3959075Srrh 	{
396*9079Srrh 		getfname();
397*9079Srrh 		if( fname[0] )
398*9079Srrh 			infile = *++filesp = opn( fname );
3999075Srrh 	}
400*9079Srrh 	else if(c1=='n' && c2=='x')
4019075Srrh 	{
402*9079Srrh 		getfname();
403*9079Srrh 		if(fname[0] == '\0') exit(0);
404*9079Srrh 		if(infile != stdin)
405*9079Srrh 			fclose(infile);
406*9079Srrh 		infile = *filesp = opn(fname);
4079075Srrh 	}
408*9079Srrh 	else if(c1 == 't' && c2 == 'm')
409*9079Srrh 		SKIP;
410*9079Srrh 	else if(c1=='h' && c2=='w')
411*9079Srrh 		SKIP;
412*9079Srrh 	else if(msflag && c1 == 'T' && c2 == 'L'){
4139075Srrh 		SKIP_TO_COM;
414*9079Srrh 		goto comx;
4159075Srrh 	}
416*9079Srrh 	else if(msflag && c1=='N' && c2 == 'R')SKIP;
417*9079Srrh 	else if(parag && msflag && (c1 == 'P' || c1 == 'I' || c1 == 'L') && c2 == 'P'){
418*9079Srrh 		printf(".%c%c",c1,c2);
419*9079Srrh 		while(C != '\n')putchar(c);
420*9079Srrh 		putchar('\n');
421*9079Srrh 	}
422*9079Srrh 	else if(parag && mac==MM && c1 == 'P' && c2 == ' '){
423*9079Srrh 		printf(".%c%c",c1,c2);
424*9079Srrh 		while(C != '\n')putchar(c);
425*9079Srrh 		putchar('\n');
426*9079Srrh 	}
427*9079Srrh 	else if(msflag && c1 == 'A' && (c2 == 'U' || c2 == 'I')){
428*9079Srrh 		if(mac==MM)SKIP;
429*9079Srrh 		else {
430*9079Srrh 			SKIP_TO_COM;
431*9079Srrh 			goto comx;
432*9079Srrh 		}
433*9079Srrh 	}
434*9079Srrh 	else if(msflag && c1 == 'F' && c2 == 'S'){
435*9079Srrh 		SKIP_TO_COM;
436*9079Srrh 		goto comx;
437*9079Srrh 	}
438*9079Srrh 	else if(msflag && (c1 == 'S' || c1 == 'N') && c2 == 'H'){
439*9079Srrh 		if(parag){
440*9079Srrh 			printf(".%c%c",c1,c2);
441*9079Srrh 			while(C != '\n')putchar(c);
442*9079Srrh 			putchar(c);
443*9079Srrh 			putchar('!');
444*9079Srrh 			while(1){
445*9079Srrh 				while(C != '\n')putchar(c);
446*9079Srrh 				putchar('\n');
447*9079Srrh 				if(C == '.')goto com;
448*9079Srrh 				putchar('!');
449*9079Srrh 				putchar(c);
450*9079Srrh 			}
451*9079Srrh 		}
452*9079Srrh 		else {
453*9079Srrh 			SKIP_TO_COM;
454*9079Srrh 			goto comx;
455*9079Srrh 		}
456*9079Srrh 	}
457*9079Srrh 	else if(c1 == 'U' && c2 == 'X'){
458*9079Srrh 		if(wordflag)printf("UNIX\n");
459*9079Srrh 		else printf("UNIX ");
460*9079Srrh 	}
461*9079Srrh 	else if(msflag && c1 == 'O' && c2 == 'K'){
462*9079Srrh 		SKIP_TO_COM;
463*9079Srrh 		goto comx;
464*9079Srrh 	}
465*9079Srrh 	else if(msflag && c1 == 'N' && c2 == 'D')
4669075Srrh 		SKIP;
467*9079Srrh 	else if(msflag && mac==MM && c1=='H' && (c2==' '||c2=='U')){
468*9079Srrh 		if(parag){
469*9079Srrh 			printf(".%c%c",c1,c2);
470*9079Srrh 			while(C != '\n')putchar(c);
471*9079Srrh 			putchar('\n');
4729075Srrh 		}
473*9079Srrh 		else {
474*9079Srrh 			SKIP;
475*9079Srrh 		}
4769075Srrh 	}
477*9079Srrh 	else if(msflag && mac==MM && c2=='L'){
478*9079Srrh 		if(disp || c1 == 'R')sdis('L','E');
479*9079Srrh 		else{
480*9079Srrh 			SKIP;
481*9079Srrh 			putchar('.');
482*9079Srrh 		}
483*9079Srrh 	}
484*9079Srrh 	else if(!msflag &&c1 == 'P' && c2 == 'S'){
485*9079Srrh 		inpic();
486*9079Srrh 	}
487*9079Srrh 	else if(msflag && (c1 == 'D' || c1 == 'N' || c1 == 'K'|| c1=='P') && c2 == 'S')
488*9079Srrh 	{
489*9079Srrh 		sdis(c1,'E');
490*9079Srrh 	}		/* removed RS-RE */
491*9079Srrh 	else if(msflag && (c1 == 'K' && c2 == 'F'))
492*9079Srrh 	{
493*9079Srrh 		sdis(c1,'E');
494*9079Srrh 	}
495*9079Srrh 	else if(msflag && c1 == 'n' && c2 == 'f')
496*9079Srrh 		sdis('f','i');
497*9079Srrh 	else if(msflag && c1 == 'c' && c2 == 'e')
498*9079Srrh 		sce();
499*9079Srrh 	else
5009075Srrh 	{
501*9079Srrh 		if(c1=='.' && c2=='.'){
502*9079Srrh 			if(msflag){
503*9079Srrh 				SKIP;
504*9079Srrh 				return;
505*9079Srrh 			}
506*9079Srrh 			while(C == '.')
507*9079Srrh 				;
508*9079Srrh 		}
509*9079Srrh 		++inmacro;
510*9079Srrh 		if(c1 <= 'Z' && msflag)regline(YES,ONE);
511*9079Srrh 		else regline(YES,TWO);
512*9079Srrh 		--inmacro;
5139075Srrh 	}
5149075Srrh }
5159075Srrh 
5169075Srrh 
5179075Srrh 
5189075Srrh macro()
5199075Srrh {
520*9079Srrh 	if(msflag){
521*9079Srrh 		do {
522*9079Srrh 			SKIP;
523*9079Srrh 		}		while(C!='.' || C!='.' || C=='.');	/* look for  .. */
524*9079Srrh 		if(c != '\n')SKIP;
525*9079Srrh 		return;
526*9079Srrh 	}
527*9079Srrh 	SKIP;
528*9079Srrh 	inmacro = YES;
5299075Srrh }
5309075Srrh 
5319075Srrh 
5329075Srrh 
5339075Srrh 
5349075Srrh sdis(a1,a2)
5359075Srrh char a1,a2;
5369075Srrh {
5379075Srrh 	register int c1,c2;
5389075Srrh 	register int eqnf;
539*9079Srrh 	int lct;
540*9079Srrh 	lct = 0;
5419075Srrh 	eqnf=1;
5429075Srrh 	SKIP;
5439075Srrh 	while(1){
544*9079Srrh 		while(C != '.')
545*9079Srrh 			if(c == '\n')continue;
546*9079Srrh 			else SKIP;
5479075Srrh 		if((c1=C) == '\n')continue;
5489075Srrh 		if((c2=C) == '\n')continue;
5499075Srrh 		if(c1==a1 && c2 == a2){
5509075Srrh 			SKIP;
551*9079Srrh 			if(lct != 0){
552*9079Srrh 				lct--;
553*9079Srrh 				continue;
554*9079Srrh 			}
5559075Srrh 			if(eqnf)putchar('.');
5569075Srrh 			putchar('\n');
5579075Srrh 			return;
5589075Srrh 		}
559*9079Srrh 		else if(a1 == 'L' && c2 == 'L'){
560*9079Srrh 			lct++;
561*9079Srrh 			SKIP;
562*9079Srrh 		}
563*9079Srrh 		else if(a1 == 'D' && c1 == 'E' && c2 == 'Q'){
564*9079Srrh 			eqn();
565*9079Srrh 			eqnf=0;
566*9079Srrh 		}
567*9079Srrh 		else if(a1 == 'f' && (c1 == 'P' || c2 == 'P')){
568*9079Srrh 			SKIP;
569*9079Srrh 			return;
570*9079Srrh 		}
5719075Srrh 		else SKIP;
5729075Srrh 	}
5739075Srrh }
5749075Srrh tbl()
5759075Srrh {
576*9079Srrh 	while(C != '.');
577*9079Srrh 	SKIP;
578*9079Srrh 	intable = YES;
5799075Srrh }
5809075Srrh stbl()
5819075Srrh {
582*9079Srrh 	while(C != '.');
583*9079Srrh 	SKIP_TO_COM;
584*9079Srrh 	if(c != 'T' || C != 'E'){
585*9079Srrh 		SKIP;
586*9079Srrh 		pc=c;
587*9079Srrh 		while(C != '.' || pc != '\n' || C != 'T' || C != 'E')pc=c;
588*9079Srrh 	}
5899075Srrh }
5909075Srrh 
5919075Srrh eqn()
5929075Srrh {
593*9079Srrh 	register int c1, c2;
594*9079Srrh 	register int dflg;
595*9079Srrh 	char last;
5969075Srrh 
597*9079Srrh 	last=0;
598*9079Srrh 	dflg = 1;
599*9079Srrh 	SKIP;
6009075Srrh 
601*9079Srrh 	for( ;;)
6029075Srrh 	{
603*9079Srrh 		if(C1 == '.'  || c == '\'')
6049075Srrh 		{
605*9079Srrh 			while(C1==' ' || c=='\t')
606*9079Srrh 				;
607*9079Srrh 			if(c=='E' && C1=='N')
6089075Srrh 			{
609*9079Srrh 				SKIP;
610*9079Srrh 				if(msflag && dflg){
611*9079Srrh 					putchar('x');
612*9079Srrh 					putchar(' ');
613*9079Srrh 					if(last){
614*9079Srrh 						putchar(last);
615*9079Srrh 						putchar('\n');
616*9079Srrh 					}
617*9079Srrh 				}
618*9079Srrh 				return;
6199075Srrh 			}
6209075Srrh 		}
621*9079Srrh 		else if(c == 'd')	/* look for delim */
6229075Srrh 		{
623*9079Srrh 			if(C1=='e' && C1=='l')
624*9079Srrh 				if( C1=='i' && C1=='m')
6259075Srrh 				{
626*9079Srrh 					while(C1 == ' ');
627*9079Srrh 					if((c1=c)=='\n' || (c2=C1)=='\n'
628*9079Srrh 					    || (c1=='o' && c2=='f' && C1=='f') )
629*9079Srrh 					{
630*9079Srrh 						ldelim = NOCHAR;
631*9079Srrh 						rdelim = NOCHAR;
632*9079Srrh 					}
633*9079Srrh 					else	{
634*9079Srrh 						ldelim = c1;
635*9079Srrh 						rdelim = c2;
636*9079Srrh 					}
6379075Srrh 				}
6389075Srrh 			dflg = 0;
6399075Srrh 		}
6409075Srrh 
641*9079Srrh 		if(c != '\n') while(C1 != '\n'){
642*9079Srrh 			if(chars[c] == PUNCT)last = c;
643*9079Srrh 			else if(c != ' ')last = 0;
644*9079Srrh 		}
6459075Srrh 	}
6469075Srrh }
6479075Srrh 
6489075Srrh 
6499075Srrh backsl()	/* skip over a complete backslash construction */
6509075Srrh {
651*9079Srrh 	int bdelim;
6529075Srrh 
653*9079Srrh sw:
654*9079Srrh 	switch(C)
6559075Srrh 	{
6569075Srrh 	case '"':
6579075Srrh 		SKIP;
6589075Srrh 		return;
6599075Srrh 	case 's':
6609075Srrh 		if(C == '\\') backsl();
6619075Srrh 		else	{
6629075Srrh 			while(C>='0' && c<='9') ;
6639075Srrh 			ungetc(c,infile);
6649075Srrh 			c = '0';
665*9079Srrh 		}
6669075Srrh 		--lp;
6679075Srrh 		return;
6689075Srrh 
6699075Srrh 	case 'f':
6709075Srrh 	case 'n':
6719075Srrh 	case '*':
6729075Srrh 		if(C != '(')
6739075Srrh 			return;
6749075Srrh 
6759075Srrh 	case '(':
676*9079Srrh 		if(msflag){
677*9079Srrh 			if(C == 'e'){
678*9079Srrh 				if(C == 'm'){
679*9079Srrh 					*lp = '-';
680*9079Srrh 					return;
681*9079Srrh 				}
682*9079Srrh 			}
683*9079Srrh 			else if(c != '\n')C;
684*9079Srrh 			return;
685*9079Srrh 		}
6869075Srrh 		if(C != '\n') C;
6879075Srrh 		return;
6889075Srrh 
6899075Srrh 	case '$':
6909075Srrh 		C;	/* discard argument number */
6919075Srrh 		return;
6929075Srrh 
6939075Srrh 	case 'b':
6949075Srrh 	case 'x':
6959075Srrh 	case 'v':
6969075Srrh 	case 'h':
6979075Srrh 	case 'w':
6989075Srrh 	case 'o':
6999075Srrh 	case 'l':
7009075Srrh 	case 'L':
7019075Srrh 		if( (bdelim=C) == '\n')
7029075Srrh 			return;
7039075Srrh 		while(C!='\n' && c!=bdelim)
7049075Srrh 			if(c == '\\') backsl();
7059075Srrh 		return;
7069075Srrh 
7079075Srrh 	case '\\':
7089075Srrh 		if(inmacro)
7099075Srrh 			goto sw;
7109075Srrh 	default:
7119075Srrh 		return;
7129075Srrh 	}
7139075Srrh }
7149075Srrh 
7159075Srrh 
7169075Srrh 
7179075Srrh 
7189075Srrh char *copys(s)
7199075Srrh register char *s;
7209075Srrh {
721*9079Srrh 	register char *t, *t0;
7229075Srrh 
723*9079Srrh 	if( (t0 = t = calloc( (unsigned)(strlen(s)+1), sizeof(*t) ) ) == NULL)
724*9079Srrh 		fatal("Cannot allocate memory", (char *) NULL);
7259075Srrh 
726*9079Srrh 	while( *t++ = *s++ )
727*9079Srrh 		;
728*9079Srrh 	return(t0);
7299075Srrh }
7309075Srrh sce(){
731*9079Srrh 	register char *ap;
732*9079Srrh 	register int n, i;
733*9079Srrh 	char a[10];
7349075Srrh 	for(ap=a;C != '\n';ap++){
7359075Srrh 		*ap = c;
7369075Srrh 		if(ap == &a[9]){
7379075Srrh 			SKIP;
7389075Srrh 			ap=a;
7399075Srrh 			break;
7409075Srrh 		}
7419075Srrh 	}
7429075Srrh 	if(ap != a)n = atoi(a);
7439075Srrh 	else n = 1;
7449075Srrh 	for(i=0;i<n;){
7459075Srrh 		if(C == '.'){
7469075Srrh 			if(C == 'c'){
7479075Srrh 				if(C == 'e'){
7489075Srrh 					while(C == ' ');
749*9079Srrh 					if(c == '0'){
750*9079Srrh 						SKIP;
751*9079Srrh 						break;
752*9079Srrh 					}
7539075Srrh 					else SKIP;
7549075Srrh 				}
7559075Srrh 				else SKIP;
7569075Srrh 			}
757*9079Srrh 			else if(c == 'P' || C == 'P'){
758*9079Srrh 				if(c != '\n')SKIP;
759*9079Srrh 				break;
760*9079Srrh 			}
761*9079Srrh 			else if(c != '\n')SKIP;
7629075Srrh 		}
7639075Srrh 		else {
7649075Srrh 			SKIP;
7659075Srrh 			i++;
7669075Srrh 		}
7679075Srrh 	}
7689075Srrh }
769*9079Srrh refer(c1)
770*9079Srrh {
771*9079Srrh 	register int c2;
772*9079Srrh 	if(c1 != '\n')
773*9079Srrh 		SKIP;
774*9079Srrh 	while(1){
775*9079Srrh 		if(C != '.')
776*9079Srrh 			SKIP;
777*9079Srrh 		else {
778*9079Srrh 			if(C != ']')
779*9079Srrh 				SKIP;
780*9079Srrh 			else {
781*9079Srrh 				while(C != '\n')
782*9079Srrh 					c2=c;
783*9079Srrh 				if(chars[c2] == PUNCT)putchar(c2);
784*9079Srrh 				return;
785*9079Srrh 			}
786*9079Srrh 		}
787*9079Srrh 	}
788*9079Srrh }
789*9079Srrh inpic(){
790*9079Srrh 	register int c1;
791*9079Srrh 	register char *p1;
792*9079Srrh 	SKIP;
793*9079Srrh 	p1 = line;
794*9079Srrh 	c = '\n';
795*9079Srrh 	while(1){
796*9079Srrh 		c1 = c;
797*9079Srrh 		if(C == '.' && c1 == '\n'){
798*9079Srrh 			if(C != 'P'){
799*9079Srrh 				if(c == '\n')continue;
800*9079Srrh 				else { SKIP; c='\n'; continue;}
801*9079Srrh 			}
802*9079Srrh 			if(C != 'E'){
803*9079Srrh 				if(c == '\n')continue;
804*9079Srrh 				else { SKIP; c='\n';continue; }
805*9079Srrh 			}
806*9079Srrh 			SKIP;
807*9079Srrh 			return;
808*9079Srrh 		}
809*9079Srrh 		else if(c == '\"'){
810*9079Srrh 			while(C != '\"'){
811*9079Srrh 				if(c == '\\'){
812*9079Srrh 					if(C == '\"')continue;
813*9079Srrh 					ungetc(c,infile);
814*9079Srrh 					backsl();
815*9079Srrh 				}
816*9079Srrh 				else *p1++ = c;
817*9079Srrh 			}
818*9079Srrh 			*p1++ = ' ';
819*9079Srrh 		}
820*9079Srrh 		else if(c == '\n' && p1 != line){
821*9079Srrh 			*p1 = '\0';
822*9079Srrh 			if(wordflag)putwords(NO);
823*9079Srrh 			else {
824*9079Srrh 				puts(line);
825*9079Srrh 				putchar('\n');
826*9079Srrh 			}
827*9079Srrh 			p1 = line;
828*9079Srrh 		}
829*9079Srrh 	}
830*9079Srrh }
831