xref: /csrg-svn/usr.bin/deroff/deroff.c (revision 17534)
19075Srrh #ifndef lint
2*17534Sralph static char sccsid[] = "@(#)deroff.c	4.5	(Berkeley)	84/12/18";
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 
22412097Smckusick 	if( (fd = fopen(p, "r")) == NULL) {
22512097Smckusick 		fprintf(stderr, "Deroff: ");
22612097Smckusick 		perror(p);
22712097Smckusick 		exit(1);
22812097Smckusick 	}
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 
722*17534Sralph 		if (nlet > 1 && chars[p1[0]] == LETTER) {
7239094Srrh 			/*
7249094Srrh 			 *	delete trailing ampersands and apostrophes
7259094Srrh 			 */
726*17534Sralph 			while( (i=chars[p[-1]]) == PUNCT || i == APOS )
7279094Srrh 				--p;
7289094Srrh 			while(p1 < p)
7299094Srrh 				putchar(*p1++);
7309094Srrh 			putchar('\n');
7319094Srrh 		} else {
7329094Srrh 			p1 = p;
7339094Srrh 		}
7349094Srrh 	}
7359094Srrh }
7369094Srrh /*
7379094Srrh  *	put out a macro using the me conventions
7389094Srrh  */
7399094Srrh #define SKIPBLANK(cp)	while(*cp == ' ' || *cp == '\t') { cp++; }
7409094Srrh #define SKIPNONBLANK(cp) while(*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
7419094Srrh 
7429094Srrh meputmac(cp, const)
7439094Srrh 	reg	char	*cp;
7449094Srrh 		int	const;
7459094Srrh {
7469094Srrh 	reg	char	*np;
7479094Srrh 		int	found;
7489094Srrh 		int	argno;
7499094Srrh 		int	last;
7509094Srrh 		int	inquote;
7519094Srrh 
7529094Srrh 	if (wordflag) {
7539094Srrh 		meputwords(YES);
7549094Srrh 		return;
7559094Srrh 	}
7569094Srrh 	for (argno = 0; *cp; argno++){
7579094Srrh 		SKIPBLANK(cp);
7589094Srrh 		inquote = (*cp == '"');
7599094Srrh 		if (inquote)
7609094Srrh 			cp++;
7619094Srrh 		for (np = cp; *np; np++){
7629094Srrh 			switch(*np){
7639094Srrh 			case '\n':
7649094Srrh 			case '\0':	break;
7659094Srrh 			case '\t':
7669094Srrh 			case ' ':	if (inquote) {
7679094Srrh 						continue;
7689094Srrh 					} else {
7699094Srrh 						goto endarg;
7709094Srrh 					}
7719094Srrh 			case '"':	if(inquote && np[1] == '"'){
7729094Srrh 						strcpy(np, np + 1);
7739094Srrh 						np++;
7749094Srrh 						continue;
7759094Srrh 					} else {
7769094Srrh 						*np = ' '; 	/* bye bye " */
7779094Srrh 						goto endarg;
7789094Srrh 					}
7799094Srrh 			default:	continue;
7809094Srrh 			}
7819094Srrh 		}
7829094Srrh 		endarg: ;
7839094Srrh 		/*
7849094Srrh 		 *	cp points at the first char in the arg
7859094Srrh 		 *	np points one beyond the last char in the arg
7869094Srrh 		 */
7879094Srrh 		if ((argconcat == 0) || (argconcat != argno)) {
7889094Srrh 			putchar(' ');
7899094Srrh 		}
7909094Srrh #ifdef FULLDEBUG
7919094Srrh 		{
7929094Srrh 			char	*p;
7939094Srrh 			printf("[%d,%d: ", argno, np - cp);
7949094Srrh 			for (p = cp; p < np; p++) {
7959094Srrh 				putchar(*p);
7969094Srrh 			}
7979094Srrh 			printf("]");
7989094Srrh 		}
7999094Srrh #endif FULLDEBUG
8009094Srrh 		/*
8019094Srrh 		 *	Determine if the argument merits being printed
8029094Srrh 		 *
8039094Srrh 		 *	const is the cut off point below which something
8049094Srrh 		 *	is not a word.
8059094Srrh 		 */
8069094Srrh 		if (   ( (np - cp) > const)
8079094Srrh 		    && (    inquote
8089094Srrh 		         || (chars[cp[0]] == LETTER)) ){
8099094Srrh 			for (cp = cp; cp < np; cp++){
8109094Srrh 				putchar(*cp);
8119094Srrh 			}
8129094Srrh 			last = np[-1];
8139094Srrh 			found++;
8149094Srrh 		} else
8159094Srrh 		if(found && (np - cp == 1) && chars[*cp] == PUNCT){
8169094Srrh 			putchar(*cp);
8179094Srrh 		} else {
8189094Srrh 			last = np[-1];
8199094Srrh 		}
8209094Srrh 		cp = np;
8219094Srrh 	}
8229094Srrh 	if(msflag && chars[last] == PUNCT)
8239094Srrh 		putchar(last);
8249094Srrh 	putchar('\n');
8259094Srrh }
8269094Srrh /*
8279094Srrh  *	put out words (for the -w option) with ms and mm conventions
8289094Srrh  */
8299094Srrh meputwords(macline)
8309094Srrh 	int	macline;
8319094Srrh {
8329094Srrh 	msputwords(macline);
8339094Srrh }
8349094Srrh /*
8359094Srrh  *
8369094Srrh  *	Skip over a nested set of macros
8379094Srrh  *
8389094Srrh  *	Possible arguments to noblock are:
8399094Srrh  *
8409094Srrh  *	fi	end of unfilled text
8419094Srrh  *	PE	pic ending
8429094Srrh  *	DE	display ending
8439094Srrh  *
8449094Srrh  *	for ms and mm only:
8459094Srrh  *		KE	keep ending
8469094Srrh  *
8479094Srrh  *		NE	undocumented match to NS (for mm?)
8489094Srrh  *		LE	mm only: matches RL or *L (for lists)
8499094Srrh  *
8509094Srrh  *	for me:
8519094Srrh  *		([lqbzcdf]
8529094Srrh  */
8539094Srrh 
8549094Srrh noblock(a1, a2)
8559094Srrh 	char a1, a2;
8569094Srrh {
8579094Srrh 	register int c1,c2;
8589094Srrh 	register int eqnf;
8599094Srrh 	int lct;
8609094Srrh 	lct = 0;
8619094Srrh 	eqnf = 1;
8629094Srrh 	SKIP;
8639094Srrh 	while(1){
8649094Srrh 		while(C != '.')
8659094Srrh 			if(c == '\n')
8669094Srrh 				continue;
8679094Srrh 			else
8689094Srrh 				SKIP;
8699094Srrh 		if((c1=C) == '\n')
8709094Srrh 			continue;
8719094Srrh 		if((c2=C) == '\n')
8729094Srrh 			continue;
8739094Srrh 		if(c1==a1 && c2 == a2){
8749094Srrh 			SKIP;
8759094Srrh 			if(lct != 0){
8769094Srrh 				lct--;
8779094Srrh 				continue;
8789094Srrh 			}
8799094Srrh 			if(eqnf)
8809094Srrh 				putchar('.');
8819094Srrh 			putchar('\n');
8829094Srrh 			return;
8839094Srrh 		} else if(a1 == 'L' && c2 == 'L'){
8849094Srrh 			lct++;
8859094Srrh 			SKIP;
8869094Srrh 		}
8879094Srrh 		/*
8889094Srrh 		 *	equations (EQ) nested within a display
8899094Srrh 		 */
8909094Srrh 		else if(c1 == 'E' && c2 == 'Q'){
8919094Srrh 			if (   (mac == ME && a1 == ')')
8929094Srrh 			    || (mac != ME && a1 == 'D') ) {
8939094Srrh 				eqn();
8949094Srrh 				eqnf=0;
8959094Srrh 			}
8969094Srrh 		}
8979094Srrh 		/*
8989094Srrh 		 *	turning on filling is done by the paragraphing
8999094Srrh 		 *	macros
9009094Srrh 		 */
9019094Srrh 		else if(a1 == 'f') {	/* .fi */
9029094Srrh 			if  (  (mac == ME && (c2 == 'h' || c2 == 'p'))
9039094Srrh 			     ||(mac != ME && (c1 == 'P' || c2 == 'P')) ) {
9049094Srrh 				SKIP;
9059094Srrh 				return;
9069094Srrh 			}
9079094Srrh 		} else {
9089094Srrh 			SKIP;
9099094Srrh 		}
9109094Srrh 	}
9119094Srrh }
9129094Srrh 
9139094Srrh EQ()
9149094Srrh {
9159094Srrh 	eqn();
9169094Srrh 	return(0);
9179094Srrh }
9189094Srrh domacro()
9199094Srrh {
9209094Srrh 	macro();
9219094Srrh 	return(0);
9229094Srrh }
9239094Srrh PS()
9249094Srrh {
9259094Srrh 	if (!msflag) {
9269094Srrh 		inpic();
9279094Srrh 	} else {
9289094Srrh 		noblock('P', 'E');
9299094Srrh 	}
9309094Srrh 	return(0);
9319094Srrh }
9329094Srrh 
9339094Srrh skip()
9349094Srrh {
9359094Srrh 	SKIP;
9369094Srrh 	return(0);
9379094Srrh }
9389094Srrh 
9399094Srrh intbl()
9409094Srrh {
9419094Srrh 	if(msflag){
9429094Srrh 		stbl();
9439094Srrh 	}
9449094Srrh 	else tbl();
9459094Srrh 	return(0);
9469094Srrh }
9479094Srrh 
9489094Srrh outtbl(){ intable = NO; }
9499094Srrh 
9509094Srrh so()
9519094Srrh {
9529094Srrh 	getfname();
9539094Srrh 	if( fname[0] )
9549094Srrh 		infile = *++filesp = opn( fname );
9559094Srrh 	return(0);
9569094Srrh }
9579094Srrh nx()
9589094Srrh {
9599094Srrh 	getfname();
9609094Srrh 	if(fname[0] == '\0') exit(0);
9619094Srrh 	if(infile != stdin)
9629094Srrh 		fclose(infile);
9639094Srrh 	infile = *filesp = opn(fname);
9649094Srrh 	return(0);
9659094Srrh }
9669094Srrh skiptocom(){ SKIP_TO_COM; return(COMX); }
9679094Srrh 
9689094Srrh PP(c12)
9699094Srrh 	pacmac	c12;
9709094Srrh {
9719094Srrh 	int	c1, c2;
9729094Srrh 
9739094Srrh 	frommac(c12, c1, c2);
9749094Srrh 	printf(".%c%c",c1,c2);
9759094Srrh 	while(C != '\n')putchar(c);
9769094Srrh 	putchar('\n');
9779094Srrh 	return(0);
9789094Srrh }
9799094Srrh AU()
9809094Srrh {
9819094Srrh 	if(mac==MM) {
9829094Srrh 		return(0);
9839094Srrh 	} else {
9849094Srrh 		SKIP_TO_COM;
9859094Srrh 		return(COMX);
9869094Srrh 	}
9879094Srrh }
9889094Srrh 
9899094Srrh SH(c12)
9909094Srrh 	pacmac	c12;
9919094Srrh {
9929094Srrh 	int	c1, c2;
9939094Srrh 
9949094Srrh 	frommac(c12, c1, c2);
9959094Srrh 
9969094Srrh 	if(parag){
9979094Srrh 		printf(".%c%c",c1,c2);
9989094Srrh 		while(C != '\n')putchar(c);
9999094Srrh 		putchar(c);
10009094Srrh 		putchar('!');
10019094Srrh 		while(1){
10029094Srrh 			while(C != '\n')putchar(c);
10039094Srrh 			putchar('\n');
10049094Srrh 			if(C == '.')
10059094Srrh 				return(COM);
10069094Srrh 			putchar('!');
10079094Srrh 			putchar(c);
10089094Srrh 		}
10099094Srrh 		/*NOTREACHED*/
10109094Srrh 	} else {
10119094Srrh 		SKIP_TO_COM;
10129094Srrh 		return(COMX);
10139094Srrh 	}
10149094Srrh }
10159094Srrh 
10169094Srrh UX()
10179094Srrh {
10189094Srrh 	if(wordflag)
10199094Srrh 		printf("UNIX\n");
10209094Srrh 	else
10219094Srrh 		printf("UNIX ");
10229094Srrh 	return(0);
10239094Srrh }
10249094Srrh 
10259094Srrh MMHU(c12)
10269094Srrh 	pacmac	c12;
10279094Srrh {
10289094Srrh 	int	c1, c2;
10299094Srrh 
10309094Srrh 	frommac(c12, c1, c2);
10319094Srrh 	if(parag){
10329094Srrh 		printf(".%c%c",c1,c2);
10339094Srrh 		while(C != '\n')putchar(c);
10349094Srrh 		putchar('\n');
10359094Srrh 	} else {
10369094Srrh 		SKIP;
10379094Srrh 	}
10389094Srrh 	return(0);
10399094Srrh }
10409094Srrh 
10419094Srrh mesnblock(c12)
10429094Srrh 	pacmac	c12;
10439094Srrh {
10449094Srrh 	int	c1, c2;
10459094Srrh 
10469094Srrh 	frommac(c12, c1, c2);
10479094Srrh 	noblock(')',c2);
10489094Srrh 	return(0);
10499094Srrh }
10509094Srrh mssnblock(c12)
10519094Srrh 	pacmac	c12;
10529094Srrh {
10539094Srrh 	int	c1, c2;
10549094Srrh 
10559094Srrh 	frommac(c12, c1, c2);
10569094Srrh 	noblock(c1,'E');
10579094Srrh 	return(0);
10589094Srrh }
10599094Srrh nf()
10609094Srrh {
10619094Srrh 	noblock('f','i');
10629094Srrh 	return(0);
10639094Srrh }
10649094Srrh 
10659094Srrh ce()
10669094Srrh {
10679094Srrh 	sce();
10689094Srrh 	return(0);
10699094Srrh }
10709094Srrh 
10719094Srrh meip(c12)
10729094Srrh 	pacmac	c12;
10739094Srrh {
10749094Srrh 	if(parag)
10759094Srrh 		mepp(c12);
10769094Srrh 	else if (wordflag)	/* save the tag */
10779094Srrh 		regline(meputmac, ONE);
10789094Srrh 	else {
10799094Srrh 		SKIP;
10809094Srrh 	}
10819094Srrh 	return(0);
10829094Srrh }
10839094Srrh /*
10849094Srrh  *	only called for -me .pp or .sh, when parag is on
10859094Srrh  */
10869094Srrh mepp(c12)
10879094Srrh 	pacmac	c12;
10889094Srrh {
10899094Srrh 	PP(c12);		/* eats the line */
10909094Srrh 	return(0);
10919094Srrh }
10929094Srrh /*
10939094Srrh  *	Start of a section heading; output the section name if doing words
10949094Srrh  */
10959094Srrh mesh(c12)
10969094Srrh 	pacmac	c12;
10979094Srrh {
10989094Srrh 	if (parag)
10999094Srrh 		mepp(c12);
11009094Srrh 	else if (wordflag)
11019094Srrh 		defcomline(c12);
11029094Srrh 	else {
11039094Srrh 		SKIP;
11049094Srrh 	}
11059094Srrh 	return(0);
11069094Srrh }
11079094Srrh /*
11089094Srrh  *	process a font setting
11099094Srrh  */
11109094Srrh mefont(c12)
11119094Srrh 	pacmac	c12;
11129094Srrh {
11139094Srrh 	argconcat = 1;
11149094Srrh 	defcomline(c12);
11159094Srrh 	argconcat = 0;
11169094Srrh 	return(0);
11179094Srrh }
11189094Srrh manfont(c12)
11199094Srrh 	pacmac	c12;
11209094Srrh {
11219094Srrh 	return(mefont(c12));
11229094Srrh }
11239094Srrh manpp(c12)
11249094Srrh 	pacmac	c12;
11259094Srrh {
11269094Srrh 	return(mepp(c12));
11279094Srrh }
11289094Srrh 
11299094Srrh defcomline(c12)
11309094Srrh 	pacmac	c12;
11319094Srrh {
11329094Srrh 	int	c1, c2;
11339094Srrh 
11349094Srrh 	frommac(c12, c1, c2);
11359094Srrh 	if(msflag && mac==MM && c2=='L'){
11369094Srrh 		if(disp || c1 == 'R') {
11379094Srrh 			noblock('L','E');
11389094Srrh 		} else {
11399094Srrh 			SKIP;
11409094Srrh 			putchar('.');
11419094Srrh 		}
11429094Srrh 	}
11439094Srrh 	else if(c1=='.' && c2=='.'){
11449094Srrh 		if(msflag){
11459094Srrh 			SKIP;
11469094Srrh 			return;
11479094Srrh 		}
11489094Srrh 		while(C == '.')
11499094Srrh 			/*VOID*/;
11509094Srrh 	}
11519094Srrh 	++inmacro;
11529094Srrh 	/*
11539094Srrh 	 *	Process the arguments to the macro
11549094Srrh 	 */
11559094Srrh 	switch(mac){
11569094Srrh 	default:
11579094Srrh 	case MM:
11589094Srrh 	case MS:
11599094Srrh 		if(c1 <= 'Z' && msflag)
11609094Srrh 			regline(msputmac, ONE);
11619094Srrh 		else
11629094Srrh 			regline(msputmac, TWO);
11639094Srrh 		break;
11649094Srrh 	case ME:
11659094Srrh 		regline(meputmac, ONE);
11669094Srrh 		break;
11679094Srrh 	}
11689094Srrh 	--inmacro;
11699094Srrh }
11709094Srrh 
11719094Srrh comline()
11729094Srrh {
11739094Srrh 	reg	int	c1;
11749094Srrh 	reg	int	c2;
11759094Srrh 		pacmac	c12;
11769094Srrh 	reg	int	mid;
11779094Srrh 		int	lb, ub;
11789094Srrh 		int	hit;
11799094Srrh 	static	int	tabsize = 0;
11809094Srrh 	static	struct	mactab	*mactab = (struct mactab *)0;
11819094Srrh 	reg	struct	mactab	*mp;
11829094Srrh 
11839094Srrh 	if (mactab == 0){
11849094Srrh 		 buildtab(&mactab, &tabsize);
11859094Srrh 	}
11869094Srrh com:
11879094Srrh 	while(C==' ' || c=='\t')
11889094Srrh 		;
11899094Srrh comx:
11909094Srrh 	if( (c1=c) == '\n')
11919094Srrh 		return;
11929094Srrh 	c2 = C;
11939094Srrh 	if(c1=='.' && c2 !='.')
11949094Srrh 		inmacro = NO;
11959094Srrh 	if(msflag && c1 == '['){
11969094Srrh 		refer(c2);
11979094Srrh 		return;
11989094Srrh 	}
11999094Srrh 	if(parag && mac==MM && c1 == 'P' && c2 == '\n'){
12009094Srrh 		printf(".P\n");
12019094Srrh 		return;
12029094Srrh 	}
12039094Srrh 	if(c2 == '\n')
12049094Srrh 		return;
12059094Srrh 	/*
12069094Srrh 	 *	Single letter macro
12079094Srrh 	 */
12089094Srrh 	if (mac == ME && (c2 == ' ' || c2 == '\t') )
12099094Srrh 		c2 = ' ';
12109094Srrh 	c12 = tomac(c1, c2);
12119094Srrh 	/*
12129094Srrh 	 *	binary search through the table of macros
12139094Srrh 	 */
12149094Srrh 	lb = 0;
12159094Srrh 	ub = tabsize - 1;
12169094Srrh 	while(lb <= ub){
12179094Srrh 		mid = (ub + lb) / 2;
12189094Srrh 		mp = &mactab[mid];
12199094Srrh 		if (mp->macname < c12)
12209094Srrh 			lb = mid + 1;
12219094Srrh 		else if (mp->macname > c12)
12229094Srrh 			ub = mid - 1;
12239094Srrh 		else {
12249094Srrh 			hit = 1;
12259094Srrh #ifdef FULLDEBUG
12269094Srrh 			printf("preliminary hit macro %c%c ", c1, c2);
12279094Srrh #endif FULLDEBUG
12289094Srrh 			switch(mp->condition){
12299094Srrh 			case NONE:	hit = YES;			break;
12309094Srrh 			case FNEST:	hit = (filesp == files);	break;
12319094Srrh 			case NOMAC:	hit = !inmacro;			break;
12329094Srrh 			case MAC:	hit = inmacro;			break;
12339094Srrh 			case PARAG:	hit = parag;			break;
12349094Srrh 			case NBLK:	hit = !keepblock;		break;
12359094Srrh 			default:	hit = 0;
12369094Srrh 			}
12379094Srrh 			if (hit) {
12389094Srrh #ifdef FULLDEBUG
12399094Srrh 				printf("MATCH\n");
12409094Srrh #endif FULLDEBUG
12419094Srrh 				switch( (*(mp->func))(c12) ) {
12429094Srrh 				default: 	return;
12439094Srrh 				case COMX:	goto comx;
12449094Srrh 				case COM:	goto com;
12459094Srrh 				}
12469094Srrh 			}
12479094Srrh #ifdef FULLDEBUG
12489094Srrh 			printf("FAIL\n");
12499094Srrh #endif FULLDEBUG
12509094Srrh 			break;
12519094Srrh 		}
12529094Srrh 	}
12539094Srrh 	defcomline(c12);
12549094Srrh }
12559094Srrh 
12569094Srrh int macsort(p1, p2)
12579094Srrh 	struct	mactab	*p1, *p2;
12589094Srrh {
12599094Srrh 	return(p1->macname - p2->macname);
12609094Srrh }
12619094Srrh 
12629094Srrh int sizetab(mp)
12639094Srrh 	reg	struct	mactab	*mp;
12649094Srrh {
12659094Srrh 	reg	int	i;
12669094Srrh 	i = 0;
12679094Srrh 	if (mp){
12689094Srrh 		for (; mp->macname; mp++, i++)
12699094Srrh 			/*VOID*/ ;
12709094Srrh 	}
12719094Srrh 	return(i);
12729094Srrh }
12739094Srrh 
12749094Srrh struct mactab *macfill(dst, src)
12759094Srrh 	reg	struct	mactab	*dst;
12769094Srrh 	reg	struct	mactab	*src;
12779094Srrh {
12789094Srrh 	if (src) {
12799094Srrh 		while(src->macname){
12809094Srrh 			*dst++ = *src++;
12819094Srrh 		}
12829094Srrh 	}
12839094Srrh 	return(dst);
12849094Srrh }
12859094Srrh 
12869094Srrh buildtab(r_back, r_size)
12879094Srrh 	struct	mactab	**r_back;
12889094Srrh 	int	*r_size;
12899094Srrh {
12909094Srrh 	int	size;
12919094Srrh 
12929094Srrh 	struct	mactab	*p, *p1, *p2;
12939094Srrh 	struct	mactab	*back;
12949094Srrh 
12959094Srrh 	size = sizetab(troffmactab);
12969094Srrh 	size += sizetab(ppmactab);
12979094Srrh 	p1 = p2 = (struct mactab *)0;
12989094Srrh 	if (msflag){
12999094Srrh 		switch(mac){
13009094Srrh 		case ME:	p1 = memactab; break;
13019094Srrh 		case MM:	p1 = msmactab;
13029094Srrh 				p2 = mmmactab; break;
13039094Srrh 
13049094Srrh 		case MS:	p1 = msmactab; break;
13059094Srrh 		case MA:	p1 = manmactab; break;
13069094Srrh 		default:	break;
13079094Srrh 		}
13089094Srrh 	}
13099094Srrh 	size += sizetab(p1);
13109094Srrh 	size += sizetab(p2);
13119094Srrh 	back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
13129094Srrh 
13139094Srrh 	p = macfill(back, troffmactab);
13149094Srrh 	p = macfill(p, ppmactab);
13159094Srrh 	p = macfill(p, p1);
13169094Srrh 	p = macfill(p, p2);
13179094Srrh 
13189094Srrh 	qsort(back, size, sizeof(struct mactab), macsort);
13199094Srrh 	*r_size = size;
13209094Srrh 	*r_back = back;
13219094Srrh }
13229094Srrh 
13239094Srrh /*
13249094Srrh  *	troff commands
13259094Srrh  */
13269094Srrh struct	mactab	troffmactab[] = {
13279094Srrh 	M(NONE,		'\\','"',	skip),	/* comment */
13289094Srrh 	M(NOMAC,	'd','e',	domacro),	/* define */
13299094Srrh 	M(NOMAC,	'i','g',	domacro),	/* ignore till .. */
13309094Srrh 	M(NOMAC,	'a','m',	domacro),	/* append macro */
13319094Srrh 	M(NBLK,		'n','f',	nf),	/* filled */
13329094Srrh 	M(NBLK,		'c','e',	ce),	/* centered */
13339094Srrh 
13349094Srrh 	M(NONE,		's','o',	so),	/* source a file */
13359094Srrh 	M(NONE,		'n','x',	nx),	/* go to next file */
13369094Srrh 
13379094Srrh 	M(NONE,		't','m',	skip),	/* print string on tty */
13389094Srrh 	M(NONE,		'h','w',	skip),	/* exception hyphen words */
13399094Srrh 	M(NONE,		0,0,		0)
13409094Srrh };
13419094Srrh /*
13429094Srrh  *	Preprocessor output
13439094Srrh  */
13449094Srrh struct	mactab	ppmactab[] = {
13459094Srrh 	M(FNEST,	'E','Q',	EQ),	/* equation starting */
13469094Srrh 	M(FNEST,	'T','S',	intbl),	/* table starting */
13479094Srrh 	M(FNEST,	'T','C',	intbl),	/* alternative table? */
13489094Srrh 	M(FNEST,	'T','&',	intbl),	/* table reformatting */
13499094Srrh 	M(NONE,		'T','E',	outtbl),/* table ending */
13509094Srrh 	M(NONE,		'P','S',	PS),	/* picture starting */
13519094Srrh 	M(NONE,		0,0,		0)
13529094Srrh };
13539094Srrh /*
13549094Srrh  *	Particular to ms and mm
13559094Srrh  */
13569094Srrh struct	mactab	msmactab[] = {
13579094Srrh 	M(NONE,		'T','L',	skiptocom),	/* title follows */
13589094Srrh 	M(NONE,		'F','S',	skiptocom),	/* start footnote */
13599094Srrh 	M(NONE,		'O','K',	skiptocom),	/* Other kws */
13609094Srrh 
13619094Srrh 	M(NONE,		'N','R',	skip),	/* undocumented */
13629094Srrh 	M(NONE,		'N','D',	skip),	/* use supplied date */
13639094Srrh 
13649094Srrh 	M(PARAG,	'P','P',	PP),	/* begin parag */
13659094Srrh 	M(PARAG,	'I','P',	PP),	/* begin indent parag, tag x */
13669094Srrh 	M(PARAG,	'L','P',	PP),	/* left blocked parag */
13679094Srrh 
13689094Srrh 	M(NONE,		'A','U',	AU),	/* author */
13699094Srrh 	M(NONE,		'A','I',	AU),	/* authors institution */
13709094Srrh 
13719094Srrh 	M(NONE,		'S','H',	SH),	/* section heading */
13729094Srrh 	M(NONE,		'S','N',	SH),	/* undocumented */
13739094Srrh 	M(NONE,		'U','X',	UX),	/* unix */
13749094Srrh 
13759094Srrh 	M(NBLK,		'D','S',	mssnblock),	/* start display text */
13769094Srrh 	M(NBLK,		'K','S',	mssnblock),	/* start keep */
13779094Srrh 	M(NBLK,		'K','F',	mssnblock),	/* start float keep */
13789094Srrh 	M(NONE,		0,0,		0)
13799094Srrh };
13809094Srrh 
13819094Srrh struct	mactab	mmmactab[] = {
13829094Srrh 	M(NONE,		'H',' ',	MMHU),	/* -mm ? */
13839094Srrh 	M(NONE,		'H','U',	MMHU),	/* -mm ? */
13849094Srrh 	M(PARAG,	'P',' ',	PP),	/* paragraph for -mm */
13859094Srrh 	M(NBLK,		'N','S',	mssnblock),	/* undocumented */
13869094Srrh 	M(NONE,		0,0,		0)
13879094Srrh };
13889094Srrh 
13899094Srrh struct	mactab	memactab[] = {
13909094Srrh 	M(PARAG,	'p','p',	mepp),
13919094Srrh 	M(PARAG,	'l','p',	mepp),
13929094Srrh 	M(PARAG,	'n','p',	mepp),
13939094Srrh 	M(NONE,		'i','p',	meip),
13949094Srrh 
13959094Srrh 	M(NONE,		's','h',	mesh),
13969094Srrh 	M(NONE,		'u','h',	mesh),
13979094Srrh 
13989094Srrh 	M(NBLK,		'(','l',	mesnblock),
13999094Srrh 	M(NBLK,		'(','q',	mesnblock),
14009094Srrh 	M(NBLK,		'(','b',	mesnblock),
14019094Srrh 	M(NBLK,		'(','z',	mesnblock),
14029094Srrh 	M(NBLK,		'(','c',	mesnblock),
14039094Srrh 
14049094Srrh 	M(NBLK,		'(','d',	mesnblock),
14059094Srrh 	M(NBLK,		'(','f',	mesnblock),
14069094Srrh 	M(NBLK,		'(','x',	mesnblock),
14079094Srrh 
14089094Srrh 	M(NONE,		'r',' ',	mefont),
14099094Srrh 	M(NONE,		'i',' ',	mefont),
14109094Srrh 	M(NONE,		'b',' ',	mefont),
14119094Srrh 	M(NONE,		'u',' ',	mefont),
14129094Srrh 	M(NONE,		'q',' ',	mefont),
14139094Srrh 	M(NONE,		'r','b',	mefont),
14149094Srrh 	M(NONE,		'b','i',	mefont),
14159094Srrh 	M(NONE,		'b','x',	mefont),
14169094Srrh 	M(NONE,		0,0,		0)
14179094Srrh };
14189094Srrh 
14199094Srrh 
14209094Srrh struct	mactab	manmactab[] = {
14219094Srrh 	M(PARAG,	'B','I',	manfont),
14229094Srrh 	M(PARAG,	'B','R',	manfont),
14239094Srrh 	M(PARAG,	'I','B',	manfont),
14249094Srrh 	M(PARAG,	'I','R',	manfont),
14259094Srrh 	M(PARAG,	'R','B',	manfont),
14269094Srrh 	M(PARAG,	'R','I',	manfont),
14279094Srrh 
14289094Srrh 	M(PARAG,	'P','P',	manpp),
14299094Srrh 	M(PARAG,	'L','P',	manpp),
14309094Srrh 	M(PARAG,	'H','P',	manpp),
14319094Srrh 	M(NONE,		0,0,		0)
14329094Srrh };
1433