Deleted Added
full compact
main.c (94957) main.c (95060)
1/* $OpenBSD: main.c,v 1.52 2002/02/16 21:27:48 millert Exp $ */
2/* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */
3
1/*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ozan Yigit at York University.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 20 unchanged lines hidden (view full) ---

29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
4/*-
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Ozan Yigit at York University.
10 *
11 * Redistribution and use in source and binary forms, with or without

--- 20 unchanged lines hidden (view full) ---

32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
37#ifndef lint
38static const char copyright[] =
39"@(#) Copyright (c) 1989, 1993\n\
40 The Regents of the University of California. All rights reserved.\n";
41#endif /* not lint */
40#include <sys/cdefs.h>
41__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
42 The Regents of the University of California. All rights reserved.\n");
43__SCCSID("@(#)main.c 8.1 (Berkeley) 6/6/93");
44__RCSID_SOURCE("$OpenBSD: main.c,v 1.52 2002/02/16 21:27:48 millert Exp $");
45__FBSDID("$FreeBSD: head/usr.bin/m4/main.c 95060 2002-04-19 17:26:21Z jmallett $");
42
46
43#ifndef lint
44#if 0
45static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
46#endif
47static const char rcsid[] =
48 "$FreeBSD: head/usr.bin/m4/main.c 94957 2002-04-17 17:26:32Z jmallett $";
49#endif /* not lint */
50
51/*
52 * main.c
53 * Facility: m4 macro processor
54 * by: oz
55 */
56
57#include <sys/types.h>
47/*
48 * main.c
49 * Facility: m4 macro processor
50 * by: oz
51 */
52
53#include <sys/types.h>
58#include <ctype.h>
59#include <err.h>
54#include <assert.h>
60#include <signal.h>
55#include <signal.h>
56#include <errno.h>
57#include <unistd.h>
61#include <stdio.h>
58#include <stdio.h>
62#include <stdlib.h>
59#include <ctype.h>
63#include <string.h>
60#include <string.h>
64#include <unistd.h>
61#include <stddef.h>
62#include <stdlib.h>
63#include <err.h>
65#include "mdef.h"
66#include "stdd.h"
67#include "extern.h"
68#include "pathnames.h"
69
70ndptr hashtab[HASHSIZE]; /* hash table for macros etc. */
64#include "mdef.h"
65#include "stdd.h"
66#include "extern.h"
67#include "pathnames.h"
68
69ndptr hashtab[HASHSIZE]; /* hash table for macros etc. */
71unsigned char buf[BUFSIZE]; /* push-back buffer */
72unsigned char *bufbase = buf; /* the base for current ilevel */
73unsigned char *bbase[MAXINP]; /* the base for each ilevel */
74unsigned char *bp = buf; /* first available character */
75unsigned char *endpbb = buf+BUFSIZE; /* end of push-back buffer */
76stae mstack[STACKMAX+1]; /* stack of m4 machine */
77char strspace[STRSPMAX+1]; /* string space for evaluation */
78char *ep = strspace; /* first free char in strspace */
79char *endest= strspace+STRSPMAX;/* end of string space */
70stae *mstack; /* stack of m4 machine */
71char *sstack; /* shadow stack, for string space extension */
72static size_t STACKMAX; /* current maximum size of stack */
80int sp; /* current m4 stack pointer */
81int fp; /* m4 call frame pointer */
73int sp; /* current m4 stack pointer */
74int fp; /* m4 call frame pointer */
82FILE *infile[MAXINP]; /* input file stack (0=stdin) */
83char *inname[MAXINP]; /* names of these input files */
84int inlineno[MAXINP]; /* current number in each input*/
85FILE *outfile[MAXOUT]; /* diversion array(0=bitbucket)*/
75struct input_file infile[MAXINP];/* input file stack (0=stdin) */
76char *inname[MAXINP]; /* names of these input files */
77int inlineno[MAXINP]; /* current number in each input file */
78FILE **outfile; /* diversion array(0=bitbucket)*/
79int maxout;
86FILE *active; /* active output file pointer */
80FILE *active; /* active output file pointer */
87char *m4temp; /* filename for diversions */
88char *m4dir; /* directory for diversions */
89int ilevel = 0; /* input file stack pointer */
90int oindex = 0; /* diversion index.. */
91char *null = ""; /* as it says.. just a null.. */
92char *m4wraps = ""; /* m4wrap string default.. */
81int ilevel = 0; /* input file stack pointer */
82int oindex = 0; /* diversion index.. */
83char *null = ""; /* as it says.. just a null.. */
84char *m4wraps = ""; /* m4wrap string default.. */
93char lquote = LQUOTE; /* left quote character (`) */
94char rquote = RQUOTE; /* right quote character (') */
95char scommt = SCOMMT; /* start character for comment */
96char ecommt = ECOMMT; /* end character for comment */
85char lquote[MAXCCHARS+1] = {LQUOTE}; /* left quote character (`) */
86char rquote[MAXCCHARS+1] = {RQUOTE}; /* right quote character (') */
87char scommt[MAXCCHARS+1] = {SCOMMT}; /* start character for comment */
88char ecommt[MAXCCHARS+1] = {ECOMMT}; /* end character for comment */
97int synccpp; /* Line synchronisation for C preprocessor */
98int chscratch; /* Scratch space for gpbc() macro */
99
100struct keyblk keywrds[] = { /* m4 keywords to be installed */
89int synccpp; /* Line synchronisation for C preprocessor */
90int chscratch; /* Scratch space for gpbc() macro */
91
92struct keyblk keywrds[] = { /* m4 keywords to be installed */
101 "include", INCLTYPE,
102 "sinclude", SINCTYPE,
103 "define", DEFITYPE,
104 "defn", DEFNTYPE,
105 "divert", DIVRTYPE,
106 "expr", EXPRTYPE,
107 "eval", EXPRTYPE,
108 "substr", SUBSTYPE,
109 "ifelse", IFELTYPE,
110 "ifdef", IFDFTYPE,
111 "len", LENGTYPE,
112 "incr", INCRTYPE,
113 "decr", DECRTYPE,
114 "dnl", DNLNTYPE,
115 "changequote", CHNQTYPE,
116 "changecom", CHNCTYPE,
117 "index", INDXTYPE,
93 { "include", INCLTYPE },
94 { "sinclude", SINCTYPE },
95 { "define", DEFITYPE },
96 { "defn", DEFNTYPE },
97 { "divert", DIVRTYPE | NOARGS },
98 { "expr", EXPRTYPE },
99 { "eval", EXPRTYPE },
100 { "substr", SUBSTYPE },
101 { "ifelse", IFELTYPE },
102 { "ifdef", IFDFTYPE },
103 { "len", LENGTYPE },
104 { "incr", INCRTYPE },
105 { "decr", DECRTYPE },
106 { "dnl", DNLNTYPE | NOARGS },
107 { "changequote", CHNQTYPE | NOARGS },
108 { "changecom", CHNCTYPE | NOARGS },
109 { "index", INDXTYPE },
118#ifdef EXTENDED
110#ifdef EXTENDED
119 "paste", PASTTYPE,
120 "spaste", SPASTYPE,
111 { "paste", PASTTYPE },
112 { "spaste", SPASTYPE },
113 /* Newer extensions, needed to handle gnu-m4 scripts */
114 { "indir", INDIRTYPE},
115 { "builtin", BUILTINTYPE},
116 { "patsubst", PATSTYPE},
117 { "regexp", REGEXPTYPE},
118 { "esyscmd", ESYSCMDTYPE},
119 { "__file__", FILENAMETYPE | NOARGS},
120 { "__line__", LINETYPE | NOARGS},
121#endif
121#endif
122 "popdef", POPDTYPE,
123 "pushdef", PUSDTYPE,
124 "dumpdef", DUMPTYPE,
125 "shift", SHIFTYPE,
126 "translit", TRNLTYPE,
127 "undefine", UNDFTYPE,
128 "undivert", UNDVTYPE,
129 "divnum", DIVNTYPE,
130 "maketemp", MKTMTYPE,
131 "errprint", ERRPTYPE,
132 "m4wrap", M4WRTYPE,
133 "m4exit", EXITTYPE,
134 "syscmd", SYSCTYPE,
135 "sysval", SYSVTYPE,
122 { "popdef", POPDTYPE },
123 { "pushdef", PUSDTYPE },
124 { "dumpdef", DUMPTYPE | NOARGS },
125 { "shift", SHIFTYPE | NOARGS },
126 { "translit", TRNLTYPE },
127 { "undefine", UNDFTYPE },
128 { "undivert", UNDVTYPE | NOARGS },
129 { "divnum", DIVNTYPE | NOARGS },
130 { "maketemp", MKTMTYPE },
131 { "errprint", ERRPTYPE | NOARGS },
132 { "m4wrap", M4WRTYPE | NOARGS },
133 { "m4exit", EXITTYPE | NOARGS },
134 { "syscmd", SYSCTYPE },
135 { "sysval", SYSVTYPE | NOARGS },
136 { "traceon", TRACEONTYPE | NOARGS },
137 { "traceoff", TRACEOFFTYPE | NOARGS },
136
138
137#ifdef unix
138 "unix", MACRTYPE,
139#if defined(unix) || defined(__unix__)
140 { "unix", SELFTYPE | NOARGS },
139#else
140#ifdef vms
141#else
142#ifdef vms
141 "vms", MACRTYPE,
143 { "vms", SELFTYPE | NOARGS },
142#endif
143#endif
144};
145
146#define MAXKEYS (sizeof(keywrds)/sizeof(struct keyblk))
147
144#endif
145#endif
146};
147
148#define MAXKEYS (sizeof(keywrds)/sizeof(struct keyblk))
149
148void macro();
149void initkwds();
150extern int optind;
151extern char *optarg;
150
152
153#define MAXRECORD 50
154static struct position {
155 char *name;
156 unsigned long line;
157} quotes[MAXRECORD], paren[MAXRECORD];
158
159static void record(struct position *, int);
160static void dump_stack(struct position *, int);
161
162static void macro(void);
163static void initkwds(void);
164static ndptr inspect(int, char *);
165static int do_look_ahead(int, const char *);
166
167static void enlarge_stack(void);
168
169int main(int, char *[]);
170
151int
152main(argc,argv)
153 int argc;
154 char *argv[];
155{
171int
172main(argc,argv)
173 int argc;
174 char *argv[];
175{
156 register int c;
157 register int n;
176 int c;
177 int n;
158 char *p;
178 char *p;
159 register FILE *ifp;
160
179
180 traceout = stderr;
181
161 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
162 signal(SIGINT, onintr);
163
164 initkwds();
182 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
183 signal(SIGINT, onintr);
184
185 initkwds();
186 initspaces();
187 STACKMAX = INITSTACKMAX;
165
188
166 while ((c = getopt(argc, argv, "D:U:s")) != -1)
189 mstack = (stae *)xalloc(sizeof(stae) * STACKMAX);
190 sstack = (char *)xalloc(STACKMAX);
191
192 maxout = 0;
193 outfile = NULL;
194 resizedivs(MAXOUT);
195
196 while ((c = getopt(argc, argv, "gst:d:D:U:o:I:")) != -1)
167 switch(c) {
168
169 case 'D': /* define something..*/
170 for (p = optarg; *p; p++)
171 if (*p == '=')
172 break;
173 if (*p)
174 *p++ = EOS;
175 dodefine(optarg, p);
176 break;
197 switch(c) {
198
199 case 'D': /* define something..*/
200 for (p = optarg; *p; p++)
201 if (*p == '=')
202 break;
203 if (*p)
204 *p++ = EOS;
205 dodefine(optarg, p);
206 break;
207 case 'I':
208 addtoincludepath(optarg);
209 break;
177 case 'U': /* undefine... */
178 remhash(optarg, TOP);
179 break;
210 case 'U': /* undefine... */
211 remhash(optarg, TOP);
212 break;
213 case 'g':
214 mimic_gnu = 1;
215 break;
216 case 'd':
217 set_trace_flags(optarg);
218 break;
180 case 's':
181 synccpp = 1;
182 break;
219 case 's':
220 synccpp = 1;
221 break;
222 case 't':
223 mark_traced(optarg, 1);
224 break;
225 case 'o':
226 trace_file(optarg);
227 break;
183 case '?':
184 usage();
185 }
186
187 argc -= optind;
188 argv += optind;
189
190 active = stdout; /* default active output */
228 case '?':
229 usage();
230 }
231
232 argc -= optind;
233 argv += optind;
234
235 active = stdout; /* default active output */
191 if ((p = strdup(_PATH_DIVDIRNAME)) == NULL)
192 err(1, "strdup");
193
194 /* filename for diversions */
195 m4dir = mkdtemp(p);
196 err_set_exit(cleanup);
197 (void) asprintf(&m4temp, "%s/%s", m4dir, _PATH_DIVNAME);
198
199 bbase[0] = bufbase;
200 if (!argc) {
201 sp = -1; /* stack pointer initialized */
202 fp = 0; /* frame pointer initialized */
236 bbase[0] = bufbase;
237 if (!argc) {
238 sp = -1; /* stack pointer initialized */
239 fp = 0; /* frame pointer initialized */
203 infile[0] = stdin; /* default input (naturally) */
240 set_input(infile+0, stdin, "stdin");
241 /* default input (naturally) */
204 if ((inname[0] = strdup("-")) == NULL)
205 err(1, NULL);
206 inlineno[0] = 1;
207 emitline();
208 macro();
209 } else
210 for (; argc--; ++argv) {
211 p = *argv;
242 if ((inname[0] = strdup("-")) == NULL)
243 err(1, NULL);
244 inlineno[0] = 1;
245 emitline();
246 macro();
247 } else
248 for (; argc--; ++argv) {
249 p = *argv;
212 if (p[0] == '-' && p[1] == '\0')
213 ifp = stdin;
214 else if ((ifp = fopen(p, "r")) == NULL)
250 if (p[0] == '-' && p[1] == EOS)
251 set_input(infile, stdin, "stdin");
252 else if (fopen_trypath(infile, p) == NULL)
215 err(1, "%s", p);
216 sp = -1;
253 err(1, "%s", p);
254 sp = -1;
217 fp = 0;
218 infile[0] = ifp;
255 fp = 0;
219 if ((inname[0] = strdup(p)) == NULL)
220 err(1, NULL);
221 inlineno[0] = 1;
222 emitline();
223 macro();
256 if ((inname[0] = strdup(p)) == NULL)
257 err(1, NULL);
258 inlineno[0] = 1;
259 emitline();
260 macro();
224 if (ifp != stdin)
225 (void)fclose(ifp);
261 release_input(infile);
226 }
227
228 if (*m4wraps) { /* anything for rundown ?? */
229 ilevel = 0; /* in case m4wrap includes.. */
230 bufbase = bp = buf; /* use the entire buffer */
262 }
263
264 if (*m4wraps) { /* anything for rundown ?? */
265 ilevel = 0; /* in case m4wrap includes.. */
266 bufbase = bp = buf; /* use the entire buffer */
231 putback(EOF); /* eof is a must !! */
232 pbstr(m4wraps); /* user-defined wrapup act */
233 macro(); /* last will and testament */
234 }
235
236 if (active != stdout)
237 active = stdout; /* reset output just in case */
267 pbstr(m4wraps); /* user-defined wrapup act */
268 macro(); /* last will and testament */
269 }
270
271 if (active != stdout)
272 active = stdout; /* reset output just in case */
238 for (n = 1; n < MAXOUT; n++) /* default wrap-up: undivert */
273 for (n = 1; n < maxout; n++) /* default wrap-up: undivert */
239 if (outfile[n] != NULL)
240 getdiv(n);
241 /* remove bitbucket if used */
274 if (outfile[n] != NULL)
275 getdiv(n);
276 /* remove bitbucket if used */
242 cleanup(0);
277 if (outfile[0] != NULL) {
278 (void) fclose(outfile[0]);
279 }
280
243 return 0;
244}
245
281 return 0;
282}
283
246ndptr inspect();
284/*
285 * Look ahead for `token'.
286 * (on input `t == token[0]')
287 * Used for comment and quoting delimiters.
288 * Returns 1 if `token' present; copied to output.
289 * 0 if `token' not found; all characters pushed back
290 */
291static int
292do_look_ahead(t, token)
293 int t;
294 const char *token;
295{
296 int i;
247
297
298 assert((unsigned char)t == (unsigned char)token[0]);
299
300 for (i = 1; *++token; i++) {
301 t = gpbc();
302 if (t == EOF || (unsigned char)t != (unsigned char)*token) {
303 putback(t);
304 while (--i)
305 putback(*--token);
306 return 0;
307 }
308 }
309 return 1;
310}
311
312#define LOOK_AHEAD(t, token) (t != EOF && \
313 (unsigned char)(t)==(unsigned char)(token)[0] && \
314 do_look_ahead(t,token))
315
248/*
249 * macro - the work horse..
250 */
316/*
317 * macro - the work horse..
318 */
251void
252macro() {
253 char token[MAXTOK];
254 register char *s;
255 register int t, l;
256 register ndptr p;
257 register int nlpar;
319static void
320macro()
321{
322 char token[MAXTOK+1];
323 int t, l;
324 ndptr p;
325 int nlpar;
258
259 cycle {
326
327 cycle {
260 if ((t = gpbc()) == '_' || (t != EOF && isalpha(t))) {
261 putback(t);
262 if ((p = inspect(s = token)) == nil) {
263 if (sp < 0)
264 while (*s)
265 putc(*s++, active);
266 else
267 while (*s)
268 chrsave(*s++);
269 }
328 t = gpbc();
329 if (t == '_' || isalpha(t)) {
330 p = inspect(t, token);
331 if (p != nil)
332 putback(l = gpbc());
333 if (p == nil || (l != LPAREN &&
334 (p->type & NEEDARGS) != 0))
335 outputstr(token);
270 else {
271 /*
272 * real thing.. First build a call frame:
273 */
274 pushf(fp); /* previous call frm */
275 pushf(p->type); /* type of the call */
276 pushf(0); /* parenthesis level */
277 fp = sp; /* new frame pointer */
278 /*
279 * now push the string arguments:
280 */
336 else {
337 /*
338 * real thing.. First build a call frame:
339 */
340 pushf(fp); /* previous call frm */
341 pushf(p->type); /* type of the call */
342 pushf(0); /* parenthesis level */
343 fp = sp; /* new frame pointer */
344 /*
345 * now push the string arguments:
346 */
281 pushs(p->defn); /* defn string */
282 pushs(p->name); /* macro name */
283 pushs(ep); /* start next..*/
347 pushs1(p->defn); /* defn string */
348 pushs1(p->name); /* macro name */
349 pushs(ep); /* start next..*/
284
350
285 putback(l = gpbc());
286 if (l != LPAREN) { /* add bracks */
287 putback(RPAREN);
288 putback(LPAREN);
351 if (l != LPAREN && PARLEV == 0) {
352 /* no bracks */
353 chrsave(EOS);
354
355 if (sp == STACKMAX)
356 errx(1, "internal stack overflow");
357 eval((const char **) mstack+fp+1, 2,
358 CALTYP);
359
360 ep = PREVEP; /* flush strspace */
361 sp = PREVSP; /* previous sp.. */
362 fp = PREVFP; /* rewind stack...*/
289 }
290 }
363 }
364 }
291 }
292 else if (t == EOF) {
293 if (sp > -1)
294 errx(1, "unexpected end of input");
365 } else if (t == EOF) {
366 if (sp > -1) {
367 warnx( "unexpected end of input, unclosed parenthesis:");
368 dump_stack(paren, PARLEV);
369 exit(1);
370 }
295 if (ilevel <= 0)
296 break; /* all done thanks.. */
371 if (ilevel <= 0)
372 break; /* all done thanks.. */
297 --ilevel;
298 (void) fclose(infile[ilevel+1]);
373 release_input(infile+ilevel--);
299 free(inname[ilevel+1]);
300 bufbase = bbase[ilevel];
301 emitline();
302 continue;
303 }
304 /*
374 free(inname[ilevel+1]);
375 bufbase = bbase[ilevel];
376 emitline();
377 continue;
378 }
379 /*
305 * non-alpha single-char token seen..
380 * non-alpha token possibly seen..
306 * [the order of else if .. stmts is important.]
307 */
381 * [the order of else if .. stmts is important.]
382 */
308 else if (t == lquote) { /* strip quotes */
309 nlpar = 1;
383 else if (LOOK_AHEAD(t,lquote)) { /* strip quotes */
384 nlpar = 0;
385 record(quotes, nlpar++);
386 /*
387 * Opening quote: scan forward until matching
388 * closing quote has been found.
389 */
310 do {
390 do {
311 if ((l = gpbc()) == rquote)
312 nlpar--;
313 else if (l == lquote)
314 nlpar++;
315 else if (l == EOF)
316 errx(1, "missing right quote");
317 if (nlpar > 0) {
318 if (sp < 0)
319 putc(l, active);
391
392 l = gpbc();
393 if (LOOK_AHEAD(l,rquote)) {
394 if (--nlpar > 0)
395 outputstr(rquote);
396 } else if (LOOK_AHEAD(l,lquote)) {
397 record(quotes, nlpar++);
398 outputstr(lquote);
399 } else if (l == EOF) {
400 if (nlpar == 1)
401 warnx("unclosed quote:");
320 else
402 else
321 chrsave(l);
403 warnx("%d unclosed quotes:", nlpar);
404 dump_stack(quotes, nlpar);
405 exit(1);
406 } else {
407 if (nlpar > 0) {
408 if (sp < 0)
409 putc(l, active);
410 else
411 CHRSAVE(l);
412 }
322 }
323 }
324 while (nlpar != 0);
325 }
326
413 }
414 }
415 while (nlpar != 0);
416 }
417
327 else if (sp < 0) { /* not in a macro at all */
328 if (t == scommt) { /* comment handling here */
418 else if (sp < 0 && LOOK_AHEAD(t, scommt)) {
419 fputs(scommt, active);
420
421 for(;;) {
422 t = gpbc();
423 if (LOOK_AHEAD(t, ecommt)) {
424 fputs(ecommt, active);
425 break;
426 }
427 if (t == EOF)
428 break;
329 putc(t, active);
429 putc(t, active);
330 while ((t = gpbc()) != ecommt)
331 putc(t, active);
332 }
430 }
431 }
432
433 else if (sp < 0) { /* not in a macro at all */
333 putc(t, active); /* output directly.. */
334 }
335
336 else switch(t) {
337
338 case LPAREN:
339 if (PARLEV > 0)
340 chrsave(t);
434 putc(t, active); /* output directly.. */
435 }
436
437 else switch(t) {
438
439 case LPAREN:
440 if (PARLEV > 0)
441 chrsave(t);
341 while ((l = gpbc()) != EOF && isspace(l))
442 while (isspace(l = gpbc()))
342 ; /* skip blank, tab, nl.. */
343 putback(l);
443 ; /* skip blank, tab, nl.. */
444 putback(l);
344 PARLEV++;
445 record(paren, PARLEV++);
345 break;
346
347 case RPAREN:
348 if (--PARLEV > 0)
349 chrsave(t);
350 else { /* end of argument list */
351 chrsave(EOS);
352
353 if (sp == STACKMAX)
354 errx(1, "internal stack overflow");
355
446 break;
447
448 case RPAREN:
449 if (--PARLEV > 0)
450 chrsave(t);
451 else { /* end of argument list */
452 chrsave(EOS);
453
454 if (sp == STACKMAX)
455 errx(1, "internal stack overflow");
456
356 if (CALTYP == MACRTYPE)
357 expand((char **) mstack+fp+1, sp-fp);
358 else
359 eval((char **) mstack+fp+1, sp-fp, CALTYP);
457 eval((const char **) mstack+fp+1, sp-fp,
458 CALTYP);
360
361 ep = PREVEP; /* flush strspace */
362 sp = PREVSP; /* previous sp.. */
363 fp = PREVFP; /* rewind stack...*/
364 }
365 break;
366
367 case COMMA:
368 if (PARLEV == 1) {
369 chrsave(EOS); /* new argument */
459
460 ep = PREVEP; /* flush strspace */
461 sp = PREVSP; /* previous sp.. */
462 fp = PREVFP; /* rewind stack...*/
463 }
464 break;
465
466 case COMMA:
467 if (PARLEV == 1) {
468 chrsave(EOS); /* new argument */
370 while ((l = gpbc()) != EOF && isspace(l))
469 while (isspace(l = gpbc()))
371 ;
372 putback(l);
373 pushs(ep);
374 } else
375 chrsave(t);
376 break;
377
378 default:
470 ;
471 putback(l);
472 pushs(ep);
473 } else
474 chrsave(t);
475 break;
476
477 default:
379 chrsave(t); /* stack the char */
478 if (LOOK_AHEAD(t, scommt)) {
479 char *p;
480 for (p = scommt; *p; p++)
481 chrsave(*p);
482 for(;;) {
483 t = gpbc();
484 if (LOOK_AHEAD(t, ecommt)) {
485 for (p = ecommt; *p; p++)
486 chrsave(*p);
487 break;
488 }
489 if (t == EOF)
490 break;
491 CHRSAVE(t);
492 }
493 } else
494 CHRSAVE(t); /* stack the char */
380 break;
381 }
382 }
383}
384
495 break;
496 }
497 }
498}
499
500/*
501 * output string directly, without pushing it for reparses.
502 */
503void
504outputstr(s)
505 const char *s;
506{
507 if (sp < 0)
508 while (*s)
509 putc(*s++, active);
510 else
511 while (*s)
512 CHRSAVE(*s++);
513}
514
385/*
386 * build an input token..
387 * consider only those starting with _ or A-Za-z. This is a
388 * combo with lookup to speed things up.
389 */
515/*
516 * build an input token..
517 * consider only those starting with _ or A-Za-z. This is a
518 * combo with lookup to speed things up.
519 */
390ndptr
391inspect(tp)
392register char *tp;
520static ndptr
521inspect(c, tp)
522 int c;
523 char *tp;
393{
524{
394 register int c;
395 register char *name = tp;
396 register char *etp = tp+MAXTOK;
397 register ndptr p;
398 register unsigned long h = 0;
525 char *name = tp;
526 char *etp = tp+MAXTOK;
527 ndptr p;
528 unsigned int h;
529
530 h = *tp++ = c;
399
531
400 while ((c = gpbc()) != EOF && (isalnum(c) || c == '_') && tp < etp)
532 while ((isalnum(c = gpbc()) || c == '_') && tp < etp)
401 h = (h << 5) + h + (*tp++ = c);
533 h = (h << 5) + h + (*tp++ = c);
402 putback(c);
403 if (tp == etp)
404 errx(1, "token too long");
405
534 if (c != EOF)
535 PUTBACK(c);
406 *tp = EOS;
536 *tp = EOS;
537 /* token is too long, it won't match anything, but it can still
538 * be output. */
539 if (tp == ep) {
540 outputstr(name);
541 while (isalnum(c = gpbc()) || c == '_') {
542 if (sp < 0)
543 putc(c, active);
544 else
545 CHRSAVE(c);
546 }
547 *name = EOS;
548 return nil;
549 }
407
550
408 for (p = hashtab[h%HASHSIZE]; p != nil; p = p->nxtptr)
409 if (STREQ(name, p->name))
551 for (p = hashtab[h % HASHSIZE]; p != nil; p = p->nxtptr)
552 if (h == p->hv && STREQ(name, p->name))
410 break;
411 return p;
412}
413
414/*
553 break;
554 return p;
555}
556
557/*
415 * initkwds - initialise m4 keywords as fast as possible.
558 * initkwds - initialise m4 keywords as fast as possible.
416 * This very similar to install, but without certain overheads,
559 * This very similar to install, but without certain overheads,
417 * such as calling lookup. Malloc is not used for storing the
418 * keyword strings, since we simply use the static pointers
560 * such as calling lookup. Malloc is not used for storing the
561 * keyword strings, since we simply use the static pointers
419 * within keywrds block.
420 */
562 * within keywrds block.
563 */
421void
422initkwds() {
423 register int i;
424 register int h;
425 register ndptr p;
564static void
565initkwds()
566{
567 size_t i;
568 unsigned int h;
569 ndptr p;
426
427 for (i = 0; i < MAXKEYS; i++) {
428 h = hash(keywrds[i].knam);
570
571 for (i = 0; i < MAXKEYS; i++) {
572 h = hash(keywrds[i].knam);
429 if ((p = malloc(sizeof(struct ndblock))) == NULL)
430 err(1, "malloc");
431 p->nxtptr = hashtab[h];
432 hashtab[h] = p;
433 p->name = keywrds[i].knam;
573 p = (ndptr) xalloc(sizeof(struct ndblock));
574 p->nxtptr = hashtab[h % HASHSIZE];
575 hashtab[h % HASHSIZE] = p;
576 p->name = xstrdup(keywrds[i].knam);
434 p->defn = null;
577 p->defn = null;
435 p->type = keywrds[i].ktyp | STATIC;
578 p->hv = h;
579 p->type = keywrds[i].ktyp & TYPEMASK;
580 if ((keywrds[i].ktyp & NOARGS) == 0)
581 p->type |= NEEDARGS;
436 }
437}
438
582 }
583}
584
585/* Look up a builtin type, even if overridden by the user */
586int
587builtin_type(key)
588 const char *key;
589{
590 int i;
591
592 for (i = 0; i != MAXKEYS; i++)
593 if (STREQ(keywrds[i].knam, key))
594 return keywrds[i].ktyp;
595 return -1;
596}
597
598char *
599builtin_realname(n)
600 int n;
601{
602 int i;
603
604 for (i = 0; i != MAXKEYS; i++)
605 if (((keywrds[i].ktyp ^ n) & TYPEMASK) == 0)
606 return keywrds[i].knam;
607 return NULL;
608}
609
610static void
611record(t, lev)
612 struct position *t;
613 int lev;
614{
615 if (lev < MAXRECORD) {
616 t[lev].name = CURRENT_NAME;
617 t[lev].line = CURRENT_LINE;
618 }
619}
620
621static void
622dump_stack(t, lev)
623 struct position *t;
624 int lev;
625{
626 int i;
627
628 for (i = 0; i < lev; i++) {
629 if (i == MAXRECORD) {
630 fprintf(stderr, " ...\n");
631 break;
632 }
633 fprintf(stderr, " %s at line %lu\n",
634 t[i].name, t[i].line);
635 }
636}
637
638
639static void
640enlarge_stack()
641{
642 STACKMAX *= 2;
643 mstack = realloc(mstack, sizeof(stae) * STACKMAX);
644 sstack = realloc(sstack, STACKMAX);
645 if (mstack == NULL || sstack == NULL)
646 errx(1, "Evaluation stack overflow (%lu)",
647 (unsigned long)STACKMAX);
648}
649
439/* Emit preprocessor #line directive if -s option used. */
440void
441emitline(void)
442{
650/* Emit preprocessor #line directive if -s option used. */
651void
652emitline(void)
653{
654
443 if (synccpp)
444 fprintf(active, "#line %d \"%s\"\n", inlineno[ilevel],
655 if (synccpp)
656 fprintf(active, "#line %d \"%s\"\n", inlineno[ilevel],
445 inname[ilevel]);
657 inname[ilevel]);
446}
658}