1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
/*
* dynamic hashed associative table for commands and variables
*/
#include "sh.h"
#include <search.h>
static int tbl_compare(const void *pa, const void *pb) {
return strcmp(((struct tbl *)pa)->name, ((struct tbl *)pb)->name);
}
void
transitional_tinit(struct table *tp, Area *ap)
{
tp->areap = ap;
tp->tbls = NULL;
tp->root = NULL;
tp->size = tp->nfree = 0;
}
struct tbl *
transitional_tsearch(void **tbl_root, const char *n)
{
struct tbl *p, **q;
unsigned int len;
len = strlen(n) + 1;
p = (struct tbl *) alloc(offsetof(struct tbl, name[0]) + len,
ATEMP);
memcpy(p->name, n, len);
q = tfind(p, (void **)tbl_root, tbl_compare);
return q ? *q : NULL;
}
struct tbl *
transitional_tenter(void **tbl_root, const char *n, Area *ap)
{
struct tbl *p, **q;
unsigned int len;
len = strlen(n) + 1;
p = (struct tbl *) alloc(offsetof(struct tbl, name[0]) + len,
ap);
p->flag = 0;
p->type = 0;
p->areap = ap;
p->u2.field = 0;
p->u.array = (struct tbl *)0;
memcpy(p->name, n, len);
q = (struct tbl **)tsearch((void *)p, (void **)tbl_root, tbl_compare);
return *q;
}
void
transitional_tdelete(void **tbl_root, struct tbl *p)
{
tdelete((void *)p, tbl_root, tbl_compare);
}
#ifdef PERF_DEBUG /* performance debugging */
void tprintinfo ARGS((struct table *tp));
void
tprintinfo(tp)
struct table *tp;
{
struct tbl *te;
char *n;
unsigned int h;
int ncmp;
int totncmp = 0, maxncmp = 0;
int nentries = 0;
struct tstate ts;
shellf("table size %d, nfree %d\n", tp->size, tp->nfree);
shellf(" Ncmp name\n");
twalk(&ts, tp);
while ((te = tnext(&ts))) {
register struct tbl **pp, *p;
h = hash(n = te->name);
ncmp = 0;
/* taken from tsearch() and added counter */
for (pp = &tp->tbls[h & (tp->size-1)]; (p = *pp); pp--) {
ncmp++;
if (*p->name == *n && strcmp(p->name, n) == 0
&& (p->flag&DEFINED))
break; /* return p; */
if (pp == tp->tbls) /* wrap */
pp += tp->size;
}
shellf(" %4d %s\n", ncmp, n);
totncmp += ncmp;
nentries++;
if (ncmp > maxncmp)
maxncmp = ncmp;
}
if (nentries)
shellf(" %d entries, worst ncmp %d, avg ncmp %d.%02d\n",
nentries, maxncmp,
totncmp / nentries,
(totncmp % nentries) * 100 / nentries);
}
#endif /* PERF_DEBUG */
|