diff options
Diffstat (limited to 'usr.bin/m4/main.c')
-rw-r--r-- | usr.bin/m4/main.c | 411 |
1 files changed, 192 insertions, 219 deletions
diff --git a/usr.bin/m4/main.c b/usr.bin/m4/main.c index f16b4df..28d075a 100644 --- a/usr.bin/m4/main.c +++ b/usr.bin/m4/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.53 2002/04/26 16:15:16 espie Exp $ */ +/* $OpenBSD: main.c,v 1.80 2011/09/27 07:24:02 espie Exp $ */ /* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */ /*- @@ -16,7 +16,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,73 +33,59 @@ * SUCH DAMAGE. */ -#ifndef lint -#if 0 -static char copyright[] = -"@(#) Copyright (c) 1989, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; -#else -#if 0 -static char rcsid[] = "$OpenBSD: main.c,v 1.53 2002/04/26 16:15:16 espie Exp $"; -#endif -#endif -#endif /* not lint */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - /* * main.c * Facility: m4 macro processor * by: oz */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); -#include <sys/types.h> #include <assert.h> #include <signal.h> +#include <err.h> #include <errno.h> #include <unistd.h> #include <stdio.h> #include <ctype.h> #include <string.h> #include <stddef.h> +#include <stdint.h> #include <stdlib.h> -#include <err.h> -#include <locale.h> +#include <ohash.h> #include "mdef.h" #include "stdd.h" #include "extern.h" #include "pathnames.h" -ndptr hashtab[HASHSIZE]; /* hash table for macros etc. */ -stae *mstack; /* stack of m4 machine */ -char *sstack; /* shadow stack, for string space extension */ +stae *mstack; /* stack of m4 machine */ +char *sstack; /* shadow stack, for string space extension */ static size_t STACKMAX; /* current maximum size of stack */ -int sp; /* current m4 stack pointer */ -int fp; /* m4 call frame pointer */ +int sp; /* current m4 stack pointer */ +int fp; /* m4 call frame pointer */ struct input_file infile[MAXINP];/* input file stack (0=stdin) */ -char *inname[MAXINP]; /* names of these input files */ -int inlineno[MAXINP]; /* current number in each input file */ FILE **outfile; /* diversion array(0=bitbucket)*/ int maxout; FILE *active; /* active output file pointer */ -int ilevel = 0; /* input file stack pointer */ -int oindex = 0; /* diversion index.. */ -char null[] = ""; /* as it says.. just a null.. */ -const char *m4wraps = ""; /* m4wrap string default.. */ +int ilevel = 0; /* input file stack pointer */ +int oindex = 0; /* diversion index.. */ +const char *null = ""; /* as it says.. just a null.. */ +char **m4wraps = NULL; /* m4wraps array. */ +int maxwraps = 0; /* size of m4wraps array */ +int wrapindex = 0; /* current offset in m4wraps */ char lquote[MAXCCHARS+1] = {LQUOTE}; /* left quote character (`) */ char rquote[MAXCCHARS+1] = {RQUOTE}; /* right quote character (') */ char scommt[MAXCCHARS+1] = {SCOMMT}; /* start character for comment */ char ecommt[MAXCCHARS+1] = {ECOMMT}; /* end character for comment */ -int synccpp; /* Line synchronisation for C preprocessor */ +int synch_lines = 0; /* line synchronisation for C preprocessor */ +int prefix_builtins = 0; /* -P option to prefix builtin keywords */ -static const struct keyblk keywrds[] = { /* m4 keywords to be installed */ +struct keyblk { + const char *knam; /* keyword name */ + int ktyp; /* keyword type */ +}; + +struct keyblk keywrds[] = { /* m4 keywords to be installed */ { "include", INCLTYPE }, { "sinclude", SINCTYPE }, { "define", DEFITYPE }, @@ -120,7 +106,7 @@ static const struct keyblk keywrds[] = { /* m4 keywords to be installed */ #ifdef EXTENDED { "paste", PASTTYPE }, { "spaste", SPASTYPE }, - /* Newer extensions, needed to handle gnu-m4 scripts */ + /* Newer extensions, needed to handle gnu-m4 scripts */ { "indir", INDIRTYPE}, { "builtin", BUILTINTYPE}, { "patsubst", PATSTYPE}, @@ -138,6 +124,7 @@ static const struct keyblk keywrds[] = { /* m4 keywords to be installed */ { "undivert", UNDVTYPE | NOARGS }, { "divnum", DIVNTYPE | NOARGS }, { "maketemp", MKTMTYPE }, + { "mkstemp", MKTMTYPE }, { "errprint", ERRPTYPE | NOARGS }, { "m4wrap", M4WRTYPE | NOARGS }, { "m4exit", EXITTYPE | NOARGS }, @@ -170,43 +157,41 @@ static void macro(void); static void initkwds(void); static ndptr inspect(int, char *); static int do_look_ahead(int, const char *); +static void reallyoutputstr(const char *); +static void reallyputchar(int); static void enlarge_stack(void); +int main(int, char *[]); + int main(int argc, char *argv[]) { int c; int n; - int rval; char *p; - setlocale(LC_ALL, ""); - - traceout = stderr; - if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); - initkwds(); + init_macros(); initspaces(); STACKMAX = INITSTACKMAX; - mstack = (stae *)xalloc(sizeof(stae) * STACKMAX); - sstack = (char *)xalloc(STACKMAX); + mstack = (stae *)xalloc(sizeof(stae) * STACKMAX, NULL); + sstack = (char *)xalloc(STACKMAX, NULL); maxout = 0; outfile = NULL; resizedivs(MAXOUT); - while ((c = getopt(argc, argv, "gst:d:D:U:o:I:")) != -1) + while ((c = getopt(argc, argv, "gst:d:D:U:o:I:P")) != -1) switch(c) { + case 'D': /* define something..*/ for (p = optarg; *p; p++) if (*p == '=') break; - if (p == optarg) - errx(1, "null variable cannot be defined"); if (*p) *p++ = EOS; dodefine(optarg, p); @@ -214,8 +199,11 @@ main(int argc, char *argv[]) case 'I': addtoincludepath(optarg); break; + case 'P': + prefix_builtins = 1; + break; case 'U': /* undefine... */ - remhash(optarg, TOP); + macro_popdef(optarg); break; case 'g': mimic_gnu = 1; @@ -224,7 +212,7 @@ main(int argc, char *argv[]) set_trace_flags(optarg); break; case 's': - synccpp = 1; + synch_lines = 1; break; case 't': mark_traced(optarg, 1); @@ -233,51 +221,55 @@ main(int argc, char *argv[]) trace_file(optarg); break; case '?': - default: usage(); } argc -= optind; argv += optind; - rval = 0; + initkwds(); + if (mimic_gnu) + setup_builtin("format", FORMATTYPE); + active = stdout; /* default active output */ bbase[0] = bufbase; if (!argc) { - sp = -1; /* stack pointer initialized */ - fp = 0; /* frame pointer initialized */ + sp = -1; /* stack pointer initialized */ + fp = 0; /* frame pointer initialized */ set_input(infile+0, stdin, "stdin"); /* default input (naturally) */ - if ((inname[0] = strdup("-")) == NULL) - err(1, NULL); - inlineno[0] = 1; - emitline(); macro(); } else for (; argc--; ++argv) { p = *argv; if (p[0] == '-' && p[1] == EOS) set_input(infile, stdin, "stdin"); - else if (fopen_trypath(infile, p) == NULL) { - warn("%s", p); - rval = 1; - continue; - } + else if (fopen_trypath(infile, p) == NULL) + err(1, "%s", p); sp = -1; fp = 0; - if ((inname[0] = strdup(p)) == NULL) - err(1, NULL); - inlineno[0] = 1; - emitline(); macro(); - release_input(infile); + release_input(infile); } - if (*m4wraps) { /* anything for rundown ?? */ + if (wrapindex) { + int i; + ilevel = 0; /* in case m4wrap includes.. */ bufbase = bp = buf; /* use the entire buffer */ - pbstr(m4wraps); /* user-defined wrapup act */ - macro(); /* last will and testament */ + if (mimic_gnu) { + while (wrapindex != 0) { + for (i = 0; i < wrapindex; i++) + pbstr(m4wraps[i]); + wrapindex =0; + macro(); + } + } else { + for (i = 0; i < wrapindex; i++) { + pbstr(m4wraps[i]); + macro(); + } + } } if (active != stdout) @@ -290,7 +282,7 @@ main(int argc, char *argv[]) (void) fclose(outfile[0]); } - exit(rval); + return 0; } /* @@ -310,17 +302,17 @@ do_look_ahead(int t, const char *token) for (i = 1; *++token; i++) { t = gpbc(); if (t == EOF || (unsigned char)t != (unsigned char)*token) { - putback(t); + pushback(t); while (--i) - putback(*--token); + pushback(*--token); return 0; } } return 1; } -#define LOOK_AHEAD(t, token) (t != EOF && \ - (unsigned char)(t)==(unsigned char)(token)[0] && \ +#define LOOK_AHEAD(t, token) (t != EOF && \ + (unsigned char)(t)==(unsigned char)(token)[0] && \ do_look_ahead(t,token)) /* @@ -336,61 +328,8 @@ macro(void) cycle { t = gpbc(); - if (t == '_' || isalpha(t)) { - p = inspect(t, token); - if (p != nil) - putback(l = gpbc()); - if (p == nil || (l != LPAREN && - (p->type & NEEDARGS) != 0)) - outputstr(token); - else { - /* - * real thing.. First build a call frame: - */ - pushf(fp); /* previous call frm */ - pushf(p->type); /* type of the call */ - pushf(0); /* parenthesis level */ - fp = sp; /* new frame pointer */ - /* - * now push the string arguments: - */ - pushs1(p->defn); /* defn string */ - pushs1(p->name); /* macro name */ - pushs(ep); /* start next..*/ - if (l != LPAREN && PARLEV == 0) { - /* no bracks */ - chrsave(EOS); - - if ((uintptr_t)sp == STACKMAX) - errx(1, "internal stack overflow"); - eval((const char **) mstack+fp+1, 2, - CALTYP); - - ep = PREVEP; /* flush strspace */ - sp = PREVSP; /* previous sp.. */ - fp = PREVFP; /* rewind stack...*/ - } - } - } else if (t == EOF) { - if (sp > -1) { - warnx( "unexpected end of input, unclosed parenthesis:"); - dump_stack(paren, PARLEV); - exit(1); - } - if (ilevel <= 0) - break; /* all done thanks.. */ - release_input(infile+ilevel--); - free(inname[ilevel+1]); - bufbase = bbase[ilevel]; - emitline(); - continue; - } - /* - * non-alpha token possibly seen.. - * [the order of else if .. stmts is important.] - */ - else if (LOOK_AHEAD(t,lquote)) { /* strip quotes */ + if (LOOK_AHEAD(t,lquote)) { /* strip quotes */ nlpar = 0; record(quotes, nlpar++); /* @@ -416,32 +355,77 @@ macro(void) } else { if (nlpar > 0) { if (sp < 0) - putc(l, active); + reallyputchar(l); else CHRSAVE(l); } } } while (nlpar != 0); - } - - else if (sp < 0 && LOOK_AHEAD(t, scommt)) { - fputs(scommt, active); + } else if (sp < 0 && LOOK_AHEAD(t, scommt)) { + reallyoutputstr(scommt); for(;;) { t = gpbc(); if (LOOK_AHEAD(t, ecommt)) { - fputs(ecommt, active); + reallyoutputstr(ecommt); break; } if (t == EOF) break; - putc(t, active); + reallyputchar(t); } - } + } else if (t == '_' || isalpha(t)) { + p = inspect(t, token); + if (p != NULL) + pushback(l = gpbc()); + if (p == NULL || (l != LPAREN && + (macro_getdef(p)->type & NEEDARGS) != 0)) + outputstr(token); + else { + /* + * real thing.. First build a call frame: + */ + pushf(fp); /* previous call frm */ + pushf(macro_getdef(p)->type); /* type of the call */ + pushf(is_traced(p)); + pushf(0); /* parenthesis level */ + fp = sp; /* new frame pointer */ + /* + * now push the string arguments: + */ + pushs1(macro_getdef(p)->defn); /* defn string */ + pushs1((char *)macro_name(p)); /* macro name */ + pushs(ep); /* start next..*/ + + if (l != LPAREN && PARLEV == 0) { + /* no bracks */ + chrsave(EOS); - else if (sp < 0) { /* not in a macro at all */ - putc(t, active); /* output directly.. */ + if (sp == (int)STACKMAX) + errx(1, "internal stack overflow"); + eval((const char **) mstack+fp+1, 2, + CALTYP, TRACESTATUS); + + ep = PREVEP; /* flush strspace */ + sp = PREVSP; /* previous sp.. */ + fp = PREVFP; /* rewind stack...*/ + } + } + } else if (t == EOF) { + if (sp > -1 && ilevel <= 0) { + warnx( "unexpected end of input, unclosed parenthesis:"); + dump_stack(paren, PARLEV); + exit(1); + } + if (ilevel <= 0) + break; /* all done thanks.. */ + release_input(infile+ilevel--); + emit_synchline(); + bufbase = bbase[ilevel]; + continue; + } else if (sp < 0) { /* not in a macro at all */ + reallyputchar(t); /* output directly.. */ } else switch(t) { @@ -449,9 +433,10 @@ macro(void) case LPAREN: if (PARLEV > 0) chrsave(t); - while (isspace(l = gpbc())) - ; /* skip blank, tab, nl.. */ - putback(l); + while (isspace(l = gpbc())) /* skip blank, tab, nl.. */ + if (PARLEV > 0) + chrsave(l); + pushback(l); record(paren, PARLEV++); break; @@ -461,11 +446,11 @@ macro(void) else { /* end of argument list */ chrsave(EOS); - if ((uintptr_t)sp == STACKMAX) + if (sp == (int)STACKMAX) errx(1, "internal stack overflow"); eval((const char **) mstack+fp+1, sp-fp, - CALTYP); + CALTYP, TRACESTATUS); ep = PREVEP; /* flush strspace */ sp = PREVSP; /* previous sp.. */ @@ -478,7 +463,7 @@ macro(void) chrsave(EOS); /* new argument */ while (isspace(l = gpbc())) ; - putback(l); + pushback(l); pushs(ep); } else chrsave(t); @@ -486,14 +471,14 @@ macro(void) default: if (LOOK_AHEAD(t, scommt)) { - char *pc; - for (pc = scommt; *pc; pc++) - chrsave(*pc); + char *cp; + for (cp = scommt; *cp; cp++) + chrsave(*cp); for(;;) { t = gpbc(); if (LOOK_AHEAD(t, ecommt)) { - for (pc = ecommt; *pc; pc++) - chrsave(*pc); + for (cp = ecommt; *cp; cp++) + chrsave(*cp); break; } if (t == EOF) @@ -514,17 +499,43 @@ void outputstr(const char *s) { if (sp < 0) - while (*s) - putc(*s++, active); + reallyoutputstr(s); else while (*s) CHRSAVE(*s++); } +void +reallyoutputstr(const char *s) +{ + if (synch_lines) { + while (*s) { + fputc(*s, active); + if (*s++ == '\n') { + infile[ilevel].synch_lineno++; + if (infile[ilevel].synch_lineno != + infile[ilevel].lineno) + do_emit_synchline(); + } + } + } else + fputs(s, active); +} + +void +reallyputchar(int c) +{ + putc(c, active); + if (synch_lines && c == '\n') { + infile[ilevel].synch_lineno++; + if (infile[ilevel].synch_lineno != infile[ilevel].lineno) + do_emit_synchline(); + } +} + /* * build an input token.. - * consider only those starting with _ or A-Za-z. This is a - * combo with lookup to speed things up. + * consider only those starting with _ or A-Za-z. */ static ndptr inspect(int c, char *tp) @@ -532,14 +543,13 @@ inspect(int c, char *tp) char *name = tp; char *etp = tp+MAXTOK; ndptr p; - unsigned int h; - h = *tp++ = c; + *tp++ = c; while ((isalnum(c = gpbc()) || c == '_') && tp < etp) - h = (h << 5) + h + (*tp++ = c); + *tp++ = c; if (c != EOF) - PUTBACK(c); + PUSHBACK(c); *tp = EOS; /* token is too long, it won't match anything, but it can still * be output. */ @@ -547,17 +557,19 @@ inspect(int c, char *tp) outputstr(name); while (isalnum(c = gpbc()) || c == '_') { if (sp < 0) - putc(c, active); + reallyputchar(c); else CHRSAVE(c); } *name = EOS; - return nil; + return NULL; } - for (p = hashtab[h % HASHSIZE]; p != nil; p = p->nxtptr) - if (h == p->hv && STREQ(name, p->name)) - break; + p = ohash_find(¯os, ohash_qlookupi(¯os, name, (const char **)&tp)); + if (p == NULL) + return NULL; + if (macro_getdef(p) == NULL) + return NULL; return p; } @@ -571,47 +583,17 @@ inspect(int c, char *tp) static void initkwds(void) { - size_t i; - unsigned int h; - ndptr p; + unsigned int type; + int i; - for (i = 0; i < MAXKEYS; i++) { - h = hash(keywrds[i].knam); - p = (ndptr) xalloc(sizeof(struct ndblock)); - p->nxtptr = hashtab[h % HASHSIZE]; - hashtab[h % HASHSIZE] = p; - p->name = xstrdup(keywrds[i].knam); - p->defn = null; - p->hv = h; - p->type = keywrds[i].ktyp & TYPEMASK; + for (i = 0; i < (int)MAXKEYS; i++) { + type = keywrds[i].ktyp & TYPEMASK; if ((keywrds[i].ktyp & NOARGS) == 0) - p->type |= NEEDARGS; + type |= NEEDARGS; + setup_builtin(keywrds[i].knam, type); } } -/* Look up a builtin type, even if overridden by the user */ -int -builtin_type(const char *key) -{ - int i; - - for (i = 0; i != MAXKEYS; i++) - if (STREQ(keywrds[i].knam, key)) - return keywrds[i].ktyp; - return -1; -} - -const char * -builtin_realname(int n) -{ - int i; - - for (i = 0; i != MAXKEYS; i++) - if (((keywrds[i].ktyp ^ n) & TYPEMASK) == 0) - return keywrds[i].knam; - return NULL; -} - static void record(struct position *t, int lev) { @@ -640,20 +622,11 @@ dump_stack(struct position *t, int lev) static void enlarge_stack(void) { - STACKMAX *= 2; - mstack = realloc(mstack, sizeof(stae) * STACKMAX); - sstack = realloc(sstack, STACKMAX); - if (mstack == NULL || sstack == NULL) - errx(1, "Evaluation stack overflow (%lu)", - (unsigned long)STACKMAX); -} - -/* Emit preprocessor #line directive if -s option used. */ -void -emitline(void) -{ - - if (synccpp) - fprintf(active, "#line %d \"%s\"\n", inlineno[ilevel], - inname[ilevel]); + STACKMAX += STACKMAX/2; + mstack = xrealloc(mstack, sizeof(stae) * STACKMAX, + "Evaluation stack overflow (%lu)", + (unsigned long)STACKMAX); + sstack = xrealloc(sstack, STACKMAX, + "Evaluation stack overflow (%lu)", + (unsigned long)STACKMAX); } |