diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-10 21:22:02 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-10 21:22:02 +0000 |
| commit | c0ea329297862003a32570a7a38fa2bcb20e57f1 (patch) | |
| tree | 7c48bd11a6710c9e2a948bab2faf845bd44b32f0 /shell | |
| parent | b7d8c0dbbd250649d647142edd33226822f3c879 (diff) | |
| download | busybox-w32-c0ea329297862003a32570a7a38fa2bcb20e57f1.tar.gz busybox-w32-c0ea329297862003a32570a7a38fa2bcb20e57f1.tar.bz2 busybox-w32-c0ea329297862003a32570a7a38fa2bcb20e57f1.zip | |
hush: fix a few thinkos in function support; make it work on NOMMU;
functions in child shells now even have $n passed to them! :)
(in main shell it still doesn't work)
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 189 |
1 files changed, 120 insertions, 69 deletions
diff --git a/shell/hush.c b/shell/hush.c index 3728583fc..dd5031951 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -452,11 +452,16 @@ enum { | |||
| 452 | BC_CONTINUE = 2, | 452 | BC_CONTINUE = 2, |
| 453 | }; | 453 | }; |
| 454 | 454 | ||
| 455 | #if ENABLE_HUSH_FUNCTIONS | ||
| 455 | struct function { | 456 | struct function { |
| 456 | struct function *next; | 457 | struct function *next; |
| 457 | char *name; | 458 | char *name; |
| 458 | struct pipe *body; | 459 | struct pipe *body; |
| 460 | #if !BB_MMU | ||
| 461 | char *body_as_string; | ||
| 462 | #endif | ||
| 459 | }; | 463 | }; |
| 464 | #endif | ||
| 460 | 465 | ||
| 461 | 466 | ||
| 462 | /* "Globals" within this file */ | 467 | /* "Globals" within this file */ |
| @@ -510,7 +515,9 @@ struct globals { | |||
| 510 | const char *cwd; | 515 | const char *cwd; |
| 511 | struct variable *top_var; /* = &G.shell_ver (set in main()) */ | 516 | struct variable *top_var; /* = &G.shell_ver (set in main()) */ |
| 512 | struct variable shell_ver; | 517 | struct variable shell_ver; |
| 518 | #if ENABLE_HUSH_FUNCTIONS | ||
| 513 | struct function *top_func; | 519 | struct function *top_func; |
| 520 | #endif | ||
| 514 | /* Signal and trap handling */ | 521 | /* Signal and trap handling */ |
| 515 | // unsigned count_SIGCHLD; | 522 | // unsigned count_SIGCHLD; |
| 516 | // unsigned handled_SIGCHLD; | 523 | // unsigned handled_SIGCHLD; |
| @@ -675,11 +682,12 @@ static void xxfree(void *ptr) | |||
| 675 | * HUSH_DEBUG >= 2 prints line number in this file where it was detected. | 682 | * HUSH_DEBUG >= 2 prints line number in this file where it was detected. |
| 676 | */ | 683 | */ |
| 677 | #if HUSH_DEBUG < 2 | 684 | #if HUSH_DEBUG < 2 |
| 678 | # define die_if_script(lineno, fmt...) die_if_script(fmt) | 685 | # define die_if_script(lineno, fmt...) die_if_script(fmt) |
| 679 | # define syntax_error(lineno, msg) syntax_error(msg) | 686 | # define syntax_error(lineno, msg) syntax_error(msg) |
| 680 | # define syntax_error_at(lineno, msg) syntax_error_at(msg) | 687 | # define syntax_error_at(lineno, msg) syntax_error_at(msg) |
| 681 | # define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch) | 688 | # define syntax_error_unterm_ch(lineno, ch) syntax_error_unterm_ch(ch) |
| 682 | # define syntax_error_unterm_str(lineno, s) syntax_error_unterm_str(s) | 689 | # define syntax_error_unterm_str(lineno, s) syntax_error_unterm_str(s) |
| 690 | # define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch) | ||
| 683 | #endif | 691 | #endif |
| 684 | 692 | ||
| 685 | static void die_if_script(unsigned lineno, const char *fmt, ...) | 693 | static void die_if_script(unsigned lineno, const char *fmt, ...) |
| @@ -729,18 +737,29 @@ static void syntax_error_unterm_str(unsigned lineno, const char *s) | |||
| 729 | die_if_script(lineno, "syntax error: unterminated %s", s); | 737 | die_if_script(lineno, "syntax error: unterminated %s", s); |
| 730 | } | 738 | } |
| 731 | 739 | ||
| 740 | static void syntax_error_unexpected_ch(unsigned lineno, char ch) | ||
| 741 | { | ||
| 742 | char msg[2]; | ||
| 743 | msg[0] = ch; | ||
| 744 | msg[1] = '\0'; | ||
| 745 | die_if_script(lineno, "syntax error: unexpected %s", msg); | ||
| 746 | xfunc_die(); | ||
| 747 | } | ||
| 748 | |||
| 732 | #if HUSH_DEBUG < 2 | 749 | #if HUSH_DEBUG < 2 |
| 733 | # undef die_if_script | 750 | # undef die_if_script |
| 734 | # undef syntax_error | 751 | # undef syntax_error |
| 735 | # undef syntax_error_at | 752 | # undef syntax_error_at |
| 736 | # undef syntax_error_unterm_ch | 753 | # undef syntax_error_unterm_ch |
| 737 | # undef syntax_error_unterm_str | 754 | # undef syntax_error_unterm_str |
| 755 | # undef syntax_error_unexpected_ch | ||
| 738 | #else | 756 | #else |
| 739 | # define die_if_script(fmt...) die_if_script(__LINE__, fmt) | 757 | # define die_if_script(fmt...) die_if_script(__LINE__, fmt) |
| 740 | # define syntax_error(msg) syntax_error(__LINE__, msg) | 758 | # define syntax_error(msg) syntax_error(__LINE__, msg) |
| 741 | # define syntax_error_at(msg) syntax_error_at(__LINE__, msg) | 759 | # define syntax_error_at(msg) syntax_error_at(__LINE__, msg) |
| 742 | # define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch) | 760 | # define syntax_error_unterm_ch(ch) syntax_error_unterm_ch(__LINE__, ch) |
| 743 | # define syntax_error_unterm_str(s) syntax_error_unterm_str(__LINE__, s) | 761 | # define syntax_error_unterm_str(s) syntax_error_unterm_str(__LINE__, s) |
| 762 | # define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch) | ||
| 744 | #endif | 763 | #endif |
| 745 | 764 | ||
| 746 | 765 | ||
| @@ -2234,8 +2253,11 @@ static char **expand_assignments(char **argv, int count) | |||
| 2234 | 2253 | ||
| 2235 | 2254 | ||
| 2236 | #if BB_MMU | 2255 | #if BB_MMU |
| 2237 | void re_execute_shell(const char *s, int is_heredoc); /* never called */ | 2256 | /* never called */ |
| 2257 | void re_execute_shell(const char *s, char *argv0, char **argv); | ||
| 2258 | |||
| 2238 | #define clean_up_after_re_execute() ((void)0) | 2259 | #define clean_up_after_re_execute() ((void)0) |
| 2260 | |||
| 2239 | static void reset_traps_to_defaults(void) | 2261 | static void reset_traps_to_defaults(void) |
| 2240 | { | 2262 | { |
| 2241 | unsigned sig; | 2263 | unsigned sig; |
| @@ -2266,16 +2288,16 @@ static void reset_traps_to_defaults(void) | |||
| 2266 | 2288 | ||
| 2267 | #else /* !BB_MMU */ | 2289 | #else /* !BB_MMU */ |
| 2268 | 2290 | ||
| 2269 | static void re_execute_shell(const char *s, int is_heredoc) NORETURN; | 2291 | static void re_execute_shell(const char *s, char *g_argv0, char **g_argv) NORETURN; |
| 2270 | static void re_execute_shell(const char *s, int is_heredoc) | 2292 | static void re_execute_shell(const char *s, char *g_argv0, char **g_argv) |
| 2271 | { | 2293 | { |
| 2272 | char param_buf[sizeof("-$%x:%x:%x:%x") + sizeof(unsigned) * 4]; | 2294 | char param_buf[sizeof("-$%x:%x:%x:%x") + sizeof(unsigned) * 4]; |
| 2273 | char *heredoc_argv[4]; | 2295 | char *heredoc_argv[4]; |
| 2274 | struct variable *cur; | 2296 | struct variable *cur; |
| 2275 | char **argv, **pp, **pp2; | 2297 | char **argv, **pp; |
| 2276 | unsigned cnt; | 2298 | unsigned cnt; |
| 2277 | 2299 | ||
| 2278 | if (is_heredoc) { | 2300 | if (!g_argv0) { /* heredoc */ |
| 2279 | argv = heredoc_argv; | 2301 | argv = heredoc_argv; |
| 2280 | argv[0] = (char *) G.argv0_for_re_execing; | 2302 | argv[0] = (char *) G.argv0_for_re_execing; |
| 2281 | argv[1] = (char *) "-<"; | 2303 | argv[1] = (char *) "-<"; |
| @@ -2292,13 +2314,16 @@ static void re_execute_shell(const char *s, int is_heredoc) | |||
| 2292 | USE_HUSH_LOOPS(, G.depth_of_loop) | 2314 | USE_HUSH_LOOPS(, G.depth_of_loop) |
| 2293 | ); | 2315 | ); |
| 2294 | /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<depth> <vars...> | 2316 | /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<depth> <vars...> |
| 2295 | * 3:-c 4:<cmd> <argN...> 5:NULL | 2317 | * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL |
| 2296 | */ | 2318 | */ |
| 2297 | cnt = 5 + G.global_argc; | 2319 | cnt = 6; |
| 2298 | for (cur = G.top_var; cur; cur = cur->next) { | 2320 | for (cur = G.top_var; cur; cur = cur->next) { |
| 2299 | if (!cur->flg_export || cur->flg_read_only) | 2321 | if (!cur->flg_export || cur->flg_read_only) |
| 2300 | cnt += 2; | 2322 | cnt += 2; |
| 2301 | } | 2323 | } |
| 2324 | pp = g_argv; | ||
| 2325 | while (*pp++) | ||
| 2326 | cnt++; | ||
| 2302 | G.argv_from_re_execing = argv = pp = xzalloc(sizeof(argv[0]) * cnt); | 2327 | G.argv_from_re_execing = argv = pp = xzalloc(sizeof(argv[0]) * cnt); |
| 2303 | *pp++ = (char *) G.argv0_for_re_execing; | 2328 | *pp++ = (char *) G.argv0_for_re_execing; |
| 2304 | *pp++ = param_buf; | 2329 | *pp++ = param_buf; |
| @@ -2335,9 +2360,9 @@ static void re_execute_shell(const char *s, int is_heredoc) | |||
| 2335 | */ | 2360 | */ |
| 2336 | *pp++ = (char *) "-c"; | 2361 | *pp++ = (char *) "-c"; |
| 2337 | *pp++ = (char *) s; | 2362 | *pp++ = (char *) s; |
| 2338 | pp2 = G.global_argv; | 2363 | *pp++ = g_argv0; |
| 2339 | while (*pp2) | 2364 | while (*g_argv) |
| 2340 | *pp++ = *pp2++; | 2365 | *pp++ = *g_argv++; |
| 2341 | /* *pp = NULL; - is already there */ | 2366 | /* *pp = NULL; - is already there */ |
| 2342 | pp = environ; | 2367 | pp = environ; |
| 2343 | 2368 | ||
| @@ -2426,7 +2451,7 @@ static void setup_heredoc(struct redir_struct *redir) | |||
| 2426 | /* Delegate blocking writes to another process */ | 2451 | /* Delegate blocking writes to another process */ |
| 2427 | disable_restore_tty_pgrp_on_exit(); | 2452 | disable_restore_tty_pgrp_on_exit(); |
| 2428 | xmove_fd(pair.wr, STDOUT_FILENO); | 2453 | xmove_fd(pair.wr, STDOUT_FILENO); |
| 2429 | re_execute_shell(heredoc, 1); | 2454 | re_execute_shell(heredoc, NULL, NULL); |
| 2430 | #endif | 2455 | #endif |
| 2431 | } | 2456 | } |
| 2432 | /* parent */ | 2457 | /* parent */ |
| @@ -2592,6 +2617,8 @@ static void free_pipe_list(struct pipe *head, int indent) | |||
| 2592 | } | 2617 | } |
| 2593 | 2618 | ||
| 2594 | 2619 | ||
| 2620 | static int run_list(struct pipe *pi); | ||
| 2621 | |||
| 2595 | static const struct built_in_command* find_builtin(const char *name) | 2622 | static const struct built_in_command* find_builtin(const char *name) |
| 2596 | { | 2623 | { |
| 2597 | const struct built_in_command *x; | 2624 | const struct built_in_command *x; |
| @@ -2604,22 +2631,39 @@ static const struct built_in_command* find_builtin(const char *name) | |||
| 2604 | return NULL; | 2631 | return NULL; |
| 2605 | } | 2632 | } |
| 2606 | 2633 | ||
| 2607 | # if ENABLE_HUSH_FUNCTIONS | 2634 | #if ENABLE_HUSH_FUNCTIONS |
| 2608 | static const struct function *find_function(const char *name) | 2635 | static const struct function *find_function(const char *name) |
| 2609 | { | 2636 | { |
| 2610 | const struct function *funcp = G.top_func; | 2637 | const struct function *funcp = G.top_func; |
| 2611 | while (funcp) { | 2638 | while (funcp) { |
| 2612 | if (strcmp(name, funcp->name) != 0) | 2639 | if (strcmp(name, funcp->name) == 0) { |
| 2613 | continue; | 2640 | break; |
| 2614 | return funcp; | 2641 | } |
| 2615 | debug_printf_exec("found function '%s'\n", name); | 2642 | funcp = funcp->next; |
| 2616 | } | 2643 | } |
| 2617 | return NULL; | 2644 | debug_printf_exec("found function '%s'\n", name); |
| 2645 | return funcp; | ||
| 2618 | } | 2646 | } |
| 2619 | #endif | 2647 | static void exec_function(const struct function *funcp, char **argv) NORETURN; |
| 2648 | static void exec_function(const struct function *funcp, char **argv) | ||
| 2649 | { | ||
| 2650 | # if BB_MMU | ||
| 2651 | int n = 1; | ||
| 2620 | 2652 | ||
| 2653 | argv[0] = G.global_argv[0]; | ||
| 2654 | G.global_argv = argv; | ||
| 2655 | while (*++argv) | ||
| 2656 | n++; | ||
| 2657 | G.global_argc = n; | ||
| 2658 | n = run_list(funcp->body); | ||
| 2659 | fflush(NULL); | ||
| 2660 | _exit(n); | ||
| 2661 | # else | ||
| 2662 | re_execute_shell(funcp->body_as_string, G.global_argv[0], argv + 1); | ||
| 2663 | #endif | ||
| 2664 | } | ||
| 2665 | #endif | ||
| 2621 | 2666 | ||
| 2622 | static int run_list(struct pipe *pi); | ||
| 2623 | 2667 | ||
| 2624 | #if BB_MMU | 2668 | #if BB_MMU |
| 2625 | #define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \ | 2669 | #define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \ |
| @@ -2688,18 +2732,15 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save, | |||
| 2688 | _exit(rcode); | 2732 | _exit(rcode); |
| 2689 | } | 2733 | } |
| 2690 | } | 2734 | } |
| 2691 | # if ENABLE_HUSH_FUNCTIONS | 2735 | #endif |
| 2736 | #if ENABLE_HUSH_FUNCTIONS | ||
| 2692 | /* Check if the command matches any functions */ | 2737 | /* Check if the command matches any functions */ |
| 2693 | { | 2738 | { |
| 2694 | int rcode; | ||
| 2695 | const struct function *funcp = find_function(argv[0]); | 2739 | const struct function *funcp = find_function(argv[0]); |
| 2696 | if (funcp) { | 2740 | if (funcp) { |
| 2697 | rcode = run_list(funcp->body); | 2741 | exec_function(funcp, argv); |
| 2698 | fflush(NULL); | ||
| 2699 | _exit(rcode); | ||
| 2700 | } | 2742 | } |
| 2701 | } | 2743 | } |
| 2702 | # endif | ||
| 2703 | #endif | 2744 | #endif |
| 2704 | 2745 | ||
| 2705 | #if ENABLE_FEATURE_SH_STANDALONE | 2746 | #if ENABLE_FEATURE_SH_STANDALONE |
| @@ -2723,7 +2764,9 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save, | |||
| 2723 | } | 2764 | } |
| 2724 | #endif | 2765 | #endif |
| 2725 | 2766 | ||
| 2767 | #if ENABLE_FEATURE_SH_STANDALONE || BB_MMU | ||
| 2726 | skip: | 2768 | skip: |
| 2769 | #endif | ||
| 2727 | debug_printf_exec("execing '%s'\n", argv[0]); | 2770 | debug_printf_exec("execing '%s'\n", argv[0]); |
| 2728 | sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); | 2771 | sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); |
| 2729 | execvp(argv[0], argv); | 2772 | execvp(argv[0], argv); |
| @@ -2761,7 +2804,9 @@ static void pseudo_exec(nommu_save_t *nommu_save, | |||
| 2761 | * since this process is about to exit */ | 2804 | * since this process is about to exit */ |
| 2762 | _exit(rcode); | 2805 | _exit(rcode); |
| 2763 | #else | 2806 | #else |
| 2764 | re_execute_shell(command->group_as_string, 0); | 2807 | re_execute_shell(command->group_as_string, |
| 2808 | G.global_argv[0], | ||
| 2809 | G.global_argv + 1); | ||
| 2765 | #endif | 2810 | #endif |
| 2766 | } | 2811 | } |
| 2767 | 2812 | ||
| @@ -3085,19 +3130,23 @@ static int run_pipe(struct pipe *pi) | |||
| 3085 | 3130 | ||
| 3086 | while ((funcp = *funcpp) != NULL) { | 3131 | while ((funcp = *funcpp) != NULL) { |
| 3087 | if (strcmp(funcp->name, command->argv[0]) == 0) { | 3132 | if (strcmp(funcp->name, command->argv[0]) == 0) { |
| 3088 | debug_printf_exec("replacing function '%s'", funcp->name); | 3133 | debug_printf_exec("replacing function '%s'\n", funcp->name); |
| 3089 | free(funcp->name); | 3134 | free(funcp->name); |
| 3090 | free_pipe_list(funcp->body, /* indent: */ 0); | 3135 | free_pipe_list(funcp->body, /* indent: */ 0); |
| 3091 | goto skip; | 3136 | goto skip; |
| 3092 | } | 3137 | } |
| 3093 | funcpp = &funcp->next; | 3138 | funcpp = &funcp->next; |
| 3094 | } | 3139 | } |
| 3095 | debug_printf_exec("remembering new function '%s'", funcp->name); | 3140 | debug_printf_exec("remembering new function '%s'\n", command->argv[0]); |
| 3096 | funcp = *funcpp = xzalloc(sizeof(*funcp)); | 3141 | funcp = *funcpp = xzalloc(sizeof(*funcp)); |
| 3097 | /*funcp->next = NULL;*/ | 3142 | /*funcp->next = NULL;*/ |
| 3098 | skip: | 3143 | skip: |
| 3099 | funcp->name = command->argv[0]; | 3144 | funcp->name = command->argv[0]; |
| 3100 | funcp->body = command->group; | 3145 | funcp->body = command->group; |
| 3146 | #if !BB_MMU | ||
| 3147 | funcp->body_as_string = command->group_as_string; | ||
| 3148 | command->group_as_string = NULL; | ||
| 3149 | #endif | ||
| 3101 | command->group = NULL; | 3150 | command->group = NULL; |
| 3102 | command->argv[0] = NULL; | 3151 | command->argv[0] = NULL; |
| 3103 | free_strings(command->argv); | 3152 | free_strings(command->argv); |
| @@ -3160,6 +3209,7 @@ static int run_pipe(struct pipe *pi) | |||
| 3160 | 3209 | ||
| 3161 | x = find_builtin(argv_expanded[0]); | 3210 | x = find_builtin(argv_expanded[0]); |
| 3162 | #if ENABLE_HUSH_FUNCTIONS | 3211 | #if ENABLE_HUSH_FUNCTIONS |
| 3212 | funcp = NULL; | ||
| 3163 | if (!x) | 3213 | if (!x) |
| 3164 | funcp = find_function(argv_expanded[0]); | 3214 | funcp = find_function(argv_expanded[0]); |
| 3165 | #endif | 3215 | #endif |
| @@ -3171,7 +3221,6 @@ static int run_pipe(struct pipe *pi) | |||
| 3171 | goto clean_up_and_ret1; | 3221 | goto clean_up_and_ret1; |
| 3172 | } | 3222 | } |
| 3173 | } | 3223 | } |
| 3174 | debug_printf("builtin inline %s\n", argv_expanded[0]); | ||
| 3175 | /* XXX setup_redirects acts on file descriptors, not FILEs. | 3224 | /* XXX setup_redirects acts on file descriptors, not FILEs. |
| 3176 | * This is perfect for work that comes after exec(). | 3225 | * This is perfect for work that comes after exec(). |
| 3177 | * Is it really safe for inline use? Experimentally, | 3226 | * Is it really safe for inline use? Experimentally, |
| @@ -3681,7 +3730,7 @@ static int run_list(struct pipe *pi) | |||
| 3681 | /* We only ran a builtin: rcode is already known | 3730 | /* We only ran a builtin: rcode is already known |
| 3682 | * and we don't need to wait for anything. */ | 3731 | * and we don't need to wait for anything. */ |
| 3683 | G.last_exitcode = rcode; | 3732 | G.last_exitcode = rcode; |
| 3684 | debug_printf_exec(": builtin exitcode %d\n", rcode); | 3733 | debug_printf_exec(": builtin/func exitcode %d\n", rcode); |
| 3685 | check_and_run_traps(0); | 3734 | check_and_run_traps(0); |
| 3686 | #if ENABLE_HUSH_LOOPS | 3735 | #if ENABLE_HUSH_LOOPS |
| 3687 | /* Was it "break" or "continue"? */ | 3736 | /* Was it "break" or "continue"? */ |
| @@ -4497,7 +4546,9 @@ static FILE *generate_stream_from_string(const char *s) | |||
| 4497 | * huge=`cat BIG` # was blocking here forever | 4546 | * huge=`cat BIG` # was blocking here forever |
| 4498 | * echo OK | 4547 | * echo OK |
| 4499 | */ | 4548 | */ |
| 4500 | re_execute_shell(s, 0); | 4549 | re_execute_shell(s, |
| 4550 | G.global_argv[0], | ||
| 4551 | G.global_argv + 1); | ||
| 4501 | #endif | 4552 | #endif |
| 4502 | } | 4553 | } |
| 4503 | 4554 | ||
| @@ -4561,34 +4612,34 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
| 4561 | 4612 | ||
| 4562 | debug_printf_parse("parse_group entered\n"); | 4613 | debug_printf_parse("parse_group entered\n"); |
| 4563 | #if ENABLE_HUSH_FUNCTIONS | 4614 | #if ENABLE_HUSH_FUNCTIONS |
| 4564 | if (ch == '(') { | 4615 | if (ch == '(' && !dest->o_quoted) { |
| 4565 | if (!dest->o_quoted) { | 4616 | if (dest->length) |
| 4566 | if (dest->length) | 4617 | done_word(dest, ctx); |
| 4567 | done_word(dest, ctx); | 4618 | if (!command->argv) |
| 4568 | if (!command->argv) | 4619 | goto skip; /* (... */ |
| 4569 | goto skip; /* (... */ | 4620 | if (command->argv[1]) { /* word word ... (... */ |
| 4570 | if (command->argv[1]) { /* word word ... (... */ | 4621 | syntax_error_unexpected_ch('('); |
| 4571 | syntax_error("unexpected character ("); | 4622 | return 1; |
| 4572 | return 1; | ||
| 4573 | } | ||
| 4574 | /* it is "word(..." or "word (..." */ | ||
| 4575 | do | ||
| 4576 | ch = i_getch(input); | ||
| 4577 | while (ch == ' ' || ch == '\t'); | ||
| 4578 | if (ch != ')') { | ||
| 4579 | syntax_error("unexpected character X"); | ||
| 4580 | return 1; | ||
| 4581 | } | ||
| 4582 | do | ||
| 4583 | ch = i_getch(input); | ||
| 4584 | while (ch == ' ' || ch == '\t' || ch == '\n'); | ||
| 4585 | if (ch != '{') { | ||
| 4586 | syntax_error("unexpected character X"); | ||
| 4587 | return 1; | ||
| 4588 | } | ||
| 4589 | command->grp_type = GRP_FUNCTION; | ||
| 4590 | goto skip; | ||
| 4591 | } | 4623 | } |
| 4624 | /* it is "word(..." or "word (..." */ | ||
| 4625 | do | ||
| 4626 | ch = i_getch(input); | ||
| 4627 | while (ch == ' ' || ch == '\t'); | ||
| 4628 | if (ch != ')') { | ||
| 4629 | syntax_error_unexpected_ch(ch); | ||
| 4630 | return 1; | ||
| 4631 | } | ||
| 4632 | nommu_addchr(&ctx->as_string, ch); | ||
| 4633 | do | ||
| 4634 | ch = i_getch(input); | ||
| 4635 | while (ch == ' ' || ch == '\t' || ch == '\n'); | ||
| 4636 | if (ch != '{') { | ||
| 4637 | syntax_error_unexpected_ch(ch); | ||
| 4638 | return 1; | ||
| 4639 | } | ||
| 4640 | nommu_addchr(&ctx->as_string, ch); | ||
| 4641 | command->grp_type = GRP_FUNCTION; | ||
| 4642 | goto skip; | ||
| 4592 | } | 4643 | } |
| 4593 | #endif | 4644 | #endif |
| 4594 | if (command->argv /* word [word]{... */ | 4645 | if (command->argv /* word [word]{... */ |
| @@ -5452,7 +5503,7 @@ static struct pipe *parse_stream(char **pstring, | |||
| 5452 | /* proper use of this character is caught by end_trigger: | 5503 | /* proper use of this character is caught by end_trigger: |
| 5453 | * if we see {, we call parse_group(..., end_trigger='}') | 5504 | * if we see {, we call parse_group(..., end_trigger='}') |
| 5454 | * and it will match } earlier (not here). */ | 5505 | * and it will match } earlier (not here). */ |
| 5455 | syntax_error("unexpected } or )"); | 5506 | syntax_error_unexpected_ch(ch); |
| 5456 | goto parse_error; | 5507 | goto parse_error; |
| 5457 | default: | 5508 | default: |
| 5458 | if (HUSH_DEBUG) | 5509 | if (HUSH_DEBUG) |
