gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gawk-diffs] [SCM] gawk branch, feature/namespaces, updated. gawk-4.1.0-


From: Arnold Robbins
Subject: [gawk-diffs] [SCM] gawk branch, feature/namespaces, updated. gawk-4.1.0-2628-ge60ecc8
Date: Wed, 12 Jul 2017 22:59:15 -0400 (EDT)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, feature/namespaces has been updated
       via  e60ecc8e61fb642ab086ae85ae52bc64c47c1981 (commit)
      from  112e04137a4d519f9cf1bedf372f7271bedfdf4e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=e60ecc8e61fb642ab086ae85ae52bc64c47c1981

commit e60ecc8e61fb642ab086ae85ae52bc64c47c1981
Author: Arnold D. Robbins <address@hidden>
Date:   Thu Jul 13 05:58:32 2017 +0300

    Support namespace in API. Make reserved words invalid in namespaces. 
Further cleanups.

diff --git a/ChangeLog b/ChangeLog
index 05a6ca0..bcf18f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2017-07-13         Arnold D. Robbins     <address@hidden>
+
+       More rationalization of the namespace code.
+
+       * awk.h (is_valid_identifier): Declare.
+       * awkgram.y (grammar: direct_func_call): Store the fully qualified
+       name in the op code.
+       (yylex): Disallow reserved words and functions as namespace name.
+       (check_params): Small code edit
+       (validate_qualified_name): Use is_lsetter.
+       (set_namespace): Check for NULL pointer first! Use is_valid_identifier
+       instead of inline code.  Disallow using reserved words as namespace
+       names.
+       * ext.c (is_valid_identifier): No longer static.
+       (make_builtin): Check name and namespace gainst reserved words and
+       fatal error if found.
+       * gawkapi.c (ns_lookup): New function to look for variables
+       in namespaces.
+       (api_sym_lookup): Check namespace for validity and use ns_lookup.
+       (api_sym_update): Ditto.
+       * profile.c (pp_print): Correctly print full function name
+       in a function call.
+
 2017-07-11         Arnold D. Robbins     <address@hidden>
 
        Continue adding namespace support to the extension API.
diff --git a/awk.h b/awk.h
index d0786f0..177c8e1 100644
--- a/awk.h
+++ b/awk.h
@@ -1520,6 +1520,7 @@ extern void close_extensions(void);
 extern awk_bool_t make_builtin(const char *name_space, const awk_ext_func_t *);
 extern NODE *get_argument(int);
 extern NODE *get_actual_argument(NODE *, int, bool);
+extern bool is_valid_identifier(const char *name);
 #define get_scalar_argument(n, i)  get_actual_argument((n), (i), false)
 #define get_array_argument(n, i)   get_actual_argument((n), (i), true)
 #endif
diff --git a/awkgram.c b/awkgram.c
index 966303d..3303c96 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -698,9 +698,9 @@ static const yytype_uint16 yyrline[] =
     1653,  1655,  1657,  1659,  1661,  1675,  1680,  1685,  1710,  1716,
     1718,  1720,  1722,  1724,  1726,  1731,  1735,  1767,  1774,  1780,
     1786,  1799,  1800,  1801,  1806,  1811,  1815,  1819,  1834,  1855,
-    1860,  1897,  1926,  1927,  1933,  1934,  1939,  1941,  1948,  1965,
-    1982,  1984,  1991,  1996,  2004,  2014,  2026,  2035,  2039,  2043,
-    2047,  2051,  2055,  2058,  2060,  2064,  2068,  2072
+    1860,  1897,  1931,  1932,  1938,  1939,  1944,  1946,  1953,  1970,
+    1987,  1989,  1996,  2001,  2009,  2019,  2031,  2040,  2044,  2048,
+    2052,  2056,  2060,  2063,  2065,  2069,  2073,  2077
 };
 #endif
 
@@ -4064,6 +4064,11 @@ regular_print:
                                        _("attempt to use non-function `%s' in 
function call"),
                                                (yyvsp[-3])->func_name);
                        }
+                       if (n != NULL && strcmp(n->stptr, 
(yyvsp[-3])->func_name) != 0) {
+                               // replace xx with ns::xx
+                               efree((void *) (yyvsp[-3])->func_name);
+                               (yyvsp[-3])->func_name = estrdup(n->stptr, 
n->stlen = strlen(n->stptr));
+                       }
                }
                param_sanity((yyvsp[-1]));
                (yyvsp[-3])->opcode = Op_func_call;
@@ -4077,49 +4082,49 @@ regular_print:
                        (yyval) = list_append(t, (yyvsp[-3]));
                }
          }
-#line 4081 "awkgram.c" /* yacc.c:1646  */
+#line 4086 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 182:
-#line 1926 "awkgram.y" /* yacc.c:1646  */
+#line 1931 "awkgram.y" /* yacc.c:1646  */
     { (yyval) = NULL; }
-#line 4087 "awkgram.c" /* yacc.c:1646  */
+#line 4092 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 183:
-#line 1928 "awkgram.y" /* yacc.c:1646  */
+#line 1933 "awkgram.y" /* yacc.c:1646  */
     { (yyval) = (yyvsp[0]); }
-#line 4093 "awkgram.c" /* yacc.c:1646  */
+#line 4098 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 184:
-#line 1933 "awkgram.y" /* yacc.c:1646  */
+#line 1938 "awkgram.y" /* yacc.c:1646  */
     { (yyval) = NULL; }
-#line 4099 "awkgram.c" /* yacc.c:1646  */
+#line 4104 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 185:
-#line 1935 "awkgram.y" /* yacc.c:1646  */
+#line 1940 "awkgram.y" /* yacc.c:1646  */
     { (yyval) = (yyvsp[-1]); }
-#line 4105 "awkgram.c" /* yacc.c:1646  */
+#line 4110 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 186:
-#line 1940 "awkgram.y" /* yacc.c:1646  */
+#line 1945 "awkgram.y" /* yacc.c:1646  */
     {  (yyval) = (yyvsp[0]); }
-#line 4111 "awkgram.c" /* yacc.c:1646  */
+#line 4116 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 187:
-#line 1942 "awkgram.y" /* yacc.c:1646  */
+#line 1947 "awkgram.y" /* yacc.c:1646  */
     {
                (yyval) = list_merge((yyvsp[-1]), (yyvsp[0]));
          }
-#line 4119 "awkgram.c" /* yacc.c:1646  */
+#line 4124 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 188:
-#line 1949 "awkgram.y" /* yacc.c:1646  */
+#line 1954 "awkgram.y" /* yacc.c:1646  */
     {
                INSTRUCTION *ip = (yyvsp[0])->lasti;
                int count = ip->sub_count;      /* # of SUBSEP-seperated 
expressions */
@@ -4133,11 +4138,11 @@ regular_print:
                sub_counter++;  /* count # of dimensions */
                (yyval) = (yyvsp[0]);
          }
-#line 4137 "awkgram.c" /* yacc.c:1646  */
+#line 4142 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 189:
-#line 1966 "awkgram.y" /* yacc.c:1646  */
+#line 1971 "awkgram.y" /* yacc.c:1646  */
     {
                INSTRUCTION *t = (yyvsp[-1]);
                if ((yyvsp[-1]) == NULL) {
@@ -4151,31 +4156,31 @@ regular_print:
                        (yyvsp[0])->sub_count = count_expressions(&t, false);
                (yyval) = list_append(t, (yyvsp[0]));
          }
-#line 4155 "awkgram.c" /* yacc.c:1646  */
+#line 4160 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 190:
-#line 1983 "awkgram.y" /* yacc.c:1646  */
+#line 1988 "awkgram.y" /* yacc.c:1646  */
     {  (yyval) = (yyvsp[0]); }
-#line 4161 "awkgram.c" /* yacc.c:1646  */
+#line 4166 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 191:
-#line 1985 "awkgram.y" /* yacc.c:1646  */
+#line 1990 "awkgram.y" /* yacc.c:1646  */
     {
                (yyval) = list_merge((yyvsp[-1]), (yyvsp[0]));
          }
-#line 4169 "awkgram.c" /* yacc.c:1646  */
+#line 4174 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 192:
-#line 1992 "awkgram.y" /* yacc.c:1646  */
+#line 1997 "awkgram.y" /* yacc.c:1646  */
     { (yyval) = (yyvsp[-1]); }
-#line 4175 "awkgram.c" /* yacc.c:1646  */
+#line 4180 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 193:
-#line 1997 "awkgram.y" /* yacc.c:1646  */
+#line 2002 "awkgram.y" /* yacc.c:1646  */
     {
                char *var_name = (yyvsp[0])->lextok;
 
@@ -4183,22 +4188,22 @@ regular_print:
                (yyvsp[0])->memory = variable((yyvsp[0])->source_line, 
var_name, Node_var_new);
                (yyval) = list_create((yyvsp[0]));
          }
-#line 4187 "awkgram.c" /* yacc.c:1646  */
+#line 4192 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 194:
-#line 2005 "awkgram.y" /* yacc.c:1646  */
+#line 2010 "awkgram.y" /* yacc.c:1646  */
     {
                char *arr = (yyvsp[-1])->lextok;
                (yyvsp[-1])->memory = variable((yyvsp[-1])->source_line, arr, 
Node_var_new);
                (yyvsp[-1])->opcode = Op_push_array;
                (yyval) = list_prepend((yyvsp[0]), (yyvsp[-1]));
          }
-#line 4198 "awkgram.c" /* yacc.c:1646  */
+#line 4203 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 195:
-#line 2015 "awkgram.y" /* yacc.c:1646  */
+#line 2020 "awkgram.y" /* yacc.c:1646  */
     {
                INSTRUCTION *ip = (yyvsp[0])->nexti;
                if (ip->opcode == Op_push
@@ -4210,73 +4215,73 @@ regular_print:
                } else
                        (yyval) = (yyvsp[0]);
          }
-#line 4214 "awkgram.c" /* yacc.c:1646  */
+#line 4219 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 196:
-#line 2027 "awkgram.y" /* yacc.c:1646  */
+#line 2032 "awkgram.y" /* yacc.c:1646  */
     {
                (yyval) = list_append((yyvsp[-1]), (yyvsp[-2]));
                if ((yyvsp[0]) != NULL)
                        mk_assignment((yyvsp[-1]), NULL, (yyvsp[0]));
          }
-#line 4224 "awkgram.c" /* yacc.c:1646  */
+#line 4229 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 197:
-#line 2036 "awkgram.y" /* yacc.c:1646  */
+#line 2041 "awkgram.y" /* yacc.c:1646  */
     {
                (yyvsp[0])->opcode = Op_postincrement;
          }
-#line 4232 "awkgram.c" /* yacc.c:1646  */
+#line 4237 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 198:
-#line 2040 "awkgram.y" /* yacc.c:1646  */
+#line 2045 "awkgram.y" /* yacc.c:1646  */
     {
                (yyvsp[0])->opcode = Op_postdecrement;
          }
-#line 4240 "awkgram.c" /* yacc.c:1646  */
+#line 4245 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 199:
-#line 2043 "awkgram.y" /* yacc.c:1646  */
+#line 2048 "awkgram.y" /* yacc.c:1646  */
     { (yyval) = NULL; }
-#line 4246 "awkgram.c" /* yacc.c:1646  */
+#line 4251 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 201:
-#line 2051 "awkgram.y" /* yacc.c:1646  */
+#line 2056 "awkgram.y" /* yacc.c:1646  */
     { yyerrok; }
-#line 4252 "awkgram.c" /* yacc.c:1646  */
+#line 4257 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 202:
-#line 2055 "awkgram.y" /* yacc.c:1646  */
+#line 2060 "awkgram.y" /* yacc.c:1646  */
     { yyerrok; }
-#line 4258 "awkgram.c" /* yacc.c:1646  */
+#line 4263 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 205:
-#line 2064 "awkgram.y" /* yacc.c:1646  */
+#line 2069 "awkgram.y" /* yacc.c:1646  */
     { yyerrok; }
-#line 4264 "awkgram.c" /* yacc.c:1646  */
+#line 4269 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 206:
-#line 2068 "awkgram.y" /* yacc.c:1646  */
+#line 2073 "awkgram.y" /* yacc.c:1646  */
     { (yyval) = (yyvsp[0]); yyerrok; }
-#line 4270 "awkgram.c" /* yacc.c:1646  */
+#line 4275 "awkgram.c" /* yacc.c:1646  */
     break;
 
   case 207:
-#line 2072 "awkgram.y" /* yacc.c:1646  */
+#line 2077 "awkgram.y" /* yacc.c:1646  */
     { yyerrok; }
-#line 4276 "awkgram.c" /* yacc.c:1646  */
+#line 4281 "awkgram.c" /* yacc.c:1646  */
     break;
 
 
-#line 4280 "awkgram.c" /* yacc.c:1646  */
+#line 4285 "awkgram.c" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -4504,7 +4509,7 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 2074 "awkgram.y" /* yacc.c:1906  */
+#line 2079 "awkgram.y" /* yacc.c:1906  */
 
 
 struct token {
@@ -6611,10 +6616,9 @@ retry:
 
                                // check for keyword, etc.
                                *end = '\0';
-                               if (do_lint && (mid = check_special(tokstart)) 
>= 0) {
-                                       lintwarn(_("using reserved identifier 
`%s' as a namespace name may be confusing"), tokstart);
-                                       // but keep going anyway
-                               }
+                               if (check_special(tokstart) >= 0)
+                                       fatal(_("using reserved identifier `%s' 
as a namespace is not allowed"), tokstart);
+
                                *end = ':';
                        } else
                                pushback();
@@ -7358,7 +7362,7 @@ check_params(char *fname, int pcount, INSTRUCTION *list)
                        error_ln(p->source_line,
                                _("function `%s': can't use special variable 
`%s' as a function parameter"),
                                        fname, name);
-               } else if (strchr(name, ':'))
+               } else if (strchr(name, ':') != NULL)
                        error_ln(p->source_line,
                                _("function `%s': parameter `%s' cannot contain 
a namespace"),
                                        fname, name);
@@ -8882,7 +8886,7 @@ validate_qualified_name(char *token)
        if ((cp = strchr(token, ':')) == NULL)
                return;
 
-       if (cp[2] != '_' && ! is_alpha(cp[2]))
+       if (! is_letter(cp[2]))
                error_ln(sourceline,
                                _("qualified identifier `%s' is badly formed"),
                                token);
@@ -8904,6 +8908,9 @@ validate_qualified_name(char *token)
 static bool
 set_namespace(INSTRUCTION *ns)
 {
+       if (ns == NULL)
+               return false;
+
        if (do_traditional || do_posix) {
                error_ln(ns->source_line, _("@namespace is a gawk extension"));
                efree(ns->lextok);
@@ -8911,37 +8918,25 @@ set_namespace(INSTRUCTION *ns)
                return false;
        }
 
-       if (ns == NULL)
-               return false;
-
-       char *cp = ns->lextok;
-       if (*cp != '_' && ! is_alpha(*cp)) {
+       if (! is_valid_identifier(ns->lextok)) {
                error_ln(ns->source_line, _("namespace name `%s' must meet 
identifier naming rules"), ns->lextok);
                efree(ns->lextok);
                bcfree(ns);
                return false;
        }
 
-       for (cp++; *cp != '\0'; cp++) {
-               if (! is_identchar(*cp)) {
-                       error_ln(ns->source_line, _("namespace name `%s' must 
meet identifier naming rules"), ns->lextok);
-                       efree(ns->lextok);
-                       bcfree(ns);
-                       return false;
-               }
-       }
-
-       if (do_lint) {
-               int mid = check_special(ns->lextok);
+       int mid = check_special(ns->lextok);
 
-               if (mid >= 0)
-                       lintwarn(_("using reserved identifier `%s' as a 
namespace name may be confusing"),
-                                       ns->lextok);
+       if (mid >= 0) {
+               error_ln(ns->source_line, _("using reserved identifier `%s' as 
a namespace is not allowed"), ns->lextok);
+               efree(ns->lextok);
+               bcfree(ns);
+               return false;
        }
 
-       if (strcmp(ns->lextok, current_namespace) == 0) {
+       if (strcmp(ns->lextok, current_namespace) == 0)
                efree(ns->lextok);
-       } else if (strcmp(ns->lextok, awk_namespace) == 0) {
+       else if (strcmp(ns->lextok, awk_namespace) == 0) {
                efree(ns->lextok);
                current_namespace = awk_namespace;
        } else {
diff --git a/awkgram.y b/awkgram.y
index 00855a0..6ab40b1 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -1906,6 +1906,11 @@ direct_func_call
                                        _("attempt to use non-function `%s' in 
function call"),
                                                $1->func_name);
                        }
+                       if (n != NULL && strcmp(n->stptr, $1->func_name) != 0) {
+                               // replace xx with ns::xx
+                               efree((void *) $1->func_name);
+                               $1->func_name = estrdup(n->stptr, n->stlen = 
strlen(n->stptr));
+                       }
                }
                param_sanity($3);
                $1->opcode = Op_func_call;
@@ -4177,10 +4182,9 @@ retry:
 
                                // check for keyword, etc.
                                *end = '\0';
-                               if (do_lint && (mid = check_special(tokstart)) 
>= 0) {
-                                       lintwarn(_("using reserved identifier 
`%s' as a namespace name may be confusing"), tokstart);
-                                       // but keep going anyway
-                               }
+                               if (check_special(tokstart) >= 0)
+                                       fatal(_("using reserved identifier `%s' 
as a namespace is not allowed"), tokstart);
+
                                *end = ':';
                        } else
                                pushback();
@@ -4924,7 +4928,7 @@ check_params(char *fname, int pcount, INSTRUCTION *list)
                        error_ln(p->source_line,
                                _("function `%s': can't use special variable 
`%s' as a function parameter"),
                                        fname, name);
-               } else if (strchr(name, ':'))
+               } else if (strchr(name, ':') != NULL)
                        error_ln(p->source_line,
                                _("function `%s': parameter `%s' cannot contain 
a namespace"),
                                        fname, name);
@@ -6448,7 +6452,7 @@ validate_qualified_name(char *token)
        if ((cp = strchr(token, ':')) == NULL)
                return;
 
-       if (cp[2] != '_' && ! is_alpha(cp[2]))
+       if (! is_letter(cp[2]))
                error_ln(sourceline,
                                _("qualified identifier `%s' is badly formed"),
                                token);
@@ -6470,6 +6474,9 @@ validate_qualified_name(char *token)
 static bool
 set_namespace(INSTRUCTION *ns)
 {
+       if (ns == NULL)
+               return false;
+
        if (do_traditional || do_posix) {
                error_ln(ns->source_line, _("@namespace is a gawk extension"));
                efree(ns->lextok);
@@ -6477,37 +6484,25 @@ set_namespace(INSTRUCTION *ns)
                return false;
        }
 
-       if (ns == NULL)
-               return false;
-
-       char *cp = ns->lextok;
-       if (*cp != '_' && ! is_alpha(*cp)) {
+       if (! is_valid_identifier(ns->lextok)) {
                error_ln(ns->source_line, _("namespace name `%s' must meet 
identifier naming rules"), ns->lextok);
                efree(ns->lextok);
                bcfree(ns);
                return false;
        }
 
-       for (cp++; *cp != '\0'; cp++) {
-               if (! is_identchar(*cp)) {
-                       error_ln(ns->source_line, _("namespace name `%s' must 
meet identifier naming rules"), ns->lextok);
-                       efree(ns->lextok);
-                       bcfree(ns);
-                       return false;
-               }
-       }
-
-       if (do_lint) {
-               int mid = check_special(ns->lextok);
+       int mid = check_special(ns->lextok);
 
-               if (mid >= 0)
-                       lintwarn(_("using reserved identifier `%s' as a 
namespace name may be confusing"),
-                                       ns->lextok);
+       if (mid >= 0) {
+               error_ln(ns->source_line, _("using reserved identifier `%s' as 
a namespace is not allowed"), ns->lextok);
+               efree(ns->lextok);
+               bcfree(ns);
+               return false;
        }
 
-       if (strcmp(ns->lextok, current_namespace) == 0) {
+       if (strcmp(ns->lextok, current_namespace) == 0)
                efree(ns->lextok);
-       } else if (strcmp(ns->lextok, awk_namespace) == 0) {
+       else if (strcmp(ns->lextok, awk_namespace) == 0) {
                efree(ns->lextok);
                current_namespace = awk_namespace;
        } else {
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 9582a7f..88fe2ad 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,9 @@
+2017-07-13         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): More updates. Especially that
+       reserved words are not allowed in either half of a fully
+       qualified name or as a namespace.
+
 2017-07-05         Arnold D. Robbins     <address@hidden>
 
        * gawktexi.in (Namespaces): More updates.
diff --git a/doc/gawk.info b/doc/gawk.info
index b76643a..7de81a3 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -22560,15 +22560,20 @@ using variable names to index the special 'SYMTAB' 
array (*note
 Auto-set::), and when making indirect function calls (*note Indirect
 Calls::).
 
-   It is a syntax error to use any 'gawk' reserved word (such as 'if' or
+   It is a fatal error to use any 'gawk' reserved word (such as 'if' or
 'for'), or the name of any built-in function (such as 'sin()' or
-'gsub()') as the second part of a fully qualified name.  Using such an
-identifier as a namespace name (currently) _is_ allowed, but produces a
-lint warning.
+'gsub()') as either part of a fully qualified name.(1)
 
    'gawk' pre-defined variable names may be used: 'NF::NR' is valid, if
 possibly not all that useful.
 
+   ---------- Footnotes ----------
+
+   (1) We hope to improve the implementation so that this restriction
+will apply only to standard 'awk' reserved words and built-in functions.
+In this case, the additional built-in functions defined by 'gawk' will
+become pre-loaded extension functions.
+
 
 File: gawk.info,  Node: Default Namespace,  Next: Changing The Namespace,  
Prev: Qualified Names,  Up: Namespaces
 
@@ -22765,8 +22770,8 @@ Other notes for reviewers:
 Profiler:
      When profiling, we include the namespace in the 'Op_Rule' and
      'Op_Func' instructions.  If the namespace is different from the
-     previous one, output an '@namespace' statement.  For each
-     identifier, if it starts with the current namespace, output only
+     previous one, we output an '@namespace' statement.  For each
+     identifier, if it starts with the current namespace, we output only
      the simple part (DONE).
 
 Debugger:
@@ -22782,38 +22787,37 @@ How does this affect '@include'?
 
 Extension functions
      Revise the current macros to pass '"awk"' as the namespace argument
-     and add new macros with '_ns' or some such in the name that pass
-     the namespace of the extension.  This preserves backwards
-     compatibility at the source level while providing access to
-     namespaces as needed.
+     and add new macros with '_ns' in the name that pass the namespace
+     of the extension.  This preserves backwards compatibility at the
+     source level while providing access to namespaces as needed.
 
      Actually, since we've decided that 'awk' namespace variables and
      function are stored unadorned, the current macros that pass '""'
      would continue to work.  Internally, we need to recognize '"awk"'
      and _not_ fully qualify the name before storing it in the symbol
-     table.
+     table.  (Both DONE).
 
 More on Extension Functions
        1. Function and variables names need to be simple identifiers.
-          This currently isn't checked in the code.  Allowing both
-          namespace + identifier and 'foo::bar' would be confusing to
-          document and to code and to test.
-
-       2. Function and variable names cannot be reserved words.  This
-          also is currently not checked, since such things aren't
-          accessable from normal 'awk' code.  (They could be accessed
-          indirectly via 'FUNCTAB' and/or indirect function calls, but
-          that is an accident of the current implementation and not
-          necessarily a well-thought-out design decision.  In fact, I
-          think it's a bad idea.)
-
-       3. Namespace names need to be valid identifiers.  If we ever
-          decide to limit such names to non-keywords, the same check
-          needs to be applied.
+          This is now checked in the code.  Allowing both namespace +
+          identifier and 'foo::bar' would be confusing to document and
+          to code and to test.
+
+       2. Function and variable names cannot be reserved words.  This is
+          now checked.
+
+       3. Namespace names need to be valid identifiers.  They cannot be
+          keywords or reserved function names.
 
        4. It's debatable if there should be a default namespace for a
           plugin.  Should it be the plugin's name?  Probably not.
 
+          So, the initial plugin API allowed for (but did not use) a
+          namespace for installing functions, but didn't for variables.
+          That's been fixed.
+
+          *FIXME*: Still need to document this in the extension chapter.
+
        5. Should the 'ext_id', which is currently just a null pointer,
           be made to point to something?  What would be carry around in
           it?
@@ -22824,7 +22828,7 @@ Additional 'gawk' built-ins
      'gensub()', 'strftime()', etc.  into "pre-defined" extension
      functions in the 'awk' namespace.  This has some advantages:
 
-       1. It gives us room to add more built-ins without their being
+       1. It gives us room to add more built-ins without they're being
           reserved words to the grammar.  This in turn means that:
 
        2. Users can define their own functions with the same name as
@@ -22847,6 +22851,11 @@ Additional 'gawk' built-ins
 
           function gensub(str, pat, result) { ... }
 
+     One challenge is the 'snode()' function in 'awkgram.y' which does
+     certain "fix-ups" for calls to certain built-in functions,
+     including some of the additional 'gawk'-specific ones.  I still
+     think this is all doable, but it will take some thought.
+
 
 File: gawk.info,  Node: Arbitrary Precision Arithmetic,  Next: Dynamic 
Extensions,  Prev: Namespaces,  Up: Top
 
@@ -36522,184 +36531,185 @@ Node: Debugging Summary910196
 Node: Namespaces911475
 Node: Global Namespace912161
 Node: Qualified Names913508
-Node: Default Namespace914888
-Node: Changing The Namespace915665
-Node: Internal Name Management916877
-Node: Namespace Example917898
-Node: Namespace Misc919967
-Node: Arbitrary Precision Arithmetic923709
-Node: Computer Arithmetic925196
-Ref: table-numeric-ranges928787
-Ref: Computer Arithmetic-Footnote-1929509
-Node: Math Definitions929566
-Ref: table-ieee-formats932880
-Ref: Math Definitions-Footnote-1933483
-Node: MPFR features933588
-Node: FP Math Caution935305
-Ref: FP Math Caution-Footnote-1936377
-Node: Inexactness of computations936746
-Node: Inexact representation937706
-Node: Comparing FP Values939066
-Node: Errors accumulate940148
-Node: Getting Accuracy941581
-Node: Try To Round944291
-Node: Setting precision945190
-Ref: table-predefined-precision-strings945887
-Node: Setting the rounding mode947717
-Ref: table-gawk-rounding-modes948091
-Ref: Setting the rounding mode-Footnote-1951499
-Node: Arbitrary Precision Integers951678
-Ref: Arbitrary Precision Integers-Footnote-1956583
-Node: Checking for MPFR956732
-Node: POSIX Floating Point Problems958029
-Ref: POSIX Floating Point Problems-Footnote-1961900
-Node: Floating point summary961938
-Node: Dynamic Extensions964128
-Node: Extension Intro965681
-Node: Plugin License966947
-Node: Extension Mechanism Outline967744
-Ref: figure-load-extension968183
-Ref: figure-register-new-function969748
-Ref: figure-call-new-function970840
-Node: Extension API Description972902
-Node: Extension API Functions Introduction974544
-Node: General Data Types979878
-Ref: General Data Types-Footnote-1987083
-Node: Memory Allocation Functions987382
-Ref: Memory Allocation Functions-Footnote-1990534
-Node: Constructor Functions990633
-Node: Registration Functions993632
-Node: Extension Functions994317
-Node: Exit Callback Functions999530
-Node: Extension Version String1000780
-Node: Input Parsers1001443
-Node: Output Wrappers1014150
-Node: Two-way processors1018662
-Node: Printing Messages1020927
-Ref: Printing Messages-Footnote-11022098
-Node: Updating ERRNO1022251
-Node: Requesting Values1022990
-Ref: table-value-types-returned1023727
-Node: Accessing Parameters1024663
-Node: Symbol Table Access1025898
-Node: Symbol table by name1026410
-Node: Symbol table by cookie1028199
-Ref: Symbol table by cookie-Footnote-11032384
-Node: Cached values1032448
-Ref: Cached values-Footnote-11035984
-Node: Array Manipulation1036075
-Ref: Array Manipulation-Footnote-11037166
-Node: Array Data Types1037203
-Ref: Array Data Types-Footnote-11039861
-Node: Array Functions1039953
-Node: Flattening Arrays1044352
-Node: Creating Arrays1051293
-Node: Redirection API1056062
-Node: Extension API Variables1058904
-Node: Extension Versioning1059537
-Ref: gawk-api-version1059974
-Node: Extension API Informational Variables1061702
-Node: Extension API Boilerplate1062766
-Node: Changes from API V11066628
-Node: Finding Extensions1067288
-Node: Extension Example1067847
-Node: Internal File Description1068645
-Node: Internal File Ops1072725
-Ref: Internal File Ops-Footnote-11084125
-Node: Using Internal File Ops1084265
-Ref: Using Internal File Ops-Footnote-11086648
-Node: Extension Samples1086922
-Node: Extension Sample File Functions1088451
-Node: Extension Sample Fnmatch1096100
-Node: Extension Sample Fork1097587
-Node: Extension Sample Inplace1098805
-Node: Extension Sample Ord1102022
-Node: Extension Sample Readdir1102858
-Ref: table-readdir-file-types1103747
-Node: Extension Sample Revout1104552
-Node: Extension Sample Rev2way1105141
-Node: Extension Sample Read write array1105881
-Node: Extension Sample Readfile1107823
-Node: Extension Sample Time1108918
-Node: Extension Sample API Tests1110266
-Node: gawkextlib1110758
-Node: Extension summary1113205
-Node: Extension Exercises1116907
-Node: Language History1118405
-Node: V7/SVR3.11120061
-Node: SVR41122213
-Node: POSIX1123647
-Node: BTL1125026
-Node: POSIX/GNU1125755
-Node: Feature History1131647
-Node: Common Extensions1146071
-Node: Ranges and Locales1147354
-Ref: Ranges and Locales-Footnote-11151970
-Ref: Ranges and Locales-Footnote-21151997
-Ref: Ranges and Locales-Footnote-31152232
-Node: Contributors1152453
-Node: History summary1158013
-Node: Installation1159393
-Node: Gawk Distribution1160337
-Node: Getting1160821
-Node: Extracting1161782
-Node: Distribution contents1163420
-Node: Unix Installation1169762
-Node: Quick Installation1170444
-Node: Shell Startup Files1172858
-Node: Additional Configuration Options1173947
-Node: Configuration Philosophy1175936
-Node: Non-Unix Installation1178305
-Node: PC Installation1178765
-Node: PC Binary Installation1179603
-Node: PC Compiling1180038
-Node: PC Using1181155
-Node: Cygwin1184200
-Node: MSYS1184970
-Node: VMS Installation1185471
-Node: VMS Compilation1186262
-Ref: VMS Compilation-Footnote-11187491
-Node: VMS Dynamic Extensions1187549
-Node: VMS Installation Details1189234
-Node: VMS Running1191487
-Node: VMS GNV1195766
-Node: VMS Old Gawk1196501
-Node: Bugs1196972
-Node: Bug address1197635
-Node: Usenet1200032
-Node: Maintainers1200809
-Node: Other Versions1202185
-Node: Installation summary1208769
-Node: Notes1209804
-Node: Compatibility Mode1210669
-Node: Additions1211451
-Node: Accessing The Source1212376
-Node: Adding Code1213811
-Node: New Ports1220029
-Node: Derived Files1224517
-Ref: Derived Files-Footnote-11230002
-Ref: Derived Files-Footnote-21230037
-Ref: Derived Files-Footnote-31230635
-Node: Future Extensions1230749
-Node: Implementation Limitations1231407
-Node: Extension Design1232590
-Node: Old Extension Problems1233744
-Ref: Old Extension Problems-Footnote-11235262
-Node: Extension New Mechanism Goals1235319
-Ref: Extension New Mechanism Goals-Footnote-11238683
-Node: Extension Other Design Decisions1238872
-Node: Extension Future Growth1240985
-Node: Old Extension Mechanism1241821
-Node: Notes summary1243584
-Node: Basic Concepts1244766
-Node: Basic High Level1245447
-Ref: figure-general-flow1245729
-Ref: figure-process-flow1246414
-Ref: Basic High Level-Footnote-11249715
-Node: Basic Data Typing1249900
-Node: Glossary1253228
-Node: Copying1285175
-Node: GNU Free Documentation License1322714
-Node: Index1347832
+Ref: Qualified Names-Footnote-1914821
+Node: Default Namespace915075
+Node: Changing The Namespace915852
+Node: Internal Name Management917064
+Node: Namespace Example918085
+Node: Namespace Misc920154
+Node: Arbitrary Precision Arithmetic924001
+Node: Computer Arithmetic925488
+Ref: table-numeric-ranges929079
+Ref: Computer Arithmetic-Footnote-1929801
+Node: Math Definitions929858
+Ref: table-ieee-formats933172
+Ref: Math Definitions-Footnote-1933775
+Node: MPFR features933880
+Node: FP Math Caution935597
+Ref: FP Math Caution-Footnote-1936669
+Node: Inexactness of computations937038
+Node: Inexact representation937998
+Node: Comparing FP Values939358
+Node: Errors accumulate940440
+Node: Getting Accuracy941873
+Node: Try To Round944583
+Node: Setting precision945482
+Ref: table-predefined-precision-strings946179
+Node: Setting the rounding mode948009
+Ref: table-gawk-rounding-modes948383
+Ref: Setting the rounding mode-Footnote-1951791
+Node: Arbitrary Precision Integers951970
+Ref: Arbitrary Precision Integers-Footnote-1956875
+Node: Checking for MPFR957024
+Node: POSIX Floating Point Problems958321
+Ref: POSIX Floating Point Problems-Footnote-1962192
+Node: Floating point summary962230
+Node: Dynamic Extensions964420
+Node: Extension Intro965973
+Node: Plugin License967239
+Node: Extension Mechanism Outline968036
+Ref: figure-load-extension968475
+Ref: figure-register-new-function970040
+Ref: figure-call-new-function971132
+Node: Extension API Description973194
+Node: Extension API Functions Introduction974836
+Node: General Data Types980170
+Ref: General Data Types-Footnote-1987375
+Node: Memory Allocation Functions987674
+Ref: Memory Allocation Functions-Footnote-1990826
+Node: Constructor Functions990925
+Node: Registration Functions993924
+Node: Extension Functions994609
+Node: Exit Callback Functions999822
+Node: Extension Version String1001072
+Node: Input Parsers1001735
+Node: Output Wrappers1014442
+Node: Two-way processors1018954
+Node: Printing Messages1021219
+Ref: Printing Messages-Footnote-11022390
+Node: Updating ERRNO1022543
+Node: Requesting Values1023282
+Ref: table-value-types-returned1024019
+Node: Accessing Parameters1024955
+Node: Symbol Table Access1026190
+Node: Symbol table by name1026702
+Node: Symbol table by cookie1028491
+Ref: Symbol table by cookie-Footnote-11032676
+Node: Cached values1032740
+Ref: Cached values-Footnote-11036276
+Node: Array Manipulation1036367
+Ref: Array Manipulation-Footnote-11037458
+Node: Array Data Types1037495
+Ref: Array Data Types-Footnote-11040153
+Node: Array Functions1040245
+Node: Flattening Arrays1044644
+Node: Creating Arrays1051585
+Node: Redirection API1056354
+Node: Extension API Variables1059196
+Node: Extension Versioning1059829
+Ref: gawk-api-version1060266
+Node: Extension API Informational Variables1061994
+Node: Extension API Boilerplate1063058
+Node: Changes from API V11066920
+Node: Finding Extensions1067580
+Node: Extension Example1068139
+Node: Internal File Description1068937
+Node: Internal File Ops1073017
+Ref: Internal File Ops-Footnote-11084417
+Node: Using Internal File Ops1084557
+Ref: Using Internal File Ops-Footnote-11086940
+Node: Extension Samples1087214
+Node: Extension Sample File Functions1088743
+Node: Extension Sample Fnmatch1096392
+Node: Extension Sample Fork1097879
+Node: Extension Sample Inplace1099097
+Node: Extension Sample Ord1102314
+Node: Extension Sample Readdir1103150
+Ref: table-readdir-file-types1104039
+Node: Extension Sample Revout1104844
+Node: Extension Sample Rev2way1105433
+Node: Extension Sample Read write array1106173
+Node: Extension Sample Readfile1108115
+Node: Extension Sample Time1109210
+Node: Extension Sample API Tests1110558
+Node: gawkextlib1111050
+Node: Extension summary1113497
+Node: Extension Exercises1117199
+Node: Language History1118697
+Node: V7/SVR3.11120353
+Node: SVR41122505
+Node: POSIX1123939
+Node: BTL1125318
+Node: POSIX/GNU1126047
+Node: Feature History1131939
+Node: Common Extensions1146363
+Node: Ranges and Locales1147646
+Ref: Ranges and Locales-Footnote-11152262
+Ref: Ranges and Locales-Footnote-21152289
+Ref: Ranges and Locales-Footnote-31152524
+Node: Contributors1152745
+Node: History summary1158305
+Node: Installation1159685
+Node: Gawk Distribution1160629
+Node: Getting1161113
+Node: Extracting1162074
+Node: Distribution contents1163712
+Node: Unix Installation1170054
+Node: Quick Installation1170736
+Node: Shell Startup Files1173150
+Node: Additional Configuration Options1174239
+Node: Configuration Philosophy1176228
+Node: Non-Unix Installation1178597
+Node: PC Installation1179057
+Node: PC Binary Installation1179895
+Node: PC Compiling1180330
+Node: PC Using1181447
+Node: Cygwin1184492
+Node: MSYS1185262
+Node: VMS Installation1185763
+Node: VMS Compilation1186554
+Ref: VMS Compilation-Footnote-11187783
+Node: VMS Dynamic Extensions1187841
+Node: VMS Installation Details1189526
+Node: VMS Running1191779
+Node: VMS GNV1196058
+Node: VMS Old Gawk1196793
+Node: Bugs1197264
+Node: Bug address1197927
+Node: Usenet1200324
+Node: Maintainers1201101
+Node: Other Versions1202477
+Node: Installation summary1209061
+Node: Notes1210096
+Node: Compatibility Mode1210961
+Node: Additions1211743
+Node: Accessing The Source1212668
+Node: Adding Code1214103
+Node: New Ports1220321
+Node: Derived Files1224809
+Ref: Derived Files-Footnote-11230294
+Ref: Derived Files-Footnote-21230329
+Ref: Derived Files-Footnote-31230927
+Node: Future Extensions1231041
+Node: Implementation Limitations1231699
+Node: Extension Design1232882
+Node: Old Extension Problems1234036
+Ref: Old Extension Problems-Footnote-11235554
+Node: Extension New Mechanism Goals1235611
+Ref: Extension New Mechanism Goals-Footnote-11238975
+Node: Extension Other Design Decisions1239164
+Node: Extension Future Growth1241277
+Node: Old Extension Mechanism1242113
+Node: Notes summary1243876
+Node: Basic Concepts1245058
+Node: Basic High Level1245739
+Ref: figure-general-flow1246021
+Ref: figure-process-flow1246706
+Ref: Basic High Level-Footnote-11250007
+Node: Basic Data Typing1250192
+Node: Glossary1253520
+Node: Copying1285467
+Node: GNU Free Documentation License1323006
+Node: Index1348124
 
 End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index d885c0b..bb4bb64 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -31277,11 +31277,14 @@ and functions in another.  This is especially 
important when using
 variable names to index the special @code{SYMTAB} array (@pxref{Auto-set}),
 and when making indirect function calls (@pxref{Indirect Calls}).
 
-It is a syntax error to use any @command{gawk} reserved word (such
+It is a fatal error to use any @command{gawk} reserved word (such
 as @code{if} or @code{for}), or the name of any built-in function
-(such as @code{sin()} or @code{gsub()}) as the second part of a
-fully qualified name.  Using such an identifier as a namespace
-name (currently) @emph{is} allowed, but produces a lint warning.
+(such as @code{sin()} or @code{gsub()}) as either part of a
+fully qualified address@hidden hope to improve the implementation so
+that this restriction will apply only to standard @command{awk}
+reserved words and built-in functions. In this case, the additional
+built-in functions defined by @command{gawk} will become pre-loaded
+extension functions.}
 
 @command{gawk} pre-defined variable names may be used:
 @code{NF::NR} is valid, if possibly not all that useful.
@@ -31479,8 +31482,8 @@ Other notes for reviewers:
 When profiling, we include the namespace in the @code{Op_Rule}
 and @code{Op_Func} instructions.  If the namespace
 is different from the previous
-one, output an @samp{@@namespace} statement.  For each identifier,
-if it starts with the current namespace, output only the simple part
+one, we output an @samp{@@namespace} statement.  For each identifier,
+if it starts with the current namespace, we output only the simple part
 (DONE).
 
 @item Debugger:
@@ -31497,7 +31500,7 @@ namespace @samp{awk} until an @code{@@namespace} is seen
 
 @item Extension functions
 Revise the current macros to pass @code{"awk"} as the namespace
-argument and add new macros with @samp{_ns} or some such in the name that
+argument and add new macros with @samp{_ns} in the name that
 pass the namespace of the extension.  This preserves backwards
 compatibility at the source level while providing access to namespaces
 as needed.
@@ -31506,30 +31509,32 @@ Actually, since we've decided that @code{awk} 
namespace variables and
 function are stored unadorned, the current macros that pass @code{""}
 would continue to work. Internally, we need to recognize @code{"awk"} and
 @emph{not} fully qualify the name before storing it in the symbol table.
+(Both DONE).
 
 @item More on Extension Functions
 @enumerate 1
 @item
-Function and variables names need to be simple identifiers. This
-currently isn't checked in the code. Allowing both namespace + identifier
+Function and variables names need to be simple identifiers. This is now
+checked in the code. Allowing both namespace + identifier
 and @code{foo::bar} would be confusing to document and to code and to test.
 
 @item
-Function and variable names cannot be reserved words. This also is currently
-not checked, since such things aren't accessable from normal @command{awk}
-code.  (They could be accessed indirectly via @code{FUNCTAB} and/or
-indirect function calls, but that is an accident of the current
-implementation and not necessarily a well-thought-out design decision.
-In fact, I think it's a bad idea.)
+Function and variable names cannot be reserved words. This is now
+checked.
 
 @item
-Namespace names need to be valid identifiers. If we ever decide to
-limit such names to non-keywords, the same check needs to be applied.
+Namespace names need to be valid identifiers. They cannot be
+keywords or reserved function names.
 
 @item
 It's debatable if there should be a default namespace for a plugin.
 Should it be the plugin's name?  Probably not.
 
+So, the initial plugin API allowed for (but did not use) a namespace
+for installing functions, but didn't for variables. That's been fixed.
+
address@hidden: Still need to document this in the extension chapter.
+
 @item
 Should the @code{ext_id}, which is currently just a null pointer,
 be made to point to something?  What would be carry around in it?
@@ -31544,7 +31549,7 @@ advantages:
 
 @enumerate 1
 @item
-It gives us room to add more built-ins without their being reserved
+It gives us room to add more built-ins without they're being reserved
 words to the grammar.  This in turn means that:
 
 @item
@@ -31573,6 +31578,9 @@ Whereas this would not:
 function gensub(str, pat, result) @{ @dots{} @}
 @end example
 
+One challenge is the @code{snode()} function in @file{awkgram.y} which does 
certain ``fix-ups''
+for calls to certain built-in functions, including some of the additional 
@command{gawk}-specific ones.
+I still think this is all doable, but it will take some thought.
 @end table
 
 @node Arbitrary Precision Arithmetic
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index 56e1bc5..3411f41 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -30291,11 +30291,14 @@ and functions in another.  This is especially 
important when using
 variable names to index the special @code{SYMTAB} array (@pxref{Auto-set}),
 and when making indirect function calls (@pxref{Indirect Calls}).
 
-It is a syntax error to use any @command{gawk} reserved word (such
+It is a fatal error to use any @command{gawk} reserved word (such
 as @code{if} or @code{for}), or the name of any built-in function
-(such as @code{sin()} or @code{gsub()}) as the second part of a
-fully qualified name.  Using such an identifier as a namespace
-name (currently) @emph{is} allowed, but produces a lint warning.
+(such as @code{sin()} or @code{gsub()}) as either part of a
+fully qualified address@hidden hope to improve the implementation so
+that this restriction will apply only to standard @command{awk}
+reserved words and built-in functions. In this case, the additional
+built-in functions defined by @command{gawk} will become pre-loaded
+extension functions.}
 
 @command{gawk} pre-defined variable names may be used:
 @code{NF::NR} is valid, if possibly not all that useful.
@@ -30493,8 +30496,8 @@ Other notes for reviewers:
 When profiling, we include the namespace in the @code{Op_Rule}
 and @code{Op_Func} instructions.  If the namespace
 is different from the previous
-one, output an @samp{@@namespace} statement.  For each identifier,
-if it starts with the current namespace, output only the simple part
+one, we output an @samp{@@namespace} statement.  For each identifier,
+if it starts with the current namespace, we output only the simple part
 (DONE).
 
 @item Debugger:
@@ -30511,7 +30514,7 @@ namespace @samp{awk} until an @code{@@namespace} is seen
 
 @item Extension functions
 Revise the current macros to pass @code{"awk"} as the namespace
-argument and add new macros with @samp{_ns} or some such in the name that
+argument and add new macros with @samp{_ns} in the name that
 pass the namespace of the extension.  This preserves backwards
 compatibility at the source level while providing access to namespaces
 as needed.
@@ -30520,30 +30523,32 @@ Actually, since we've decided that @code{awk} 
namespace variables and
 function are stored unadorned, the current macros that pass @code{""}
 would continue to work. Internally, we need to recognize @code{"awk"} and
 @emph{not} fully qualify the name before storing it in the symbol table.
+(Both DONE).
 
 @item More on Extension Functions
 @enumerate 1
 @item
-Function and variables names need to be simple identifiers. This
-currently isn't checked in the code. Allowing both namespace + identifier
+Function and variables names need to be simple identifiers. This is now
+checked in the code. Allowing both namespace + identifier
 and @code{foo::bar} would be confusing to document and to code and to test.
 
 @item
-Function and variable names cannot be reserved words. This also is currently
-not checked, since such things aren't accessable from normal @command{awk}
-code.  (They could be accessed indirectly via @code{FUNCTAB} and/or
-indirect function calls, but that is an accident of the current
-implementation and not necessarily a well-thought-out design decision.
-In fact, I think it's a bad idea.)
+Function and variable names cannot be reserved words. This is now
+checked.
 
 @item
-Namespace names need to be valid identifiers. If we ever decide to
-limit such names to non-keywords, the same check needs to be applied.
+Namespace names need to be valid identifiers. They cannot be
+keywords or reserved function names.
 
 @item
 It's debatable if there should be a default namespace for a plugin.
 Should it be the plugin's name?  Probably not.
 
+So, the initial plugin API allowed for (but did not use) a namespace
+for installing functions, but didn't for variables. That's been fixed.
+
address@hidden: Still need to document this in the extension chapter.
+
 @item
 Should the @code{ext_id}, which is currently just a null pointer,
 be made to point to something?  What would be carry around in it?
@@ -30558,7 +30563,7 @@ advantages:
 
 @enumerate 1
 @item
-It gives us room to add more built-ins without their being reserved
+It gives us room to add more built-ins without they're being reserved
 words to the grammar.  This in turn means that:
 
 @item
@@ -30587,6 +30592,9 @@ Whereas this would not:
 function gensub(str, pat, result) @{ @dots{} @}
 @end example
 
+One challenge is the @code{snode()} function in @file{awkgram.y} which does 
certain ``fix-ups''
+for calls to certain built-in functions, including some of the additional 
@command{gawk}-specific ones.
+I still think this is all doable, but it will take some thought.
 @end table
 
 @node Arbitrary Precision Arithmetic
diff --git a/ext.c b/ext.c
index 99bc159..f1cbe71 100644
--- a/ext.c
+++ b/ext.c
@@ -79,7 +79,7 @@ load_ext(const char *lib_name)
 
 /* is_valid_identifier --- return true if name is a valid simple identifier */
 
-static bool
+bool
 is_valid_identifier(const char *name)
 {
        const char *sp = name;
@@ -115,12 +115,20 @@ make_builtin(const char *name_space, const awk_ext_func_t 
*funcinfo)
 
        assert(name_space != NULL);
        if (name_space[0] == '\0' || strcmp(name_space, awk_namespace) == 0) {
+               if (check_special(name) >= 0)
+                       fatal(_("make_builtin: can't use gawk built-in `%s' as 
function name"), name);
+
                f = lookup(name, false);
                install_name = estrdup(name, strlen(name));
        } else {
                if (! is_valid_identifier(name_space))
                        return awk_false;
 
+               if (check_special(name_space) >= 0)
+                       fatal(_("make_builtin: can't use gawk built-in `%s' as 
namespace name"), name_space);
+               if (check_special(name) >= 0)
+                       fatal(_("make_builtin: can't use gawk built-in `%s' as 
function name"), name);
+
                size_t len = strlen(name_space) + 2 + strlen(name) + 1;
                char *buf;
                emalloc(buf, char *, len, "make_builtin");
@@ -131,6 +139,7 @@ make_builtin(const char *name_space, const awk_ext_func_t 
*funcinfo)
        }
 
        if (f != NULL) {
+               // found it, but it shouldn't be there if we want to install 
this function
                if (f->type == Node_func) {
                        /* user-defined function */
                        fatal(_("make_builtin: can't redefine function `%s'"), 
name);
@@ -142,10 +151,7 @@ make_builtin(const char *name_space, const awk_ext_func_t 
*funcinfo)
                } else
                        /* variable name etc. */
                        fatal(_("make_builtin: function name `%s' previously 
defined"), name);
-       } else if (check_special(name) >= 0)
-               fatal(_("make_builtin: can't use gawk built-in `%s' as function 
name"), name);
-       // else
-       //      what to do if f == NULL?
+       }
 
        if (count < 0)
                fatal(_("make_builtin: negative argument count for function 
`%s'"),
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 8bb9759..cc87160 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,10 @@
+2017-07-13         Arnold D. Robbins     <address@hidden>
+
+       * testext.c (init_test_ext): Add installation of a variable and a
+       function in a namespace, and test using them.
+       (do_test_function): New function.
+       (ns_test_func): New function entry for it.
+
 2017-06-22         Andrew J. Schorr     <address@hidden>
 
        * rwarray.c (read_value): Use malloc instead of calloc, since
diff --git a/extension/testext.c b/extension/testext.c
index 572475e..44a504f 100644
--- a/extension/testext.c
+++ b/extension/testext.c
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2012, 2013, 2014, 2015
+ * Copyright (C) 2012, 2013, 2014, 2015, 2017
  * the Free Software Foundation, Inc.
  *
  * This file is part of GAWK, the GNU implementation of the
@@ -1034,6 +1034,17 @@ static void at_exit2(void *data, int exit_status)
        printf(" exit_status = %d\n", exit_status);
 }
 
+/* do_test_function --- test function for test namespace */
+
+static awk_value_t *
+do_test_function(int nargs, awk_value_t *result, struct awk_ext_func *unused)
+{
+       printf("test::test_function() called.\n");
+       fflush(stdout);
+
+       return make_number(0.0, result);
+}
+
 static awk_ext_func_t func_table[] = {
        { "dump_array_and_delete", dump_array_and_delete, 2, 2, awk_false, NULL 
},
        { "try_modify_environ", try_modify_environ, 0, 0, awk_false, NULL },
@@ -1051,6 +1062,10 @@ static awk_ext_func_t func_table[] = {
        { "get_file", do_get_file, 4, 4, awk_false, NULL },
 };
 
+static awk_ext_func_t ns_test_func = {
+       "test_function", do_test_function, 0, 0, awk_false, NULL
+};
+
 /* init_testext --- additional initialization function */
 
 static awk_bool_t init_testext(void)
@@ -1058,6 +1073,7 @@ static awk_bool_t init_testext(void)
        awk_value_t value;
        static const char message[] = "hello, world";   /* of course */
        static const char message2[] = "i am a scalar";
+       static const char message3[] = "in namespace test";
 
        /* This is used by the getfile test */
        if (sym_lookup("TESTEXT_QUIET", AWK_NUMBER, & value))
@@ -1075,6 +1091,9 @@ BEGIN {
        for (i in new_array)
                printf("new_array[\"%s\"] = \"%s\"\n", i, new_array[i])
        print ""
+       printf("test::testval = %s\n", test::testval)
+       test::test_function()
+       print ""
 }
 */
 
@@ -1092,6 +1111,13 @@ BEGIN {
 
        create_new_array();
 
+       if (! sym_update_ns("test", "testval",
+                       make_const_string(message3, strlen(message3), & value)))
+               printf("testext: sym_update_ns(\"test\", \"testval\") 
failed!\n");
+
+       if (! add_ext_func("test", & ns_test_func))
+               printf("testext: add_ext_func(\"test\", ns_test_func) 
failed!\n");
+
        return awk_true;
 }
 
diff --git a/gawkapi.c b/gawkapi.c
index 015a046..a4a46d9 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2012-2016 the Free Software Foundation, Inc.
+ * Copyright (C) 2012-2017 the Free Software Foundation, Inc.
  *
  * This file is part of GAWK, the GNU implementation of the
  * AWK Programming Language.
@@ -32,6 +32,7 @@ extern int currule;
 
 static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, 
awk_valtype_t wanted);
 static char *valtype2str(awk_valtype_t type);
+static NODE *ns_lookup(const char *name_space, const char *name, char 
**full_name);
 
 /*
  * api_get_argument --- get the count'th paramater, zero-based.
@@ -686,11 +687,15 @@ api_sym_lookup(awk_ext_id_t id,
 
        update_global_values();         /* make sure stuff like NF, NR, are up 
to date */
 
-       // FIXME, need to handle namespaces if name not null and not empty
        if (   name == NULL
            || *name == '\0'
            || result == NULL
-           || (node = lookup(name, false)) == NULL)
+           || ! is_valid_identifier(name)
+           || name_space == NULL
+           || (name_space[0] != '\0' && ! is_valid_identifier(name_space)))
+               return awk_false;
+
+       if ((node = ns_lookup(name_space, name, NULL)) == NULL)
                return awk_false;
 
        if (is_off_limits_var(name))    /* a built-in variable */
@@ -732,7 +737,10 @@ api_sym_update(awk_ext_id_t id,
 
        if (   name == NULL
            || *name == '\0'
-           || value == NULL)
+           || value == NULL
+           || ! is_valid_identifier(name)
+           || name_space == NULL
+           || (name_space[0] != '\0' && ! is_valid_identifier(name_space)))
                return awk_false;
 
        switch (value->val_type) {
@@ -751,23 +759,21 @@ api_sym_update(awk_ext_id_t id,
                return awk_false;
        }
 
-       // FIXME: Deal with namespaces
-       node = lookup(name, false);
+       char *full_name = NULL;
+       node = ns_lookup(name_space, name, & full_name);
 
        if (node == NULL) {
                /* new value to be installed */
                if (value->val_type == AWK_ARRAY) {
                        array_node = awk_value_to_node(value);
-                       node = install_symbol(estrdup((char *) name, 
strlen(name)),
-                                       Node_var_array);
+                       node = install_symbol(full_name, Node_var_array);
                        array_node->vname = node->vname;
                        *node = *array_node;
                        freenode(array_node);
                        value->array_cookie = node;     /* pass new cookie back 
to extension */
                } else {
                        /* regular variable */
-                       node = install_symbol(estrdup((char *) name, 
strlen(name)),
-                                       Node_var);
+                       node = install_symbol(full_name, Node_var);
                        node->var_value = awk_value_to_node(value);
                }
 
@@ -779,11 +785,14 @@ api_sym_update(awk_ext_id_t id,
         * OK except for AWK_ARRAY.
         */
        if (   (node->flags & NO_EXT_SET) != 0
-           || is_off_limits_var(name)) {       /* most built-in vars not 
allowed */
+           || is_off_limits_var(full_name)) {  /* most built-in vars not 
allowed */
                node->flags |= NO_EXT_SET;
+               efree((void *) full_name);
                return awk_false;
        }
 
+       efree((void *) full_name);
+
        if (    value->val_type != AWK_ARRAY
            && (node->type == Node_var || node->type == Node_var_new)) {
                unref(node->var_value);
@@ -1468,3 +1477,31 @@ valtype2str(awk_valtype_t type)
 
        return buf;
 }
+
+/* ns_lookup --- correctly build name before looking it up */
+
+static NODE *
+ns_lookup(const char *name_space, const char *name, char **fullname)
+{
+       assert(name_space != NULL);
+       assert(name != NULL);
+
+       if (name_space[0] == '\0' || strcmp(name_space, awk_namespace) == 0) {
+               if (fullname != NULL)
+                       *fullname = estrdup(name, strlen(name));
+               return lookup(name, false);
+       }
+
+       size_t len = strlen(name_space) + 2 + strlen(name) + 1;
+       char *buf;
+       emalloc(buf, char *, len, "ns_lookup");
+       sprintf(buf, "%s::%s", name_space, name);
+
+       NODE *f = lookup(buf, false);
+       if (fullname != NULL)
+               *fullname = buf;
+       else
+               efree((void *) buf);
+
+       return f;
+}
diff --git a/profile.c b/profile.c
index 82006f3..7687062 100644
--- a/profile.c
+++ b/profile.c
@@ -736,9 +736,10 @@ cleanup:
                case Op_indirect_func_call:
                case Op_func_call:
                {
-                       char *fname = pc->func_name;
                        char *pre;
                        int pcount;
+                       bool malloced = false;
+                       char *fname = adjust_namespace(pc->func_name, & 
malloced);
 
                        if (pc->opcode == Op_indirect_func_call)
                                pre = "@";
@@ -756,6 +757,8 @@ cleanup:
                                pp_free(t1);
                        }
                        pp_push(pc->opcode, str, CAN_FREE);
+                       if (malloced)
+                               efree((void *) fname);
                }
                        break;
 
diff --git a/test/testext.ok b/test/testext.ok
index 897a733..fbc3c26 100644
--- a/test/testext.ok
+++ b/test/testext.ok
@@ -86,6 +86,9 @@ message_string = hello, world
 new_array["hello"] = "world"
 new_array["answer"] = "42"
 
+test::testval = in namespace test
+test::test_function() called.
+
 at_exit2 called (should be first): data = NULL, exit_status = 0
 at_exit1 called (should be second): (data is & data_for_1), data value = 
0xdeadbeef, exit_status = 0
 at_exit0 called (should be third): data = NULL, exit_status = 0

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog           |  23 +++
 awk.h               |   1 +
 awkgram.c           | 153 +++++++++----------
 awkgram.y           |  49 +++---
 doc/ChangeLog       |   6 +
 doc/gawk.info       | 422 +++++++++++++++++++++++++++-------------------------
 doc/gawk.texi       |  44 +++---
 doc/gawktexi.in     |  44 +++---
 ext.c               |  16 +-
 extension/ChangeLog |   7 +
 extension/testext.c |  28 +++-
 gawkapi.c           |  59 ++++++--
 profile.c           |   5 +-
 test/testext.ok     |   3 +
 14 files changed, 494 insertions(+), 366 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]