diff options
Diffstat (limited to 'symbol.c')
-rw-r--r-- | symbol.c | 84 |
1 files changed, 81 insertions, 3 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,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; +} |