aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-04 12:12:58 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-04 12:12:58 +0000
commit6da69cddc022773a062a039e354d1ad0ed3e32c8 (patch)
tree83874ddaf0f8d3726fea433e2fa3c405a63092bc /shell
parentdfa9de71769f2ce9449b43f389962cc977663179 (diff)
downloadbusybox-w32-6da69cddc022773a062a039e354d1ad0ed3e32c8.tar.gz
busybox-w32-6da69cddc022773a062a039e354d1ad0ed3e32c8.tar.bz2
busybox-w32-6da69cddc022773a062a039e354d1ad0ed3e32c8.zip
hush: get rid of charmap[]
function old new delta parse_stream 1447 1508 +61 get_local_var_value - 31 +31 run_list 2018 2020 +2 pseudo_exec_argv 151 149 -2 maybe_set_sighandler 50 47 -3 hush_exit 93 90 -3 builtin_wait 275 272 -3 check_and_run_traps 169 164 -5 hush_main 985 977 -8 file_get 260 240 -20 builtin_trap 438 414 -24 set_in_charmap 30 - -30 lookup_param 31 - -31 parse_and_run_stream 153 54 -99 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 2/9 up/down: 94/-228) Total: -134 bytes
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c145
1 files changed, 55 insertions, 90 deletions
diff --git a/shell/hush.c b/shell/hush.c
index efb20d91e..a57d5d811 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -61,7 +61,6 @@
61 * figure out what to do with backslash-newline 61 * figure out what to do with backslash-newline
62 * propagate syntax errors, die on resource errors? 62 * propagate syntax errors, die on resource errors?
63 * continuation lines, both explicit and implicit - done? 63 * continuation lines, both explicit and implicit - done?
64 * maybe change charmap[] to use 2-bit entries
65 * 64 *
66 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 65 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
67 */ 66 */
@@ -201,30 +200,25 @@ static void debug_print_strings(const char *prefix, char **vv)
201 * Leak hunting. Use hush_leaktool.sh for post-processing. 200 * Leak hunting. Use hush_leaktool.sh for post-processing.
202 */ 201 */
203#ifdef FOR_HUSH_LEAKTOOL 202#ifdef FOR_HUSH_LEAKTOOL
204/* suppress "warning: no previous prototype..." */ 203static void *xxmalloc(int lineno, size_t size)
205void *xxmalloc(int lineno, size_t size);
206void *xxrealloc(int lineno, void *ptr, size_t size);
207char *xxstrdup(int lineno, const char *str);
208void xxfree(void *ptr);
209void *xxmalloc(int lineno, size_t size)
210{ 204{
211 void *ptr = xmalloc((size + 0xff) & ~0xff); 205 void *ptr = xmalloc((size + 0xff) & ~0xff);
212 fdprintf(2, "line %d: malloc %p\n", lineno, ptr); 206 fdprintf(2, "line %d: malloc %p\n", lineno, ptr);
213 return ptr; 207 return ptr;
214} 208}
215void *xxrealloc(int lineno, void *ptr, size_t size) 209static void *xxrealloc(int lineno, void *ptr, size_t size)
216{ 210{
217 ptr = xrealloc(ptr, (size + 0xff) & ~0xff); 211 ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
218 fdprintf(2, "line %d: realloc %p\n", lineno, ptr); 212 fdprintf(2, "line %d: realloc %p\n", lineno, ptr);
219 return ptr; 213 return ptr;
220} 214}
221char *xxstrdup(int lineno, const char *str) 215static char *xxstrdup(int lineno, const char *str)
222{ 216{
223 char *ptr = xstrdup(str); 217 char *ptr = xstrdup(str);
224 fdprintf(2, "line %d: strdup %p\n", lineno, ptr); 218 fdprintf(2, "line %d: strdup %p\n", lineno, ptr);
225 return ptr; 219 return ptr;
226} 220}
227void xxfree(void *ptr) 221static void xxfree(void *ptr)
228{ 222{
229 fdprintf(2, "free %p\n", ptr); 223 fdprintf(2, "free %p\n", ptr);
230 free(ptr); 224 free(ptr);
@@ -491,14 +485,6 @@ struct globals {
491 const char *cwd; 485 const char *cwd;
492 struct variable *top_var; /* = &G.shell_ver (set in main()) */ 486 struct variable *top_var; /* = &G.shell_ver (set in main()) */
493 struct variable shell_ver; 487 struct variable shell_ver;
494#if ENABLE_FEATURE_SH_STANDALONE
495 struct nofork_save_area nofork_save;
496#endif
497#if ENABLE_HUSH_JOB
498 sigjmp_buf toplevel_jb;
499#endif
500 unsigned char charmap[256];
501 char user_input_buf[ENABLE_FEATURE_EDITING ? BUFSIZ : 2];
502 /* Signal and trap handling */ 488 /* Signal and trap handling */
503// unsigned count_SIGCHLD; 489// unsigned count_SIGCHLD;
504// unsigned handled_SIGCHLD; 490// unsigned handled_SIGCHLD;
@@ -507,6 +493,13 @@ struct globals {
507 char **traps; /* char *traps[NSIG] */ 493 char **traps; /* char *traps[NSIG] */
508 sigset_t blocked_set; 494 sigset_t blocked_set;
509 sigset_t inherited_set; 495 sigset_t inherited_set;
496 char user_input_buf[ENABLE_FEATURE_EDITING ? BUFSIZ : 2];
497#if ENABLE_FEATURE_SH_STANDALONE
498 struct nofork_save_area nofork_save;
499#endif
500#if ENABLE_HUSH_JOB
501 sigjmp_buf toplevel_jb;
502#endif
510}; 503};
511#define G (*ptr_to_globals) 504#define G (*ptr_to_globals)
512/* Not #defining name to G.name - this quickly gets unwieldy 505/* Not #defining name to G.name - this quickly gets unwieldy
@@ -1042,9 +1035,7 @@ static struct variable *get_local_var(const char *name)
1042 return NULL; 1035 return NULL;
1043} 1036}
1044 1037
1045/* Basically useful version until someone wants to get fancier, 1038static const char *get_local_var_value(const char *src)
1046 * see the bash man page under "Parameter Expansion" */
1047static const char *lookup_param(const char *src)
1048{ 1039{
1049 struct variable *var = get_local_var(src); 1040 struct variable *var = get_local_var(src);
1050 if (var) 1041 if (var)
@@ -1842,7 +1833,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
1842 o_free(&dest); 1833 o_free(&dest);
1843 } 1834 }
1844 skip_expand: 1835 skip_expand:
1845 hooks.lookupvar = lookup_param; 1836 hooks.lookupvar = get_local_var_value;
1846 hooks.setvar = arith_set_local_var; 1837 hooks.setvar = arith_set_local_var;
1847 hooks.endofname = endofname; 1838 hooks.endofname = endofname;
1848 res = arith(exp_str ? exp_str : arg, &errcode, &hooks); 1839 res = arith(exp_str ? exp_str : arg, &errcode, &hooks);
@@ -1898,7 +1889,7 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
1898 val = G.global_argv[i]; 1889 val = G.global_argv[i];
1899 /* else val remains NULL: $N with too big N */ 1890 /* else val remains NULL: $N with too big N */
1900 } else 1891 } else
1901 val = lookup_param(var); 1892 val = get_local_var_value(var);
1902 1893
1903 /* handle any expansions */ 1894 /* handle any expansions */
1904 if (exp_len) { 1895 if (exp_len) {
@@ -4118,7 +4109,7 @@ static int handle_dollar(o_string *dest, struct in_str *input)
4118 4109
4119static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote_end) 4110static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote_end)
4120{ 4111{
4121 int ch, m; 4112 int ch;
4122 int next; 4113 int next;
4123 4114
4124 again: 4115 again:
@@ -4136,7 +4127,6 @@ static int parse_stream_dquoted(o_string *dest, struct in_str *input, int dquote
4136 return 1; 4127 return 1;
4137 } 4128 }
4138 next = '\0'; 4129 next = '\0';
4139 m = G.charmap[ch];
4140 if (ch != '\n') { 4130 if (ch != '\n') {
4141 next = i_peek(input); 4131 next = i_peek(input);
4142 } 4132 }
@@ -4206,11 +4196,11 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4206{ 4196{
4207 struct parse_context ctx; 4197 struct parse_context ctx;
4208 o_string dest = NULL_O_STRING; 4198 o_string dest = NULL_O_STRING;
4209 int ch, m;
4210 int redir_fd; 4199 int redir_fd;
4211 redir_type redir_style;
4212 int is_in_dquote;
4213 int next; 4200 int next;
4201 int is_in_dquote;
4202 int ch;
4203 redir_type redir_style;
4214 4204
4215 /* Double-quote state is handled in the state variable is_in_dquote. 4205 /* Double-quote state is handled in the state variable is_in_dquote.
4216 * A single-quote triggers a bypass of the main loop until its mate is 4206 * A single-quote triggers a bypass of the main loop until its mate is
@@ -4219,6 +4209,10 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4219 debug_printf_parse("parse_stream entered, end_trigger='%c'\n", 4209 debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
4220 end_trigger ? : 'X'); 4210 end_trigger ? : 'X');
4221 4211
4212 G.ifs = get_local_var_value("IFS");
4213 if (G.ifs == NULL)
4214 G.ifs = " \t\n";
4215
4222 reset: 4216 reset:
4223#if ENABLE_HUSH_INTERACTIVE 4217#if ENABLE_HUSH_INTERACTIVE
4224 input->promptmode = 0; /* PS1 */ 4218 input->promptmode = 0; /* PS1 */
@@ -4227,6 +4221,9 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4227 initialize_context(&ctx); 4221 initialize_context(&ctx);
4228 is_in_dquote = 0; 4222 is_in_dquote = 0;
4229 while (1) { 4223 while (1) {
4224 const char *is_ifs;
4225 const char *is_special;
4226
4230 if (is_in_dquote) { 4227 if (is_in_dquote) {
4231 if (parse_stream_dquoted(&dest, input, '"')) { 4228 if (parse_stream_dquoted(&dest, input, '"')) {
4232 goto parse_error; 4229 goto parse_error;
@@ -4234,18 +4231,38 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4234 /* We reached closing '"' */ 4231 /* We reached closing '"' */
4235 is_in_dquote = 0; 4232 is_in_dquote = 0;
4236 } 4233 }
4237 m = CHAR_IFS;
4238 next = '\0'; 4234 next = '\0';
4239 ch = i_getch(input); 4235 ch = i_getch(input);
4240 if (ch != EOF) { 4236 debug_printf_parse(": ch=%c (%d) escape=%d\n",
4241 m = G.charmap[ch]; 4237 ch, ch, dest.o_escape);
4242 if (ch != '\n') { 4238 if (ch == EOF) {
4243 next = i_peek(input); 4239 struct pipe *pi;
4240 if (done_word(&dest, &ctx)) {
4241 goto parse_error;
4242 }
4243 o_free(&dest);
4244 done_pipe(&ctx, PIPE_SEQ);
4245 /* If we got nothing... */
4246 pi = ctx.list_head;
4247 if (pi->num_cmds == 0
4248 IF_HAS_KEYWORDS( && pi->res_word == RES_NONE)
4249 ) {
4250 free_pipe_list(pi, 0);
4251 pi = NULL;
4244 } 4252 }
4253 debug_printf_parse("parse_stream return %p\n", pi);
4254 return pi;
4245 } 4255 }
4246 debug_printf_parse(": ch=%c (%d) m=%d escape=%d\n", 4256 if (ch != '\n') {
4247 ch, ch, m, dest.o_escape); 4257 next = i_peek(input);
4248 if (m == CHAR_ORDINARY) { 4258 }
4259
4260 is_ifs = strchr(G.ifs, ch);
4261 is_special = strchr("<>;&|(){}#'" /* special outside of "str" */
4262 "\\$\"" USE_HUSH_TICK("`") /* always special */
4263 , ch);
4264
4265 if (!is_special && !is_ifs) { /* ordinary char */
4249 o_addQchr(&dest, ch); 4266 o_addQchr(&dest, ch);
4250 if ((dest.o_assignment == MAYBE_ASSIGNMENT 4267 if ((dest.o_assignment == MAYBE_ASSIGNMENT
4251 || dest.o_assignment == WORD_IS_KEYWORD) 4268 || dest.o_assignment == WORD_IS_KEYWORD)
@@ -4257,27 +4274,7 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4257 continue; 4274 continue;
4258 } 4275 }
4259 4276
4260 /* m is SPECIAL ($,`), IFS, or ORDINARY_IF_QUOTED (*,#) */ 4277 if (is_ifs) {
4261
4262 if (m == CHAR_IFS) {
4263 if (ch == EOF) {
4264 struct pipe *pi;
4265 if (done_word(&dest, &ctx)) {
4266 goto parse_error;
4267 }
4268 o_free(&dest);
4269 done_pipe(&ctx, PIPE_SEQ);
4270 /* If we got nothing... */
4271 pi = ctx.list_head;
4272 if (pi->num_cmds == 0
4273 IF_HAS_KEYWORDS( && pi->res_word == RES_NONE)
4274 ) {
4275 free_pipe_list(pi, 0);
4276 pi = NULL;
4277 }
4278 debug_printf_parse("parse_stream return %p\n", pi);
4279 return pi;
4280 }
4281 if (done_word(&dest, &ctx)) { 4278 if (done_word(&dest, &ctx)) {
4282 goto parse_error; 4279 goto parse_error;
4283 } 4280 }
@@ -4317,11 +4314,9 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4317 return ctx.list_head; 4314 return ctx.list_head;
4318 } 4315 }
4319 } 4316 }
4320 if (m == CHAR_IFS) 4317 if (is_ifs)
4321 continue; 4318 continue;
4322 4319
4323 /* m is SPECIAL (e.g. $,`) or ORDINARY_IF_QUOTED (*,#) */
4324
4325 if (dest.o_assignment == MAYBE_ASSIGNMENT) { 4320 if (dest.o_assignment == MAYBE_ASSIGNMENT) {
4326 /* ch is a special char and thus this word 4321 /* ch is a special char and thus this word
4327 * cannot be an assignment */ 4322 * cannot be an assignment */
@@ -4579,33 +4574,6 @@ static struct pipe *parse_stream(struct in_str *input, int end_trigger)
4579 } 4574 }
4580} 4575}
4581 4576
4582static void set_in_charmap(const char *set, int code)
4583{
4584 while (*set)
4585 G.charmap[(unsigned char)*set++] = code;
4586}
4587
4588static void update_charmap(void)
4589{
4590 G.ifs = getenv("IFS");
4591 if (G.ifs == NULL)
4592 G.ifs = " \t\n";
4593 /* Precompute a list of 'flow through' behavior so it can be treated
4594 * quickly up front. Computation is necessary because of IFS.
4595 * Special case handling of IFS == " \t\n" is not implemented.
4596 * The charmap[] array only really needs two bits each,
4597 * and on most machines that would be faster (reduced L1 cache use).
4598 */
4599 memset(G.charmap, CHAR_ORDINARY, sizeof(G.charmap));
4600#if ENABLE_HUSH_TICK
4601 set_in_charmap("\\$\"`", CHAR_SPECIAL);
4602#else
4603 set_in_charmap("\\$\"", CHAR_SPECIAL);
4604#endif
4605 set_in_charmap("<>;&|(){}#'", CHAR_ORDINARY_IF_QUOTED);
4606 set_in_charmap(G.ifs, CHAR_IFS); /* are ordinary if quoted */
4607}
4608
4609/* Execiting from string: eval, sh -c '...' 4577/* Execiting from string: eval, sh -c '...'
4610 * or from file: /etc/profile, . file, sh <script>, sh (intereactive) 4578 * or from file: /etc/profile, . file, sh <script>, sh (intereactive)
4611 * end_trigger controls how often we stop parsing 4579 * end_trigger controls how often we stop parsing
@@ -4617,15 +4585,12 @@ static void parse_and_run_stream(struct in_str *inp, int end_trigger)
4617 while (1) { 4585 while (1) {
4618 struct pipe *pipe_list; 4586 struct pipe *pipe_list;
4619 4587
4620 update_charmap();
4621
4622 pipe_list = parse_stream(inp, end_trigger); 4588 pipe_list = parse_stream(inp, end_trigger);
4623 if (!pipe_list) /* EOF */ 4589 if (!pipe_list) /* EOF */
4624 break; 4590 break;
4625 debug_print_tree(pipe_list, 0); 4591 debug_print_tree(pipe_list, 0);
4626 debug_printf_exec("parse_and_run_stream: run_and_free_list\n"); 4592 debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
4627 run_and_free_list(pipe_list); 4593 run_and_free_list(pipe_list);
4628 /* Loop on syntax errors, return on EOF: */
4629 } 4594 }
4630} 4595}
4631 4596