diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-04-14 06:55:20 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-04-14 06:55:20 -0700 |
commit | d3064bd9a5116f57e60f3da91ffcf3f1a58b9ab0 (patch) | |
tree | 0a85191b0044e42e18d181d2ef71e5ccd696823e | |
parent | 71937179ae771612b60fd7c5b08212e38c6f0ddb (diff) | |
download | egawk-d3064bd9a5116f57e60f3da91ffcf3f1a58b9ab0.tar.gz egawk-d3064bd9a5116f57e60f3da91ffcf3f1a58b9ab0.tar.bz2 egawk-d3064bd9a5116f57e60f3da91ffcf3f1a58b9ab0.zip |
@let: add self-checks to symbol management code.
* symbol.c (remove_common, install): Check the sanity of the
installation and removal of parameter and alias symbols. This
is purely compile-time so the cycles are worth it.
-rw-r--r-- | symbol.c | 17 |
1 files changed, 15 insertions, 2 deletions
@@ -247,10 +247,16 @@ remove_common(NODE *p) tmp = make_string(p->vname, strlen(p->vname)); tmp2 = in_array(table, tmp); - if (tmp2 != NULL && tmp2->dup_ent != NULL) + if (tmp2 == NULL) { + /* nothing: diagnosing this leads to certain false positives. */ + } else if (tmp2->dup_ent == p) { tmp2->dup_ent = tmp2->dup_ent->dup_ent; - else + } else if (tmp2->dup_ent == NULL && tmp2 == p) { (void) assoc_remove(table, tmp); + } else { + fatal(_("LIFO local variable allocation not observed (p %p, found %p, dup %p)"), + p, tmp2, tmp2->dup_ent); + } unref(tmp); } @@ -436,10 +442,17 @@ install(const char *name, NODE *parm, NODETYPE type) } if (type == Node_param_list || type == Node_alias) { + NODE *dchk; r->dup_ent = NULL; prev = in_array(table, n_name); if (prev == NULL) goto simple; + if (prev == r) + fatal("primary symbol %s (%p/ type %d) entered twice into symbol table", + r->vname, r, r->type); + for (dchk = prev->dup_ent; dchk != NULL; dchk = dchk->dup_ent) + if (dchk == r) + fatal("shadowing symbol entered twice into symbol table"); r->dup_ent = prev->dup_ent; prev->dup_ent = r; unref(n_name); |