>Number:         156306
>Category:       bin
>Synopsis:       sh(1): request for exp-run for various changes
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Apr 10 15:30:10 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator:     Jilles Tjoelker
>Release:        FreeBSD 9.0-CURRENT i386
>Organization:
The FreeBSD Project
>Environment:
The patch applies to r219623-r220520 for sure and likely some later versions.
>Description:
I would like an -exp run for the attached patch.

Changes are:
* fix PR bin/104432, remove exp and let builtins
* fix PR bin/151720, flag error for ${#foo[x]}
* add $'quoting'
* apply set -u to variables in arithmetic
>How-To-Repeat:
-
>Fix:

--- sh-exp-20110410.patch begins here ---
Index: bin/sh/builtins.def
===================================================================
--- bin/sh/builtins.def (revision 219743)
+++ bin/sh/builtins.def (working copy)
@@ -60,7 +60,6 @@
 evalcmd                -s eval
 execcmd                -s exec
 exitcmd                -s exit
-expcmd         exp let
 exportcmd      -s export -s readonly
 #exprcmd               expr
 falsecmd       false
Index: bin/sh/arith_yacc.c
===================================================================
--- bin/sh/arith_yacc.c (revision 219743)
+++ bin/sh/arith_yacc.c (working copy)
@@ -97,6 +97,8 @@
        arith_t result;
 
        str = lookupvar(varname);
+       if (uflag && str == NULL)
+               yyerror("variable not set");
        if (str == NULL || *str == '\0')
                str = "0";
        errno = 0;
@@ -338,41 +340,3 @@
        return result;
 }
 
-/*
- *  The exp(1) builtin.
- */
-int
-expcmd(int argc, char **argv)
-{
-       const char *p;
-       char *concat;
-       char **ap;
-       arith_t i;
-
-       if (argc > 1) {
-               p = argv[1];
-               if (argc > 2) {
-                       /*
-                        * Concatenate arguments.
-                        */
-                       STARTSTACKSTR(concat);
-                       ap = argv + 2;
-                       for (;;) {
-                               while (*p)
-                                       STPUTC(*p++, concat);
-                               if ((p = *ap++) == NULL)
-                                       break;
-                               STPUTC(' ', concat);
-                       }
-                       STPUTC('\0', concat);
-                       p = grabstackstr(concat);
-               }
-       } else
-               p = "";
-
-       i = arith(p);
-
-       out1fmt(ARITH_FORMAT_STR "\n", i);
-       return !i;
-}
-
Index: bin/sh/arith.h
===================================================================
--- bin/sh/arith.h      (revision 219743)
+++ bin/sh/arith.h      (working copy)
@@ -36,4 +36,3 @@
 
 arith_t arith(const char *);
 void arith_lex_reset(void);
-int expcmd(int, char **);
Index: bin/sh/mksyntax.c
===================================================================
--- bin/sh/mksyntax.c   (revision 219743)
+++ bin/sh/mksyntax.c   (working copy)
@@ -64,6 +64,7 @@
        { "CWORD",      "character is nothing special" },
        { "CNL",        "newline character" },
        { "CBACK",      "a backslash character" },
+       { "CSBACK",     "a backslash character in single quotes" },
        { "CSQUOTE",    "single quote" },
        { "CDQUOTE",    "double quote" },
        { "CENDQUOTE",  "a terminating quote" },
@@ -224,6 +225,7 @@
        init();
        fputs("\n/* syntax table used when in single quotes */\n", cfile);
        add("\n", "CNL");
+       add("\\", "CSBACK");
        add("'", "CENDQUOTE");
        /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
        add("!*?[=~:/-", "CCTL");
Index: bin/sh/parser.c
===================================================================
--- bin/sh/parser.c     (revision 219743)
+++ bin/sh/parser.c     (working copy)
@@ -1127,6 +1127,127 @@
 
 
 /*
+ * Called to parse a backslash escape sequence inside $'...'.
+ * The backslash has already been read.
+ */
+static char *
+readcstyleesc(char *out)
+{
+       int c, v, i, n;
+
+       c = pgetc();
+       switch (c) {
+       case '\0':
+               synerror("Unterminated quoted string");
+       case '\n':
+               plinno++;
+               if (doprompt)
+                       setprompt(2);
+               else
+                       setprompt(0);
+               return out;
+       case '\\':
+       case '\'':
+       case '"':
+               v = c;
+               break;
+       case 'a': v = '\a'; break;
+       case 'b': v = '\b'; break;
+       case 'e': v = '\033'; break;
+       case 'f': v = '\f'; break;
+       case 'n': v = '\n'; break;
+       case 'r': v = '\r'; break;
+       case 't': v = '\t'; break;
+       case 'v': v = '\v'; break;
+       case 'x':
+                 v = 0;
+                 for (;;) {
+                         c = pgetc();
+                         if (c >= '0' && c <= '9')
+                                 v = (v << 4) + c - '0';
+                         else if (c >= 'A' && c <= 'F')
+                                 v = (v << 4) + c - 'A' + 10;
+                         else if (c >= 'a' && c <= 'f')
+                                 v = (v << 4) + c - 'a' + 10;
+                         else
+                                 break;
+                 }
+                 pungetc();
+                 break;
+       case '0': case '1': case '2': case '3':
+       case '4': case '5': case '6': case '7':
+                 v = c - '0';
+                 c = pgetc();
+                 if (c >= '0' && c <= '7') {
+                         v <<= 3;
+                         v += c - '0';
+                         c = pgetc();
+                         if (c >= '0' && c <= '7') {
+                                 v <<= 3;
+                                 v += c - '0';
+                         } else
+                                 pungetc();
+                 } else
+                         pungetc();
+                 break;
+       case 'c':
+                 c = pgetc();
+                 if (c < 0x3f || c > 0x7a || c == 0x60)
+                         synerror("Bad escape sequence");
+                 if (c == '\\' && pgetc() != '\\')
+                         synerror("Bad escape sequence");
+                 if (c == '?')
+                         v = 127;
+                 else
+                         v = c & 0x1f;
+                 break;
+       case 'u':
+       case 'U':
+                 n = c == 'U' ? 8 : 4;
+                 v = 0;
+                 for (i = 0; i < n; i++) {
+                         c = pgetc();
+                         if (c >= '0' && c <= '9')
+                                 v = (v << 4) + c - '0';
+                         else if (c >= 'A' && c <= 'F')
+                                 v = (v << 4) + c - 'A' + 10;
+                         else if (c >= 'a' && c <= 'f')
+                                 v = (v << 4) + c - 'a' + 10;
+                         else
+                                 synerror("Bad escape sequence");
+                 }
+                 if (v == 0 || (v >= 0xd800 && v <= 0xdfff))
+                         synerror("Bad escape sequence");
+                 /* We really need iconv here. */
+                 if (v > 127)
+                         v = '?';
+                 break;
+       default:
+                 synerror("Bad escape sequence");
+       }
+       v = (char)v;
+       /*
+        * We can't handle NUL bytes.
+        * POSIX says we should skip till the closing quote.
+        */
+       if (v == '\0') {
+               while ((c = pgetc()) != '\'') {
+                       if (c == '\\')
+                               c = pgetc();
+                       if (c == PEOF)
+                               synerror("Unterminated quoted string");
+               }
+               pungetc();
+               return out;
+       }
+       if (SQSYNTAX[v] == CCTL)
+               USTPUTC(CTLESC, out);
+       USTPUTC(v, out);
+       return out;
+}
+
+
+/*
  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
  * is not NULL, read a here document.  In the latter case, eofmark is the
  * word which marks the end of the document and striptabs is true if
@@ -1158,6 +1279,7 @@
        struct tokenstate state_static[MAXNEST_static];
        int maxnest = MAXNEST_static;
        struct tokenstate *state = state_static;
+       int sqiscstyle = 0;
 
        startlinno = plinno;
        quotef = 0;
@@ -1188,6 +1310,12 @@
                                        setprompt(0);
                                c = pgetc();
                                goto loop;              /* continue outer loop 
*/
+                       case CSBACK:
+                               if (sqiscstyle) {
+                                       out = readcstyleesc(out);
+                                       break;
+                               }
+                               /* FALLTHROUGH */
                        case CWORD:
                                USTPUTC(c, out);
                                break;
@@ -1232,6 +1360,7 @@
                        case CSQUOTE:
                                USTPUTC(CTLQUOTEMARK, out);
                                state[level].syntax = SQSYNTAX;
+                               sqiscstyle = 0;
                                break;
                        case CDQUOTE:
                                USTPUTC(CTLQUOTEMARK, out);
@@ -1450,11 +1579,7 @@
        int c1;
 
        c = pgetc();
-       if (c != '(' && c != '{' && (is_eof(c) || !is_name(c)) &&
-           !is_special(c)) {
-               USTPUTC('$', out);
-               pungetc();
-       } else if (c == '(') {  /* $(command) or $((arith)) */
+       if (c == '(') { /* $(command) or $((arith)) */
                if (pgetc() == '(') {
                        PARSEARITH();
                } else {
@@ -1465,7 +1590,7 @@
                            state[level].syntax == DQSYNTAX ||
                            state[level].syntax == ARISYNTAX);
                }
-       } else {
+       } else if (c == '{' || is_name(c) || is_special(c)) {
                USTPUTC(CTLVAR, out);
                typeloc = out - stackblock();
                USTPUTC(VSNORMAL, out);
@@ -1569,6 +1694,8 @@
                                }
                        }
                } else if (subtype != VSERROR) {
+                       if (subtype == VSLENGTH && c != '}')
+                               subtype = VSERROR;
                        pungetc();
                }
                STPUTC('=', out);
@@ -1610,6 +1737,14 @@
                                newvarnest++;
                        }
                }
+       } else if (c == '\'' && state[level].syntax == BASESYNTAX) {
+               /* $'cstylequotes' */
+               USTPUTC(CTLQUOTEMARK, out);
+               state[level].syntax = SQSYNTAX;
+               sqiscstyle = 1;
+       } else {
+               USTPUTC('$', out);
+               pungetc();
        }
        goto parsesub_return;
 }
--- sh-exp-20110410.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to