diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | awk.h | 1 | ||||
-rw-r--r-- | awkgram.c | 36 | ||||
-rw-r--r-- | awkgram.y | 36 | ||||
-rw-r--r-- | gawkapi.c | 28 |
5 files changed, 76 insertions, 38 deletions
@@ -1,3 +1,16 @@ +2015-01-06 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awk.h (variable_create): Declare new function. + * awkgram.y (variable_create): New function to create a variable + taking the deferred variable list into consideration. + (variable): Call new function variable_create if the variable is + not found. + * gawkapi.c (api_sym_update): If an array is being created, then + call new function variable_create instead of install_symbol. If this + is the first reference to a deferred variable, than the new array + may contain elements that must be merged into the array provided by + the extension. + 2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com> * io.c (wait_any): If the `interesting' argument is non-zero, then we @@ -1318,6 +1318,7 @@ extern NODE *do_asorti(int nargs); extern unsigned long (*hash)(const char *s, size_t len, unsigned long hsize, size_t *code); extern void init_env_array(NODE *env_node); /* awkgram.c */ +extern NODE *variable_create(char *name, NODETYPE type); extern NODE *variable(int location, char *name, NODETYPE type); extern int parse_program(INSTRUCTION **pcode); extern void track_ext_func(const char *name); @@ -7052,6 +7052,20 @@ is_deferred_variable(const char *name) return false; } +/* variable_create --- create a new variable */ +NODE * +variable_create(char *name, NODETYPE type) +{ + struct deferred_variable *dv; + + for (dv = deferred_variables; dv != NULL; dv = dv->next) { + if (strcmp(name, dv->name) == 0) { + efree(name); + return (*dv->load_func)(); + } + } + return install_symbol(name, type); +} /* variable --- make sure NAME is in the symbol table */ @@ -7066,25 +7080,11 @@ variable(int location, char *name, NODETYPE type) r->vname); if (r == symbol_table) symtab_used = true; - } else { - /* not found */ - struct deferred_variable *dv; - - for (dv = deferred_variables; true; dv = dv->next) { - if (dv == NULL) { - /* - * This is the only case in which we may not free the string. - */ - return install_symbol(name, type); - } - if (strcmp(name, dv->name) == 0) { - r = (*dv->load_func)(); - break; - } - } + efree(name); + return r; } - efree(name); - return r; + /* not found */ + return variable_create(name, type); } /* process_deferred --- if the program uses SYMTAB, load deferred variables */ @@ -4714,6 +4714,20 @@ is_deferred_variable(const char *name) return false; } +/* variable_create --- create a new variable */ +NODE * +variable_create(char *name, NODETYPE type) +{ + struct deferred_variable *dv; + + for (dv = deferred_variables; dv != NULL; dv = dv->next) { + if (strcmp(name, dv->name) == 0) { + efree(name); + return (*dv->load_func)(); + } + } + return install_symbol(name, type); +} /* variable --- make sure NAME is in the symbol table */ @@ -4728,25 +4742,11 @@ variable(int location, char *name, NODETYPE type) r->vname); if (r == symbol_table) symtab_used = true; - } else { - /* not found */ - struct deferred_variable *dv; - - for (dv = deferred_variables; true; dv = dv->next) { - if (dv == NULL) { - /* - * This is the only case in which we may not free the string. - */ - return install_symbol(name, type); - } - if (strcmp(name, dv->name) == 0) { - r = (*dv->load_func)(); - break; - } - } + efree(name); + return r; } - efree(name); - return r; + /* not found */ + return variable_create(name, type); } /* process_deferred --- if the program uses SYMTAB, load deferred variables */ @@ -579,10 +579,34 @@ 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; + array_node = awk_value_to_node(value); - node = install_symbol(estrdup((char *) name, strlen(name)), - Node_var_array); + /* + * use variable_create instead of install_symbol in + * 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 **list; + NODE akind; + unsigned long i; + + akind.flags = (AINDEX|AVALUE); + list = node->alist(node, & akind); + for (i = 0; i < nel; i++) { + NODE **aptr; + aptr = assoc_lookup(array_node, list[2*i]); + unref(*aptr); + unref(list[2*i]); /* alist duped it */ + *aptr = dupnode(list[2*i+1]); + } + efree(list); + assoc_clear(node); + } *node = *array_node; freenode(array_node); value->array_cookie = node; /* pass new cookie back to extension */ |