diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-04 15:24:40 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-04 15:24:40 +0000 |
commit | a24c8caeb29a11fafc748399ab6b30e6b8e638f0 (patch) | |
tree | 6405a35e0da6b9946f1c50ece8fae2ad1aa4ed20 /shell | |
parent | 7c9861214b2d81603902d344cfdef3342d8d4b5b (diff) | |
download | busybox-w32-a24c8caeb29a11fafc748399ab6b30e6b8e638f0.tar.gz busybox-w32-a24c8caeb29a11fafc748399ab6b30e6b8e638f0.tar.bz2 busybox-w32-a24c8caeb29a11fafc748399ab6b30e6b8e638f0.zip |
hush: remove code which errors out on $- and $_, it's useless;
wrap some longish lines
function old new delta
handle_dollar 667 626 -41
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 287 |
1 files changed, 152 insertions, 135 deletions
diff --git a/shell/hush.c b/shell/hush.c index 6ae42c8b5..0ac42c90b 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1517,13 +1517,16 @@ static int o_save_ptr_helper(o_string *o, int n) | |||
1517 | list = (char**)o->data; | 1517 | list = (char**)o->data; |
1518 | memmove(list + n + 0x10, list + n, string_len); | 1518 | memmove(list + n + 0x10, list + n, string_len); |
1519 | o->length += 0x10 * sizeof(list[0]); | 1519 | o->length += 0x10 * sizeof(list[0]); |
1520 | } else | 1520 | } else { |
1521 | debug_printf_list("list[%d]=%d string_start=%d\n", n, string_len, string_start); | 1521 | debug_printf_list("list[%d]=%d string_start=%d\n", |
1522 | n, string_len, string_start); | ||
1523 | } | ||
1522 | } else { | 1524 | } else { |
1523 | /* We have empty slot at list[n], reuse without growth */ | 1525 | /* We have empty slot at list[n], reuse without growth */ |
1524 | string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */ | 1526 | string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */ |
1525 | string_len = o->length - string_start; | 1527 | string_len = o->length - string_start; |
1526 | debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n", n, string_len, string_start); | 1528 | debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n", |
1529 | n, string_len, string_start); | ||
1527 | o->has_empty_slot = 0; | 1530 | o->has_empty_slot = 0; |
1528 | } | 1531 | } |
1529 | list[n] = (char*)(ptrdiff_t)string_len; | 1532 | 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) | |||
1917 | } | 1920 | } |
1918 | 1921 | ||
1919 | arg[0] = first_ch; | 1922 | arg[0] = first_ch; |
1920 | |||
1921 | #if ENABLE_HUSH_TICK | 1923 | #if ENABLE_HUSH_TICK |
1922 | store_val: | 1924 | store_val: |
1923 | #endif | 1925 | #endif |
@@ -2203,8 +2205,12 @@ typedef struct nommu_save_t { | |||
2203 | * XXX no exit() here. If you don't exec, use _exit instead. | 2205 | * XXX no exit() here. If you don't exec, use _exit instead. |
2204 | * The at_exit handlers apparently confuse the calling process, | 2206 | * The at_exit handlers apparently confuse the calling process, |
2205 | * in particular stdin handling. Not sure why? -- because of vfork! (vda) */ | 2207 | * in particular stdin handling. Not sure why? -- because of vfork! (vda) */ |
2206 | static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded) NORETURN; | 2208 | static void pseudo_exec_argv(nommu_save_t *nommu_save, |
2207 | static void pseudo_exec_argv(nommu_save_t *nommu_save, char **argv, int assignment_cnt, char **argv_expanded) | 2209 | char **argv, int assignment_cnt, |
2210 | char **argv_expanded) NORETURN; | ||
2211 | static void pseudo_exec_argv(nommu_save_t *nommu_save, | ||
2212 | char **argv, int assignment_cnt, | ||
2213 | char **argv_expanded) | ||
2208 | { | 2214 | { |
2209 | int rcode; | 2215 | int rcode; |
2210 | char **new_env; | 2216 | char **new_env; |
@@ -2279,8 +2285,12 @@ static int run_list(struct pipe *pi); | |||
2279 | 2285 | ||
2280 | /* Called after [v]fork() in run_pipe() | 2286 | /* Called after [v]fork() in run_pipe() |
2281 | */ | 2287 | */ |
2282 | static void pseudo_exec(nommu_save_t *nommu_save, struct command *command, char **argv_expanded) NORETURN; | 2288 | static void pseudo_exec(nommu_save_t *nommu_save, |
2283 | static void pseudo_exec(nommu_save_t *nommu_save, struct command *command, char **argv_expanded) | 2289 | struct command *command, |
2290 | char **argv_expanded) NORETURN; | ||
2291 | static void pseudo_exec(nommu_save_t *nommu_save, | ||
2292 | struct command *command, | ||
2293 | char **argv_expanded) | ||
2284 | { | 2294 | { |
2285 | if (command->argv) | 2295 | if (command->argv) |
2286 | pseudo_exec_argv(nommu_save, command->argv, command->assignment_cnt, argv_expanded); | 2296 | pseudo_exec_argv(nommu_save, command->argv, command->assignment_cnt, argv_expanded); |
@@ -2655,7 +2665,8 @@ static int run_pipe(struct pipe *pi) | |||
2655 | setup_redirects(command, squirrel); | 2665 | setup_redirects(command, squirrel); |
2656 | new_env = expand_assignments(argv, command->assignment_cnt); | 2666 | new_env = expand_assignments(argv, command->assignment_cnt); |
2657 | old_env = putenv_all_and_save_old(new_env); | 2667 | old_env = putenv_all_and_save_old(new_env); |
2658 | debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv_expanded[1]); | 2668 | debug_printf_exec(": builtin '%s' '%s'...\n", |
2669 | x->cmd, argv_expanded[1]); | ||
2659 | rcode = x->function(argv_expanded) & 0xff; | 2670 | rcode = x->function(argv_expanded) & 0xff; |
2660 | #if ENABLE_FEATURE_SH_STANDALONE | 2671 | #if ENABLE_FEATURE_SH_STANDALONE |
2661 | clean_up_and_ret: | 2672 | clean_up_and_ret: |
@@ -2677,7 +2688,8 @@ static int run_pipe(struct pipe *pi) | |||
2677 | save_nofork_data(&G.nofork_save); | 2688 | save_nofork_data(&G.nofork_save); |
2678 | new_env = expand_assignments(argv, command->assignment_cnt); | 2689 | new_env = expand_assignments(argv, command->assignment_cnt); |
2679 | old_env = putenv_all_and_save_old(new_env); | 2690 | old_env = putenv_all_and_save_old(new_env); |
2680 | debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]); | 2691 | debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", |
2692 | argv_expanded[0], argv_expanded[1]); | ||
2681 | rcode = run_nofork_applet_prime(&G.nofork_save, i, argv_expanded); | 2693 | rcode = run_nofork_applet_prime(&G.nofork_save, i, argv_expanded); |
2682 | goto clean_up_and_ret; | 2694 | goto clean_up_and_ret; |
2683 | } | 2695 | } |
@@ -2701,7 +2713,8 @@ static int run_pipe(struct pipe *pi) | |||
2701 | #endif | 2713 | #endif |
2702 | command = &(pi->cmds[i]); | 2714 | command = &(pi->cmds[i]); |
2703 | if (command->argv) { | 2715 | if (command->argv) { |
2704 | debug_printf_exec(": pipe member '%s' '%s'...\n", command->argv[0], command->argv[1]); | 2716 | debug_printf_exec(": pipe member '%s' '%s'...\n", |
2717 | command->argv[0], command->argv[1]); | ||
2705 | } else | 2718 | } else |
2706 | debug_printf_exec(": pipe member with no argv\n"); | 2719 | debug_printf_exec(": pipe member with no argv\n"); |
2707 | 2720 | ||
@@ -2841,7 +2854,9 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
2841 | struct command *command = &pi->cmds[prn]; | 2854 | struct command *command = &pi->cmds[prn]; |
2842 | char **argv = command->argv; | 2855 | char **argv = command->argv; |
2843 | 2856 | ||
2844 | fprintf(stderr, "%*s prog %d assignment_cnt:%d", lvl*2, "", prn, command->assignment_cnt); | 2857 | fprintf(stderr, "%*s prog %d assignment_cnt:%d", |
2858 | lvl*2, "", prn, | ||
2859 | command->assignment_cnt); | ||
2845 | if (command->group) { | 2860 | if (command->group) { |
2846 | fprintf(stderr, " group %s: (argv=%p)\n", | 2861 | fprintf(stderr, " group %s: (argv=%p)\n", |
2847 | GRPTYPE[command->grp_type], | 2862 | GRPTYPE[command->grp_type], |
@@ -3046,8 +3061,9 @@ static int run_list(struct pipe *pi) | |||
3046 | pi->cmds[0].argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++); | 3061 | pi->cmds[0].argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++); |
3047 | pi->cmds[0].assignment_cnt = 1; | 3062 | pi->cmds[0].assignment_cnt = 1; |
3048 | } | 3063 | } |
3049 | if (rword == RES_IN) /* "for v IN list;..." - "in" has no cmds anyway */ | 3064 | if (rword == RES_IN) { |
3050 | continue; | 3065 | continue; /* "for v IN list;..." - "in" has no cmds anyway */ |
3066 | } | ||
3051 | if (rword == RES_DONE) { | 3067 | if (rword == RES_DONE) { |
3052 | continue; /* "done" has no cmds too */ | 3068 | continue; /* "done" has no cmds too */ |
3053 | } | 3069 | } |
@@ -3603,7 +3619,8 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
3603 | debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); | 3619 | debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); |
3604 | if (reserved_word(word, ctx)) { | 3620 | if (reserved_word(word, ctx)) { |
3605 | o_reset(word); | 3621 | o_reset(word); |
3606 | debug_printf_parse("done_word return %d\n", (ctx->ctx_res_w == RES_SNTX)); | 3622 | debug_printf_parse("done_word return %d\n", |
3623 | (ctx->ctx_res_w == RES_SNTX)); | ||
3607 | return (ctx->ctx_res_w == RES_SNTX); | 3624 | return (ctx->ctx_res_w == RES_SNTX); |
3608 | } | 3625 | } |
3609 | } | 3626 | } |
@@ -3800,7 +3817,8 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
3800 | || dest->nonnull /* ""(... */ | 3817 | || dest->nonnull /* ""(... */ |
3801 | ) { | 3818 | ) { |
3802 | syntax(NULL); | 3819 | syntax(NULL); |
3803 | debug_printf_parse("parse_group return 1: syntax error, groups and arglists don't mix\n"); | 3820 | debug_printf_parse("parse_group return 1: " |
3821 | "syntax error, groups and arglists don't mix\n"); | ||
3804 | return 1; | 3822 | return 1; |
3805 | } | 3823 | } |
3806 | endch = '}'; | 3824 | endch = '}'; |
@@ -3812,7 +3830,8 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
3812 | /* empty ()/{} or parse error? */ | 3830 | /* empty ()/{} or parse error? */ |
3813 | if (!pipe_list || pipe_list == ERR_PTR) { | 3831 | if (!pipe_list || pipe_list == ERR_PTR) { |
3814 | syntax(NULL); | 3832 | syntax(NULL); |
3815 | debug_printf_parse("parse_group return 1: parse_stream returned %p\n", pipe_list); | 3833 | debug_printf_parse("parse_group return 1: " |
3834 | "parse_stream returned %p\n", pipe_list); | ||
3816 | return 1; | 3835 | return 1; |
3817 | } | 3836 | } |
3818 | command->group = pipe_list; | 3837 | command->group = pipe_list; |
@@ -3910,7 +3929,7 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db | |||
3910 | break; | 3929 | break; |
3911 | if (ch == '(') | 3930 | if (ch == '(') |
3912 | count++; | 3931 | count++; |
3913 | if (ch == ')') | 3932 | if (ch == ')') { |
3914 | if (--count < 0) { | 3933 | if (--count < 0) { |
3915 | if (!dbl) | 3934 | if (!dbl) |
3916 | break; | 3935 | break; |
@@ -3919,6 +3938,7 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db | |||
3919 | break; | 3938 | break; |
3920 | } | 3939 | } |
3921 | } | 3940 | } |
3941 | } | ||
3922 | o_addchr(dest, ch); | 3942 | o_addchr(dest, ch); |
3923 | if (ch == '\'') { | 3943 | if (ch == '\'') { |
3924 | add_till_single_quote(dest, input); | 3944 | add_till_single_quote(dest, input); |
@@ -3971,136 +3991,130 @@ static int handle_dollar(o_string *dest, struct in_str *input) | |||
3971 | o_addchr(dest, ch | quote_mask); | 3991 | o_addchr(dest, ch | quote_mask); |
3972 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 3992 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
3973 | } else switch (ch) { | 3993 | } else switch (ch) { |
3974 | case '$': /* pid */ | 3994 | case '$': /* pid */ |
3975 | case '!': /* last bg pid */ | 3995 | case '!': /* last bg pid */ |
3976 | case '?': /* last exit code */ | 3996 | case '?': /* last exit code */ |
3977 | case '#': /* number of args */ | 3997 | case '#': /* number of args */ |
3978 | case '*': /* args */ | 3998 | case '*': /* args */ |
3979 | case '@': /* args */ | 3999 | case '@': /* args */ |
3980 | goto make_one_char_var; | 4000 | goto make_one_char_var; |
3981 | case '{': { | 4001 | case '{': { |
3982 | bool first_char, all_digits; | 4002 | bool first_char, all_digits; |
3983 | 4003 | ||
3984 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4004 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
3985 | i_getch(input); | 4005 | i_getch(input); |
3986 | /* XXX maybe someone will try to escape the '}' */ | 4006 | /* XXX maybe someone will try to escape the '}' */ |
3987 | expansion = 0; | 4007 | expansion = 0; |
3988 | first_char = true; | 4008 | first_char = true; |
3989 | all_digits = false; | 4009 | all_digits = false; |
3990 | while (1) { | 4010 | while (1) { |
3991 | ch = i_getch(input); | 4011 | ch = i_getch(input); |
3992 | if (ch == '}') | 4012 | if (ch == '}') |
3993 | break; | 4013 | break; |
3994 | 4014 | ||
3995 | if (first_char) { | 4015 | if (first_char) { |
3996 | if (ch == '#') | 4016 | if (ch == '#') |
3997 | /* ${#var}: length of var contents */ | 4017 | /* ${#var}: length of var contents */ |
3998 | goto char_ok; | 4018 | goto char_ok; |
3999 | else if (isdigit(ch)) { | 4019 | else if (isdigit(ch)) { |
4000 | all_digits = true; | 4020 | all_digits = true; |
4001 | goto char_ok; | 4021 | goto char_ok; |
4002 | } | ||
4003 | } | 4022 | } |
4023 | } | ||
4004 | 4024 | ||
4005 | if (expansion < 2 && | 4025 | if (expansion < 2 |
4006 | ((all_digits && !isdigit(ch)) || | 4026 | && ( (all_digits && !isdigit(ch)) |
4007 | (!all_digits && !isalnum(ch) && ch != '_'))) | 4027 | || (!all_digits && !isalnum(ch) && ch != '_') |
4008 | { | 4028 | ) |
4009 | /* handle parameter expansions | 4029 | ) { |
4010 | * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02 | 4030 | /* handle parameter expansions |
4011 | */ | 4031 | * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02 |
4012 | if (first_char) | 4032 | */ |
4013 | goto case_default; | 4033 | if (first_char) |
4014 | switch (ch) { | 4034 | goto case_default; |
4015 | case ':': /* null modifier */ | 4035 | switch (ch) { |
4016 | if (expansion == 0) { | 4036 | case ':': /* null modifier */ |
4017 | debug_printf_parse(": null modifier\n"); | 4037 | if (expansion == 0) { |
4018 | ++expansion; | 4038 | debug_printf_parse(": null modifier\n"); |
4019 | break; | 4039 | ++expansion; |
4020 | } | 4040 | break; |
4021 | goto case_default; | 4041 | } |
4022 | 4042 | goto case_default; | |
4023 | #if 0 /* not implemented yet :( */ | 4043 | #if 0 /* not implemented yet :( */ |
4024 | case '#': /* remove prefix */ | 4044 | case '#': /* remove prefix */ |
4025 | case '%': /* remove suffix */ | 4045 | case '%': /* remove suffix */ |
4026 | if (expansion == 0) { | 4046 | if (expansion == 0) { |
4027 | debug_printf_parse(": remove suffix/prefix\n"); | 4047 | debug_printf_parse(": remove suffix/prefix\n"); |
4028 | expansion = 2; | 4048 | expansion = 2; |
4029 | break; | 4049 | break; |
4030 | } | 4050 | } |
4031 | goto case_default; | 4051 | goto case_default; |
4032 | #endif | 4052 | #endif |
4033 | 4053 | case '-': /* default value */ | |
4034 | case '-': /* default value */ | 4054 | case '=': /* assign default */ |
4035 | case '=': /* assign default */ | 4055 | case '+': /* alternative */ |
4036 | case '+': /* alternative */ | 4056 | case '?': /* error indicate */ |
4037 | case '?': /* error indicate */ | 4057 | debug_printf_parse(": parameter expansion\n"); |
4038 | debug_printf_parse(": parameter expansion\n"); | 4058 | expansion = 2; |
4039 | expansion = 2; | 4059 | break; |
4040 | break; | 4060 | default: |
4041 | 4061 | case_default: | |
4042 | default: | 4062 | syntax("unterminated ${name}"); |
4043 | case_default: | 4063 | debug_printf_parse("handle_dollar return 1: unterminated ${name}\n"); |
4044 | syntax("unterminated ${name}"); | 4064 | return 1; |
4045 | debug_printf_parse("handle_dollar return 1: unterminated ${name}\n"); | ||
4046 | return 1; | ||
4047 | } | ||
4048 | } | 4065 | } |
4049 | |||
4050 | char_ok: | ||
4051 | debug_printf_parse(": '%c'\n", ch); | ||
4052 | o_addchr(dest, ch | quote_mask); | ||
4053 | quote_mask = 0; | ||
4054 | first_char = false; | ||
4055 | } | 4066 | } |
4067 | char_ok: | ||
4068 | debug_printf_parse(": '%c'\n", ch); | ||
4069 | o_addchr(dest, ch | quote_mask); | ||
4070 | quote_mask = 0; | ||
4071 | first_char = false; | ||
4072 | } | ||
4073 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
4074 | break; | ||
4075 | } | ||
4076 | case '(': { | ||
4077 | i_getch(input); | ||
4078 | #if ENABLE_SH_MATH_SUPPORT | ||
4079 | if (i_peek(input) == '(') { | ||
4080 | i_getch(input); | ||
4081 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
4082 | o_addchr(dest, /*quote_mask |*/ '+'); | ||
4083 | add_till_closing_paren(dest, input, true); | ||
4056 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4084 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4057 | break; | 4085 | break; |
4058 | } | 4086 | } |
4059 | case '(': { | ||
4060 | i_getch(input); | ||
4061 | |||
4062 | #if ENABLE_SH_MATH_SUPPORT | ||
4063 | if (i_peek(input) == '(') { | ||
4064 | i_getch(input); | ||
4065 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
4066 | o_addchr(dest, /*quote_mask |*/ '+'); | ||
4067 | add_till_closing_paren(dest, input, true); | ||
4068 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | ||
4069 | break; | ||
4070 | } | ||
4071 | #endif | 4087 | #endif |
4072 | |||
4073 | #if ENABLE_HUSH_TICK | 4088 | #if ENABLE_HUSH_TICK |
4074 | //int pos = dest->length; | 4089 | //int pos = dest->length; |
4075 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4090 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4076 | o_addchr(dest, quote_mask | '`'); | 4091 | o_addchr(dest, quote_mask | '`'); |
4077 | add_till_closing_paren(dest, input, false); | 4092 | add_till_closing_paren(dest, input, false); |
4078 | //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos); | 4093 | //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos); |
4079 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4094 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4080 | #endif | 4095 | #endif |
4081 | break; | 4096 | break; |
4097 | } | ||
4098 | case '_': | ||
4099 | i_getch(input); | ||
4100 | ch = i_peek(input); | ||
4101 | if (isalnum(ch)) { /* it's $_name or $_123 */ | ||
4102 | ch = '_'; | ||
4103 | goto make_var; | ||
4082 | } | 4104 | } |
4083 | case '_': | 4105 | /* else: it's $_ */ |
4084 | i_getch(input); | 4106 | /* TODO: */ |
4085 | ch = i_peek(input); | 4107 | /* $_ Shell or shell script name; or last cmd name */ |
4086 | if (isalnum(ch)) { /* it's $_name or $_123 */ | 4108 | /* $- Option flags set by set builtin or shell options (-i etc) */ |
4087 | ch = '_'; | 4109 | default: |
4088 | goto make_var; | 4110 | o_addQchr(dest, '$'); |
4089 | } | ||
4090 | /* else: it's $_ */ | ||
4091 | case '-': | ||
4092 | /* still unhandled, but should be eventually */ | ||
4093 | bb_error_msg("unhandled syntax: $%c", ch); | ||
4094 | return 1; | ||
4095 | break; | ||
4096 | default: | ||
4097 | o_addQchr(dest, '$'); | ||
4098 | } | 4111 | } |
4099 | debug_printf_parse("handle_dollar return 0\n"); | 4112 | debug_printf_parse("handle_dollar return 0\n"); |
4100 | return 0; | 4113 | return 0; |
4101 | } | 4114 | } |
4102 | 4115 | ||
4103 | static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote_end) | 4116 | static int parse_stream_dquoted(o_string *dest, |
4117 | struct in_str *input, int dquote_end) | ||
4104 | { | 4118 | { |
4105 | int ch; | 4119 | int ch; |
4106 | int next; | 4120 | int next; |
@@ -4149,7 +4163,8 @@ static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote | |||
4149 | } | 4163 | } |
4150 | if (ch == '$') { | 4164 | if (ch == '$') { |
4151 | if (handle_dollar(dest, input) != 0) { | 4165 | if (handle_dollar(dest, input) != 0) { |
4152 | debug_printf_parse("parse_stream_dquoted return 1: handle_dollar returned non-0\n"); | 4166 | debug_printf_parse("parse_stream_dquoted return 1: " |
4167 | "handle_dollar returned non-0\n"); | ||
4153 | return 1; | 4168 | return 1; |
4154 | } | 4169 | } |
4155 | goto again; | 4170 | goto again; |
@@ -4196,8 +4211,8 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger) | |||
4196 | 4211 | ||
4197 | /* Double-quote state is handled in the state variable is_in_dquote. | 4212 | /* Double-quote state is handled in the state variable is_in_dquote. |
4198 | * A single-quote triggers a bypass of the main loop until its mate is | 4213 | * A single-quote triggers a bypass of the main loop until its mate is |
4199 | * found. When recursing, quote state is passed in via dest->o_escape. */ | 4214 | * found. When recursing, quote state is passed in via dest->o_escape. |
4200 | 4215 | */ | |
4201 | debug_printf_parse("parse_stream entered, end_trigger='%c'\n", | 4216 | debug_printf_parse("parse_stream entered, end_trigger='%c'\n", |
4202 | end_trigger ? : 'X'); | 4217 | end_trigger ? : 'X'); |
4203 | 4218 | ||
@@ -4338,7 +4353,8 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger) | |||
4338 | break; | 4353 | break; |
4339 | case '$': | 4354 | case '$': |
4340 | if (handle_dollar(&dest, input) != 0) { | 4355 | if (handle_dollar(&dest, input) != 0) { |
4341 | debug_printf_parse("parse_stream parse error: handle_dollar returned non-0\n"); | 4356 | debug_printf_parse("parse_stream parse error: " |
4357 | "handle_dollar returned non-0\n"); | ||
4342 | goto parse_error; | 4358 | goto parse_error; |
4343 | } | 4359 | } |
4344 | break; | 4360 | break; |
@@ -4532,8 +4548,9 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger) | |||
4532 | 4548 | ||
4533 | /* Clean up allocated tree. | 4549 | /* Clean up allocated tree. |
4534 | * Samples for finding leaks on syntax error recovery path. | 4550 | * Samples for finding leaks on syntax error recovery path. |
4535 | * Execute them from interactive shell and watch pmap `pidof hush`. | 4551 | * Run them from interactive shell, watch pmap `pidof hush`. |
4536 | * while if false; then false; fi do break; done (bash accepts it) | 4552 | * while if false; then false; fi do break; done |
4553 | * (bash accepts it) | ||
4537 | * while if false; then false; fi; do break; fi | 4554 | * while if false; then false; fi; do break; fi |
4538 | */ | 4555 | */ |
4539 | pctx = &ctx; | 4556 | pctx = &ctx; |