Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: BUG: Initializations of named references with an empty string should trigger an error



With my patch only the first command would remain valid. Here is an updated patch that includes doc changes.

Philippe


On Thu, May 22, 2025 at 6:36 PM Mikael Magnusson <mikachu@xxxxxxxxx> wrote:
On Thu, May 22, 2025 at 1:32 PM Philippe Altherr
<philippe.altherr@xxxxxxxxx> wrote:
>
> $ typeset -n ref1=""
> zsh: invalid variable name:
> $ typeset ref2
> $ typeset -n ref2
> $ typeset -p ref2
> typeset -n ref2=''
>
> Interestingly converting a scalar initialized with an empty string triggers the invalid name error:
>
> $ typeset ref3=""
> $ typeset -n ref3
> zsh: invalid variable name:

This reminds me of something I noticed earlier when I was looking at
the current manpage:
       An empty reference such as one of

              typeset -n pname
              typeset -n pname=
              typeset -n pname=""

This is possibly a bit confusing since it implies that the last two
commands are not identical, which they are. If there are no complaints
I'll just remove the third line. (Other identical commands would be
typeset"" -n"" pname= and typese"t" -"n" pname"=" for example, which I
think everyone will agree would be silly to list.)

--
Mikael Magnusson
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 59e964519..34b88a285 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -677,20 +677,17 @@ expand var(rname).  This also applies to `tt(unset )var(pname)' and to
 most subsequent uses of `tt(typeset)' with the exceptions of declaring
 a local in a called function, or updating a current-scope parameter with
 `tt(typeset -n)' or `tt(typeset +n)'. Thus to remove a named reference,
-use either `tt(unset -n )var(pname)' (preferred) or one of:
+use either `tt(unset -n )var(pname)' (preferred) or:
 ifzman()
-example(tt(typeset -n )var(pname=)
-tt(typeset +n )var(pname))
+example(tt(typeset +n )var(pname))
 
 followed by
 ifzman()
 indent(tt(unset )var(pname))
 
-An empty reference such as one of
+An empty reference such as
 ifzman()
-example(tt(typeset -n )var(pname)
-tt(typeset -n )var(pname)tt(=)
-tt(typeset -n )var(pname)tt(=""))
+example(tt(typeset -n )var(pname))
 
 acts as a placeholder.  The first non-empty assignment to var(pname)
 initializes the reference, and subsequently any expansions of, or
diff --git a/Src/params.c b/Src/params.c
index 7b515515e..e0cf45a51 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -3233,7 +3233,7 @@ assignsparam(char *s, char *val, int flags)
 	/* errflag |= ERRFLAG_ERROR; */
 	return NULL;
     }
-    if (*val && (v->pm->node.flags & PM_NAMEREF)) {
+    if ((v->pm->node.flags & PM_NAMEREF)) {
 	if (!valid_refname(val)) {
 	    zerr("invalid variable name: %s", val);
 	    zsfree(val);
@@ -6463,6 +6463,9 @@ upscope(Param pm, int reflevel)
 mod_export int
 valid_refname(char *val)
 {
+    if (!*val)
+	return 0;
+
     char *t = itype_end(val, INAMESPC, 0);
 
     if (idigit(*val))
diff --git a/Test/K01nameref.ztst b/Test/K01nameref.ztst
index 54f0aaf68..edbae06d9 100644
--- a/Test/K01nameref.ztst
+++ b/Test/K01nameref.ztst
@@ -141,8 +141,8 @@
 
  typeset -n ptr=
  typeset -n
-0:nameref placeholder
->ptr=''
+1:invalid empty nameref
+*?*invalid variable name: 
 
  typeset -n ptr
  ptr=var
@@ -170,6 +170,17 @@
 0:convert scalar to nameref
 >ptr=var
 
+ typeset ptr
+ typeset -n ptr
+ typeset -n
+0:convert uninitialized scalar to nameref
+>ptr
+
+ typeset ptr=''
+ typeset -n ptr
+1:convert empty scalar to nameref
+*?*invalid variable name: 
+
  typeset -n ptr=var
  typeset +n ptr
  typeset -p ptr
@@ -1007,8 +1018,8 @@ F:runs in `setopt noexec` so $(...) returns nothing
 >typeset ref=RW
 
  () {
-  typeset -n r1 r2=
-  typeset -p r1 r2
+  typeset -n r1
+  typeset -p r1
   print -- ${(!)r1-unset}
   print -- ${+r1}
   typeset -p r1
@@ -1016,7 +1027,6 @@ F:runs in `setopt noexec` so $(...) returns nothing
 0:unset nameref remains unset when resolved
 F:relies on global TYPESET_TO_UNSET in %prep
 >typeset -n r1
->typeset -n r2=''
 >unset
 >0
 >typeset -n r1
diff --git a/Test/V10private.ztst b/Test/V10private.ztst
index 26004a2dc..975145c24 100644
--- a/Test/V10private.ztst
+++ b/Test/V10private.ztst
@@ -374,7 +374,7 @@ F:Here ptr1 finds private ptr2 by scope mismatch
 
  () {
    typeset -n ptr1=ptr2
-   private -n ptr2=	# Assignment makes this a placeholder, not unset
+   private -n ptr2=foo
    typeset -p ptr1 ptr2
    typeset val=LOCAL
    () {
@@ -389,12 +389,12 @@ F:Here ptr1 finds private ptr2 by scope mismatch
 F:See K01nameref.ztst up-reference part 5
 F:Here ptr1 finds private ptr2 by scope mismatch
 >typeset -n ptr1=ptr2
->typeset -hn ptr2=''
+>typeset -hn ptr2=foo
 >ptr1=ptr2
 >ptr1=
 >ptr2=
 >typeset -n ptr1=ptr2
->typeset -hn ptr2=''
+>typeset -hn ptr2=foo
 *?*ptr1: assignment failed
 *?*no such variable: ptr2
 


Messages sorted by: Reverse Date, Date, Thread, Author