#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
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);
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;
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;
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);
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;
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);
}
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;
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 */
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);
* 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');
}
} 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])
*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;
}
#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
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. */
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;
}
}
-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.
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;
}
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