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