Home | History | Annotate | Line # | Download | only in deroff
deroff.c revision 1.1
      1  1.1  perry /*	$NetBSD: deroff.c,v 1.1 2005/06/29 20:58:50 perry Exp $	*/
      2  1.1  perry 
      3  1.1  perry /* taken from: OpenBSD: deroff.c,v 1.6 2004/06/02 14:58:46 tom Exp */
      4  1.1  perry 
      5  1.1  perry /*-
      6  1.1  perry  * Copyright (c) 1988, 1993
      7  1.1  perry  *	The Regents of the University of California.  All rights reserved.
      8  1.1  perry  *
      9  1.1  perry  * Redistribution and use in source and binary forms, with or without
     10  1.1  perry  * modification, are permitted provided that the following conditions
     11  1.1  perry  * are met:
     12  1.1  perry  * 1. Redistributions of source code must retain the above copyright
     13  1.1  perry  *    notice, this list of conditions and the following disclaimer.
     14  1.1  perry  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.1  perry  *    notice, this list of conditions and the following disclaimer in the
     16  1.1  perry  *    documentation and/or other materials provided with the distribution.
     17  1.1  perry  * 3. Neither the name of the University nor the names of its contributors
     18  1.1  perry  *    may be used to endorse or promote products derived from this software
     19  1.1  perry  *    without specific prior written permission.
     20  1.1  perry  *
     21  1.1  perry  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  1.1  perry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  1.1  perry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  1.1  perry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  1.1  perry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  1.1  perry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  1.1  perry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  1.1  perry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  1.1  perry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  1.1  perry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  1.1  perry  * SUCH DAMAGE.
     32  1.1  perry  */
     33  1.1  perry /*
     34  1.1  perry  * Copyright (C) Caldera International Inc.  2001-2002.
     35  1.1  perry  * All rights reserved.
     36  1.1  perry  *
     37  1.1  perry  * Redistribution and use in source and binary forms, with or without
     38  1.1  perry  * modification, are permitted provided that the following conditions
     39  1.1  perry  * are met:
     40  1.1  perry  * 1. Redistributions of source code and documentation must retain the above
     41  1.1  perry  *    copyright notice, this list of conditions and the following disclaimer.
     42  1.1  perry  * 2. Redistributions in binary form must reproduce the above copyright
     43  1.1  perry  *    notice, this list of conditions and the following disclaimer in the
     44  1.1  perry  *    documentation and/or other materials provided with the distribution.
     45  1.1  perry  * 3. All advertising materials mentioning features or use of this software
     46  1.1  perry  *    must display the following acknowledgement:
     47  1.1  perry  *	This product includes software developed or owned by Caldera
     48  1.1  perry  *	International, Inc.
     49  1.1  perry  * 4. Neither the name of Caldera International, Inc. nor the names of other
     50  1.1  perry  *    contributors may be used to endorse or promote products derived from
     51  1.1  perry  *    this software without specific prior written permission.
     52  1.1  perry  *
     53  1.1  perry  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
     54  1.1  perry  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
     55  1.1  perry  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     56  1.1  perry  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     57  1.1  perry  * IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
     58  1.1  perry  * INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     59  1.1  perry  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     60  1.1  perry  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     61  1.1  perry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     62  1.1  perry  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     63  1.1  perry  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     64  1.1  perry  * POSSIBILITY OF SUCH DAMAGE.
     65  1.1  perry  */
     66  1.1  perry 
     67  1.1  perry #ifndef lint
     68  1.1  perry static const char copyright[] =
     69  1.1  perry "@(#) Copyright (c) 1988, 1993\n\
     70  1.1  perry 	The Regents of the University of California.  All rights reserved.\n";
     71  1.1  perry #endif /* not lint */
     72  1.1  perry 
     73  1.1  perry #ifndef lint
     74  1.1  perry #if 0
     75  1.1  perry static const char sccsid[] = "@(#)deroff.c	8.1 (Berkeley) 6/6/93";
     76  1.1  perry #else
     77  1.1  perry static const char rcsid[] = "$NetBSD: deroff.c,v 1.1 2005/06/29 20:58:50 perry Exp $";
     78  1.1  perry #endif
     79  1.1  perry #endif /* not lint */
     80  1.1  perry 
     81  1.1  perry #include <err.h>
     82  1.1  perry #include <limits.h>
     83  1.1  perry #include <stdio.h>
     84  1.1  perry #include <stdlib.h>
     85  1.1  perry #include <string.h>
     86  1.1  perry #include <unistd.h>
     87  1.1  perry 
     88  1.1  perry /*
     89  1.1  perry  *	Deroff command -- strip troff, eqn, and Tbl sequences from
     90  1.1  perry  *	a file.  Has two flags argument, -w, to cause output one word per line
     91  1.1  perry  *	rather than in the original format.
     92  1.1  perry  *	-mm (or -ms) causes the corresponding macro's to be interpreted
     93  1.1  perry  *	so that just sentences are output
     94  1.1  perry  *	-ml  also gets rid of lists.
     95  1.1  perry  *	Deroff follows .so and .nx commands, removes contents of macro
     96  1.1  perry  *	definitions, equations (both .EQ ... .EN and $...$),
     97  1.1  perry  *	Tbl command sequences, and Troff backslash constructions.
     98  1.1  perry  *
     99  1.1  perry  *	All input is through the Cget macro;
    100  1.1  perry  *	the most recently read character is in c.
    101  1.1  perry  *
    102  1.1  perry  *	Modified by Robert Henry to process -me and -man macros.
    103  1.1  perry  */
    104  1.1  perry 
    105  1.1  perry #define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
    106  1.1  perry #define C1get ( (c=getc(infile)) == EOF ? eof() :  c)
    107  1.1  perry 
    108  1.1  perry #ifdef DEBUG
    109  1.1  perry #  define C	_C()
    110  1.1  perry #  define C1	_C1()
    111  1.1  perry #else /* not DEBUG */
    112  1.1  perry #  define C	Cget
    113  1.1  perry #  define C1	C1get
    114  1.1  perry #endif /* not DEBUG */
    115  1.1  perry 
    116  1.1  perry #define SKIP while (C != '\n')
    117  1.1  perry #define SKIP_TO_COM SKIP; SKIP; pc=c; while (C != '.' || pc != '\n' || C > 'Z')pc=c
    118  1.1  perry 
    119  1.1  perry #define	YES 1
    120  1.1  perry #define	NO 0
    121  1.1  perry #define	MS 0	/* -ms */
    122  1.1  perry #define	MM 1	/* -mm */
    123  1.1  perry #define	ME 2	/* -me */
    124  1.1  perry #define	MA 3	/* -man */
    125  1.1  perry 
    126  1.1  perry #ifdef DEBUG
    127  1.1  perry char *mactab[] = { "-ms", "-mm", "-me", "-ma" };
    128  1.1  perry #endif /* DEBUG */
    129  1.1  perry 
    130  1.1  perry #define	ONE 1
    131  1.1  perry #define	TWO 2
    132  1.1  perry 
    133  1.1  perry #define NOCHAR -2
    134  1.1  perry #define SPECIAL 0
    135  1.1  perry #define APOS 1
    136  1.1  perry #define PUNCT 2
    137  1.1  perry #define DIGIT 3
    138  1.1  perry #define LETTER 4
    139  1.1  perry 
    140  1.1  perry #define MAXFILES 20
    141  1.1  perry 
    142  1.1  perry int	iflag;
    143  1.1  perry int	wordflag;
    144  1.1  perry int	msflag;		/* processing a source written using a mac package */
    145  1.1  perry int	mac;		/* which package */
    146  1.1  perry int	disp;
    147  1.1  perry int	parag;
    148  1.1  perry int	inmacro;
    149  1.1  perry int	intable;
    150  1.1  perry int	keepblock;	/* keep blocks of text; normally false when msflag */
    151  1.1  perry 
    152  1.1  perry char chars[128];  /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
    153  1.1  perry 
    154  1.1  perry char line[LINE_MAX];
    155  1.1  perry char *lp;
    156  1.1  perry 
    157  1.1  perry int c;
    158  1.1  perry int pc;
    159  1.1  perry int ldelim;
    160  1.1  perry int rdelim;
    161  1.1  perry 
    162  1.1  perry char fname[PATH_MAX];
    163  1.1  perry FILE *files[MAXFILES];
    164  1.1  perry FILE **filesp;
    165  1.1  perry FILE *infile;
    166  1.1  perry 
    167  1.1  perry int argc;
    168  1.1  perry char **argv;
    169  1.1  perry 
    170  1.1  perry /*
    171  1.1  perry  *	Macro processing
    172  1.1  perry  *
    173  1.1  perry  *	Macro table definitions
    174  1.1  perry  */
    175  1.1  perry typedef	int pacmac;		/* compressed macro name */
    176  1.1  perry int	argconcat = 0;		/* concat arguments together (-me only) */
    177  1.1  perry 
    178  1.1  perry #define	tomac(c1, c2)		((((c1) & 0xFF) << 8) | ((c2) & 0xFF))
    179  1.1  perry #define	frommac(src, c1, c2)	(((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF))
    180  1.1  perry 
    181  1.1  perry struct mactab{
    182  1.1  perry 	int	condition;
    183  1.1  perry 	pacmac	macname;
    184  1.1  perry 	int	(*func)();	/* XXX - args */
    185  1.1  perry };
    186  1.1  perry 
    187  1.1  perry struct	mactab	troffmactab[];
    188  1.1  perry struct	mactab	ppmactab[];
    189  1.1  perry struct	mactab	msmactab[];
    190  1.1  perry struct	mactab	mmmactab[];
    191  1.1  perry struct	mactab	memactab[];
    192  1.1  perry struct	mactab	manmactab[];
    193  1.1  perry 
    194  1.1  perry /*
    195  1.1  perry  *	Macro table initialization
    196  1.1  perry  */
    197  1.1  perry #define	M(cond, c1, c2, func) {cond, tomac(c1, c2), func}
    198  1.1  perry 
    199  1.1  perry /*
    200  1.1  perry  *	Flags for matching conditions other than
    201  1.1  perry  *	the macro name
    202  1.1  perry  */
    203  1.1  perry #define	NONE		0
    204  1.1  perry #define	FNEST		1		/* no nested files */
    205  1.1  perry #define	NOMAC		2		/* no macro */
    206  1.1  perry #define	MAC		3		/* macro */
    207  1.1  perry #define	PARAG		4		/* in a paragraph */
    208  1.1  perry #define	MSF		5		/* msflag is on */
    209  1.1  perry #define	NBLK		6		/* set if no blocks to be kept */
    210  1.1  perry 
    211  1.1  perry /*
    212  1.1  perry  *	Return codes from macro minions, determine where to jump,
    213  1.1  perry  *	how to repeat/reprocess text
    214  1.1  perry  */
    215  1.1  perry #define	COMX		1		/* goto comx */
    216  1.1  perry #define	COM		2		/* goto com */
    217  1.1  perry 
    218  1.1  perry int	 skeqn(void);
    219  1.1  perry int	 eof(void);
    220  1.1  perry int	 _C1(void);
    221  1.1  perry int	 _C(void);
    222  1.1  perry int	 EQ(void);
    223  1.1  perry int	 domacro(void);
    224  1.1  perry int	 PS(void);
    225  1.1  perry int	 skip(void);
    226  1.1  perry int	 intbl(void);
    227  1.1  perry int	 outtbl(void);
    228  1.1  perry int	 so(void);
    229  1.1  perry int	 nx(void);
    230  1.1  perry int	 skiptocom(void);
    231  1.1  perry int	 PP(pacmac);
    232  1.1  perry int	 AU(void);
    233  1.1  perry int	 SH(pacmac);
    234  1.1  perry int	 UX(void);
    235  1.1  perry int	 MMHU(pacmac);
    236  1.1  perry int	 mesnblock(pacmac);
    237  1.1  perry int	 mssnblock(pacmac);
    238  1.1  perry int	 nf(void);
    239  1.1  perry int	 ce(void);
    240  1.1  perry int	 meip(pacmac);
    241  1.1  perry int	 mepp(pacmac);
    242  1.1  perry int	 mesh(pacmac);
    243  1.1  perry int	 mefont(pacmac);
    244  1.1  perry int	 manfont(pacmac);
    245  1.1  perry int	 manpp(pacmac);
    246  1.1  perry int	 macsort(const void *, const void *);
    247  1.1  perry int	 sizetab(struct mactab *);
    248  1.1  perry void	 getfname(void);
    249  1.1  perry void	 textline(char *, int);
    250  1.1  perry void	 work(void);
    251  1.1  perry void	 regline(void (*)(char *, int), int);
    252  1.1  perry void	 macro(void);
    253  1.1  perry void	 tbl(void);
    254  1.1  perry void	 stbl(void);
    255  1.1  perry void	 eqn(void);
    256  1.1  perry void	 backsl(void);
    257  1.1  perry void	 sce(void);
    258  1.1  perry void	 refer(int);
    259  1.1  perry void	 inpic(void);
    260  1.1  perry void	 msputmac(char *, int);
    261  1.1  perry void	 msputwords(int);
    262  1.1  perry void	 meputmac(char *, int);
    263  1.1  perry void	 meputwords(int);
    264  1.1  perry void	 noblock(char, char);
    265  1.1  perry void	 defcomline(pacmac);
    266  1.1  perry void	 comline(void);
    267  1.1  perry void	 buildtab(struct mactab **, int *);
    268  1.1  perry FILE	*opn(char *);
    269  1.1  perry struct mactab *macfill(struct mactab *, struct mactab *);
    270  1.1  perry __dead void usage(void);
    271  1.1  perry 
    272  1.1  perry int
    273  1.1  perry main(int ac, char **av)
    274  1.1  perry {
    275  1.1  perry 	int	i, ch;
    276  1.1  perry 	int	errflg = 0;
    277  1.1  perry 	int	kflag = NO;
    278  1.1  perry 
    279  1.1  perry 	iflag = NO;
    280  1.1  perry 	wordflag = NO;
    281  1.1  perry 	msflag = NO;
    282  1.1  perry 	mac = ME;
    283  1.1  perry 	disp = NO;
    284  1.1  perry 	parag = NO;
    285  1.1  perry 	inmacro = NO;
    286  1.1  perry 	intable = NO;
    287  1.1  perry 	ldelim	= NOCHAR;
    288  1.1  perry 	rdelim	= NOCHAR;
    289  1.1  perry 	keepblock = YES;
    290  1.1  perry 
    291  1.1  perry 	while ((ch = getopt(ac, av, "ikpwm:")) != -1) {
    292  1.1  perry 		switch (ch) {
    293  1.1  perry 		case 'i':
    294  1.1  perry 			iflag = YES;
    295  1.1  perry 			break;
    296  1.1  perry 		case 'k':
    297  1.1  perry 			kflag = YES;
    298  1.1  perry 			break;
    299  1.1  perry 		case 'm':
    300  1.1  perry 			msflag = YES;
    301  1.1  perry 			keepblock = NO;
    302  1.1  perry 			switch (optarg[0]) {
    303  1.1  perry 			case 'm':
    304  1.1  perry 				mac = MM;
    305  1.1  perry 				break;
    306  1.1  perry 			case 's':
    307  1.1  perry 				mac = MS;
    308  1.1  perry 				break;
    309  1.1  perry 			case 'e':
    310  1.1  perry 				mac = ME;
    311  1.1  perry 				break;
    312  1.1  perry 			case 'a':
    313  1.1  perry 				mac = MA;
    314  1.1  perry 				break;
    315  1.1  perry 			case 'l':
    316  1.1  perry 				disp = YES;
    317  1.1  perry 				break;
    318  1.1  perry 			default:
    319  1.1  perry 				errflg++;
    320  1.1  perry 				break;
    321  1.1  perry 			}
    322  1.1  perry 			if (errflg == 0 && optarg[1] != '\0')
    323  1.1  perry 				errflg++;
    324  1.1  perry 			break;
    325  1.1  perry 		case 'p':
    326  1.1  perry 			parag = YES;
    327  1.1  perry 			break;
    328  1.1  perry 		case 'w':
    329  1.1  perry 			wordflag = YES;
    330  1.1  perry 			kflag = YES;
    331  1.1  perry 			break;
    332  1.1  perry 		default:
    333  1.1  perry 			errflg++;
    334  1.1  perry 		}
    335  1.1  perry 	}
    336  1.1  perry 	argc = ac - optind;
    337  1.1  perry 	argv = av + optind;
    338  1.1  perry 
    339  1.1  perry 	if (kflag)
    340  1.1  perry 		keepblock = YES;
    341  1.1  perry 	if (errflg)
    342  1.1  perry 		usage();
    343  1.1  perry 
    344  1.1  perry #ifdef DEBUG
    345  1.1  perry 	printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n",
    346  1.1  perry 		msflag, mactab[mac], keepblock, disp);
    347  1.1  perry #endif /* DEBUG */
    348  1.1  perry 	if (argc == 0) {
    349  1.1  perry 		infile = stdin;
    350  1.1  perry 	} else {
    351  1.1  perry 		infile = opn(argv[0]);
    352  1.1  perry 		--argc;
    353  1.1  perry 		++argv;
    354  1.1  perry 	}
    355  1.1  perry 	files[0] = infile;
    356  1.1  perry 	filesp = &files[0];
    357  1.1  perry 
    358  1.1  perry 	for (i = 'a'; i <= 'z' ; ++i)
    359  1.1  perry 		chars[i] = LETTER;
    360  1.1  perry 	for (i = 'A'; i <= 'Z'; ++i)
    361  1.1  perry 		chars[i] = LETTER;
    362  1.1  perry 	for (i = '0'; i <= '9'; ++i)
    363  1.1  perry 		chars[i] = DIGIT;
    364  1.1  perry 	chars['\''] = APOS;
    365  1.1  perry 	chars['&'] = APOS;
    366  1.1  perry 	chars['.'] = PUNCT;
    367  1.1  perry 	chars[','] = PUNCT;
    368  1.1  perry 	chars[';'] = PUNCT;
    369  1.1  perry 	chars['?'] = PUNCT;
    370  1.1  perry 	chars[':'] = PUNCT;
    371  1.1  perry 	work();
    372  1.1  perry 	exit(0);
    373  1.1  perry }
    374  1.1  perry 
    375  1.1  perry int
    376  1.1  perry skeqn(void)
    377  1.1  perry {
    378  1.1  perry 
    379  1.1  perry 	while ((c = getc(infile)) != rdelim) {
    380  1.1  perry 		if (c == EOF)
    381  1.1  perry 			c = eof();
    382  1.1  perry 		else if (c == '"') {
    383  1.1  perry 			while ((c = getc(infile)) != '"') {
    384  1.1  perry 				if (c == EOF ||
    385  1.1  perry 				    (c == '\\' && (c = getc(infile)) == EOF))
    386  1.1  perry 					c = eof();
    387  1.1  perry 			}
    388  1.1  perry 		}
    389  1.1  perry 	}
    390  1.1  perry 	if (msflag)
    391  1.1  perry 		return((c = 'x'));
    392  1.1  perry 	return((c = ' '));
    393  1.1  perry }
    394  1.1  perry 
    395  1.1  perry FILE *
    396  1.1  perry opn(char *p)
    397  1.1  perry {
    398  1.1  perry 	FILE *fd;
    399  1.1  perry 
    400  1.1  perry 	if ((fd = fopen(p, "r")) == NULL)
    401  1.1  perry 		err(1, "fopen %s", p);
    402  1.1  perry 
    403  1.1  perry 	return(fd);
    404  1.1  perry }
    405  1.1  perry 
    406  1.1  perry int
    407  1.1  perry eof(void)
    408  1.1  perry {
    409  1.1  perry 
    410  1.1  perry 	if (infile != stdin)
    411  1.1  perry 		fclose(infile);
    412  1.1  perry 	if (filesp > files)
    413  1.1  perry 		infile = *--filesp;
    414  1.1  perry 	else if (argc > 0) {
    415  1.1  perry 		infile = opn(argv[0]);
    416  1.1  perry 		--argc;
    417  1.1  perry 		++argv;
    418  1.1  perry 	} else
    419  1.1  perry 		exit(0);
    420  1.1  perry 	return(C);
    421  1.1  perry }
    422  1.1  perry 
    423  1.1  perry void
    424  1.1  perry getfname(void)
    425  1.1  perry {
    426  1.1  perry 	char *p;
    427  1.1  perry 	struct chain {
    428  1.1  perry 		struct chain *nextp;
    429  1.1  perry 		char *datap;
    430  1.1  perry 	} *q;
    431  1.1  perry 	static struct chain *namechain= NULL;
    432  1.1  perry 
    433  1.1  perry 	while (C == ' ')
    434  1.1  perry 		;	/* nothing */
    435  1.1  perry 
    436  1.1  perry 	for (p = fname ; p - fname < sizeof(fname) && (*p = c) != '\n' &&
    437  1.1  perry 	    c != ' ' && c != '\t' && c != '\\'; ++p)
    438  1.1  perry 		C;
    439  1.1  perry 	*p = '\0';
    440  1.1  perry 	while (c != '\n')
    441  1.1  perry 		C;
    442  1.1  perry 
    443  1.1  perry 	/* see if this name has already been used */
    444  1.1  perry 	for (q = namechain ; q; q = q->nextp)
    445  1.1  perry 		if (strcmp(fname, q->datap) == 0) {
    446  1.1  perry 			fname[0] = '\0';
    447  1.1  perry 			return;
    448  1.1  perry 		}
    449  1.1  perry 
    450  1.1  perry 	q = (struct chain *) malloc(sizeof(struct chain));
    451  1.1  perry 	if (q == NULL)
    452  1.1  perry 		err(1, NULL);
    453  1.1  perry 	q->nextp = namechain;
    454  1.1  perry 	q->datap = strdup(fname);
    455  1.1  perry 	if (q->datap == NULL)
    456  1.1  perry 		err(1, NULL);
    457  1.1  perry 	namechain = q;
    458  1.1  perry }
    459  1.1  perry 
    460  1.1  perry /*ARGSUSED*/
    461  1.1  perry void
    462  1.1  perry textline(char *str, int constant)
    463  1.1  perry {
    464  1.1  perry 
    465  1.1  perry 	if (wordflag) {
    466  1.1  perry 		msputwords(0);
    467  1.1  perry 		return;
    468  1.1  perry 	}
    469  1.1  perry 	puts(str);
    470  1.1  perry }
    471  1.1  perry 
    472  1.1  perry void
    473  1.1  perry work(void)
    474  1.1  perry {
    475  1.1  perry 
    476  1.1  perry 	for (;;) {
    477  1.1  perry 		C;
    478  1.1  perry #ifdef FULLDEBUG
    479  1.1  perry 		printf("Starting work with `%c'\n", c);
    480  1.1  perry #endif /* FULLDEBUG */
    481  1.1  perry 		if (c == '.' || c == '\'')
    482  1.1  perry 			comline();
    483  1.1  perry 		else
    484  1.1  perry 			regline(textline, TWO);
    485  1.1  perry 	}
    486  1.1  perry }
    487  1.1  perry 
    488  1.1  perry void
    489  1.1  perry regline(void (*pfunc)(char *, int), int constant)
    490  1.1  perry {
    491  1.1  perry 
    492  1.1  perry 	line[0] = c;
    493  1.1  perry 	lp = line;
    494  1.1  perry 	while (lp - line < sizeof(line)) {
    495  1.1  perry 		if (c == '\\') {
    496  1.1  perry 			*lp = ' ';
    497  1.1  perry 			backsl();
    498  1.1  perry 		}
    499  1.1  perry 		if (c == '\n')
    500  1.1  perry 			break;
    501  1.1  perry 		if (intable && c == 'T') {
    502  1.1  perry 			*++lp = C;
    503  1.1  perry 			if (c == '{' || c == '}') {
    504  1.1  perry 				lp[-1] = ' ';
    505  1.1  perry 				*lp = C;
    506  1.1  perry 			}
    507  1.1  perry 		} else {
    508  1.1  perry 			*++lp = C;
    509  1.1  perry 		}
    510  1.1  perry 	}
    511  1.1  perry 	*lp = '\0';
    512  1.1  perry 
    513  1.1  perry 	if (line[0] != '\0')
    514  1.1  perry 		(*pfunc)(line, constant);
    515  1.1  perry }
    516  1.1  perry 
    517  1.1  perry void
    518  1.1  perry macro(void)
    519  1.1  perry {
    520  1.1  perry 
    521  1.1  perry 	if (msflag) {
    522  1.1  perry 		do {
    523  1.1  perry 			SKIP;
    524  1.1  perry 		} while (C!='.' || C!='.' || C=='.');	/* look for  .. */
    525  1.1  perry 		if (c != '\n')
    526  1.1  perry 			SKIP;
    527  1.1  perry 		return;
    528  1.1  perry 	}
    529  1.1  perry 	SKIP;
    530  1.1  perry 	inmacro = YES;
    531  1.1  perry }
    532  1.1  perry 
    533  1.1  perry void
    534  1.1  perry tbl(void)
    535  1.1  perry {
    536  1.1  perry 
    537  1.1  perry 	while (C != '.')
    538  1.1  perry 		;	/* nothing */
    539  1.1  perry 	SKIP;
    540  1.1  perry 	intable = YES;
    541  1.1  perry }
    542  1.1  perry 
    543  1.1  perry void
    544  1.1  perry stbl(void)
    545  1.1  perry {
    546  1.1  perry 
    547  1.1  perry 	while (C != '.')
    548  1.1  perry 		;	/* nothing */
    549  1.1  perry 	SKIP_TO_COM;
    550  1.1  perry 	if (c != 'T' || C != 'E') {
    551  1.1  perry 		SKIP;
    552  1.1  perry 		pc = c;
    553  1.1  perry 		while (C != '.' || pc != '\n' || C != 'T' || C != 'E')
    554  1.1  perry 			pc = c;
    555  1.1  perry 	}
    556  1.1  perry }
    557  1.1  perry 
    558  1.1  perry void
    559  1.1  perry eqn(void)
    560  1.1  perry {
    561  1.1  perry 	int c1, c2;
    562  1.1  perry 	int dflg;
    563  1.1  perry 	char last;
    564  1.1  perry 
    565  1.1  perry 	last=0;
    566  1.1  perry 	dflg = 1;
    567  1.1  perry 	SKIP;
    568  1.1  perry 
    569  1.1  perry 	for (;;) {
    570  1.1  perry 		if (C1 == '.'  || c == '\'') {
    571  1.1  perry 			while (C1 == ' ' || c == '\t')
    572  1.1  perry 				;
    573  1.1  perry 			if (c == 'E' && C1 == 'N') {
    574  1.1  perry 				SKIP;
    575  1.1  perry 				if (msflag && dflg) {
    576  1.1  perry 					putchar('x');
    577  1.1  perry 					putchar(' ');
    578  1.1  perry 					if (last) {
    579  1.1  perry 						putchar(last);
    580  1.1  perry 						putchar('\n');
    581  1.1  perry 					}
    582  1.1  perry 				}
    583  1.1  perry 				return;
    584  1.1  perry 			}
    585  1.1  perry 		} else if (c == 'd') {
    586  1.1  perry 			/* look for delim */
    587  1.1  perry 			if (C1 == 'e' && C1 == 'l')
    588  1.1  perry 				if (C1 == 'i' && C1 == 'm') {
    589  1.1  perry 					while (C1 == ' ')
    590  1.1  perry 						;	/* nothing */
    591  1.1  perry 
    592  1.1  perry 					if ((c1 = c) == '\n' ||
    593  1.1  perry 					    (c2 = C1) == '\n' ||
    594  1.1  perry 					    (c1 == 'o' && c2 == 'f' && C1=='f')) {
    595  1.1  perry 						ldelim = NOCHAR;
    596  1.1  perry 						rdelim = NOCHAR;
    597  1.1  perry 					} else {
    598  1.1  perry 						ldelim = c1;
    599  1.1  perry 						rdelim = c2;
    600  1.1  perry 					}
    601  1.1  perry 				}
    602  1.1  perry 			dflg = 0;
    603  1.1  perry 		}
    604  1.1  perry 
    605  1.1  perry 		if (c != '\n')
    606  1.1  perry 			while (C1 != '\n') {
    607  1.1  perry 				if (chars[c] == PUNCT)
    608  1.1  perry 					last = c;
    609  1.1  perry 				else if (c != ' ')
    610  1.1  perry 					last = 0;
    611  1.1  perry 			}
    612  1.1  perry 	}
    613  1.1  perry }
    614  1.1  perry 
    615  1.1  perry /* skip over a complete backslash construction */
    616  1.1  perry void
    617  1.1  perry backsl(void)
    618  1.1  perry {
    619  1.1  perry 	int bdelim;
    620  1.1  perry 
    621  1.1  perry sw:
    622  1.1  perry 	switch (C) {
    623  1.1  perry 	case '"':
    624  1.1  perry 		SKIP;
    625  1.1  perry 		return;
    626  1.1  perry 
    627  1.1  perry 	case 's':
    628  1.1  perry 		if (C == '\\')
    629  1.1  perry 			backsl();
    630  1.1  perry 		else {
    631  1.1  perry 			while (C >= '0' && c <= '9')
    632  1.1  perry 				;	/* nothing */
    633  1.1  perry 			ungetc(c, infile);
    634  1.1  perry 			c = '0';
    635  1.1  perry 		}
    636  1.1  perry 		--lp;
    637  1.1  perry 		return;
    638  1.1  perry 
    639  1.1  perry 	case 'f':
    640  1.1  perry 	case 'n':
    641  1.1  perry 	case '*':
    642  1.1  perry 		if (C != '(')
    643  1.1  perry 			return;
    644  1.1  perry 
    645  1.1  perry 	case '(':
    646  1.1  perry 		if (msflag) {
    647  1.1  perry 			if (C == 'e') {
    648  1.1  perry 				if (C == 'm') {
    649  1.1  perry 					*lp = '-';
    650  1.1  perry 					return;
    651  1.1  perry 				}
    652  1.1  perry 			}
    653  1.1  perry 			else if (c != '\n')
    654  1.1  perry 				C;
    655  1.1  perry 			return;
    656  1.1  perry 		}
    657  1.1  perry 		if (C != '\n')
    658  1.1  perry 			C;
    659  1.1  perry 		return;
    660  1.1  perry 
    661  1.1  perry 	case '$':
    662  1.1  perry 		C;	/* discard argument number */
    663  1.1  perry 		return;
    664  1.1  perry 
    665  1.1  perry 	case 'b':
    666  1.1  perry 	case 'x':
    667  1.1  perry 	case 'v':
    668  1.1  perry 	case 'h':
    669  1.1  perry 	case 'w':
    670  1.1  perry 	case 'o':
    671  1.1  perry 	case 'l':
    672  1.1  perry 	case 'L':
    673  1.1  perry 		if ((bdelim = C) == '\n')
    674  1.1  perry 			return;
    675  1.1  perry 		while (C != '\n' && c != bdelim)
    676  1.1  perry 			if (c == '\\')
    677  1.1  perry 				backsl();
    678  1.1  perry 		return;
    679  1.1  perry 
    680  1.1  perry 	case '\\':
    681  1.1  perry 		if (inmacro)
    682  1.1  perry 			goto sw;
    683  1.1  perry 
    684  1.1  perry 	default:
    685  1.1  perry 		return;
    686  1.1  perry 	}
    687  1.1  perry }
    688  1.1  perry 
    689  1.1  perry void
    690  1.1  perry sce(void)
    691  1.1  perry {
    692  1.1  perry 	char *ap;
    693  1.1  perry 	int n, i;
    694  1.1  perry 	char a[10];
    695  1.1  perry 
    696  1.1  perry 	for (ap = a; C != '\n'; ap++) {
    697  1.1  perry 		*ap = c;
    698  1.1  perry 		if (ap == &a[9]) {
    699  1.1  perry 			SKIP;
    700  1.1  perry 			ap = a;
    701  1.1  perry 			break;
    702  1.1  perry 		}
    703  1.1  perry 	}
    704  1.1  perry 	if (ap != a)
    705  1.1  perry 		n = atoi(a);
    706  1.1  perry 	else
    707  1.1  perry 		n = 1;
    708  1.1  perry 	for (i = 0; i < n;) {
    709  1.1  perry 		if (C == '.') {
    710  1.1  perry 			if (C == 'c') {
    711  1.1  perry 				if (C == 'e') {
    712  1.1  perry 					while (C == ' ')
    713  1.1  perry 						;	/* nothing */
    714  1.1  perry 					if (c == '0') {
    715  1.1  perry 						SKIP;
    716  1.1  perry 						break;
    717  1.1  perry 					} else
    718  1.1  perry 						SKIP;
    719  1.1  perry 				}
    720  1.1  perry 				else
    721  1.1  perry 					SKIP;
    722  1.1  perry 			} else if (c == 'P' || C == 'P') {
    723  1.1  perry 				if (c != '\n')
    724  1.1  perry 					SKIP;
    725  1.1  perry 				break;
    726  1.1  perry 			} else if (c != '\n')
    727  1.1  perry 				SKIP;
    728  1.1  perry 		} else {
    729  1.1  perry 			SKIP;
    730  1.1  perry 			i++;
    731  1.1  perry 		}
    732  1.1  perry 	}
    733  1.1  perry }
    734  1.1  perry 
    735  1.1  perry void
    736  1.1  perry refer(int c1)
    737  1.1  perry {
    738  1.1  perry 	int c2;
    739  1.1  perry 
    740  1.1  perry 	if (c1 != '\n')
    741  1.1  perry 		SKIP;
    742  1.1  perry 
    743  1.1  perry 	for (c2 = -1;;) {
    744  1.1  perry 		if (C != '.')
    745  1.1  perry 			SKIP;
    746  1.1  perry 		else {
    747  1.1  perry 			if (C != ']')
    748  1.1  perry 				SKIP;
    749  1.1  perry 			else {
    750  1.1  perry 				while (C != '\n')
    751  1.1  perry 					c2 = c;
    752  1.1  perry 				if (c2 != -1 && chars[c2] == PUNCT)
    753  1.1  perry 					putchar(c2);
    754  1.1  perry 				return;
    755  1.1  perry 			}
    756  1.1  perry 		}
    757  1.1  perry 	}
    758  1.1  perry }
    759  1.1  perry 
    760  1.1  perry void
    761  1.1  perry inpic(void)
    762  1.1  perry {
    763  1.1  perry 	int c1;
    764  1.1  perry 	char *p1;
    765  1.1  perry 
    766  1.1  perry 	SKIP;
    767  1.1  perry 	p1 = line;
    768  1.1  perry 	c = '\n';
    769  1.1  perry 	for (;;) {
    770  1.1  perry 		c1 = c;
    771  1.1  perry 		if (C == '.' && c1 == '\n') {
    772  1.1  perry 			if (C != 'P') {
    773  1.1  perry 				if (c == '\n')
    774  1.1  perry 					continue;
    775  1.1  perry 				else {
    776  1.1  perry 					SKIP;
    777  1.1  perry 					c = '\n';
    778  1.1  perry 					continue;
    779  1.1  perry 				}
    780  1.1  perry 			}
    781  1.1  perry 			if (C != 'E') {
    782  1.1  perry 				if (c == '\n')
    783  1.1  perry 					continue;
    784  1.1  perry 				else {
    785  1.1  perry 					SKIP;
    786  1.1  perry 					c = '\n';
    787  1.1  perry 					continue;
    788  1.1  perry 				}
    789  1.1  perry 			}
    790  1.1  perry 			SKIP;
    791  1.1  perry 			return;
    792  1.1  perry 		}
    793  1.1  perry 		else if (c == '\"') {
    794  1.1  perry 			while (C != '\"') {
    795  1.1  perry 				if (c == '\\') {
    796  1.1  perry 					if (C == '\"')
    797  1.1  perry 						continue;
    798  1.1  perry 					ungetc(c, infile);
    799  1.1  perry 					backsl();
    800  1.1  perry 				} else
    801  1.1  perry 					*p1++ = c;
    802  1.1  perry 			}
    803  1.1  perry 			*p1++ = ' ';
    804  1.1  perry 		}
    805  1.1  perry 		else if (c == '\n' && p1 != line) {
    806  1.1  perry 			*p1 = '\0';
    807  1.1  perry 			if (wordflag)
    808  1.1  perry 				msputwords(NO);
    809  1.1  perry 			else {
    810  1.1  perry 				puts(line);
    811  1.1  perry 				putchar('\n');
    812  1.1  perry 			}
    813  1.1  perry 			p1 = line;
    814  1.1  perry 		}
    815  1.1  perry 	}
    816  1.1  perry }
    817  1.1  perry 
    818  1.1  perry #ifdef DEBUG
    819  1.1  perry int
    820  1.1  perry _C1(void)
    821  1.1  perry {
    822  1.1  perry 
    823  1.1  perry 	return(C1get);
    824  1.1  perry }
    825  1.1  perry 
    826  1.1  perry int
    827  1.1  perry _C(void)
    828  1.1  perry {
    829  1.1  perry 
    830  1.1  perry 	return(Cget);
    831  1.1  perry }
    832  1.1  perry #endif /* DEBUG */
    833  1.1  perry 
    834  1.1  perry /*
    835  1.1  perry  *	Put out a macro line, using ms and mm conventions.
    836  1.1  perry  */
    837  1.1  perry void
    838  1.1  perry msputmac(char *s, int constant)
    839  1.1  perry {
    840  1.1  perry 	char *t;
    841  1.1  perry 	int found;
    842  1.1  perry 	int last;
    843  1.1  perry 
    844  1.1  perry 	last = 0;
    845  1.1  perry 	found = 0;
    846  1.1  perry 	if (wordflag) {
    847  1.1  perry 		msputwords(YES);
    848  1.1  perry 		return;
    849  1.1  perry 	}
    850  1.1  perry 	while (*s) {
    851  1.1  perry 		while (*s == ' ' || *s == '\t')
    852  1.1  perry 			putchar(*s++);
    853  1.1  perry 		for (t = s ; *t != ' ' && *t != '\t' && *t != '\0' ; ++t)
    854  1.1  perry 			;	/* nothing */
    855  1.1  perry 		if (*s == '\"')
    856  1.1  perry 			s++;
    857  1.1  perry 		if (t > s + constant && chars[(unsigned char)s[0]] == LETTER &&
    858  1.1  perry 		    chars[(unsigned char)s[1]] == LETTER) {
    859  1.1  perry 			while (s < t)
    860  1.1  perry 				if (*s == '\"')
    861  1.1  perry 					s++;
    862  1.1  perry 				else
    863  1.1  perry 					putchar(*s++);
    864  1.1  perry 			last = *(t-1);
    865  1.1  perry 			found++;
    866  1.1  perry 		} else if (found && chars[(unsigned char)s[0]] == PUNCT &&
    867  1.1  perry 		    s[1] == '\0') {
    868  1.1  perry 			putchar(*s++);
    869  1.1  perry 		} else {
    870  1.1  perry 			last = *(t - 1);
    871  1.1  perry 			s = t;
    872  1.1  perry 		}
    873  1.1  perry 	}
    874  1.1  perry 	putchar('\n');
    875  1.1  perry 	if (msflag && chars[last] == PUNCT) {
    876  1.1  perry 		putchar(last);
    877  1.1  perry 		putchar('\n');
    878  1.1  perry 	}
    879  1.1  perry }
    880  1.1  perry 
    881  1.1  perry /*
    882  1.1  perry  *	put out words (for the -w option) with ms and mm conventions
    883  1.1  perry  */
    884  1.1  perry void
    885  1.1  perry msputwords(int macline)
    886  1.1  perry {
    887  1.1  perry 	char *p, *p1;
    888  1.1  perry 	int i, nlet;
    889  1.1  perry 
    890  1.1  perry 	for (p1 = line;;) {
    891  1.1  perry 		/*
    892  1.1  perry 		 *	skip initial specials ampersands and apostrophes
    893  1.1  perry 		 */
    894  1.1  perry 		while (chars[(unsigned char)*p1] < DIGIT)
    895  1.1  perry 			if (*p1++ == '\0')
    896  1.1  perry 				return;
    897  1.1  perry 		nlet = 0;
    898  1.1  perry 		for (p = p1 ; (i = chars[(unsigned char)*p]) != SPECIAL ; ++p)
    899  1.1  perry 			if (i == LETTER)
    900  1.1  perry 				++nlet;
    901  1.1  perry 
    902  1.1  perry 		if (nlet > 1 && chars[(unsigned char)p1[0]] == LETTER) {
    903  1.1  perry 			/*
    904  1.1  perry 			 *	delete trailing ampersands and apostrophes
    905  1.1  perry 			 */
    906  1.1  perry 			while ((i = chars[(unsigned char)p[-1]]) == PUNCT ||
    907  1.1  perry 			    i == APOS )
    908  1.1  perry 				--p;
    909  1.1  perry 			while (p1 < p)
    910  1.1  perry 				putchar(*p1++);
    911  1.1  perry 			putchar('\n');
    912  1.1  perry 		} else {
    913  1.1  perry 			p1 = p;
    914  1.1  perry 		}
    915  1.1  perry 	}
    916  1.1  perry }
    917  1.1  perry 
    918  1.1  perry /*
    919  1.1  perry  *	put out a macro using the me conventions
    920  1.1  perry  */
    921  1.1  perry #define SKIPBLANK(cp)	while (*cp == ' ' || *cp == '\t') { cp++; }
    922  1.1  perry #define SKIPNONBLANK(cp) while (*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
    923  1.1  perry 
    924  1.1  perry void
    925  1.1  perry meputmac(char *cp, int constant)
    926  1.1  perry {
    927  1.1  perry 	char	*np;
    928  1.1  perry 	int	found;
    929  1.1  perry 	int	argno;
    930  1.1  perry 	int	last;
    931  1.1  perry 	int	inquote;
    932  1.1  perry 
    933  1.1  perry 	last = 0;
    934  1.1  perry 	found = 0;
    935  1.1  perry 	if (wordflag) {
    936  1.1  perry 		meputwords(YES);
    937  1.1  perry 		return;
    938  1.1  perry 	}
    939  1.1  perry 	for (argno = 0; *cp; argno++) {
    940  1.1  perry 		SKIPBLANK(cp);
    941  1.1  perry 		inquote = (*cp == '"');
    942  1.1  perry 		if (inquote)
    943  1.1  perry 			cp++;
    944  1.1  perry 		for (np = cp; *np; np++) {
    945  1.1  perry 			switch (*np) {
    946  1.1  perry 			case '\n':
    947  1.1  perry 			case '\0':
    948  1.1  perry 				break;
    949  1.1  perry 
    950  1.1  perry 			case '\t':
    951  1.1  perry 			case ' ':
    952  1.1  perry 				if (inquote)
    953  1.1  perry 					continue;
    954  1.1  perry 				else
    955  1.1  perry 					goto endarg;
    956  1.1  perry 
    957  1.1  perry 			case '"':
    958  1.1  perry 				if (inquote && np[1] == '"') {
    959  1.1  perry 					memmove(np, np + 1, strlen(np));
    960  1.1  perry 					np++;
    961  1.1  perry 					continue;
    962  1.1  perry 				} else {
    963  1.1  perry 					*np = ' '; 	/* bye bye " */
    964  1.1  perry 					goto endarg;
    965  1.1  perry 				}
    966  1.1  perry 
    967  1.1  perry 			default:
    968  1.1  perry 				continue;
    969  1.1  perry 			}
    970  1.1  perry 		}
    971  1.1  perry 		endarg: ;
    972  1.1  perry 		/*
    973  1.1  perry 		 *	cp points at the first char in the arg
    974  1.1  perry 		 *	np points one beyond the last char in the arg
    975  1.1  perry 		 */
    976  1.1  perry 		if ((argconcat == 0) || (argconcat != argno))
    977  1.1  perry 			putchar(' ');
    978  1.1  perry #ifdef FULLDEBUG
    979  1.1  perry 		{
    980  1.1  perry 			char	*p;
    981  1.1  perry 			printf("[%d,%d: ", argno, np - cp);
    982  1.1  perry 			for (p = cp; p < np; p++) {
    983  1.1  perry 				putchar(*p);
    984  1.1  perry 			}
    985  1.1  perry 			printf("]");
    986  1.1  perry 		}
    987  1.1  perry #endif /* FULLDEBUG */
    988  1.1  perry 		/*
    989  1.1  perry 		 *	Determine if the argument merits being printed
    990  1.1  perry 		 *
    991  1.1  perry 		 *	constant is the cut off point below which something
    992  1.1  perry 		 *	is not a word.
    993  1.1  perry 		 */
    994  1.1  perry 		if (((np - cp) > constant) &&
    995  1.1  perry 		    (inquote || (chars[(unsigned char)cp[0]] == LETTER))) {
    996  1.1  perry 			for (cp = cp; cp < np; cp++)
    997  1.1  perry 				putchar(*cp);
    998  1.1  perry 			last = np[-1];
    999  1.1  perry 			found++;
   1000  1.1  perry 		} else if (found && (np - cp == 1) &&
   1001  1.1  perry 		    chars[(unsigned char)*cp] == PUNCT) {
   1002  1.1  perry 			putchar(*cp);
   1003  1.1  perry 		} else {
   1004  1.1  perry 			last = np[-1];
   1005  1.1  perry 		}
   1006  1.1  perry 		cp = np;
   1007  1.1  perry 	}
   1008  1.1  perry 	if (msflag && chars[last] == PUNCT)
   1009  1.1  perry 		putchar(last);
   1010  1.1  perry 	putchar('\n');
   1011  1.1  perry }
   1012  1.1  perry 
   1013  1.1  perry /*
   1014  1.1  perry  *	put out words (for the -w option) with ms and mm conventions
   1015  1.1  perry  */
   1016  1.1  perry void
   1017  1.1  perry meputwords(int macline)
   1018  1.1  perry {
   1019  1.1  perry 
   1020  1.1  perry 	msputwords(macline);
   1021  1.1  perry }
   1022  1.1  perry 
   1023  1.1  perry /*
   1024  1.1  perry  *
   1025  1.1  perry  *	Skip over a nested set of macros
   1026  1.1  perry  *
   1027  1.1  perry  *	Possible arguments to noblock are:
   1028  1.1  perry  *
   1029  1.1  perry  *	fi	end of unfilled text
   1030  1.1  perry  *	PE	pic ending
   1031  1.1  perry  *	DE	display ending
   1032  1.1  perry  *
   1033  1.1  perry  *	for ms and mm only:
   1034  1.1  perry  *		KE	keep ending
   1035  1.1  perry  *
   1036  1.1  perry  *		NE	undocumented match to NS (for mm?)
   1037  1.1  perry  *		LE	mm only: matches RL or *L (for lists)
   1038  1.1  perry  *
   1039  1.1  perry  *	for me:
   1040  1.1  perry  *		([lqbzcdf]
   1041  1.1  perry  */
   1042  1.1  perry void
   1043  1.1  perry noblock(char a1, char a2)
   1044  1.1  perry {
   1045  1.1  perry 	int c1,c2;
   1046  1.1  perry 	int eqnf;
   1047  1.1  perry 	int lct;
   1048  1.1  perry 
   1049  1.1  perry 	lct = 0;
   1050  1.1  perry 	eqnf = 1;
   1051  1.1  perry 	SKIP;
   1052  1.1  perry 	for (;;) {
   1053  1.1  perry 		while (C != '.')
   1054  1.1  perry 			if (c == '\n')
   1055  1.1  perry 				continue;
   1056  1.1  perry 			else
   1057  1.1  perry 				SKIP;
   1058  1.1  perry 		if ((c1 = C) == '\n')
   1059  1.1  perry 			continue;
   1060  1.1  perry 		if ((c2 = C) == '\n')
   1061  1.1  perry 			continue;
   1062  1.1  perry 		if (c1 == a1 && c2 == a2) {
   1063  1.1  perry 			SKIP;
   1064  1.1  perry 			if (lct != 0) {
   1065  1.1  perry 				lct--;
   1066  1.1  perry 				continue;
   1067  1.1  perry 			}
   1068  1.1  perry 			if (eqnf)
   1069  1.1  perry 				putchar('.');
   1070  1.1  perry 			putchar('\n');
   1071  1.1  perry 			return;
   1072  1.1  perry 		} else if (a1 == 'L' && c2 == 'L') {
   1073  1.1  perry 			lct++;
   1074  1.1  perry 			SKIP;
   1075  1.1  perry 		}
   1076  1.1  perry 		/*
   1077  1.1  perry 		 *	equations (EQ) nested within a display
   1078  1.1  perry 		 */
   1079  1.1  perry 		else if (c1 == 'E' && c2 == 'Q') {
   1080  1.1  perry 			if ((mac == ME && a1 == ')')
   1081  1.1  perry 			    || (mac != ME && a1 == 'D')) {
   1082  1.1  perry 				eqn();
   1083  1.1  perry 				eqnf=0;
   1084  1.1  perry 			}
   1085  1.1  perry 		}
   1086  1.1  perry 		/*
   1087  1.1  perry 		 *	turning on filling is done by the paragraphing
   1088  1.1  perry 		 *	macros
   1089  1.1  perry 		 */
   1090  1.1  perry 		else if (a1 == 'f') {	/* .fi */
   1091  1.1  perry 			if  ((mac == ME && (c2 == 'h' || c2 == 'p'))
   1092  1.1  perry 			    || (mac != ME && (c1 == 'P' || c2 == 'P'))) {
   1093  1.1  perry 				SKIP;
   1094  1.1  perry 				return;
   1095  1.1  perry 			}
   1096  1.1  perry 		} else {
   1097  1.1  perry 			SKIP;
   1098  1.1  perry 		}
   1099  1.1  perry 	}
   1100  1.1  perry }
   1101  1.1  perry 
   1102  1.1  perry int
   1103  1.1  perry EQ(void)
   1104  1.1  perry {
   1105  1.1  perry 
   1106  1.1  perry 	eqn();
   1107  1.1  perry 	return(0);
   1108  1.1  perry }
   1109  1.1  perry 
   1110  1.1  perry int
   1111  1.1  perry domacro(void)
   1112  1.1  perry {
   1113  1.1  perry 
   1114  1.1  perry 	macro();
   1115  1.1  perry 	return(0);
   1116  1.1  perry }
   1117  1.1  perry 
   1118  1.1  perry int
   1119  1.1  perry PS(void)
   1120  1.1  perry {
   1121  1.1  perry 
   1122  1.1  perry 	for (C; c == ' ' || c == '\t'; C)
   1123  1.1  perry 		;	/* nothing */
   1124  1.1  perry 
   1125  1.1  perry 	if (c == '<') {		/* ".PS < file" -- don't expect a .PE */
   1126  1.1  perry 		SKIP;
   1127  1.1  perry 		return(0);
   1128  1.1  perry 	}
   1129  1.1  perry 	if (!msflag)
   1130  1.1  perry 		inpic();
   1131  1.1  perry 	else
   1132  1.1  perry 		noblock('P', 'E');
   1133  1.1  perry 	return(0);
   1134  1.1  perry }
   1135  1.1  perry 
   1136  1.1  perry int
   1137  1.1  perry skip(void)
   1138  1.1  perry {
   1139  1.1  perry 
   1140  1.1  perry 	SKIP;
   1141  1.1  perry 	return(0);
   1142  1.1  perry }
   1143  1.1  perry 
   1144  1.1  perry int
   1145  1.1  perry intbl(void)
   1146  1.1  perry {
   1147  1.1  perry 
   1148  1.1  perry 	if (msflag)
   1149  1.1  perry 		stbl();
   1150  1.1  perry 	else
   1151  1.1  perry 		tbl();
   1152  1.1  perry 	return(0);
   1153  1.1  perry }
   1154  1.1  perry 
   1155  1.1  perry int
   1156  1.1  perry outtbl(void)
   1157  1.1  perry {
   1158  1.1  perry 
   1159  1.1  perry 	intable = NO;
   1160  1.1  perry 	return(0);
   1161  1.1  perry }
   1162  1.1  perry 
   1163  1.1  perry int
   1164  1.1  perry so(void)
   1165  1.1  perry {
   1166  1.1  perry 
   1167  1.1  perry 	if (!iflag) {
   1168  1.1  perry 		getfname();
   1169  1.1  perry 		if (fname[0]) {
   1170  1.1  perry 			if (++filesp - &files[0] > MAXFILES)
   1171  1.1  perry 				err(1, "too many nested files (max %d)",
   1172  1.1  perry 				    MAXFILES);
   1173  1.1  perry 			infile = *filesp = opn(fname);
   1174  1.1  perry 		}
   1175  1.1  perry 	}
   1176  1.1  perry 	return(0);
   1177  1.1  perry }
   1178  1.1  perry 
   1179  1.1  perry int
   1180  1.1  perry nx(void)
   1181  1.1  perry {
   1182  1.1  perry 
   1183  1.1  perry 	if (!iflag) {
   1184  1.1  perry 		getfname();
   1185  1.1  perry 		if (fname[0] == '\0')
   1186  1.1  perry 			exit(0);
   1187  1.1  perry 		if (infile != stdin)
   1188  1.1  perry 			fclose(infile);
   1189  1.1  perry 		infile = *filesp = opn(fname);
   1190  1.1  perry 	}
   1191  1.1  perry 	return(0);
   1192  1.1  perry }
   1193  1.1  perry 
   1194  1.1  perry int
   1195  1.1  perry skiptocom(void)
   1196  1.1  perry {
   1197  1.1  perry 
   1198  1.1  perry 	SKIP_TO_COM;
   1199  1.1  perry 	return(COMX);
   1200  1.1  perry }
   1201  1.1  perry 
   1202  1.1  perry int
   1203  1.1  perry PP(pacmac c12)
   1204  1.1  perry {
   1205  1.1  perry 	int c1, c2;
   1206  1.1  perry 
   1207  1.1  perry 	frommac(c12, c1, c2);
   1208  1.1  perry 	printf(".%c%c", c1, c2);
   1209  1.1  perry 	while (C != '\n')
   1210  1.1  perry 		putchar(c);
   1211  1.1  perry 	putchar('\n');
   1212  1.1  perry 	return(0);
   1213  1.1  perry }
   1214  1.1  perry 
   1215  1.1  perry int
   1216  1.1  perry AU(void)
   1217  1.1  perry {
   1218  1.1  perry 
   1219  1.1  perry 	if (mac == MM)
   1220  1.1  perry 		return(0);
   1221  1.1  perry 	SKIP_TO_COM;
   1222  1.1  perry 	return(COMX);
   1223  1.1  perry }
   1224  1.1  perry 
   1225  1.1  perry int
   1226  1.1  perry SH(pacmac c12)
   1227  1.1  perry {
   1228  1.1  perry 	int c1, c2;
   1229  1.1  perry 
   1230  1.1  perry 	frommac(c12, c1, c2);
   1231  1.1  perry 
   1232  1.1  perry 	if (parag) {
   1233  1.1  perry 		printf(".%c%c", c1, c2);
   1234  1.1  perry 		while (C != '\n')
   1235  1.1  perry 			putchar(c);
   1236  1.1  perry 		putchar(c);
   1237  1.1  perry 		putchar('!');
   1238  1.1  perry 		for (;;) {
   1239  1.1  perry 			while (C != '\n')
   1240  1.1  perry 				putchar(c);
   1241  1.1  perry 			putchar('\n');
   1242  1.1  perry 			if (C == '.')
   1243  1.1  perry 				return(COM);
   1244  1.1  perry 			putchar('!');
   1245  1.1  perry 			putchar(c);
   1246  1.1  perry 		}
   1247  1.1  perry 		/*NOTREACHED*/
   1248  1.1  perry 	} else {
   1249  1.1  perry 		SKIP_TO_COM;
   1250  1.1  perry 		return(COMX);
   1251  1.1  perry 	}
   1252  1.1  perry }
   1253  1.1  perry 
   1254  1.1  perry int
   1255  1.1  perry UX(void)
   1256  1.1  perry {
   1257  1.1  perry 
   1258  1.1  perry 	if (wordflag)
   1259  1.1  perry 		printf("UNIX\n");
   1260  1.1  perry 	else
   1261  1.1  perry 		printf("UNIX ");
   1262  1.1  perry 	return(0);
   1263  1.1  perry }
   1264  1.1  perry 
   1265  1.1  perry int
   1266  1.1  perry MMHU(pacmac c12)
   1267  1.1  perry {
   1268  1.1  perry 	int c1, c2;
   1269  1.1  perry 
   1270  1.1  perry 	frommac(c12, c1, c2);
   1271  1.1  perry 	if (parag) {
   1272  1.1  perry 		printf(".%c%c", c1, c2);
   1273  1.1  perry 		while (C != '\n')
   1274  1.1  perry 			putchar(c);
   1275  1.1  perry 		putchar('\n');
   1276  1.1  perry 	} else {
   1277  1.1  perry 		SKIP;
   1278  1.1  perry 	}
   1279  1.1  perry 	return(0);
   1280  1.1  perry }
   1281  1.1  perry 
   1282  1.1  perry int
   1283  1.1  perry mesnblock(pacmac c12)
   1284  1.1  perry {
   1285  1.1  perry 	int c1, c2;
   1286  1.1  perry 
   1287  1.1  perry 	frommac(c12, c1, c2);
   1288  1.1  perry 	noblock(')', c2);
   1289  1.1  perry 	return(0);
   1290  1.1  perry }
   1291  1.1  perry 
   1292  1.1  perry int
   1293  1.1  perry mssnblock(pacmac c12)
   1294  1.1  perry {
   1295  1.1  perry 	int c1, c2;
   1296  1.1  perry 
   1297  1.1  perry 	frommac(c12, c1, c2);
   1298  1.1  perry 	noblock(c1, 'E');
   1299  1.1  perry 	return(0);
   1300  1.1  perry }
   1301  1.1  perry 
   1302  1.1  perry int
   1303  1.1  perry nf(void)
   1304  1.1  perry {
   1305  1.1  perry 
   1306  1.1  perry 	noblock('f', 'i');
   1307  1.1  perry 	return(0);
   1308  1.1  perry }
   1309  1.1  perry 
   1310  1.1  perry int
   1311  1.1  perry ce(void)
   1312  1.1  perry {
   1313  1.1  perry 
   1314  1.1  perry 	sce();
   1315  1.1  perry 	return(0);
   1316  1.1  perry }
   1317  1.1  perry 
   1318  1.1  perry int
   1319  1.1  perry meip(pacmac c12)
   1320  1.1  perry {
   1321  1.1  perry 
   1322  1.1  perry 	if (parag)
   1323  1.1  perry 		mepp(c12);
   1324  1.1  perry 	else if (wordflag)	/* save the tag */
   1325  1.1  perry 		regline(meputmac, ONE);
   1326  1.1  perry 	else
   1327  1.1  perry 		SKIP;
   1328  1.1  perry 	return(0);
   1329  1.1  perry }
   1330  1.1  perry 
   1331  1.1  perry /*
   1332  1.1  perry  *	only called for -me .pp or .sh, when parag is on
   1333  1.1  perry  */
   1334  1.1  perry int
   1335  1.1  perry mepp(pacmac c12)
   1336  1.1  perry {
   1337  1.1  perry 
   1338  1.1  perry 	PP(c12);		/* eats the line */
   1339  1.1  perry 	return(0);
   1340  1.1  perry }
   1341  1.1  perry 
   1342  1.1  perry /*
   1343  1.1  perry  *	Start of a section heading; output the section name if doing words
   1344  1.1  perry  */
   1345  1.1  perry int
   1346  1.1  perry mesh(pacmac c12)
   1347  1.1  perry {
   1348  1.1  perry 
   1349  1.1  perry 	if (parag)
   1350  1.1  perry 		mepp(c12);
   1351  1.1  perry 	else if (wordflag)
   1352  1.1  perry 		defcomline(c12);
   1353  1.1  perry 	else
   1354  1.1  perry 		SKIP;
   1355  1.1  perry 	return(0);
   1356  1.1  perry }
   1357  1.1  perry 
   1358  1.1  perry /*
   1359  1.1  perry  *	process a font setting
   1360  1.1  perry  */
   1361  1.1  perry int
   1362  1.1  perry mefont(pacmac c12)
   1363  1.1  perry {
   1364  1.1  perry 
   1365  1.1  perry 	argconcat = 1;
   1366  1.1  perry 	defcomline(c12);
   1367  1.1  perry 	argconcat = 0;
   1368  1.1  perry 	return(0);
   1369  1.1  perry }
   1370  1.1  perry 
   1371  1.1  perry int
   1372  1.1  perry manfont(pacmac c12)
   1373  1.1  perry {
   1374  1.1  perry 
   1375  1.1  perry 	return(mefont(c12));
   1376  1.1  perry }
   1377  1.1  perry 
   1378  1.1  perry int
   1379  1.1  perry manpp(pacmac c12)
   1380  1.1  perry {
   1381  1.1  perry 
   1382  1.1  perry 	return(mepp(c12));
   1383  1.1  perry }
   1384  1.1  perry 
   1385  1.1  perry void
   1386  1.1  perry defcomline(pacmac c12)
   1387  1.1  perry {
   1388  1.1  perry 	int c1, c2;
   1389  1.1  perry 
   1390  1.1  perry 	frommac(c12, c1, c2);
   1391  1.1  perry 	if (msflag && mac == MM && c2 == 'L') {
   1392  1.1  perry 		if (disp || c1 == 'R') {
   1393  1.1  perry 			noblock('L', 'E');
   1394  1.1  perry 		} else {
   1395  1.1  perry 			SKIP;
   1396  1.1  perry 			putchar('.');
   1397  1.1  perry 		}
   1398  1.1  perry 	}
   1399  1.1  perry 	else if (c1 == '.' && c2 == '.') {
   1400  1.1  perry 		if (msflag) {
   1401  1.1  perry 			SKIP;
   1402  1.1  perry 			return;
   1403  1.1  perry 		}
   1404  1.1  perry 		while (C == '.')
   1405  1.1  perry 			/*VOID*/;
   1406  1.1  perry 	}
   1407  1.1  perry 	++inmacro;
   1408  1.1  perry 	/*
   1409  1.1  perry 	 *	Process the arguments to the macro
   1410  1.1  perry 	 */
   1411  1.1  perry 	switch (mac) {
   1412  1.1  perry 	default:
   1413  1.1  perry 	case MM:
   1414  1.1  perry 	case MS:
   1415  1.1  perry 		if (c1 <= 'Z' && msflag)
   1416  1.1  perry 			regline(msputmac, ONE);
   1417  1.1  perry 		else
   1418  1.1  perry 			regline(msputmac, TWO);
   1419  1.1  perry 		break;
   1420  1.1  perry 	case ME:
   1421  1.1  perry 		regline(meputmac, ONE);
   1422  1.1  perry 		break;
   1423  1.1  perry 	}
   1424  1.1  perry 	--inmacro;
   1425  1.1  perry }
   1426  1.1  perry 
   1427  1.1  perry void
   1428  1.1  perry comline(void)
   1429  1.1  perry {
   1430  1.1  perry 	int	c1;
   1431  1.1  perry 	int	c2;
   1432  1.1  perry 	pacmac	c12;
   1433  1.1  perry 	int	mid;
   1434  1.1  perry 	int	lb, ub;
   1435  1.1  perry 	int	hit;
   1436  1.1  perry 	static	int	tabsize = 0;
   1437  1.1  perry 	static	struct	mactab	*mactab = (struct mactab *)0;
   1438  1.1  perry 	struct	mactab	*mp;
   1439  1.1  perry 
   1440  1.1  perry 	if (mactab == 0)
   1441  1.1  perry 		 buildtab(&mactab, &tabsize);
   1442  1.1  perry com:
   1443  1.1  perry 	while (C == ' ' || c == '\t')
   1444  1.1  perry 		;
   1445  1.1  perry comx:
   1446  1.1  perry 	if ((c1 = c) == '\n')
   1447  1.1  perry 		return;
   1448  1.1  perry 	c2 = C;
   1449  1.1  perry 	if (c1 == '.' && c2 != '.')
   1450  1.1  perry 		inmacro = NO;
   1451  1.1  perry 	if (msflag && c1 == '[') {
   1452  1.1  perry 		refer(c2);
   1453  1.1  perry 		return;
   1454  1.1  perry 	}
   1455  1.1  perry 	if (parag && mac==MM && c1 == 'P' && c2 == '\n') {
   1456  1.1  perry 		printf(".P\n");
   1457  1.1  perry 		return;
   1458  1.1  perry 	}
   1459  1.1  perry 	if (c2 == '\n')
   1460  1.1  perry 		return;
   1461  1.1  perry 	/*
   1462  1.1  perry 	 *	Single letter macro
   1463  1.1  perry 	 */
   1464  1.1  perry 	if (mac == ME && (c2 == ' ' || c2 == '\t') )
   1465  1.1  perry 		c2 = ' ';
   1466  1.1  perry 	c12 = tomac(c1, c2);
   1467  1.1  perry 	/*
   1468  1.1  perry 	 *	binary search through the table of macros
   1469  1.1  perry 	 */
   1470  1.1  perry 	lb = 0;
   1471  1.1  perry 	ub = tabsize - 1;
   1472  1.1  perry 	while (lb <= ub) {
   1473  1.1  perry 		mid = (ub + lb) / 2;
   1474  1.1  perry 		mp = &mactab[mid];
   1475  1.1  perry 		if (mp->macname < c12)
   1476  1.1  perry 			lb = mid + 1;
   1477  1.1  perry 		else if (mp->macname > c12)
   1478  1.1  perry 			ub = mid - 1;
   1479  1.1  perry 		else {
   1480  1.1  perry 			hit = 1;
   1481  1.1  perry #ifdef FULLDEBUG
   1482  1.1  perry 			printf("preliminary hit macro %c%c ", c1, c2);
   1483  1.1  perry #endif /* FULLDEBUG */
   1484  1.1  perry 			switch (mp->condition) {
   1485  1.1  perry 			case NONE:
   1486  1.1  perry 				hit = YES;
   1487  1.1  perry 				break;
   1488  1.1  perry 			case FNEST:
   1489  1.1  perry 				hit = (filesp == files);
   1490  1.1  perry 				break;
   1491  1.1  perry 			case NOMAC:
   1492  1.1  perry 				hit = !inmacro;
   1493  1.1  perry 				break;
   1494  1.1  perry 			case MAC:
   1495  1.1  perry 				hit = inmacro;
   1496  1.1  perry 				break;
   1497  1.1  perry 			case PARAG:
   1498  1.1  perry 				hit = parag;
   1499  1.1  perry 				break;
   1500  1.1  perry 			case NBLK:
   1501  1.1  perry 				hit = !keepblock;
   1502  1.1  perry 				break;
   1503  1.1  perry 			default:
   1504  1.1  perry 				hit = 0;
   1505  1.1  perry 			}
   1506  1.1  perry 
   1507  1.1  perry 			if (hit) {
   1508  1.1  perry #ifdef FULLDEBUG
   1509  1.1  perry 				printf("MATCH\n");
   1510  1.1  perry #endif /* FULLDEBUG */
   1511  1.1  perry 				switch ((*(mp->func))(c12)) {
   1512  1.1  perry 				default:
   1513  1.1  perry 					return;
   1514  1.1  perry 				case COMX:
   1515  1.1  perry 					goto comx;
   1516  1.1  perry 				case COM:
   1517  1.1  perry 					goto com;
   1518  1.1  perry 				}
   1519  1.1  perry 			}
   1520  1.1  perry #ifdef FULLDEBUG
   1521  1.1  perry 			printf("FAIL\n");
   1522  1.1  perry #endif /* FULLDEBUG */
   1523  1.1  perry 			break;
   1524  1.1  perry 		}
   1525  1.1  perry 	}
   1526  1.1  perry 	defcomline(c12);
   1527  1.1  perry }
   1528  1.1  perry 
   1529  1.1  perry int
   1530  1.1  perry macsort(const void *p1, const void *p2)
   1531  1.1  perry {
   1532  1.1  perry 	struct mactab *t1 = (struct mactab *)p1;
   1533  1.1  perry 	struct mactab *t2 = (struct mactab *)p2;
   1534  1.1  perry 
   1535  1.1  perry 	return(t1->macname - t2->macname);
   1536  1.1  perry }
   1537  1.1  perry 
   1538  1.1  perry int
   1539  1.1  perry sizetab(struct mactab *mp)
   1540  1.1  perry {
   1541  1.1  perry 	int i;
   1542  1.1  perry 
   1543  1.1  perry 	i = 0;
   1544  1.1  perry 	if (mp) {
   1545  1.1  perry 		for (; mp->macname; mp++, i++)
   1546  1.1  perry 			/*VOID*/ ;
   1547  1.1  perry 	}
   1548  1.1  perry 	return(i);
   1549  1.1  perry }
   1550  1.1  perry 
   1551  1.1  perry struct mactab *
   1552  1.1  perry macfill(struct mactab *dst, struct mactab *src)
   1553  1.1  perry {
   1554  1.1  perry 
   1555  1.1  perry 	if (src) {
   1556  1.1  perry 		while (src->macname)
   1557  1.1  perry 			*dst++ = *src++;
   1558  1.1  perry 	}
   1559  1.1  perry 	return(dst);
   1560  1.1  perry }
   1561  1.1  perry 
   1562  1.1  perry __dead void
   1563  1.1  perry usage(void)
   1564  1.1  perry {
   1565  1.1  perry 	extern char *__progname;
   1566  1.1  perry 
   1567  1.1  perry 	fprintf(stderr, "usage: %s [-ikpw ] [ -m ( a | e | m | s | l ) ] [ filename ] ... \n", __progname);
   1568  1.1  perry 	exit(1);
   1569  1.1  perry }
   1570  1.1  perry 
   1571  1.1  perry void
   1572  1.1  perry buildtab(struct mactab **r_back, int *r_size)
   1573  1.1  perry {
   1574  1.1  perry 	int	size;
   1575  1.1  perry 	struct	mactab	*p, *p1, *p2;
   1576  1.1  perry 	struct	mactab	*back;
   1577  1.1  perry 
   1578  1.1  perry 	size = sizetab(troffmactab) + sizetab(ppmactab);
   1579  1.1  perry 	p1 = p2 = NULL;
   1580  1.1  perry 	if (msflag) {
   1581  1.1  perry 		switch (mac) {
   1582  1.1  perry 		case ME:
   1583  1.1  perry 			p1 = memactab;
   1584  1.1  perry 			break;
   1585  1.1  perry 		case MM:
   1586  1.1  perry 			p1 = msmactab;
   1587  1.1  perry 			p2 = mmmactab;
   1588  1.1  perry 			break;
   1589  1.1  perry 		case MS:
   1590  1.1  perry 			p1 = msmactab;
   1591  1.1  perry 			break;
   1592  1.1  perry 		case MA:
   1593  1.1  perry 			p1 = manmactab;
   1594  1.1  perry 			break;
   1595  1.1  perry 		default:
   1596  1.1  perry 			break;
   1597  1.1  perry 		}
   1598  1.1  perry 	}
   1599  1.1  perry 	size += sizetab(p1);
   1600  1.1  perry 	size += sizetab(p2);
   1601  1.1  perry 	back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
   1602  1.1  perry 	if (back == NULL)
   1603  1.1  perry 		err(1, NULL);
   1604  1.1  perry 
   1605  1.1  perry 	p = macfill(back, troffmactab);
   1606  1.1  perry 	p = macfill(p, ppmactab);
   1607  1.1  perry 	p = macfill(p, p1);
   1608  1.1  perry 	p = macfill(p, p2);
   1609  1.1  perry 
   1610  1.1  perry 	qsort(back, size, sizeof(struct mactab), macsort);
   1611  1.1  perry 	*r_size = size;
   1612  1.1  perry 	*r_back = back;
   1613  1.1  perry }
   1614  1.1  perry 
   1615  1.1  perry /*
   1616  1.1  perry  *	troff commands
   1617  1.1  perry  */
   1618  1.1  perry struct	mactab	troffmactab[] = {
   1619  1.1  perry 	M(NONE,		'\\','"',	skip),	/* comment */
   1620  1.1  perry 	M(NOMAC,	'd','e',	domacro),	/* define */
   1621  1.1  perry 	M(NOMAC,	'i','g',	domacro),	/* ignore till .. */
   1622  1.1  perry 	M(NOMAC,	'a','m',	domacro),	/* append macro */
   1623  1.1  perry 	M(NBLK,		'n','f',	nf),	/* filled */
   1624  1.1  perry 	M(NBLK,		'c','e',	ce),	/* centered */
   1625  1.1  perry 
   1626  1.1  perry 	M(NONE,		's','o',	so),	/* source a file */
   1627  1.1  perry 	M(NONE,		'n','x',	nx),	/* go to next file */
   1628  1.1  perry 
   1629  1.1  perry 	M(NONE,		't','m',	skip),	/* print string on tty */
   1630  1.1  perry 	M(NONE,		'h','w',	skip),	/* exception hyphen words */
   1631  1.1  perry 	M(NONE,		0,0,		0)
   1632  1.1  perry };
   1633  1.1  perry 
   1634  1.1  perry /*
   1635  1.1  perry  *	Preprocessor output
   1636  1.1  perry  */
   1637  1.1  perry struct	mactab	ppmactab[] = {
   1638  1.1  perry 	M(FNEST,	'E','Q',	EQ),	/* equation starting */
   1639  1.1  perry 	M(FNEST,	'T','S',	intbl),	/* table starting */
   1640  1.1  perry 	M(FNEST,	'T','C',	intbl),	/* alternative table? */
   1641  1.1  perry 	M(FNEST,	'T','&',	intbl),	/* table reformatting */
   1642  1.1  perry 	M(NONE,		'T','E',	outtbl),/* table ending */
   1643  1.1  perry 	M(NONE,		'P','S',	PS),	/* picture starting */
   1644  1.1  perry 	M(NONE,		0,0,		0)
   1645  1.1  perry };
   1646  1.1  perry 
   1647  1.1  perry /*
   1648  1.1  perry  *	Particular to ms and mm
   1649  1.1  perry  */
   1650  1.1  perry struct	mactab	msmactab[] = {
   1651  1.1  perry 	M(NONE,		'T','L',	skiptocom),	/* title follows */
   1652  1.1  perry 	M(NONE,		'F','S',	skiptocom),	/* start footnote */
   1653  1.1  perry 	M(NONE,		'O','K',	skiptocom),	/* Other kws */
   1654  1.1  perry 
   1655  1.1  perry 	M(NONE,		'N','R',	skip),	/* undocumented */
   1656  1.1  perry 	M(NONE,		'N','D',	skip),	/* use supplied date */
   1657  1.1  perry 
   1658  1.1  perry 	M(PARAG,	'P','P',	PP),	/* begin parag */
   1659  1.1  perry 	M(PARAG,	'I','P',	PP),	/* begin indent parag, tag x */
   1660  1.1  perry 	M(PARAG,	'L','P',	PP),	/* left blocked parag */
   1661  1.1  perry 
   1662  1.1  perry 	M(NONE,		'A','U',	AU),	/* author */
   1663  1.1  perry 	M(NONE,		'A','I',	AU),	/* authors institution */
   1664  1.1  perry 
   1665  1.1  perry 	M(NONE,		'S','H',	SH),	/* section heading */
   1666  1.1  perry 	M(NONE,		'S','N',	SH),	/* undocumented */
   1667  1.1  perry 	M(NONE,		'U','X',	UX),	/* unix */
   1668  1.1  perry 
   1669  1.1  perry 	M(NBLK,		'D','S',	mssnblock),	/* start display text */
   1670  1.1  perry 	M(NBLK,		'K','S',	mssnblock),	/* start keep */
   1671  1.1  perry 	M(NBLK,		'K','F',	mssnblock),	/* start float keep */
   1672  1.1  perry 	M(NONE,		0,0,		0)
   1673  1.1  perry };
   1674  1.1  perry 
   1675  1.1  perry struct	mactab	mmmactab[] = {
   1676  1.1  perry 	M(NONE,		'H',' ',	MMHU),	/* -mm ? */
   1677  1.1  perry 	M(NONE,		'H','U',	MMHU),	/* -mm ? */
   1678  1.1  perry 	M(PARAG,	'P',' ',	PP),	/* paragraph for -mm */
   1679  1.1  perry 	M(NBLK,		'N','S',	mssnblock),	/* undocumented */
   1680  1.1  perry 	M(NONE,		0,0,		0)
   1681  1.1  perry };
   1682  1.1  perry 
   1683  1.1  perry struct	mactab	memactab[] = {
   1684  1.1  perry 	M(PARAG,	'p','p',	mepp),
   1685  1.1  perry 	M(PARAG,	'l','p',	mepp),
   1686  1.1  perry 	M(PARAG,	'n','p',	mepp),
   1687  1.1  perry 	M(NONE,		'i','p',	meip),
   1688  1.1  perry 
   1689  1.1  perry 	M(NONE,		's','h',	mesh),
   1690  1.1  perry 	M(NONE,		'u','h',	mesh),
   1691  1.1  perry 
   1692  1.1  perry 	M(NBLK,		'(','l',	mesnblock),
   1693  1.1  perry 	M(NBLK,		'(','q',	mesnblock),
   1694  1.1  perry 	M(NBLK,		'(','b',	mesnblock),
   1695  1.1  perry 	M(NBLK,		'(','z',	mesnblock),
   1696  1.1  perry 	M(NBLK,		'(','c',	mesnblock),
   1697  1.1  perry 
   1698  1.1  perry 	M(NBLK,		'(','d',	mesnblock),
   1699  1.1  perry 	M(NBLK,		'(','f',	mesnblock),
   1700  1.1  perry 	M(NBLK,		'(','x',	mesnblock),
   1701  1.1  perry 
   1702  1.1  perry 	M(NONE,		'r',' ',	mefont),
   1703  1.1  perry 	M(NONE,		'i',' ',	mefont),
   1704  1.1  perry 	M(NONE,		'b',' ',	mefont),
   1705  1.1  perry 	M(NONE,		'u',' ',	mefont),
   1706  1.1  perry 	M(NONE,		'q',' ',	mefont),
   1707  1.1  perry 	M(NONE,		'r','b',	mefont),
   1708  1.1  perry 	M(NONE,		'b','i',	mefont),
   1709  1.1  perry 	M(NONE,		'b','x',	mefont),
   1710  1.1  perry 	M(NONE,		0,0,		0)
   1711  1.1  perry };
   1712  1.1  perry 
   1713  1.1  perry struct	mactab	manmactab[] = {
   1714  1.1  perry 	M(PARAG,	'B','I',	manfont),
   1715  1.1  perry 	M(PARAG,	'B','R',	manfont),
   1716  1.1  perry 	M(PARAG,	'I','B',	manfont),
   1717  1.1  perry 	M(PARAG,	'I','R',	manfont),
   1718  1.1  perry 	M(PARAG,	'R','B',	manfont),
   1719  1.1  perry 	M(PARAG,	'R','I',	manfont),
   1720  1.1  perry 
   1721  1.1  perry 	M(PARAG,	'P','P',	manpp),
   1722  1.1  perry 	M(PARAG,	'L','P',	manpp),
   1723  1.1  perry 	M(PARAG,	'H','P',	manpp),
   1724  1.1  perry 	M(NONE,		0,0,		0)
   1725  1.1  perry };
   1726