xref: /plan9/sys/src/cmd/deroff.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier /*
63e12c5d1SDavid du Colombier  * Deroff command -- strip troff, eqn, and tbl sequences from
73e12c5d1SDavid du Colombier  * a file.  Has three flags argument, -w, to cause output one word per line
83e12c5d1SDavid du Colombier  * rather than in the original format.
93e12c5d1SDavid du Colombier  * -mm (or -ms) causes the corresponding macro's to be interpreted
103e12c5d1SDavid du Colombier  * so that just sentences are output
113e12c5d1SDavid du Colombier  * -ml  also gets rid of lists.
123e12c5d1SDavid du Colombier  * -i causes deroff to ignore .so and .nx commands.
133e12c5d1SDavid du Colombier  * Deroff follows .so and .nx commands, removes contents of macro
143e12c5d1SDavid du Colombier  * definitions, equations (both .EQ ... .EN and $...$),
153e12c5d1SDavid du Colombier  * Tbl command sequences, and Troff backslash vconstructions.
163e12c5d1SDavid du Colombier  *
173e12c5d1SDavid du Colombier  * All input is through the C macro; the most recently read character is in c.
183e12c5d1SDavid du Colombier  */
193e12c5d1SDavid du Colombier 
20*9a747e4fSDavid du Colombier /*
213e12c5d1SDavid du Colombier #define	C	((c = Bgetrune(infile)) < 0?\
223e12c5d1SDavid du Colombier 			eof():\
233e12c5d1SDavid du Colombier 			((c == ldelim) && (filesp == files)?\
243e12c5d1SDavid du Colombier 				skeqn():\
253e12c5d1SDavid du Colombier 				(c == '\n'?\
263e12c5d1SDavid du Colombier 					(linect++,c):\
273e12c5d1SDavid du Colombier 						c)))
28*9a747e4fSDavid du Colombier 
293e12c5d1SDavid du Colombier #define	C1	((c = Bgetrune(infile)) == Beof?\
303e12c5d1SDavid du Colombier 			eof():\
313e12c5d1SDavid du Colombier 			(c == '\n'?\
323e12c5d1SDavid du Colombier 				(linect++,c):\
333e12c5d1SDavid du Colombier 				c))
34*9a747e4fSDavid du Colombier */
35*9a747e4fSDavid du Colombier 
36*9a747e4fSDavid du Colombier /* lose those macros! */
37*9a747e4fSDavid du Colombier #define	C	fC()
38*9a747e4fSDavid du Colombier #define	C1	fC1()
39*9a747e4fSDavid du Colombier 
403e12c5d1SDavid du Colombier #define	SKIP	while(C != '\n')
413e12c5d1SDavid du Colombier #define SKIP1	while(C1 != '\n')
423e12c5d1SDavid du Colombier #define SKIP_TO_COM		SKIP;\
433e12c5d1SDavid du Colombier 				SKIP;\
443e12c5d1SDavid du Colombier 				pc=c;\
453e12c5d1SDavid du Colombier 				while(C != '.' || pc != '\n' || C > 'Z')\
463e12c5d1SDavid du Colombier 						pc=c
473e12c5d1SDavid du Colombier 
483e12c5d1SDavid du Colombier #define YES		1
493e12c5d1SDavid du Colombier #define NO		0
503e12c5d1SDavid du Colombier #define MS		0
513e12c5d1SDavid du Colombier #define MM		1
523e12c5d1SDavid du Colombier #define ONE		1
533e12c5d1SDavid du Colombier #define TWO		2
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier #define NOCHAR		-2
563e12c5d1SDavid du Colombier #define	EXTENDED	-1		/* All runes above 0x7F */
573e12c5d1SDavid du Colombier #define SPECIAL		0
583e12c5d1SDavid du Colombier #define APOS		1
593e12c5d1SDavid du Colombier #define PUNCT		2
603e12c5d1SDavid du Colombier #define DIGIT		3
613e12c5d1SDavid du Colombier #define LETTER		4
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier int	linect	= 0;
653e12c5d1SDavid du Colombier int	wordflag= NO;
66*9a747e4fSDavid du Colombier int	underscoreflag = NO;
673e12c5d1SDavid du Colombier int	msflag	= NO;
683e12c5d1SDavid du Colombier int	iflag	= NO;
693e12c5d1SDavid du Colombier int	mac	= MM;
703e12c5d1SDavid du Colombier int	disp	= 0;
713e12c5d1SDavid du Colombier int	inmacro	= NO;
723e12c5d1SDavid du Colombier int	intable	= NO;
733e12c5d1SDavid du Colombier int	eqnflag	= 0;
743e12c5d1SDavid du Colombier 
753e12c5d1SDavid du Colombier #define	MAX_ASCII	0X80
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier char	chars[MAX_ASCII];	/* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
783e12c5d1SDavid du Colombier 
797dd7cddfSDavid du Colombier Rune	line[30000];
803e12c5d1SDavid du Colombier Rune*	lp;
813e12c5d1SDavid du Colombier 
823e12c5d1SDavid du Colombier long	c;
833e12c5d1SDavid du Colombier long	pc;
843e12c5d1SDavid du Colombier int	ldelim	= NOCHAR;
853e12c5d1SDavid du Colombier int	rdelim	= NOCHAR;
863e12c5d1SDavid du Colombier 
873e12c5d1SDavid du Colombier 
883e12c5d1SDavid du Colombier char**	argv;
893e12c5d1SDavid du Colombier 
903e12c5d1SDavid du Colombier char	fname[50];
913e12c5d1SDavid du Colombier Biobuf*	files[15];
923e12c5d1SDavid du Colombier Biobuf**filesp;
933e12c5d1SDavid du Colombier Biobuf*	infile;
943e12c5d1SDavid du Colombier char*	devnull	= "/dev/null";
953e12c5d1SDavid du Colombier Biobuf	*infile;
963e12c5d1SDavid du Colombier Biobuf	bout;
973e12c5d1SDavid du Colombier 
983e12c5d1SDavid du Colombier long	skeqn(void);
993e12c5d1SDavid du Colombier Biobuf*	opn(char *p);
1003e12c5d1SDavid du Colombier int	eof(void);
1017dd7cddfSDavid du Colombier int	charclass(int);
1023e12c5d1SDavid du Colombier void	getfname(void);
1033e12c5d1SDavid du Colombier void	fatal(char *s, char *p);
1043e12c5d1SDavid du Colombier void	usage(void);
1053e12c5d1SDavid du Colombier void	work(void);
1063e12c5d1SDavid du Colombier void	putmac(Rune *rp, int vconst);
1073e12c5d1SDavid du Colombier void	regline(int macline, int vconst);
1083e12c5d1SDavid du Colombier void	putwords(void);
1093e12c5d1SDavid du Colombier void	comline(void);
1103e12c5d1SDavid du Colombier void	macro(void);
1113e12c5d1SDavid du Colombier void	eqn(void);
1123e12c5d1SDavid du Colombier void	tbl(void);
1133e12c5d1SDavid du Colombier void	stbl(void);
1143e12c5d1SDavid du Colombier void	sdis(char a1, char a2);
1153e12c5d1SDavid du Colombier void	sce(void);
1163e12c5d1SDavid du Colombier void	backsl(void);
1173e12c5d1SDavid du Colombier char*	copys(char *s);
1183e12c5d1SDavid du Colombier void	refer(int c1);
1193e12c5d1SDavid du Colombier void	inpic(void);
1203e12c5d1SDavid du Colombier 
121*9a747e4fSDavid du Colombier int
fC(void)122*9a747e4fSDavid du Colombier fC(void)
123*9a747e4fSDavid du Colombier {
124*9a747e4fSDavid du Colombier 	c = Bgetrune(infile);
125*9a747e4fSDavid du Colombier 	if(c < 0)
126*9a747e4fSDavid du Colombier 		return eof();
127*9a747e4fSDavid du Colombier 	if(c == ldelim && filesp == files)
128*9a747e4fSDavid du Colombier 		return skeqn();
129*9a747e4fSDavid du Colombier 	if(c == '\n')
130*9a747e4fSDavid du Colombier 		linect++;
131*9a747e4fSDavid du Colombier 	return c;
132*9a747e4fSDavid du Colombier }
133*9a747e4fSDavid du Colombier 
134*9a747e4fSDavid du Colombier int
fC1(void)135*9a747e4fSDavid du Colombier fC1(void)
136*9a747e4fSDavid du Colombier {
137*9a747e4fSDavid du Colombier 	c = Bgetrune(infile);
138*9a747e4fSDavid du Colombier 	if(c == Beof)
139*9a747e4fSDavid du Colombier 		return eof();
140*9a747e4fSDavid du Colombier 	if(c == '\n')
141*9a747e4fSDavid du Colombier 		linect++;
142*9a747e4fSDavid du Colombier 	return c;
143*9a747e4fSDavid du Colombier }
144*9a747e4fSDavid du Colombier 
1453e12c5d1SDavid du Colombier void
main(int argc,char * av[])1463e12c5d1SDavid du Colombier main(int argc, char *av[])
1473e12c5d1SDavid du Colombier {
1483e12c5d1SDavid du Colombier 	int i;
1493e12c5d1SDavid du Colombier 	char *f;
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier 	argv = av;
1523e12c5d1SDavid du Colombier 	Binit(&bout, 1, OWRITE);
1533e12c5d1SDavid du Colombier 	ARGBEGIN{
1543e12c5d1SDavid du Colombier 	case 'w':
1553e12c5d1SDavid du Colombier 		wordflag = YES;
1563e12c5d1SDavid du Colombier 		break;
157*9a747e4fSDavid du Colombier 	case '_':
158*9a747e4fSDavid du Colombier 		wordflag = YES;
159*9a747e4fSDavid du Colombier 		underscoreflag = YES;
160*9a747e4fSDavid du Colombier 		break;
1613e12c5d1SDavid du Colombier 	case 'm':
1623e12c5d1SDavid du Colombier 		msflag = YES;
1633e12c5d1SDavid du Colombier 		if(f = ARGF())
1643e12c5d1SDavid du Colombier 			switch(*f)
1653e12c5d1SDavid du Colombier 			{
1663e12c5d1SDavid du Colombier 			case 'm':	mac = MM; break;
1673e12c5d1SDavid du Colombier 			case 's':	mac = MS; break;
1683e12c5d1SDavid du Colombier 			case 'l':	disp = 1; break;
1693e12c5d1SDavid du Colombier 			default:	usage();
1703e12c5d1SDavid du Colombier 			}
1713e12c5d1SDavid du Colombier 		else
1723e12c5d1SDavid du Colombier 			usage();
1733e12c5d1SDavid du Colombier 		break;
1743e12c5d1SDavid du Colombier 	case 'i':
1753e12c5d1SDavid du Colombier 		iflag = YES;
1763e12c5d1SDavid du Colombier 		break;
1773e12c5d1SDavid du Colombier 	default:
1783e12c5d1SDavid du Colombier 		usage();
1793e12c5d1SDavid du Colombier 	}ARGEND
1803e12c5d1SDavid du Colombier 	if(*argv)
1813e12c5d1SDavid du Colombier 		infile = opn(*argv++);
1823e12c5d1SDavid du Colombier 	else{
1833e12c5d1SDavid du Colombier 		infile = malloc(sizeof(Biobuf));
1843e12c5d1SDavid du Colombier 		Binit(infile, 0, OREAD);
1853e12c5d1SDavid du Colombier 	}
1863e12c5d1SDavid du Colombier 	files[0] = infile;
1873e12c5d1SDavid du Colombier 	filesp = &files[0];
1883e12c5d1SDavid du Colombier 
1893e12c5d1SDavid du Colombier 	for(i='a'; i<='z' ; ++i)
1903e12c5d1SDavid du Colombier 		chars[i] = LETTER;
1913e12c5d1SDavid du Colombier 	for(i='A'; i<='Z'; ++i)
1923e12c5d1SDavid du Colombier 		chars[i] = LETTER;
1933e12c5d1SDavid du Colombier 	for(i='0'; i<='9'; ++i)
1943e12c5d1SDavid du Colombier 		chars[i] = DIGIT;
1953e12c5d1SDavid du Colombier 	chars['\''] = APOS;
1963e12c5d1SDavid du Colombier 	chars['&'] = APOS;
1973e12c5d1SDavid du Colombier 	chars['\b'] = APOS;
1983e12c5d1SDavid du Colombier 	chars['.'] = PUNCT;
1993e12c5d1SDavid du Colombier 	chars[','] = PUNCT;
2003e12c5d1SDavid du Colombier 	chars[';'] = PUNCT;
2013e12c5d1SDavid du Colombier 	chars['?'] = PUNCT;
2023e12c5d1SDavid du Colombier 	chars[':'] = PUNCT;
2033e12c5d1SDavid du Colombier 	work();
2043e12c5d1SDavid du Colombier }
2053e12c5d1SDavid du Colombier 
2063e12c5d1SDavid du Colombier long
skeqn(void)2073e12c5d1SDavid du Colombier skeqn(void)
2083e12c5d1SDavid du Colombier {
2093e12c5d1SDavid du Colombier 	while(C1 != rdelim)
2103e12c5d1SDavid du Colombier 		if(c == '\\')
2113e12c5d1SDavid du Colombier 			c = C1;
2123e12c5d1SDavid du Colombier 		else if(c == '"')
2133e12c5d1SDavid du Colombier 			while(C1 != '"')
2143e12c5d1SDavid du Colombier 				if(c == '\\')
2153e12c5d1SDavid du Colombier 					C1;
2163e12c5d1SDavid du Colombier 	if (msflag)
2173e12c5d1SDavid du Colombier 		eqnflag = 1;
2183e12c5d1SDavid du Colombier 	return(c = ' ');
2193e12c5d1SDavid du Colombier }
2203e12c5d1SDavid du Colombier 
2213e12c5d1SDavid du Colombier Biobuf*
opn(char * p)2223e12c5d1SDavid du Colombier opn(char *p)
2233e12c5d1SDavid du Colombier {
2243e12c5d1SDavid du Colombier 	Biobuf *fd;
2253e12c5d1SDavid du Colombier 
2263e12c5d1SDavid du Colombier 	while ((fd = Bopen(p, OREAD)) == 0) {
2273e12c5d1SDavid du Colombier 		if(msflag || p == devnull)
2283e12c5d1SDavid du Colombier 			fatal("Cannot open file %s - quitting\n", p);
2293e12c5d1SDavid du Colombier 		else {
2303e12c5d1SDavid du Colombier 			fprint(2, "Deroff: Cannot open file %s - continuing\n", p);
2313e12c5d1SDavid du Colombier 			p = devnull;
2323e12c5d1SDavid du Colombier 		}
2333e12c5d1SDavid du Colombier 	}
2343e12c5d1SDavid du Colombier 	linect = 0;
2353e12c5d1SDavid du Colombier 	return(fd);
2363e12c5d1SDavid du Colombier }
2373e12c5d1SDavid du Colombier 
2383e12c5d1SDavid du Colombier int
eof(void)2393e12c5d1SDavid du Colombier eof(void)
2403e12c5d1SDavid du Colombier {
2413e12c5d1SDavid du Colombier 	if(Bfildes(infile) != 0)
242219b2ee8SDavid du Colombier 		Bterm(infile);
2433e12c5d1SDavid du Colombier 	if(filesp > files)
2443e12c5d1SDavid du Colombier 		infile = *--filesp;
2453e12c5d1SDavid du Colombier 	else
2463e12c5d1SDavid du Colombier 	if(*argv)
2473e12c5d1SDavid du Colombier 		infile = opn(*argv++);
2483e12c5d1SDavid du Colombier 	else
2493e12c5d1SDavid du Colombier 		exits(0);
2503e12c5d1SDavid du Colombier 	return(C);
2513e12c5d1SDavid du Colombier }
2523e12c5d1SDavid du Colombier 
2533e12c5d1SDavid du Colombier void
getfname(void)2543e12c5d1SDavid du Colombier getfname(void)
2553e12c5d1SDavid du Colombier {
2563e12c5d1SDavid du Colombier 	char *p;
2573e12c5d1SDavid du Colombier 	Rune r;
258*9a747e4fSDavid du Colombier 	Dir *dir;
2593e12c5d1SDavid du Colombier 	struct chain
2603e12c5d1SDavid du Colombier 	{
2613e12c5d1SDavid du Colombier 		struct	chain*	nextp;
2623e12c5d1SDavid du Colombier 		char*	datap;
2633e12c5d1SDavid du Colombier 	} *q;
2643e12c5d1SDavid du Colombier 
2653e12c5d1SDavid du Colombier 	static struct chain *namechain= 0;
2663e12c5d1SDavid du Colombier 
2673e12c5d1SDavid du Colombier 	while(C == ' ')
2683e12c5d1SDavid du Colombier 		;
2693e12c5d1SDavid du Colombier 	for(p = fname; (r=c) != '\n' && r != ' ' && r != '\t' && r != '\\'; C)
2703e12c5d1SDavid du Colombier 		p += runetochar(p, &r);
2713e12c5d1SDavid du Colombier 	*p = '\0';
2723e12c5d1SDavid du Colombier 	while(c != '\n')
2733e12c5d1SDavid du Colombier 		C;
2743e12c5d1SDavid du Colombier 	if(!strcmp(fname, "/sys/lib/tmac/tmac.cs")
2753e12c5d1SDavid du Colombier 			|| !strcmp(fname, "/sys/lib/tmac/tmac.s")) {
2763e12c5d1SDavid du Colombier 		fname[0] = '\0';
2773e12c5d1SDavid du Colombier 		return;
2783e12c5d1SDavid du Colombier 	}
279*9a747e4fSDavid du Colombier 	dir = dirstat(fname);
280*9a747e4fSDavid du Colombier 	if(dir!=nil && ((dir->mode & DMDIR) || dir->type != 'M')) {
281*9a747e4fSDavid du Colombier 		free(dir);
2823e12c5d1SDavid du Colombier 		fname[0] = '\0';
2833e12c5d1SDavid du Colombier 		return;
2843e12c5d1SDavid du Colombier 	}
285*9a747e4fSDavid du Colombier 	free(dir);
2863e12c5d1SDavid du Colombier 	/*
2873e12c5d1SDavid du Colombier 	 * see if this name has already been used
2883e12c5d1SDavid du Colombier 	 */
2893e12c5d1SDavid du Colombier 
2903e12c5d1SDavid du Colombier 	for(q = namechain; q; q = q->nextp)
2913e12c5d1SDavid du Colombier 		if( !strcmp(fname, q->datap)) {
2923e12c5d1SDavid du Colombier 			fname[0] = '\0';
2933e12c5d1SDavid du Colombier 			return;
2943e12c5d1SDavid du Colombier 		}
2953e12c5d1SDavid du Colombier 	q = (struct chain*)malloc(sizeof(struct chain));
2963e12c5d1SDavid du Colombier 	q->nextp = namechain;
2973e12c5d1SDavid du Colombier 	q->datap = copys(fname);
2983e12c5d1SDavid du Colombier 	namechain = q;
2993e12c5d1SDavid du Colombier }
3003e12c5d1SDavid du Colombier 
3013e12c5d1SDavid du Colombier void
usage(void)3023e12c5d1SDavid du Colombier usage(void)
3033e12c5d1SDavid du Colombier {
304*9a747e4fSDavid du Colombier 	fprint(2,"usage: deroff [-nw_pi] [-m (m s l)] [file ...] \n");
3053e12c5d1SDavid du Colombier 	exits("usage");
3063e12c5d1SDavid du Colombier }
3073e12c5d1SDavid du Colombier 
3083e12c5d1SDavid du Colombier void
fatal(char * s,char * p)3093e12c5d1SDavid du Colombier fatal(char *s, char *p)
3103e12c5d1SDavid du Colombier {
3113e12c5d1SDavid du Colombier 	fprint(2, "deroff: ");
3123e12c5d1SDavid du Colombier 	fprint(2, s, p);
3133e12c5d1SDavid du Colombier 	exits(s);
3143e12c5d1SDavid du Colombier }
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier void
work(void)3173e12c5d1SDavid du Colombier work(void)
3183e12c5d1SDavid du Colombier {
3193e12c5d1SDavid du Colombier 
3203e12c5d1SDavid du Colombier 	for(;;) {
3213e12c5d1SDavid du Colombier 		eqnflag = 0;
3223e12c5d1SDavid du Colombier 		if(C == '.'  ||  c == '\'')
3233e12c5d1SDavid du Colombier 			comline();
3243e12c5d1SDavid du Colombier 		else
3253e12c5d1SDavid du Colombier 			regline(NO, TWO);
3263e12c5d1SDavid du Colombier 	}
3273e12c5d1SDavid du Colombier }
3283e12c5d1SDavid du Colombier 
3293e12c5d1SDavid du Colombier void
regline(int macline,int vconst)3303e12c5d1SDavid du Colombier regline(int macline, int vconst)
3313e12c5d1SDavid du Colombier {
3323e12c5d1SDavid du Colombier 	line[0] = c;
3333e12c5d1SDavid du Colombier 	lp = line;
3343e12c5d1SDavid du Colombier 	for(;;) {
3353e12c5d1SDavid du Colombier 		if(c == '\\') {
3363e12c5d1SDavid du Colombier 			*lp = ' ';
3373e12c5d1SDavid du Colombier 			backsl();
3383e12c5d1SDavid du Colombier 			if(c == '%')	/* no blank for hyphenation char */
3393e12c5d1SDavid du Colombier 				lp--;
3403e12c5d1SDavid du Colombier 		}
3413e12c5d1SDavid du Colombier 		if(c == '\n')
3423e12c5d1SDavid du Colombier 			break;
3433e12c5d1SDavid du Colombier 		if(intable && c=='T') {
3443e12c5d1SDavid du Colombier 			*++lp = C;
3453e12c5d1SDavid du Colombier 			if(c=='{' || c=='}') {
3463e12c5d1SDavid du Colombier 				lp[-1] = ' ';
3473e12c5d1SDavid du Colombier 				*lp = C;
3483e12c5d1SDavid du Colombier 			}
3493e12c5d1SDavid du Colombier 		} else {
3503e12c5d1SDavid du Colombier 			if(msflag == 1 && eqnflag == 1) {
3513e12c5d1SDavid du Colombier 				eqnflag = 0;
3523e12c5d1SDavid du Colombier 				*++lp = 'x';
3533e12c5d1SDavid du Colombier 			}
3543e12c5d1SDavid du Colombier 			*++lp = C;
3553e12c5d1SDavid du Colombier 		}
3563e12c5d1SDavid du Colombier 	}
3573e12c5d1SDavid du Colombier 	*lp = '\0';
3583e12c5d1SDavid du Colombier 	if(lp != line) {
3593e12c5d1SDavid du Colombier 		if(wordflag)
3603e12c5d1SDavid du Colombier 			putwords();
3613e12c5d1SDavid du Colombier 		else
3623e12c5d1SDavid du Colombier 		if(macline)
3633e12c5d1SDavid du Colombier 			putmac(line,vconst);
3643e12c5d1SDavid du Colombier 		else
3653e12c5d1SDavid du Colombier 			Bprint(&bout, "%S\n", line);
3663e12c5d1SDavid du Colombier 	}
3673e12c5d1SDavid du Colombier }
3683e12c5d1SDavid du Colombier 
3693e12c5d1SDavid du Colombier void
putmac(Rune * rp,int vconst)3703e12c5d1SDavid du Colombier putmac(Rune *rp, int vconst)
3713e12c5d1SDavid du Colombier {
3723e12c5d1SDavid du Colombier 	Rune *t;
3733e12c5d1SDavid du Colombier 	int found;
3743e12c5d1SDavid du Colombier 	Rune last;
3753e12c5d1SDavid du Colombier 
3763e12c5d1SDavid du Colombier 	found = 0;
3773e12c5d1SDavid du Colombier 	last = 0;
3783e12c5d1SDavid du Colombier 	while(*rp) {
3793e12c5d1SDavid du Colombier 		while(*rp == ' ' || *rp == '\t')
3803e12c5d1SDavid du Colombier 			Bputrune(&bout, *rp++);
3813e12c5d1SDavid du Colombier 		for(t = rp; *t != ' ' && *t != '\t' && *t != '\0'; t++)
3823e12c5d1SDavid du Colombier 			;
3833e12c5d1SDavid du Colombier 		if(*rp == '\"')
3843e12c5d1SDavid du Colombier 			rp++;
3857dd7cddfSDavid du Colombier 		if(t > rp+vconst && charclass(*rp) == LETTER
3867dd7cddfSDavid du Colombier 				&& charclass(rp[1]) == LETTER) {
3873e12c5d1SDavid du Colombier 			while(rp < t)
3883e12c5d1SDavid du Colombier 				if(*rp == '\"')
3893e12c5d1SDavid du Colombier 					rp++;
3903e12c5d1SDavid du Colombier 				else
3913e12c5d1SDavid du Colombier 					Bputrune(&bout, *rp++);
3923e12c5d1SDavid du Colombier 			last = t[-1];
3933e12c5d1SDavid du Colombier 			found++;
3943e12c5d1SDavid du Colombier 		} else
3957dd7cddfSDavid du Colombier 		if(found && charclass(*rp) == PUNCT && rp[1] == '\0')
3963e12c5d1SDavid du Colombier 			Bputrune(&bout, *rp++);
3973e12c5d1SDavid du Colombier 		else {
3983e12c5d1SDavid du Colombier 			last = t[-1];
3993e12c5d1SDavid du Colombier 			rp = t;
4003e12c5d1SDavid du Colombier 		}
4013e12c5d1SDavid du Colombier 	}
4023e12c5d1SDavid du Colombier 	Bputc(&bout, '\n');
4037dd7cddfSDavid du Colombier 	if(msflag && charclass(last) == PUNCT)
4043e12c5d1SDavid du Colombier 		Bprint(&bout, " %C\n", last);
4053e12c5d1SDavid du Colombier }
4063e12c5d1SDavid du Colombier 
4073e12c5d1SDavid du Colombier /*
4083e12c5d1SDavid du Colombier  * break into words for -w option
4093e12c5d1SDavid du Colombier  */
4103e12c5d1SDavid du Colombier void
putwords(void)4113e12c5d1SDavid du Colombier putwords(void)
4123e12c5d1SDavid du Colombier {
4133e12c5d1SDavid du Colombier 	Rune *p, *p1;
4143e12c5d1SDavid du Colombier 	int i, nlet;
4153e12c5d1SDavid du Colombier 
4163e12c5d1SDavid du Colombier 
4173e12c5d1SDavid du Colombier 	for(p1 = line;;) {
4183e12c5d1SDavid du Colombier 		/*
4193e12c5d1SDavid du Colombier 		 * skip initial specials ampersands and apostrophes
4203e12c5d1SDavid du Colombier 		 */
4217dd7cddfSDavid du Colombier 		while((i = charclass(*p1)) != EXTENDED && i < DIGIT)
4223e12c5d1SDavid du Colombier 			if(*p1++ == '\0')
4233e12c5d1SDavid du Colombier 				return;
4243e12c5d1SDavid du Colombier 		nlet = 0;
425*9a747e4fSDavid du Colombier 		for(p = p1; (i = charclass(*p)) != SPECIAL || (underscoreflag && *p=='_'); p++)
426*9a747e4fSDavid du Colombier 			if(i == LETTER || (underscoreflag && *p == '_'))
4273e12c5d1SDavid du Colombier 				nlet++;
4283e12c5d1SDavid du Colombier 		/*
4293e12c5d1SDavid du Colombier 		 * MDM definition of word
4303e12c5d1SDavid du Colombier 		 */
4313e12c5d1SDavid du Colombier 		if(nlet > 1) {
4323e12c5d1SDavid du Colombier 			/*
4333e12c5d1SDavid du Colombier 			 * delete trailing ampersands and apostrophes
4343e12c5d1SDavid du Colombier 			 */
4353e12c5d1SDavid du Colombier 			while(*--p == '\'' || *p == '&'
4367dd7cddfSDavid du Colombier 					   || charclass(*p) == PUNCT)
4373e12c5d1SDavid du Colombier 				;
4383e12c5d1SDavid du Colombier 			while(p1 <= p)
4393e12c5d1SDavid du Colombier 				Bputrune(&bout, *p1++);
4403e12c5d1SDavid du Colombier 			Bputc(&bout, '\n');
4413e12c5d1SDavid du Colombier 		} else
4423e12c5d1SDavid du Colombier 			p1 = p;
4433e12c5d1SDavid du Colombier 	}
4443e12c5d1SDavid du Colombier }
4453e12c5d1SDavid du Colombier 
4463e12c5d1SDavid du Colombier void
comline(void)4473e12c5d1SDavid du Colombier comline(void)
4483e12c5d1SDavid du Colombier {
4493e12c5d1SDavid du Colombier 	long c1, c2;
4503e12c5d1SDavid du Colombier 
4513e12c5d1SDavid du Colombier 	while(C==' ' || c=='\t')
4523e12c5d1SDavid du Colombier 		;
4533e12c5d1SDavid du Colombier comx:
4543e12c5d1SDavid du Colombier 	if((c1=c) == '\n')
4553e12c5d1SDavid du Colombier 		return;
4563e12c5d1SDavid du Colombier 	c2 = C;
4573e12c5d1SDavid du Colombier 	if(c1=='.' && c2!='.')
4583e12c5d1SDavid du Colombier 		inmacro = NO;
4593e12c5d1SDavid du Colombier 	if(msflag && c1 == '['){
4603e12c5d1SDavid du Colombier 		refer(c2);
4613e12c5d1SDavid du Colombier 		return;
4623e12c5d1SDavid du Colombier 	}
4633e12c5d1SDavid du Colombier 	if(c2 == '\n')
4643e12c5d1SDavid du Colombier 		return;
4653e12c5d1SDavid du Colombier 	if(c1 == '\\' && c2 == '\"')
4663e12c5d1SDavid du Colombier 		SKIP;
4673e12c5d1SDavid du Colombier 	else
4683e12c5d1SDavid du Colombier 	if (filesp==files && c1=='E' && c2=='Q')
4693e12c5d1SDavid du Colombier 			eqn();
4703e12c5d1SDavid du Colombier 	else
4713e12c5d1SDavid du Colombier 	if(filesp==files && c1=='T' && (c2=='S' || c2=='C' || c2=='&')) {
4723e12c5d1SDavid du Colombier 		if(msflag)
4733e12c5d1SDavid du Colombier 			stbl();
4743e12c5d1SDavid du Colombier 		else
4753e12c5d1SDavid du Colombier 			tbl();
4763e12c5d1SDavid du Colombier 	}
4773e12c5d1SDavid du Colombier 	else
4783e12c5d1SDavid du Colombier 	if(c1=='T' && c2=='E')
4793e12c5d1SDavid du Colombier 		intable = NO;
4803e12c5d1SDavid du Colombier 	else if (!inmacro &&
4813e12c5d1SDavid du Colombier 			((c1 == 'd' && c2 == 'e') ||
4823e12c5d1SDavid du Colombier 		   	 (c1 == 'i' && c2 == 'g') ||
4833e12c5d1SDavid du Colombier 		   	 (c1 == 'a' && c2 == 'm')))
4843e12c5d1SDavid du Colombier 				macro();
4853e12c5d1SDavid du Colombier 	else
4863e12c5d1SDavid du Colombier 	if(c1=='s' && c2=='o') {
4873e12c5d1SDavid du Colombier 		if(iflag)
4883e12c5d1SDavid du Colombier 			SKIP;
4893e12c5d1SDavid du Colombier 		else {
4903e12c5d1SDavid du Colombier 			getfname();
4913e12c5d1SDavid du Colombier 			if(fname[0]) {
4923e12c5d1SDavid du Colombier 				if(infile = opn(fname))
4933e12c5d1SDavid du Colombier 					*++filesp = infile;
4943e12c5d1SDavid du Colombier 				else infile = *filesp;
4953e12c5d1SDavid du Colombier 			}
4963e12c5d1SDavid du Colombier 		}
4973e12c5d1SDavid du Colombier 	}
4983e12c5d1SDavid du Colombier 	else
4993e12c5d1SDavid du Colombier 	if(c1=='n' && c2=='x')
5003e12c5d1SDavid du Colombier 		if(iflag)
5013e12c5d1SDavid du Colombier 			SKIP;
5023e12c5d1SDavid du Colombier 		else {
5033e12c5d1SDavid du Colombier 			getfname();
5043e12c5d1SDavid du Colombier 			if(fname[0] == '\0')
5053e12c5d1SDavid du Colombier 				exits(0);
5063e12c5d1SDavid du Colombier 			if(Bfildes(infile) != 0)
507219b2ee8SDavid du Colombier 				Bterm(infile);
5083e12c5d1SDavid du Colombier 			infile = *filesp = opn(fname);
5093e12c5d1SDavid du Colombier 		}
5103e12c5d1SDavid du Colombier 	else
5113e12c5d1SDavid du Colombier 	if(c1 == 't' && c2 == 'm')
5123e12c5d1SDavid du Colombier 		SKIP;
5133e12c5d1SDavid du Colombier 	else
5143e12c5d1SDavid du Colombier 	if(c1=='h' && c2=='w')
5153e12c5d1SDavid du Colombier 		SKIP;
5163e12c5d1SDavid du Colombier 	else
5173e12c5d1SDavid du Colombier 	if(msflag && c1 == 'T' && c2 == 'L') {
5183e12c5d1SDavid du Colombier 		SKIP_TO_COM;
5193e12c5d1SDavid du Colombier 		goto comx;
5203e12c5d1SDavid du Colombier 	}
5213e12c5d1SDavid du Colombier 	else
5223e12c5d1SDavid du Colombier 	if(msflag && c1=='N' && c2 == 'R')
5233e12c5d1SDavid du Colombier 		SKIP;
5243e12c5d1SDavid du Colombier 	else
525219b2ee8SDavid du Colombier 	if(msflag && c1 == 'A' && (c2 == 'U' || c2 == 'I')){
5263e12c5d1SDavid du Colombier 		if(mac==MM)SKIP;
5273e12c5d1SDavid du Colombier 		else {
5283e12c5d1SDavid du Colombier 			SKIP_TO_COM;
5293e12c5d1SDavid du Colombier 			goto comx;
5303e12c5d1SDavid du Colombier 		}
5313e12c5d1SDavid du Colombier 	} else
5323e12c5d1SDavid du Colombier 	if(msflag && c1=='F' && c2=='S') {
5333e12c5d1SDavid du Colombier 		SKIP_TO_COM;
5343e12c5d1SDavid du Colombier 		goto comx;
5353e12c5d1SDavid du Colombier 	}
5363e12c5d1SDavid du Colombier 	else
5373e12c5d1SDavid du Colombier 	if(msflag && (c1=='S' || c1=='N') && c2=='H') {
5383e12c5d1SDavid du Colombier 		SKIP_TO_COM;
5393e12c5d1SDavid du Colombier 		goto comx;
5403e12c5d1SDavid du Colombier 	} else
5413e12c5d1SDavid du Colombier 	if(c1 == 'U' && c2 == 'X') {
5423e12c5d1SDavid du Colombier 		if(wordflag)
5433e12c5d1SDavid du Colombier 			Bprint(&bout, "UNIX\n");
5443e12c5d1SDavid du Colombier 		else
5453e12c5d1SDavid du Colombier 			Bprint(&bout, "UNIX ");
5463e12c5d1SDavid du Colombier 	} else
5473e12c5d1SDavid du Colombier 	if(msflag && c1=='O' && c2=='K') {
5483e12c5d1SDavid du Colombier 		SKIP_TO_COM;
5493e12c5d1SDavid du Colombier 		goto comx;
5503e12c5d1SDavid du Colombier 	} else
5513e12c5d1SDavid du Colombier 	if(msflag && c1=='N' && c2=='D')
5523e12c5d1SDavid du Colombier 		SKIP;
5533e12c5d1SDavid du Colombier 	else
554219b2ee8SDavid du Colombier 	if(msflag && mac==MM && c1=='H' && (c2==' '||c2=='U'))
5553e12c5d1SDavid du Colombier 		SKIP;
556219b2ee8SDavid du Colombier 	else
5573e12c5d1SDavid du Colombier 	if(msflag && mac==MM && c2=='L') {
5583e12c5d1SDavid du Colombier 		if(disp || c1=='R')
5593e12c5d1SDavid du Colombier 			sdis('L', 'E');
5603e12c5d1SDavid du Colombier 		else {
5613e12c5d1SDavid du Colombier 			SKIP;
5623e12c5d1SDavid du Colombier 			Bprint(&bout, " .");
5633e12c5d1SDavid du Colombier 		}
5643e12c5d1SDavid du Colombier 	} else
5653e12c5d1SDavid du Colombier 	if(!msflag && c1=='P' && c2=='S') {
5663e12c5d1SDavid du Colombier 		inpic();
5673e12c5d1SDavid du Colombier 	} else
5683e12c5d1SDavid du Colombier 	if(msflag && (c1=='D' || c1=='N' || c1=='K'|| c1=='P') && c2=='S') {
5693e12c5d1SDavid du Colombier 		sdis(c1, 'E');
5703e12c5d1SDavid du Colombier 	} else
5713e12c5d1SDavid du Colombier 	if(msflag && (c1 == 'K' && c2 == 'F')) {
5723e12c5d1SDavid du Colombier 		sdis(c1,'E');
5733e12c5d1SDavid du Colombier 	} else
5743e12c5d1SDavid du Colombier 	if(msflag && c1=='n' && c2=='f')
5753e12c5d1SDavid du Colombier 		sdis('f','i');
5763e12c5d1SDavid du Colombier 	else
5773e12c5d1SDavid du Colombier 	if(msflag && c1=='c' && c2=='e')
5783e12c5d1SDavid du Colombier 		sce();
5793e12c5d1SDavid du Colombier 	else {
5803e12c5d1SDavid du Colombier 		if(c1=='.' && c2=='.') {
5813e12c5d1SDavid du Colombier 			if(msflag) {
5823e12c5d1SDavid du Colombier 				SKIP;
5833e12c5d1SDavid du Colombier 				return;
5843e12c5d1SDavid du Colombier 			}
5853e12c5d1SDavid du Colombier 			while(C == '.')
5863e12c5d1SDavid du Colombier 				;
5873e12c5d1SDavid du Colombier 		}
5883e12c5d1SDavid du Colombier 		inmacro++;
5893e12c5d1SDavid du Colombier 		if(c1 <= 'Z' && msflag)
5903e12c5d1SDavid du Colombier 			regline(YES,ONE);
5913e12c5d1SDavid du Colombier 		else {
5923e12c5d1SDavid du Colombier 			if(wordflag)
5933e12c5d1SDavid du Colombier 				C;
5943e12c5d1SDavid du Colombier 			regline(YES,TWO);
5953e12c5d1SDavid du Colombier 		}
5963e12c5d1SDavid du Colombier 		inmacro--;
5973e12c5d1SDavid du Colombier 	}
5983e12c5d1SDavid du Colombier }
5993e12c5d1SDavid du Colombier 
6003e12c5d1SDavid du Colombier void
macro(void)6013e12c5d1SDavid du Colombier macro(void)
6023e12c5d1SDavid du Colombier {
6033e12c5d1SDavid du Colombier 	if(msflag) {
6043e12c5d1SDavid du Colombier 		do {
6053e12c5d1SDavid du Colombier 			SKIP1;
6063e12c5d1SDavid du Colombier 		} while(C1 != '.' || C1 != '.' || C1 == '.');
6073e12c5d1SDavid du Colombier 		if(c != '\n')
6083e12c5d1SDavid du Colombier 			SKIP;
6093e12c5d1SDavid du Colombier 		return;
6103e12c5d1SDavid du Colombier 	}
6113e12c5d1SDavid du Colombier 	SKIP;
6123e12c5d1SDavid du Colombier 	inmacro = YES;
6133e12c5d1SDavid du Colombier }
6143e12c5d1SDavid du Colombier 
6153e12c5d1SDavid du Colombier void
sdis(char a1,char a2)6163e12c5d1SDavid du Colombier sdis(char a1, char a2)
6173e12c5d1SDavid du Colombier {
6183e12c5d1SDavid du Colombier 	int c1, c2;
6193e12c5d1SDavid du Colombier 	int eqnf;
6203e12c5d1SDavid du Colombier 	int lct;
6213e12c5d1SDavid du Colombier 
6223e12c5d1SDavid du Colombier 	if(a1 == 'P'){
6233e12c5d1SDavid du Colombier 		while(C1 == ' ')
6243e12c5d1SDavid du Colombier 			;
6253e12c5d1SDavid du Colombier 		if(c == '<') {
6263e12c5d1SDavid du Colombier 			SKIP1;
6273e12c5d1SDavid du Colombier 			return;
6283e12c5d1SDavid du Colombier 		}
6293e12c5d1SDavid du Colombier 	}
6303e12c5d1SDavid du Colombier 	lct = 0;
6313e12c5d1SDavid du Colombier 	eqnf = 1;
6323e12c5d1SDavid du Colombier 	if(c != '\n')
6333e12c5d1SDavid du Colombier 		SKIP1;
6343e12c5d1SDavid du Colombier 	for(;;) {
6353e12c5d1SDavid du Colombier 		while(C1 != '.')
6363e12c5d1SDavid du Colombier 			if(c == '\n')
6373e12c5d1SDavid du Colombier 				continue;
6383e12c5d1SDavid du Colombier 			else
6393e12c5d1SDavid du Colombier 				SKIP1;
6403e12c5d1SDavid du Colombier 		if((c1=C1) == '\n')
6413e12c5d1SDavid du Colombier 			continue;
6423e12c5d1SDavid du Colombier 		if((c2=C1) == '\n') {
6433e12c5d1SDavid du Colombier 			if(a1 == 'f' && (c1 == 'P' || c1 == 'H'))
6443e12c5d1SDavid du Colombier 				return;
6453e12c5d1SDavid du Colombier 			continue;
6463e12c5d1SDavid du Colombier 		}
6473e12c5d1SDavid du Colombier 		if(c1==a1 && c2 == a2) {
6483e12c5d1SDavid du Colombier 			SKIP1;
6493e12c5d1SDavid du Colombier 			if(lct != 0){
6503e12c5d1SDavid du Colombier 				lct--;
6513e12c5d1SDavid du Colombier 				continue;
6523e12c5d1SDavid du Colombier 			}
6533e12c5d1SDavid du Colombier 			if(eqnf)
6543e12c5d1SDavid du Colombier 				Bprint(&bout, " .");
6553e12c5d1SDavid du Colombier 			Bputc(&bout, '\n');
6563e12c5d1SDavid du Colombier 			return;
6573e12c5d1SDavid du Colombier 		} else
6583e12c5d1SDavid du Colombier 		if(a1 == 'L' && c2 == 'L') {
6593e12c5d1SDavid du Colombier 			lct++;
6603e12c5d1SDavid du Colombier 			SKIP1;
6613e12c5d1SDavid du Colombier 		} else
6623e12c5d1SDavid du Colombier 		if(a1 == 'D' && c1 == 'E' && c2 == 'Q') {
6633e12c5d1SDavid du Colombier 			eqn();
6643e12c5d1SDavid du Colombier 			eqnf = 0;
6653e12c5d1SDavid du Colombier 		} else
6663e12c5d1SDavid du Colombier 		if(a1 == 'f') {
6673e12c5d1SDavid du Colombier 			if((mac == MS && c2 == 'P') ||
6683e12c5d1SDavid du Colombier 				(mac == MM && c1 == 'H' && c2 == 'U')){
6693e12c5d1SDavid du Colombier 				SKIP1;
6703e12c5d1SDavid du Colombier 				return;
6713e12c5d1SDavid du Colombier 			}
6723e12c5d1SDavid du Colombier 			SKIP1;
6733e12c5d1SDavid du Colombier 		}
6743e12c5d1SDavid du Colombier 		else
6753e12c5d1SDavid du Colombier 			SKIP1;
6763e12c5d1SDavid du Colombier 	}
6773e12c5d1SDavid du Colombier }
6783e12c5d1SDavid du Colombier 
6793e12c5d1SDavid du Colombier void
tbl(void)6803e12c5d1SDavid du Colombier tbl(void)
6813e12c5d1SDavid du Colombier {
6823e12c5d1SDavid du Colombier 	while(C != '.')
6833e12c5d1SDavid du Colombier 		;
6843e12c5d1SDavid du Colombier 	SKIP;
6853e12c5d1SDavid du Colombier 	intable = YES;
6863e12c5d1SDavid du Colombier }
6873e12c5d1SDavid du Colombier 
6883e12c5d1SDavid du Colombier void
stbl(void)6893e12c5d1SDavid du Colombier stbl(void)
6903e12c5d1SDavid du Colombier {
6913e12c5d1SDavid du Colombier 	while(C != '.')
6923e12c5d1SDavid du Colombier 		;
6933e12c5d1SDavid du Colombier 	SKIP_TO_COM;
6943e12c5d1SDavid du Colombier 	if(c != 'T' || C != 'E') {
6953e12c5d1SDavid du Colombier 		SKIP;
6963e12c5d1SDavid du Colombier 		pc = c;
6973e12c5d1SDavid du Colombier 		while(C != '.' || pc != '\n' || C != 'T' || C != 'E')
6983e12c5d1SDavid du Colombier 			pc = c;
6993e12c5d1SDavid du Colombier 	}
7003e12c5d1SDavid du Colombier }
7013e12c5d1SDavid du Colombier 
7023e12c5d1SDavid du Colombier void
eqn(void)7033e12c5d1SDavid du Colombier eqn(void)
7043e12c5d1SDavid du Colombier {
7053e12c5d1SDavid du Colombier 	long c1, c2;
7063e12c5d1SDavid du Colombier 	int dflg;
7073e12c5d1SDavid du Colombier 	char last;
7083e12c5d1SDavid du Colombier 
7093e12c5d1SDavid du Colombier 	last = 0;
7103e12c5d1SDavid du Colombier 	dflg = 1;
7113e12c5d1SDavid du Colombier 	SKIP;
7123e12c5d1SDavid du Colombier 
7133e12c5d1SDavid du Colombier 	for(;;) {
7143e12c5d1SDavid du Colombier 		if(C1 == '.'  || c == '\'') {
7153e12c5d1SDavid du Colombier 			while(C1==' ' || c=='\t')
7163e12c5d1SDavid du Colombier 				;
7173e12c5d1SDavid du Colombier 			if(c=='E' && C1=='N') {
7183e12c5d1SDavid du Colombier 				SKIP;
7193e12c5d1SDavid du Colombier 				if(msflag && dflg) {
7203e12c5d1SDavid du Colombier 					Bputc(&bout, 'x');
7213e12c5d1SDavid du Colombier 					Bputc(&bout, ' ');
7223e12c5d1SDavid du Colombier 					if(last) {
7233e12c5d1SDavid du Colombier 						Bputc(&bout, last);
7243e12c5d1SDavid du Colombier 						Bputc(&bout, '\n');
7253e12c5d1SDavid du Colombier 					}
7263e12c5d1SDavid du Colombier 				}
7273e12c5d1SDavid du Colombier 				return;
7283e12c5d1SDavid du Colombier 			}
7293e12c5d1SDavid du Colombier 		} else
7303e12c5d1SDavid du Colombier 		if(c == 'd') {
7313e12c5d1SDavid du Colombier 			if(C1=='e' && C1=='l')
7323e12c5d1SDavid du Colombier 				if(C1=='i' && C1=='m') {
7333e12c5d1SDavid du Colombier 					while(C1 == ' ')
7343e12c5d1SDavid du Colombier 						;
7353e12c5d1SDavid du Colombier 					if((c1=c)=='\n' || (c2=C1)=='\n' ||
7363e12c5d1SDavid du Colombier 					  (c1=='o' && c2=='f' && C1=='f')) {
7373e12c5d1SDavid du Colombier 						ldelim = NOCHAR;
7383e12c5d1SDavid du Colombier 						rdelim = NOCHAR;
7393e12c5d1SDavid du Colombier 					} else {
7403e12c5d1SDavid du Colombier 						ldelim = c1;
7413e12c5d1SDavid du Colombier 						rdelim = c2;
7423e12c5d1SDavid du Colombier 					}
7433e12c5d1SDavid du Colombier 				}
7443e12c5d1SDavid du Colombier 			dflg = 0;
7453e12c5d1SDavid du Colombier 		}
7463e12c5d1SDavid du Colombier 		if(c != '\n')
7473e12c5d1SDavid du Colombier 			while(C1 != '\n') {
7483e12c5d1SDavid du Colombier 				if(chars[c] == PUNCT)
7493e12c5d1SDavid du Colombier 					last = c;
7503e12c5d1SDavid du Colombier 				else
7513e12c5d1SDavid du Colombier 				if(c != ' ')
7523e12c5d1SDavid du Colombier 					last = 0;
7533e12c5d1SDavid du Colombier 			}
7543e12c5d1SDavid du Colombier 	}
7553e12c5d1SDavid du Colombier }
7563e12c5d1SDavid du Colombier 
7573e12c5d1SDavid du Colombier /*
7583e12c5d1SDavid du Colombier  * skip over a complete backslash vconstruction
7593e12c5d1SDavid du Colombier  */
7603e12c5d1SDavid du Colombier void
backsl(void)7613e12c5d1SDavid du Colombier backsl(void)
7623e12c5d1SDavid du Colombier {
7633e12c5d1SDavid du Colombier 	int bdelim;
7643e12c5d1SDavid du Colombier 
7653e12c5d1SDavid du Colombier sw:
7663e12c5d1SDavid du Colombier 	switch(C1)
7673e12c5d1SDavid du Colombier 	{
7683e12c5d1SDavid du Colombier 	case '"':
7693e12c5d1SDavid du Colombier 		SKIP1;
7703e12c5d1SDavid du Colombier 		return;
7713e12c5d1SDavid du Colombier 
7723e12c5d1SDavid du Colombier 	case 's':
7733e12c5d1SDavid du Colombier 		if(C1 == '\\')
7743e12c5d1SDavid du Colombier 			backsl();
7753e12c5d1SDavid du Colombier 		else {
7763e12c5d1SDavid du Colombier 			while(C1>='0' && c<='9')
7773e12c5d1SDavid du Colombier 				;
7783e12c5d1SDavid du Colombier 			Bungetrune(infile);
7793e12c5d1SDavid du Colombier 			c = '0';
7803e12c5d1SDavid du Colombier 		}
7813e12c5d1SDavid du Colombier 		lp--;
7823e12c5d1SDavid du Colombier 		return;
7833e12c5d1SDavid du Colombier 
7843e12c5d1SDavid du Colombier 	case 'f':
7853e12c5d1SDavid du Colombier 	case 'n':
7863e12c5d1SDavid du Colombier 	case '*':
7873e12c5d1SDavid du Colombier 		if(C1 != '(')
7883e12c5d1SDavid du Colombier 			return;
7893e12c5d1SDavid du Colombier 
7903e12c5d1SDavid du Colombier 	case '(':
7913e12c5d1SDavid du Colombier 		if(msflag) {
7923e12c5d1SDavid du Colombier 			if(C == 'e') {
7933e12c5d1SDavid du Colombier 				if(C1 == 'm') {
7943e12c5d1SDavid du Colombier 					*lp = '-';
7953e12c5d1SDavid du Colombier 					return;
7963e12c5d1SDavid du Colombier 				}
7973e12c5d1SDavid du Colombier 			} else
7983e12c5d1SDavid du Colombier 			if(c != '\n')
7993e12c5d1SDavid du Colombier 				C1;
8003e12c5d1SDavid du Colombier 			return;
8013e12c5d1SDavid du Colombier 		}
8023e12c5d1SDavid du Colombier 		if(C1 != '\n')
8033e12c5d1SDavid du Colombier 			C1;
8043e12c5d1SDavid du Colombier 		return;
8053e12c5d1SDavid du Colombier 
8063e12c5d1SDavid du Colombier 	case '$':
8073e12c5d1SDavid du Colombier 		C1;	/* discard argument number */
8083e12c5d1SDavid du Colombier 		return;
8093e12c5d1SDavid du Colombier 
8103e12c5d1SDavid du Colombier 	case 'b':
8113e12c5d1SDavid du Colombier 	case 'x':
8123e12c5d1SDavid du Colombier 	case 'v':
8133e12c5d1SDavid du Colombier 	case 'h':
8143e12c5d1SDavid du Colombier 	case 'w':
8153e12c5d1SDavid du Colombier 	case 'o':
8163e12c5d1SDavid du Colombier 	case 'l':
8173e12c5d1SDavid du Colombier 	case 'L':
8183e12c5d1SDavid du Colombier 		if((bdelim=C1) == '\n')
8193e12c5d1SDavid du Colombier 			return;
8203e12c5d1SDavid du Colombier 		while(C1!='\n' && c!=bdelim)
8213e12c5d1SDavid du Colombier 			if(c == '\\')
8223e12c5d1SDavid du Colombier 				backsl();
8233e12c5d1SDavid du Colombier 		return;
8243e12c5d1SDavid du Colombier 
8253e12c5d1SDavid du Colombier 	case '\\':
8263e12c5d1SDavid du Colombier 		if(inmacro)
8273e12c5d1SDavid du Colombier 			goto sw;
8283e12c5d1SDavid du Colombier 	default:
8293e12c5d1SDavid du Colombier 		return;
8303e12c5d1SDavid du Colombier 	}
8313e12c5d1SDavid du Colombier }
8323e12c5d1SDavid du Colombier 
8333e12c5d1SDavid du Colombier char*
copys(char * s)8343e12c5d1SDavid du Colombier copys(char *s)
8353e12c5d1SDavid du Colombier {
8363e12c5d1SDavid du Colombier 	char *t, *t0;
8373e12c5d1SDavid du Colombier 
8383e12c5d1SDavid du Colombier 	if((t0 = t = malloc((strlen(s)+1))) == 0)
8393e12c5d1SDavid du Colombier 		fatal("Cannot allocate memory", (char*)0);
8403e12c5d1SDavid du Colombier 	while(*t++ = *s++)
8413e12c5d1SDavid du Colombier 		;
8423e12c5d1SDavid du Colombier 	return(t0);
8433e12c5d1SDavid du Colombier }
8443e12c5d1SDavid du Colombier 
8453e12c5d1SDavid du Colombier void
sce(void)8463e12c5d1SDavid du Colombier sce(void)
8473e12c5d1SDavid du Colombier {
8483e12c5d1SDavid du Colombier 	int n = 1;
8493e12c5d1SDavid du Colombier 
8503e12c5d1SDavid du Colombier 	while (C != L'\n' && !(L'0' <= c && c <= L'9'))
8513e12c5d1SDavid du Colombier 		;
8523e12c5d1SDavid du Colombier 	if (c != L'\n') {
8533e12c5d1SDavid du Colombier 		for (n = c-L'0';'0' <= C && c <= L'9';)
8543e12c5d1SDavid du Colombier 			n = n*10 + c-L'0';
8553e12c5d1SDavid du Colombier 	}
8563e12c5d1SDavid du Colombier 	while(n) {
8573e12c5d1SDavid du Colombier 		if(C == '.') {
8583e12c5d1SDavid du Colombier 			if(C == 'c') {
8593e12c5d1SDavid du Colombier 				if(C == 'e') {
8603e12c5d1SDavid du Colombier 					while(C == ' ')
8613e12c5d1SDavid du Colombier 						;
8623e12c5d1SDavid du Colombier 					if(c == '0') {
8633e12c5d1SDavid du Colombier 						SKIP;
8643e12c5d1SDavid du Colombier 						break;
8653e12c5d1SDavid du Colombier 					} else
8663e12c5d1SDavid du Colombier 						SKIP;
8673e12c5d1SDavid du Colombier 				} else
8683e12c5d1SDavid du Colombier 					SKIP;
8693e12c5d1SDavid du Colombier 			} else
8703e12c5d1SDavid du Colombier 			if(c == 'P' || C == 'P') {
8713e12c5d1SDavid du Colombier 				if(c != '\n')
8723e12c5d1SDavid du Colombier 					SKIP;
8733e12c5d1SDavid du Colombier 				break;
8743e12c5d1SDavid du Colombier 			} else
8753e12c5d1SDavid du Colombier 				if(c != '\n')
8763e12c5d1SDavid du Colombier 					SKIP;
8773e12c5d1SDavid du Colombier 		} else {
8783e12c5d1SDavid du Colombier 			SKIP;
8793e12c5d1SDavid du Colombier 			n--;
8803e12c5d1SDavid du Colombier 		}
8813e12c5d1SDavid du Colombier 	}
8823e12c5d1SDavid du Colombier }
8833e12c5d1SDavid du Colombier 
8843e12c5d1SDavid du Colombier void
refer(int c1)8853e12c5d1SDavid du Colombier refer(int c1)
8863e12c5d1SDavid du Colombier {
8873e12c5d1SDavid du Colombier 	int c2;
8883e12c5d1SDavid du Colombier 
8893e12c5d1SDavid du Colombier 	if(c1 != '\n')
8903e12c5d1SDavid du Colombier 		SKIP;
8913e12c5d1SDavid du Colombier 	c2 = 0;
8923e12c5d1SDavid du Colombier 	for(;;) {
8933e12c5d1SDavid du Colombier 		if(C != '.')
8943e12c5d1SDavid du Colombier 			SKIP;
8953e12c5d1SDavid du Colombier 		else {
8963e12c5d1SDavid du Colombier 			if(C != ']')
8973e12c5d1SDavid du Colombier 				SKIP;
8983e12c5d1SDavid du Colombier 			else {
8993e12c5d1SDavid du Colombier 				while(C != '\n')
9003e12c5d1SDavid du Colombier 					c2 = c;
9017dd7cddfSDavid du Colombier 				if(charclass(c2) == PUNCT)
9023e12c5d1SDavid du Colombier 					Bprint(&bout, " %C",c2);
9033e12c5d1SDavid du Colombier 				return;
9043e12c5d1SDavid du Colombier 			}
9053e12c5d1SDavid du Colombier 		}
9063e12c5d1SDavid du Colombier 	}
9073e12c5d1SDavid du Colombier }
9083e12c5d1SDavid du Colombier 
9093e12c5d1SDavid du Colombier void
inpic(void)9103e12c5d1SDavid du Colombier inpic(void)
9113e12c5d1SDavid du Colombier {
9123e12c5d1SDavid du Colombier 	int c1;
9133e12c5d1SDavid du Colombier 	Rune *p1;
9143e12c5d1SDavid du Colombier 
9153e12c5d1SDavid du Colombier /*	SKIP1;*/
9163e12c5d1SDavid du Colombier 	while(C1 != '\n')
9173e12c5d1SDavid du Colombier 		if(c == '<'){
9183e12c5d1SDavid du Colombier 			SKIP1;
9193e12c5d1SDavid du Colombier 			return;
9203e12c5d1SDavid du Colombier 		}
9213e12c5d1SDavid du Colombier 	p1 = line;
9223e12c5d1SDavid du Colombier 	c = '\n';
9233e12c5d1SDavid du Colombier 	for(;;) {
9243e12c5d1SDavid du Colombier 		c1 = c;
9253e12c5d1SDavid du Colombier 		if(C1 == '.' && c1 == '\n') {
9263e12c5d1SDavid du Colombier 			if(C1 != 'P' || C1 != 'E') {
9273e12c5d1SDavid du Colombier 				if(c != '\n'){
9283e12c5d1SDavid du Colombier 					SKIP1;
9293e12c5d1SDavid du Colombier 					c = '\n';
9303e12c5d1SDavid du Colombier 				}
9313e12c5d1SDavid du Colombier 				continue;
9323e12c5d1SDavid du Colombier 			}
9333e12c5d1SDavid du Colombier 			SKIP1;
9343e12c5d1SDavid du Colombier 			return;
9353e12c5d1SDavid du Colombier 		} else
9363e12c5d1SDavid du Colombier 		if(c == '\"') {
9373e12c5d1SDavid du Colombier 			while(C1 != '\"') {
9383e12c5d1SDavid du Colombier 				if(c == '\\') {
9393e12c5d1SDavid du Colombier 					if(C1 == '\"')
9403e12c5d1SDavid du Colombier 						continue;
9413e12c5d1SDavid du Colombier 					Bungetrune(infile);
9423e12c5d1SDavid du Colombier 					backsl();
9433e12c5d1SDavid du Colombier 				} else
9443e12c5d1SDavid du Colombier 					*p1++ = c;
9453e12c5d1SDavid du Colombier 			}
9463e12c5d1SDavid du Colombier 			*p1++ = ' ';
9473e12c5d1SDavid du Colombier 		} else
9483e12c5d1SDavid du Colombier 		if(c == '\n' && p1 != line) {
9493e12c5d1SDavid du Colombier 			*p1 = '\0';
9503e12c5d1SDavid du Colombier 			if(wordflag)
9513e12c5d1SDavid du Colombier 				putwords();
9523e12c5d1SDavid du Colombier 			else
9533e12c5d1SDavid du Colombier 				Bprint(&bout, "%S\n\n", line);
9543e12c5d1SDavid du Colombier 			p1 = line;
9553e12c5d1SDavid du Colombier 		}
9563e12c5d1SDavid du Colombier 	}
9573e12c5d1SDavid du Colombier }
9587dd7cddfSDavid du Colombier 
9597dd7cddfSDavid du Colombier int
charclass(int c)9607dd7cddfSDavid du Colombier charclass(int c)
9617dd7cddfSDavid du Colombier {
9627dd7cddfSDavid du Colombier 	if(c < MAX_ASCII)
9637dd7cddfSDavid du Colombier 		return chars[c];
9647dd7cddfSDavid du Colombier 	switch(c){
9657dd7cddfSDavid du Colombier 	case 0x2013: case 0x2014:	/* en dash, em dash */
9667dd7cddfSDavid du Colombier 		return SPECIAL;
9677dd7cddfSDavid du Colombier 	}
9687dd7cddfSDavid du Colombier 	return EXTENDED;
9697dd7cddfSDavid du Colombier }
970