svn commit: [26121] trunk/busybox/shell: hush_test/hush-parsing hush_test/hush-v etc...

vda at busybox.net vda at busybox.net
Thu Apr 16 10:59:40 UTC 2009


Author: vda
Date: 2009-04-16 10:59:40 +0000 (Thu, 16 Apr 2009)
New Revision: 26121

Log:
hush: fix "if { echo foo; } then { echo bar; } fi" parsing

function                                             old     new   delta
done_word                                            728     793     +65
parse_stream                                        2084    2098     +14



Added:
   trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.right
   trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.tests

Modified:
   trunk/busybox/shell/hush.c
   trunk/busybox/shell/hush_test/hush-vars/param_glob.tests


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2009-04-15 23:29:44 UTC (rev 26120)
+++ trunk/busybox/shell/hush.c	2009-04-16 10:59:40 UTC (rev 26121)
@@ -4154,6 +4154,8 @@
 	}
 	return NULL;
 }
+/* Return 0: not a keyword, 1: keyword
+ */
 static int reserved_word(o_string *word, struct parse_context *ctx)
 {
 #if ENABLE_HUSH_CASE
@@ -4163,6 +4165,8 @@
 #endif
 	const struct reserved_combo *r;
 
+	if (word->o_quoted)
+		return 0;
 	r = match_reserved_word(word);
 	if (!r)
 		return 0;
@@ -4177,13 +4181,14 @@
 	if (r->flag == 0) { /* '!' */
 		if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
 			syntax_error("! ! command");
-			IF_HAS_KEYWORDS(ctx->ctx_res_w = RES_SNTX;)
+			ctx->ctx_res_w = RES_SNTX;
 		}
 		ctx->ctx_inverted = 1;
 		return 1;
 	}
 	if (r->flag & FLAG_START) {
 		struct parse_context *old;
+
 		old = xmalloc(sizeof(*old));
 		debug_printf_parse("push stack %p\n", old);
 		*old = *ctx;   /* physical copy */
@@ -4193,11 +4198,21 @@
 		syntax_error_at(word->data);
 		ctx->ctx_res_w = RES_SNTX;
 		return 1;
+	} else {
+		/* "{...} fi" is ok. "{...} if" is not
+		 * Example:
+		 * if { echo foo; } then { echo bar; } fi */
+		if (ctx->command->group)
+			done_pipe(ctx, PIPE_SEQ);
 	}
+
 	ctx->ctx_res_w = r->res;
 	ctx->old_flag = r->flag;
+	word->o_assignment = r->assignment_flag;
+
 	if (ctx->old_flag & FLAG_END) {
 		struct parse_context *old;
+
 		done_pipe(ctx, PIPE_SEQ);
 		debug_printf_parse("pop stack %p\n", ctx->stack);
 		old = ctx->stack;
@@ -4213,7 +4228,6 @@
 		*ctx = *old;   /* physical copy */
 		free(old);
 	}
-	word->o_assignment = r->assignment_flag;
 	return 1;
 }
 #endif
@@ -4273,19 +4287,6 @@
 			word->o_assignment = MAYBE_ASSIGNMENT;
 		}
 
-		if (command->group) {
-			/* "{ echo foo; } echo bar" - bad */
-			/* NB: bash allows e.g.:
-			 * if true; then { echo foo; } fi
-			 * while if false; then false; fi do break; done
-			 * and disallows:
-			 * while if false; then false; fi; do; break; done
-			 * TODO? */
-			syntax_error_at(word->data);
-			debug_printf_parse("done_word return 1: syntax error, "
-					"groups and arglists don't mix\n");
-			return 1;
-		}
 #if HAS_KEYWORDS
 # if ENABLE_HUSH_CASE
 		if (ctx->ctx_dsemicolon
@@ -4311,6 +4312,13 @@
 			}
 		}
 #endif
+		if (command->group) {
+			/* "{ echo foo; } echo bar" - bad */
+			syntax_error_at(word->data);
+			debug_printf_parse("done_word return 1: syntax error, "
+					"groups and arglists don't mix\n");
+			return 1;
+		}
 		if (word->o_quoted /* word had "xx" or 'xx' at least as part of it. */
 		 /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */
 		 && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL)
@@ -4720,7 +4728,8 @@
 #if ENABLE_HUSH_FUNCTIONS
 	if (ch == '(' && !dest->o_quoted) {
 		if (dest->length)
-			done_word(dest, ctx);
+			if (done_word(dest, ctx))
+				return 1;
 		if (!command->argv)
 			goto skip; /* (... */
 		if (command->argv[1]) { /* word word ... (... */
@@ -4778,10 +4787,10 @@
 #endif
 		/* empty ()/{} or parse error? */
 		if (!pipe_list || pipe_list == ERR_PTR) {
+			/* parse_stream already emitted error msg */
 #if !BB_MMU
 			free(as_string);
 #endif
-			syntax_error(NULL);
 			debug_printf_parse("parse_group return 1: "
 				"parse_stream returned %p\n", pipe_list);
 			return 1;

Added: trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.right
===================================================================
--- trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.right	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.right	2009-04-16 10:59:40 UTC (rev 26121)
@@ -0,0 +1,11 @@
+Semicolons after } can be omitted 1:
+foo
+bar
+Semicolons after } can be omitted 2:
+foo
+bar
+Semicolons after fi can be omitted:
+foo
+bar
+baz
+Done:0

Added: trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.tests
===================================================================
--- trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.tests	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.tests	2009-04-16 10:59:40 UTC (rev 26121)
@@ -0,0 +1,10 @@
+echo "Semicolons after } can be omitted 1:"
+if { echo foo; } then { echo bar; } fi
+
+echo "Semicolons after } can be omitted 2:"
+while { echo foo; } do { echo bar; break; } done
+
+echo "Semicolons after fi can be omitted:"
+while if echo foo; then echo bar; fi do echo baz; break; done
+
+echo Done:$?


Property changes on: trunk/busybox/shell/hush_test/hush-parsing/groups_and_keywords1.tests
___________________________________________________________________
Added: svn:executable
   + *

Modified: trunk/busybox/shell/hush_test/hush-vars/param_glob.tests
===================================================================
--- trunk/busybox/shell/hush_test/hush-vars/param_glob.tests	2009-04-15 23:29:44 UTC (rev 26120)
+++ trunk/busybox/shell/hush_test/hush-vars/param_glob.tests	2009-04-16 10:59:40 UTC (rev 26121)
@@ -1,5 +1,5 @@
 if test $# = 0; then
-    #BUG in builtin_exec! will glob param!
+    # UNFIXED BUG in builtin_exec! will glob param!
     #exec "$THIS_SH" "$0" 'param_glob.t*'
     "$THIS_SH" "$0" 'param_glob.t*'
     exit



More information about the busybox-cvs mailing list