/* * 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; } }
/*! \brief Apply the preconditoner. \copydoc Preconditioner::apply(X&,const Y&) */ virtual void apply (Domain& v, const Range& d) { Range& md = const_cast<Range&>(d); comm_.copyOwnerToAll(md,md); auto endrow=ilu_.end(); for ( auto row = ilu_.begin(); row != endrow; ++row ) { auto rhs(d[row.index()]); for ( auto col = row->begin(); col.index() < row.index(); ++col ) { col->mmv(v[col.index()],rhs); } v[row.index()] = rhs; } comm_.copyOwnerToAll(v, v); auto rendrow = ilu_.beforeBegin(); for( auto row = ilu_.beforeEnd(); row != rendrow; --row) { auto rhs(v[row.index()]); auto col = row->beforeEnd(); for( ; col.index() > row.index(); --col) { col->mmv(v[col.index()], rhs); } v[row.index()] = 0; col->umv(rhs, v[row.index()]); } comm_.copyOwnerToAll(v, v); v *= w_; }
void *incmem_debug(void *x, size_t ol, size_t nl, char *file, int line) { void *y = getmem_debug(nl, file, line); mmv(y, x, ol < nl ? ol : nl); freemem_debug(x, file, line); return y; }
char *sdup_debug(const char *src, char *file, int line) { size_t n = 1 + strlen(src); char *x = getmem_debug(n, file, line); mmv(x, src, n); return x; }
/* * This function creates a new char * and fills it with a copy of src */ char *(sdup)(const char *src) { size_t n = 1 + strlen(src); char *x = getmem(n); mmv(x, src, n); return x; }
static void *true_incmem(void *x, size_t old_size, size_t new_size) { void * y = realloc(x, new_size); if (y == 0) { y = malloc(new_size); if (y == 0) { fprintf(stderr, "ouch: malloc() failed\n"); die(); } mmv(y, x, old_size < new_size ? old_size : new_size); free(x); } return y; }
/* * This function duplicates a given hash table; the data is not copied */ struct HT *copyHT(struct HT *ht) { struct HT *nht = newHT(ht->nb_lists, ht->cmpdata, ht->hash, ht->deldata); struct hash_item *t; int i, j; for (i = 0; i < nht->nb_lists; i ++) { j = 0; t = ht->lists[i]; while (t) { t = t->next; j ++; } if (j != 0) { nht->lists[i] = getmem(j * sizeof(struct hash_item)); mmv(nht->lists[i], ht->lists[i], j * sizeof(struct hash_item)); } } return nht; }
/* * 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; } } }