diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-30 18:54:52 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-03-30 18:54:52 +0200 |
commit | cecbc986112cdd5ce95d15221979edf4281f5f7f (patch) | |
tree | 5a6ce9c9206e60a64afae229dac73491c7019ec5 | |
parent | 0e89fd9c39655fe721dd8a7a09a6c532f4255c42 (diff) | |
download | busybox-w32-cecbc986112cdd5ce95d15221979edf4281f5f7f.tar.gz busybox-w32-cecbc986112cdd5ce95d15221979edf4281f5f7f.tar.bz2 busybox-w32-cecbc986112cdd5ce95d15221979edf4281f5f7f.zip |
hush: fix source1.tests
function old new delta
parse_and_run_stream 95 139 +44
static_get 22 25 +3
file_get 260 263 +3
builtin_umask 133 132 -1
parse_stream 2442 2425 -17
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/2 up/down: 50/-18) Total: 32 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 64 |
1 files changed, 37 insertions, 27 deletions
diff --git a/shell/hush.c b/shell/hush.c index e4c3a7d77..a47652470 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -445,8 +445,6 @@ enum { | |||
445 | /* Used for initialization: o_string foo = NULL_O_STRING; */ | 445 | /* Used for initialization: o_string foo = NULL_O_STRING; */ |
446 | #define NULL_O_STRING { NULL } | 446 | #define NULL_O_STRING { NULL } |
447 | 447 | ||
448 | /* I can almost use ordinary FILE*. Is open_memstream() universally | ||
449 | * available? Where is it documented? */ | ||
450 | typedef struct in_str { | 448 | typedef struct in_str { |
451 | const char *p; | 449 | const char *p; |
452 | /* eof_flag=1: last char in ->p is really an EOF */ | 450 | /* eof_flag=1: last char in ->p is really an EOF */ |
@@ -455,6 +453,7 @@ typedef struct in_str { | |||
455 | #if ENABLE_HUSH_INTERACTIVE | 453 | #if ENABLE_HUSH_INTERACTIVE |
456 | smallint promptmode; /* 0: PS1, 1: PS2 */ | 454 | smallint promptmode; /* 0: PS1, 1: PS2 */ |
457 | #endif | 455 | #endif |
456 | int last_char; | ||
458 | FILE *file; | 457 | FILE *file; |
459 | int (*get) (struct in_str *) FAST_FUNC; | 458 | int (*get) (struct in_str *) FAST_FUNC; |
460 | int (*peek) (struct in_str *) FAST_FUNC; | 459 | int (*peek) (struct in_str *) FAST_FUNC; |
@@ -1077,22 +1076,22 @@ static void die_if_script(unsigned lineno, const char *fmt, ...) | |||
1077 | xfunc_die(); | 1076 | xfunc_die(); |
1078 | } | 1077 | } |
1079 | 1078 | ||
1080 | static void syntax_error(unsigned lineno, const char *msg) | 1079 | static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg) |
1081 | { | 1080 | { |
1082 | if (msg) | 1081 | if (msg) |
1083 | die_if_script(lineno, "syntax error: %s", msg); | 1082 | bb_error_msg("syntax error: %s", msg); |
1084 | else | 1083 | else |
1085 | die_if_script(lineno, "syntax error", NULL); | 1084 | bb_error_msg("syntax error"); |
1086 | } | 1085 | } |
1087 | 1086 | ||
1088 | static void syntax_error_at(unsigned lineno, const char *msg) | 1087 | static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg) |
1089 | { | 1088 | { |
1090 | die_if_script(lineno, "syntax error at '%s'", msg); | 1089 | bb_error_msg("syntax error at '%s'", msg); |
1091 | } | 1090 | } |
1092 | 1091 | ||
1093 | static void syntax_error_unterm_str(unsigned lineno, const char *s) | 1092 | static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s) |
1094 | { | 1093 | { |
1095 | die_if_script(lineno, "syntax error: unterminated %s", s); | 1094 | bb_error_msg("syntax error: unterminated %s", s); |
1096 | } | 1095 | } |
1097 | 1096 | ||
1098 | static void syntax_error_unterm_ch(unsigned lineno, char ch) | 1097 | static void syntax_error_unterm_ch(unsigned lineno, char ch) |
@@ -1101,12 +1100,12 @@ static void syntax_error_unterm_ch(unsigned lineno, char ch) | |||
1101 | syntax_error_unterm_str(lineno, msg); | 1100 | syntax_error_unterm_str(lineno, msg); |
1102 | } | 1101 | } |
1103 | 1102 | ||
1104 | static void syntax_error_unexpected_ch(unsigned lineno, int ch) | 1103 | static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch) |
1105 | { | 1104 | { |
1106 | char msg[2]; | 1105 | char msg[2]; |
1107 | msg[0] = ch; | 1106 | msg[0] = ch; |
1108 | msg[1] = '\0'; | 1107 | msg[1] = '\0'; |
1109 | die_if_script(lineno, "syntax error: unexpected %s", ch == EOF ? "EOF" : msg); | 1108 | bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg); |
1110 | } | 1109 | } |
1111 | 1110 | ||
1112 | #if HUSH_DEBUG < 2 | 1111 | #if HUSH_DEBUG < 2 |
@@ -1843,6 +1842,7 @@ static int FAST_FUNC static_get(struct in_str *i) | |||
1843 | int ch = *i->p; | 1842 | int ch = *i->p; |
1844 | if (ch != '\0') { | 1843 | if (ch != '\0') { |
1845 | i->p++; | 1844 | i->p++; |
1845 | i->last_char = ch; | ||
1846 | return ch; | 1846 | return ch; |
1847 | } | 1847 | } |
1848 | return EOF; | 1848 | return EOF; |
@@ -1964,6 +1964,7 @@ static int FAST_FUNC file_get(struct in_str *i) | |||
1964 | do ch = fgetc(i->file); while (ch == '\0'); | 1964 | do ch = fgetc(i->file); while (ch == '\0'); |
1965 | } | 1965 | } |
1966 | debug_printf("file_get: got '%c' %d\n", ch, ch); | 1966 | debug_printf("file_get: got '%c' %d\n", ch, ch); |
1967 | i->last_char = ch; | ||
1967 | return ch; | 1968 | return ch; |
1968 | } | 1969 | } |
1969 | 1970 | ||
@@ -4008,7 +4009,7 @@ static int encode_string(o_string *as_string, | |||
4008 | * Scan input until EOF or end_trigger char. | 4009 | * Scan input until EOF or end_trigger char. |
4009 | * Return a list of pipes to execute, or NULL on EOF | 4010 | * Return a list of pipes to execute, or NULL on EOF |
4010 | * or if end_trigger character is met. | 4011 | * or if end_trigger character is met. |
4011 | * On syntax error, exit is shell is not interactive, | 4012 | * On syntax error, exit if shell is not interactive, |
4012 | * reset parsing machinery and start parsing anew, | 4013 | * reset parsing machinery and start parsing anew, |
4013 | * or return ERR_PTR. | 4014 | * or return ERR_PTR. |
4014 | */ | 4015 | */ |
@@ -4037,8 +4038,6 @@ static struct pipe *parse_stream(char **pstring, | |||
4037 | * here we should use blank chars as separators, not $IFS | 4038 | * here we should use blank chars as separators, not $IFS |
4038 | */ | 4039 | */ |
4039 | 4040 | ||
4040 | reset: /* we come back here only on syntax errors in interactive shell */ | ||
4041 | |||
4042 | if (MAYBE_ASSIGNMENT != 0) | 4041 | if (MAYBE_ASSIGNMENT != 0) |
4043 | dest.o_assignment = MAYBE_ASSIGNMENT; | 4042 | dest.o_assignment = MAYBE_ASSIGNMENT; |
4044 | initialize_context(&ctx); | 4043 | initialize_context(&ctx); |
@@ -4532,20 +4531,17 @@ static struct pipe *parse_stream(char **pstring, | |||
4532 | } while (HAS_KEYWORDS && pctx); | 4531 | } while (HAS_KEYWORDS && pctx); |
4533 | /* Free text, clear all dest fields */ | 4532 | /* Free text, clear all dest fields */ |
4534 | o_free(&dest); | 4533 | o_free(&dest); |
4534 | |||
4535 | G.last_exitcode = 1; | ||
4535 | /* If we are not in top-level parse, we return, | 4536 | /* If we are not in top-level parse, we return, |
4536 | * our caller will propagate error. | 4537 | * our caller will propagate error. |
4537 | */ | 4538 | */ |
4538 | if (end_trigger != ';') { | ||
4539 | #if !BB_MMU | 4539 | #if !BB_MMU |
4540 | if (pstring) | 4540 | if (pstring) |
4541 | *pstring = NULL; | 4541 | *pstring = NULL; |
4542 | #endif | 4542 | #endif |
4543 | debug_leave(); | 4543 | debug_leave(); |
4544 | return ERR_PTR; | 4544 | return ERR_PTR; |
4545 | } | ||
4546 | /* Discard cached input, force prompt */ | ||
4547 | input->p = NULL; | ||
4548 | goto reset; | ||
4549 | } | 4545 | } |
4550 | } | 4546 | } |
4551 | 4547 | ||
@@ -5550,8 +5546,24 @@ static void parse_and_run_stream(struct in_str *inp, int end_trigger) | |||
5550 | inp->promptmode = 0; /* PS1 */ | 5546 | inp->promptmode = 0; /* PS1 */ |
5551 | #endif | 5547 | #endif |
5552 | pipe_list = parse_stream(NULL, inp, end_trigger); | 5548 | pipe_list = parse_stream(NULL, inp, end_trigger); |
5553 | if (!pipe_list) { /* EOF */ | 5549 | if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */ |
5554 | if (empty) | 5550 | /* If we are in "big" script |
5551 | * (not in `cmd` or something similar)... | ||
5552 | */ | ||
5553 | if (pipe_list == ERR_PTR && end_trigger == ';') { | ||
5554 | /* Discard cached input (rest of line) */ | ||
5555 | int ch = inp->last_char; | ||
5556 | while (ch != EOF && ch != '\n') { | ||
5557 | //bb_error_msg("Discarded:'%c'", ch); | ||
5558 | ch = i_getch(inp); | ||
5559 | } | ||
5560 | /* Force prompt */ | ||
5561 | inp->p = NULL; | ||
5562 | /* This stream isn't empty */ | ||
5563 | empty = 0; | ||
5564 | continue; | ||
5565 | } | ||
5566 | if (!pipe_list && empty) | ||
5555 | G.last_exitcode = 0; | 5567 | G.last_exitcode = 0; |
5556 | break; | 5568 | break; |
5557 | } | 5569 | } |
@@ -8630,8 +8642,6 @@ static int FAST_FUNC builtin_source(char **argv) | |||
8630 | #endif | 8642 | #endif |
8631 | save_and_replace_G_args(&sv, argv); | 8643 | save_and_replace_G_args(&sv, argv); |
8632 | 8644 | ||
8633 | //TODO: syntax errors in sourced file should never abort the "calling" script. | ||
8634 | //Try: bash -c '. ./bad_file; echo YES' | ||
8635 | parse_and_run_file(input); | 8645 | parse_and_run_file(input); |
8636 | fclose(input); | 8646 | fclose(input); |
8637 | 8647 | ||