From owner-svn-src-head@FreeBSD.ORG Sun Mar 2 22:59:35 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 60DA0B38; Sun, 2 Mar 2014 22:59:35 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4DA7412DF; Sun, 2 Mar 2014 22:59:35 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s22MxZrW017093; Sun, 2 Mar 2014 22:59:35 GMT (envelope-from jilles@svn.freebsd.org) Received: (from jilles@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s22MxZim017092; Sun, 2 Mar 2014 22:59:35 GMT (envelope-from jilles@svn.freebsd.org) Message-Id: <201403022259.s22MxZim017092@svn.freebsd.org> From: Jilles Tjoelker Date: Sun, 2 Mar 2014 22:59:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r262697 - 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-head@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Mar 2014 22:59:35 -0000 Author: jilles Date: Sun Mar 2 22:59:34 2014 New Revision: 262697 URL: http://svnweb.freebsd.org/changeset/base/262697 Log: sh: Simplify expari(). Redo expari() like evalvar(). This makes the logic more understandable and avoids possible problems if arithmetic expansion occurs if CTLESC characters are not generated (looking backwards for CTLARI is not generally possible in that case but the old code tried anyway). This adds an extra argstr() recursion. Modified: head/bin/sh/expand.c Modified: head/bin/sh/expand.c ============================================================================== --- head/bin/sh/expand.c Sun Mar 2 21:25:32 2014 (r262696) +++ head/bin/sh/expand.c Sun Mar 2 22:59:34 2014 (r262697) @@ -100,7 +100,7 @@ static struct arglist exparg; /* holds static void argstr(char *, int); static char *exptilde(char *, int); -static void expari(int); +static char *expari(char *); static void expbackq(union node *, int, int); static int subevalvar(char *, char *, int, int, int, int, int); static char *evalvar(char *, int); @@ -207,7 +207,7 @@ expandarg(union node *arg, struct arglis /* * Perform parameter expansion, command substitution and arithmetic * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE. - * Processing ends at a CTLENDVAR character as well as '\0'. + * 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, EXP_CASE or EXP_REDIR are set, keep and/or generate CTLESC * characters to allow for further processing. @@ -232,6 +232,7 @@ argstr(char *p, int flag) switch (c = *p++) { case '\0': case CTLENDVAR: + case CTLENDARI: goto breakloop; case CTLQUOTEMARK: lit_quoted = 1; @@ -262,8 +263,8 @@ argstr(char *p, int flag) expbackq(argbackq->n, c & CTLQUOTE, flag); argbackq = argbackq->next; break; - case CTLENDARI: - expari(flag); + case CTLARI: + p = expari(p); break; case ':': case '=': @@ -388,59 +389,56 @@ removerecordregions(int endoff) } /* - * Expand arithmetic expression. Backup to start of expression, - * evaluate, place result in (backed up) result, adjust string position. + * Expand arithmetic expression. + * Note that flag is not required as digits never require CTLESC characters. */ -static void -expari(int flag) +static char * +expari(char *p) { - char *p, *q, *start; + char *q, *start; arith_t result; int begoff; - int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); int quoted; + int c; + int nesting; + int adj; - /* - * This routine is slightly over-complicated for - * efficiency. First we make sure there is - * enough space for the result, which may be bigger - * than the expression. Next we - * scan backwards looking for the start of arithmetic. If the - * next previous character is a CTLESC character, then we - * have to rescan starting from the beginning since CTLESC - * characters have to be processed left to right. - */ - CHECKSTRSPACE(DIGITS(result) - 2, expdest); - USTPUTC('\0', expdest); - start = stackblock(); - p = expdest - 2; - while (p >= start && *p != CTLARI) - --p; - if (p < start || *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(); + argstr(p, 0); removerecordregions(begoff); - if (quotes) - rmescapes(p+2); + STPUTC('\0', expdest); + start = stackblock() + begoff; + q = grabstackstr(expdest); - result = arith(p+2); + result = arith(start); ungrabstackstr(q, expdest); - fmtstr(p, DIGITS(result), ARITH_FORMAT_STR, result); - while (*p++) - ; - if (quoted == 0) - recordregion(begoff, p - 1 - start, 0); - result = expdest - p + 1; - STADJUST(-result, expdest); + + start = stackblock() + begoff; + adj = start - expdest; + STADJUST(adj, expdest); + + CHECKSTRSPACE((int)(DIGITS(result) + 1), expdest); + fmtstr(expdest, DIGITS(result), ARITH_FORMAT_STR, result); + adj = strlen(expdest); + STADJUST(adj, expdest); + if (!quoted) + recordregion(begoff, expdest - stackblock(), 0); + nesting = 1; + while (nesting > 0) { + c = *p++; + if (c == CTLESC) + p++; + else if (c == CTLARI) + nesting++; + else if (c == CTLENDARI) + nesting--; + else if (c == CTLVAR) + p++; /* ignore variable substitution byte */ + else if (c == '\0') + return p - 1; + } + return p; }