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} |