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

Re: 'emulate sh -c' and $0

On May 30,  5:14pm, Richard Hansen wrote:
} Would it add too much complexity to the code or documentation if the
} emulate builtin did more than just toggle options (specifically:
} temporarily change the binding of $0 to the original value)?

No, probably not.  We could certainly get away with making the change
to $0 be an additional effect of the (relatively new) -c option, i.e.,

    emulate sh

changes only the options, but 

    emulate sh -c 'some command'

changes both options and $0 in the scope of 'some command'.  In fact I
like that idea a lot, now that I've written it down ... but it'd be a
bit complicated to add that to "sticky emulation" so a simpler plan is
probably better.

} > The use cases in both directions seem pretty unusual to me.  Losing the
} > ability to "localize" $0 for scripts feels almost as likely to create
} > questions as does your situation.
} I'm not sure what you mean by losing the ability to localize $0.

You gave two examples in your original message on this thread: the current
behavior and the behavior you expected.  Someone else might be expecting
the current behavior, and I don't see any clear criteria for deciding
which one is "best."  If we make any of the suggested changes here, the
current behavior is lost.

} I see a few OK options:
}   * Option #1:
}     3. When 'emulate sh' starts, temporarily set argzero to
}        orig_argzero.  Restore argzero when 'emulate sh' returns.
}   * Option #2:
}     3. Add a new option; let's call it LOCALIZE_ARGZERO for now.  If
}        LOCALIZE_ARGZERO is enabled, use argzero to expand $0.  If
}        LOCALIZE_ARGZERO is disabled, use orig_argzero to expand $0.
}     4. Enable LOCALIZE_ARGZERO by default, but disable it in sh
}        emulation mode.
}     5. Stop disabling FUNCTION_ARGZERO by default in sh emulation mode.
}   * Option #3:
}     3. Modify the expansion rules for $0 as follows:  If
}        FUNCTION_ARGZERO is enabled, use argzero to expand $0.  If
}        FUNCTION_ARGZERO is disabled, use orig_argzero to expand $0.

I was initially leaning toward #3, because #1 takes away the current
behavior and because I'd rather not add yet another option as in #2 ...
but then I had a different idea ...

It seems to me that the ideal situation would be that

    emulate sh

works exactly as it does now ("With SINGLE ARGUMENT set up zsh options"
says the doc, emphasis mine) but that

    emulate sh -c 'some command'

alters the behavior of $0 as well.  The advantage of this is that the -c
option to emulate is relatively new; any scripts relying on the current
$0 behavior are likely old and won't use -c.  The drawback to this is
"sticky emulation" for functions, which is based entirely on option
settings; but that can be made to work if we add an option.  Hence:

If we leave FUNCTION_ARGZERO as it is (that is, off by default for sh
emulation) and add an option POSIX_ARGZERO which exposes the global
argzero when set (inverting your Option #2) but which is never on by
default, then bin_emulate can set POSIX_ARGZERO in the -c scope when
emulating sh/ksh, and it will be sticky for functions defined there.

We wouldn't even have to build those smarts into bin_emulate; a user
who wanted the POSIX semantics could explicitly do

    emulate sh -o POSIX_ARGZERO -c '...'

The only "magic" necessary is that POSIX_ARGZERO exposes the original
value of $0 in spite of the current FUNCTION_ARGZERO setting.

Here are the bits outside bin_emulate, and not yet with doc.  I suppose
there may be some places where posixzero needs to be saved / changed /
restored, which this hasn't covered.

diff --git a/Src/init.c b/Src/init.c
index fd12412..5e92f59 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -226,7 +226,7 @@ parseargs(char **argv, char **runscript)
     char **x;
     LinkList paramlist;
-    argzero = *argv++;
+    argzero = posixzero = *argv++;
     SHIN = 0;
     /* There's a bit of trickery with opts[INTERACTIVE] here.  It starts *
@@ -253,7 +253,7 @@ parseargs(char **argv, char **runscript)
     if (*argv) {
 	if (unset(SHINSTDIN)) {
 	    if (cmd)
-		argzero = *argv;
+		argzero = posixzero = *argv;
 		*runscript = *argv;
 	    opts[INTERACTIVE] &= 1;
@@ -275,6 +275,7 @@ parseargs(char **argv, char **runscript)
     while ((*x++ = (char *)getlinknode(paramlist)));
     argzero = ztrdup(argzero);
+    posixzero = ztrdup(posixzero);
 /* Insert into list in order of pointer value */
diff --git a/Src/options.c b/Src/options.c
index ce73d99..e83dc58 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -207,6 +207,7 @@ static struct optname optns[] = {
 {{NULL, "pathscript",	      OPT_EMULATE|OPT_BOURNE},	 PATHSCRIPT},
 {{NULL, "pipefail",           OPT_EMULATE},              PIPEFAIL},
 {{NULL, "posixaliases",       OPT_EMULATE|OPT_BOURNE},	 POSIXALIASES},
+{{NULL, "posixargzero",       OPT_EMULATE},              POSIXARGZERO},
 {{NULL, "posixbuiltins",      OPT_EMULATE|OPT_BOURNE},	 POSIXBUILTINS},
 {{NULL, "posixcd",            OPT_EMULATE|OPT_BOURNE},	 POSIXCD},
diff --git a/Src/params.c b/Src/params.c
index 7901029..0699ead 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -67,6 +67,7 @@ char **path,		/* $path        */
 char *argzero,		/* $0           */
+     *posixzero,	/* $0           */
      *home,		/* $HOME        */
      *nullcmd,		/* $NULLCMD     */
      *oldpwd,		/* $OLDPWD      */
@@ -194,6 +195,8 @@ static const struct gsu_integer euid_gsu =
 static const struct gsu_integer ttyidle_gsu =
 { ttyidlegetfn, nullintsetfn, stdunsetfn };
+static const struct gsu_scalar argzero_gsu =
+{ argzerogetfn, nullstrsetfn, nullunsetfn };
 static const struct gsu_scalar username_gsu =
 { usernamegetfn, usernamesetfn, stdunsetfn };
 static const struct gsu_scalar dash_gsu =
@@ -285,6 +288,7 @@ IPDEF2("WORDCHARS", wordchars_gsu, 0),
 IPDEF2("_", underscore_gsu, PM_DONTIMPORT),
 IPDEF2("KEYBOARD_HACK", keyboard_hack_gsu, PM_DONTIMPORT),
+IPDEF2("0", argzero_gsu, 0),
 #ifdef USE_LOCALE
 # define LCIPDEF(name) IPDEF2(name, lc_blah_gsu, PM_UNSET)
@@ -340,7 +344,6 @@ IPDEF7U("RPROMPT2", &rprompt2),
 IPDEF7("PS3", &prompt3),
 IPDEF7("PS4", &prompt4),
 IPDEF7("SPROMPT", &sprompt),
-IPDEF7("0", &argzero),
 #define IPDEF8(A,B,C,D) {{NULL,A,D|PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(colonarr_gsu),0,0,NULL,C,NULL,0}
 IPDEF8("CDPATH", &cdpath, "cdpath", 0),
@@ -3981,6 +3984,17 @@ lcsetfn(Param pm, char *x)
 #endif /* USE_LOCALE */
+/* Function to get value for special parameter `0' */
+static char *
+argzerogetfn(UNUSED(Param pm))
+    if (isset(POSIXARGZERO))
+	return posixzero;
+    return argzero;
 /* Function to get value for special parameter `HISTSIZE' */
diff --git a/Src/zsh.h b/Src/zsh.h
index 5fbff57..620883b 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2151,6 +2151,7 @@ enum {

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