diff options
Diffstat (limited to 'str_array.c')
-rw-r--r-- | str_array.c | 173 |
1 files changed, 116 insertions, 57 deletions
diff --git a/str_array.c b/str_array.c index 8fb6ba8a..33c9ddcc 100644 --- a/str_array.c +++ b/str_array.c @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 1986, 1988, 1989, 1991-2011 the Free Software Foundation, Inc. + * Copyright (C) 1986, 1988, 1989, 1991-2013 the Free Software Foundation, Inc. * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. @@ -55,14 +55,10 @@ static NODE **str_list(NODE *symbol, NODE *subs); static NODE **str_copy(NODE *symbol, NODE *newsymb); static NODE **str_dump(NODE *symbol, NODE *ndump); -#ifdef ARRAYDEBUG -static NODE **str_option(NODE *opt, NODE *val); -#endif - - -array_ptr str_array_func[] = { +afunc_t str_array_func[] = { str_array_init, - (array_ptr) 0, + (afunc_t) 0, + null_length, str_lookup, str_exists, str_clear, @@ -70,9 +66,26 @@ array_ptr str_array_func[] = { str_list, str_copy, str_dump, -#ifdef ARRAYDEBUG - str_option -#endif + (afunc_t) 0, +}; + +static NODE **env_remove(NODE *symbol, NODE *subs); +static NODE **env_store(NODE *symbol, NODE *subs); +static NODE **env_clear(NODE *symbol, NODE *subs); + +/* special case for ENVIRON */ +afunc_t env_array_func[] = { + str_array_init, + (afunc_t) 0, + null_length, + str_lookup, + str_exists, + env_clear, + env_remove, + str_list, + str_copy, + str_dump, + env_store, }; static inline NODE **str_find(NODE *symbol, NODE *s1, size_t code1, unsigned long hash1); @@ -85,18 +98,23 @@ static unsigned long awk_hash(const char *s, size_t len, unsigned long hsize, si unsigned long (*hash)(const char *s, size_t len, unsigned long hsize, size_t *code) = awk_hash; -/* str_array_init --- check relevant environment variables */ +/* str_array_init --- array initialization routine */ static NODE ** str_array_init(NODE *symbol ATTRIBUTE_UNUSED, NODE *subs ATTRIBUTE_UNUSED) { - long newval; - const char *val; + if (symbol == NULL) { /* first time */ + long newval; + const char *val; + + /* check relevant environment variables */ + if ((newval = getenv_long("STR_CHAIN_MAX")) > 0) + STR_CHAIN_MAX = newval; + if ((val = getenv("AWK_HASH")) != NULL && strcmp(val, "gst") == 0) + hash = gst_hash_string; + } else + null_array(symbol); - if ((newval = getenv_long("STR_CHAIN_MAX")) > 0) - STR_CHAIN_MAX = newval; - if ((val = getenv("AWK_HASH")) != NULL && strcmp(val, "gst") == 0) - hash = gst_hash_string; return (NODE **) ! NULL; } @@ -158,7 +176,7 @@ str_lookup(NODE *symbol, NODE *subs) * never be used. */ - if (subs->flags & NUMCUR) { + if ((subs->flags & (MPFN|MPZN|NUMCUR)) == NUMCUR) { tmp->numbr = subs->numbr; tmp->flags |= NUMCUR; } @@ -187,16 +205,15 @@ str_lookup(NODE *symbol, NODE *subs) static NODE ** str_exists(NODE *symbol, NODE *subs) { - NODE **lhs; unsigned long hash1; size_t code1; - assert(symbol->table_size > 0); + if (symbol->table_size == 0) + return NULL; subs = force_string(subs); hash1 = hash(subs->stptr, subs->stlen, (unsigned long) symbol->array_size, & code1); - lhs = str_find(symbol, subs, code1, hash1); - return lhs; + return str_find(symbol, subs, code1, hash1); } /* str_clear --- flush all the values in symbol[] */ @@ -226,8 +243,7 @@ str_clear(NODE *symbol, NODE *subs ATTRIBUTE_UNUSED) if (symbol->buckets != NULL) efree(symbol->buckets); - init_array(symbol); /* re-initialize symbol */ - symbol->flags &= ~ARRAYMAXED; + symbol->ainit(symbol, NULL); /* re-initialize symbol */ return NULL; } @@ -242,7 +258,8 @@ str_remove(NODE *symbol, NODE *subs) NODE *s2; size_t s1_len; - assert(symbol->table_size > 0); + if (symbol->table_size == 0) + return NULL; s2 = force_string(subs); hash1 = hash(s2->stptr, s2->stlen, (unsigned long) symbol->array_size, NULL); @@ -272,8 +289,7 @@ str_remove(NODE *symbol, NODE *subs) if (--symbol->table_size == 0) { if (symbol->buckets != NULL) efree(symbol->buckets); - init_array(symbol); /* re-initialize symbol */ - symbol->flags &= ~ARRAYMAXED; + symbol->ainit(symbol, NULL); /* re-initialize symbol */ } return (NODE **) ! NULL; /* return success */ @@ -335,6 +351,7 @@ str_copy(NODE *symbol, NODE *newsymb) newchain->ahcode = chain->ahcode; *pnew = newchain; + newchain->ahnext = NULL; pnew = & newchain->ahnext; } } @@ -357,15 +374,18 @@ str_list(NODE *symbol, NODE *t) BUCKET *b; unsigned long num_elems, list_size, i, k = 0; int elem_size = 1; + assoc_kind_t assoc_kind; - assert(symbol->table_size > 0); + if (symbol->table_size == 0) + return NULL; - if ((t->flags & (AINDEX|AVALUE)) == (AINDEX|AVALUE)) + assoc_kind = (assoc_kind_t) t->flags; + if ((assoc_kind & (AINDEX|AVALUE)) == (AINDEX|AVALUE)) elem_size = 2; /* allocate space for array */ num_elems = symbol->table_size; - if ((t->flags & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE)) + if ((assoc_kind & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE)) num_elems = 1; list_size = elem_size * num_elems; @@ -377,17 +397,17 @@ str_list(NODE *symbol, NODE *t) for (b = symbol->buckets[i]; b != NULL; b = b->ahnext) { /* index */ subs = b->ahname; - if (t->flags & AINUM) + if ((assoc_kind & AINUM) != 0) (void) force_number(subs); list[k++] = dupnode(subs); /* value */ - if (t->flags & AVALUE) { + if ((assoc_kind & AVALUE) != 0) { val = b->ahvalue; if (val->type == Node_val) { - if ((t->flags & AVNUM) != 0) + if ((assoc_kind & AVNUM) != 0) (void) force_number(val); - else if ((t->flags & AVSTR) != 0) + else if ((assoc_kind & AVSTR) != 0) val = force_string(val); } list[k++] = val; @@ -443,7 +463,7 @@ str_dump(NODE *symbol, NODE *ndump) fprintf(output_fp, "flags: %s\n", flags2str(symbol->flags)); } indent(indent_level); - fprintf(output_fp, "STR_CHAIN_MAX: %lu\n", STR_CHAIN_MAX); + fprintf(output_fp, "STR_CHAIN_MAX: %lu\n", (unsigned long) STR_CHAIN_MAX); indent(indent_level); fprintf(output_fp, "array_size: %lu\n", (unsigned long) symbol->array_size); indent(indent_level); @@ -670,27 +690,6 @@ grow_table(NODE *symbol) } -#ifdef ARRAYDEBUG - -static NODE ** -str_option(NODE *opt, NODE *val) -{ - int newval; - NODE *tmp; - NODE **ret = (NODE **) ! NULL; - - tmp = force_string(opt); - (void) force_number(val); - if (STREQ(tmp->stptr, "STR_CHAIN_MAX")) { - newval = (int) val->numbr; - if (newval > 0) - STR_CHAIN_MAX = newval; - } else - ret = NULL; - return ret; -} -#endif - /* From bonzini@gnu.org Mon Oct 28 16:05:26 2002 @@ -757,3 +756,63 @@ scramble(unsigned long x) return x; } + +/* env_remove --- for ENVIRON, remove value from real environment */ + +static NODE ** +env_remove(NODE *symbol, NODE *subs) +{ + NODE **val = str_remove(symbol, subs); + + if (val != NULL) + (void) unsetenv(subs->stptr); + + return val; +} + +/* env_clear --- clear out the environment when ENVIRON is deleted */ + +static NODE ** +env_clear(NODE *symbol, NODE *subs) +{ + extern char **environ; + NODE **val = str_clear(symbol, subs); + + environ = NULL; /* ZAP! */ + + /* str_clear zaps the vtable, reset it */ + symbol->array_funcs = env_array_func; + + return val; +} + +/* env_store --- post assign function for ENVIRON, put new value into env */ + +static NODE ** +env_store(NODE *symbol, NODE *subs) +{ + NODE **val = str_exists(symbol, subs); + const char *newval; + + assert(val != NULL); + + newval = (*val)->stptr; + if (newval == NULL) + newval = ""; + + (void) setenv(subs->stptr, newval, 1); + + return val; +} + +/* init_env_array --- set up the pointers for ENVIRON. A bit hacky. */ + +void +init_env_array(NODE *env_node) +{ + /* If POSIX simply don't reset the vtable and things work as before */ + if (do_posix) + return; + + env_node->array_funcs = env_array_func; +} |