svn commit: trunk/busybox/shell

vda at busybox.net vda at busybox.net
Sat May 5 08:10:52 PDT 2007


Author: vda
Date: 2007-05-05 08:10:52 -0700 (Sat, 05 May 2007)
New Revision: 18560

Log:
hush: preparatory patch for removing extra empty pipes generation
in parse stage. No real code change here.


Modified:
   trunk/busybox/shell/hush.c


Changeset:
Modified: trunk/busybox/shell/hush.c
===================================================================
--- trunk/busybox/shell/hush.c	2007-05-04 21:38:14 UTC (rev 18559)
+++ trunk/busybox/shell/hush.c	2007-05-05 15:10:52 UTC (rev 18560)
@@ -125,10 +125,10 @@
 #define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
 #endif
 
-#define SPECIAL_VAR_SYMBOL 03
-#define FLAG_EXIT_FROM_LOOP 1
+#define SPECIAL_VAR_SYMBOL   3
+#define FLAG_EXIT_FROM_LOOP  1
 #define FLAG_PARSE_SEMICOLON (1 << 1)		/* symbol ';' is special for parser */
-#define FLAG_REPARSING	     (1 << 2)		/* >=2nd pass */
+#define FLAG_REPARSING	     (1 << 2)		/* >= 2nd pass */
 
 typedef enum {
 	REDIRECT_INPUT     = 1,
@@ -199,10 +199,10 @@
 	struct pipe *list_head;
 	struct pipe *pipe;
 	struct redir_struct *pending_redirect;
-	reserved_style w;
-	int old_flag;               /* for figuring out valid reserved words */
+	reserved_style res_w;
+	int old_flag;           /* for figuring out valid reserved words */
 	struct p_context *stack;
-	int type;           /* define type of parser : ";$" common or special symbol */
+	int parse_type;         /* define type of parser : ";$" common or special symbol */
 	/* How about quoting status? */
 };
 
@@ -410,8 +410,8 @@
 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 flag);
-static int parse_string_outer(const char *s, int flag);
+static int parse_stream_outer(struct in_str *inp, int parse_flag);
+static int parse_string_outer(const char *s, int parse_flag);
 static int parse_file_outer(FILE *f);
 /*   job management: */
 static int checkjobs(struct pipe* fg_pipe);
@@ -1854,23 +1854,24 @@
 	};
 
 	int pin, prn;
-	char **argv;
 	pin = 0;
 	while (pi) {
 		fprintf(stderr, "%*spipe %d r_mode=%s followup=%d %s\n", lvl*2, "",
 				pin, RES[pi->r_mode], pi->followup, PIPE[pi->followup]);
 		prn = 0;
 		while (prn < pi->num_progs) {
+			struct child_prog *child = &pi->progs[prn];
+			char **argv = child->argv;
+
 			fprintf(stderr, "%*s prog %d", lvl*2, "", prn);
-			if (pi->progs[prn].group) {
+			if (child->group) {
 				fprintf(stderr, " group %s: (argv=%p)\n",
-						(pi->subshell ? "()" : "{}"),
-						pi->progs[prn].argv);
-				debug_print_tree(pi->progs[prn].group, lvl+1);
+						(child->subshell ? "()" : "{}"),
+						argv);
+				debug_print_tree(child->group, lvl+1);
 				prn++;
 				continue;
 			}
-			argv = pi->progs[prn].argv;
 			if (argv) while (*argv) {
 				fprintf(stderr, " '%s'", *argv);
 				argv++;
@@ -1901,7 +1902,7 @@
 	int flag_rep = 0;
 	int save_num_progs;
 	int flag_skip = 1;
-	int rcode = 0; /* probaly for gcc only */
+	int rcode = 0; /* probably for gcc only */
 	int flag_restore = 0;
 	int if_code = 0, next_if_code = 0;  /* need double-buffer to handle elif */
 	reserved_style rmode, skip_more_in_this_rmode = RES_XXXX;
@@ -1968,17 +1969,15 @@
 	}
 #endif
 
-	for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) {
-		if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL
-		 || pi->r_mode == RES_FOR
-		) {
+	for (; pi; pi = flag_restore ? rpipe : pi->next) {
+		rmode = pi->r_mode;
+		if (rmode == RES_WHILE || rmode == RES_UNTIL || rmode == RES_FOR) {
 			flag_restore = 0;
 			if (!rpipe) {
 				flag_rep = 0;
 				rpipe = pi;
 			}
 		}
-		rmode = pi->r_mode;
 		debug_printf_exec(": rmode=%d if_code=%d next_if_code=%d skip_more=%d\n",
 				rmode, if_code, next_if_code, skip_more_in_this_rmode);
 		if (rmode == skip_more_in_this_rmode && flag_skip) {
@@ -2535,7 +2534,7 @@
 	ctx->child = NULL;
 	ctx->list_head = new_pipe();
 	ctx->pipe = ctx->list_head;
-	ctx->w = RES_NONE;
+	ctx->res_w = RES_NONE;
 	ctx->stack = NULL;
 	ctx->old_flag = 0;
 	done_command(ctx);   /* creates the memory for working child */
@@ -2574,29 +2573,29 @@
 	enum { NRES = sizeof(reserved_list)/sizeof(reserved_list[0]) };
 	const struct reserved_combo *r;
 
-	for (r = reserved_list;	r < reserved_list+NRES; 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 (ctx->w == RES_IN || ctx->w == RES_FOR) {
+				if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
 					syntax();
 					free(new);
-					ctx->w = RES_SNTX;
+					ctx->res_w = RES_SNTX;
 					b_reset(dest);
 					return 1;
 				}
 				*new = *ctx;   /* physical copy */
 				initialize_context(ctx);
 				ctx->stack = new;
-			} else if (ctx->w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
+			} else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
 				syntax();
-				ctx->w = RES_SNTX;
+				ctx->res_w = RES_SNTX;
 				b_reset(dest);
 				return 1;
 			}
-			ctx->w = r->code;
+			ctx->res_w = r->code;
 			ctx->old_flag = r->flag;
 			if (ctx->old_flag & FLAG_END) {
 				struct p_context *old;
@@ -2623,7 +2622,7 @@
 	glob_t *glob_target;
 	int gr, flags = 0;
 
-	debug_printf_parse("done_word: '%s' %p\n", dest->data, child);
+	debug_printf_parse("done_word entered: '%s' %p\n", dest->data, child);
 	if (dest->length == 0 && !dest->nonnull) {
 		debug_printf_parse("done_word return 0: true null, ignored\n");
 		return 0;
@@ -2636,15 +2635,16 @@
 			debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
 			return 1;
 		}
-		if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {
-			debug_printf_parse(": checking %s for reserved-ness\n", dest->data);
+		if (!child->argv && (ctx->parse_type & FLAG_PARSE_SEMICOLON)) {
+			debug_printf_parse(": checking '%s' for reserved-ness\n", dest->data);
 			if (reserved_word(dest, ctx)) {
-				debug_printf_parse("done_word return %d\n", (ctx->w == RES_SNTX));
-				return (ctx->w == RES_SNTX);
+				debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX));
+				return (ctx->res_w == RES_SNTX);
 			}
 		}
 		glob_target = &child->glob_result;
-		if (child->argv) flags |= GLOB_APPEND;
+		if (child->argv)
+			flags |= GLOB_APPEND;
 	}
 	gr = xglob(dest, flags, glob_target);
 	if (gr != 0) {
@@ -2663,7 +2663,7 @@
 	} else {
 		child->argv = glob_target->gl_pathv;
 	}
-	if (ctx->w == RES_FOR) {
+	if (ctx->res_w == RES_FOR) {
 		done_word(dest, ctx);
 		done_pipe(ctx, PIPE_SEQ);
 	}
@@ -2676,56 +2676,63 @@
 static int done_command(struct p_context *ctx)
 {
 	/* The child is really already in the pipe structure, so
-	 * advance the pipe counter and make a new, null child.
-	 * Only real trickiness here is that the uncommitted
-	 * child structure, to which ctx->child points, is not
-	 * counted in pi->num_progs. */
+	 * advance the pipe counter and make a new, null child. */
 	struct pipe *pi = ctx->pipe;
-	struct child_prog *prog = ctx->child;
+	struct child_prog *child = ctx->child;
 
-	if (prog && prog->group == NULL
-	 && prog->argv == NULL
-	 && prog->redirects == NULL
-	) {
-		debug_printf("done_command: skipping null command\n");
-		return 0;
-	}
-	if (prog) {
+	if (child) {
+		if (child->group == NULL
+		 && child->argv == NULL
+		 && child->redirects == NULL
+		) {
+			debug_printf_parse("done_command: skipping null command\n");
+			return 0;
+		}
 		pi->num_progs++;
-		debug_printf("done_command: num_progs incremented to %d\n", pi->num_progs);
+		debug_printf_parse("done_command: ++num_progs=%d\n", pi->num_progs);
 	} else {
-		debug_printf("done_command: initializing\n");
+		debug_printf_parse("done_command: initializing, num_progs=%d\n", pi->num_progs);
 	}
+
+	/* Only real trickiness here is that the uncommitted
+	 * child structure is not counted in pi->num_progs. */
 	pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
+	child = &pi->progs[pi->num_progs];
 
-	prog = pi->progs + pi->num_progs;
-	memset(prog, 0, sizeof(*prog));
-	/*prog->redirects = NULL;*/
-	/*prog->argv = NULL; */
-	/*prog->is_stopped = 0;*/
-	/*prog->group = NULL;*/
-	/*prog->glob_result.gl_pathv = NULL;*/
-	prog->family = pi;
-	/*prog->sp = 0;*/
-	ctx->child = prog;
-	prog->type = ctx->type;
+	memset(child, 0, sizeof(*child));
+	/*child->redirects = NULL;*/
+	/*child->argv = NULL;*/
+	/*child->is_stopped = 0;*/
+	/*child->group = NULL;*/
+	/*child->glob_result.gl_pathv = NULL;*/
+	child->family = pi;
+	/*child->sp = 0;*/
+	child->type = ctx->parse_type;
 
+	ctx->child = child;
 	/* but ctx->pipe and ctx->list_head remain unchanged */
+
 	return 0;
 }
 
 static int done_pipe(struct p_context *ctx, pipe_style type)
 {
 	struct pipe *new_p;
+
+	debug_printf_parse("done_pipe entered, followup %d\n", type);
 	done_command(ctx);  /* implicit closure of previous command */
-	debug_printf_parse("done_pipe, type %d\n", type);
 	ctx->pipe->followup = type;
-	ctx->pipe->r_mode = ctx->w;
+	ctx->pipe->r_mode = ctx->res_w;
 	new_p = new_pipe();
 	ctx->pipe->next = new_p;
 	ctx->pipe = new_p;
 	ctx->child = NULL;
+// TODO: even just <enter> on command line basically generates
+// tree of three NOPs (!).
+// Can we detect that previous done_command have seen "skipping null command"
+// condition and NOT create new pipe here?
 	done_command(ctx);  /* set up new pipe to accept commands */
+	debug_printf_parse("done_pipe return 0\n");
 	return 0;
 }
 
@@ -3055,7 +3062,7 @@
 		}
 		if (m == MAP_IFS_IF_UNQUOTED) {
 			if (done_word(dest, ctx)) {
-				debug_printf_parse("parse_stream return 1\n");
+				debug_printf_parse("parse_stream return 1: done_word!=0\n");
 				return 1;
 			}
 			/* If we aren't performing a substitution, treat
@@ -3066,9 +3073,9 @@
 			}
 		}
 		if ((end_trigger && strchr(end_trigger, ch))
-		 && !dest->quote && ctx->w == RES_NONE
+		 && !dest->quote && ctx->res_w == RES_NONE
 		) {
-			debug_printf_parse("parse_stream return 0\n");
+			debug_printf_parse("parse_stream return 0: end_trigger char found\n");
 			return 0;
 		}
 		if (m == MAP_IFS_IF_UNQUOTED)
@@ -3089,7 +3096,7 @@
 		case '\\':
 			if (next == EOF) {
 				syntax();
-				debug_printf_parse("parse_stream return 1\n");
+				debug_printf_parse("parse_stream return 1: \\<eof>\n");
 				return 1;
 			}
 			b_addqchr(dest, '\\', dest->quote);
@@ -3111,7 +3118,7 @@
 			}
 			if (ch == EOF) {
 				syntax();
-				debug_printf_parse("parse_stream return 1\n");
+				debug_printf_parse("parse_stream return 1: unterminated '\n");
 				return 1;
 			}
 			break;
@@ -3204,7 +3211,7 @@
 	 * that is, we were really supposed to get end_trigger, and never got
 	 * one before the EOF.  Can't use the standard "syntax error" return code,
 	 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
-	debug_printf_parse("parse_stream return -%d\n", end_trigger != NULL);
+	debug_printf_parse("parse_stream return %d\n", -(end_trigger != NULL));
 	if (end_trigger)
 		return -1;
 	return 0;
@@ -3220,7 +3227,8 @@
 {
 	/* char *ifs and char map[256] are both globals. */
 	ifs = getenv("IFS");
-	if (ifs == NULL) ifs = " \t\n";
+	if (ifs == NULL)
+		ifs = " \t\n";
 	/* Precompute a list of 'flow through' behavior so it can be treated
 	 * quickly up front.  Computation is necessary because of IFS.
 	 * Special case handling of IFS == " \t\n" is not implemented.
@@ -3235,24 +3243,26 @@
 
 /* most recursion does not come through here, the exception is
  * from builtin_source() */
-static int parse_stream_outer(struct in_str *inp, int flag)
+static int parse_stream_outer(struct in_str *inp, int parse_flag)
 {
 // FIXME: '{ true | exit 3; echo $? }' is parsed as a whole,
 // as a result $? is replaced by 0, not 3!
-// Need to stop & execute stuff at ';', not parse till EOL!
 
 	struct p_context ctx;
 	o_string temp = NULL_O_STRING;
 	int rcode;
 	do {
-		ctx.type = flag;
+		ctx.parse_type = parse_flag;
 		initialize_context(&ctx);
 		update_ifs_map();
-		if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
+		if (!(parse_flag & FLAG_PARSE_SEMICOLON) || (parse_flag & FLAG_REPARSING))
 			mapset(";$&|", MAP_ORDINARY);
 #if ENABLE_HUSH_INTERACTIVE
 		inp->promptmode = 1;
 #endif
+		/* We will stop & execute after each ';' or '\n'.
+		 * Example: "sleep 9999; echo TEST" + ctrl-C:
+		 * TEST should be printed */
 		rcode = parse_stream(&temp, &ctx, inp, ";\n");
 		if (rcode != 1 && ctx.old_flag != 0) {
 			syntax();
@@ -3274,15 +3284,15 @@
 			free_pipe_list(ctx.list_head, 0);
 		}
 		b_free(&temp);
-	} while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP));   /* loop on syntax errors, return on EOF */
+	} while (rcode != -1 && !(parse_flag & FLAG_EXIT_FROM_LOOP));   /* loop on syntax errors, return on EOF */
 	return 0;
 }
 
-static int parse_string_outer(const char *s, int flag)
+static int parse_string_outer(const char *s, int parse_flag)
 {
 	struct in_str input;
 	setup_string_in_str(&input, s);
-	return parse_stream_outer(&input, flag);
+	return parse_stream_outer(&input, parse_flag);
 }
 
 static int parse_file_outer(FILE *f)
@@ -3303,7 +3313,7 @@
 	pid_t shell_pgrp;
 
 	saved_task_pgrp = shell_pgrp = getpgrp();
-	debug_printf("saved_task_pgrp=%d\n", saved_task_pgrp);
+	debug_printf_jobs("saved_task_pgrp=%d\n", saved_task_pgrp);
 	fcntl(interactive_fd, F_SETFD, FD_CLOEXEC);
 
 	/* If we were ran as 'hush &',
@@ -3319,7 +3329,7 @@
 	set_misc_sighandler(SIG_IGN);
 //huh?	signal(SIGCHLD, SIG_IGN);
 
-	/* We _must_ restore tty pgrp fatal signals */
+	/* We _must_ restore tty pgrp on fatal signals */
 	set_fatal_sighandler(sigexit);
 
 	/* Put ourselves in our own process group.  */



More information about the busybox-cvs mailing list