[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Inconsistency in Namespace Internal Name Management, Ver 5.1.1
From: |
arnold |
Subject: |
Re: Inconsistency in Namespace Internal Name Management, Ver 5.1.1 |
Date: |
Wed, 05 Jan 2022 12:12:29 -0700 |
User-agent: |
Heirloom mailx 12.5 7/5/10 |
Hi.
Thanks for the report.
J Naman <jnaman2@gmail.com> wrote:
> Ref: 15.6 Internal Name Management (in Namespaces)
> "For backwards compatibility, all identifiers in the awk namespace are
> stored internally as
> unadorned identifiers (that is, without a leading ‘awk::’). This is mainly
> relevant when
> using such identifiers as indices for SYMTAB, FUNCTAB, and
> PROCINFO["identifiers"]"
>
> The above is True for user-defined functions (UDFs)
> defined with a namespace qualified name, i.e. ns::foo()
> @namespace "ns"
> ns::foo is YES in FUNCTAB
> ns::foo is YES in PROCINFO["identifiers"];
>
> *NOT True* for UDFs defined with awk namespace qualified name, i.e.
> awk::foo()
Thanks for this report and for the test case sent privately.
Below is the fix. Your test case uncovered a nasty bug that was
due to how LALR(1) parsing works, no less!
I will be pushing to Git shortly.
Thanks,
Arnold
--------------------------
diff --git a/awkgram.y b/awkgram.y
index 0729d353..07de872f 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -57,6 +57,7 @@ static void dumpintlstr2(const char *str1, size_t len1, const
char *str2, size_t
static bool include_source(INSTRUCTION *file, void **srcfile_p);
static bool load_library(INSTRUCTION *file, void **srcfile_p);
static void set_namespace(INSTRUCTION *ns, INSTRUCTION *comment);
+static void change_namespace(const char *new_namespace);
static void next_sourcefile(void);
static char *tokexpand(void);
static NODE *set_profile_text(NODE *n, const char *str, size_t len);
@@ -112,6 +113,7 @@ static void add_sign_to_num(NODE *n, char sign);
static bool at_seen = false;
static bool want_source = false;
+static bool want_namespace = false;
static bool want_regexp = false; /* lexical scanning kludge */
static enum {
FUNC_HEADER,
@@ -317,7 +319,20 @@ rule
}
| '@' LEX_NAMESPACE namespace statement_term
{
+ /*
+ * 1/2022:
+ * We have an interesting isssue here. This production isn't
+ * reduced until after the token following the statement_term
+ * is seen. As a result, the change in namespace doesn't take
+ * effect until then. That's fine if the first token is
'function'
+ * or BEGIN or some such, but it's a disaster if it's an
identifer;
+ * that identifier will be in the previous namespace.
+ * Therefore, the actual setting of the namespace is done
immediately
+ * down in the scanner.
+ */
+
want_source = false;
+ want_namespace = false;
at_seen = false;
// this frees $3 storage in all cases
@@ -4078,6 +4093,8 @@ retry:
yylval = GET_INSTRUCTION(Op_token);
if (want_source) {
yylval->lextok = estrdup(tokstart, tok - tokstart);
+ if (want_namespace)
+ change_namespace(yylval->lextok);
return lasttok = FILENAME;
}
@@ -4418,6 +4435,8 @@ retry:
switch (class) {
case LEX_NAMESPACE:
+ want_namespace = true;
+ // fall through
case LEX_INCLUDE:
case LEX_LOAD:
want_source = true;
@@ -6818,7 +6837,7 @@ done:
return i;
}
-/* set_namespace --- change the current namespace */
+/* set_namespace --- update namespace data structures */
static void
set_namespace(INSTRUCTION *ns, INSTRUCTION *comment)
@@ -6849,13 +6868,9 @@ set_namespace(INSTRUCTION *ns, INSTRUCTION *comment)
return;
}
- if (strcmp(ns->lextok, current_namespace) == 0)
- ; // nothing to do
- else if (strcmp(ns->lextok, awk_namespace) == 0) {
- set_current_namespace(awk_namespace);
- } else {
- set_current_namespace(estrdup(ns->lextok, strlen(ns->lextok)));
- }
+ // Actual changing of namespace is done earlier.
+ // See comments in the production and in yylex().
+
efree(ns->lextok);
// save info and push on front of list of namespaces seen
@@ -6868,11 +6883,35 @@ set_namespace(INSTRUCTION *ns, INSTRUCTION *comment)
ns->lextok = NULL;
bcfree(ns);
- namespace_changed = true;
-
return;
}
+/* change_namespace --- change the current namespace */
+
+static void
+change_namespace(const char *new_namespace)
+{
+ /* error messages will come from set_namespace(), above */
+
+ if (! is_valid_identifier(new_namespace))
+ return;
+
+ int mid = check_special(new_namespace);
+
+ if (mid >= 0)
+ return;
+
+ if (strcmp(new_namespace, current_namespace) == 0)
+ ; // nothing to do
+ else if (strcmp(new_namespace, awk_namespace) == 0) {
+ set_current_namespace(awk_namespace);
+ } else {
+ set_current_namespace(estrdup(new_namespace,
strlen(new_namespace)));
+ }
+
+ namespace_changed = true;
+}
+
/* qualify_name --- put name into namespace */
static char *
diff --git a/symbol.c b/symbol.c
index be01369c..300fa871 100644
--- a/symbol.c
+++ b/symbol.c
@@ -604,7 +604,10 @@ load_symbols()
|| r->type == Node_var
|| r->type == Node_var_array
|| r->type == Node_var_new) {
- tmp = make_string(r->vname, strlen(r->vname));
+ if (strncmp(r->vname, "awk::", 5) == 0)
+ tmp = make_string(r->vname + 5,
strlen(r->vname) - 5);
+ else
+ tmp = make_string(r->vname,
strlen(r->vname));
aptr = assoc_lookup(sym_array, tmp);
unref(tmp);
unref(*aptr);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: Inconsistency in Namespace Internal Name Management, Ver 5.1.1,
arnold <=