Module Name: src Committed By: kre Date: Sat Jun 3 10:31:16 UTC 2017
Modified Files: src/bin/sh: expand.c expand.h memalloc.h parser.c Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.106 -r1.107 src/bin/sh/expand.c cvs rdiff -u -r1.21 -r1.22 src/bin/sh/expand.h cvs rdiff -u -r1.15 -r1.16 src/bin/sh/memalloc.h cvs rdiff -u -r1.130 -r1.131 src/bin/sh/parser.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/bin/sh/expand.c diff -u src/bin/sh/expand.c:1.106 src/bin/sh/expand.c:1.107 --- src/bin/sh/expand.c:1.106 Sun May 28 00:38:01 2017 +++ src/bin/sh/expand.c Sat Jun 3 10:31:16 2017 @@ -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 ifsfirst; /* first stru 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 struct strlist *msort(struct strl 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 @@ expandarg(union node *arg, struct arglis 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 @@ expandarg(union node *arg, struct arglis /* * 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 @@ expandarg(union node *arg, struct arglis /* * 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 @@ argstr(char *p, int flag) 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 @@ argstr(char *p, int flag) } } -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 @@ exptilde(char *p, int flag) 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 @@ removerecordregions(int endoff) * 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 @@ expari(int flag) * 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)); removerecordregions(begoff); if (quotes) - rmescapes(p+2); + rmescapes(start); /* should be a no-op */ q = grabstackstr(expdest); - result = arith(p+2); + result = arith(start); + VTRACE(DBG_EXPAND, ("expari: after arith: result=%jd '%s' q@'%.3s'\n", + result, ed, q)); ungrabstackstr(q, expdest); - fmtstr(p, SPACE_NEEDED, "%"PRIdMAX, result); - while (*p++) + start = stackblock() + begoff; + adjustment = expdest - start; + VTRACE(DBG_EXPAND, ("expari: removing %d ", adjustment)); + STADJUST(-adjustment, expdest); /* remove the argstr() */ + VTRACE(DBG_EXPAND, ("ed \"%.*s\", expdest \"%s\"\n", + expdest-ed, ed, expdest)); + + CHECKSTRSPACE(SPACE_NEEDED, expdest); + fmtstr(expdest, SPACE_NEEDED, "%"PRIdMAX, result); + VTRACE(DBG_EXPAND, ("expari: after fmtstr: ed \"%s\" expdest \"%s\"\n", + ed, expdest)); + + for (q = expdest; *q++ != '\0'; ) ; - if (quoted == 0) - recordregion(begoff, p - 1 - start, 0); - adjustment = expdest - p + 1; + if (quoted == 0) /* allow weird splitting */ + recordregion(begoff, q - 1 - start, 0); + adjustment = expdest - q + 1; STADJUST(-adjustment, expdest); + VTRACE(DBG_EXPAND, ("expari: adding %d ed \"%.*s\", " + "expdest \"%s\" returning \"%.5s...\"\n", -adjustment, expdest-ed, + ed, expdest, p)); + + return p; } @@ -461,7 +510,7 @@ expbackq(union node *cmd, int quoted, in int startloc = dest - stackblock(); char const *syntax = quoted? DQSYNTAX : BASESYNTAX; int saveherefd; - int quotes = flag & (EXP_FULL | EXP_CASE); + int quotes = flag & (EXP_GLOB | EXP_CASE); int nnl; INTOFF; @@ -527,37 +576,21 @@ expbackq(union node *cmd, int quoted, in } - STATIC int -subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes) +subevalvar(const char *p, const char *str, int subtype, int startloc, + int varflags) { char *startp; - char *loc = NULL; - char *q; - int c = 0; int saveherefd = herefd; struct nodelist *saveargbackq = argbackq; - int amount, how; + int amount; herefd = -1; - switch (subtype) { - case VSTRIMLEFT: - case VSTRIMLEFTMAX: - case VSTRIMRIGHT: - case VSTRIMRIGHTMAX: - how = (varflags & (VSQUOTE|VSPATQ)) == VSQUOTE ? 0 : EXP_CASE; - break; - default: - how = 0; - break; - } - argstr(p, how); + argstr(p, EXP_TILDE); STACKSTRNUL(expdest); herefd = saveherefd; argbackq = saveargbackq; startp = stackblock() + startloc; - if (str == NULL) - str = stackblock() + strloc; switch (subtype) { case VSASSIGN: @@ -578,6 +611,44 @@ subevalvar(char *p, char *str, int strlo : nullstr); /* NOTREACHED */ + default: + abort(); + } +} + +STATIC int +subevalvar_trim(const char *p, int strloc, int subtype, int startloc, + int varflags, int quotes) +{ + char *startp; + char *str; + char *loc = NULL; + char *q; + int c = 0; + int saveherefd = herefd; + struct nodelist *saveargbackq = argbackq; + int amount; + + herefd = -1; + switch (subtype) { + case VSTRIMLEFT: + case VSTRIMLEFTMAX: + case VSTRIMRIGHT: + case VSTRIMRIGHTMAX: + break; + default: + abort(); + break; + } + argstr(p, (varflags & (VSQUOTE|VSPATQ)) == VSQUOTE ? 0 : EXP_CASE); + STACKSTRNUL(expdest); + herefd = saveherefd; + argbackq = saveargbackq; + startp = stackblock() + startloc; + str = stackblock() + strloc; + + switch (subtype) { + case VSTRIMLEFT: for (loc = startp; loc < str; loc++) { c = *loc; @@ -660,12 +731,12 @@ recordright: * input string. */ -STATIC char * -evalvar(char *p, int flag) +STATIC const char * +evalvar(const char *p, int flag) { int subtype; int varflags; - char *var; + const char *var; char *val; int patloc; int c; @@ -674,7 +745,7 @@ evalvar(char *p, int flag) int startloc; int varlen; int apply_ifs; - int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); + int quotes = flag & (EXP_GLOB | EXP_CASE | EXP_REDIR); varflags = (unsigned char)*p++; subtype = varflags & VSTYPE; @@ -682,12 +753,11 @@ evalvar(char *p, int flag) special = !is_name(*p); p = strchr(p, '=') + 1; -again: /* jump here after setting a variable with ${var=text} */ + again: /* jump here after setting a variable with ${var=text} */ if (varflags & VSLINENO) { set = 1; - special = 0; - val = var; - p[-1] = '\0'; + special = p - var; + val = NULL; } else if (special) { set = varisset(var, varflags & VSNUL); val = NULL; @@ -720,7 +790,19 @@ again: /* jump here after setting a vari if (set && subtype != VSPLUS) { /* insert the value of the variable */ if (special) { - varvalue(var, varflags & VSQUOTE, subtype, flag); + if (varflags & VSLINENO) { + /* + * The LINENO hack + */ + while (--special > 0) { +/* not needed, it is a number... + if (quotes && syntax[(int)*var] == CCTL) + STPUTC(CTLESC, expdest); +*/ + STPUTC(*var++, expdest); + } + } else + varvalue(var, varflags&VSQUOTE, subtype, flag); if (subtype == VSLENGTH) { varlen = expdest - stackblock() - startloc; STADJUST(-varlen, expdest); @@ -798,8 +880,8 @@ again: /* jump here after setting a vari */ STPUTC('\0', expdest); patloc = expdest - stackblock(); - if (subevalvar(p, NULL, patloc, subtype, - startloc, varflags, quotes) == 0) { + if (subevalvar_trim(p, patloc, subtype, startloc, varflags, + quotes) == 0) { int amount = (expdest - stackblock() - patloc) + 1; STADJUST(-amount, expdest); } @@ -812,7 +894,9 @@ again: /* jump here after setting a vari case VSQUESTION: if (set) break; - if (subevalvar(p, var, 0, subtype, startloc, varflags, quotes)) { + if (subevalvar(p, var, subtype, startloc, varflags)) { + /* if subevalvar() returns, it always returns 1 */ + varflags &= ~VSNUL; /* * Remove any recorded regions beyond @@ -827,7 +911,9 @@ again: /* jump here after setting a vari default: abort(); } +#if 0 p[-1] = '='; /* recover overwritten '=' */ +#endif if (apply_ifs) recordregion(startloc, expdest - stackblock(), @@ -860,7 +946,7 @@ again: /* jump here after setting a vari */ STATIC int -varisset(char *name, int nulok) +varisset(const char *name, int nulok) { if (*name == '!') return backgndpid != -1; @@ -880,11 +966,10 @@ varisset(char *name, int nulok) char *ap; int num = atoi(name); - if (num > shellparam.nparam) - return 0; - if (num == 0) ap = arg0; + else if (num > shellparam.nparam) + return 0; else ap = shellparam.p[num - 1]; @@ -901,7 +986,7 @@ varisset(char *name, int nulok) */ STATIC void -varvalue(char *name, int quoted, int subtype, int flag) +varvalue(const char *name, int quoted, int subtype, int flag) { int num; char *p; @@ -910,9 +995,12 @@ varvalue(char *name, int quoted, int sub char **ap; char const *syntax; + if (subtype == VSLENGTH) /* no magic required ... */ + flag &= ~EXP_FULL; + #define STRTODEST(p) \ do {\ - if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \ + if (flag & (EXP_GLOB | EXP_CASE) && subtype != VSLENGTH) { \ syntax = quoted? DQSYNTAX : BASESYNTAX; \ while (*p) { \ if (syntax[(int)*p] == CCTL) \ @@ -928,33 +1016,31 @@ varvalue(char *name, int quoted, int sub switch (*name) { case '$': num = rootpid; - goto numvar; + break; case '?': num = exitstatus; - goto numvar; + break; case '#': num = shellparam.nparam; - goto numvar; + break; case '!': num = backgndpid; -numvar: - expdest = cvtnum(num, expdest); break; case '-': for (i = 0; i < option_flags; i++) { if (optlist[optorder[i]].val) STPUTC(optlist[optorder[i]].letter, expdest); } - break; + return; case '@': - if (flag & EXP_FULL && quoted) { + if (flag & EXP_SPLIT && quoted) { for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { STRTODEST(p); if (*ap) /* A NUL separates args inside "" */ STPUTC('\0', expdest); } - break; + return; } /* fall through */ case '*': @@ -965,25 +1051,34 @@ numvar: break; if (sep) STPUTC(sep, expdest); - else if ((flag & (EXP_FULL|EXP_IN_QUOTES)) == EXP_FULL + else if ((flag & (EXP_SPLIT|EXP_IN_QUOTES)) == EXP_SPLIT && !quoted && **ap != '\0') STPUTC('\0', expdest); } - break; - case '0': - p = arg0; - STRTODEST(p); - break; + return; default: if (is_digit(*name)) { - num = atoi(name); - if (num > 0 && num <= shellparam.nparam) { - p = shellparam.p[num - 1]; - STRTODEST(p); - } + long lnum; + + errno = 0; + lnum = strtol(name, &p, 10); + if (errno != 0 || (*p != '\0' && *p != '=')) + return; + + if (lnum == 0) + p = arg0; + else if (lnum > 0 && lnum <= shellparam.nparam) + p = shellparam.p[lnum - 1]; + else + return; + STRTODEST(p); } - break; + return; } + /* + * only the specials with an int value arrive here + */ + expdest = cvtnum(num, expdest); } @@ -1157,8 +1252,6 @@ expandmeta(struct strlist *str, int flag /* TODO - EXP_REDIR */ while (str) { - if (fflag) - goto nometa; p = str->text; for (;;) { /* fast check for meta chars */ if ((c = *p++) == '\0') @@ -1181,7 +1274,7 @@ expandmeta(struct strlist *str, int flag /* * no matches */ -nometa: + nometa: *exparg.lastp = str; rmescapes(str->text); exparg.lastp = &str->next; @@ -1196,6 +1289,17 @@ nometa: } } +STATIC void +add_args(struct strlist *str) +{ + while (str) { + *exparg.lastp = str; + rmescapes(str->text); + exparg.lastp = &str->next; + str = str->next; + } +} + /* * Do metacharacter (i.e. *, ?, [...]) expansion. @@ -1641,7 +1745,7 @@ casematch(union node *pattern, char *val } /* - * Our own itoa(). + * Our own itoa(). Assumes result buffer is on the stack */ STATIC char * @@ -1649,13 +1753,15 @@ cvtnum(int num, char *buf) { char temp[32]; int neg = num < 0; - char *p = temp + 31; + char *p = temp + sizeof temp - 1; - temp[31] = '\0'; + if (neg) + num = -num; + *p = '\0'; do { *--p = num % 10 + '0'; - } while ((num /= 10) != 0); + } while ((num /= 10) != 0 && p > temp + 1); if (neg) *--p = '-'; Index: src/bin/sh/expand.h diff -u src/bin/sh/expand.h:1.21 src/bin/sh/expand.h:1.22 --- src/bin/sh/expand.h:1.21 Wed Apr 26 17:43:33 2017 +++ src/bin/sh/expand.h Sat Jun 3 10:31:16 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: expand.h,v 1.21 2017/04/26 17:43:33 christos Exp $ */ +/* $NetBSD: expand.h,v 1.22 2017/06/03 10:31:16 kre Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -50,18 +50,20 @@ struct arglist { /* * expandarg() flags */ -#define EXP_FULL 0x1 /* perform word splitting & file globbing */ +#define EXP_SPLIT 0x1 /* perform word splitting */ #define EXP_TILDE 0x2 /* do normal tilde expansion */ -#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ -#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ +#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ +#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ #define EXP_IFS_SPLIT 0x20 /* need to record arguments for ifs breakup */ #define EXP_IN_QUOTES 0x40 /* don't set EXP_IFS_SPLIT again */ +#define EXP_GLOB 0x80 /* perform filename globbing */ +#define EXP_FULL (EXP_SPLIT | EXP_GLOB) union node; + void expandhere(union node *, int); void expandarg(union node *, struct arglist *, int); -void expari(int); void rmescapes(char *); int casematch(union node *, char *); Index: src/bin/sh/memalloc.h diff -u src/bin/sh/memalloc.h:1.15 src/bin/sh/memalloc.h:1.16 --- src/bin/sh/memalloc.h:1.15 Fri Feb 15 17:26:06 2008 +++ src/bin/sh/memalloc.h Sat Jun 3 10:31:16 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: memalloc.h,v 1.15 2008/02/15 17:26:06 matt Exp $ */ +/* $NetBSD: memalloc.h,v 1.16 2017/06/03 10:31:16 kre Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -72,6 +72,7 @@ void ungrabstackstr(char *, char *); #define STUNPUTC(p) (++sstrnleft, --p) #define STTOPC(p) p[-1] #define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount)) +#define STUNSTR(amount) (sstrnleft -= (amount)) #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft) #define ckfree(p) free((pointer)(p)) Index: src/bin/sh/parser.c diff -u src/bin/sh/parser.c:1.130 src/bin/sh/parser.c:1.131 --- src/bin/sh/parser.c:1.130 Mon May 29 10:43:27 2017 +++ src/bin/sh/parser.c Sat Jun 3 10:31:16 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: parser.c,v 1.130 2017/05/29 10:43:27 kre Exp $ */ +/* $NetBSD: parser.c,v 1.131 2017/06/03 10:31:16 kre Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; #else -__RCSID("$NetBSD: parser.c,v 1.130 2017/05/29 10:43:27 kre Exp $"); +__RCSID("$NetBSD: parser.c,v 1.131 2017/06/03 10:31:16 kre Exp $"); #endif #endif /* not lint */ @@ -1903,6 +1903,7 @@ parsesub: { */ parsearith: { +#if 0 if (syntax == ARISYNTAX) { /* * we collapse embedded arithmetic expansion to @@ -1915,10 +1916,12 @@ parsearith: { * two closing ))'s to follow later. */ parenlevel += 2; - } else { + } else +#endif + { TS_PUSH(); syntax = ARISYNTAX; - ++arinest; + arinest = 1; varnest = 0; USTPUTC(CTLARI, out); @@ -1926,6 +1929,7 @@ parsearith: { USTPUTC('"',out); else USTPUTC(' ',out); + } goto parsearith_return; }