summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2024-03-04 21:07:01 -0800
committerBart Schaefer <schaefer@zsh.org>2024-03-04 21:07:01 -0800
commit610b18875ad9f4498a57e9af6903bcac3b14ff46 (patch)
tree44123f9fbd7650323f320cb81b4ed05448dd36d1 /Src
parent05c7b21e2b30873d002b50b37e2fbd3803d4b608 (diff)
downloadzsh-610b18875ad9f4498a57e9af6903bcac3b14ff46.tar.gz
zsh-610b18875ad9f4498a57e9af6903bcac3b14ff46.zip
52650 plus minor fixes: add -u for named references pointing to "upper" scope
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/ksh93.c2
-rw-r--r--Src/builtin.c2
-rw-r--r--Src/exec.c22
-rw-r--r--Src/params.c32
4 files changed, 43 insertions, 15 deletions
diff --git a/Src/Modules/ksh93.c b/Src/Modules/ksh93.c
index 9af5e1d69..6760cbca0 100644
--- a/Src/Modules/ksh93.c
+++ b/Src/Modules/ksh93.c
@@ -38,7 +38,7 @@
*/
static struct builtin bintab[] = {
- BUILTIN("nameref", BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "gr", "n")
+ BUILTIN("nameref", BINF_ASSIGN, (HandlerFunc)bin_typeset, 0, -1, 0, "gur", "n")
};
#include "zsh.mdh"
diff --git a/Src/builtin.c b/Src/builtin.c
index 83144677b..ba9cb03c2 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2699,7 +2699,7 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
off |= bit;
}
if (OPT_MINUS(ops,'n')) {
- if ((on|off) & ~PM_READONLY) {
+ if ((on|off) & ~(PM_READONLY|PM_UPPER)) {
zwarnnam(name, "no other attributes allowed with -n");
return 1;
}
diff --git a/Src/exec.c b/Src/exec.c
index d85adbea5..0231bc361 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -2604,6 +2604,17 @@ addvars(Estate state, Wordcode pc, int addflags)
opts[ALLEXPORT] = allexp;
} else
pm = assignsparam(name, val, myflags);
+ if (!pm) {
+ lastval = 1;
+ /*
+ * This is cheating but some exec functions propagate
+ * assignment status only from command substitution
+ *
+ * zerr("%s: assignment failed", name);
+ */
+ if (!cmdoutval)
+ cmdoutval = 1;
+ }
if (errflag) {
state->pc = opc;
return;
@@ -2628,7 +2639,16 @@ addvars(Estate state, Wordcode pc, int addflags)
}
fprintf(xtrerr, ") ");
}
- assignaparam(name, arr, myflags);
+ if (!assignaparam(name, arr, myflags)) {
+ lastval = 1;
+ /*
+ * See above RE "cheating"
+ *
+ * zerr("%s: array assignment failed", name);
+ */
+ if (!cmdoutval)
+ cmdoutval = 1;
+ }
if (errflag) {
state->pc = opc;
return;
diff --git a/Src/params.c b/Src/params.c
index e83e4aa5e..263cd0c52 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1060,8 +1060,7 @@ createparam(char *name, int flags)
"BUG: local parameter is not unset");
oldpm = lastpm;
}
- } else
- flags |= PM_NAMEREF;
+ }
}
DPUTS(oldpm && oldpm->level > locallevel,
@@ -6267,10 +6266,12 @@ resolve_nameref(Param pm, const Asgment stop)
}
} 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));
+ if (!(stop && (stop->flags & (PM_LOCAL)))) {
+ int scope = ((pm->node.flags & PM_NAMEREF) ?
+ ((pm->node.flags & PM_UPPER) ? -1 :
+ pm->base) : ((Param)hn)->level);
+ hn = (HashNode)upscope((Param)hn, scope);
+ }
/* user can't tag a nameref, safe for loop detection */
pm->node.flags |= PM_TAGGED;
}
@@ -6316,11 +6317,13 @@ setloopvar(char *name, char *value)
static void
setscope(Param pm)
{
- if (pm->node.flags & PM_NAMEREF) {
+ queue_signals();
+ if (pm->node.flags & PM_NAMEREF) do {
Param basepm;
struct asgment stop;
char *refname = GETREFNAME(pm);
char *t = refname ? itype_end(refname, INAMESPC, 0) : NULL;
+ int q = queue_signal_level();
/* Temporarily change nameref to array parameter itself */
if (t && *t == '[')
@@ -6330,9 +6333,11 @@ setscope(Param pm)
stop.name = "";
stop.value.scalar = NULL;
stop.flags = PM_NAMEREF;
- if (locallevel)
+ if (locallevel && !(pm->node.flags & PM_UPPER))
stop.flags |= PM_LOCAL;
+ dont_queue_signals(); /* Prevent unkillable loops */
basepm = (Param)resolve_nameref(pm, &stop);
+ restore_queue_signals(q);
if (t) {
pm->width = t - refname;
*t = '[';
@@ -6345,7 +6350,7 @@ setscope(Param pm)
if (upscope(pm, pm->base) == pm) {
zerr("%s: invalid self reference", refname);
unsetparam_pm(pm, 0, 1);
- return;
+ break;
}
pm->node.flags &= ~PM_SELFREF;
} else if (pm->base == pm->level) {
@@ -6353,7 +6358,7 @@ setscope(Param pm)
strcmp(pm->node.nam, refname) == 0) {
zerr("%s: invalid self reference", refname);
unsetparam_pm(pm, 0, 1);
- return;
+ break;
}
}
} else if ((t = GETREFNAME(basepm))) {
@@ -6361,7 +6366,7 @@ setscope(Param pm)
strcmp(pm->node.nam, t) == 0) {
zerr("%s: invalid self reference", refname);
unsetparam_pm(pm, 0, 1);
- return;
+ break;
}
}
} else
@@ -6381,7 +6386,8 @@ setscope(Param pm)
zerr("%s: invalid self reference", refname);
unsetparam_pm(pm, 0, 1);
}
- }
+ } while (0);
+ unqueue_signals();
}
/**/
@@ -6393,6 +6399,8 @@ upscope(Param pm, int reflevel)
pm = up;
up = up->old;
}
+ if (reflevel < 0 && locallevel > 0)
+ return pm->level == locallevel ? up : pm;
return pm;
}