summaryrefslogtreecommitdiff
path: root/Src/Modules/parameter.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Modules/parameter.c')
-rw-r--r--Src/Modules/parameter.c662
1 files changed, 662 insertions, 0 deletions
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