diff --git a/edit.c b/edit.c index c94678d..b63727e 100644 --- a/edit.c +++ b/edit.c @@ -25,7 +25,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.174 2009/08/28 19:57:39 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.175 2009/08/28 20:30:54 tg Exp $"); /* tty driver characters we are interested in */ typedef struct { @@ -4161,8 +4161,7 @@ vi_cmd(int argcnt, const char *cmd) /* lookup letter in alias list... */ alias[1] = cmd[1]; - ap = ktsearch(&aliases, alias, hash(alias), - NULL); + ap = ktsearch(&aliases, alias, hash(alias)); if (!cmd[1] || !ap || !(ap->flag & ISSET)) return (-1); /* check if this is a recursive call... */ diff --git a/eval.c b/eval.c index f9c6ca6..d64a39f 100644 --- a/eval.c +++ b/eval.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.65 2009/08/28 19:57:40 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.66 2009/08/28 20:30:55 tg Exp $"); /* * string expansion @@ -1425,7 +1425,7 @@ homedir(char *name) { struct tbl *ap; - ap = ktenter(&homedirs, name, hash(name), NULL); + ap = ktenter(&homedirs, name, hash(name)); if (!(ap->flag & ISSET)) { struct passwd *pw; diff --git a/exec.c b/exec.c index 8ef5338..d22c31d 100644 --- a/exec.c +++ b/exec.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.63 2009/08/28 19:57:40 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.64 2009/08/28 20:30:55 tg Exp $"); static int comexec(struct op *, struct tbl *volatile, const char **, int volatile, volatile int *); @@ -567,7 +567,7 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap, rv = 127; break; } - if (!(ftp = findfunc(cp, hash(cp), false, NULL)) || + if (!(ftp = findfunc(cp, hash(cp), false)) || !(ftp->flag & ISSET)) { warningf(true, "%s: function not defined by %s", @@ -789,7 +789,7 @@ shcomexec(const char **wp) { struct tbl *tp; - tp = ktsearch(&builtins, *wp, hash(*wp), NULL); + tp = ktsearch(&builtins, *wp, hash(*wp)); if (tp == NULL) internal_errorf("shcomexec: %s", *wp); return (call_builtin(tp, wp)); @@ -800,17 +800,17 @@ shcomexec(const char **wp) * is created if none is found. */ struct tbl * -findfunc(const char *name, uint32_t h, bool create, struct table_entry *pte) +findfunc(const char *name, uint32_t h, bool create) { struct block *l; struct tbl *tp = NULL; for (l = e->loc; l; l = l->next) { - tp = ktsearch(&l->funs, name, h, pte); + tp = ktsearch(&l->funs, name, h); if (tp) break; if (!l->next && create) { - tp = ktenter(&l->funs, name, h, pte); + tp = ktenter(&l->funs, name, h); tp->flag = DEFINED; tp->type = CFUNC; tp->val.t = NULL; @@ -828,11 +828,10 @@ int define(const char *name, struct op *t) { struct tbl *tp; - struct table_entry te; bool was_set = false; while (1) { - tp = findfunc(name, hash(name), true, &te); + tp = findfunc(name, hash(name), true); if (tp->flag & ISSET) was_set = true; @@ -853,7 +852,7 @@ define(const char *name, struct op *t) } if (t == NULL) { /* undefine */ - ktremove(&te); + ktdelete(tp); return (was_set ? 0 : 1); } @@ -886,7 +885,7 @@ builtin(const char *name, int (*func) (const char **)) break; } - tp = ktenter(&builtins, name, hash(name), NULL); + tp = ktenter(&builtins, name, hash(name)); tp->flag = DEFINED | flag; tp->type = CSHELL; tp->val.f = func; @@ -912,14 +911,14 @@ findcom(const char *name, int flags) flags &= ~FC_FUNC; goto Search; } - tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h, NULL) : NULL; + tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL; /* POSIX says special builtins first, then functions, then * POSIX regular builtins, then search path... */ if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI)) tp = tbi; if (!tp && (flags & FC_FUNC)) { - tp = findfunc(name, h, false, NULL); + tp = findfunc(name, h, false); if (tp && !(tp->flag & ISSET)) { if ((fpath = str_val(global("FPATH"))) == null) { tp->u.fpath = NULL; @@ -934,7 +933,7 @@ findcom(const char *name, int flags) if (!tp && (flags & FC_UNREGBI) && tbi) tp = tbi; if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) { - tp = ktsearch(&taliases, name, h, NULL); + tp = ktsearch(&taliases, name, h); if (tp && (tp->flag & ISSET) && access(tp->val.s, X_OK) != 0) { if (tp->flag & ALLOC) { tp->flag &= ~ALLOC; @@ -949,7 +948,7 @@ findcom(const char *name, int flags) (flags & FC_PATH)) { if (!tp) { if (insert && !(flags & FC_DEFPATH)) { - tp = ktenter(&taliases, name, h, NULL); + tp = ktenter(&taliases, name, h); tp->type = CTALIAS; } else { tp = &temp; diff --git a/expr.c b/expr.c index edea666..c8b0e2c 100644 --- a/expr.c +++ b/expr.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.30 2009/08/08 13:08:50 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.31 2009/08/28 20:30:55 tg Exp $"); /* The order of these enums is constrained by the order of opinfo[] */ enum token { @@ -608,6 +608,8 @@ tempvar(void) vp->flag = ISSET|INTEGER; vp->type = 0; vp->areap = ATEMP; + vp->tablep = NULL; + vp->hval = 0; vp->val.i = 0; vp->name[0] = '\0'; return (vp); diff --git a/funcs.c b/funcs.c index 36a0a79..b07e628 100644 --- a/funcs.c +++ b/funcs.c @@ -25,7 +25,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.122 2009/08/28 19:57:40 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.123 2009/08/28 20:30:56 tg Exp $"); #if HAVE_KILLPG /* @@ -637,11 +637,13 @@ c_whence(const char **wp) fcflags &= ~(FC_BI | FC_FUNC); while ((vflag || rv == 0) && (id = *wp++) != NULL) { + uint32_t h = 0; + tp = NULL; if ((iam_whence || vflag) && !pflag) - tp = ktsearch(&keywords, id, hash(id), NULL); + tp = ktsearch(&keywords, id, h = hash(id)); if (!tp && !pflag) { - tp = ktsearch(&aliases, id, hash(id), NULL); + tp = ktsearch(&aliases, id, h ? h : hash(id)); if (tp && !(tp->flag & ISSET)) tp = NULL; } @@ -879,7 +881,7 @@ c_typeset(const char **wp) for (i = builtin_opt.optind; wp[i]; i++) { if (func) { f = findfunc(wp[i], hash(wp[i]), - (fset&UCASEV_AL) ? true : false, NULL); + (fset&UCASEV_AL) ? true : false); if (!f) { /* AT&T ksh does ++rv: bogus */ rv = 1; @@ -1138,7 +1140,7 @@ c_alias(const char **wp) } h = hash(alias); if (val == NULL && !tflag && !xflag) { - ap = ktsearch(t, alias, h, NULL); + ap = ktsearch(t, alias, h); if (ap != NULL && (ap->flag&ISSET)) { if (pflag) shf_puts("alias ", shl_stdout); @@ -1154,7 +1156,7 @@ c_alias(const char **wp) } continue; } - ap = ktenter(t, alias, h, NULL); + ap = ktenter(t, alias, h); ap->type = tflag ? CTALIAS : CALIAS; /* Are we setting the value or just some flags? */ if ((val && !tflag) || (!val && tflag && !Uflag)) { @@ -1214,7 +1216,7 @@ c_unalias(const char **wp) wp += builtin_opt.optind; for (; *wp != NULL; wp++) { - ap = ktsearch(t, *wp, hash(*wp), NULL); + ap = ktsearch(t, *wp, hash(*wp)); if (ap == NULL) { rv = 1; /* POSIX */ continue; diff --git a/lex.c b/lex.c index bf445a0..a350b13 100644 --- a/lex.c +++ b/lex.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.91 2009/08/28 19:57:41 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.92 2009/08/28 20:30:56 tg Exp $"); /* * states while lexing word @@ -909,17 +909,15 @@ yylex(int cf) if (*ident != '\0' && (cf&(KEYWORD|ALIAS))) { struct tbl *p; - struct table_entry te; uint32_t h = hash(ident); /* { */ - if ((cf & KEYWORD) && - (p = ktsearch(&keywords, ident, h, NULL)) && + if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) && (!(cf & ESACONLY) || p->val.i == ESAC || p->val.i == '}')) { afree(yylval.cp, ATEMP); return (p->val.i); } - if ((cf & ALIAS) && (p = ktsearch(&aliases, ident, h, &te)) && + if ((cf & ALIAS) && (p = ktsearch(&aliases, ident, h)) && (p->flag & ISSET)) { /* * this still points to the same character as the @@ -946,7 +944,7 @@ yylex(int cf) * delete alias upon encountering function * definition */ - ktremove(&te); + ktdelete(p); else { Source *s = source; diff --git a/main.c b/main.c index b0c1887..f2fdc49 100644 --- a/main.c +++ b/main.c @@ -33,7 +33,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.139 2009/08/28 19:57:42 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.140 2009/08/28 20:30:57 tg Exp $"); extern char **environ; @@ -1236,6 +1236,8 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist) static void texpand(struct table *, size_t); static int tnamecmp(const void *, const void *); +static struct tbl *ktscan(struct table *, const char *, uint32_t, + struct tbl ***); /* Bob Jenkins' one-at-a-time hash */ uint32_t @@ -1276,7 +1278,7 @@ texpand(struct table *tp, size_t nsize) for (i = 0; i < osize; i++) if ((tblp = otblp[i]) != NULL) { if ((tblp->flag & DEFINED)) { - for (p = &ntblp[hash(tblp->name) & + for (p = &ntblp[tblp->hval & (tp->size - 1)]; *p != NULL; p--) if (p == ntblp) /* wrap */ p += tp->size; @@ -1299,48 +1301,39 @@ ktinit(struct table *tp, Area *ap, size_t tsize) texpand(tp, tsize); } -void -ktremove(struct table_entry *pte) +/* table, name (key) to search for, hash(n) */ +static struct tbl * +ktscan(struct table *tp, const char *n, uint32_t h, struct tbl ***ppp) { - struct tbl *p; + struct tbl **pp, *p; - p = *(pte->ep); - *(pte->ep) = NULL; - ++(pte->tp->nfree); + /* search for name in hashed table */ + for (pp = &tp->tbls[h & (tp->size - 1)]; (p = *pp) != NULL; pp--) { + if (p->hval == h && !strcmp(p->name, n) && (p->flag & DEFINED)) + goto found; + if (pp == tp->tbls) + /* wrap */ + pp += tp->size; + } + /* not found */ + p = NULL; - afree(p, p->areap); + found: + if (ppp) + *ppp = pp; + return (p); } /* table, name (key) to search for, hash(n) */ struct tbl * -ktsearch(struct table *tp, const char *n, uint32_t h, struct table_entry *pte) +ktsearch(struct table *tp, const char *n, uint32_t h) { - struct tbl **pp, *p; - - if (tp->size == 0) - return (NULL); - - /* search for name in hashed table */ - for (pp = &tp->tbls[h & (tp->size - 1)]; (p = *pp) != NULL; pp--) { - if (*p->name == *n && strcmp(p->name, n) == 0 && - (p->flag & DEFINED)) { - /* found */ - if (pte) { - pte->tp = tp; - pte->ep = pp; - } - return (p); - } - if (pp == tp->tbls) /* wrap */ - pp += tp->size; - } - - return (NULL); + return (tp->size ? ktscan(tp, n, h, NULL) : NULL); } /* table, name (key) to enter, hash(n) */ struct tbl * -ktenter(struct table *tp, const char *n, uint32_t h, struct table_entry *pte) +ktenter(struct table *tp, const char *n, uint32_t h) { struct tbl **pp, *p; int len; @@ -1348,30 +1341,23 @@ ktenter(struct table *tp, const char *n, uint32_t h, struct table_entry *pte) if (tp->size == 0) texpand(tp, INIT_TBLS); Search: - /* search for name in hashed table */ - for (pp = &tp->tbls[h & (tp->size - 1)]; (p = *pp) != NULL; pp--) { - if (*p->name == *n && strcmp(p->name, n) == 0) { - /* found */ - if (pte) { - pte->tp = tp; - pte->ep = pp; - } - return (p); - } - if (pp == tp->tbls) /* wrap */ - pp += tp->size; - } + if ((p = ktscan(tp, n, h, &pp))) + return (p); - if (tp->nfree <= 0) { /* too full */ + if (tp->nfree <= 0) { + /* too full */ texpand(tp, 2 * tp->size); goto Search; } + /* create new tbl entry */ len = strlen(n) + 1; p = alloc(offsetof(struct tbl, name[0]) + len, tp->areap); p->flag = 0; p->type = 0; p->areap = tp->areap; + p->tablep = tp; + p->hval = h; p->u2.field = 0; p->u.array = NULL; memcpy(p->name, n, len); @@ -1379,13 +1365,27 @@ ktenter(struct table *tp, const char *n, uint32_t h, struct table_entry *pte) /* enter in tp->tbls */ tp->nfree--; *pp = p; - if (pte) { - pte->tp = tp; - pte->ep = pp; - } return (p); } +void +ktdelete(struct tbl *p) +{ + struct tbl **pp; + + if (p->tablep && p->tablep->size && ktscan(p->tablep, p->name, + p->hval, &pp) == p) { + /* ktremove p */ + *pp = NULL; + p->tablep->nfree++; + /* get rid of p */ + afree(p, p->areap); + } else { + /* mark p as free for garbage collection via texpand */ + p->flag = 0; + } +} + void ktwalk(struct tstate *ts, struct table *tp) { diff --git a/sh.h b/sh.h index 225e8dc..2a2792f 100644 --- a/sh.h +++ b/sh.h @@ -134,7 +134,7 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.327 2009/08/28 19:57:42 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.328 2009/08/28 20:30:58 tg Exp $"); #endif #define MKSH_VERSION "R39 2009/08/08" @@ -851,11 +851,6 @@ struct table { short size, nfree; /* hash size (always 2^^n), free entries */ }; -struct table_entry { - struct table *tp; /* table this entry is in */ - struct tbl **ep; /* entry pointer (&tp->tbls[i]) */ -}; - struct tbl { /* table item */ Area *areap; /* area to allocate from */ union { @@ -869,6 +864,7 @@ struct tbl { /* table item */ struct tbl *array; /* array values */ const char *fpath; /* temporary path to undef function */ } u; + struct table *tablep; /* table we're ktenter'd in */ union { int field; /* field with for -L/-R/-Z */ int errno_; /* CEXEC/CTALIAS */ @@ -876,6 +872,7 @@ struct tbl { /* table item */ int type; /* command type (see below), base (if INTEGER), * or offset from val.s of value (if EXPORT) */ Tflag flag; /* flags */ + uint32_t hval; /* hash(name) */ uint32_t index; /* index for an array */ char name[4]; /* name -- variable length */ }; @@ -1376,7 +1373,7 @@ int glob_str(char *, XPtrV *, int); /* exec.c */ int execute(struct op * volatile, volatile int, volatile int * volatile); int shcomexec(const char **); -struct tbl *findfunc(const char *, uint32_t, bool, struct table_entry *); +struct tbl *findfunc(const char *, uint32_t, bool); int define(const char *, struct op *); void builtin(const char *, int (*)(const char **)); struct tbl *findcom(const char *, int); @@ -1545,9 +1542,9 @@ void coproc_cleanup(int); struct temp *maketemp(Area *, Temp_type, struct temp **); uint32_t hash(const char *); void ktinit(struct table *, Area *, size_t); -struct tbl *ktsearch(struct table *, const char *, uint32_t, struct table_entry *); -struct tbl *ktenter(struct table *, const char *, uint32_t, struct table_entry *); -void ktremove(struct table_entry *); +struct tbl *ktsearch(struct table *, const char *, uint32_t); +struct tbl *ktenter(struct table *, const char *, uint32_t); +void ktdelete(struct tbl *); void ktwalk(struct tstate *, struct table *); struct tbl *ktnext(struct tstate *); struct tbl **ktsort(struct table *); diff --git a/syn.c b/syn.c index 6fc5ebc..da4a309 100644 --- a/syn.c +++ b/syn.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.40 2009/08/28 19:57:43 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.41 2009/08/28 20:30:59 tg Exp $"); struct nesting_state { int start_token; /* token than began nesting (eg, FOR) */ @@ -743,7 +743,7 @@ initkeywords(void) /* must be 80% of 2^n (currently 20 keywords) */ 32); for (tt = tokentab; tt->name; tt++) { if (tt->reserved) { - p = ktenter(&keywords, tt->name, hash(tt->name), NULL); + p = ktenter(&keywords, tt->name, hash(tt->name)); p->flag |= DEFINED|ISSET; p->type = CKEYWD; p->val.i = tt->val; diff --git a/var.c b/var.c index a2f6f2b..cceaea9 100644 --- a/var.c +++ b/var.c @@ -22,7 +22,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/var.c,v 1.79 2009/08/28 19:57:43 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/var.c,v 1.80 2009/08/28 20:30:59 tg Exp $"); /* * Variables @@ -128,8 +128,7 @@ initvar(void) ktinit(&specials, APERM, /* must be 80% of 2^n (currently 12 specials) */ 16); for (i = 0; names[i].name; i++) { - tp = ktenter(&specials, names[i].name, hash(names[i].name), - NULL); + tp = ktenter(&specials, names[i].name, hash(names[i].name)); tp->flag = DEFINED|ISSET; tp->type = names[i].v; } @@ -226,7 +225,7 @@ global(const char *n) return (vp); } for (l = e->loc; ; l = l->next) { - vp = ktsearch(&l->vars, n, h, NULL); + vp = ktsearch(&l->vars, n, h); if (vp != NULL) { if (array) return (arraysearch(vp, val)); @@ -236,7 +235,7 @@ global(const char *n) if (l->next == NULL) break; } - vp = ktenter(&l->vars, n, h, NULL); + vp = ktenter(&l->vars, n, h); if (array) vp = arraysearch(vp, val); vp->flag |= DEFINED; @@ -266,13 +265,12 @@ local(const char *n, bool copy) vp->areap = ATEMP; return (vp); } - vp = ktenter(&l->vars, n, h, NULL); + vp = ktenter(&l->vars, n, h); if (copy && !(vp->flag & DEFINED)) { struct block *ll = l; struct tbl *vq = NULL; - while ((ll = ll->next) && !(vq = ktsearch(&ll->vars, n, h, - NULL))) + while ((ll = ll->next) && !(vq = ktsearch(&ll->vars, n, h))) ; if (vq) { vp->flag |= vq->flag & @@ -894,8 +892,7 @@ makenv(void) /* unexport any redefined instances */ for (l2 = l->next; l2 != NULL; l2 = l2->next) { - vp2 = ktsearch(&l2->vars, vp->name, h, - NULL); + vp2 = ktsearch(&l2->vars, vp->name, h); if (vp2 != NULL) vp2->flag &= ~EXPORT; } @@ -1029,7 +1026,7 @@ special(const char *name) { struct tbl *tp; - tp = ktsearch(&specials, name, hash(name), NULL); + tp = ktsearch(&specials, name, hash(name)); return (tp && (tp->flag & ISSET) ? tp->type : V_NONE); } @@ -1037,11 +1034,11 @@ special(const char *name) static void unspecial(const char *name) { - struct table_entry te = { NULL, NULL }; + struct tbl *tp; - ktsearch(&specials, name, hash(name), &te); - if (te.ep) - ktremove(&te); + tp = ktsearch(&specials, name, hash(name)); + if (tp) + ktdelete(tp); } static time_t seconds; /* time SECONDS last set */ @@ -1269,6 +1266,10 @@ arraysearch(struct tbl *vp, uint32_t val) new->areap = vp->areap; new->u2.field = vp->u2.field; new->index = val; + /* XXX array indices must not be ktdelete'd, for now */ + new->tablep = NULL; + new->hval = vp->hval; + if (curr != new) { /* not reusing old array entry */ prev->u.array = new; new->u.array = curr;