aboutsummaryrefslogtreecommitdiffstats
path: root/gawkapi.c
diff options
context:
space:
mode:
authorAndrew J. Schorr <aschorr@telemetry-investments.com>2015-01-06 20:17:35 -0500
committerAndrew J. Schorr <aschorr@telemetry-investments.com>2015-01-06 20:17:35 -0500
commitf38a8f801496ea91cef7a8507e2919f6586d0694 (patch)
tree65afc30f5423e623189f381a1cf2ff8a8a023620 /gawkapi.c
parent9121c3059288f36e004108e02ed4d826b84604e7 (diff)
downloadegawk-f38a8f801496ea91cef7a8507e2919f6586d0694.tar.gz
egawk-f38a8f801496ea91cef7a8507e2919f6586d0694.tar.bz2
egawk-f38a8f801496ea91cef7a8507e2919f6586d0694.zip
Fix bug in API deferred variable creation and add a test case.
Diffstat (limited to 'gawkapi.c')
-rw-r--r--gawkapi.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/gawkapi.c b/gawkapi.c
index 5630185c..e8879022 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -579,7 +579,7 @@ api_sym_update(awk_ext_id_t id,
if (node == NULL) {
/* new value to be installed */
if (value->val_type == AWK_ARRAY) {
- unsigned long nel;
+ bool is_deferred;
array_node = awk_value_to_node(value);
/*
@@ -587,27 +587,35 @@ api_sym_update(awk_ext_id_t id,
* case this is a deferred variable such as PROCINFO
* or ENVIRON
*/
- node = variable_create(estrdup((char *) name, strlen(name)), Node_var_array);
- array_node->vname = node->vname;
- if ((nel = assoc_length(node)) > 0) {
- /* merge the 2 arrays */
+ node = variable_create(estrdup((char *) name, strlen(name)), Node_var_array, & is_deferred);
+ if (is_deferred) {
+ /*
+ * merge the user-supplied elements into the
+ * already-existing array. Since ENVIRON
+ * has special array_funcs, we need to retain
+ * the auto-created array!
+ */
+ unsigned long nel;
NODE **list;
NODE akind;
unsigned long i;
+ nel = assoc_length(array_node);
akind.flags = (AINDEX|AVALUE);
- list = node->alist(node, & akind);
+ list = array_node->alist(array_node, & akind);
for (i = 0; i < nel; i++) {
NODE **aptr;
- aptr = assoc_lookup(array_node, list[2*i]);
+ aptr = assoc_lookup(node, list[2*i]);
unref(*aptr);
unref(list[2*i]); /* alist duped it */
*aptr = dupnode(list[2*i+1]);
}
efree(list);
- assoc_clear(node);
+ assoc_clear(array_node);
+ } else {
+ array_node->vname = node->vname;
+ *node = *array_node;
}
- *node = *array_node;
freenode(array_node);
value->array_cookie = node; /* pass new cookie back to extension */
} else {