mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-05-23 00:31:29 +02:00
51360: Initial implementation of named references.
This commit is contained in:
parent
d3edf31830
commit
511e020c68
7 changed files with 266 additions and 16 deletions
|
@ -1,5 +1,9 @@
|
|||
2023-02-12 Bart Schaefer <schaefer@zsh.org>
|
||||
|
||||
* 51360: Src/Modules/param_private.c, Src/Modules/parameter.c,
|
||||
Src/builtin.c, Src/params.c, Src/subst.c, Src/zsh.h: Initial
|
||||
implementation of named references.
|
||||
|
||||
* 51404: Src/jobs.c: Nullify filelist after deleting (fix segfault)
|
||||
|
||||
2023-02-09 Oliver Kiddle <opk@zsh.org>
|
||||
|
|
|
@ -512,9 +512,16 @@ static GetNodeFunc getparamnode;
|
|||
static HashNode
|
||||
getprivatenode(HashTable ht, const char *nam)
|
||||
{
|
||||
HashNode hn = getparamnode(ht, nam);
|
||||
/* getparamnode() would follow namerefs, we must not do that here */
|
||||
HashNode hn = gethashnode2(ht, nam);
|
||||
Param pm = (Param) hn;
|
||||
|
||||
/* autoload has precedence over nameref, so getparamnode() */
|
||||
if (pm && (pm->node.flags & PM_AUTOLOAD)) {
|
||||
hn = getparamnode(ht, nam);
|
||||
pm = (Param) hn;
|
||||
/* how would an autoloaded private behave? return here? */
|
||||
}
|
||||
while (!fakelevel && pm && locallevel > pm->level && is_private(pm)) {
|
||||
if (!(pm->node.flags & PM_UNSET)) {
|
||||
/*
|
||||
|
@ -533,6 +540,12 @@ getprivatenode(HashTable ht, const char *nam)
|
|||
}
|
||||
pm = pm->old;
|
||||
}
|
||||
|
||||
/* resolve nameref after skipping private parameters */
|
||||
if (pm && (pm->node.flags & PM_NAMEREF) &&
|
||||
(pm->u.str || (pm->node.flags & PM_UNSET)))
|
||||
pm = (Param) resolve_nameref(pm, NULL);
|
||||
|
||||
return (HashNode)pm;
|
||||
}
|
||||
|
||||
|
@ -571,7 +584,7 @@ printprivatenode(HashNode hn, int printflags)
|
|||
|
||||
static struct builtin bintab[] = {
|
||||
/* Copied from BUILTIN("local"), "P" added */
|
||||
BUILTIN("private", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_private, 0, -1, 0, "AE:%F:%HL:%PR:%TUZ:%ahi:%lmprtux", "P")
|
||||
BUILTIN("private", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_private, 0, -1, 0, "AE:%F:%HL:%PR:%TUZ:%ahi:%lnmprtux", "P")
|
||||
};
|
||||
|
||||
static struct features module_features = {
|
||||
|
|
|
@ -49,13 +49,15 @@ paramtypestr(Param pm)
|
|||
if (pm->node.flags & PM_AUTOLOAD)
|
||||
return dupstring("undefined");
|
||||
|
||||
switch (PM_TYPE(f)) {
|
||||
/* For simplicity we treat PM_NAMEREF as PM_TYPE(PM_SCALAR) */
|
||||
switch (PM_TYPE(f)|(f & PM_NAMEREF)) {
|
||||
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;
|
||||
case PM_NAMEREF: val = "nameref"; break;
|
||||
}
|
||||
DPUTS(!val, "BUG: type not handled in parameter");
|
||||
val = dupstring(val);
|
||||
|
|
|
@ -55,7 +55,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("cd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "qsPL", NULL),
|
||||
BUILTIN("chdir", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "qsPL", NULL),
|
||||
BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL),
|
||||
BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klmp:%rtuxz", NULL),
|
||||
BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klmnp:%rtuxz", NULL),
|
||||
BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL),
|
||||
BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmprs", NULL),
|
||||
BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
|
||||
|
@ -88,7 +88,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL),
|
||||
BUILTIN("kill", BINF_HANDLES_OPTS, bin_kill, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL),
|
||||
BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%ahi:%lp:%rtux", NULL),
|
||||
BUILTIN("local", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%ahi:%lnp:%rtux", NULL),
|
||||
BUILTIN("logout", 0, bin_break, 0, 1, BIN_LOGOUT, NULL, NULL),
|
||||
|
||||
#if defined(ZSH_MEM) & defined(ZSH_MEM_DEBUG)
|
||||
|
@ -121,7 +121,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("trap", BINF_PSPECIAL | BINF_HANDLES_OPTS, bin_trap, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsSw", "v"),
|
||||
BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klp:%rtuxmz", NULL),
|
||||
BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL | BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klp:%rtuxmnz", NULL),
|
||||
BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
|
||||
BUILTIN("unalias", 0, bin_unhash, 0, -1, BIN_UNALIAS, "ams", NULL),
|
||||
BUILTIN("unfunction", 0, bin_unhash, 1, -1, BIN_UNFUNCTION, "m", "f"),
|
||||
|
@ -2030,6 +2030,19 @@ typeset_single(char *cname, char *pname, Param pm, int func,
|
|||
int usepm, tc, keeplocal = 0, newspecial = NS_NONE, readonly, dont_set = 0;
|
||||
char *subscript;
|
||||
|
||||
if (pm && (pm->node.flags & PM_NAMEREF) && !((off|on) & PM_NAMEREF)) {
|
||||
if (!(off & PM_NAMEREF))
|
||||
pm = (Param)resolve_nameref(pm, NULL);
|
||||
if (pm && (pm->node.flags & PM_NAMEREF) &&
|
||||
(on & ~(PM_NAMEREF|PM_LOCAL))) {
|
||||
/* Changing type of PM_SPECIAL|PM_AUTOLOAD is a fatal error. *
|
||||
* Should this be a fatal error as well, rather than warning? */
|
||||
zwarnnam(cname, "%s: can't change type of a named reference",
|
||||
pname);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we use the existing pm? Note that this isn't the end of the
|
||||
* story, because if we try and create a new pm at the same
|
||||
|
@ -2406,6 +2419,11 @@ typeset_single(char *cname, char *pname, Param pm, int func,
|
|||
return NULL;
|
||||
}
|
||||
} else if ((subscript = strchr(pname, '['))) {
|
||||
if (on & PM_NAMEREF) {
|
||||
zerrnam(cname,
|
||||
"%s: reference variable cannot be an array", pname);
|
||||
return NULL;
|
||||
}
|
||||
if (on & PM_READONLY) {
|
||||
zerrnam(cname,
|
||||
"%s: can't create readonly array elements", pname);
|
||||
|
@ -2640,6 +2658,14 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
|
|||
else if (OPT_PLUS(ops,optval))
|
||||
off |= bit;
|
||||
}
|
||||
if (OPT_MINUS(ops,'n')) {
|
||||
if (on|off) {
|
||||
zwarnnam(name, "no other attributes allowed with -n");
|
||||
return 1;
|
||||
}
|
||||
on |= PM_NAMEREF;
|
||||
} else if (OPT_PLUS(ops,'n'))
|
||||
off |= PM_NAMEREF;
|
||||
roff = off;
|
||||
|
||||
/* Sanity checks on the options. Remove conflicting options. */
|
||||
|
@ -3022,6 +3048,27 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
|
|||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (on & PM_NAMEREF) {
|
||||
if (asg->value.scalar &&
|
||||
(strcmp(asg->name, asg->value.scalar) == 0 ||
|
||||
((pm = (Param)resolve_nameref((Param)hn, asg)) &&
|
||||
(pm->node.flags & PM_NAMEREF)))) {
|
||||
if (pm->node.flags & PM_SPECIAL)
|
||||
zwarnnam(name, "%s: invalid reference", pm->node.nam);
|
||||
else
|
||||
zwarnnam(name, "%s: invalid self reference", asg->name);
|
||||
returnval = 1;
|
||||
continue;
|
||||
}
|
||||
if (hn) {
|
||||
/* namerefs always start over fresh */
|
||||
if (((Param)hn)->level >= locallevel)
|
||||
unsetparam_pm((Param)hn, 0, 1);
|
||||
hn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!typeset_single(name, asg->name, (Param)hn,
|
||||
func, on, off, roff, asg, NULL,
|
||||
ops, 0))
|
||||
|
@ -3805,7 +3852,8 @@ bin_unset(char *name, char **argv, Options ops, int func)
|
|||
returnval = 1;
|
||||
}
|
||||
} else {
|
||||
if (unsetparam_pm(pm, 0, 1))
|
||||
if ((pm = (Param)resolve_nameref(pm, NULL)) &&
|
||||
unsetparam_pm(pm, 0, 1))
|
||||
returnval = 1;
|
||||
}
|
||||
if (ss)
|
||||
|
|
190
Src/params.c
190
Src/params.c
|
@ -536,6 +536,9 @@ getparamnode(HashTable ht, const char *nam)
|
|||
nam);
|
||||
}
|
||||
}
|
||||
|
||||
if (hn && ht == realparamtab)
|
||||
hn = resolve_nameref(pm, NULL);
|
||||
return hn;
|
||||
}
|
||||
|
||||
|
@ -993,6 +996,34 @@ createparam(char *name, int flags)
|
|||
gethashnode2(paramtab, name) :
|
||||
paramtab->getnode(paramtab, name));
|
||||
|
||||
if (oldpm && (oldpm->node.flags & PM_NAMEREF) &&
|
||||
!(flags & PM_NAMEREF)) {
|
||||
Param lastpm;
|
||||
struct asgment stop;
|
||||
stop.flags = PM_NAMEREF | (flags & PM_LOCAL);
|
||||
stop.name = oldpm->node.nam;
|
||||
stop.value.scalar = oldpm->u.str;
|
||||
lastpm = (Param)resolve_nameref(oldpm, &stop);
|
||||
if (lastpm) {
|
||||
if (lastpm->node.flags & PM_NAMEREF) {
|
||||
if (lastpm->u.str && *(lastpm->u.str)) {
|
||||
name = lastpm->u.str;
|
||||
oldpm = NULL;
|
||||
} else {
|
||||
if (!(lastpm->node.flags & PM_READONLY))
|
||||
lastpm->node.flags |= PM_UNSET;
|
||||
return lastpm;
|
||||
}
|
||||
} else {
|
||||
/* nameref pointing to an unset local */
|
||||
DPUTS(!(lastpm->node.flags & PM_UNSET),
|
||||
"BUG: local parameter is not unset");
|
||||
oldpm = lastpm;
|
||||
}
|
||||
} else
|
||||
flags |= PM_NAMEREF;
|
||||
}
|
||||
|
||||
DPUTS(oldpm && oldpm->level > locallevel,
|
||||
"BUG: old local parameter not deleted");
|
||||
if (oldpm && (oldpm->level == locallevel || !(flags & PM_LOCAL))) {
|
||||
|
@ -2109,6 +2140,23 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
|
|||
memset(v, 0, sizeof(*v));
|
||||
else
|
||||
v = (Value) hcalloc(sizeof *v);
|
||||
if ((pm->node.flags & PM_NAMEREF) && pm->u.str && *(pm->u.str)) {
|
||||
/* only happens for namerefs pointing to array elements */
|
||||
char *ref = dupstring(pm->u.str);
|
||||
char *ss = pm->width ? ref + pm->width : NULL;
|
||||
if (ss) {
|
||||
sav = *ss;
|
||||
*ss = 0;
|
||||
}
|
||||
Param p1 = (Param)gethashnode2(paramtab, ref);
|
||||
if (!(p1 && (pm = upscope(p1, pm->base))) ||
|
||||
((pm->node.flags & PM_UNSET) &&
|
||||
!(pm->node.flags & PM_DECLARED)))
|
||||
return NULL;
|
||||
if (ss)
|
||||
*ss = sav;
|
||||
s = ss;
|
||||
}
|
||||
if (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED)) {
|
||||
/* Overload v->isarr as the flag bits for hashed arrays. */
|
||||
v->isarr = flags | (isvarat ? SCANPM_ISVAR_AT : 0);
|
||||
|
@ -2677,6 +2725,7 @@ assignstrvalue(Value v, char *val, int flags)
|
|||
}
|
||||
break;
|
||||
}
|
||||
setscope(v->pm);
|
||||
if ((!v->pm->env && !(v->pm->node.flags & PM_EXPORTED) &&
|
||||
!(isset(ALLEXPORT) && !(v->pm->node.flags & PM_HASHELEM))) ||
|
||||
(v->pm->node.flags & PM_ARRAY) || v->pm->ename)
|
||||
|
@ -3084,11 +3133,20 @@ assignsparam(char *s, char *val, int flags)
|
|||
}
|
||||
}
|
||||
if (!v && !(v = getvalue(&vbuf, &t, 1))) {
|
||||
unqueue_signals();
|
||||
zsfree(val);
|
||||
unqueue_signals();
|
||||
/* errflag |= ERRFLAG_ERROR; */
|
||||
return NULL;
|
||||
}
|
||||
if (*val && (v->pm->node.flags & PM_NAMEREF)) {
|
||||
if (!valid_refname(val)) {
|
||||
zerr("invalid variable name: %s", val);
|
||||
zsfree(val);
|
||||
unqueue_signals();
|
||||
errflag |= ERRFLAG_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (flags & ASSPM_WARN)
|
||||
check_warn_pm(v->pm, "scalar", created, 1);
|
||||
v->pm->node.flags &= ~PM_DEFAULTED;
|
||||
|
@ -3115,8 +3173,8 @@ assignsparam(char *s, char *val, int flags)
|
|||
lhs.u.l = lhs.u.l + (zlong)rhs.u.d;
|
||||
}
|
||||
setnumvalue(v, lhs);
|
||||
unqueue_signals();
|
||||
zsfree(val);
|
||||
unqueue_signals();
|
||||
return v->pm; /* avoid later setstrvalue() call */
|
||||
case PM_ARRAY:
|
||||
if (unset(KSHARRAYS)) {
|
||||
|
@ -3141,9 +3199,9 @@ assignsparam(char *s, char *val, int flags)
|
|||
case PM_INTEGER:
|
||||
case PM_EFLOAT:
|
||||
case PM_FFLOAT:
|
||||
zsfree(val);
|
||||
unqueue_signals();
|
||||
zerr("attempt to add to slice of a numeric variable");
|
||||
zsfree(val);
|
||||
return NULL;
|
||||
case PM_ARRAY:
|
||||
kshappend:
|
||||
|
@ -3602,7 +3660,8 @@ unsetparam(char *s)
|
|||
if ((pm = (Param) (paramtab == realparamtab ?
|
||||
/* getnode2() to avoid autoloading */
|
||||
paramtab->getnode2(paramtab, s) :
|
||||
paramtab->getnode(paramtab, s))))
|
||||
paramtab->getnode(paramtab, s))) &&
|
||||
!(pm->node.flags & PM_NAMEREF))
|
||||
unsetparam_pm(pm, 0, 1);
|
||||
unqueue_signals();
|
||||
}
|
||||
|
@ -5783,7 +5842,8 @@ static const struct paramtypes pmtypes[] = {
|
|||
{ PM_TAGGED, "tagged", 't', 0},
|
||||
{ PM_EXPORTED, "exported", 'x', 0},
|
||||
{ PM_UNIQUE, "unique", 'U', 0},
|
||||
{ PM_TIED, "tied", 'T', 0}
|
||||
{ PM_TIED, "tied", 'T', 0},
|
||||
{ PM_NAMEREF, "namref", 'n', 0}
|
||||
};
|
||||
|
||||
#define PMTYPES_SIZE ((int)(sizeof(pmtypes)/sizeof(struct paramtypes)))
|
||||
|
@ -6037,3 +6097,123 @@ printparamnode(HashNode hn, int printflags)
|
|||
else if (!(printflags & PRINT_KV_PAIR))
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export HashNode
|
||||
resolve_nameref(Param pm, const Asgment stop)
|
||||
{
|
||||
HashNode hn = (HashNode)pm;
|
||||
const char *seek = stop ? stop->value.scalar : NULL;
|
||||
|
||||
if (pm && (pm->node.flags & PM_NAMEREF)) {
|
||||
if (pm && (pm->node.flags & (PM_UNSET|PM_TAGGED))) {
|
||||
/* Semaphore with createparam() */
|
||||
pm->node.flags &= ~PM_UNSET;
|
||||
/* See V10private.ztst end is in scope but private:
|
||||
if (pm->node.flags & PM_SPECIAL)
|
||||
return NULL;
|
||||
*/
|
||||
return (HashNode) pm;
|
||||
} else if (pm->u.str) {
|
||||
if ((pm->node.flags & PM_TAGGED) ||
|
||||
(stop && strcmp(pm->u.str, stop->name) == 0)) {
|
||||
/* zwarnnam(pm->u.str, "invalid self reference"); */
|
||||
return stop ? (HashNode)pm : NULL;
|
||||
}
|
||||
if (*(pm->u.str))
|
||||
seek = pm->u.str;
|
||||
}
|
||||
}
|
||||
else if (pm && !(stop && (stop->flags & PM_NAMEREF)))
|
||||
return (HashNode)pm;
|
||||
if (seek) {
|
||||
queue_signals();
|
||||
/* pm->width is the offset of any subscript */
|
||||
if (pm && (pm->node.flags & PM_NAMEREF) && pm->width) {
|
||||
if (stop) {
|
||||
if (stop->flags & PM_NAMEREF)
|
||||
hn = (HashNode)pm;
|
||||
else
|
||||
hn = NULL;
|
||||
} else {
|
||||
/* this has to be the end of any chain */
|
||||
hn = (HashNode)pm; /* see fetchvalue() */
|
||||
}
|
||||
} else if ((hn = gethashnode2(realparamtab, seek))) {
|
||||
if (pm) {
|
||||
if (!(stop && (stop->flags & (PM_LOCAL))))
|
||||
hn = (HashNode)upscope((Param)hn,
|
||||
((pm->node.flags & PM_NAMEREF) ?
|
||||
pm->base : ((Param)hn)->level));
|
||||
/* user can't tag a nameref, safe for loop detection */
|
||||
pm->node.flags |= PM_TAGGED;
|
||||
}
|
||||
if (hn) {
|
||||
if (hn->flags & PM_AUTOLOAD)
|
||||
hn = getparamnode(realparamtab, seek);
|
||||
if (!(hn->flags & PM_UNSET))
|
||||
hn = resolve_nameref((Param)hn, stop);
|
||||
}
|
||||
if (pm)
|
||||
pm->node.flags &= ~PM_TAGGED;
|
||||
} else if (stop && (stop->flags & PM_NAMEREF))
|
||||
hn = (HashNode)pm;
|
||||
unqueue_signals();
|
||||
}
|
||||
|
||||
return hn;
|
||||
}
|
||||
|
||||
/**/
|
||||
static void
|
||||
setscope(Param pm)
|
||||
{
|
||||
if (pm->node.flags & PM_NAMEREF) {
|
||||
Param basepm;
|
||||
char *t = pm->u.str ? itype_end(pm->u.str, IIDENT, 0) : NULL;
|
||||
|
||||
/* Temporarily change nameref to array parameter itself */
|
||||
if (t && *t == '[')
|
||||
*t = 0;
|
||||
else
|
||||
t = 0;
|
||||
basepm = (Param)resolve_nameref(pm, NULL);
|
||||
if (t) {
|
||||
pm->width = t - pm->u.str;
|
||||
*t = '[';
|
||||
}
|
||||
if (basepm)
|
||||
pm->base = ((basepm->node.flags & PM_NAMEREF) ?
|
||||
basepm->base : basepm->level);
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export Param
|
||||
upscope(Param pm, int reflevel)
|
||||
{
|
||||
Param up = pm->old;
|
||||
while (pm && up && up->level >= reflevel) {
|
||||
pm = up;
|
||||
if (up)
|
||||
up = up->old;
|
||||
}
|
||||
return pm;
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export int
|
||||
valid_refname(char *val)
|
||||
{
|
||||
char *t = itype_end(val, IIDENT, 0);
|
||||
|
||||
if (*t != 0) {
|
||||
if (*t == '[') {
|
||||
tokenize(t = dupstring(t+1));
|
||||
t = parse_subscript(t, 0, ']');
|
||||
} else {
|
||||
t = NULL;
|
||||
}
|
||||
}
|
||||
return !!t;
|
||||
}
|
||||
|
|
|
@ -2573,13 +2573,14 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
|
|||
!(v->pm->node.flags & PM_UNSET))) {
|
||||
int f = v->pm->node.flags;
|
||||
|
||||
switch (PM_TYPE(f)) {
|
||||
switch (PM_TYPE(f)|(f & PM_NAMEREF)) {
|
||||
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;
|
||||
case PM_NAMEREF: val = "nameref"; break;
|
||||
}
|
||||
val = dupstring(val);
|
||||
if (v->pm->level)
|
||||
|
|
|
@ -1852,8 +1852,9 @@ struct param {
|
|||
GsuHash h;
|
||||
} gsu;
|
||||
|
||||
int base; /* output base or floating point prec */
|
||||
int width; /* field width */
|
||||
int base; /* output base or floating point prec or */
|
||||
/* for namerefs, locallevel of reference */
|
||||
int width; /* field width or nameref subscript idx */
|
||||
char *env; /* location in environment, if exported */
|
||||
char *ename; /* name of corresponding environment var */
|
||||
Param old; /* old struct for use with local */
|
||||
|
@ -1932,9 +1933,10 @@ struct tieddata {
|
|||
*/
|
||||
#define PM_HASHELEM (1<<28) /* is a hash-element */
|
||||
#define PM_NAMEDDIR (1<<29) /* has a corresponding nameddirtab entry */
|
||||
#define PM_NAMEREF (1<<30) /* pointer to a different parameter */
|
||||
|
||||
/* The option string corresponds to the first of the variables above */
|
||||
#define TYPESET_OPTSTR "aiEFALRZlurtxUhHTkz"
|
||||
#define TYPESET_OPTSTR "aiEFALRZlurtxUhHT"
|
||||
|
||||
/* These typeset options take an optional numeric argument */
|
||||
#define TYPESET_OPTNUM "LRZiEF"
|
||||
|
|
Loading…
Reference in a new issue