unsigned int ohash_qlookupi(struct ohash *h, const char *s, const char **e) { u_int32_t hv; hv = ohash_interval(s, e); return ohash_lookup_interval(h, s, *e, hv); }
GNode * Targ_FindNodei(const char *name, const char *ename, int flags) { uint32_t hv; hv = ohash_interval(name, &ename); return Targ_FindNodeih(name, ename, hv, flags); }
int main(int argc, char *argv[]) { uint32_t i; uint32_t v; uint32_t h; uint32_t slots; const char *errstr; const char *e; char **occupied; char **t; int tn; Init_Stats(); if (argc != 3) exit(1); tn = strtonum(argv[1], 1, INT_MAX, &errstr); if (errstr) exit(1); t = table[tn-1]; slots = strtonum(argv[2], 0, INT_MAX, &errstr); if (errstr) exit(1); if (slots) { occupied = calloc(slots, sizeof(char *)); if (!occupied) exit(1); } else occupied = NULL; printf("/* File created by generate %d %d, do not edit */\n", tn, slots); for (i = 0; t[i] != NULL; i++) { e = NULL; v = ohash_interval(t[i], &e); if (slots) { h = v % slots; if (occupied[h]) { fprintf(stderr, "Collision: %s / %s (%d)\n", occupied[h], t[i], h); exit(1); } occupied[h] = t[i]; } i++; printf("#define K_%s %u\n", t[i], v); } if (slots) printf("#define MAGICSLOTS%d %u\n", tn, slots); exit(0); }
static void set_magic_shell_variable() { const char *name = "SHELL"; const char *ename = NULL; uint32_t k; Var *v; k = ohash_interval(name, &ename); v = find_global_var_without_env(name, ename, k); var_set_value(v, _PATH_BSHELL); /* XXX the environment shall never affect it */ v->flags = VAR_SHELL | VAR_SEEN_ENV; }
struct LoopVar * Var_NewLoopVar(const char *name, const char *ename) { struct LoopVar *l; uint32_t k; l = emalloc(sizeof(struct LoopVar)); /* we obtain a new variable quickly, make a snapshot of its old * value, and make sure the environment cannot touch us. */ /* XXX: should we avoid dynamic variables ? */ k = ohash_interval(name, &ename); l->me = find_global_var_without_env(name, ename, k); l->old = *(l->me); l->me->flags = VAR_SEEN_ENV | VAR_DUMMY; return l; }
/* Variable lookup function: return idx for dynamic variable, or * GLOBAL_INDEX if name is not dynamic. Set up *pk for further use. */ static int classify_var(const char *name, const char **enamePtr, uint32_t *pk) { size_t len; *pk = ohash_interval(name, enamePtr); len = *enamePtr - name; /* substitute short version for long local name */ switch (*pk % MAGICSLOTS1) { /* MAGICSLOTS should be the */ case K_LONGALLSRC % MAGICSLOTS1:/* smallest constant yielding */ /* distinct case values */ if (*pk == K_LONGALLSRC && len == strlen(LONGALLSRC) && strncmp(name, LONGALLSRC, len) == 0) return ALLSRC_INDEX; break; case K_LONGARCHIVE % MAGICSLOTS1: if (*pk == K_LONGARCHIVE && len == strlen(LONGARCHIVE) && strncmp(name, LONGARCHIVE, len) == 0) return ARCHIVE_INDEX; break; case K_LONGIMPSRC % MAGICSLOTS1: if (*pk == K_LONGIMPSRC && len == strlen(LONGIMPSRC) && strncmp(name, LONGIMPSRC, len) == 0) return IMPSRC_INDEX; break; case K_LONGMEMBER % MAGICSLOTS1: if (*pk == K_LONGMEMBER && len == strlen(LONGMEMBER) && strncmp(name, LONGMEMBER, len) == 0) return MEMBER_INDEX; break; case K_LONGOODATE % MAGICSLOTS1: if (*pk == K_LONGOODATE && len == strlen(LONGOODATE) && strncmp(name, LONGOODATE, len) == 0) return OODATE_INDEX; break; case K_LONGPREFIX % MAGICSLOTS1: if (*pk == K_LONGPREFIX && len == strlen(LONGPREFIX) && strncmp(name, LONGPREFIX, len) == 0) return PREFIX_INDEX; break; case K_LONGTARGET % MAGICSLOTS1: if (*pk == K_LONGTARGET && len == strlen(LONGTARGET) && strncmp(name, LONGTARGET, len) == 0) return TARGET_INDEX; break; case K_TARGET % MAGICSLOTS1: if (name[0] == TARGET[0] && len == 1) return TARGET_INDEX; break; case K_OODATE % MAGICSLOTS1: if (name[0] == OODATE[0] && len == 1) return OODATE_INDEX; break; case K_ALLSRC % MAGICSLOTS1: if (name[0] == ALLSRC[0] && len == 1) return ALLSRC_INDEX; break; case K_IMPSRC % MAGICSLOTS1: if (name[0] == IMPSRC[0] && len == 1) return IMPSRC_INDEX; break; case K_PREFIX % MAGICSLOTS1: if (name[0] == PREFIX[0] && len == 1) return PREFIX_INDEX; break; case K_ARCHIVE % MAGICSLOTS1: if (name[0] == ARCHIVE[0] && len == 1) return ARCHIVE_INDEX; break; case K_MEMBER % MAGICSLOTS1: if (name[0] == MEMBER[0] && len == 1) return MEMBER_INDEX; break; case K_FTARGET % MAGICSLOTS1: if (name[0] == FTARGET[0] && name[1] == FTARGET[1] && len == 2) return FTARGET_INDEX; break; case K_DTARGET % MAGICSLOTS1: if (name[0] == DTARGET[0] && name[1] == DTARGET[1] && len == 2) return DTARGET_INDEX; break; case K_FPREFIX % MAGICSLOTS1: if (name[0] == FPREFIX[0] && name[1] == FPREFIX[1] && len == 2) return FPREFIX_INDEX; break; case K_DPREFIX % MAGICSLOTS1: if (name[0] == DPREFIX[0] && name[1] == DPREFIX[1] && len == 2) return DPREFIX_INDEX; break; case K_FARCHIVE % MAGICSLOTS1: if (name[0] == FARCHIVE[0] && name[1] == FARCHIVE[1] && len == 2) return FARCHIVE_INDEX; break; case K_DARCHIVE % MAGICSLOTS1: if (name[0] == DARCHIVE[0] && name[1] == DARCHIVE[1] && len == 2) return DARCHIVE_INDEX; break; case K_FMEMBER % MAGICSLOTS1: if (name[0] == FMEMBER[0] && name[1] == FMEMBER[1] && len == 2) return FMEMBER_INDEX; break; case K_DMEMBER % MAGICSLOTS1: if (name[0] == DMEMBER[0] && name[1] == DMEMBER[1] && len == 2) return DMEMBER_INDEX; break; default: break; } return GLOBAL_INDEX; }
/* Evaluate conditional in line. * returns COND_SKIP, COND_PARSE, COND_INVALID, COND_ISFOR, COND_ISINCLUDE, * COND_ISUNDEF. * A conditional line looks like this: * <cond-type> <expr> * where <cond-type> is any of if, ifmake, ifnmake, ifdef, * ifndef, elif, elifmake, elifnmake, elifdef, elifndef * and <expr> consists of &&, ||, !, make(target), defined(variable) * and parenthetical groupings thereof. */ int Cond_Eval(const char *line) { /* find end of keyword */ const char *end; uint32_t k; size_t len; struct If *ifp; bool value = false; int level; /* Level at which to report errors. */ level = PARSE_FATAL; for (end = line; islower(*end); end++) ; /* quick path: recognize special targets early on */ if (*end == '.' || *end == ':') return COND_INVALID; len = end - line; k = ohash_interval(line, &end); switch(k % MAGICSLOTS2) { case K_COND_IF % MAGICSLOTS2: if (k == K_COND_IF && len == strlen(COND_IF) && strncmp(line, COND_IF, len) == 0) { ifp = ifs + COND_IF_INDEX; } else return COND_INVALID; break; case K_COND_IFDEF % MAGICSLOTS2: if (k == K_COND_IFDEF && len == strlen(COND_IFDEF) && strncmp(line, COND_IFDEF, len) == 0) { ifp = ifs + COND_IFDEF_INDEX; } else return COND_INVALID; break; case K_COND_IFNDEF % MAGICSLOTS2: if (k == K_COND_IFNDEF && len == strlen(COND_IFNDEF) && strncmp(line, COND_IFNDEF, len) == 0) { ifp = ifs + COND_IFNDEF_INDEX; } else return COND_INVALID; break; case K_COND_IFMAKE % MAGICSLOTS2: if (k == K_COND_IFMAKE && len == strlen(COND_IFMAKE) && strncmp(line, COND_IFMAKE, len) == 0) { ifp = ifs + COND_IFMAKE_INDEX; } else return COND_INVALID; break; case K_COND_IFNMAKE % MAGICSLOTS2: if (k == K_COND_IFNMAKE && len == strlen(COND_IFNMAKE) && strncmp(line, COND_IFNMAKE, len) == 0) { ifp = ifs + COND_IFNMAKE_INDEX; } else return COND_INVALID; break; case K_COND_ELIF % MAGICSLOTS2: if (k == K_COND_ELIF && len == strlen(COND_ELIF) && strncmp(line, COND_ELIF, len) == 0) { ifp = ifs + COND_ELIF_INDEX; } else return COND_INVALID; break; case K_COND_ELIFDEF % MAGICSLOTS2: if (k == K_COND_ELIFDEF && len == strlen(COND_ELIFDEF) && strncmp(line, COND_ELIFDEF, len) == 0) { ifp = ifs + COND_ELIFDEF_INDEX; } else return COND_INVALID; break; case K_COND_ELIFNDEF % MAGICSLOTS2: if (k == K_COND_ELIFNDEF && len == strlen(COND_ELIFNDEF) && strncmp(line, COND_ELIFNDEF, len) == 0) { ifp = ifs + COND_ELIFNDEF_INDEX; } else return COND_INVALID; break; case K_COND_ELIFMAKE % MAGICSLOTS2: if (k == K_COND_ELIFMAKE && len == strlen(COND_ELIFMAKE) && strncmp(line, COND_ELIFMAKE, len) == 0) { ifp = ifs + COND_ELIFMAKE_INDEX; } else return COND_INVALID; break; case K_COND_ELIFNMAKE % MAGICSLOTS2: if (k == K_COND_ELIFNMAKE && len == strlen(COND_ELIFNMAKE) && strncmp(line, COND_ELIFNMAKE, len) == 0) { ifp = ifs + COND_ELIFNMAKE_INDEX; } else return COND_INVALID; break; case K_COND_ELSE % MAGICSLOTS2: /* valid conditional whose value is the inverse * of the previous if we parsed. */ if (k == K_COND_ELSE && len == strlen(COND_ELSE) && strncmp(line, COND_ELSE, len) == 0) { if (condTop == MAXIF) { Parse_Error(level, "if-less else"); return COND_INVALID; } else if (skipIfLevel == 0) { value = !condStack[condTop].value; ifp = ifs + COND_ELSE_INDEX; } else return COND_SKIP; } else return COND_INVALID; break; case K_COND_ENDIF % MAGICSLOTS2: if (k == K_COND_ENDIF && len == strlen(COND_ENDIF) && strncmp(line, COND_ENDIF, len) == 0) { /* End of a conditional section. If skipIfLevel is * non-zero, that conditional was skipped, so lines * following it should also be skipped. Hence, we * return COND_SKIP. Otherwise, the conditional was * read so succeeding lines should be parsed (think * about it...) so we return COND_PARSE, unless this * endif isn't paired with a decent if. */ if (skipIfLevel != 0) { skipIfLevel--; return COND_SKIP; } else { if (condTop == MAXIF) { Parse_Error(level, "if-less endif"); return COND_INVALID; } else { skipLine = false; condTop++; return COND_PARSE; } } } else return COND_INVALID; break; /* Recognize other keywords there, to simplify parser's task */ case K_COND_FOR % MAGICSLOTS2: if (k == K_COND_FOR && len == strlen(COND_FOR) && strncmp(line, COND_FOR, len) == 0) return COND_ISFOR; else return COND_INVALID; case K_COND_UNDEF % MAGICSLOTS2: if (k == K_COND_UNDEF && len == strlen(COND_UNDEF) && strncmp(line, COND_UNDEF, len) == 0) return COND_ISUNDEF; else return COND_INVALID; case K_COND_POISON % MAGICSLOTS2: if (k == K_COND_POISON && len == strlen(COND_POISON) && strncmp(line, COND_POISON, len) == 0) return COND_ISPOISON; else return COND_INVALID; case K_COND_INCLUDE % MAGICSLOTS2: if (k == K_COND_INCLUDE && len == strlen(COND_INCLUDE) && strncmp(line, COND_INCLUDE, len) == 0) return COND_ISINCLUDE; else return COND_INVALID; default: /* Not a valid conditional type. No error... */ return COND_INVALID; } if (ifp->isElse) { if (condTop == MAXIF) { Parse_Error(level, "if-less elif"); return COND_INVALID; } else if (skipIfLevel != 0 || condStack[condTop].value) { /* * Skip if we're meant to or is an else-type * conditional and previous corresponding one was * evaluated to true. */ skipLine = true; return COND_SKIP; } } else if (skipLine) { /* Don't even try to evaluate a conditional that's not an else * if we're skipping things... */ skipIfLevel++; return COND_SKIP; } else condTop--; if (condTop < 0) { /* This is the one case where we can definitely proclaim a fatal * error. If we don't, we're hosed. */ Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.", MAXIF); condTop = 0; return COND_INVALID; } if (ifp->defProc) { /* Initialize file-global variables for parsing. */ condDefProc = ifp->defProc; condInvert = ifp->doNot; line += len; while (*line == ' ' || *line == '\t') line++; condExpr = line; condPushBack = None; switch (CondE(true)) { case True: if (CondToken(true) == EndOfFile) { value = true; break; } goto err; /* FALLTHROUGH */ case False: if (CondToken(true) == EndOfFile) { value = false; break; } /* FALLTHROUGH */ case Err: err: Parse_Error(level, "Malformed conditional (%s)", line); return COND_INVALID; default: break; } } condStack[condTop].value = value; Parse_FillLocation(&condStack[condTop].origin); skipLine = !value; return value ? COND_PARSE : COND_SKIP; }