diff options
Diffstat (limited to 'symbol.c')
-rw-r--r-- | symbol.c | 190 |
1 files changed, 146 insertions, 44 deletions
@@ -44,9 +44,21 @@ static NODE *get_name_from_awk_ns(const char *name); static AWK_CONTEXT *curr_ctxt = NULL; static int ctxt_level; -static NODE *global_table, *param_table; +static NODE *global_table, *param_table, *alias_table; NODE *symbol_table, *func_table; +/* Table search sequence used by lookup */ +enum { + TAB_PARAM, + TAB_ALIAS, + TAB_GLOBAL, + TAB_FUNC, + TAB_SYM, + TAB_COUNT +}; + +static NODE *tables[TAB_COUNT]; + /* Use a flag to avoid a strcmp() call inside install() */ static bool installing_specials = false; @@ -63,11 +75,22 @@ init_symbol_table() memset(param_table, '\0', sizeof(NODE)); null_array(param_table); + getnode(alias_table); + memset(alias_table, '\0', sizeof(NODE)); + null_array(alias_table); + installing_specials = true; func_table = install_symbol(estrdup("FUNCTAB", 7), Node_var_array); symbol_table = install_symbol(estrdup("SYMTAB", 6), Node_var_array); installing_specials = false; + + /* ``It's turtles, all the way down.'' */ + tables[TAB_PARAM] = param_table; /* parameters shadow everything else */ + tables[TAB_ALIAS] = alias_table; /* symbol macros for anonymous globals */ + tables[TAB_GLOBAL] = global_table; /* SYMTAB and FUNCTAB found first, can't be redefined */ + tables[TAB_FUNC] = func_table; /* then functions */ + tables[TAB_SYM] = symbol_table; /* then globals */ } /* @@ -93,24 +116,16 @@ lookup(const char *name) { NODE *n; NODE *tmp; - NODE *tables[5]; /* manual init below, for z/OS */ int i; - /* ``It's turtles, all the way down.'' */ - tables[0] = param_table; /* parameters shadow everything */ - tables[1] = global_table; /* SYMTAB and FUNCTAB found first, can't be redefined */ - tables[2] = func_table; /* then functions */ - tables[3] = symbol_table; /* then globals */ - tables[4] = NULL; - tmp = get_name_from_awk_ns(name); n = NULL; - for (i = 0; tables[i] != NULL; i++) { + for (i = 0; i < TAB_COUNT; i++) { if (assoc_empty(tables[i])) continue; - if ((do_posix || do_traditional) && tables[i] == global_table) + if ((do_posix || do_traditional) && i == TAB_GLOBAL) continue; n = in_array(tables[i], tmp); @@ -121,28 +136,71 @@ lookup(const char *name) unref(tmp); if (n == NULL || n->type == Node_val) /* non-variable in SYMTAB */ return NULL; + /* If the name is found in the param or alias table and has multiple + * entries, then select the most recently pushed one in place of n. + */ + if ((i == TAB_PARAM || i == TAB_ALIAS) && n->dup_ent) + n = n->dup_ent; + + /* Alias resolution */ + if (i == TAB_ALIAS) + n = n->let_alias; + + /* Simple entry: return the entry itself. + */ return n; /* new place */ } /* make_params --- allocate function parameters for the symbol table */ -NODE * +NODE ** make_params(char **pnames, int pcount) { - NODE *p, *parms; + NODE **pp, **parms; int i; if (pcount <= 0 || pnames == NULL) return NULL; - ezalloc(parms, NODE *, pcount * sizeof(NODE), "make_params"); + emalloc(parms, NODE **, pcount * sizeof(NODE *), "make_params"); - for (i = 0, p = parms; i < pcount; i++, p++) { + for (i = 0, pp = parms; i < pcount; i++, pp++) { + NODE *p; + getnode(p); + memset(p, 0, sizeof *p); p->type = Node_param_list; p->param = pnames[i]; /* shadows pname and vname */ p->param_cnt = i; + *pp = p; + } + + return parms; +} + +/* extend_locals --- add a parameter to an existing param vector */ + +NODE **extend_locals(NODE **parms, const char *pname, int lcount) +{ + NODE *p; + + if (parms == NULL) { + emalloc(parms, NODE **, lcount * sizeof(NODE *), "extend_locals"); + } else { + erealloc(parms, NODE **, lcount * sizeof(NODE *), "extend_locals"); } + getnode(p); + memset(p, 0, sizeof *p); + + p->type = Node_param_list; + p->param = (char *) pname; + p->param_cnt = lcount - 1; + + parms[lcount - 1] = p; + + /* Unlike make_params, this also installs. */ + install(pname, p, Node_param_list); + return parms; } @@ -152,7 +210,7 @@ void install_params(NODE *func) { int i, pcount; - NODE *parms; + NODE **parms; if (func == NULL) return; @@ -164,7 +222,7 @@ install_params(NODE *func) return; for (i = 0; i < pcount; i++) - (void) install(parms[i].param, parms + i, Node_param_list); + (void) install(parms[i]->param, parms[i], Node_param_list); } @@ -172,10 +230,35 @@ install_params(NODE *func) * remove_params --- remove function parameters out of the symbol table. */ +static void +remove_common(NODE *p) +{ + NODE *tmp; + NODE *tmp2; + NODE *table; + + assert(p->type == Node_param_list || p->type == Node_alias); + + if (p->type == Node_param_list) + table = param_table; + else + table = alias_table; + + tmp = make_string(p->vname, strlen(p->vname)); + tmp2 = in_array(table, tmp); + + if (tmp2 != NULL && tmp2->dup_ent != NULL) + tmp2->dup_ent = tmp2->dup_ent->dup_ent; + else + (void) assoc_remove(table, tmp); + + unref(tmp); +} + void -remove_params(NODE *func) +remove_locals(NODE *func) { - NODE *parms, *p; + NODE **parms, *p; int i, pcount; if (func == NULL) @@ -183,29 +266,46 @@ remove_params(NODE *func) assert(func->type == Node_func); - if ( (pcount = func->param_cnt) <= 0 + if ( (pcount = func->frame_cnt) <= 0 || (parms = func->fparms) == NULL) return; - for (i = pcount - 1; i >= 0; i--) { - NODE *tmp; - NODE *tmp2; + for (i = pcount - 1; i >= 0; i--) + remove_common(parms[i]); - p = parms + i; - assert(p->type == Node_param_list); - tmp = make_string(p->vname, strlen(p->vname)); - tmp2 = in_array(param_table, tmp); - if (tmp2 != NULL && tmp2->dup_ent != NULL) - tmp2->dup_ent = tmp2->dup_ent->dup_ent; - else - (void) assoc_remove(param_table, tmp); + assoc_clear(param_table); /* shazzam! */ +} - unref(tmp); - } +void +install_let(NODE *let, const char *alias) +{ + free(let->param); + let->param = (char *) alias; + install(alias, let, let->type); +} - assoc_clear(param_table); /* shazzam! */ +NODE * +install_global_let(const char *alias, NODE *anon_global) +{ + NODE *let; + + getnode(let); + memset(let, 0, sizeof *let); + + let->type = Node_alias; + let->param = (char *) alias; + let->let_alias = anon_global; + + install(alias, let, Node_alias); + + return let; } +void +remove_let(NODE *let) +{ + remove_common(let); +} /* remove_symbol --- remove a symbol from the symbol table */ @@ -239,14 +339,14 @@ destroy_symbol(NODE *r) switch (r->type) { case Node_func: - if (r->param_cnt > 0) { + if (r->frame_cnt > 0) { NODE *n; int i; - int pcount = r->param_cnt; + int pcount = r->frame_cnt; /* function parameters of type Node_param_list */ for (i = 0; i < pcount; i++) { - n = r->fparms + i; + n = r->fparms[i]; efree(n->param); } efree(r->fparms); @@ -315,6 +415,8 @@ install(const char *name, NODE *parm, NODETYPE type) || type == Node_ext_func || type == Node_builtin_func) { table = func_table; + } else if (type == Node_alias) { + table = alias_table; } else if (installing_specials) { table = global_table; } @@ -330,7 +432,7 @@ install(const char *name, NODE *parm, NODETYPE type) var_count++; /* total, includes Node_func */ } - if (type == Node_param_list) { + if (type == Node_param_list || type == Node_alias) { prev = in_array(table, n_name); if (prev == NULL) goto simple; @@ -686,22 +788,22 @@ check_param_names(void) for (i = 0; i < max; i += 2) { f = list[i+1]; - if (f->type == Node_builtin_func || f->param_cnt == 0) + if (f->type == Node_builtin_func || f->frame_cnt == 0) continue; - /* loop over each param in function i */ - for (j = 0; j < f->param_cnt; j++) { + /* loop over each param/local in function i */ + for (j = 0; j < f->frame_cnt; j++) { /* compare to function names */ /* use a fake node to avoid malloc/free of make_string */ - n.stptr = f->fparms[j].param; - n.stlen = strlen(f->fparms[j].param); + n.stptr = f->fparms[j]->param; + n.stlen = strlen(f->fparms[j]->param); if (in_array(func_table, & n)) { error( _("function `%s': cannot use function `%s' as a parameter name"), list[i]->stptr, - f->fparms[j].param); + f->fparms[j]->param); result = false; } } |