Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/bin/sh Fixes to shell expand (that is, $ stuff) from FreeBSD...
details: https://anonhg.NetBSD.org/src/rev/4d0317694ee7
branches: trunk
changeset: 824373:4d0317694ee7
user: kre <kre%NetBSD.org@localhost>
date: Sat Jun 03 10:31:16 2017 +0000
description:
Fixes to shell expand (that is, $ stuff) from FreeBSD (implemented
differently...)
In particular ${01} is now $1 not $0 (for ${0any-digits})
${4294967297} is most probably now ""
(unless you have a very large number of params)
it is no longer an alias for $1 (4294967297 & 0xFFFFFFFF) == 1
$(( expr $(( more )) stuff )) is no longer the same as
$(( expr (( more )) stuff )) which was sometimes OK, as in:
$(( 3 + $(( 2 - 1 )) * 3 ))
but not always as in:
$(( 1$((1 + 1))1 ))
which should be 121, but was an arith syntax error as
1((1 + 1))1
is meaningless.
Probably some more. This also sprinkles a little const, splits a big
func that had 2 (kind of unrelated) purposes into two simpler ones,
and avoids some (semi-dubious) modifications (and restores) in the input
string to insert \0's when they were needed.
diffstat:
bin/sh/expand.c | 374 ++++++++++++++++++++++++++++++++++-------------------
bin/sh/expand.h | 12 +-
bin/sh/memalloc.h | 3 +-
bin/sh/parser.c | 12 +-
4 files changed, 257 insertions(+), 144 deletions(-)
diffs (truncated from 830 to 300 lines):
diff -r dd62cbb3d407 -r 4d0317694ee7 bin/sh/expand.c
--- a/bin/sh/expand.c Sat Jun 03 10:27:05 2017 +0000
+++ b/bin/sh/expand.c Sat Jun 03 10:31:16 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: expand.c,v 1.106 2017/05/28 00:38:01 kre Exp $ */
+/* $NetBSD: expand.c,v 1.107 2017/06/03 10:31:16 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
#else
-__RCSID("$NetBSD: expand.c,v 1.106 2017/05/28 00:38:01 kre Exp $");
+__RCSID("$NetBSD: expand.c,v 1.107 2017/06/03 10:31:16 kre Exp $");
#endif
#endif /* not lint */
@@ -97,13 +97,15 @@
struct ifsregion *ifslastp; /* last struct in list */
struct arglist exparg; /* holds expanded arg list */
-STATIC void argstr(char *, int);
-STATIC char *exptilde(char *, int);
+STATIC const char *argstr(const char *, int);
+STATIC const char *exptilde(const char *, int);
STATIC void expbackq(union node *, int, int);
-STATIC int subevalvar(char *, char *, int, int, int, int, int);
-STATIC char *evalvar(char *, int);
-STATIC int varisset(char *, int);
-STATIC void varvalue(char *, int, int, int);
+STATIC const char *expari(const char *, int);
+STATIC int subevalvar(const char *, const char *, int, int, int);
+STATIC int subevalvar_trim(const char *, int, int, int, int, int);
+STATIC const char *evalvar(const char *, int);
+STATIC int varisset(const char *, int);
+STATIC void varvalue(const char *, int, int, int);
STATIC void recordregion(int, int, int);
STATIC void removerecordregions(int);
STATIC void ifsbreakup(char *, struct arglist *);
@@ -116,6 +118,7 @@
STATIC int patmatch(const char *, const char *, int);
STATIC char *cvtnum(int, char *);
static int collate_range_cmp(wchar_t, wchar_t);
+STATIC void add_args(struct strlist *);
/*
* Expand shell variables and backquotes inside a here document.
@@ -156,12 +159,16 @@
struct strlist *sp;
char *p;
+ if (fflag) /* no filename expandsion */
+ flag &= ~EXP_GLOB;
+
argbackq = arg->narg.backquote;
STARTSTACKSTR(expdest);
ifsfirst.next = NULL;
ifslastp = NULL;
argstr(arg->narg.text, flag);
if (arglist == NULL) {
+ STACKSTRNUL(expdest);
return; /* here document expanded */
}
STPUTC('\0', expdest);
@@ -170,11 +177,14 @@
/*
* TODO - EXP_REDIR
*/
- if (flag & EXP_FULL) {
+ if (flag & EXP_SPLIT) {
ifsbreakup(p, &exparg);
*exparg.lastp = NULL;
exparg.lastp = &exparg.list;
- expandmeta(exparg.list, flag);
+ if (flag & EXP_GLOB)
+ expandmeta(exparg.list, flag);
+ else
+ add_args(exparg.list);
} else {
if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
rmescapes(p);
@@ -195,35 +205,50 @@
/*
* Perform variable and command substitution.
- * If EXP_FULL is set, output CTLESC characters to allow for further processing.
+ * If EXP_GLOB is set, output CTLESC characters to allow for further processing.
+ * If EXP_SPLIT is set, remember location of result for later,
* Otherwise treat $@ like $* since no splitting will be performed.
*/
-STATIC void
-argstr(char *p, int flag)
+STATIC const char *
+argstr(const char *p, int flag)
{
char c;
- int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */
+ int quotes = flag & (EXP_GLOB | EXP_CASE | EXP_REDIR); /* do CTLESC */
int firsteq = 1;
const char *ifs = NULL;
int ifs_split = EXP_IFS_SPLIT;
+#ifdef DEBUG
+ const char *ed = expdest;
+#endif
if (flag & EXP_IFS_SPLIT)
ifs = ifsval();
+ VTRACE(DBG_EXPAND, ("argstr(\"%s\", %#x) quotes=%#x\n", p,flag,quotes));
+
if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
p = exptilde(p, flag);
for (;;) {
switch (c = *p++) {
case '\0':
+ VTRACE(DBG_EXPAND, ("argstr returning at \"\" "
+ "added \"%.*s\" to expdest (followed by: %2.2x)\n",
+ expdest-ed, ed, *expdest));
+ return p - 1;
case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */
- return;
+ case CTLENDARI: /* end of a $(( )) string */
+ VTRACE(DBG_EXPAND, ("argstr returning at \"%.6s\"..."
+ " after %2.2x; "
+ "added \"%.*s\" to expdest (followed by: %2.2x)\n",
+ p, p[-1]&0xff, expdest-ed, ed, *expdest));
+ return p;
case CTLQUOTEMARK:
/* "$@" syntax adherence hack */
if (p[0] == CTLVAR && p[1] & VSQUOTE &&
p[2] == '@' && p[3] == '=')
break;
- if ((flag & EXP_FULL) != 0)
+ if ((flag & EXP_SPLIT) != 0)
STPUTC(c, expdest);
ifs_split = 0;
break;
@@ -238,14 +263,23 @@
break;
case CTLVAR:
p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split));
+ VTRACE(DBG_EXPAND, ("argstr evalvar "
+ "added \"%.*s\" to expdest (followed by: %2.2x)\n",
+ expdest-ed, ed, *expdest));
break;
case CTLBACKQ:
case CTLBACKQ|CTLQUOTE:
expbackq(argbackq->n, c & CTLQUOTE, flag);
argbackq = argbackq->next;
+ VTRACE(DBG_EXPAND, ("argstr expbackq "
+ "added \"%.*s\" to expdest (followed by: %2.2x)\n",
+ expdest-ed, ed, *expdest));
break;
- case CTLENDARI:
- expari(flag);
+ case CTLARI:
+ p = expari(p, flag);
+ VTRACE(DBG_EXPAND, ("argstr expari "
+ "+ \"%.*s\" to dest (fwd by: %2.2x) p=\"%.5s...\"\n",
+ expdest-ed, ed, *expdest, p));
break;
case ':':
case '=':
@@ -276,18 +310,25 @@
}
}
-STATIC char *
-exptilde(char *p, int flag)
+STATIC const char *
+exptilde(const char *p, int flag)
{
- char c, *startp = p;
+ char c;
+ const char *startp = p;
struct passwd *pw;
const char *home;
- int quotes = flag & (EXP_FULL | EXP_CASE);
+ int quotes = flag & (EXP_GLOB | EXP_CASE);
+ char *user;
+ user = expdest; /* we will just borrow top of stack */
while ((c = *p) != '\0') {
switch(c) {
case CTLESC:
- return (startp);
+ case CTLVAR:
+ case CTLBACKQ:
+ case CTLBACKQ | CTLQUOTE:
+ case CTLARI:
+ case CTLENDARI:
case CTLQUOTEMARK:
return (startp);
case ':':
@@ -297,30 +338,27 @@
case '/':
goto done;
}
+ STPUTC(c, user);
p++;
}
-done:
- *p = '\0';
- if (*(startp+1) == '\0') {
- if ((home = lookupvar("HOME")) == NULL)
- goto lose;
- } else {
- if ((pw = getpwnam(startp+1)) == NULL)
- goto lose;
+ done:
+ STACKSTRNUL(user);
+ if (*expdest == '\0')
+ home = lookupvar("HOME");
+ else if ((pw = getpwnam(expdest)) == NULL)
+ home = NULL;
+ else
home = pw->pw_dir;
- }
- if (*home == '\0')
- goto lose;
- *p = c;
+ STUNSTR(user - expdest); /* return borrowed string space */
+
+ if (home == NULL || *home == '\0')
+ return startp;
while ((c = *home++) != '\0') {
if (quotes && SQSYNTAX[(int)c] == CCTL)
STPUTC(CTLESC, expdest);
STPUTC(c, expdest);
}
return (p);
-lose:
- *p = c;
- return (startp);
}
@@ -368,15 +406,18 @@
* Expand arithmetic expression. Backup to start of expression,
* evaluate, place result in (backed up) result, adjust string position.
*/
-void
-expari(int flag)
+STATIC const char *
+expari(const char *p, int flag)
{
- char *p, *q, *start;
+ char *q, *start;
intmax_t result;
int adjustment;
int begoff;
- int quotes = flag & (EXP_FULL | EXP_CASE);
+ int quotes = flag & (EXP_GLOB | EXP_CASE);
int quoted;
+#ifdef DEBUG
+ const char *ed = expdest;
+#endif
/* ifsfree(); */
@@ -400,46 +441,54 @@
* generate decimal, which takes (often) less digits (never more)
* so this is safe, if occasionally slightly wasteful.
*/
-#define SPACE_NEEDED ((sizeof(intmax_t) * CHAR_BIT + 2) / 3 + 2)
+#define SPACE_NEEDED ((int)((sizeof(intmax_t) * CHAR_BIT + 2) / 3 + 2))
/*
* Only need check for SPACE_NEEDED-2 as we have already
* consumed (but will overwrite) 2 chars, the CTLARI, and the
* flags (quoting) byte (if those had not already been seen,
* we would not be here.)
*/
- CHECKSTRSPACE((int)(SPACE_NEEDED - 2), expdest);
- USTPUTC('\0', expdest);
- start = stackblock();
- p = expdest - 1;
- while (*p != CTLARI && p >= start)
- --p;
- if (*p != CTLARI)
- error("missing CTLARI (shouldn't happen)");
- if (p > start && *(p-1) == CTLESC)
- for (p = start; *p != CTLARI; p++)
- if (*p == CTLESC)
- p++;
-
- if (p[1] == '"')
- quoted=1;
- else
- quoted=0;
- begoff = p - start;
+ quoted = *p++ == '"';
+ begoff = expdest - stackblock();
+ VTRACE(DBG_EXPAND, ("expari: '%c' \"%s\" begoff %d\n", p[-1],p,begoff));
+ p = argstr(p, 0); /* expand $(( )) string */
+ STPUTC('\0', expdest);
+ start = stackblock() + begoff;
+ VTRACE(DBG_EXPAND, ("expari: argstr added: '%s' start: \"%.8s\"\n",
+ ed, start));
Home |
Main Index |
Thread Index |
Old Index