aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-05-21 10:18:23 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-05-21 10:18:23 +0000
commit219e88d0505f9c06d42772333995887ca694465a (patch)
tree6b581bd94ea16537313768a61113fb95ba453485
parent004baba2d6857a3cc0c5d25020ec257169a2d2b7 (diff)
downloadbusybox-w32-219e88d0505f9c06d42772333995887ca694465a.tar.gz
busybox-w32-219e88d0505f9c06d42772333995887ca694465a.tar.bz2
busybox-w32-219e88d0505f9c06d42772333995887ca694465a.zip
hush: using smallints where we can. save ~20 bytes in code and
some data storage at runtime.
-rw-r--r--shell/hush.c97
1 files changed, 50 insertions, 47 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 107b821f8..90c89fba2 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -137,9 +137,10 @@ static const char *indenter(int i)
137#endif 137#endif
138 138
139#define SPECIAL_VAR_SYMBOL 3 139#define SPECIAL_VAR_SYMBOL 3
140#define FLAG_EXIT_FROM_LOOP 1 140
141#define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */ 141#define PARSEFLAG_EXIT_FROM_LOOP 1
142#define FLAG_REPARSING (1 << 2) /* >= 2nd pass */ 142#define PARSEFLAG_SEMICOLON (1 << 1) /* symbol ';' is special for parser */
143#define PARSEFLAG_REPARSING (1 << 2) /* >= 2nd pass */
143 144
144typedef enum { 145typedef enum {
145 REDIRECT_INPUT = 1, 146 REDIRECT_INPUT = 1,
@@ -210,10 +211,10 @@ struct p_context {
210 struct pipe *list_head; 211 struct pipe *list_head;
211 struct pipe *pipe; 212 struct pipe *pipe;
212 struct redir_struct *pending_redirect; 213 struct redir_struct *pending_redirect;
213 reserved_style res_w; 214 smallint res_w;
214 int old_flag; /* for figuring out valid reserved words */ 215 smallint parse_type; /* bitmask of PARSEFLAG_xxx, defines type of parser : ";$" common or special symbol */
216 int old_flag; /* bitmask of FLAG_xxx, for figuring out valid reserved words */
215 struct p_context *stack; 217 struct p_context *stack;
216 int parse_type; /* define type of parser : ";$" common or special symbol */
217 /* How about quoting status? */ 218 /* How about quoting status? */
218}; 219};
219 220
@@ -249,17 +250,17 @@ struct pipe {
249 struct pipe *next; 250 struct pipe *next;
250 int num_progs; /* total number of programs in job */ 251 int num_progs; /* total number of programs in job */
251 int running_progs; /* number of programs running (not exited) */ 252 int running_progs; /* number of programs running (not exited) */
252 char *cmdbuf; /* buffer various argv's point into */ 253 int stopped_progs; /* number of programs alive, but stopped */
253#if ENABLE_HUSH_JOB 254#if ENABLE_HUSH_JOB
254 int jobid; /* job number */ 255 int jobid; /* job number */
255 char *cmdtext; /* name of job */
256 pid_t pgrp; /* process group ID for the job */ 256 pid_t pgrp; /* process group ID for the job */
257 char *cmdtext; /* name of job */
257#endif 258#endif
259 char *cmdbuf; /* buffer various argv's point into */
258 struct child_prog *progs; /* array of commands in pipe */ 260 struct child_prog *progs; /* array of commands in pipe */
259 int stopped_progs; /* number of programs alive, but stopped */
260 int job_context; /* bitmask defining current context */ 261 int job_context; /* bitmask defining current context */
261 pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ 262 smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
262 reserved_style r_mode; /* supports if, for, while, until */ 263 smallint res_word; /* needed for if, for, while, until... */
263}; 264};
264 265
265struct close_me { 266struct close_me {
@@ -271,8 +272,8 @@ struct variables {
271 struct variables *next; 272 struct variables *next;
272 const char *name; 273 const char *name;
273 const char *value; 274 const char *value;
274 int flg_export; 275 smallint flg_export;
275 int flg_read_only; 276 smallint flg_read_only;
276}; 277};
277 278
278typedef struct { 279typedef struct {
@@ -703,8 +704,8 @@ static int builtin_eval(char **argv)
703 704
704 if (argv[1]) { 705 if (argv[1]) {
705 str = make_string(argv + 1); 706 str = make_string(argv + 1);
706 parse_string_outer(str, FLAG_EXIT_FROM_LOOP | 707 parse_string_outer(str, PARSEFLAG_EXIT_FROM_LOOP |
707 FLAG_PARSE_SEMICOLON); 708 PARSEFLAG_SEMICOLON);
708 free(str); 709 free(str);
709 rcode = last_return_code; 710 rcode = last_return_code;
710 } 711 }
@@ -1897,10 +1898,11 @@ static void debug_print_tree(struct pipe *pi, int lvl)
1897 }; 1898 };
1898 1899
1899 int pin, prn; 1900 int pin, prn;
1901
1900 pin = 0; 1902 pin = 0;
1901 while (pi) { 1903 while (pi) {
1902 fprintf(stderr, "%*spipe %d r_mode=%s followup=%d %s\n", lvl*2, "", 1904 fprintf(stderr, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "",
1903 pin, RES[pi->r_mode], pi->followup, PIPE[pi->followup]); 1905 pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]);
1904 prn = 0; 1906 prn = 0;
1905 while (prn < pi->num_progs) { 1907 while (prn < pi->num_progs) {
1906 struct child_prog *child = &pi->progs[prn]; 1908 struct child_prog *child = &pi->progs[prn];
@@ -1942,21 +1944,22 @@ static int run_list_real(struct pipe *pi)
1942 int rcode = 0; /* probably for gcc only */ 1944 int rcode = 0; /* probably for gcc only */
1943 int flag_restore = 0; 1945 int flag_restore = 0;
1944 int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ 1946 int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */
1945 reserved_style rmode, skip_more_in_this_rmode = RES_XXXX; 1947 reserved_style rword;
1948 reserved_style skip_more_for_this_rword = RES_XXXX;
1946 1949
1947 debug_printf_exec("run_list_real start lvl %d\n", run_list_level + 1); 1950 debug_printf_exec("run_list_real start lvl %d\n", run_list_level + 1);
1948 1951
1949 /* check syntax for "for" */ 1952 /* check syntax for "for" */
1950 for (rpipe = pi; rpipe; rpipe = rpipe->next) { 1953 for (rpipe = pi; rpipe; rpipe = rpipe->next) {
1951 if ((rpipe->r_mode == RES_IN || rpipe->r_mode == RES_FOR) 1954 if ((rpipe->res_word == RES_IN || rpipe->res_word == RES_FOR)
1952 && (rpipe->next == NULL) 1955 && (rpipe->next == NULL)
1953 ) { 1956 ) {
1954 syntax(); /* unterminated FOR (no IN or no commands after IN) */ 1957 syntax(); /* unterminated FOR (no IN or no commands after IN) */
1955 debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level); 1958 debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level);
1956 return 1; 1959 return 1;
1957 } 1960 }
1958 if ((rpipe->r_mode == RES_IN && rpipe->next->r_mode == RES_IN && rpipe->next->progs[0].argv != NULL) 1961 if ((rpipe->res_word == RES_IN && rpipe->next->res_word == RES_IN && rpipe->next->progs[0].argv != NULL)
1959 || (rpipe->r_mode == RES_FOR && rpipe->next->r_mode != RES_IN) 1962 || (rpipe->res_word == RES_FOR && rpipe->next->res_word != RES_IN)
1960 ) { 1963 ) {
1961 /* TODO: what is tested in the first condition? */ 1964 /* TODO: what is tested in the first condition? */
1962 syntax(); /* 2nd: malformed FOR (not followed by IN) */ 1965 syntax(); /* 2nd: malformed FOR (not followed by IN) */
@@ -2008,32 +2011,32 @@ static int run_list_real(struct pipe *pi)
2008#endif 2011#endif
2009 2012
2010 for (; pi; pi = flag_restore ? rpipe : pi->next) { 2013 for (; pi; pi = flag_restore ? rpipe : pi->next) {
2011 rmode = pi->r_mode; 2014 rword = pi->res_word;
2012 if (rmode == RES_WHILE || rmode == RES_UNTIL || rmode == RES_FOR) { 2015 if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) {
2013 flag_restore = 0; 2016 flag_restore = 0;
2014 if (!rpipe) { 2017 if (!rpipe) {
2015 flag_rep = 0; 2018 flag_rep = 0;
2016 rpipe = pi; 2019 rpipe = pi;
2017 } 2020 }
2018 } 2021 }
2019 debug_printf_exec(": rmode=%d if_code=%d next_if_code=%d skip_more=%d\n", 2022 debug_printf_exec(": rword=%d if_code=%d next_if_code=%d skip_more=%d\n",
2020 rmode, if_code, next_if_code, skip_more_in_this_rmode); 2023 rword, if_code, next_if_code, skip_more_for_this_rword);
2021 if (rmode == skip_more_in_this_rmode && flag_skip) { 2024 if (rword == skip_more_for_this_rword && flag_skip) {
2022 if (pi->followup == PIPE_SEQ) 2025 if (pi->followup == PIPE_SEQ)
2023 flag_skip = 0; 2026 flag_skip = 0;
2024 continue; 2027 continue;
2025 } 2028 }
2026 flag_skip = 1; 2029 flag_skip = 1;
2027 skip_more_in_this_rmode = RES_XXXX; 2030 skip_more_for_this_rword = RES_XXXX;
2028 if (rmode == RES_THEN || rmode == RES_ELSE) 2031 if (rword == RES_THEN || rword == RES_ELSE)
2029 if_code = next_if_code; 2032 if_code = next_if_code;
2030 if (rmode == RES_THEN && if_code) 2033 if (rword == RES_THEN && if_code)
2031 continue; 2034 continue;
2032 if (rmode == RES_ELSE && !if_code) 2035 if (rword == RES_ELSE && !if_code)
2033 continue; 2036 continue;
2034 if (rmode == RES_ELIF && !if_code) 2037 if (rword == RES_ELIF && !if_code)
2035 break; 2038 break;
2036 if (rmode == RES_FOR && pi->num_progs) { 2039 if (rword == RES_FOR && pi->num_progs) {
2037 if (!for_lcur) { 2040 if (!for_lcur) {
2038 /* if no variable values after "in" we skip "for" */ 2041 /* if no variable values after "in" we skip "for" */
2039 if (!pi->next->progs->argv) 2042 if (!pi->next->progs->argv)
@@ -2059,13 +2062,13 @@ static int run_list_real(struct pipe *pi)
2059 pi->progs->argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++); 2062 pi->progs->argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++);
2060 pi->progs->glob_result.gl_pathv[0] = pi->progs->argv[0]; 2063 pi->progs->glob_result.gl_pathv[0] = pi->progs->argv[0];
2061 } 2064 }
2062 if (rmode == RES_IN) 2065 if (rword == RES_IN)
2063 continue; 2066 continue;
2064 if (rmode == RES_DO) { 2067 if (rword == RES_DO) {
2065 if (!flag_rep) 2068 if (!flag_rep)
2066 continue; 2069 continue;
2067 } 2070 }
2068 if (rmode == RES_DONE) { 2071 if (rword == RES_DONE) {
2069 if (flag_rep) { 2072 if (flag_rep) {
2070 flag_restore = 1; 2073 flag_restore = 1;
2071 } else { 2074 } else {
@@ -2107,16 +2110,16 @@ static int run_list_real(struct pipe *pi)
2107 debug_printf_exec(": setting last_return_code=%d\n", rcode); 2110 debug_printf_exec(": setting last_return_code=%d\n", rcode);
2108 last_return_code = rcode; 2111 last_return_code = rcode;
2109 pi->num_progs = save_num_progs; /* restore number of programs */ 2112 pi->num_progs = save_num_progs; /* restore number of programs */
2110 if (rmode == RES_IF || rmode == RES_ELIF) 2113 if (rword == RES_IF || rword == RES_ELIF)
2111 next_if_code = rcode; /* can be overwritten a number of times */ 2114 next_if_code = rcode; /* can be overwritten a number of times */
2112 if (rmode == RES_WHILE) 2115 if (rword == RES_WHILE)
2113 flag_rep = !last_return_code; 2116 flag_rep = !last_return_code;
2114 if (rmode == RES_UNTIL) 2117 if (rword == RES_UNTIL)
2115 flag_rep = last_return_code; 2118 flag_rep = last_return_code;
2116 if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR) 2119 if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR)
2117 || (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND) 2120 || (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND)
2118 ) { 2121 ) {
2119 skip_more_in_this_rmode = rmode; 2122 skip_more_for_this_rword = rword;
2120 } 2123 }
2121 checkjobs(NULL); 2124 checkjobs(NULL);
2122 } 2125 }
@@ -2192,7 +2195,7 @@ static int free_pipe_list(struct pipe *head, int indent)
2192 struct pipe *pi, *next; 2195 struct pipe *pi, *next;
2193 2196
2194 for (pi = head; pi; pi = next) { 2197 for (pi = head; pi; pi = next) {
2195 debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->r_mode); 2198 debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->res_word);
2196 rcode = free_pipe(pi, indent); 2199 rcode = free_pipe(pi, indent);
2197 debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup); 2200 debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup);
2198 next = pi->next; 2201 next = pi->next;
@@ -2786,7 +2789,7 @@ static struct pipe *new_pipe(void)
2786 /*pi->next = NULL;*/ 2789 /*pi->next = NULL;*/
2787 /*pi->followup = 0; invalid */ 2790 /*pi->followup = 0; invalid */
2788 if (RES_NONE) 2791 if (RES_NONE)
2789 pi->r_mode = RES_NONE; 2792 pi->res_word = RES_NONE;
2790 return pi; 2793 return pi;
2791} 2794}
2792 2795
@@ -2898,7 +2901,7 @@ static int done_word(o_string *dest, struct p_context *ctx)
2898 debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); 2901 debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
2899 return 1; 2902 return 1;
2900 } 2903 }
2901 if (!child->argv && (ctx->parse_type & FLAG_PARSE_SEMICOLON)) { 2904 if (!child->argv && (ctx->parse_type & PARSEFLAG_SEMICOLON)) {
2902 debug_printf_parse(": checking '%s' for reserved-ness\n", dest->data); 2905 debug_printf_parse(": checking '%s' for reserved-ness\n", dest->data);
2903 if (reserved_word(dest, ctx)) { 2906 if (reserved_word(dest, ctx)) {
2904 debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX)); 2907 debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX));
@@ -2986,7 +2989,7 @@ static int done_pipe(struct p_context *ctx, pipe_style type)
2986 debug_printf_parse("done_pipe entered, followup %d\n", type); 2989 debug_printf_parse("done_pipe entered, followup %d\n", type);
2987 not_null = done_command(ctx); /* implicit closure of previous command */ 2990 not_null = done_command(ctx); /* implicit closure of previous command */
2988 ctx->pipe->followup = type; 2991 ctx->pipe->followup = type;
2989 ctx->pipe->r_mode = ctx->res_w; 2992 ctx->pipe->res_word = ctx->res_w;
2990 /* Without this check, even just <enter> on command line generates 2993 /* Without this check, even just <enter> on command line generates
2991 * tree of three NOPs (!). Which is harmless but annoying. 2994 * tree of three NOPs (!). Which is harmless but annoying.
2992 * IOW: it is safe to do it unconditionally. */ 2995 * IOW: it is safe to do it unconditionally. */
@@ -3510,7 +3513,7 @@ static int parse_stream_outer(struct in_str *inp, int parse_flag)
3510 ctx.parse_type = parse_flag; 3513 ctx.parse_type = parse_flag;
3511 initialize_context(&ctx); 3514 initialize_context(&ctx);
3512 update_charmap(); 3515 update_charmap();
3513 if (!(parse_flag & FLAG_PARSE_SEMICOLON) || (parse_flag & FLAG_REPARSING)) 3516 if (!(parse_flag & PARSEFLAG_SEMICOLON) || (parse_flag & PARSEFLAG_REPARSING))
3514 set_in_charmap(";$&|", CHAR_ORDINARY); 3517 set_in_charmap(";$&|", CHAR_ORDINARY);
3515#if ENABLE_HUSH_INTERACTIVE 3518#if ENABLE_HUSH_INTERACTIVE
3516 inp->promptmode = 1; 3519 inp->promptmode = 1;
@@ -3539,7 +3542,7 @@ static int parse_stream_outer(struct in_str *inp, int parse_flag)
3539 free_pipe_list(ctx.list_head, 0); 3542 free_pipe_list(ctx.list_head, 0);
3540 } 3543 }
3541 b_free(&temp); 3544 b_free(&temp);
3542 } while (rcode != -1 && !(parse_flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ 3545 } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */
3543 return 0; 3546 return 0;
3544} 3547}
3545 3548
@@ -3555,7 +3558,7 @@ static int parse_file_outer(FILE *f)
3555 int rcode; 3558 int rcode;
3556 struct in_str input; 3559 struct in_str input;
3557 setup_file_in_str(&input, f); 3560 setup_file_in_str(&input, f);
3558 rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON); 3561 rcode = parse_stream_outer(&input, PARSEFLAG_SEMICOLON);
3559 return rcode; 3562 return rcode;
3560} 3563}
3561 3564
@@ -3646,7 +3649,7 @@ int hush_main(int argc, char **argv)
3646 case 'c': 3649 case 'c':
3647 global_argv = argv + optind; 3650 global_argv = argv + optind;
3648 global_argc = argc - optind; 3651 global_argc = argc - optind;
3649 opt = parse_string_outer(optarg, FLAG_PARSE_SEMICOLON); 3652 opt = parse_string_outer(optarg, PARSEFLAG_SEMICOLON);
3650 goto final_return; 3653 goto final_return;
3651 case 'i': 3654 case 'i':
3652 /* Well, we cannot just declare interactiveness, 3655 /* Well, we cannot just declare interactiveness,