aboutsummaryrefslogtreecommitdiffstats
path: root/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c190
1 files changed, 146 insertions, 44 deletions
diff --git a/symbol.c b/symbol.c
index 78b29bba..69f0a664 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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;
}
}