diff options
Diffstat (limited to 'symbol.c')
-rw-r--r-- | symbol.c | 95 |
1 files changed, 85 insertions, 10 deletions
@@ -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,11 +104,17 @@ 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++) { - if (tables[i]->table_size == 0) + if (assoc_empty(tables[i])) continue; if ((do_posix || do_traditional) && tables[i] == global_table) @@ -299,12 +307,22 @@ static NODE * install(const char *name, NODE *parm, NODETYPE type) { NODE *r; - NODE **aptr; 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) { @@ -334,14 +352,12 @@ install(const char *name, NODE *parm, NODETYPE type) goto simple; r->dup_ent = prev->dup_ent; prev->dup_ent = r; + unref(n_name); } else { simple: /* the simple case */ - aptr = assoc_lookup(table, n_name); - unref(*aptr); - *aptr = r; + assoc_set(table, n_name, r); } - unref(n_name); if (install_func) (*install_func)(r); @@ -644,7 +660,7 @@ check_param_names(void) bool result = true; NODE n; - if (func_table->table_size == 0) + if (assoc_empty(func_table)) return result; max = func_table->table_size * 2; @@ -946,3 +962,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; +} |