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

Re: Feature request: ZSH_XTRACEFD variable



On Sun, 2020-05-03 at 06:43 +0200, Roman Perepelitsa wrote:
> On Sun, May 3, 2020 at 2:07 AM Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx> wrote:
> > 
> > I would have expected the unsetfn to be called for any special parameter.
> 
> I've bumped into a similar issue with LC_* parameters. Here are a
> couple of test cases:
> 
> 1.
> 
>   (
>     unset -m 'LC_*|LANG'
>     export LC_CTYPE='en_US.UTF-8'  # set this to any UTF-8 locale you have
>     echo '\u276F'  # this works
>     () {
>       local LC_ALL=C
>     }
>     echo '\u276F'  # this doesn't work
>   )
> 
> 2.
> 
>   (
>     unset -m 'LC_*|LANG'
>     LC_COLLATE=en_US.UTF-8
>     x=(-a --b)
>     print -r -- ${(on)x}  # this prints "-a --b"
>     () {
>       local LC_ALL= LC_COLLATE=C
>       print -r -- ${(on)x}
>     }
>     print -r -- ${(on)x}  # this prints "--b -a"
>   )

Something like the attached?  Slightly but not extensively tested, so I could easily
have missed something.

pws

diff --git a/Src/params.c b/Src/params.c
index 863b32600..122f5da7d 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -5569,6 +5569,14 @@ startparamscope(void)
     locallevel++;
 }
 
+#ifdef USE_LOCALE
+/*
+ * Flag that one of the special LC_ functions or LANG changed on scope
+ * end
+ */
+static int lc_update_needed;
+#endif /* USE_LOCALE */
+
 /* End a parameter scope: delete the parameters local to the scope. */
 
 /**/
@@ -5579,7 +5587,28 @@ endparamscope(void)
     locallevel--;
     /* This pops anything from a higher locallevel */
     saveandpophiststack(0, HFILE_USE_OPTIONS);
+#ifdef USE_LOCALE
+    lc_update_needed = 0;
+#endif
     scanhashtable(paramtab, 0, 0, 0, scanendscope, 0);
+#ifdef USE_LOCALE
+    if (lc_update_needed)
+    {
+	/* Locale changed --- ensure it is restored. */
+	char *val;
+	if ((val = getsparam_u("LC_ALL")) && *val) {
+	    setlocale(LC_ALL, val);
+	} else {
+	    struct localename *ln;
+	    if ((val = getsparam_u("LANG")) && *val)
+		setlang(val);
+	    for (ln = lc_names; ln->name; ln++) {
+		if ((val = getsparam_u(ln->name)) && *val)
+		    setlocale(ln->category, val);
+	    }
+	}
+    }
+#endif /* USE_LOCALE */
     unqueue_signals();
 }
 
@@ -5600,6 +5629,11 @@ scanendscope(HashNode hn, UNUSED(int flags))
 	     */
 	    Param tpm = pm->old;
 
+#ifdef USE_LOCALE
+	    if (!strncmp(pm->node.nam, "LC_", 3) ||
+		!strcmp(pm->node.nam, "LANG"))
+		lc_update_needed = 1;
+#endif
 	    if (!strcmp(pm->node.nam, "SECONDS"))
 	    {
 		setsecondstype(pm, PM_TYPE(tpm->node.flags), PM_TYPE(pm->node.flags));


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