aboutsummaryrefslogtreecommitdiffstats
path: root/awkgram.y
diff options
context:
space:
mode:
Diffstat (limited to 'awkgram.y')
-rw-r--r--awkgram.y123
1 files changed, 83 insertions, 40 deletions
diff --git a/awkgram.y b/awkgram.y
index 49ac3ef6..22a8df7a 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -60,6 +60,7 @@ 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 char *qualify_name(const char *name, size_t len);
static INSTRUCTION *trailing_comment;
static INSTRUCTION *outer_comment;
static INSTRUCTION *interblock_comment;
@@ -116,7 +117,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 +284,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) {
@@ -464,11 +465,33 @@ action
}
;
-func_name
+qualified_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_name
+ : qualified_name
| 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 +530,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 */
@@ -840,7 +863,7 @@ statement
/* else
$1 and $4 are NULLs */
}
- | LEX_FOR '(' NAME LEX_IN simple_variable r_paren opt_nls statement
+ | LEX_FOR '(' qualified_name LEX_IN simple_variable r_paren opt_nls statement
{
INSTRUCTION *ip;
char *var_name = $3->lextok;
@@ -1209,7 +1232,7 @@ regular_print:
}
}
- | LEX_DELETE NAME { sub_counter = 0; } delete_subscript_list
+ | LEX_DELETE qualified_name { sub_counter = 0; } delete_subscript_list
{
char *arr = $2->lextok;
@@ -1242,7 +1265,7 @@ regular_print:
$$ = list_append(list_append($4, $2), $1);
}
}
- | LEX_DELETE '(' NAME ')'
+ | LEX_DELETE '(' qualified_name ')'
/*
* this is for tawk compatibility. maybe the warnings
* should always be done.
@@ -2006,21 +2029,16 @@ direct_func_call
: FUNC_CALL '(' opt_fcall_expression_list r_paren
{
NODE *n;
- const char *name = $1->func_name;
-
- if (current_namespace != awk_namespace && strchr(name, ':') == NULL) {
- size_t len = strlen(current_namespace) + 2 + strlen(name) + 1;
- char *buf;
-
- emalloc(buf, char *, len, "direct_func_call");
- sprintf(buf, "%s::%s", current_namespace, name);
+ char *name = $1->func_name;
+ char *qname = qualify_name(name, strlen(name));
- efree((void *) $1->func_name);
- $1->func_name = buf;
+ if (qname != name) {
+ efree((char *) name);
+ $1->func_name = qname;
}
if (! at_seen) {
- n = lookup($1->func_name, true);
+ n = lookup($1->func_name);
if (n != NULL && n->type != Node_func
&& n->type != Node_ext_func) {
error_ln($1->source_line,
@@ -2115,17 +2133,16 @@ subscript_list
;
simple_variable
- : NAME
+ : qualified_name
{
- char *var_name = $1->lextok;
-
$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
+ | qualified_name subscript_list
{
char *arr = $1->lextok;
+
$1->memory = variable($1->source_line, arr, Node_var_new);
$1->opcode = Op_push_array;
$$ = list_prepend($2, $1);
@@ -3041,15 +3058,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);
}
}
@@ -4350,7 +4365,7 @@ retry:
goto out;
case FUNC_BODY:
/* in body, name must be in symbol table for it to be a parameter */
- if ((f = lookup(tokstart, false)) != NULL) {
+ if ((f = lookup(tokstart)) != NULL) {
if (f->type == Node_builtin_func)
break;
else
@@ -4458,7 +4473,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;
@@ -4846,7 +4861,7 @@ parms_shadow(INSTRUCTION *pc, bool *shadow)
* about all shadowed parameters.
*/
for (i = 0; i < pcount; i++) {
- if (lookup(fp[i].param, false) != NULL) {
+ if (lookup(fp[i].param) != NULL) {
warning(
_("function `%s': parameter `%s' shadows global variable"),
fname, fp[i].param);
@@ -5014,7 +5029,7 @@ install_function(char *fname, INSTRUCTION *fi, INSTRUCTION *plist)
NODE *r, *f;
int pcount = 0;
- r = lookup(fname, true);
+ r = lookup(fname);
if (r != NULL) {
error_ln(fi->source_line, _("function name `%s' previously defined"), fname);
return -1;
@@ -5023,6 +5038,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;
@@ -5214,7 +5234,7 @@ variable(int location, char *name, NODETYPE type)
{
NODE *r;
- if ((r = lookup(name, true)) != NULL) {
+ if ((r = lookup(name)) != NULL) {
if (r->type == Node_func || r->type == Node_ext_func )
error_ln(location, _("function `%s' called with space between name and `(',\nor used as a variable or an array"),
r->vname);
@@ -6799,15 +6819,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 +6841,28 @@ set_namespace(INSTRUCTION *ns, INSTRUCTION *comment)
return;
}
+
+/* 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;
+
+ NODE *p = lookup(name);
+ if (p != NULL && p->type == Node_param_list)
+ 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;
+ }
+
+ return (char *) name;
+}