xref: /freebsd/usr.bin/m4/main.c (revision 9510535891940ddf876c987e8c6bae0cea0491e2)
19b50d902SRodney W. Grimes /*-
29b50d902SRodney W. Grimes  * Copyright (c) 1989, 1993
39b50d902SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
49b50d902SRodney W. Grimes  *
59b50d902SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
69b50d902SRodney W. Grimes  * Ozan Yigit at York University.
79b50d902SRodney W. Grimes  *
89b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
99b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
109b50d902SRodney W. Grimes  * are met:
119b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
129b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
139b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
149b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
159b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
169b50d902SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
179b50d902SRodney W. Grimes  *    must display the following acknowledgement:
189b50d902SRodney W. Grimes  *	This product includes software developed by the University of
199b50d902SRodney W. Grimes  *	California, Berkeley and its contributors.
209b50d902SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
219b50d902SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
229b50d902SRodney W. Grimes  *    without specific prior written permission.
239b50d902SRodney W. Grimes  *
249b50d902SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
259b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
269b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
279b50d902SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
289b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
299b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
309b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
319b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
329b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
339b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
349b50d902SRodney W. Grimes  * SUCH DAMAGE.
359b50d902SRodney W. Grimes  */
369b50d902SRodney W. Grimes 
379b50d902SRodney W. Grimes #ifndef lint
3895105358SPhilippe Charnier static const char copyright[] =
399b50d902SRodney W. Grimes "@(#) Copyright (c) 1989, 1993\n\
409b50d902SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
419b50d902SRodney W. Grimes #endif /* not lint */
429b50d902SRodney W. Grimes 
439b50d902SRodney W. Grimes #ifndef lint
4495105358SPhilippe Charnier #if 0
459b50d902SRodney W. Grimes static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/6/93";
4695105358SPhilippe Charnier #endif
4795105358SPhilippe Charnier static const char rcsid[] =
4895105358SPhilippe Charnier 	"$Id$";
499b50d902SRodney W. Grimes #endif /* not lint */
509b50d902SRodney W. Grimes 
519b50d902SRodney W. Grimes /*
529b50d902SRodney W. Grimes  * main.c
539b50d902SRodney W. Grimes  * Facility: m4 macro processor
549b50d902SRodney W. Grimes  * by: oz
559b50d902SRodney W. Grimes  */
569b50d902SRodney W. Grimes 
579b50d902SRodney W. Grimes #include <sys/types.h>
589b50d902SRodney W. Grimes #include <ctype.h>
5995105358SPhilippe Charnier #include <err.h>
6095105358SPhilippe Charnier #include <signal.h>
6195105358SPhilippe Charnier #include <stdio.h>
629b50d902SRodney W. Grimes #include <string.h>
6395105358SPhilippe Charnier #include <unistd.h>
649b50d902SRodney W. Grimes #include "mdef.h"
659b50d902SRodney W. Grimes #include "stdd.h"
669b50d902SRodney W. Grimes #include "extern.h"
679b50d902SRodney W. Grimes #include "pathnames.h"
689b50d902SRodney W. Grimes 
699b50d902SRodney W. Grimes ndptr hashtab[HASHSIZE];	/* hash table for macros etc.  */
707c5eeb39SAndrey A. Chernov unsigned char buf[BUFSIZE];              /* push-back buffer            */
717c5eeb39SAndrey A. Chernov unsigned char *bufbase = buf;            /* the base for current ilevel */
727c5eeb39SAndrey A. Chernov unsigned char *bbase[MAXINP];            /* the base for each ilevel    */
737c5eeb39SAndrey A. Chernov unsigned char *bp = buf;                 /* first available character   */
747c5eeb39SAndrey A. Chernov unsigned char *endpbb = buf+BUFSIZE;     /* end of push-back buffer     */
759b50d902SRodney W. Grimes stae mstack[STACKMAX+1]; 	/* stack of m4 machine         */
769b50d902SRodney W. Grimes char strspace[STRSPMAX+1];	/* string space for evaluation */
779b50d902SRodney W. Grimes char *ep = strspace;		/* first free char in strspace */
789b50d902SRodney W. Grimes char *endest= strspace+STRSPMAX;/* end of string space	       */
799b50d902SRodney W. Grimes int sp; 			/* current m4  stack pointer   */
809b50d902SRodney W. Grimes int fp; 			/* m4 call frame pointer       */
819b50d902SRodney W. Grimes FILE *infile[MAXINP];		/* input file stack (0=stdin)  */
829b50d902SRodney W. Grimes FILE *outfile[MAXOUT];		/* diversion array(0=bitbucket)*/
839b50d902SRodney W. Grimes FILE *active;			/* active output file pointer  */
849b50d902SRodney W. Grimes char *m4temp;			/* filename for diversions     */
859b50d902SRodney W. Grimes int ilevel = 0; 		/* input file stack pointer    */
869b50d902SRodney W. Grimes int oindex = 0; 		/* diversion index..	       */
879b50d902SRodney W. Grimes char *null = "";                /* as it says.. just a null..  */
889b50d902SRodney W. Grimes char *m4wraps = "";             /* m4wrap string default..     */
899b50d902SRodney W. Grimes char lquote = LQUOTE;		/* left quote character  (`)   */
909b50d902SRodney W. Grimes char rquote = RQUOTE;		/* right quote character (')   */
919b50d902SRodney W. Grimes char scommt = SCOMMT;		/* start character for comment */
929b50d902SRodney W. Grimes char ecommt = ECOMMT;		/* end character for comment   */
939b50d902SRodney W. Grimes 
949b50d902SRodney W. Grimes struct keyblk keywrds[] = {	/* m4 keywords to be installed */
959b50d902SRodney W. Grimes 	"include",      INCLTYPE,
969b50d902SRodney W. Grimes 	"sinclude",     SINCTYPE,
979b50d902SRodney W. Grimes 	"define",       DEFITYPE,
989b50d902SRodney W. Grimes 	"defn",         DEFNTYPE,
999b50d902SRodney W. Grimes 	"divert",       DIVRTYPE,
1009b50d902SRodney W. Grimes 	"expr",         EXPRTYPE,
1019b50d902SRodney W. Grimes 	"eval",         EXPRTYPE,
1029b50d902SRodney W. Grimes 	"substr",       SUBSTYPE,
1039b50d902SRodney W. Grimes 	"ifelse",       IFELTYPE,
1049b50d902SRodney W. Grimes 	"ifdef",        IFDFTYPE,
1059b50d902SRodney W. Grimes 	"len",          LENGTYPE,
1069b50d902SRodney W. Grimes 	"incr",         INCRTYPE,
1079b50d902SRodney W. Grimes 	"decr",         DECRTYPE,
1089b50d902SRodney W. Grimes 	"dnl",          DNLNTYPE,
1099b50d902SRodney W. Grimes 	"changequote",  CHNQTYPE,
1109b50d902SRodney W. Grimes 	"changecom",    CHNCTYPE,
1119b50d902SRodney W. Grimes 	"index",        INDXTYPE,
1129b50d902SRodney W. Grimes #ifdef EXTENDED
1139b50d902SRodney W. Grimes 	"paste",        PASTTYPE,
1149b50d902SRodney W. Grimes 	"spaste",       SPASTYPE,
1159b50d902SRodney W. Grimes #endif
1169b50d902SRodney W. Grimes 	"popdef",       POPDTYPE,
1179b50d902SRodney W. Grimes 	"pushdef",      PUSDTYPE,
1189b50d902SRodney W. Grimes 	"dumpdef",      DUMPTYPE,
1199b50d902SRodney W. Grimes 	"shift",        SHIFTYPE,
1209b50d902SRodney W. Grimes 	"translit",     TRNLTYPE,
1219b50d902SRodney W. Grimes 	"undefine",     UNDFTYPE,
1229b50d902SRodney W. Grimes 	"undivert",     UNDVTYPE,
1239b50d902SRodney W. Grimes 	"divnum",       DIVNTYPE,
1249b50d902SRodney W. Grimes 	"maketemp",     MKTMTYPE,
1259b50d902SRodney W. Grimes 	"errprint",     ERRPTYPE,
1269b50d902SRodney W. Grimes 	"m4wrap",       M4WRTYPE,
1279b50d902SRodney W. Grimes 	"m4exit",       EXITTYPE,
1289b50d902SRodney W. Grimes 	"syscmd",       SYSCTYPE,
1299b50d902SRodney W. Grimes 	"sysval",       SYSVTYPE,
1309b50d902SRodney W. Grimes 
1319b50d902SRodney W. Grimes #ifdef unix
1329b50d902SRodney W. Grimes 	"unix",         MACRTYPE,
1339b50d902SRodney W. Grimes #else
1349b50d902SRodney W. Grimes #ifdef vms
1359b50d902SRodney W. Grimes 	"vms",          MACRTYPE,
1369b50d902SRodney W. Grimes #endif
1379b50d902SRodney W. Grimes #endif
1389b50d902SRodney W. Grimes };
1399b50d902SRodney W. Grimes 
1409b50d902SRodney W. Grimes #define MAXKEYS	(sizeof(keywrds)/sizeof(struct keyblk))
1419b50d902SRodney W. Grimes 
1429b50d902SRodney W. Grimes extern int optind;
1439b50d902SRodney W. Grimes extern char *optarg;
1449b50d902SRodney W. Grimes 
1459b50d902SRodney W. Grimes void macro();
1469b50d902SRodney W. Grimes void initkwds();
1479b50d902SRodney W. Grimes extern int getopt();
1489b50d902SRodney W. Grimes 
1499b50d902SRodney W. Grimes int
1509b50d902SRodney W. Grimes main(argc,argv)
1519b50d902SRodney W. Grimes 	int argc;
1529b50d902SRodney W. Grimes 	char *argv[];
1539b50d902SRodney W. Grimes {
1549b50d902SRodney W. Grimes 	register int c;
1559b50d902SRodney W. Grimes 	register int n;
1569b50d902SRodney W. Grimes 	char *p;
1579b50d902SRodney W. Grimes 	register FILE *ifp;
1589b50d902SRodney W. Grimes 
1599b50d902SRodney W. Grimes 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1609b50d902SRodney W. Grimes 		signal(SIGINT, onintr);
1619b50d902SRodney W. Grimes 
1629b50d902SRodney W. Grimes 	initkwds();
1639b50d902SRodney W. Grimes 
1641c8af878SWarner Losh 	while ((c = getopt(argc, argv, "tD:U:o:")) != -1)
1659b50d902SRodney W. Grimes 		switch(c) {
1669b50d902SRodney W. Grimes 
1679b50d902SRodney W. Grimes 		case 'D':               /* define something..*/
1689b50d902SRodney W. Grimes 			for (p = optarg; *p; p++)
1699b50d902SRodney W. Grimes 				if (*p == '=')
1709b50d902SRodney W. Grimes 					break;
1719b50d902SRodney W. Grimes 			if (*p)
1729b50d902SRodney W. Grimes 				*p++ = EOS;
1739b50d902SRodney W. Grimes 			dodefine(optarg, p);
1749b50d902SRodney W. Grimes 			break;
1759b50d902SRodney W. Grimes 		case 'U':               /* undefine...       */
1769b50d902SRodney W. Grimes 			remhash(optarg, TOP);
1779b50d902SRodney W. Grimes 			break;
1789b50d902SRodney W. Grimes 		case 'o':		/* specific output   */
1799b50d902SRodney W. Grimes 		case '?':
1809b50d902SRodney W. Grimes 			usage();
1819b50d902SRodney W. Grimes 		}
1829b50d902SRodney W. Grimes 
1839b50d902SRodney W. Grimes         argc -= optind;
1849b50d902SRodney W. Grimes         argv += optind;
1859b50d902SRodney W. Grimes 
1869b50d902SRodney W. Grimes 	active = stdout;		/* default active output     */
1879b50d902SRodney W. Grimes 					/* filename for diversions   */
1889b50d902SRodney W. Grimes 	m4temp = mktemp(xstrdup(_PATH_DIVNAME));
1899b50d902SRodney W. Grimes 
1909b50d902SRodney W. Grimes 	bbase[0] = bufbase;
1919b50d902SRodney W. Grimes         if (!argc) {
1929b50d902SRodney W. Grimes  		sp = -1;		/* stack pointer initialized */
1939b50d902SRodney W. Grimes 		fp = 0; 		/* frame pointer initialized */
1949b50d902SRodney W. Grimes 		infile[0] = stdin;	/* default input (naturally) */
1959b50d902SRodney W. Grimes 		macro();
1969b50d902SRodney W. Grimes 	} else
1979b50d902SRodney W. Grimes 		for (; argc--; ++argv) {
1989b50d902SRodney W. Grimes 			p = *argv;
1999b50d902SRodney W. Grimes 			if (p[0] == '-' && p[1] == '\0')
2009b50d902SRodney W. Grimes 				ifp = stdin;
2019b50d902SRodney W. Grimes 			else if ((ifp = fopen(p, "r")) == NULL)
20295105358SPhilippe Charnier 				err(1, "%s", p);
2039b50d902SRodney W. Grimes 			sp = -1;
2049b50d902SRodney W. Grimes 			fp = 0;
2059b50d902SRodney W. Grimes 			infile[0] = ifp;
2069b50d902SRodney W. Grimes 			macro();
2079b50d902SRodney W. Grimes 			if (ifp != stdin)
2089b50d902SRodney W. Grimes 				(void)fclose(ifp);
2099b50d902SRodney W. Grimes 		}
2109b50d902SRodney W. Grimes 
2119b50d902SRodney W. Grimes 	if (*m4wraps) { 		/* anything for rundown ??   */
2129b50d902SRodney W. Grimes 		ilevel = 0;		/* in case m4wrap includes.. */
2139b50d902SRodney W. Grimes 		bufbase = bp = buf;	/* use the entire buffer   */
2149b50d902SRodney W. Grimes 		putback(EOF);		/* eof is a must !!	     */
2159b50d902SRodney W. Grimes 		pbstr(m4wraps); 	/* user-defined wrapup act   */
2169b50d902SRodney W. Grimes 		macro();		/* last will and testament   */
2179b50d902SRodney W. Grimes 	}
2189b50d902SRodney W. Grimes 
2199b50d902SRodney W. Grimes 	if (active != stdout)
2209b50d902SRodney W. Grimes 		active = stdout;	/* reset output just in case */
2219b50d902SRodney W. Grimes 	for (n = 1; n < MAXOUT; n++)	/* default wrap-up: undivert */
2229b50d902SRodney W. Grimes 		if (outfile[n] != NULL)
2239b50d902SRodney W. Grimes 			getdiv(n);
2249b50d902SRodney W. Grimes 					/* remove bitbucket if used  */
2259b50d902SRodney W. Grimes 	if (outfile[0] != NULL) {
2269b50d902SRodney W. Grimes 		(void) fclose(outfile[0]);
2279b50d902SRodney W. Grimes 		m4temp[UNIQUE] = '0';
2289b50d902SRodney W. Grimes #ifdef vms
2299b50d902SRodney W. Grimes 		(void) remove(m4temp);
2309b50d902SRodney W. Grimes #else
2319b50d902SRodney W. Grimes 		(void) unlink(m4temp);
2329b50d902SRodney W. Grimes #endif
2339b50d902SRodney W. Grimes 	}
2349b50d902SRodney W. Grimes 
2359b50d902SRodney W. Grimes 	return 0;
2369b50d902SRodney W. Grimes }
2379b50d902SRodney W. Grimes 
2389b50d902SRodney W. Grimes ndptr inspect();
2399b50d902SRodney W. Grimes 
2409b50d902SRodney W. Grimes /*
2419b50d902SRodney W. Grimes  * macro - the work horse..
2429b50d902SRodney W. Grimes  */
2439b50d902SRodney W. Grimes void
2449b50d902SRodney W. Grimes macro() {
2459b50d902SRodney W. Grimes 	char token[MAXTOK];
2469b50d902SRodney W. Grimes 	register char *s;
2479b50d902SRodney W. Grimes 	register int t, l;
2489b50d902SRodney W. Grimes 	register ndptr p;
2499b50d902SRodney W. Grimes 	register int  nlpar;
2509b50d902SRodney W. Grimes 
2519b50d902SRodney W. Grimes 	cycle {
2527c5eeb39SAndrey A. Chernov 		if ((t = gpbc()) == '_' || (t != EOF && isalpha(t))) {
2539b50d902SRodney W. Grimes 			putback(t);
2549b50d902SRodney W. Grimes 			if ((p = inspect(s = token)) == nil) {
2559b50d902SRodney W. Grimes 				if (sp < 0)
2569b50d902SRodney W. Grimes 					while (*s)
2579b50d902SRodney W. Grimes 						putc(*s++, active);
2589b50d902SRodney W. Grimes 				else
2599b50d902SRodney W. Grimes 					while (*s)
2609b50d902SRodney W. Grimes 						chrsave(*s++);
2619b50d902SRodney W. Grimes 			}
2629b50d902SRodney W. Grimes 			else {
2639b50d902SRodney W. Grimes 		/*
2649b50d902SRodney W. Grimes 		 * real thing.. First build a call frame:
2659b50d902SRodney W. Grimes 		 */
2669b50d902SRodney W. Grimes 				pushf(fp);	/* previous call frm */
2679b50d902SRodney W. Grimes 				pushf(p->type); /* type of the call  */
2689b50d902SRodney W. Grimes 				pushf(0);	/* parenthesis level */
2699b50d902SRodney W. Grimes 				fp = sp;	/* new frame pointer */
2709b50d902SRodney W. Grimes 		/*
2719b50d902SRodney W. Grimes 		 * now push the string arguments:
2729b50d902SRodney W. Grimes 		 */
2739b50d902SRodney W. Grimes 				pushs(p->defn);	      /* defn string */
2749b50d902SRodney W. Grimes 				pushs(p->name);	      /* macro name  */
2759b50d902SRodney W. Grimes 				pushs(ep);	      /* start next..*/
2769b50d902SRodney W. Grimes 
2779b50d902SRodney W. Grimes 				putback(l = gpbc());
2789b50d902SRodney W. Grimes 				if (l != LPAREN)  {   /* add bracks  */
2799b50d902SRodney W. Grimes 					putback(RPAREN);
2809b50d902SRodney W. Grimes 					putback(LPAREN);
2819b50d902SRodney W. Grimes 				}
2829b50d902SRodney W. Grimes 			}
2839b50d902SRodney W. Grimes 		}
2849b50d902SRodney W. Grimes 		else if (t == EOF) {
2859b50d902SRodney W. Grimes 			if (sp > -1)
28695105358SPhilippe Charnier 				errx(1, "unexpected end of input");
2879b50d902SRodney W. Grimes 			if (ilevel <= 0)
2889b50d902SRodney W. Grimes 				break;			/* all done thanks.. */
2899b50d902SRodney W. Grimes 			--ilevel;
2909b50d902SRodney W. Grimes 			(void) fclose(infile[ilevel+1]);
2919b50d902SRodney W. Grimes 			bufbase = bbase[ilevel];
2929b50d902SRodney W. Grimes 			continue;
2939b50d902SRodney W. Grimes 		}
2949b50d902SRodney W. Grimes 	/*
2959b50d902SRodney W. Grimes 	 * non-alpha single-char token seen..
2969b50d902SRodney W. Grimes 	 * [the order of else if .. stmts is important.]
2979b50d902SRodney W. Grimes 	 */
2989b50d902SRodney W. Grimes 		else if (t == lquote) { 		/* strip quotes */
2999b50d902SRodney W. Grimes 			nlpar = 1;
3009b50d902SRodney W. Grimes 			do {
3019b50d902SRodney W. Grimes 				if ((l = gpbc()) == rquote)
3029b50d902SRodney W. Grimes 					nlpar--;
3039b50d902SRodney W. Grimes 				else if (l == lquote)
3049b50d902SRodney W. Grimes 					nlpar++;
3059b50d902SRodney W. Grimes 				else if (l == EOF)
30695105358SPhilippe Charnier 					errx(1, "missing right quote");
3079b50d902SRodney W. Grimes 				if (nlpar > 0) {
3089b50d902SRodney W. Grimes 					if (sp < 0)
3099b50d902SRodney W. Grimes 						putc(l, active);
3109b50d902SRodney W. Grimes 					else
3119b50d902SRodney W. Grimes 						chrsave(l);
3129b50d902SRodney W. Grimes 				}
3139b50d902SRodney W. Grimes 			}
3149b50d902SRodney W. Grimes 			while (nlpar != 0);
3159b50d902SRodney W. Grimes 		}
3169b50d902SRodney W. Grimes 
3179b50d902SRodney W. Grimes 		else if (sp < 0) {		/* not in a macro at all */
3189b50d902SRodney W. Grimes 			if (t == scommt) {	/* comment handling here */
3199b50d902SRodney W. Grimes 				putc(t, active);
3209b50d902SRodney W. Grimes 				while ((t = gpbc()) != ecommt)
3219b50d902SRodney W. Grimes 					putc(t, active);
3229b50d902SRodney W. Grimes 			}
3239b50d902SRodney W. Grimes 			putc(t, active);	/* output directly..	 */
3249b50d902SRodney W. Grimes 		}
3259b50d902SRodney W. Grimes 
3269b50d902SRodney W. Grimes 		else switch(t) {
3279b50d902SRodney W. Grimes 
3289b50d902SRodney W. Grimes 		case LPAREN:
3299b50d902SRodney W. Grimes 			if (PARLEV > 0)
3309b50d902SRodney W. Grimes 				chrsave(t);
3317c5eeb39SAndrey A. Chernov 			while ((l = gpbc()) != EOF && isspace(l))
3329b50d902SRodney W. Grimes 				;		/* skip blank, tab, nl.. */
3339b50d902SRodney W. Grimes 			putback(l);
3349b50d902SRodney W. Grimes 			PARLEV++;
3359b50d902SRodney W. Grimes 			break;
3369b50d902SRodney W. Grimes 
3379b50d902SRodney W. Grimes 		case RPAREN:
3389b50d902SRodney W. Grimes 			if (--PARLEV > 0)
3399b50d902SRodney W. Grimes 				chrsave(t);
3409b50d902SRodney W. Grimes 			else {			/* end of argument list */
3419b50d902SRodney W. Grimes 				chrsave(EOS);
3429b50d902SRodney W. Grimes 
3439b50d902SRodney W. Grimes 				if (sp == STACKMAX)
34495105358SPhilippe Charnier 					errx(1, "internal stack overflow");
3459b50d902SRodney W. Grimes 
3469b50d902SRodney W. Grimes 				if (CALTYP == MACRTYPE)
3479b50d902SRodney W. Grimes 					expand((char **) mstack+fp+1, sp-fp);
3489b50d902SRodney W. Grimes 				else
3499b50d902SRodney W. Grimes 					eval((char **) mstack+fp+1, sp-fp, CALTYP);
3509b50d902SRodney W. Grimes 
3519b50d902SRodney W. Grimes 				ep = PREVEP;	/* flush strspace */
3529b50d902SRodney W. Grimes 				sp = PREVSP;	/* previous sp..  */
3539b50d902SRodney W. Grimes 				fp = PREVFP;	/* rewind stack...*/
3549b50d902SRodney W. Grimes 			}
3559b50d902SRodney W. Grimes 			break;
3569b50d902SRodney W. Grimes 
3579b50d902SRodney W. Grimes 		case COMMA:
3589b50d902SRodney W. Grimes 			if (PARLEV == 1) {
3599b50d902SRodney W. Grimes 				chrsave(EOS);		/* new argument   */
3607c5eeb39SAndrey A. Chernov 				while ((l = gpbc()) != EOF && isspace(l))
3619b50d902SRodney W. Grimes 					;
3629b50d902SRodney W. Grimes 				putback(l);
3639b50d902SRodney W. Grimes 				pushs(ep);
3649b50d902SRodney W. Grimes 			} else
3659b50d902SRodney W. Grimes 				chrsave(t);
3669b50d902SRodney W. Grimes 			break;
3679b50d902SRodney W. Grimes 
3689b50d902SRodney W. Grimes 		default:
3699b50d902SRodney W. Grimes 			chrsave(t);			/* stack the char */
3709b50d902SRodney W. Grimes 			break;
3719b50d902SRodney W. Grimes 		}
3729b50d902SRodney W. Grimes 	}
3739b50d902SRodney W. Grimes }
3749b50d902SRodney W. Grimes 
3759b50d902SRodney W. Grimes /*
3769b50d902SRodney W. Grimes  * build an input token..
3779b50d902SRodney W. Grimes  * consider only those starting with _ or A-Za-z. This is a
3789b50d902SRodney W. Grimes  * combo with lookup to speed things up.
3799b50d902SRodney W. Grimes  */
3809b50d902SRodney W. Grimes ndptr
3819b50d902SRodney W. Grimes inspect(tp)
3829b50d902SRodney W. Grimes register char *tp;
3839b50d902SRodney W. Grimes {
3847c5eeb39SAndrey A. Chernov 	register int c;
3859b50d902SRodney W. Grimes 	register char *name = tp;
3869b50d902SRodney W. Grimes 	register char *etp = tp+MAXTOK;
3879b50d902SRodney W. Grimes 	register ndptr p;
3889b50d902SRodney W. Grimes 	register unsigned long h = 0;
3899b50d902SRodney W. Grimes 
3907c5eeb39SAndrey A. Chernov 	while ((c = gpbc()) != EOF && (isalnum(c) || c == '_') && tp < etp)
3919b50d902SRodney W. Grimes 		h = (h << 5) + h + (*tp++ = c);
3929b50d902SRodney W. Grimes 	putback(c);
3939b50d902SRodney W. Grimes 	if (tp == etp)
39495105358SPhilippe Charnier 		errx(1, "token too long");
3959b50d902SRodney W. Grimes 
3969b50d902SRodney W. Grimes 	*tp = EOS;
3979b50d902SRodney W. Grimes 
3989b50d902SRodney W. Grimes 	for (p = hashtab[h%HASHSIZE]; p != nil; p = p->nxtptr)
3999b50d902SRodney W. Grimes 		if (STREQ(name, p->name))
4009b50d902SRodney W. Grimes 			break;
4019b50d902SRodney W. Grimes 	return p;
4029b50d902SRodney W. Grimes }
4039b50d902SRodney W. Grimes 
4049b50d902SRodney W. Grimes /*
4059b50d902SRodney W. Grimes  * initkwds - initialise m4 keywords as fast as possible.
4069b50d902SRodney W. Grimes  * This very similar to install, but without certain overheads,
4079b50d902SRodney W. Grimes  * such as calling lookup. Malloc is not used for storing the
4089b50d902SRodney W. Grimes  * keyword strings, since we simply use the static  pointers
4099b50d902SRodney W. Grimes  * within keywrds block.
4109b50d902SRodney W. Grimes  */
4119b50d902SRodney W. Grimes void
4129b50d902SRodney W. Grimes initkwds() {
4139b50d902SRodney W. Grimes 	register int i;
4149b50d902SRodney W. Grimes 	register int h;
4159b50d902SRodney W. Grimes 	register ndptr p;
4169b50d902SRodney W. Grimes 
4179b50d902SRodney W. Grimes 	for (i = 0; i < MAXKEYS; i++) {
4189b50d902SRodney W. Grimes 		h = hash(keywrds[i].knam);
4199b50d902SRodney W. Grimes 		p = (ndptr) xalloc(sizeof(struct ndblock));
4209b50d902SRodney W. Grimes 		p->nxtptr = hashtab[h];
4219b50d902SRodney W. Grimes 		hashtab[h] = p;
4229b50d902SRodney W. Grimes 		p->name = keywrds[i].knam;
4239b50d902SRodney W. Grimes 		p->defn = null;
4249b50d902SRodney W. Grimes 		p->type = keywrds[i].ktyp | STATIC;
4259b50d902SRodney W. Grimes 	}
4269b50d902SRodney W. Grimes }
427