hush: fix incorrect processing of echo "'$var'".
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 16 May 2007 09:36:55 +0000 (09:36 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 16 May 2007 09:36:55 +0000 (09:36 -0000)
hush: rename map[] and MAP_xxx, making them easier to understand.
hush: move testcase (which now passes) from hush-bugs to hush-parsing

shell/hush.c
shell/hush_test/hush-bugs/quote1.right [deleted file]
shell/hush_test/hush-bugs/quote1.tests [deleted file]
shell/hush_test/hush-parsing/quote1.right [new file with mode: 0644]
shell/hush_test/hush-parsing/quote1.tests [new file with mode: 0755]

index 87e003db45a22dfd152aab392996555ea9a26225..e49c0c98990d06f3075854faa25437cfc5ad554d 100644 (file)
@@ -71,7 +71,7 @@
  *      memory leak finding and plugging - done?
  *      more testing, especially quoting rules and redirection
  *      document how quoting rules not precisely followed for variable assignments
- *      maybe change map[] to use 2-bit entries
+ *      maybe change charmap[] to use 2-bit entries
  *      (eventually) remove all the printf's
  *
  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
@@ -281,12 +281,12 @@ extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
 
 /* "globals" within this file */
 enum {
-       MAP_ORDINARY             = 0,
-       MAP_FLOWTROUGH_IF_QUOTED = 1,
-       MAP_IFS_IF_UNQUOTED      = 2, /* flow through if quoted too */
-       MAP_NEVER_FLOWTROUGH     = 3,
+       CHAR_ORDINARY           = 0,
+       CHAR_ORDINARY_IF_QUOTED = 1, /* example: *, # */
+       CHAR_IFS                = 2, /* treated as ordinary if quoted */
+       CHAR_SPECIAL            = 3, /* example: $ */
 };
-static unsigned char map[256];
+static unsigned char charmap[256];
 static const char *ifs;
 static int fake_mode;
 static struct close_me *close_me_head;
@@ -2311,7 +2311,7 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
  * Caller can deallocate entire list by single free(list). */
 
 /* Helpers first:
- * count_XXX estimates, how large block do we need. It's okay
+ * count_XXX estimates size of the block we need. It's okay
  * to over-estimate sizes a bit, if it makes code simpler */
 static int count_ifs(const char *str)
 {
@@ -3360,17 +3360,17 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
        debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger);
 
        while ((ch = b_getch(input)) != EOF) {
-               m = map[ch];
+               m = charmap[ch];
                next = (ch == '\n') ? '\0' : b_peek(input);
                debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n",
                                                ch, ch, m, dest->quote);
-               if (m == MAP_ORDINARY
-                || (m != MAP_NEVER_FLOWTROUGH && dest->quote)
+               if (m == CHAR_ORDINARY
+                || (m != CHAR_SPECIAL && dest->quote)
                ) {
                        b_addqchr(dest, ch, dest->quote);
                        continue;
                }
-               if (m == MAP_IFS_IF_UNQUOTED) {
+               if (m == CHAR_IFS) {
                        if (done_word(dest, ctx)) {
                                debug_printf_parse("parse_stream return 1: done_word!=0\n");
                                return 1;
@@ -3388,7 +3388,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
                        debug_printf_parse("parse_stream return 0: end_trigger char found\n");
                        return 0;
                }
-               if (m == MAP_IFS_IF_UNQUOTED)
+               if (m == CHAR_IFS)
                        continue;
                switch (ch) {
                case '#':
@@ -3527,28 +3527,28 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
        return 0;
 }
 
-static void mapset(const char *set, int code)
+static void set_in_charmap(const char *set, int code)
 {
        while (*set)
-               map[(unsigned char)*set++] = code;
+               charmap[(unsigned char)*set++] = code;
 }
 
-static void update_ifs_map(void)
+static void update_charmap(void)
 {
-       /* char *ifs and char map[256] are both globals. */
+       /* char *ifs and char charmap[256] are both globals. */
        ifs = getenv("IFS");
        if (ifs == NULL)
                ifs = " \t\n";
        /* Precompute a list of 'flow through' behavior so it can be treated
         * quickly up front.  Computation is necessary because of IFS.
         * Special case handling of IFS == " \t\n" is not implemented.
-        * The map[] array only really needs two bits each, and on most machines
-        * that would be faster because of the reduced L1 cache footprint.
+        * The charmap[] array only really needs two bits each,
+        * and on most machines that would be faster (reduced L1 cache use).
         */
-       memset(map, MAP_ORDINARY, sizeof(map)); /* most chars flow through always */
-       mapset("\\$'\"`", MAP_NEVER_FLOWTROUGH);
-       mapset("<>;&|(){}#", MAP_FLOWTROUGH_IF_QUOTED);
-       mapset(ifs, MAP_IFS_IF_UNQUOTED);  /* also flow through if quoted */
+       memset(charmap, CHAR_ORDINARY, sizeof(charmap));
+       set_in_charmap("\\$\"`", CHAR_SPECIAL);
+       set_in_charmap("<>;&|(){}#'", CHAR_ORDINARY_IF_QUOTED);
+       set_in_charmap(ifs, CHAR_IFS);  /* also flow through if quoted */
 }
 
 /* most recursion does not come through here, the exception is
@@ -3561,9 +3561,9 @@ static int parse_stream_outer(struct in_str *inp, int parse_flag)
        do {
                ctx.parse_type = parse_flag;
                initialize_context(&ctx);
-               update_ifs_map();
+               update_charmap();
                if (!(parse_flag & FLAG_PARSE_SEMICOLON) || (parse_flag & FLAG_REPARSING))
-                       mapset(";$&|", MAP_ORDINARY);
+                       set_in_charmap(";$&|", CHAR_ORDINARY);
 #if ENABLE_HUSH_INTERACTIVE
                inp->promptmode = 1;
 #endif
@@ -3665,7 +3665,7 @@ int hush_main(int argc, char **argv)
         * hush_main(), therefore we cannot rely on the BSS to zero out this
         * stuff.  Reset these to 0 every time. */
        ifs = NULL;
-       /* map[] is taken care of with call to update_ifs_map() */
+       /* charmap[] is taken care of with call to update_charmap() */
        fake_mode = 0;
        close_me_head = NULL;
 #if ENABLE_HUSH_INTERACTIVE
diff --git a/shell/hush_test/hush-bugs/quote1.right b/shell/hush_test/hush-bugs/quote1.right
deleted file mode 100644 (file)
index cb38205..0000000
+++ /dev/null
@@ -1 +0,0 @@
-'1'
diff --git a/shell/hush_test/hush-bugs/quote1.tests b/shell/hush_test/hush-bugs/quote1.tests
deleted file mode 100755 (executable)
index f558954..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-a=1
-echo "'$a'"
diff --git a/shell/hush_test/hush-parsing/quote1.right b/shell/hush_test/hush-parsing/quote1.right
new file mode 100644 (file)
index 0000000..cb38205
--- /dev/null
@@ -0,0 +1 @@
+'1'
diff --git a/shell/hush_test/hush-parsing/quote1.tests b/shell/hush_test/hush-parsing/quote1.tests
new file mode 100755 (executable)
index 0000000..f558954
--- /dev/null
@@ -0,0 +1,2 @@
+a=1
+echo "'$a'"