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