hush: continue fixing quoting and subst: fix glob_and_assign.tests.
authorDenis Vlasenko <vda.linux@googlemail.com>
Tue, 17 Jun 2008 07:24:29 +0000 (07:24 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Tue, 17 Jun 2008 07:24:29 +0000 (07:24 -0000)
shell/hush.c
shell/hush_test/hush-bugs/glob_and_assign.right
shell/hush_test/hush-bugs/glob_and_assign.tests
shell/hush_test/run-all

index e64cc476d16b236bcbe9953a2485eaed1ff84870..ae12ebec49c73622a5627fda4ea0231812d2fce0 100644 (file)
 #define debug_printf_expand(...) do {} while (0)
 #define debug_printf_glob(...)   do {} while (0)
 #define debug_printf_list(...)   do {} while (0)
+#define debug_printf_subst(...)  do {} while (0)
 #define debug_printf_clean(...)  do {} while (0)
 
 #ifndef debug_printf
 #define debug_printf_list(...) fprintf(stderr, __VA_ARGS__)
 #endif
 
+#ifndef debug_printf_subst
+#define debug_printf_subst(...) fprintf(stderr, __VA_ARGS__)
+#endif
+
 /* Keep unconditionally on for now */
 #define ENABLE_HUSH_DEBUG 1
 
@@ -516,8 +521,6 @@ static int run_list(struct pipe *pi);
 static void pseudo_exec_argv(char **ptrs2free, char **argv) ATTRIBUTE_NORETURN;
 static void pseudo_exec(char **ptrs2free, struct child_prog *child) ATTRIBUTE_NORETURN;
 static int run_pipe(struct pipe *pi);
-/*   variable assignment: */
-static int is_assignment(const char *s);
 /*   data structure manipulation: */
 static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input);
 static void initialize_context(struct p_context *ctx);
@@ -573,6 +576,16 @@ static int glob_needed(const char *s)
        return 0;
 }
 
+static int is_assignment(const char *s)
+{
+       if (!s || !isalpha(*s))
+               return 0;
+       s++;
+       while (isalnum(*s) || *s == '_')
+               s++;
+       return *s == '=';
+}
+
 static char **add_malloced_strings_to_strings(char **strings, char **add)
 {
        int i;
@@ -938,7 +951,7 @@ static void o_addQstr(o_string *o, const char *str, int len)
                if (ordinary_cnt == len)
                        return;
                str += ordinary_cnt;
-               len -= ordinary_cnt - 1; /* we are processing + 1 char below */
+               len -= ordinary_cnt + 1; /* we are processing + 1 char below */
 
                ch = *str++;
                sz = 1;
@@ -1000,7 +1013,7 @@ static int o_save_ptr_helper(o_string *o, int n)
                string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
                string_len = o->length - string_start;
                if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
-                       debug_printf_list("list[%d]=%d string_start=%d (growing)", n, string_len, string_start);
+                       debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
                        /* list[n] points to string_start, make space for 16 more pointers */
                        o->maxlen += 0x10 * sizeof(list[0]);
                        o->data = xrealloc(o->data, o->maxlen + 1);
@@ -1008,12 +1021,12 @@ static int o_save_ptr_helper(o_string *o, int n)
                        memmove(list + n + 0x10, list + n, string_len);
                        o->length += 0x10 * sizeof(list[0]);
                } else
-                       debug_printf_list("list[%d]=%d string_start=%d", n, string_len, string_start);
+                       debug_printf_list("list[%d]=%d string_start=%d\n", n, string_len, string_start);
        } else {
                /* We have empty slot at list[n], reuse without growth */
                string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
                string_len = o->length - string_start;
-               debug_printf_list("list[%d]=%d string_start=%d (empty slot)", n, string_len, string_start);
+               debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n", n, string_len, string_start);
                o->has_empty_slot = 0;
        }
        list[n] = (char*)string_len;
@@ -1048,15 +1061,15 @@ static int o_glob(o_string *o, int n)
        int gr;
        char *pattern;
 
-       debug_printf_glob("start o_glob: n:%d o->data:%p", n, o->data);
+       debug_printf_glob("start o_glob: n:%d o->data:%p\n", n, o->data);
        if (!o->data)
                return o_save_ptr_helper(o, n);
        pattern = o->data + o_get_last_ptr(o, n);
-       debug_printf_glob("glob pattern '%s'", pattern);
+       debug_printf_glob("glob pattern '%s'\n", pattern);
        if (!glob_needed(pattern)) {
  literal:
                o->length = unbackslash(pattern) - o->data;
-               debug_printf_glob("glob pattern '%s' is literal", pattern);
+               debug_printf_glob("glob pattern '%s' is literal\n", pattern);
                return o_save_ptr_helper(o, n);
        }
 
@@ -1108,7 +1121,7 @@ static char **o_finalize_list(o_string *o, int n)
        n = o_save_ptr(o, n); /* force growth for list[n] if necessary */
        if (DEBUG_EXPAND)
                debug_print_list("finalized", o, n);
-       debug_printf_expand("finalized n:%d", n);
+       debug_printf_expand("finalized n:%d\n", n);
        list = (char**)o->data;
        string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
        list[--n] = NULL;
@@ -2285,7 +2298,7 @@ static int expand_on_ifs(o_string *output, int n, const char *str)
        while (1) {
                int word_len = strcspn(str, ifs);
                if (word_len) {
-                       o_addQstr(output, str, word_len);
+                       o_addstr(output, str, word_len);
                        str += word_len;
                }
                if (!*str)  /* EOL - do not finalize word */
@@ -2328,7 +2341,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
                o_string subst_result = NULL_O_STRING;
 #endif
 
-               o_addQstr(output, arg, p - arg);
+               o_addstr(output, arg, p - arg);
                debug_print_list("expand_vars_to_list[1]", output, n);
                arg = ++p;
                p = strchr(p, SPECIAL_VAR_SYMBOL);
@@ -2374,7 +2387,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
                         * and in this case should treat it like '$*' - see 'else...' below */
                        if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */
                                while (1) {
-                                       o_addQstr(output, global_argv[i], strlen(global_argv[i]));
+                                       o_addQstr(output, global_argv[i], strlen(global_argv[i])); ///really Q?
                                        if (++i >= global_argc)
                                                break;
                                        o_addchr(output, '\0');
@@ -2383,7 +2396,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
                                }
                        } else { /* quoted $*: add as one word */
                                while (1) {
-                                       o_addQstr(output, global_argv[i], strlen(global_argv[i]));
+                                       o_addQstr(output, global_argv[i], strlen(global_argv[i])); ///really Q?
                                        if (!global_argv[++i])
                                                break;
                                        if (ifs[0])
@@ -2397,10 +2410,10 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
                        *p = '\0';
                        arg++;
 //TODO: can we just stuff it into "output" directly?
-                       //bb_error_msg("SUBST '%s' first_ch %x", arg, first_ch);
+                       debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
                        setup_string_in_str(&input, arg);
                        process_command_subs(&subst_result, &input, NULL);
-                       //bb_error_msg("RES '%s'", subst_result.data);
+                       debug_printf_subst("SUBST RES '%s'\n", subst_result.data);
                        val = subst_result.data;
                        goto store_val;
                }
@@ -2421,14 +2434,16 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
 #endif
                        *p = SPECIAL_VAR_SYMBOL;
                        if (!(first_ch & 0x80)) { /* unquoted $VAR */
+                               debug_printf_expand("unquoted '%s', output->o_quote:%d\n", val, output->o_quote);
                                if (val) {
                                        n = expand_on_ifs(output, n, val);
                                        val = NULL;
                                }
-                       } /* else: quoted $VAR, val will be appended below */
+                       } else /* quoted $VAR, val will be appended below */
+                               debug_printf_expand("quoted '%s', output->o_quote:%d\n", val, output->o_quote);
                }
                if (val) {
-                       o_addQstr(output, val, strlen(val));
+                       o_addQstr(output, val, strlen(val)); ///maybe q?
                }
 
 #if ENABLE_HUSH_TICK
@@ -2439,7 +2454,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
 
        if (arg[0]) {
                debug_print_list("expand_vars_to_list[a]", output, n);
-               o_addQstr(output, arg, strlen(arg) + 1);
+               /* this part is literal, and it was already pre-quoted
+                * if needed (much earlier), do not use o_addQstr here! */
+               o_addstr(output, arg, strlen(arg) + 1);
                debug_print_list("expand_vars_to_list[b]", output, n);
        } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
         && !(ored_ch & 0x80) /* and all vars were not quoted. */
@@ -2460,8 +2477,10 @@ static char **expand_variables(char **argv, int or_mask)
        char **v;
        o_string output = NULL_O_STRING;
 
-       if (or_mask & 0x100)
+       if (or_mask & 0x100) {
+               output.o_quote = 1;
                output.o_glob = 1;
+       }
 
        n = 0;
        v = argv;
@@ -2637,16 +2656,6 @@ static void unset_local_var(const char *name)
        }
 }
 
-static int is_assignment(const char *s)
-{
-       if (!s || !isalpha(*s))
-               return 0;
-       s++;
-       while (isalnum(*s) || *s == '_')
-               s++;
-       return *s == '=';
-}
-
 /* the src parameter allows us to peek forward to a possible &n syntax
  * for file descriptor duplication, e.g., "2>&1".
  * Return code is 0 normally, 1 if a syntax error is detected in src.
@@ -3341,7 +3350,7 @@ static int handle_dollar(o_string *dest, struct in_str *input)
                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
                        o_addchr(dest, quote_mask | '`');
                        add_till_closing_curly_brace(dest, input);
-                       //bb_error_msg("RES '%s'", dest->data + pos);
+                       //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
                        break;
                }
@@ -3496,7 +3505,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
                        o_addchr(dest, dest->o_quote ? 0x80 | '`' : '`');
                        add_till_backquote(dest, input);
                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
-                       //bb_error_msg("RES '%s'", dest->data + pos);
+                       //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
                        break;
                }
 #endif
index dae8323617c53801127f68bbd1fa0a6a8557abba..d46e44363124f95e8517e35e298f01a7c8962f9e 100644 (file)
@@ -1,2 +1,6 @@
-ZVAR=z.map
-*.map
+ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
+ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
+*.tmp
+ZVAR=z.tmp z.tmp
+ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
+ZVAR=z.tmp ZVAR=*.tmp ZVAR=[z].tmp
index ea11e364b3904d339c54959370844efb3bb503df..0b158f20f22e6dabeffbd1c52c03f76c88d5814f 100755 (executable)
@@ -1,18 +1,10 @@
-## # bash zbad2
-## ZVAR=z.map
-## *.map
-## # hush zbad2
-## ZVAR=z.map
-## z.map  <====== !!!
-
-## hush does globbing for "VAR=val" too!
-## it should do it only for non-assignments.
-## even if word looks like assignment, it can be non-assignment:
-## ZVAR=*.map /bin/echo ZVAR=*.map
-## ^dont_glob           ^glob
-
->ZVAR=z.map
-ZVAR=*.map /bin/echo ZVAR=*.map
-ZVAR=*.map
+>ZVAR=z.tmp
+>z.tmp
+ZVAR=*.tmp echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
+ZVAR=*.tmp /bin/echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
+ZVAR=*.tmp
 echo "$ZVAR"
-rm ZVAR=z.map
+echo $ZVAR
+echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
+/bin/echo ZVAR=*.tmp "ZVAR=*.tmp" "ZVAR=[z].tmp"
+rm ZVAR=z.tmp z.tmp
index 5cec85af63c2dc10fb28a8394828bf18655ce804..b79af2f6704ceced0241d85903663d65b1c0125f 100755 (executable)
@@ -1,5 +1,14 @@
 #!/bin/sh
 
+unset LANG LANGUAGE
+unset LC_COLLATE
+unset LC_CTYPE
+unset LC_MONETARY
+unset LC_MESSAGES
+unset LC_NUMERIC
+unset LC_TIME
+unset LC_ALL
+
 test -x hush || {
     echo "No ./hush - creating a link to ../../busybox"
     ln -s ../../busybox hush