static char *tag_function (int argc, char *argv[]) { if (argc >= 1) { MACRO *macro, *submacro; STREAM *stream; char buf[32]; int c; /* remove the macro */ remove_macro (macros_space[nmacros_space-1], argv[0]); /* create the new functional macro */ macro = new_macro (FUNCTIONAL_MACRO, strdup (argv[0]), NULL); /* create macros for the function */ for (c = 1; c < argc; c++) { sprintf (buf, "%d", c); submacro = new_macro (NORMAL_MACRO, strdup (argv[c]), strdup ("")); add_macro (macro->data, submacro, FALSE); } /* read the function stream */ stream = stopen (NULL, NULL); read_function_body (_i_stream, stream); macro->value = stbuffer (stream); if (!macro->value) macro->value = strdup (""); add_macro (macros_space[nmacros_space-1], macro, TRUE); } return NULL; }
/* * add the special macros to the macro table */ static void add_special_macros(void) { struct macro *m; HTT_put(¯os, new_macro(), "__LINE__"); HTT_put(¯os, new_macro(), "__FILE__"); HTT_put(¯os, new_macro(), "__DATE__"); HTT_put(¯os, new_macro(), "__TIME__"); HTT_put(¯os, new_macro(), "__STDC__"); m = new_macro(); m->narg = 1; m->arg = getmem(sizeof(char *)); m->arg[0] = sdup("foo"); HTT_put(¯os, m, "_Pragma"); if (c99_compliant) { m = new_macro(); m->cval.t = getmem(9); m->cval.t[0] = NUMBER; mmv(m->cval.t + 1, "199901L", 8); m->cval.length = 9; HTT_put(¯os, m, "__STDC_VERSION__"); } if (c99_hosted) { m = new_macro(); m->cval.t = getmem(3); m->cval.t[0] = NUMBER; mmv(m->cval.t + 1, "1", 2); m->cval.length = 3; } }
static char *tag_macro (int argc, char *argv[]) { if (argc >= 1) { if (argc >= 2) { char *value = process_text (argv[1]); MACRO *macro = get_macro (macros_space[0], argv[0]); /* modify macro */ if (macro) { modify_macro (macro, value); } /* new macro */ else { macro = new_macro (NORMAL_MACRO, strdup (argv[0]), value); add_macro (macros_space[0], macro, TRUE); } } else { /* remove macro */ remove_macro (macros_space[0], argv[0]); } } return NULL; }
static void handle_macro(char *s) { char *name; if (name = parse_identifier(&s)) { eol(s); new_macro(name,nodotneeded ?"endm":".endm"); myfree(name); } else syntax_error(10); /* identifier expected */ }
int insert_macro(const char *macroname, const char *macrodef, dbref player, struct macrotable **node) { struct macrotable *newmacro; newmacro = new_macro(macroname, macrodef, player); if (!(*node)) { *node = newmacro; return 1; } else return (grow_macro_tree((*node), newmacro)); }
static void handle_macro(char *s) { char *name; if (name = parse_identifier(&s)) { s = skip(s); if (ISEOL(s)) s = NULL; /* no named arguments */ new_macro(name,endm_dirlist,s); myfree(name); } else syntax_error(10); /* identifier expected */ }
static int process_macros(struct state *cur, struct block *info, const char *dummy, scconf_block *blk) { scconf_item *item; const char *name; for (item = blk->items; item; item = item->next) { name = item->key; if (item->type != SCCONF_ITEM_TYPE_VALUE) continue; #if 0 printf("Defining %s\n", name); #endif new_macro(cur->profile, name, item->value.list); } return 0; }
int macrochain(struct macrotable *lastnode, FILE * f) { char *line, *line2; struct macrotable *newmacro; if (!(line = file_line(f))) return 0; line2 = file_line(f); newmacro = (struct macrotable *) new_macro(line, line2, getref(f)); free(line); free(line2); if (!macrotop) macrotop = (struct macrotable *) newmacro; else { newmacro->left = lastnode; lastnode->right = newmacro; } return (1 + macrochain(newmacro, f)); }
/* * We found a #define directive; parse the end of the line, perform * sanity checks, store the new macro into the "macros" hash table. * * In case of a redefinition of a macro: we enforce the rule that a * macro should be redefined identically, including the spelling of * parameters. We emit an error on offending code; dura lex, sed lex. * After all, it is easy to avoid such problems, with a #undef directive. */ int handle_define(struct lexer_state *ls) { struct macro *m = 0, *n; struct token_fifo mv; int ltwws = 1, redef = 0; char *mname = 0; int narg; size_t nt; long l = ls->line; mv.art = mv.nt = 0; mv.t = NULL; /* find the next non-white token on the line, this should be the macro name */ while (!next_token(ls) && ls->ctok->type != NEWLINE) { if (ttMWS(ls->ctok->type)) continue; if (ls->ctok->type == NAME) mname = sdup(ls->ctok->name); break; } if (mname == 0) { error(l, "missing macro name"); return 1; } if (check_special_macro(mname)) { error(l, "trying to redefine the special macro %s", mname); goto warp_error; } /* * If a macro with this name was already defined: the K&R * states that the new macro should be identical to the old one * (with some arcane rule of equivalence of whitespace); otherwise, * redefining the macro is an error. Most preprocessors would * only emit a warning (or nothing at all) on an unidentical * redefinition. * * Since it is easy to avoid this error (with a #undef directive), * we choose to enforce the rule and emit an error. */ if ((n = HTT_get(¯os, mname)) != 0) { /* redefinition of a macro: we must check that we define it identical */ redef = 1; n->cval.rp = 0; freemem(mname); mname = 0; } if (!redef) { m = new_macro(); m->narg = -1; #define mval mv } if (next_token(ls)) goto define_end; /* * Check if the token immediately following the macro name is * a left parenthesis; if so, then this is a macro with arguments. * Collect their names and try to match the next parenthesis. */ if (ls->ctok->type == LPAR) { int i, j; int need_comma = 0, saw_mdots = 0; narg = 0; while (!next_token(ls)) { if (ls->ctok->type == NEWLINE) { error(l, "truncated macro definition"); goto define_error; } if (ls->ctok->type == COMMA) { if (saw_mdots) { error(l, "'...' must end the macro " "argument list"); goto warp_error; } if (!need_comma) { error(l, "void macro argument"); goto warp_error; } need_comma = 0; continue; } else if (ls->ctok->type == NAME) { if (saw_mdots) { error(l, "'...' must end the macro " "argument list"); goto warp_error; } if (need_comma) { error(l, "missing comma in " "macro argument list"); goto warp_error; } if (!redef) { aol(m->arg, narg, sdup(ls->ctok->name), 8); /* we must keep track of m->narg so that cleanup in case of error works. */ m->narg = narg; if (narg == 128 && (ls->flags & WARN_STANDARD)) warning(l, "more arguments to " "macro than the ISO " "limit (127)"); if (narg == 32767) { error(l, "too many arguments " "in macro definition " "(max 32766)"); goto warp_error; } } else { /* this is a redefinition of the macro; check equality between old and new definitions */ if (narg >= n->narg) goto redef_error; if (strcmp(ls->ctok->name, n->arg[narg ++])) goto redef_error; } need_comma = 1; continue; } else if ((ls->flags & MACRO_VAARG) && ls->ctok->type == MDOTS) { if (need_comma) { error(l, "missing comma before '...'"); goto warp_error; } if (redef && !n->vaarg) goto redef_error; if (!redef) m->vaarg = 1; saw_mdots = 1; need_comma = 1; continue; } else if (ls->ctok->type == RPAR) { if (narg > 0 && !need_comma) { error(l, "void macro argument"); goto warp_error; } if (redef && n->vaarg && !saw_mdots) goto redef_error; break; } else if (ttMWS(ls->ctok->type)) { continue; } error(l, "invalid macro argument"); goto warp_error; } if (!redef) { for (i = 1; i < narg; i ++) for (j = 0; j < i; j ++) if (!strcmp(m->arg[i], m->arg[j])) { error(l, "duplicate macro " "argument"); goto warp_error; } } if (!redef) m->narg = narg; } else { if (!ttWHI(ls->ctok->type) && (ls->flags & WARN_STANDARD)) warning(ls->line, "identifier not followed by " "whitespace in #define"); ls->flags |= READ_AGAIN; narg = 0; } if (redef) nt = 0; /* now, we have the arguments. Let's get the macro contents. */ while (!next_token(ls) && ls->ctok->type != NEWLINE) { struct token t; t.type = ls->ctok->type; if (ltwws && ttMWS(t.type)) continue; t.line = 0; if (t.type == NAME) { int i; if ((ls->flags & MACRO_VAARG) && !strcmp(ls->ctok->name, "__VA_ARGS__")) { if (redef) { if (!n->vaarg) goto redef_error; } else if (!m->vaarg) { error(l, "'__VA_ARGS__' is forbidden " "in macros with a fixed " "number of arguments"); goto warp_error; } t.type = MACROARG; t.line = redef ? n->narg : m->narg; } for (i = 0; i < narg; i ++) if (!strcmp(redef ? n->arg[i] : m->arg[i], ls->ctok->name)) { t.type = MACROARG; /* this is a hack: we store the argument number in the line field */ t.line = i; break; } } if (!redef && S_TOKEN(t.type)) t.name = sdup(ls->ctok->name); if (ttMWS(t.type)) { if (ltwws) continue; #ifdef SEMPER_FIDELIS t.type = OPT_NONE; #else t.type = NONE; #endif ltwws = 1; } else ltwws = 0; if (!redef) { /* we ensure that each macro token has a correct line number */ if (t.type != MACROARG) t.line = 1; aol(mval.t, mval.nt, t, TOKEN_LIST_MEMG); } else { int tt; if (n->cval.rp >= n->cval.length) { #ifdef SEMPER_FIDELIS if (t.type != OPT_NONE) goto redef_error; #else if (t.type != NONE) goto redef_error; #endif } else if (t.type != n->cval.t[n->cval.rp]) { goto redef_error; } else if (t.type == MACROARG) { unsigned anum = n->cval.t[n->cval.rp + 1]; if (anum >= 128U) anum = ((anum & 127U) << 8) | m->cval.t[n->cval.rp + 2]; if (anum != (unsigned)t.line) goto redef_error; } else if (S_TOKEN(t.type) && strcmp(ls->ctok->name, (char *)(n->cval.t + n->cval.rp + 1))) { goto redef_error; } tt = n->cval.t[n->cval.rp ++]; if (S_TOKEN(tt)) n->cval.rp += 1 + strlen((char *)(n->cval.t + n->cval.rp)); else if (tt == MACROARG) { if (n->cval.t[++ n->cval.rp] >= 128) n->cval.rp ++; } nt ++; } } if (redef) { if (n->cval.rp < n->cval.length) goto redef_error_2; return 0; } /* now we have the complete macro; perform some checks about the operators # and ##, and, if everything is ok, store the macro into the hash table */ define_end: #ifdef SEMPER_FIDELIS if (mval.nt && mval.t[mval.nt - 1].type == OPT_NONE) { #else if (mval.nt && mval.t[mval.nt - 1].type == NONE) { #endif mval.nt --; if (mval.nt == 0) freemem(mval.t); } if (mval.nt != 0) { /* some checks about the macro */ if (mval.t[0].type == DSHARP || mval.t[0].type == DIG_DSHARP || mval.t[mval.nt - 1].type == DSHARP || mval.t[mval.nt - 1].type == DIG_DSHARP) { error(l, "operator '##' may neither begin " "nor end a macro"); goto define_error; } if (m->narg >= 0) { size_t i; for (i = 0; i < mval.nt; i ++) if ((mval.t[i].type == SHARP || mval.t[i].type == DIG_SHARP) && (i == (mval.nt - 1) || (ttMWS(mval.t[i + 1].type) && (i == mval.nt - 2 || mval.t[i + 2].type != MACROARG)) || (!ttMWS(mval.t[i + 1].type) && mval.t[i + 1].type != MACROARG))) { error(l, "operator '#' not followed " "by a macro argument"); goto define_error; } } } { size_t i, l; for (i = 0, l = 0; i < mval.nt; i ++) { l ++; if (S_TOKEN(mval.t[i].type)) l += 1 + strlen(mval.t[i].name); else if (mval.t[i].type == MACROARG) { l ++; if (mval.t[i].line >= 128) l ++; } } m->cval.length = l; if (l) m->cval.t = getmem(l); for (i = 0, l = 0; i < mval.nt; i ++) { m->cval.t[l ++] = mval.t[i].type; if (S_TOKEN(mval.t[i].type)) { size_t x = 1 + strlen(mval.t[i].name); mmv(m->cval.t + l, mval.t[i].name, x); l += x; freemem(mval.t[i].name); } else if (mval.t[i].type == MACROARG) { unsigned anum = mval.t[i].line; if (anum >= 128) { m->cval.t[l ++] = 128 | (anum >> 8); m->cval.t[l ++] = anum & 0xFF; } else { m->cval.t[l ++] = anum; } } }