diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-29 21:12:29 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-29 21:12:29 +0200 |
commit | 469998015f57a552718420a4050d90e5dae6a6fd (patch) | |
tree | 7abea9787997b088dbbf5857b8bbe9446a383274 | |
parent | 0f018b30700989462de0a15b8285206d16170c1f (diff) | |
download | busybox-469998015f57a552718420a4050d90e5dae6a6fd.tar.gz |
ash: [PARSER] Add FAKEEOFMARK for expandstr
Upstream commit:
Date: Thu, 27 Dec 2007 13:54:16 +1100
[PARSER] Add FAKEEOFMARK for expandstr
Previously expandstr used the string "" to indicate that it needs to be
treated just like a here-doc except that there is no terminator. However,
the string "" is in fact a valid here-doc terminator so now that we deal
with it correctly expandstr no longer works in the presence of new-lines
in the prompt.
This patch introduces the FAKEEOFMARK macro which does not equal any
real EOF marker but is distinct from the NULL pointer which is used to
indicate non-here-doc contexts.
Thanks to Markus Triska for reporting this regression.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Unfortunately, I did not find the failing example for this old fix.
I also tweaked the code which was added by this commit:
"
Date: Mon Sep 24 18:30:02 2007 +0000
ash: fix prompt expansion (Natanael Copa <natanael.copa@gmail.com>)
"
since other parts of code do expect expandstr() to use DQSYNTAX, not PSSYNTAX.
function old new delta
parse_stream 2609 2634 +25
setprompt_if 128 133 +5
read_profile 32 37 +5
evalcommand 1334 1339 +5
expandstr 122 120 -2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/1 up/down: 40/-2) Total: 38 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 46 |
1 files changed, 27 insertions, 19 deletions
diff --git a/shell/ash.c b/shell/ash.c index 2bfec83e6..3184249f5 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2488,8 +2488,18 @@ putprompt(const char *s) #endif /* expandstr() needs parsing machinery, so it is far away ahead... */ -static const char *expandstr(const char *ps); +static const char *expandstr(const char *ps, int syntax_type); +/* Values for syntax param */ +#define BASESYNTAX 0 /* not in quotes */ +#define DQSYNTAX 1 /* in double quotes */ +#define SQSYNTAX 2 /* in single quotes */ +#define ARISYNTAX 3 /* in arithmetic */ +#define PSSYNTAX 4 /* prompt. never passed to SIT() */ +/* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */ +/* + * called by editline -- any expansions to the prompt should be added here. + */ static void setprompt_if(smallint do_set, int whichprompt) { @@ -2513,7 +2523,7 @@ setprompt_if(smallint do_set, int whichprompt) } #if ENABLE_ASH_EXPAND_PRMT pushstackmark(&smark, stackblocksize()); - putprompt(expandstr(prompt)); + putprompt(expandstr(prompt, PSSYNTAX)); popstackmark(&smark); #else putprompt(prompt); @@ -2838,13 +2848,6 @@ enum { /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF, * caller must ensure proper cast on it if c is *char_ptr! */ -/* Values for syntax param */ -#define BASESYNTAX 0 /* not in quotes */ -#define DQSYNTAX 1 /* in double quotes */ -#define SQSYNTAX 2 /* in single quotes */ -#define ARISYNTAX 3 /* in arithmetic */ -#define PSSYNTAX 4 /* prompt. never passed to SIT() */ - #if USE_SIT_FUNCTION static int @@ -9709,7 +9712,7 @@ evalcommand(union node *cmd, int flags) if (xflag) { const char *pfx = ""; - fdprintf(preverrout_fd, "%s", expandstr(ps4val())); + fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX)); sp = varlist.list; while (sp) { @@ -11522,6 +11525,15 @@ decode_dollar_squote(void) } #endif +/* Used by expandstr to get here-doc like behaviour. */ +#define FAKEEOFMARK ((char*)(uintptr_t)1) + +static ALWAYS_INLINE int +realeofmark(const char *eofmark) +{ + return eofmark && eofmark != FAKEEOFMARK; +} + /* * If eofmark is NULL, read a word or a redirection symbol. If eofmark * is not NULL, read a here document. In the latter case, eofmark is the @@ -11767,7 +11779,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) * we are at the end of the here document, this routine sets the c to PEOF. */ checkend: { - if (eofmark) { + if (realeofmark(eofmark)) { int markloc; char *p; @@ -12472,22 +12484,18 @@ parseheredoc(void) } -/* - * called by editline -- any expansions to the prompt should be added here. - */ static const char * -expandstr(const char *ps) +expandstr(const char *ps, int syntax_type) { union node n; int saveprompt; - /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value, - * and token processing _can_ alter it (delete NULs etc). */ + /* XXX Fix (char *) cast. */ setinputstring((char *)ps); saveprompt = doprompt; doprompt = 0; - readtoken1(pgetc(), PSSYNTAX, nullstr, 0); + readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0); doprompt = saveprompt; popfile(); @@ -13548,7 +13556,7 @@ procargs(char **argv) static void read_profile(const char *name) { - name = expandstr(name); + name = expandstr(name, DQSYNTAX); if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0) return; cmdloop(0); |