zsh/Src/Modules/parameter.c
2003-09-08 11:17:20 +00:00

2104 lines
45 KiB
C

/*
* 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"
/* 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->gets.hfn = hashgetfn;
pm->sets.hfn = hashsetfn;
pm->unsetfn = stdunsetfn;
pm->u.hash = ht = newhashtable(0, name, NULL);
pm->ct = 0;
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(HashTable ht, char *name)
{
Param rpm, pm = NULL;
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 = dupstring("");
pm->flags |= PM_UNSET;
}
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) {
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 = zcalloc(sizeof(*cn));
cn->flags = HASHED;
cn->u.cmd = 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;
if (!ht)
return;
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.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 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);
}
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 = dupstring("");
pm->flags |= PM_UNSET;
}
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 &&
((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, int exp)
{
HashNode hn = shfunctab->removenode(shfunctab, pm->nam);
if (hn)
shfunctab->freenode(hn);
}
/**/
static void
setfunctions(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 HashNode
getfunction(HashTable ht, char *name, int dis)
{
Shfunc shf;
Param pm = NULL;
pm = (Param) zhalloc(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;
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(HashTable ht, ScanFunc func, int flags, int dis)
{
struct param pm;
int i;
HashNode hn;
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;
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(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(HashTable ht, char *name, int dis)
{
Param pm = NULL;
Builtin bn;
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 ((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(HashTable ht, ScanFunc func, int flags, int dis)
{
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 < 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(Param pm)
{
return getreswords(0);
}
/**/
static char **
disreswordsgetfn(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, 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(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 HashNode
getpmoption(HashTable ht, char *name)
{
Param pm = NULL;
int n;
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)))
{
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(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) {
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, int dummy)
{
if (!(((Builtin) hn)->flags & BINF_ADDED) &&
!strcmp(((Builtin) hn)->optstr, modpmname))
modpmfound = 1;
}
/**/
static void
modpmparamscan(HashNode hn, 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(HashTable ht, char *name)
{
Param pm = NULL;
char *type = NULL;
LinkNode node;
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 (!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(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");
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 (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(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(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(HashTable ht, char *name)
{
Param pm = NULL;
Histent he;
char *p;
int ok = 1;
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 (*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(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];
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;
while (he) {
if (func != scancountparams) {
sprintf(buf, "%d", he->histnum);
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(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(HashTable ht, char *name)
{
Param pm = NULL;
int job;
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 ((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(HashTable ht, ScanFunc func, int flags)
{
struct param pm;
int job;
char buf[40];
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 (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(HashTable ht, char *name)
{
Param pm = NULL;
int job;
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 ((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(HashTable ht, ScanFunc func, int flags)
{
struct param pm;
int job;
char buf[40];
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 (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(HashTable ht, char *name)
{
Param pm = NULL;
int job;
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 ((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(HashTable ht, ScanFunc func, int flags)
{
struct param pm;
int job;
char buf[40];
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 (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) zcalloc(sizeof(*nd));
nd->flags = 0;
nd->dir = value;
nameddirtab->addnode(nameddirtab, ztrdup(pm->nam), nd);
}
}
/**/
static void
unsetpmnameddir(Param pm, int exp)
{
HashNode hd = nameddirtab->removenode(nameddirtab, pm->nam);
if (hd)
nameddirtab->freenode(hd);
}
/**/
static void
setpmnameddirs(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) zcalloc(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 HashNode
getpmnameddir(HashTable ht, char *name)
{
Param pm = NULL;
Nameddir nd;
pm = (Param) zhalloc(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;
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(HashTable ht, ScanFunc func, int flags)
{
struct param pm;
int i;
HashNode hn;
Nameddir nd;
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;
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(HashTable ht, char *name)
{
Param pm = NULL;
Nameddir nd;
nameddirtab->filltable(nameddirtab);
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 ((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(HashTable ht, ScanFunc func, int flags)
{
struct param pm;
int i;
HashNode hn;
Nameddir nd;
nameddirtab->filltable(nameddirtab);
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 < 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, int exp)
{
HashNode hd = aliastab->removenode(aliastab, pm->nam);
if (hd)
aliastab->freenode(hd);
}
/**/
static void
unsetpmsalias(Param pm, int exp)
{
HashNode hd = sufaliastab->removenode(sufaliastab, pm->nam);
if (hd)
sufaliastab->freenode(hd);
}
/**/
static void
setaliases(HashTable alht, 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 void
assignaliasdefs(Param pm, int flags)
{
pm->flags = PM_SCALAR;
/* we really need to squirrel the flags away somewhere... */
switch (flags) {
case 0:
pm->sets.cfn = setpmralias;
break;
case ALIAS_GLOBAL:
pm->sets.cfn = setpmgalias;
break;
case ALIAS_SUFFIX:
pm->sets.cfn = setpmsalias;
break;
case DISABLED:
pm->sets.cfn = setpmdisralias;
break;
case ALIAS_GLOBAL|DISABLED:
pm->sets.cfn = setpmdisgalias;
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;
}
/**/
static HashNode
getalias(HashTable alht, HashTable ht, char *name, int flags)
{
Param pm = NULL;
Alias al;
pm = (Param) zhalloc(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, HashTable ht, ScanFunc func,
int pmflags, int alflags)
{
struct param pm;
int i;
Alias al;
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;
void (*hsetfn) _((Param, HashTable));
void (*setfn) _((Param, char **));
char **(*getfn) _((Param));
void (*unsetfn) _((Param, int));
Param pm;
};
static struct pardef partab[] = {
{ "parameters", PM_READONLY,
getpmparameter, scanpmparameters, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "commands", 0,
getpmcommand, scanpmcommands, setpmcommands,
NULL, NULL, stdunsetfn, NULL },
{ "functions", 0,
getpmfunction, scanpmfunctions, setpmfunctions,
NULL, NULL, stdunsetfn, NULL },
{ "dis_functions", 0,
getpmdisfunction, scanpmdisfunctions, setpmdisfunctions,
NULL, NULL, stdunsetfn, NULL },
{ "funcstack", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
arrsetfn, funcstackgetfn, stdunsetfn, NULL },
{ "builtins", PM_READONLY,
getpmbuiltin, scanpmbuiltins, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "dis_builtins", PM_READONLY,
getpmdisbuiltin, scanpmdisbuiltins, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
arrsetfn, reswordsgetfn, stdunsetfn, NULL },
{ "dis_reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
arrsetfn, disreswordsgetfn, stdunsetfn, NULL },
{ "options", 0,
getpmoption, scanpmoptions, setpmoptions,
NULL, NULL, stdunsetfn, NULL },
{ "modules", PM_READONLY,
getpmmodule, scanpmmodules, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "dirstack", PM_ARRAY|PM_SPECIAL|PM_REMOVABLE,
NULL, NULL, NULL,
dirssetfn, dirsgetfn, stdunsetfn, NULL },
{ "history", PM_READONLY,
getpmhistory, scanpmhistory, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "historywords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
NULL, NULL, NULL,
arrsetfn, histwgetfn, stdunsetfn, NULL },
{ "jobtexts", PM_READONLY,
getpmjobtext, scanpmjobtexts, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "jobstates", PM_READONLY,
getpmjobstate, scanpmjobstates, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "jobdirs", PM_READONLY,
getpmjobdir, scanpmjobdirs, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "nameddirs", 0,
getpmnameddir, scanpmnameddirs, setpmnameddirs,
NULL, NULL, stdunsetfn, NULL },
{ "userdirs", PM_READONLY,
getpmuserdir, scanpmuserdirs, hashsetfn,
NULL, NULL, stdunsetfn, NULL },
{ "aliases", 0,
getpmralias, scanpmraliases, setpmraliases,
NULL, NULL, stdunsetfn, NULL },
{ "galiases", 0,
getpmgalias, scanpmgaliases, setpmgaliases,
NULL, NULL, stdunsetfn, NULL },
{ "saliases", 0,
getpmsalias, scanpmsaliases, setpmsaliases,
NULL, NULL, stdunsetfn, NULL },
{ "dis_aliases", 0,
getpmdisralias, scanpmdisraliases, setpmdisraliases,
NULL, NULL, stdunsetfn, NULL },
{ "dis_galiases", 0,
getpmdisgalias, scanpmdisgaliases, setpmdisgaliases,
NULL, NULL, stdunsetfn, NULL },
{ "dis_saliases", 0,
getpmdissalias, scanpmdissaliases, setpmdissaliases,
NULL, NULL, stdunsetfn, NULL },
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};
/**/
int
setup_(Module m)
{
incleanup = 0;
return 0;
}
/**/
int
boot_(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->hsetfn)
def->pm->sets.hfn = def->hsetfn;
} 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;
}
}
return 0;
}
/**/
int
cleanup_(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_(Module m)
{
return 0;
}