aboutsummaryrefslogtreecommitdiffstats
path: root/awkgram.y
diff options
context:
space:
mode:
Diffstat (limited to 'awkgram.y')
-rw-r--r--awkgram.y145
1 files changed, 128 insertions, 17 deletions
diff --git a/awkgram.y b/awkgram.y
index 49ac3ef6..85f3e014 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -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;
+}