diff options
Diffstat (limited to 'str_array.c')
-rw-r--r-- | str_array.c | 115 |
1 files changed, 97 insertions, 18 deletions
diff --git a/str_array.c b/str_array.c index 460e2f1d..65e0b741 100644 --- a/str_array.c +++ b/str_array.c @@ -2,23 +2,23 @@ * str_array.c - routines for associative arrays of string indices. */ -/* +/* * Copyright (C) 1986, 1988, 1989, 1991-2013, 2016, * the Free Software Foundation, Inc. - * + * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. - * + * * GAWK is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * + * * GAWK is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA @@ -70,6 +70,25 @@ afunc_t str_array_func[] = { (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); static void grow_table(NODE *symbol); @@ -107,7 +126,7 @@ str_array_init(NODE *symbol ATTRIBUTE_UNUSED, NODE *subs ATTRIBUTE_UNUSED) * isn't there. Returns a pointer ala get_lhs to where its value is stored. * * SYMBOL is the address of the node (or other pointer) being dereferenced. - * SUBS is a number or string used as the subscript. + * SUBS is a number or string used as the subscript. */ static NODE ** @@ -149,7 +168,7 @@ str_lookup(NODE *symbol, NODE *subs) * flag on it since other variables could be using the same * reference-counted value. */ - if (subs->stfmt != -1 || (subs->flags & MAYBE_NUM) != 0) { + if (subs->stfmt != STFMT_UNUSED || (subs->flags & MAYBE_NUM) != 0) { NODE *tmp; /* @@ -175,7 +194,7 @@ str_lookup(NODE *symbol, NODE *subs) } subs = tmp; } else { - /* string value already "frozen" */ + /* string value already "frozen" */ subs = dupnode(subs); } @@ -226,7 +245,7 @@ str_clear(NODE *symbol, NODE *subs ATTRIBUTE_UNUSED) r = b->ahvalue; if (r->type == Node_var_array) { assoc_clear(r); /* recursively clear all sub-arrays */ - efree(r->vname); + efree(r->vname); freenode(r); } else unref(r); @@ -303,7 +322,7 @@ str_copy(NODE *symbol, NODE *newsymb) BUCKET **old, **new, **pnew; BUCKET *chain, *newchain; unsigned long cursize, i; - + assert(symbol->table_size > 0); /* find the current hash size */ @@ -349,7 +368,7 @@ str_copy(NODE *symbol, NODE *newsymb) newchain->ahnext = NULL; pnew = & newchain->ahnext; } - } + } newsymb->table_size = symbol->table_size; newsymb->buckets = new; @@ -383,9 +402,9 @@ str_list(NODE *symbol, NODE *t) if ((assoc_kind & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE)) num_elems = 1; list_size = elem_size * num_elems; - + emalloc(list, NODE **, list_size * sizeof(NODE *), "str_list"); - + /* populate it */ for (i = 0; i < symbol->array_size; i++) { @@ -409,7 +428,7 @@ str_list(NODE *symbol, NODE *t) } if (k >= list_size) return list; - } + } } return list; } @@ -426,7 +445,7 @@ str_kilobytes(NODE *symbol) bucket_cnt = symbol->table_size; /* This does not include extra memory for indices with stfmt != -1 */ - kb = (((AWKNUM) bucket_cnt) * sizeof (BUCKET) + + kb = (((AWKNUM) bucket_cnt) * sizeof (BUCKET) + ((AWKNUM) symbol->array_size) * sizeof (BUCKET *)) / 1024.0; return kb; } @@ -514,7 +533,7 @@ str_dump(NODE *symbol, NODE *ndump) return NULL; #undef HCNT -} +} /* awk_hash --- calculate the hash function of the string in subs */ @@ -627,11 +646,11 @@ grow_table(NODE *symbol) * very large (> 8K), we just double more or less, instead of * just jumping from 8K to 64K. */ - + static const unsigned long sizes[] = { 13, 127, 1021, 8191, 16381, 32749, 65497, 131101, 262147, 524309, 1048583, 2097169, - 4194319, 8388617, 16777259, 33554467, + 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459, 536870923, 1073741827 }; @@ -751,3 +770,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; +} |