hush: remove code which errors out on $- and $_, it's useless;

wrap some longish lines

function                                             old     new   delta
handle_dollar                                        667     626     -41
This commit is contained in:
Denis Vlasenko 2009-04-04 15:24:40 +00:00
parent 7c9861214b
commit a24c8caeb2

View File

@ -1517,13 +1517,16 @@ static int o_save_ptr_helper(o_string *o, int n)
list = (char**)o->data;
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", n, string_len, string_start);
} else {
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", 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*)(ptrdiff_t)string_len;
@ -1917,7 +1920,6 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
}
arg[0] = first_ch;
#if ENABLE_HUSH_TICK
store_val:
#endif
@ -2203,8 +2205,12 @@ typedef struct nommu_save_t {
* XXX no exit() here. If you don't exec, use _exit instead.
* The at_exit handlers apparently confuse the calling process,
* in particular stdin handling. Not sure why? -- because of vfork! (vda) */
static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded) NORETURN;
static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded)
static void pseudo_exec_argv(nommu_save_t *nommu_save,
char **argv, int assignment_cnt,
char **argv_expanded) NORETURN;
static void pseudo_exec_argv(nommu_save_t *nommu_save,
char **argv, int assignment_cnt,
char **argv_expanded)
{
int rcode;
char **new_env;
@ -2279,8 +2285,12 @@ static int run_list(struct pipe *pi);
/* Called after [v]fork() in run_pipe()
*/
static void pseudo_exec(nommu_save_t *nommu_save, struct command *command, char **argv_expanded) NORETURN;
static void pseudo_exec(nommu_save_t *nommu_save, struct command *command, char **argv_expanded)
static void pseudo_exec(nommu_save_t *nommu_save,
struct command *command,
char **argv_expanded) NORETURN;
static void pseudo_exec(nommu_save_t *nommu_save,
struct command *command,
char **argv_expanded)
{
if (command->argv)
pseudo_exec_argv(nommu_save, command->argv, command->assignment_cnt, argv_expanded);
@ -2655,7 +2665,8 @@ static int run_pipe(struct pipe *pi)
setup_redirects(command, squirrel);
new_env = expand_assignments(argv, command->assignment_cnt);
old_env = putenv_all_and_save_old(new_env);
debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv_expanded[1]);
debug_printf_exec(": builtin '%s' '%s'...\n",
x->cmd, argv_expanded[1]);
rcode = x->function(argv_expanded) & 0xff;
#if ENABLE_FEATURE_SH_STANDALONE
clean_up_and_ret:
@ -2677,7 +2688,8 @@ static int run_pipe(struct pipe *pi)
save_nofork_data(&G.nofork_save);
new_env = expand_assignments(argv, command->assignment_cnt);
old_env = putenv_all_and_save_old(new_env);
debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]);
debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
argv_expanded[0], argv_expanded[1]);
rcode = run_nofork_applet_prime(&G.nofork_save, i, argv_expanded);
goto clean_up_and_ret;
}
@ -2701,7 +2713,8 @@ static int run_pipe(struct pipe *pi)
#endif
command = &(pi->cmds[i]);
if (command->argv) {
debug_printf_exec(": pipe member '%s' '%s'...\n", command->argv[0], command->argv[1]);
debug_printf_exec(": pipe member '%s' '%s'...\n",
command->argv[0], command->argv[1]);
} else
debug_printf_exec(": pipe member with no argv\n");
@ -2841,7 +2854,9 @@ static void debug_print_tree(struct pipe *pi, int lvl)
struct command *command = &pi->cmds[prn];
char **argv = command->argv;
fprintf(stderr, "%*s prog %d assignment_cnt:%d", lvl*2, "", prn, command->assignment_cnt);
fprintf(stderr, "%*s prog %d assignment_cnt:%d",
lvl*2, "", prn,
command->assignment_cnt);
if (command->group) {
fprintf(stderr, " group %s: (argv=%p)\n",
GRPTYPE[command->grp_type],
@ -3046,8 +3061,9 @@ static int run_list(struct pipe *pi)
pi->cmds[0].argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++);
pi->cmds[0].assignment_cnt = 1;
}
if (rword == RES_IN) /* "for v IN list;..." - "in" has no cmds anyway */
continue;
if (rword == RES_IN) {
continue; /* "for v IN list;..." - "in" has no cmds anyway */
}
if (rword == RES_DONE) {
continue; /* "done" has no cmds too */
}
@ -3603,7 +3619,8 @@ static int done_word(o_string *word, struct parse_context *ctx)
debug_printf_parse(": checking '%s' for reserved-ness\n", word->data);
if (reserved_word(word, ctx)) {
o_reset(word);
debug_printf_parse("done_word return %d\n", (ctx->ctx_res_w == RES_SNTX));
debug_printf_parse("done_word return %d\n",
(ctx->ctx_res_w == RES_SNTX));
return (ctx->ctx_res_w == RES_SNTX);
}
}
@ -3800,7 +3817,8 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
|| dest->nonnull /* ""(... */
) {
syntax(NULL);
debug_printf_parse("parse_group return 1: syntax error, groups and arglists don't mix\n");
debug_printf_parse("parse_group return 1: "
"syntax error, groups and arglists don't mix\n");
return 1;
}
endch = '}';
@ -3812,7 +3830,8 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
/* empty ()/{} or parse error? */
if (!pipe_list || pipe_list == ERR_PTR) {
syntax(NULL);
debug_printf_parse("parse_group return 1: parse_stream returned %p\n", pipe_list);
debug_printf_parse("parse_group return 1: "
"parse_stream returned %p\n", pipe_list);
return 1;
}
command->group = pipe_list;
@ -3910,7 +3929,7 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db
break;
if (ch == '(')
count++;
if (ch == ')')
if (ch == ')') {
if (--count < 0) {
if (!dbl)
break;
@ -3919,6 +3938,7 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db
break;
}
}
}
o_addchr(dest, ch);
if (ch == '\'') {
add_till_single_quote(dest, input);
@ -3971,136 +3991,130 @@ static int handle_dollar(o_string *dest, struct in_str *input)
o_addchr(dest, ch | quote_mask);
o_addchr(dest, SPECIAL_VAR_SYMBOL);
} else switch (ch) {
case '$': /* pid */
case '!': /* last bg pid */
case '?': /* last exit code */
case '#': /* number of args */
case '*': /* args */
case '@': /* args */
goto make_one_char_var;
case '{': {
bool first_char, all_digits;
case '$': /* pid */
case '!': /* last bg pid */
case '?': /* last exit code */
case '#': /* number of args */
case '*': /* args */
case '@': /* args */
goto make_one_char_var;
case '{': {
bool first_char, all_digits;
o_addchr(dest, SPECIAL_VAR_SYMBOL);
i_getch(input);
/* XXX maybe someone will try to escape the '}' */
expansion = 0;
first_char = true;
all_digits = false;
while (1) {
ch = i_getch(input);
if (ch == '}')
break;
if (first_char) {
if (ch == '#')
/* ${#var}: length of var contents */
goto char_ok;
else if (isdigit(ch)) {
all_digits = true;
goto char_ok;
}
}
if (expansion < 2 &&
((all_digits && !isdigit(ch)) ||
(!all_digits && !isalnum(ch) && ch != '_')))
{
/* handle parameter expansions
* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
*/
if (first_char)
goto case_default;
switch (ch) {
case ':': /* null modifier */
if (expansion == 0) {
debug_printf_parse(": null modifier\n");
++expansion;
break;
}
goto case_default;
#if 0 /* not implemented yet :( */
case '#': /* remove prefix */
case '%': /* remove suffix */
if (expansion == 0) {
debug_printf_parse(": remove suffix/prefix\n");
expansion = 2;
break;
}
goto case_default;
#endif
case '-': /* default value */
case '=': /* assign default */
case '+': /* alternative */
case '?': /* error indicate */
debug_printf_parse(": parameter expansion\n");
expansion = 2;
break;
default:
case_default:
syntax("unterminated ${name}");
debug_printf_parse("handle_dollar return 1: unterminated ${name}\n");
return 1;
}
}
char_ok:
debug_printf_parse(": '%c'\n", ch);
o_addchr(dest, ch | quote_mask);
quote_mask = 0;
first_char = false;
}
o_addchr(dest, SPECIAL_VAR_SYMBOL);
break;
}
case '(': {
i_getch(input);
#if ENABLE_SH_MATH_SUPPORT
if (i_peek(input) == '(') {
i_getch(input);
o_addchr(dest, SPECIAL_VAR_SYMBOL);
o_addchr(dest, /*quote_mask |*/ '+');
add_till_closing_paren(dest, input, true);
o_addchr(dest, SPECIAL_VAR_SYMBOL);
o_addchr(dest, SPECIAL_VAR_SYMBOL);
i_getch(input);
/* XXX maybe someone will try to escape the '}' */
expansion = 0;
first_char = true;
all_digits = false;
while (1) {
ch = i_getch(input);
if (ch == '}')
break;
}
#endif
#if ENABLE_HUSH_TICK
//int pos = dest->length;
o_addchr(dest, SPECIAL_VAR_SYMBOL);
o_addchr(dest, quote_mask | '`');
add_till_closing_paren(dest, input, false);
//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
o_addchr(dest, SPECIAL_VAR_SYMBOL);
if (first_char) {
if (ch == '#')
/* ${#var}: length of var contents */
goto char_ok;
else if (isdigit(ch)) {
all_digits = true;
goto char_ok;
}
}
if (expansion < 2
&& ( (all_digits && !isdigit(ch))
|| (!all_digits && !isalnum(ch) && ch != '_')
)
) {
/* handle parameter expansions
* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
*/
if (first_char)
goto case_default;
switch (ch) {
case ':': /* null modifier */
if (expansion == 0) {
debug_printf_parse(": null modifier\n");
++expansion;
break;
}
goto case_default;
#if 0 /* not implemented yet :( */
case '#': /* remove prefix */
case '%': /* remove suffix */
if (expansion == 0) {
debug_printf_parse(": remove suffix/prefix\n");
expansion = 2;
break;
}
goto case_default;
#endif
case '-': /* default value */
case '=': /* assign default */
case '+': /* alternative */
case '?': /* error indicate */
debug_printf_parse(": parameter expansion\n");
expansion = 2;
break;
default:
case_default:
syntax("unterminated ${name}");
debug_printf_parse("handle_dollar return 1: unterminated ${name}\n");
return 1;
}
}
char_ok:
debug_printf_parse(": '%c'\n", ch);
o_addchr(dest, ch | quote_mask);
quote_mask = 0;
first_char = false;
}
o_addchr(dest, SPECIAL_VAR_SYMBOL);
break;
}
case '(': {
i_getch(input);
#if ENABLE_SH_MATH_SUPPORT
if (i_peek(input) == '(') {
i_getch(input);
o_addchr(dest, SPECIAL_VAR_SYMBOL);
o_addchr(dest, /*quote_mask |*/ '+');
add_till_closing_paren(dest, input, true);
o_addchr(dest, SPECIAL_VAR_SYMBOL);
break;
}
case '_':
i_getch(input);
ch = i_peek(input);
if (isalnum(ch)) { /* it's $_name or $_123 */
ch = '_';
goto make_var;
}
/* else: it's $_ */
case '-':
/* still unhandled, but should be eventually */
bb_error_msg("unhandled syntax: $%c", ch);
return 1;
break;
default:
o_addQchr(dest, '$');
#endif
#if ENABLE_HUSH_TICK
//int pos = dest->length;
o_addchr(dest, SPECIAL_VAR_SYMBOL);
o_addchr(dest, quote_mask | '`');
add_till_closing_paren(dest, input, false);
//debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos);
o_addchr(dest, SPECIAL_VAR_SYMBOL);
#endif
break;
}
case '_':
i_getch(input);
ch = i_peek(input);
if (isalnum(ch)) { /* it's $_name or $_123 */
ch = '_';
goto make_var;
}
/* else: it's $_ */
/* TODO: */
/* $_ Shell or shell script name; or last cmd name */
/* $- Option flags set by set builtin or shell options (-i etc) */
default:
o_addQchr(dest, '$');
}
debug_printf_parse("handle_dollar return 0\n");
return 0;
}
static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote_end)
static int parse_stream_dquoted(o_string *dest,
struct in_str *input, int dquote_end)
{
int ch;
int next;
@ -4149,7 +4163,8 @@ static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote
}
if (ch == '$') {
if (handle_dollar(dest, input) != 0) {
debug_printf_parse("parse_stream_dquoted return 1: handle_dollar returned non-0\n");
debug_printf_parse("parse_stream_dquoted return 1: "
"handle_dollar returned non-0\n");
return 1;
}
goto again;
@ -4196,8 +4211,8 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
/* Double-quote state is handled in the state variable is_in_dquote.
* A single-quote triggers a bypass of the main loop until its mate is
* found. When recursing, quote state is passed in via dest->o_escape. */
* found. When recursing, quote state is passed in via dest->o_escape.
*/
debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
end_trigger ? : 'X');
@ -4338,7 +4353,8 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
break;
case '$':
if (handle_dollar(&dest, input) != 0) {
debug_printf_parse("parse_stream parse error: handle_dollar returned non-0\n");
debug_printf_parse("parse_stream parse error: "
"handle_dollar returned non-0\n");
goto parse_error;
}
break;
@ -4532,8 +4548,9 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
/* Clean up allocated tree.
* Samples for finding leaks on syntax error recovery path.
* Execute them from interactive shell and watch pmap `pidof hush`.
* while if false; then false; fi do break; done (bash accepts it)
* Run them from interactive shell, watch pmap `pidof hush`.
* while if false; then false; fi do break; done
* (bash accepts it)
* while if false; then false; fi; do break; fi
*/
pctx = &ctx;