xref: /csrg-svn/usr.bin/deroff/deroff.c (revision 12097)
19075Srrh #ifndef lint
2*12097Smckusick static char sccsid[] = "@(#)deroff.c	4.4	(Berkeley)	83/04/29";
39075Srrh #endif not lint
49075Srrh 
59094Srrh #include <stdio.h>
69075Srrh 
79094Srrh /*
89094Srrh  *	Deroff command -- strip troff, eqn, and Tbl sequences from
99094Srrh  *	a file.  Has two flags argument, -w, to cause output one word per line
109094Srrh  *	rather than in the original format.
119094Srrh  *	-mm (or -ms) causes the corresponding macro's to be interpreted
129094Srrh  *	so that just sentences are output
139094Srrh  *	-ml  also gets rid of lists.
149094Srrh  *	Deroff follows .so and .nx commands, removes contents of macro
159094Srrh  *	definitions, equations (both .EQ ... .EN and $...$),
169094Srrh  *	Tbl command sequences, and Troff backslash constructions.
179094Srrh  *
189094Srrh  *	All input is through the Cget macro;
199094Srrh  *	the most recently read character is in c.
209094Srrh  *
219094Srrh  *	Modified by Robert Henry to process -me and -man macros.
229094Srrh  */
239075Srrh 
249094Srrh #define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
259094Srrh #define C1get ( (c=getc(infile)) == EOF ? eof() :  c)
269075Srrh 
279094Srrh #ifdef DEBUG
289094Srrh #  define C	_C()
299094Srrh #  define C1	_C1()
309094Srrh #else not DEBUG
319094Srrh #  define C	Cget
329094Srrh #  define C1	C1get
339094Srrh #endif not DEBUG
349075Srrh 
359075Srrh #define SKIP while(C != '\n')
369075Srrh #define SKIP_TO_COM SKIP; SKIP; pc=c; while(C != '.' || pc != '\n' || C > 'Z')pc=c
379075Srrh 
389094Srrh #define	YES 1
399094Srrh #define	NO 0
409094Srrh #define	MS 0	/* -ms */
419094Srrh #define	MM 1	/* -mm */
429094Srrh #define	ME 2	/* -me */
439094Srrh #define	MA 3	/* -man */
449075Srrh 
459094Srrh #ifdef DEBUG
469094Srrh char *mactab[] = {"-ms", "-mm", "-me", "-ma"};
479094Srrh #endif DEBUG
489094Srrh 
499094Srrh #define	ONE 1
509094Srrh #define	TWO 2
519094Srrh 
529075Srrh #define NOCHAR -2
539075Srrh #define SPECIAL 0
549075Srrh #define APOS 1
559079Srrh #define PUNCT 2
569079Srrh #define DIGIT 3
579079Srrh #define LETTER 4
589075Srrh 
599094Srrh int	wordflag;
609094Srrh int	msflag;		/* processing a source written using a mac package */
619094Srrh int	mac;		/* which package */
629094Srrh int	disp;
639094Srrh int	parag;
649094Srrh int	inmacro;
659094Srrh int	intable;
669094Srrh int	keepblock;	/* keep blocks of text; normally false when msflag */
679075Srrh 
689079Srrh char chars[128];  /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
699075Srrh 
709075Srrh char line[512];
719075Srrh char *lp;
729075Srrh 
739075Srrh int c;
749075Srrh int pc;
759094Srrh int ldelim;
769094Srrh int rdelim;
779075Srrh 
789075Srrh 
799075Srrh int argc;
809075Srrh char **argv;
819075Srrh 
829075Srrh char fname[50];
839075Srrh FILE *files[15];
849075Srrh FILE **filesp;
859075Srrh FILE *infile;
869094Srrh FILE	*opn();
879094Srrh /*
889094Srrh  *	Flags for matching conditions other than
899094Srrh  *	the macro name
909094Srrh  */
919094Srrh #define	NONE		0
929094Srrh #define	FNEST		1		/* no nested files */
939094Srrh #define	NOMAC		2		/* no macro */
949094Srrh #define	MAC		3		/* macro */
959094Srrh #define	PARAG		4		/* in a paragraph */
969094Srrh #define	MSF		5		/* msflag is on */
979094Srrh #define	NBLK		6		/* set if no blocks to be kept */
989075Srrh 
999094Srrh /*
1009094Srrh  *	Return codes from macro minions, determine where to jump,
1019094Srrh  *	how to repeat/reprocess text
1029094Srrh  */
1039094Srrh #define	COMX		1		/* goto comx */
1049094Srrh #define	COM		2		/* goto com */
1059094Srrh 
1069075Srrh main(ac, av)
1079075Srrh int ac;
1089075Srrh char **av;
1099075Srrh {
1109079Srrh 	register int i;
1119094Srrh 	int	errflg = 0;
1129094Srrh 	register	optchar;
1139079Srrh 	FILE *opn();
1149094Srrh 	int	kflag = NO;
1159094Srrh 	char	*p;
1169075Srrh 
1179094Srrh 	wordflag = NO;
1189094Srrh 	msflag = NO;
1199094Srrh 	mac = ME;
1209094Srrh 	disp = NO;
1219094Srrh 	parag = NO;
1229094Srrh 	inmacro = NO;
1239094Srrh 	intable = NO;
1249094Srrh 	ldelim	= NOCHAR;
1259094Srrh 	rdelim	= NOCHAR;
1269094Srrh 	keepblock = YES;
1279094Srrh 
1289094Srrh 	for(argc = ac - 1, argv = av + 1;
1299094Srrh 	    (   (argc > 0)
1309094Srrh 	     && (argv[0][0] == '-')
1319094Srrh 	     && (argv[0][1] != '\0') );
1329094Srrh 	    --argc, ++argv
1339094Srrh 	){
1349094Srrh 		for(p = argv[0]+1; *p; ++p) {
1359094Srrh 			switch(*p) {
1369094Srrh 			case 'p':
1379094Srrh 				parag=YES;
1389094Srrh 				break;
1399094Srrh 			case 'k':
1409094Srrh 				kflag = YES;
1419094Srrh 				break;
1429094Srrh 			case 'w':
1439094Srrh 				wordflag = YES;
1449094Srrh 				kflag = YES;
1459094Srrh 				break;
1469094Srrh 			case 'm':
1479094Srrh 				msflag = YES;
1489094Srrh 				keepblock = NO;
1499094Srrh 				switch(p[1]){
1509094Srrh 				case 'm':	mac = MM; p++; break;
1519094Srrh 				case 's':	mac = MS; p++; break;
1529094Srrh 				case 'e':	mac = ME; p++; break;
1539094Srrh 				case 'a':	mac = MA; p++; break;
1549094Srrh 				case 'l':	disp = YES; p++; break;
1559094Srrh 				default:	errflg++; break;
1569094Srrh 				}
1579094Srrh 				break;
1589094Srrh 			default:
1599094Srrh 				errflg++;
1609094Srrh 			}
1619094Srrh 		}
1629075Srrh 	}
1639094Srrh 
1649094Srrh 	if (kflag)
1659094Srrh 		keepblock = YES;
1669079Srrh 	if (errflg)
1679094Srrh 		fatal("usage: deroff [ -w ] [ -k] [ -m (a e m s l) ] [ file ] ... \n",
1689094Srrh 			(char *) NULL);
1699094Srrh 
1709094Srrh #ifdef DEBUG
1719094Srrh 	printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n",
1729094Srrh 		msflag, mactab[mac], keepblock, disp);
1739094Srrh #endif DEBUG
1749094Srrh 	if (argc == 0){
1759079Srrh 		infile = stdin;
1769094Srrh 	} else {
1779094Srrh 		infile = opn(argv[0]);
1789094Srrh 		--argc;
1799094Srrh 		++argv;
1809094Srrh 	}
1819094Srrh 
1829094Srrh 
1839079Srrh 	files[0] = infile;
1849079Srrh 	filesp = &files[0];
1859075Srrh 
1869079Srrh 	for(i='a'; i<='z' ; ++i)
1879079Srrh 		chars[i] = LETTER;
1889079Srrh 	for(i='A'; i<='Z'; ++i)
1899079Srrh 		chars[i] = LETTER;
1909079Srrh 	for(i='0'; i<='9'; ++i)
1919079Srrh 		chars[i] = DIGIT;
1929079Srrh 	chars['\''] = APOS;
1939079Srrh 	chars['&'] = APOS;
1949079Srrh 	chars['.'] = PUNCT;
1959079Srrh 	chars[','] = PUNCT;
1969079Srrh 	chars[';'] = PUNCT;
1979079Srrh 	chars['?'] = PUNCT;
1989079Srrh 	chars[':'] = PUNCT;
1999079Srrh 	work();
2009079Srrh }
2019079Srrh char *calloc();
2029075Srrh 
2039075Srrh skeqn()
2049075Srrh {
2059079Srrh 	while((c = getc(infile)) != rdelim)
2069079Srrh 		if(c == EOF)
2079079Srrh 			c = eof();
2089079Srrh 		else if(c == '"')
2099079Srrh 			while( (c = getc(infile)) != '"')
2109079Srrh 				if(c == EOF)
2119075Srrh 					c = eof();
2129079Srrh 				else if(c == '\\')
2139079Srrh 					if((c = getc(infile)) == EOF)
2149079Srrh 						c = eof();
2159079Srrh 	if(msflag)return(c='x');
2169079Srrh 	return(c = ' ');
2179075Srrh }
2189075Srrh 
2199075Srrh FILE *opn(p)
2209075Srrh register char *p;
2219075Srrh {
2229079Srrh 	FILE *fd;
2239075Srrh 
224*12097Smckusick 	if( (fd = fopen(p, "r")) == NULL) {
225*12097Smckusick 		fprintf(stderr, "Deroff: ");
226*12097Smckusick 		perror(p);
227*12097Smckusick 		exit(1);
228*12097Smckusick 	}
2299075Srrh 
2309079Srrh 	return(fd);
2319075Srrh }
2329075Srrh 
2339075Srrh eof()
2349075Srrh {
2359079Srrh 	if(infile != stdin)
2369079Srrh 		fclose(infile);
2379079Srrh 	if(filesp > files)
2389079Srrh 		infile = *--filesp;
2399094Srrh 	else if (argc > 0) {
2409094Srrh 		infile = opn(argv[0]);
2419094Srrh 		--argc;
2429094Srrh 		++argv;
2439094Srrh 	} else
2449079Srrh 		exit(0);
2459079Srrh 	return(C);
2469075Srrh }
2479075Srrh 
2489075Srrh getfname()
2499075Srrh {
2509079Srrh 	register char *p;
2519079Srrh 	struct chain {
2529079Srrh 		struct chain *nextp;
2539079Srrh 		char *datap;
2549079Srrh 	} *chainblock;
2559079Srrh 	register struct chain *q;
2569079Srrh 	static struct chain *namechain	= NULL;
2579079Srrh 	char *copys();
2589075Srrh 
2599079Srrh 	while(C == ' ') ;
2609075Srrh 
2619079Srrh 	for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p)
2629079Srrh 		C;
2639079Srrh 	*p = '\0';
2649079Srrh 	while(c != '\n')
2659079Srrh 		C;
2669075Srrh 
2679079Srrh 	/* see if this name has already been used */
2689075Srrh 
2699079Srrh 	for(q = namechain ; q; q = q->nextp)
2709079Srrh 		if( ! strcmp(fname, q->datap))
2719075Srrh 		{
2729079Srrh 			fname[0] = '\0';
2739079Srrh 			return;
2749075Srrh 		}
2759075Srrh 
2769079Srrh 	q = (struct chain *) calloc(1, sizeof(*chainblock));
2779079Srrh 	q->nextp = namechain;
2789079Srrh 	q->datap = copys(fname);
2799079Srrh 	namechain = q;
2809075Srrh }
2819075Srrh 
2829075Srrh fatal(s,p)
2839075Srrh char *s, *p;
2849075Srrh {
2859079Srrh 	fprintf(stderr, "Deroff: ");
2869079Srrh 	fprintf(stderr, s, p);
2879079Srrh 	exit(1);
2889075Srrh }
2899079Srrh 
2909094Srrh /*ARGSUSED*/
2919094Srrh textline(str, const)
2929094Srrh 	char	*str;
2939094Srrh 	int	const;
2949094Srrh {
2959094Srrh 	if (wordflag) {
2969094Srrh 		msputwords(0);
2979094Srrh 		return;
2989094Srrh 	}
2999094Srrh 	puts(str);
3009094Srrh }
3019094Srrh 
3029075Srrh work()
3039075Srrh {
3049079Srrh 	for( ;; )
3059075Srrh 	{
3069094Srrh 		C;
3079094Srrh #ifdef FULLDEBUG
3089094Srrh 		printf("Starting work with `%c'\n", c);
3099094Srrh #endif FULLDEBUG
3109094Srrh 		if(c == '.'  ||  c == '\'')
3119079Srrh 			comline();
3129079Srrh 		else
3139094Srrh 			regline(textline, TWO);
3149075Srrh 	}
3159075Srrh }
3169075Srrh 
3179094Srrh regline(pfunc, const)
3189094Srrh 	int	(*pfunc)();
3199094Srrh 	int	const;
3209075Srrh {
3219079Srrh 	line[0] = c;
3229079Srrh 	lp = line;
3239079Srrh 	for( ; ; )
3249075Srrh 	{
3259094Srrh 		if(c == '\\') {
3269079Srrh 			*lp = ' ';
3279079Srrh 			backsl();
3289075Srrh 		}
3299094Srrh 		if(c == '\n')
3309094Srrh 			break;
3319094Srrh 		if(intable && c=='T') {
3329079Srrh 			*++lp = C;
3339094Srrh 			if(c=='{' || c=='}') {
3349079Srrh 				lp[-1] = ' ';
3359079Srrh 				*lp = C;
3369075Srrh 			}
3379094Srrh 		} else {
3389094Srrh 			*++lp = C;
3399075Srrh 		}
3409075Srrh 	}
3419075Srrh 
3429079Srrh 	*lp = '\0';
3439075Srrh 
3449079Srrh 	if(line[0] != '\0')
3459094Srrh 		(*pfunc)(line, const);
3469075Srrh }
3479075Srrh 
3489075Srrh macro()
3499075Srrh {
3509079Srrh 	if(msflag){
3519079Srrh 		do {
3529079Srrh 			SKIP;
3539079Srrh 		}		while(C!='.' || C!='.' || C=='.');	/* look for  .. */
3549079Srrh 		if(c != '\n')SKIP;
3559079Srrh 		return;
3569079Srrh 	}
3579079Srrh 	SKIP;
3589079Srrh 	inmacro = YES;
3599075Srrh }
3609075Srrh 
3619075Srrh tbl()
3629075Srrh {
3639079Srrh 	while(C != '.');
3649079Srrh 	SKIP;
3659079Srrh 	intable = YES;
3669075Srrh }
3679075Srrh stbl()
3689075Srrh {
3699079Srrh 	while(C != '.');
3709079Srrh 	SKIP_TO_COM;
3719079Srrh 	if(c != 'T' || C != 'E'){
3729079Srrh 		SKIP;
3739079Srrh 		pc=c;
3749079Srrh 		while(C != '.' || pc != '\n' || C != 'T' || C != 'E')pc=c;
3759079Srrh 	}
3769075Srrh }
3779075Srrh 
3789075Srrh eqn()
3799075Srrh {
3809079Srrh 	register int c1, c2;
3819079Srrh 	register int dflg;
3829079Srrh 	char last;
3839075Srrh 
3849079Srrh 	last=0;
3859079Srrh 	dflg = 1;
3869079Srrh 	SKIP;
3879075Srrh 
3889079Srrh 	for( ;;)
3899075Srrh 	{
3909079Srrh 		if(C1 == '.'  || c == '\'')
3919075Srrh 		{
3929079Srrh 			while(C1==' ' || c=='\t')
3939079Srrh 				;
3949079Srrh 			if(c=='E' && C1=='N')
3959075Srrh 			{
3969079Srrh 				SKIP;
3979079Srrh 				if(msflag && dflg){
3989079Srrh 					putchar('x');
3999079Srrh 					putchar(' ');
4009079Srrh 					if(last){
4019079Srrh 						putchar(last);
4029079Srrh 						putchar('\n');
4039079Srrh 					}
4049079Srrh 				}
4059079Srrh 				return;
4069075Srrh 			}
4079075Srrh 		}
4089079Srrh 		else if(c == 'd')	/* look for delim */
4099075Srrh 		{
4109079Srrh 			if(C1=='e' && C1=='l')
4119079Srrh 				if( C1=='i' && C1=='m')
4129075Srrh 				{
4139079Srrh 					while(C1 == ' ');
4149079Srrh 					if((c1=c)=='\n' || (c2=C1)=='\n'
4159079Srrh 					    || (c1=='o' && c2=='f' && C1=='f') )
4169079Srrh 					{
4179079Srrh 						ldelim = NOCHAR;
4189079Srrh 						rdelim = NOCHAR;
4199079Srrh 					}
4209079Srrh 					else	{
4219079Srrh 						ldelim = c1;
4229079Srrh 						rdelim = c2;
4239079Srrh 					}
4249075Srrh 				}
4259075Srrh 			dflg = 0;
4269075Srrh 		}
4279075Srrh 
4289079Srrh 		if(c != '\n') while(C1 != '\n'){
4299079Srrh 			if(chars[c] == PUNCT)last = c;
4309079Srrh 			else if(c != ' ')last = 0;
4319079Srrh 		}
4329075Srrh 	}
4339075Srrh }
4349075Srrh 
4359075Srrh backsl()	/* skip over a complete backslash construction */
4369075Srrh {
4379079Srrh 	int bdelim;
4389075Srrh 
4399079Srrh sw:
4409079Srrh 	switch(C)
4419075Srrh 	{
4429075Srrh 	case '"':
4439075Srrh 		SKIP;
4449075Srrh 		return;
4459075Srrh 	case 's':
4469075Srrh 		if(C == '\\') backsl();
4479075Srrh 		else	{
4489075Srrh 			while(C>='0' && c<='9') ;
4499075Srrh 			ungetc(c,infile);
4509075Srrh 			c = '0';
4519079Srrh 		}
4529075Srrh 		--lp;
4539075Srrh 		return;
4549075Srrh 
4559075Srrh 	case 'f':
4569075Srrh 	case 'n':
4579075Srrh 	case '*':
4589075Srrh 		if(C != '(')
4599075Srrh 			return;
4609075Srrh 
4619075Srrh 	case '(':
4629079Srrh 		if(msflag){
4639079Srrh 			if(C == 'e'){
4649079Srrh 				if(C == 'm'){
4659079Srrh 					*lp = '-';
4669079Srrh 					return;
4679079Srrh 				}
4689079Srrh 			}
4699079Srrh 			else if(c != '\n')C;
4709079Srrh 			return;
4719079Srrh 		}
4729075Srrh 		if(C != '\n') C;
4739075Srrh 		return;
4749075Srrh 
4759075Srrh 	case '$':
4769075Srrh 		C;	/* discard argument number */
4779075Srrh 		return;
4789075Srrh 
4799075Srrh 	case 'b':
4809075Srrh 	case 'x':
4819075Srrh 	case 'v':
4829075Srrh 	case 'h':
4839075Srrh 	case 'w':
4849075Srrh 	case 'o':
4859075Srrh 	case 'l':
4869075Srrh 	case 'L':
4879075Srrh 		if( (bdelim=C) == '\n')
4889075Srrh 			return;
4899075Srrh 		while(C!='\n' && c!=bdelim)
4909075Srrh 			if(c == '\\') backsl();
4919075Srrh 		return;
4929075Srrh 
4939075Srrh 	case '\\':
4949075Srrh 		if(inmacro)
4959075Srrh 			goto sw;
4969075Srrh 	default:
4979075Srrh 		return;
4989075Srrh 	}
4999075Srrh }
5009075Srrh 
5019075Srrh char *copys(s)
5029075Srrh register char *s;
5039075Srrh {
5049079Srrh 	register char *t, *t0;
5059075Srrh 
5069079Srrh 	if( (t0 = t = calloc( (unsigned)(strlen(s)+1), sizeof(*t) ) ) == NULL)
5079079Srrh 		fatal("Cannot allocate memory", (char *) NULL);
5089075Srrh 
5099079Srrh 	while( *t++ = *s++ )
5109079Srrh 		;
5119079Srrh 	return(t0);
5129075Srrh }
5139094Srrh 
5149094Srrh sce()
5159094Srrh {
5169079Srrh 	register char *ap;
5179079Srrh 	register int n, i;
5189079Srrh 	char a[10];
5199075Srrh 	for(ap=a;C != '\n';ap++){
5209075Srrh 		*ap = c;
5219075Srrh 		if(ap == &a[9]){
5229075Srrh 			SKIP;
5239075Srrh 			ap=a;
5249075Srrh 			break;
5259075Srrh 		}
5269075Srrh 	}
5279075Srrh 	if(ap != a)n = atoi(a);
5289075Srrh 	else n = 1;
5299075Srrh 	for(i=0;i<n;){
5309075Srrh 		if(C == '.'){
5319075Srrh 			if(C == 'c'){
5329075Srrh 				if(C == 'e'){
5339075Srrh 					while(C == ' ');
5349079Srrh 					if(c == '0'){
5359079Srrh 						SKIP;
5369079Srrh 						break;
5379079Srrh 					}
5389075Srrh 					else SKIP;
5399075Srrh 				}
5409075Srrh 				else SKIP;
5419075Srrh 			}
5429079Srrh 			else if(c == 'P' || C == 'P'){
5439079Srrh 				if(c != '\n')SKIP;
5449079Srrh 				break;
5459079Srrh 			}
5469079Srrh 			else if(c != '\n')SKIP;
5479075Srrh 		}
5489075Srrh 		else {
5499075Srrh 			SKIP;
5509075Srrh 			i++;
5519075Srrh 		}
5529075Srrh 	}
5539075Srrh }
5549094Srrh 
5559079Srrh refer(c1)
5569079Srrh {
5579079Srrh 	register int c2;
5589079Srrh 	if(c1 != '\n')
5599079Srrh 		SKIP;
5609079Srrh 	while(1){
5619079Srrh 		if(C != '.')
5629079Srrh 			SKIP;
5639079Srrh 		else {
5649079Srrh 			if(C != ']')
5659079Srrh 				SKIP;
5669079Srrh 			else {
5679079Srrh 				while(C != '\n')
5689079Srrh 					c2=c;
5699079Srrh 				if(chars[c2] == PUNCT)putchar(c2);
5709079Srrh 				return;
5719079Srrh 			}
5729079Srrh 		}
5739079Srrh 	}
5749079Srrh }
5759094Srrh 
5769094Srrh inpic()
5779094Srrh {
5789079Srrh 	register int c1;
5799079Srrh 	register char *p1;
5809079Srrh 	SKIP;
5819079Srrh 	p1 = line;
5829079Srrh 	c = '\n';
5839079Srrh 	while(1){
5849079Srrh 		c1 = c;
5859079Srrh 		if(C == '.' && c1 == '\n'){
5869079Srrh 			if(C != 'P'){
5879079Srrh 				if(c == '\n')continue;
5889079Srrh 				else { SKIP; c='\n'; continue;}
5899079Srrh 			}
5909079Srrh 			if(C != 'E'){
5919079Srrh 				if(c == '\n')continue;
5929079Srrh 				else { SKIP; c='\n';continue; }
5939079Srrh 			}
5949079Srrh 			SKIP;
5959079Srrh 			return;
5969079Srrh 		}
5979079Srrh 		else if(c == '\"'){
5989079Srrh 			while(C != '\"'){
5999079Srrh 				if(c == '\\'){
6009079Srrh 					if(C == '\"')continue;
6019079Srrh 					ungetc(c,infile);
6029079Srrh 					backsl();
6039079Srrh 				}
6049079Srrh 				else *p1++ = c;
6059079Srrh 			}
6069079Srrh 			*p1++ = ' ';
6079079Srrh 		}
6089079Srrh 		else if(c == '\n' && p1 != line){
6099079Srrh 			*p1 = '\0';
6109094Srrh 			if(wordflag)msputwords(NO);
6119079Srrh 			else {
6129079Srrh 				puts(line);
6139079Srrh 				putchar('\n');
6149079Srrh 			}
6159079Srrh 			p1 = line;
6169079Srrh 		}
6179079Srrh 	}
6189079Srrh }
6199094Srrh 
6209094Srrh #ifdef DEBUG
6219094Srrh _C1()
6229094Srrh {
6239094Srrh 	return(C1get);
6249094Srrh }
6259094Srrh _C()
6269094Srrh {
6279094Srrh 	return(Cget);
6289094Srrh }
6299094Srrh #endif DEBUG
6309094Srrh 
6319094Srrh /*
6329094Srrh  *	Macro processing
6339094Srrh  *
6349094Srrh  *	Macro table definitions
6359094Srrh  */
6369094Srrh #define	reg	register
6379094Srrh typedef	int pacmac;		/* compressed macro name */
6389094Srrh int	argconcat = 0;		/* concat arguments together (-me only) */
6399094Srrh 
6409094Srrh #define	tomac(c1, c2)		((((c1) & 0xFF) << 8) | ((c2) & 0xFF))
6419094Srrh #define	frommac(src, c1, c2)	(((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF))
6429094Srrh 
6439094Srrh struct	mactab{
6449094Srrh 	int	condition;
6459094Srrh 	pacmac	macname;
6469094Srrh 	int	(*func)();
6479094Srrh };
6489094Srrh struct	mactab	troffmactab[];
6499094Srrh struct	mactab	ppmactab[];
6509094Srrh struct	mactab	msmactab[];
6519094Srrh struct	mactab	mmmactab[];
6529094Srrh struct	mactab	memactab[];
6539094Srrh struct	mactab	manmactab[];
6549094Srrh /*
6559094Srrh  *	macro table initialization
6569094Srrh  */
6579094Srrh #define	M(cond, c1, c2, func) {cond, tomac(c1, c2), func}
6589094Srrh 
6599094Srrh /*
6609094Srrh  *	Put out a macro line, using ms and mm conventions.
6619094Srrh  */
6629094Srrh msputmac(s, const)
6639094Srrh 	register char *s;
6649094Srrh 	int	const;
6659094Srrh {
6669094Srrh 	register char *t;
6679094Srrh 	register found;
6689094Srrh 	int last;
6699094Srrh 	found = 0;
6709094Srrh 
6719094Srrh 	if (wordflag) {
6729094Srrh 		msputwords(YES);
6739094Srrh 		return;
6749094Srrh 	}
6759094Srrh 	while(*s)
6769094Srrh 	{
6779094Srrh 		while(*s==' ' || *s=='\t')
6789094Srrh 			putchar(*s++);
6799094Srrh 		for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t)
6809094Srrh 			;
6819094Srrh 		if(*s == '\"')s++;
6829094Srrh 		if(t>s+const && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER){
6839094Srrh 			while(s < t)
6849094Srrh 				if(*s == '\"')s++;
6859094Srrh 				else
6869094Srrh 					putchar(*s++);
6879094Srrh 			last = *(t-1);
6889094Srrh 			found++;
6899094Srrh 		}
6909094Srrh 		else if(found && chars[ s[0] ] == PUNCT && s[1] == '\0')
6919094Srrh 			putchar(*s++);
6929094Srrh 		else{
6939094Srrh 			last = *(t-1);
6949094Srrh 			s = t;
6959094Srrh 		}
6969094Srrh 	}
6979094Srrh 	putchar('\n');
6989094Srrh 	if(msflag && chars[last] == PUNCT){
6999094Srrh 		putchar(last);
7009094Srrh 		putchar('\n');
7019094Srrh 	}
7029094Srrh }
7039094Srrh /*
7049094Srrh  *	put out words (for the -w option) with ms and mm conventions
7059094Srrh  */
7069094Srrh msputwords(macline)
7079094Srrh 	int macline;	/* is this is a macro line */
7089094Srrh {
7099094Srrh 	register char *p, *p1;
7109094Srrh 	int i, nlet;
7119094Srrh 
7129094Srrh 	for(p1 = line ; ;) {
7139094Srrh 		/*
7149094Srrh 		 *	skip initial specials ampersands and apostrophes
7159094Srrh 		 */
7169094Srrh 		while( chars[*p1] < DIGIT)
7179094Srrh 			if(*p1++ == '\0') return;
7189094Srrh 		nlet = 0;
7199094Srrh 		for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p)
7209094Srrh 			if(i == LETTER) ++nlet;
7219094Srrh 
7229094Srrh 		if (   (macline && nlet > 1)
7239094Srrh 		    || (!macline && nlet > 2
7249094Srrh 				 && chars[p1[0]] == LETTER
7259094Srrh 				 && chars[p1[1]] == LETTER) )
7269094Srrh 		{
7279094Srrh 			/*
7289094Srrh 			 *	delete trailing ampersands and apostrophes
7299094Srrh 			 */
7309094Srrh 			while(  (p[-1]=='\'')
7319094Srrh 			     || (p[-1]=='&')
7329094Srrh 			     || (chars[p[-1]] == PUNCT) ){
7339094Srrh 				--p;
7349094Srrh 			}
7359094Srrh 			while(p1 < p)
7369094Srrh 				putchar(*p1++);
7379094Srrh 			putchar('\n');
7389094Srrh 		} else {
7399094Srrh 			p1 = p;
7409094Srrh 		}
7419094Srrh 	}
7429094Srrh }
7439094Srrh /*
7449094Srrh  *	put out a macro using the me conventions
7459094Srrh  */
7469094Srrh #define SKIPBLANK(cp)	while(*cp == ' ' || *cp == '\t') { cp++; }
7479094Srrh #define SKIPNONBLANK(cp) while(*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
7489094Srrh 
7499094Srrh meputmac(cp, const)
7509094Srrh 	reg	char	*cp;
7519094Srrh 		int	const;
7529094Srrh {
7539094Srrh 	reg	char	*np;
7549094Srrh 		int	found;
7559094Srrh 		int	argno;
7569094Srrh 		int	last;
7579094Srrh 		int	inquote;
7589094Srrh 
7599094Srrh 	if (wordflag) {
7609094Srrh 		meputwords(YES);
7619094Srrh 		return;
7629094Srrh 	}
7639094Srrh 	for (argno = 0; *cp; argno++){
7649094Srrh 		SKIPBLANK(cp);
7659094Srrh 		inquote = (*cp == '"');
7669094Srrh 		if (inquote)
7679094Srrh 			cp++;
7689094Srrh 		for (np = cp; *np; np++){
7699094Srrh 			switch(*np){
7709094Srrh 			case '\n':
7719094Srrh 			case '\0':	break;
7729094Srrh 			case '\t':
7739094Srrh 			case ' ':	if (inquote) {
7749094Srrh 						continue;
7759094Srrh 					} else {
7769094Srrh 						goto endarg;
7779094Srrh 					}
7789094Srrh 			case '"':	if(inquote && np[1] == '"'){
7799094Srrh 						strcpy(np, np + 1);
7809094Srrh 						np++;
7819094Srrh 						continue;
7829094Srrh 					} else {
7839094Srrh 						*np = ' '; 	/* bye bye " */
7849094Srrh 						goto endarg;
7859094Srrh 					}
7869094Srrh 			default:	continue;
7879094Srrh 			}
7889094Srrh 		}
7899094Srrh 		endarg: ;
7909094Srrh 		/*
7919094Srrh 		 *	cp points at the first char in the arg
7929094Srrh 		 *	np points one beyond the last char in the arg
7939094Srrh 		 */
7949094Srrh 		if ((argconcat == 0) || (argconcat != argno)) {
7959094Srrh 			putchar(' ');
7969094Srrh 		}
7979094Srrh #ifdef FULLDEBUG
7989094Srrh 		{
7999094Srrh 			char	*p;
8009094Srrh 			printf("[%d,%d: ", argno, np - cp);
8019094Srrh 			for (p = cp; p < np; p++) {
8029094Srrh 				putchar(*p);
8039094Srrh 			}
8049094Srrh 			printf("]");
8059094Srrh 		}
8069094Srrh #endif FULLDEBUG
8079094Srrh 		/*
8089094Srrh 		 *	Determine if the argument merits being printed
8099094Srrh 		 *
8109094Srrh 		 *	const is the cut off point below which something
8119094Srrh 		 *	is not a word.
8129094Srrh 		 */
8139094Srrh 		if (   ( (np - cp) > const)
8149094Srrh 		    && (    inquote
8159094Srrh 		         || (chars[cp[0]] == LETTER)) ){
8169094Srrh 			for (cp = cp; cp < np; cp++){
8179094Srrh 				putchar(*cp);
8189094Srrh 			}
8199094Srrh 			last = np[-1];
8209094Srrh 			found++;
8219094Srrh 		} else
8229094Srrh 		if(found && (np - cp == 1) && chars[*cp] == PUNCT){
8239094Srrh 			putchar(*cp);
8249094Srrh 		} else {
8259094Srrh 			last = np[-1];
8269094Srrh 		}
8279094Srrh 		cp = np;
8289094Srrh 	}
8299094Srrh 	if(msflag && chars[last] == PUNCT)
8309094Srrh 		putchar(last);
8319094Srrh 	putchar('\n');
8329094Srrh }
8339094Srrh /*
8349094Srrh  *	put out words (for the -w option) with ms and mm conventions
8359094Srrh  */
8369094Srrh meputwords(macline)
8379094Srrh 	int	macline;
8389094Srrh {
8399094Srrh 	msputwords(macline);
8409094Srrh }
8419094Srrh /*
8429094Srrh  *
8439094Srrh  *	Skip over a nested set of macros
8449094Srrh  *
8459094Srrh  *	Possible arguments to noblock are:
8469094Srrh  *
8479094Srrh  *	fi	end of unfilled text
8489094Srrh  *	PE	pic ending
8499094Srrh  *	DE	display ending
8509094Srrh  *
8519094Srrh  *	for ms and mm only:
8529094Srrh  *		KE	keep ending
8539094Srrh  *
8549094Srrh  *		NE	undocumented match to NS (for mm?)
8559094Srrh  *		LE	mm only: matches RL or *L (for lists)
8569094Srrh  *
8579094Srrh  *	for me:
8589094Srrh  *		([lqbzcdf]
8599094Srrh  */
8609094Srrh 
8619094Srrh noblock(a1, a2)
8629094Srrh 	char a1, a2;
8639094Srrh {
8649094Srrh 	register int c1,c2;
8659094Srrh 	register int eqnf;
8669094Srrh 	int lct;
8679094Srrh 	lct = 0;
8689094Srrh 	eqnf = 1;
8699094Srrh 	SKIP;
8709094Srrh 	while(1){
8719094Srrh 		while(C != '.')
8729094Srrh 			if(c == '\n')
8739094Srrh 				continue;
8749094Srrh 			else
8759094Srrh 				SKIP;
8769094Srrh 		if((c1=C) == '\n')
8779094Srrh 			continue;
8789094Srrh 		if((c2=C) == '\n')
8799094Srrh 			continue;
8809094Srrh 		if(c1==a1 && c2 == a2){
8819094Srrh 			SKIP;
8829094Srrh 			if(lct != 0){
8839094Srrh 				lct--;
8849094Srrh 				continue;
8859094Srrh 			}
8869094Srrh 			if(eqnf)
8879094Srrh 				putchar('.');
8889094Srrh 			putchar('\n');
8899094Srrh 			return;
8909094Srrh 		} else if(a1 == 'L' && c2 == 'L'){
8919094Srrh 			lct++;
8929094Srrh 			SKIP;
8939094Srrh 		}
8949094Srrh 		/*
8959094Srrh 		 *	equations (EQ) nested within a display
8969094Srrh 		 */
8979094Srrh 		else if(c1 == 'E' && c2 == 'Q'){
8989094Srrh 			if (   (mac == ME && a1 == ')')
8999094Srrh 			    || (mac != ME && a1 == 'D') ) {
9009094Srrh 				eqn();
9019094Srrh 				eqnf=0;
9029094Srrh 			}
9039094Srrh 		}
9049094Srrh 		/*
9059094Srrh 		 *	turning on filling is done by the paragraphing
9069094Srrh 		 *	macros
9079094Srrh 		 */
9089094Srrh 		else if(a1 == 'f') {	/* .fi */
9099094Srrh 			if  (  (mac == ME && (c2 == 'h' || c2 == 'p'))
9109094Srrh 			     ||(mac != ME && (c1 == 'P' || c2 == 'P')) ) {
9119094Srrh 				SKIP;
9129094Srrh 				return;
9139094Srrh 			}
9149094Srrh 		} else {
9159094Srrh 			SKIP;
9169094Srrh 		}
9179094Srrh 	}
9189094Srrh }
9199094Srrh 
9209094Srrh EQ()
9219094Srrh {
9229094Srrh 	eqn();
9239094Srrh 	return(0);
9249094Srrh }
9259094Srrh domacro()
9269094Srrh {
9279094Srrh 	macro();
9289094Srrh 	return(0);
9299094Srrh }
9309094Srrh PS()
9319094Srrh {
9329094Srrh 	if (!msflag) {
9339094Srrh 		inpic();
9349094Srrh 	} else {
9359094Srrh 		noblock('P', 'E');
9369094Srrh 	}
9379094Srrh 	return(0);
9389094Srrh }
9399094Srrh 
9409094Srrh skip()
9419094Srrh {
9429094Srrh 	SKIP;
9439094Srrh 	return(0);
9449094Srrh }
9459094Srrh 
9469094Srrh intbl()
9479094Srrh {
9489094Srrh 	if(msflag){
9499094Srrh 		stbl();
9509094Srrh 	}
9519094Srrh 	else tbl();
9529094Srrh 	return(0);
9539094Srrh }
9549094Srrh 
9559094Srrh outtbl(){ intable = NO; }
9569094Srrh 
9579094Srrh so()
9589094Srrh {
9599094Srrh 	getfname();
9609094Srrh 	if( fname[0] )
9619094Srrh 		infile = *++filesp = opn( fname );
9629094Srrh 	return(0);
9639094Srrh }
9649094Srrh nx()
9659094Srrh {
9669094Srrh 	getfname();
9679094Srrh 	if(fname[0] == '\0') exit(0);
9689094Srrh 	if(infile != stdin)
9699094Srrh 		fclose(infile);
9709094Srrh 	infile = *filesp = opn(fname);
9719094Srrh 	return(0);
9729094Srrh }
9739094Srrh skiptocom(){ SKIP_TO_COM; return(COMX); }
9749094Srrh 
9759094Srrh PP(c12)
9769094Srrh 	pacmac	c12;
9779094Srrh {
9789094Srrh 	int	c1, c2;
9799094Srrh 
9809094Srrh 	frommac(c12, c1, c2);
9819094Srrh 	printf(".%c%c",c1,c2);
9829094Srrh 	while(C != '\n')putchar(c);
9839094Srrh 	putchar('\n');
9849094Srrh 	return(0);
9859094Srrh }
9869094Srrh AU()
9879094Srrh {
9889094Srrh 	if(mac==MM) {
9899094Srrh 		return(0);
9909094Srrh 	} else {
9919094Srrh 		SKIP_TO_COM;
9929094Srrh 		return(COMX);
9939094Srrh 	}
9949094Srrh }
9959094Srrh 
9969094Srrh SH(c12)
9979094Srrh 	pacmac	c12;
9989094Srrh {
9999094Srrh 	int	c1, c2;
10009094Srrh 
10019094Srrh 	frommac(c12, c1, c2);
10029094Srrh 
10039094Srrh 	if(parag){
10049094Srrh 		printf(".%c%c",c1,c2);
10059094Srrh 		while(C != '\n')putchar(c);
10069094Srrh 		putchar(c);
10079094Srrh 		putchar('!');
10089094Srrh 		while(1){
10099094Srrh 			while(C != '\n')putchar(c);
10109094Srrh 			putchar('\n');
10119094Srrh 			if(C == '.')
10129094Srrh 				return(COM);
10139094Srrh 			putchar('!');
10149094Srrh 			putchar(c);
10159094Srrh 		}
10169094Srrh 		/*NOTREACHED*/
10179094Srrh 	} else {
10189094Srrh 		SKIP_TO_COM;
10199094Srrh 		return(COMX);
10209094Srrh 	}
10219094Srrh }
10229094Srrh 
10239094Srrh UX()
10249094Srrh {
10259094Srrh 	if(wordflag)
10269094Srrh 		printf("UNIX\n");
10279094Srrh 	else
10289094Srrh 		printf("UNIX ");
10299094Srrh 	return(0);
10309094Srrh }
10319094Srrh 
10329094Srrh MMHU(c12)
10339094Srrh 	pacmac	c12;
10349094Srrh {
10359094Srrh 	int	c1, c2;
10369094Srrh 
10379094Srrh 	frommac(c12, c1, c2);
10389094Srrh 	if(parag){
10399094Srrh 		printf(".%c%c",c1,c2);
10409094Srrh 		while(C != '\n')putchar(c);
10419094Srrh 		putchar('\n');
10429094Srrh 	} else {
10439094Srrh 		SKIP;
10449094Srrh 	}
10459094Srrh 	return(0);
10469094Srrh }
10479094Srrh 
10489094Srrh mesnblock(c12)
10499094Srrh 	pacmac	c12;
10509094Srrh {
10519094Srrh 	int	c1, c2;
10529094Srrh 
10539094Srrh 	frommac(c12, c1, c2);
10549094Srrh 	noblock(')',c2);
10559094Srrh 	return(0);
10569094Srrh }
10579094Srrh mssnblock(c12)
10589094Srrh 	pacmac	c12;
10599094Srrh {
10609094Srrh 	int	c1, c2;
10619094Srrh 
10629094Srrh 	frommac(c12, c1, c2);
10639094Srrh 	noblock(c1,'E');
10649094Srrh 	return(0);
10659094Srrh }
10669094Srrh nf()
10679094Srrh {
10689094Srrh 	noblock('f','i');
10699094Srrh 	return(0);
10709094Srrh }
10719094Srrh 
10729094Srrh ce()
10739094Srrh {
10749094Srrh 	sce();
10759094Srrh 	return(0);
10769094Srrh }
10779094Srrh 
10789094Srrh meip(c12)
10799094Srrh 	pacmac	c12;
10809094Srrh {
10819094Srrh 	if(parag)
10829094Srrh 		mepp(c12);
10839094Srrh 	else if (wordflag)	/* save the tag */
10849094Srrh 		regline(meputmac, ONE);
10859094Srrh 	else {
10869094Srrh 		SKIP;
10879094Srrh 	}
10889094Srrh 	return(0);
10899094Srrh }
10909094Srrh /*
10919094Srrh  *	only called for -me .pp or .sh, when parag is on
10929094Srrh  */
10939094Srrh mepp(c12)
10949094Srrh 	pacmac	c12;
10959094Srrh {
10969094Srrh 	PP(c12);		/* eats the line */
10979094Srrh 	return(0);
10989094Srrh }
10999094Srrh /*
11009094Srrh  *	Start of a section heading; output the section name if doing words
11019094Srrh  */
11029094Srrh mesh(c12)
11039094Srrh 	pacmac	c12;
11049094Srrh {
11059094Srrh 	if (parag)
11069094Srrh 		mepp(c12);
11079094Srrh 	else if (wordflag)
11089094Srrh 		defcomline(c12);
11099094Srrh 	else {
11109094Srrh 		SKIP;
11119094Srrh 	}
11129094Srrh 	return(0);
11139094Srrh }
11149094Srrh /*
11159094Srrh  *	process a font setting
11169094Srrh  */
11179094Srrh mefont(c12)
11189094Srrh 	pacmac	c12;
11199094Srrh {
11209094Srrh 	argconcat = 1;
11219094Srrh 	defcomline(c12);
11229094Srrh 	argconcat = 0;
11239094Srrh 	return(0);
11249094Srrh }
11259094Srrh manfont(c12)
11269094Srrh 	pacmac	c12;
11279094Srrh {
11289094Srrh 	return(mefont(c12));
11299094Srrh }
11309094Srrh manpp(c12)
11319094Srrh 	pacmac	c12;
11329094Srrh {
11339094Srrh 	return(mepp(c12));
11349094Srrh }
11359094Srrh 
11369094Srrh defcomline(c12)
11379094Srrh 	pacmac	c12;
11389094Srrh {
11399094Srrh 	int	c1, c2;
11409094Srrh 
11419094Srrh 	frommac(c12, c1, c2);
11429094Srrh 	if(msflag && mac==MM && c2=='L'){
11439094Srrh 		if(disp || c1 == 'R') {
11449094Srrh 			noblock('L','E');
11459094Srrh 		} else {
11469094Srrh 			SKIP;
11479094Srrh 			putchar('.');
11489094Srrh 		}
11499094Srrh 	}
11509094Srrh 	else if(c1=='.' && c2=='.'){
11519094Srrh 		if(msflag){
11529094Srrh 			SKIP;
11539094Srrh 			return;
11549094Srrh 		}
11559094Srrh 		while(C == '.')
11569094Srrh 			/*VOID*/;
11579094Srrh 	}
11589094Srrh 	++inmacro;
11599094Srrh 	/*
11609094Srrh 	 *	Process the arguments to the macro
11619094Srrh 	 */
11629094Srrh 	switch(mac){
11639094Srrh 	default:
11649094Srrh 	case MM:
11659094Srrh 	case MS:
11669094Srrh 		if(c1 <= 'Z' && msflag)
11679094Srrh 			regline(msputmac, ONE);
11689094Srrh 		else
11699094Srrh 			regline(msputmac, TWO);
11709094Srrh 		break;
11719094Srrh 	case ME:
11729094Srrh 		regline(meputmac, ONE);
11739094Srrh 		break;
11749094Srrh 	}
11759094Srrh 	--inmacro;
11769094Srrh }
11779094Srrh 
11789094Srrh comline()
11799094Srrh {
11809094Srrh 	reg	int	c1;
11819094Srrh 	reg	int	c2;
11829094Srrh 		pacmac	c12;
11839094Srrh 	reg	int	mid;
11849094Srrh 		int	lb, ub;
11859094Srrh 		int	hit;
11869094Srrh 	static	int	tabsize = 0;
11879094Srrh 	static	struct	mactab	*mactab = (struct mactab *)0;
11889094Srrh 	reg	struct	mactab	*mp;
11899094Srrh 
11909094Srrh 	if (mactab == 0){
11919094Srrh 		 buildtab(&mactab, &tabsize);
11929094Srrh 	}
11939094Srrh com:
11949094Srrh 	while(C==' ' || c=='\t')
11959094Srrh 		;
11969094Srrh comx:
11979094Srrh 	if( (c1=c) == '\n')
11989094Srrh 		return;
11999094Srrh 	c2 = C;
12009094Srrh 	if(c1=='.' && c2 !='.')
12019094Srrh 		inmacro = NO;
12029094Srrh 	if(msflag && c1 == '['){
12039094Srrh 		refer(c2);
12049094Srrh 		return;
12059094Srrh 	}
12069094Srrh 	if(parag && mac==MM && c1 == 'P' && c2 == '\n'){
12079094Srrh 		printf(".P\n");
12089094Srrh 		return;
12099094Srrh 	}
12109094Srrh 	if(c2 == '\n')
12119094Srrh 		return;
12129094Srrh 	/*
12139094Srrh 	 *	Single letter macro
12149094Srrh 	 */
12159094Srrh 	if (mac == ME && (c2 == ' ' || c2 == '\t') )
12169094Srrh 		c2 = ' ';
12179094Srrh 	c12 = tomac(c1, c2);
12189094Srrh 	/*
12199094Srrh 	 *	binary search through the table of macros
12209094Srrh 	 */
12219094Srrh 	lb = 0;
12229094Srrh 	ub = tabsize - 1;
12239094Srrh 	while(lb <= ub){
12249094Srrh 		mid = (ub + lb) / 2;
12259094Srrh 		mp = &mactab[mid];
12269094Srrh 		if (mp->macname < c12)
12279094Srrh 			lb = mid + 1;
12289094Srrh 		else if (mp->macname > c12)
12299094Srrh 			ub = mid - 1;
12309094Srrh 		else {
12319094Srrh 			hit = 1;
12329094Srrh #ifdef FULLDEBUG
12339094Srrh 			printf("preliminary hit macro %c%c ", c1, c2);
12349094Srrh #endif FULLDEBUG
12359094Srrh 			switch(mp->condition){
12369094Srrh 			case NONE:	hit = YES;			break;
12379094Srrh 			case FNEST:	hit = (filesp == files);	break;
12389094Srrh 			case NOMAC:	hit = !inmacro;			break;
12399094Srrh 			case MAC:	hit = inmacro;			break;
12409094Srrh 			case PARAG:	hit = parag;			break;
12419094Srrh 			case NBLK:	hit = !keepblock;		break;
12429094Srrh 			default:	hit = 0;
12439094Srrh 			}
12449094Srrh 			if (hit) {
12459094Srrh #ifdef FULLDEBUG
12469094Srrh 				printf("MATCH\n");
12479094Srrh #endif FULLDEBUG
12489094Srrh 				switch( (*(mp->func))(c12) ) {
12499094Srrh 				default: 	return;
12509094Srrh 				case COMX:	goto comx;
12519094Srrh 				case COM:	goto com;
12529094Srrh 				}
12539094Srrh 			}
12549094Srrh #ifdef FULLDEBUG
12559094Srrh 			printf("FAIL\n");
12569094Srrh #endif FULLDEBUG
12579094Srrh 			break;
12589094Srrh 		}
12599094Srrh 	}
12609094Srrh 	defcomline(c12);
12619094Srrh }
12629094Srrh 
12639094Srrh int macsort(p1, p2)
12649094Srrh 	struct	mactab	*p1, *p2;
12659094Srrh {
12669094Srrh 	return(p1->macname - p2->macname);
12679094Srrh }
12689094Srrh 
12699094Srrh int sizetab(mp)
12709094Srrh 	reg	struct	mactab	*mp;
12719094Srrh {
12729094Srrh 	reg	int	i;
12739094Srrh 	i = 0;
12749094Srrh 	if (mp){
12759094Srrh 		for (; mp->macname; mp++, i++)
12769094Srrh 			/*VOID*/ ;
12779094Srrh 	}
12789094Srrh 	return(i);
12799094Srrh }
12809094Srrh 
12819094Srrh struct mactab *macfill(dst, src)
12829094Srrh 	reg	struct	mactab	*dst;
12839094Srrh 	reg	struct	mactab	*src;
12849094Srrh {
12859094Srrh 	if (src) {
12869094Srrh 		while(src->macname){
12879094Srrh 			*dst++ = *src++;
12889094Srrh 		}
12899094Srrh 	}
12909094Srrh 	return(dst);
12919094Srrh }
12929094Srrh 
12939094Srrh buildtab(r_back, r_size)
12949094Srrh 	struct	mactab	**r_back;
12959094Srrh 	int	*r_size;
12969094Srrh {
12979094Srrh 	int	size;
12989094Srrh 
12999094Srrh 	struct	mactab	*p, *p1, *p2;
13009094Srrh 	struct	mactab	*back;
13019094Srrh 
13029094Srrh 	size = sizetab(troffmactab);
13039094Srrh 	size += sizetab(ppmactab);
13049094Srrh 	p1 = p2 = (struct mactab *)0;
13059094Srrh 	if (msflag){
13069094Srrh 		switch(mac){
13079094Srrh 		case ME:	p1 = memactab; break;
13089094Srrh 		case MM:	p1 = msmactab;
13099094Srrh 				p2 = mmmactab; break;
13109094Srrh 
13119094Srrh 		case MS:	p1 = msmactab; break;
13129094Srrh 		case MA:	p1 = manmactab; break;
13139094Srrh 		default:	break;
13149094Srrh 		}
13159094Srrh 	}
13169094Srrh 	size += sizetab(p1);
13179094Srrh 	size += sizetab(p2);
13189094Srrh 	back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
13199094Srrh 
13209094Srrh 	p = macfill(back, troffmactab);
13219094Srrh 	p = macfill(p, ppmactab);
13229094Srrh 	p = macfill(p, p1);
13239094Srrh 	p = macfill(p, p2);
13249094Srrh 
13259094Srrh 	qsort(back, size, sizeof(struct mactab), macsort);
13269094Srrh 	*r_size = size;
13279094Srrh 	*r_back = back;
13289094Srrh }
13299094Srrh 
13309094Srrh /*
13319094Srrh  *	troff commands
13329094Srrh  */
13339094Srrh struct	mactab	troffmactab[] = {
13349094Srrh 	M(NONE,		'\\','"',	skip),	/* comment */
13359094Srrh 	M(NOMAC,	'd','e',	domacro),	/* define */
13369094Srrh 	M(NOMAC,	'i','g',	domacro),	/* ignore till .. */
13379094Srrh 	M(NOMAC,	'a','m',	domacro),	/* append macro */
13389094Srrh 	M(NBLK,		'n','f',	nf),	/* filled */
13399094Srrh 	M(NBLK,		'c','e',	ce),	/* centered */
13409094Srrh 
13419094Srrh 	M(NONE,		's','o',	so),	/* source a file */
13429094Srrh 	M(NONE,		'n','x',	nx),	/* go to next file */
13439094Srrh 
13449094Srrh 	M(NONE,		't','m',	skip),	/* print string on tty */
13459094Srrh 	M(NONE,		'h','w',	skip),	/* exception hyphen words */
13469094Srrh 	M(NONE,		0,0,		0)
13479094Srrh };
13489094Srrh /*
13499094Srrh  *	Preprocessor output
13509094Srrh  */
13519094Srrh struct	mactab	ppmactab[] = {
13529094Srrh 	M(FNEST,	'E','Q',	EQ),	/* equation starting */
13539094Srrh 	M(FNEST,	'T','S',	intbl),	/* table starting */
13549094Srrh 	M(FNEST,	'T','C',	intbl),	/* alternative table? */
13559094Srrh 	M(FNEST,	'T','&',	intbl),	/* table reformatting */
13569094Srrh 	M(NONE,		'T','E',	outtbl),/* table ending */
13579094Srrh 	M(NONE,		'P','S',	PS),	/* picture starting */
13589094Srrh 	M(NONE,		0,0,		0)
13599094Srrh };
13609094Srrh /*
13619094Srrh  *	Particular to ms and mm
13629094Srrh  */
13639094Srrh struct	mactab	msmactab[] = {
13649094Srrh 	M(NONE,		'T','L',	skiptocom),	/* title follows */
13659094Srrh 	M(NONE,		'F','S',	skiptocom),	/* start footnote */
13669094Srrh 	M(NONE,		'O','K',	skiptocom),	/* Other kws */
13679094Srrh 
13689094Srrh 	M(NONE,		'N','R',	skip),	/* undocumented */
13699094Srrh 	M(NONE,		'N','D',	skip),	/* use supplied date */
13709094Srrh 
13719094Srrh 	M(PARAG,	'P','P',	PP),	/* begin parag */
13729094Srrh 	M(PARAG,	'I','P',	PP),	/* begin indent parag, tag x */
13739094Srrh 	M(PARAG,	'L','P',	PP),	/* left blocked parag */
13749094Srrh 
13759094Srrh 	M(NONE,		'A','U',	AU),	/* author */
13769094Srrh 	M(NONE,		'A','I',	AU),	/* authors institution */
13779094Srrh 
13789094Srrh 	M(NONE,		'S','H',	SH),	/* section heading */
13799094Srrh 	M(NONE,		'S','N',	SH),	/* undocumented */
13809094Srrh 	M(NONE,		'U','X',	UX),	/* unix */
13819094Srrh 
13829094Srrh 	M(NBLK,		'D','S',	mssnblock),	/* start display text */
13839094Srrh 	M(NBLK,		'K','S',	mssnblock),	/* start keep */
13849094Srrh 	M(NBLK,		'K','F',	mssnblock),	/* start float keep */
13859094Srrh 	M(NONE,		0,0,		0)
13869094Srrh };
13879094Srrh 
13889094Srrh struct	mactab	mmmactab[] = {
13899094Srrh 	M(NONE,		'H',' ',	MMHU),	/* -mm ? */
13909094Srrh 	M(NONE,		'H','U',	MMHU),	/* -mm ? */
13919094Srrh 	M(PARAG,	'P',' ',	PP),	/* paragraph for -mm */
13929094Srrh 	M(NBLK,		'N','S',	mssnblock),	/* undocumented */
13939094Srrh 	M(NONE,		0,0,		0)
13949094Srrh };
13959094Srrh 
13969094Srrh struct	mactab	memactab[] = {
13979094Srrh 	M(PARAG,	'p','p',	mepp),
13989094Srrh 	M(PARAG,	'l','p',	mepp),
13999094Srrh 	M(PARAG,	'n','p',	mepp),
14009094Srrh 	M(NONE,		'i','p',	meip),
14019094Srrh 
14029094Srrh 	M(NONE,		's','h',	mesh),
14039094Srrh 	M(NONE,		'u','h',	mesh),
14049094Srrh 
14059094Srrh 	M(NBLK,		'(','l',	mesnblock),
14069094Srrh 	M(NBLK,		'(','q',	mesnblock),
14079094Srrh 	M(NBLK,		'(','b',	mesnblock),
14089094Srrh 	M(NBLK,		'(','z',	mesnblock),
14099094Srrh 	M(NBLK,		'(','c',	mesnblock),
14109094Srrh 
14119094Srrh 	M(NBLK,		'(','d',	mesnblock),
14129094Srrh 	M(NBLK,		'(','f',	mesnblock),
14139094Srrh 	M(NBLK,		'(','x',	mesnblock),
14149094Srrh 
14159094Srrh 	M(NONE,		'r',' ',	mefont),
14169094Srrh 	M(NONE,		'i',' ',	mefont),
14179094Srrh 	M(NONE,		'b',' ',	mefont),
14189094Srrh 	M(NONE,		'u',' ',	mefont),
14199094Srrh 	M(NONE,		'q',' ',	mefont),
14209094Srrh 	M(NONE,		'r','b',	mefont),
14219094Srrh 	M(NONE,		'b','i',	mefont),
14229094Srrh 	M(NONE,		'b','x',	mefont),
14239094Srrh 	M(NONE,		0,0,		0)
14249094Srrh };
14259094Srrh 
14269094Srrh 
14279094Srrh struct	mactab	manmactab[] = {
14289094Srrh 	M(PARAG,	'B','I',	manfont),
14299094Srrh 	M(PARAG,	'B','R',	manfont),
14309094Srrh 	M(PARAG,	'I','B',	manfont),
14319094Srrh 	M(PARAG,	'I','R',	manfont),
14329094Srrh 	M(PARAG,	'R','B',	manfont),
14339094Srrh 	M(PARAG,	'R','I',	manfont),
14349094Srrh 
14359094Srrh 	M(PARAG,	'P','P',	manpp),
14369094Srrh 	M(PARAG,	'L','P',	manpp),
14379094Srrh 	M(PARAG,	'H','P',	manpp),
14389094Srrh 	M(NONE,		0,0,		0)
14399094Srrh };
1440