From owner-svn-src-all@freebsd.org Thu Dec 31 18:47:56 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 496BEA56FBD; Thu, 31 Dec 2015 18:47:56 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 23AC61B48; Thu, 31 Dec 2015 18:47:56 +0000 (UTC) (envelope-from jilles@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tBVIltMO007471; Thu, 31 Dec 2015 18:47:55 GMT (envelope-from jilles@FreeBSD.org) Received: (from jilles@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tBVIltHT007469; Thu, 31 Dec 2015 18:47:55 GMT (envelope-from jilles@FreeBSD.org) Message-Id: <201512311847.tBVIltHT007469@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jilles set sender to jilles@FreeBSD.org using -f From: Jilles Tjoelker Date: Thu, 31 Dec 2015 18:47:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292994 - head/bin/sh X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Dec 2015 18:47:56 -0000 Author: jilles Date: Thu Dec 31 18:47:54 2015 New Revision: 292994 URL: https://svnweb.freebsd.org/changeset/base/292994 Log: sh: Perform pathname generation during the first expansion phases. This avoids the need to add and remove CTLESC bytes if pathname generation will not be performed (set -f). Side effect: the order of operations is slightly different: pathname generation in ${$+* $(CMD)} will not see filesystem changes from CMD. Modified: head/bin/sh/expand.c head/bin/sh/expand.h Modified: head/bin/sh/expand.c ============================================================================== --- head/bin/sh/expand.c Thu Dec 31 18:29:24 2015 (r292993) +++ head/bin/sh/expand.c Thu Dec 31 18:47:54 2015 (r292994) @@ -84,7 +84,7 @@ __FBSDID("$FreeBSD$"); enum wordstate { WORD_IDLE, WORD_WS_DELIMITED, WORD_QUOTEMARK }; struct worddest { - struct arglist list; + struct arglist *list; enum wordstate state; }; @@ -102,7 +102,7 @@ static int varisset(const char *, int); static void strtodest(const char *, int, int, int, struct worddest *); static void reprocess(int, int, int, int, struct worddest *); static void varvalue(const char *, int, int, int, struct worddest *); -static void expandmeta(struct arglist *, struct arglist *); +static void expandmeta(char *, struct arglist *); static void expmeta(char *, char *, struct arglist *); static int expsortcmp(const void *, const void *); static int patmatch(const char *, const char *); @@ -162,7 +162,7 @@ stputs_quotes(const char *data, const ch #define STPUTS_QUOTES(data, syntax, p) p = stputs_quotes((data), syntax, p) static char * -nextword(char c, char *p, struct worddest *dst) +nextword(char c, int flag, char *p, struct worddest *dst) { int is_ws; @@ -170,20 +170,23 @@ nextword(char c, char *p, struct worddes if (p != stackblock() || (is_ws ? dst->state == WORD_QUOTEMARK : dst->state != WORD_WS_DELIMITED) || c == '\0') { STPUTC('\0', p); - appendarglist(&dst->list, grabstackstr(p)); + if (flag & EXP_GLOB) + expandmeta(grabstackstr(p), dst->list); + else + appendarglist(dst->list, grabstackstr(p)); dst->state = is_ws ? WORD_WS_DELIMITED : WORD_IDLE; } else if (!is_ws && dst->state == WORD_WS_DELIMITED) dst->state = WORD_IDLE; /* Reserve space while the stack string is empty. */ - appendarglist(&dst->list, NULL); - dst->list.count--; + appendarglist(dst->list, NULL); + dst->list->count--; STARTSTACKSTR(p); return p; } -#define NEXTWORD(c, p, dstlist) p = nextword(c, p, dstlist) +#define NEXTWORD(c, flag, p, dstlist) p = nextword(c, flag, p, dstlist) static char * -stputs_split(const char *data, const char *syntax, char *p, +stputs_split(const char *data, const char *syntax, int flag, char *p, struct worddest *dst) { const char *ifs; @@ -194,16 +197,16 @@ stputs_split(const char *data, const cha CHECKSTRSPACE(2, p); c = *data++; if (strchr(ifs, c) != NULL) { - NEXTWORD(c, p, dst); + NEXTWORD(c, flag, p, dst); continue; } - if (syntax[(int)c] == CCTL) + if (flag & EXP_GLOB && syntax[(int)c] == CCTL) USTPUTC(CTLESC, p); USTPUTC(c, p); } return (p); } -#define STPUTS_SPLIT(data, syntax, p, dst) p = stputs_split((data), syntax, p, dst) +#define STPUTS_SPLIT(data, syntax, flag, p, dst) p = stputs_split((data), syntax, flag, p, dst) /* * Perform expansions on an argument, placing the resulting list of arguments @@ -222,8 +225,10 @@ expandarg(union node *arg, struct arglis { struct worddest exparg; + if (fflag) + flag &= ~EXP_GLOB; argbackq = arg->narg.backquote; - emptyarglist(&exparg.list); + exparg.list = arglist; exparg.state = WORD_IDLE; STARTSTACKSTR(expdest); argstr(arg->narg.text, flag, &exparg); @@ -231,15 +236,17 @@ expandarg(union node *arg, struct arglis STACKSTRNUL(expdest); return; /* here document expanded */ } - if ((flag & EXP_FULL) == 0 || expdest != stackblock() || + if ((flag & EXP_SPLIT) == 0 || expdest != stackblock() || exparg.state == WORD_QUOTEMARK) { STPUTC('\0', expdest); - if (flag & EXP_FULL) - appendarglist(&exparg.list, grabstackstr(expdest)); + if (flag & EXP_SPLIT) { + if (flag & EXP_GLOB) + expandmeta(grabstackstr(expdest), exparg.list); + else + appendarglist(exparg.list, grabstackstr(expdest)); + } } - if (flag & EXP_FULL) - expandmeta(&exparg.list, arglist); - else + if ((flag & EXP_SPLIT) == 0) appendarglist(arglist, grabstackstr(expdest)); } @@ -250,16 +257,16 @@ expandarg(union node *arg, struct arglis * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE. * Processing ends at a CTLENDVAR or CTLENDARI character as well as '\0'. * This is used to expand word in ${var+word} etc. - * If EXP_FULL or EXP_CASE are set, keep and/or generate CTLESC + * If EXP_GLOB or EXP_CASE are set, keep and/or generate CTLESC * characters to allow for further processing. * - * If EXP_FULL is set, dst receives any complete words produced. + * If EXP_SPLIT is set, dst receives any complete words produced. */ static char * argstr(char *p, int flag, struct worddest *dst) { char c; - int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ + int quotes = flag & (EXP_GLOB | EXP_CASE); /* do CTLESC */ int firsteq = 1; int split_lit; int lit_quoted; @@ -283,7 +290,7 @@ argstr(char *p, int flag, struct worddes if (p[0] == CTLVAR && (p[1] & VSQUOTE) != 0 && p[2] == '@' && p[3] == '=') break; - if ((flag & EXP_FULL) != 0 && expdest == stackblock()) + if ((flag & EXP_SPLIT) != 0 && expdest == stackblock()) dst->state = WORD_QUOTEMARK; break; case CTLQUOTEEND: @@ -293,7 +300,7 @@ argstr(char *p, int flag, struct worddes c = *p++; if (split_lit && !lit_quoted && strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, expdest, dst); + NEXTWORD(c, flag, expdest, dst); break; } if (quotes) @@ -319,7 +326,7 @@ argstr(char *p, int flag, struct worddes */ if (split_lit && !lit_quoted && strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, expdest, dst); + NEXTWORD(c, flag, expdest, dst); break; } USTPUTC(c, expdest); @@ -333,7 +340,7 @@ argstr(char *p, int flag, struct worddes default: if (split_lit && !lit_quoted && strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) { - NEXTWORD(c, expdest, dst); + NEXTWORD(c, flag, expdest, dst); break; } USTPUTC(c, expdest); @@ -438,7 +445,7 @@ expbackq(union node *cmd, int quoted, in struct nodelist *saveargbackq; char lastc; char const *syntax = quoted? DQSYNTAX : BASESYNTAX; - int quotes = flag & (EXP_FULL | EXP_CASE); + int quotes = flag & (EXP_GLOB | EXP_CASE); size_t nnl; const char *ifs; @@ -452,7 +459,7 @@ expbackq(union node *cmd, int quoted, in p = in.buf; lastc = '\0'; nnl = 0; - if (!quoted && flag & EXP_FULL) + if (!quoted && flag & EXP_SPLIT) ifs = ifsset() ? ifsval() : " \t\n"; else ifs = ""; @@ -476,7 +483,7 @@ expbackq(union node *cmd, int quoted, in } else { if (nnl > 0) { if (strchr(ifs, '\n') != NULL) { - NEXTWORD('\n', dest, dst); + NEXTWORD('\n', flag, dest, dst); nnl = 0; } else { CHECKSTRSPACE(nnl + 2, dest); @@ -487,7 +494,7 @@ expbackq(union node *cmd, int quoted, in } } if (strchr(ifs, lastc) != NULL) - NEXTWORD(lastc, dest, dst); + NEXTWORD(lastc, flag, dest, dst); else { CHECKSTRSPACE(2, dest); if (quotes && syntax[(int)lastc] == CCTL) @@ -743,7 +750,7 @@ again: /* jump here after setting a vari case VSPLUS: case VSMINUS: if (!set) { - argstr(p, flag | (flag & EXP_FULL ? EXP_SPLIT_LIT : 0) | + argstr(p, flag | (flag & EXP_SPLIT ? EXP_SPLIT_LIT : 0) | (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0), dst); break; } @@ -763,7 +770,7 @@ again: /* jump here after setting a vari patloc = expdest - stackblock(); subevalvar_trim(p, patloc, subtype, startloc); reprocess(startloc, flag, VSNORMAL, varflags & VSQUOTE, dst); - if (flag & EXP_FULL && *var == '@' && varflags & VSQUOTE) + if (flag & EXP_SPLIT && *var == '@' && varflags & VSQUOTE) dst->state = WORD_QUOTEMARK; break; @@ -860,9 +867,9 @@ strtodest(const char *p, int flag, int s subtype == VSTRIMLEFTMAX || subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX) STPUTS(p, expdest); - else if (flag & EXP_FULL && !quoted && dst != NULL) - STPUTS_SPLIT(p, BASESYNTAX, expdest, dst); - else if (flag & (EXP_FULL | EXP_CASE)) + else if (flag & EXP_SPLIT && !quoted && dst != NULL) + STPUTS_SPLIT(p, BASESYNTAX, flag, expdest, dst); + else if (flag & (EXP_GLOB | EXP_CASE)) STPUTS_QUOTES(p, quoted ? DQSYNTAX : BASESYNTAX, expdest); else STPUTS(p, expdest); @@ -902,8 +909,8 @@ reprocess(int startloc, int flag, int su zpos += zlen + 1; if (zpos == len + 1) break; - if (flag & EXP_FULL && (quoted || (zlen > 0 && zpos < len))) - NEXTWORD('\0', expdest, dst); + if (flag & EXP_SPLIT && (quoted || (zlen > 0 && zpos < len))) + NEXTWORD('\0', flag, expdest, dst); } } @@ -951,14 +958,15 @@ varvalue(const char *name, int quoted, i strtodest(buf, flag, subtype, quoted, dst); return; case '@': - if (flag & EXP_FULL && quoted) { + if (flag & EXP_SPLIT && quoted) { for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { strtodest(p, flag, subtype, quoted, dst); if (*ap) { if (splitlater) STPUTC('\0', expdest); else - NEXTWORD('\0', expdest, dst); + NEXTWORD('\0', flag, expdest, + dst); } } if (shellparam.nparam > 0) @@ -978,11 +986,11 @@ varvalue(const char *name, int quoted, i break; if (sep[0]) strtodest(sep, flag, subtype, quoted, dst); - else if (flag & EXP_FULL && !quoted && **ap != '\0') { + else if (flag & EXP_SPLIT && !quoted && **ap != '\0') { if (splitlater) STPUTC('\0', expdest); else - NEXTWORD('\0', expdest, dst); + NEXTWORD('\0', flag, expdest, dst); } } return; @@ -1014,40 +1022,34 @@ static char expdir[PATH_MAX]; * The results are stored in the list dstlist. */ static void -expandmeta(struct arglist *srclist, struct arglist *dstlist) +expandmeta(char *pattern, struct arglist *dstlist) { char *p; int firstmatch; - int i; char c; - for (i = 0; i < srclist->count; i++) { firstmatch = dstlist->count; - if (!fflag) { - p = srclist->args[i]; + p = pattern; for (; (c = *p) != '\0'; p++) { /* fast check for meta chars */ if (c == '*' || c == '?' || c == '[') { INTOFF; - expmeta(expdir, srclist->args[i], - dstlist); + expmeta(expdir, pattern, dstlist); INTON; break; } } - } if (dstlist->count == firstmatch) { /* * no matches */ - rmescapes(srclist->args[i]); - appendarglist(dstlist, srclist->args[i]); + rmescapes(pattern); + appendarglist(dstlist, pattern); } else { qsort(&dstlist->args[firstmatch], dstlist->count - firstmatch, sizeof(dstlist->args[0]), expsortcmp); } - } } Modified: head/bin/sh/expand.h ============================================================================== --- head/bin/sh/expand.h Thu Dec 31 18:29:24 2015 (r292993) +++ head/bin/sh/expand.h Thu Dec 31 18:47:54 2015 (r292994) @@ -43,12 +43,15 @@ 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_CASE 0x10 /* keeps quotes around for CASE pattern */ #define EXP_SPLIT_LIT 0x20 /* IFS split literal text ${v+-a b c} */ #define EXP_LIT_QUOTED 0x40 /* for EXP_SPLIT_LIT, start off quoted */ +#define EXP_GLOB 0x80 /* perform file globbing */ + +#define EXP_FULL (EXP_SPLIT | EXP_GLOB) void emptyarglist(struct arglist *);