Home | History | Annotate | Line # | Download | only in m4
main.c revision 1.12
      1  1.12    cgd /*	$NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $	*/
      2   1.9    tls 
      3   1.8  glass /*-
      4   1.8  glass  * Copyright (c) 1989, 1993
      5   1.8  glass  *	The Regents of the University of California.  All rights reserved.
      6   1.8  glass  *
      7   1.8  glass  * This code is derived from software contributed to Berkeley by
      8   1.8  glass  * Ozan Yigit at York University.
      9   1.8  glass  *
     10   1.8  glass  * Redistribution and use in source and binary forms, with or without
     11   1.8  glass  * modification, are permitted provided that the following conditions
     12   1.8  glass  * are met:
     13   1.8  glass  * 1. Redistributions of source code must retain the above copyright
     14   1.8  glass  *    notice, this list of conditions and the following disclaimer.
     15   1.8  glass  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.8  glass  *    notice, this list of conditions and the following disclaimer in the
     17   1.8  glass  *    documentation and/or other materials provided with the distribution.
     18   1.8  glass  * 3. All advertising materials mentioning features or use of this software
     19   1.8  glass  *    must display the following acknowledgement:
     20   1.8  glass  *	This product includes software developed by the University of
     21   1.8  glass  *	California, Berkeley and its contributors.
     22   1.8  glass  * 4. Neither the name of the University nor the names of its contributors
     23   1.8  glass  *    may be used to endorse or promote products derived from this software
     24   1.8  glass  *    without specific prior written permission.
     25   1.8  glass  *
     26   1.8  glass  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27   1.8  glass  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28   1.8  glass  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29   1.8  glass  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30   1.8  glass  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31   1.8  glass  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32   1.8  glass  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33   1.8  glass  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34   1.8  glass  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35   1.8  glass  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36   1.8  glass  * SUCH DAMAGE.
     37   1.8  glass  */
     38   1.1    cgd 
     39   1.8  glass #ifndef lint
     40   1.8  glass static char copyright[] =
     41   1.8  glass "@(#) Copyright (c) 1989, 1993\n\
     42   1.8  glass 	The Regents of the University of California.  All rights reserved.\n";
     43   1.8  glass #endif /* not lint */
     44   1.8  glass 
     45   1.8  glass #ifndef lint
     46   1.9    tls #if 0
     47   1.8  glass static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/6/93";
     48   1.9    tls #else
     49  1.12    cgd static char rcsid[] = "$NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $";
     50   1.9    tls #endif
     51   1.8  glass #endif /* not lint */
     52   1.1    cgd 
     53   1.1    cgd /*
     54   1.8  glass  * main.c
     55   1.8  glass  * Facility: m4 macro processor
     56   1.8  glass  * by: oz
     57   1.1    cgd  */
     58   1.1    cgd 
     59   1.8  glass #include <sys/types.h>
     60   1.8  glass #include <signal.h>
     61   1.8  glass #include <errno.h>
     62   1.8  glass #include <unistd.h>
     63   1.8  glass #include <stdio.h>
     64   1.8  glass #include <ctype.h>
     65   1.8  glass #include <string.h>
     66   1.8  glass #include "mdef.h"
     67   1.8  glass #include "stdd.h"
     68   1.8  glass #include "extern.h"
     69   1.8  glass #include "pathnames.h"
     70   1.8  glass 
     71   1.8  glass ndptr hashtab[HASHSIZE];	/* hash table for macros etc.  */
     72   1.1    cgd char buf[BUFSIZE];		/* push-back buffer	       */
     73   1.8  glass char *bufbase = buf;		/* the base for current ilevel */
     74   1.8  glass char *bbase[MAXINP];		/* the base for each ilevel    */
     75   1.1    cgd char *bp = buf; 		/* first available character   */
     76   1.1    cgd char *endpbb = buf+BUFSIZE;	/* end of push-back buffer     */
     77   1.1    cgd stae mstack[STACKMAX+1]; 	/* stack of m4 machine         */
     78   1.1    cgd char strspace[STRSPMAX+1];	/* string space for evaluation */
     79   1.1    cgd char *ep = strspace;		/* first free char in strspace */
     80   1.1    cgd char *endest= strspace+STRSPMAX;/* end of string space	       */
     81   1.1    cgd int sp; 			/* current m4  stack pointer   */
     82   1.1    cgd int fp; 			/* m4 call frame pointer       */
     83   1.1    cgd FILE *infile[MAXINP];		/* input file stack (0=stdin)  */
     84   1.1    cgd FILE *outfile[MAXOUT];		/* diversion array(0=bitbucket)*/
     85   1.1    cgd FILE *active;			/* active output file pointer  */
     86   1.8  glass char *m4temp;			/* filename for diversions     */
     87   1.1    cgd int ilevel = 0; 		/* input file stack pointer    */
     88   1.1    cgd int oindex = 0; 		/* diversion index..	       */
     89   1.1    cgd char *null = "";                /* as it says.. just a null..  */
     90   1.1    cgd char *m4wraps = "";             /* m4wrap string default..     */
     91   1.8  glass char *progname;			/* name of this program        */
     92  1.11     pk char lquote[MAXCCHARS+1] = {LQUOTE};	/* left quote character  (`)   */
     93  1.11     pk char rquote[MAXCCHARS+1] = {RQUOTE};	/* right quote character (')   */
     94  1.11     pk char scommt[MAXCCHARS+1] = {SCOMMT};	/* start character for comment */
     95  1.11     pk char ecommt[MAXCCHARS+1] = {ECOMMT};	/* end character for comment   */
     96   1.2  glass 
     97   1.8  glass struct keyblk keywrds[] = {	/* m4 keywords to be installed */
     98   1.8  glass 	"include",      INCLTYPE,
     99   1.8  glass 	"sinclude",     SINCTYPE,
    100   1.8  glass 	"define",       DEFITYPE,
    101   1.8  glass 	"defn",         DEFNTYPE,
    102   1.8  glass 	"divert",       DIVRTYPE,
    103   1.8  glass 	"expr",         EXPRTYPE,
    104   1.8  glass 	"eval",         EXPRTYPE,
    105   1.8  glass 	"substr",       SUBSTYPE,
    106   1.8  glass 	"ifelse",       IFELTYPE,
    107   1.8  glass 	"ifdef",        IFDFTYPE,
    108   1.8  glass 	"len",          LENGTYPE,
    109   1.8  glass 	"incr",         INCRTYPE,
    110   1.8  glass 	"decr",         DECRTYPE,
    111   1.8  glass 	"dnl",          DNLNTYPE,
    112   1.8  glass 	"changequote",  CHNQTYPE,
    113   1.8  glass 	"changecom",    CHNCTYPE,
    114   1.8  glass 	"index",        INDXTYPE,
    115   1.8  glass #ifdef EXTENDED
    116   1.8  glass 	"paste",        PASTTYPE,
    117   1.8  glass 	"spaste",       SPASTYPE,
    118   1.8  glass #endif
    119   1.8  glass 	"popdef",       POPDTYPE,
    120   1.8  glass 	"pushdef",      PUSDTYPE,
    121   1.8  glass 	"dumpdef",      DUMPTYPE,
    122   1.8  glass 	"shift",        SHIFTYPE,
    123   1.8  glass 	"translit",     TRNLTYPE,
    124   1.8  glass 	"undefine",     UNDFTYPE,
    125   1.8  glass 	"undivert",     UNDVTYPE,
    126   1.8  glass 	"divnum",       DIVNTYPE,
    127   1.8  glass 	"maketemp",     MKTMTYPE,
    128   1.8  glass 	"errprint",     ERRPTYPE,
    129   1.8  glass 	"m4wrap",       M4WRTYPE,
    130   1.8  glass 	"m4exit",       EXITTYPE,
    131   1.8  glass 	"syscmd",       SYSCTYPE,
    132   1.8  glass 	"sysval",       SYSVTYPE,
    133   1.2  glass 
    134  1.10    cgd #if defined(unix) || defined(__NetBSD__)
    135   1.8  glass 	"unix",         MACRTYPE,
    136   1.2  glass #else
    137   1.8  glass #ifdef vms
    138   1.8  glass 	"vms",          MACRTYPE,
    139   1.1    cgd #endif
    140   1.1    cgd #endif
    141   1.8  glass };
    142   1.8  glass 
    143   1.8  glass #define MAXKEYS	(sizeof(keywrds)/sizeof(struct keyblk))
    144   1.1    cgd 
    145   1.8  glass extern int optind;
    146   1.8  glass extern char *optarg;
    147   1.1    cgd 
    148   1.8  glass void macro();
    149   1.8  glass void initkwds();
    150   1.8  glass extern int getopt();
    151   1.1    cgd 
    152   1.8  glass int
    153   1.8  glass main(argc,argv)
    154   1.8  glass 	int argc;
    155   1.8  glass 	char *argv[];
    156   1.8  glass {
    157   1.2  glass 	register int c;
    158   1.8  glass 	register int n;
    159   1.8  glass 	char *p;
    160   1.8  glass 	register FILE *ifp;
    161   1.8  glass 
    162   1.8  glass 	progname = basename(argv[0]);
    163   1.8  glass 
    164   1.8  glass 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
    165   1.8  glass 		signal(SIGINT, onintr);
    166   1.1    cgd 
    167   1.8  glass 	initkwds();
    168   1.1    cgd 
    169   1.8  glass 	while ((c = getopt(argc, argv, "tD:U:o:")) != EOF)
    170   1.8  glass 		switch(c) {
    171   1.1    cgd 
    172   1.8  glass 		case 'D':               /* define something..*/
    173   1.8  glass 			for (p = optarg; *p; p++)
    174   1.8  glass 				if (*p == '=')
    175   1.8  glass 					break;
    176   1.8  glass 			if (*p)
    177   1.8  glass 				*p++ = EOS;
    178   1.8  glass 			dodefine(optarg, p);
    179   1.8  glass 			break;
    180   1.8  glass 		case 'U':               /* undefine...       */
    181   1.8  glass 			remhash(optarg, TOP);
    182   1.8  glass 			break;
    183   1.8  glass 		case 'o':		/* specific output   */
    184   1.8  glass 		case '?':
    185   1.8  glass 			usage();
    186   1.2  glass 		}
    187   1.1    cgd 
    188   1.8  glass         argc -= optind;
    189   1.8  glass         argv += optind;
    190   1.2  glass 
    191   1.8  glass 	active = stdout;		/* default active output     */
    192   1.8  glass 					/* filename for diversions   */
    193   1.8  glass 	m4temp = mktemp(xstrdup(_PATH_DIVNAME));
    194   1.2  glass 
    195   1.8  glass 	bbase[0] = bufbase;
    196   1.8  glass         if (!argc) {
    197   1.8  glass  		sp = -1;		/* stack pointer initialized */
    198   1.8  glass 		fp = 0; 		/* frame pointer initialized */
    199   1.8  glass 		infile[0] = stdin;	/* default input (naturally) */
    200   1.8  glass 		macro();
    201   1.8  glass 	} else
    202   1.8  glass 		for (; argc--; ++argv) {
    203   1.8  glass 			p = *argv;
    204   1.8  glass 			if (p[0] == '-' && p[1] == '\0')
    205   1.8  glass 				ifp = stdin;
    206   1.8  glass 			else if ((ifp = fopen(p, "r")) == NULL)
    207   1.8  glass 				oops("%s: %s", p, strerror(errno));
    208   1.8  glass 			sp = -1;
    209   1.8  glass 			fp = 0;
    210   1.8  glass 			infile[0] = ifp;
    211   1.8  glass 			macro();
    212   1.8  glass 			if (ifp != stdin)
    213   1.8  glass 				(void)fclose(ifp);
    214   1.8  glass 		}
    215   1.2  glass 
    216   1.8  glass 	if (*m4wraps) { 		/* anything for rundown ??   */
    217   1.8  glass 		ilevel = 0;		/* in case m4wrap includes.. */
    218   1.8  glass 		bufbase = bp = buf;	/* use the entire buffer   */
    219   1.8  glass 		putback(EOF);		/* eof is a must !!	     */
    220   1.8  glass 		pbstr(m4wraps); 	/* user-defined wrapup act   */
    221   1.8  glass 		macro();		/* last will and testament   */
    222   1.8  glass 	}
    223   1.2  glass 
    224   1.8  glass 	if (active != stdout)
    225   1.8  glass 		active = stdout;	/* reset output just in case */
    226   1.8  glass 	for (n = 1; n < MAXOUT; n++)	/* default wrap-up: undivert */
    227   1.8  glass 		if (outfile[n] != NULL)
    228   1.8  glass 			getdiv(n);
    229   1.8  glass 					/* remove bitbucket if used  */
    230   1.8  glass 	if (outfile[0] != NULL) {
    231   1.8  glass 		(void) fclose(outfile[0]);
    232   1.8  glass 		m4temp[UNIQUE] = '0';
    233   1.8  glass #ifdef vms
    234   1.8  glass 		(void) remove(m4temp);
    235   1.8  glass #else
    236   1.8  glass 		(void) unlink(m4temp);
    237   1.2  glass #endif
    238   1.8  glass 	}
    239   1.8  glass 
    240   1.8  glass 	return 0;
    241   1.8  glass }
    242   1.2  glass 
    243   1.8  glass ndptr inspect();
    244   1.1    cgd 
    245   1.8  glass /*
    246  1.11     pk  * Look ahead (at most MAXCCHARS characters) for `token'.
    247  1.11     pk  * (on input `t == token[0]')
    248  1.11     pk  * Used for comment and quoting delimiters.
    249  1.11     pk  * Returns 1 if `token' present; copied to output.
    250  1.11     pk  *         0 if `token' not found; all characters pushed back
    251  1.11     pk  */
    252  1.11     pk int
    253  1.11     pk do_look_ahead(t, token)
    254  1.11     pk 	int	t;
    255  1.11     pk 	char	*token;
    256  1.11     pk {
    257  1.11     pk 	int i;
    258  1.11     pk 
    259  1.11     pk 	if (t != token[0])
    260  1.11     pk 		oops("internal error", "");
    261  1.11     pk 
    262  1.11     pk 	for (i = 1; *++token; i++) {
    263  1.11     pk 		t = gpbc();
    264  1.11     pk 		if (t == EOF || t != *token) {
    265  1.11     pk 			if (t != EOF)
    266  1.11     pk 				putback(t);
    267  1.11     pk 			while (--i)
    268  1.11     pk 				putback(*--token);
    269  1.11     pk 			return 0;
    270  1.11     pk 		}
    271  1.11     pk 	}
    272  1.11     pk 	return 1;
    273  1.11     pk }
    274  1.11     pk 
    275  1.11     pk #define LOOK_AHEAD(t, token) ((t)==(token)[0] && do_look_ahead(t,token))
    276  1.11     pk 
    277  1.11     pk /*
    278   1.8  glass  * macro - the work horse..
    279   1.8  glass  */
    280   1.8  glass void
    281   1.8  glass macro() {
    282  1.12    cgd 	char token[MAXTOK], chars[2];
    283   1.8  glass 	register char *s;
    284   1.8  glass 	register int t, l;
    285   1.8  glass 	register ndptr p;
    286   1.8  glass 	register int  nlpar;
    287   1.1    cgd 
    288   1.8  glass 	cycle {
    289  1.11     pk 		t = gpbc();
    290  1.11     pk 		if (t == '_' || isalpha(t)) {
    291   1.8  glass 			putback(t);
    292   1.8  glass 			if ((p = inspect(s = token)) == nil) {
    293   1.8  glass 				if (sp < 0)
    294   1.8  glass 					while (*s)
    295   1.8  glass 						putc(*s++, active);
    296   1.8  glass 				else
    297   1.8  glass 					while (*s)
    298   1.8  glass 						chrsave(*s++);
    299   1.8  glass 			}
    300   1.8  glass 			else {
    301   1.8  glass 		/*
    302   1.8  glass 		 * real thing.. First build a call frame:
    303   1.8  glass 		 */
    304   1.8  glass 				pushf(fp);	/* previous call frm */
    305   1.8  glass 				pushf(p->type); /* type of the call  */
    306   1.8  glass 				pushf(0);	/* parenthesis level */
    307   1.8  glass 				fp = sp;	/* new frame pointer */
    308   1.8  glass 		/*
    309   1.8  glass 		 * now push the string arguments:
    310   1.8  glass 		 */
    311   1.8  glass 				pushs(p->defn);	      /* defn string */
    312   1.8  glass 				pushs(p->name);	      /* macro name  */
    313   1.8  glass 				pushs(ep);	      /* start next..*/
    314   1.8  glass 
    315   1.8  glass 				putback(l = gpbc());
    316   1.8  glass 				if (l != LPAREN)  {   /* add bracks  */
    317   1.8  glass 					putback(RPAREN);
    318   1.8  glass 					putback(LPAREN);
    319   1.2  glass 				}
    320   1.8  glass 			}
    321   1.8  glass 		}
    322   1.8  glass 		else if (t == EOF) {
    323   1.8  glass 			if (sp > -1)
    324   1.8  glass 				oops("unexpected end of input", "");
    325   1.8  glass 			if (ilevel <= 0)
    326   1.8  glass 				break;			/* all done thanks.. */
    327   1.8  glass 			--ilevel;
    328   1.8  glass 			(void) fclose(infile[ilevel+1]);
    329   1.8  glass 			bufbase = bbase[ilevel];
    330   1.8  glass 			continue;
    331   1.8  glass 		}
    332   1.8  glass 	/*
    333  1.12    cgd 	 * non-alpha token possibly seen..
    334   1.8  glass 	 * [the order of else if .. stmts is important.]
    335   1.8  glass 	 */
    336  1.11     pk 		else if (LOOK_AHEAD(t,lquote)) {	/* strip quotes */
    337   1.8  glass 			nlpar = 1;
    338   1.8  glass 			do {
    339  1.12    cgd 
    340  1.11     pk 				l = gpbc();
    341  1.12    cgd 				if (LOOK_AHEAD(l,rquote)) {
    342   1.8  glass 					nlpar--;
    343  1.12    cgd 					s = rquote;
    344  1.12    cgd 				} else if (LOOK_AHEAD(l,lquote)) {
    345   1.8  glass 					nlpar++;
    346  1.12    cgd 					s = lquote;
    347  1.12    cgd 				} else if (l == EOF)
    348   1.8  glass 					oops("missing right quote", "");
    349  1.12    cgd 				else {
    350  1.12    cgd 					chars[0] = l;
    351  1.12    cgd 					chars[1] = '\0';
    352  1.12    cgd 					s = chars;
    353  1.12    cgd 				}
    354   1.8  glass 				if (nlpar > 0) {
    355   1.8  glass 					if (sp < 0)
    356  1.12    cgd 						while (*s)
    357  1.12    cgd 							putc(*s++, active);
    358   1.8  glass 					else
    359  1.12    cgd 						while (*s)
    360  1.12    cgd 							chrsave(*s++);
    361   1.2  glass 				}
    362   1.8  glass 			}
    363   1.8  glass 			while (nlpar != 0);
    364   1.8  glass 		}
    365   1.1    cgd 
    366  1.11     pk 		else if (sp < 0 && LOOK_AHEAD(t, scommt)) {
    367  1.11     pk 			int i;
    368  1.11     pk 			for (i = 0; i < MAXCCHARS && scommt[i]; i++)
    369  1.11     pk 				putc(scommt[i], active);
    370  1.11     pk 
    371  1.11     pk 			for(;;) {
    372  1.11     pk 				t = gpbc();
    373  1.11     pk 				if (LOOK_AHEAD(t, ecommt)) {
    374  1.11     pk 					for (i = 0; i < MAXCCHARS && ecommt[i];
    375  1.11     pk 					     i++)
    376  1.11     pk 						putc(ecommt[i], active);
    377  1.11     pk 					break;
    378  1.11     pk 				}
    379  1.11     pk 				if (t == EOF)
    380  1.11     pk 					break;
    381   1.8  glass 				putc(t, active);
    382   1.1    cgd 			}
    383  1.11     pk 		}
    384  1.11     pk 
    385  1.11     pk 		else if (sp < 0) {		/* not in a macro at all */
    386   1.8  glass 			putc(t, active);	/* output directly..	 */
    387   1.8  glass 		}
    388   1.1    cgd 
    389   1.8  glass 		else switch(t) {
    390   1.2  glass 
    391   1.8  glass 		case LPAREN:
    392   1.8  glass 			if (PARLEV > 0)
    393   1.8  glass 				chrsave(t);
    394   1.8  glass 			while (isspace(l = gpbc()))
    395   1.8  glass 				;		/* skip blank, tab, nl.. */
    396   1.8  glass 			putback(l);
    397   1.8  glass 			PARLEV++;
    398   1.8  glass 			break;
    399   1.1    cgd 
    400   1.8  glass 		case RPAREN:
    401   1.8  glass 			if (--PARLEV > 0)
    402   1.8  glass 				chrsave(t);
    403   1.8  glass 			else {			/* end of argument list */
    404   1.8  glass 				chrsave(EOS);
    405   1.8  glass 
    406   1.8  glass 				if (sp == STACKMAX)
    407   1.8  glass 					oops("internal stack overflow", "");
    408   1.8  glass 
    409   1.8  glass 				if (CALTYP == MACRTYPE)
    410   1.8  glass 					expand((char **) mstack+fp+1, sp-fp);
    411   1.8  glass 				else
    412   1.8  glass 					eval((char **) mstack+fp+1, sp-fp, CALTYP);
    413   1.8  glass 
    414   1.8  glass 				ep = PREVEP;	/* flush strspace */
    415   1.8  glass 				sp = PREVSP;	/* previous sp..  */
    416   1.8  glass 				fp = PREVFP;	/* rewind stack...*/
    417   1.8  glass 			}
    418   1.8  glass 			break;
    419   1.1    cgd 
    420   1.8  glass 		case COMMA:
    421   1.8  glass 			if (PARLEV == 1) {
    422   1.8  glass 				chrsave(EOS);		/* new argument   */
    423   1.8  glass 				while (isspace(l = gpbc()))
    424   1.8  glass 					;
    425   1.8  glass 				putback(l);
    426   1.8  glass 				pushs(ep);
    427   1.8  glass 			} else
    428   1.8  glass 				chrsave(t);
    429   1.8  glass 			break;
    430   1.2  glass 
    431   1.2  glass 		default:
    432   1.8  glass 			chrsave(t);			/* stack the char */
    433   1.8  glass 			break;
    434   1.8  glass 		}
    435   1.2  glass 	}
    436   1.8  glass }
    437   1.2  glass 
    438   1.8  glass /*
    439   1.8  glass  * build an input token..
    440   1.8  glass  * consider only those starting with _ or A-Za-z. This is a
    441   1.8  glass  * combo with lookup to speed things up.
    442   1.8  glass  */
    443   1.8  glass ndptr
    444   1.8  glass inspect(tp)
    445   1.8  glass register char *tp;
    446   1.8  glass {
    447   1.8  glass 	register char c;
    448   1.8  glass 	register char *name = tp;
    449   1.8  glass 	register char *etp = tp+MAXTOK;
    450   1.8  glass 	register ndptr p;
    451   1.8  glass 	register unsigned long h = 0;
    452   1.2  glass 
    453   1.8  glass 	while ((isalnum(c = gpbc()) || c == '_') && tp < etp)
    454   1.8  glass 		h = (h << 5) + h + (*tp++ = c);
    455   1.8  glass 	putback(c);
    456   1.8  glass 	if (tp == etp)
    457   1.8  glass 		oops("token too long", "");
    458   1.1    cgd 
    459   1.8  glass 	*tp = EOS;
    460   1.1    cgd 
    461   1.8  glass 	for (p = hashtab[h%HASHSIZE]; p != nil; p = p->nxtptr)
    462   1.8  glass 		if (STREQ(name, p->name))
    463   1.8  glass 			break;
    464   1.8  glass 	return p;
    465   1.8  glass }
    466   1.7    cgd 
    467   1.8  glass /*
    468   1.8  glass  * initkwds - initialise m4 keywords as fast as possible.
    469   1.8  glass  * This very similar to install, but without certain overheads,
    470   1.8  glass  * such as calling lookup. Malloc is not used for storing the
    471   1.8  glass  * keyword strings, since we simply use the static  pointers
    472   1.8  glass  * within keywrds block.
    473   1.8  glass  */
    474   1.8  glass void
    475   1.8  glass initkwds() {
    476   1.8  glass 	register int i;
    477   1.8  glass 	register int h;
    478   1.8  glass 	register ndptr p;
    479   1.1    cgd 
    480   1.8  glass 	for (i = 0; i < MAXKEYS; i++) {
    481   1.8  glass 		h = hash(keywrds[i].knam);
    482   1.8  glass 		p = (ndptr) xalloc(sizeof(struct ndblock));
    483   1.8  glass 		p->nxtptr = hashtab[h];
    484   1.8  glass 		hashtab[h] = p;
    485   1.8  glass 		p->name = keywrds[i].knam;
    486   1.8  glass 		p->defn = null;
    487   1.8  glass 		p->type = keywrds[i].ktyp | STATIC;
    488   1.1    cgd 	}
    489   1.8  glass }
    490