diff options
author | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2015-01-06 20:17:35 -0500 |
---|---|---|
committer | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2015-01-06 20:17:35 -0500 |
commit | f38a8f801496ea91cef7a8507e2919f6586d0694 (patch) | |
tree | 65afc30f5423e623189f381a1cf2ff8a8a023620 /gawkapi.c | |
parent | 9121c3059288f36e004108e02ed4d826b84604e7 (diff) | |
download | egawk-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.c | 26 |
1 files changed, 17 insertions, 9 deletions
@@ -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 { |