From f5a2c482ef3fe4bea71bc8c6da72c9d9ec402649 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Tue, 4 May 1999 21:25:24 +0000 Subject: zsh-workers:6198 --- Src/hashtable.c | 4 + Src/options.c | 9 - Src/params.c | 565 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- Src/subst.c | 28 +-- Src/zsh.h | 13 ++ 5 files changed, 577 insertions(+), 42 deletions(-) diff --git a/Src/hashtable.c b/Src/hashtable.c index 72e4db21b..0451cc8cb 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -350,6 +350,10 @@ scanhashtable(HashTable ht, int sorted, int flags1, int flags2, ScanFunc scanfun { struct scanstatus st; + if (ht->scanfunc) { + ht->scanfunc(ht, scanfunc, scanflags); + return; + } if (sorted) { int i, ct = ht->ct; VARARR(HashNode, hnsorttab, ct); diff --git a/Src/options.c b/Src/options.c index 19677dfa9..3d6de21f8 100644 --- a/Src/options.c +++ b/Src/options.c @@ -45,15 +45,6 @@ char opts[OPT_SIZE]; /**/ HashTable optiontab; -typedef struct optname *Optname; - -struct optname { - HashNode next; /* next in hash chain */ - char *nam; /* hash data */ - int flags; - int optno; /* option number */ -}; - /* The canonical option name table */ #define OPT_CSH EMULATE_CSH diff --git a/Src/params.c b/Src/params.c index 079b89cf6..841871550 100644 --- a/Src/params.c +++ b/Src/params.c @@ -255,7 +255,11 @@ static Param argvparam; /* hash table containing the parameters */ /**/ -HashTable paramtab; +HashTable paramtab, realparamtab; + +#ifndef DYNAMIC +#define getparamnode gethashnode2 +#endif /* DYNAMIC */ /**/ HashTable @@ -278,6 +282,7 @@ newparamtable(int size, char const *name) return ht; } +#ifdef DYNAMIC /**/ static HashNode getparamnode(HashTable ht, char *nam) @@ -294,6 +299,7 @@ getparamnode(HashTable ht, char *nam) } return hn; } +#endif /* DYNAMIC */ /* Copy a parameter hash table */ @@ -406,6 +412,495 @@ getvaluearr(Value v) return NULL; } +/* empty dummy function for special hash parameters */ + +static void +shempty() +{ +} + +/* Create a simple special hash parameter. */ + +/**/ +Param +createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan) +{ + Param pm; + HashTable ht; + + if (!(pm = createparam(name, PM_SPECIAL|PM_REMOVABLE|PM_HASHED))) + return NULL; + + pm->level = locallevel; + pm->gets.hfn = hashgetfn; + pm->sets.hfn = hashsetfn; + pm->unsetfn = stdunsetfn; + pm->u.hash = ht = newhashtable(7, name, NULL); + + ht->hash = hasher; + ht->emptytable = (TableFunc) shempty; + ht->filltable = NULL; + ht->addnode = (AddNodeFunc) shempty; + ht->getnode = ht->getnode2 = get; + ht->removenode = (RemoveNodeFunc) shempty; + ht->disablenode = NULL; + ht->enablenode = NULL; + ht->freenode = (FreeNodeFunc) shempty; + ht->printnode = NULL; + ht->scanfunc = scan; + + return pm; +} + +/* Functions for the parameters special parameter. */ + +static HashNode +getpmparameter(HashTable ht, char *name) +{ + Param rpm, pm = NULL; + + HEAPALLOC { + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) && + !(rpm->flags & PM_UNSET)) + pm->u.str = paramtypestr(rpm); + else { + pm->u.str = ""; + pm->flags |= PM_UNSET; + } + } LASTALLOC; + + return (HashNode) pm; +} + +static void +scanpmparameters(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < realparamtab->hsize; i++) + for (hn = realparamtab->nodes[i]; hn; hn = hn->next) { + pm.nam = hn->nam; + if (func != scancountparams) + pm.u.str = paramtypestr((Param) hn); + func((HashNode) &pm, flags); + } +} + +/* Functions for the commands special parameter. */ + +static void +setpmcommand(Param pm, char *value) +{ + if (isset(RESTRICTED)) + zwarnnam(NULL, "restricted: %s", value, 0); + else { + Cmdnam cn = zcalloc(sizeof(*cn)); + + cn->flags = HASHED; + cn->u.cmd = ztrdup(value); + + cmdnamtab->addnode(cmdnamtab, ztrdup(pm->nam), (HashNode) cn); + } +} + +static void +unsetpmcommand(Param pm, int exp) +{ + HashNode hn = cmdnamtab->removenode(cmdnamtab, pm->nam); + + if (hn) + cmdnamtab->freenode(hn); +} + +static void +setpmcommands(Param pm, HashTable ht) +{ + int i; + HashNode hn; + + for (i = 0; i < ht->hsize; i++) + for (hn = ht->nodes[i]; hn; hn = hn->next) { + Cmdnam cn = zcalloc(sizeof(*cn)); + struct value v; + + v.isarr = v.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + + cn->flags = HASHED; + cn->u.cmd = ztrdup(getstrvalue(&v)); + + cmdnamtab->addnode(cmdnamtab, ztrdup(hn->nam), (HashNode) cn); + } +} + +static HashNode +getpmcommand(HashTable ht, char *name) +{ + Cmdnam cmd; + Param pm = NULL; + + if (!(cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name)) && + isset(HASHLISTALL)) { + cmdnamtab->filltable(cmdnamtab); + cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name); + } + HEAPALLOC { + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmcommand; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmcommand; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if (cmd) { + if (cmd->flags & HASHED) + pm->u.str = cmd->u.cmd; + else { + pm->u.str = zhalloc(strlen(*(cmd->u.name)) + + strlen(name) + 2); + strcpy(pm->u.str, *(cmd->u.name)); + strcat(pm->u.str, "/"); + strcat(pm->u.str, name); + } + } else { + pm->u.str = ""; + pm->flags |= PM_UNSET; + } + } LASTALLOC; + + return (HashNode) pm; +} + +static void +scanpmcommands(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + Cmdnam cmd; + + if (isset(HASHLISTALL)) + cmdnamtab->filltable(cmdnamtab); + + pm.flags = PM_SCALAR; + pm.sets.cfn = setpmcommand; + pm.gets.cfn = strgetfn; + pm.unsetfn = unsetpmcommand; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < cmdnamtab->hsize; i++) + for (hn = cmdnamtab->nodes[i]; hn; hn = hn->next) { + pm.nam = hn->nam; + cmd = (Cmdnam) hn; + if (func != scancountparams) { + if (cmd->flags & HASHED) + pm.u.str = cmd->u.cmd; + else { + pm.u.str = zhalloc(strlen(*(cmd->u.name)) + + strlen(cmd->nam) + 2); + strcpy(pm.u.str, *(cmd->u.name)); + strcat(pm.u.str, "/"); + strcat(pm.u.str, cmd->nam); + } + } + func((HashNode) &pm, flags); + } +} + +/* Functions for the functions special parameter. */ + +static void +setfunction(char *name, char *value) +{ + char *val; + Shfunc shf; + List list; + int sn; + + val = ztrdup(value); + val = metafy(val, strlen(val), META_REALLOC); + + HEAPALLOC { + list = parse_string(val); + } LASTALLOC; + + if (!list || list == &dummy_list) { + zwarnnam(NULL, "invalid function definition", val, 0); + zsfree(val); + return; + } + PERMALLOC { + shf = (Shfunc) zalloc(sizeof(*shf)); + shf->funcdef = (List) dupstruct(list); + shf->flags = 0; + + if (!strncmp(name, "TRAP", 4) && + (sn = getsignum(name + 4)) != -1) { + if (settrap(sn, shf->funcdef)) { + freestruct(shf->funcdef); + zfree(shf, sizeof(*shf)); + zsfree(val); + LASTALLOC_RETURN; + } + sigtrapped[sn] |= ZSIG_FUNC; + } + shfunctab->addnode(shfunctab, ztrdup(name), shf); + } LASTALLOC; + + zsfree(val); +} + +static void +setpmfunction(Param pm, char *value) +{ + setfunction(pm->nam, value); +} + +static void +unsetpmfunction(Param pm, int exp) +{ + HashNode hn = shfunctab->removenode(shfunctab, pm->nam); + + if (hn) + shfunctab->freenode(hn); +} + +static void +setpmfunctions(Param pm, HashTable ht) +{ + int i; + HashNode hn; + + for (i = 0; i < ht->hsize; i++) + for (hn = ht->nodes[i]; hn; hn = hn->next) { + struct value v; + + v.isarr = v.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + + setfunction(hn->nam, getstrvalue(&v)); + } +} + +static HashNode +getpmfunction(HashTable ht, char *name) +{ + Shfunc shf; + Param pm = NULL; + + HEAPALLOC { + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmfunction; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmfunction; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((shf = (Shfunc) shfunctab->getnode(shfunctab, name))) { + if (shf->flags & PM_UNDEFINED) + pm->u.str = "undefined"; + else { + char *t = getpermtext((void *) dupstruct((void *) + shf->funcdef)), *h; + + h = dupstring(t); + zsfree(t); + unmetafy(h, NULL); + + pm->u.str = h; + } + } else { + pm->u.str = ""; + pm->flags |= PM_UNSET; + } + } LASTALLOC; + + return (HashNode) pm; +} + +static void +scanpmfunctions(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + + pm.flags = PM_SCALAR; + pm.sets.cfn = setpmcommand; + pm.gets.cfn = strgetfn; + pm.unsetfn = unsetpmcommand; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < shfunctab->hsize; i++) + for (hn = shfunctab->nodes[i]; hn; hn = hn->next) { + if (!(hn->flags & DISABLED)) { + pm.nam = hn->nam; + if (func != scancountparams) { + if (((Shfunc) hn)->flags & PM_UNDEFINED) + pm.u.str = "undefined"; + else { + char *t = getpermtext((void *) + dupstruct((void *) ((Shfunc) hn)->funcdef)); + + unmetafy((pm.u.str = dupstring(t)), NULL); + zsfree(t); + } + } + func((HashNode) &pm, flags); + } + } +} + +/* Functions for the options special parameter. */ + +static void +setpmoption(Param pm, char *value) +{ + int n; + + if (!value || (strcmp(value, "on") && strcmp(value, "off"))) + zwarnnam(NULL, "invalid value: %s", value, 0); + else if (!(n = optlookup(pm->nam))) + zwarnnam(NULL, "no such option: %s", pm->nam, 0); + else if (dosetopt(n, (value && strcmp(value, "off")), 0)) + zwarnnam(NULL, "can't change option: %s", pm->nam, 0); +} + +static void +unsetpmoption(Param pm, int exp) +{ + int n; + + if (!(n = optlookup(pm->nam))) + zwarnnam(NULL, "no such option: %s", pm->nam, 0); + else if (dosetopt(n, 0, 0)) + zwarnnam(NULL, "can't change option: %s", pm->nam, 0); +} + +static void +setpmoptions(Param pm, HashTable ht) +{ + int i; + HashNode hn; + + for (i = 0; i < ht->hsize; i++) + for (hn = ht->nodes[i]; hn; hn = hn->next) { + struct value v; + char *val; + + v.isarr = v.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + + val = getstrvalue(&v); + if (!val || (strcmp(val, "on") && strcmp(val, "off"))) + zwarnnam(NULL, "invalid value: %s", val, 0); + else if (dosetopt(optlookup(hn->nam), + (val && strcmp(val, "off")), 0)) + zwarnnam(NULL, "can't change option: %s", hn->nam, 0); + } +} + +static HashNode +getpmoption(HashTable ht, char *name) +{ + Param pm = NULL; + int n; + + HEAPALLOC { + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmoption; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmoption; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((n = optlookup(name))) + pm->u.str = dupstring(opts[n] ? "on" : "off"); + else { + pm->u.str = ""; + pm->flags |= PM_UNSET; + } + } LASTALLOC; + + return (HashNode) pm; +} + +static void +scanpmoptions(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + + pm.flags = PM_SCALAR; + pm.sets.cfn = setpmoption; + pm.gets.cfn = strgetfn; + pm.unsetfn = unsetpmoption; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < optiontab->hsize; i++) + for (hn = optiontab->nodes[i]; hn; hn = hn->next) { + pm.nam = hn->nam; + pm.u.str = opts[((Optname) hn)->optno] ? "on" : "off"; + func((HashNode) &pm, flags); + } +} + /* Set up parameter hash table. This will add predefined * * parameter entries as well as setting up parameter table * * entries for environment variables we inherit. */ @@ -419,7 +914,7 @@ createparamtable(void) char buf[50], *str, *iname; int num_env; - paramtab = newparamtable(151, "paramtab"); + paramtab = realparamtab = newparamtable(151, "paramtab"); /* Add the special parameters to the hash table */ for (ip = special_params; ip->nam; ip++) @@ -509,6 +1004,15 @@ createparamtable(void) setsparam("ZSH_VERSION", ztrdup(ZSH_VERSION)); setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *))); for (t = sigs; (*sigptr++ = ztrdup(*t++)); ); + + pm = createspecialhash("parameters", getpmparameter, scanpmparameters); + pm->flags |= PM_READONLY; + pm = createspecialhash("commands", getpmcommand, scanpmcommands); + pm->sets.hfn = setpmcommands; + pm = createspecialhash("functions", getpmfunction, scanpmfunctions); + pm->sets.hfn = setpmfunctions; + pm = createspecialhash("options", getpmoption, scanpmoptions); + pm->sets.hfn = setpmoptions; } LASTALLOC; noerrs = 0; @@ -559,7 +1063,9 @@ createparam(char *name, int flags) Param pm, oldpm; if (name != nulstring) { - oldpm = (Param) gethashnode2(paramtab, name); + oldpm = (Param) (paramtab == realparamtab ? + gethashnode2(paramtab, name) : + paramtab->getnode(paramtab, name)); if (oldpm && oldpm->level == locallevel) { if (!(oldpm->flags & PM_UNSET) || (oldpm->flags & PM_SPECIAL)) { @@ -842,8 +1348,7 @@ getarg(char **str, int *inv, Value v, int a2, long *w) *inv = 0; /* We've already obtained the "index" (key) */ *w = v->b = -1; r = isset(KSHARRAYS) ? 1 : 0; - } else - if (!(r = mathevalarg(s, &s)) || (isset(KSHARRAYS) && r >= 0)) + } else if (!(r = mathevalarg(s, &s)) || (isset(KSHARRAYS) && r >= 0)) r++; if (word && !v->isarr) { s = t = getstrvalue(v); @@ -2706,6 +3211,47 @@ freeparamnode(HashNode hn) zfree(pm, sizeof(struct param)); } +/* Return a string describing the type of a parameter. */ + +/**/ +char * +paramtypestr(Param pm) +{ + char *val; + int f = pm->flags; + + if (!(f & PM_UNSET)) { + switch (PM_TYPE(f)) { + case PM_SCALAR: val = "scalar"; break; + case PM_ARRAY: val = "array"; break; + case PM_INTEGER: val = "integer"; break; + case PM_HASHED: val = "association"; break; + } + val = dupstring(val); + if (f & PM_LEFT) + val = dyncat(val, "-left"); + if (f & PM_RIGHT_B) + val = dyncat(val, "-right_blanks"); + if (f & PM_RIGHT_Z) + val = dyncat(val, "-right_zeros"); + if (f & PM_LOWER) + val = dyncat(val, "-lower"); + if (f & PM_UPPER) + val = dyncat(val, "-upper"); + if (f & PM_READONLY) + val = dyncat(val, "-readonly"); + if (f & PM_TAGGED) + val = dyncat(val, "-tag"); + if (f & PM_EXPORTED) + val = dyncat(val, "-export"); + if (f & PM_UNIQUE) + val = dyncat(val, "-unique"); + } else + val = dupstring(""); + + return val; +} + /* Print a parameter */ /**/ @@ -2715,11 +3261,13 @@ printparamnode(HashNode hn, int printflags) Param p = (Param) hn; char *t, **u; - if (p->flags & (PM_UNSET | PM_AUTOLOAD)) + if (p->flags & PM_UNSET) return; /* Print the attributes of the parameter */ if (printflags & PRINT_TYPE) { + if (p->flags & PM_AUTOLOAD) + printf("undefined "); if (p->flags & PM_INTEGER) printf("integer "); else if (p->flags & PM_ARRAY) @@ -2753,6 +3301,11 @@ printparamnode(HashNode hn, int printflags) } quotedzputs(p->nam, stdout); + + if (p->flags & PM_AUTOLOAD) { + putchar('\n'); + return; + } if (printflags & PRINT_KV_PAIR) putchar(' '); else diff --git a/Src/subst.c b/Src/subst.c index e8e22f943..c34bcefd7 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1008,33 +1008,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) if (wantt) { if (v && v->pm && !(v->pm->flags & PM_UNSET)) { - int f = v->pm->flags; - - switch (PM_TYPE(f)) { - case PM_SCALAR: val = "scalar"; break; - case PM_ARRAY: val = "array"; break; - case PM_INTEGER: val = "integer"; break; - case PM_HASHED: val = "association"; break; - } - val = dupstring(val); - if (f & PM_LEFT) - val = dyncat(val, "-left"); - if (f & PM_RIGHT_B) - val = dyncat(val, "-right_blanks"); - if (f & PM_RIGHT_Z) - val = dyncat(val, "-right_zeros"); - if (f & PM_LOWER) - val = dyncat(val, "-lower"); - if (f & PM_UPPER) - val = dyncat(val, "-upper"); - if (f & PM_READONLY) - val = dyncat(val, "-readonly"); - if (f & PM_TAGGED) - val = dyncat(val, "-tag"); - if (f & PM_EXPORTED) - val = dyncat(val, "-export"); - if (f & PM_UNIQUE) - val = dyncat(val, "-unique"); + val = paramtypestr(v->pm); vunset = 0; } else val = dupstring(""); diff --git a/Src/zsh.h b/Src/zsh.h index 1eefc51c1..62e5bdf83 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -228,6 +228,7 @@ typedef struct linklist *LinkList; typedef struct hashnode *HashNode; typedef struct hashtable *HashTable; +typedef struct optname *Optname; typedef struct reswd *Reswd; typedef struct alias *Alias; typedef struct param *Param; @@ -684,6 +685,8 @@ typedef void (*FreeNodeFunc) _((HashNode)); * scanhashtable or scanmatchtable */ typedef void (*ScanFunc) _((HashNode, int)); +typedef void (*ScanTabFunc) _((HashTable, ScanFunc, int)); + typedef void (*PrintTableStats) _((HashTable)); /* hash table for standard open hashing */ @@ -707,6 +710,7 @@ struct hashtable { ScanFunc enablenode; /* pointer to function to enable a node */ FreeNodeFunc freenode; /* pointer to function to free a node */ ScanFunc printnode; /* pointer to function to print a node */ + ScanTabFunc scanfunc; /* pointer to function to scan table */ #ifdef HASHTABLE_INTERNAL_MEMBERS HASHTABLE_INTERNAL_MEMBERS /* internal use in hashtable.c */ @@ -726,6 +730,15 @@ struct hashnode { * reserved words. */ #define DISABLED (1<<0) +/* node in shell option table */ + +struct optname { + HashNode next; /* next in hash chain */ + char *nam; /* hash data */ + int flags; + int optno; /* option number */ +}; + /* node in shell reserved word hash table (reswdtab) */ struct reswd { -- cgit 1.4.1