svn commit: trunk/busybox/shell: hush_test hush_test/hush-bugs hush_test etc...

vda at busybox.net vda at busybox.net
Sun May 13 11:34:54 PDT 2007


Author: vda
Date: 2007-05-13 11:34:53 -0700 (Sun, 13 May 2007)
New Revision: 18611

Log:
hush: fix '{ false; echo $?; }' bug.
hush: expand testsuite. variable expansion is still very broken



Added:
   trunk/busybox/shell/hush_test/hush-bugs/
   trunk/busybox/shell/hush_test/hush-bugs/argv0.right
   trunk/busybox/shell/hush_test/hush-bugs/argv0.tests
   trunk/busybox/shell/hush_test/hush-bugs/quote1.right
   trunk/busybox/shell/hush_test/hush-bugs/quote1.tests
   trunk/busybox/shell/hush_test/hush-bugs/quote2.right
   trunk/busybox/shell/hush_test/hush-bugs/quote2.tests
   trunk/busybox/shell/hush_test/hush-bugs/starquoted.right
   trunk/busybox/shell/hush_test/hush-bugs/starquoted.tests
   trunk/busybox/shell/hush_test/hush-vars/star.right
   trunk/busybox/shell/hush_test/hush-vars/star.tests

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


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2007-05-12 18:39:28 UTC (rev 18610)
+++ trunk/busybox/shell/hush.c	2007-05-13 18:34:53 UTC (rev 18611)
@@ -371,7 +371,7 @@
 static int b_addchr(o_string *o, int ch);
 static void b_reset(o_string *o);
 static int b_addqchr(o_string *o, int ch, int quote);
-static int b_adduint(o_string *o, unsigned i);
+//static int b_adduint(o_string *o, unsigned i);
 /*  in_str manipulations: */
 static int static_get(struct in_str *i);
 static int static_peek(struct in_str *i);
@@ -413,7 +413,7 @@
 static const char *lookup_param(const char *src);
 static char *make_string(char **inp);
 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
-static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
+//static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
 static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, const char *end_trigger);
 /*   setup: */
 static int parse_stream_outer(struct in_str *inp, int parse_flag);
@@ -1015,17 +1015,17 @@
 	return b_addchr(o, ch);
 }
 
-static int b_adduint(o_string *o, unsigned i)
-{
-	int r;
-	char buf[sizeof(unsigned)*3 + 1];
-	char *p = buf;
-	*(utoa_to_buf(i, buf, sizeof(buf))) = '\0';
-	/* no escape checking necessary */
-	do r = b_addchr(o, *p++); while (r == 0 && *p);
-	return r;
-}
-
+//static int b_adduint(o_string *o, unsigned i)
+//{
+//	int r;
+//	char buf[sizeof(unsigned)*3 + 1];
+//	char *p = buf;
+//	*(utoa_to_buf(i, buf, sizeof(buf))) = '\0';
+//	/* no escape checking necessary */
+//	do r = b_addchr(o, *p++); while (r == 0 && *p);
+//	return r;
+//}
+//
 static int static_get(struct in_str *i)
 {
 	int ch = *i->p++;
@@ -1288,9 +1288,7 @@
 				getpid(), argv[i]);
 // FIXME: vfork case??
 		p = insert_var_value(argv[i]);
-		putenv(strdup(p));
-		if (p != argv[i])
-			free(p);
+		putenv(p == argv[i] ? xstrdup(p) : p);
 	}
 	argv += i;
 	/* If a variable is assigned in a forest, and nobody listens,
@@ -1699,10 +1697,11 @@
 		}
 		for (i = 0; is_assignment(argv[i]); i++) {
 			p = insert_var_value(argv[i]);
-			putenv(strdup(p));
 			if (p != argv[i]) {
 				child->sp--;
-				free(p);
+				putenv(p);
+			} else {
+				putenv(xstrdup(p));
 			}
 		}
 		if (child->sp) {
@@ -2292,39 +2291,42 @@
 static char **make_list_in(char **inp, char *name)
 {
 	int len, i;
+#if 0
 	int name_len = strlen(name);
-	int n = 0;
+#endif
+	int n;
 	char **list;
 	char *p1, *p2, *p3;
 
 	/* create list of variable values */
 	list = xmalloc(sizeof(*list));
+	n = 0;
 	for (i = 0; inp[i]; i++) {
 		p3 = insert_var_value(inp[i]);
 		p1 = p3;
 		while (*p1) {
-			if ((*p1 == ' ')) {
+			if (*p1 == ' ') {
 				p1++;
 				continue;
 			}
-			p2 = strchr(p1, ' ');
-			if (p2) {
-				len = p2 - p1;
-			} else {
-				len = strlen(p1);
-				p2 = p1 + len;
-			}
+			p2 = strchrnul(p1, ' ');
+			len = p2 - p1;
 			/* we use n + 2 in realloc for list, because we add
 			 * new element and then we will add NULL element */
 			list = xrealloc(list, sizeof(*list) * (n + 2));
+			list[n] = xasprintf("%s=%.*s", name, len, p1);
+#if 0 /* faster, but more code */
 			list[n] = xmalloc(2 + name_len + len);
 			strcpy(list[n], name);
-			strcat(list[n], "=");
-			strncat(list[n], p1, len);
-			list[n++][name_len + len + 1] = '\0';
+			list[n][name_len] = '=';
+			strncat(&(list[n][name_len + 1]), p1, len);
+			list[n][name_len + len + 1] = '\0';
+#endif
+			n++;
 			p1 = p2;
 		}
-		if (p3 != inp[i]) free(p3);
+		if (p3 != inp[i])
+			free(p3);
 	}
 	list[n] = NULL;
 	return list;
@@ -2335,8 +2337,10 @@
 	int res_str_len = 0;
 	int len;
 	int done = 0;
-	char *p, *res_str = NULL;
+	int i;
 	const char *p1;
+	char *p, *p2;
+	char *res_str = NULL;
 
 	while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
 		if (p != inp) {
@@ -2348,11 +2352,42 @@
 		inp = ++p;
 		p = strchr(inp, SPECIAL_VAR_SYMBOL);
 		*p = '\0';
-		p1 = lookup_param(inp);
+
+		switch (inp[0]) {
+		case '$':
+			/* FIXME: (echo $$) should still print pid of main shell */
+			p1 = utoa(getpid());
+			break;
+		case '!':
+			p1 = last_bg_pid ? utoa(last_bg_pid) : (char*)"";
+			break;
+		case '?':
+			p1 = utoa(last_return_code);
+			break;
+		case '#':
+			p1 = utoa(global_argc ? global_argc-1 : 0);
+			break;
+		case '*':
+		case '@': /* FIXME: we treat $@ as $* for now */
+			len = 1;
+			for (i = 1; i < global_argc; i++)
+				len += strlen(global_argv[i]) + 1;
+			p1 = p2 = alloca(--len);
+			for (i = 1; i < global_argc; i++) {
+				strcpy(p2, global_argv[i]);
+				p2 += strlen(global_argv[i]);
+				*p2++ = ifs[0];
+			}
+			*--p2 = '\0';
+			break;
+		default:
+			p1 = lookup_param(inp);
+		}
+
 		if (p1) {
 			len = res_str_len + strlen(p1);
-			res_str = xrealloc(res_str, (1 + len));
-			strcpy((res_str + res_str_len), p1);
+			res_str = xrealloc(res_str, 1 + len);
+			strcpy(res_str + res_str_len, p1);
 			res_str_len = len;
 		}
 		*p = SPECIAL_VAR_SYMBOL;
@@ -2956,21 +2991,20 @@
 	char *p;
 	char *str = NULL;
 	int n;
-	int len = 2;
+	int val_len;
+	int len = 0;
 
 	for (n = 0; inp[n]; n++) {
 		p = insert_var_value(inp[n]);
-		str = xrealloc(str, (len + strlen(p)));
-		if (n) {
-			strcat(str, " ");
-		} else {
-			*str = '\0';
-		}
-		strcat(str, p);
-		len = strlen(str) + 3;
+		val_len = strlen(p);
+		str = xrealloc(str, len + val_len + 3); /* +3: space, '\n', <nul>*/
+		str[len++] = ' ';
+		strcpy(str + len, p);
+		len += val_len;
 		if (p != inp[n]) free(p);
 	}
-	len = strlen(str);
+	/* We do not check for case where loop had no iterations at all
+	 * - cannot happen? */
 	str[len] = '\n';
 	str[len+1] = '\0';
 	return str;
@@ -2979,46 +3013,39 @@
 /* return code: 0 for OK, 1 for syntax error */
 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
 {
-	int i, advance = 0;
-	char sep[] = " ";
-	int ch = input->peek(input);  /* first character after the $ */
+//	int i;
+//	char sep[] = " ";
+	int ch = b_peek(input);  /* first character after the $ */
 
 	debug_printf_parse("handle_dollar entered: ch='%c'\n", ch);
-	if (isalpha(ch)) {
+	if (isalpha(ch) || ch == '?') {
 		b_addchr(dest, SPECIAL_VAR_SYMBOL);
 		ctx->child->sp++;
 		while (1) {
+			debug_printf_parse(": '%c'\n", ch);
+			b_getch(input);
+			b_addchr(dest, ch);
 			ch = b_peek(input);
 			if (!isalnum(ch) && ch != '_')
 				break;
-			debug_printf_parse(": '%c'\n", ch);
-			b_getch(input);
-			b_addchr(dest, ch);
 		}
 		b_addchr(dest, SPECIAL_VAR_SYMBOL);
 	} else if (isdigit(ch)) {
-		i = ch - '0';  /* XXX is $0 special? */
-		if (i < global_argc) {
-			parse_string(dest, ctx, global_argv[i]); /* recursion */
-		}
-		advance = 1;
+ make_one_char_var:
+		b_addchr(dest, SPECIAL_VAR_SYMBOL);
+		ctx->child->sp++;
+		debug_printf_parse(": '%c'\n", ch);
+		b_getch(input);
+		b_addchr(dest, ch);
+		b_addchr(dest, SPECIAL_VAR_SYMBOL);
 	} else switch (ch) {
-		case '$':
-			b_adduint(dest, getpid());
-			advance = 1;
-			break;
-		case '!':
-			if (last_bg_pid > 0) b_adduint(dest, last_bg_pid);
-			advance = 1;
-			break;
-		case '?':
-			b_adduint(dest, last_return_code);
-			advance = 1;
-			break;
-		case '#':
-			b_adduint(dest, global_argc ? global_argc-1 : 0);
-			advance = 1;
-			break;
+		case '$': /* pid */
+		case '!': /* last bg pid */
+		case '?': /* last exit code */
+		case '#': /* number of args */
+		case '*': /* args */
+		case '@': /* args */
+			goto make_one_char_var;
 		case '{':
 			b_addchr(dest, SPECIAL_VAR_SYMBOL);
 			ctx->child->sp++;
@@ -3042,15 +3069,6 @@
 			b_getch(input);
 			process_command_subs(dest, ctx, input, ")");
 			break;
-		case '*':
-			sep[0] = ifs[0];
-			for (i = 1; i < global_argc; i++) {
-				parse_string(dest, ctx, global_argv[i]);
-				if (i+1 < global_argc)
-					parse_string(dest, ctx, sep);
-			}
-			break;
-		case '@':
 		case '-':
 		case '_':
 			/* still unhandled, but should be eventually */
@@ -3058,25 +3076,19 @@
 			return 1;
 			break;
 		default:
-			b_addqchr(dest,'$', dest->quote);
+			b_addqchr(dest, '$', dest->quote);
 	}
-	/* Eat the character if the flag was set.  If the compiler
-	 * is smart enough, we could substitute "b_getch(input);"
-	 * for all the "advance = 1;" above, and also end up with
-	 * a nice size-optimized program.  Hah!  That'll be the day.
-	 */
-	if (advance) b_getch(input);
 	debug_printf_parse("handle_dollar return 0\n");
 	return 0;
 }
 
-static int parse_string(o_string *dest, struct p_context *ctx, const char *src)
-{
-	struct in_str foo;
-	setup_string_in_str(&foo, src);
-	return parse_stream(dest, ctx, &foo, NULL);
-}
-
+//static int parse_string(o_string *dest, struct p_context *ctx, const char *src)
+//{
+//	struct in_str foo;
+//	setup_string_in_str(&foo, src);
+//	return parse_stream(dest, ctx, &foo, NULL);
+//}
+//
 /* return code is 0 for normal exit, 1 for syntax error */
 static int parse_stream(o_string *dest, struct p_context *ctx,
 	struct in_str *input, const char *end_trigger)

Added: trunk/busybox/shell/hush_test/hush-bugs/argv0.right
===================================================================
--- trunk/busybox/shell/hush_test/hush-bugs/argv0.right	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-bugs/argv0.right	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1 @@
+OK

Added: trunk/busybox/shell/hush_test/hush-bugs/argv0.tests
===================================================================
--- trunk/busybox/shell/hush_test/hush-bugs/argv0.tests	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-bugs/argv0.tests	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1,4 @@
+if test $# = 0; then
+    exec "$THIS_SH" "$0" arg
+fi
+echo OK


Property changes on: trunk/busybox/shell/hush_test/hush-bugs/argv0.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/busybox/shell/hush_test/hush-bugs/quote1.right
===================================================================
--- trunk/busybox/shell/hush_test/hush-bugs/quote1.right	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-bugs/quote1.right	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1 @@
+'1'

Added: trunk/busybox/shell/hush_test/hush-bugs/quote1.tests
===================================================================
--- trunk/busybox/shell/hush_test/hush-bugs/quote1.tests	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-bugs/quote1.tests	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1,2 @@
+a=1
+echo "'$a'"


Property changes on: trunk/busybox/shell/hush_test/hush-bugs/quote1.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/busybox/shell/hush_test/hush-bugs/quote2.right
===================================================================
--- trunk/busybox/shell/hush_test/hush-bugs/quote2.right	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-bugs/quote2.right	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1 @@
+>1

Added: trunk/busybox/shell/hush_test/hush-bugs/quote2.tests
===================================================================
--- trunk/busybox/shell/hush_test/hush-bugs/quote2.tests	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-bugs/quote2.tests	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1,2 @@
+a=1
+echo ">$a"


Property changes on: trunk/busybox/shell/hush_test/hush-bugs/quote2.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/busybox/shell/hush_test/hush-bugs/starquoted.right
===================================================================
--- trunk/busybox/shell/hush_test/hush-bugs/starquoted.right	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-bugs/starquoted.right	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1 @@
+.1 abc d e f.

Added: trunk/busybox/shell/hush_test/hush-bugs/starquoted.tests
===================================================================
--- trunk/busybox/shell/hush_test/hush-bugs/starquoted.tests	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-bugs/starquoted.tests	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1,4 @@
+if test $# = 0; then
+    exec "$THIS_SH" starquoted.tests 1 abc 'd e f'
+fi
+for a in "$*"; do echo ".$a."; done


Property changes on: trunk/busybox/shell/hush_test/hush-bugs/starquoted.tests
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/busybox/shell/hush_test/hush-vars/star.right
===================================================================
--- trunk/busybox/shell/hush_test/hush-vars/star.right	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-vars/star.right	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1,5 @@
+.1.
+.abc.
+.d.
+.e.
+.f.

Added: trunk/busybox/shell/hush_test/hush-vars/star.tests
===================================================================
--- trunk/busybox/shell/hush_test/hush-vars/star.tests	                        (rev 0)
+++ trunk/busybox/shell/hush_test/hush-vars/star.tests	2007-05-13 18:34:53 UTC (rev 18611)
@@ -0,0 +1,8 @@
+if test $# = 0; then
+    exec "$THIS_SH" star.tests 1 abc 'd e f'
+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


Property changes on: trunk/busybox/shell/hush_test/hush-vars/star.tests
___________________________________________________________________
Name: svn:executable
   + *

Modified: trunk/busybox/shell/hush_test/hush-vars/var.right
===================================================================
--- trunk/busybox/shell/hush_test/hush-vars/var.right	2007-05-12 18:39:28 UTC (rev 18610)
+++ trunk/busybox/shell/hush_test/hush-vars/var.right	2007-05-13 18:34:53 UTC (rev 18611)
@@ -1,4 +1,4 @@
 http://busybox.net
 http://busybox.net_abc
 1
-0
+1

Modified: trunk/busybox/shell/hush_test/hush-vars/var.tests
===================================================================
--- trunk/busybox/shell/hush_test/hush-vars/var.tests	2007-05-12 18:39:28 UTC (rev 18610)
+++ trunk/busybox/shell/hush_test/hush-vars/var.tests	2007-05-13 18:34:53 UTC (rev 18611)
@@ -6,5 +6,4 @@
 true
 false; echo $?
 true
-# BUG: prints 0, must be 1
 { false; echo $?; }



More information about the busybox-cvs mailing list