@@ -119,7 +119,7 @@ STATIC const char *subevalvar(char *, char *, int, int, int, int, int);
STATIC char *evalvar(char *, int);
STATIC size_t strtodest(const char *, const char *, int);
STATIC void memtodest(const char *, size_t, const char *, int);
-STATIC ssize_t varvalue(char *, int, int, int *);
+STATIC ssize_t varvalue(char *, int, int, int);
STATIC void expandmeta(struct strlist *, int);
#ifdef HAVE_GLOB
STATIC void addglob(const glob_t *);
@@ -712,7 +712,6 @@ evalvar(char *p, int flag)
int c;
int startloc;
ssize_t varlen;
- int easy;
int quoted;
varflags = *p++;
@@ -723,12 +722,11 @@ evalvar(char *p, int flag)
quoted = flag & EXP_QUOTED;
var = p;
- easy = (!quoted || (*var == '@' && shellparam.nparam));
startloc = expdest - (char *)stackblock();
p = strchr(p, '=') + 1;
again:
- varlen = varvalue(var, varflags, flag, "ed);
+ varlen = varvalue(var, varflags, flag, quoted);
if (varflags & VSNUL)
varlen--;
@@ -771,8 +769,11 @@ vsplus:
if (subtype == VSNORMAL) {
record:
- if (!easy)
- goto end;
+ if (quoted) {
+ quoted = *var == '@' && shellparam.nparam;
+ if (!quoted)
+ goto end;
+ }
recordregion(startloc, expdest - (char *)stackblock(), quoted);
goto end;
}
@@ -878,7 +879,7 @@ strtodest(p, syntax, quotes)
*/
STATIC ssize_t
-varvalue(char *name, int varflags, int flags, int *quotedp)
+varvalue(char *name, int varflags, int flags, int quoted)
{
int num;
char *p;
@@ -887,11 +888,11 @@ varvalue(char *name, int varflags, int flags, int *quotedp)
char sepc;
char **ap;
char const *syntax;
- int quoted = *quotedp;
int subtype = varflags & VSTYPE;
int discard = subtype == VSPLUS || subtype == VSLENGTH;
int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
ssize_t len = 0;
+ char c;
sep = (flags & EXP_FULL) << CHAR_BIT;
syntax = quoted ? DQSYNTAX : BASESYNTAX;
@@ -928,12 +929,25 @@ numvar:
goto param;
/* fall through */
case '*':
- if (quoted)
- sep = 0;
- sep |= ifsset() ? ifsval()[0] : ' ';
+ /* We will set c to 0 or ~0 depending on whether
+ * we're doing field splitting. We won't do field
+ * splitting if either we're quoted or sep is zero.
+ *
+ * Instead of testing (quoted || !sep) the following
+ * trick optimises away any branches by using the
+ * fact that EXP_QUOTED (which is the only bit that
+ * can be set in quoted) is the same as EXP_FULL <<
+ * CHAR_BIT (which is the only bit that can be set
+ * in sep).
+ */
+#if EXP_QUOTED >> CHAR_BIT != EXP_FULL
+#error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
+#endif
+ c = !((quoted | ~sep) & EXP_QUOTED) - 1;
+ sep &= ~quoted;
+ sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
param:
sepc = sep;
- *quotedp = !sepc;
if (!(ap = shellparam.p))
return -1;
while ((p = *ap++)) {