From 292e6676632a8c0ec58ba6a005d2478aa57e799d Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Thu, 9 Jun 2011 23:12:23 +0000 Subject: [PATCH] sh: Do parameter expansion before printing PS4 (set -x). The function name expandstr() and the general idea of doing this kind of expansion by treating the text as a here document without end marker is from dash. All variants of parameter expansion and arithmetic expansion also work (the latter is not required by POSIX but it does not take extra code and many other shells also allow it). Command substitution is prevented because I think it causes too much code to be re-entered (for example creating an unbounded recursion of trace lines). Unfortunately, our LINENO is somewhat crude, otherwise PS4='$LINENO+ ' would be quite useful. --- bin/sh/eval.c | 5 ++- bin/sh/expand.c | 1 + bin/sh/parser.c | 44 ++++++++++++++++++++++ bin/sh/parser.h | 1 + bin/sh/sh.1 | 4 +- tools/regression/bin/sh/execution/set-x3.0 | 9 +++++ 6 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 tools/regression/bin/sh/execution/set-x3.0 diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 585f91ead32a..92a18e4b2b3b 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -745,8 +745,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) /* Print the command if xflag is set. */ if (xflag) { char sep = 0; - const char *p; - out2str(ps4val()); + const char *p, *ps4; + ps4 = expandstr(ps4val()); + out2str(ps4 != NULL ? ps4 : ps4val()); for (sp = varlist.list ; sp ; sp = sp->next) { if (sep != 0) out2c(' '); diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 108a77c4be68..aaa91acc3392 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -174,6 +174,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag) ifslastp = NULL; argstr(arg->narg.text, flag); if (arglist == NULL) { + STACKSTRNUL(expdest); return; /* here document expanded */ } STPUTC('\0', expdest); diff --git a/bin/sh/parser.c b/bin/sh/parser.c index 151970b79d08..2fea1ecb5270 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -2029,3 +2029,47 @@ getprompt(void *unused __unused) ps[i] = '\0'; return (ps); } + + +const char * +expandstr(char *ps) +{ + union node n; + struct jmploc jmploc; + struct jmploc *const savehandler = handler; + const int saveprompt = doprompt; + struct parsefile *const savetopfile = getcurrentfile(); + struct parser_temp *const saveparser_temp = parser_temp; + const char *result = NULL; + + if (!setjmp(jmploc.loc)) { + handler = &jmploc; + parser_temp = NULL; + setinputstring(ps, 1); + doprompt = 0; + readtoken1(pgetc(), DQSYNTAX, "\n\n", 0); + if (backquotelist != NULL) + error("Command substitution not allowed here"); + + n.narg.type = NARG; + n.narg.next = NULL; + n.narg.text = wordtext; + n.narg.backquote = backquotelist; + + expandarg(&n, NULL, 0); + result = stackblock(); + INTOFF; + } + handler = savehandler; + doprompt = saveprompt; + popfilesupto(savetopfile); + if (parser_temp != saveparser_temp) { + parser_temp_free_all(); + parser_temp = saveparser_temp; + } + if (result != NULL) { + INTON; + } else if (exception == EXINT) + raise(SIGINT); + return result; +} diff --git a/bin/sh/parser.h b/bin/sh/parser.h index e213e2140617..9a996d04a603 100644 --- a/bin/sh/parser.h +++ b/bin/sh/parser.h @@ -82,3 +82,4 @@ void fixredir(union node *, const char *, int); int goodname(const char *); int isassignment(const char *); char *getprompt(void *); +const char *expandstr(char *); diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 42e55d391b3e..0ce07bd9f0ce 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd May 21, 2011 +.Dd June 9, 2011 .Dt SH 1 .Os .Sh NAME @@ -324,7 +324,7 @@ Useful for debugging. Write each command (preceded by the value of the .Va PS4 -variable) +variable subjected to parameter expansion and arithmetic expansion) to standard error before it is executed. Useful for debugging. .El diff --git a/tools/regression/bin/sh/execution/set-x3.0 b/tools/regression/bin/sh/execution/set-x3.0 new file mode 100644 index 000000000000..1ca57aca6baa --- /dev/null +++ b/tools/regression/bin/sh/execution/set-x3.0 @@ -0,0 +1,9 @@ +# $FreeBSD$ + +key='must contain this' +PS4='$key+ ' +{ r=`set -x; { :; } 2>&1 >/dev/null`; } 2>/dev/null +case $r in +*"$key"*) true ;; +*) false ;; +esac