aboutsummaryrefslogtreecommitdiffstats
path: root/array.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2010-11-18 23:00:31 +0200
committerArnold D. Robbins <arnold@skeeve.com>2010-11-18 23:00:31 +0200
commit6f3612539c425da2bc1d34db621696e6a273b01c (patch)
tree9623b3ac2c54a93e5eed3be2b1dda7f4e4bf0e47 /array.c
parent4e3701015635401df2fc4da58abaab7645f4ebd3 (diff)
downloadegawk-6f3612539c425da2bc1d34db621696e6a273b01c.tar.gz
egawk-6f3612539c425da2bc1d34db621696e6a273b01c.tar.bz2
egawk-6f3612539c425da2bc1d34db621696e6a273b01c.zip
Bring latest byte code gawk into git. Hurray!
Diffstat (limited to 'array.c')
-rw-r--r--array.c539
1 files changed, 328 insertions, 211 deletions
diff --git a/array.c b/array.c
index dc78c27f..6d1468b0 100644
--- a/array.c
+++ b/array.c
@@ -42,14 +42,17 @@ static int AVG_CHAIN_MAX = 2; /* 11/2002: Modern machines are bigger, cut this d
#include "awk.h"
-static NODE *assoc_find P((NODE *symbol, NODE *subs, unsigned long hash1));
-static void grow_table P((NODE *symbol));
+static size_t SUBSEPlen;
+static char *SUBSEP;
-static unsigned long gst_hash_string P((const char *str, size_t len, unsigned long hsize, size_t *code));
-static unsigned long scramble P((unsigned long x));
-static unsigned long awk_hash P((const char *s, size_t len, unsigned long hsize, size_t *code));
+static NODE *assoc_find(NODE *symbol, NODE *subs, unsigned long hash1);
+static void grow_table(NODE *symbol);
-unsigned long (*hash)P((const char *s, size_t len, unsigned long hsize, size_t *code)) = awk_hash;
+static unsigned long gst_hash_string(const char *str, size_t len, unsigned long hsize, size_t *code);
+static unsigned long scramble(unsigned long x);
+static unsigned long awk_hash(const char *s, size_t len, unsigned long hsize, size_t *code);
+
+unsigned long (*hash)(const char *s, size_t len, unsigned long hsize, size_t *code) = awk_hash;
/* array_init --- possibly temporary function for experimentation purposes */
@@ -71,60 +74,6 @@ array_init()
}
/*
- * get_actual --- proceed to the actual Node_var_array,
- * change Node_var_new to an array.
- * If canfatal and type isn't good, die fatally,
- * otherwise return the final actual value.
- */
-
-NODE *
-get_actual(NODE *symbol, int canfatal)
-{
- int isparam = (symbol->type == Node_param_list
- && (symbol->flags & FUNC) == 0);
- NODE *save_symbol = symbol;
-
- if (isparam) {
- save_symbol = symbol = stack_ptr[symbol->param_cnt];
- if (symbol->type == Node_array_ref)
- symbol = symbol->orig_array;
- }
-
- switch (symbol->type) {
- case Node_var_new:
- symbol->type = Node_var_array;
- symbol->var_array = NULL;
- /* fall through */
- case Node_var_array:
- break;
-
- case Node_array_ref:
- case Node_param_list:
- if ((symbol->flags & FUNC) == 0)
- cant_happen();
- /* else
- fall through */
-
- default:
- /* notably Node_var but catches also e.g. FS[1] = "x" */
- if (canfatal) {
- if ((symbol->flags & FUNC) != 0)
- fatal(_("attempt to use function `%s' as an array"),
- save_symbol->vname);
- else if (isparam)
- fatal(_("attempt to use scalar parameter `%s' as an array"),
- save_symbol->vname);
- else
- fatal(_("attempt to use scalar `%s' as array"),
- save_symbol->vname);
- } else
- break;
- }
-
- return symbol;
-}
-
-/*
* array_vname --- print the name of the array
*
* Returns a pointer to a statically maintained dynamically allocated string.
@@ -139,15 +88,13 @@ get_actual(NODE *symbol, int canfatal)
#define MAX_LEN 0
char *
-array_vname(register const NODE *symbol)
+array_vname(const NODE *symbol)
{
- if (symbol->type == Node_param_list)
- symbol = stack_ptr[symbol->param_cnt];
-
+ static char *message = NULL;
+
if (symbol->type != Node_array_ref || symbol->orig_array->type != Node_var_array)
return symbol->vname;
else {
- static char *message = NULL;
static size_t msglen = 0;
char *s;
size_t len;
@@ -256,50 +203,165 @@ array_vname(register const NODE *symbol)
}
#undef MAX_LEN
+/* make_aname --- construct a sub-array name for multi-dimensional array */
+
+char *
+make_aname(NODE *array, NODE *subs)
+{
+ static char *aname = NULL;
+ static size_t aname_len;
+ size_t slen;
+
+ slen = strlen(array->vname) + subs->stlen + 6;
+ if (aname == NULL) {
+ emalloc(aname, char *, slen, "make_aname");
+ aname_len = slen;
+ } else if (slen > aname_len) {
+ erealloc(aname, char *, slen, "make_aname");
+ aname_len = slen;
+ }
+ sprintf(aname, "%s[\"%.*s\"]", array->vname, (int) subs->stlen, subs->stptr);
+ return aname;
+}
+
+
+/*
+ * get_array --- proceed to the actual Node_var_array,
+ * change Node_var_new to an array.
+ * If canfatal and type isn't good, die fatally,
+ * otherwise return the final actual value.
+ */
+
+NODE *
+get_array(NODE *symbol, int canfatal)
+{
+ NODE *save_symbol = symbol;
+ int isparam = FALSE;
+
+ if (symbol->type == Node_param_list && (symbol->flags & FUNC) == 0) {
+ save_symbol = symbol = GET_PARAM(symbol->param_cnt);
+ isparam = TRUE;
+ if (symbol->type == Node_array_ref)
+ symbol = symbol->orig_array;
+ }
+
+ switch (symbol->type) {
+ case Node_var_new:
+ symbol->type = Node_var_array;
+ symbol->var_array = NULL;
+ /* fall through */
+ case Node_var_array:
+ break;
+
+ case Node_array_ref:
+ case Node_param_list:
+ if ((symbol->flags & FUNC) == 0)
+ cant_happen();
+ /* else
+ fall through */
+
+ default:
+ /* notably Node_var but catches also e.g. FS[1] = "x" */
+ if (canfatal) {
+ if (symbol->type == Node_val)
+ fatal(_("attempt to use a scalar value as array"));
+
+ if ((symbol->flags & FUNC) != 0)
+ fatal(_("attempt to use function `%s' as an array"),
+ save_symbol->vname);
+ else if (isparam)
+ fatal(_("attempt to use scalar parameter `%s' as an array"),
+ save_symbol->vname);
+ else
+ fatal(_("attempt to use scalar `%s' as array"),
+ save_symbol->vname);
+ } else
+ break;
+ }
+
+ return symbol;
+}
+
+
+/* set_SUBSEP --- update SUBSEP related variables when SUBSEP assigned to */
+
+void
+set_SUBSEP()
+{
+ SUBSEP = force_string(SUBSEP_node->var_value)->stptr;
+ SUBSEPlen = SUBSEP_node->var_value->stlen;
+}
+
/* concat_exp --- concatenate expression list into a single string */
NODE *
-concat_exp(register NODE *tree)
+concat_exp(int nargs, int do_subsep)
{
- register NODE *r;
+ /* do_subsep is false for Node-concat */
+ NODE *r;
char *str;
char *s;
- size_t len;
- int offset;
- size_t subseplen;
- const char *subsep;
-
- if (tree->type != Node_expression_list)
- return force_string(tree_eval(tree));
- r = force_string(tree_eval(tree->lnode));
- if (tree->rnode == NULL)
- return r;
- subseplen = SUBSEP_node->var_value->stlen;
- subsep = SUBSEP_node->var_value->stptr;
- len = r->stlen + subseplen + 2;
- emalloc(str, char *, len, "concat_exp");
- memcpy(str, r->stptr, r->stlen+1);
+ long len; /* NOT size_t, which is unsigned! */
+ size_t subseplen = 0;
+ int i;
+ extern NODE **args_array;
+
+ if (nargs == 1)
+ return POP_STRING();
+
+ if (do_subsep)
+ subseplen = SUBSEPlen;
+
+ len = -subseplen;
+ for (i = 1; i <= nargs; i++) {
+ r = POP();
+ if (r->type == Node_var_array) {
+ while (--i > 0)
+ DEREF(args_array[i]); /* avoid memory leak */
+ fatal(_("attempt to use array `%s' in a scalar context"), array_vname(r));
+ }
+ args_array[i] = force_string(r);
+ len += r->stlen + subseplen;
+ }
+
+ emalloc(str, char *, len + 2, "concat_exp");
+
+ r = args_array[nargs];
+ memcpy(str, r->stptr, r->stlen);
s = str + r->stlen;
- free_temp(r);
- for (tree = tree->rnode; tree != NULL; tree = tree->rnode) {
+ DEREF(r);
+ for (i = nargs - 1; i > 0; i--) {
if (subseplen == 1)
- *s++ = *subsep;
- else {
- memcpy(s, subsep, subseplen+1);
+ *s++ = *SUBSEP;
+ else if (subseplen > 0) {
+ memcpy(s, SUBSEP, subseplen);
s += subseplen;
}
- r = force_string(tree_eval(tree->lnode));
- len += r->stlen + subseplen;
- offset = s - str;
- erealloc(str, char *, len, "concat_exp");
- s = str + offset;
- memcpy(s, r->stptr, r->stlen+1);
+ r = args_array[i];
+ memcpy(s, r->stptr, r->stlen);
s += r->stlen;
- free_temp(r);
+ DEREF(r);
+ }
+
+ return make_str_node(str, len, ALREADY_MALLOCED);
+}
+
+/* ahash_unref --- remove reference to a Node_ahash */
+
+void
+ahash_unref(NODE *tmp)
+{
+ if (tmp == NULL)
+ return;
+
+ assert(tmp->type == Node_ahash);
+
+ if (tmp->ahname_ref > 1)
+ tmp->ahname_ref--;
+ else {
+ efree(tmp->ahname_str);
+ freenode(tmp);
}
- r = make_str_node(str, s - str, ALREADY_MALLOCED);
- r->flags |= TEMP;
- return r;
}
/* assoc_clear --- flush all the values in symbol[] before doing a split() */
@@ -315,12 +377,18 @@ assoc_clear(NODE *symbol)
for (i = 0; i < symbol->array_size; i++) {
for (bucket = symbol->var_array[i]; bucket != NULL; bucket = next) {
next = bucket->ahnext;
- unref(bucket->ahvalue);
- unref(bucket); /* unref() will free the ahname_str */
+ if (bucket->ahvalue->type == Node_var_array) {
+ NODE *r = bucket->ahvalue;
+ assoc_clear(r); /* recursively clear all sub-arrays */
+ efree(r->vname);
+ freenode(r);
+ } else
+ unref(bucket->ahvalue);
+ ahash_unref(bucket); /* unref() will free the ahname_str */
}
symbol->var_array[i] = NULL;
}
- free(symbol->var_array);
+ efree(symbol->var_array);
symbol->var_array = NULL;
symbol->array_size = symbol->table_size = 0;
symbol->flags &= ~ARRAYMAXED;
@@ -329,9 +397,9 @@ assoc_clear(NODE *symbol)
/* awk_hash --- calculate the hash function of the string in subs */
static unsigned long
-awk_hash(register const char *s, register size_t len, unsigned long hsize, size_t *code)
+awk_hash(const char *s, size_t len, unsigned long hsize, size_t *code)
{
- register unsigned long h = 0;
+ unsigned long h = 0;
/*
* This is INCREDIBLY ugly, but fast. We break the string up into
@@ -375,7 +443,7 @@ awk_hash(register const char *s, register size_t len, unsigned long hsize, size_
}
if (len > (8 - 1)) {
- register size_t loop = len >> 3;
+ size_t loop = len >> 3;
do {
HASHC;
HASHC;
@@ -390,7 +458,7 @@ awk_hash(register const char *s, register size_t len, unsigned long hsize, size_
#else /* ! VAXC */
/* "Duff's Device" for those who can handle it */
if (len > 0) {
- register size_t loop = (len + 8 - 1) >> 3;
+ size_t loop = (len + 8 - 1) >> 3;
switch (len & (8 - 1)) {
case 0:
@@ -418,9 +486,9 @@ awk_hash(register const char *s, register size_t len, unsigned long hsize, size_
/* assoc_find --- locate symbol[subs] */
static NODE * /* NULL if not found */
-assoc_find(NODE *symbol, register NODE *subs, unsigned long hash1)
+assoc_find(NODE *symbol, NODE *subs, unsigned long hash1)
{
- register NODE *bucket;
+ NODE *bucket;
const char *s1_str;
size_t s1_len;
NODE *s2;
@@ -451,26 +519,17 @@ assoc_find(NODE *symbol, register NODE *subs, unsigned long hash1)
NODE *
in_array(NODE *symbol, NODE *subs)
{
- register unsigned long hash1;
+ unsigned long hash1;
NODE *ret;
- symbol = get_array(symbol);
+ assert(symbol->type == Node_var_array);
- /*
- * Evaluate subscript first, it could have side effects.
- */
- subs = concat_exp(subs); /* concat_exp returns a string node */
- if (symbol->var_array == NULL) {
- free_temp(subs);
+ if (symbol->var_array == NULL)
return NULL;
- }
+
hash1 = hash(subs->stptr, subs->stlen, (unsigned long) symbol->array_size, NULL);
ret = assoc_find(symbol, subs, hash1);
- free_temp(subs);
- if (ret)
- return ret->ahvalue;
- else
- return NULL;
+ return (ret ? ret->ahvalue : NULL);
}
/*
@@ -485,8 +544,8 @@ in_array(NODE *symbol, NODE *subs)
NODE **
assoc_lookup(NODE *symbol, NODE *subs, int reference)
{
- register unsigned long hash1;
- register NODE *bucket;
+ unsigned long hash1;
+ NODE *bucket;
size_t code;
assert(symbol->type == Node_var_array);
@@ -503,10 +562,8 @@ assoc_lookup(NODE *symbol, NODE *subs, int reference)
hash1 = hash(subs->stptr, subs->stlen,
(unsigned long) symbol->array_size, & code);
bucket = assoc_find(symbol, subs, hash1);
- if (bucket != NULL) {
- free_temp(subs);
+ if (bucket != NULL)
return &(bucket->ahvalue);
- }
}
if (do_lint && reference) {
@@ -542,21 +599,12 @@ assoc_lookup(NODE *symbol, NODE *subs, int reference)
bucket->flags |= MALLOC;
bucket->ahname_ref = 1;
- /* For TEMP node, reuse the storage directly */
- if ((subs->flags & TEMP) != 0) {
- bucket->ahname_str = subs->stptr;
- bucket->ahname_len = subs->stlen;
- bucket->ahname_str[bucket->ahname_len] = '\0';
- subs->flags &= ~TEMP; /* for good measure */
- freenode(subs);
- } else {
- emalloc(bucket->ahname_str, char *, subs->stlen + 2, "assoc_lookup");
- bucket->ahname_len = subs->stlen;
- memcpy(bucket->ahname_str, subs->stptr, subs->stlen);
- bucket->ahname_str[bucket->ahname_len] = '\0';
- }
-
+ emalloc(bucket->ahname_str, char *, subs->stlen + 2, "assoc_lookup");
+ bucket->ahname_len = subs->stlen;
+ memcpy(bucket->ahname_str, subs->stptr, subs->stlen);
+ bucket->ahname_str[bucket->ahname_len] = '\0';
bucket->ahvalue = Nnull_string;
+
bucket->ahnext = symbol->var_array[hash1];
bucket->ahcode = code;
symbol->var_array[hash1] = bucket;
@@ -567,30 +615,43 @@ assoc_lookup(NODE *symbol, NODE *subs, int reference)
/*
* `symbol' is array
- * `tree' is subscript
+ * `nsubs' is no of subscripts
*/
void
-do_delete(NODE *sym, NODE *tree)
+do_delete(NODE *symbol, int nsubs)
{
- register unsigned long hash1;
- register NODE *bucket, *last;
+ unsigned long hash1;
+ NODE *bucket, *last;
NODE *subs;
- register NODE *symbol = get_array(sym);
- if (tree == NULL) { /* delete array */
+ assert(symbol->type == Node_var_array);
+
+#define free_subs(n) do { \
+ NODE *s = PEEK(n - 1); \
+ if (s->type == Node_val) { \
+ (void) force_string(s); /* may have side effects ? */ \
+ DEREF(s); \
+ } \
+} while (--n > 0)
+
+ if (nsubs == 0) { /* delete array */
assoc_clear(symbol);
return;
}
+ /* NB: subscripts are in reverse order on stack */
+ subs = PEEK(nsubs - 1);
+ if (subs->type != Node_val) {
+ if (--nsubs > 0)
+ free_subs(nsubs);
+ fatal(_("attempt to use array `%s' in a scalar context"), array_vname(subs));
+ }
+ (void) force_string(subs);
+
last = NULL; /* shut up gcc -Wall */
hash1 = 0; /* ditto */
- /*
- * Always evaluate subscript, it could have side effects.
- */
- subs = concat_exp(tree); /* concat_exp returns string node */
-
if (symbol->var_array != NULL) {
hash1 = hash(subs->stptr, subs->stlen,
(unsigned long) symbol->array_size, NULL);
@@ -621,28 +682,48 @@ do_delete(NODE *sym, NODE *tree)
if (bucket == NULL) {
if (do_lint)
lintwarn(_("delete: index `%s' not in array `%s'"),
- subs->stptr, array_vname(sym));
- free_temp(subs);
+ subs->stptr, array_vname(symbol));
+ DEREF(subs);
+
+ /* avoid memory leak, free rest of the subs */
+ if (--nsubs > 0)
+ free_subs(nsubs);
return;
}
- free_temp(subs);
+ DEREF(subs);
+ if (bucket->ahvalue->type == Node_var_array) {
+ NODE *r = bucket->ahvalue;
+ do_delete(r, nsubs - 1);
+ if (r->var_array != NULL || nsubs > 1)
+ return;
+ /* else
+ cleared a sub_array, free index */
+ } else if (--nsubs > 0) {
+ /* e.g.: a[1] = 1; delete a[1][1] */
+ free_subs(nsubs);
+ fatal(_("attempt to use scalar `%s[\"%.*s\"]' as an array"),
+ symbol->vname, bucket->ahname_len, bucket->ahname_str);
+ } else
+ unref(bucket->ahvalue);
if (last != NULL)
last->ahnext = bucket->ahnext;
else
symbol->var_array[hash1] = bucket->ahnext;
- unref(bucket->ahvalue);
- unref(bucket); /* unref() will free the ahname_str */
+
+ ahash_unref(bucket); /* unref() will free the ahname_str */
symbol->table_size--;
if (symbol->table_size <= 0) {
- memset(symbol->var_array, '\0',
- sizeof(NODE *) * symbol->array_size);
symbol->table_size = symbol->array_size = 0;
symbol->flags &= ~ARRAYMAXED;
- free((char *) symbol->var_array);
- symbol->var_array = NULL;
+ if (symbol->var_array != NULL) {
+ efree((char *) symbol->var_array);
+ symbol->var_array = NULL;
+ }
}
+
+#undef free_subs
}
/* do_delete_loop --- simulate ``for (iggy in foo) delete foo[iggy]'' */
@@ -654,13 +735,11 @@ do_delete(NODE *sym, NODE *tree)
*/
void
-do_delete_loop(NODE *symbol, NODE *tree)
+do_delete_loop(NODE *symbol, NODE **lhs)
{
long i;
- NODE **lhs;
- Func_ptr after_assign = NULL;
- symbol = get_array(symbol);
+ assert(symbol->type == Node_var_array);
if (symbol->var_array == NULL)
return;
@@ -668,12 +747,9 @@ do_delete_loop(NODE *symbol, NODE *tree)
/* get first index value */
for (i = 0; i < symbol->array_size; i++) {
if (symbol->var_array[i] != NULL) {
- lhs = get_lhs(tree->lnode, & after_assign, FALSE);
unref(*lhs);
*lhs = make_string(symbol->var_array[i]->ahname_str,
symbol->var_array[i]->ahname_len);
- if (after_assign)
- (*after_assign)();
break;
}
}
@@ -701,7 +777,7 @@ grow_table(NODE *symbol)
* just jumping from 8K to 64K.
*/
static const long sizes[] = { 13, 127, 1021, 8191, 16381, 32749, 65497,
-#if ! defined(MSDOS) && ! defined(OS2) && ! defined(atarist)
+#if ! defined(OS2)
131101, 262147, 524309, 1048583, 2097169,
4194319, 8388617, 16777259, 33554467,
67108879, 134217757, 268435459, 536870923,
@@ -748,7 +824,7 @@ grow_table(NODE *symbol)
new[hash1] = chain;
}
}
- free(old);
+ efree(old);
done:
/*
@@ -759,43 +835,43 @@ done:
symbol->array_size = newsize;
}
-/* set_SUBSEP --- make sure SUBSEP always has a string value */
-
-void
-set_SUBSEP(void)
-{
-
- (void) force_string(SUBSEP_node->var_value);
- return;
-}
-
/* pr_node --- print simple node info */
static void
pr_node(NODE *n)
{
if ((n->flags & (NUMCUR|NUMBER)) != 0)
- printf("%g", n->numbr);
+ printf("%s %g p: %p", flags2str(n->flags), n->numbr, n);
else
- printf("%.*s", (int) n->stlen, n->stptr);
+ printf("%s %.*s p: %p", flags2str(n->flags), (int) n->stlen, n->stptr, n);
+}
+
+
+static void
+indent(int indent_level)
+{
+ int k;
+ for (k = 0; k < indent_level; k++)
+ printf("\t");
}
/* assoc_dump --- dump the contents of an array */
NODE *
-assoc_dump(NODE *symbol)
+assoc_dump(NODE *symbol, int indent_level)
{
long i;
NODE *bucket;
+ indent(indent_level);
if (symbol->var_array == NULL) {
printf(_("%s: empty (null)\n"), symbol->vname);
- return tmp_number((AWKNUM) 0);
+ return make_number((AWKNUM) 0);
}
if (symbol->table_size == 0) {
printf(_("%s: empty (zero)\n"), symbol->vname);
- return tmp_number((AWKNUM) 0);
+ return make_number((AWKNUM) 0);
}
printf(_("%s: table_size = %d, array_size = %d\n"), symbol->vname,
@@ -804,41 +880,46 @@ assoc_dump(NODE *symbol)
for (i = 0; i < symbol->array_size; i++) {
for (bucket = symbol->var_array[i]; bucket != NULL;
bucket = bucket->ahnext) {
- printf("%s: I: [len %d <%.*s>] V: [",
+ indent(indent_level);
+ printf("%s: I: [len %d <%.*s> p: %p] V: [",
symbol->vname,
(int) bucket->ahname_len,
(int) bucket->ahname_len,
+ bucket->ahname_str,
bucket->ahname_str);
- pr_node(bucket->ahvalue);
+ if (bucket->ahvalue->type == Node_var_array) {
+ printf("\n");
+ assoc_dump(bucket->ahvalue, indent_level + 1);
+ indent(indent_level);
+ } else
+ pr_node(bucket->ahvalue);
printf("]\n");
}
}
- return tmp_number((AWKNUM) 0);
+ return make_number((AWKNUM) 0);
}
/* do_adump --- dump an array: interface to assoc_dump */
NODE *
-do_adump(NODE *tree)
+do_adump(int nargs)
{
NODE *r, *a;
- a = tree->lnode;
-
+ a = POP();
if (a->type == Node_param_list) {
printf(_("%s: is parameter\n"), a->vname);
- a = stack_ptr[a->param_cnt];
+ a = GET_PARAM(a->param_cnt);
}
-
if (a->type == Node_array_ref) {
printf(_("%s: array_ref to %s\n"), a->vname,
a->orig_array->vname);
a = a->orig_array;
}
-
- r = assoc_dump(a);
-
+ if (a->type != Node_var_array)
+ fatal(_("adump: argument not an array"));
+ r = assoc_dump(a, 0);
return r;
}
@@ -894,7 +975,20 @@ dup_table(NODE *symbol, NODE *newsymb)
memcpy(bucket->ahname_str, chain->ahname_str, chain->ahname_len);
bucket->ahname_str[bucket->ahname_len] = '\0';
- bucket->ahvalue = dupnode(chain->ahvalue);
+ if (chain->ahvalue->type == Node_var_array) {
+ NODE *r;
+ char *aname;
+ size_t aname_len;
+ getnode(r);
+ r->type = Node_var_array;
+ aname_len = strlen(newsymb->vname) + chain->ahname_len + 4;
+ emalloc(aname, char *, aname_len + 2, "dup_table");
+ sprintf(aname, "%s[\"%.*s\"]", newsymb->vname, (int) chain->ahname_len, chain->ahname_str);
+ r->vname = aname;
+ dup_table(chain->ahvalue, r);
+ bucket->ahvalue = r;
+ } else
+ bucket->ahvalue = dupnode(chain->ahvalue);
/*
* put the node on the corresponding
@@ -989,7 +1083,7 @@ assoc_from_list(NODE *symbol, NODE *list)
{
NODE *next;
unsigned long i = 0;
- register unsigned long hash1;
+ unsigned long hash1;
char buf[100];
for (; list != NULL; list = next) {
@@ -1033,7 +1127,7 @@ assoc_sort_inplace(NODE *symbol, ASORT_TYPE how)
if (symbol->var_array == NULL
|| symbol->array_size <= 0
|| symbol->table_size <= 0)
- return tmp_number((AWKNUM) 0);
+ return make_number((AWKNUM) 0);
/* build a linked list out of all the entries in the table */
if (how == VALUE) {
@@ -1041,9 +1135,11 @@ assoc_sort_inplace(NODE *symbol, ASORT_TYPE how)
num = 0;
for (i = 0; i < symbol->array_size; i++) {
for (bucket = symbol->var_array[i]; bucket != NULL; bucket = next) {
+ if (bucket->ahvalue->type == Node_var_array)
+ fatal(_("attempt to use array in a scalar context"));
next = bucket->ahnext;
if (bucket->ahname_ref == 1) {
- free(bucket->ahname_str);
+ efree(bucket->ahname_str);
bucket->ahname_str = NULL;
bucket->ahname_len = 0;
} else {
@@ -1051,7 +1147,7 @@ assoc_sort_inplace(NODE *symbol, ASORT_TYPE how)
getnode(r);
*r = *bucket;
- unref(bucket);
+ ahash_unref(bucket);
bucket = r;
bucket->flags |= MALLOC;
bucket->ahname_ref = 1;
@@ -1072,7 +1168,13 @@ assoc_sort_inplace(NODE *symbol, ASORT_TYPE how)
next = bucket->ahnext;
/* toss old value */
- unref(bucket->ahvalue);
+ if (bucket->ahvalue->type == Node_var_array) {
+ NODE *r = bucket->ahvalue;
+ assoc_clear(r);
+ efree(r->vname);
+ freenode(r);
+ } else
+ unref(bucket->ahvalue);
/* move index into value */
if (bucket->ahname_ref == 1) {
@@ -1086,7 +1188,7 @@ assoc_sort_inplace(NODE *symbol, ASORT_TYPE how)
bucket->ahvalue = make_string(bucket->ahname_str, bucket->ahname_len);
getnode(r);
*r = *bucket;
- unref(bucket);
+ ahash_unref(bucket);
bucket = r;
bucket->flags |= MALLOC;
bucket->ahname_ref = 1;
@@ -1116,20 +1218,35 @@ assoc_sort_inplace(NODE *symbol, ASORT_TYPE how)
*/
assoc_from_list(symbol, list);
- return tmp_number((AWKNUM) num);
+ return make_number((AWKNUM) num);
}
/* asort_actual --- do the actual work to sort the input array */
static NODE *
-asort_actual(NODE *tree, ASORT_TYPE how)
+asort_actual(int nargs, ASORT_TYPE how)
{
- NODE *array = get_array(tree->lnode);
+ NODE *dest = NULL;
+ NODE *array;
+
+ if (nargs == 2) { /* 2nd optional arg */
+ dest = POP_PARAM();
+ if (dest->type != Node_var_array) {
+ fatal(how == VALUE ?
+ _("asort: second argument not an array") :
+ _("asorti: second argument not an array"));
+ }
+ assoc_clear(dest);
+ }
- if (tree->rnode != NULL) { /* 2nd optional arg */
- NODE *dest = get_array(tree->rnode->lnode);
+ array = POP_PARAM();
+ if (array->type != Node_var_array) {
+ fatal(how == VALUE ?
+ _("asort: first argument not an array") :
+ _("asorti: first argument not an array"));
+ }
- assoc_clear(dest);
+ if (dest != NULL) {
dup_table(array, dest);
array = dest;
}
@@ -1140,17 +1257,17 @@ asort_actual(NODE *tree, ASORT_TYPE how)
/* do_asort --- sort array by value */
NODE *
-do_asort(NODE *tree)
+do_asort(int nargs)
{
- return asort_actual(tree, VALUE);
+ return asort_actual(nargs, VALUE);
}
/* do_asorti --- sort array by index */
NODE *
-do_asorti(NODE *tree)
+do_asorti(int nargs)
{
- return asort_actual(tree, INDEX);
+ return asort_actual(nargs, INDEX);
}
/*