diff options
author | Peter Stephenson <pws@users.sourceforge.net> | 2004-12-07 16:54:58 +0000 |
---|---|---|
committer | Peter Stephenson <pws@users.sourceforge.net> | 2004-12-07 16:54:58 +0000 |
commit | 69b4b8bdde76b5aee6befa2b66957db22b3f6353 (patch) | |
tree | 505c080a68853aa351a887a3eac55c4737997885 | |
parent | ddc186f3f69ee72f97d222eba424667164f73526 (diff) | |
download | zsh-69b4b8bdde76b5aee6befa2b66957db22b3f6353.tar.gz zsh-69b4b8bdde76b5aee6befa2b66957db22b3f6353.tar.xz zsh-69b4b8bdde76b5aee6befa2b66957db22b3f6353.zip |
20605: Use separate structure with get/set/unset methods fro parameters.
Separate justification width of parameters from base/precision.
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | Doc/Zsh/builtins.yo | 47 | ||||
-rw-r--r-- | Src/Modules/datetime.c | 5 | ||||
-rw-r--r-- | Src/Modules/langinfo.c | 30 | ||||
-rw-r--r-- | Src/Modules/mapfile.c | 34 | ||||
-rw-r--r-- | Src/Modules/parameter.c | 465 | ||||
-rw-r--r-- | Src/Modules/system.c | 6 | ||||
-rw-r--r-- | Src/Modules/termcap.c | 34 | ||||
-rw-r--r-- | Src/Modules/terminfo.c | 42 | ||||
-rw-r--r-- | Src/Modules/zftp.c | 4 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 4 | ||||
-rw-r--r-- | Src/Zle/complete.c | 130 | ||||
-rw-r--r-- | Src/Zle/computil.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_params.c | 136 | ||||
-rw-r--r-- | Src/Zle/zleparameter.c | 52 | ||||
-rw-r--r-- | Src/builtin.c | 171 | ||||
-rw-r--r-- | Src/exec.c | 10 | ||||
-rw-r--r-- | Src/module.c | 4 | ||||
-rw-r--r-- | Src/params.c | 423 | ||||
-rw-r--r-- | Src/subst.c | 62 | ||||
-rw-r--r-- | Src/zsh.h | 98 | ||||
-rw-r--r-- | Test/B02typeset.ztst | 94 |
22 files changed, 1044 insertions, 821 deletions
diff --git a/ChangeLog b/ChangeLog index a13b21812..4626e6bd8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2004-12-07 Peter Stephenson <pws@csr.com> + * 20605: Doc/Zsh/builtins.yo, Src/builtin.c, Src/exec.c, + Src/module.c, Src/params.c, Src/subst.c, Src/zsh.h, + Src/Modules/datetime.c, Src/Modules/langinfo.c, + Src/Modules/mapfile.c, Src/Modules/parameter.c, + Src/Modules/system.c, Src/Modules/termcap.c, + Src/Modules/terminfo.c, Src/Modules/zftp.c, Src/Zle/compctl.c, + Src/Zle/complete.c, Src/Zle/computil.c, Src/Zle/zle_params.c, + Src/Zle/zleparameter.c, Test/B02typeset.ztst: Use separate + structures for get, set and unset methods of parameters. + Separate width and base/precision for parameters, so that + justification works for integers. + * 20606: Test/V03mathfunc.ztst: simple verification of pseudorandom numbers. diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index a1e9df79a..60ab9d911 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -483,7 +483,8 @@ Bring each specified var(job) in turn to the foreground. If no var(job) is specified, resume the current job. ) findex(float) -item(tt(float) [ {tt(PLUS())|tt(-)}tt(EFHghlprtux) ] [ var(name)[tt(=)var(value)] ... ])( +item(tt(float) [ {tt(PLUS())|tt(-)}tt(EFHghlprtux) ] [ tt(-LRZ) [ var(n) ]] \ +[ var(name)[tt(=)var(value)] ... ])( Equivalent to tt(typeset -E), except that options irrelevant to floating point numbers are not permitted. ) @@ -585,7 +586,8 @@ the form of a call to hash. ) alias(history)(fc -l) findex(integer) -item(tt(integer) [ {tt(PLUS())|tt(-)}tt(Hghilprtux) ] [ var(name)[tt(=)var(value)] ... ])( +item(tt(integer) [ {tt(PLUS())|tt(-)}tt(Hghilprtux) ] \ +[ tt(-LRZ) [ var(n) ]] [ var(name)[tt(=)var(value)] ... ])( Equivalent to tt(typeset -i), except that options irrelevant to integers are not permitted. ) @@ -704,7 +706,8 @@ sitem([var(mm)tt(:)]var(ss))(minutes and seconds) endsitem() ) findex(local) -item(tt(local) [ {tt(PLUS())|tt(-)}tt(AEFHLRUZahilprtux) [var(n)]] [ var(name)[tt(=)var(value)] ] ...)( +item(tt(local) [ {tt(PLUS())|tt(-)}tt(AEFHUahlprtux) ] \ +[ tt(-LRZi) [ var(n) ]] [ var(name)[tt(=)var(value)] ] ...)( Same as tt(typeset), except that the options tt(-g), and tt(-f) are not permitted. In this case the tt(-x) option does not force the use of tt(-g), i.e. exported variables will be local to functions. @@ -1217,10 +1220,12 @@ Equivalent to tt(whence -v). findex(typeset) cindex(parameters, setting) cindex(parameters, declaring) -xitem(tt(typeset) [ {tt(PLUS())|tt(-)}tt(AEFHLRUZafghiklprtuxmz) [var(n)]] [ \ +xitem(tt(typeset) [ {tt(PLUS())|tt(-)}tt(AEFHUafghklprtuxmz) ] [ tt(-LRZi) \ +[ var(n) ]] [ \ var(name)[tt(=)var(value)] ... ]) -item(tt(typeset) -T [ {tt(PLUS()|tt(-))}tt(LRUZrux) ] \ - var(SCALAR)[tt(=)var(value)] var(array) tt([) var(sep) tt(]))( +item(tt(typeset) -T [ {tt(PLUS()|tt(-))}tt(Urux) ] \ + [ tt(-LRZ) [ var(n) ]] \ + var(SCALAR)[tt(=)var(value)] var(array) tt([) var(sep) tt(]))( Set or display attributes and values for shell parameters. A parameter is created for each var(name) that does not already refer @@ -1312,20 +1317,21 @@ ifnzman(noderef(Array Parameters))\ ) item(tt(-L))( Left justify and remove leading blanks from var(value). -If var(n) is nonzero, it defines the width of the field; -otherwise it is determined by the width of the value of the first -assignment. +If var(n) is nonzero, it defines the width of the field. +If var(n) is zero, the width is determined by the width of the value of +the first assignment. In the case of numeric parameters, the length of the +complete value assigned to the parameter is used to determine the width, +not the value that would be output. When the parameter is expanded, it is filled on the right with blanks or truncated if necessary to fit the field. +Note truncation can lead to unexpected results with numeric parameters. Leading zeros are removed if the tt(-Z) flag is also set. ) item(tt(-R))( -Right justify and fill with leading blanks. If var(n) is nonzero -if defines the width of the field; -otherwise it is determined by the width of the value of the first -assignment. -When the parameter is expanded, the field is left filled with -blanks or truncated from the end. +Similar to tt(-L), except that right justification is used; +when the parameter is expanded, the field is left filled with +blanks or truncated from the end. May not be combined with the tt(-Z) +flag. ) item(tt(-U))( For arrays (but not for associative arrays), keep only the first @@ -1334,11 +1340,12 @@ colon-separated special parameters like tt(PATH) or tt(FIGNORE), etc. This flag has a different meaning when used with tt(-f); see below. ) item(tt(-Z))( -Right justify and fill with leading zeros if the first non-blank -character is a digit and the tt(-L) flag has not been set. -If var(n) is nonzero it defines the width of the field; -otherwise it is determined by the width of the value of the -first assignment. +Specially handled if set along with the tt(-L) flag. +Otherwise, similar to tt(-R), except that leading zeros are used for +padding instead of blanks if the first non-blank character is a digit. +Numeric parameters are specially handled: they are always eligible +for padding with zeroes, and the zeroes are inserted at an appropriate +place in the output. ) item(tt(-a))( The names refer to array parameters. An array parameter may be diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c index 209675e5a..4a3478800 100644 --- a/Src/Modules/datetime.c +++ b/Src/Modules/datetime.c @@ -86,9 +86,12 @@ static struct builtin bintab[] = { BUILTIN("strftime", 0, bin_strftime, 2, 2, 0, "s:", NULL), }; +static const struct gsu_integer epochseconds_gsu = +{ getcurrentsecs, NULL, stdunsetfn }; + static struct paramdef patab[] = { PARAMDEF("EPOCHSECONDS", PM_INTEGER|PM_SPECIAL|PM_READONLY, - NULL, NULL, &getcurrentsecs, stdunsetfn), + NULL, &epochseconds_gsu), }; /**/ diff --git a/Src/Modules/langinfo.c b/Src/Modules/langinfo.c index 677440f52..10754e36c 100644 --- a/Src/Modules/langinfo.c +++ b/Src/Modules/langinfo.c @@ -417,9 +417,7 @@ createlihash() return NULL; pm->level = pm->old ? locallevel : 0; - pm->gets.hfn = hashgetfn; - pm->sets.hfn = hashsetfn; - pm->unsetfn = stdunsetfn; + pm->gsu.h = &stdhash_gsu; pm->u.hash = ht = newhashtable(7, langinfo_nam, NULL); ht->hash = hasher; @@ -447,19 +445,10 @@ getlanginfo(UNUSED(HashTable ht), char *name) unmetafy(name, &len); - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(sizeof(struct param)); pm->nam = dupstring(name); pm->flags = PM_READONLY | PM_SCALAR; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; - pm->sets.ifn = NULL; - pm->gets.ifn = intgetfn; - pm->unsetfn = NULL; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; + pm->gsu.s = &nullsetscalar_gsu; if(name) elem = liitem(name); @@ -486,17 +475,8 @@ scanlanginfo(UNUSED(HashTable ht), ScanFunc func, int flags) char **element, *langstr; nl_item *nlcode; - pm = (Param) zhalloc(sizeof(struct param)); - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; - pm->sets.ifn = NULL; - pm->gets.ifn = intgetfn; - pm->unsetfn = NULL; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - + pm = (Param) hcalloc(sizeof(struct param)); + pm->gsu.s = &nullsetscalar_gsu; pm->flags = PM_READONLY | PM_SCALAR; nlcode = &nl_vals[0]; diff --git a/Src/Modules/mapfile.c b/Src/Modules/mapfile.c index 66e311c63..0ba7e6fd9 100644 --- a/Src/Modules/mapfile.c +++ b/Src/Modules/mapfile.c @@ -74,6 +74,9 @@ shempty(void) { } +static const struct gsu_hash mapfiles_gsu = +{ hashgetfn, setpmmapfiles, stdunsetfn }; + /* Create the special hash parameter. */ /**/ @@ -91,9 +94,7 @@ createmapfilehash() return NULL; pm->level = pm->old ? locallevel : 0; - pm->gets.hfn = hashgetfn; - pm->sets.hfn = setpmmapfiles; - pm->unsetfn = stdunsetfn; + pm->gsu.h = &mapfiles_gsu; pm->u.hash = ht = newhashtable(7, mapfile_nam, NULL); ht->hash = hasher; @@ -257,6 +258,9 @@ get_contents(char *fname) return val; } +static const struct gsu_scalar mapfile_gsu = +{ strgetfn, setpmmapfile, unsetpmmapfile }; + /**/ static HashNode getpmmapfile(UNUSED(HashTable ht), char *name) @@ -264,18 +268,10 @@ getpmmapfile(UNUSED(HashTable ht), char *name) char *contents; Param pm = NULL; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(sizeof(struct param)); pm->nam = dupstring(name); pm->flags = PM_SCALAR; - pm->sets.cfn = setpmmapfile; - pm->gets.cfn = strgetfn; - pm->unsetfn = unsetpmmapfile; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; - + pm->gsu.s = &mapfile_gsu; pm->flags |= (mapfile_pm->flags & PM_READONLY); /* Set u.str to contents of file given by name */ @@ -288,6 +284,7 @@ getpmmapfile(UNUSED(HashTable ht), char *name) return (HashNode) pm; } + /**/ static void scanpmmapfile(UNUSED(HashTable ht), ScanFunc func, int flags) @@ -298,16 +295,9 @@ scanpmmapfile(UNUSED(HashTable ht), ScanFunc func, int flags) if (!(dir = opendir("."))) return; + memset((void *)&pm, 0, sizeof(struct param)); pm.flags = PM_SCALAR; - pm.sets.cfn = setpmmapfile; - pm.gets.cfn = strgetfn; - pm.unsetfn = unsetpmmapfile; - pm.ct = 0; - pm.env = NULL; - pm.ename = NULL; - pm.old = NULL; - pm.level = 0; - + pm.gsu.s = &mapfile_gsu; pm.flags |= (mapfile_pm->flags & PM_READONLY); /* Here we scan the current directory, calling func() for each file */ diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 1df6631fe..6b7db0387 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -56,11 +56,8 @@ createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan) return NULL; pm->level = pm->old ? locallevel : 0; - pm->gets.hfn = hashgetfn; - pm->sets.hfn = hashsetfn; - pm->unsetfn = stdunsetfn; + pm->gsu.h = &stdhash_gsu; pm->u.hash = ht = newhashtable(0, name, NULL); - pm->ct = 0; ht->hash = hasher; ht->emptytable = (TableFunc) shempty; @@ -140,17 +137,10 @@ getpmparameter(UNUSED(HashTable ht), char *name) { Param rpm, pm = NULL; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) && !(rpm->flags & PM_UNSET)) pm->u.str = paramtypestr(rpm); @@ -169,15 +159,9 @@ scanpmparameters(UNUSED(HashTable ht), ScanFunc func, int flags) int i; HashNode hn; + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; for (i = 0; i < realparamtab->hsize; i++) for (hn = realparamtab->nodes[i]; hn; hn = hn->next) { @@ -249,6 +233,10 @@ setpmcommands(UNUSED(Param pm), HashTable ht) deleteparamtable(ht); } +static const struct gsu_scalar pmcommand_gsu = +{ strgetfn, setpmcommand, unsetpmcommand }; + + /**/ static HashNode getpmcommand(UNUSED(HashTable ht), char *name) @@ -261,17 +249,10 @@ getpmcommand(UNUSED(HashTable ht), char *name) cmdnamtab->filltable(cmdnamtab); cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name); } - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &pmcommand_gsu; if (cmd) { if (cmd->flags & HASHED) pm->u.str = cmd->u.cmd; @@ -300,15 +281,9 @@ scanpmcommands(UNUSED(HashTable ht), ScanFunc func, int flags) if (isset(HASHLISTALL)) cmdnamtab->filltable(cmdnamtab); + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &pmcommand_gsu; for (i = 0; i < cmdnamtab->hsize; i++) for (hn = cmdnamtab->nodes[i]; hn; hn = hn->next) { @@ -431,6 +406,11 @@ setpmdisfunctions(Param pm, HashTable ht) setfunctions(pm, ht, DISABLED); } +static const struct gsu_scalar pmfunction_gsu = +{ strgetfn, setpmfunction, unsetpmfunction }; +static const struct gsu_scalar pmdisfunction_gsu = +{ strgetfn, setpmdisfunction, unsetpmfunction }; + /**/ static HashNode getfunction(UNUSED(HashTable ht), char *name, int dis) @@ -438,17 +418,10 @@ getfunction(UNUSED(HashTable ht), char *name, int dis) Shfunc shf; Param pm = NULL; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(sizeof(struct param)); pm->nam = dupstring(name); pm->flags = PM_SCALAR; - pm->sets.cfn = (dis ? setpmdisfunction : setpmfunction); - pm->gets.cfn = strgetfn; - pm->unsetfn = unsetpmfunction; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; + pm->gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu; if ((shf = (Shfunc) shfunctab->getnode2(shfunctab, name)) && (dis ? (shf->flags & DISABLED) : !(shf->flags & DISABLED))) { @@ -504,15 +477,9 @@ scanfunctions(UNUSED(HashTable ht), ScanFunc func, int flags, int dis) int i; HashNode hn; + memset((void *)&pm, 0, sizeof(struct param)); pm.flags = PM_SCALAR; - pm.sets.cfn = (dis ? setpmdisfunction : setpmfunction); - pm.gets.cfn = strgetfn; - pm.unsetfn = unsetpmcommand; - pm.ct = 0; - pm.env = NULL; - pm.ename = NULL; - pm.old = NULL; - pm.level = 0; + pm.gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu; for (i = 0; i < shfunctab->hsize; i++) for (hn = shfunctab->nodes[i]; hn; hn = hn->next) { @@ -594,17 +561,10 @@ getbuiltin(UNUSED(HashTable ht), char *name, int dis) Param pm = NULL; Builtin bn; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; if ((bn = (Builtin) builtintab->getnode2(builtintab, name)) && (dis ? (bn->flags & DISABLED) : !(bn->flags & DISABLED))) { char *t = ((bn->handlerfunc || (bn->flags & BINF_PREFIX)) ? @@ -640,15 +600,9 @@ scanbuiltins(UNUSED(HashTable ht), ScanFunc func, int flags, int dis) int i; HashNode hn; + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; for (i = 0; i < builtintab->hsize; i++) for (hn = builtintab->nodes[i]; hn; hn = hn->next) { @@ -776,6 +730,9 @@ setpmoptions(UNUSED(Param pm), HashTable ht) deleteparamtable(ht); } +static const struct gsu_scalar pmoption_gsu = +{ strgetfn, setpmoption, unsetpmoption }; + /**/ static HashNode getpmoption(UNUSED(HashTable ht), char *name) @@ -783,17 +740,10 @@ getpmoption(UNUSED(HashTable ht), char *name) Param pm = NULL; int n; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &pmoption_gsu; if ((n = optlookup(name))) { @@ -819,15 +769,9 @@ scanpmoptions(UNUSED(HashTable ht), ScanFunc func, int flags) int i; HashNode hn; + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &pmoption_gsu; for (i = 0; i < optiontab->hsize; i++) for (hn = optiontab->nodes[i]; hn; hn = hn->next) { @@ -883,17 +827,10 @@ getpmmodule(UNUSED(HashTable ht), char *name) char *type = NULL; LinkNode node; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; if (!type) { Module m; @@ -948,15 +885,9 @@ scanpmmodules(UNUSED(HashTable ht), ScanFunc func, int flags) Conddef p; char *loaded = dupstring("loaded"); + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; for (node = firstnode(modules); node; incnode(node)) { m = (Module) getdata(node); @@ -1039,17 +970,10 @@ getpmhistory(UNUSED(HashTable ht), char *name) char *p; int ok = 1; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; if (*name != '0' || name[1]) { if (*name == '0') @@ -1078,15 +1002,9 @@ scanpmhistory(UNUSED(HashTable ht), ScanFunc func, int flags) Histent he = gethistent(i, GETHIST_UPWARD); char buf[40]; + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; while (he) { if (func != scancountparams) { @@ -1169,17 +1087,10 @@ getpmjobtext(UNUSED(HashTable ht), char *name) Param pm = NULL; int job; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; if ((job = atoi(name)) >= 1 && job <= maxjob && jobtab[job].stat && jobtab[job].procs && @@ -1200,15 +1111,9 @@ scanpmjobtexts(UNUSED(HashTable ht), ScanFunc func, int flags) int job; char buf[40]; + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; for (job = 1; job <= maxjob; job++) { if (jobtab[job].stat && jobtab[job].procs && @@ -1279,17 +1184,10 @@ getpmjobstate(UNUSED(HashTable ht), char *name) Param pm = NULL; int job; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; if ((job = atoi(name)) >= 1 && job <= maxjob && jobtab[job].stat && jobtab[job].procs && @@ -1310,15 +1208,9 @@ scanpmjobstates(UNUSED(HashTable ht), ScanFunc func, int flags) int job; char buf[40]; + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; for (job = 1; job <= maxjob; job++) { if (jobtab[job].stat && jobtab[job].procs && @@ -1354,17 +1246,10 @@ getpmjobdir(UNUSED(HashTable ht), char *name) Param pm = NULL; int job; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; if ((job = atoi(name)) >= 1 && job <= maxjob && jobtab[job].stat && jobtab[job].procs && @@ -1385,15 +1270,9 @@ scanpmjobdirs(UNUSED(HashTable ht), ScanFunc func, int flags) int job; char buf[40]; + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; for (job = 1; job <= maxjob; job++) { if (jobtab[job].stat && jobtab[job].procs && @@ -1485,6 +1364,9 @@ setpmnameddirs(UNUSED(Param pm), HashTable ht) opts[INTERACTIVE] = i; } +static const struct gsu_scalar pmnamedir_gsu = +{ strgetfn, setpmnameddir, unsetpmnameddir }; + /**/ static HashNode getpmnameddir(UNUSED(HashTable ht), char *name) @@ -1492,17 +1374,10 @@ getpmnameddir(UNUSED(HashTable ht), char *name) Param pm = NULL; Nameddir nd; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(sizeof(struct param)); pm->nam = dupstring(name); pm->flags = PM_SCALAR; - pm->sets.cfn = setpmnameddir; - pm->gets.cfn = strgetfn; - pm->unsetfn = unsetpmnameddir; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; + pm->gsu.s = &pmnamedir_gsu; if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) && !(nd->flags & ND_USERNAME)) pm->u.str = dupstring(nd->dir); @@ -1522,15 +1397,9 @@ scanpmnameddirs(UNUSED(HashTable ht), ScanFunc func, int flags) HashNode hn; Nameddir nd; + memset((void *)&pm, 0, sizeof(struct param)); pm.flags = PM_SCALAR; - pm.sets.cfn = setpmnameddir; - pm.gets.cfn = strgetfn; - pm.unsetfn = unsetpmnameddir; - pm.ct = 0; - pm.env = NULL; - pm.ename = NULL; - pm.old = NULL; - pm.level = 0; + pm.gsu.s = &pmnamedir_gsu; for (i = 0; i < nameddirtab->hsize; i++) for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) { @@ -1556,17 +1425,10 @@ getpmuserdir(UNUSED(HashTable ht), char *name) nameddirtab->filltable(nameddirtab); - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) && (nd->flags & ND_USERNAME)) pm->u.str = dupstring(nd->dir); @@ -1588,15 +1450,9 @@ scanpmuserdirs(UNUSED(HashTable ht), ScanFunc func, int flags) nameddirtab->filltable(nameddirtab); + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; for (i = 0; i < nameddirtab->hsize; i++) for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) { @@ -1766,6 +1622,19 @@ setpmdissaliases(Param pm, HashTable ht) setaliases(sufaliastab, pm, ht, ALIAS_SUFFIX|DISABLED); } +static const struct gsu_scalar pmralias_gsu = +{ strgetfn, setpmralias, unsetpmalias }; +static const struct gsu_scalar pmgalias_gsu = +{ strgetfn, setpmgalias, unsetpmalias }; +static const struct gsu_scalar pmsalias_gsu = +{ strgetfn, setpmsalias, unsetpmsalias }; +static const struct gsu_scalar pmdisralias_gsu = +{ strgetfn, setpmdisralias, unsetpmalias }; +static const struct gsu_scalar pmdisgalias_gsu = +{ strgetfn, setpmdisgalias, unsetpmalias }; +static const struct gsu_scalar pmdissalias_gsu = +{ strgetfn, setpmdissalias, unsetpmsalias }; + /**/ static void assignaliasdefs(Param pm, int flags) @@ -1775,40 +1644,29 @@ assignaliasdefs(Param pm, int flags) /* we really need to squirrel the flags away somewhere... */ switch (flags) { case 0: - pm->sets.cfn = setpmralias; - break; + pm->gsu.s = &pmralias_gsu; + break; case ALIAS_GLOBAL: - pm->sets.cfn = setpmgalias; - break; + pm->gsu.s = &pmgalias_gsu; + break; case ALIAS_SUFFIX: - pm->sets.cfn = setpmsalias; - break; + pm->gsu.s = &pmsalias_gsu; + break; case DISABLED: - pm->sets.cfn = setpmdisralias; - break; + pm->gsu.s = &pmdisralias_gsu; + break; case ALIAS_GLOBAL|DISABLED: - pm->sets.cfn = setpmdisgalias; - break; + pm->gsu.s = &pmdisgalias_gsu; + break; case ALIAS_SUFFIX|DISABLED: - pm->sets.cfn = setpmdissalias; - break; - } - - pm->gets.cfn = strgetfn; - if (flags & ALIAS_SUFFIX) - pm->unsetfn = unsetpmsalias; - else - pm->unsetfn = unsetpmalias; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; + pm->gsu.s = &pmdissalias_gsu; + break; + } } /**/ @@ -1818,7 +1676,7 @@ getalias(HashTable alht, UNUSED(HashTable ht), char *name, int flags) Param pm = NULL; Alias al; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(sizeof(struct param)); pm->nam = dupstring(name); assignaliasdefs(pm, flags); @@ -1884,6 +1742,7 @@ scanaliases(HashTable alht, UNUSED(HashTable ht), ScanFunc func, int i; Alias al; + memset((void *)&pm, 0, sizeof(struct param)); assignaliasdefs(&pm, alflags); for (i = 0; i < alht->hsize; i++) @@ -1948,90 +1807,122 @@ struct pardef { int flags; GetNodeFunc getnfn; ScanTabFunc scantfn; - void (*hsetfn) _((Param, HashTable)); - void (*setfn) _((Param, char **)); - char **(*getfn) _((Param)); - void (*unsetfn) _((Param, int)); + GsuHash hash_gsu; + GsuArray array_gsu; Param pm; }; +static const struct gsu_hash pmcommands_gsu = +{ hashgetfn, setpmcommands, stdunsetfn }; +static const struct gsu_hash pmfunctions_gsu = +{ hashgetfn, setpmfunctions, stdunsetfn }; +static const struct gsu_hash pmdisfunctions_gsu = +{ hashgetfn, setpmdisfunctions, stdunsetfn }; +static const struct gsu_hash pmoptions_gsu = +{ hashgetfn, setpmoptions, stdunsetfn }; +static const struct gsu_hash pmnameddirs_gsu = +{ hashgetfn, setpmnameddirs, stdunsetfn }; +static const struct gsu_hash pmraliases_gsu = +{ hashgetfn, setpmraliases, stdunsetfn }; +static const struct gsu_hash pmgaliases_gsu = +{ hashgetfn, setpmgaliases, stdunsetfn }; +static const struct gsu_hash pmsaliases_gsu = +{ hashgetfn, setpmsaliases, stdunsetfn }; +static const struct gsu_hash pmdisraliases_gsu = +{ hashgetfn, setpmdisraliases, stdunsetfn }; +static const struct gsu_hash pmdisgaliases_gsu = +{ hashgetfn, setpmdisgaliases, stdunsetfn }; +static const struct gsu_hash pmdissaliases_gsu = +{ hashgetfn, setpmdissaliases, stdunsetfn }; + +static const struct gsu_array funcstack_gsu = +{ funcstackgetfn, arrsetfn, stdunsetfn }; +static const struct gsu_array reswords_gsu = +{ reswordsgetfn, arrsetfn, stdunsetfn }; +static const struct gsu_array disreswords_gsu = +{ disreswordsgetfn, arrsetfn, stdunsetfn }; +static const struct gsu_array dirs_gsu = +{ dirsgetfn, dirssetfn, stdunsetfn }; +static const struct gsu_array historywords_gsu = +{ histwgetfn, arrsetfn, stdunsetfn }; + static struct pardef partab[] = { { "parameters", PM_READONLY, - getpmparameter, scanpmparameters, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmparameter, scanpmparameters, &nullsethash_gsu, + NULL, NULL }, { "commands", 0, - getpmcommand, scanpmcommands, setpmcommands, - NULL, NULL, stdunsetfn, NULL }, + getpmcommand, scanpmcommands, &pmcommands_gsu, + NULL, NULL }, { "functions", 0, - getpmfunction, scanpmfunctions, setpmfunctions, - NULL, NULL, stdunsetfn, NULL }, + getpmfunction, scanpmfunctions, &pmfunctions_gsu, + NULL, NULL }, { "dis_functions", 0, - getpmdisfunction, scanpmdisfunctions, setpmdisfunctions, - NULL, NULL, stdunsetfn, NULL }, + getpmdisfunction, scanpmdisfunctions, &pmdisfunctions_gsu, + NULL, NULL }, { "funcstack", PM_ARRAY|PM_SPECIAL|PM_READONLY, NULL, NULL, NULL, - arrsetfn, funcstackgetfn, stdunsetfn, NULL }, + &funcstack_gsu, NULL }, { "builtins", PM_READONLY, - getpmbuiltin, scanpmbuiltins, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmbuiltin, scanpmbuiltins, NULL, + NULL, NULL }, { "dis_builtins", PM_READONLY, - getpmdisbuiltin, scanpmdisbuiltins, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmdisbuiltin, scanpmdisbuiltins, + NULL, NULL, }, { "reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY, NULL, NULL, NULL, - arrsetfn, reswordsgetfn, stdunsetfn, NULL }, + &reswords_gsu, NULL }, { "dis_reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY, NULL, NULL, NULL, - arrsetfn, disreswordsgetfn, stdunsetfn, NULL }, + &disreswords_gsu, NULL }, { "options", 0, - getpmoption, scanpmoptions, setpmoptions, - NULL, NULL, stdunsetfn, NULL }, + getpmoption, scanpmoptions, &pmoptions_gsu, + NULL, NULL }, { "modules", PM_READONLY, - getpmmodule, scanpmmodules, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmmodule, scanpmmodules, NULL, + NULL, NULL }, { "dirstack", PM_ARRAY|PM_SPECIAL|PM_REMOVABLE, NULL, NULL, NULL, - dirssetfn, dirsgetfn, stdunsetfn, NULL }, + &dirs_gsu, NULL }, { "history", PM_READONLY, - getpmhistory, scanpmhistory, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmhistory, scanpmhistory, NULL, + NULL, NULL, }, { "historywords", PM_ARRAY|PM_SPECIAL|PM_READONLY, NULL, NULL, NULL, - arrsetfn, histwgetfn, stdunsetfn, NULL }, + &historywords_gsu, NULL }, { "jobtexts", PM_READONLY, - getpmjobtext, scanpmjobtexts, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmjobtext, scanpmjobtexts, NULL, + NULL, NULL }, { "jobstates", PM_READONLY, - getpmjobstate, scanpmjobstates, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmjobstate, scanpmjobstates, NULL, + NULL, NULL }, { "jobdirs", PM_READONLY, - getpmjobdir, scanpmjobdirs, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmjobdir, scanpmjobdirs, NULL, + NULL, NULL }, { "nameddirs", 0, - getpmnameddir, scanpmnameddirs, setpmnameddirs, - NULL, NULL, stdunsetfn, NULL }, + getpmnameddir, scanpmnameddirs, &pmnameddirs_gsu, + NULL, NULL }, { "userdirs", PM_READONLY, - getpmuserdir, scanpmuserdirs, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmuserdir, scanpmuserdirs, NULL, + NULL, NULL }, { "aliases", 0, - getpmralias, scanpmraliases, setpmraliases, - NULL, NULL, stdunsetfn, NULL }, + getpmralias, scanpmraliases, &pmraliases_gsu, + NULL, NULL }, { "galiases", 0, - getpmgalias, scanpmgaliases, setpmgaliases, - NULL, NULL, stdunsetfn, NULL }, + getpmgalias, scanpmgaliases, &pmgaliases_gsu, + NULL, NULL }, { "saliases", 0, - getpmsalias, scanpmsaliases, setpmsaliases, - NULL, NULL, stdunsetfn, NULL }, + getpmsalias, scanpmsaliases, &pmsaliases_gsu, + NULL, NULL }, { "dis_aliases", 0, - getpmdisralias, scanpmdisraliases, setpmdisraliases, - NULL, NULL, stdunsetfn, NULL }, + getpmdisralias, scanpmdisraliases, &pmdisraliases_gsu, + NULL, NULL }, { "dis_galiases", 0, - getpmdisgalias, scanpmdisgaliases, setpmdisgaliases, - NULL, NULL, stdunsetfn, NULL }, + getpmdisgalias, scanpmdisgaliases, &pmdisgaliases_gsu, + NULL, NULL }, { "dis_saliases", 0, - getpmdissalias, scanpmdissaliases, setpmdissaliases, - NULL, NULL, stdunsetfn, NULL }, - { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + getpmdissalias, scanpmdissaliases, &pmdissaliases_gsu, + NULL, NULL }, + { NULL, 0, NULL, NULL, NULL, NULL, NULL } }; /**/ @@ -2062,15 +1953,13 @@ boot_(UNUSED(Module m)) def->scantfn))) return 1; def->pm->flags |= def->flags; - if (def->hsetfn) - def->pm->sets.hfn = def->hsetfn; + if (def->hash_gsu) + def->pm->gsu.h = def->hash_gsu; } else { if (!(def->pm = createparam(def->name, def->flags | PM_HIDE| PM_HIDEVAL | PM_REMOVABLE))) return 1; - def->pm->sets.afn = def->setfn; - def->pm->gets.afn = def->getfn; - def->pm->unsetfn = def->unsetfn; + def->pm->gsu.a = def->array_gsu; } } return 0; diff --git a/Src/Modules/system.c b/Src/Modules/system.c index f292c1924..3f932c9fa 100644 --- a/Src/Modules/system.c +++ b/Src/Modules/system.c @@ -358,6 +358,8 @@ static struct builtin bintab[] = { BUILTIN("syswrite", 0, bin_syswrite, 1, 1, 0, "c:o:", NULL), }; +static const struct gsu_array errnos_gsu = +{ errnosgetfn, arrsetfn, stdunsetfn }; /* The load/unload routines required by the zsh library interface */ @@ -390,9 +392,7 @@ boot_(Module m) if (!(pm_nos = createparam("errnos", PM_ARRAY|PM_SPECIAL|PM_READONLY| PM_HIDE|PM_HIDEVAL|PM_REMOVABLE))) return 1; - pm_nos->gets.afn = errnosgetfn; - pm_nos->sets.afn = arrsetfn; - pm_nos->unsetfn = stdunsetfn; + pm_nos->gsu.a = &errnos_gsu; if (!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab))) { tidyparam(pm_nos); diff --git a/Src/Modules/termcap.c b/Src/Modules/termcap.c index a74a0538e..4c94038b2 100644 --- a/Src/Modules/termcap.c +++ b/Src/Modules/termcap.c @@ -197,9 +197,7 @@ createtchash() return NULL; pm->level = pm->old ? locallevel : 0; - pm->gets.hfn = hashgetfn; - pm->sets.hfn = hashsetfn; - pm->unsetfn = stdunsetfn; + pm->gsu.h = &stdhash_gsu; pm->u.hash = ht = newhashtable(7, termcap_nam, NULL); ht->hash = hasher; @@ -233,29 +231,21 @@ gettermcap(UNUSED(HashTable ht), char *name) unmetafy(name, &len); - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(sizeof(struct param)); pm->nam = dupstring(name); pm->flags = PM_READONLY; - pm->unsetfn = NULL; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; u = buf; /* logic in the following cascade copied from echotc, above */ if ((num = tgetnum(name)) != -1) { - pm->sets.ifn = NULL; - pm->gets.ifn = intgetfn; + pm->gsu.i = &nullsetinteger_gsu; pm->u.val = num; pm->flags |= PM_INTEGER; return (HashNode) pm; } - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; + pm->gsu.s = &nullsetscalar_gsu; switch (ztgetflag(name)) { case -1: break; @@ -338,17 +328,11 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags) "MT", "Xh", "Xl", "Xo", "Xr", "Xt", "Xv", "sA", "sL", NULL}; #endif - pm = (Param) zhalloc(sizeof(struct param)); - pm->unsetfn = NULL; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; + pm = (Param) hcalloc(sizeof(struct param)); u = buf; pm->flags = PM_READONLY | PM_SCALAR; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; + pm->gsu.s = &nullsetscalar_gsu; for (capcode = (char **)boolcodes; *capcode; capcode++) { if ((num = ztgetflag(*capcode)) != -1) { @@ -359,8 +343,7 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags) } pm->flags = PM_READONLY | PM_INTEGER; - pm->sets.ifn = NULL; - pm->gets.ifn = intgetfn; + pm->gsu.i = &nullsetinteger_gsu; for (capcode = (char **)numcodes; *capcode; capcode++) { if ((num = tgetnum(*capcode)) != -1) { @@ -371,8 +354,7 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags) } pm->flags = PM_READONLY | PM_SCALAR; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; + pm->gsu.s = &nullsetscalar_gsu; for (capcode = (char **)strcodes; *capcode; capcode++) { if ((tcstr = (char *)tgetstr(*capcode,&u)) != NULL && diff --git a/Src/Modules/terminfo.c b/Src/Modules/terminfo.c index 6e9e32588..610df5a6d 100644 --- a/Src/Modules/terminfo.c +++ b/Src/Modules/terminfo.c @@ -165,9 +165,7 @@ createtihash() return NULL; pm->level = pm->old ? locallevel : 0; - pm->gets.hfn = hashgetfn; - pm->sets.hfn = hashsetfn; - pm->unsetfn = stdunsetfn; + pm->gsu.h = &stdhash_gsu; pm->u.hash = ht = newhashtable(7, terminfo_nam, NULL); ht->hash = hasher; @@ -201,42 +199,32 @@ getterminfo(UNUSED(HashTable ht), char *name) unmetafy(name, &len); - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(sizeof(struct param)); pm->nam = dupstring(name); pm->flags = PM_READONLY; - pm->unsetfn = NULL; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - pm->level = 0; if (((num = tigetnum(name)) != -1) && (num != -2)) { pm->u.val = num; pm->flags |= PM_INTEGER; - pm->sets.ifn = NULL; - pm->gets.ifn = intgetfn; + pm->gsu.i = &nullsetinteger_gsu; } else if ((num = tigetflag(name)) != -1) { pm->u.str = num ? dupstring("yes") : dupstring("no"); pm->flags |= PM_SCALAR; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; + pm->gsu.s = &nullsetscalar_gsu; } else if ((tistr = (char *)tigetstr(name)) != NULL && tistr != (char *)-1) { pm->u.str = dupstring(tistr); pm->flags |= PM_SCALAR; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; + pm->gsu.s = &nullsetscalar_gsu; } else { /* zwarn("no such capability: %s", name, 0); */ pm->u.str = dupstring(""); pm->flags |= PM_UNSET; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; + pm->gsu.s = &nullsetscalar_gsu; } return (HashNode) pm; } @@ -319,16 +307,10 @@ scanterminfo(UNUSED(HashTable ht), ScanFunc func, int flags) "slength", NULL}; #endif - pm = (Param) zhalloc(sizeof(struct param)); - pm->unsetfn = NULL; - pm->ct = 0; - pm->env = NULL; - pm->ename = NULL; - pm->old = NULL; - + pm = (Param) hcalloc(sizeof(struct param)); + pm->flags = PM_READONLY | PM_SCALAR; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; + pm->gsu.s = &nullsetscalar_gsu; for (capname = (char **)boolnames; *capname; capname++) { if ((num = tigetflag(*capname)) != -1) { @@ -339,8 +321,7 @@ scanterminfo(UNUSED(HashTable ht), ScanFunc func, int flags) } pm->flags = PM_READONLY | PM_INTEGER; - pm->sets.ifn = NULL; - pm->gets.ifn = intgetfn; + pm->gsu.i = &nullsetinteger_gsu; for (capname = (char **)numnames; *capname; capname++) { if (((num = tigetnum(*capname)) != -1) && (num != -2)) { @@ -351,8 +332,7 @@ scanterminfo(UNUSED(HashTable ht), ScanFunc func, int flags) } pm->flags = PM_READONLY | PM_SCALAR; - pm->sets.cfn = NULL; - pm->gets.cfn = strgetfn; + pm->gsu.s = &nullsetscalar_gsu; for (capname = (char **)strnames; *capname; capname++) { if ((tistr = (char *)tigetstr(*capname)) != NULL && diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c index f41d902db..399070939 100644 --- a/Src/Modules/zftp.c +++ b/Src/Modules/zftp.c @@ -513,9 +513,9 @@ zfsetparam(char *name, void *val, int flags) return; } if (type == PM_INTEGER) - pm->sets.ifn(pm, *(off_t *)val); + pm->gsu.i->setfn(pm, *(off_t *)val); else - pm->sets.cfn(pm, (char *)val); + pm->gsu.s->setfn(pm, (char *)val); } /* diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 2f2996013..a71921a04 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -1975,7 +1975,7 @@ addmatch(char *s, char *t) } else if (addwhat == CC_QUOTEFLAG || addwhat == -2 || (addwhat == -3 && !(hn->flags & DISABLED)) || (addwhat == -4 && (PM_TYPE(pm->flags) == PM_SCALAR) && - !pm->level && (tt = pm->gets.cfn(pm)) && *tt == '/') || + !pm->level && (tt = pm->gsu.s->getfn(pm)) && *tt == '/') || (addwhat == -9 && !(hn->flags & PM_UNSET) && !pm->level) || (addwhat > 0 && ((!(hn->flags & PM_UNSET) && @@ -3750,7 +3750,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) dumphashtable(aliastab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS))); if (keypm && cc == &cc_dummy) { /* Add the keys of the parameter in keypm. */ - HashTable t = keypm->gets.hfn(keypm); + HashTable t = keypm->gsu.h->getfn(keypm); if (t) scanhashtable(t, 0, 0, PM_UNSET, addhnmatch, 0); diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c index d015ab356..717be8896 100644 --- a/Src/Zle/complete.c +++ b/Src/Zle/complete.c @@ -943,56 +943,82 @@ bin_compset(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) * order of the CP_* bits in comp.h */ #define VAL(X) ((void *) (&(X))) +#define GSU(X) ((GsuScalar)(void *) (&(X))) struct compparam { char *name; int type; - void *var, *set, *get; + void *var; + GsuScalar gsu; }; +static const struct gsu_scalar compvarscalar_gsu = +{ strvargetfn, strvarsetfn, compunsetfn }; +static const struct gsu_scalar complist_gsu = +{ get_complist, set_complist, compunsetfn }; +static const struct gsu_scalar unambig_gsu = +{ get_unambig, nullstrsetfn, compunsetfn }; +static const struct gsu_scalar unambig_pos_gsu = +{ get_unambig_pos, nullstrsetfn, compunsetfn }; +static const struct gsu_scalar insert_pos_gsu = +{ get_insert_pos, nullstrsetfn, compunsetfn }; + +static const struct gsu_integer compvarinteger_gsu = +{ intvargetfn, intvarsetfn, compunsetfn }; +static const struct gsu_integer nmatches_gsu = +{ get_nmatches, NULL, compunsetfn }; +static const struct gsu_integer unambig_curs_gsu = +{ get_unambig_curs, NULL, compunsetfn }; +static const struct gsu_integer listlines_gsu = +{ get_listlines, NULL, compunsetfn }; + +static const struct gsu_array compvararray_gsu = +{ arrvargetfn, arrvarsetfn, compunsetfn }; + + static struct compparam comprparams[] = { - { "words", PM_ARRAY, VAL(compwords), NULL, NULL }, - { "redirections", PM_ARRAY, VAL(compredirs), NULL, NULL }, - { "CURRENT", PM_INTEGER, VAL(compcurrent), NULL, NULL }, - { "PREFIX", PM_SCALAR, VAL(compprefix), NULL, NULL }, - { "SUFFIX", PM_SCALAR, VAL(compsuffix), NULL, NULL }, - { "IPREFIX", PM_SCALAR, VAL(compiprefix), NULL, NULL }, - { "ISUFFIX", PM_SCALAR, VAL(compisuffix), NULL, NULL }, - { "QIPREFIX", PM_SCALAR | PM_READONLY, VAL(compqiprefix), NULL, NULL }, - { "QISUFFIX", PM_SCALAR | PM_READONLY, VAL(compqisuffix), NULL, NULL }, - { NULL, 0, NULL, NULL, NULL } + { "words", PM_ARRAY, VAL(compwords), NULL }, + { "redirections", PM_ARRAY, VAL(compredirs), NULL }, + { "CURRENT", PM_INTEGER, VAL(compcurrent), NULL }, + { "PREFIX", PM_SCALAR, VAL(compprefix), NULL }, + { "SUFFIX", PM_SCALAR, VAL(compsuffix), NULL }, + { "IPREFIX", PM_SCALAR, VAL(compiprefix), NULL }, + { "ISUFFIX", PM_SCALAR, VAL(compisuffix), NULL }, + { "QIPREFIX", PM_SCALAR | PM_READONLY, VAL(compqiprefix), NULL }, + { "QISUFFIX", PM_SCALAR | PM_READONLY, VAL(compqisuffix), NULL }, + { NULL, 0, NULL, NULL } }; static struct compparam compkparams[] = { - { "nmatches", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_nmatches) }, - { "context", PM_SCALAR, VAL(compcontext), NULL, NULL }, - { "parameter", PM_SCALAR, VAL(compparameter), NULL, NULL }, - { "redirect", PM_SCALAR, VAL(compredirect), NULL, NULL }, - { "quote", PM_SCALAR | PM_READONLY, VAL(compquote), NULL, NULL }, - { "quoting", PM_SCALAR | PM_READONLY, VAL(compquoting), NULL, NULL }, - { "restore", PM_SCALAR, VAL(comprestore), NULL, NULL }, - { "list", PM_SCALAR, NULL, VAL(set_complist), VAL(get_complist) }, - { "insert", PM_SCALAR, VAL(compinsert), NULL, NULL }, - { "exact", PM_SCALAR, VAL(compexact), NULL, NULL }, - { "exact_string", PM_SCALAR, VAL(compexactstr), NULL, NULL }, - { "pattern_match", PM_SCALAR, VAL(comppatmatch), NULL, NULL }, - { "pattern_insert", PM_SCALAR, VAL(comppatinsert), NULL, NULL }, - { "unambiguous", PM_SCALAR | PM_READONLY, NULL, NULL, VAL(get_unambig) }, - { "unambiguous_cursor", PM_INTEGER | PM_READONLY, NULL, NULL, - VAL(get_unambig_curs) }, - { "unambiguous_positions", PM_SCALAR | PM_READONLY, NULL, NULL, - VAL(get_unambig_pos) }, - { "insert_positions", PM_SCALAR | PM_READONLY, NULL, NULL, - VAL(get_insert_pos) }, - { "list_max", PM_INTEGER, VAL(complistmax), NULL, NULL }, - { "last_prompt", PM_SCALAR, VAL(complastprompt), NULL, NULL }, - { "to_end", PM_SCALAR, VAL(comptoend), NULL, NULL }, - { "old_list", PM_SCALAR, VAL(compoldlist), NULL, NULL }, - { "old_insert", PM_SCALAR, VAL(compoldins), NULL, NULL }, - { "vared", PM_SCALAR, VAL(compvared), NULL, NULL }, - { "list_lines", PM_INTEGER | PM_READONLY, NULL, NULL, VAL(get_listlines) }, - { "all_quotes", PM_SCALAR | PM_READONLY, VAL(compqstack), NULL, NULL }, - { "ignored", PM_INTEGER | PM_READONLY, VAL(compignored), NULL, NULL }, - { NULL, 0, NULL, NULL, NULL } + { "nmatches", PM_INTEGER | PM_READONLY, NULL, GSU(nmatches_gsu) }, + { "context", PM_SCALAR, VAL(compcontext), NULL }, + { "parameter", PM_SCALAR, VAL(compparameter), NULL }, + { "redirect", PM_SCALAR, VAL(compredirect), NULL }, + { "quote", PM_SCALAR | PM_READONLY, VAL(compquote), NULL }, + { "quoting", PM_SCALAR | PM_READONLY, VAL(compquoting), NULL }, + { "restore", PM_SCALAR, VAL(comprestore), NULL }, + { "list", PM_SCALAR, NULL, GSU(complist_gsu) }, + { "insert", PM_SCALAR, VAL(compinsert), NULL }, + { "exact", PM_SCALAR, VAL(compexact), NULL }, + { "exact_string", PM_SCALAR, VAL(compexactstr), NULL }, + { "pattern_match", PM_SCALAR, VAL(comppatmatch), NULL }, + { "pattern_insert", PM_SCALAR, VAL(comppatinsert), NULL }, + { "unambiguous", PM_SCALAR | PM_READONLY, NULL, GSU(unambig_gsu) }, + { "unambiguous_cursor", PM_INTEGER | PM_READONLY, NULL, + GSU(unambig_curs_gsu) }, + { "unambiguous_positions", PM_SCALAR | PM_READONLY, NULL, + GSU(unambig_pos_gsu) }, + { "insert_positions", PM_SCALAR | PM_READONLY, NULL, + GSU(insert_pos_gsu) }, + { "list_max", PM_INTEGER, VAL(complistmax), NULL }, + { "last_prompt", PM_SCALAR, VAL(complastprompt), NULL }, + { "to_end", PM_SCALAR, VAL(comptoend), NULL }, + { "old_list", PM_SCALAR, VAL(compoldlist), NULL }, + { "old_insert", PM_SCALAR, VAL(compoldins), NULL }, + { "vared", PM_SCALAR, VAL(compvared), NULL }, + { "list_lines", PM_INTEGER | PM_READONLY, NULL, GSU(listlines_gsu) }, + { "all_quotes", PM_SCALAR | PM_READONLY, VAL(compqstack), NULL }, + { "ignored", PM_INTEGER | PM_READONLY, VAL(compignored), NULL }, + { NULL, 0, NULL, NULL } }; #define COMPSTATENAME "compstate" @@ -1012,27 +1038,25 @@ addcompparams(struct compparam *cp, Param *pp) if ((pm->u.data = cp->var)) { switch(PM_TYPE(cp->type)) { case PM_SCALAR: - pm->sets.cfn = strvarsetfn; - pm->gets.cfn = strvargetfn; + pm->gsu.s = &compvarscalar_gsu; break; case PM_INTEGER: - pm->sets.ifn = intvarsetfn; - pm->gets.ifn = intvargetfn; - pm->ct = 10; + pm->gsu.i = &compvarinteger_gsu; + pm->base = 10; break; case PM_ARRAY: - pm->sets.afn = arrvarsetfn; - pm->gets.afn = arrvargetfn; + pm->gsu.a = &compvararray_gsu; break; } } else { - pm->sets.cfn = (void (*) _((Param, char *))) cp->set; - pm->gets.cfn = (char *(*) _((Param))) cp->get; + pm->gsu.s = cp->gsu; } - pm->unsetfn = compunsetfn; } } +static const struct gsu_hash compstate_gsu = +{ get_compstate, set_compstate, compunsetfn }; + /**/ void makecompparams(void) @@ -1050,9 +1074,7 @@ makecompparams(void) comprpms[CPN_COMPSTATE] = cpm; tht = paramtab; cpm->level = locallevel + 1; - cpm->gets.hfn = get_compstate; - cpm->sets.hfn = set_compstate; - cpm->unsetfn = compunsetfn; + cpm->gsu.h = &compstate_gsu; cpm->u.hash = paramtab = newparamtable(31, COMPSTATENAME); addcompparams(compkparams, compkpms); paramtab = tht; diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index 9450aa3ad..aa62cc78b 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -3377,7 +3377,7 @@ bin_compquote(char *nam, char **args, Options ops, UNUSED(int func)) break; case PM_ARRAY: { - char **val = v->pm->gets.afn(v->pm); + char **val = v->pm->gsu.a->getfn(v->pm); char **new = (char **) zalloc((arrlen(val) + 1) * sizeof(char *)); char **p = new; diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index d5fa6dd26..4a12dc2e7 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -44,60 +44,86 @@ * RBUFFER (scalar) portion of buffer to the right of the cursor */ -#define FN(X) ( (void (*) _((void))) (X) ) +static const struct gsu_scalar buffer_gsu = +{ get_buffer, set_buffer, zleunsetfn }; +static const struct gsu_scalar context_gsu = +{ get_context, nullstrsetfn, zleunsetfn }; +static const struct gsu_scalar cutbuffer_gsu = +{ get_cutbuffer, set_cutbuffer, unset_cutbuffer }; +static const struct gsu_scalar keymap_gsu = +{ get_keymap, nullstrsetfn, zleunsetfn }; +static const struct gsu_scalar keys_gsu = +{ get_keys, nullstrsetfn, zleunsetfn }; +static const struct gsu_scalar lastsearch_gsu = +{ get_lsearch, nullstrsetfn, zleunsetfn }; +static const struct gsu_scalar lastwidget_gsu = +{ get_lwidget, nullstrsetfn, zleunsetfn }; +static const struct gsu_scalar lbuffer_gsu = +{ get_lbuffer, set_lbuffer, zleunsetfn }; +static const struct gsu_scalar postdisplay_gsu = +{ get_postdisplay, set_postdisplay, zleunsetfn }; +static const struct gsu_scalar prebuffer_gsu = +{ get_prebuffer, nullstrsetfn, zleunsetfn }; +static const struct gsu_scalar predisplay_gsu = +{ get_predisplay, set_predisplay, zleunsetfn }; +static const struct gsu_scalar rbuffer_gsu = +{ get_rbuffer, set_rbuffer, zleunsetfn }; +static const struct gsu_scalar widget_gsu = +{ get_widget, nullstrsetfn, zleunsetfn }; +static const struct gsu_scalar widgetfunc_gsu = +{ get_widgetfunc, nullstrsetfn, zleunsetfn }; +static const struct gsu_scalar widgetstyle_gsu = +{ get_widgetstyle, nullstrsetfn, zleunsetfn }; + +static const struct gsu_integer bufferlines_gsu = +{ get_bufferlines, NULL, zleunsetfn }; +static const struct gsu_integer cursor_gsu = +{ get_cursor, set_cursor, zleunsetfn }; +static const struct gsu_integer histno_gsu = +{ get_histno, set_histno, zleunsetfn }; +static const struct gsu_integer mark_gsu = +{ get_mark, set_mark, zleunsetfn }; +static const struct gsu_integer numeric_gsu = +{ get_numeric, set_numeric, unset_numeric }; +static const struct gsu_integer pending_gsu = +{ get_pending, NULL, zleunsetfn }; + +static const struct gsu_array killring_gsu = +{ get_killring, set_killring, unset_killring }; + +#define GSU(X) ( (GsuScalar)(void*)(&(X)) ) static struct zleparam { char *name; int type; - void (*setfn) _((void)); - void (*getfn) _((void)); - void (*unsetfn) _((Param, int)); + GsuScalar gsu; void *data; } zleparams[] = { - { "BUFFER", PM_SCALAR, FN(set_buffer), FN(get_buffer), - zleunsetfn, NULL }, - { "BUFFERLINES", PM_INTEGER | PM_READONLY, NULL, FN(get_bufferlines), - zleunsetfn, NULL }, - { "CONTEXT", PM_SCALAR | PM_READONLY, NULL, FN(get_context), - zleunsetfn, NULL }, - { "CURSOR", PM_INTEGER, FN(set_cursor), FN(get_cursor), - zleunsetfn, NULL }, - { "CUTBUFFER", PM_SCALAR, FN(set_cutbuffer), FN(get_cutbuffer), - unset_cutbuffer, NULL }, - { "HISTNO", PM_INTEGER, FN(set_histno), FN(get_histno), - zleunsetfn, NULL }, - { "KEYMAP", PM_SCALAR | PM_READONLY, NULL, FN(get_keymap), - zleunsetfn, NULL }, - { "KEYS", PM_SCALAR | PM_READONLY, NULL, FN(get_keys), - zleunsetfn, NULL }, - { "killring", PM_ARRAY, FN(set_killring), FN(get_killring), - unset_killring, NULL }, - { "LASTSEARCH", PM_SCALAR | PM_READONLY, NULL, FN(get_lsearch), - zleunsetfn, NULL }, - { "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget), - zleunsetfn, NULL }, - { "LBUFFER", PM_SCALAR, FN(set_lbuffer), FN(get_lbuffer), - zleunsetfn, NULL }, - { "MARK", PM_INTEGER, FN(set_mark), FN(get_mark), - zleunsetfn, NULL }, - { "NUMERIC", PM_INTEGER | PM_UNSET, FN(set_numeric), FN(get_numeric), - unset_numeric, NULL }, - { "PENDING", PM_INTEGER | PM_READONLY, NULL, FN(get_pending), - zleunsetfn, NULL }, - { "POSTDISPLAY", PM_SCALAR, FN(set_postdisplay), FN(get_postdisplay), - zleunsetfn, NULL }, - { "PREBUFFER", PM_SCALAR | PM_READONLY, NULL, FN(get_prebuffer), - zleunsetfn, NULL }, - { "PREDISPLAY", PM_SCALAR, FN(set_predisplay), FN(get_predisplay), - zleunsetfn, NULL }, - { "RBUFFER", PM_SCALAR, FN(set_rbuffer), FN(get_rbuffer), - zleunsetfn, NULL }, - { "WIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_widget), - zleunsetfn, NULL }, - { "WIDGETFUNC", PM_SCALAR | PM_READONLY, NULL, FN(get_widgetfunc), - zleunsetfn, NULL }, - { "WIDGETSTYLE", PM_SCALAR | PM_READONLY, NULL, FN(get_widgetstyle), - zleunsetfn, NULL }, - { NULL, 0, NULL, NULL, NULL, NULL } + { "BUFFER", PM_SCALAR, GSU(buffer_gsu), NULL }, + { "BUFFERLINES", PM_INTEGER | PM_READONLY, GSU(bufferlines_gsu), + NULL }, + { "CONTEXT", PM_SCALAR | PM_READONLY, GSU(context_gsu), + NULL }, + { "CURSOR", PM_INTEGER, GSU(cursor_gsu), + NULL }, + { "CUTBUFFER", PM_SCALAR, GSU(cutbuffer_gsu), NULL }, + { "HISTNO", PM_INTEGER, GSU(histno_gsu), NULL }, + { "KEYMAP", PM_SCALAR | PM_READONLY, GSU(keymap_gsu), NULL }, + { "KEYS", PM_SCALAR | PM_READONLY, GSU(keys_gsu), NULL }, + { "killring", PM_ARRAY, GSU(killring_gsu), NULL }, + { "LASTSEARCH", PM_SCALAR | PM_READONLY, GSU(lastsearch_gsu), NULL }, + { "LASTWIDGET", PM_SCALAR | PM_READONLY, GSU(lastwidget_gsu), NULL }, + { "LBUFFER", PM_SCALAR, GSU(lbuffer_gsu), NULL }, + { "MARK", PM_INTEGER, GSU(mark_gsu), NULL }, + { "NUMERIC", PM_INTEGER | PM_UNSET, GSU(numeric_gsu), NULL }, + { "PENDING", PM_INTEGER | PM_READONLY, GSU(pending_gsu), NULL }, + { "POSTDISPLAY", PM_SCALAR, GSU(postdisplay_gsu), NULL }, + { "PREBUFFER", PM_SCALAR | PM_READONLY, GSU(prebuffer_gsu), NULL }, + { "PREDISPLAY", PM_SCALAR, GSU(predisplay_gsu), NULL }, + { "RBUFFER", PM_SCALAR, GSU(rbuffer_gsu), NULL }, + { "WIDGET", PM_SCALAR | PM_READONLY, GSU(widget_gsu), NULL }, + { "WIDGETFUNC", PM_SCALAR | PM_READONLY, GSU(widgetfunc_gsu), NULL }, + { "WIDGETSTYLE", PM_SCALAR | PM_READONLY, GSU(widgetstyle_gsu), NULL }, + { NULL, 0, NULL, NULL } }; /**/ @@ -117,20 +143,16 @@ makezleparams(int ro) pm->u.data = zp->data; switch(PM_TYPE(zp->type)) { case PM_SCALAR: - pm->sets.cfn = (void (*) _((Param, char *))) zp->setfn; - pm->gets.cfn = (char *(*) _((Param))) zp->getfn; + pm->gsu.s = zp->gsu; break; case PM_ARRAY: - pm->sets.afn = (void (*) _((Param, char **))) zp->setfn; - pm->gets.afn = (char **(*) _((Param))) zp->getfn; + pm->gsu.a = (GsuArray)zp->gsu; break; case PM_INTEGER: - pm->sets.ifn = (void (*) _((Param, zlong))) zp->setfn; - pm->gets.ifn = (zlong (*) _((Param))) zp->getfn; - pm->ct = 10; + pm->gsu.i = (GsuInteger)zp->gsu; + pm->base = 10; break; } - pm->unsetfn = zp->unsetfn; if ((zp->type & PM_UNSET) && (zmod.flags & MOD_MULT)) pm->flags &= ~PM_UNSET; } diff --git a/Src/Zle/zleparameter.c b/Src/Zle/zleparameter.c index 38b2a3608..ed415c960 100644 --- a/Src/Zle/zleparameter.c +++ b/Src/Zle/zleparameter.c @@ -51,11 +51,8 @@ createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan) return NULL; pm->level = pm->old ? locallevel : 0; - pm->gets.hfn = hashgetfn; - pm->sets.hfn = hashsetfn; - pm->unsetfn = stdunsetfn; + pm->gsu.h = &stdhash_gsu; pm->u.hash = ht = newhashtable(0, name, NULL); - pm->ct = 0; ht->hash = hasher; ht->emptytable = (TableFunc) shempty; @@ -101,17 +98,11 @@ getpmwidgets(UNUSED(HashTable ht), char *name) Param pm = NULL; Thingy th; - pm = (Param) zhalloc(sizeof(struct param)); + pm = (Param) hcalloc(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; + pm->gsu.s = &nullsetscalar_gsu; + if ((th = (Thingy) thingytab->getnode(thingytab, name)) && !(th->flags & DISABLED)) pm->u.str = widgetstr(th->widget); @@ -130,15 +121,9 @@ scanpmwidgets(UNUSED(HashTable ht), ScanFunc func, int flags) int i; HashNode hn; + memset((void *)&pm, 0, sizeof(struct param)); 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; + pm.gsu.s = &nullsetscalar_gsu; for (i = 0; i < thingytab->hsize; i++) for (hn = thingytab->nodes[i]; hn; hn = hn->next) { @@ -177,21 +162,22 @@ struct pardef { int flags; GetNodeFunc getnfn; ScanTabFunc scantfn; - void (*hsetfn) _((Param, HashTable)); - void (*setfn) _((Param, char **)); - char **(*getfn) _((Param)); - void (*unsetfn) _((Param, int)); + GsuHash hash_gsu; + GsuArray array_gsu; Param pm; }; +static const struct gsu_array keymaps_gsu = +{ keymapsgetfn, arrsetfn, stdunsetfn }; + static struct pardef partab[] = { { "widgets", PM_READONLY, - getpmwidgets, scanpmwidgets, hashsetfn, - NULL, NULL, stdunsetfn, NULL }, + getpmwidgets, scanpmwidgets, &stdhash_gsu, + NULL, NULL }, { "keymaps", PM_ARRAY|PM_SPECIAL|PM_READONLY, NULL, NULL, NULL, - arrsetfn, keymapsgetfn, stdunsetfn, NULL }, - { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + &keymaps_gsu, NULL }, + { NULL, 0, NULL, NULL, NULL, NULL, NULL } }; /**/ @@ -215,14 +201,12 @@ boot_(UNUSED(Module m)) def->scantfn))) return 1; def->pm->flags |= def->flags; - if (def->hsetfn) - def->pm->sets.hfn = def->hsetfn; + if (def->hash_gsu) + def->pm->gsu.h = def->hash_gsu; } else { if (!(def->pm = createparam(def->name, def->flags | PM_HIDE))) return 1; - def->pm->sets.afn = def->setfn; - def->pm->gets.afn = def->getfn; - def->pm->unsetfn = def->unsetfn; + def->pm->gsu.a = def->array_gsu; } } return 0; diff --git a/Src/builtin.c b/Src/builtin.c index 3a471760a..a3e7149d9 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -71,7 +71,7 @@ static struct builtin builtins[] = */ BUILTIN("fc", 0, bin_fc, 0, -1, BIN_FC, "nlre:IRWAdDfEimpPa", NULL), BUILTIN("fg", 0, bin_fg, 0, -1, BIN_FG, NULL, NULL), - BUILTIN("float", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "E:%F:%Hghlprtux", "E"), + BUILTIN("float", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "E:%F:%HL:%R:%Z:%ghlprtux", "E"), BUILTIN("functions", BINF_PLUSOPTS, bin_functions, 0, -1, 0, "kmtuUz", NULL), BUILTIN("getln", 0, bin_read, 0, -1, 0, "ecnAlE", "zr"), BUILTIN("getopts", 0, bin_getopts, 2, -1, 0, NULL, NULL), @@ -82,7 +82,7 @@ static struct builtin builtins[] = #endif BUILTIN("history", 0, bin_fc, 0, -1, BIN_FC, "nrdDfEimpPa", "l"), - BUILTIN("integer", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "Hghi:%lprtux", "i"), + BUILTIN("integer", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "HL:%R:%Z:%ghi:%lprtux", "i"), BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL), BUILTIN("kill", 0, bin_kill, 0, -1, 0, NULL, NULL), BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL), @@ -1719,13 +1719,73 @@ enum { NS_SECONDS }; +static const struct gsu_scalar tiedarr_gsu = +{ tiedarrgetfn, tiedarrsetfn, tiedarrunsetfn }; + +/* Install a base if we are turning on a numeric option with an argument */ + +static int +typeset_setbase(const char *name, Param pm, Options ops, int on, int always) +{ + char *arg = NULL; + + if ((on & PM_INTEGER) && OPT_HASARG(ops,'i')) + arg = OPT_ARG(ops,'i'); + else if ((on & PM_EFLOAT) && OPT_HASARG(ops,'E')) + arg = OPT_ARG(ops,'E'); + else if ((on & PM_FFLOAT) && OPT_HASARG(ops,'F')) + arg = OPT_ARG(ops,'F'); + + if (arg) { + char *eptr; + pm->base = (int)zstrtol(arg, &eptr, 10); + if (*eptr) { + if (on & PM_INTEGER) + zwarnnam(name, "bad base value: %s", arg, 0); + else + zwarnnam(name, "bad precision value: %s", arg, 0); + return 1; + } + } else if (always) + pm->base = 0; + + return 0; +} + +/* Install a width if we are turning on a padding option with an argument */ + +static int +typeset_setwidth(const char * name, Param pm, Options ops, int on, int always) +{ + char *arg = NULL; + + if ((on & PM_LEFT) && OPT_HASARG(ops,'L')) + arg = OPT_ARG(ops,'L'); + else if ((on & PM_RIGHT_B) && OPT_HASARG(ops,'R')) + arg = OPT_ARG(ops,'R'); + else if ((on & PM_RIGHT_Z) && OPT_HASARG(ops,'Z')) + arg = OPT_ARG(ops,'Z'); + + if (arg) { + char *eptr; + pm->width = (int)zstrtol(arg, &eptr, 10); + if (*eptr) { + zwarnnam(name, "bad width value: %s", arg, 0); + return 1; + } + } else if (always) + pm->width = 0; + + return 0; +} + /* function to set a single parameter */ /**/ static Param typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), int on, int off, int roff, char *value, Param altpm, - Options ops, int auxlen, int joinchar) + Options ops, int joinchar) { int usepm, tc, keeplocal = 0, newspecial = NS_NONE, readonly; char *subscript; @@ -1862,25 +1922,28 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), Param apm; char **x; if (PM_TYPE(pm->flags) == PM_ARRAY) { - x = (*pm->gets.afn)(pm); + x = (*pm->gsu.a->getfn)(pm); uniqarray(x); if (pm->ename && x) arrfixenv(pm->ename, x); } else if (PM_TYPE(pm->flags) == PM_SCALAR && pm->ename && (apm = (Param) paramtab->getnode(paramtab, pm->ename))) { - x = (*apm->gets.afn)(apm); + x = (*apm->gsu.a->getfn)(apm); uniqarray(x); if (x) arrfixenv(pm->nam, x); } } pm->flags = (pm->flags | (on & ~PM_READONLY)) & ~(off | PM_UNSET); - /* This auxlen/pm->ct stuff is a nasty hack. */ - if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER | - PM_EFLOAT | PM_FFLOAT)) && - auxlen) - pm->ct = auxlen; + if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) { + if (typeset_setwidth(cname, pm, ops, on, 0)) + return NULL; + } + if (on & (PM_INTEGER | PM_EFLOAT | PM_FFLOAT)) { + if (typeset_setbase(cname, pm, ops, on, 0)) + return NULL; + } if (!(pm->flags & (PM_ARRAY|PM_HASHED))) { if (pm->flags & PM_EXPORTED) { if (!(pm->flags & PM_UNSET) && !pm->env && !value) @@ -1960,7 +2023,8 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), } tpm->old = pm->old; tpm->level = pm->level; - tpm->ct = pm->ct; + tpm->base = pm->base; + tpm->width = pm->width; if (pm->env) delenv(pm); tpm->env = NULL; @@ -1981,11 +2045,14 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), * Final tweak: if we've turned on one of the flags with * numbers, we should use the appropriate integer. */ - if (on & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z|PM_INTEGER| - PM_EFLOAT|PM_FFLOAT)) - pm->ct = auxlen; - else - pm->ct = 0; + if (on & (PM_LEFT|PM_RIGHT_B|PM_RIGHT_Z)) { + if (typeset_setwidth(cname, pm, ops, on, 1)) + return NULL; + } + if (on & (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) { + if (typeset_setbase(cname, pm, ops, on, 1)) + return NULL; + } } else if ((subscript = strchr(pname, '['))) { if (on & PM_READONLY) { zerrnam(cname, @@ -2027,7 +2094,14 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), */ pm = createparam(pname, on & ~PM_READONLY); DPUTS(!pm, "BUG: parameter not created"); - pm->ct = auxlen; + if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) { + if (typeset_setwidth(cname, pm, ops, on, 0)) + return NULL; + } + if (on & (PM_INTEGER | PM_EFLOAT | PM_FFLOAT)) { + if (typeset_setbase(cname, pm, ops, on, 0)) + return NULL; + } } else { if (isident(pname)) zerrnam(cname, "not valid in this context: %s", pname, 0); @@ -2049,9 +2123,7 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), tdp->joinchar = joinchar; tdp->arrptr = &altpm->u.arr; - pm->sets.cfn = tiedarrsetfn; - pm->gets.cfn = tiedarrgetfn; - pm->unsetfn = tiedarrunsetfn; + pm->gsu.s = &tiedarr_gsu; pm->u.data = tdp; } @@ -2075,20 +2147,20 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func), */ switch (PM_TYPE(pm->flags)) { case PM_SCALAR: - pm->sets.cfn(pm, ztrdup("")); + pm->gsu.s->setfn(pm, ztrdup("")); break; case PM_INTEGER: - pm->sets.ifn(pm, 0); + pm->gsu.i->setfn(pm, 0); break; case PM_EFLOAT: case PM_FFLOAT: - pm->sets.ffn(pm, 0.0); + pm->gsu.f->setfn(pm, 0.0); break; case PM_ARRAY: - pm->sets.afn(pm, mkarray(NULL)); + pm->gsu.a->setfn(pm, mkarray(NULL)); break; case PM_HASHED: - pm->sets.hfn(pm, newparamtable(17, pm->nam)); + pm->gsu.h->setfn(pm, newparamtable(17, pm->nam)); break; } } @@ -2118,7 +2190,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) char *optstr = TYPESET_OPTSTR; int on = 0, off = 0, roff, bit = PM_ARRAY; int i; - int returnval = 0, printflags = 0, auxlen = 0; + int returnval = 0, printflags = 0; /* hash -f is really the builtin `functions' */ if (OPT_ISSET(ops,'f')) @@ -2134,43 +2206,27 @@ bin_typeset(char *name, char **argv, Options ops, int func) on |= bit; else if (OPT_PLUS(ops,optval)) off |= bit; - /* - * There is only a single field in struct param for widths, - * precisions and bases. Until this gets fixed, we can therefore - * bundle all optional arguments up into a single word. You - * may think this is very nasty, but then you should have seen the - * code before option arguments were handled properly. - */ - if (OPT_HASARG(ops,optval)) { - char *eptr, *arg = OPT_ARG(ops,optval); - auxlen = (int)zstrtol(arg, &eptr, 10); - if (*eptr) { - zwarnnam(name, "bad integer value: %s", arg, 0); - return 1; - } - } } roff = off; /* Sanity checks on the options. Remove conflicting options. */ if (on & PM_FFLOAT) { - off |= PM_RIGHT_B | PM_LEFT | PM_RIGHT_Z | PM_UPPER | PM_ARRAY | - PM_HASHED | PM_INTEGER | PM_EFLOAT; + off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_INTEGER | PM_EFLOAT; /* Allow `float -F' to work even though float sets -E by default */ on &= ~PM_EFLOAT; } if (on & PM_EFLOAT) - off |= PM_RIGHT_B | PM_LEFT | PM_RIGHT_Z | PM_UPPER | PM_ARRAY | - PM_HASHED | PM_INTEGER | PM_FFLOAT; + off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_INTEGER | PM_FFLOAT; if (on & PM_INTEGER) - off |= PM_RIGHT_B | PM_LEFT | PM_RIGHT_Z | PM_UPPER | PM_ARRAY | - PM_HASHED | PM_EFLOAT | PM_FFLOAT; - if (on & PM_LEFT) - off |= PM_RIGHT_B | PM_INTEGER | PM_EFLOAT | PM_FFLOAT; + off |= PM_UPPER | PM_ARRAY | PM_HASHED | PM_EFLOAT | PM_FFLOAT; + /* + * Allowing -Z with -L is a feature: left justify, suppressing + * leading zeroes. + */ + if (on & (PM_LEFT|PM_RIGHT_Z)) + off |= PM_RIGHT_B; if (on & PM_RIGHT_B) - off |= PM_LEFT | PM_INTEGER | PM_EFLOAT | PM_FFLOAT; - if (on & PM_RIGHT_Z) - off |= PM_INTEGER | PM_EFLOAT | PM_FFLOAT; + off |= PM_LEFT | PM_RIGHT_Z; if (on & PM_UPPER) off |= PM_LOWER; if (on & PM_LOWER) @@ -2279,8 +2335,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) (Param)paramtab->getnode(paramtab, asg->name), func, (on | PM_ARRAY) & ~PM_EXPORTED, - off, roff, asg->value, NULL, ops, auxlen, - 0))) { + off, roff, asg->value, NULL, ops, 0))) { unqueue_signals(); return 1; } @@ -2292,7 +2347,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) (Param)paramtab->getnode(paramtab, asg0.name), func, on, off, roff, asg0.value, apm, - ops, auxlen, joinchar))) { + ops, joinchar))) { if (oldval) zsfree(oldval); unsetparam_pm(apm, 1, 1); @@ -2367,7 +2422,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) for (pmnode = firstnode(pmlist); pmnode; incnode(pmnode)) { pm = (Param) getdata(pmnode); if (!typeset_single(name, pm->nam, pm, func, on, off, roff, - asg->value, NULL, ops, auxlen, 0)) + asg->value, NULL, ops, 0)) returnval = 1; } } @@ -2382,7 +2437,7 @@ bin_typeset(char *name, char **argv, Options ops, int func) gethashnode2(paramtab, asg->name) : paramtab->getnode(paramtab, asg->name)), func, on, off, roff, asg->value, NULL, - ops, auxlen, 0)) + ops, 0)) returnval = 1; } unqueue_signals(); @@ -2681,7 +2736,7 @@ bin_unset(char *name, char **argv, Options ops, int func) } else if (ss) { if (PM_TYPE(pm->flags) == PM_HASHED) { HashTable tht = paramtab; - if ((paramtab = pm->gets.hfn(pm))) { + if ((paramtab = pm->gsu.h->getfn(pm))) { *--sse = 0; unsetparam(ss+1); *sse = ']'; diff --git a/Src/exec.c b/Src/exec.c index 49503db0f..47772a502 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2592,20 +2592,20 @@ restore_params(LinkList restorelist, LinkList removelist) tpm->flags = pm->flags; switch (PM_TYPE(pm->flags)) { case PM_SCALAR: - tpm->sets.cfn(tpm, pm->u.str); + tpm->gsu.s->setfn(tpm, pm->u.str); break; case PM_INTEGER: - tpm->sets.ifn(tpm, pm->u.val); + tpm->gsu.i->setfn(tpm, pm->u.val); break; case PM_EFLOAT: case PM_FFLOAT: - tpm->sets.ffn(tpm, pm->u.dval); + tpm->gsu.f->setfn(tpm, pm->u.dval); break; case PM_ARRAY: - tpm->sets.afn(tpm, pm->u.arr); + tpm->gsu.a->setfn(tpm, pm->u.arr); break; case PM_HASHED: - tpm->sets.hfn(tpm, pm->u.hash); + tpm->gsu.h->setfn(tpm, pm->u.hash); break; } pm = tpm; diff --git a/Src/module.c b/Src/module.c index 3e1c0b177..4510d3037 100644 --- a/Src/module.c +++ b/Src/module.c @@ -1894,9 +1894,7 @@ addparamdef(Paramdef d) pm->level = 0; pm->u.data = d->var; - pm->sets.ifn = (void (*)(Param, zlong)) d->set; - pm->gets.ifn = (zlong (*)(Param)) d->get; - pm->unsetfn = (void (*)(Param, int)) d->unset; + pm->gsu.i = (GsuInteger) d->gsu; return 0; } diff --git a/Src/params.c b/Src/params.c index e898f9409..6ebbf58bd 100644 --- a/Src/params.c +++ b/Src/params.c @@ -106,10 +106,114 @@ struct timeval shtimer; /* 0 if this $TERM setup is usable, otherwise it contains TERM_* flags */ - /**/ mod_export int termflags; - + +/* Standard methods for get/set/unset pointers in parameters */ + +/**/ +mod_export const struct gsu_scalar stdscalar_gsu = +{ strgetfn, strsetfn, stdunsetfn }; +/**/ +mod_export const struct gsu_scalar varscalar_gsu = +{ strvargetfn, strvarsetfn, stdunsetfn }; +/**/ +mod_export const struct gsu_scalar nullsetscalar_gsu = +{ strgetfn, nullstrsetfn, NULL }; + +/**/ +mod_export const struct gsu_integer stdinteger_gsu = +{ intgetfn, intsetfn, stdunsetfn }; +/**/ +mod_export const struct gsu_integer varinteger_gsu = +{ intvargetfn, intvarsetfn, stdunsetfn }; +/**/ +mod_export const struct gsu_integer nullsetinteger_gsu = +{ intgetfn, NULL, NULL }; + +/**/ +mod_export const struct gsu_float stdfloat_gsu = +{ floatgetfn, floatsetfn, stdunsetfn }; + +/**/ +mod_export const struct gsu_array stdarray_gsu = +{ arrgetfn, arrsetfn, stdunsetfn }; +/**/ +mod_export const struct gsu_array vararray_gsu = +{ arrvargetfn, arrvarsetfn, stdunsetfn }; + +/**/ +mod_export const struct gsu_hash stdhash_gsu = +{ hashgetfn, hashsetfn, stdunsetfn }; +/**/ +mod_export const struct gsu_hash nullsethash_gsu = +{ hashgetfn, nullsethashfn, NULL }; + + +/* Non standard methods (not exported) */ +static const struct gsu_integer pound_gsu = +{ poundgetfn, nullintsetfn, stdunsetfn }; +static const struct gsu_integer errno_gsu = +{ errnogetfn, errnosetfn, stdunsetfn }; +static const struct gsu_integer gid_gsu = +{ gidgetfn, gidsetfn, stdunsetfn }; +static const struct gsu_integer egid_gsu = +{ egidgetfn, egidsetfn, stdunsetfn }; +static const struct gsu_integer histsize_gsu = +{ histsizegetfn, histsizesetfn, stdunsetfn }; +static const struct gsu_integer random_gsu = +{ randomgetfn, randomsetfn, stdunsetfn }; +static const struct gsu_integer savehist_gsu = +{ savehistsizegetfn, savehistsizesetfn, stdunsetfn }; +static const struct gsu_integer intseconds_gsu = +{ intsecondsgetfn, intsecondssetfn, stdunsetfn }; +static const struct gsu_float floatseconds_gsu = +{ floatsecondsgetfn, floatsecondssetfn, stdunsetfn }; +static const struct gsu_integer uid_gsu = +{ uidgetfn, uidsetfn, stdunsetfn }; +static const struct gsu_integer euid_gsu = +{ euidgetfn, euidsetfn, stdunsetfn }; +static const struct gsu_integer ttyidle_gsu = +{ ttyidlegetfn, nullintsetfn, stdunsetfn }; + +static const struct gsu_scalar username_gsu = +{ usernamegetfn, usernamesetfn, stdunsetfn }; +static const struct gsu_scalar dash_gsu = +{ dashgetfn, nullstrsetfn, stdunsetfn }; +static const struct gsu_scalar histchars_gsu = +{ histcharsgetfn, histcharssetfn, stdunsetfn }; +static const struct gsu_scalar home_gsu = +{ homegetfn, homesetfn, stdunsetfn }; +static const struct gsu_scalar term_gsu = +{ termgetfn, termsetfn, stdunsetfn }; +static const struct gsu_scalar wordchars_gsu = +{ wordcharsgetfn, wordcharssetfn, stdunsetfn }; +static const struct gsu_scalar ifs_gsu = +{ ifsgetfn, ifssetfn, stdunsetfn }; +static const struct gsu_scalar underscore_gsu = +{ underscoregetfn, nullstrsetfn, stdunsetfn }; +#ifdef USE_LOCALE +static const struct gsu_scalar lc_blah_gsu = +{ strgetfn, lcsetfn, stdunsetfn }; +static const struct gsu_scalar lang_gsu = +{ strgetfn, langsetfn, stdunsetfn }; +static const struct gsu_scalar lc_all_gsu = +{ strgetfn, lc_allsetfn, stdunsetfn }; +#endif + +static const struct gsu_integer varint_readonly_gsu = +{ intvargetfn, nullintsetfn, stdunsetfn }; +static const struct gsu_integer zlevar_gsu = +{ intvargetfn, zlevarsetfn, stdunsetfn }; + +static const struct gsu_scalar colonarr_gsu = +{ colonarrgetfn, colonarrsetfn, stdunsetfn }; + +static const struct gsu_integer argc_gsu = +{ poundgetfn, nullintsetfn, stdunsetfn }; +static const struct gsu_array pipestatus_gsu = +{ pipestatgetfn, pipestatsetfn, stdunsetfn }; + /* Nodes for special parameters for parameter hash table */ #ifdef HAVE_UNION_INIT @@ -122,10 +226,9 @@ typedef struct iparam { char *nam; /* hash data */ int flags; /* PM_* flags (defined in zsh.h) */ void *value; - void (*func1) _((void)); /* set func */ - char *(*func2) _((void)); /* get func */ - void (*unsetfn) _((Param, int)); /* unset func */ - int ct; /* output base or field width */ + void *gsu; /* get/set/unset methods */ + int base; /* output base */ + int width; /* output field width */ char *env; /* location in environment, if exported */ char *ename; /* name of corresponding environment var */ Param old; /* old struct for use with local */ @@ -134,35 +237,35 @@ typedef struct iparam { #endif static initparam special_params[] ={ -#define SFN(X) BR(((void (*)_((Param, char *)))(X))) -#define GFN(X) BR(((char *(*)_((Param)))(X))) -#define IPDEF1(A,B,C,D) {NULL,A,PM_INTEGER|PM_SPECIAL|D,BR(NULL),SFN(C),GFN(B),stdunsetfn,10,NULL,NULL,NULL,0} -IPDEF1("#", poundgetfn, nullintsetfn, PM_READONLY), -IPDEF1("ERRNO", errnogetfn, errnosetfn, 0), -IPDEF1("GID", gidgetfn, gidsetfn, PM_DONTIMPORT | PM_RESTRICTED), -IPDEF1("EGID", egidgetfn, egidsetfn, PM_DONTIMPORT | PM_RESTRICTED), -IPDEF1("HISTSIZE", histsizegetfn, histsizesetfn, PM_RESTRICTED), -IPDEF1("RANDOM", randomgetfn, randomsetfn, 0), -IPDEF1("SAVEHIST", savehistsizegetfn, savehistsizesetfn, PM_RESTRICTED), -IPDEF1("SECONDS", intsecondsgetfn, intsecondssetfn, 0), -IPDEF1("UID", uidgetfn, uidsetfn, PM_DONTIMPORT | PM_RESTRICTED), -IPDEF1("EUID", euidgetfn, euidsetfn, PM_DONTIMPORT | PM_RESTRICTED), -IPDEF1("TTYIDLE", ttyidlegetfn, nullintsetfn, PM_READONLY), - -#define IPDEF2(A,B,C,D) {NULL,A,PM_SCALAR|PM_SPECIAL|D,BR(NULL),SFN(C),GFN(B),stdunsetfn,0,NULL,NULL,NULL,0} -IPDEF2("USERNAME", usernamegetfn, usernamesetfn, PM_DONTIMPORT|PM_RESTRICTED), -IPDEF2("-", dashgetfn, nullstrsetfn, PM_READONLY), -IPDEF2("histchars", histcharsgetfn, histcharssetfn, PM_DONTIMPORT), -IPDEF2("HOME", homegetfn, homesetfn, 0), -IPDEF2("TERM", termgetfn, termsetfn, 0), -IPDEF2("WORDCHARS", wordcharsgetfn, wordcharssetfn, 0), -IPDEF2("IFS", ifsgetfn, ifssetfn, PM_DONTIMPORT), -IPDEF2("_", underscoregetfn, nullstrsetfn, PM_READONLY), +#define GSU(X) BR((GsuScalar)(void *)(&(X))) +#define NULL_GSU BR((GsuScalar)(void *)NULL) +#define IPDEF1(A,B,C) {NULL,A,PM_INTEGER|PM_SPECIAL|C,BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0} +IPDEF1("#", pound_gsu, PM_READONLY), +IPDEF1("ERRNO", errno_gsu, 0), +IPDEF1("GID", gid_gsu, PM_DONTIMPORT | PM_RESTRICTED), +IPDEF1("EGID", egid_gsu, PM_DONTIMPORT | PM_RESTRICTED), +IPDEF1("HISTSIZE", histsize_gsu, PM_RESTRICTED), +IPDEF1("RANDOM", random_gsu, 0), +IPDEF1("SAVEHIST", savehist_gsu, PM_RESTRICTED), +IPDEF1("SECONDS", intseconds_gsu, 0), +IPDEF1("UID", uid_gsu, PM_DONTIMPORT | PM_RESTRICTED), +IPDEF1("EUID", euid_gsu, PM_DONTIMPORT | PM_RESTRICTED), +IPDEF1("TTYIDLE", ttyidle_gsu, PM_READONLY), + +#define IPDEF2(A,B,C) {NULL,A,PM_SCALAR|PM_SPECIAL|C,BR(NULL),GSU(B),0,0,NULL,NULL,NULL,0} +IPDEF2("USERNAME", username_gsu, PM_DONTIMPORT|PM_RESTRICTED), +IPDEF2("-", dash_gsu, PM_READONLY), +IPDEF2("histchars", histchars_gsu, PM_DONTIMPORT), +IPDEF2("HOME", home_gsu, 0), +IPDEF2("TERM", term_gsu, 0), +IPDEF2("WORDCHARS", wordchars_gsu, 0), +IPDEF2("IFS", ifs_gsu, PM_DONTIMPORT), +IPDEF2("_", underscore_gsu, PM_READONLY), #ifdef USE_LOCALE -# define LCIPDEF(name) IPDEF2(name, strgetfn, lcsetfn, PM_UNSET) -IPDEF2("LANG", strgetfn, langsetfn, PM_UNSET), -IPDEF2("LC_ALL", strgetfn, lc_allsetfn, PM_UNSET), +# define LCIPDEF(name) IPDEF2(name, lc_blah_gsu, PM_UNSET) +IPDEF2("LANG", lang_gsu, PM_UNSET), +IPDEF2("LC_ALL", lc_all_gsu, PM_UNSET), # ifdef LC_COLLATE LCIPDEF("LC_COLLATE"), # endif @@ -180,7 +283,7 @@ LCIPDEF("LC_TIME"), # endif #endif /* USE_LOCALE */ -#define IPDEF4(A,B) {NULL,A,PM_INTEGER|PM_READONLY|PM_SPECIAL,BR((void *)B),SFN(nullintsetfn),GFN(intvargetfn),stdunsetfn,10,NULL,NULL,NULL,0} +#define IPDEF4(A,B) {NULL,A,PM_INTEGER|PM_READONLY|PM_SPECIAL,BR((void *)B),GSU(varint_readonly_gsu),10,0,NULL,NULL,NULL,0} IPDEF4("!", &lastpid), IPDEF4("$", &mypid), IPDEF4("?", &lastval), @@ -188,14 +291,14 @@ IPDEF4("HISTCMD", &curhist), IPDEF4("LINENO", &lineno), IPDEF4("PPID", &ppid), -#define IPDEF5(A,B,F) {NULL,A,PM_INTEGER|PM_SPECIAL,BR((void *)B),SFN(F),GFN(intvargetfn),stdunsetfn,10,NULL,NULL,NULL,0} -IPDEF5("COLUMNS", &columns, zlevarsetfn), -IPDEF5("LINES", &lines, zlevarsetfn), -IPDEF5("OPTIND", &zoptind, intvarsetfn), -IPDEF5("SHLVL", &shlvl, intvarsetfn), -IPDEF5("TRY_BLOCK_ERROR", &try_errflag, intvarsetfn), +#define IPDEF5(A,B,F) {NULL,A,PM_INTEGER|PM_SPECIAL,BR((void *)B),GSU(varinteger_gsu),10,0,NULL,NULL,NULL,0} +IPDEF5("COLUMNS", &columns, zlevar_gsu), +IPDEF5("LINES", &lines, zlevar_gsu), +IPDEF5("OPTIND", &zoptind, varinteger_gsu), +IPDEF5("SHLVL", &shlvl, varinteger_gsu), +IPDEF5("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu), -#define IPDEF7(A,B) {NULL,A,PM_SCALAR|PM_SPECIAL,BR((void *)B),SFN(strvarsetfn),GFN(strvargetfn),stdunsetfn,0,NULL,NULL,NULL,0} +#define IPDEF7(A,B) {NULL,A,PM_SCALAR|PM_SPECIAL,BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} IPDEF7("OPTARG", &zoptarg), IPDEF7("NULLCMD", &nullcmd), IPDEF7("POSTEDIT", &postedit), @@ -211,7 +314,7 @@ IPDEF7("PS4", &prompt4), IPDEF7("SPROMPT", &sprompt), IPDEF7("0", &argzero), -#define IPDEF8(A,B,C,D) {NULL,A,D|PM_SCALAR|PM_SPECIAL,BR((void *)B),SFN(colonarrsetfn),GFN(colonarrgetfn),stdunsetfn,0,NULL,C,NULL,0} +#define IPDEF8(A,B,C,D) {NULL,A,D|PM_SCALAR|PM_SPECIAL,BR((void *)B),GSU(colonarr_gsu),0,0,NULL,C,NULL,0} IPDEF8("CDPATH", &cdpath, "cdpath", 0), IPDEF8("FIGNORE", &fignore, "fignore", 0), IPDEF8("FPATH", &fpath, "fpath", 0), @@ -223,18 +326,18 @@ IPDEF8("PSVAR", &psvar, "psvar", 0), /* MODULE_PATH is not imported for security reasons */ IPDEF8("MODULE_PATH", &module_path, "module_path", PM_DONTIMPORT|PM_RESTRICTED), -#define IPDEF9F(A,B,C,D) {NULL,A,D|PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT,BR((void *)B),SFN(arrvarsetfn),GFN(arrvargetfn),stdunsetfn,0,NULL,C,NULL,0} +#define IPDEF9F(A,B,C,D) {NULL,A,D|PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT,BR((void *)B),GSU(vararray_gsu),0,0,NULL,C,NULL,0} #define IPDEF9(A,B,C) IPDEF9F(A,B,C,0) IPDEF9F("*", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), IPDEF9F("@", &pparams, NULL, PM_ARRAY|PM_SPECIAL|PM_DONTIMPORT|PM_READONLY), -{NULL,NULL,0,BR(NULL),SFN(NULL),GFN(NULL),NULL,0,NULL,NULL,NULL,0}, +{NULL,NULL,0,BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0}, -#define IPDEF10(A,B,C) {NULL,A,PM_ARRAY|PM_SPECIAL,BR(NULL),SFN(C),GFN(B),stdunsetfn,10,NULL,NULL,NULL,0} +#define IPDEF10(A,B) {NULL,A,PM_ARRAY|PM_SPECIAL,BR(NULL),GSU(B),10,0,NULL,NULL,NULL,0} /* The following parameters are not available in sh/ksh compatibility * * mode. All of these have sh compatible equivalents. */ -IPDEF1("ARGC", poundgetfn, nullintsetfn, PM_READONLY), -IPDEF2("HISTCHARS", histcharsgetfn, histcharssetfn, PM_DONTIMPORT), +IPDEF1("ARGC", argc_gsu, PM_READONLY), +IPDEF2("HISTCHARS", histchars_gsu, PM_DONTIMPORT), IPDEF4("status", &lastval), IPDEF7("prompt", &prompt), IPDEF7("PROMPT", &prompt), @@ -254,9 +357,9 @@ IPDEF9("watch", &watch, "WATCH"), IPDEF9F("module_path", &module_path, "MODULE_PATH", PM_RESTRICTED), IPDEF9F("path", &path, "PATH", PM_RESTRICTED), -IPDEF10("pipestatus", pipestatgetfn, pipestatsetfn), +IPDEF10("pipestatus", pipestatus_gsu), -{NULL,NULL,0,BR(NULL),SFN(NULL),GFN(NULL),NULL,0,NULL,NULL,NULL,0}, +{NULL,NULL,0,BR(NULL),NULL_GSU,0,0,NULL,NULL,NULL,0}, }; /* @@ -456,9 +559,9 @@ getvaluearr(Value v) if (v->arr) return v->arr; else if (PM_TYPE(v->pm->flags) == PM_ARRAY) - return v->arr = v->pm->gets.afn(v->pm); + return v->arr = v->pm->gsu.a->getfn(v->pm); else if (PM_TYPE(v->pm->flags) == PM_HASHED) { - v->arr = paramvalarr(v->pm->gets.hfn(v->pm), v->isarr); + v->arr = paramvalarr(v->pm->gsu.h->getfn(v->pm), v->isarr); /* Can't take numeric slices of associative arrays */ v->start = 0; v->end = numparamvals + 1; @@ -631,31 +734,25 @@ assigngetset(Param pm) { switch (PM_TYPE(pm->flags)) { case PM_SCALAR: - pm->sets.cfn = strsetfn; - pm->gets.cfn = strgetfn; + pm->gsu.s = &stdscalar_gsu; break; case PM_INTEGER: - pm->sets.ifn = intsetfn; - pm->gets.ifn = intgetfn; + pm->gsu.i = &stdinteger_gsu; break; case PM_EFLOAT: case PM_FFLOAT: - pm->sets.ffn = floatsetfn; - pm->gets.ffn = floatgetfn; + pm->gsu.f = &stdfloat_gsu; break; case PM_ARRAY: - pm->sets.afn = arrsetfn; - pm->gets.afn = arrgetfn; + pm->gsu.a = &stdarray_gsu; break; case PM_HASHED: - pm->sets.hfn = hashsetfn; - pm->gets.hfn = hashgetfn; + pm->gsu.h = &stdhash_gsu; break; default: DPUTS(1, "BUG: tried to create param node without valid flag"); break; } - pm->unsetfn = stdunsetfn; } /* Create a parameter, so that it can be assigned to. Returns NULL if the * @@ -699,7 +796,7 @@ createparam(char *name, int flags) } pm = oldpm; - pm->ct = 0; + pm->base = pm->width = 0; oldpm = pm->old; } else { pm = (Param) zshcalloc(sizeof *pm); @@ -741,25 +838,26 @@ copyparam(Param tpm, Param pm, int toplevel) * with sets.?fn() usage). */ tpm->flags = pm->flags; - tpm->ct = pm->ct; + tpm->base = pm->base; + tpm->width = pm->width; if (!toplevel) tpm->flags &= ~PM_SPECIAL; switch (PM_TYPE(pm->flags)) { case PM_SCALAR: - tpm->u.str = ztrdup(pm->gets.cfn(pm)); + tpm->u.str = ztrdup(pm->gsu.s->getfn(pm)); break; case PM_INTEGER: - tpm->u.val = pm->gets.ifn(pm); + tpm->u.val = pm->gsu.i->getfn(pm); break; case PM_EFLOAT: case PM_FFLOAT: - tpm->u.dval = pm->gets.ffn(pm); + tpm->u.dval = pm->gsu.f->getfn(pm); break; case PM_ARRAY: - tpm->u.arr = zarrdup(pm->gets.afn(pm)); + tpm->u.arr = zarrdup(pm->gsu.a->getfn(pm)); break; case PM_HASHED: - tpm->u.hash = copyparamtable(pm->gets.hfn(pm), pm->nam); + tpm->u.hash = copyparamtable(pm->gsu.h->getfn(pm), pm->nam); break; } /* @@ -985,10 +1083,10 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w) remnulargs(s); /* This is probably always a no-op, but ... */ if (!rev) { if (ishash) { - HashTable ht = v->pm->gets.hfn(v->pm); + HashTable ht = v->pm->gsu.h->getfn(v->pm); if (!ht) { ht = newparamtable(17, v->pm->nam); - v->pm->sets.hfn(v->pm, ht); + v->pm->gsu.h->setfn(v->pm, ht); } untokenize(s); if (!(v->pm = (Param) ht->getnode(ht, s))) { @@ -1447,15 +1545,16 @@ getstrvalue(Value v) } return s; case PM_INTEGER: - convbase(buf, v->pm->gets.ifn(v->pm), v->pm->ct); + convbase(buf, v->pm->gsu.i->getfn(v->pm), v->pm->base); s = dupstring(buf); break; case PM_EFLOAT: case PM_FFLOAT: - s = convfloat(v->pm->gets.ffn(v->pm), v->pm->ct, v->pm->flags, NULL); + s = convfloat(v->pm->gsu.f->getfn(v->pm), + v->pm->base, v->pm->flags, NULL); break; case PM_SCALAR: - s = v->pm->gets.cfn(v->pm); + s = v->pm->gsu.s->getfn(v->pm); break; default: s = NULL; @@ -1526,9 +1625,9 @@ getintvalue(Value v) if (v->inv) return v->start; if (PM_TYPE(v->pm->flags) == PM_INTEGER) - return v->pm->gets.ifn(v->pm); + return v->pm->gsu.i->getfn(v->pm); if (v->pm->flags & (PM_EFLOAT|PM_FFLOAT)) - return (zlong)v->pm->gets.ffn(v->pm); + return (zlong)v->pm->gsu.f->getfn(v->pm); return mathevali(getstrvalue(v)); } @@ -1544,10 +1643,10 @@ getnumvalue(Value v) } else if (v->inv) { mn.u.l = v->start; } else if (PM_TYPE(v->pm->flags) == PM_INTEGER) { - mn.u.l = v->pm->gets.ifn(v->pm); + mn.u.l = v->pm->gsu.i->getfn(v->pm); } else if (v->pm->flags & (PM_EFLOAT|PM_FFLOAT)) { mn.type = MN_FLOAT; - mn.u.d = v->pm->gets.ffn(v->pm); + mn.u.d = v->pm->gsu.f->getfn(v->pm); } else return matheval(getstrvalue(v)); return mn; @@ -1572,12 +1671,12 @@ export_param(Param pm) #endif return; } else if (PM_TYPE(pm->flags) == PM_INTEGER) - convbase(val = buf, pm->gets.ifn(pm), pm->ct); + convbase(val = buf, pm->gsu.i->getfn(pm), pm->base); else if (pm->flags & (PM_EFLOAT|PM_FFLOAT)) - val = convfloat(pm->gets.ffn(pm), pm->ct, + val = convfloat(pm->gsu.f->getfn(pm), pm->base, pm->flags, NULL); else - val = pm->gets.cfn(pm); + val = pm->gsu.s->getfn(pm); addenv(pm, val); } @@ -1605,14 +1704,15 @@ setstrvalue(Value v, char *val) switch (PM_TYPE(v->pm->flags)) { case PM_SCALAR: if (v->start == 0 && v->end == -1) { - (v->pm->sets.cfn) (v->pm, val); - if (v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z) && !v->pm->ct) - v->pm->ct = strlen(val); + v->pm->gsu.s->setfn(v->pm, val); + if ((v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) && + !v->pm->width) + v->pm->width = strlen(val); } else { char *z, *x; int zlen; - z = dupstring((v->pm->gets.cfn) (v->pm)); + z = dupstring(v->pm->gsu.s->getfn(v->pm)); zlen = strlen(z); if (v->inv && unset(KSHARRAYS)) v->start--, v->end--; @@ -1631,25 +1731,31 @@ setstrvalue(Value v, char *val) strncpy(x, z, v->start); strcpy(x + v->start, val); strcat(x + v->start, z + v->end); - (v->pm->sets.cfn) (v->pm, x); + v->pm->gsu.s->setfn(v->pm, x); zsfree(val); } break; case PM_INTEGER: if (val) { - (v->pm->sets.ifn) (v->pm, mathevali(val)); + v->pm->gsu.i->setfn(v->pm, mathevali(val)); zsfree(val); + if ((v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) && + !v->pm->width) + v->pm->width = strlen(val); } - if (!v->pm->ct && lastbase != -1) - v->pm->ct = lastbase; + if (!v->pm->base && lastbase != -1) + v->pm->base = lastbase; break; case PM_EFLOAT: case PM_FFLOAT: if (val) { mnumber mn = matheval(val); - (v->pm->sets.ffn) (v->pm, (mn.type & MN_FLOAT) ? mn.u.d : + v->pm->gsu.f->setfn(v->pm, (mn.type & MN_FLOAT) ? mn.u.d : (double)mn.u.l); zsfree(val); + if ((v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) && + !v->pm->width) + v->pm->width = strlen(val); } break; case PM_ARRAY: @@ -1663,7 +1769,7 @@ setstrvalue(Value v, char *val) break; case PM_HASHED: { - (foundparam->sets.cfn) (foundparam, val); + foundparam->gsu.s->setfn(foundparam, val); } break; } @@ -1700,14 +1806,14 @@ setnumvalue(Value v, mnumber val) setstrvalue(v, ztrdup(p)); break; case PM_INTEGER: - (v->pm->sets.ifn) (v->pm, (val.type & MN_INTEGER) ? val.u.l : - (zlong) val.u.d); + v->pm->gsu.i->setfn(v->pm, (val.type & MN_INTEGER) ? val.u.l : + (zlong) val.u.d); setstrvalue(v, NULL); break; case PM_EFLOAT: case PM_FFLOAT: - (v->pm->sets.ffn) (v->pm, (val.type & MN_INTEGER) ? - (double)val.u.l : val.u.d); + v->pm->gsu.f->setfn(v->pm, (val.type & MN_INTEGER) ? + (double)val.u.l : val.u.d); setstrvalue(v, NULL); break; } @@ -1737,7 +1843,7 @@ setarrvalue(Value v, char **val) if (PM_TYPE(v->pm->flags) == PM_HASHED) arrhashsetfn(v->pm, val, 0); else - (v->pm->sets.afn) (v->pm, val); + v->pm->gsu.a->setfn(v->pm, val); } else if (v->start == -1 && v->end == 0 && PM_TYPE(v->pm->flags) == PM_HASHED) { arrhashsetfn(v->pm, val, 1); @@ -1758,7 +1864,7 @@ setarrvalue(Value v, char **val) } if (v->end < v->start) v->end = v->start; - q = old = v->pm->gets.afn(v->pm); + q = old = v->pm->gsu.a->getfn(v->pm); n = arrlen(old); if (v->start < 0) { v->start += n; @@ -1786,7 +1892,7 @@ setarrvalue(Value v, char **val) *p++ = ztrdup(*q++); *p = NULL; - (v->pm->sets.afn) (v->pm, new); + v->pm->gsu.a->setfn(v->pm, new); freearray(val); } } @@ -1848,7 +1954,7 @@ getaparam(char *s) if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) && PM_TYPE(v->pm->flags) == PM_ARRAY) - return v->pm->gets.afn(v->pm); + return v->pm->gsu.a->getfn(v->pm); return NULL; } @@ -1863,7 +1969,7 @@ gethparam(char *s) if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) && PM_TYPE(v->pm->flags) == PM_HASHED) - return paramvalarr(v->pm->gets.hfn(v->pm), SCANPM_WANTVALS); + return paramvalarr(v->pm->gsu.h->getfn(v->pm), SCANPM_WANTVALS); return NULL; } @@ -1878,7 +1984,7 @@ gethkparam(char *s) if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) && PM_TYPE(v->pm->flags) == PM_HASHED) - return paramvalarr(v->pm->gets.hfn(v->pm), SCANPM_WANTKEYS); + return paramvalarr(v->pm->gsu.h->getfn(v->pm), SCANPM_WANTKEYS); return NULL; } @@ -1952,7 +2058,7 @@ assignsparam(char *s, char *val, int augment) return v->pm; /* avoid later setstrvalue() call */ case PM_ARRAY: if (unset(KSHARRAYS)) { - v->start = arrlen(v->pm->gets.afn(v->pm)); + v->start = arrlen(v->pm->gsu.a->getfn(v->pm)); v->end = v->start + 1; } else { /* ksh appends scalar to first element */ @@ -1967,7 +2073,7 @@ assignsparam(char *s, char *val, int augment) if (v->end > 0) v->start = v->end; else - v->start = v->end = strlen(v->pm->gets.cfn(v->pm)) + + v->start = v->end = strlen(v->pm->gsu.s->getfn(v->pm)) + v->end + 1; break; case PM_INTEGER: @@ -2064,7 +2170,7 @@ assignaparam(char *s, char **val, int augment) if (augment) { if (v->start == 0 && v->end == -1) { if (PM_TYPE(v->pm->flags) & PM_ARRAY) { - v->start = arrlen(v->pm->gets.afn(v->pm)); + v->start = arrlen(v->pm->gsu.a->getfn(v->pm)); v->end = v->start + 1; } else if (PM_TYPE(v->pm->flags) & PM_HASHED) v->start = -1, v->end = 0; @@ -2072,7 +2178,7 @@ assignaparam(char *s, char **val, int augment) if (v->end > 0) v->start = v->end--; else if (PM_TYPE(v->pm->flags) & PM_ARRAY) { - v->end = arrlen(v->pm->gets.afn(v->pm)) + v->end; + v->end = arrlen(v->pm->gsu.a->getfn(v->pm)) + v->end; v->start = v->end + 1; } } @@ -2147,7 +2253,7 @@ setiparam(char *s, zlong val) if (ss) { *ss = '['; } else { - pm->ct = outputradix; + pm->base = outputradix; } v = getvalue(&vbuf, &t, 1); DPUTS(!v, "BUG: value not found for new parameter"); @@ -2190,7 +2296,7 @@ setnparam(char *s, mnumber val) if (ss) { *ss = '['; } else if (val.type & MN_INTEGER) { - pm->ct = outputradix; + pm->base = outputradix; } v = getvalue(&vbuf, &t, 1); DPUTS(!v, "BUG: value not found for new parameter"); @@ -2232,7 +2338,7 @@ unsetparam_pm(Param pm, int altflag, int exp) zerr("%s: restricted", pm->nam, 0); return 1; } - pm->unsetfn(pm, exp); + pm->gsu.s->unsetfn(pm, exp); if (pm->env) delenv(pm); @@ -2281,7 +2387,7 @@ unsetparam_pm(Param pm, int altflag, int exp) if ((PM_TYPE(oldpm->flags) == PM_SCALAR) && !(pm->flags & PM_HASHELEM) && (oldpm->flags & PM_NAMEDDIR) && - oldpm->sets.cfn == strsetfn) + oldpm->gsu.s == &stdscalar_gsu) adduserdir(oldpm->nam, oldpm->u.str, 0, 0); if (oldpm->flags & PM_EXPORTED) { /* @@ -2300,16 +2406,20 @@ unsetparam_pm(Param pm, int altflag, int exp) } /* Standard function to unset a parameter. This is mostly delegated to * - * the specific set function. */ + * the specific set function. + * + * This could usefully be made type-specific, but then we need + * to be more careful when calling the unset method directly. + */ /**/ mod_export void stdunsetfn(Param pm, UNUSED(int exp)) { switch (PM_TYPE(pm->flags)) { - case PM_SCALAR: pm->sets.cfn(pm, NULL); break; - case PM_ARRAY: pm->sets.afn(pm, NULL); break; - case PM_HASHED: pm->sets.hfn(pm, NULL); break; + case PM_SCALAR: pm->gsu.s->setfn(pm, NULL); break; + case PM_ARRAY: pm->gsu.a->setfn(pm, NULL); break; + case PM_HASHED: pm->gsu.h->setfn(pm, NULL); break; default: if (!(pm->flags & PM_SPECIAL)) pm->u.str = NULL; @@ -2425,6 +2535,15 @@ hashsetfn(Param pm, HashTable x) pm->u.hash = x; } +/* Function to dispose of setting of an unsettable hash */ + +/**/ +mod_export void +nullsethashfn(Param pm, HashTable x) +{ + deleteparamtable(x); +} + /* Function to set value of an association parameter using key/value pairs */ /**/ @@ -2433,7 +2552,7 @@ arrhashsetfn(Param pm, char **val, int augment) { /* Best not to shortcut this by using the existing hash table, * * since that could cause trouble for special hashes. This way, * - * it's up to pm->sets.hfn() what to do. */ + * it's up to pm->gsu.h->setfn() what to do. */ int alen = arrlen(val); HashTable opmtab = paramtab, ht = 0; char **aptr = val; @@ -2447,7 +2566,7 @@ arrhashsetfn(Param pm, char **val, int augment) return; } if (alen) - if (!(augment && (ht = paramtab = pm->gets.hfn(pm)))) + if (!(augment && (ht = paramtab = pm->gsu.h->getfn(pm)))) ht = paramtab = newparamtable(17, pm->nam); while (*aptr) { /* The parameter name is ztrdup'd... */ @@ -2463,7 +2582,7 @@ arrhashsetfn(Param pm, char **val, int augment) setstrvalue(v, *aptr++); } paramtab = opmtab; - pm->sets.hfn(pm, ht); + pm->gsu.h->setfn(pm, ht); free(val); /* not freearray() */ } @@ -2671,7 +2790,7 @@ tiedarrunsetfn(Param pm, UNUSED(int exp)) * in typeset_single to hold the special data which we now * need to delete. */ - pm->sets.cfn(pm, NULL); + pm->gsu.s->setfn(pm, NULL); zfree(pm->u.data, sizeof(struct tieddata)); /* paranoia -- shouldn't need these, but in case we reuse the struct... */ pm->u.data = NULL; @@ -2822,13 +2941,11 @@ setsecondstype(Param pm, int on, int off) /* Only one of the numeric types is allowed. */ if (tp == PM_EFLOAT || tp == PM_FFLOAT) { - pm->gets.ffn = floatsecondsgetfn; - pm->sets.ffn = floatsecondssetfn; + pm->gsu.f = &floatseconds_gsu; } else if (tp == PM_INTEGER) { - pm->gets.ifn = intsecondsgetfn; - pm->sets.ifn = intsecondssetfn; + pm->gsu.i = &intseconds_gsu; } else return 1; @@ -2881,10 +2998,10 @@ uidgetfn(UNUSED(Param pm)) /**/ void -uidsetfn(UNUSED(Param pm), uid_t x) +uidsetfn(UNUSED(Param pm), zlong x) { #ifdef HAVE_SETUID - setuid(x); + setuid((uid_t)x); #endif } @@ -2901,10 +3018,10 @@ euidgetfn(UNUSED(Param pm)) /**/ void -euidsetfn(UNUSED(Param pm), uid_t x) +euidsetfn(UNUSED(Param pm), zlong x) { #ifdef HAVE_SETEUID - seteuid(x); + seteuid((uid_t)x); #endif } @@ -2921,10 +3038,10 @@ gidgetfn(UNUSED(Param pm)) /**/ void -gidsetfn(UNUSED(Param pm), gid_t x) +gidsetfn(UNUSED(Param pm), zlong x) { #ifdef HAVE_SETUID - setgid(x); + setgid((gid_t)x); #endif } @@ -2941,10 +3058,10 @@ egidgetfn(UNUSED(Param pm)) /**/ void -egidsetfn(UNUSED(Param pm), gid_t x) +egidsetfn(UNUSED(Param pm), zlong x) { #ifdef HAVE_SETEUID - setegid(x); + setegid((gid_t)x); #endif } @@ -3650,27 +3767,28 @@ scanendscope(HashNode hn, UNUSED(int flags)) pm->old = tpm->old; pm->flags = (tpm->flags & ~PM_NORESTORE); pm->level = tpm->level; - pm->ct = tpm->ct; + pm->base = tpm->base; + pm->width = tpm->width; if (pm->env) delenv(pm); if (!(tpm->flags & PM_NORESTORE)) switch (PM_TYPE(pm->flags)) { case PM_SCALAR: - pm->sets.cfn(pm, tpm->u.str); + pm->gsu.s->setfn(pm, tpm->u.str); break; case PM_INTEGER: - pm->sets.ifn(pm, tpm->u.val); + pm->gsu.i->setfn(pm, tpm->u.val); break; case PM_EFLOAT: case PM_FFLOAT: - pm->sets.ffn(pm, tpm->u.dval); + pm->gsu.f->setfn(pm, tpm->u.dval); break; case PM_ARRAY: - pm->sets.afn(pm, tpm->u.arr); + pm->gsu.a->setfn(pm, tpm->u.arr); break; case PM_HASHED: - pm->sets.hfn(pm, tpm->u.hash); + pm->gsu.h->setfn(pm, tpm->u.hash); break; } zfree(tpm, sizeof(*tpm)); @@ -3696,7 +3814,7 @@ freeparamnode(HashNode hn) /* Since the second flag to unsetfn isn't used, I don't * * know what its value should be. */ if (delunset) - pm->unsetfn(pm, 1); + pm->gsu.s->unsetfn(pm, 1); zsfree(pm->nam); /* If this variable was tied by the user, ename was ztrdup'd */ if (pm->flags & PM_TIED) @@ -3707,8 +3825,9 @@ freeparamnode(HashNode hn) /* Print a parameter */ enum paramtypes_flags { - PMTF_USE_CT = (1<<0), - PMTF_TEST_LEVEL = (1<<1) + PMTF_USE_BASE = (1<<0), + PMTF_USE_WIDTH = (1<<1), + PMTF_TEST_LEVEL = (1<<2) }; struct paramtypes { @@ -3720,15 +3839,15 @@ struct paramtypes { static const struct paramtypes pmtypes[] = { { PM_AUTOLOAD, "undefined", 0, 0}, - { PM_INTEGER, "integer", 'i', PMTF_USE_CT}, + { PM_INTEGER, "integer", 'i', PMTF_USE_BASE}, { PM_EFLOAT, "float", 'E', 0}, { PM_FFLOAT, "float", 'F', 0}, { PM_ARRAY, "array", 'a', 0}, { PM_HASHED, "association", 'A', 0}, { 0, "local", 0, PMTF_TEST_LEVEL}, - { PM_LEFT, "left justified", 'L', PMTF_USE_CT}, - { PM_RIGHT_B, "right justified", 'R', PMTF_USE_CT}, - { PM_RIGHT_Z, "zero filled", 'Z', PMTF_USE_CT}, + { PM_LEFT, "left justified", 'L', PMTF_USE_WIDTH}, + { PM_RIGHT_B, "right justified", 'R', PMTF_USE_WIDTH}, + { PM_RIGHT_Z, "zero filled", 'Z', PMTF_USE_WIDTH}, { PM_LOWER, "lowercase", 'l', 0}, { PM_UPPER, "uppercase", 'u', 0}, { PM_READONLY, "readonly", 'r', 0}, @@ -3776,8 +3895,12 @@ printparamnode(HashNode hn, int printflags) } else { printf("%s ", pmptr->string); } - if ((pmptr->flags & PMTF_USE_CT) && p->ct) { - printf("%d ", p->ct); + if ((pmptr->flags & PMTF_USE_BASE) && p->base) { + printf("%d ", p->base); + doneminus = 0; + } + if ((pmptr->flags & PMTF_USE_WIDTH) && p->width) { + printf("%d ", p->width); doneminus = 0; } } @@ -3812,27 +3935,27 @@ printparamnode(HashNode hn, int printflags) switch (PM_TYPE(p->flags)) { case PM_SCALAR: /* string: simple output */ - if (p->gets.cfn && (t = p->gets.cfn(p))) + if (p->gsu.s->getfn && (t = p->gsu.s->getfn(p))) quotedzputs(t, stdout); break; case PM_INTEGER: /* integer */ #ifdef ZSH_64_BIT_TYPE - fputs(output64(p->gets.ifn(p)), stdout); + fputs(output64(p->gsu.i->getfn(p)), stdout); #else - printf("%ld", p->gets.ifn(p)); + printf("%ld", p->gsu.i->getfn(p)); #endif break; case PM_EFLOAT: case PM_FFLOAT: /* float */ - convfloat(p->gets.ffn(p), p->ct, p->flags, stdout); + convfloat(p->gsu.f->getfn(p), p->base, p->flags, stdout); break; case PM_ARRAY: /* array */ if (!(printflags & PRINT_KV_PAIR)) putchar('('); - u = p->gets.afn(p); + u = p->gsu.a->getfn(p); if(*u) { quotedzputs(*u++, stdout); while (*u) { @@ -3848,7 +3971,7 @@ printparamnode(HashNode hn, int printflags) if (!(printflags & PRINT_KV_PAIR)) putchar('('); { - HashTable ht = p->gets.hfn(p); + HashTable ht = p->gsu.h->getfn(p); if (ht) scanhashtable(ht, 0, 0, PM_UNSET, ht->printnode, PRINT_KV_PAIR); diff --git a/Src/subst.c b/Src/subst.c index da3db5844..defb53bd9 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -1649,7 +1649,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) * necessary joining of arrays until this point * to avoid the multsub() horror. */ - int tmplen = arrlen(v->pm->gets.afn(v->pm)); + int tmplen = arrlen(v->pm->gsu.a->getfn(v->pm)); if (v->start < 0) v->start += tmplen + v->inv; @@ -1667,7 +1667,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) * Bet that's easier said than done. */ val = getstrvalue(v); - fwidth = v->pm->ct ? v->pm->ct : (int)strlen(val); + fwidth = v->pm->width ? v->pm->width : (int)strlen(val); switch (v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) { char *t; unsigned int t0; @@ -1695,17 +1695,67 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) int zero = 1; if (strlen(val) < fwidth) { + char *valprefend = val; if (v->pm->flags & PM_RIGHT_Z) { - for (t = val; iblank(*t); t++); - if (!*t || !idigit(*t)) + /* + * This is a documented feature: when deciding + * whether to pad with zeroes, ignore + * leading blanks already in the value; + * only look for numbers after that. + * Not sure how useful this really is. + * It's certainly confusing to code around. + */ + for (t = val; iblank(*t); t++) + ; + /* + * Allow padding after initial minus + * for numeric variables. + */ + if ((v->pm->flags & + (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) && + *t == '-') + t++; + /* + * Allow padding after initial 0x or + * base# for integer variables. + */ + if (v->pm->flags & PM_INTEGER) { + if (isset(CBASES) && + t[0] == '0' && t[1] == 'x') + t += 2; + else if ((valprefend = strchr(t, '#'))) + t = valprefend + 1; + } + valprefend = t; + if (!*t) + zero = 0; + else if (v->pm->flags & + (PM_INTEGER|PM_EFLOAT|PM_FFLOAT)) { + /* zero always OK */ + } else if (!idigit(*t)) zero = 0; } t = (char *) hcalloc(fwidth + 1); memset(t, (((v->pm->flags & PM_RIGHT_B) || !zero) ? ' ' : '0'), fwidth); + /* + * How can the following trigger? We + * haven't altered val or fwidth since + * the last time we tested this. + */ if ((t0 = strlen(val)) > fwidth) t0 = fwidth; - strcpy(t + (fwidth - t0), val); + /* + * Copy - or 0x or base# before any padding + * zeroes. + */ + if (zero && val != valprefend) { + int preflen = valprefend - val; + memcpy(t, val, preflen); + strcpy(t + (fwidth - t0) + preflen, + valprefend); + } else + strcpy(t + (fwidth - t0), val); val = t; } else { t = (char *) hcalloc(fwidth + 1); @@ -2019,7 +2069,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) if (arrasg > 1) { Param pm = sethparam(idbeg, a); if (pm) - aval = paramvalarr(pm->gets.hfn(pm), hkeys|hvals); + aval = paramvalarr(pm->gsu.h->getfn(pm), hkeys|hvals); } else setaparam(idbeg, a); } else { diff --git a/Src/zsh.h b/Src/zsh.h index 655737e30..065712457 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1123,6 +1123,49 @@ struct patprog { #define dummy_patprog1 ((Patprog) 1) #define dummy_patprog2 ((Patprog) 2) +/* standard node types for get/set/unset union in parameter */ + +/* + * note non-standard const in pointer declaration: structures are + * assumed to be read-only. + */ +typedef const struct gsu_scalar *GsuScalar; +typedef const struct gsu_integer *GsuInteger; +typedef const struct gsu_float *GsuFloat; +typedef const struct gsu_array *GsuArray; +typedef const struct gsu_hash *GsuHash; + +struct gsu_scalar { + char *(*getfn) _((Param)); + void (*setfn) _((Param, char *)); + void (*unsetfn) _((Param, int)); +}; + +struct gsu_integer { + zlong (*getfn) _((Param)); + void (*setfn) _((Param, zlong)); + void (*unsetfn) _((Param, int)); +}; + +struct gsu_float { + double (*getfn) _((Param)); + void (*setfn) _((Param, double)); + void (*unsetfn) _((Param, int)); +}; + +struct gsu_array { + char **(*getfn) _((Param)); + void (*setfn) _((Param, char **)); + void (*unsetfn) _((Param, int)); +}; + +struct gsu_hash { + HashTable (*getfn) _((Param)); + void (*setfn) _((Param, HashTable)); + void (*unsetfn) _((Param, int)); +}; + + /* node used in parameter hash table (paramtab) */ struct param { @@ -1142,28 +1185,24 @@ struct param { HashTable hash; /* value if declared assoc (PM_HASHED) */ } u; - /* pointer to function to set value of this parameter */ - union { - void (*cfn) _((Param, char *)); - void (*ifn) _((Param, zlong)); - void (*ffn) _((Param, double)); - void (*afn) _((Param, char **)); - void (*hfn) _((Param, HashTable)); - } sets; - - /* pointer to function to get value of this parameter */ + /* + * get/set/unset methods. + * + * Unlike the data union, this points to a single instance + * for every type (although there are special types, e.g. + * tied arrays have a different gsu_scalar struct from the + * normal one). It's really a poor man's vtable. + */ union { - char *(*cfn) _((Param)); - zlong (*ifn) _((Param)); - double (*ffn) _((Param)); - char **(*afn) _((Param)); - HashTable (*hfn) _((Param)); - } gets; - - /* pointer to function to unset this parameter */ - void (*unsetfn) _((Param, int)); - - int ct; /* output base or field width */ + GsuScalar s; + GsuInteger i; + GsuFloat f; + GsuArray a; + GsuHash h; + } gsu; + + int base; /* output base or floating point prec */ + int width; /* field width */ char *env; /* location in environment, if exported */ char *ename; /* name of corresponding environment var */ Param old; /* old struct for use with local */ @@ -1272,22 +1311,17 @@ struct paramdef { char *name; int flags; void *var; - void *set; - void *get; - void *unset; + void *gsu; /* get/set/unset structure */ }; -#define PARAMDEF(name, flags, var, set, get, unset) \ - { name, flags, (void *) var, (void *) set, (void *) get, (void *) unset } +#define PARAMDEF(name, flags, var, gsu) \ + { name, flags, (void *) var, (void *) gsu, } #define INTPARAMDEF(name, var) \ - { name, PM_INTEGER, (void *) var, (void *) intvarsetfn, \ - (void *) intvargetfn, (void *) stdunsetfn } + { name, PM_INTEGER, (void *) var, (void *) &stdinteger_gsu } #define STRPARAMDEF(name, var) \ - { name, PM_SCALAR, (void *) var, (void *) strvarsetfn, \ - (void *) strvargetfn, (void *) stdunsetfn } + { name, PM_SCALAR, (void *) var, (void *) &varscalar_gsu } #define ARRPARAMDEF(name, var) \ - { name, PM_ARRAY, (void *) var, (void *) arrvarsetfn, \ - (void *) arrvargetfn, (void *) stdunsetfn } + { name, PM_ARRAY, (void *) var, (void *) &vararray_gsu } #define setsparam(S,V) assignsparam(S,V,0) #define setaparam(S,V) assignaparam(S,V,0) diff --git a/Test/B02typeset.ztst b/Test/B02typeset.ztst index 752a8e94a..0d7f0dcd5 100644 --- a/Test/B02typeset.ztst +++ b/Test/B02typeset.ztst @@ -18,7 +18,6 @@ # Function tracing (typeset -ft) E02xtrace # Not yet tested: -# Justification (-L, -R, -Z) # Case conversion (-l, -u) # Assorted illegal flag combinations @@ -244,6 +243,99 @@ 0:Local scalar subscript assignment >abc + typeset -L 10 fools + for fools in " once" "twice" " thrice" " oops too long here"; do + print "'$fools'" + done +0:Left justification of scalars +>'once ' +>'twice ' +>'thrice ' +>'oops too l' + + typeset -L 10 -F 3 foolf + for foolf in 1.3 4.6 -2.987 -4.91031; do + print "'$foolf'" + done +0:Left justification of floating point +>'1.300 ' +>'4.600 ' +>'-2.987 ' +>'-4.910 ' + + typeset -L 10 -Z foolzs + for foolzs in 001.3 04.6 -2.987 -04.91231; do + print "'$foolzs'" + done +0:Left justification of scalars with zero suppression +>'1.3 ' +>'4.6 ' +>'-2.987 ' +>'-04.91231 ' + + typeset -R 10 foors + for foors in short longer even-longer; do + print "'$foors'" + done +0:Right justification of scalars +>' short' +>' longer' +>'ven-longer' + + typeset -Z 10 foozs + for foozs in 42 -42 " 43" " -43"; do + print "'$foozs'" + done +0:Right justification of scalars with zeroes +>'0000000042' +>' -42' +>' 000000043' +>' -43' + + integer -Z 10 foozi + for foozi in 42 -42 " 43" " -43"; do + print "'$foozi'" + done +0:Right justification of integers with zero, no initial base +>'0000000042' +>'-000000042' +>'0000000043' +>'-000000043' +# In case you hadn't twigged, the spaces are absorbed in the initial +# math evaluation, so don't get through. + + unsetopt cbases + integer -Z 10 -i 16 foozi16 + for foozi16 in 42 -42 " 43" " -43"; do + print "'$foozi16'" + done +0:Right justification of integers with zero, base 16, C_BASES off +>'16#000002A' +>'-16#00002A' +>'16#000002B' +>'-16#00002B' + + setopt cbases + integer -Z 10 -i 16 foozi16c + for foozi16c in 42 -42 " 43" " -43"; do + print "'$foozi16c'" + done +0:Right justification of integers with zero, base 16, C_BASES on +>'0x0000002A' +>'-0x000002A' +>'0x0000002B' +>'-0x000002B' + + typeset -F 3 -Z 10 foozf + for foozf in 3.14159 -3.14159 4 -4; do + print "'$foozf'" + done +0:Right justification of fixed point numbers with zero +>'000003.142' +>'-00003.142' +>'000004.000' +>'-00004.000' + stress00 print $scalar $array 0q:Stress test: all parameters are local and unset, using -m |