summaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-05-23 15:22:50 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-05-23 15:22:50 +0000
commit90e485ce79b8a0cd345bc5be76100291ec589579 (patch)
treeb994e960b598f802820ddd5cf712678903c404de /shell/hush.c
parent1744cb18610aece474ba080f43aa5dc89177388e (diff)
downloadbusybox-w32-90e485ce79b8a0cd345bc5be76100291ec589579.tar.gz
busybox-w32-90e485ce79b8a0cd345bc5be76100291ec589579.tar.bz2
busybox-w32-90e485ce79b8a0cd345bc5be76100291ec589579.zip
hush: make syntax error messages a bit more useful
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 1545b041f..579950ff9 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -423,11 +423,20 @@ enum { run_list_level = 0 };
423#define B_NOSPAC 1 423#define B_NOSPAC 1
424#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" 424#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
425 425
426static void __syntax(int line) 426#if 1
427/* Normal */
428static void syntax(const char *msg)
429{
430 bb_error_msg(msg ? "%s: %s" : "syntax error", "syntax error", msg);
431}
432#else
433/* Debug */
434static void syntax_lineno(int line)
427{ 435{
428 bb_error_msg("syntax error hush.c:%d", line); 436 bb_error_msg("syntax error hush.c:%d", line);
429} 437}
430#define syntax() __syntax(__LINE__) 438#define syntax(str) syntax_lineno(__LINE__)
439#endif
431 440
432/* Index of subroutines: */ 441/* Index of subroutines: */
433/* function prototypes for builtins */ 442/* function prototypes for builtins */
@@ -1981,7 +1990,7 @@ static int run_list_real(struct pipe *pi)
1981 if ((rpipe->res_word == RES_IN || rpipe->res_word == RES_FOR) 1990 if ((rpipe->res_word == RES_IN || rpipe->res_word == RES_FOR)
1982 && (rpipe->next == NULL) 1991 && (rpipe->next == NULL)
1983 ) { 1992 ) {
1984 syntax(); /* unterminated FOR (no IN or no commands after IN) */ 1993 syntax("malformed for"); /* no IN or no commands after IN */
1985 debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); 1994 debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level);
1986 return 1; 1995 return 1;
1987 } 1996 }
@@ -1989,7 +1998,7 @@ static int run_list_real(struct pipe *pi)
1989 || (rpipe->res_word == RES_FOR && rpipe->next->res_word != RES_IN) 1998 || (rpipe->res_word == RES_FOR && rpipe->next->res_word != RES_IN)
1990 ) { 1999 ) {
1991 /* TODO: what is tested in the first condition? */ 2000 /* TODO: what is tested in the first condition? */
1992 syntax(); /* 2nd: malformed FOR (not followed by IN) */ 2001 syntax("malformed for"); /* 2nd condition: not followed by IN */
1993 debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); 2002 debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level);
1994 return 1; 2003 return 1;
1995 } 2004 }
@@ -2914,7 +2923,7 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
2914 debug_printf("push stack\n"); 2923 debug_printf("push stack\n");
2915#if ENABLE_HUSH_LOOPS 2924#if ENABLE_HUSH_LOOPS
2916 if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) { 2925 if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
2917 syntax(); 2926 syntax("malformed for"); /* example: 'for if' */
2918 ctx->res_w = RES_SNTX; 2927 ctx->res_w = RES_SNTX;
2919 b_reset(dest); 2928 b_reset(dest);
2920 return 1; 2929 return 1;
@@ -2925,7 +2934,7 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
2925 initialize_context(ctx); 2934 initialize_context(ctx);
2926 ctx->stack = new; 2935 ctx->stack = new;
2927 } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) { 2936 } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
2928 syntax(); 2937 syntax(NULL);
2929 ctx->res_w = RES_SNTX; 2938 ctx->res_w = RES_SNTX;
2930 b_reset(dest); 2939 b_reset(dest);
2931 return 1; 2940 return 1;
@@ -2968,7 +2977,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
2968 glob_target = &ctx->pending_redirect->word; 2977 glob_target = &ctx->pending_redirect->word;
2969 } else { 2978 } else {
2970 if (child->group) { 2979 if (child->group) {
2971 syntax(); 2980 syntax(NULL);
2972 debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); 2981 debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
2973 return 1; 2982 return 1;
2974 } 2983 }
@@ -3224,21 +3233,15 @@ static int parse_group(o_string *dest, struct p_context *ctx,
3224 3233
3225 debug_printf_parse("parse_group entered\n"); 3234 debug_printf_parse("parse_group entered\n");
3226 if (child->argv) { 3235 if (child->argv) {
3227 syntax(); 3236 syntax(NULL);
3228 debug_printf_parse("parse_group return 1: syntax error, groups and arglists don't mix\n"); 3237 debug_printf_parse("parse_group return 1: syntax error, groups and arglists don't mix\n");
3229 return 1; 3238 return 1;
3230 } 3239 }
3231 initialize_context(&sub); 3240 initialize_context(&sub);
3232 switch (ch) { 3241 endch = "}";
3233 case '(': 3242 if (ch == '(') {
3234 endch = ")"; 3243 endch = ")";
3235 child->subshell = 1; 3244 child->subshell = 1;
3236 break;
3237 case '{':
3238 endch = "}";
3239 break;
3240 default:
3241 syntax(); /* really logic error */
3242 } 3245 }
3243 rcode = parse_stream(dest, &sub, input, endch); 3246 rcode = parse_stream(dest, &sub, input, endch);
3244 done_word(dest, &sub); /* finish off the final word in the subcontext */ 3247 done_word(dest, &sub); /* finish off the final word in the subcontext */
@@ -3307,7 +3310,7 @@ static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *i
3307 while (1) { 3310 while (1) {
3308 ch = b_getch(input); 3311 ch = b_getch(input);
3309 if (ch == EOF) { 3312 if (ch == EOF) {
3310 syntax(); 3313 syntax("unterminated ${name}");
3311 debug_printf_parse("handle_dollar return 1: unterminated ${name}\n"); 3314 debug_printf_parse("handle_dollar return 1: unterminated ${name}\n");
3312 return 1; 3315 return 1;
3313 } 3316 }
@@ -3368,7 +3371,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3368 || (m != CHAR_SPECIAL && dest->quote) 3371 || (m != CHAR_SPECIAL && dest->quote)
3369 ) { 3372 ) {
3370 if (ch == EOF) { 3373 if (ch == EOF) {
3371 syntax(); 3374 syntax("unterminated \"");
3372 debug_printf_parse("parse_stream return 1: unterminated \"\n"); 3375 debug_printf_parse("parse_stream return 1: unterminated \"\n");
3373 return 1; 3376 return 1;
3374 } 3377 }
@@ -3412,7 +3415,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3412 break; 3415 break;
3413 case '\\': 3416 case '\\':
3414 if (next == EOF) { 3417 if (next == EOF) {
3415 syntax(); 3418 syntax("\\<eof>");
3416 debug_printf_parse("parse_stream return 1: \\<eof>\n"); 3419 debug_printf_parse("parse_stream return 1: \\<eof>\n");
3417 return 1; 3420 return 1;
3418 } 3421 }
@@ -3434,7 +3437,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3434 b_addchr(dest, ch); 3437 b_addchr(dest, ch);
3435 } 3438 }
3436 if (ch == EOF) { 3439 if (ch == EOF) {
3437 syntax(); 3440 syntax("unterminated '");
3438 debug_printf_parse("parse_stream return 1: unterminated '\n"); 3441 debug_printf_parse("parse_stream return 1: unterminated '\n");
3439 return 1; 3442 return 1;
3440 } 3443 }
@@ -3455,11 +3458,14 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3455 if (next == '>') { 3458 if (next == '>') {
3456 redir_style = REDIRECT_APPEND; 3459 redir_style = REDIRECT_APPEND;
3457 b_getch(input); 3460 b_getch(input);
3458 } else if (next == '(') { 3461 }
3459 syntax(); /* until we support >(list) Process Substitution */ 3462#if 0
3463 else if (next == '(') {
3464 syntax(">(process) not supported");
3460 debug_printf_parse("parse_stream return 1: >(process) not supported\n"); 3465 debug_printf_parse("parse_stream return 1: >(process) not supported\n");
3461 return 1; 3466 return 1;
3462 } 3467 }
3468#endif
3463 setup_redirect(ctx, redir_fd, redir_style, input); 3469 setup_redirect(ctx, redir_fd, redir_style, input);
3464 break; 3470 break;
3465 case '<': 3471 case '<':
@@ -3472,11 +3478,14 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3472 } else if (next == '>') { 3478 } else if (next == '>') {
3473 redir_style = REDIRECT_IO; 3479 redir_style = REDIRECT_IO;
3474 b_getch(input); 3480 b_getch(input);
3475 } else if (next == '(') { 3481 }
3476 syntax(); /* until we support <(list) Process Substitution */ 3482#if 0
3483 else if (next == '(') {
3484 syntax("<(process) not supported");
3477 debug_printf_parse("parse_stream return 1: <(process) not supported\n"); 3485 debug_printf_parse("parse_stream return 1: <(process) not supported\n");
3478 return 1; 3486 return 1;
3479 } 3487 }
3488#endif
3480 setup_redirect(ctx, redir_fd, redir_style, input); 3489 setup_redirect(ctx, redir_fd, redir_style, input);
3481 break; 3490 break;
3482 case ';': 3491 case ';':
@@ -3513,13 +3522,12 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3513 break; 3522 break;
3514 case ')': 3523 case ')':
3515 case '}': 3524 case '}':
3516 syntax(); /* Proper use of this character is caught by end_trigger */ 3525 syntax("unexpected }"); /* Proper use of this character is caught by end_trigger */
3517 debug_printf_parse("parse_stream return 1: unexpected '}'\n"); 3526 debug_printf_parse("parse_stream return 1: unexpected '}'\n");
3518 return 1; 3527 return 1;
3519 default: 3528 default:
3520 syntax(); /* this is really an internal logic error */ 3529 if (ENABLE_HUSH_DEBUG)
3521 debug_printf_parse("parse_stream return 1: internal logic error\n"); 3530 bb_error_msg_and_die("BUG: unexpected %c\n", ch);
3522 return 1;
3523 } 3531 }
3524 } 3532 }
3525 /* Complain if quote? No, maybe we just finished a command substitution 3533 /* Complain if quote? No, maybe we just finished a command substitution
@@ -3585,7 +3593,7 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
3585 * TEST should be printed */ 3593 * TEST should be printed */
3586 rcode = parse_stream(&temp, &ctx, inp, ";\n"); 3594 rcode = parse_stream(&temp, &ctx, inp, ";\n");
3587 if (rcode != 1 && ctx.old_flag != 0) { 3595 if (rcode != 1 && ctx.old_flag != 0) {
3588 syntax(); 3596 syntax(NULL);
3589 } 3597 }
3590 if (rcode != 1 && ctx.old_flag == 0) { 3598 if (rcode != 1 && ctx.old_flag == 0) {
3591 done_word(&temp, &ctx); 3599 done_word(&temp, &ctx);