From a4f331d3c3ea5b358613992a48556cc9cbfdf139 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 7 Apr 2009 06:03:22 +0000 Subject: implement support for parameter substitution via #/% operators --- shell/hush.c | 65 ++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 24 deletions(-) (limited to 'shell/hush.c') diff --git a/shell/hush.c b/shell/hush.c index 792886944..1740187d4 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -43,7 +43,6 @@ * Here Documents ( << word ) * Functions * Tilde Expansion - * Parameter Expansion for substring processing ${var#word} ${var%word} * * Bash stuff (maybe optionally enable?): * &> and >& redirection of stdout+stderr @@ -76,6 +75,7 @@ #include #endif #include "math.h" +#include "match.h" #ifdef WANT_TO_TEST_NOMMU # undef BB_MMU @@ -1667,8 +1667,9 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) char first_ch, ored_ch; int i; const char *val; - char *p; + char *dyn_val, *p; + dyn_val = NULL; ored_ch = 0; debug_printf_expand("expand_vars_to_list: arg '%s'\n", arg); @@ -1844,7 +1845,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) ++var; } else { /* maybe handle parameter expansion */ - exp_off = strcspn(var, ":-=+?"); + exp_off = strcspn(var, ":-=+?%#"); if (!var[exp_off]) exp_off = 0; if (exp_off) { @@ -1873,29 +1874,45 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) val = utoa(val ? strlen(val) : 0); debug_printf_expand("%s\n", val); } else if (exp_off) { - /* we need to do an expansion */ - int exp_test = (!val || (exp_null && !val[0])); - if (exp_op == '+') - exp_test = !exp_test; - debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, - exp_null ? "true" : "false", exp_test); - if (exp_test) { - if (exp_op == '?') - maybe_die(var, *exp_word ? exp_word : "parameter null or not set"); + if (exp_op == '%' || exp_op == '#') { + /* we need to do a pattern match */ + bool zero; + char *loc; + scan_t scan = pick_scan(exp_op, *exp_word, &zero); + if (exp_op == *exp_word) /* ## or %% */ + ++exp_word; + val = dyn_val = xstrdup(val); + loc = scan(dyn_val, exp_word, zero); + if (zero) + val = loc; else - val = exp_word; - - if (exp_op == '=') { - if (isdigit(var[0]) || var[0] == '#') { - maybe_die(var, "special vars cannot assign in this way"); - val = NULL; - } else { - char *new_var = xmalloc(strlen(var) + strlen(val) + 2); - sprintf(new_var, "%s=%s", var, val); - set_local_var(new_var, -1, 0); + *loc = '\0'; + } else { + /* we need to do an expansion */ + int exp_test = (!val || (exp_null && !val[0])); + if (exp_op == '+') + exp_test = !exp_test; + debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, + exp_null ? "true" : "false", exp_test); + if (exp_test) { + if (exp_op == '?') + maybe_die(var, *exp_word ? exp_word : "parameter null or not set"); + else + val = exp_word; + + if (exp_op == '=') { + if (isdigit(var[0]) || var[0] == '#') { + maybe_die(var, "special vars cannot assign in this way"); + val = NULL; + } else { + char *new_var = xmalloc(strlen(var) + strlen(val) + 2); + sprintf(new_var, "%s=%s", var, val); + set_local_var(new_var, -1, 0); + } } } } + var[exp_off] = exp_save; } @@ -1921,6 +1938,8 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask) if (val) { o_addQstr(output, val, strlen(val)); } + free(dyn_val); + dyn_val = NULL; /* Do the check to avoid writing to a const string */ if (*p != SPECIAL_VAR_SYMBOL) *p = SPECIAL_VAR_SYMBOL; @@ -4428,7 +4447,6 @@ static int handle_dollar(o_string *as_string, break; } goto case_default; -#if 0 /* not implemented yet :( */ case '#': /* remove prefix */ case '%': /* remove suffix */ if (expansion == 0) { @@ -4437,7 +4455,6 @@ static int handle_dollar(o_string *as_string, break; } goto case_default; -#endif case '-': /* default value */ case '=': /* assign default */ case '+': /* alternative */ -- cgit v1.2.3