void doprintfilename(struct input_file *f) { pbstr(rquote); pbstr(f->name); pbstr(lquote); }
void eprint(void) /* try to print context around error */ { char *p, *q; p = ep - 1; if (p > ebuf && *p == '\n') p--; for ( ; p >= ebuf && *p != '\n'; p--) ; while (*p == '\n') p++; fprintf(stderr, " context is\n\t"); for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--) ; for (; p < q; p++) if (isprint(*p)) putc(*p, stderr); fprintf(stderr, " >>> "); for (; p < ep; p++) if (isprint(*p)) putc(*p, stderr); fprintf(stderr, " <<< "); while (pb >= pbuf) putc(*pb--, stderr); fgets(ebuf, sizeof ebuf, curfile->fin); fprintf(stderr, "%s", ebuf); pbstr("\n.G2\n"); /* safety first */ ep = ebuf; }
void doregexp(const char *argv[], int argc) { int error; regex_t re; regmatch_t *pmatch; const char *source; if (argc <= 3) { warnx("Too few arguments to regexp"); return; } /* special gnu case */ if (argv[3][0] == '\0' && mimic_gnu) { if (argc == 4 || argv[4] == NULL) return; else pbstr(argv[4]); } source = mimic_gnu ? twiddle(argv[3]) : argv[3]; error = regcomp(&re, source, REG_EXTENDED|REG_NEWLINE); if (error != 0) exit_regerror(error, &re, source); pmatch = xreallocarray(NULL, re.re_nsub+1, sizeof(regmatch_t), NULL); if (argc == 4 || argv[4] == NULL) do_regexpindex(argv[2], &re, source, pmatch); else do_regexp(argv[2], &re, source, argv[4], pmatch); free(pmatch); regfree(&re); }
struct symtab *copythru(char *s) /* collect the macro name or body for thru */ { struct symtab *p; char *q, *addnewline(char *); p = lookup(s); if (p != NULL) { if (p->s_type == DEFNAME) { p->s_val.p = addnewline(p->s_val.p); return p; } else ERROR "%s used as define and name", s FATAL; } /* have to collect the definition */ pbstr(s); /* first char is the delimiter */ q = delimstr("thru body"); s = "nameless"; p = lookup(s); if (p != NULL) { if (p->s_val.p) free(p->s_val.p); p->s_val.p = q; } else { YYSTYPE u; u.p = q; p = makevar(tostring(s), DEFNAME, u); } p->s_val.p = addnewline(p->s_val.p); dprintf("installing %s as `%s'\n", s, p->s_val.p); return p; }
/* * dodefn - push back a quoted definition of * the given name. */ static void dodefn(const char *name) { struct macro_definition *p; if ((p = lookup_macro_definition(name)) != NULL) { if ((p->type & TYPEMASK) == MACRTYPE) { pbstr(rquote); pbstr(p->defn); pbstr(lquote); } else { pbstr(p->defn); pbstr(BUILTIN_MARKER); } } }
Obj *copythru(char *s) /* collect the macro name or body for thru */ { Obj *p; char *q; p = lookup(s, 0); if (p != NULL) { if (p->type == DEFNAME) { p->val = addnewline(p->val); return p; } else ERROR "%s used as define and name", s FATAL; } /* have to collect the definition */ pbstr(s); /* first char is the delimiter */ q = delimstr("thru body"); p = lookup("nameless", 1); if (p != NULL) if (p->val) free(p->val); p->type = DEFNAME; p->val = q; p->val = addnewline(p->val); dprintf("installing nameless as `%s'\n", p->val); return p; }
/* * dodefn - push back a quoted definition of * the given name. */ static void dodefn(const char *name) { ndptr p; const char *real; if ((p = lookup(name)) != nil) { if (p->defn != null) { pbstr(rquote); pbstr(p->defn); pbstr(lquote); } else if ((real = builtin_realname(p->type)) != NULL) { pbstr(real); pbstr(BUILTIN_MARKER); } } }
/* * showwrap * * Loop through the list of m4wrap strings. Call pbstr() so that the * string will be displayed, then delete the list entry and free the memory * allocated for it. */ static void showwrap() { struct Wrap *prev; while (wrapstart) { pbstr(wrapstart->wrapstr); free(wrapstart->wrapstr); prev = wrapstart; wrapstart = wrapstart->nxt; free(prev); } }
static void do_regexp(const char *string, regex_t *re, const char *replace, regmatch_t *pm) { int error; switch(error = regexec(re, string, re->re_nsub+1, pm, 0)) { case 0: add_replace(string, re, replace, pm); pbstr(getstring()); break; case REG_NOMATCH: break; default: exit_regerror(error, re); } }
void doesyscmd(const char *cmd) { int p[2]; pid_t pid, cpid; char *argv[4]; int cc; int status; /* Follow gnu m4 documentation: first flush buffers. */ fflush(NULL); argv[0] = "sh"; argv[1] = "-c"; argv[2] = (char *)cmd; argv[3] = NULL; /* Just set up standard output, share stderr and stdin with m4 */ if (pipe(p) == -1) err(1, "bad pipe"); switch(cpid = fork()) { case -1: err(1, "bad fork"); /* NOTREACHED */ case 0: (void) close(p[0]); (void) dup2(p[1], 1); (void) close(p[1]); execv(_PATH_BSHELL, argv); exit(1); default: /* Read result in two stages, since m4's buffer is * pushback-only. */ (void) close(p[1]); do { char result[BUFSIZE]; cc = read(p[0], result, sizeof result); if (cc > 0) addchars(result, cc); } while (cc > 0 || (cc == -1 && errno == EINTR)); (void) close(p[0]); while ((pid = wait(&status)) != cpid && pid >= 0) continue; pbstr(getstring()); } }
/* argv[2]: string * argv[3]: regexp * argv[4]: opt rep */ void dopatsubst(const char *argv[], int argc) { if (argc <= 3) { warnx("Too few arguments to patsubst"); return; } /* special case: empty regexp */ if (argv[3][0] == '\0') { const char *s; size_t len; if (argc > 4 && argv[4]) len = strlen(argv[4]); else len = 0; for (s = argv[2]; *s != '\0'; s++) { addchars(argv[4], len); addchar(*s); } } else { int error; regex_t re; regmatch_t *pmatch; int mode = REG_EXTENDED; const char *source; size_t l = strlen(argv[3]); if (!mimic_gnu || (argv[3][0] == '^') || (l > 0 && argv[3][l-1] == '$')) mode |= REG_NEWLINE; source = mimic_gnu ? twiddle(argv[3]) : argv[3]; error = regcomp(&re, source, mode); if (error != 0) exit_regerror(error, &re, source); pmatch = xreallocarray(NULL, re.re_nsub+1, sizeof(regmatch_t), NULL); do_subst(argv[2], &re, source, argc > 4 && argv[4] != NULL ? argv[4] : "", pmatch); free(pmatch); regfree(&re); } pbstr(getstring()); }
static wchar_t * inpmatch(wchar_t *s) { wchar_t *tp = token+1; while (*s) { *tp = getchr(); if (*tp++ != *s++) { *tp = EOS; pbstr(token+1); return (0); } } *tp = EOS; return (token); }
static void do_subst(const char *string, regex_t *re, const char *source, const char *replace, regmatch_t *pm) { int error; int flags = 0; const char *last_match = NULL; while ((error = regexec(re, string, re->re_nsub+1, pm, flags)) == 0) { if (pm[0].rm_eo != 0) { if (string[pm[0].rm_eo-1] == '\n') flags = 0; else flags = REG_NOTBOL; } /* NULL length matches are special... We use the `vi-mode' * rule: don't allow a NULL-match at the last match * position. */ if (pm[0].rm_so == pm[0].rm_eo && string + pm[0].rm_so == last_match) { if (*string == '\0') return; addchar(*string); if (*string++ == '\n') flags = 0; else flags = REG_NOTBOL; continue; } last_match = string + pm[0].rm_so; addchars(string, pm[0].rm_so); add_replace(string, re, replace, pm); string += pm[0].rm_eo; } if (error != REG_NOMATCH) exit_regerror(error, re, source); pbstr(string); }
static void expand(wchar_t **a1, int c) { wchar_t *dp; struct nlist *sp; sp = (struct nlist *)a1[-1]; if (sp->tflag || trace) { #if !defined(__lint) /* lint doesn't grok "%ws" */ int i; (void) fprintf(stderr, "Trace(%d): %ws", Cp-callst, a1[0]); #endif if (c > 0) { #if !defined(__lint) /* lint doesn't grok "%ws" */ (void) fprintf(stderr, "(%ws", chkbltin(a1[1])); for (i = 2; i <= c; ++i) (void) fprintf(stderr, ",%ws", chkbltin(a1[i])); #endif (void) fprintf(stderr, ")"); } (void) fprintf(stderr, "\n"); } dp = sp->def; for (; *dp; ++dp) { if (is_builtin(*dp)) { (*barray[builtin_idx(*dp)].bfunc)(a1, c); } else if (dp[1] == '$') { if (is_digit(*dp)) { int n; if ((n = *dp-'0') <= c) pbstr(a1[n]); ++dp; } else if (*dp == '#') { pbnum((long)c); ++dp; } else if (*dp == '*' || *dp == '@') { int i = c; wchar_t **a = a1; if (i > 0) for (;;) { if (*dp == '@') pbstr(rquote); pbstr(a[i--]); if (*dp == '@') pbstr(lquote); if (i <= 0) break; pbstr(L","); } ++dp; } else putbak(*dp); } else putbak(*dp); } }
/* * expand_macro - user-defined macro expansion */ void expand_macro(const char *argv[], int argc) { const char *t; const char *p; int n; int argno; t = argv[0]; /* defn string as a whole */ p = t; while (*p) p++; p--; /* last character of defn */ while (p > t) { if (*(p - 1) != ARGFLAG) PUSHBACK(*p); else { switch (*p) { case '#': pbnum(argc - 2); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if ((argno = *p - '0') < argc - 1) pbstr(argv[argno + 1]); break; case '*': if (argc > 2) { for (n = argc - 1; n > 2; n--) { pbstr(argv[n]); pushback(COMMA); } pbstr(argv[2]); } break; case '@': if (argc > 2) { for (n = argc - 1; n > 2; n--) { pbstr(rquote); pbstr(argv[n]); pbstr(lquote); pushback(COMMA); } pbstr(rquote); pbstr(argv[2]); pbstr(lquote); } break; default: PUSHBACK(*p); PUSHBACK('$'); break; } p--; } p--; } if (p == t) /* do last character */ PUSHBACK(*p); }
/* * expand_builtin - evaluate built-in macros. */ void expand_builtin(const char *argv[], int argc, int td) { int c, n; int ac; static int sysval = 0; #ifdef DEBUG printf("argc = %d\n", argc); for (n = 0; n < argc; n++) printf("argv[%d] = %s\n", n, argv[n]); fflush(stdout); #endif /* * if argc == 3 and argv[2] is null, then we * have macro-or-builtin() type call. We adjust * argc to avoid further checking.. */ /* we keep the initial value for those built-ins that differentiate * between builtin() and builtin. */ ac = argc; if (argc == 3 && !*(argv[2]) && !mimic_gnu) argc--; switch (td & TYPEMASK) { case DEFITYPE: if (argc > 2) dodefine(argv[2], (argc > 3) ? argv[3] : null); break; case PUSDTYPE: if (argc > 2) dopushdef(argv[2], (argc > 3) ? argv[3] : null); break; case DUMPTYPE: dodump(argv, argc); break; case TRACEONTYPE: dotrace(argv, argc, 1); break; case TRACEOFFTYPE: dotrace(argv, argc, 0); break; case EXPRTYPE: /* * doexpr - evaluate arithmetic * expression */ { int base = 10; int maxdigits = 0; const char *errstr; if (argc > 3) { base = strtonum(argv[3], 2, 36, &errstr); if (errstr) { m4errx(1, "expr: base %s invalid.", argv[3]); } } if (argc > 4) { maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr); if (errstr) { m4errx(1, "expr: maxdigits %s invalid.", argv[4]); } } if (argc > 2) pbnumbase(expr(argv[2]), base, maxdigits); break; } case IFELTYPE: if (argc > 4) doifelse(argv, argc); break; case IFDFTYPE: /* * doifdef - select one of two * alternatives based on the existence of * another definition */ if (argc > 3) { if (lookup_macro_definition(argv[2]) != NULL) pbstr(argv[3]); else if (argc > 4) pbstr(argv[4]); } break; case LENGTYPE: /* * dolen - find the length of the * argument */ pbnum((argc > 2) ? strlen(argv[2]) : 0); break; case INCRTYPE: /* * doincr - increment the value of the * argument */ if (argc > 2) pbnum(atoi(argv[2]) + 1); break; case DECRTYPE: /* * dodecr - decrement the value of the * argument */ if (argc > 2) pbnum(atoi(argv[2]) - 1); break; case SYSCTYPE: /* * dosys - execute system command */ if (argc > 2) { fflush(stdout); sysval = system(argv[2]); } break; case SYSVTYPE: /* * dosysval - return value of the last * system call. * */ pbnum(sysval); break; case ESYSCMDTYPE: if (argc > 2) doesyscmd(argv[2]); break; case INCLTYPE: if (argc > 2) if (!doincl(argv[2])) { if (mimic_gnu) { warn("%s at line %lu: include(%s)", CURRENT_NAME, CURRENT_LINE, argv[2]); exit_code = 1; } else err(1, "%s at line %lu: include(%s)", CURRENT_NAME, CURRENT_LINE, argv[2]); } break; case SINCTYPE: if (argc > 2) (void) doincl(argv[2]); break; #ifdef EXTENDED case PASTTYPE: if (argc > 2) if (!dopaste(argv[2])) err(1, "%s at line %lu: paste(%s)", CURRENT_NAME, CURRENT_LINE, argv[2]); break; case SPASTYPE: if (argc > 2) (void) dopaste(argv[2]); break; case FORMATTYPE: doformat(argv, argc); break; #endif case CHNQTYPE: dochq(argv, ac); break; case CHNCTYPE: dochc(argv, argc); break; case SUBSTYPE: /* * dosub - select substring * */ if (argc > 3) dosub(argv, argc); break; case SHIFTYPE: /* * doshift - push back all arguments * except the first one (i.e. skip * argv[2]) */ if (argc > 3) { for (n = argc - 1; n > 3; n--) { pbstr(rquote); pbstr(argv[n]); pbstr(lquote); pushback(COMMA); } pbstr(rquote); pbstr(argv[3]); pbstr(lquote); } break; case DIVRTYPE: if (argc > 2 && (n = atoi(argv[2])) != 0) dodiv(n); else { active = stdout; oindex = 0; } break; case UNDVTYPE: doundiv(argv, argc); break; case DIVNTYPE: /* * dodivnum - return the number of * current output diversion */ pbnum(oindex); break; case UNDFTYPE: /* * doundefine - undefine a previously * defined macro(s) or m4 keyword(s). */ if (argc > 2) for (n = 2; n < argc; n++) macro_undefine(argv[n]); break; case POPDTYPE: /* * dopopdef - remove the topmost * definitions of macro(s) or m4 * keyword(s). */ if (argc > 2) for (n = 2; n < argc; n++) macro_popdef(argv[n]); break; case MKTMTYPE: /* * dotemp - create a temporary file */ if (argc > 2) { int fd; char *temp; temp = xstrdup(argv[2]); fd = mkstemp(temp); if (fd == -1) err(1, "%s at line %lu: couldn't make temp file %s", CURRENT_NAME, CURRENT_LINE, argv[2]); close(fd); pbstr(temp); free(temp); } break; case TRNLTYPE: /* * dotranslit - replace all characters in * the source string that appears in the * "from" string with the corresponding * characters in the "to" string. */ if (argc > 3) { char *temp; temp = xalloc(strlen(argv[2])+1, NULL); if (argc > 4) map(temp, argv[2], argv[3], argv[4]); else map(temp, argv[2], argv[3], null); pbstr(temp); free(temp); } else if (argc > 2) pbstr(argv[2]); break; case INDXTYPE: /* * doindex - find the index of the second * argument string in the first argument * string. -1 if not present. */ pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); break; case ERRPTYPE: /* * doerrp - print the arguments to stderr * file */ if (argc > 2) { for (n = 2; n < argc; n++) fprintf(stderr, "%s ", argv[n]); fprintf(stderr, "\n"); } break; case DNLNTYPE: /* * dodnl - eat-up-to and including * newline */ while ((c = gpbc()) != '\n' && c != EOF) ; break; case M4WRTYPE: /* * dom4wrap - set up for * wrap-up/wind-down activity */ if (argc > 2) dom4wrap(argv[2]); break; case EXITTYPE: /* * doexit - immediate exit from m4. */ killdiv(); exit((argc > 2) ? atoi(argv[2]) : 0); break; case DEFNTYPE: if (argc > 2) for (n = 2; n < argc; n++) dodefn(argv[n]); break; case INDIRTYPE: /* Indirect call */ if (argc > 2) doindir(argv, argc); break; case BUILTINTYPE: /* Builtins only */ if (argc > 2) dobuiltin(argv, argc); break; case PATSTYPE: if (argc > 2) dopatsubst(argv, argc); break; case REGEXPTYPE: if (argc > 2) doregexp(argv, argc); break; case LINETYPE: doprintlineno(infile+ilevel); break; case FILENAMETYPE: doprintfilename(infile+ilevel); break; case SELFTYPE: pbstr(rquote); pbstr(argv[1]); pbstr(lquote); break; default: m4errx(1, "eval: major botch."); break; } }
void doformat(const char *argv[], int argc) { const char *format = argv[2]; int pos = 3; int left_padded; long width; size_t l; const char *thisarg; char temp[2]; long extra; while (*format != 0) { if (*format != '%') { addchar(*format++); continue; } format++; if (*format == '%') { addchar(*format++); continue; } if (*format == 0) { addchar('%'); break; } if (*format == '*') { format++; if (pos >= argc) m4errx(1, "Format with too many format specifiers."); width = strtol(argv[pos++], NULL, 10); } else { width = strtol(format, (char **)&format, 10); } if (width < 0) { left_padded = 1; width = -width; } else { left_padded = 0; } if (*format == '.') { format++; if (*format == '*') { format++; if (pos >= argc) m4errx(1, "Format with too many format specifiers."); extra = strtol(argv[pos++], NULL, 10); } else { extra = strtol(format, (char **)&format, 10); } } else { extra = LONG_MAX; } if (pos >= argc) m4errx(1, "Format with too many format specifiers."); switch(*format) { case 's': thisarg = argv[pos++]; break; case 'c': temp[0] = strtoul(argv[pos++], NULL, 10); temp[1] = 0; thisarg = temp; break; default: m4errx(1, "Unsupported format specification: %s.", argv[2]); } format++; l = strlen(thisarg); if (l > extra) l = extra; if (!left_padded) { while (l < width--) addchar(' '); } addchars(thisarg, l); if (left_padded) { while (l < width--) addchar(' '); } } pbstr(getstring()); }
int yylex(void) { register int c; tbl *tp; extern tbl *keytbl[], *deftbl[]; beg: while ((c=gtc())==' ' || c=='\n') ; yylval.token = c; switch(c) { case EOF: return(EOF); case '~': return(SPACE); case '^': return(THIN); case '\t': return(TAB); case '{': return('{'); case '}': return('}'); case '"': for (sp=0; (c=gtc())!='"' && c != '\n'; ) { if (c == '\\') if ((c = gtc()) != '"') token[sp++] = '\\'; token[sp++] = c; if (sp>=SSIZE) error(FATAL, "quoted string %.20s... too long", token); } token[sp]='\0'; yylval.str = &token[0]; if (c == '\n') error(!FATAL, "missing \" in %.20s", token); return(QTEXT); } if (c==righteq) return(EOF); putbak(c); if (getstr(token, SSIZE)) return EOF; if (dbg)printf(".\tlex token = |%s|\n", token); if ((tp = lookup(deftbl, token, NULL)) != NULL) { putbak(' '); pbstr(tp->defn); putbak(' '); if (dbg) printf(".\tfound %s|=%s|\n", token, tp->defn); } else if ((tp = lookup(keytbl, token, NULL)) == NULL) { if(dbg)printf(".\t%s is not a keyword\n", token); return(CONTIG); } else if ((intptr_t)tp->defn == DEFINE || (intptr_t)tp->defn == NDEFINE || (intptr_t)tp->defn == TDEFINE) define((intptr_t)tp->defn); else if (tp->defn == (char *) DELIM) delim(); else if (tp->defn == (char *) GSIZE) globsize(); else if (tp->defn == (char *) GFONT) globfont(); else if (tp->defn == (char *) INCLUDE) include(); else if (tp->defn == (char *) SPACE) space(); else { return((intptr_t) tp->defn); } goto beg; }
int main(int argc, char **argv) { wchar_t t; int i, opt_end = 0; int sigs[] = {SIGHUP, SIGINT, SIGPIPE, 0}; #if defined(__lint) yydebug = 0; #endif for (i = 0; sigs[i]; ++i) { if (signal(sigs[i], SIG_IGN) != SIG_IGN) (void) signal(sigs[i], catchsig); } tempfile = mktemp(tmp_name); (void) close(creat(tempfile, 0)); (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); if ((mb_cur_max = MB_CUR_MAX) > 1) wide = 1; procnam = argv[0]; getflags(&argc, &argv, &opt_end); initalloc(); setfname("-"); if (argc > 1) { --argc; ++argv; if (strcmp(argv[0], "-")) { ifile[ifx] = m4open(&argv, "r", &argc); setfname(argv[0]); } } for (;;) { token[0] = t = getchr(); token[1] = EOS; if (t == WEOF) { if (ifx > 0) { (void) fclose(ifile[ifx]); ipflr = ipstk[--ifx]; continue; } getflags(&argc, &argv, &opt_end); if (argc <= 1) /* * If dowrap() has been called, the m4wrap * macro has been processed, and a linked * list of m4wrap strings has been created. * The list starts at wrapstart. */ if (wrapstart) { /* * Now that EOF has been processed, * display the m4wrap strings. */ showwrap(); continue; } else break; --argc; ++argv; if (ifile[ifx] != stdin) (void) fclose(ifile[ifx]); if (strcmp(argv[0], "-")) ifile[ifx] = m4open(&argv, "r", &argc); else ifile[ifx] = stdin; setfname(argv[0]); continue; } if (is_alpha(t) || t == '_') { wchar_t *tp = token+1; int tlim = toksize; struct nlist *macadd; /* temp variable */ while ((*tp = getchr()) != WEOF && (is_alnum(*tp) || *tp == '_')) { tp++; if (--tlim <= 0) error2(gettext( "more than %d chars in word"), toksize); } putbak(*tp); *tp = EOS; macadd = lookup(token); *Ap = (wchar_t *)macadd; if (macadd->def) { if ((wchar_t *)(++Ap) >= astklm) { --Ap; error2(gettext( "more than %d items on " "argument stack"), stksize); } if (Cp++ == NULL) Cp = callst; Cp->argp = Ap; *Ap++ = op; puttok(token); stkchr(EOS); t = getchr(); putbak(t); if (t != '(') pbstr(L"()"); else /* try to fix arg count */ *Ap++ = op; Cp->plev = 0; } else { puttok(token); } } else if (match(t, lquote)) { int qlev = 1; for (;;) { token[0] = t = getchr(); token[1] = EOS; if (match(t, rquote)) { if (--qlev > 0) puttok(token); else break; } else if (match(t, lquote)) { ++qlev; puttok(token); } else { if (t == WEOF) error(gettext( "EOF in quote")); putchr(t); } } } else if (match(t, lcom) && ((lcom[0] != L'#' || lcom[1] != L'\0') || prev_char != '$')) { /* * Don't expand commented macro (between lcom and * rcom). * What we know so far is that we have found the * left comment char (lcom). * Make sure we haven't found '#' (lcom) immediately * preceded by '$' because we want to expand "$#". */ puttok(token); for (;;) { token[0] = t = getchr(); token[1] = EOS; if (match(t, rcom)) { puttok(token); break; } else { if (t == WEOF) error(gettext( "EOF in comment")); putchr(t); } } } else if (Cp == NULL) { putchr(t); } else if (t == '(') { if (Cp->plev) stkchr(t); else { /* skip white before arg */ while ((t = getchr()) != WEOF && is_space(t)) ; putbak(t); } ++Cp->plev; } else if (t == ')') { --Cp->plev; if (Cp->plev == 0) { stkchr(EOS); expand(Cp->argp, Ap-Cp->argp-1); op = *Cp->argp; Ap = Cp->argp-1; if (--Cp < callst) Cp = NULL; } else stkchr(t); } else if (t == ',' && Cp->plev <= 1) { stkchr(EOS); *Ap = op; if ((wchar_t *)(++Ap) >= astklm) { --Ap; error2(gettext( "more than %d items on argument stack"), stksize); } while ((t = getchr()) != WEOF && is_space(t)) ; putbak(t); } else { stkchr(t); } } if (Cp != NULL) error(gettext( "EOF in argument list")); delexit(exitstat, 1); return (0); }
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(); initspaces(); STACKMAX = INITSTACKMAX; mstack = (stae *)xalloc(sizeof(stae) * STACKMAX); sstack = (char *)xalloc(STACKMAX); maxout = 0; outfile = NULL; resizedivs(MAXOUT); while ((c = getopt(argc, argv, "gst:d:D:U:o:I:")) != -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); break; case 'I': addtoincludepath(optarg); break; case 'U': /* undefine... */ remhash(optarg, TOP); break; case 'g': mimic_gnu = 1; break; case 'd': set_trace_flags(optarg); break; case 's': synccpp = 1; break; case 't': mark_traced(optarg, 1); break; case 'o': trace_file(optarg); break; case '?': default: usage(); } argc -= optind; argv += optind; rval = 0; active = stdout; /* default active output */ bbase[0] = bufbase; if (!argc) { 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; } sp = -1; fp = 0; if ((inname[0] = strdup(p)) == NULL) err(1, NULL); inlineno[0] = 1; emitline(); macro(); release_input(infile); } if (*m4wraps) { /* anything for rundown ?? */ 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 (active != stdout) active = stdout; /* reset output just in case */ for (n = 1; n < maxout; n++) /* default wrap-up: undivert */ if (outfile[n] != NULL) getdiv(n); /* remove bitbucket if used */ if (outfile[0] != NULL) { (void) fclose(outfile[0]); } exit(rval); }
int main(int argc, char *argv[]) { int c; int n; char *p; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); init_macros(); initspaces(); STACKMAX = INITSTACKMAX; mstack = xreallocarray(NULL, STACKMAX, sizeof(stae), NULL); sstack = xalloc(STACKMAX, NULL); maxout = 0; outfile = NULL; resizedivs(MAXOUT); 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) *p++ = EOS; dodefine(optarg, p); break; case 'I': addtoincludepath(optarg); break; case 'P': prefix_builtins = 1; break; case 'U': /* undefine... */ macro_popdef(optarg); break; case 'g': mimic_gnu = 1; break; case 'd': set_trace_flags(optarg); break; case 's': synch_lines = 1; break; case 't': mark_traced(optarg, 1); break; case 'o': trace_file(optarg); break; case '?': usage(); } argc -= optind; argv += optind; 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 */ set_input(infile+0, stdin, "stdin"); /* default input (naturally) */ 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) err(1, "%s", p); sp = -1; fp = 0; macro(); release_input(infile); } if (wrapindex) { int i; ilevel = 0; /* in case m4wrap includes.. */ bufbase = bp = buf; /* use the entire buffer */ 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) active = stdout; /* reset output just in case */ for (n = 1; n < maxout; n++) /* default wrap-up: undivert */ if (outfile[n] != NULL) getdiv(n); /* remove bitbucket if used */ if (outfile[0] != NULL) { (void) fclose(outfile[0]); } return exit_code; }
yylex(void) { register int c; tbl *tp; begin: while ((c = input()) == ' ' || c == '\n' || c == '\t') ; yylval = c; switch (c) { case EOF: ERROR "unexpected end of input inside equation" WARNING; return(EOF); case '~': return(SPACE); case '^': return(THIN); /* case '\t': return(TAB); */ case '{': return('{'); case '}': return('}'); case '"': for (sp = 0; (c=input())!='"' && c != '\n'; ) { if (c == '\\') if ((c = input()) != '"') token[sp++] = '\\'; token[sp++] = c; if (sp >= SSIZE) ERROR "quoted string %.20s... too long", token FATAL; } token[sp] = '\0'; yylval = (int) &token[0]; if (c == '\n') ERROR "missing \" in %.20s", token WARNING; return(QTEXT); } if (!display && c == righteq) return(EOF); unput(c); getstr(token, SSIZE); dprintf(".\tlex token = |%s|\n", token); if ((tp = lookup(deftbl, token)) != NULL) { /* defined term */ c = input(); unput(c); if (c == '(') /* macro with args */ dodef(tp); else { /* no args */ unput(' '); pbstr(tp->cval); dprintf(".\tfound %s|=%s|\n", token, tp->cval); } goto begin; } if ((tp = lookup(keytbl, token)) == NULL) /* not a keyword */ return CONTIG; switch (tp->ival) { /* some kind of keyword */ case DEFINE: case TDEFINE: case NDEFINE: define(tp->ival); break; case IFDEF: ifdef(); break; case DELIM: delim(); break; case GSIZE: globsize(); break; case GFONT: globfont(); break; case INCLUDE: include(); break; case SPACE: space(); break; case DOTEQ: /* .EQ inside equation -- should warn if at bottom level */ break; case DOTEN: if (curfile == infile) return EOF; /* else ignore nested .EN */ break; default: return tp->ival; } goto begin; }