summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko2007-05-23 00:32:25 +0000
committerDenis Vlasenko2007-05-23 00:32:25 +0000
commit1a7358612ff2dfdfc9fa461faa946c577666787f (patch)
tree3edf610e1f0bab6f33e90716fc1550f0c9060991 /shell
parent94dace30160131fc3f45b3f486463c49cda05204 (diff)
downloadbusybox-1a7358612ff2dfdfc9fa461faa946c577666787f.zip
busybox-1a7358612ff2dfdfc9fa461faa946c577666787f.tar.gz
hush: fix a bit different instance of "No EOL" bug,
add testsuite for that. Expand another testsuite.
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c84
-rw-r--r--shell/hush_test/hush-parsing/noeol2.right1
-rwxr-xr-xshell/hush_test/hush-parsing/noeol2.tests7
-rw-r--r--shell/hush_test/hush-vars/star.right1
-rwxr-xr-xshell/hush_test/hush-vars/star.tests4
5 files changed, 57 insertions, 40 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 61c03f7..aab6ff3 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2836,14 +2836,13 @@ static struct pipe *new_pipe(void)
static void initialize_context(struct p_context *ctx)
{
- ctx->pipe = NULL;
- ctx->pending_redirect = NULL;
ctx->child = NULL;
- ctx->list_head = new_pipe();
- ctx->pipe = ctx->list_head;
+ ctx->pipe = ctx->list_head = new_pipe();
+ ctx->pending_redirect = NULL;
ctx->res_w = RES_NONE;
- ctx->stack = NULL;
+ //only ctx->parse_type is not touched... is this intentional?
ctx->old_flag = 0;
+ ctx->stack = NULL;
done_command(ctx); /* creates the memory for working child */
}
@@ -2886,44 +2885,44 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
const struct reserved_combo *r;
for (r = reserved_list; r < reserved_list + NRES; r++) {
- if (strcmp(dest->data, r->literal) == 0) {
- debug_printf("found reserved word %s, code %d\n", r->literal, r->code);
- if (r->flag & FLAG_START) {
- struct p_context *new = xmalloc(sizeof(struct p_context));
- debug_printf("push stack\n");
+ if (strcmp(dest->data, r->literal) != 0)
+ continue;
+ debug_printf("found reserved word %s, code %d\n", r->literal, r->code);
+ if (r->flag & FLAG_START) {
+ struct p_context *new;
+ debug_printf("push stack\n");
#if ENABLE_HUSH_LOOPS
- if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
- syntax();
- free(new);
- ctx->res_w = RES_SNTX;
- b_reset(dest);
- return 1;
- }
-#endif
- *new = *ctx; /* physical copy */
- initialize_context(ctx);
- ctx->stack = new;
- } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
+ if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
syntax();
ctx->res_w = RES_SNTX;
b_reset(dest);
return 1;
}
- ctx->res_w = r->code;
- ctx->old_flag = r->flag;
- if (ctx->old_flag & FLAG_END) {
- struct p_context *old;
- debug_printf("pop stack\n");
- done_pipe(ctx, PIPE_SEQ);
- old = ctx->stack;
- old->child->group = ctx->list_head;
- old->child->subshell = 0;
- *ctx = *old; /* physical copy */
- free(old);
- }
+#endif
+ new = xmalloc(sizeof(*new));
+ *new = *ctx; /* physical copy */
+ initialize_context(ctx);
+ ctx->stack = new;
+ } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
+ syntax();
+ ctx->res_w = RES_SNTX;
b_reset(dest);
return 1;
}
+ ctx->res_w = r->code;
+ ctx->old_flag = r->flag;
+ if (ctx->old_flag & FLAG_END) {
+ struct p_context *old;
+ debug_printf("pop stack\n");
+ done_pipe(ctx, PIPE_SEQ);
+ old = ctx->stack;
+ old->child->group = ctx->list_head;
+ old->child->subshell = 0;
+ *ctx = *old; /* physical copy */
+ free(old);
+ }
+ b_reset(dest);
+ return 1;
}
return 0;
}
@@ -3155,7 +3154,8 @@ static int process_command_subs(o_string *dest, struct p_context *ctx,
/* recursion to generate command */
retcode = parse_stream(&result, &inner, input, subst_end);
- if (retcode != 0) return retcode; /* syntax error or EOF */
+ if (retcode != 0)
+ return retcode; /* syntax error or EOF */
done_word(&result, &inner);
done_pipe(&inner, PIPE_SEQ);
b_free(&result);
@@ -3357,9 +3357,15 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger);
- while ((ch = b_getch(input)) != EOF) {
- m = charmap[ch];
- next = (ch == '\n') ? '\0' : b_peek(input);
+ while (1) {
+ ch = b_getch(input);
+ m = CHAR_IFS;
+ next = '\0';
+ if (ch != EOF) {
+ m = charmap[ch];
+ if (ch != '\n')
+ next = b_peek(input);
+ }
debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n",
ch, ch, m, dest->quote);
if (m == CHAR_ORDINARY
@@ -3373,6 +3379,8 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
debug_printf_parse("parse_stream return 1: done_word!=0\n");
return 1;
}
+ if (ch == EOF)
+ break;
/* If we aren't performing a substitution, treat
* a newline as a command separator.
* [why we don't handle it exactly like ';'? --vda] */
diff --git a/shell/hush_test/hush-parsing/noeol2.right b/shell/hush_test/hush-parsing/noeol2.right
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/shell/hush_test/hush-parsing/noeol2.right
@@ -0,0 +1 @@
+1
diff --git a/shell/hush_test/hush-parsing/noeol2.tests b/shell/hush_test/hush-parsing/noeol2.tests
new file mode 100755
index 0000000..1220f05
--- /dev/null
+++ b/shell/hush_test/hush-parsing/noeol2.tests
@@ -0,0 +1,7 @@
+# last line has no EOL!
+if true
+then
+ echo 1
+else
+ echo 2
+fi \ No newline at end of file
diff --git a/shell/hush_test/hush-vars/star.right b/shell/hush_test/hush-vars/star.right
index b33b176..0ecc55b 100644
--- a/shell/hush_test/hush-vars/star.right
+++ b/shell/hush_test/hush-vars/star.right
@@ -3,3 +3,4 @@
.d.
.e.
.f.
+.1 abc d e f.
diff --git a/shell/hush_test/hush-vars/star.tests b/shell/hush_test/hush-vars/star.tests
index 1914dde..5554c40 100755
--- a/shell/hush_test/hush-vars/star.tests
+++ b/shell/hush_test/hush-vars/star.tests
@@ -4,5 +4,5 @@ fi
# 'd e f' should be split into 3 separate args:
for a in $*; do echo ".$a."; done
-# must produce .1 abc d e f. Currently does not
-#for a in "$*"; do echo ".$a."; done
+# must produce .1 abc d e f.
+for a in "$*"; do echo ".$a."; done