openenvutils/commandshell/shell/src/modules/parameter.c
changeset 0 2e3d3ce01487
child 1 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // parameter.c - parameter interface to zsh internals
       
     2 //
       
     3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     4 //
       
     5 /*
       
     6  * This file is part of zsh, the Z shell.
       
     7  *
       
     8  * Copyright (c) 1999 Sven Wischnowsky
       
     9  * All rights reserved.
       
    10  *
       
    11  * Permission is hereby granted, without written agreement and without
       
    12  * license or royalty fees, to use, copy, modify, and distribute this
       
    13  * software and to distribute modified versions of this software for any
       
    14  * purpose, provided that the above copyright notice and the following
       
    15  * two paragraphs appear in all copies of this software.
       
    16  *
       
    17  * In no event shall Sven Wischnowsky or the Zsh Development Group be liable
       
    18  * to any party for direct, indirect, special, incidental, or consequential
       
    19  * damages arising out of the use of this software and its documentation,
       
    20  * even if Sven Wischnowsky and the Zsh Development Group have been advised of
       
    21  * the possibility of such damage.
       
    22  *
       
    23  * Sven Wischnowsky and the Zsh Development Group specifically disclaim any
       
    24  * warranties, including, but not limited to, the implied warranties of
       
    25  * merchantability and fitness for a particular purpose.  The software
       
    26  * provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
       
    27  * Zsh Development Group have no obligation to provide maintenance,
       
    28  * support, updates, enhancements, or modifications.
       
    29  *
       
    30  */
       
    31 
       
    32 #include "parameter.mdh"
       
    33 #include "parameter.pro"
       
    34 
       
    35 #ifdef __SYMBIAN32__
       
    36 #ifdef __WINSCW__
       
    37 #pragma warn_unusedarg off
       
    38 #pragma warn_possunwant off
       
    39 #endif//__WINSCW__
       
    40 #endif//__SYMBIAN32__
       
    41 
       
    42 /* This says if we are cleaning up when the module is unloaded. */
       
    43 
       
    44 static int incleanup;
       
    45 
       
    46 /* Empty dummy function for special hash parameters. */
       
    47 
       
    48 /**/
       
    49 static void
       
    50 shempty(void)
       
    51 {
       
    52 }
       
    53 
       
    54 /* Create a simple special hash parameter. */
       
    55 
       
    56 /**/
       
    57 static Param
       
    58 createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan)
       
    59 {
       
    60     Param pm;
       
    61     HashTable ht;
       
    62 
       
    63     if (!(pm = createparam(name, PM_SPECIAL|PM_HIDE|PM_HIDEVAL|
       
    64 			   PM_REMOVABLE|PM_HASHED)))
       
    65 	return NULL;
       
    66 
       
    67     pm->level = pm->old ? locallevel : 0;
       
    68     pm->gsu.h = &stdhash_gsu;
       
    69     pm->u.hash = ht = newhashtable(0, name, NULL);
       
    70 
       
    71     ht->hash        = hasher;
       
    72     ht->emptytable  = (TableFunc) shempty;
       
    73     ht->filltable   = NULL;
       
    74     ht->addnode     = (AddNodeFunc) shempty;
       
    75     ht->getnode     = ht->getnode2 = get;
       
    76     ht->removenode  = (RemoveNodeFunc) shempty;
       
    77     ht->disablenode = NULL;
       
    78     ht->enablenode  = NULL;
       
    79     ht->freenode    = (FreeNodeFunc) shempty;
       
    80     ht->printnode   = printparamnode;
       
    81     ht->scantab     = scan;
       
    82 
       
    83     return pm;
       
    84 }
       
    85 
       
    86 /* Functions for the parameters special parameter. */
       
    87 
       
    88 /* Return a string describing the type of a parameter. */
       
    89 
       
    90 /**/
       
    91 static char *
       
    92 paramtypestr(Param pm)
       
    93 {
       
    94     char *val = NULL;
       
    95     int f = pm->flags;
       
    96 
       
    97     if (!(f & PM_UNSET)) {
       
    98 	if (pm->flags & PM_AUTOLOAD)
       
    99 	    return dupstring("undefined");
       
   100 
       
   101 	switch (PM_TYPE(f)) {
       
   102 	case PM_SCALAR:  val = "scalar"; break;
       
   103 	case PM_ARRAY:   val = "array"; break;
       
   104 	case PM_INTEGER: val = "integer"; break;
       
   105 	case PM_EFLOAT:
       
   106 	case PM_FFLOAT:  val = "float"; break;
       
   107 	case PM_HASHED:  val = "association"; break;
       
   108 	}
       
   109 	DPUTS(!val, "BUG: type not handled in parameter");
       
   110 	val = dupstring(val);
       
   111 	if (pm->level)
       
   112 	    val = dyncat(val, "-local");
       
   113 	if (f & PM_LEFT)
       
   114 	    val = dyncat(val, "-left");
       
   115 	if (f & PM_RIGHT_B)
       
   116 	    val = dyncat(val, "-right_blanks");
       
   117 	if (f & PM_RIGHT_Z)
       
   118 	    val = dyncat(val, "-right_zeros");
       
   119 	if (f & PM_LOWER)
       
   120 	    val = dyncat(val, "-lower");
       
   121 	if (f & PM_UPPER)
       
   122 	    val = dyncat(val, "-upper");
       
   123 	if (f & PM_READONLY)
       
   124 	    val = dyncat(val, "-readonly");
       
   125 	if (f & PM_TAGGED)
       
   126 	    val = dyncat(val, "-tag");
       
   127 	if (f & PM_EXPORTED)
       
   128 	    val = dyncat(val, "-export");
       
   129 	if (f & PM_UNIQUE)
       
   130 	    val = dyncat(val, "-unique");
       
   131 	if (f & PM_HIDE)
       
   132 	    val = dyncat(val, "-hide");
       
   133 	if (f & PM_HIDEVAL)
       
   134 	    val = dyncat(val, "-hideval");
       
   135 	if (f & PM_SPECIAL)
       
   136 	    val = dyncat(val, "-special");
       
   137     } else
       
   138 	val = dupstring("");
       
   139 
       
   140     return val;
       
   141 }
       
   142 
       
   143 /**/
       
   144 static HashNode
       
   145 getpmparameter(UNUSED(HashTable ht), char *name)
       
   146 {
       
   147     Param rpm, pm = NULL;
       
   148 
       
   149     pm = (Param) hcalloc(sizeof(struct param));
       
   150     pm->nam = dupstring(name);
       
   151     pm->flags = PM_SCALAR | PM_READONLY;
       
   152     pm->gsu.s = &nullsetscalar_gsu;
       
   153     if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
       
   154 	!(rpm->flags & PM_UNSET))
       
   155 	pm->u.str = paramtypestr(rpm);
       
   156     else {
       
   157 	pm->u.str = dupstring("");
       
   158 	pm->flags |= PM_UNSET;
       
   159     }
       
   160     return (HashNode) pm;
       
   161 }
       
   162 
       
   163 /**/
       
   164 static void
       
   165 scanpmparameters(UNUSED(HashTable ht), ScanFunc func, int flags)
       
   166 {
       
   167     struct param pm;
       
   168     int i;
       
   169     HashNode hn;
       
   170 
       
   171     memset((void *)&pm, 0, sizeof(struct param));
       
   172     pm.flags = PM_SCALAR | PM_READONLY;
       
   173     pm.gsu.s = &nullsetscalar_gsu;
       
   174 
       
   175     for (i = 0; i < realparamtab->hsize; i++)
       
   176 	for (hn = realparamtab->nodes[i]; hn; hn = hn->next) {
       
   177 	    if (((Param)hn)->flags & PM_UNSET)
       
   178 		continue;
       
   179 	    pm.nam = hn->nam;
       
   180 	    if (func != scancountparams &&
       
   181 		((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
   182 		 !(flags & SCANPM_WANTKEYS)))
       
   183 		pm.u.str = paramtypestr((Param) hn);
       
   184 	    func((HashNode) &pm, flags);
       
   185 	}
       
   186 }
       
   187 
       
   188 /* Functions for the commands special parameter. */
       
   189 
       
   190 /**/
       
   191 static void
       
   192 setpmcommand(Param pm, char *value)
       
   193 {
       
   194     if (isset(RESTRICTED)) {
       
   195 	zwarn("restricted: %s", value, 0);
       
   196 	zsfree(value);
       
   197     } else {
       
   198 	Cmdnam cn = zshcalloc(sizeof(*cn));
       
   199 
       
   200 	cn->flags = HASHED;
       
   201 	cn->u.cmd = value;
       
   202 
       
   203 	cmdnamtab->addnode(cmdnamtab, ztrdup(pm->nam), (HashNode) cn);
       
   204     }
       
   205 }
       
   206 
       
   207 /**/
       
   208 static void
       
   209 unsetpmcommand(Param pm, UNUSED(int exp))
       
   210 {
       
   211     HashNode hn = cmdnamtab->removenode(cmdnamtab, pm->nam);
       
   212 
       
   213     if (hn)
       
   214 	cmdnamtab->freenode(hn);
       
   215 }
       
   216 
       
   217 /**/
       
   218 static void
       
   219 setpmcommands(UNUSED(Param pm), HashTable ht)
       
   220 {
       
   221     int i;
       
   222     HashNode hn;
       
   223 
       
   224     if (!ht)
       
   225 	return;
       
   226 
       
   227     for (i = 0; i < ht->hsize; i++)
       
   228 	for (hn = ht->nodes[i]; hn; hn = hn->next) {
       
   229 	    Cmdnam cn = zshcalloc(sizeof(*cn));
       
   230 	    struct value v;
       
   231 
       
   232 	    v.isarr = v.inv = v.start = 0;
       
   233 	    v.end = -1;
       
   234 	    v.arr = NULL;
       
   235 	    v.pm = (Param) hn;
       
   236 
       
   237 	    cn->flags = HASHED;
       
   238 	    cn->u.cmd = ztrdup(getstrvalue(&v));
       
   239 
       
   240 	    cmdnamtab->addnode(cmdnamtab, ztrdup(hn->nam), (HashNode) cn);
       
   241 	}
       
   242     deleteparamtable(ht);
       
   243 }
       
   244 
       
   245 static const struct gsu_scalar pmcommand_gsu =
       
   246 { strgetfn, setpmcommand, unsetpmcommand };
       
   247 
       
   248 
       
   249 /**/
       
   250 static HashNode
       
   251 getpmcommand(UNUSED(HashTable ht), char *name)
       
   252 {
       
   253     Cmdnam cmd;
       
   254     Param pm = NULL;
       
   255 
       
   256     if (!(cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name)) &&
       
   257 	isset(HASHLISTALL)) {
       
   258 	cmdnamtab->filltable(cmdnamtab);
       
   259 	cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name);
       
   260     }
       
   261     pm = (Param) hcalloc(sizeof(struct param));
       
   262     pm->nam = dupstring(name);
       
   263     pm->flags = PM_SCALAR;
       
   264     pm->gsu.s = &pmcommand_gsu;
       
   265     if (cmd) {
       
   266 	if (cmd->flags & HASHED)
       
   267 	    pm->u.str = cmd->u.cmd;
       
   268 	else {
       
   269 	    pm->u.str = zhalloc(strlen(*(cmd->u.name)) + strlen(name) + 2);
       
   270 	    strcpy(pm->u.str, *(cmd->u.name));
       
   271 	    strcat(pm->u.str, "/");
       
   272 	    strcat(pm->u.str, name);
       
   273 	}
       
   274     } else {
       
   275 	pm->u.str = dupstring("");
       
   276 	pm->flags |= PM_UNSET;
       
   277     }
       
   278     return (HashNode) pm;
       
   279 }
       
   280 
       
   281 /**/
       
   282 static void
       
   283 scanpmcommands(UNUSED(HashTable ht), ScanFunc func, int flags)
       
   284 {
       
   285     struct param pm;
       
   286     int i;
       
   287     HashNode hn;
       
   288     Cmdnam cmd;
       
   289 
       
   290     if (isset(HASHLISTALL))
       
   291 	cmdnamtab->filltable(cmdnamtab);
       
   292 
       
   293     memset((void *)&pm, 0, sizeof(struct param));
       
   294     pm.flags = PM_SCALAR;
       
   295     pm.gsu.s = &pmcommand_gsu;
       
   296 
       
   297     for (i = 0; i < cmdnamtab->hsize; i++)
       
   298 	for (hn = cmdnamtab->nodes[i]; hn; hn = hn->next) {
       
   299 	    pm.nam = hn->nam;
       
   300 	    cmd = (Cmdnam) hn;
       
   301 	    if (func != scancountparams &&
       
   302 		((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
   303 		 !(flags & SCANPM_WANTKEYS))) {
       
   304 		if (cmd->flags & HASHED)
       
   305 		    pm.u.str = cmd->u.cmd;
       
   306 		else {
       
   307 		    pm.u.str = zhalloc(strlen(*(cmd->u.name)) +
       
   308 				       strlen(cmd->nam) + 2);
       
   309 		    strcpy(pm.u.str, *(cmd->u.name));
       
   310 		    strcat(pm.u.str, "/");
       
   311 		    strcat(pm.u.str, cmd->nam);
       
   312 		}
       
   313 	    }
       
   314 	    func((HashNode) &pm, flags);
       
   315 	}
       
   316 }
       
   317 
       
   318 /* Functions for the functions special parameter. */
       
   319 
       
   320 /**/
       
   321 static void
       
   322 setfunction(char *name, char *val, int dis)
       
   323 {
       
   324     char *value = dupstring(val);
       
   325     Shfunc shf;
       
   326     Eprog prog;
       
   327     int sn;
       
   328 
       
   329     val = metafy(val, strlen(val), META_REALLOC);
       
   330 
       
   331     prog = parse_string(val);
       
   332 
       
   333     if (!prog || prog == &dummy_eprog) {
       
   334 	zwarn("invalid function definition", value, 0);
       
   335 	zsfree(val);
       
   336 	return;
       
   337     }
       
   338     shf = (Shfunc) zalloc(sizeof(*shf));
       
   339     shf->funcdef = dupeprog(prog, 0);
       
   340     shf->flags = dis;
       
   341 
       
   342     if (!strncmp(name, "TRAP", 4) &&
       
   343 	(sn = getsignum(name + 4)) != -1) {
       
   344 	if (settrap(sn, shf->funcdef)) {
       
   345 	    freeeprog(shf->funcdef);
       
   346 	    zfree(shf, sizeof(*shf));
       
   347 	    zsfree(val);
       
   348 	    return;
       
   349 	}
       
   350 	sigtrapped[sn] |= ZSIG_FUNC;
       
   351     }
       
   352     shfunctab->addnode(shfunctab, ztrdup(name), shf);
       
   353     zsfree(val);
       
   354 }
       
   355 
       
   356 /**/
       
   357 static void
       
   358 setpmfunction(Param pm, char *value)
       
   359 {
       
   360     setfunction(pm->nam, value, 0);
       
   361 }
       
   362 
       
   363 /**/
       
   364 static void
       
   365 setpmdisfunction(Param pm, char *value)
       
   366 {
       
   367     setfunction(pm->nam, value, DISABLED);
       
   368 }
       
   369 
       
   370 /**/
       
   371 static void
       
   372 unsetpmfunction(Param pm, UNUSED(int exp))
       
   373 {
       
   374     HashNode hn = shfunctab->removenode(shfunctab, pm->nam);
       
   375 
       
   376     if (hn)
       
   377 	shfunctab->freenode(hn);
       
   378 }
       
   379 
       
   380 /**/
       
   381 static void
       
   382 setfunctions(UNUSED(Param pm), HashTable ht, int dis)
       
   383 {
       
   384     int i;
       
   385     HashNode hn;
       
   386 
       
   387     if (!ht)
       
   388 	return;
       
   389 
       
   390     for (i = 0; i < ht->hsize; i++)
       
   391 	for (hn = ht->nodes[i]; hn; hn = hn->next) {
       
   392 	    struct value v;
       
   393 
       
   394 	    v.isarr = v.inv = v.start = 0;
       
   395 	    v.end = -1;
       
   396 	    v.arr = NULL;
       
   397 	    v.pm = (Param) hn;
       
   398 
       
   399 	    setfunction(hn->nam, ztrdup(getstrvalue(&v)), dis);
       
   400 	}
       
   401     deleteparamtable(ht);
       
   402 }
       
   403 
       
   404 /**/
       
   405 static void
       
   406 setpmfunctions(Param pm, HashTable ht)
       
   407 {
       
   408     setfunctions(pm, ht, 0);
       
   409 }
       
   410 
       
   411 /**/
       
   412 static void
       
   413 setpmdisfunctions(Param pm, HashTable ht)
       
   414 {
       
   415     setfunctions(pm, ht, DISABLED);
       
   416 }
       
   417 
       
   418 static const struct gsu_scalar pmfunction_gsu =
       
   419 { strgetfn, setpmfunction, unsetpmfunction };
       
   420 static const struct gsu_scalar pmdisfunction_gsu =
       
   421 { strgetfn, setpmdisfunction, unsetpmfunction };
       
   422 
       
   423 /**/
       
   424 static HashNode
       
   425 getfunction(UNUSED(HashTable ht), char *name, int dis)
       
   426 {
       
   427     Shfunc shf;
       
   428     Param pm = NULL;
       
   429 
       
   430     pm = (Param) hcalloc(sizeof(struct param));
       
   431     pm->nam = dupstring(name);
       
   432     pm->flags = PM_SCALAR;
       
   433     pm->gsu.s = dis ? &pmdisfunction_gsu :  &pmfunction_gsu;
       
   434 
       
   435     if ((shf = (Shfunc) shfunctab->getnode2(shfunctab, name)) &&
       
   436 	(dis ? (shf->flags & DISABLED) : !(shf->flags & DISABLED))) {
       
   437 	if (shf->flags & PM_UNDEFINED) {
       
   438 	    pm->u.str = dyncat("builtin autoload -X",
       
   439 			       ((shf->flags & PM_UNALIASED) ?
       
   440 				((shf->flags & PM_TAGGED) ? "Ut" : "U") :
       
   441 				((shf->flags & PM_TAGGED) ? "t" : "")));
       
   442 	} else {
       
   443 	    char *t = getpermtext(shf->funcdef, NULL), *n, *h;
       
   444 
       
   445 	    if (shf->funcdef->flags & EF_RUN) {
       
   446 		n = nicedupstring(name);
       
   447 		h = (char *) zhalloc(strlen(t) + strlen(n) + 9);
       
   448 		h[0] = '\t';
       
   449 		strcpy(h + 1, t);
       
   450 		strcat(h, "\n\t");
       
   451 		strcat(h, n);
       
   452 		strcat(h, " \"$@\"");
       
   453 	    } else
       
   454 		h = dyncat("\t", t);
       
   455 	    zsfree(t);
       
   456 	    unmetafy(h, NULL);
       
   457 
       
   458 	    pm->u.str = h;
       
   459 	}
       
   460     } else {
       
   461 	pm->u.str = dupstring("");
       
   462 	pm->flags |= PM_UNSET;
       
   463     }
       
   464     return (HashNode) pm;
       
   465 }
       
   466 
       
   467 /**/
       
   468 static HashNode
       
   469 getpmfunction(HashTable ht, char *name)
       
   470 {
       
   471     return getfunction(ht, name, 0);
       
   472 }
       
   473 
       
   474 /**/
       
   475 static HashNode
       
   476 getpmdisfunction(HashTable ht, char *name)
       
   477 {
       
   478     return getfunction(ht, name, DISABLED);
       
   479 }
       
   480 
       
   481 /**/
       
   482 static void
       
   483 scanfunctions(UNUSED(HashTable ht), ScanFunc func, int flags, int dis)
       
   484 {
       
   485     struct param pm;
       
   486     int i;
       
   487     HashNode hn;
       
   488 
       
   489     memset((void *)&pm, 0, sizeof(struct param));
       
   490     pm.flags = PM_SCALAR;
       
   491     pm.gsu.s = dis ? &pmdisfunction_gsu : &pmfunction_gsu;
       
   492 
       
   493     for (i = 0; i < shfunctab->hsize; i++)
       
   494 	for (hn = shfunctab->nodes[i]; hn; hn = hn->next) {
       
   495 	    if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED)) {
       
   496 		pm.nam = hn->nam;
       
   497 		if (func != scancountparams &&
       
   498 		    ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
   499 		     !(flags & SCANPM_WANTKEYS))) {
       
   500 		    if (((Shfunc) hn)->flags & PM_UNDEFINED) {
       
   501 			Shfunc shf = (Shfunc) hn;
       
   502 			pm.u.str =
       
   503 			    dyncat("builtin autoload -X",
       
   504 				   ((shf->flags & PM_UNALIASED) ?
       
   505 				    ((shf->flags & PM_TAGGED) ? "Ut" : "U") :
       
   506 				    ((shf->flags & PM_TAGGED) ? "t" : "")));
       
   507 		    } else {
       
   508 			char *t = getpermtext(((Shfunc) hn)->funcdef, NULL), *n;
       
   509 
       
   510 			if (((Shfunc) hn)->funcdef->flags & EF_RUN) {
       
   511 			    n = nicedupstring(hn->nam);
       
   512 			    pm.u.str = (char *) zhalloc(strlen(t) + strlen(n) + 9);
       
   513 			    pm.u.str[0] = '\t';
       
   514 			    strcpy(pm.u.str + 1, t);
       
   515 			    strcat(pm.u.str, "\n\t");
       
   516 			    strcat(pm.u.str, n);
       
   517 			    strcat(pm.u.str, " \"$@\"");
       
   518 			} else
       
   519 			    pm.u.str = dyncat("\t", t);
       
   520 			unmetafy(pm.u.str, NULL);
       
   521 			zsfree(t);
       
   522 		    }
       
   523 		}
       
   524 		func((HashNode) &pm, flags);
       
   525 	    }
       
   526 	}
       
   527 }
       
   528 
       
   529 /**/
       
   530 static void
       
   531 scanpmfunctions(HashTable ht, ScanFunc func, int flags)
       
   532 {
       
   533     scanfunctions(ht, func, flags, 0);
       
   534 }
       
   535 
       
   536 /**/
       
   537 static void
       
   538 scanpmdisfunctions(HashTable ht, ScanFunc func, int flags)
       
   539 {
       
   540     scanfunctions(ht, func, flags, DISABLED);
       
   541 }
       
   542 
       
   543 /* Functions for the funcstack special parameter. */
       
   544 
       
   545 /**/
       
   546 static char **
       
   547 funcstackgetfn(UNUSED(Param pm))
       
   548 {
       
   549     Funcstack f;
       
   550     int num;
       
   551     char **ret, **p;
       
   552 
       
   553     for (f = funcstack, num = 0; f; f = f->prev, num++);
       
   554 
       
   555     ret = (char **) zhalloc((num + 1) * sizeof(char *));
       
   556 
       
   557     for (f = funcstack, p = ret; f; f = f->prev, p++)
       
   558 	*p = f->name;
       
   559     *p = NULL;
       
   560 
       
   561     return ret;
       
   562 }
       
   563 
       
   564 /* Functions for the builtins special parameter. */
       
   565 
       
   566 /**/
       
   567 static HashNode
       
   568 getbuiltin(UNUSED(HashTable ht), char *name, int dis)
       
   569 {
       
   570     Param pm = NULL;
       
   571     Builtin bn;
       
   572 
       
   573     pm = (Param) hcalloc(sizeof(struct param));
       
   574     pm->nam = dupstring(name);
       
   575     pm->flags = PM_SCALAR | PM_READONLY;
       
   576     pm->gsu.s = &nullsetscalar_gsu;
       
   577     if ((bn = (Builtin) builtintab->getnode2(builtintab, name)) &&
       
   578 	(dis ? (bn->flags & DISABLED) : !(bn->flags & DISABLED))) {
       
   579 	char *t = ((bn->handlerfunc || (bn->flags & BINF_PREFIX)) ?
       
   580 		   "defined" : "undefined");
       
   581 
       
   582 	pm->u.str = dupstring(t);
       
   583     } else {
       
   584 	pm->u.str = dupstring("");
       
   585 	pm->flags |= PM_UNSET;
       
   586     }
       
   587     return (HashNode) pm;
       
   588 }
       
   589 
       
   590 /**/
       
   591 static HashNode
       
   592 getpmbuiltin(HashTable ht, char *name)
       
   593 {
       
   594     return getbuiltin(ht, name, 0);
       
   595 }
       
   596 
       
   597 /**/
       
   598 static HashNode
       
   599 getpmdisbuiltin(HashTable ht, char *name)
       
   600 {
       
   601     return getbuiltin(ht, name, DISABLED);
       
   602 }
       
   603 
       
   604 /**/
       
   605 static void
       
   606 scanbuiltins(UNUSED(HashTable ht), ScanFunc func, int flags, int dis)
       
   607 {
       
   608     struct param pm;
       
   609     int i;
       
   610     HashNode hn;
       
   611 
       
   612     memset((void *)&pm, 0, sizeof(struct param));
       
   613     pm.flags = PM_SCALAR | PM_READONLY;
       
   614     pm.gsu.s = &nullsetscalar_gsu;
       
   615 
       
   616     for (i = 0; i < builtintab->hsize; i++)
       
   617 	for (hn = builtintab->nodes[i]; hn; hn = hn->next) {
       
   618 	    if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED)) {
       
   619 		pm.nam = hn->nam;
       
   620 		if (func != scancountparams &&
       
   621 		    ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
   622 		     !(flags & SCANPM_WANTKEYS))) {
       
   623 		    char *t = ((((Builtin) hn)->handlerfunc ||
       
   624 				(hn->flags & BINF_PREFIX)) ?
       
   625 			       "defined" : "undefined");
       
   626 
       
   627 		    pm.u.str = dupstring(t);
       
   628 		}
       
   629 		func((HashNode) &pm, flags);
       
   630 	    }
       
   631 	}
       
   632 }
       
   633 
       
   634 /**/
       
   635 static void
       
   636 scanpmbuiltins(HashTable ht, ScanFunc func, int flags)
       
   637 {
       
   638     scanbuiltins(ht, func, flags, 0);
       
   639 }
       
   640 
       
   641 /**/
       
   642 static void
       
   643 scanpmdisbuiltins(HashTable ht, ScanFunc func, int flags)
       
   644 {
       
   645     scanbuiltins(ht, func, flags, DISABLED);
       
   646 }
       
   647 
       
   648 /* Functions for the reswords special parameter. */
       
   649 
       
   650 /**/
       
   651 static char **
       
   652 getreswords(int dis)
       
   653 {
       
   654     int i;
       
   655     HashNode hn;
       
   656     char **ret, **p;
       
   657 
       
   658     p = ret = (char **) zhalloc((reswdtab->ct + 1) * sizeof(char *));
       
   659 
       
   660     for (i = 0; i < reswdtab->hsize; i++)
       
   661 	for (hn = reswdtab->nodes[i]; hn; hn = hn->next)
       
   662 	    if (dis ? (hn->flags & DISABLED) : !(hn->flags & DISABLED))
       
   663 		*p++ = dupstring(hn->nam);
       
   664     *p = NULL;
       
   665 
       
   666     return ret;
       
   667 }
       
   668 
       
   669 /**/
       
   670 static char **
       
   671 reswordsgetfn(UNUSED(Param pm))
       
   672 {
       
   673     return getreswords(0);
       
   674 }
       
   675 
       
   676 /**/
       
   677 static char **
       
   678 disreswordsgetfn(UNUSED(Param pm))
       
   679 {
       
   680     return getreswords(DISABLED);
       
   681 }
       
   682 
       
   683 /* Functions for the options special parameter. */
       
   684 
       
   685 /**/
       
   686 static void
       
   687 setpmoption(Param pm, char *value)
       
   688 {
       
   689     int n;
       
   690 
       
   691     if (!value || (strcmp(value, "on") && strcmp(value, "off")))
       
   692 	zwarn("invalid value: %s", value, 0);
       
   693     else if (!(n = optlookup(pm->nam)))
       
   694 	zwarn("no such option: %s", pm->nam, 0);
       
   695     else if (dosetopt(n, (value && strcmp(value, "off")), 0))
       
   696 	zwarn("can't change option: %s", pm->nam, 0);
       
   697     zsfree(value);
       
   698 }
       
   699 
       
   700 /**/
       
   701 static void
       
   702 unsetpmoption(Param pm, UNUSED(int exp))
       
   703 {
       
   704     int n;
       
   705 
       
   706     if (!(n = optlookup(pm->nam)))
       
   707 	zwarn("no such option: %s", pm->nam, 0);
       
   708     else if (dosetopt(n, 0, 0))
       
   709 	zwarn("can't change option: %s", pm->nam, 0);
       
   710 }
       
   711 
       
   712 /**/
       
   713 static void
       
   714 setpmoptions(UNUSED(Param pm), HashTable ht)
       
   715 {
       
   716     int i;
       
   717     HashNode hn;
       
   718 
       
   719     if (!ht)
       
   720 	return;
       
   721 
       
   722     for (i = 0; i < ht->hsize; i++)
       
   723 	for (hn = ht->nodes[i]; hn; hn = hn->next) {
       
   724 	    struct value v;
       
   725 	    char *val;
       
   726 
       
   727 	    v.isarr = v.inv = v.start = 0;
       
   728 	    v.end = -1;
       
   729 	    v.arr = NULL;
       
   730 	    v.pm = (Param) hn;
       
   731 
       
   732 	    val = getstrvalue(&v);
       
   733 	    if (!val || (strcmp(val, "on") && strcmp(val, "off")))
       
   734 		zwarn("invalid value: %s", val, 0);
       
   735 	    else if (dosetopt(optlookup(hn->nam),
       
   736 			      (val && strcmp(val, "off")), 0))
       
   737 		zwarn("can't change option: %s", hn->nam, 0);
       
   738 	}
       
   739     deleteparamtable(ht);
       
   740 }
       
   741 
       
   742 static const struct gsu_scalar pmoption_gsu =
       
   743 { strgetfn, setpmoption, unsetpmoption };
       
   744 
       
   745 /**/
       
   746 static HashNode
       
   747 getpmoption(UNUSED(HashTable ht), char *name)
       
   748 {
       
   749     Param pm = NULL;
       
   750     int n;
       
   751 
       
   752     pm = (Param) hcalloc(sizeof(struct param));
       
   753     pm->nam = dupstring(name);
       
   754     pm->flags = PM_SCALAR;
       
   755     pm->gsu.s = &pmoption_gsu;
       
   756 
       
   757     if ((n = optlookup(name)))
       
   758     {
       
   759 	int ison;
       
   760 	if (n > 0)
       
   761 	    ison = opts[n];
       
   762 	else
       
   763 	    ison = !opts[-n];
       
   764 	pm->u.str = dupstring(ison ? "on" : "off");
       
   765     }
       
   766     else {
       
   767 	pm->u.str = dupstring("");
       
   768 	pm->flags |= PM_UNSET;
       
   769     }
       
   770     return (HashNode) pm;
       
   771 }
       
   772 
       
   773 /**/
       
   774 static void
       
   775 scanpmoptions(UNUSED(HashTable ht), ScanFunc func, int flags)
       
   776 {
       
   777     struct param pm;
       
   778     int i;
       
   779     HashNode hn;
       
   780 
       
   781     memset((void *)&pm, 0, sizeof(struct param));
       
   782     pm.flags = PM_SCALAR;
       
   783     pm.gsu.s = &pmoption_gsu;
       
   784 
       
   785     for (i = 0; i < optiontab->hsize; i++)
       
   786 	for (hn = optiontab->nodes[i]; hn; hn = hn->next) {
       
   787 	    int optno = ((Optname) hn)->optno, ison;
       
   788 	    pm.nam = hn->nam;
       
   789 	    ison = optno < 0 ? !opts[-optno] : opts[optno];
       
   790 	    pm.u.str = dupstring(ison ? "on" : "off");
       
   791 	    func((HashNode) &pm, flags);
       
   792 	}
       
   793 }
       
   794 
       
   795 /* Functions for the modules special parameter. */
       
   796 
       
   797 static char *modpmname;
       
   798 static int modpmfound;
       
   799 
       
   800 /**/
       
   801 static void
       
   802 modpmbuiltinscan(HashNode hn, UNUSED(int dummy))
       
   803 {
       
   804     if (!(((Builtin) hn)->flags & BINF_ADDED) &&
       
   805 	!strcmp(((Builtin) hn)->optstr, modpmname))
       
   806 	modpmfound = 1;
       
   807 }
       
   808 
       
   809 /**/
       
   810 static void
       
   811 modpmparamscan(HashNode hn, UNUSED(int dummy))
       
   812 {
       
   813     if ((((Param) hn)->flags & PM_AUTOLOAD) &&
       
   814 	!strcmp(((Param) hn)->u.str, modpmname))
       
   815 	modpmfound = 1;
       
   816 }
       
   817 
       
   818 /**/
       
   819 static int
       
   820 findmodnode(LinkList l, char *nam)
       
   821 {
       
   822     LinkNode node;
       
   823 
       
   824     for (node = firstnode(l); node; incnode(node))
       
   825 	if (!strcmp(nam, (char *) getdata(node)))
       
   826 	    return 1;
       
   827 
       
   828     return 0;
       
   829 }
       
   830 
       
   831 /**/
       
   832 static HashNode
       
   833 getpmmodule(UNUSED(HashTable ht), char *name)
       
   834 {
       
   835     Param pm = NULL;
       
   836     char *type = NULL;
       
   837     LinkNode node;
       
   838 
       
   839     pm = (Param) hcalloc(sizeof(struct param));
       
   840     pm->nam = dupstring(name);
       
   841     pm->flags = PM_SCALAR | PM_READONLY;
       
   842     pm->gsu.s = &nullsetscalar_gsu;
       
   843 
       
   844     if (!type) {
       
   845 	Module m;
       
   846 
       
   847 	for (node = firstnode(modules); node; incnode(node)) {
       
   848 	    m = (Module) getdata(node);
       
   849 	    if (m->u.handle && !(m->flags & MOD_UNLOAD) &&
       
   850 		!strcmp(name, m->nam)) {
       
   851 		type = ((m->flags & MOD_ALIAS) ?
       
   852 			dyncat("alias:", m->u.alias) : "loaded");
       
   853 		break;
       
   854 	    }
       
   855 	}
       
   856     }
       
   857     modpmname = name;
       
   858     modpmfound = 0;
       
   859     if (!type) {
       
   860 	scanhashtable(builtintab, 0, 0, 0, modpmbuiltinscan, 0);
       
   861 	if (!modpmfound) {
       
   862 	    Conddef p;
       
   863 
       
   864 	    for (p = condtab; p; p = p->next)
       
   865 		if (p->module && !strcmp(name, p->module)) {
       
   866 		    modpmfound = 1;
       
   867 		    break;
       
   868 		}
       
   869 	    if (!modpmfound)
       
   870 		scanhashtable(realparamtab, 0, 0, 0, modpmparamscan, 0);
       
   871 	}
       
   872 	if (modpmfound)
       
   873 	    type = "autoloaded";
       
   874     }
       
   875     if (type)
       
   876 	pm->u.str = dupstring(type);
       
   877     else {
       
   878 	pm->u.str = dupstring("");
       
   879 	pm->flags |= PM_UNSET;
       
   880     }
       
   881     return (HashNode) pm;
       
   882 }
       
   883 
       
   884 /**/
       
   885 static void
       
   886 scanpmmodules(UNUSED(HashTable ht), ScanFunc func, int flags)
       
   887 {
       
   888     struct param pm;
       
   889     int i;
       
   890     HashNode hn;
       
   891     LinkList done = newlinklist();
       
   892     LinkNode node;
       
   893     Module m;
       
   894     Conddef p;
       
   895     char *loaded = dupstring("loaded");
       
   896 
       
   897     memset((void *)&pm, 0, sizeof(struct param));
       
   898     pm.flags = PM_SCALAR | PM_READONLY;
       
   899     pm.gsu.s = &nullsetscalar_gsu;
       
   900 
       
   901     for (node = firstnode(modules); node; incnode(node)) {
       
   902 	m = (Module) getdata(node);
       
   903 	if (m->u.handle && !(m->flags & MOD_UNLOAD)) {
       
   904 	    pm.nam = m->nam;
       
   905 	    pm.u.str = ((m->flags & MOD_ALIAS) ?
       
   906 			dyncat("alias:", m->u.alias) : loaded);
       
   907 	    addlinknode(done, pm.nam);
       
   908 	    func((HashNode) &pm, flags);
       
   909 	}
       
   910     }
       
   911     pm.u.str = dupstring("autoloaded");
       
   912     for (i = 0; i < builtintab->hsize; i++)
       
   913 	for (hn = builtintab->nodes[i]; hn; hn = hn->next) {
       
   914 	    if (!(((Builtin) hn)->flags & BINF_ADDED) &&
       
   915 		!findmodnode(done, ((Builtin) hn)->optstr)) {
       
   916 		pm.nam = ((Builtin) hn)->optstr;
       
   917 		addlinknode(done, pm.nam);
       
   918 		func((HashNode) &pm, flags);
       
   919 	    }
       
   920 	}
       
   921     for (p = condtab; p; p = p->next)
       
   922 	if (p->module && !findmodnode(done, p->module)) {
       
   923 	    pm.nam = p->module;
       
   924 	    addlinknode(done, pm.nam);
       
   925 	    func((HashNode) &pm, flags);
       
   926 	}
       
   927     for (i = 0; i < realparamtab->hsize; i++)
       
   928 	for (hn = realparamtab->nodes[i]; hn; hn = hn->next) {
       
   929 	    if ((((Param) hn)->flags & PM_AUTOLOAD) &&
       
   930 		!findmodnode(done, ((Param) hn)->u.str)) {
       
   931 		pm.nam = ((Param) hn)->u.str;
       
   932 		addlinknode(done, pm.nam);
       
   933 		func((HashNode) &pm, flags);
       
   934 	    }
       
   935 	}
       
   936 }
       
   937 
       
   938 /* Functions for the dirstack special parameter. */
       
   939 
       
   940 /**/
       
   941 static void
       
   942 dirssetfn(UNUSED(Param pm), char **x)
       
   943 {
       
   944     char **ox = x;
       
   945 
       
   946     if (!incleanup) {
       
   947 	freelinklist(dirstack, freestr);
       
   948 	dirstack = znewlinklist();
       
   949 	while (x && *x)
       
   950 	    zaddlinknode(dirstack, ztrdup(*x++));
       
   951     }
       
   952     if (ox)
       
   953 	freearray(ox);
       
   954 }
       
   955 
       
   956 /**/
       
   957 static char **
       
   958 dirsgetfn(UNUSED(Param pm))
       
   959 {
       
   960     int l = countlinknodes(dirstack);
       
   961     char **ret = (char **) zhalloc((l + 1) * sizeof(char *)), **p;
       
   962     LinkNode n;
       
   963 
       
   964     for (n = firstnode(dirstack), p = ret; n; incnode(n), p++)
       
   965 	*p = dupstring((char *) getdata(n));
       
   966     *p = NULL;
       
   967 
       
   968     return ret;
       
   969 }
       
   970 
       
   971 /* Functions for the history special parameter. */
       
   972 
       
   973 /**/
       
   974 static HashNode
       
   975 getpmhistory(UNUSED(HashTable ht), char *name)
       
   976 {
       
   977     Param pm = NULL;
       
   978     Histent he;
       
   979     char *p;
       
   980     int ok = 1;
       
   981 
       
   982     pm = (Param) hcalloc(sizeof(struct param));
       
   983     pm->nam = dupstring(name);
       
   984     pm->flags = PM_SCALAR | PM_READONLY;
       
   985     pm->gsu.s = &nullsetscalar_gsu;
       
   986 
       
   987     if (*name != '0' || name[1]) {
       
   988 	if (*name == '0')
       
   989 	    ok = 0;
       
   990 	else {
       
   991 	    for (p = name; *p && idigit(*p); p++);
       
   992 	    if (*p)
       
   993 		ok = 0;
       
   994 	}
       
   995     }
       
   996     if (ok && (he = quietgethist(atoi(name))))
       
   997 	pm->u.str = dupstring(he->text);
       
   998     else {
       
   999 	pm->u.str = dupstring("");
       
  1000 	pm->flags |= PM_UNSET;
       
  1001     }
       
  1002     return (HashNode) pm;
       
  1003 }
       
  1004 
       
  1005 /**/
       
  1006 static void
       
  1007 scanpmhistory(UNUSED(HashTable ht), ScanFunc func, int flags)
       
  1008 {
       
  1009     struct param pm;
       
  1010     int i = addhistnum(curhist, -1, HIST_FOREIGN);
       
  1011     Histent he = gethistent(i, GETHIST_UPWARD);
       
  1012     char buf[40];
       
  1013 
       
  1014     memset((void *)&pm, 0, sizeof(struct param));
       
  1015     pm.flags = PM_SCALAR | PM_READONLY;
       
  1016     pm.gsu.s = &nullsetscalar_gsu;
       
  1017 
       
  1018     while (he) {
       
  1019 	if (func != scancountparams) {
       
  1020 	    convbase(buf, he->histnum, 10);
       
  1021 	    pm.nam = dupstring(buf);
       
  1022 	    if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
  1023 		!(flags & SCANPM_WANTKEYS))
       
  1024 		pm.u.str = dupstring(he->text);
       
  1025 	}
       
  1026 	func((HashNode) &pm, flags);
       
  1027 
       
  1028 	he = up_histent(he);
       
  1029     }
       
  1030 }
       
  1031 
       
  1032 /* Function for the historywords special parameter. */
       
  1033 
       
  1034 /**/
       
  1035 static char **
       
  1036 histwgetfn(UNUSED(Param pm))
       
  1037 {
       
  1038     char **ret, **p, *h, *e, sav;
       
  1039     LinkList l = newlinklist(), ll;
       
  1040     LinkNode n;
       
  1041     int i = addhistnum(curhist, -1, HIST_FOREIGN), iw;
       
  1042     Histent he = gethistent(i, GETHIST_UPWARD);
       
  1043 
       
  1044     if ((ll = bufferwords(NULL, NULL, NULL)))
       
  1045         for (n = firstnode(ll); n; incnode(n))
       
  1046             pushnode(l, getdata(n));
       
  1047 
       
  1048     while (he) {
       
  1049 	for (iw = he->nwords - 1; iw >= 0; iw--) {
       
  1050 	    h = he->text + he->words[iw * 2];
       
  1051 	    e = he->text + he->words[iw * 2 + 1];
       
  1052 	    sav = *e;
       
  1053 	    *e = '\0';
       
  1054 	    addlinknode(l, dupstring(h));
       
  1055 	    *e = sav;
       
  1056 	}
       
  1057 	he = up_histent(he);
       
  1058     }
       
  1059     ret = (char **) zhalloc((countlinknodes(l) + 1) * sizeof(char *));
       
  1060 
       
  1061     for (p = ret, n = firstnode(l); n; incnode(n), p++)
       
  1062 	*p = (char *) getdata(n);
       
  1063     *p = NULL;
       
  1064 
       
  1065     return ret;
       
  1066 }
       
  1067 
       
  1068 /* Functions for the jobtexts special parameter. */
       
  1069 
       
  1070 /**/
       
  1071 static char *
       
  1072 pmjobtext(int job)
       
  1073 {
       
  1074     Process pn;
       
  1075     int len = 1;
       
  1076     char *ret;
       
  1077 
       
  1078     for (pn = jobtab[job].procs; pn; pn = pn->next)
       
  1079 	len += strlen(pn->text) + 3;
       
  1080 
       
  1081     ret = (char *) zhalloc(len);
       
  1082     ret[0] = '\0';
       
  1083 
       
  1084     for (pn = jobtab[job].procs; pn; pn = pn->next) {
       
  1085 	strcat(ret, pn->text);
       
  1086 	if (pn->next)
       
  1087 	    strcat(ret, " | ");
       
  1088     }
       
  1089     return ret;
       
  1090 }
       
  1091 
       
  1092 /**/
       
  1093 static HashNode
       
  1094 getpmjobtext(UNUSED(HashTable ht), char *name)
       
  1095 {
       
  1096     Param pm = NULL;
       
  1097     int job;
       
  1098 
       
  1099     pm = (Param) hcalloc(sizeof(struct param));
       
  1100     pm->nam = dupstring(name);
       
  1101     pm->flags = PM_SCALAR | PM_READONLY;
       
  1102     pm->gsu.s = &nullsetscalar_gsu;
       
  1103 
       
  1104     if ((job = atoi(name)) >= 1 && job <= maxjob &&
       
  1105 	jobtab[job].stat && jobtab[job].procs &&
       
  1106 	!(jobtab[job].stat & STAT_NOPRINT))
       
  1107 	pm->u.str = pmjobtext(job);
       
  1108     else {
       
  1109 	pm->u.str = dupstring("");
       
  1110 	pm->flags |= PM_UNSET;
       
  1111     }
       
  1112     return (HashNode) pm;
       
  1113 }
       
  1114 
       
  1115 /**/
       
  1116 static void
       
  1117 scanpmjobtexts(UNUSED(HashTable ht), ScanFunc func, int flags)
       
  1118 {
       
  1119     struct param pm;
       
  1120     int job;
       
  1121     char buf[40];
       
  1122 
       
  1123     memset((void *)&pm, 0, sizeof(struct param));
       
  1124     pm.flags = PM_SCALAR | PM_READONLY;
       
  1125     pm.gsu.s = &nullsetscalar_gsu;
       
  1126 
       
  1127     for (job = 1; job <= maxjob; job++) {
       
  1128 	if (jobtab[job].stat && jobtab[job].procs &&
       
  1129 	    !(jobtab[job].stat & STAT_NOPRINT)) {
       
  1130 	    if (func != scancountparams) {
       
  1131 		sprintf(buf, "%d", job);
       
  1132 		pm.nam = dupstring(buf);
       
  1133 		if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
  1134 		    !(flags & SCANPM_WANTKEYS))
       
  1135 		    pm.u.str = pmjobtext(job);
       
  1136 	    }
       
  1137 	    func((HashNode) &pm, flags);
       
  1138 	}
       
  1139     }
       
  1140 }
       
  1141 
       
  1142 /* Functions for the jobstates special parameter. */
       
  1143 
       
  1144 /**/
       
  1145 static char *
       
  1146 pmjobstate(int job)
       
  1147 {
       
  1148     Process pn;
       
  1149     char buf[256], buf2[128], *ret, *state, *cp;
       
  1150 
       
  1151     if (job == curjob)
       
  1152 	cp = ":+";
       
  1153     else if (job == prevjob)
       
  1154 	cp = ":-";
       
  1155     else
       
  1156 	cp = ":";
       
  1157 
       
  1158     if (jobtab[job].stat & STAT_DONE)
       
  1159 	ret = dyncat("done", cp);
       
  1160     else if (jobtab[job].stat & STAT_STOPPED)
       
  1161 	ret = dyncat("suspended", cp);
       
  1162     else
       
  1163 	ret = dyncat("running", cp);
       
  1164 
       
  1165     for (pn = jobtab[job].procs; pn; pn = pn->next) {
       
  1166 
       
  1167 	if (pn->status == SP_RUNNING)
       
  1168 	    state = "running";
       
  1169 	else if (WIFEXITED(pn->status)) {
       
  1170 	    if (WEXITSTATUS(pn->status))
       
  1171 		sprintf((state = buf2), "exit %d", (pn->status));
       
  1172 	    else
       
  1173 		state = "done";
       
  1174 	} else if (WIFSTOPPED(pn->status))
       
  1175 	    state = sigmsg(WSTOPSIG(pn->status));
       
  1176 	else if (WCOREDUMP(pn->status))
       
  1177 	    sprintf((state = buf2), "%s (core dumped)",
       
  1178 		    sigmsg(WTERMSIG(pn->status)));
       
  1179 	else
       
  1180 	    state = sigmsg(WTERMSIG(pn->status));
       
  1181 
       
  1182 	sprintf(buf, ":%d=%s", (int)pn->pid, state);
       
  1183 
       
  1184 	ret = dyncat(ret, buf);
       
  1185     }
       
  1186     return ret;
       
  1187 }
       
  1188 
       
  1189 /**/
       
  1190 static HashNode
       
  1191 getpmjobstate(UNUSED(HashTable ht), char *name)
       
  1192 {
       
  1193     Param pm = NULL;
       
  1194     int job;
       
  1195 
       
  1196     pm = (Param) hcalloc(sizeof(struct param));
       
  1197     pm->nam = dupstring(name);
       
  1198     pm->flags = PM_SCALAR | PM_READONLY;
       
  1199     pm->gsu.s = &nullsetscalar_gsu;
       
  1200 
       
  1201     if ((job = atoi(name)) >= 1 && job <= maxjob &&
       
  1202 	jobtab[job].stat && jobtab[job].procs &&
       
  1203 	!(jobtab[job].stat & STAT_NOPRINT))
       
  1204 	pm->u.str = pmjobstate(job);
       
  1205     else {
       
  1206 	pm->u.str = dupstring("");
       
  1207 	pm->flags |= PM_UNSET;
       
  1208     }
       
  1209     return (HashNode) pm;
       
  1210 }
       
  1211 
       
  1212 /**/
       
  1213 static void
       
  1214 scanpmjobstates(UNUSED(HashTable ht), ScanFunc func, int flags)
       
  1215 {
       
  1216     struct param pm;
       
  1217     int job;
       
  1218     char buf[40];
       
  1219 
       
  1220     memset((void *)&pm, 0, sizeof(struct param));
       
  1221     pm.flags = PM_SCALAR | PM_READONLY;
       
  1222     pm.gsu.s = &nullsetscalar_gsu;
       
  1223 
       
  1224     for (job = 1; job <= maxjob; job++) {
       
  1225 	if (jobtab[job].stat && jobtab[job].procs &&
       
  1226 	    !(jobtab[job].stat & STAT_NOPRINT)) {
       
  1227 	    if (func != scancountparams) {
       
  1228 		sprintf(buf, "%d", job);
       
  1229 		pm.nam = dupstring(buf);
       
  1230 		if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
  1231 		    !(flags & SCANPM_WANTKEYS))
       
  1232 		    pm.u.str = pmjobstate(job);
       
  1233 	    }
       
  1234 	    func((HashNode) &pm, flags);
       
  1235 	}
       
  1236     }
       
  1237 }
       
  1238 
       
  1239 /* Functions for the jobdirs special parameter. */
       
  1240 
       
  1241 /**/
       
  1242 static char *
       
  1243 pmjobdir(int job)
       
  1244 {
       
  1245     char *ret;
       
  1246 
       
  1247     ret = dupstring(jobtab[job].pwd ? jobtab[job].pwd : pwd);
       
  1248     return ret;
       
  1249 }
       
  1250 
       
  1251 /**/
       
  1252 static HashNode
       
  1253 getpmjobdir(UNUSED(HashTable ht), char *name)
       
  1254 {
       
  1255     Param pm = NULL;
       
  1256     int job;
       
  1257 
       
  1258     pm = (Param) hcalloc(sizeof(struct param));
       
  1259     pm->nam = dupstring(name);
       
  1260     pm->flags = PM_SCALAR | PM_READONLY;
       
  1261     pm->gsu.s = &nullsetscalar_gsu;
       
  1262 
       
  1263     if ((job = atoi(name)) >= 1 && job <= maxjob &&
       
  1264 	jobtab[job].stat && jobtab[job].procs &&
       
  1265 	!(jobtab[job].stat & STAT_NOPRINT))
       
  1266 	pm->u.str = pmjobdir(job);
       
  1267     else {
       
  1268 	pm->u.str = dupstring("");
       
  1269 	pm->flags |= PM_UNSET;
       
  1270     }
       
  1271     return (HashNode) pm;
       
  1272 }
       
  1273 
       
  1274 /**/
       
  1275 static void
       
  1276 scanpmjobdirs(UNUSED(HashTable ht), ScanFunc func, int flags)
       
  1277 {
       
  1278     struct param pm;
       
  1279     int job;
       
  1280     char buf[40];
       
  1281 
       
  1282     memset((void *)&pm, 0, sizeof(struct param));
       
  1283     pm.flags = PM_SCALAR | PM_READONLY;
       
  1284     pm.gsu.s = &nullsetscalar_gsu;
       
  1285 
       
  1286     for (job = 1; job <= maxjob; job++) {
       
  1287        if (jobtab[job].stat && jobtab[job].procs &&
       
  1288            !(jobtab[job].stat & STAT_NOPRINT)) {
       
  1289            if (func != scancountparams) {
       
  1290 	       sprintf(buf, "%d", job);
       
  1291 	       pm.nam = dupstring(buf);
       
  1292                if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
  1293 		   !(flags & SCANPM_WANTKEYS))
       
  1294 		   pm.u.str = pmjobdir(job);
       
  1295 	   }
       
  1296            func((HashNode) &pm, flags);
       
  1297        }
       
  1298     }
       
  1299 }
       
  1300 
       
  1301 /* Functions for the nameddirs special parameter. */
       
  1302 
       
  1303 /**/
       
  1304 static void
       
  1305 setpmnameddir(Param pm, char *value)
       
  1306 {
       
  1307     if (!value)
       
  1308 	zwarn("invalid value: ''", NULL, 0);
       
  1309     else {
       
  1310 	Nameddir nd = (Nameddir) zshcalloc(sizeof(*nd));
       
  1311 
       
  1312 	nd->flags = 0;
       
  1313 	nd->dir = value;
       
  1314 	nameddirtab->addnode(nameddirtab, ztrdup(pm->nam), nd);
       
  1315     }
       
  1316 }
       
  1317 
       
  1318 /**/
       
  1319 static void
       
  1320 unsetpmnameddir(Param pm, UNUSED(int exp))
       
  1321 {
       
  1322     HashNode hd = nameddirtab->removenode(nameddirtab, pm->nam);
       
  1323 
       
  1324     if (hd)
       
  1325 	nameddirtab->freenode(hd);
       
  1326 }
       
  1327 
       
  1328 /**/
       
  1329 static void
       
  1330 setpmnameddirs(UNUSED(Param pm), HashTable ht)
       
  1331 {
       
  1332     int i;
       
  1333     HashNode hn, next, hd;
       
  1334 
       
  1335     if (!ht)
       
  1336 	return;
       
  1337 
       
  1338     for (i = 0; i < nameddirtab->hsize; i++)
       
  1339 	for (hn = nameddirtab->nodes[i]; hn; hn = next) {
       
  1340 	    next = hn->next;
       
  1341 	    if (!(((Nameddir) hn)->flags & ND_USERNAME) &&
       
  1342 		(hd = nameddirtab->removenode(nameddirtab, hn->nam)))
       
  1343 		nameddirtab->freenode(hd);
       
  1344 	}
       
  1345 
       
  1346     for (i = 0; i < ht->hsize; i++)
       
  1347 	for (hn = ht->nodes[i]; hn; hn = hn->next) {
       
  1348 	    struct value v;
       
  1349 	    char *val;
       
  1350 
       
  1351 	    v.isarr = v.inv = v.start = 0;
       
  1352 	    v.end = -1;
       
  1353 	    v.arr = NULL;
       
  1354 	    v.pm = (Param) hn;
       
  1355 
       
  1356 	    if (!(val = getstrvalue(&v)))
       
  1357 		zwarn("invalid value: ''", NULL, 0);
       
  1358 	    else {
       
  1359 		Nameddir nd = (Nameddir) zshcalloc(sizeof(*nd));
       
  1360 
       
  1361 		nd->flags = 0;
       
  1362 		nd->dir = ztrdup(val);
       
  1363 		nameddirtab->addnode(nameddirtab, ztrdup(hn->nam), nd);
       
  1364 	    }
       
  1365 	}
       
  1366 
       
  1367     /* The INTERACTIVE stuff ensures that the dirs are not immediatly removed
       
  1368      * when the sub-pms are deleted. */
       
  1369 
       
  1370     i = opts[INTERACTIVE];
       
  1371     opts[INTERACTIVE] = 0;
       
  1372     deleteparamtable(ht);
       
  1373     opts[INTERACTIVE] = i;
       
  1374 }
       
  1375 
       
  1376 static const struct gsu_scalar pmnamedir_gsu =
       
  1377 { strgetfn, setpmnameddir, unsetpmnameddir };
       
  1378 
       
  1379 /**/
       
  1380 static HashNode
       
  1381 getpmnameddir(UNUSED(HashTable ht), char *name)
       
  1382 {
       
  1383     Param pm = NULL;
       
  1384     Nameddir nd;
       
  1385 
       
  1386     pm = (Param) hcalloc(sizeof(struct param));
       
  1387     pm->nam = dupstring(name);
       
  1388     pm->flags = PM_SCALAR;
       
  1389     pm->gsu.s = &pmnamedir_gsu;
       
  1390     if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
       
  1391 	!(nd->flags & ND_USERNAME))
       
  1392 	pm->u.str = dupstring(nd->dir);
       
  1393     else {
       
  1394 	pm->u.str = dupstring("");
       
  1395 	pm->flags |= PM_UNSET;
       
  1396     }
       
  1397     return (HashNode) pm;
       
  1398 }
       
  1399 
       
  1400 /**/
       
  1401 static void
       
  1402 scanpmnameddirs(UNUSED(HashTable ht), ScanFunc func, int flags)
       
  1403 {
       
  1404     struct param pm;
       
  1405     int i;
       
  1406     HashNode hn;
       
  1407     Nameddir nd;
       
  1408 
       
  1409     memset((void *)&pm, 0, sizeof(struct param));
       
  1410     pm.flags = PM_SCALAR;
       
  1411     pm.gsu.s = &pmnamedir_gsu;
       
  1412 
       
  1413     for (i = 0; i < nameddirtab->hsize; i++)
       
  1414 	for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) {
       
  1415 	    if (!((nd = (Nameddir) hn)->flags & ND_USERNAME)) {
       
  1416 		pm.nam = hn->nam;
       
  1417 		if (func != scancountparams &&
       
  1418 		    ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
  1419 		     !(flags & SCANPM_WANTKEYS)))
       
  1420 		    pm.u.str = dupstring(nd->dir);
       
  1421 		func((HashNode) &pm, flags);
       
  1422 	    }
       
  1423 	}
       
  1424 }
       
  1425 
       
  1426 /* Functions for the userdirs special parameter. */
       
  1427 
       
  1428 /**/
       
  1429 static HashNode
       
  1430 getpmuserdir(UNUSED(HashTable ht), char *name)
       
  1431 {
       
  1432     Param pm = NULL;
       
  1433     Nameddir nd;
       
  1434 
       
  1435     nameddirtab->filltable(nameddirtab);
       
  1436 
       
  1437     pm = (Param) hcalloc(sizeof(struct param));
       
  1438     pm->nam = dupstring(name);
       
  1439     pm->flags = PM_SCALAR | PM_READONLY;
       
  1440     pm->gsu.s = &nullsetscalar_gsu;
       
  1441     if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
       
  1442 	(nd->flags & ND_USERNAME))
       
  1443 	pm->u.str = dupstring(nd->dir);
       
  1444     else {
       
  1445 	pm->u.str = dupstring("");
       
  1446 	pm->flags |= PM_UNSET;
       
  1447     }
       
  1448     return (HashNode) pm;
       
  1449 }
       
  1450 
       
  1451 /**/
       
  1452 static void
       
  1453 scanpmuserdirs(UNUSED(HashTable ht), ScanFunc func, int flags)
       
  1454 {
       
  1455     struct param pm;
       
  1456     int i;
       
  1457     HashNode hn;
       
  1458     Nameddir nd;
       
  1459 
       
  1460     nameddirtab->filltable(nameddirtab);
       
  1461 
       
  1462     memset((void *)&pm, 0, sizeof(struct param));
       
  1463     pm.flags = PM_SCALAR | PM_READONLY;
       
  1464     pm.gsu.s = &nullsetscalar_gsu;
       
  1465 
       
  1466     for (i = 0; i < nameddirtab->hsize; i++)
       
  1467 	for (hn = nameddirtab->nodes[i]; hn; hn = hn->next) {
       
  1468 	    if ((nd = (Nameddir) hn)->flags & ND_USERNAME) {
       
  1469 		pm.nam = hn->nam;
       
  1470 		if (func != scancountparams &&
       
  1471 		    ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
  1472 		     !(flags & SCANPM_WANTKEYS)))
       
  1473 		    pm.u.str = dupstring(nd->dir);
       
  1474 		func((HashNode) &pm, flags);
       
  1475 	    }
       
  1476 	}
       
  1477 }
       
  1478 
       
  1479 /* Functions for the raliases, galiases and saliases special parameters. */
       
  1480 
       
  1481 /**/
       
  1482 static void
       
  1483 setalias(HashTable ht, Param pm, char *value, int flags)
       
  1484 {
       
  1485     ht->addnode(ht, ztrdup(pm->nam),
       
  1486 		createaliasnode(value, flags));
       
  1487 }
       
  1488 
       
  1489 /**/
       
  1490 static void
       
  1491 setpmralias(Param pm, char *value)
       
  1492 {
       
  1493     setalias(aliastab, pm, value, 0);
       
  1494 }
       
  1495 
       
  1496 /**/
       
  1497 static void
       
  1498 setpmdisralias(Param pm, char *value)
       
  1499 {
       
  1500     setalias(aliastab, pm, value, DISABLED);
       
  1501 }
       
  1502 
       
  1503 /**/
       
  1504 static void
       
  1505 setpmgalias(Param pm, char *value)
       
  1506 {
       
  1507     setalias(aliastab, pm, value, ALIAS_GLOBAL);
       
  1508 }
       
  1509 
       
  1510 /**/
       
  1511 static void
       
  1512 setpmdisgalias(Param pm, char *value)
       
  1513 {
       
  1514     setalias(aliastab, pm, value, ALIAS_GLOBAL|DISABLED);
       
  1515 }
       
  1516 
       
  1517 /**/
       
  1518 static void
       
  1519 setpmsalias(Param pm, char *value)
       
  1520 {
       
  1521     setalias(sufaliastab, pm, value, ALIAS_SUFFIX);
       
  1522 }
       
  1523 
       
  1524 /**/
       
  1525 static void
       
  1526 setpmdissalias(Param pm, char *value)
       
  1527 {
       
  1528     setalias(sufaliastab, pm, value, ALIAS_SUFFIX|DISABLED);
       
  1529 }
       
  1530 
       
  1531 /**/
       
  1532 static void
       
  1533 unsetpmalias(Param pm, UNUSED(int exp))
       
  1534 {
       
  1535     HashNode hd = aliastab->removenode(aliastab, pm->nam);
       
  1536 
       
  1537     if (hd)
       
  1538 	aliastab->freenode(hd);
       
  1539 }
       
  1540 
       
  1541 /**/
       
  1542 static void
       
  1543 unsetpmsalias(Param pm, UNUSED(int exp))
       
  1544 {
       
  1545     HashNode hd = sufaliastab->removenode(sufaliastab, pm->nam);
       
  1546 
       
  1547     if (hd)
       
  1548 	sufaliastab->freenode(hd);
       
  1549 }
       
  1550 
       
  1551 /**/
       
  1552 static void
       
  1553 setaliases(HashTable alht, UNUSED(Param pm), HashTable ht, int flags)
       
  1554 {
       
  1555     int i;
       
  1556     HashNode hn, next, hd;
       
  1557 
       
  1558     if (!ht)
       
  1559 	return;
       
  1560 
       
  1561     for (i = 0; i < alht->hsize; i++)
       
  1562 	for (hn = alht->nodes[i]; hn; hn = next) {
       
  1563 	    next = hn->next;
       
  1564 	    /*
       
  1565 	     * The following respects the DISABLED flag, e.g.
       
  1566 	     * we get a different behaviour for raliases and dis_raliases.
       
  1567 	     * The predecessor to this code didn't do that; presumably
       
  1568 	     * that was a bug.
       
  1569 	     */
       
  1570 	    if (flags == ((Alias)hn)->flags &&
       
  1571 		(hd = alht->removenode(alht, hn->nam)))
       
  1572 		alht->freenode(hd);
       
  1573 	}
       
  1574 
       
  1575     for (i = 0; i < ht->hsize; i++)
       
  1576 	for (hn = ht->nodes[i]; hn; hn = hn->next) {
       
  1577 	    struct value v;
       
  1578 	    char *val;
       
  1579 
       
  1580 	    v.isarr = v.inv = v.start = 0;
       
  1581 	    v.end = -1;
       
  1582 	    v.arr = NULL;
       
  1583 	    v.pm = (Param) hn;
       
  1584 
       
  1585 	    if ((val = getstrvalue(&v)))
       
  1586 		alht->addnode(alht, ztrdup(hn->nam),
       
  1587 			      createaliasnode(ztrdup(val), flags));
       
  1588 	}
       
  1589     deleteparamtable(ht);
       
  1590 }
       
  1591 
       
  1592 /**/
       
  1593 static void
       
  1594 setpmraliases(Param pm, HashTable ht)
       
  1595 {
       
  1596     setaliases(aliastab, pm, ht, 0);
       
  1597 }
       
  1598 
       
  1599 /**/
       
  1600 static void
       
  1601 setpmdisraliases(Param pm, HashTable ht)
       
  1602 {
       
  1603     setaliases(aliastab, pm, ht, DISABLED);
       
  1604 }
       
  1605 
       
  1606 /**/
       
  1607 static void
       
  1608 setpmgaliases(Param pm, HashTable ht)
       
  1609 {
       
  1610     setaliases(aliastab, pm, ht, ALIAS_GLOBAL);
       
  1611 }
       
  1612 
       
  1613 /**/
       
  1614 static void
       
  1615 setpmdisgaliases(Param pm, HashTable ht)
       
  1616 {
       
  1617     setaliases(aliastab, pm, ht, ALIAS_GLOBAL|DISABLED);
       
  1618 }
       
  1619 
       
  1620 /**/
       
  1621 static void
       
  1622 setpmsaliases(Param pm, HashTable ht)
       
  1623 {
       
  1624     setaliases(sufaliastab, pm, ht, ALIAS_SUFFIX);
       
  1625 }
       
  1626 
       
  1627 /**/
       
  1628 static void
       
  1629 setpmdissaliases(Param pm, HashTable ht)
       
  1630 {
       
  1631     setaliases(sufaliastab, pm, ht, ALIAS_SUFFIX|DISABLED);
       
  1632 }
       
  1633 
       
  1634 static const struct gsu_scalar pmralias_gsu =
       
  1635 { strgetfn, setpmralias, unsetpmalias };
       
  1636 static const struct gsu_scalar pmgalias_gsu =
       
  1637 { strgetfn, setpmgalias, unsetpmalias };
       
  1638 static const struct gsu_scalar pmsalias_gsu =
       
  1639 { strgetfn, setpmsalias, unsetpmsalias };
       
  1640 static const struct gsu_scalar pmdisralias_gsu =
       
  1641 { strgetfn, setpmdisralias, unsetpmalias };
       
  1642 static const struct gsu_scalar pmdisgalias_gsu =
       
  1643 { strgetfn, setpmdisgalias, unsetpmalias };
       
  1644 static const struct gsu_scalar pmdissalias_gsu =
       
  1645 { strgetfn, setpmdissalias, unsetpmsalias };
       
  1646 
       
  1647 /**/
       
  1648 static void
       
  1649 assignaliasdefs(Param pm, int flags)
       
  1650 {
       
  1651     pm->flags = PM_SCALAR;
       
  1652 
       
  1653     /* we really need to squirrel the flags away somewhere... */
       
  1654     switch (flags) {
       
  1655     case 0:
       
  1656 	pm->gsu.s = &pmralias_gsu;
       
  1657 	break;
       
  1658 
       
  1659     case ALIAS_GLOBAL:
       
  1660 	pm->gsu.s = &pmgalias_gsu;
       
  1661 	break;
       
  1662 
       
  1663     case ALIAS_SUFFIX:
       
  1664 	pm->gsu.s = &pmsalias_gsu;
       
  1665 	break;
       
  1666 
       
  1667     case DISABLED:
       
  1668 	pm->gsu.s = &pmdisralias_gsu;
       
  1669 	break;
       
  1670 
       
  1671     case ALIAS_GLOBAL|DISABLED:
       
  1672 	pm->gsu.s = &pmdisgalias_gsu;
       
  1673 	break;
       
  1674 
       
  1675     case ALIAS_SUFFIX|DISABLED:
       
  1676 	pm->gsu.s = &pmdissalias_gsu;
       
  1677 	break;
       
  1678     }
       
  1679 }
       
  1680 
       
  1681 /**/
       
  1682 static HashNode
       
  1683 getalias(HashTable alht, UNUSED(HashTable ht), char *name, int flags)
       
  1684 {
       
  1685     Param pm = NULL;
       
  1686     Alias al;
       
  1687 
       
  1688     pm = (Param) hcalloc(sizeof(struct param));
       
  1689     pm->nam = dupstring(name);
       
  1690 
       
  1691     assignaliasdefs(pm, flags);
       
  1692 
       
  1693     if ((al = (Alias) alht->getnode2(alht, name)) &&
       
  1694 	flags == al->flags)
       
  1695 	pm->u.str = dupstring(al->text);
       
  1696     else {
       
  1697 	pm->u.str = dupstring("");
       
  1698 	pm->flags |= PM_UNSET;
       
  1699     }
       
  1700     return (HashNode) pm;
       
  1701 }
       
  1702 
       
  1703 /**/
       
  1704 static HashNode
       
  1705 getpmralias(HashTable ht, char *name)
       
  1706 {
       
  1707     return getalias(aliastab, ht, name, 0);
       
  1708 }
       
  1709 
       
  1710 /**/
       
  1711 static HashNode
       
  1712 getpmdisralias(HashTable ht, char *name)
       
  1713 {
       
  1714     return getalias(aliastab, ht, name, DISABLED);
       
  1715 }
       
  1716 
       
  1717 /**/
       
  1718 static HashNode
       
  1719 getpmgalias(HashTable ht, char *name)
       
  1720 {
       
  1721     return getalias(aliastab, ht, name, ALIAS_GLOBAL);
       
  1722 }
       
  1723 
       
  1724 /**/
       
  1725 static HashNode
       
  1726 getpmdisgalias(HashTable ht, char *name)
       
  1727 {
       
  1728     return getalias(aliastab, ht, name, ALIAS_GLOBAL|DISABLED);
       
  1729 }
       
  1730 
       
  1731 /**/
       
  1732 static HashNode
       
  1733 getpmsalias(HashTable ht, char *name)
       
  1734 {
       
  1735     return getalias(sufaliastab, ht, name, ALIAS_SUFFIX);
       
  1736 }
       
  1737 
       
  1738 /**/
       
  1739 static HashNode
       
  1740 getpmdissalias(HashTable ht, char *name)
       
  1741 {
       
  1742     return getalias(sufaliastab, ht, name, ALIAS_SUFFIX|DISABLED);
       
  1743 }
       
  1744 
       
  1745 /**/
       
  1746 static void
       
  1747 scanaliases(HashTable alht, UNUSED(HashTable ht), ScanFunc func,
       
  1748 	    int pmflags, int alflags)
       
  1749 {
       
  1750     struct param pm;
       
  1751     int i;
       
  1752     Alias al;
       
  1753 
       
  1754     memset((void *)&pm, 0, sizeof(struct param));
       
  1755     assignaliasdefs(&pm, alflags);
       
  1756 
       
  1757     for (i = 0; i < alht->hsize; i++)
       
  1758 	for (al = (Alias) alht->nodes[i]; al; al = (Alias) al->next) {
       
  1759 	    if (alflags == al->flags) {
       
  1760 		pm.nam = al->nam;
       
  1761 		if (func != scancountparams &&
       
  1762 		    ((pmflags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
       
  1763 		     !(pmflags & SCANPM_WANTKEYS)))
       
  1764 		    pm.u.str = dupstring(al->text);
       
  1765 		func((HashNode) &pm, pmflags);
       
  1766 	    }
       
  1767 	}
       
  1768 }
       
  1769 
       
  1770 /**/
       
  1771 static void
       
  1772 scanpmraliases(HashTable ht, ScanFunc func, int flags)
       
  1773 {
       
  1774     scanaliases(aliastab, ht, func, flags, 0);
       
  1775 }
       
  1776 
       
  1777 /**/
       
  1778 static void
       
  1779 scanpmdisraliases(HashTable ht, ScanFunc func, int flags)
       
  1780 {
       
  1781     scanaliases(aliastab, ht, func, flags, DISABLED);
       
  1782 }
       
  1783 
       
  1784 /**/
       
  1785 static void
       
  1786 scanpmgaliases(HashTable ht, ScanFunc func, int flags)
       
  1787 {
       
  1788     scanaliases(aliastab, ht, func, flags, ALIAS_GLOBAL);
       
  1789 }
       
  1790 
       
  1791 /**/
       
  1792 static void
       
  1793 scanpmdisgaliases(HashTable ht, ScanFunc func, int flags)
       
  1794 {
       
  1795     scanaliases(aliastab, ht, func, flags, ALIAS_GLOBAL|DISABLED);
       
  1796 }
       
  1797 
       
  1798 /**/
       
  1799 static void
       
  1800 scanpmsaliases(HashTable ht, ScanFunc func, int flags)
       
  1801 {
       
  1802     scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX);
       
  1803 }
       
  1804 
       
  1805 /**/
       
  1806 static void
       
  1807 scanpmdissaliases(HashTable ht, ScanFunc func, int flags)
       
  1808 {
       
  1809     scanaliases(sufaliastab, ht, func, flags, ALIAS_SUFFIX|DISABLED);
       
  1810 }
       
  1811 
       
  1812 /* Table for defined parameters. */
       
  1813 
       
  1814 struct pardef {
       
  1815     char *name;
       
  1816     int flags;
       
  1817     GetNodeFunc getnfn;
       
  1818     ScanTabFunc scantfn;
       
  1819     GsuHash hash_gsu;
       
  1820     GsuArray array_gsu;
       
  1821     Param pm;
       
  1822 };
       
  1823 
       
  1824 /*
       
  1825  * This is a duplicate of nullsethash_gsu.  On some systems
       
  1826  * (such as Cygwin) we can't put a pointer to an imported variable
       
  1827  * in a compile-time initialiser, so we use this instead.
       
  1828  */
       
  1829 static const struct gsu_hash pmnullsethash_gsu =
       
  1830 { hashgetfn, nullsethashfn, nullunsetfn };
       
  1831 static const struct gsu_hash pmcommands_gsu =
       
  1832 { hashgetfn, setpmcommands, stdunsetfn };
       
  1833 static const struct gsu_hash pmfunctions_gsu =
       
  1834 { hashgetfn, setpmfunctions, stdunsetfn };
       
  1835 static const struct gsu_hash pmdisfunctions_gsu =
       
  1836 { hashgetfn, setpmdisfunctions, stdunsetfn };
       
  1837 static const struct gsu_hash pmoptions_gsu =
       
  1838 { hashgetfn, setpmoptions, stdunsetfn };
       
  1839 static const struct gsu_hash pmnameddirs_gsu =
       
  1840 { hashgetfn, setpmnameddirs, stdunsetfn };
       
  1841 static const struct gsu_hash pmraliases_gsu =
       
  1842 { hashgetfn, setpmraliases, stdunsetfn };
       
  1843 static const struct gsu_hash pmgaliases_gsu =
       
  1844 { hashgetfn, setpmgaliases, stdunsetfn };
       
  1845 static const struct gsu_hash pmsaliases_gsu =
       
  1846 { hashgetfn, setpmsaliases, stdunsetfn };
       
  1847 static const struct gsu_hash pmdisraliases_gsu =
       
  1848 { hashgetfn, setpmdisraliases, stdunsetfn };
       
  1849 static const struct gsu_hash pmdisgaliases_gsu =
       
  1850 { hashgetfn, setpmdisgaliases, stdunsetfn };
       
  1851 static const struct gsu_hash pmdissaliases_gsu =
       
  1852 { hashgetfn, setpmdissaliases, stdunsetfn };
       
  1853 
       
  1854 static const struct gsu_array funcstack_gsu =
       
  1855 { funcstackgetfn, arrsetfn, stdunsetfn };
       
  1856 static const struct gsu_array reswords_gsu =
       
  1857 { reswordsgetfn, arrsetfn, stdunsetfn };
       
  1858 static const struct gsu_array disreswords_gsu =
       
  1859 { disreswordsgetfn, arrsetfn, stdunsetfn };
       
  1860 static const struct gsu_array dirs_gsu =
       
  1861 { dirsgetfn, dirssetfn, stdunsetfn };
       
  1862 static const struct gsu_array historywords_gsu =
       
  1863 { histwgetfn, arrsetfn, stdunsetfn };
       
  1864 
       
  1865 static struct pardef partab[] = {
       
  1866     { "parameters", PM_READONLY,
       
  1867       getpmparameter, scanpmparameters, &pmnullsethash_gsu,
       
  1868       NULL, NULL },
       
  1869     { "commands", 0,
       
  1870       getpmcommand, scanpmcommands, &pmcommands_gsu,
       
  1871       NULL, NULL },
       
  1872     { "functions", 0,
       
  1873       getpmfunction, scanpmfunctions, &pmfunctions_gsu,
       
  1874       NULL, NULL },
       
  1875     { "dis_functions", 0,
       
  1876       getpmdisfunction, scanpmdisfunctions, &pmdisfunctions_gsu,
       
  1877       NULL, NULL },
       
  1878     { "funcstack", PM_ARRAY|PM_SPECIAL|PM_READONLY,
       
  1879       NULL, NULL, NULL,
       
  1880       &funcstack_gsu, NULL },
       
  1881     { "builtins", PM_READONLY,
       
  1882       getpmbuiltin, scanpmbuiltins, NULL,
       
  1883       NULL, NULL },
       
  1884     { "dis_builtins", PM_READONLY,
       
  1885       getpmdisbuiltin, scanpmdisbuiltins,
       
  1886       NULL, NULL, },
       
  1887     { "reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
       
  1888       NULL, NULL, NULL,
       
  1889       &reswords_gsu, NULL },
       
  1890     { "dis_reswords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
       
  1891       NULL, NULL, NULL,
       
  1892       &disreswords_gsu, NULL },
       
  1893     { "options", 0,
       
  1894       getpmoption, scanpmoptions, &pmoptions_gsu,
       
  1895       NULL, NULL },
       
  1896     { "modules", PM_READONLY,
       
  1897       getpmmodule, scanpmmodules, NULL,
       
  1898       NULL, NULL },
       
  1899     { "dirstack", PM_ARRAY|PM_SPECIAL|PM_REMOVABLE,
       
  1900       NULL, NULL, NULL,
       
  1901       &dirs_gsu, NULL },
       
  1902     { "history", PM_READONLY,
       
  1903       getpmhistory, scanpmhistory, NULL,
       
  1904       NULL, NULL,  },
       
  1905     { "historywords", PM_ARRAY|PM_SPECIAL|PM_READONLY,
       
  1906       NULL, NULL, NULL,
       
  1907       &historywords_gsu, NULL },
       
  1908     { "jobtexts", PM_READONLY,
       
  1909       getpmjobtext, scanpmjobtexts, NULL,
       
  1910       NULL, NULL },
       
  1911     { "jobstates", PM_READONLY,
       
  1912       getpmjobstate, scanpmjobstates, NULL,
       
  1913       NULL, NULL },
       
  1914     { "jobdirs", PM_READONLY,
       
  1915       getpmjobdir, scanpmjobdirs, NULL,
       
  1916       NULL, NULL },
       
  1917     { "nameddirs", 0,
       
  1918       getpmnameddir, scanpmnameddirs, &pmnameddirs_gsu,
       
  1919       NULL, NULL },
       
  1920     { "userdirs", PM_READONLY,
       
  1921       getpmuserdir, scanpmuserdirs, NULL,
       
  1922       NULL, NULL },
       
  1923     { "aliases", 0,
       
  1924       getpmralias, scanpmraliases, &pmraliases_gsu,
       
  1925       NULL, NULL },
       
  1926     { "galiases", 0,
       
  1927       getpmgalias, scanpmgaliases, &pmgaliases_gsu,
       
  1928       NULL, NULL },
       
  1929     { "saliases", 0,
       
  1930       getpmsalias, scanpmsaliases, &pmsaliases_gsu,
       
  1931       NULL, NULL },
       
  1932     { "dis_aliases", 0,
       
  1933       getpmdisralias, scanpmdisraliases, &pmdisraliases_gsu,
       
  1934       NULL, NULL },
       
  1935     { "dis_galiases", 0,
       
  1936       getpmdisgalias, scanpmdisgaliases, &pmdisgaliases_gsu,
       
  1937       NULL, NULL },
       
  1938     { "dis_saliases", 0,
       
  1939       getpmdissalias, scanpmdissaliases, &pmdissaliases_gsu,
       
  1940       NULL, NULL },
       
  1941     { NULL, 0, NULL, NULL, NULL, NULL, NULL }
       
  1942 };
       
  1943 
       
  1944 /**/
       
  1945 int
       
  1946 setup_(UNUSED(Module m))
       
  1947 {
       
  1948     incleanup = 0;
       
  1949 
       
  1950     return 0;
       
  1951 }
       
  1952 
       
  1953 /**/
       
  1954 int
       
  1955 boot_(UNUSED(Module m))
       
  1956 {
       
  1957     /* Create the special associative arrays.
       
  1958      * As an example for autoloaded parameters, this is probably a bad
       
  1959      * example, because the zsh core doesn't support creation of
       
  1960      * special hashes, yet. */
       
  1961 
       
  1962     struct pardef *def;
       
  1963 
       
  1964     for (def = partab; def->name; def++) {
       
  1965 	unsetparam(def->name);
       
  1966 
       
  1967 	if (def->getnfn) {
       
  1968 	    if (!(def->pm = createspecialhash(def->name, def->getnfn,
       
  1969 					      def->scantfn)))
       
  1970 		return 1;
       
  1971 	    def->pm->flags |= def->flags;
       
  1972 	    if (def->hash_gsu)
       
  1973 		def->pm->gsu.h = def->hash_gsu;
       
  1974 	} else {
       
  1975 	    if (!(def->pm = createparam(def->name, def->flags | PM_HIDE|
       
  1976 					PM_HIDEVAL | PM_REMOVABLE)))
       
  1977 		return 1;
       
  1978 	    def->pm->gsu.a = def->array_gsu;
       
  1979 	}
       
  1980     }
       
  1981     return 0;
       
  1982 }
       
  1983 
       
  1984 /**/
       
  1985 int
       
  1986 cleanup_(UNUSED(Module m))
       
  1987 {
       
  1988     Param pm;
       
  1989     struct pardef *def;
       
  1990 
       
  1991     incleanup = 1;
       
  1992 
       
  1993     for (def = partab; def->name; def++) {
       
  1994 	if ((pm = (Param) paramtab->getnode(paramtab, def->name)) &&
       
  1995 	    pm == def->pm) {
       
  1996 	    pm->flags &= ~PM_READONLY;
       
  1997 	    unsetparam_pm(pm, 0, 1);
       
  1998 	}
       
  1999     }
       
  2000     return 0;
       
  2001 }
       
  2002 
       
  2003 /**/
       
  2004 int
       
  2005 finish_(UNUSED(Module m))
       
  2006 {
       
  2007     return 0;
       
  2008 }