summaryrefslogtreecommitdiffstats
path: root/contrib/awk/array.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/awk/array.c')
-rw-r--r--contrib/awk/array.c185
1 files changed, 165 insertions, 20 deletions
diff --git a/contrib/awk/array.c b/contrib/awk/array.c
index 4906384..da1ac3f 100644
--- a/contrib/awk/array.c
+++ b/contrib/awk/array.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-1999 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2000 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -61,8 +61,8 @@ register NODE *tree;
r = force_string(tree_eval(tree->lnode));
if (tree->rnode == NULL)
return r;
- subseplen = SUBSEP_node->lnode->stlen;
- subsep = SUBSEP_node->lnode->stptr;
+ 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);
@@ -214,11 +214,23 @@ register NODE *subs;
int hash1;
{
register NODE *bucket;
+ NODE *s1, *s2;
for (bucket = symbol->var_array[hash1]; bucket != NULL;
bucket = bucket->ahnext) {
- if (cmp_nodes(bucket->ahname, subs) == 0)
- return bucket;
+ /*
+ * This used to use cmp_nodes() here. That's wrong.
+ * Array indexes are strings; compare as such, always!
+ */
+ s1 = bucket->ahname;
+ s1 = force_string(s1);
+ s2 = subs;
+
+ if (s1->stlen == s2->stlen) {
+ if (s1->stlen == 0 /* "" is a valid index */
+ || STREQN(s1->stptr, s2->stptr, s1->stlen))
+ return bucket;
+ }
}
return NULL;
}
@@ -234,6 +246,8 @@ NODE *symbol, *subs;
if (symbol->type == Node_param_list)
symbol = stack_ptr[symbol->param_cnt];
+ if (symbol->type == Node_array_ref)
+ symbol = symbol->orig_array;
if ((symbol->flags & SCALAR) != 0)
fatal("attempt to use scalar as array");
/*
@@ -266,6 +280,8 @@ NODE *symbol, *subs;
register int hash1;
register NODE *bucket;
+ assert(symbol->type == Node_var_array || symbol->type == Node_var);
+
(void) force_string(subs);
if ((symbol->flags & SCALAR) != 0)
@@ -308,20 +324,9 @@ NODE *symbol, *subs;
getnode(bucket);
bucket->type = Node_ahash;
- if (subs->flags & TEMP)
- bucket->ahname = dupnode(subs);
- else {
- unsigned int saveflags = subs->flags;
-
- subs->flags &= ~MALLOC;
- bucket->ahname = dupnode(subs);
- subs->flags = saveflags;
- }
+ bucket->ahname = dupnode(subs);
free_temp(subs);
- /* array subscripts are strings */
- bucket->ahname->flags &= ~NUMBER;
- bucket->ahname->flags |= STRING;
bucket->ahvalue = Nnull_string;
bucket->ahnext = symbol->var_array[hash1];
symbol->var_array[hash1] = bucket;
@@ -343,6 +348,8 @@ NODE *symbol, *tree;
if (symbol->type == Node_var)
return;
}
+ if (symbol->type == Node_array_ref)
+ symbol = symbol->orig_array;
if (symbol->type == Node_var_array) {
if (symbol->var_array == NULL)
return;
@@ -360,9 +367,24 @@ NODE *symbol, *tree;
last = NULL;
for (bucket = symbol->var_array[hash1]; bucket != NULL;
- last = bucket, bucket = bucket->ahnext)
- if (cmp_nodes(bucket->ahname, subs) == 0)
- break;
+ last = bucket, bucket = bucket->ahnext) {
+ /*
+ * This used to use cmp_nodes() here. That's wrong.
+ * Array indexes are strings; compare as such, always!
+ */
+ NODE *s1, *s2;
+
+ s1 = bucket->ahname;
+ s1 = force_string(s1);
+ s2 = subs;
+
+ if (s1->stlen == s2->stlen) {
+ if (s1->stlen == 0 /* "" is a valid index */
+ || STREQN(s1->stptr, s2->stptr, s1->stlen))
+ break;
+ }
+ }
+
if (bucket == NULL) {
if (do_lint)
warning("delete: index `%s' not in array `%s'",
@@ -389,6 +411,50 @@ NODE *symbol, *tree;
}
}
+/* do_delete_loop --- simulate ``for (iggy in foo) delete foo[iggy]'' */
+
+/*
+ * The primary hassle here is that `iggy' needs to have some arbitrary
+ * array index put in it before we can clear the array, we can't
+ * just replace the loop with `delete foo'.
+ */
+
+void
+do_delete_loop(symbol, tree)
+NODE *symbol, *tree;
+{
+ size_t i;
+ NODE *n, **lhs;
+ Func_ptr after_assign = NULL;
+
+ if (symbol->type == Node_param_list) {
+ symbol = stack_ptr[symbol->param_cnt];
+ if (symbol->type == Node_var)
+ return;
+ }
+ if (symbol->type == Node_array_ref)
+ symbol = symbol->orig_array;
+ if (symbol->type == Node_var_array) {
+ if (symbol->var_array == NULL)
+ return;
+ } else
+ fatal("delete: illegal use of variable `%s' as array",
+ symbol->vname);
+
+ /* 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);
+ unref(*lhs);
+ *lhs = dupnode(symbol->var_array[i]->ahname);
+ break;
+ }
+ }
+
+ /* blast the array in one shot */
+ assoc_clear(symbol);
+}
+
/* assoc_scan --- start a ``for (iggy in foo)'' loop */
void
@@ -528,3 +594,82 @@ done:
symbol->var_array = new;
symbol->array_size = newsize;
}
+
+/* pr_node --- print simple node info */
+
+static void
+pr_node(n)
+NODE *n;
+{
+ if ((n->flags & (NUM|NUMBER)) != 0)
+ printf("%g", n->numbr);
+ else
+ printf("%.*s", (int) n->stlen, n->stptr);
+}
+
+/* assoc_dump --- dump the contents of an array */
+
+NODE *
+assoc_dump(symbol)
+NODE *symbol;
+{
+ int i;
+ NODE *bucket;
+
+ if (symbol->var_array == NULL) {
+ printf("%s: empty (null)\n", symbol->vname);
+ return tmp_number((AWKNUM) 0);
+ }
+
+ if (symbol->table_size == 0) {
+ printf("%s: empty (zero)\n", symbol->vname);
+ return tmp_number((AWKNUM) 0);
+ }
+
+ printf("%s: table_size = %d, array_size = %d\n", symbol->vname,
+ symbol->table_size, symbol->array_size);
+
+ for (i = 0; i < symbol->array_size; i++) {
+ for (bucket = symbol->var_array[i]; bucket != NULL;
+ bucket = bucket->ahnext) {
+ printf("%s: I: [(%p, %ld, %s) len %d <%.*s>] V: [",
+ symbol->vname,
+ bucket->ahname,
+ bucket->ahname->stref,
+ flags2str(bucket->ahname->flags),
+ (int) bucket->ahname->stlen,
+ (int) bucket->ahname->stlen,
+ bucket->ahname->stptr);
+ pr_node(bucket->ahvalue);
+ printf("]\n");
+ }
+ }
+
+ return tmp_number((AWKNUM) 0);
+}
+
+/* do_adump --- dump an array: interface to assoc_dump */
+
+NODE *
+do_adump(tree)
+NODE *tree;
+{
+ NODE *r, *a;
+
+ a = tree->lnode;
+
+ if (a->type == Node_param_list) {
+ printf("%s: is paramater\n", a->vname);
+ a = stack_ptr[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);
+
+ return r;
+}
OpenPOWER on IntegriCloud