diff options
Diffstat (limited to 'awkgram.y')
-rw-r--r-- | awkgram.y | 145 |
1 files changed, 128 insertions, 17 deletions
@@ -60,6 +60,8 @@ static void next_sourcefile(void); static char *tokexpand(void); static NODE *set_profile_text(NODE *n, const char *str, size_t len); static int check_qualified_special(char *token); +static bool is_all_upper(const char *name); +static char *qualify_name(const char *name, size_t len); static INSTRUCTION *trailing_comment; static INSTRUCTION *outer_comment; static INSTRUCTION *interblock_comment; @@ -116,7 +118,7 @@ static enum { FUNC_BODY, DONT_CHECK } want_param_names = DONT_CHECK; /* ditto */ -static char *in_function; /* parsing kludge */ +static bool in_function; /* parsing kludge */ static int rule = 0; const char *const ruletab[] = { @@ -283,7 +285,7 @@ rule } | function_prologue action { - in_function = NULL; + in_function = false; (void) mk_function($1, $2); want_param_names = DONT_CHECK; if (pending_comment != NULL) { @@ -466,9 +468,27 @@ action func_name : NAME - { $$ = $1; } + { + const char *name = $1->lextok; + char *qname = qualify_name(name, strlen(name)); + + if (qname != name) { + efree((void *)name); + $1->lextok = qname; + } + $$ = $1; + } | FUNC_CALL - { $$ = $1; } + { + const char *name = $1->lextok; + char *qname = qualify_name(name, strlen(name)); + + if (qname != name) { + efree((void *)name); + $1->lextok = qname; + } + $$ = $1; + } | lex_builtin { yyerror(_("`%s' is a built-in function, it cannot be redefined"), @@ -507,7 +527,7 @@ function_prologue $1->comment = func_comment; if (install_function($2->lextok, $1, $5) < 0) YYABORT; - in_function = $2->lextok; + in_function = true; $2->lextok = NULL; bcfree($2); /* $5 already free'd in install_function */ @@ -2006,6 +2026,7 @@ direct_func_call : FUNC_CALL '(' opt_fcall_expression_list r_paren { NODE *n; +#if 0 const char *name = $1->func_name; if (current_namespace != awk_namespace && strchr(name, ':') == NULL) { @@ -2018,6 +2039,15 @@ direct_func_call efree((void *) $1->func_name); $1->func_name = buf; } +#else + char *name = $1->func_name; + char *qname = qualify_name(name, strlen(name)); + + if (qname != name) { + efree((char *) name); + $1->func_name = qname; + } +#endif if (! at_seen) { n = lookup($1->func_name, true); @@ -2117,10 +2147,42 @@ subscript_list simple_variable : NAME { +#if 0 + // FIXME: Code here and at function call + // should be moved into a function char *var_name = $1->lextok; + bool is_all_upper = true; + char *cp; + for (cp = var_name; *cp != '\0'; cp++) { + if (! isupper(*cp)) { + is_all_upper = false; + break; + } + } + + if (current_namespace != awk_namespace && strchr(var_name, ':') == NULL && ! is_all_upper) { + size_t len = strlen(current_namespace) + 2 + strlen(var_name) + 1; + char *buf; + + emalloc(buf, char *, len, "simple_variable"); + sprintf(buf, "%s::%s", current_namespace, var_name); + + efree((void *) $1->lextok); + $1->lextok = buf; + } +#else + const char *name = $1->lextok; + char *qname = qualify_name(name, strlen(name)); + + if (qname != name) { + efree((void *)name); + $1->lextok = qname; + } +#endif + $1->opcode = Op_push; - $1->memory = variable($1->source_line, var_name, Node_var_new); + $1->memory = variable($1->source_line, $1->lextok, Node_var_new); $$ = list_create($1); } | NAME subscript_list @@ -3041,15 +3103,13 @@ next_sourcefile() lexeme = sourcefile->lexeme; sourceline = sourcefile->srclines; source = sourcefile->src; - if (current_namespace != awk_namespace) - efree((char *) current_namespace); - current_namespace = sourcefile->namespace; + set_current_namespace(sourcefile->namespace); } else { lexptr = NULL; sourceline = 0; source = NULL; lasttok = 0; - current_namespace = awk_namespace; + set_current_namespace(awk_namespace); } } @@ -4458,7 +4518,7 @@ make_instruction: return lasttok = class; } out: - tokkey = estrdup(tokstart, tok - tokstart); + tokkey = estrdup(tokstart, tok - tokstart - 1); if (*lexptr == '(') { yylval = bcalloc(Op_token, 2, sourceline); yylval->lextok = tokkey; @@ -5023,6 +5083,11 @@ install_function(char *fname, INSTRUCTION *fi, INSTRUCTION *plist) if (plist != NULL) pcount = plist->lasti->param_count + 1; f = install_symbol(fname, Node_func); + if (f->vname != fname) { + // DON'T free fname, it's done later + fname = f->vname; + } + fi->func_body = f; f->param_cnt = pcount; f->code_ptr = fi; @@ -6799,15 +6864,13 @@ set_namespace(INSTRUCTION *ns, INSTRUCTION *comment) } if (strcmp(ns->lextok, current_namespace) == 0) - efree(ns->lextok); + ; // nothing to do else if (strcmp(ns->lextok, awk_namespace) == 0) { - efree(ns->lextok); - current_namespace = awk_namespace; + set_current_namespace(awk_namespace); } else { - if (current_namespace != awk_namespace) - efree((char *) current_namespace); - current_namespace = ns->lextok; + set_current_namespace(estrdup(ns->lextok, strlen(ns->lextok))); } + efree(ns->lextok); // save info and push on front of list of namespaces seen INSTRUCTION *new_ns = instruction(Op_K_namespace); @@ -6823,3 +6886,51 @@ set_namespace(INSTRUCTION *ns, INSTRUCTION *comment) return; } + +/* is_all_upper --- return true if name is all uppercase letters */ + +/* + * DON'T use isupper(), it's locale aware! + */ + +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; +} + +/* qualify_name --- put name into namespace */ + +static char * +qualify_name(const char *name, size_t len) +{ + if (strchr(name, ':') != NULL) // already qualified + return (char *) name; + + if (current_namespace != awk_namespace && ! is_all_upper(name)) { + size_t length = strlen(current_namespace) + 2 + len + 1; + char *buf; + + emalloc(buf, char *, length, "qualify_name"); + sprintf(buf, "%s::%s", current_namespace, name); + + return buf; + } + + // is this right? + return (char *) name; +} |