--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openenvutils/commandshell/shell/src/modules/parameter.c Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,2008 @@
+// parameter.c - parameter interface to zsh internals
+//
+// © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
+//
+/*
+ * 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"
+
+#ifdef __SYMBIAN32__
+#ifdef __WINSCW__
+#pragma warn_unusedarg off
+#pragma warn_possunwant off
+#endif//__WINSCW__
+#endif//__SYMBIAN32__
+
+/* This says if we are cleaning up when the module is unloaded. */
+
+static int incleanup;
+
+/* 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_HIDE|PM_HIDEVAL|
+ PM_REMOVABLE|PM_HASHED)))
+ return NULL;
+
+ pm->level = pm->old ? locallevel : 0;
+ pm->gsu.h = &stdhash_gsu;
+ pm->u.hash = ht = newhashtable(0, 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)) {
+ if (pm->flags & PM_AUTOLOAD)
+ return dupstring("undefined");
+
+ switch (PM_TYPE(f)) {
+ case PM_SCALAR: val = "scalar"; break;
+ case PM_ARRAY: val = "array"; break;
+ case PM_INTEGER: val = "integer"; break;
+ case PM_EFLOAT:
+ case PM_FFLOAT: val = "float"; break;
+ case PM_HASHED: val = "association"; break;
+ }
+ DPUTS(!val, "BUG: type not handled in parameter");
+ val = dupstring(val);
+ if (pm->level)
+ val = dyncat(val, "-local");
+ 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");
+ if (f & PM_HIDE)
+ val = dyncat(val, "-hide");
+ if (f & PM_HIDEVAL)
+ val = dyncat(val, "-hideval");
+ if (f & PM_SPECIAL)
+ val = dyncat(val, "-special");
+ } else
+ val = dupstring("");
+
+ return val;
+}
+
+/**/
+static HashNode
+getpmparameter(UNUSED(HashTable ht), char *name)
+{
+ Param rpm, pm = NULL;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR | PM_READONLY;
+ pm->gsu.s = &nullsetscalar_gsu;
+ if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
+ !(rpm->flags & PM_UNSET))
+ pm->u.str = paramtypestr(rpm);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmparameters(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ for (i = 0; i < realparamtab->hsize; i++)
+ for (hn = realparamtab->nodes[i]; hn; hn = hn->next) {
+ if (((Param)hn)->flags & PM_UNSET)
+ continue;
+ pm.nam = hn->nam;
+ if (func != scancountparams &&
+ ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS)))
+ 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)) {
+ zwarn("restricted: %s", value, 0);
+ zsfree(value);
+ } else {
+ Cmdnam cn = zshcalloc(sizeof(*cn));
+
+ cn->flags = HASHED;
+ cn->u.cmd = value;
+
+ cmdnamtab->addnode(cmdnamtab, ztrdup(pm->nam), (HashNode) cn);
+ }
+}
+
+/**/
+static void
+unsetpmcommand(Param pm, UNUSED(int exp))
+{
+ HashNode hn = cmdnamtab->removenode(cmdnamtab, pm->nam);
+
+ if (hn)
+ cmdnamtab->freenode(hn);
+}
+
+/**/
+static void
+setpmcommands(UNUSED(Param pm), HashTable ht)
+{
+ int i;
+ HashNode hn;
+
+ if (!ht)
+ return;
+
+ for (i = 0; i < ht->hsize; i++)
+ for (hn = ht->nodes[i]; hn; hn = hn->next) {
+ Cmdnam cn = zshcalloc(sizeof(*cn));
+ struct value v;
+
+ v.isarr = v.inv = v.start = 0;
+ v.end = -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);
+ }
+ deleteparamtable(ht);
+}
+
+static const struct gsu_scalar pmcommand_gsu =
+{ strgetfn, setpmcommand, unsetpmcommand };
+
+
+/**/
+static HashNode
+getpmcommand(UNUSED(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);
+ }
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR;
+ pm->gsu.s = &pmcommand_gsu;
+ 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 = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmcommands(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+ Cmdnam cmd;
+
+ if (isset(HASHLISTALL))
+ cmdnamtab->filltable(cmdnamtab);
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR;
+ pm.gsu.s = &pmcommand_gsu;
+
+ 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 &&
+ ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS))) {
+ 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 *val, int dis)
+{
+ char *value = dupstring(val);
+ Shfunc shf;
+ Eprog prog;
+ int sn;
+
+ val = metafy(val, strlen(val), META_REALLOC);
+
+ prog = parse_string(val);
+
+ if (!prog || prog == &dummy_eprog) {
+ zwarn("invalid function definition", value, 0);
+ zsfree(val);
+ return;
+ }
+ shf = (Shfunc) zalloc(sizeof(*shf));
+ shf->funcdef = dupeprog(prog, 0);
+ shf->flags = dis;
+
+ if (!strncmp(name, "TRAP", 4) &&
+ (sn = getsignum(name + 4)) != -1) {
+ if (settrap(sn, shf->funcdef)) {
+ freeeprog(shf->funcdef);
+ zfree(shf, sizeof(*shf));
+ zsfree(val);
+ return;
+ }
+ sigtrapped[sn] |= ZSIG_FUNC;
+ }
+ shfunctab->addnode(shfunctab, ztrdup(name), shf);
+ zsfree(val);
+}
+
+/**/
+static void
+setpmfunction(Param pm, char *value)
+{
+ setfunction(pm->nam, value, 0);
+}
+
+/**/
+static void
+setpmdisfunction(Param pm, char *value)
+{
+ setfunction(pm->nam, value, DISABLED);
+}
+
+/**/
+static void
+unsetpmfunction(Param pm, UNUSED(int exp))
+{
+ HashNode hn = shfunctab->removenode(shfunctab, pm->nam);
+
+ if (hn)
+ shfunctab->freenode(hn);
+}
+
+/**/
+static void
+setfunctions(UNUSED(Param pm), HashTable ht, int dis)
+{
+ int i;
+ HashNode hn;
+
+ if (!ht)
+ return;
+
+ for (i = 0; i < ht->hsize; i++)
+ for (hn = ht->nodes[i]; hn; hn = hn->next) {
+ struct value v;
+
+ v.isarr = v.inv = v.start = 0;
+ v.end = -1;
+ v.arr = NULL;
+ v.pm = (Param) hn;
+
+ setfunction(hn->nam, ztrdup(getstrvalue(&v)), dis);
+ }
+ deleteparamtable(ht);
+}
+
+/**/
+static void
+setpmfunctions(Param pm, HashTable ht)
+{
+ setfunctions(pm, ht, 0);
+}
+
+/**/
+static void
+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)
+{
+ Shfunc shf;
+ Param pm = NULL;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR;
+ pm->gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu;
+
+ if ((shf = (Shfunc) shfunctab->getnode2(shfunctab, name)) &&
+ (dis ? (shf->flags & DISABLED) : !(shf->flags & DISABLED))) {
+ if (shf->flags & PM_UNDEFINED) {
+ pm->u.str = dyncat("builtin autoload -X",
+ ((shf->flags & PM_UNALIASED) ?
+ ((shf->flags & PM_TAGGED) ? "Ut" : "U") :
+ ((shf->flags & PM_TAGGED) ? "t" : "")));
+ } else {
+ char *t = getpermtext(shf->funcdef, NULL), *n, *h;
+
+ if (shf->funcdef->flags & EF_RUN) {
+ n = nicedupstring(name);
+ h = (char *) zhalloc(strlen(t) + strlen(n) + 9);
+ h[0] = '\t';
+ strcpy(h + 1, t);
+ strcat(h, "\n\t");
+ strcat(h, n);
+ strcat(h, " \"$@\"");
+ } else
+ h = dyncat("\t", t);
+ zsfree(t);
+ unmetafy(h, NULL);
+
+ pm->u.str = h;
+ }
+ } else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static HashNode
+getpmfunction(HashTable ht, char *name)
+{
+ return getfunction(ht, name, 0);
+}
+
+/**/
+static HashNode
+getpmdisfunction(HashTable ht, char *name)
+{
+ return getfunction(ht, name, DISABLED);
+}
+
+/**/
+static void
+scanfunctions(UNUSED(HashTable ht), ScanFunc func, int flags, int dis)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR;
+ pm.gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu;
+
+ for (i = 0; i < shfunctab->hsize; i++)
+ for (hn = shfunctab->nodes[i]; hn; hn = hn->next) {
+ if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED)) {
+ pm.nam = hn->nam;
+ if (func != scancountparams &&
+ ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS))) {
+ if (((Shfunc) hn)->flags & PM_UNDEFINED) {
+ Shfunc shf = (Shfunc) hn;
+ pm.u.str =
+ dyncat("builtin autoload -X",
+ ((shf->flags & PM_UNALIASED) ?
+ ((shf->flags & PM_TAGGED) ? "Ut" : "U") :
+ ((shf->flags & PM_TAGGED) ? "t" : "")));
+ } else {
+ char *t = getpermtext(((Shfunc) hn)->funcdef, NULL), *n;
+
+ if (((Shfunc) hn)->funcdef->flags & EF_RUN) {
+ n = nicedupstring(hn->nam);
+ pm.u.str = (char *) zhalloc(strlen(t) + strlen(n) + 9);
+ pm.u.str[0] = '\t';
+ strcpy(pm.u.str + 1, t);
+ strcat(pm.u.str, "\n\t");
+ strcat(pm.u.str, n);
+ strcat(pm.u.str, " \"$@\"");
+ } else
+ pm.u.str = dyncat("\t", t);
+ unmetafy(pm.u.str, NULL);
+ zsfree(t);
+ }
+ }
+ func((HashNode) &pm, flags);
+ }
+ }
+}
+
+/**/
+static void
+scanpmfunctions(HashTable ht, ScanFunc func, int flags)
+{
+ scanfunctions(ht, func, flags, 0);
+}
+
+/**/
+static void
+scanpmdisfunctions(HashTable ht, ScanFunc func, int flags)
+{
+ scanfunctions(ht, func, flags, DISABLED);
+}
+
+/* Functions for the funcstack special parameter. */
+
+/**/
+static char **
+funcstackgetfn(UNUSED(Param pm))
+{
+ Funcstack f;
+ int num;
+ char **ret, **p;
+
+ for (f = funcstack, num = 0; f; f = f->prev, num++);
+
+ ret = (char **) zhalloc((num + 1) * sizeof(char *));
+
+ for (f = funcstack, p = ret; f; f = f->prev, p++)
+ *p = f->name;
+ *p = NULL;
+
+ return ret;
+}
+
+/* Functions for the builtins special parameter. */
+
+/**/
+static HashNode
+getbuiltin(UNUSED(HashTable ht), char *name, int dis)
+{
+ Param pm = NULL;
+ Builtin bn;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR | PM_READONLY;
+ 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)) ?
+ "defined" : "undefined");
+
+ pm->u.str = dupstring(t);
+ } else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static HashNode
+getpmbuiltin(HashTable ht, char *name)
+{
+ return getbuiltin(ht, name, 0);
+}
+
+/**/
+static HashNode
+getpmdisbuiltin(HashTable ht, char *name)
+{
+ return getbuiltin(ht, name, DISABLED);
+}
+
+/**/
+static void
+scanbuiltins(UNUSED(HashTable ht), ScanFunc func, int flags, int dis)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ for (i = 0; i < builtintab->hsize; i++)
+ for (hn = builtintab->nodes[i]; hn; hn = hn->next) {
+ if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED)) {
+ pm.nam = hn->nam;
+ if (func != scancountparams &&
+ ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS))) {
+ char *t = ((((Builtin) hn)->handlerfunc ||
+ (hn->flags & BINF_PREFIX)) ?
+ "defined" : "undefined");
+
+ pm.u.str = dupstring(t);
+ }
+ func((HashNode) &pm, flags);
+ }
+ }
+}
+
+/**/
+static void
+scanpmbuiltins(HashTable ht, ScanFunc func, int flags)
+{
+ scanbuiltins(ht, func, flags, 0);
+}
+
+/**/
+static void
+scanpmdisbuiltins(HashTable ht, ScanFunc func, int flags)
+{
+ scanbuiltins(ht, func, flags, DISABLED);
+}
+
+/* Functions for the reswords special parameter. */
+
+/**/
+static char **
+getreswords(int dis)
+{
+ int i;
+ HashNode hn;
+ char **ret, **p;
+
+ p = ret = (char **) zhalloc((reswdtab->ct + 1) * sizeof(char *));
+
+ for (i = 0; i < reswdtab->hsize; i++)
+ for (hn = reswdtab->nodes[i]; hn; hn = hn->next)
+ if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED))
+ *p++ = dupstring(hn->nam);
+ *p = NULL;
+
+ return ret;
+}
+
+/**/
+static char **
+reswordsgetfn(UNUSED(Param pm))
+{
+ return getreswords(0);
+}
+
+/**/
+static char **
+disreswordsgetfn(UNUSED(Param pm))
+{
+ return getreswords(DISABLED);
+}
+
+/* Functions for the options special parameter. */
+
+/**/
+static void
+setpmoption(Param pm, char *value)
+{
+ int n;
+
+ if (!value || (strcmp(value, "on") && strcmp(value, "off")))
+ zwarn("invalid value: %s", value, 0);
+ else if (!(n = optlookup(pm->nam)))
+ zwarn("no such option: %s", pm->nam, 0);
+ else if (dosetopt(n, (value && strcmp(value, "off")), 0))
+ zwarn("can't change option: %s", pm->nam, 0);
+ zsfree(value);
+}
+
+/**/
+static void
+unsetpmoption(Param pm, UNUSED(int exp))
+{
+ int n;
+
+ if (!(n = optlookup(pm->nam)))
+ zwarn("no such option: %s", pm->nam, 0);
+ else if (dosetopt(n, 0, 0))
+ zwarn("can't change option: %s", pm->nam, 0);
+}
+
+/**/
+static void
+setpmoptions(UNUSED(Param pm), HashTable ht)
+{
+ int i;
+ HashNode hn;
+
+ if (!ht)
+ return;
+
+ 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.start = 0;
+ v.end = -1;
+ v.arr = NULL;
+ v.pm = (Param) hn;
+
+ val = getstrvalue(&v);
+ if (!val || (strcmp(val, "on") && strcmp(val, "off")))
+ zwarn("invalid value: %s", val, 0);
+ else if (dosetopt(optlookup(hn->nam),
+ (val && strcmp(val, "off")), 0))
+ zwarn("can't change option: %s", hn->nam, 0);
+ }
+ deleteparamtable(ht);
+}
+
+static const struct gsu_scalar pmoption_gsu =
+{ strgetfn, setpmoption, unsetpmoption };
+
+/**/
+static HashNode
+getpmoption(UNUSED(HashTable ht), char *name)
+{
+ Param pm = NULL;
+ int n;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR;
+ pm->gsu.s = &pmoption_gsu;
+
+ if ((n = optlookup(name)))
+ {
+ int ison;
+ if (n > 0)
+ ison = opts[n];
+ else
+ ison = !opts[-n];
+ pm->u.str = dupstring(ison ? "on" : "off");
+ }
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmoptions(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR;
+ pm.gsu.s = &pmoption_gsu;
+
+ for (i = 0; i < optiontab->hsize; i++)
+ for (hn = optiontab->nodes[i]; hn; hn = hn->next) {
+ int optno = ((Optname) hn)->optno, ison;
+ pm.nam = hn->nam;
+ ison = optno < 0 ? !opts[-optno] : opts[optno];
+ pm.u.str = dupstring(ison ? "on" : "off");
+ func((HashNode) &pm, flags);
+ }
+}
+
+/* Functions for the modules special parameter. */
+
+static char *modpmname;
+static int modpmfound;
+
+/**/
+static void
+modpmbuiltinscan(HashNode hn, UNUSED(int dummy))
+{
+ if (!(((Builtin) hn)->flags & BINF_ADDED) &&
+ !strcmp(((Builtin) hn)->optstr, modpmname))
+ modpmfound = 1;
+}
+
+/**/
+static void
+modpmparamscan(HashNode hn, UNUSED(int dummy))
+{
+ if ((((Param) hn)->flags & PM_AUTOLOAD) &&
+ !strcmp(((Param) hn)->u.str, modpmname))
+ modpmfound = 1;
+}
+
+/**/
+static int
+findmodnode(LinkList l, char *nam)
+{
+ LinkNode node;
+
+ for (node = firstnode(l); node; incnode(node))
+ if (!strcmp(nam, (char *) getdata(node)))
+ return 1;
+
+ return 0;
+}
+
+/**/
+static HashNode
+getpmmodule(UNUSED(HashTable ht), char *name)
+{
+ Param pm = NULL;
+ char *type = NULL;
+ LinkNode node;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR | PM_READONLY;
+ pm->gsu.s = &nullsetscalar_gsu;
+
+ if (!type) {
+ Module m;
+
+ for (node = firstnode(modules); node; incnode(node)) {
+ m = (Module) getdata(node);
+ if (m->u.handle && !(m->flags & MOD_UNLOAD) &&
+ !strcmp(name, m->nam)) {
+ type = ((m->flags & MOD_ALIAS) ?
+ dyncat("alias:", m->u.alias) : "loaded");
+ break;
+ }
+ }
+ }
+ modpmname = name;
+ modpmfound = 0;
+ if (!type) {
+ scanhashtable(builtintab, 0, 0, 0, modpmbuiltinscan, 0);
+ if (!modpmfound) {
+ Conddef p;
+
+ for (p = condtab; p; p = p->next)
+ if (p->module && !strcmp(name, p->module)) {
+ modpmfound = 1;
+ break;
+ }
+ if (!modpmfound)
+ scanhashtable(realparamtab, 0, 0, 0, modpmparamscan, 0);
+ }
+ if (modpmfound)
+ type = "autoloaded";
+ }
+ if (type)
+ pm->u.str = dupstring(type);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmmodules(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+ LinkList done = newlinklist();
+ LinkNode node;
+ Module m;
+ Conddef p;
+ char *loaded = dupstring("loaded");
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ for (node = firstnode(modules); node; incnode(node)) {
+ m = (Module) getdata(node);
+ if (m->u.handle && !(m->flags & MOD_UNLOAD)) {
+ pm.nam = m->nam;
+ pm.u.str = ((m->flags & MOD_ALIAS) ?
+ dyncat("alias:", m->u.alias) : loaded);
+ addlinknode(done, pm.nam);
+ func((HashNode) &pm, flags);
+ }
+ }
+ pm.u.str = dupstring("autoloaded");
+ for (i = 0; i < builtintab->hsize; i++)
+ for (hn = builtintab->nodes[i]; hn; hn = hn->next) {
+ if (!(((Builtin) hn)->flags & BINF_ADDED) &&
+ !findmodnode(done, ((Builtin) hn)->optstr)) {
+ pm.nam = ((Builtin) hn)->optstr;
+ addlinknode(done, pm.nam);
+ func((HashNode) &pm, flags);
+ }
+ }
+ for (p = condtab; p; p = p->next)
+ if (p->module && !findmodnode(done, p->module)) {
+ pm.nam = p->module;
+ addlinknode(done, pm.nam);
+ func((HashNode) &pm, flags);
+ }
+ for (i = 0; i < realparamtab->hsize; i++)
+ for (hn = realparamtab->nodes[i]; hn; hn = hn->next) {
+ if ((((Param) hn)->flags & PM_AUTOLOAD) &&
+ !findmodnode(done, ((Param) hn)->u.str)) {
+ pm.nam = ((Param) hn)->u.str;
+ addlinknode(done, pm.nam);
+ func((HashNode) &pm, flags);
+ }
+ }
+}
+
+/* Functions for the dirstack special parameter. */
+
+/**/
+static void
+dirssetfn(UNUSED(Param pm), char **x)
+{
+ char **ox = x;
+
+ if (!incleanup) {
+ freelinklist(dirstack, freestr);
+ dirstack = znewlinklist();
+ while (x && *x)
+ zaddlinknode(dirstack, ztrdup(*x++));
+ }
+ if (ox)
+ freearray(ox);
+}
+
+/**/
+static char **
+dirsgetfn(UNUSED(Param pm))
+{
+ int l = countlinknodes(dirstack);
+ char **ret = (char **) zhalloc((l + 1) * sizeof(char *)), **p;
+ LinkNode n;
+
+ for (n = firstnode(dirstack), p = ret; n; incnode(n), p++)
+ *p = dupstring((char *) getdata(n));
+ *p = NULL;
+
+ return ret;
+}
+
+/* Functions for the history special parameter. */
+
+/**/
+static HashNode
+getpmhistory(UNUSED(HashTable ht), char *name)
+{
+ Param pm = NULL;
+ Histent he;
+ char *p;
+ int ok = 1;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR | PM_READONLY;
+ pm->gsu.s = &nullsetscalar_gsu;
+
+ if (*name != '0' || name[1]) {
+ if (*name == '0')
+ ok = 0;
+ else {
+ for (p = name; *p && idigit(*p); p++);
+ if (*p)
+ ok = 0;
+ }
+ }
+ if (ok && (he = quietgethist(atoi(name))))
+ pm->u.str = dupstring(he->text);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmhistory(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int i = addhistnum(curhist, -1, HIST_FOREIGN);
+ Histent he = gethistent(i, GETHIST_UPWARD);
+ char buf[40];
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ while (he) {
+ if (func != scancountparams) {
+ convbase(buf, he->histnum, 10);
+ pm.nam = dupstring(buf);
+ if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS))
+ pm.u.str = dupstring(he->text);
+ }
+ func((HashNode) &pm, flags);
+
+ he = up_histent(he);
+ }
+}
+
+/* Function for the historywords special parameter. */
+
+/**/
+static char **
+histwgetfn(UNUSED(Param pm))
+{
+ char **ret, **p, *h, *e, sav;
+ LinkList l = newlinklist(), ll;
+ LinkNode n;
+ int i = addhistnum(curhist, -1, HIST_FOREIGN), iw;
+ Histent he = gethistent(i, GETHIST_UPWARD);
+
+ if ((ll = bufferwords(NULL, NULL, NULL)))
+ for (n = firstnode(ll); n; incnode(n))
+ pushnode(l, getdata(n));
+
+ while (he) {
+ for (iw = he->nwords - 1; iw >= 0; iw--) {
+ h = he->text + he->words[iw * 2];
+ e = he->text + he->words[iw * 2 + 1];
+ sav = *e;
+ *e = '\0';
+ addlinknode(l, dupstring(h));
+ *e = sav;
+ }
+ he = up_histent(he);
+ }
+ ret = (char **) zhalloc((countlinknodes(l) + 1) * sizeof(char *));
+
+ for (p = ret, n = firstnode(l); n; incnode(n), p++)
+ *p = (char *) getdata(n);
+ *p = NULL;
+
+ return ret;
+}
+
+/* Functions for the jobtexts special parameter. */
+
+/**/
+static char *
+pmjobtext(int job)
+{
+ Process pn;
+ int len = 1;
+ char *ret;
+
+ for (pn = jobtab[job].procs; pn; pn = pn->next)
+ len += strlen(pn->text) + 3;
+
+ ret = (char *) zhalloc(len);
+ ret[0] = '\0';
+
+ for (pn = jobtab[job].procs; pn; pn = pn->next) {
+ strcat(ret, pn->text);
+ if (pn->next)
+ strcat(ret, " | ");
+ }
+ return ret;
+}
+
+/**/
+static HashNode
+getpmjobtext(UNUSED(HashTable ht), char *name)
+{
+ Param pm = NULL;
+ int job;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR | PM_READONLY;
+ pm->gsu.s = &nullsetscalar_gsu;
+
+ if ((job = atoi(name)) >= 1 && job <= maxjob &&
+ jobtab[job].stat && jobtab[job].procs &&
+ !(jobtab[job].stat & STAT_NOPRINT))
+ pm->u.str = pmjobtext(job);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmjobtexts(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int job;
+ char buf[40];
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ for (job = 1; job <= maxjob; job++) {
+ if (jobtab[job].stat && jobtab[job].procs &&
+ !(jobtab[job].stat & STAT_NOPRINT)) {
+ if (func != scancountparams) {
+ sprintf(buf, "%d", job);
+ pm.nam = dupstring(buf);
+ if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS))
+ pm.u.str = pmjobtext(job);
+ }
+ func((HashNode) &pm, flags);
+ }
+ }
+}
+
+/* Functions for the jobstates special parameter. */
+
+/**/
+static char *
+pmjobstate(int job)
+{
+ Process pn;
+ char buf[256], buf2[128], *ret, *state, *cp;
+
+ if (job == curjob)
+ cp = ":+";
+ else if (job == prevjob)
+ cp = ":-";
+ else
+ cp = ":";
+
+ if (jobtab[job].stat & STAT_DONE)
+ ret = dyncat("done", cp);
+ else if (jobtab[job].stat & STAT_STOPPED)
+ ret = dyncat("suspended", cp);
+ else
+ ret = dyncat("running", cp);
+
+ for (pn = jobtab[job].procs; pn; pn = pn->next) {
+
+ if (pn->status == SP_RUNNING)
+ state = "running";
+ else if (WIFEXITED(pn->status)) {
+ if (WEXITSTATUS(pn->status))
+ sprintf((state = buf2), "exit %d", (pn->status));
+ else
+ state = "done";
+ } else if (WIFSTOPPED(pn->status))
+ state = sigmsg(WSTOPSIG(pn->status));
+ else if (WCOREDUMP(pn->status))
+ sprintf((state = buf2), "%s (core dumped)",
+ sigmsg(WTERMSIG(pn->status)));
+ else
+ state = sigmsg(WTERMSIG(pn->status));
+
+ sprintf(buf, ":%d=%s", (int)pn->pid, state);
+
+ ret = dyncat(ret, buf);
+ }
+ return ret;
+}
+
+/**/
+static HashNode
+getpmjobstate(UNUSED(HashTable ht), char *name)
+{
+ Param pm = NULL;
+ int job;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR | PM_READONLY;
+ pm->gsu.s = &nullsetscalar_gsu;
+
+ if ((job = atoi(name)) >= 1 && job <= maxjob &&
+ jobtab[job].stat && jobtab[job].procs &&
+ !(jobtab[job].stat & STAT_NOPRINT))
+ pm->u.str = pmjobstate(job);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmjobstates(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int job;
+ char buf[40];
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ for (job = 1; job <= maxjob; job++) {
+ if (jobtab[job].stat && jobtab[job].procs &&
+ !(jobtab[job].stat & STAT_NOPRINT)) {
+ if (func != scancountparams) {
+ sprintf(buf, "%d", job);
+ pm.nam = dupstring(buf);
+ if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS))
+ pm.u.str = pmjobstate(job);
+ }
+ func((HashNode) &pm, flags);
+ }
+ }
+}
+
+/* Functions for the jobdirs special parameter. */
+
+/**/
+static char *
+pmjobdir(int job)
+{
+ char *ret;
+
+ ret = dupstring(jobtab[job].pwd ? jobtab[job].pwd : pwd);
+ return ret;
+}
+
+/**/
+static HashNode
+getpmjobdir(UNUSED(HashTable ht), char *name)
+{
+ Param pm = NULL;
+ int job;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR | PM_READONLY;
+ pm->gsu.s = &nullsetscalar_gsu;
+
+ if ((job = atoi(name)) >= 1 && job <= maxjob &&
+ jobtab[job].stat && jobtab[job].procs &&
+ !(jobtab[job].stat & STAT_NOPRINT))
+ pm->u.str = pmjobdir(job);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmjobdirs(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int job;
+ char buf[40];
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ for (job = 1; job <= maxjob; job++) {
+ if (jobtab[job].stat && jobtab[job].procs &&
+ !(jobtab[job].stat & STAT_NOPRINT)) {
+ if (func != scancountparams) {
+ sprintf(buf, "%d", job);
+ pm.nam = dupstring(buf);
+ if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS))
+ pm.u.str = pmjobdir(job);
+ }
+ func((HashNode) &pm, flags);
+ }
+ }
+}
+
+/* Functions for the nameddirs special parameter. */
+
+/**/
+static void
+setpmnameddir(Param pm, char *value)
+{
+ if (!value)
+ zwarn("invalid value: ''", NULL, 0);
+ else {
+ Nameddir nd = (Nameddir) zshcalloc(sizeof(*nd));
+
+ nd->flags = 0;
+ nd->dir = value;
+ nameddirtab->addnode(nameddirtab, ztrdup(pm->nam), nd);
+ }
+}
+
+/**/
+static void
+unsetpmnameddir(Param pm, UNUSED(int exp))
+{
+ HashNode hd = nameddirtab->removenode(nameddirtab, pm->nam);
+
+ if (hd)
+ nameddirtab->freenode(hd);
+}
+
+/**/
+static void
+setpmnameddirs(UNUSED(Param pm), HashTable ht)
+{
+ int i;
+ HashNode hn, next, hd;
+
+ if (!ht)
+ return;
+
+ for (i = 0; i < nameddirtab->hsize; i++)
+ for (hn = nameddirtab->nodes[i]; hn; hn = next) {
+ next = hn->next;
+ if (!(((Nameddir) hn)->flags & ND_USERNAME) &&
+ (hd = nameddirtab->removenode(nameddirtab, hn->nam)))
+ nameddirtab->freenode(hd);
+ }
+
+ 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.start = 0;
+ v.end = -1;
+ v.arr = NULL;
+ v.pm = (Param) hn;
+
+ if (!(val = getstrvalue(&v)))
+ zwarn("invalid value: ''", NULL, 0);
+ else {
+ Nameddir nd = (Nameddir) zshcalloc(sizeof(*nd));
+
+ nd->flags = 0;
+ nd->dir = ztrdup(val);
+ nameddirtab->addnode(nameddirtab, ztrdup(hn->nam), nd);
+ }
+ }
+
+ /* The INTERACTIVE stuff ensures that the dirs are not immediatly removed
+ * when the sub-pms are deleted. */
+
+ i = opts[INTERACTIVE];
+ opts[INTERACTIVE] = 0;
+ deleteparamtable(ht);
+ opts[INTERACTIVE] = i;
+}
+
+static const struct gsu_scalar pmnamedir_gsu =
+{ strgetfn, setpmnameddir, unsetpmnameddir };
+
+/**/
+static HashNode
+getpmnameddir(UNUSED(HashTable ht), char *name)
+{
+ Param pm = NULL;
+ Nameddir nd;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR;
+ pm->gsu.s = &pmnamedir_gsu;
+ if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
+ !(nd->flags & ND_USERNAME))
+ pm->u.str = dupstring(nd->dir);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmnameddirs(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+ Nameddir nd;
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR;
+ pm.gsu.s = &pmnamedir_gsu;
+
+ for (i = 0; i < nameddirtab->hsize; i++)
+ for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) {
+ if (!((nd = (Nameddir) hn)->flags & ND_USERNAME)) {
+ pm.nam = hn->nam;
+ if (func != scancountparams &&
+ ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS)))
+ pm.u.str = dupstring(nd->dir);
+ func((HashNode) &pm, flags);
+ }
+ }
+}
+
+/* Functions for the userdirs special parameter. */
+
+/**/
+static HashNode
+getpmuserdir(UNUSED(HashTable ht), char *name)
+{
+ Param pm = NULL;
+ Nameddir nd;
+
+ nameddirtab->filltable(nameddirtab);
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+ pm->flags = PM_SCALAR | PM_READONLY;
+ pm->gsu.s = &nullsetscalar_gsu;
+ if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
+ (nd->flags & ND_USERNAME))
+ pm->u.str = dupstring(nd->dir);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static void
+scanpmuserdirs(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+ Nameddir nd;
+
+ nameddirtab->filltable(nameddirtab);
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.flags = PM_SCALAR | PM_READONLY;
+ pm.gsu.s = &nullsetscalar_gsu;
+
+ for (i = 0; i < nameddirtab->hsize; i++)
+ for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) {
+ if ((nd = (Nameddir) hn)->flags & ND_USERNAME) {
+ pm.nam = hn->nam;
+ if (func != scancountparams &&
+ ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(flags & SCANPM_WANTKEYS)))
+ pm.u.str = dupstring(nd->dir);
+ func((HashNode) &pm, flags);
+ }
+ }
+}
+
+/* Functions for the raliases, galiases and saliases special parameters. */
+
+/**/
+static void
+setalias(HashTable ht, Param pm, char *value, int flags)
+{
+ ht->addnode(ht, ztrdup(pm->nam),
+ createaliasnode(value, flags));
+}
+
+/**/
+static void
+setpmralias(Param pm, char *value)
+{
+ setalias(aliastab, pm, value, 0);
+}
+
+/**/
+static void
+setpmdisralias(Param pm, char *value)
+{
+ setalias(aliastab, pm, value, DISABLED);
+}
+
+/**/
+static void
+setpmgalias(Param pm, char *value)
+{
+ setalias(aliastab, pm, value, ALIAS_GLOBAL);
+}
+
+/**/
+static void
+setpmdisgalias(Param pm, char *value)
+{
+ setalias(aliastab, pm, value, ALIAS_GLOBAL|DISABLED);
+}
+
+/**/
+static void
+setpmsalias(Param pm, char *value)
+{
+ setalias(sufaliastab, pm, value, ALIAS_SUFFIX);
+}
+
+/**/
+static void
+setpmdissalias(Param pm, char *value)
+{
+ setalias(sufaliastab, pm, value, ALIAS_SUFFIX|DISABLED);
+}
+
+/**/
+static void
+unsetpmalias(Param pm, UNUSED(int exp))
+{
+ HashNode hd = aliastab->removenode(aliastab, pm->nam);
+
+ if (hd)
+ aliastab->freenode(hd);
+}
+
+/**/
+static void
+unsetpmsalias(Param pm, UNUSED(int exp))
+{
+ HashNode hd = sufaliastab->removenode(sufaliastab, pm->nam);
+
+ if (hd)
+ sufaliastab->freenode(hd);
+}
+
+/**/
+static void
+setaliases(HashTable alht, UNUSED(Param pm), HashTable ht, int flags)
+{
+ int i;
+ HashNode hn, next, hd;
+
+ if (!ht)
+ return;
+
+ for (i = 0; i < alht->hsize; i++)
+ for (hn = alht->nodes[i]; hn; hn = next) {
+ next = hn->next;
+ /*
+ * The following respects the DISABLED flag, e.g.
+ * we get a different behaviour for raliases and dis_raliases.
+ * The predecessor to this code didn't do that; presumably
+ * that was a bug.
+ */
+ if (flags == ((Alias)hn)->flags &&
+ (hd = alht->removenode(alht, hn->nam)))
+ alht->freenode(hd);
+ }
+
+ 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.start = 0;
+ v.end = -1;
+ v.arr = NULL;
+ v.pm = (Param) hn;
+
+ if ((val = getstrvalue(&v)))
+ alht->addnode(alht, ztrdup(hn->nam),
+ createaliasnode(ztrdup(val), flags));
+ }
+ deleteparamtable(ht);
+}
+
+/**/
+static void
+setpmraliases(Param pm, HashTable ht)
+{
+ setaliases(aliastab, pm, ht, 0);
+}
+
+/**/
+static void
+setpmdisraliases(Param pm, HashTable ht)
+{
+ setaliases(aliastab, pm, ht, DISABLED);
+}
+
+/**/
+static void
+setpmgaliases(Param pm, HashTable ht)
+{
+ setaliases(aliastab, pm, ht, ALIAS_GLOBAL);
+}
+
+/**/
+static void
+setpmdisgaliases(Param pm, HashTable ht)
+{
+ setaliases(aliastab, pm, ht, ALIAS_GLOBAL|DISABLED);
+}
+
+/**/
+static void
+setpmsaliases(Param pm, HashTable ht)
+{
+ setaliases(sufaliastab, pm, ht, ALIAS_SUFFIX);
+}
+
+/**/
+static void
+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)
+{
+ pm->flags = PM_SCALAR;
+
+ /* we really need to squirrel the flags away somewhere... */
+ switch (flags) {
+ case 0:
+ pm->gsu.s = &pmralias_gsu;
+ break;
+
+ case ALIAS_GLOBAL:
+ pm->gsu.s = &pmgalias_gsu;
+ break;
+
+ case ALIAS_SUFFIX:
+ pm->gsu.s = &pmsalias_gsu;
+ break;
+
+ case DISABLED:
+ pm->gsu.s = &pmdisralias_gsu;
+ break;
+
+ case ALIAS_GLOBAL|DISABLED:
+ pm->gsu.s = &pmdisgalias_gsu;
+ break;
+
+ case ALIAS_SUFFIX|DISABLED:
+ pm->gsu.s = &pmdissalias_gsu;
+ break;
+ }
+}
+
+/**/
+static HashNode
+getalias(HashTable alht, UNUSED(HashTable ht), char *name, int flags)
+{
+ Param pm = NULL;
+ Alias al;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->nam = dupstring(name);
+
+ assignaliasdefs(pm, flags);
+
+ if ((al = (Alias) alht->getnode2(alht, name)) &&
+ flags == al->flags)
+ pm->u.str = dupstring(al->text);
+ else {
+ pm->u.str = dupstring("");
+ pm->flags |= PM_UNSET;
+ }
+ return (HashNode) pm;
+}
+
+/**/
+static HashNode
+getpmralias(HashTable ht, char *name)
+{
+ return getalias(aliastab, ht, name, 0);
+}
+
+/**/
+static HashNode
+getpmdisralias(HashTable ht, char *name)
+{
+ return getalias(aliastab, ht, name, DISABLED);
+}
+
+/**/
+static HashNode
+getpmgalias(HashTable ht, char *name)
+{
+ return getalias(aliastab, ht, name, ALIAS_GLOBAL);
+}
+
+/**/
+static HashNode
+getpmdisgalias(HashTable ht, char *name)
+{
+ return getalias(aliastab, ht, name, ALIAS_GLOBAL|DISABLED);
+}
+
+/**/
+static HashNode
+getpmsalias(HashTable ht, char *name)
+{
+ return getalias(sufaliastab, ht, name, ALIAS_SUFFIX);
+}
+
+/**/
+static HashNode
+getpmdissalias(HashTable ht, char *name)
+{
+ return getalias(sufaliastab, ht, name, ALIAS_SUFFIX|DISABLED);
+}
+
+/**/
+static void
+scanaliases(HashTable alht, UNUSED(HashTable ht), ScanFunc func,
+ int pmflags, int alflags)
+{
+ struct param pm;
+ int i;
+ Alias al;
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ assignaliasdefs(&pm, alflags);
+
+ for (i = 0; i < alht->hsize; i++)
+ for (al = (Alias) alht->nodes[i]; al; al = (Alias) al->next) {
+ if (alflags == al->flags) {
+ pm.nam = al->nam;
+ if (func != scancountparams &&
+ ((pmflags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
+ !(pmflags & SCANPM_WANTKEYS)))
+ pm.u.str = dupstring(al->text);
+ func((HashNode) &pm, pmflags);
+ }
+ }
+}
+
+/**/
+static void
+scanpmraliases(HashTable ht, ScanFunc func, int flags)
+{
+ scanaliases(aliastab, ht, func, flags, 0);
+}
+
+/**/
+static void
+scanpmdisraliases(HashTable ht, ScanFunc func, int flags)
+{
+ scanaliases(aliastab, ht, func, flags, DISABLED);
+}
+
+/**/
+static void
+scanpmgaliases(HashTable ht, ScanFunc func, int flags)
+{
+ scanaliases(aliastab, ht, func, flags, ALIAS_GLOBAL);
+}
+
+/**/
+static void
+scanpmdisgaliases(HashTable ht, ScanFunc func, int flags)
+{
+ scanaliases(aliastab, ht, func, flags, ALIAS_GLOBAL|DISABLED);
+}
+
+/**/
+static void
+scanpmsaliases(HashTable ht, ScanFunc func, int flags)
+{
+ scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX);
+}
+
+/**/
+static void
+scanpmdissaliases(HashTable ht, ScanFunc func, int flags)
+{
+ scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX|DISABLED);
+}
+
+/* Table for defined parameters. */
+
+struct pardef {
+ char *name;
+ int flags;
+ GetNodeFunc getnfn;
+ ScanTabFunc scantfn;
+ GsuHash hash_gsu;
+ GsuArray array_gsu;
+ Param pm;
+};
+
+/*
+ * This is a duplicate of nullsethash_gsu. On some systems
+ * (such as Cygwin) we can't put a pointer to an imported variable
+ * in a compile-time initialiser, so we use this instead.
+ */
+static const struct gsu_hash pmnullsethash_gsu =
+{ hashgetfn, nullsethashfn, nullunsetfn };
+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, &pmnullsethash_gsu,
+ NULL, NULL },
+ { "commands", 0,
+ getpmcommand, scanpmcommands, &pmcommands_gsu,
+ NULL, NULL },
+ { "functions", 0,
+ getpmfunction, scanpmfunctions, &pmfunctions_gsu,
+ NULL, NULL },
+ { "dis_functions", 0,
+ getpmdisfunction, scanpmdisfunctions, &pmdisfunctions_gsu,
+ NULL, NULL },
+ { "funcstack", PM_ARRAY|PM_SPECIAL|PM_READONLY,
+ NULL, NULL, NULL,
+ &funcstack_gsu, NULL },
+ { "builtins", PM_READONLY,
+ getpmbuiltin, scanpmbuiltins, NULL,
+ NULL, NULL },
+ { "dis_builtins", PM_READONLY,
+ getpmdisbuiltin, scanpmdisbuiltins,
+ NULL, NULL, },
+ { "reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
+ NULL, NULL, NULL,
+ &reswords_gsu, NULL },
+ { "dis_reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
+ NULL, NULL, NULL,
+ &disreswords_gsu, NULL },
+ { "options", 0,
+ getpmoption, scanpmoptions, &pmoptions_gsu,
+ NULL, NULL },
+ { "modules", PM_READONLY,
+ getpmmodule, scanpmmodules, NULL,
+ NULL, NULL },
+ { "dirstack", PM_ARRAY|PM_SPECIAL|PM_REMOVABLE,
+ NULL, NULL, NULL,
+ &dirs_gsu, NULL },
+ { "history", PM_READONLY,
+ getpmhistory, scanpmhistory, NULL,
+ NULL, NULL, },
+ { "historywords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
+ NULL, NULL, NULL,
+ &historywords_gsu, NULL },
+ { "jobtexts", PM_READONLY,
+ getpmjobtext, scanpmjobtexts, NULL,
+ NULL, NULL },
+ { "jobstates", PM_READONLY,
+ getpmjobstate, scanpmjobstates, NULL,
+ NULL, NULL },
+ { "jobdirs", PM_READONLY,
+ getpmjobdir, scanpmjobdirs, NULL,
+ NULL, NULL },
+ { "nameddirs", 0,
+ getpmnameddir, scanpmnameddirs, &pmnameddirs_gsu,
+ NULL, NULL },
+ { "userdirs", PM_READONLY,
+ getpmuserdir, scanpmuserdirs, NULL,
+ NULL, NULL },
+ { "aliases", 0,
+ getpmralias, scanpmraliases, &pmraliases_gsu,
+ NULL, NULL },
+ { "galiases", 0,
+ getpmgalias, scanpmgaliases, &pmgaliases_gsu,
+ NULL, NULL },
+ { "saliases", 0,
+ getpmsalias, scanpmsaliases, &pmsaliases_gsu,
+ NULL, NULL },
+ { "dis_aliases", 0,
+ getpmdisralias, scanpmdisraliases, &pmdisraliases_gsu,
+ NULL, NULL },
+ { "dis_galiases", 0,
+ getpmdisgalias, scanpmdisgaliases, &pmdisgaliases_gsu,
+ NULL, NULL },
+ { "dis_saliases", 0,
+ getpmdissalias, scanpmdissaliases, &pmdissaliases_gsu,
+ NULL, NULL },
+ { NULL, 0, NULL, NULL, NULL, NULL, NULL }
+};
+
+/**/
+int
+setup_(UNUSED(Module m))
+{
+ incleanup = 0;
+
+ return 0;
+}
+
+/**/
+int
+boot_(UNUSED(Module m))
+{
+ /* Create the special associative arrays.
+ * As an example for autoloaded parameters, this is probably a bad
+ * example, because the zsh core doesn't support creation of
+ * special hashes, yet. */
+
+ struct pardef *def;
+
+ for (def = partab; def->name; def++) {
+ unsetparam(def->name);
+
+ if (def->getnfn) {
+ if (!(def->pm = createspecialhash(def->name, def->getnfn,
+ def->scantfn)))
+ return 1;
+ def->pm->flags |= def->flags;
+ 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->gsu.a = def->array_gsu;
+ }
+ }
+ return 0;
+}
+
+/**/
+int
+cleanup_(UNUSED(Module m))
+{
+ Param pm;
+ struct pardef *def;
+
+ incleanup = 1;
+
+ for (def = partab; def->name; def++) {
+ if ((pm = (Param) paramtab->getnode(paramtab, def->name)) &&
+ pm == def->pm) {
+ pm->flags &= ~PM_READONLY;
+ unsetparam_pm(pm, 0, 1);
+ }
+ }
+ return 0;
+}
+
+/**/
+int
+finish_(UNUSED(Module m))
+{
+ return 0;
+}