aboutsummaryrefslogtreecommitdiffstats
path: root/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c84
1 files changed, 81 insertions, 3 deletions
diff --git a/symbol.c b/symbol.c
index 9f8af3a0..fc598da5 100644
--- a/symbol.c
+++ b/symbol.c
@@ -39,6 +39,7 @@ static void (*install_func)(NODE *) = NULL;
static NODE *make_symbol(const char *name, NODETYPE type);
static NODE *install(const char *name, NODE *parm, NODETYPE type);
static void free_bcpool(INSTRUCTION_POOL *pl);
+static const char *fix_up_namespace(const char *name, bool *malloced);
static AWK_CONTEXT *curr_ctxt = NULL;
static int ctxt_level;
@@ -88,12 +89,13 @@ install_symbol(const char *name, NODETYPE type)
*/
NODE *
-lookup(const char *name)
+lookup(const char *name, bool do_qualify)
{
NODE *n;
NODE *tmp;
NODE *tables[5]; /* manual init below, for z/OS */
int i;
+ bool malloced = false;
/* ``It's turtles, all the way down.'' */
tables[0] = param_table; /* parameters shadow everything */
@@ -102,7 +104,13 @@ lookup(const char *name)
tables[3] = symbol_table; /* then globals */
tables[4] = NULL;
- tmp = make_string(name, strlen(name));
+ if (do_qualify)
+ name = fix_up_namespace(name, & malloced);
+
+ if (malloced)
+ tmp = make_str_node(name, strlen(name), ALREADY_MALLOCED);
+ else
+ tmp = make_string(name, strlen(name));
n = NULL;
for (i = 0; tables[i] != NULL; i++) {
@@ -303,8 +311,19 @@ install(const char *name, NODE *parm, NODETYPE type)
NODE *table;
NODE *n_name;
NODE *prev;
+ bool malloced = false;
+
+ if (type == Node_param_list) {
+ n_name = make_string(name, strlen(name));
+ } else {
+ name = fix_up_namespace(name, & malloced);
+
+ if (malloced)
+ n_name = make_str_node(name, strlen(name), ALREADY_MALLOCED);
+ else
+ n_name = make_string(name, strlen(name));
+ }
- n_name = make_string(name, strlen(name));
table = symbol_table;
if (type == Node_param_list) {
@@ -946,3 +965,62 @@ free_bcpool(INSTRUCTION_POOL *pl)
for (i = 0; i < MAX_INSTRUCTION_ALLOC; i++)
free_bc_mempool(& pl->pool[i], i + 1);
}
+
+/* is_all_upper --- return true if name is all uppercase letters */
+
+static bool
+is_all_upper(const char *name)
+{
+ for (; *name != '\0'; name ++) {
+ switch (*name) {
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'X': case 'Y':
+ case 'Z':
+ break;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* fix_up_namespace --- qualify / dequalify a simple name */
+
+static const char *
+fix_up_namespace(const char *name, bool *malloced)
+{
+ static char awk_ns[] = "awk::";
+ const size_t awk_ns_len = sizeof(awk_ns) - 1; // don't include trailing \0
+ char *cp;
+
+ assert(malloced != NULL);
+ *malloced = false;
+
+ // first, check if it's qualified
+ if ((cp = strchr(name, ':')) != NULL) {
+ // does it start with awk:: ?
+ if (strncmp(name, awk_ns, awk_ns_len) == 0)
+ return cp + 2; // just trailing part
+
+ // otherwise it's fully qualified, not in the awk n.s.
+ return name;
+ }
+
+ // not fully qualified
+ if (current_namespace == awk_namespace || is_all_upper(name))
+ return name; // put it into awk namespace
+
+ // make it fully qualified
+ size_t len = strlen(current_namespace) + 2 + strlen(name) + 1;
+ char *buf = NULL;
+
+ emalloc(buf, char *, len, "fix_up_namespace");
+ sprintf(buf, "%s::%s", current_namespace, name);
+ *malloced = true;
+
+ return buf;
+}