hush: fix incorrect processing of echo "'$var'".

hush: rename map[] and MAP_xxx, making them easier to understand.
hush: move testcase (which now passes) from hush-bugs to hush-parsing
This commit is contained in:
Denis Vlasenko 2007-05-16 09:36:55 +00:00
parent 418a7fb29b
commit 8f6bdb42df
3 changed files with 25 additions and 25 deletions

View File

@ -71,7 +71,7 @@
* memory leak finding and plugging - done? * memory leak finding and plugging - done?
* more testing, especially quoting rules and redirection * more testing, especially quoting rules and redirection
* document how quoting rules not precisely followed for variable assignments * document how quoting rules not precisely followed for variable assignments
* maybe change map[] to use 2-bit entries * maybe change charmap[] to use 2-bit entries
* (eventually) remove all the printf's * (eventually) remove all the printf's
* *
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
@ -281,12 +281,12 @@ extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
/* "globals" within this file */ /* "globals" within this file */
enum { enum {
MAP_ORDINARY = 0, CHAR_ORDINARY = 0,
MAP_FLOWTROUGH_IF_QUOTED = 1, CHAR_ORDINARY_IF_QUOTED = 1, /* example: *, # */
MAP_IFS_IF_UNQUOTED = 2, /* flow through if quoted too */ CHAR_IFS = 2, /* treated as ordinary if quoted */
MAP_NEVER_FLOWTROUGH = 3, CHAR_SPECIAL = 3, /* example: $ */
}; };
static unsigned char map[256]; static unsigned char charmap[256];
static const char *ifs; static const char *ifs;
static int fake_mode; static int fake_mode;
static struct close_me *close_me_head; static struct close_me *close_me_head;
@ -2311,7 +2311,7 @@ static int xglob(o_string *dest, int flags, glob_t *pglob)
* Caller can deallocate entire list by single free(list). */ * Caller can deallocate entire list by single free(list). */
/* Helpers first: /* Helpers first:
* count_XXX estimates, how large block do we need. It's okay * count_XXX estimates size of the block we need. It's okay
* to over-estimate sizes a bit, if it makes code simpler */ * to over-estimate sizes a bit, if it makes code simpler */
static int count_ifs(const char *str) static int count_ifs(const char *str)
{ {
@ -3360,17 +3360,17 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger); debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger);
while ((ch = b_getch(input)) != EOF) { while ((ch = b_getch(input)) != EOF) {
m = map[ch]; m = charmap[ch];
next = (ch == '\n') ? '\0' : b_peek(input); next = (ch == '\n') ? '\0' : b_peek(input);
debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n", debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n",
ch, ch, m, dest->quote); ch, ch, m, dest->quote);
if (m == MAP_ORDINARY if (m == CHAR_ORDINARY
|| (m != MAP_NEVER_FLOWTROUGH && dest->quote) || (m != CHAR_SPECIAL && dest->quote)
) { ) {
b_addqchr(dest, ch, dest->quote); b_addqchr(dest, ch, dest->quote);
continue; continue;
} }
if (m == MAP_IFS_IF_UNQUOTED) { if (m == CHAR_IFS) {
if (done_word(dest, ctx)) { if (done_word(dest, ctx)) {
debug_printf_parse("parse_stream return 1: done_word!=0\n"); debug_printf_parse("parse_stream return 1: done_word!=0\n");
return 1; return 1;
@ -3388,7 +3388,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
debug_printf_parse("parse_stream return 0: end_trigger char found\n"); debug_printf_parse("parse_stream return 0: end_trigger char found\n");
return 0; return 0;
} }
if (m == MAP_IFS_IF_UNQUOTED) if (m == CHAR_IFS)
continue; continue;
switch (ch) { switch (ch) {
case '#': case '#':
@ -3527,28 +3527,28 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
return 0; return 0;
} }
static void mapset(const char *set, int code) static void set_in_charmap(const char *set, int code)
{ {
while (*set) while (*set)
map[(unsigned char)*set++] = code; charmap[(unsigned char)*set++] = code;
} }
static void update_ifs_map(void) static void update_charmap(void)
{ {
/* char *ifs and char map[256] are both globals. */ /* char *ifs and char charmap[256] are both globals. */
ifs = getenv("IFS"); ifs = getenv("IFS");
if (ifs == NULL) if (ifs == NULL)
ifs = " \t\n"; ifs = " \t\n";
/* Precompute a list of 'flow through' behavior so it can be treated /* Precompute a list of 'flow through' behavior so it can be treated
* quickly up front. Computation is necessary because of IFS. * quickly up front. Computation is necessary because of IFS.
* Special case handling of IFS == " \t\n" is not implemented. * Special case handling of IFS == " \t\n" is not implemented.
* The map[] array only really needs two bits each, and on most machines * The charmap[] array only really needs two bits each,
* that would be faster because of the reduced L1 cache footprint. * and on most machines that would be faster (reduced L1 cache use).
*/ */
memset(map, MAP_ORDINARY, sizeof(map)); /* most chars flow through always */ memset(charmap, CHAR_ORDINARY, sizeof(charmap));
mapset("\\$'\"`", MAP_NEVER_FLOWTROUGH); set_in_charmap("\\$\"`", CHAR_SPECIAL);
mapset("<>;&|(){}#", MAP_FLOWTROUGH_IF_QUOTED); set_in_charmap("<>;&|(){}#'", CHAR_ORDINARY_IF_QUOTED);
mapset(ifs, MAP_IFS_IF_UNQUOTED); /* also flow through if quoted */ set_in_charmap(ifs, CHAR_IFS); /* also flow through if quoted */
} }
/* most recursion does not come through here, the exception is /* most recursion does not come through here, the exception is
@ -3561,9 +3561,9 @@ static int parse_stream_outer(struct in_str *inp, int parse_flag)
do { do {
ctx.parse_type = parse_flag; ctx.parse_type = parse_flag;
initialize_context(&ctx); initialize_context(&ctx);
update_ifs_map(); update_charmap();
if (!(parse_flag & FLAG_PARSE_SEMICOLON) || (parse_flag & FLAG_REPARSING)) if (!(parse_flag & FLAG_PARSE_SEMICOLON) || (parse_flag & FLAG_REPARSING))
mapset(";$&|", MAP_ORDINARY); set_in_charmap(";$&|", CHAR_ORDINARY);
#if ENABLE_HUSH_INTERACTIVE #if ENABLE_HUSH_INTERACTIVE
inp->promptmode = 1; inp->promptmode = 1;
#endif #endif
@ -3665,7 +3665,7 @@ int hush_main(int argc, char **argv)
* hush_main(), therefore we cannot rely on the BSS to zero out this * hush_main(), therefore we cannot rely on the BSS to zero out this
* stuff. Reset these to 0 every time. */ * stuff. Reset these to 0 every time. */
ifs = NULL; ifs = NULL;
/* map[] is taken care of with call to update_ifs_map() */ /* charmap[] is taken care of with call to update_charmap() */
fake_mode = 0; fake_mode = 0;
close_me_head = NULL; close_me_head = NULL;
#if ENABLE_HUSH_INTERACTIVE #if ENABLE_HUSH_INTERACTIVE