home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
gnu
/
pdksh-src.lha
/
src
/
amiga
/
pdksh
/
sh
/
table.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-01
|
5KB
|
257 lines
#ifndef lint
static char *RCSid = "$Id: table.c,v 1.2 1992/04/25 08:33:28 sjg Exp $";
#endif
/*
* dynamic hashed associative table for commands and variables
*/
#include "stdh.h"
#include <errno.h>
#include <setjmp.h>
#include "sh.h"
#define INIT_TBLS 8 /* initial table size (power of 2) */
static struct tstate {
int left;
struct tbl **next;
} tstate;
static void texpand ARGS((struct table *tp, int nsize));
static int tnamecmp ARGS((void *p1, void *p2));
unsigned int
hash(n)
register char * n;
{
register unsigned int h = 0;
while (*n != '\0')
h = 2*h + *n++;
return h * 32821; /* scatter bits */
}
#if 0
phash(s) char *s; {
printf("%2d: %s\n", hash(s)%32, s);
}
#endif
void
tinit(tp, ap)
register struct table *tp;
register Area *ap;
{
tp->areap = ap;
tp->size = tp->free = 0;
tp->tbls = NULL;
}
static void
texpand(tp, nsize)
register struct table *tp;
int nsize;
{
register int i;
register struct tbl *tblp, **p;
register struct tbl **ntblp, **otblp = tp->tbls;
int osize = tp->size;
ntblp = (struct tbl**) alloc(sizeofN(struct tbl *, nsize), tp->areap);
for (i = 0; i < nsize; i++)
ntblp[i] = NULL;
tp->size = nsize;
tp->free = 8*nsize/10; /* table can get 80% full */
tp->tbls = ntblp;
if (otblp == NULL)
return;
for (i = 0; i < osize; i++)
if ((tblp = otblp[i]) != NULL)
if ((tblp->flag&DEFINED)) {
for (p = &ntblp[hash(tblp->name) &
(tp->size-1)];
*p != NULL; p--)
if (p == ntblp) /* wrap */
p += tp->size;
*p = tblp;
tp->free--;
} else {
afree((void*)tblp, tp->areap);
}
afree((void*)otblp, tp->areap);
}
struct tbl *
tsearch(tp, n, h)
register struct table *tp; /* table */
register char *n; /* name to enter */
unsigned int h; /* hash(n) */
{
register 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))
return p;
if (pp == tp->tbls) /* wrap */
pp += tp->size;
}
return NULL;
}
struct tbl *
tenter(tp, n, h)
register struct table *tp; /* table */
register char *n; /* name to enter */
unsigned int h; /* hash(n) */
{
register struct tbl **pp, *p;
register char *cp;
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)
return p; /* found */
if (pp == tp->tbls) /* wrap */
pp += tp->size;
}
if (tp->free <= 0) { /* too full */
texpand(tp, 2*tp->size);
goto Search;
}
/* create new tbl entry */
for (cp = n; *cp != '\0'; cp++)
;
p = (struct tbl *) alloc(offsetof(struct tbl, name[(cp-n)+1]), tp->areap);
p->flag = 0;
p->type = 0;
for (cp = p->name; *n != '\0';)
*cp++ = *n++;
*cp = '\0';
/* enter in tp->tbls */
tp->free--;
*pp = p;
return p;
}
void
tdelete(p)
register struct tbl *p;
{
p->flag = 0;
}
void
twalk(tp)
register struct table *tp;
{
tstate.left = tp->size;
tstate.next = tp->tbls;
}
struct tbl *
tnext()
{
while (--tstate.left >= 0) {
struct tbl *p = *tstate.next++;
if (p != NULL && (p->flag&DEFINED))
return p;
}
return NULL;
}
static int
tnamecmp(p1, p2)
void *p1, *p2;
{
return strcmp(((struct tbl *)p1)->name, ((struct tbl *)p2)->name);
}
struct tbl **
tsort(tp)
register struct table *tp;
{
register int i;
register struct tbl **p, **sp, **dp;
p = (struct tbl **)alloc(sizeofN(struct tbl *, tp->size+1), ATEMP);
sp = tp->tbls; /* source */
dp = p; /* dest */
for (i = 0; i < tp->size; i++)
if ((*dp = *sp++) != NULL && ((*dp)->flag&DEFINED))
dp++;
i = dp - p;
qsortp((void**)p, (size_t)i, tnamecmp);
p[i] = NULL;
return p;
}
#ifdef amigados
/* need to copy tables, since I only have vfork (), no real fork () */
/* assume initialized source and destination tables */
void
tbl_copy (struct table *src, struct table *dst, Area *ap)
{
struct tbl *t, *tn;
twalk (src);
tinit (dst, ap);
while (t = tnext ())
{
#ifdef DEBUG
fprintf (shlout, "%s: type %d, val $%lx, flag ",
t->name, t->type, t->val.i);
#define PRFLAG(fl) \
if (t->flag & fl) fprintf (shlout, #fl "|");
PRFLAG(ALLOC);
PRFLAG(DEFINED);
PRFLAG(ISSET);
PRFLAG(SPECIAL);
PRFLAG(INTEGER);
PRFLAG(RDONLY);
PRFLAG(EXPORT);
PRFLAG(LOCAL);
PRFLAG(TRACE);
PRFLAG(FUNCT);
PRFLAG(EXPALIAS);
fprintf (shlout, "\n");
#endif
tn = tenter (dst, t->name, hash (t->name));
tn->flag = t->flag;
tn->type = t->type;
if (t->flag & INTEGER)
tn->val.i = t->val.i;
else if (t->flag & FUNCT)
if (t->type == CFUNC)
tn->val.t = t->val.t ? tcopy (t->val.t, ap) : 0;
else
tn->val.f = t->val.f;
else if (t->flag & EXPORT)
tn->val.s = strsave (t->val.s, ap);
else
{
tn->type = 0;
tn->val.s = (t->flag & ALLOC) ?
strsave (t->val.s + t->type, ap) : 0;
}
}
lastarea = ap;
}
#endif