diff options
-rw-r--r-- | Doc/Zsh/mod_parameter.yo | 49 | ||||
-rw-r--r-- | Src/Modules/parameter.c | 662 | ||||
-rw-r--r-- | Src/Modules/parameter.mdd | 3 |
3 files changed, 714 insertions, 0 deletions
diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo new file mode 100644 index 000000000..c84dd18eb --- /dev/null +++ b/Doc/Zsh/mod_parameter.yo @@ -0,0 +1,49 @@ +texinode(The parameter Module)(The sched Module)(The files Module)(Zsh Modules) +sect(The parameter Module) +cindex(parameters, special) +The tt(parameter) module gives access to some of the internal hash +tables used by the shell, by defining four special associative arrays. + +startitem() +vindex(options) +item(tt(options))( +The keys for this associative array are the names of the options that +can be set and unset using the tt(setopt) and tt(unsetopt) +builtins. The value of each key is either the string tt(on) if the +option is currently set, or the string tt(off) if the option is unset. +Setting a key to one of these strings is like setting or unsetting +the option, respectively. Unsetting a key in this array is like +setting it to the value tt(off). +) +vindex(commands) +item(tt(command))( +This array gives access to the command hash table. The keys are the +names of external commands, the values are the pathnames of the files +that would be executed when the command would be invoked. Setting a +key in this array defines a new entry in this table in the same way as +with the tt(hash) builtin. Unsetting a key as in `tt(unset +"commands[foo]")' removes the entry for the given key from the command +hash table. +) +vindex(functions) +item(tt(functions))( +This association maps function names to their definitions. Setting a +key in it is like defining a function with the name given by the key +and the body given by the value. Unsetting a key removes the +definition for the function named by the key. +) +vindex(parameters) +item(tt(parameters))( +The keys in this associative array are the names of the parameters +currently defined. The values are strings describing the type of the +parameter, in the same format used by the tt(t) parameter flag, see +ifzman(\ +zmanref(zshexpn) +)\ +ifnzman(\ +noderef(Parameter Expansion) +)\ +. +Setting or unsetting keys in this array is not possible. +) +enditem() diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c new file mode 100644 index 000000000..2257933f5 --- /dev/null +++ b/Src/Modules/parameter.c @@ -0,0 +1,662 @@ +/* + * parameter.c - parameter interface to zsh internals + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 1999 Sven Wischnowsky + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Sven Wischnowsky or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Sven Wischnowsky and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Sven Wischnowsky and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "parameter.mdh" +#include "parameter.pro" + +/* Empty dummy function for special hash parameters. */ + +/**/ +static void +shempty(void) +{ +} + +/* Create a simple special hash parameter. */ + +/**/ +static Param +createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan) +{ + Param pm; + HashTable ht; + + if (!(pm = createparam(name, PM_SPECIAL|PM_REMOVABLE|PM_HASHED))) + return NULL; + + pm->level = pm->old ? locallevel : 0; + pm->gets.hfn = hashgetfn; + pm->sets.hfn = hashsetfn; + pm->unsetfn = stdunsetfn; + pm->u.hash = ht = newhashtable(7, name, NULL); + + ht->hash = hasher; + ht->emptytable = (TableFunc) shempty; + ht->filltable = NULL; + ht->addnode = (AddNodeFunc) shempty; + ht->getnode = ht->getnode2 = get; + ht->removenode = (RemoveNodeFunc) shempty; + ht->disablenode = NULL; + ht->enablenode = NULL; + ht->freenode = (FreeNodeFunc) shempty; + ht->printnode = printparamnode; + ht->scantab = scan; + + return pm; +} + +/* Functions for the parameters special parameter. */ + +/* Return a string describing the type of a parameter. */ + +/**/ +static char * +paramtypestr(Param pm) +{ + char *val = NULL; + int f = pm->flags; + + if (!(f & PM_UNSET)) { + switch (PM_TYPE(f)) { + case PM_SCALAR: val = "scalar"; break; + case PM_ARRAY: val = "array"; break; + case PM_INTEGER: val = "integer"; break; + case PM_HASHED: val = "association"; break; + } + DPUTS(!val, "BUG: type not handled in parameter"); + val = dupstring(val); + if (f & PM_LEFT) + val = dyncat(val, "-left"); + if (f & PM_RIGHT_B) + val = dyncat(val, "-right_blanks"); + if (f & PM_RIGHT_Z) + val = dyncat(val, "-right_zeros"); + if (f & PM_LOWER) + val = dyncat(val, "-lower"); + if (f & PM_UPPER) + val = dyncat(val, "-upper"); + if (f & PM_READONLY) + val = dyncat(val, "-readonly"); + if (f & PM_TAGGED) + val = dyncat(val, "-tag"); + if (f & PM_EXPORTED) + val = dyncat(val, "-export"); + if (f & PM_UNIQUE) + val = dyncat(val, "-unique"); + } else + val = dupstring(""); + + return val; +} + +/**/ +static HashNode +getpmparameter(HashTable ht, char *name) +{ + Param rpm, pm = NULL; + + HEAPALLOC { + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR | PM_READONLY; + pm->sets.cfn = NULL; + pm->gets.cfn = strgetfn; + pm->unsetfn = NULL; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) && + !(rpm->flags & PM_UNSET)) + pm->u.str = paramtypestr(rpm); + else { + pm->u.str = ""; + pm->flags |= PM_UNSET; + } + } LASTALLOC; + + return (HashNode) pm; +} + +/**/ +static void +scanpmparameters(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + + pm.flags = PM_SCALAR | PM_READONLY; + pm.sets.cfn = NULL; + pm.gets.cfn = strgetfn; + pm.unsetfn = NULL; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < realparamtab->hsize; i++) + for (hn = realparamtab->nodes[i]; hn; hn = hn->next) { + pm.nam = hn->nam; + if (func != scancountparams) + pm.u.str = paramtypestr((Param) hn); + func((HashNode) &pm, flags); + } +} + +/* Functions for the commands special parameter. */ + +/**/ +static void +setpmcommand(Param pm, char *value) +{ + if (isset(RESTRICTED)) + zwarnnam(NULL, "restricted: %s", value, 0); + else { + Cmdnam cn = zcalloc(sizeof(*cn)); + + cn->flags = HASHED; + cn->u.cmd = ztrdup(value); + + cmdnamtab->addnode(cmdnamtab, ztrdup(pm->nam), (HashNode) cn); + } +} + +/**/ +static void +unsetpmcommand(Param pm, int exp) +{ + HashNode hn = cmdnamtab->removenode(cmdnamtab, pm->nam); + + if (hn) + cmdnamtab->freenode(hn); +} + +/**/ +static void +setpmcommands(Param pm, HashTable ht) +{ + int i; + HashNode hn; + + for (i = 0; i < ht->hsize; i++) + for (hn = ht->nodes[i]; hn; hn = hn->next) { + Cmdnam cn = zcalloc(sizeof(*cn)); + struct value v; + + v.isarr = v.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + + cn->flags = HASHED; + cn->u.cmd = ztrdup(getstrvalue(&v)); + + cmdnamtab->addnode(cmdnamtab, ztrdup(hn->nam), (HashNode) cn); + } +} + +/**/ +static HashNode +getpmcommand(HashTable ht, char *name) +{ + Cmdnam cmd; + Param pm = NULL; + + if (!(cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name)) && + isset(HASHLISTALL)) { + cmdnamtab->filltable(cmdnamtab); + cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name); + } + HEAPALLOC { + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmcommand; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmcommand; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + if (cmd) { + if (cmd->flags & HASHED) + pm->u.str = cmd->u.cmd; + else { + pm->u.str = zhalloc(strlen(*(cmd->u.name)) + + strlen(name) + 2); + strcpy(pm->u.str, *(cmd->u.name)); + strcat(pm->u.str, "/"); + strcat(pm->u.str, name); + } + } else { + pm->u.str = ""; + pm->flags |= PM_UNSET; + } + } LASTALLOC; + + return (HashNode) pm; +} + +/**/ +static void +scanpmcommands(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + Cmdnam cmd; + + if (isset(HASHLISTALL)) + cmdnamtab->filltable(cmdnamtab); + + pm.flags = PM_SCALAR; + pm.sets.cfn = setpmcommand; + pm.gets.cfn = strgetfn; + pm.unsetfn = unsetpmcommand; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < cmdnamtab->hsize; i++) + for (hn = cmdnamtab->nodes[i]; hn; hn = hn->next) { + pm.nam = hn->nam; + cmd = (Cmdnam) hn; + if (func != scancountparams) { + if (cmd->flags & HASHED) + pm.u.str = cmd->u.cmd; + else { + pm.u.str = zhalloc(strlen(*(cmd->u.name)) + + strlen(cmd->nam) + 2); + strcpy(pm.u.str, *(cmd->u.name)); + strcat(pm.u.str, "/"); + strcat(pm.u.str, cmd->nam); + } + } + func((HashNode) &pm, flags); + } +} + +/* Functions for the functions special parameter. */ + +/**/ +static void +setfunction(char *name, char *value) +{ + char *val; + Shfunc shf; + List list; + int sn; + + val = ztrdup(value); + val = metafy(val, strlen(val), META_REALLOC); + + HEAPALLOC { + list = parse_string(val); + } LASTALLOC; + + if (!list || list == &dummy_list) { + zwarnnam(NULL, "invalid function definition", val, 0); + zsfree(val); + return; + } + PERMALLOC { + shf = (Shfunc) zalloc(sizeof(*shf)); + shf->funcdef = (List) dupstruct(list); + shf->flags = 0; + + if (!strncmp(name, "TRAP", 4) && + (sn = getsignum(name + 4)) != -1) { + if (settrap(sn, shf->funcdef)) { + freestruct(shf->funcdef); + zfree(shf, sizeof(*shf)); + zsfree(val); + LASTALLOC_RETURN; + } + sigtrapped[sn] |= ZSIG_FUNC; + } + shfunctab->addnode(shfunctab, ztrdup(name), shf); + } LASTALLOC; + + zsfree(val); +} + +/**/ +static void +setpmfunction(Param pm, char *value) +{ + setfunction(pm->nam, value); +} + +/**/ +static void +unsetpmfunction(Param pm, int exp) +{ + HashNode hn = shfunctab->removenode(shfunctab, pm->nam); + + if (hn) + shfunctab->freenode(hn); +} + +/**/ +static void +setpmfunctions(Param pm, HashTable ht) +{ + int i; + HashNode hn; + + for (i = 0; i < ht->hsize; i++) + for (hn = ht->nodes[i]; hn; hn = hn->next) { + struct value v; + + v.isarr = v.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + + setfunction(hn->nam, getstrvalue(&v)); + } +} + +/**/ +static HashNode +getpmfunction(HashTable ht, char *name) +{ + Shfunc shf; + Param pm = NULL; + + HEAPALLOC { + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmfunction; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmfunction; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((shf = (Shfunc) shfunctab->getnode(shfunctab, name))) { + if (shf->flags & PM_UNDEFINED) + pm->u.str = "undefined"; + else { + char *t = getpermtext((void *) dupstruct((void *) + shf->funcdef)), *h; + + h = dupstring(t); + zsfree(t); + unmetafy(h, NULL); + + pm->u.str = h; + } + } else { + pm->u.str = ""; + pm->flags |= PM_UNSET; + } + } LASTALLOC; + + return (HashNode) pm; +} + +/**/ +static void +scanpmfunctions(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + + pm.flags = PM_SCALAR; + pm.sets.cfn = setpmcommand; + pm.gets.cfn = strgetfn; + pm.unsetfn = unsetpmcommand; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < shfunctab->hsize; i++) + for (hn = shfunctab->nodes[i]; hn; hn = hn->next) { + if (!(hn->flags & DISABLED)) { + pm.nam = hn->nam; + if (func != scancountparams) { + if (((Shfunc) hn)->flags & PM_UNDEFINED) + pm.u.str = "undefined"; + else { + char *t = getpermtext((void *) + dupstruct((void *) ((Shfunc) hn)->funcdef)); + + unmetafy((pm.u.str = dupstring(t)), NULL); + zsfree(t); + } + } + func((HashNode) &pm, flags); + } + } +} + +/* Functions for the options special parameter. */ + +/**/ +static void +setpmoption(Param pm, char *value) +{ + int n; + + if (!value || (strcmp(value, "on") && strcmp(value, "off"))) + zwarnnam(NULL, "invalid value: %s", value, 0); + else if (!(n = optlookup(pm->nam))) + zwarnnam(NULL, "no such option: %s", pm->nam, 0); + else if (dosetopt(n, (value && strcmp(value, "off")), 0)) + zwarnnam(NULL, "can't change option: %s", pm->nam, 0); +} + +/**/ +static void +unsetpmoption(Param pm, int exp) +{ + int n; + + if (!(n = optlookup(pm->nam))) + zwarnnam(NULL, "no such option: %s", pm->nam, 0); + else if (dosetopt(n, 0, 0)) + zwarnnam(NULL, "can't change option: %s", pm->nam, 0); +} + +/**/ +static void +setpmoptions(Param pm, HashTable ht) +{ + int i; + HashNode hn; + + for (i = 0; i < ht->hsize; i++) + for (hn = ht->nodes[i]; hn; hn = hn->next) { + struct value v; + char *val; + + v.isarr = v.inv = v.a = 0; + v.b = -1; + v.arr = NULL; + v.pm = (Param) hn; + + val = getstrvalue(&v); + if (!val || (strcmp(val, "on") && strcmp(val, "off"))) + zwarnnam(NULL, "invalid value: %s", val, 0); + else if (dosetopt(optlookup(hn->nam), + (val && strcmp(val, "off")), 0)) + zwarnnam(NULL, "can't change option: %s", hn->nam, 0); + } +} + +/**/ +static HashNode +getpmoption(HashTable ht, char *name) +{ + Param pm = NULL; + int n; + + HEAPALLOC { + pm = (Param) zhalloc(sizeof(struct param)); + pm->nam = dupstring(name); + pm->flags = PM_SCALAR; + pm->sets.cfn = setpmoption; + pm->gets.cfn = strgetfn; + pm->unsetfn = unsetpmoption; + pm->ct = 0; + pm->env = NULL; + pm->ename = NULL; + pm->old = NULL; + pm->level = 0; + + if ((n = optlookup(name))) + pm->u.str = dupstring(opts[n] ? "on" : "off"); + else { + pm->u.str = ""; + pm->flags |= PM_UNSET; + } + } LASTALLOC; + + return (HashNode) pm; +} + +/**/ +static void +scanpmoptions(HashTable ht, ScanFunc func, int flags) +{ + struct param pm; + int i; + HashNode hn; + + pm.flags = PM_SCALAR; + pm.sets.cfn = setpmoption; + pm.gets.cfn = strgetfn; + pm.unsetfn = unsetpmoption; + pm.ct = 0; + pm.env = NULL; + pm.ename = NULL; + pm.old = NULL; + pm.level = 0; + + for (i = 0; i < optiontab->hsize; i++) + for (hn = optiontab->nodes[i]; hn; hn = hn->next) { + pm.nam = hn->nam; + pm.u.str = opts[((Optname) hn)->optno] ? "on" : "off"; + func((HashNode) &pm, flags); + } +} + +/* Names and Params for the special parameters. */ + +#define PAR_NAM "parameters" +#define CMD_NAM "commands" +#define FUN_NAM "functions" +#define OPT_NAM "options" + +static Param parpm, cmdpm, funpm, optpm; + +/**/ +int +setup_parameter(Module m) +{ + return 0; +} + +/**/ +int +boot_parameter(Module m) +{ + /* Create the special associative arrays. + * As an example for autoloaded parameters, this is probably a bad + * example, because we the zsh core doesn't support creation of + * special hashes, yet. */ + + unsetparam(PAR_NAM); + if (!(parpm = createspecialhash(PAR_NAM, getpmparameter, + scanpmparameters))) + return 1; + parpm->flags |= PM_READONLY; + unsetparam(CMD_NAM); + if (!(cmdpm = createspecialhash(CMD_NAM, getpmcommand, + scanpmcommands))) + return 1; + cmdpm->sets.hfn = setpmcommands; + unsetparam(FUN_NAM); + if (!(funpm = createspecialhash(FUN_NAM, getpmfunction, + scanpmfunctions))) + return 1; + funpm->sets.hfn = setpmfunctions; + unsetparam(OPT_NAM); + if (!(optpm = createspecialhash(OPT_NAM, getpmoption, + scanpmoptions))) + return 1; + optpm->sets.hfn = setpmoptions; + + return 0; +} + +#ifdef MODULE + +/**/ +int +cleanup_parameter(Module m) +{ + Param pm; + + /* Remove the special parameters if they are still the same. */ + + if ((pm = (Param) paramtab->getnode(paramtab, PAR_NAM)) && pm == parpm) { + pm->flags &= ~PM_READONLY; + unsetparam_pm(pm, 0, 1); + } + if ((pm = (Param) paramtab->getnode(paramtab, CMD_NAM)) && pm == cmdpm) + unsetparam_pm(pm, 0, 1); + if ((pm = (Param) paramtab->getnode(paramtab, FUN_NAM)) && pm == funpm) + unsetparam_pm(pm, 0, 1); + if ((pm = (Param) paramtab->getnode(paramtab, OPT_NAM)) && pm == optpm) + unsetparam_pm(pm, 0, 1); + return 0; +} + +/**/ +int +finish_parameter(Module m) +{ + return 0; +} + +#endif diff --git a/Src/Modules/parameter.mdd b/Src/Modules/parameter.mdd new file mode 100644 index 000000000..e2820aa9c --- /dev/null +++ b/Src/Modules/parameter.mdd @@ -0,0 +1,3 @@ +autoparams="parameters commands functions options" + +objects="parameter.o" |