gawk-diffs
[Top][All Lists]
Advanced

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

[gawk-diffs] [SCM] gawk branch, master, updated. gawk-4.1.0-3596-g663aff


From: Arnold Robbins
Subject: [gawk-diffs] [SCM] gawk branch, master, updated. gawk-4.1.0-3596-g663aff4
Date: Fri, 11 Jan 2019 08:15:22 -0500 (EST)

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, master has been updated
       via  663aff4ae012468c54d2e994e839d0e75210ef80 (commit)
      from  feebb01f31e29740b050da1531416c90a12352ca (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=663aff4ae012468c54d2e994e839d0e75210ef80

commit 663aff4ae012468c54d2e994e839d0e75210ef80
Author: Arnold D. Robbins <address@hidden>
Date:   Fri Jan 11 15:14:33 2019 +0200

    Squashed merge of feature/namespaces. Add code and doc.

diff --git a/ChangeLog b/ChangeLog
index 11b57fe..5f04e8a 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -80,6 +80,26 @@
        check for an empty array instead of comparing table_size to 0.
        * symbol.c (lookup, check_param_names): Ditto.
 
+2018-12-31         Arnold D. Robbins     <address@hidden>
+
+       Clean up namespace handling for the profiler.
+
+       * awkgram.y (make_pp_namespace): Remove function, not needed.
+       (set_namespace): Use estrdup to save the current namespace.
+       * main.c (main): Before dumping the program, set current_namespace
+       to awk_namespace.
+       * profile.c (pprint): Use "awk" for comparison, not "awk::".
+       (pp_namespace): Just print the name in the @namespace line.
+       (adjust_namespace): Adjust for the fact that namespaces no longer
+       have the trailing "::".
+
+2018-12-30         Arnold D. Robbins     <address@hidden>
+
+       * awk.h (check_qualified_name): Remove declaration.
+       * awkgram.y (check_qualified_special): Renamed from
+       check_qualified_name and made static.
+       * profile.c (pprint): Improve comment on namespace list.
+
 2018-12-21         Arnold D. Robbins     <address@hidden>
 
        * configure.ac: Remove -O only if .developing has 'debug' in it.
@@ -104,12 +124,41 @@
        * protos.h (timegm): Add timegm proto on systems lacking it.
        * replace.c (timegm): Include missing_d/timegm.c if needed.
 
+2018-12-12         Arnold D. Robbins     <address@hidden>
+
+       * NEWS: Updated some.
+
+2018-12-12         Arnold D. Robbins     <address@hidden>
+
+       * awk.h: Add new Op_K_namespace opcode for pretty printing.
+       * awkgram.y (namespace_chain): New variable, list of successive
+       @namespace directives seen, for the pretty printer.
+       (namespace_comment): Removed.
+       (set_namespace): Takes comment as second argument, builds the chain.
+       (mk_function, append_rule): Adjust to store the chain.
+       * debug.c (print_ns_list): New function.
+       (print_instruction): Adjust Op_rule and Op_func to use print_ns_list.
+       Add case for Op_K_namespace.
+       * eval.c (optable): Add entry for Op_K_namespace.
+       (opcode2str, op2str): Edit / add leading comments, respectively.
+       * profile.c (pp_namespace_list): New function.
+       (pprint): Adjust code to call pp_namespace_list.
+
 2018-12-06         Arnold D. Robbins     <address@hidden>
 
        * configure.ac: Add -ggdb3 to CFLAGS if developing and remove
        -O2 from Makefile, extension/Makefile, and support/Makefile.
        * config.guess, config.sub: Updated from GNULIB.
 
+2018-12-06         Arnold D. Robbins     <address@hidden>
+
+       * awkgram.y (namespace_comment): New variable.
+       (Grammar): Handle comments after @namespace statements.
+       (mk_function): Add any comment onto the saved namespace.
+       (append_rule): Ditto.
+       * profile.c (pp_namespace): Add second argument for a comment.
+       Adjust all calls.
+
 2018-12-02         Arnold D. Robbins     <address@hidden>
 
        * awkgram.y (mk_program): Add in leading and trailing comments
@@ -1092,6 +1141,69 @@
        * awk.h: Add DJGPP in #if for include of nonposix.h
        * nonposix.h (btowc, putwc): Add declarations for DJGPP.
 
+2017-07-26         Arnold D. Robbins     <address@hidden>
+
+       * awk.h (validate_qualified_name): Return type back to bool.
+       * awkgram.y (validate_qualified_name): Return type back to bool.
+       (lookup_builtin): Make allowances for `awk::' prefix on name.
+       * interpret.h (r_interpret): For indirect call, always pass true
+       for do_qualify argument of lookup.
+       * main.c (main): Make note of errors in -v values, use this
+       to exit failure if any happen.  Only change current_namespace
+       to 'awk::' if doing pretty printing.
+       (arg_assign): If validate_qualified name returns false, error out.
+
+2017-07-26         Arnold D. Robbins     <address@hidden>
+
+       * awkgram.y (set_namespace): Change return type void, adjust
+       all return statements.
+       address@hidden: Don't YYABORT on bad namespace so that we can check
+       the rest of the program.
+       (validate_qualified_name): Check traditional / posix first. Return
+       after printing an error message; we don't want to print multiple
+       messages for the same identifer.
+       * interpret.h (r_interpret): For indirect call, set do_qualify
+       parameter of lookup based on presence of a colon.
+
+2017-07-20         Arnold D. Robbins     <address@hidden>
+
+       Make qualified names work with -v and command-line assignments.
+
+       * awk.h (validate_qualified_name, check_qualified_name): Declare.
+       * awkgram.y (validate_qualified_name): No longer static.
+       (check_qualified_name): Ditto.
+       * main.c (arg_assign): Allow colons in identifiers. If not a
+       bad identifier, call validate_qualified_name and instead of
+       check_special use check_qualified_name.
+
+2017-07-17         Arnold D. Robbins     <address@hidden>
+
+       Allow identifiers that are gawk extensions to be used as plain
+       identifiers outside the "awk" namespace. Make the real
+       builtins available via awk::builtin_name(). Standard awk reserved
+       words and builtin functions remain reserved.
+
+       * awk.h (getfname): Add boolean parameter to prepend namespace
+       or not.
+       * awkgram.y (check_qualified_name): New function. Enforces that
+       standard awk reserved words and functions aren't allowed, and
+       allows awk::gawk_extension from non-"awk" namespace.
+       [direct_func_call]: Always convert name to fully qualified.
+       (getfname): Add boolean parameter to prepend namespace
+       or not. Adjust code.
+       (yylex): Separate out validation code from code building the
+       NAME token.  Use check_qualified_name to decide if token is
+       special instead of check_special.
+       (validate_qualified_name): Just checks the form of the fully
+       qualified name.
+       * debug.c (print_instruction): Update call to getfname.
+       * profile.c (pprint): Update call to getfname.
+
+2017-07-17         Arnold D. Robbins     <address@hidden>
+
+       * awkgram.y [direct_func_call]: Save full variable name for
+       indirect calls too.
+
 2017-07-17         Arnold D. Robbins     <address@hidden>
 
        * awkgram.y [non_post_simp_exp]: Merge LEX_BUILTIN and
@@ -1112,6 +1224,42 @@
 
        * re.c (research): Don't use dfa if need_start is true.
 
+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 against 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.
+
+       * awk.h (make_builtin): Add leading name_space parameter.
+       * ext.c (make_builtin): Add leading name_space parameter.
+       Do the appropriate checking and building of a name before
+       installing in the symbol table.
+       * gawkapi.c (add_ext_func): Use name_space, not namespace.
+       Check that the parameter isn't NULL.
+       (api_sym_lookup, api_sym_update): Use name_space, not namespace.
+       * gawkapi.h: Use name_space, not namespace, everywhere.
+
 2017-07-11         Arnold D. Robbins     <address@hidden>
 
        * awk.h (is_letter): Add declaration.
@@ -1138,6 +1286,17 @@
 
 2017-07-07         Arnold D. Robbins     <address@hidden>
 
+       * awkgram.y (yyerror): Produce better diagnostics for source
+       files that are not whole syntactic units.
+
+       * gawkapi.c (api_sym_lookup, api_sym_update): Add namespace parameter.
+       Currently unused.
+       * gawkapi.h (api_sym_lookup, api_sym_update): Add namespace parameter.
+       (api_sym_lookup_ns, api_sym_update_ns): New macros.
+       (api_sym_lookup, api_sym_update): Adjust macro bodies.
+
+2017-07-07         Arnold D. Robbins     <address@hidden>
+
        * gawapi.h: Bring descriptive comments up to date, minor edits.
        * io.c: Add some initial comments to functions where they were missing.
 
@@ -1145,6 +1304,57 @@
 
        * gawkapi.h, gawkapi.c: Typo fixes in comments.
 
+2017-07-01         Arnold D. Robbins     <address@hidden>
+
+       * symbol.c (install): Don't call fix_up_namespace if
+       installing parameters.
+       * profile.c (remove_namespace): Renamed to
+       (adjust_namespace): Make smarter and add boolean parameter for
+       if return was mallc'ed. Adjust calls.
+
+2017-06-30         Arnold D. Robbins     <address@hidden>
+
+       Add namespace info into Op_Rule and Op_Func.
+       Fix memory management problem.
+       The changes temporarily break the test suite.
+
+       * awk.h (MAX_INSTRUCTION_ALLOC): Increase to 4.
+       (Op_K_namespace): Remove, not needed.
+       * eval.c (optypetab): Remove Op_K_namespace.
+       * awkgram.y (make_pp_namespace): New function.
+       (yylex): For BEGIN etc, allocate 4 in the instruction.
+       (install_func): Save namespace name for Op_rule.
+       (append_rule): Save namespace name for Op_rule.
+       * debug.c (print_instruction): Print namespace for Op_rule, Op_func.
+       Remove Op_K_namespace.
+       * profile.c (pp_namespace, remove_namespace): New functions.
+       (pprint): Call `pp_namespace'. Use `remove_namespace' on variable
+       names.
+       (pp_func): Ditto on both.
+       * symbol.c (lookup): Initialize `malloced' to false.
+       (install): Ditto.
+
+       Unbreak the test suite:
+
+       * awk.h (namespace_changed): Declare new boolean variable.
+       * awkgram.y (namespace_changed): Define new boolean variable.
+       (set_namespace): Set it to true when the namespace is changed.
+       * main.c (main): Set current_namespace to "awk::" for the pretty
+       printer.
+       * profile.c (pp_namespace): If namespace_changed is false, return.
+
+2017-06-28         Arnold D. Robbins     <address@hidden>
+
+       * awk.h [ns_name]: Add macro in preparation for use.
+       * debug.c (print_instruction): Add case for Op_K_namespace.
+       Not really used yet.
+       * symbol.c (fix_up_namespace): Bug fix to always allocate
+       memory for a full name. Add boolean parameter to indicate
+       if memory was malloc'ed or not.
+       (lookup): Adjust call to fix_up_namespace and use make_str_node
+       if the string was malloced.
+       (install): Ditto.
+
 2017-06-26         Arnold D. Robbins     <address@hidden>
 
        * configure.ac: Turn a tab into a space in AC_DEFINE(SUPPLY_INTDIV).
@@ -1204,6 +1414,62 @@
        * config.guess, config.sub: Update to latest from GNULIB.
        * gettext.h: Pull in a few nice changes from GNULIB version.
 
+2017-06-16         Arnold D. Robbins     <address@hidden>
+
+       * awk.h (lookup): Add second parameter.
+       * array.c (assoc_list): Adjust call to lookup.
+       * awkgram.y (grammar, parms_shadow, install_function, variable):
+       Ditto.
+       * command.y [Grammar]: Ditto.
+       * debug.c (find_symbol): Ditto.
+       * ext.c (make_builtin): Ditto.
+       * gawkapi.c (api_sym_lookup, api_sym_update): Ditto.
+       * interpret.h (r_interpret): Ditto.
+       * main.c (arg_assign): Ditto.
+       (main): Reset current_namespace after parsing.
+       * symbol.c (lookup): New second parameter, do_qualify. Use it
+       to qualify names or not.
+       (install): Call fix_up_namespace.
+       (is_all_upper): New helper routine.
+       (fix_up_namespace): New function.
+
+2017-06-13         Arnold D. Robbins     <address@hidden>
+
+       * awk.h (awk_namespace, current_namespace): Move to const char.
+       (SRCFILE): Add namespace element.
+       * awkgram.y (awk_namespace, current_namespace): Move to const char.
+       (set_namespace): New function.
+       [Grammer]: Call it.
+       (tokentab): Add "namespace" entry.
+       (include_source): Push the current namespace.
+       (next_sourcefile): Pop the current namespace.
+       (yylex): Add lint warning if a reserved word is used as a namespace
+       name.
+       (validate_qualified_name): Make it an error to use a reserved
+       word as the second part of a fully qualified name.
+
+2017-06-11         Arnold D. Robbins     <address@hidden>
+
+       * awk.h (awk_namespace, current_namespace): Declare.
+       (opcodeval): Add Op_K_namespace.
+       * awkgram.y (awk_namespace, current_namespace): Define.
+       (LEX_NAMESPACE): Add lexing and parsing of address@hidden directive'.
+       (tokentab): Add "namespace" entry.
+       (yylex): Check if first part of qualified identifier is
+       a reserved word or function.
+       * eval.c (optypetab): Add Op_K_namespace.
+
+2017-06-06         Arnold D. Robbins     <address@hidden>
+
+       * awkgram.y (yylex): Allow :: in identifiers (the "NAME" token).
+       Use validate_qualified_name to check it.
+       (validate_qualified_name): New function.
+
+2017-05-30         Arnold D. Robbins     <address@hidden>
+
+       * awkgram.y (nextc): Force -e chunks to be syntactic units.
+       Needed for namespaces to work correctly.
+
 2017-05-30         Arnold D. Robbins     <address@hidden>
 
        * NEWS: Mention PROCINFO["argv"].
diff --git a/NEWS b/NEWS
index 25a5a6a..e5f34f8 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,13 @@ Changes from 4.2.x to 5.0.0
    from scratch. As a result, comments in many corner cases that were
    previously lost are now included in the formatted output.
 
+7. Namespaces have been implemented! See the manual.  One consequence of this
+   is that file included with -i, read with -f, and command line program
+   segments must all be self-contained syntactic units. E.g., you can no
+   longer do something like this:
+
+       gawk -e 'BEGIN {' -e 'print "hello" }'
+
 Changes from 4.2.1 to 4.2.2
 ---------------------------
 
diff --git a/TODO b/TODO
index 6bade17..b621ab6 100644
--- a/TODO
+++ b/TODO
@@ -88,21 +88,6 @@ Things To Think About That May Never Happen
        Try running with diehard. See http://www.diehard-software.org,
        https://github.com/emeryberger/DieHard
 
-       Implement namespaces.  Arnold suggested the following in an email:
-       - Extend the definition of an 'identifier' to include "." as a valid
-         character although an identifier can't start with it.
-       - Extension libraries install functions and global variables with names
-         that have a "." in them:  XML.parse(), XML.name, whatever.
-       - Awk code can read/write such variables and call such functions,
-         but they cannot define such functions
-        function XML.foo() { .. }      # error
-         or create a variable with such a name if it doesn't exist. This would
-         be a run-time error, not a parse-time error.
-       - This last rule may be too restrictive.
-       I don't want to get into fancy rules a la perl and file-scope visibility
-       etc, I'd like to keep things simple.  But how we design this is going
-       to be very important.
-
        Include a sample rpm spec file in a new packaging subdirectory.
        (Really needed?)
 
diff --git a/array.c b/array.c
index f2e64f6..34b7076 100644
--- a/array.c
+++ b/array.c
@@ -1317,7 +1317,7 @@ assoc_list(NODE *symbol, const char *sort_str, 
sort_context_t sort_ctxt)
                if (sp == sort_str || *sp != '\0')
                        fatal(_("`%s' is invalid as a function name"), 
sort_str);
 
-               f = lookup(sort_str);
+               f = lookup(sort_str, false);
                if (f == NULL || f->type != Node_func)
                        fatal(_("sort comparison function `%s' is not 
defined"), sort_str);
 
diff --git a/awk.h b/awk.h
index d6aaf6e..bac788b 100644
--- a/awk.h
+++ b/awk.h
@@ -669,6 +669,7 @@ typedef enum opcodeval {
        Op_K_getline_redir,
        Op_K_getline,
        Op_K_nextfile,
+       Op_K_namespace,
 
        Op_builtin,
        Op_sub_builtin,         /* sub, gsub and gensub */
@@ -921,6 +922,9 @@ typedef struct exp_instruction {
 #define condpair_left   d.di
 #define condpair_right  x.xi
 
+/* Op_Rule, Op_Func */
+#define ns_name                d.name
+
 /* Op_store_var */
 #define initval         x.xn
 
@@ -1017,11 +1021,12 @@ typedef struct srcfile {
        char *lexptr_begin;
        int lasttok;
        INSTRUCTION *comment;   /* comment on @load line */
+       const char *namespace;
 } SRCFILE;
 
 // structure for INSTRUCTION pool, needed mainly for debugger
 typedef struct instruction_pool {
-#define MAX_INSTRUCTION_ALLOC  3       // we don't call bcalloc with more than 
this
+#define MAX_INSTRUCTION_ALLOC  4       // we don't call bcalloc with more than 
this
        struct instruction_mem_pool {
                struct instruction_block *block_list;
                INSTRUCTION *free_space;        // free location in active block
@@ -1204,6 +1209,10 @@ extern char envsep;
 
 extern char casetable[];       /* for case-independent regexp matching */
 
+extern const char awk_namespace[];     /* "awk" */
+extern const char *current_namespace;
+extern bool namespace_changed;
+
 /* ------------------------- Runtime stack -------------------------------- */
 
 typedef union stack_item {
@@ -1396,7 +1405,7 @@ extern int parse_program(INSTRUCTION **pcode);
 extern void track_ext_func(const char *name);
 extern void dump_funcs(void);
 extern void dump_vars(const char *fname);
-extern const char *getfname(NODE *(*)(int));
+extern const char *getfname(NODE *(*)(int), bool prepend_awk);
 extern NODE *stopme(int nargs);
 extern void shadow_funcs(void);
 extern int check_special(const char *name);
@@ -1413,6 +1422,7 @@ extern bool is_alnum(int c);
 extern bool is_letter(int c);
 extern bool is_identchar(int c);
 extern NODE *make_regnode(int type, NODE *exp);
+extern bool validate_qualified_name(char *token);
 /* builtin.c */
 extern double double_to_int(double d);
 extern NODE *do_exp(int nargs);
@@ -1503,9 +1513,10 @@ extern NODE *do_ext(int nargs);
 void load_ext(const char *lib_name);   /* temporary */
 extern void close_extensions(void);
 #ifdef DYNAMIC
-extern awk_bool_t make_builtin(const awk_ext_func_t *);
+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
@@ -1701,7 +1712,7 @@ extern NODE *remove_symbol(NODE *r);
 extern void destroy_symbol(NODE *r);
 extern void release_symbols(NODE *symlist, int keep_globals);
 extern void append_symbol(NODE *r);
-extern NODE *lookup(const char *name);
+extern NODE *lookup(const char *name, bool do_qualify);
 extern NODE *make_params(char **pnames, int pcount);
 extern void install_params(NODE *func);
 extern void remove_params(NODE *func);
diff --git a/awkgram.c b/awkgram.c
index 993dfc4..aa86581 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -98,13 +98,16 @@ static void dumpintlstr(const char *str, size_t len);
 static void dumpintlstr2(const char *str1, size_t len1, const char *str2, 
size_t len2);
 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 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 INSTRUCTION *trailing_comment;
 static INSTRUCTION *outer_comment;
 static INSTRUCTION *interblock_comment;
 static INSTRUCTION *pending_comment;
+static INSTRUCTION *namespace_chain;
 
 #ifdef DEBUG_COMMENTS
 static void
@@ -202,6 +205,10 @@ extern INSTRUCTION *rule_list;
 extern int max_args;
 extern NODE **args_array;
 
+const char awk_namespace[] = "awk";
+const char *current_namespace = awk_namespace;
+bool namespace_changed = false;
+
 static INSTRUCTION *rule_block[sizeof(ruletab)];
 
 static INSTRUCTION *ip_rec;
@@ -221,7 +228,7 @@ extern double fmod(double x, double y);
 
 #define YYSTYPE INSTRUCTION *
 
-#line 225 "awkgram.c" /* yacc.c:338  */
+#line 232 "awkgram.c" /* yacc.c:338  */
 # ifndef YY_NULLPTR
 #  if defined __cplusplus
 #   if 201103L <= __cplusplus
@@ -305,9 +312,10 @@ extern int yydebug;
     LEX_INCLUDE = 304,
     LEX_EVAL = 305,
     LEX_LOAD = 306,
-    NEWLINE = 307,
-    SLASH_BEFORE_EQUAL = 308,
-    UNARY = 309
+    LEX_NAMESPACE = 307,
+    NEWLINE = 308,
+    SLASH_BEFORE_EQUAL = 309,
+    UNARY = 310
   };
 #endif
 /* Tokens.  */
@@ -360,9 +368,10 @@ extern int yydebug;
 #define LEX_INCLUDE 304
 #define LEX_EVAL 305
 #define LEX_LOAD 306
-#define NEWLINE 307
-#define SLASH_BEFORE_EQUAL 308
-#define UNARY 309
+#define LEX_NAMESPACE 307
+#define NEWLINE 308
+#define SLASH_BEFORE_EQUAL 309
+#define UNARY 310
 
 /* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@@ -611,21 +620,21 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   1209
+#define YYLAST   1191
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  76
+#define YYNTOKENS  77
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  70
+#define YYNNTS  71
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  203
+#define YYNRULES  207
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  349
+#define YYNSTATES  355
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   309
+#define YYMAXUTOK   310
 
 #define YYTRANSLATE(YYX)                                                \
   ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -637,16 +646,16 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    64,     2,     2,    67,    63,     2,     2,
-      68,    69,    61,    59,    56,    60,     2,    62,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    55,    75,
-      57,     2,    58,    54,    70,     2,     2,     2,     2,     2,
+       2,     2,     2,    65,     2,     2,    68,    64,     2,     2,
+      69,    70,    62,    60,    57,    61,     2,    63,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    56,    76,
+      58,     2,    59,    55,    71,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    71,     2,    72,    66,     2,     2,     2,     2,     2,
+       2,    72,     2,    73,    67,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    73,     2,    74,     2,     2,     2,     2,
+       2,     2,     2,    74,     2,    75,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -664,34 +673,35 @@ static const yytype_uint8 yytranslate[] =
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
       35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    65
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      66
 };
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   223,   223,   224,   229,   239,   243,   255,   263,   277,
-     288,   298,   311,   321,   323,   328,   338,   340,   346,   350,
-     355,   385,   397,   409,   415,   424,   442,   444,   446,   452,
-     460,   461,   465,   465,   499,   498,   532,   547,   549,   554,
-     555,   575,   580,   581,   585,   596,   601,   608,   716,   767,
-     817,   943,   964,   985,   995,  1005,  1015,  1026,  1039,  1057,
-    1056,  1070,  1088,  1088,  1186,  1186,  1219,  1249,  1257,  1258,
-    1264,  1265,  1272,  1277,  1290,  1305,  1307,  1315,  1322,  1324,
-    1332,  1341,  1343,  1352,  1353,  1361,  1366,  1366,  1379,  1385,
-    1397,  1401,  1423,  1424,  1430,  1431,  1440,  1441,  1446,  1451,
-    1468,  1470,  1472,  1479,  1480,  1486,  1487,  1492,  1494,  1501,
-    1503,  1511,  1516,  1527,  1528,  1533,  1535,  1542,  1544,  1552,
-    1557,  1567,  1568,  1573,  1580,  1584,  1586,  1588,  1601,  1618,
-    1628,  1635,  1637,  1642,  1644,  1646,  1654,  1656,  1661,  1663,
-    1668,  1670,  1672,  1729,  1731,  1733,  1735,  1737,  1739,  1741,
-    1743,  1757,  1762,  1767,  1792,  1798,  1800,  1802,  1804,  1806,
-    1808,  1813,  1817,  1849,  1857,  1863,  1869,  1882,  1883,  1884,
-    1889,  1894,  1898,  1902,  1917,  1938,  1943,  1980,  2009,  2010,
-    2016,  2017,  2022,  2024,  2031,  2048,  2065,  2067,  2074,  2079,
-    2087,  2097,  2109,  2118,  2122,  2127,  2131,  2135,  2139,  2144,
-    2145,  2149,  2153,  2157
+       0,   230,   230,   231,   236,   246,   250,   262,   270,   284,
+     295,   305,   315,   328,   338,   340,   345,   355,   357,   362,
+     364,   366,   372,   376,   381,   411,   423,   435,   441,   450,
+     468,   470,   472,   478,   486,   487,   491,   491,   525,   524,
+     558,   573,   575,   580,   581,   601,   606,   607,   611,   622,
+     627,   634,   742,   793,   843,   969,   990,  1011,  1021,  1031,
+    1041,  1052,  1065,  1083,  1082,  1096,  1114,  1114,  1212,  1212,
+    1245,  1275,  1283,  1284,  1290,  1291,  1298,  1303,  1316,  1331,
+    1333,  1341,  1348,  1350,  1358,  1367,  1369,  1378,  1379,  1387,
+    1392,  1392,  1405,  1411,  1423,  1427,  1449,  1450,  1456,  1457,
+    1466,  1467,  1472,  1477,  1494,  1496,  1498,  1505,  1506,  1512,
+    1513,  1518,  1520,  1527,  1529,  1537,  1542,  1553,  1554,  1559,
+    1561,  1568,  1570,  1578,  1583,  1593,  1594,  1599,  1606,  1610,
+    1612,  1614,  1627,  1644,  1654,  1661,  1663,  1668,  1670,  1672,
+    1680,  1682,  1687,  1689,  1694,  1696,  1698,  1755,  1757,  1759,
+    1761,  1763,  1765,  1767,  1769,  1783,  1788,  1793,  1818,  1824,
+    1826,  1828,  1830,  1832,  1834,  1839,  1843,  1875,  1883,  1889,
+    1895,  1908,  1909,  1910,  1915,  1920,  1924,  1928,  1943,  1964,
+    1969,  2006,  2048,  2049,  2055,  2056,  2061,  2063,  2070,  2087,
+    2104,  2106,  2113,  2118,  2126,  2136,  2148,  2157,  2161,  2166,
+    2170,  2174,  2178,  2183,  2184,  2188,  2192,  2196
 };
 #endif
 
@@ -709,17 +719,18 @@ static const char *const yytname[] =
   "LEX_NEXT", "LEX_EXIT", "LEX_FUNCTION", "LEX_BEGINFILE", "LEX_ENDFILE",
   "LEX_GETLINE", "LEX_NEXTFILE", "LEX_IN", "LEX_AND", "LEX_OR",
   "INCREMENT", "DECREMENT", "LEX_BUILTIN", "LEX_LENGTH", "LEX_EOF",
-  "LEX_INCLUDE", "LEX_EVAL", "LEX_LOAD", "NEWLINE", "SLASH_BEFORE_EQUAL",
-  "'?'", "':'", "','", "'<'", "'>'", "'+'", "'-'", "'*'", "'/'", "'%'",
-  "'!'", "UNARY", "'^'", "'$'", "'('", "')'", "'@'", "'['", "']'", "'{'",
-  "'}'", "';'", "$accept", "program", "rule", "source", "library",
-  "pattern", "action", "func_name", "lex_builtin", "function_prologue",
-  "address@hidden", "regexp", "address@hidden", "typed_regexp", "a_slash", 
"statements",
-  "statement_term", "statement", "non_compound_stmt", "address@hidden", 
"simple_stmt",
-  "address@hidden", "address@hidden", "opt_simple_stmt", "case_statements", 
"case_statement",
-  "case_value", "print", "print_expression_list", "output_redir", 
"address@hidden",
-  "if_statement", "nls", "opt_nls", "input_redir", "opt_param_list",
-  "param_list", "opt_exp", "opt_expression_list", "expression_list",
+  "LEX_INCLUDE", "LEX_EVAL", "LEX_LOAD", "LEX_NAMESPACE", "NEWLINE",
+  "SLASH_BEFORE_EQUAL", "'?'", "':'", "','", "'<'", "'>'", "'+'", "'-'",
+  "'*'", "'/'", "'%'", "'!'", "UNARY", "'^'", "'$'", "'('", "')'", "'@'",
+  "'['", "']'", "'{'", "'}'", "';'", "$accept", "program", "rule",
+  "source", "library", "namespace", "pattern", "action", "func_name",
+  "lex_builtin", "function_prologue", "address@hidden", "regexp", 
"address@hidden",
+  "typed_regexp", "a_slash", "statements", "statement_term", "statement",
+  "non_compound_stmt", "address@hidden", "simple_stmt", "address@hidden", 
"address@hidden",
+  "opt_simple_stmt", "case_statements", "case_statement", "case_value",
+  "print", "print_expression_list", "output_redir", "address@hidden", 
"if_statement",
+  "nls", "opt_nls", "input_redir", "opt_param_list", "param_list",
+  "opt_exp", "opt_expression_list", "expression_list",
   "opt_fcall_expression_list", "fcall_expression_list", "fcall_exp", "exp",
   "assign_operator", "relop_or_less", "a_relop", "common_exp", "simp_exp",
   "simp_exp_nc", "non_post_simp_exp", "func_call", "direct_func_call",
@@ -740,61 +751,62 @@ static const yytype_uint16 yytoknum[] =
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
      295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
-     305,   306,   307,   308,    63,    58,    44,    60,    62,    43,
-      45,    42,    47,    37,    33,   309,    94,    36,    40,    41,
-      64,    91,    93,   123,   125,    59
+     305,   306,   307,   308,   309,    63,    58,    44,    60,    62,
+      43,    45,    42,    47,    37,    33,   310,    94,    36,    40,
+      41,    64,    91,    93,   123,   125,    59
 };
 # endif
 
-#define YYPACT_NINF -277
+#define YYPACT_NINF -283
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-277)))
+  (!!((Yystate) == (-283)))
 
-#define YYTABLE_NINF -115
+#define YYTABLE_NINF -119
 
 #define yytable_value_is_error(Yytable_value) \
-  (!!((Yytable_value) == (-115)))
+  (!!((Yytable_value) == (-119)))
 
   /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
      STATE-NUM.  */
 static const yytype_int16 yypact[] =
 {
-    -277,   349,  -277,  -277,   -34,   -17,  -277,  -277,  -277,  -277,
-     166,  -277,  -277,    62,    62,    62,    -7,    -4,  -277,  -277,
-    -277,  1112,  1112,  -277,  1112,  1139,   842,    26,  -277,   -24,
-      -6,  -277,  -277,    87,   857,  1038,   344,   372,  -277,  -277,
-    -277,  -277,   233,   768,   842,  -277,     0,  -277,  -277,  -277,
-    -277,  -277,    84,    78,  -277,    99,  -277,  -277,  -277,   768,
-     768,   157,   105,   106,   105,   105,  1112,   113,  -277,  -277,
-     108,   320,    44,    47,  -277,   120,  -277,  -277,  -277,    87,
-    -277,   120,  -277,   171,  -277,  -277,  1065,   178,  1112,  1112,
-    1112,   120,  -277,  -277,  -277,  1112,  1112,   146,   344,  1112,
-    1112,  1112,  1112,  1112,  1112,  1112,  1112,  1112,  1112,  1112,
-    1112,  -277,   177,  -277,  -277,   173,  1112,  -277,  -277,  -277,
-     128,   109,  -277,  1080,    20,  1080,  -277,  -277,  -277,  -277,
-    1112,  -277,   128,   128,   320,  -277,  -277,  -277,  1112,  -277,
-     160,   889,  -277,  -277,     3,    18,  -277,    39,    18,    87,
-    -277,   572,  -277,  -277,  -277,    25,  -277,    16,   618,  1021,
-    -277,   126,  1080,    62,    82,    82,   105,   105,   105,   105,
-      82,    82,   105,   105,   105,   105,  -277,  -277,  1080,  -277,
-    1065,   815,  -277,    43,   344,  -277,  -277,  1080,   178,  -277,
-    1080,  -277,  -277,  -277,  -277,  -277,   134,  -277,    12,   136,
-     137,   120,   140,    18,    18,  -277,  -277,    18,  1112,    18,
-     120,  -277,  -277,    18,  -277,  -277,  1080,  -277,   150,   120,
-    1112,  -277,  -277,  -277,  -277,  -277,  -277,   128,   112,  -277,
-    1112,  1112,  -277,   223,  1112,  1112,   688,   922,  -277,  -277,
-    -277,    18,  1080,  -277,  -277,  -277,   619,   572,   120,  -277,
-    -277,  1080,   120,  -277,    59,   320,    18,   -17,   169,   320,
-     320,   208,    -9,  -277,   150,  -277,   842,   240,  -277,   198,
-    -277,  -277,  -277,  -277,  -277,   120,  -277,  -277,     1,  -277,
-    -277,  -277,   120,   120,   176,   178,   120,   108,  -277,  -277,
-     688,  -277,  -277,    -6,   688,  1112,   128,   735,   160,  1112,
-     231,  -277,  -277,   320,   120,   285,   120,  1038,   120,   148,
-     120,   688,   120,   970,   688,  -277,   311,   200,  -277,   182,
-    -277,  -277,   970,   128,  -277,  -277,  -277,   251,   253,  -277,
-    -277,   200,  -277,   120,  -277,   128,   120,  -277,  -277,   120,
-    -277,   120,   688,  -277,   422,   688,  -277,   497,  -277
+    -283,   316,  -283,  -283,   -45,   -28,  -283,  -283,  -283,  -283,
+     160,  -283,  -283,    23,    23,    23,   -39,   -18,  -283,  -283,
+    -283,  1047,  1047,  -283,  1047,  1075,   818,   257,  -283,    99,
+     -20,  -283,  -283,    11,  1017,   974,   378,   415,  -283,  -283,
+    -283,  -283,   329,   742,   818,  -283,     0,  -283,  -283,  -283,
+    -283,  -283,    25,     9,  -283,    22,  -283,  -283,  -283,   742,
+     742,    79,    46,    18,    46,    46,  1047,   114,  -283,  -283,
+      13,   286,    44,    47,    60,  -283,    94,  -283,  -283,  -283,
+      11,  -283,    94,  -283,   151,  -283,  -283,  1002,   162,  1047,
+    1047,  1047,    94,  -283,  -283,  -283,  1047,  1047,   132,   378,
+    1047,  1047,  1047,  1047,  1047,  1047,  1047,  1047,  1047,  1047,
+    1047,  1047,  -283,   170,  -283,  -283,   168,  1047,  -283,  -283,
+    -283,   116,    14,  -283,  1132,    76,  1132,  -283,  -283,  -283,
+    -283,  1047,  -283,   116,   116,   286,  -283,  -283,  -283,  1047,
+    -283,   144,   846,  -283,  -283,    34,    91,  -283,    39,    91,
+    -283,    59,    91,    11,  -283,   542,  -283,  -283,  -283,   145,
+    -283,   135,   580,  1113,  -283,   189,  1132,    23,   230,   230,
+      46,    46,    46,    46,   230,   230,    46,    46,    46,    46,
+    -283,  -283,  1132,  -283,  1002,   770,  -283,    27,   378,  -283,
+    -283,  1132,   162,  -283,  1132,  -283,  -283,  -283,  -283,  -283,
+    -283,  -283,   119,  -283,    12,   123,   126,    94,   128,    91,
+      91,  -283,  -283,    91,  1047,    91,    94,  -283,  -283,    91,
+    -283,  -283,  1132,  -283,   122,    94,  1047,  -283,  -283,  -283,
+    -283,  -283,  -283,   116,    73,  -283,  1047,  1047,  -283,   198,
+    1047,  1047,   660,   895,  -283,  -283,  -283,    91,  1132,  -283,
+    -283,  -283,   590,   542,    94,  -283,  -283,  1132,    94,  -283,
+      28,   286,    91,   -28,   141,   286,   286,   190,   -23,  -283,
+     122,  -283,   818,   205,  -283,   325,  -283,  -283,  -283,  -283,
+    -283,    94,  -283,  -283,   115,  -283,  -283,  -283,    94,    94,
+     153,   162,    94,    13,  -283,  -283,   660,  -283,  -283,   -20,
+     660,  1047,   116,   694,   144,  1047,   209,  -283,  -283,   286,
+      94,  1090,    94,   974,    94,   152,    94,   660,    94,   929,
+     660,  -283,   342,   176,  -283,   158,  -283,  -283,   929,   116,
+    -283,  -283,  -283,   236,   243,  -283,  -283,   176,  -283,    94,
+    -283,   116,    94,  -283,  -283,    94,  -283,    94,   660,  -283,
+     390,   660,  -283,   466,  -283
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -802,65 +814,68 @@ static const yytype_int16 yypact[] =
      means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     0,     1,     6,     0,   189,   171,   172,    21,    22,
-       0,    23,    24,   178,     0,     0,     0,   166,     5,    90,
-      38,     0,     0,    37,     0,     0,     0,     0,     3,     0,
-       0,   161,    34,     4,    19,   132,   140,   141,   143,   167,
-     175,   191,   168,     0,     0,   186,     0,   190,    27,    26,
-      30,    31,     0,     0,    28,    94,   179,   169,   170,     0,
-       0,     0,   174,   168,   173,   162,     0,   195,   168,   109,
-       0,   107,     0,     0,   176,    92,   201,     7,     8,    42,
-      39,    92,     9,     0,    91,   136,     0,     0,     0,     0,
-       0,    92,   137,   139,   138,     0,     0,     0,   142,     0,
+       2,     0,     1,     6,     0,   193,   175,   176,    25,    26,
+       0,    27,    28,   182,     0,     0,     0,   170,     5,    94,
+      42,     0,     0,    41,     0,     0,     0,     0,     3,     0,
+       0,   165,    38,     4,    23,   136,   144,   145,   147,   171,
+     179,   195,   172,     0,     0,   190,     0,   194,    31,    30,
+      34,    35,     0,     0,    32,    98,   183,   173,   174,     0,
+       0,     0,   178,   172,   177,   166,     0,   199,   172,   113,
+       0,   111,     0,     0,     0,   180,    96,   205,     7,     8,
+      46,    43,    96,     9,     0,    95,   140,     0,     0,     0,
+       0,     0,    96,   141,   143,   142,     0,     0,     0,   146,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   134,   133,   151,   152,     0,     0,   117,    36,   122,
-       0,     0,   115,   121,     0,   107,   188,   187,    29,    32,
-       0,   150,     0,     0,     0,   193,   194,   192,   110,   198,
-       0,     0,   163,    14,     0,     0,    17,     0,     0,    93,
-     196,     0,    43,    35,   127,   128,   129,   125,   126,     0,
-     203,   130,    20,   178,   148,   149,   145,   146,   147,   144,
-     159,   160,   156,   157,   158,   155,   124,   135,   123,   177,
-     118,     0,   185,     0,    95,   164,   165,   111,     0,   112,
-     108,    13,    10,    16,    11,    41,     0,    59,     0,     0,
-       0,    92,     0,     0,     0,    81,    82,     0,   103,     0,
-      92,    40,    53,     0,    62,    46,    67,    39,   199,    92,
-       0,   154,   119,   120,   116,   100,    98,     0,     0,   153,
-       0,   103,    64,     0,     0,     0,     0,    68,    54,    55,
-      56,     0,   104,    57,   197,    61,     0,     0,    92,   200,
-      44,   131,    92,   101,     0,     0,     0,   180,     0,     0,
-       0,     0,   189,    69,     0,    58,     0,    85,    83,     0,
-      45,    25,    33,   102,    99,    92,    60,    65,     0,   182,
-     184,    66,    92,    92,     0,     0,    92,     0,    86,    63,
-       0,   181,   183,     0,     0,     0,     0,     0,    84,     0,
-      88,    70,    48,     0,    92,     0,    92,    87,    92,     0,
-      92,     0,    92,    68,     0,    72,     0,     0,    71,     0,
-      49,    50,    68,     0,    89,    75,    78,     0,     0,    79,
-      80,     0,   202,    92,    47,     0,    92,    77,    76,    92,
-      39,    92,     0,    39,     0,     0,    52,     0,    51
+       0,     0,   138,   137,   155,   156,     0,     0,   121,    40,
+     126,     0,     0,   119,   125,     0,   111,   192,   191,    33,
+      36,     0,   154,     0,     0,     0,   197,   198,   196,   114,
+     202,     0,     0,   167,    15,     0,     0,    18,     0,     0,
+      21,     0,     0,    97,   200,     0,    47,    39,   131,   132,
+     133,   129,   130,     0,   207,   134,    24,   182,   152,   153,
+     149,   150,   151,   148,   163,   164,   160,   161,   162,   159,
+     128,   139,   127,   181,   122,     0,   189,     0,    99,   168,
+     169,   115,     0,   116,   112,    14,    10,    17,    11,    20,
+      12,    45,     0,    63,     0,     0,     0,    96,     0,     0,
+       0,    85,    86,     0,   107,     0,    96,    44,    57,     0,
+      66,    50,    71,    43,   203,    96,     0,   158,   123,   124,
+     120,   104,   102,     0,     0,   157,     0,   107,    68,     0,
+       0,     0,     0,    72,    58,    59,    60,     0,   108,    61,
+     201,    65,     0,     0,    96,   204,    48,   135,    96,   105,
+       0,     0,     0,   184,     0,     0,     0,     0,   193,    73,
+       0,    62,     0,    89,    87,     0,    49,    29,    37,   106,
+     103,    96,    64,    69,     0,   186,   188,    70,    96,    96,
+       0,     0,    96,     0,    90,    67,     0,   185,   187,     0,
+       0,     0,     0,     0,    88,     0,    92,    74,    52,     0,
+      96,     0,    96,    91,    96,     0,    96,     0,    96,    72,
+       0,    76,     0,     0,    75,     0,    53,    54,    72,     0,
+      93,    79,    82,     0,     0,    83,    84,     0,   206,    96,
+      51,     0,    96,    81,    80,    96,    43,    96,     0,    43,
+       0,     0,    56,     0,    55
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -277,  -277,  -277,  -277,  -277,  -277,   232,  -277,  -277,  -277,
-    -277,   -55,  -277,   -85,  -277,  -208,    95,  -152,  -277,  -277,
-    -232,  -277,  -277,  -276,  -277,  -277,  -277,  -277,  -277,  -277,
-    -277,  -277,     7,     5,  -277,  -277,  -277,    33,  -277,   -29,
-      94,  -277,   -14,    -1,  -277,  -277,  -277,   -31,    17,  -277,
-     244,  -277,   114,   107,  -277,  -277,    -3,   -36,  -277,  -277,
-     -57,    -2,  -277,   -27,  -240,   -64,  -277,   -15,   -59,   -10
+    -283,  -283,  -283,  -283,  -283,  -283,  -283,   226,  -283,  -283,
+    -283,  -283,   -63,  -283,   -77,  -283,  -215,   -73,   -30,  -283,
+    -283,  -234,  -283,  -283,  -282,  -283,  -283,  -283,  -283,  -283,
+    -283,  -283,  -283,     5,   -35,  -283,  -283,  -283,    24,  -283,
+     -43,   101,  -283,   -15,    -1,  -283,  -283,  -283,   -40,    17,
+    -283,   237,  -283,    -6,    96,  -283,  -283,   -16,   -42,  -283,
+    -283,   -81,    -2,  -283,   -27,  -186,   -65,  -283,   -62,   -68,
+      -8
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,    28,   145,   148,    29,    77,    53,    54,    30,
-     183,    31,    83,   119,    32,   151,    78,   211,   212,   231,
-     213,   246,   257,   264,   309,   318,   331,   214,   267,   289,
-     299,   215,   149,   150,   131,   227,   228,   241,   268,    70,
-     120,   121,   122,   216,   116,    94,    95,    35,    36,    37,
-      38,    39,    40,    55,   277,   278,   279,    45,    46,    47,
-      41,    42,   137,   217,   218,   142,   248,   219,   333,   141
+      -1,     1,    28,   146,   149,   152,    29,    78,    53,    54,
+      30,   187,    31,    84,   120,    32,   155,    79,   217,   218,
+     237,   219,   252,   263,   270,   315,   324,   337,   220,   273,
+     295,   305,   221,   153,   154,   132,   233,   234,   247,   274,
+      70,   121,   122,   123,   222,   117,    95,    96,    35,    36,
+      37,    38,    39,    40,    55,   283,   284,   285,    45,    46,
+      47,    41,    42,   138,   223,   224,   143,   254,    82,   339,
+     142
 };
 
   /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
@@ -868,345 +883,344 @@ static const yytype_int16 yydefgoto[] =
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_int16 yytable[] =
 {
-      34,   154,    80,    80,   191,   263,   140,   270,    33,   247,
-     127,    56,    57,    58,    81,   124,   232,   126,   291,    63,
-      63,   138,    63,    68,    96,    71,    85,   176,    19,     4,
-     156,    86,   285,    63,    43,    85,    79,   323,    62,    64,
-     193,    65,   123,   125,   225,   143,   335,   226,   146,    75,
-     144,    76,    98,   147,    44,   -12,   179,    87,   123,   123,
-     273,    59,    44,   274,    60,   134,     5,    75,   185,   186,
-      19,    44,    44,    92,    93,    72,    91,    73,   -12,   334,
-     233,   263,    92,    93,   261,   155,   152,   157,   158,   159,
-     263,   -15,   182,    76,   161,   162,   160,    63,    63,    63,
-      63,    63,    63,    63,    63,    63,    63,    63,    63,   138,
-     180,   181,   -96,   253,   -15,   178,   164,   165,   166,   167,
-     168,   169,   170,   171,   172,   173,   174,   175,    63,    25,
-      81,   229,   344,    81,   128,   347,  -115,   187,   300,    84,
-     190,    74,   302,   101,   102,   103,   129,   184,   104,   315,
-     113,   114,    79,   132,   133,    79,   130,   135,   136,   321,
-       4,    56,   324,   252,    91,    91,   222,   224,    91,    48,
-      49,   104,    19,   316,   317,    74,   153,   139,  -114,   123,
-     123,   -97,     5,  -115,  -115,   163,   118,   177,    81,    81,
-     346,   275,    81,   348,    81,   282,   283,   139,    81,   138,
-      19,   188,   230,   249,   234,   235,   236,   242,   237,  -106,
-      79,    79,    50,    51,    79,   244,    79,   269,   254,   251,
-      79,   280,   -92,   298,   250,    76,    81,   258,   296,   255,
-     242,   330,   304,   259,   260,   284,    52,   287,   281,   310,
-     192,    81,   280,   194,   295,   125,   111,   112,    79,   286,
-    -106,   288,   308,   271,    91,   332,   210,   272,   337,   336,
-     338,   329,    82,    79,   256,    71,   301,  -106,   307,    67,
-     221,   341,   339,  -106,     0,   292,     0,   113,   114,     0,
-     290,     0,   306,     0,     0,     0,   115,   293,   294,     0,
-     312,   297,     0,     0,   303,    85,   305,    63,   238,   239,
-      86,     0,   240,     0,   243,    63,     0,     0,   245,   311,
-       0,   313,     0,   314,   319,   320,     0,   322,   325,   326,
-     118,     0,     0,     0,    98,     0,    87,    88,    89,     0,
-      85,     0,     0,     0,     0,    86,   265,     0,   340,    90,
-       0,   342,    92,    93,   343,     0,   345,     0,     0,     2,
-       3,   276,     4,     5,     0,     0,     6,     7,     0,     0,
-      76,    87,    88,    89,    20,     0,     0,     8,     9,     0,
-     327,   328,     0,    23,    90,     0,     0,    92,    93,     0,
-       0,     0,     0,     0,     0,    10,    11,    12,    13,   139,
-       0,     0,     0,    14,    15,    16,    17,    18,     0,     0,
-       0,    19,    20,    99,   100,   101,   102,   103,    21,    22,
-     104,    23,     0,    24,     0,     0,    25,    26,     0,    27,
-       0,     0,   -18,   195,   -18,     4,     5,     0,     0,     6,
-       7,   105,   106,   107,   108,   109,     0,     0,   110,     0,
-       0,     0,   196,     0,   197,   198,   199,   -74,   -74,   200,
-     201,   202,   203,   204,   205,   206,   207,   208,     0,     0,
-       0,    13,   209,     0,     0,     0,    14,    15,    16,    17,
-       0,     0,     0,     0,   -74,    20,     0,     0,     0,     0,
-       0,    21,    22,     0,    23,     0,    24,     0,     0,    25,
-      26,     0,    61,     0,     0,    75,   -74,    76,   195,     0,
-       4,     5,     0,     0,     6,     7,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   196,     0,   197,
-     198,   199,   -73,   -73,   200,   201,   202,   203,   204,   205,
-     206,   207,   208,     0,     0,     0,    13,   209,     0,     0,
-       0,    14,    15,    16,    17,     0,     0,     0,     0,   -73,
+      34,   125,    81,    81,   128,   141,    33,   160,   253,   269,
+     158,    56,    57,    58,   139,   184,   238,   127,   291,    63,
+      63,    75,    63,    68,    43,    71,    97,     5,   231,   279,
+      59,   232,   280,    63,    80,   195,   180,   329,    62,    64,
+     197,    65,   124,   126,    44,   144,   341,   156,   147,    44,
+     145,    60,    99,   148,    76,    75,   183,   164,   124,   124,
+     199,   150,   114,   115,    85,   135,   151,   276,   189,   190,
+      92,    92,    44,   196,   259,   129,   198,   139,   130,   200,
+     131,   239,     4,   140,  -118,   269,   159,   -13,   161,   162,
+     163,    25,   -16,   225,   269,   165,   166,  -100,    63,    63,
+      63,    63,    63,    63,    63,    63,    63,    63,    63,    63,
+     -13,   235,   -19,   105,   185,   -16,   182,   168,   169,   170,
+     171,   172,   173,   174,   175,   176,   177,   178,   179,    63,
+      92,   350,   297,    92,   353,   -19,   244,   245,   191,   340,
+     246,   194,   249,  -101,    19,    86,   251,    19,   188,   186,
+      87,    80,    19,   321,    80,    86,   157,    80,   136,   137,
+     133,   134,   255,    48,    49,    56,     5,    77,   258,   228,
+     230,   167,   242,    76,   271,    77,    88,   322,   323,   119,
+     225,   250,   181,   124,   124,   192,   140,    44,   236,   282,
+     256,   225,   240,    93,    94,   241,   281,   243,    77,  -119,
+     288,   289,   264,    93,    94,    19,    50,    51,   292,   275,
+     302,   287,   267,   248,    80,    80,   294,   290,    80,   277,
+      80,   286,   301,   278,    80,   257,   260,   -96,   304,   293,
+     314,    52,   338,   216,   225,   261,   248,   310,   225,   265,
+     266,   312,   286,   343,   316,   336,   296,  -119,  -119,   318,
+     344,   126,    80,   299,   300,   225,    83,   303,   225,   335,
+       4,   262,    67,   227,   342,   313,   306,    80,   298,   345,
+     308,    71,   307,     0,     0,   317,   347,   319,     0,   320,
+     325,   326,     0,   328,     0,     0,   225,   327,   225,   225,
+     330,   225,   102,   103,   104,     0,    86,   105,     0,     0,
+     309,    87,   311,    63,   346,     0,    72,   348,    73,    74,
+     349,    63,   351,     0,     0,     0,     2,     3,   352,     4,
+       5,   354,     0,     6,     7,     0,   139,    88,    89,    90,
+      99,     0,     0,     0,     8,     9,  -110,     0,     0,     0,
+       0,    91,   112,   113,    93,    94,     0,     0,     0,   331,
+     332,   119,    10,    11,    12,    13,   140,     0,     0,     0,
+      14,    15,    16,    17,    18,     0,     0,     0,     0,    19,
+      20,     0,     0,   114,   115,     0,    21,    22,  -110,    23,
+       0,    24,    92,   116,    25,    26,     0,    27,     0,     0,
+     -22,   201,   -22,     4,     5,  -110,    20,     6,     7,     0,
+       0,  -110,   333,   334,     0,    23,     0,     0,     0,     0,
+     202,     0,   203,   204,   205,   -78,   -78,   206,   207,   208,
+     209,   210,   211,   212,   213,   214,     0,     0,     0,    13,
+     215,     0,     0,     0,    14,    15,    16,    17,   100,   101,
+     102,   103,   104,   -78,    20,   105,     0,     0,     0,     0,
+      21,    22,     0,    23,     0,    24,     0,     0,    25,    26,
+       0,    61,     0,     0,    76,   -78,    77,   201,     0,     4,
+       5,     0,     0,     6,     7,   106,   107,   108,   109,   110,
+       0,     0,   111,     0,     0,     0,   202,     0,   203,   204,
+     205,   -77,   -77,   206,   207,   208,   209,   210,   211,   212,
+     213,   214,     0,     0,     0,    13,   215,     0,     0,     0,
+      14,    15,    16,    17,     0,     0,     0,     0,     0,   -77,
       20,     0,     0,     0,     0,     0,    21,    22,     0,    23,
        0,    24,     0,     0,    25,    26,     0,    61,     0,     0,
-      75,   -73,    76,   195,     0,     4,     5,     0,     0,     6,
+      76,   -77,    77,   201,     0,     4,     5,     0,     0,     6,
        7,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   196,     0,   197,   198,   199,     0,     0,   200,
-     201,   202,   203,   204,   205,   206,   207,   208,     0,     0,
-       0,    13,   209,     0,     0,     0,    14,    15,    16,    17,
-      69,     0,     4,     5,     0,    20,     6,     7,    85,     0,
-    -105,    21,    22,    86,    23,     0,    24,     0,     0,    25,
-      26,     0,    61,     0,     0,    75,   210,    76,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,    13,    87,
-      88,     0,     0,    14,    15,    16,    17,     0,     0,     0,
-       0,  -105,    20,     0,     0,    92,    93,     0,    21,    22,
-       0,    23,     0,    24,     0,     0,    25,   266,  -105,    61,
-       0,     4,     5,     0,  -105,     6,     7,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   196,     0,
-     197,   198,   199,     0,     0,   200,   201,   202,   203,   204,
-     205,   206,   207,   208,     0,     0,     0,    13,   209,     0,
-       0,     0,    14,    15,    16,    17,     0,     0,     4,     5,
-       0,    20,     6,     7,     0,     0,     0,    21,    22,     0,
-      23,     0,    24,     0,     0,    25,    26,     0,    61,     0,
-       0,    75,     0,    76,     0,     0,     0,     0,     0,   117,
-       0,     4,     5,     0,    13,     6,     7,   118,     0,    14,
-      15,    16,    17,     0,     0,     0,     0,     0,    20,     0,
-       0,     0,     0,     0,    21,    22,     0,    23,     0,    24,
-       0,     0,    25,    26,     0,    61,     0,    13,     0,     0,
-      76,     0,    14,    15,    16,    17,   223,     0,     4,     5,
-       0,    20,     6,     7,   118,     0,     0,    21,    22,     0,
-      23,     0,    24,     0,     0,    25,    26,  -113,    61,     0,
-       0,     0,     0,    69,     0,     4,     5,     0,     0,     6,
-       7,     0,     0,     0,    13,     0,     0,     0,     0,    14,
-      15,    16,    17,     0,     0,     0,     0,    85,    20,     0,
-       0,     0,    86,     0,    21,    22,     0,    23,     0,    24,
-       0,    13,    25,    26,     0,    61,    14,    15,    16,    17,
-     189,     0,     4,     5,     0,    20,     6,     7,    87,    88,
-      89,    21,    22,     0,    23,     0,    24,     0,     0,    25,
-      26,    90,    61,    91,    92,    93,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     4,   262,     0,    13,     6,
-       7,     0,     0,    14,    15,    16,    17,     0,     0,     0,
-       0,     0,    20,     0,     0,   198,     0,     0,    21,    22,
-       0,    23,     0,    24,   205,   206,    25,    26,     0,    61,
+       0,     0,   202,     0,   203,   204,   205,     0,     0,   206,
+     207,   208,   209,   210,   211,   212,   213,   214,     0,     0,
+       0,    13,   215,     0,     0,     0,    14,    15,    16,    17,
+      86,    69,     0,     4,     5,    87,    20,     6,     7,     0,
+       0,  -109,    21,    22,     0,    23,     0,    24,     0,     0,
+      25,    26,     0,    61,     0,     0,    76,   216,    77,     0,
+       0,    88,    89,     0,     0,     0,     0,     0,     0,    13,
+       0,     0,     0,     0,    14,    15,    16,    17,    93,    94,
+       0,     0,     0,  -109,    20,     0,     0,     0,     0,     0,
+      21,    22,     0,    23,     0,    24,     0,     0,    25,   272,
+    -109,    61,     0,     4,     5,     0,  -109,     6,     7,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     202,     0,   203,   204,   205,     0,     0,   206,   207,   208,
+     209,   210,   211,   212,   213,   214,     0,     4,     5,    13,
+     215,     6,     7,     0,    14,    15,    16,    17,     0,     0,
+       0,     0,     0,     0,    20,     0,     0,     0,     0,     0,
+      21,    22,     0,    23,     0,    24,     0,     0,    25,    26,
+       0,    61,     0,    13,    76,     0,    77,     0,    14,    15,
+      16,    17,     0,   118,     0,     4,     5,     0,    20,     6,
+       7,   119,     0,     0,    21,    22,     0,    23,     0,    24,
+       0,     0,    25,    26,     0,    61,     0,     0,     0,     0,
+      77,   229,     0,     4,     5,     0,     0,     6,     7,   119,
        0,    13,     0,     0,     0,     0,    14,    15,    16,    17,
-       0,     0,     0,     4,     5,    20,     0,     6,     7,     0,
-       0,    21,    22,     0,    23,     0,    24,     0,     0,    25,
-      26,     0,    61,   198,     0,     0,     0,     0,     0,     0,
-       0,     0,   205,   206,     0,     0,     0,     0,     0,    13,
-       0,     0,     0,     0,    14,    15,    16,    17,     0,     0,
-       0,     0,     0,    20,     0,     0,     0,     0,     0,    21,
-      22,    85,    23,     0,    24,     0,    86,    25,    26,     0,
-      61,     4,     5,     0,     0,     6,     7,     0,     0,     0,
-      97,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    87,    88,    89,     0,     0,     0,     4,     5,
-       0,     0,     6,     7,   118,    90,   220,    13,    92,    93,
+       0,     0,     0,     0,     0,     0,    20,     0,     0,     0,
+       0,     0,    21,    22,     0,    23,     0,    24,     0,    13,
+      25,    26,  -117,    61,    14,    15,    16,    17,     0,    69,
+       0,     4,     5,     0,    20,     6,     7,     0,     0,     0,
+      21,    22,     0,    23,     0,    24,     0,     0,    25,    26,
+       0,    61,     0,     0,     0,     0,     0,   193,     0,     4,
+       5,     0,     0,     6,     7,     0,     0,    13,     0,     0,
        0,     0,    14,    15,    16,    17,     0,     0,     0,     0,
-      85,    20,     0,     0,     0,    86,     0,    21,    22,     0,
-      23,     0,    24,     0,    13,    25,    26,     0,    61,    14,
-      15,    16,    17,     0,     0,     4,     5,     0,    20,     6,
-       7,    87,    88,    89,    21,    22,     0,    23,     0,    24,
-       0,     0,    25,    26,    90,    61,     0,    92,    93,     0,
-       0,     0,     4,     5,     0,     0,     6,     7,     0,     0,
-       0,    13,     0,     0,     0,     0,    14,    15,    16,    17,
-       0,     0,     0,     0,     0,    20,     0,     0,     0,     0,
-       0,    21,    22,     0,    23,     0,    24,     0,     0,    25,
-      26,     0,    61,    14,    15,    16,    17,     0,     0,     0,
        0,     0,    20,     0,     0,     0,     0,     0,    21,    22,
-       0,    23,     0,    24,     0,     0,    25,    66,     0,    61
+       0,    23,     0,    24,     0,    13,    25,    26,     0,    61,
+      14,    15,    16,    17,     0,     0,     0,     0,     4,   268,
+      20,     0,     6,     7,     0,     0,    21,    22,     0,    23,
+       0,    24,     0,     0,    25,    26,     0,    61,   204,     0,
+       0,     0,     0,     0,     0,     0,     0,   211,   212,     0,
+       0,     0,     4,     5,    13,     0,     6,     7,     0,    14,
+      15,    16,    17,     0,     0,     0,     0,     0,     0,    20,
+       0,     0,   204,     0,     0,    21,    22,     0,    23,     0,
+      24,   211,   212,    25,    26,     0,    61,     0,    13,     0,
+       0,     0,     0,    14,    15,    16,    17,     4,     5,     0,
+       0,     6,     7,    20,     0,     0,    98,     0,     0,    21,
+      22,     0,    23,     0,    24,     0,     0,    25,    26,     0,
+      61,     0,     0,     0,     0,     4,     5,     0,     0,     6,
+       7,   119,     0,    13,     0,     0,     0,     0,    14,    15,
+      16,    17,     0,     0,     0,     0,     0,    86,    20,     0,
+       0,     0,    87,     0,    21,    22,     0,    23,     0,    24,
+       0,    13,    25,    26,     0,    61,    14,    15,    16,    17,
+       4,     5,     0,     0,     6,     7,    20,     0,    88,    89,
+      90,     0,    21,    22,     0,    23,     0,    24,     0,     0,
+      25,    26,    91,    61,    92,    93,    94,     0,     4,     5,
+       0,     0,     6,     7,     0,     0,    13,     0,     0,     0,
+       0,    14,    15,    16,    17,     0,     0,     0,     0,     0,
+      86,    20,     0,     0,     0,    87,     0,    21,    22,     0,
+      23,     0,    24,     0,     0,    25,    26,     0,    61,    14,
+      15,    16,    17,    86,     0,     0,     0,     0,    87,    20,
+       0,    88,    89,    90,     0,    21,    22,     0,    23,     0,
+      24,     0,    86,    25,    66,    91,    61,    87,    93,    94,
+       0,     0,     0,     0,    88,    89,    90,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    77,     0,    91,   226,
+       0,    93,    94,    88,    89,    90,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    91,     0,     0,
+      93,    94
 };
 
 static const yytype_int16 yycheck[] =
 {
-       1,    86,    29,    30,     1,   237,    70,   247,     1,   217,
-      46,    13,    14,    15,    29,    44,     4,    17,    17,    21,
-      22,     1,    24,    25,    34,    26,    10,   112,    52,     3,
-      87,    15,    41,    35,    68,    10,    29,   313,    21,    22,
-       1,    24,    43,    44,     1,     1,   322,     4,     1,    73,
-       6,    75,    35,     6,    71,    52,   120,    41,    59,    60,
-       1,    68,    71,     4,    68,    66,     4,    73,   132,   133,
-      52,    71,    71,    57,    58,    49,    56,    51,    75,   319,
-      68,   313,    57,    58,   236,    86,    81,    88,    89,    90,
-     322,    52,    72,    75,    95,    96,    91,    99,   100,   101,
-     102,   103,   104,   105,   106,   107,   108,   109,   110,     1,
-       1,   121,    69,     1,    75,   116,    99,   100,   101,   102,
-     103,   104,   105,   106,   107,   108,   109,   110,   130,    67,
-     145,   188,   340,   148,    50,   343,    10,   138,   290,    52,
-     141,    27,   294,    61,    62,    63,    68,   130,    66,     1,
-      44,    45,   145,    59,    60,   148,    57,    44,    45,   311,
-       3,   163,   314,   227,    56,    56,   180,   181,    56,     3,
-       4,    66,    52,    25,    26,    61,     5,    69,    69,   180,
-     181,    69,     4,    57,    58,    39,     9,    14,   203,   204,
-     342,   255,   207,   345,   209,   259,   260,    69,   213,     1,
-      52,    41,    68,   218,    68,    68,   201,   208,    68,    11,
-     203,   204,    46,    47,   207,   210,   209,   246,   228,   220,
-     213,   257,    74,   287,   219,    75,   241,     4,   285,   230,
-     231,   316,   296,   234,   235,    27,    70,   266,    69,   303,
-     145,   256,   278,   148,    68,   246,    13,    14,   241,   264,
-      52,    11,    21,   248,    56,    55,    74,   252,     7,   323,
-       7,   316,    30,   256,   231,   266,   293,    69,   299,    25,
-     163,   335,   331,    75,    -1,   278,    -1,    44,    45,    -1,
-     275,    -1,   297,    -1,    -1,    -1,    53,   282,   283,    -1,
-     305,   286,    -1,    -1,   295,    10,   297,   299,   203,   204,
-      15,    -1,   207,    -1,   209,   307,    -1,    -1,   213,   304,
-      -1,   306,    -1,   308,   309,   310,    -1,   312,     7,     8,
-       9,    -1,    -1,    -1,   307,    -1,    41,    42,    43,    -1,
-      10,    -1,    -1,    -1,    -1,    15,   241,    -1,   333,    54,
-      -1,   336,    57,    58,   339,    -1,   341,    -1,    -1,     0,
-       1,   256,     3,     4,    -1,    -1,     7,     8,    -1,    -1,
-      75,    41,    42,    43,    53,    -1,    -1,    18,    19,    -1,
-      59,    60,    -1,    62,    54,    -1,    -1,    57,    58,    -1,
-      -1,    -1,    -1,    -1,    -1,    36,    37,    38,    39,    69,
-      -1,    -1,    -1,    44,    45,    46,    47,    48,    -1,    -1,
-      -1,    52,    53,    59,    60,    61,    62,    63,    59,    60,
-      66,    62,    -1,    64,    -1,    -1,    67,    68,    -1,    70,
-      -1,    -1,    73,     1,    75,     3,     4,    -1,    -1,     7,
-       8,    59,    60,    61,    62,    63,    -1,    -1,    66,    -1,
-      -1,    -1,    20,    -1,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    33,    34,    35,    -1,    -1,
-      -1,    39,    40,    -1,    -1,    -1,    44,    45,    46,    47,
-      -1,    -1,    -1,    -1,    52,    53,    -1,    -1,    -1,    -1,
-      -1,    59,    60,    -1,    62,    -1,    64,    -1,    -1,    67,
-      68,    -1,    70,    -1,    -1,    73,    74,    75,     1,    -1,
-       3,     4,    -1,    -1,     7,     8,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    20,    -1,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      33,    34,    35,    -1,    -1,    -1,    39,    40,    -1,    -1,
-      -1,    44,    45,    46,    47,    -1,    -1,    -1,    -1,    52,
-      53,    -1,    -1,    -1,    -1,    -1,    59,    60,    -1,    62,
-      -1,    64,    -1,    -1,    67,    68,    -1,    70,    -1,    -1,
-      73,    74,    75,     1,    -1,     3,     4,    -1,    -1,     7,
+       1,    44,    29,    30,    46,    70,     1,    88,   223,   243,
+      87,    13,    14,    15,     1,     1,     4,    17,    41,    21,
+      22,    27,    24,    25,    69,    26,    34,     4,     1,     1,
+      69,     4,     4,    35,    29,     1,   113,   319,    21,    22,
+       1,    24,    43,    44,    72,     1,   328,    82,     1,    72,
+       6,    69,    35,     6,    74,    61,   121,    92,    59,    60,
+       1,     1,    44,    45,    53,    66,     6,   253,   133,   134,
+      57,    57,    72,   146,     1,    50,   149,     1,    69,   152,
+      58,    69,     3,    70,    70,   319,    87,    53,    89,    90,
+      91,    68,    53,   155,   328,    96,    97,    70,   100,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
+      76,   192,    53,    67,   122,    76,   117,   100,   101,   102,
+     103,   104,   105,   106,   107,   108,   109,   110,   111,   131,
+      57,   346,    17,    57,   349,    76,   209,   210,   139,   325,
+     213,   142,   215,    70,    53,    10,   219,    53,   131,    73,
+      15,   146,    53,     1,   149,    10,     5,   152,    44,    45,
+      59,    60,   224,     3,     4,   167,     4,    76,   233,   184,
+     185,    39,   207,    74,   247,    76,    41,    25,    26,     9,
+     242,   216,    14,   184,   185,    41,    70,    72,    69,   262,
+     225,   253,    69,    58,    59,    69,   261,    69,    76,    10,
+     265,   266,     4,    58,    59,    53,    46,    47,   270,   252,
+     291,    70,   242,   214,   209,   210,    11,    27,   213,   254,
+     215,   263,    69,   258,   219,   226,   234,    75,   293,   272,
+      21,    71,    56,    75,   296,   236,   237,   302,   300,   240,
+     241,   303,   284,     7,   309,   322,   281,    58,    59,   311,
+       7,   252,   247,   288,   289,   317,    30,   292,   320,   322,
+       3,   237,    25,   167,   329,   305,   296,   262,   284,   337,
+     300,   272,   299,    -1,    -1,   310,   341,   312,    -1,   314,
+     315,   316,    -1,   318,    -1,    -1,   348,   317,   350,   351,
+     320,   353,    62,    63,    64,    -1,    10,    67,    -1,    -1,
+     301,    15,   303,   305,   339,    -1,    49,   342,    51,    52,
+     345,   313,   347,    -1,    -1,    -1,     0,     1,   348,     3,
+       4,   351,    -1,     7,     8,    -1,     1,    41,    42,    43,
+     313,    -1,    -1,    -1,    18,    19,    11,    -1,    -1,    -1,
+      -1,    55,    13,    14,    58,    59,    -1,    -1,    -1,     7,
+       8,     9,    36,    37,    38,    39,    70,    -1,    -1,    -1,
+      44,    45,    46,    47,    48,    -1,    -1,    -1,    -1,    53,
+      54,    -1,    -1,    44,    45,    -1,    60,    61,    53,    63,
+      -1,    65,    57,    54,    68,    69,    -1,    71,    -1,    -1,
+      74,     1,    76,     3,     4,    70,    54,     7,     8,    -1,
+      -1,    76,    60,    61,    -1,    63,    -1,    -1,    -1,    -1,
+      20,    -1,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    -1,    -1,    -1,    39,
+      40,    -1,    -1,    -1,    44,    45,    46,    47,    60,    61,
+      62,    63,    64,    53,    54,    67,    -1,    -1,    -1,    -1,
+      60,    61,    -1,    63,    -1,    65,    -1,    -1,    68,    69,
+      -1,    71,    -1,    -1,    74,    75,    76,     1,    -1,     3,
+       4,    -1,    -1,     7,     8,    60,    61,    62,    63,    64,
+      -1,    -1,    67,    -1,    -1,    -1,    20,    -1,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    -1,    -1,    -1,    39,    40,    -1,    -1,    -1,
+      44,    45,    46,    47,    -1,    -1,    -1,    -1,    -1,    53,
+      54,    -1,    -1,    -1,    -1,    -1,    60,    61,    -1,    63,
+      -1,    65,    -1,    -1,    68,    69,    -1,    71,    -1,    -1,
+      74,    75,    76,     1,    -1,     3,     4,    -1,    -1,     7,
        8,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    20,    -1,    22,    23,    24,    -1,    -1,    27,
       28,    29,    30,    31,    32,    33,    34,    35,    -1,    -1,
       -1,    39,    40,    -1,    -1,    -1,    44,    45,    46,    47,
-       1,    -1,     3,     4,    -1,    53,     7,     8,    10,    -1,
-      11,    59,    60,    15,    62,    -1,    64,    -1,    -1,    67,
-      68,    -1,    70,    -1,    -1,    73,    74,    75,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    39,    41,
-      42,    -1,    -1,    44,    45,    46,    47,    -1,    -1,    -1,
-      -1,    52,    53,    -1,    -1,    57,    58,    -1,    59,    60,
-      -1,    62,    -1,    64,    -1,    -1,    67,    68,    69,    70,
-      -1,     3,     4,    -1,    75,     7,     8,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    20,    -1,
-      22,    23,    24,    -1,    -1,    27,    28,    29,    30,    31,
-      32,    33,    34,    35,    -1,    -1,    -1,    39,    40,    -1,
-      -1,    -1,    44,    45,    46,    47,    -1,    -1,     3,     4,
-      -1,    53,     7,     8,    -1,    -1,    -1,    59,    60,    -1,
-      62,    -1,    64,    -1,    -1,    67,    68,    -1,    70,    -1,
-      -1,    73,    -1,    75,    -1,    -1,    -1,    -1,    -1,     1,
-      -1,     3,     4,    -1,    39,     7,     8,     9,    -1,    44,
-      45,    46,    47,    -1,    -1,    -1,    -1,    -1,    53,    -1,
-      -1,    -1,    -1,    -1,    59,    60,    -1,    62,    -1,    64,
-      -1,    -1,    67,    68,    -1,    70,    -1,    39,    -1,    -1,
-      75,    -1,    44,    45,    46,    47,     1,    -1,     3,     4,
-      -1,    53,     7,     8,     9,    -1,    -1,    59,    60,    -1,
-      62,    -1,    64,    -1,    -1,    67,    68,    69,    70,    -1,
-      -1,    -1,    -1,     1,    -1,     3,     4,    -1,    -1,     7,
-       8,    -1,    -1,    -1,    39,    -1,    -1,    -1,    -1,    44,
-      45,    46,    47,    -1,    -1,    -1,    -1,    10,    53,    -1,
-      -1,    -1,    15,    -1,    59,    60,    -1,    62,    -1,    64,
-      -1,    39,    67,    68,    -1,    70,    44,    45,    46,    47,
-       1,    -1,     3,     4,    -1,    53,     7,     8,    41,    42,
-      43,    59,    60,    -1,    62,    -1,    64,    -1,    -1,    67,
-      68,    54,    70,    56,    57,    58,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,     3,     4,    -1,    39,     7,
-       8,    -1,    -1,    44,    45,    46,    47,    -1,    -1,    -1,
-      -1,    -1,    53,    -1,    -1,    23,    -1,    -1,    59,    60,
-      -1,    62,    -1,    64,    32,    33,    67,    68,    -1,    70,
+      10,     1,    -1,     3,     4,    15,    54,     7,     8,    -1,
+      -1,    11,    60,    61,    -1,    63,    -1,    65,    -1,    -1,
+      68,    69,    -1,    71,    -1,    -1,    74,    75,    76,    -1,
+      -1,    41,    42,    -1,    -1,    -1,    -1,    -1,    -1,    39,
+      -1,    -1,    -1,    -1,    44,    45,    46,    47,    58,    59,
+      -1,    -1,    -1,    53,    54,    -1,    -1,    -1,    -1,    -1,
+      60,    61,    -1,    63,    -1,    65,    -1,    -1,    68,    69,
+      70,    71,    -1,     3,     4,    -1,    76,     7,     8,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      20,    -1,    22,    23,    24,    -1,    -1,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    -1,     3,     4,    39,
+      40,     7,     8,    -1,    44,    45,    46,    47,    -1,    -1,
+      -1,    -1,    -1,    -1,    54,    -1,    -1,    -1,    -1,    -1,
+      60,    61,    -1,    63,    -1,    65,    -1,    -1,    68,    69,
+      -1,    71,    -1,    39,    74,    -1,    76,    -1,    44,    45,
+      46,    47,    -1,     1,    -1,     3,     4,    -1,    54,     7,
+       8,     9,    -1,    -1,    60,    61,    -1,    63,    -1,    65,
+      -1,    -1,    68,    69,    -1,    71,    -1,    -1,    -1,    -1,
+      76,     1,    -1,     3,     4,    -1,    -1,     7,     8,     9,
       -1,    39,    -1,    -1,    -1,    -1,    44,    45,    46,    47,
-      -1,    -1,    -1,     3,     4,    53,    -1,     7,     8,    -1,
-      -1,    59,    60,    -1,    62,    -1,    64,    -1,    -1,    67,
-      68,    -1,    70,    23,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    32,    33,    -1,    -1,    -1,    -1,    -1,    39,
-      -1,    -1,    -1,    -1,    44,    45,    46,    47,    -1,    -1,
-      -1,    -1,    -1,    53,    -1,    -1,    -1,    -1,    -1,    59,
-      60,    10,    62,    -1,    64,    -1,    15,    67,    68,    -1,
-      70,     3,     4,    -1,    -1,     7,     8,    -1,    -1,    -1,
-      12,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    41,    42,    43,    -1,    -1,    -1,     3,     4,
-      -1,    -1,     7,     8,     9,    54,    55,    39,    57,    58,
+      -1,    -1,    -1,    -1,    -1,    -1,    54,    -1,    -1,    -1,
+      -1,    -1,    60,    61,    -1,    63,    -1,    65,    -1,    39,
+      68,    69,    70,    71,    44,    45,    46,    47,    -1,     1,
+      -1,     3,     4,    -1,    54,     7,     8,    -1,    -1,    -1,
+      60,    61,    -1,    63,    -1,    65,    -1,    -1,    68,    69,
+      -1,    71,    -1,    -1,    -1,    -1,    -1,     1,    -1,     3,
+       4,    -1,    -1,     7,     8,    -1,    -1,    39,    -1,    -1,
       -1,    -1,    44,    45,    46,    47,    -1,    -1,    -1,    -1,
-      10,    53,    -1,    -1,    -1,    15,    -1,    59,    60,    -1,
-      62,    -1,    64,    -1,    39,    67,    68,    -1,    70,    44,
-      45,    46,    47,    -1,    -1,     3,     4,    -1,    53,     7,
-       8,    41,    42,    43,    59,    60,    -1,    62,    -1,    64,
-      -1,    -1,    67,    68,    54,    70,    -1,    57,    58,    -1,
-      -1,    -1,     3,     4,    -1,    -1,     7,     8,    -1,    -1,
-      -1,    39,    -1,    -1,    -1,    -1,    44,    45,    46,    47,
-      -1,    -1,    -1,    -1,    -1,    53,    -1,    -1,    -1,    -1,
-      -1,    59,    60,    -1,    62,    -1,    64,    -1,    -1,    67,
-      68,    -1,    70,    44,    45,    46,    47,    -1,    -1,    -1,
-      -1,    -1,    53,    -1,    -1,    -1,    -1,    -1,    59,    60,
-      -1,    62,    -1,    64,    -1,    -1,    67,    68,    -1,    70
+      -1,    -1,    54,    -1,    -1,    -1,    -1,    -1,    60,    61,
+      -1,    63,    -1,    65,    -1,    39,    68,    69,    -1,    71,
+      44,    45,    46,    47,    -1,    -1,    -1,    -1,     3,     4,
+      54,    -1,     7,     8,    -1,    -1,    60,    61,    -1,    63,
+      -1,    65,    -1,    -1,    68,    69,    -1,    71,    23,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    32,    33,    -1,
+      -1,    -1,     3,     4,    39,    -1,     7,     8,    -1,    44,
+      45,    46,    47,    -1,    -1,    -1,    -1,    -1,    -1,    54,
+      -1,    -1,    23,    -1,    -1,    60,    61,    -1,    63,    -1,
+      65,    32,    33,    68,    69,    -1,    71,    -1,    39,    -1,
+      -1,    -1,    -1,    44,    45,    46,    47,     3,     4,    -1,
+      -1,     7,     8,    54,    -1,    -1,    12,    -1,    -1,    60,
+      61,    -1,    63,    -1,    65,    -1,    -1,    68,    69,    -1,
+      71,    -1,    -1,    -1,    -1,     3,     4,    -1,    -1,     7,
+       8,     9,    -1,    39,    -1,    -1,    -1,    -1,    44,    45,
+      46,    47,    -1,    -1,    -1,    -1,    -1,    10,    54,    -1,
+      -1,    -1,    15,    -1,    60,    61,    -1,    63,    -1,    65,
+      -1,    39,    68,    69,    -1,    71,    44,    45,    46,    47,
+       3,     4,    -1,    -1,     7,     8,    54,    -1,    41,    42,
+      43,    -1,    60,    61,    -1,    63,    -1,    65,    -1,    -1,
+      68,    69,    55,    71,    57,    58,    59,    -1,     3,     4,
+      -1,    -1,     7,     8,    -1,    -1,    39,    -1,    -1,    -1,
+      -1,    44,    45,    46,    47,    -1,    -1,    -1,    -1,    -1,
+      10,    54,    -1,    -1,    -1,    15,    -1,    60,    61,    -1,
+      63,    -1,    65,    -1,    -1,    68,    69,    -1,    71,    44,
+      45,    46,    47,    10,    -1,    -1,    -1,    -1,    15,    54,
+      -1,    41,    42,    43,    -1,    60,    61,    -1,    63,    -1,
+      65,    -1,    10,    68,    69,    55,    71,    15,    58,    59,
+      -1,    -1,    -1,    -1,    41,    42,    43,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    76,    -1,    55,    56,
+      -1,    58,    59,    41,    42,    43,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    55,    -1,    -1,
+      58,    59
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    77,     0,     1,     3,     4,     7,     8,    18,    19,
-      36,    37,    38,    39,    44,    45,    46,    47,    48,    52,
-      53,    59,    60,    62,    64,    67,    68,    70,    78,    81,
-      85,    87,    90,   108,   119,   123,   124,   125,   126,   127,
-     128,   136,   137,    68,    71,   133,   134,   135,     3,     4,
-      46,    47,    70,    83,    84,   129,   137,   137,   137,    68,
-      68,    70,   124,   137,   124,   124,    68,   126,   137,     1,
-     115,   119,    49,    51,   128,    73,    75,    82,    92,   108,
-     139,   143,    82,    88,    52,    10,    15,    41,    42,    43,
-      54,    56,    57,    58,   121,   122,   145,    12,   124,    59,
-      60,    61,    62,    63,    66,    59,    60,    61,    62,    63,
-      66,    13,    14,    44,    45,    53,   120,     1,     9,    89,
-     116,   117,   118,   119,   115,   119,    17,   133,    50,    68,
-      57,   110,   116,   116,   119,    44,    45,   138,     1,    69,
-     141,   145,   141,     1,     6,    79,     1,     6,    80,   108,
-     109,    91,   109,     5,    89,   119,   136,   119,   119,   119,
-     109,   119,   119,    39,   124,   124,   124,   124,   124,   124,
-     124,   124,   124,   124,   124,   124,    89,    14,   119,   141,
-       1,   145,    72,    86,   124,   141,   141,   119,    41,     1,
-     119,     1,    92,     1,    92,     1,    20,    22,    23,    24,
-      27,    28,    29,    30,    31,    32,    33,    34,    35,    40,
-      74,    93,    94,    96,   103,   107,   119,   139,   140,   143,
-      55,   129,   118,     1,   118,     1,     4,   111,   112,   136,
-      68,    95,     4,    68,    68,    68,   109,    68,    92,    92,
-      92,   113,   119,    92,   109,    92,    97,    91,   142,   143,
-     109,   119,   141,     1,   145,   119,   113,    98,     4,   119,
-     119,    93,     4,    96,    99,    92,    68,   104,   114,   115,
-     140,   109,   109,     1,     4,   141,    92,   130,   131,   132,
-     133,    69,   141,   141,    27,    41,   143,   115,    11,   105,
-     109,    17,   132,   109,   109,    68,   136,   109,   141,   106,
-      93,   139,    93,   119,   141,   119,   143,   123,    21,   100,
-     141,   109,   143,   109,   109,     1,    25,    26,   101,   109,
-     109,    93,   109,    99,    93,     7,     8,    59,    60,    87,
-      89,   102,    55,   144,   140,    99,   141,     7,     7,   144,
-     109,   141,   109,   109,    91,   109,    93,    91,    93
+       0,    78,     0,     1,     3,     4,     7,     8,    18,    19,
+      36,    37,    38,    39,    44,    45,    46,    47,    48,    53,
+      54,    60,    61,    63,    65,    68,    69,    71,    79,    83,
+      87,    89,    92,   110,   121,   125,   126,   127,   128,   129,
+     130,   138,   139,    69,    72,   135,   136,   137,     3,     4,
+      46,    47,    71,    85,    86,   131,   139,   139,   139,    69,
+      69,    71,   126,   139,   126,   126,    69,   128,   139,     1,
+     117,   121,    49,    51,    52,   130,    74,    76,    84,    94,
+     110,   141,   145,    84,    90,    53,    10,    15,    41,    42,
+      43,    55,    57,    58,    59,   123,   124,   147,    12,   126,
+      60,    61,    62,    63,    64,    67,    60,    61,    62,    63,
+      64,    67,    13,    14,    44,    45,    54,   122,     1,     9,
+      91,   118,   119,   120,   121,   117,   121,    17,   135,    50,
+      69,    58,   112,   118,   118,   121,    44,    45,   140,     1,
+      70,   143,   147,   143,     1,     6,    80,     1,     6,    81,
+       1,     6,    82,   110,   111,    93,   111,     5,    91,   121,
+     138,   121,   121,   121,   111,   121,   121,    39,   126,   126,
+     126,   126,   126,   126,   126,   126,   126,   126,   126,   126,
+      91,    14,   121,   143,     1,   147,    73,    88,   126,   143,
+     143,   121,    41,     1,   121,     1,    94,     1,    94,     1,
+      94,     1,    20,    22,    23,    24,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    40,    75,    95,    96,    98,
+     105,   109,   121,   141,   142,   145,    56,   131,   120,     1,
+     120,     1,     4,   113,   114,   138,    69,    97,     4,    69,
+      69,    69,   111,    69,    94,    94,    94,   115,   121,    94,
+     111,    94,    99,    93,   144,   145,   111,   121,   143,     1,
+     147,   121,   115,   100,     4,   121,   121,    95,     4,    98,
+     101,    94,    69,   106,   116,   117,   142,   111,   111,     1,
+       4,   143,    94,   132,   133,   134,   135,    70,   143,   143,
+      27,    41,   145,   117,    11,   107,   111,    17,   134,   111,
+     111,    69,   138,   111,   143,   108,    95,   141,    95,   121,
+     143,   121,   145,   125,    21,   102,   143,   111,   145,   111,
+     111,     1,    25,    26,   103,   111,   111,    95,   111,   101,
+      95,     7,     8,    60,    61,    89,    91,   104,    56,   146,
+     142,   101,   143,     7,     7,   146,   111,   143,   111,   111,
+      93,   111,    95,    93,    95
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    76,    77,    77,    77,    77,    77,    78,    78,    78,
-      78,    78,    79,    79,    79,    80,    80,    80,    81,    81,
-      81,    81,    81,    81,    81,    82,    83,    83,    83,    83,
-      84,    84,    86,    85,    88,    87,    89,    90,    90,    91,
-      91,    91,    92,    92,    93,    93,    93,    93,    93,    93,
-      93,    93,    93,    93,    94,    94,    94,    94,    94,    95,
-      94,    94,    97,    96,    98,    96,    96,    96,    99,    99,
-     100,   100,   100,   101,   101,   102,   102,   102,   102,   102,
-     102,   103,   103,   104,   104,   105,   106,   105,   107,   107,
-     108,   108,   109,   109,   110,   110,   111,   111,   112,   112,
-     112,   112,   112,   113,   113,   114,   114,   115,   115,   115,
-     115,   115,   115,   116,   116,   117,   117,   117,   117,   117,
-     117,   118,   118,   119,   119,   119,   119,   119,   119,   119,
-     119,   119,   119,   120,   120,   120,   121,   121,   122,   122,
-     123,   123,   123,   124,   124,   124,   124,   124,   124,   124,
-     124,   124,   124,   124,   125,   125,   125,   125,   125,   125,
-     125,   126,   126,   126,   126,   126,   126,   126,   126,   126,
-     126,   126,   126,   126,   126,   127,   127,   128,   129,   129,
-     130,   130,   131,   131,   132,   133,   134,   134,   135,   136,
-     136,   137,   137,   138,   138,   138,   139,   140,   141,   142,
-     142,   143,   144,   145
+       0,    77,    78,    78,    78,    78,    78,    79,    79,    79,
+      79,    79,    79,    80,    80,    80,    81,    81,    81,    82,
+      82,    82,    83,    83,    83,    83,    83,    83,    83,    84,
+      85,    85,    85,    85,    86,    86,    88,    87,    90,    89,
+      91,    92,    92,    93,    93,    93,    94,    94,    95,    95,
+      95,    95,    95,    95,    95,    95,    95,    95,    96,    96,
+      96,    96,    96,    97,    96,    96,    99,    98,   100,    98,
+      98,    98,   101,   101,   102,   102,   102,   103,   103,   104,
+     104,   104,   104,   104,   104,   105,   105,   106,   106,   107,
+     108,   107,   109,   109,   110,   110,   111,   111,   112,   112,
+     113,   113,   114,   114,   114,   114,   114,   115,   115,   116,
+     116,   117,   117,   117,   117,   117,   117,   118,   118,   119,
+     119,   119,   119,   119,   119,   120,   120,   121,   121,   121,
+     121,   121,   121,   121,   121,   121,   121,   122,   122,   122,
+     123,   123,   124,   124,   125,   125,   125,   126,   126,   126,
+     126,   126,   126,   126,   126,   126,   126,   126,   127,   127,
+     127,   127,   127,   127,   127,   128,   128,   128,   128,   128,
+     128,   128,   128,   128,   128,   128,   128,   128,   128,   129,
+     129,   130,   131,   131,   132,   132,   133,   133,   134,   135,
+     136,   136,   137,   138,   138,   139,   139,   140,   140,   140,
+     141,   142,   143,   144,   144,   145,   146,   147
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
        0,     2,     0,     2,     2,     2,     2,     2,     2,     2,
-       4,     4,     1,     2,     1,     1,     2,     1,     0,     1,
-       3,     1,     1,     1,     1,     5,     1,     1,     1,     2,
-       1,     1,     0,     7,     0,     3,     1,     1,     1,     0,
-       2,     2,     1,     2,     2,     3,     1,     9,     6,     8,
-       8,    12,    11,     1,     2,     2,     2,     2,     3,     0,
-       4,     2,     0,     4,     0,     4,     4,     1,     0,     1,
-       0,     2,     2,     5,     4,     1,     2,     2,     1,     1,
-       1,     1,     1,     1,     3,     0,     0,     3,     6,     9,
-       1,     2,     0,     1,     0,     2,     0,     1,     1,     3,
-       1,     2,     3,     0,     1,     0,     1,     1,     3,     1,
-       2,     3,     3,     0,     1,     1,     3,     1,     2,     3,
-       3,     1,     1,     3,     3,     3,     3,     3,     3,     3,
-       3,     5,     1,     1,     1,     2,     1,     1,     1,     1,
-       1,     1,     2,     1,     3,     3,     3,     3,     3,     3,
-       3,     2,     2,     5,     4,     3,     3,     3,     3,     3,
-       3,     1,     2,     3,     4,     4,     1,     1,     1,     2,
-       2,     1,     1,     2,     2,     1,     2,     4,     0,     1,
-       0,     2,     1,     2,     1,     3,     1,     2,     2,     1,
-       2,     1,     3,     1,     1,     0,     2,     2,     1,     0,
-       1,     1,     1,     2
+       4,     4,     4,     1,     2,     1,     1,     2,     1,     1,
+       2,     1,     0,     1,     3,     1,     1,     1,     1,     5,
+       1,     1,     1,     2,     1,     1,     0,     7,     0,     3,
+       1,     1,     1,     0,     2,     2,     1,     2,     2,     3,
+       1,     9,     6,     8,     8,    12,    11,     1,     2,     2,
+       2,     2,     3,     0,     4,     2,     0,     4,     0,     4,
+       4,     1,     0,     1,     0,     2,     2,     5,     4,     1,
+       2,     2,     1,     1,     1,     1,     1,     1,     3,     0,
+       0,     3,     6,     9,     1,     2,     0,     1,     0,     2,
+       0,     1,     1,     3,     1,     2,     3,     0,     1,     0,
+       1,     1,     3,     1,     2,     3,     3,     0,     1,     1,
+       3,     1,     2,     3,     3,     1,     1,     3,     3,     3,
+       3,     3,     3,     3,     3,     5,     1,     1,     1,     2,
+       1,     1,     1,     1,     1,     1,     2,     1,     3,     3,
+       3,     3,     3,     3,     3,     2,     2,     5,     4,     3,
+       3,     3,     3,     3,     3,     1,     2,     3,     4,     4,
+       1,     1,     1,     2,     2,     1,     1,     2,     2,     1,
+       2,     4,     0,     1,     0,     2,     1,     2,     1,     3,
+       1,     2,     2,     1,     2,     1,     3,     1,     1,     0,
+       2,     2,     1,     0,     1,     1,     1,     2
 };
 
 
@@ -1883,22 +1897,22 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 223 "awkgram.y" /* yacc.c:1645  */
+#line 230 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 1889 "awkgram.c" /* yacc.c:1645  */
+#line 1903 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 3:
-#line 225 "awkgram.y" /* yacc.c:1645  */
+#line 232 "awkgram.y" /* yacc.c:1645  */
     {
                rule = 0;
                yyerrok;
          }
-#line 1898 "awkgram.c" /* yacc.c:1645  */
+#line 1912 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 4:
-#line 230 "awkgram.y" /* yacc.c:1645  */
+#line 237 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[0]) != NULL) {
                        if ((yyvsp[-1]) == NULL)
@@ -1908,19 +1922,19 @@ yyreduce:
                }
                (yyval) = (yyvsp[-1]);
          }
-#line 1912 "awkgram.c" /* yacc.c:1645  */
+#line 1926 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 5:
-#line 240 "awkgram.y" /* yacc.c:1645  */
+#line 247 "awkgram.y" /* yacc.c:1645  */
     {
                next_sourcefile();
          }
-#line 1920 "awkgram.c" /* yacc.c:1645  */
+#line 1934 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 6:
-#line 244 "awkgram.y" /* yacc.c:1645  */
+#line 251 "awkgram.y" /* yacc.c:1645  */
     {
                rule = 0;
                /*
@@ -1929,11 +1943,11 @@ yyreduce:
                 */
                /* yyerrok; */
          }
-#line 1933 "awkgram.c" /* yacc.c:1645  */
+#line 1947 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 7:
-#line 256 "awkgram.y" /* yacc.c:1645  */
+#line 263 "awkgram.y" /* yacc.c:1645  */
     {
                (void) append_rule((yyvsp[-1]), (yyvsp[0]));
                if (pending_comment != NULL) {
@@ -1941,11 +1955,11 @@ yyreduce:
                        pending_comment = NULL;
                }
          }
-#line 1945 "awkgram.c" /* yacc.c:1645  */
+#line 1959 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 8:
-#line 264 "awkgram.y" /* yacc.c:1645  */
+#line 271 "awkgram.y" /* yacc.c:1645  */
     {
                if (rule != Rule) {
                        msg(_("%s blocks must have an action part"), 
ruletab[rule]);
@@ -1959,11 +1973,11 @@ yyreduce:
                        (void) append_rule((yyvsp[-1]), NULL);
                }
          }
-#line 1963 "awkgram.c" /* yacc.c:1645  */
+#line 1977 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 9:
-#line 278 "awkgram.y" /* yacc.c:1645  */
+#line 285 "awkgram.y" /* yacc.c:1645  */
     {
                in_function = NULL;
                (void) mk_function((yyvsp[-1]), (yyvsp[0]));
@@ -1974,11 +1988,11 @@ yyreduce:
                }
                yyerrok;
          }
-#line 1978 "awkgram.c" /* yacc.c:1645  */
+#line 1992 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 10:
-#line 289 "awkgram.y" /* yacc.c:1645  */
+#line 296 "awkgram.y" /* yacc.c:1645  */
     {
                want_source = false;
                at_seen = false;
@@ -1988,11 +2002,11 @@ yyreduce:
                }
                yyerrok;
          }
-#line 1992 "awkgram.c" /* yacc.c:1645  */
+#line 2006 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 11:
-#line 299 "awkgram.y" /* yacc.c:1645  */
+#line 306 "awkgram.y" /* yacc.c:1645  */
     {
                want_source = false;
                at_seen = false;
@@ -2002,11 +2016,25 @@ yyreduce:
                }
                yyerrok;
          }
-#line 2006 "awkgram.c" /* yacc.c:1645  */
+#line 2020 "awkgram.c" /* yacc.c:1645  */
     break;
 
   case 12:
-#line 312 "awkgram.y" /* yacc.c:1645  */
+#line 316 "awkgram.y" /* yacc.c:1645  */
+    {
+               want_source = false;
+               at_seen = false;
+
+               // this frees $3 storage in all cases
+               set_namespace((yyvsp[-1]), (yyvsp[0]));
+
+               yyerrok;
+         }
+#line 2034 "awkgram.c" /* yacc.c:1645  */
+    break;
+
+  case 13:
+#line 329 "awkgram.y" /* yacc.c:1645  */
     {
                void *srcfile = NULL;
 
@@ -2016,23 +2044,23 @@ yyreduce:
                bcfree((yyvsp[0]));
                (yyval) = (INSTRUCTION *) srcfile;
          }
-#line 2020 "awkgram.c" /* yacc.c:1645  */
+#line 2048 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 13:
-#line 322 "awkgram.y" /* yacc.c:1645  */
+  case 14:
+#line 339 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 2026 "awkgram.c" /* yacc.c:1645  */
+#line 2054 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 14:
-#line 324 "awkgram.y" /* yacc.c:1645  */
+  case 15:
+#line 341 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 2032 "awkgram.c" /* yacc.c:1645  */
+#line 2060 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 15:
-#line 329 "awkgram.y" /* yacc.c:1645  */
+  case 16:
+#line 346 "awkgram.y" /* yacc.c:1645  */
     {
                void *srcfile;
 
@@ -2042,40 +2070,58 @@ yyreduce:
                bcfree((yyvsp[0]));
                (yyval) = (INSTRUCTION *) srcfile;
          }
-#line 2046 "awkgram.c" /* yacc.c:1645  */
+#line 2074 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 16:
-#line 339 "awkgram.y" /* yacc.c:1645  */
+  case 17:
+#line 356 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 2052 "awkgram.c" /* yacc.c:1645  */
+#line 2080 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 17:
-#line 341 "awkgram.y" /* yacc.c:1645  */
+  case 18:
+#line 358 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 2058 "awkgram.c" /* yacc.c:1645  */
+#line 2086 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 18:
-#line 346 "awkgram.y" /* yacc.c:1645  */
+  case 19:
+#line 363 "awkgram.y" /* yacc.c:1645  */
+    { (yyval) = (yyvsp[0]); }
+#line 2092 "awkgram.c" /* yacc.c:1645  */
+    break;
+
+  case 20:
+#line 365 "awkgram.y" /* yacc.c:1645  */
+    { (yyval) = NULL; }
+#line 2098 "awkgram.c" /* yacc.c:1645  */
+    break;
+
+  case 21:
+#line 367 "awkgram.y" /* yacc.c:1645  */
+    { (yyval) = NULL; }
+#line 2104 "awkgram.c" /* yacc.c:1645  */
+    break;
+
+  case 22:
+#line 372 "awkgram.y" /* yacc.c:1645  */
     {
                rule = Rule;
                (yyval) = NULL;
          }
-#line 2067 "awkgram.c" /* yacc.c:1645  */
+#line 2113 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 19:
-#line 351 "awkgram.y" /* yacc.c:1645  */
+  case 23:
+#line 377 "awkgram.y" /* yacc.c:1645  */
     {
                rule = Rule;
          }
-#line 2075 "awkgram.c" /* yacc.c:1645  */
+#line 2121 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 20:
-#line 356 "awkgram.y" /* yacc.c:1645  */
+  case 24:
+#line 382 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *tp;
 
@@ -2105,11 +2151,11 @@ yyreduce:
                        (yyval) = list_append(list_merge((yyvsp[-2]), 
(yyvsp[0])), tp);
                rule = Rule;
          }
-#line 2109 "awkgram.c" /* yacc.c:1645  */
+#line 2155 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 21:
-#line 386 "awkgram.y" /* yacc.c:1645  */
+  case 25:
+#line 412 "awkgram.y" /* yacc.c:1645  */
     {
                static int begin_seen = 0;
 
@@ -2121,11 +2167,11 @@ yyreduce:
                (yyvsp[0])->source_file = source;
                (yyval) = (yyvsp[0]);
          }
-#line 2125 "awkgram.c" /* yacc.c:1645  */
+#line 2171 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 22:
-#line 398 "awkgram.y" /* yacc.c:1645  */
+  case 26:
+#line 424 "awkgram.y" /* yacc.c:1645  */
     {
                static int end_seen = 0;
 
@@ -2137,31 +2183,31 @@ yyreduce:
                (yyvsp[0])->source_file = source;
                (yyval) = (yyvsp[0]);
          }
-#line 2141 "awkgram.c" /* yacc.c:1645  */
+#line 2187 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 23:
-#line 410 "awkgram.y" /* yacc.c:1645  */
+  case 27:
+#line 436 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[0])->in_rule = rule = BEGINFILE;
                (yyvsp[0])->source_file = source;
                (yyval) = (yyvsp[0]);
          }
-#line 2151 "awkgram.c" /* yacc.c:1645  */
+#line 2197 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 24:
-#line 416 "awkgram.y" /* yacc.c:1645  */
+  case 28:
+#line 442 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[0])->in_rule = rule = ENDFILE;
                (yyvsp[0])->source_file = source;
                (yyval) = (yyvsp[0]);
          }
-#line 2161 "awkgram.c" /* yacc.c:1645  */
+#line 2207 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 25:
-#line 425 "awkgram.y" /* yacc.c:1645  */
+  case 29:
+#line 451 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *ip = make_braced_statements((yyvsp[-4]), 
(yyvsp[-3]), (yyvsp[-2]));
 
@@ -2176,48 +2222,48 @@ yyreduce:
 
                (yyval) = ip;
          }
-#line 2180 "awkgram.c" /* yacc.c:1645  */
+#line 2226 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 26:
-#line 443 "awkgram.y" /* yacc.c:1645  */
+  case 30:
+#line 469 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 2186 "awkgram.c" /* yacc.c:1645  */
+#line 2232 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 27:
-#line 445 "awkgram.y" /* yacc.c:1645  */
+  case 31:
+#line 471 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 2192 "awkgram.c" /* yacc.c:1645  */
+#line 2238 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 28:
-#line 447 "awkgram.y" /* yacc.c:1645  */
+  case 32:
+#line 473 "awkgram.y" /* yacc.c:1645  */
     {
                yyerror(_("`%s' is a built-in function, it cannot be 
redefined"),
                                        tokstart);
                YYABORT;
          }
-#line 2202 "awkgram.c" /* yacc.c:1645  */
+#line 2248 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 29:
-#line 453 "awkgram.y" /* yacc.c:1645  */
+  case 33:
+#line 479 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = (yyvsp[0]);
                at_seen = false;
          }
-#line 2211 "awkgram.c" /* yacc.c:1645  */
+#line 2257 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 32:
-#line 465 "awkgram.y" /* yacc.c:1645  */
+  case 36:
+#line 491 "awkgram.y" /* yacc.c:1645  */
     { want_param_names = FUNC_HEADER; }
-#line 2217 "awkgram.c" /* yacc.c:1645  */
+#line 2263 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 33:
-#line 466 "awkgram.y" /* yacc.c:1645  */
+  case 37:
+#line 492 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *func_comment = NULL;
                // Merge any comments found in the parameter list with those
@@ -2243,17 +2289,17 @@ yyreduce:
                (yyval) = (yyvsp[-6]);
                want_param_names = FUNC_BODY;
          }
-#line 2247 "awkgram.c" /* yacc.c:1645  */
+#line 2293 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 34:
-#line 499 "awkgram.y" /* yacc.c:1645  */
+  case 38:
+#line 525 "awkgram.y" /* yacc.c:1645  */
     { want_regexp = true; }
-#line 2253 "awkgram.c" /* yacc.c:1645  */
+#line 2299 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 35:
-#line 501 "awkgram.y" /* yacc.c:1645  */
+  case 39:
+#line 527 "awkgram.y" /* yacc.c:1645  */
     {
                  NODE *n, *exp;
                  char *re;
@@ -2282,11 +2328,11 @@ yyreduce:
                  (yyval)->opcode = Op_match_rec;
                  (yyval)->memory = n;
                }
-#line 2286 "awkgram.c" /* yacc.c:1645  */
+#line 2332 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 36:
-#line 533 "awkgram.y" /* yacc.c:1645  */
+  case 40:
+#line 559 "awkgram.y" /* yacc.c:1645  */
     {
                  char *re;
                  size_t len;
@@ -2299,23 +2345,23 @@ yyreduce:
                  (yyval)->opcode = Op_push_re;
                  (yyval)->memory = make_typed_regex(re, len);
                }
-#line 2303 "awkgram.c" /* yacc.c:1645  */
+#line 2349 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 37:
-#line 548 "awkgram.y" /* yacc.c:1645  */
+  case 41:
+#line 574 "awkgram.y" /* yacc.c:1645  */
     { bcfree((yyvsp[0])); }
-#line 2309 "awkgram.c" /* yacc.c:1645  */
+#line 2355 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 39:
-#line 554 "awkgram.y" /* yacc.c:1645  */
+  case 43:
+#line 580 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 2315 "awkgram.c" /* yacc.c:1645  */
+#line 2361 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 40:
-#line 556 "awkgram.y" /* yacc.c:1645  */
+  case 44:
+#line 582 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[0]) == NULL) {
                        (yyval) = (yyvsp[-1]);
@@ -2335,29 +2381,29 @@ yyreduce:
 
                yyerrok;
          }
-#line 2339 "awkgram.c" /* yacc.c:1645  */
+#line 2385 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 41:
-#line 576 "awkgram.y" /* yacc.c:1645  */
+  case 45:
+#line 602 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = NULL; }
-#line 2345 "awkgram.c" /* yacc.c:1645  */
+#line 2391 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 42:
-#line 580 "awkgram.y" /* yacc.c:1645  */
+  case 46:
+#line 606 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 2351 "awkgram.c" /* yacc.c:1645  */
+#line 2397 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 43:
-#line 581 "awkgram.y" /* yacc.c:1645  */
+  case 47:
+#line 607 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 2357 "awkgram.c" /* yacc.c:1645  */
+#line 2403 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 44:
-#line 586 "awkgram.y" /* yacc.c:1645  */
+  case 48:
+#line 612 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[0]) != NULL) {
                        INSTRUCTION *ip;
@@ -2368,31 +2414,31 @@ yyreduce:
                } else
                        (yyval) = NULL;
          }
-#line 2372 "awkgram.c" /* yacc.c:1645  */
+#line 2418 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 45:
-#line 597 "awkgram.y" /* yacc.c:1645  */
+  case 49:
+#line 623 "awkgram.y" /* yacc.c:1645  */
     {
                trailing_comment = (yyvsp[0]);  // NULL or comment
                (yyval) = make_braced_statements((yyvsp[-2]), (yyvsp[-1]), 
(yyvsp[0]));
          }
-#line 2381 "awkgram.c" /* yacc.c:1645  */
+#line 2427 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 46:
-#line 602 "awkgram.y" /* yacc.c:1645  */
+  case 50:
+#line 628 "awkgram.y" /* yacc.c:1645  */
     {
                if (do_pretty_print)
                        (yyval) = list_prepend((yyvsp[0]), 
instruction(Op_exec_count));
                else
                        (yyval) = (yyvsp[0]);
          }
-#line 2392 "awkgram.c" /* yacc.c:1645  */
+#line 2438 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 47:
-#line 609 "awkgram.y" /* yacc.c:1645  */
+  case 51:
+#line 635 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *dflt, *curr = NULL, *cexp, *cstmt;
                INSTRUCTION *ip, *nextc, *tbreak;
@@ -2500,11 +2546,11 @@ yyreduce:
                break_allowed--;
                fix_break_continue(ip, tbreak, NULL);
          }
-#line 2504 "awkgram.c" /* yacc.c:1645  */
+#line 2550 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 48:
-#line 717 "awkgram.y" /* yacc.c:1645  */
+  case 52:
+#line 743 "awkgram.y" /* yacc.c:1645  */
     {
                /*
                 *    -----------------
@@ -2555,11 +2601,11 @@ yyreduce:
                continue_allowed--;
                fix_break_continue(ip, tbreak, tcont);
          }
-#line 2559 "awkgram.c" /* yacc.c:1645  */
+#line 2605 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 49:
-#line 768 "awkgram.y" /* yacc.c:1645  */
+  case 53:
+#line 794 "awkgram.y" /* yacc.c:1645  */
     {
                /*
                 *    -----------------
@@ -2609,11 +2655,11 @@ yyreduce:
                /* else
                        $1 and $4 are NULLs */
          }
-#line 2613 "awkgram.c" /* yacc.c:1645  */
+#line 2659 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 50:
-#line 818 "awkgram.y" /* yacc.c:1645  */
+  case 54:
+#line 844 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *ip;
                char *var_name = (yyvsp[-5])->lextok;
@@ -2739,11 +2785,11 @@ regular_loop:
                break_allowed--;
                continue_allowed--;
          }
-#line 2743 "awkgram.c" /* yacc.c:1645  */
+#line 2789 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 51:
-#line 944 "awkgram.y" /* yacc.c:1645  */
+  case 55:
+#line 970 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-7]) != NULL) {
                        merge_comments((yyvsp[-7]), NULL);
@@ -2764,11 +2810,11 @@ regular_loop:
                break_allowed--;
                continue_allowed--;
          }
-#line 2768 "awkgram.c" /* yacc.c:1645  */
+#line 2814 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 52:
-#line 965 "awkgram.y" /* yacc.c:1645  */
+  case 56:
+#line 991 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-6]) != NULL) {
                        merge_comments((yyvsp[-6]), NULL);
@@ -2789,22 +2835,22 @@ regular_loop:
                break_allowed--;
                continue_allowed--;
          }
-#line 2793 "awkgram.c" /* yacc.c:1645  */
+#line 2839 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 53:
-#line 986 "awkgram.y" /* yacc.c:1645  */
+  case 57:
+#line 1012 "awkgram.y" /* yacc.c:1645  */
     {
                if (do_pretty_print)
                        (yyval) = list_prepend((yyvsp[0]), 
instruction(Op_exec_count));
                else
                        (yyval) = (yyvsp[0]);
          }
-#line 2804 "awkgram.c" /* yacc.c:1645  */
+#line 2850 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 54:
-#line 996 "awkgram.y" /* yacc.c:1645  */
+  case 58:
+#line 1022 "awkgram.y" /* yacc.c:1645  */
     {
                if (! break_allowed)
                        error_ln((yyvsp[-1])->source_line,
@@ -2814,11 +2860,11 @@ regular_loop:
                if ((yyvsp[0]) != NULL)
                        (yyval) = list_append((yyval), (yyvsp[0]));
          }
-#line 2818 "awkgram.c" /* yacc.c:1645  */
+#line 2864 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 55:
-#line 1006 "awkgram.y" /* yacc.c:1645  */
+  case 59:
+#line 1032 "awkgram.y" /* yacc.c:1645  */
     {
                if (! continue_allowed)
                        error_ln((yyvsp[-1])->source_line,
@@ -2828,11 +2874,11 @@ regular_loop:
                if ((yyvsp[0]) != NULL)
                        (yyval) = list_append((yyval), (yyvsp[0]));
          }
-#line 2832 "awkgram.c" /* yacc.c:1645  */
+#line 2878 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 56:
-#line 1016 "awkgram.y" /* yacc.c:1645  */
+  case 60:
+#line 1042 "awkgram.y" /* yacc.c:1645  */
     {
                /* if inside function (rule = 0), resolve context at run-time */
                if (rule && rule != Rule)
@@ -2843,11 +2889,11 @@ regular_loop:
                if ((yyvsp[0]) != NULL)
                        (yyval) = list_append((yyval), (yyvsp[0]));
          }
-#line 2847 "awkgram.c" /* yacc.c:1645  */
+#line 2893 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 57:
-#line 1027 "awkgram.y" /* yacc.c:1645  */
+  case 61:
+#line 1053 "awkgram.y" /* yacc.c:1645  */
     {
                /* if inside function (rule = 0), resolve context at run-time */
                if (rule == BEGIN || rule == END || rule == ENDFILE)
@@ -2860,11 +2906,11 @@ regular_loop:
                if ((yyvsp[0]) != NULL)
                        (yyval) = list_append((yyval), (yyvsp[0]));
          }
-#line 2864 "awkgram.c" /* yacc.c:1645  */
+#line 2910 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 58:
-#line 1040 "awkgram.y" /* yacc.c:1645  */
+  case 62:
+#line 1066 "awkgram.y" /* yacc.c:1645  */
     {
                /* Initialize the two possible jump targets, the actual target
                 * is resolved at run-time.
@@ -2881,20 +2927,20 @@ regular_loop:
                if ((yyvsp[0]) != NULL)
                        (yyval) = list_append((yyval), (yyvsp[0]));
          }
-#line 2885 "awkgram.c" /* yacc.c:1645  */
+#line 2931 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 59:
-#line 1057 "awkgram.y" /* yacc.c:1645  */
+  case 63:
+#line 1083 "awkgram.y" /* yacc.c:1645  */
     {
                if (! in_function)
                        yyerror(_("`return' used outside function context"));
          }
-#line 2894 "awkgram.c" /* yacc.c:1645  */
+#line 2940 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 60:
-#line 1060 "awkgram.y" /* yacc.c:1645  */
+  case 64:
+#line 1086 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-1]) == NULL) {
                        (yyval) = list_create((yyvsp[-3]));
@@ -2905,28 +2951,28 @@ regular_loop:
                if ((yyvsp[0]) != NULL)
                        (yyval) = list_append((yyval), (yyvsp[0]));
          }
-#line 2909 "awkgram.c" /* yacc.c:1645  */
+#line 2955 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 61:
-#line 1071 "awkgram.y" /* yacc.c:1645  */
+  case 65:
+#line 1097 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[0]) != NULL)
                        (yyval) = list_append((yyvsp[-1]), (yyvsp[0]));
                else
                        (yyval) = (yyvsp[-1]);
          }
-#line 2920 "awkgram.c" /* yacc.c:1645  */
+#line 2966 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 62:
-#line 1088 "awkgram.y" /* yacc.c:1645  */
+  case 66:
+#line 1114 "awkgram.y" /* yacc.c:1645  */
     { in_print = true; in_parens = 0; }
-#line 2926 "awkgram.c" /* yacc.c:1645  */
+#line 2972 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 63:
-#line 1089 "awkgram.y" /* yacc.c:1645  */
+  case 67:
+#line 1115 "awkgram.y" /* yacc.c:1645  */
     {
                /*
                 * Optimization: plain `print' has no expression list, so $3 is 
null.
@@ -3023,17 +3069,17 @@ regular_print:
                        }
                }
          }
-#line 3027 "awkgram.c" /* yacc.c:1645  */
+#line 3073 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 64:
-#line 1186 "awkgram.y" /* yacc.c:1645  */
+  case 68:
+#line 1212 "awkgram.y" /* yacc.c:1645  */
     { sub_counter = 0; }
-#line 3033 "awkgram.c" /* yacc.c:1645  */
+#line 3079 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 65:
-#line 1187 "awkgram.y" /* yacc.c:1645  */
+  case 69:
+#line 1213 "awkgram.y" /* yacc.c:1645  */
     {
                char *arr = (yyvsp[-2])->lextok;
 
@@ -3066,11 +3112,11 @@ regular_print:
                        (yyval) = list_append(list_append((yyvsp[0]), 
(yyvsp[-2])), (yyvsp[-3]));
                }
          }
-#line 3070 "awkgram.c" /* yacc.c:1645  */
+#line 3116 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 66:
-#line 1224 "awkgram.y" /* yacc.c:1645  */
+  case 70:
+#line 1250 "awkgram.y" /* yacc.c:1645  */
     {
                static bool warned = false;
                char *arr = (yyvsp[-1])->lextok;
@@ -3096,54 +3142,54 @@ regular_print:
                                fatal(_("`delete' is not allowed with 
FUNCTAB"));
                }
          }
-#line 3100 "awkgram.c" /* yacc.c:1645  */
+#line 3146 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 67:
-#line 1250 "awkgram.y" /* yacc.c:1645  */
+  case 71:
+#line 1276 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = optimize_assignment((yyvsp[0]));
          }
-#line 3108 "awkgram.c" /* yacc.c:1645  */
+#line 3154 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 68:
-#line 1257 "awkgram.y" /* yacc.c:1645  */
+  case 72:
+#line 1283 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3114 "awkgram.c" /* yacc.c:1645  */
+#line 3160 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 69:
-#line 1259 "awkgram.y" /* yacc.c:1645  */
+  case 73:
+#line 1285 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3120 "awkgram.c" /* yacc.c:1645  */
+#line 3166 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 70:
-#line 1264 "awkgram.y" /* yacc.c:1645  */
+  case 74:
+#line 1290 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3126 "awkgram.c" /* yacc.c:1645  */
+#line 3172 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 71:
-#line 1266 "awkgram.y" /* yacc.c:1645  */
+  case 75:
+#line 1292 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-1]) == NULL)
                        (yyval) = list_create((yyvsp[0]));
                else
                        (yyval) = list_prepend((yyvsp[-1]), (yyvsp[0]));
          }
-#line 3137 "awkgram.c" /* yacc.c:1645  */
+#line 3183 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 72:
-#line 1273 "awkgram.y" /* yacc.c:1645  */
+  case 76:
+#line 1299 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3143 "awkgram.c" /* yacc.c:1645  */
+#line 3189 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 73:
-#line 1278 "awkgram.y" /* yacc.c:1645  */
+  case 77:
+#line 1304 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *casestmt = (yyvsp[0]);
                if ((yyvsp[0]) == NULL)
@@ -3156,11 +3202,11 @@ regular_print:
                bcfree((yyvsp[-2]));
                (yyval) = (yyvsp[-4]);
          }
-#line 3160 "awkgram.c" /* yacc.c:1645  */
+#line 3206 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 74:
-#line 1291 "awkgram.y" /* yacc.c:1645  */
+  case 78:
+#line 1317 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *casestmt = (yyvsp[0]);
                if ((yyvsp[0]) == NULL)
@@ -3172,17 +3218,17 @@ regular_print:
                (yyvsp[-3])->comment = (yyvsp[-1]);
                (yyval) = (yyvsp[-3]);
          }
-#line 3176 "awkgram.c" /* yacc.c:1645  */
+#line 3222 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 75:
-#line 1306 "awkgram.y" /* yacc.c:1645  */
+  case 79:
+#line 1332 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = (yyvsp[0]); }
-#line 3182 "awkgram.c" /* yacc.c:1645  */
+#line 3228 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 76:
-#line 1308 "awkgram.y" /* yacc.c:1645  */
+  case 80:
+#line 1334 "awkgram.y" /* yacc.c:1645  */
     {
                NODE *n = (yyvsp[0])->memory;
                (void) force_number(n);
@@ -3190,28 +3236,28 @@ regular_print:
                bcfree((yyvsp[-1]));
                (yyval) = (yyvsp[0]);
          }
-#line 3194 "awkgram.c" /* yacc.c:1645  */
+#line 3240 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 77:
-#line 1316 "awkgram.y" /* yacc.c:1645  */
+  case 81:
+#line 1342 "awkgram.y" /* yacc.c:1645  */
     {
                NODE *n = (yyvsp[0])->lasti->memory;
                bcfree((yyvsp[-1]));
                add_sign_to_num(n, '+');
                (yyval) = (yyvsp[0]);
          }
-#line 3205 "awkgram.c" /* yacc.c:1645  */
+#line 3251 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 78:
-#line 1323 "awkgram.y" /* yacc.c:1645  */
+  case 82:
+#line 1349 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = (yyvsp[0]); }
-#line 3211 "awkgram.c" /* yacc.c:1645  */
+#line 3257 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 79:
-#line 1325 "awkgram.y" /* yacc.c:1645  */
+  case 83:
+#line 1351 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[0])->memory->type == Node_regex)
                        (yyvsp[0])->opcode = Op_push_re;
@@ -3219,57 +3265,57 @@ regular_print:
                        (yyvsp[0])->opcode = Op_push;
                (yyval) = (yyvsp[0]);
          }
-#line 3223 "awkgram.c" /* yacc.c:1645  */
+#line 3269 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 80:
-#line 1333 "awkgram.y" /* yacc.c:1645  */
+  case 84:
+#line 1359 "awkgram.y" /* yacc.c:1645  */
     {
                assert(((yyvsp[0])->memory->flags & REGEX) == REGEX);
                (yyvsp[0])->opcode = Op_push_re;
                (yyval) = (yyvsp[0]);
          }
-#line 3233 "awkgram.c" /* yacc.c:1645  */
+#line 3279 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 81:
-#line 1342 "awkgram.y" /* yacc.c:1645  */
+  case 85:
+#line 1368 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3239 "awkgram.c" /* yacc.c:1645  */
+#line 3285 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 82:
-#line 1344 "awkgram.y" /* yacc.c:1645  */
+  case 86:
+#line 1370 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3245 "awkgram.c" /* yacc.c:1645  */
+#line 3291 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 84:
-#line 1354 "awkgram.y" /* yacc.c:1645  */
+  case 88:
+#line 1380 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = (yyvsp[-1]);
          }
-#line 3253 "awkgram.c" /* yacc.c:1645  */
+#line 3299 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 85:
-#line 1361 "awkgram.y" /* yacc.c:1645  */
+  case 89:
+#line 1387 "awkgram.y" /* yacc.c:1645  */
     {
                in_print = false;
                in_parens = 0;
                (yyval) = NULL;
          }
-#line 3263 "awkgram.c" /* yacc.c:1645  */
+#line 3309 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 86:
-#line 1366 "awkgram.y" /* yacc.c:1645  */
+  case 90:
+#line 1392 "awkgram.y" /* yacc.c:1645  */
     { in_print = false; in_parens = 0; }
-#line 3269 "awkgram.c" /* yacc.c:1645  */
+#line 3315 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 87:
-#line 1367 "awkgram.y" /* yacc.c:1645  */
+  case 91:
+#line 1393 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-2])->redir_type == redirect_twoway
                        && (yyvsp[0])->lasti->opcode == Op_K_getline_redir
@@ -3279,21 +3325,21 @@ regular_print:
                        lintwarn(_("concatenation as I/O `>' redirection target 
is ambiguous"));
                (yyval) = list_prepend((yyvsp[0]), (yyvsp[-2]));
          }
-#line 3283 "awkgram.c" /* yacc.c:1645  */
+#line 3329 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 88:
-#line 1380 "awkgram.y" /* yacc.c:1645  */
+  case 92:
+#line 1406 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-1]) != NULL)
                        (yyvsp[-5])->comment = (yyvsp[-1]);
                (yyval) = mk_condition((yyvsp[-3]), (yyvsp[-5]), (yyvsp[0]), 
NULL, NULL);
          }
-#line 3293 "awkgram.c" /* yacc.c:1645  */
+#line 3339 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 89:
-#line 1387 "awkgram.y" /* yacc.c:1645  */
+  case 93:
+#line 1413 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-4]) != NULL)
                        (yyvsp[-8])->comment = (yyvsp[-4]);
@@ -3301,19 +3347,19 @@ regular_print:
                        (yyvsp[-2])->comment = (yyvsp[-1]);
                (yyval) = mk_condition((yyvsp[-6]), (yyvsp[-8]), (yyvsp[-3]), 
(yyvsp[-2]), (yyvsp[0]));
          }
-#line 3305 "awkgram.c" /* yacc.c:1645  */
+#line 3351 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 90:
-#line 1398 "awkgram.y" /* yacc.c:1645  */
+  case 94:
+#line 1424 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = (yyvsp[0]);
          }
-#line 3313 "awkgram.c" /* yacc.c:1645  */
+#line 3359 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 91:
-#line 1402 "awkgram.y" /* yacc.c:1645  */
+  case 95:
+#line 1428 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-1]) != NULL && (yyvsp[0]) != NULL) {
                        if ((yyvsp[-1])->memory->comment_type == EOL_COMMENT) {
@@ -3331,59 +3377,59 @@ regular_print:
                } else
                        (yyval) = NULL;
          }
-#line 3335 "awkgram.c" /* yacc.c:1645  */
+#line 3381 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 92:
-#line 1423 "awkgram.y" /* yacc.c:1645  */
+  case 96:
+#line 1449 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3341 "awkgram.c" /* yacc.c:1645  */
+#line 3387 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 93:
-#line 1425 "awkgram.y" /* yacc.c:1645  */
+  case 97:
+#line 1451 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3347 "awkgram.c" /* yacc.c:1645  */
+#line 3393 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 94:
-#line 1430 "awkgram.y" /* yacc.c:1645  */
+  case 98:
+#line 1456 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3353 "awkgram.c" /* yacc.c:1645  */
+#line 3399 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 95:
-#line 1432 "awkgram.y" /* yacc.c:1645  */
+  case 99:
+#line 1458 "awkgram.y" /* yacc.c:1645  */
     {
                bcfree((yyvsp[-1]));
                (yyval) = (yyvsp[0]);
          }
-#line 3362 "awkgram.c" /* yacc.c:1645  */
+#line 3408 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 96:
-#line 1440 "awkgram.y" /* yacc.c:1645  */
+  case 100:
+#line 1466 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3368 "awkgram.c" /* yacc.c:1645  */
+#line 3414 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 97:
-#line 1442 "awkgram.y" /* yacc.c:1645  */
+  case 101:
+#line 1468 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3374 "awkgram.c" /* yacc.c:1645  */
+#line 3420 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 98:
-#line 1447 "awkgram.y" /* yacc.c:1645  */
+  case 102:
+#line 1473 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[0])->param_count = 0;
                (yyval) = list_create((yyvsp[0]));
          }
-#line 3383 "awkgram.c" /* yacc.c:1645  */
+#line 3429 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 99:
-#line 1452 "awkgram.y" /* yacc.c:1645  */
+  case 103:
+#line 1478 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-2]) != NULL && (yyvsp[0]) != NULL) {
                        (yyvsp[0])->param_count = 
(yyvsp[-2])->lasti->param_count + 1;
@@ -3400,76 +3446,76 @@ regular_print:
                } else
                        (yyval) = NULL;
          }
-#line 3404 "awkgram.c" /* yacc.c:1645  */
+#line 3450 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 100:
-#line 1469 "awkgram.y" /* yacc.c:1645  */
+  case 104:
+#line 1495 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3410 "awkgram.c" /* yacc.c:1645  */
+#line 3456 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 101:
-#line 1471 "awkgram.y" /* yacc.c:1645  */
+  case 105:
+#line 1497 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[-1]); }
-#line 3416 "awkgram.c" /* yacc.c:1645  */
+#line 3462 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 102:
-#line 1473 "awkgram.y" /* yacc.c:1645  */
+  case 106:
+#line 1499 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[-2]); }
-#line 3422 "awkgram.c" /* yacc.c:1645  */
+#line 3468 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 103:
-#line 1479 "awkgram.y" /* yacc.c:1645  */
+  case 107:
+#line 1505 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3428 "awkgram.c" /* yacc.c:1645  */
+#line 3474 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 104:
-#line 1481 "awkgram.y" /* yacc.c:1645  */
+  case 108:
+#line 1507 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3434 "awkgram.c" /* yacc.c:1645  */
+#line 3480 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 105:
-#line 1486 "awkgram.y" /* yacc.c:1645  */
+  case 109:
+#line 1512 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3440 "awkgram.c" /* yacc.c:1645  */
+#line 3486 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 106:
-#line 1488 "awkgram.y" /* yacc.c:1645  */
+  case 110:
+#line 1514 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3446 "awkgram.c" /* yacc.c:1645  */
+#line 3492 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 107:
-#line 1493 "awkgram.y" /* yacc.c:1645  */
+  case 111:
+#line 1519 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = mk_expression_list(NULL, (yyvsp[0])); }
-#line 3452 "awkgram.c" /* yacc.c:1645  */
+#line 3498 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 108:
-#line 1495 "awkgram.y" /* yacc.c:1645  */
+  case 112:
+#line 1521 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-1]) != NULL)
                        (yyvsp[-2])->lasti->comment = (yyvsp[-1]);
                (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
                yyerrok;
          }
-#line 3463 "awkgram.c" /* yacc.c:1645  */
+#line 3509 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 109:
-#line 1502 "awkgram.y" /* yacc.c:1645  */
+  case 113:
+#line 1528 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3469 "awkgram.c" /* yacc.c:1645  */
+#line 3515 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 110:
-#line 1504 "awkgram.y" /* yacc.c:1645  */
+  case 114:
+#line 1530 "awkgram.y" /* yacc.c:1645  */
     {
                /*
                 * Returning the expression list instead of NULL lets
@@ -3477,66 +3523,66 @@ regular_print:
                 */
                (yyval) = (yyvsp[-1]);
          }
-#line 3481 "awkgram.c" /* yacc.c:1645  */
+#line 3527 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 111:
-#line 1512 "awkgram.y" /* yacc.c:1645  */
+  case 115:
+#line 1538 "awkgram.y" /* yacc.c:1645  */
     {
                /* Ditto */
                (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
          }
-#line 3490 "awkgram.c" /* yacc.c:1645  */
+#line 3536 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 112:
-#line 1517 "awkgram.y" /* yacc.c:1645  */
+  case 116:
+#line 1543 "awkgram.y" /* yacc.c:1645  */
     {
                /* Ditto */
                if ((yyvsp[-1]) != NULL)
                        (yyvsp[-2])->lasti->comment = (yyvsp[-1]);
                (yyval) = (yyvsp[-2]);
          }
-#line 3501 "awkgram.c" /* yacc.c:1645  */
+#line 3547 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 113:
-#line 1527 "awkgram.y" /* yacc.c:1645  */
+  case 117:
+#line 1553 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3507 "awkgram.c" /* yacc.c:1645  */
+#line 3553 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 114:
-#line 1529 "awkgram.y" /* yacc.c:1645  */
+  case 118:
+#line 1555 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3513 "awkgram.c" /* yacc.c:1645  */
+#line 3559 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 115:
-#line 1534 "awkgram.y" /* yacc.c:1645  */
+  case 119:
+#line 1560 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = mk_expression_list(NULL, (yyvsp[0])); }
-#line 3519 "awkgram.c" /* yacc.c:1645  */
+#line 3565 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 116:
-#line 1536 "awkgram.y" /* yacc.c:1645  */
+  case 120:
+#line 1562 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-1]) != NULL)
                        (yyvsp[-2])->lasti->comment = (yyvsp[-1]);
                (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
                yyerrok;
          }
-#line 3530 "awkgram.c" /* yacc.c:1645  */
+#line 3576 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 117:
-#line 1543 "awkgram.y" /* yacc.c:1645  */
+  case 121:
+#line 1569 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 3536 "awkgram.c" /* yacc.c:1645  */
+#line 3582 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 118:
-#line 1545 "awkgram.y" /* yacc.c:1645  */
+  case 122:
+#line 1571 "awkgram.y" /* yacc.c:1645  */
     {
                /*
                 * Returning the expression list instead of NULL lets
@@ -3544,74 +3590,74 @@ regular_print:
                 */
                (yyval) = (yyvsp[-1]);
          }
-#line 3548 "awkgram.c" /* yacc.c:1645  */
+#line 3594 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 119:
-#line 1553 "awkgram.y" /* yacc.c:1645  */
+  case 123:
+#line 1579 "awkgram.y" /* yacc.c:1645  */
     {
                /* Ditto */
                (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
          }
-#line 3557 "awkgram.c" /* yacc.c:1645  */
+#line 3603 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 120:
-#line 1558 "awkgram.y" /* yacc.c:1645  */
+  case 124:
+#line 1584 "awkgram.y" /* yacc.c:1645  */
     {
                /* Ditto */
                if ((yyvsp[-1]) != NULL)
                        (yyvsp[-2])->comment = (yyvsp[-1]);
                (yyval) = (yyvsp[-2]);
          }
-#line 3568 "awkgram.c" /* yacc.c:1645  */
+#line 3614 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 121:
-#line 1567 "awkgram.y" /* yacc.c:1645  */
+  case 125:
+#line 1593 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3574 "awkgram.c" /* yacc.c:1645  */
+#line 3620 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 122:
-#line 1568 "awkgram.y" /* yacc.c:1645  */
+  case 126:
+#line 1594 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = list_create((yyvsp[0])); }
-#line 3580 "awkgram.c" /* yacc.c:1645  */
+#line 3626 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 123:
-#line 1574 "awkgram.y" /* yacc.c:1645  */
+  case 127:
+#line 1600 "awkgram.y" /* yacc.c:1645  */
     {
                if (do_lint && (yyvsp[0])->lasti->opcode == Op_match_rec)
                        lintwarn_ln((yyvsp[-1])->source_line,
                                _("regular expression on right of assignment"));
                (yyval) = mk_assignment((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1]));
          }
-#line 3591 "awkgram.c" /* yacc.c:1645  */
+#line 3637 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 124:
-#line 1581 "awkgram.y" /* yacc.c:1645  */
+  case 128:
+#line 1607 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = mk_assignment((yyvsp[-2]), list_create((yyvsp[0])), 
(yyvsp[-1]));
          }
-#line 3599 "awkgram.c" /* yacc.c:1645  */
+#line 3645 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 125:
-#line 1585 "awkgram.y" /* yacc.c:1645  */
+  case 129:
+#line 1611 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3605 "awkgram.c" /* yacc.c:1645  */
+#line 3651 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 126:
-#line 1587 "awkgram.y" /* yacc.c:1645  */
+  case 130:
+#line 1613 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3611 "awkgram.c" /* yacc.c:1645  */
+#line 3657 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 127:
-#line 1589 "awkgram.y" /* yacc.c:1645  */
+  case 131:
+#line 1615 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-2])->lasti->opcode == Op_match_rec)
                        warning_ln((yyvsp[-1])->source_line,
@@ -3624,11 +3670,11 @@ regular_print:
                bcfree((yyvsp[0]));
                (yyval) = list_append((yyvsp[-2]), (yyvsp[-1]));
          }
-#line 3628 "awkgram.c" /* yacc.c:1645  */
+#line 3674 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 128:
-#line 1602 "awkgram.y" /* yacc.c:1645  */
+  case 132:
+#line 1628 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[-2])->lasti->opcode == Op_match_rec)
                        warning_ln((yyvsp[-1])->source_line,
@@ -3645,11 +3691,11 @@ regular_print:
                        (yyval) = list_append(list_merge((yyvsp[-2]), 
(yyvsp[0])), (yyvsp[-1]));
                }
          }
-#line 3649 "awkgram.c" /* yacc.c:1645  */
+#line 3695 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 129:
-#line 1619 "awkgram.y" /* yacc.c:1645  */
+  case 133:
+#line 1645 "awkgram.y" /* yacc.c:1645  */
     {
                if (do_lint_old)
                        warning_ln((yyvsp[-1])->source_line,
@@ -3659,91 +3705,91 @@ regular_print:
                (yyvsp[-1])->expr_count = 1;
                (yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), 
(yyvsp[-1]));
          }
-#line 3663 "awkgram.c" /* yacc.c:1645  */
+#line 3709 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 130:
-#line 1629 "awkgram.y" /* yacc.c:1645  */
+  case 134:
+#line 1655 "awkgram.y" /* yacc.c:1645  */
     {
                if (do_lint && (yyvsp[0])->lasti->opcode == Op_match_rec)
                        lintwarn_ln((yyvsp[-1])->source_line,
                                _("regular expression on right of comparison"));
                (yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), 
(yyvsp[-1]));
          }
-#line 3674 "awkgram.c" /* yacc.c:1645  */
+#line 3720 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 131:
-#line 1636 "awkgram.y" /* yacc.c:1645  */
+  case 135:
+#line 1662 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_condition((yyvsp[-4]), (yyvsp[-3]), (yyvsp[-2]), 
(yyvsp[-1]), (yyvsp[0])); }
-#line 3680 "awkgram.c" /* yacc.c:1645  */
+#line 3726 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 132:
-#line 1638 "awkgram.y" /* yacc.c:1645  */
+  case 136:
+#line 1664 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3686 "awkgram.c" /* yacc.c:1645  */
+#line 3732 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 133:
-#line 1643 "awkgram.y" /* yacc.c:1645  */
+  case 137:
+#line 1669 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3692 "awkgram.c" /* yacc.c:1645  */
+#line 3738 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 134:
-#line 1645 "awkgram.y" /* yacc.c:1645  */
+  case 138:
+#line 1671 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3698 "awkgram.c" /* yacc.c:1645  */
+#line 3744 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 135:
-#line 1647 "awkgram.y" /* yacc.c:1645  */
+  case 139:
+#line 1673 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[0])->opcode = Op_assign_quotient;
                (yyval) = (yyvsp[0]);
          }
-#line 3707 "awkgram.c" /* yacc.c:1645  */
+#line 3753 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 136:
-#line 1655 "awkgram.y" /* yacc.c:1645  */
+  case 140:
+#line 1681 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3713 "awkgram.c" /* yacc.c:1645  */
+#line 3759 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 137:
-#line 1657 "awkgram.y" /* yacc.c:1645  */
+  case 141:
+#line 1683 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3719 "awkgram.c" /* yacc.c:1645  */
+#line 3765 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 138:
-#line 1662 "awkgram.y" /* yacc.c:1645  */
+  case 142:
+#line 1688 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3725 "awkgram.c" /* yacc.c:1645  */
+#line 3771 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 139:
-#line 1664 "awkgram.y" /* yacc.c:1645  */
+  case 143:
+#line 1690 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3731 "awkgram.c" /* yacc.c:1645  */
+#line 3777 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 140:
-#line 1669 "awkgram.y" /* yacc.c:1645  */
+  case 144:
+#line 1695 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3737 "awkgram.c" /* yacc.c:1645  */
+#line 3783 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 141:
-#line 1671 "awkgram.y" /* yacc.c:1645  */
+  case 145:
+#line 1697 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 3743 "awkgram.c" /* yacc.c:1645  */
+#line 3789 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 142:
-#line 1673 "awkgram.y" /* yacc.c:1645  */
+  case 146:
+#line 1699 "awkgram.y" /* yacc.c:1645  */
     {
                int count = 2;
                bool is_simple_var = false;
@@ -3797,47 +3843,47 @@ regular_print:
                                max_args = count;
                }
          }
-#line 3801 "awkgram.c" /* yacc.c:1645  */
+#line 3847 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 144:
-#line 1732 "awkgram.y" /* yacc.c:1645  */
+  case 148:
+#line 1758 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3807 "awkgram.c" /* yacc.c:1645  */
+#line 3853 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 145:
-#line 1734 "awkgram.y" /* yacc.c:1645  */
+  case 149:
+#line 1760 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3813 "awkgram.c" /* yacc.c:1645  */
+#line 3859 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 146:
-#line 1736 "awkgram.y" /* yacc.c:1645  */
+  case 150:
+#line 1762 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3819 "awkgram.c" /* yacc.c:1645  */
+#line 3865 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 147:
-#line 1738 "awkgram.y" /* yacc.c:1645  */
+  case 151:
+#line 1764 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3825 "awkgram.c" /* yacc.c:1645  */
+#line 3871 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 148:
-#line 1740 "awkgram.y" /* yacc.c:1645  */
+  case 152:
+#line 1766 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3831 "awkgram.c" /* yacc.c:1645  */
+#line 3877 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 149:
-#line 1742 "awkgram.y" /* yacc.c:1645  */
+  case 153:
+#line 1768 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3837 "awkgram.c" /* yacc.c:1645  */
+#line 3883 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 150:
-#line 1744 "awkgram.y" /* yacc.c:1645  */
+  case 154:
+#line 1770 "awkgram.y" /* yacc.c:1645  */
     {
                /*
                 * In BEGINFILE/ENDFILE, allow `getline [var] < file'
@@ -3851,29 +3897,29 @@ regular_print:
                                _("non-redirected `getline' undefined inside 
END action"));
                (yyval) = mk_getline((yyvsp[-2]), (yyvsp[-1]), (yyvsp[0]), 
redirect_input);
          }
-#line 3855 "awkgram.c" /* yacc.c:1645  */
+#line 3901 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 151:
-#line 1758 "awkgram.y" /* yacc.c:1645  */
+  case 155:
+#line 1784 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[0])->opcode = Op_postincrement;
                (yyval) = mk_assignment((yyvsp[-1]), NULL, (yyvsp[0]));
          }
-#line 3864 "awkgram.c" /* yacc.c:1645  */
+#line 3910 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 152:
-#line 1763 "awkgram.y" /* yacc.c:1645  */
+  case 156:
+#line 1789 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[0])->opcode = Op_postdecrement;
                (yyval) = mk_assignment((yyvsp[-1]), NULL, (yyvsp[0]));
          }
-#line 3873 "awkgram.c" /* yacc.c:1645  */
+#line 3919 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 153:
-#line 1768 "awkgram.y" /* yacc.c:1645  */
+  case 157:
+#line 1794 "awkgram.y" /* yacc.c:1645  */
     {
                if (do_lint_old) {
                    warning_ln((yyvsp[-1])->source_line,
@@ -3893,64 +3939,64 @@ regular_print:
                        (yyval) = list_append(list_merge(t, (yyvsp[0])), 
(yyvsp[-1]));
                }
          }
-#line 3897 "awkgram.c" /* yacc.c:1645  */
+#line 3943 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 154:
-#line 1793 "awkgram.y" /* yacc.c:1645  */
+  case 158:
+#line 1819 "awkgram.y" /* yacc.c:1645  */
     {
                  (yyval) = mk_getline((yyvsp[-1]), (yyvsp[0]), (yyvsp[-3]), 
(yyvsp[-2])->redir_type);
                  bcfree((yyvsp[-2]));
                }
-#line 3906 "awkgram.c" /* yacc.c:1645  */
+#line 3952 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 155:
-#line 1799 "awkgram.y" /* yacc.c:1645  */
+  case 159:
+#line 1825 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3912 "awkgram.c" /* yacc.c:1645  */
+#line 3958 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 156:
-#line 1801 "awkgram.y" /* yacc.c:1645  */
+  case 160:
+#line 1827 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3918 "awkgram.c" /* yacc.c:1645  */
+#line 3964 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 157:
-#line 1803 "awkgram.y" /* yacc.c:1645  */
+  case 161:
+#line 1829 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3924 "awkgram.c" /* yacc.c:1645  */
+#line 3970 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 158:
-#line 1805 "awkgram.y" /* yacc.c:1645  */
+  case 162:
+#line 1831 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3930 "awkgram.c" /* yacc.c:1645  */
+#line 3976 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 159:
-#line 1807 "awkgram.y" /* yacc.c:1645  */
+  case 163:
+#line 1833 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3936 "awkgram.c" /* yacc.c:1645  */
+#line 3982 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 160:
-#line 1809 "awkgram.y" /* yacc.c:1645  */
+  case 164:
+#line 1835 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3942 "awkgram.c" /* yacc.c:1645  */
+#line 3988 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 161:
-#line 1814 "awkgram.y" /* yacc.c:1645  */
+  case 165:
+#line 1840 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = list_create((yyvsp[0]));
          }
-#line 3950 "awkgram.c" /* yacc.c:1645  */
+#line 3996 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 162:
-#line 1818 "awkgram.y" /* yacc.c:1645  */
+  case 166:
+#line 1844 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[0])->opcode == Op_match_rec) {
                        (yyvsp[0])->opcode = Op_nomatch;
@@ -3982,11 +4028,11 @@ regular_print:
                        }
                }
           }
-#line 3986 "awkgram.c" /* yacc.c:1645  */
+#line 4032 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 163:
-#line 1850 "awkgram.y" /* yacc.c:1645  */
+  case 167:
+#line 1876 "awkgram.y" /* yacc.c:1645  */
     {
                // Always include. Allows us to lint warn on
                // print "foo" > "bar" 1
@@ -3994,31 +4040,31 @@ regular_print:
                // print "foo" > ("bar" 1)
                (yyval) = list_append((yyvsp[-1]), bcalloc(Op_parens, 1, 
sourceline));
          }
-#line 3998 "awkgram.c" /* yacc.c:1645  */
+#line 4044 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 164:
-#line 1858 "awkgram.y" /* yacc.c:1645  */
+  case 168:
+#line 1884 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = snode((yyvsp[-1]), (yyvsp[-3]));
                if ((yyval) == NULL)
                        YYABORT;
          }
-#line 4008 "awkgram.c" /* yacc.c:1645  */
+#line 4054 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 165:
-#line 1864 "awkgram.y" /* yacc.c:1645  */
+  case 169:
+#line 1890 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = snode((yyvsp[-1]), (yyvsp[-3]));
                if ((yyval) == NULL)
                        YYABORT;
          }
-#line 4018 "awkgram.c" /* yacc.c:1645  */
+#line 4064 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 166:
-#line 1870 "awkgram.y" /* yacc.c:1645  */
+  case 170:
+#line 1896 "awkgram.y" /* yacc.c:1645  */
     {
                static bool warned = false;
 
@@ -4031,45 +4077,45 @@ regular_print:
                if ((yyval) == NULL)
                        YYABORT;
          }
-#line 4035 "awkgram.c" /* yacc.c:1645  */
+#line 4081 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 169:
-#line 1885 "awkgram.y" /* yacc.c:1645  */
+  case 173:
+#line 1911 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[-1])->opcode = Op_preincrement;
                (yyval) = mk_assignment((yyvsp[0]), NULL, (yyvsp[-1]));
          }
-#line 4044 "awkgram.c" /* yacc.c:1645  */
+#line 4090 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 170:
-#line 1890 "awkgram.y" /* yacc.c:1645  */
+  case 174:
+#line 1916 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[-1])->opcode = Op_predecrement;
                (yyval) = mk_assignment((yyvsp[0]), NULL, (yyvsp[-1]));
          }
-#line 4053 "awkgram.c" /* yacc.c:1645  */
+#line 4099 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 171:
-#line 1895 "awkgram.y" /* yacc.c:1645  */
+  case 175:
+#line 1921 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = list_create((yyvsp[0]));
          }
-#line 4061 "awkgram.c" /* yacc.c:1645  */
+#line 4107 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 172:
-#line 1899 "awkgram.y" /* yacc.c:1645  */
+  case 176:
+#line 1925 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = list_create((yyvsp[0]));
          }
-#line 4069 "awkgram.c" /* yacc.c:1645  */
+#line 4115 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 173:
-#line 1903 "awkgram.y" /* yacc.c:1645  */
+  case 177:
+#line 1929 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[0])->lasti->opcode == Op_push_i
                        && ((yyvsp[0])->lasti->memory->flags & STRING) == 0
@@ -4084,11 +4130,11 @@ regular_print:
                        (yyval) = list_append((yyvsp[0]), (yyvsp[-1]));
                }
          }
-#line 4088 "awkgram.c" /* yacc.c:1645  */
+#line 4134 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 174:
-#line 1918 "awkgram.y" /* yacc.c:1645  */
+  case 178:
+#line 1944 "awkgram.y" /* yacc.c:1645  */
     {
                if ((yyvsp[0])->lasti->opcode == Op_push_i
                        && ((yyvsp[0])->lasti->memory->flags & STRING) == 0
@@ -4106,20 +4152,20 @@ regular_print:
                        (yyval) = list_append((yyvsp[0]), (yyvsp[-1]));
                }
          }
-#line 4110 "awkgram.c" /* yacc.c:1645  */
+#line 4156 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 175:
-#line 1939 "awkgram.y" /* yacc.c:1645  */
+  case 179:
+#line 1965 "awkgram.y" /* yacc.c:1645  */
     {
                func_use((yyvsp[0])->lasti->func_name, FUNC_USE);
                (yyval) = (yyvsp[0]);
          }
-#line 4119 "awkgram.c" /* yacc.c:1645  */
+#line 4165 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 176:
-#line 1944 "awkgram.y" /* yacc.c:1645  */
+  case 180:
+#line 1970 "awkgram.y" /* yacc.c:1645  */
     {
                /* indirect function call */
                INSTRUCTION *f, *t;
@@ -4153,16 +4199,28 @@ regular_print:
                (yyval) = list_prepend((yyvsp[0]), t);
                at_seen = false;
          }
-#line 4157 "awkgram.c" /* yacc.c:1645  */
+#line 4203 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 177:
-#line 1981 "awkgram.y" /* yacc.c:1645  */
+  case 181:
+#line 2007 "awkgram.y" /* yacc.c:1645  */
     {
                NODE *n;
+               const char *name = (yyvsp[-3])->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);
+
+                       efree((void *) (yyvsp[-3])->func_name);
+                       (yyvsp[-3])->func_name = buf;
+               }
 
                if (! at_seen) {
-                       n = lookup((yyvsp[-3])->func_name);
+                       n = lookup((yyvsp[-3])->func_name, true);
                        if (n != NULL && n->type != Node_func
                            && n->type != Node_ext_func) {
                                error_ln((yyvsp[-3])->source_line,
@@ -4170,6 +4228,7 @@ regular_print:
                                                (yyvsp[-3])->func_name);
                        }
                }
+
                param_sanity((yyvsp[-1]));
                (yyvsp[-3])->opcode = Op_func_call;
                (yyvsp[-3])->func_body = NULL;
@@ -4182,49 +4241,49 @@ regular_print:
                        (yyval) = list_append(t, (yyvsp[-3]));
                }
          }
-#line 4186 "awkgram.c" /* yacc.c:1645  */
+#line 4245 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 178:
-#line 2009 "awkgram.y" /* yacc.c:1645  */
+  case 182:
+#line 2048 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 4192 "awkgram.c" /* yacc.c:1645  */
+#line 4251 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 179:
-#line 2011 "awkgram.y" /* yacc.c:1645  */
+  case 183:
+#line 2050 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 4198 "awkgram.c" /* yacc.c:1645  */
+#line 4257 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 180:
-#line 2016 "awkgram.y" /* yacc.c:1645  */
+  case 184:
+#line 2055 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 4204 "awkgram.c" /* yacc.c:1645  */
+#line 4263 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 181:
-#line 2018 "awkgram.y" /* yacc.c:1645  */
+  case 185:
+#line 2057 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[-1]); }
-#line 4210 "awkgram.c" /* yacc.c:1645  */
+#line 4269 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 182:
-#line 2023 "awkgram.y" /* yacc.c:1645  */
+  case 186:
+#line 2062 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = (yyvsp[0]); }
-#line 4216 "awkgram.c" /* yacc.c:1645  */
+#line 4275 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 183:
-#line 2025 "awkgram.y" /* yacc.c:1645  */
+  case 187:
+#line 2064 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = list_merge((yyvsp[-1]), (yyvsp[0]));
          }
-#line 4224 "awkgram.c" /* yacc.c:1645  */
+#line 4283 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 184:
-#line 2032 "awkgram.y" /* yacc.c:1645  */
+  case 188:
+#line 2071 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *ip = (yyvsp[0])->lasti;
                int count = ip->sub_count;      /* # of SUBSEP-seperated 
expressions */
@@ -4238,11 +4297,11 @@ regular_print:
                sub_counter++;  /* count # of dimensions */
                (yyval) = (yyvsp[0]);
          }
-#line 4242 "awkgram.c" /* yacc.c:1645  */
+#line 4301 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 185:
-#line 2049 "awkgram.y" /* yacc.c:1645  */
+  case 189:
+#line 2088 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *t = (yyvsp[-1]);
                if ((yyvsp[-1]) == NULL) {
@@ -4256,31 +4315,31 @@ regular_print:
                        (yyvsp[0])->sub_count = count_expressions(&t, false);
                (yyval) = list_append(t, (yyvsp[0]));
          }
-#line 4260 "awkgram.c" /* yacc.c:1645  */
+#line 4319 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 186:
-#line 2066 "awkgram.y" /* yacc.c:1645  */
+  case 190:
+#line 2105 "awkgram.y" /* yacc.c:1645  */
     {  (yyval) = (yyvsp[0]); }
-#line 4266 "awkgram.c" /* yacc.c:1645  */
+#line 4325 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 187:
-#line 2068 "awkgram.y" /* yacc.c:1645  */
+  case 191:
+#line 2107 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = list_merge((yyvsp[-1]), (yyvsp[0]));
          }
-#line 4274 "awkgram.c" /* yacc.c:1645  */
+#line 4333 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 188:
-#line 2075 "awkgram.y" /* yacc.c:1645  */
+  case 192:
+#line 2114 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[-1]); }
-#line 4280 "awkgram.c" /* yacc.c:1645  */
+#line 4339 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 189:
-#line 2080 "awkgram.y" /* yacc.c:1645  */
+  case 193:
+#line 2119 "awkgram.y" /* yacc.c:1645  */
     {
                char *var_name = (yyvsp[0])->lextok;
 
@@ -4288,22 +4347,22 @@ regular_print:
                (yyvsp[0])->memory = variable((yyvsp[0])->source_line, 
var_name, Node_var_new);
                (yyval) = list_create((yyvsp[0]));
          }
-#line 4292 "awkgram.c" /* yacc.c:1645  */
+#line 4351 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 190:
-#line 2088 "awkgram.y" /* yacc.c:1645  */
+  case 194:
+#line 2127 "awkgram.y" /* yacc.c:1645  */
     {
                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 4303 "awkgram.c" /* yacc.c:1645  */
+#line 4362 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 191:
-#line 2098 "awkgram.y" /* yacc.c:1645  */
+  case 195:
+#line 2137 "awkgram.y" /* yacc.c:1645  */
     {
                INSTRUCTION *ip = (yyvsp[0])->nexti;
                if (ip->opcode == Op_push
@@ -4315,85 +4374,85 @@ regular_print:
                } else
                        (yyval) = (yyvsp[0]);
          }
-#line 4319 "awkgram.c" /* yacc.c:1645  */
+#line 4378 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 192:
-#line 2110 "awkgram.y" /* yacc.c:1645  */
+  case 196:
+#line 2149 "awkgram.y" /* yacc.c:1645  */
     {
                (yyval) = list_append((yyvsp[-1]), (yyvsp[-2]));
                if ((yyvsp[0]) != NULL)
                        mk_assignment((yyvsp[-1]), NULL, (yyvsp[0]));
          }
-#line 4329 "awkgram.c" /* yacc.c:1645  */
+#line 4388 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 193:
-#line 2119 "awkgram.y" /* yacc.c:1645  */
+  case 197:
+#line 2158 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[0])->opcode = Op_postincrement;
          }
-#line 4337 "awkgram.c" /* yacc.c:1645  */
+#line 4396 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 194:
-#line 2123 "awkgram.y" /* yacc.c:1645  */
+  case 198:
+#line 2162 "awkgram.y" /* yacc.c:1645  */
     {
                (yyvsp[0])->opcode = Op_postdecrement;
          }
-#line 4345 "awkgram.c" /* yacc.c:1645  */
+#line 4404 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 195:
-#line 2127 "awkgram.y" /* yacc.c:1645  */
+  case 199:
+#line 2166 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 4351 "awkgram.c" /* yacc.c:1645  */
+#line 4410 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 196:
-#line 2131 "awkgram.y" /* yacc.c:1645  */
+  case 200:
+#line 2170 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); }
-#line 4357 "awkgram.c" /* yacc.c:1645  */
+#line 4416 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 197:
-#line 2135 "awkgram.y" /* yacc.c:1645  */
+  case 201:
+#line 2174 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); yyerrok; }
-#line 4363 "awkgram.c" /* yacc.c:1645  */
+#line 4422 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 198:
-#line 2139 "awkgram.y" /* yacc.c:1645  */
+  case 202:
+#line 2178 "awkgram.y" /* yacc.c:1645  */
     { yyerrok; }
-#line 4369 "awkgram.c" /* yacc.c:1645  */
+#line 4428 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 199:
-#line 2144 "awkgram.y" /* yacc.c:1645  */
+  case 203:
+#line 2183 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = NULL; }
-#line 4375 "awkgram.c" /* yacc.c:1645  */
+#line 4434 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 201:
-#line 2149 "awkgram.y" /* yacc.c:1645  */
+  case 205:
+#line 2188 "awkgram.y" /* yacc.c:1645  */
     { yyerrok; }
-#line 4381 "awkgram.c" /* yacc.c:1645  */
+#line 4440 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 202:
-#line 2153 "awkgram.y" /* yacc.c:1645  */
+  case 206:
+#line 2192 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); yyerrok; }
-#line 4387 "awkgram.c" /* yacc.c:1645  */
+#line 4446 "awkgram.c" /* yacc.c:1645  */
     break;
 
-  case 203:
-#line 2157 "awkgram.y" /* yacc.c:1645  */
+  case 207:
+#line 2196 "awkgram.y" /* yacc.c:1645  */
     { (yyval) = (yyvsp[0]); yyerrok; }
-#line 4393 "awkgram.c" /* yacc.c:1645  */
+#line 4452 "awkgram.c" /* yacc.c:1645  */
     break;
 
 
-#line 4397 "awkgram.c" /* yacc.c:1645  */
+#line 4456 "awkgram.c" /* yacc.c:1645  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -4620,7 +4679,7 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 2159 "awkgram.y" /* yacc.c:1903  */
+#line 2198 "awkgram.y" /* yacc.c:1903  */
 
 
 struct token {
@@ -4673,7 +4732,7 @@ static const struct token tokentab[] = {
 {"BEGIN",      Op_rule,         LEX_BEGIN,     0,              0,      0},
 {"BEGINFILE",  Op_rule,         LEX_BEGINFILE, GAWKX,          0,      0},
 {"END",                Op_rule,         LEX_END,       0,              0,      
0},
-{"ENDFILE",            Op_rule,         LEX_ENDFILE,   GAWKX,          0,      
0},
+{"ENDFILE",    Op_rule,         LEX_ENDFILE,   GAWKX,          0,      0},
 #ifdef ARRAYDEBUG
 {"adump",      Op_builtin,    LEX_BUILTIN,     GAWKX|A(1)|A(2)|DEBUG_USE,      
do_adump,       0},
 #endif
@@ -4719,6 +4778,7 @@ static const struct token tokentab[] = {
 {"lshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_lshift,      
MPF(lshift)},
 {"match",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2)|A(3), do_match,    
0},
 {"mktime",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2), do_mktime, 0},
+{"namespace",          Op_symbol,       LEX_NAMESPACE, GAWKX,          0,      
0},
 {"next",       Op_K_next,       LEX_NEXT,      0,              0,      0},
 {"nextfile",   Op_K_nextfile, LEX_NEXTFILE,    0,              0,      0},
 {"or",         Op_builtin,    LEX_BUILTIN,     GAWKX,          do_or,  
MPF(or)},
@@ -4765,15 +4825,22 @@ static int cur_ring_idx;
 /* getfname --- return name of a builtin function (for pretty printing) */
 
 const char *
-getfname(NODE *(*fptr)(int))
+getfname(NODE *(*fptr)(int), bool prepend_awk)
 {
        int i, j;
+       static char buf[100];
 
        j = sizeof(tokentab) / sizeof(tokentab[0]);
        /* linear search, no other way to do it */
-       for (i = 0; i < j; i++)
-               if (tokentab[i].ptr == fptr || tokentab[i].ptr2 == fptr)
+       for (i = 0; i < j; i++) {
+               if (tokentab[i].ptr == fptr || tokentab[i].ptr2 == fptr) {
+                       if (prepend_awk && (tokentab[i].flags & GAWKX) != 0) {
+                               sprintf(buf, "awk::%s", tokentab[i].operator);
+                               return buf;
+                       }
                        return tokentab[i].operator;
+               }
+       }
 
        return NULL;
 }
@@ -4938,6 +5005,9 @@ yyerror(const char *m, ...)
        char *buf;
        int count;
        static char end_of_file_line[] = "(END OF FILE)";
+       static char syntax_error[] = "syntax error";
+       static size_t syn_err_len = sizeof(syntax_error) - 1;
+       bool generic_error = (strncmp(m, syntax_error, syn_err_len) == 0);
 
        print_included_from();
 
@@ -4968,7 +5038,11 @@ yyerror(const char *m, ...)
                bp = thisline + strlen(thisline);
        }
 
-       msg("%.*s", (int) (bp - thisline), thisline);
+       if (lexeof && mesg == NULL && generic_error) {
+               msg("%s", end_of_file_line);
+               mesg = _("source files / command-line arguments must contain 
complete functions or rules");
+       } else
+               msg("%.*s", (int) (bp - thisline), thisline);
 
        va_start(args, m);
        if (mesg == NULL)
@@ -5336,6 +5410,7 @@ include_source(INSTRUCTION *file, void **srcfile_p)
        sourcefile->lexptr_begin = lexptr_begin;
        sourcefile->lexeme = lexeme;
        sourcefile->lasttok = lasttok;
+       sourcefile->namespace = current_namespace;
 
        /* included file becomes the current source */
        sourcefile = s;
@@ -5345,6 +5420,7 @@ include_source(INSTRUCTION *file, void **srcfile_p)
        lasttok = 0;
        lexeof = false;
        eof_warned = false;
+       current_namespace = awk_namespace;
        *srcfile_p = (void *) s;
        return true;
 }
@@ -5450,11 +5526,15 @@ next_sourcefile()
                lexeme = sourcefile->lexeme;
                sourceline = sourcefile->srclines;
                source = sourcefile->src;
+               if (current_namespace != awk_namespace)
+                       efree((char *) current_namespace);
+               current_namespace = sourcefile->namespace;
        } else {
                lexptr = NULL;
                sourceline = 0;
                source = NULL;
                lasttok = 0;
+               current_namespace = awk_namespace;
        }
 }
 
@@ -5700,6 +5780,9 @@ check_bad_char(int c)
 
 /* nextc --- get the next input character */
 
+// For namespaces, -e chunks must be syntactic units.
+#define NO_CONTINUE_SOURCE_STRINGS     1
+
 static int
 nextc(bool check_for_bad)
 {
@@ -5787,6 +5870,7 @@ again:
                return END_SRC;
        }
 }
+#undef NO_CONTINUE_SOURCE_STRINGS
 
 /* pushback --- push a character back on the input */
 
@@ -6707,18 +6791,39 @@ retry:
        while (c != END_FILE && is_identchar(c)) {
                tokadd(c);
                c = nextc(true);
+
+               if (! do_traditional && c == ':') {
+                       int peek = nextc(true);
+
+                       if (peek == ':') {      // saw identifier::
+                               tokadd(c);
+                               tokadd(c);
+                               c = nextc(true);
+                       } else
+                               pushback();
+                               // then continue around the loop, c == ':'
+               }
        }
        tokadd('\0');
        pushback();
 
+       (void) validate_qualified_name(tokstart);
+
        /* See if it is a special token. */
-       if ((mid = check_special(tokstart)) >= 0) {
+       if ((mid = check_qualified_special(tokstart)) >= 0) {
                static int warntab[sizeof(tokentab) / sizeof(tokentab[0])];
                int class = tokentab[mid].class;
 
-               if ((class == LEX_INCLUDE || class == LEX_LOAD || class == 
LEX_EVAL)
-                               && lasttok != '@')
-                       goto out;
+               switch (class) {
+               case LEX_EVAL:
+               case LEX_INCLUDE:
+               case LEX_LOAD:
+               case LEX_NAMESPACE:
+                       if (lasttok != '@')
+                               goto out;
+               default:
+                       break;
+               }
 
                /* allow parameter names to shadow the names of gawk extension 
built-ins */
                if ((tokentab[mid].flags & GAWKX) != 0) {
@@ -6730,7 +6835,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)) != NULL) {
+                               if ((f = lookup(tokstart, false)) != NULL) {
                                        if (f->type == Node_builtin_func)
                                                break;
                                        else
@@ -6773,6 +6878,7 @@ retry:
                        continue_allowed++;
 
                switch (class) {
+               case LEX_NAMESPACE:
                case LEX_INCLUDE:
                case LEX_LOAD:
                        want_source = true;
@@ -6792,7 +6898,7 @@ retry:
                case LEX_END:
                case LEX_BEGINFILE:
                case LEX_ENDFILE:
-                       yylval = bcalloc(tokentab[mid].value, 3, sourceline);
+                       yylval = bcalloc(tokentab[mid].value, 4, sourceline);
                        break;
 
                case LEX_FOR:
@@ -7225,7 +7331,7 @@ parms_shadow(INSTRUCTION *pc, bool *shadow)
         * about all shadowed parameters.
         */
        for (i = 0; i < pcount; i++) {
-               if (lookup(fp[i].param) != NULL) {
+               if (lookup(fp[i].param, false) != NULL) {
                        warning(
        _("function `%s': parameter `%s' shadows global variable"),
                                        fname, fp[i].param);
@@ -7357,8 +7463,11 @@ mk_function(INSTRUCTION *fi, INSTRUCTION *def)
                trailing_comment = NULL;
        }
 
-       if (do_pretty_print)
+       if (do_pretty_print) {
+               fi[3].nexti = namespace_chain;
+               namespace_chain = NULL;
                (void) list_prepend(def, instruction(Op_exec_count));
+       }
 
        /* fi->opcode = Op_func */
        (fi + 1)->firsti = def->nexti;
@@ -7390,7 +7499,7 @@ install_function(char *fname, INSTRUCTION *fi, 
INSTRUCTION *plist)
        NODE *r, *f;
        int pcount = 0;
 
-       r = lookup(fname);
+       r = lookup(fname, true);
        if (r != NULL) {
                error_ln(fi->source_line, _("function name `%s' previously 
defined"), fname);
                return -1;
@@ -7443,7 +7552,10 @@ 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, ':') != NULL)
+                       error_ln(p->source_line,
+                               _("function `%s': parameter `%s' cannot contain 
a namespace"),
+                                       fname, name);
 
                /* check for duplicate parameters */
                for (j = 0; j < i; j++) {
@@ -7587,7 +7699,7 @@ variable(int location, char *name, NODETYPE type)
 {
        NODE *r;
 
-       if ((r = lookup(name)) != NULL) {
+       if ((r = lookup(name, true)) != 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);
@@ -8054,8 +8166,11 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
 
        if (rule != Rule) {
                rp = pattern;
-               if (do_pretty_print)
+               if (do_pretty_print) {
+                       rp[3].nexti = namespace_chain;
+                       namespace_chain = NULL;
                        (void) list_append(action, instruction(Op_no_op));
+               }
                (rp + 1)->firsti = action->nexti;
                (rp + 1)->lasti = action->lasti;
                (rp + 2)->first_line = pattern->source_line;
@@ -8066,11 +8181,16 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
                        interblock_comment = NULL;
                }
        } else {
-               rp = bcalloc(Op_rule, 3, 0);
+               rp = bcalloc(Op_rule, 4, 0);
                rp->in_rule = Rule;
                rp->source_file = source;
                tp = instruction(Op_no_op);
 
+               if (do_pretty_print) {
+                       rp[3].nexti = namespace_chain;
+                       namespace_chain = NULL;
+               }
+
                if (pattern == NULL) {
                        /* assert(action != NULL); */
                        if (do_pretty_print)
@@ -8788,6 +8908,9 @@ one_line_close(int fd)
 builtin_func_t
 lookup_builtin(const char *name)
 {
+       if (strncmp(name, "awk::", 5) == 0)
+               name += 5;
+
        int mid = check_special(name);
 
        if (mid == -1)
@@ -9018,3 +9141,170 @@ make_braced_statements(INSTRUCTION *lbrace, INSTRUCTION 
*stmts, INSTRUCTION *rbr
 
        return ip;
 }
+
+/* validate_qualified_name --- make sure that a qualified name is built 
correctly */
+
+/*
+ * This routine returns upon first error, no need to produce multiple, possibly
+ * conflicting / confusing error messages.
+ */
+
+bool
+validate_qualified_name(char *token)
+{
+       char *cp, *cp2;
+
+       // no colon, by definition it's well formed
+       if ((cp = strchr(token, ':')) == NULL)
+               return true;
+
+       if (do_traditional || do_posix) {
+               error_ln(sourceline, _("identifier %s: qualified names not 
allowed in traditional / POSIX mode"), token);
+               return false;
+       }
+
+       if (cp[1] != ':') {     // could happen from command line
+               error_ln(sourceline, _("identifier %s: namespace separator is 
two colons, not one"), token);
+               return false;
+       }
+
+       if (! is_letter(cp[2])) {
+               error_ln(sourceline,
+                               _("qualified identifier `%s' is badly formed"),
+                               token);
+               return false;
+       }
+
+       if ((cp2 = strchr(cp+2, ':')) != NULL) {
+               error_ln(sourceline,
+                       _("identifier `%s': namespace separator can only appear 
once in a qualified name"),
+                       token);
+               return false;
+       }
+
+       return true;
+}
+
+/* check_qualified_special --- decide if a name is special or not */
+
+static int
+check_qualified_special(char *token)
+{
+       char *cp;
+
+       if ((cp = strchr(token, ':')) == NULL && current_namespace == 
awk_namespace)
+               return check_special(token);
+
+       /*
+        * Now it's more complicated.  Here are the rules.
+        *
+        * 1. Namespace name cannot be a standard awk reserved word or function.
+        * 2. Subordinate part of the name cannot be standard awk reserved word 
or function.
+        * 3. If namespace part is explicitly "awk", return result of 
check_special().
+        * 4. Else return -1 (gawk extensions allowed, we check standard awk in 
step 2).
+        */
+
+       const struct token *tok;
+       int i;
+       if (cp == NULL) {       // namespace not awk, but a simple identifier
+               i = check_special(token);
+               if (i < 0)
+                       return i;
+
+               tok = & tokentab[i];
+               if ((tok->flags & GAWKX) != 0 && tok->class == LEX_BUILTIN)
+                       return -1;
+               else
+                       return i;
+       }
+
+       char *ns, *end, *subname;
+       ns = token;
+       *(end = cp) = '\0';     // temporarily turn it into standalone string
+       subname = end + 2;
+
+       // First check the namespace part
+       i = check_special(ns);
+       if (i >= 0 && (tokentab[i].flags & GAWKX) == 0) {
+               error_ln(sourceline, _("using reserved identifier `%s' as a 
namespace is not allowed"), ns);
+               goto done;
+       }
+
+       // Now check the subordinate part
+       i = check_special(subname);
+       if (i >= 0 && (tokentab[i].flags & GAWKX) == 0 && strcmp(ns, "awk") != 
0) {
+               error_ln(sourceline, _("using reserved identifier `%s' as 
second component of a qualified name is not allowed"), subname);
+               goto done;
+       }
+
+       if (strcmp(ns, "awk") == 0) {
+               i = check_special(subname);
+               if (i >= 0) {
+                       if ((tokentab[i].flags & GAWKX) != 0 && 
tokentab[i].class == LEX_BUILTIN)
+                               ;       // gawk additional builtin function, is 
ok
+                       else
+                               error_ln(sourceline, _("using reserved 
identifier `%s' as second component of a qualified name is not allowed"), 
subname);
+               }
+       } else
+               i = -1;
+done:
+       *end = ':';
+       return i;
+}
+
+/* set_namespace --- change the current namespace */
+
+static void
+set_namespace(INSTRUCTION *ns, INSTRUCTION *comment)
+{
+       if (ns == NULL)
+               return;
+
+       if (do_traditional || do_posix) {
+               error_ln(ns->source_line, _("@namespace is a gawk extension"));
+               efree(ns->lextok);
+               bcfree(ns);
+               return;
+       }
+
+       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;
+       }
+
+       int mid = check_special(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;
+       }
+
+       if (strcmp(ns->lextok, current_namespace) == 0)
+               efree(ns->lextok);
+       else if (strcmp(ns->lextok, awk_namespace) == 0) {
+               efree(ns->lextok);
+               current_namespace = awk_namespace;
+       } else {
+               if (current_namespace != awk_namespace)
+                       efree((char *) current_namespace);
+               current_namespace = ns->lextok;
+       }
+
+       // save info and push on front of list of namespaces seen
+       INSTRUCTION *new_ns = instruction(Op_K_namespace);
+       new_ns->comment = comment;
+       new_ns->ns_name = estrdup(current_namespace, strlen(current_namespace));
+       new_ns->nexti = namespace_chain;
+       namespace_chain = new_ns;
+
+       ns->lextok = NULL;
+       bcfree(ns);
+
+       namespace_changed = true;
+
+       return;
+}
diff --git a/awkgram.y b/awkgram.y
index e0af4c1..49ac3ef 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -55,13 +55,16 @@ static void dumpintlstr(const char *str, size_t len);
 static void dumpintlstr2(const char *str1, size_t len1, const char *str2, 
size_t len2);
 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 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 INSTRUCTION *trailing_comment;
 static INSTRUCTION *outer_comment;
 static INSTRUCTION *interblock_comment;
 static INSTRUCTION *pending_comment;
+static INSTRUCTION *namespace_chain;
 
 #ifdef DEBUG_COMMENTS
 static void
@@ -159,6 +162,10 @@ extern INSTRUCTION *rule_list;
 extern int max_args;
 extern NODE **args_array;
 
+const char awk_namespace[] = "awk";
+const char *current_namespace = awk_namespace;
+bool namespace_changed = false;
+
 static INSTRUCTION *rule_block[sizeof(ruletab)];
 
 static INSTRUCTION *ip_rec;
@@ -193,7 +200,7 @@ extern double fmod(double x, double y);
 %token LEX_AND LEX_OR INCREMENT DECREMENT
 %token LEX_BUILTIN LEX_LENGTH
 %token LEX_EOF
-%token LEX_INCLUDE LEX_EVAL LEX_LOAD
+%token LEX_INCLUDE LEX_EVAL LEX_LOAD LEX_NAMESPACE
 %token NEWLINE
 
 /* Lowest to highest */
@@ -305,6 +312,16 @@ rule
                }
                yyerrok;
          }
+       | '@' LEX_NAMESPACE namespace statement_term
+         {
+               want_source = false;
+               at_seen = false;
+
+               // this frees $3 storage in all cases
+               set_namespace($3, $4);
+
+               yyerrok;
+         }
        ;
 
 source
@@ -341,6 +358,15 @@ library
          { $$ = NULL; }
        ;
 
+namespace
+       : FILENAME
+         { $$ = $1; }
+       | FILENAME error
+         { $$ = NULL; }
+       | error
+         { $$ = NULL; }
+       ;
+
 pattern
        : /* empty */
          {
@@ -1980,9 +2006,21 @@ 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);
+
+                       efree((void *) $1->func_name);
+                       $1->func_name = buf;
+               }
 
                if (! at_seen) {
-                       n = lookup($1->func_name);
+                       n = lookup($1->func_name, true);
                        if (n != NULL && n->type != Node_func
                            && n->type != Node_ext_func) {
                                error_ln($1->source_line,
@@ -1990,6 +2028,7 @@ direct_func_call
                                                $1->func_name);
                        }
                }
+
                param_sanity($3);
                $1->opcode = Op_func_call;
                $1->func_body = NULL;
@@ -2208,7 +2247,7 @@ static const struct token tokentab[] = {
 {"BEGIN",      Op_rule,         LEX_BEGIN,     0,              0,      0},
 {"BEGINFILE",  Op_rule,         LEX_BEGINFILE, GAWKX,          0,      0},
 {"END",                Op_rule,         LEX_END,       0,              0,      
0},
-{"ENDFILE",            Op_rule,         LEX_ENDFILE,   GAWKX,          0,      
0},
+{"ENDFILE",    Op_rule,         LEX_ENDFILE,   GAWKX,          0,      0},
 #ifdef ARRAYDEBUG
 {"adump",      Op_builtin,    LEX_BUILTIN,     GAWKX|A(1)|A(2)|DEBUG_USE,      
do_adump,       0},
 #endif
@@ -2254,6 +2293,7 @@ static const struct token tokentab[] = {
 {"lshift",     Op_builtin,    LEX_BUILTIN,     GAWKX|A(2),     do_lshift,      
MPF(lshift)},
 {"match",      Op_builtin,      LEX_BUILTIN,   NOT_OLD|A(2)|A(3), do_match,    
0},
 {"mktime",     Op_builtin,      LEX_BUILTIN,   GAWKX|A(1)|A(2), do_mktime, 0},
+{"namespace",          Op_symbol,       LEX_NAMESPACE, GAWKX,          0,      
0},
 {"next",       Op_K_next,       LEX_NEXT,      0,              0,      0},
 {"nextfile",   Op_K_nextfile, LEX_NEXTFILE,    0,              0,      0},
 {"or",         Op_builtin,    LEX_BUILTIN,     GAWKX,          do_or,  
MPF(or)},
@@ -2300,15 +2340,22 @@ static int cur_ring_idx;
 /* getfname --- return name of a builtin function (for pretty printing) */
 
 const char *
-getfname(NODE *(*fptr)(int))
+getfname(NODE *(*fptr)(int), bool prepend_awk)
 {
        int i, j;
+       static char buf[100];
 
        j = sizeof(tokentab) / sizeof(tokentab[0]);
        /* linear search, no other way to do it */
-       for (i = 0; i < j; i++)
-               if (tokentab[i].ptr == fptr || tokentab[i].ptr2 == fptr)
+       for (i = 0; i < j; i++) {
+               if (tokentab[i].ptr == fptr || tokentab[i].ptr2 == fptr) {
+                       if (prepend_awk && (tokentab[i].flags & GAWKX) != 0) {
+                               sprintf(buf, "awk::%s", tokentab[i].operator);
+                               return buf;
+                       }
                        return tokentab[i].operator;
+               }
+       }
 
        return NULL;
 }
@@ -2473,6 +2520,9 @@ yyerror(const char *m, ...)
        char *buf;
        int count;
        static char end_of_file_line[] = "(END OF FILE)";
+       static char syntax_error[] = "syntax error";
+       static size_t syn_err_len = sizeof(syntax_error) - 1;
+       bool generic_error = (strncmp(m, syntax_error, syn_err_len) == 0);
 
        print_included_from();
 
@@ -2503,7 +2553,11 @@ yyerror(const char *m, ...)
                bp = thisline + strlen(thisline);
        }
 
-       msg("%.*s", (int) (bp - thisline), thisline);
+       if (lexeof && mesg == NULL && generic_error) {
+               msg("%s", end_of_file_line);
+               mesg = _("source files / command-line arguments must contain 
complete functions or rules");
+       } else
+               msg("%.*s", (int) (bp - thisline), thisline);
 
        va_start(args, m);
        if (mesg == NULL)
@@ -2871,6 +2925,7 @@ include_source(INSTRUCTION *file, void **srcfile_p)
        sourcefile->lexptr_begin = lexptr_begin;
        sourcefile->lexeme = lexeme;
        sourcefile->lasttok = lasttok;
+       sourcefile->namespace = current_namespace;
 
        /* included file becomes the current source */
        sourcefile = s;
@@ -2880,6 +2935,7 @@ include_source(INSTRUCTION *file, void **srcfile_p)
        lasttok = 0;
        lexeof = false;
        eof_warned = false;
+       current_namespace = awk_namespace;
        *srcfile_p = (void *) s;
        return true;
 }
@@ -2985,11 +3041,15 @@ next_sourcefile()
                lexeme = sourcefile->lexeme;
                sourceline = sourcefile->srclines;
                source = sourcefile->src;
+               if (current_namespace != awk_namespace)
+                       efree((char *) current_namespace);
+               current_namespace = sourcefile->namespace;
        } else {
                lexptr = NULL;
                sourceline = 0;
                source = NULL;
                lasttok = 0;
+               current_namespace = awk_namespace;
        }
 }
 
@@ -3235,6 +3295,9 @@ check_bad_char(int c)
 
 /* nextc --- get the next input character */
 
+// For namespaces, -e chunks must be syntactic units.
+#define NO_CONTINUE_SOURCE_STRINGS     1
+
 static int
 nextc(bool check_for_bad)
 {
@@ -3322,6 +3385,7 @@ again:
                return END_SRC;
        }
 }
+#undef NO_CONTINUE_SOURCE_STRINGS
 
 /* pushback --- push a character back on the input */
 
@@ -4242,18 +4306,39 @@ retry:
        while (c != END_FILE && is_identchar(c)) {
                tokadd(c);
                c = nextc(true);
+
+               if (! do_traditional && c == ':') {
+                       int peek = nextc(true);
+
+                       if (peek == ':') {      // saw identifier::
+                               tokadd(c);
+                               tokadd(c);
+                               c = nextc(true);
+                       } else
+                               pushback();
+                               // then continue around the loop, c == ':'
+               }
        }
        tokadd('\0');
        pushback();
 
+       (void) validate_qualified_name(tokstart);
+
        /* See if it is a special token. */
-       if ((mid = check_special(tokstart)) >= 0) {
+       if ((mid = check_qualified_special(tokstart)) >= 0) {
                static int warntab[sizeof(tokentab) / sizeof(tokentab[0])];
                int class = tokentab[mid].class;
 
-               if ((class == LEX_INCLUDE || class == LEX_LOAD || class == 
LEX_EVAL)
-                               && lasttok != '@')
-                       goto out;
+               switch (class) {
+               case LEX_EVAL:
+               case LEX_INCLUDE:
+               case LEX_LOAD:
+               case LEX_NAMESPACE:
+                       if (lasttok != '@')
+                               goto out;
+               default:
+                       break;
+               }
 
                /* allow parameter names to shadow the names of gawk extension 
built-ins */
                if ((tokentab[mid].flags & GAWKX) != 0) {
@@ -4265,7 +4350,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)) != NULL) {
+                               if ((f = lookup(tokstart, false)) != NULL) {
                                        if (f->type == Node_builtin_func)
                                                break;
                                        else
@@ -4308,6 +4393,7 @@ retry:
                        continue_allowed++;
 
                switch (class) {
+               case LEX_NAMESPACE:
                case LEX_INCLUDE:
                case LEX_LOAD:
                        want_source = true;
@@ -4327,7 +4413,7 @@ retry:
                case LEX_END:
                case LEX_BEGINFILE:
                case LEX_ENDFILE:
-                       yylval = bcalloc(tokentab[mid].value, 3, sourceline);
+                       yylval = bcalloc(tokentab[mid].value, 4, sourceline);
                        break;
 
                case LEX_FOR:
@@ -4760,7 +4846,7 @@ parms_shadow(INSTRUCTION *pc, bool *shadow)
         * about all shadowed parameters.
         */
        for (i = 0; i < pcount; i++) {
-               if (lookup(fp[i].param) != NULL) {
+               if (lookup(fp[i].param, false) != NULL) {
                        warning(
        _("function `%s': parameter `%s' shadows global variable"),
                                        fname, fp[i].param);
@@ -4892,8 +4978,11 @@ mk_function(INSTRUCTION *fi, INSTRUCTION *def)
                trailing_comment = NULL;
        }
 
-       if (do_pretty_print)
+       if (do_pretty_print) {
+               fi[3].nexti = namespace_chain;
+               namespace_chain = NULL;
                (void) list_prepend(def, instruction(Op_exec_count));
+       }
 
        /* fi->opcode = Op_func */
        (fi + 1)->firsti = def->nexti;
@@ -4925,7 +5014,7 @@ install_function(char *fname, INSTRUCTION *fi, 
INSTRUCTION *plist)
        NODE *r, *f;
        int pcount = 0;
 
-       r = lookup(fname);
+       r = lookup(fname, true);
        if (r != NULL) {
                error_ln(fi->source_line, _("function name `%s' previously 
defined"), fname);
                return -1;
@@ -4978,7 +5067,10 @@ 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, ':') != NULL)
+                       error_ln(p->source_line,
+                               _("function `%s': parameter `%s' cannot contain 
a namespace"),
+                                       fname, name);
 
                /* check for duplicate parameters */
                for (j = 0; j < i; j++) {
@@ -5122,7 +5214,7 @@ variable(int location, char *name, NODETYPE type)
 {
        NODE *r;
 
-       if ((r = lookup(name)) != NULL) {
+       if ((r = lookup(name, true)) != 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);
@@ -5589,8 +5681,11 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
 
        if (rule != Rule) {
                rp = pattern;
-               if (do_pretty_print)
+               if (do_pretty_print) {
+                       rp[3].nexti = namespace_chain;
+                       namespace_chain = NULL;
                        (void) list_append(action, instruction(Op_no_op));
+               }
                (rp + 1)->firsti = action->nexti;
                (rp + 1)->lasti = action->lasti;
                (rp + 2)->first_line = pattern->source_line;
@@ -5601,11 +5696,16 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
                        interblock_comment = NULL;
                }
        } else {
-               rp = bcalloc(Op_rule, 3, 0);
+               rp = bcalloc(Op_rule, 4, 0);
                rp->in_rule = Rule;
                rp->source_file = source;
                tp = instruction(Op_no_op);
 
+               if (do_pretty_print) {
+                       rp[3].nexti = namespace_chain;
+                       namespace_chain = NULL;
+               }
+
                if (pattern == NULL) {
                        /* assert(action != NULL); */
                        if (do_pretty_print)
@@ -6323,6 +6423,9 @@ one_line_close(int fd)
 builtin_func_t
 lookup_builtin(const char *name)
 {
+       if (strncmp(name, "awk::", 5) == 0)
+               name += 5;
+
        int mid = check_special(name);
 
        if (mid == -1)
@@ -6553,3 +6656,170 @@ make_braced_statements(INSTRUCTION *lbrace, INSTRUCTION 
*stmts, INSTRUCTION *rbr
 
        return ip;
 }
+
+/* validate_qualified_name --- make sure that a qualified name is built 
correctly */
+
+/*
+ * This routine returns upon first error, no need to produce multiple, possibly
+ * conflicting / confusing error messages.
+ */
+
+bool
+validate_qualified_name(char *token)
+{
+       char *cp, *cp2;
+
+       // no colon, by definition it's well formed
+       if ((cp = strchr(token, ':')) == NULL)
+               return true;
+
+       if (do_traditional || do_posix) {
+               error_ln(sourceline, _("identifier %s: qualified names not 
allowed in traditional / POSIX mode"), token);
+               return false;
+       }
+
+       if (cp[1] != ':') {     // could happen from command line
+               error_ln(sourceline, _("identifier %s: namespace separator is 
two colons, not one"), token);
+               return false;
+       }
+
+       if (! is_letter(cp[2])) {
+               error_ln(sourceline,
+                               _("qualified identifier `%s' is badly formed"),
+                               token);
+               return false;
+       }
+
+       if ((cp2 = strchr(cp+2, ':')) != NULL) {
+               error_ln(sourceline,
+                       _("identifier `%s': namespace separator can only appear 
once in a qualified name"),
+                       token);
+               return false;
+       }
+
+       return true;
+}
+
+/* check_qualified_special --- decide if a name is special or not */
+
+static int
+check_qualified_special(char *token)
+{
+       char *cp;
+
+       if ((cp = strchr(token, ':')) == NULL && current_namespace == 
awk_namespace)
+               return check_special(token);
+
+       /*
+        * Now it's more complicated.  Here are the rules.
+        *
+        * 1. Namespace name cannot be a standard awk reserved word or function.
+        * 2. Subordinate part of the name cannot be standard awk reserved word 
or function.
+        * 3. If namespace part is explicitly "awk", return result of 
check_special().
+        * 4. Else return -1 (gawk extensions allowed, we check standard awk in 
step 2).
+        */
+
+       const struct token *tok;
+       int i;
+       if (cp == NULL) {       // namespace not awk, but a simple identifier
+               i = check_special(token);
+               if (i < 0)
+                       return i;
+
+               tok = & tokentab[i];
+               if ((tok->flags & GAWKX) != 0 && tok->class == LEX_BUILTIN)
+                       return -1;
+               else
+                       return i;
+       }
+
+       char *ns, *end, *subname;
+       ns = token;
+       *(end = cp) = '\0';     // temporarily turn it into standalone string
+       subname = end + 2;
+
+       // First check the namespace part
+       i = check_special(ns);
+       if (i >= 0 && (tokentab[i].flags & GAWKX) == 0) {
+               error_ln(sourceline, _("using reserved identifier `%s' as a 
namespace is not allowed"), ns);
+               goto done;
+       }
+
+       // Now check the subordinate part
+       i = check_special(subname);
+       if (i >= 0 && (tokentab[i].flags & GAWKX) == 0 && strcmp(ns, "awk") != 
0) {
+               error_ln(sourceline, _("using reserved identifier `%s' as 
second component of a qualified name is not allowed"), subname);
+               goto done;
+       }
+
+       if (strcmp(ns, "awk") == 0) {
+               i = check_special(subname);
+               if (i >= 0) {
+                       if ((tokentab[i].flags & GAWKX) != 0 && 
tokentab[i].class == LEX_BUILTIN)
+                               ;       // gawk additional builtin function, is 
ok
+                       else
+                               error_ln(sourceline, _("using reserved 
identifier `%s' as second component of a qualified name is not allowed"), 
subname);
+               }
+       } else
+               i = -1;
+done:
+       *end = ':';
+       return i;
+}
+
+/* set_namespace --- change the current namespace */
+
+static void
+set_namespace(INSTRUCTION *ns, INSTRUCTION *comment)
+{
+       if (ns == NULL)
+               return;
+
+       if (do_traditional || do_posix) {
+               error_ln(ns->source_line, _("@namespace is a gawk extension"));
+               efree(ns->lextok);
+               bcfree(ns);
+               return;
+       }
+
+       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;
+       }
+
+       int mid = check_special(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;
+       }
+
+       if (strcmp(ns->lextok, current_namespace) == 0)
+               efree(ns->lextok);
+       else if (strcmp(ns->lextok, awk_namespace) == 0) {
+               efree(ns->lextok);
+               current_namespace = awk_namespace;
+       } else {
+               if (current_namespace != awk_namespace)
+                       efree((char *) current_namespace);
+               current_namespace = ns->lextok;
+       }
+
+       // save info and push on front of list of namespaces seen
+       INSTRUCTION *new_ns = instruction(Op_K_namespace);
+       new_ns->comment = comment;
+       new_ns->ns_name = estrdup(current_namespace, strlen(current_namespace));
+       new_ns->nexti = namespace_chain;
+       namespace_chain = new_ns;
+
+       ns->lextok = NULL;
+       bcfree(ns);
+
+       namespace_changed = true;
+
+       return;
+}
diff --git a/awklib/eg/lib/inplace.awk b/awklib/eg/lib/inplace.awk
index 6771bc4..68dad92 100644
--- a/awklib/eg/lib/inplace.awk
+++ b/awklib/eg/lib/inplace.awk
@@ -21,11 +21,15 @@
 #
 # Andrew J. Schorr, address@hidden
 # January 2013
+#
+# Revised for namespaces
+# Arnold Robbins, address@hidden
+# July 2017
 
 @load "inplace"
 
-# Please set INPLACE_SUFFIX to make a backup copy.  For example, you may
-# want to set INPLACE_SUFFIX to .bak on the command line or in a BEGIN rule.
+# Please set inplace::suffix to make a backup copy.  For example, you may
+# want to set inplace::suffix to .bak on the command line or in a BEGIN rule.
 
 # By default, each filename on the command line will be edited inplace.
 # But you can selectively disable this by adding an inplace=0 argument
@@ -33,23 +37,25 @@
 # reenable it later on the commandline by putting inplace=1 before files
 # that you wish to be subject to inplace editing.
 
-# N.B. We call inplace_end() in the BEGINFILE and END rules so that any
+# N.B. We call inplace::end() in the BEGINFILE and END rules so that any
 # actions in an ENDFILE rule will be redirected as expected.
 
address@hidden "inplace"
+
 BEGIN {
-    inplace = 1         # enabled by default
+    enable = 1         # enabled by default
 }
 
 BEGINFILE {
-    if (_inplace_filename != "")
-        inplace_end(_inplace_filename, INPLACE_SUFFIX)
-    if (inplace)
-        inplace_begin(_inplace_filename = FILENAME, INPLACE_SUFFIX)
+    if (filename != "")
+        end(filename, suffix)
+    if (enable)
+        begin(filename = FILENAME, suffix)
     else
-        _inplace_filename = ""
+        filename = ""
 }
 
 END {
-    if (_inplace_filename != "")
-        inplace_end(_inplace_filename, INPLACE_SUFFIX)
+    if (filename != "")
+        end(filename, suffix)
 }
diff --git a/awklib/eg/lib/ns_passwd.awk b/awklib/eg/lib/ns_passwd.awk
new file mode 100644
index 0000000..b9b6bce
--- /dev/null
+++ b/awklib/eg/lib/ns_passwd.awk
@@ -0,0 +1,72 @@
+# ns_passwd.awk --- access password file information
+#
+# Arnold Robbins, address@hidden, Public Domain
+# May 1993
+# Revised October 2000
+# Revised December 2010
+#
+# Reworked for namespaces June 2017, with help from
+# Andrew J.: Schorr, address@hidden
+
address@hidden "passwd"
+
+BEGIN {
+    # tailor this to suit your system
+    Awklib = "/usr/local/libexec/awk/"
+}
+
+function Init(    oldfs, oldrs, olddol0, pwcat, using_fw, using_fpat)
+{
+    if (Inited)
+        return
+
+    oldfs = FS
+    oldrs = RS
+    olddol0 = $0
+    using_fw = (PROCINFO["FS"] == "FIELDWIDTHS")
+    using_fpat = (PROCINFO["FS"] == "FPAT")
+    FS = ":"
+    RS = "\n"
+
+    pwcat = Awklib "pwcat"
+    while ((pwcat | getline) > 0) {
+        Byname[$1] = $0
+        Byuid[$3] = $0
+        Bycount[++Total] = $0
+    }
+    close(pwcat)
+    Count = 0
+    Inited = 1
+    FS = oldfs
+    if (using_fw)
+        FIELDWIDTHS = FIELDWIDTHS
+    else if (using_fpat)
+        FPAT = FPAT
+    RS = oldrs
+    $0 = olddol0
+}
+
+function awk::getpwnam(name)
+{
+    Init()
+    return Byname[name]
+}
+
+function awk::getpwuid(uid)
+{
+    Init()
+    return Byuid[uid]
+}
+
+function awk::getpwent()
+{
+    Init()
+    if (Count < Total)
+        return Bycount[++Count]
+    return ""
+}
+
+function awk::endpwent()
+{
+    Count = 0
+}
diff --git a/command.c b/command.c
index c8ee163..b076530 100644
--- a/command.c
+++ b/command.c
@@ -1954,7 +1954,7 @@ yyreduce:
 #line 472 "command.y" /* yacc.c:1645  */
     {
                NODE *n;
-               n = lookup((yyvsp[0])->a_string);
+               n = lookup((yyvsp[0])->a_string, true);
                if (n == NULL || n->type != Node_func)
                        yyerror(_("no such function - \"%s\""), 
(yyvsp[0])->a_string);
                else {
diff --git a/command.y b/command.y
index 58880de..553a7c3 100644
--- a/command.y
+++ b/command.y
@@ -471,7 +471,7 @@ func_name
        : D_STRING
          {
                NODE *n;
-               n = lookup($1->a_string);
+               n = lookup($1->a_string, true);
                if (n == NULL || n->type != Node_func)
                        yyerror(_("no such function - \"%s\""), $1->a_string);
                else {
diff --git a/debug.c b/debug.c
index 6c6a59f..f8aa6ad 100644
--- a/debug.c
+++ b/debug.c
@@ -310,6 +310,7 @@ static void delete_item(struct list_item *d);
 static int breakpoint_triggered(BREAKPOINT *b);
 static int watchpoint_triggered(struct list_item *w);
 static void print_instruction(INSTRUCTION *pc, Func_print print_func, FILE 
*fp, int in_dump);
+static void print_ns_list(INSTRUCTION *pc, Func_print print_func, FILE *fp, 
int in_dump);
 static int print_code(INSTRUCTION *pc, void *x);
 static void next_command();
 static void debug_post_execute(INSTRUCTION *pc);
@@ -1031,7 +1032,7 @@ NODE *find_symbol(const char *name, char **pname)
        if (prog_running)
                r = find_param(name, cur_frame, pname);
        if (r == NULL)
-               r = lookup(name);
+               r = lookup(name, false); // for now, require fully qualified 
name
        if (r == NULL)
                fprintf(out_fp, _("no symbol `%s' in current context\n"), name);
        return r;
@@ -3882,8 +3883,13 @@ print_instruction(INSTRUCTION *pc, Func_print 
print_func, FILE *fp, int in_dump)
                break;
 
        case Op_func:
-               print_func(fp, "[param_cnt = %d] [source_file = %s]\n", pcount,
+               print_func(fp, "[param_cnt = %d] [source_file = %s]", pcount,
                                pc->source_file ? pc->source_file : "cmd. 
line");
+               if (pc[3].nexti != NULL) {
+                       print_func(fp, "[ns_list = %p]\n", pc[3].nexti);
+                       print_ns_list(pc[3].nexti, print_func, fp, in_dump);
+               } else
+                       print_func(fp, "\n");
                break;
 
        case Op_K_getline_redir:
@@ -3958,6 +3964,15 @@ print_instruction(INSTRUCTION *pc, Func_print 
print_func, FILE *fp, int in_dump)
                        print_func(fp, "\n");
                break;
 
+       case Op_K_namespace:
+               print_func(fp, "[namespace = %s]", pc->ns_name);
+               if (pc->nexti)
+                       print_func(fp, "[nexti = %p]", pc->nexti);
+               if (pc->comment)
+                       print_func(fp, "[comment = %p]", pc->comment);
+               print_func(fp, "\n");
+               break;
+
        case Op_arrayfor_incr:
                print_func(fp, "[array_var = %s] [target_jmp = %p]\n",
                                pc->array_var->type == Node_param_list ?
@@ -3996,7 +4011,7 @@ print_instruction(INSTRUCTION *pc, Func_print print_func, 
FILE *fp, int in_dump)
                break;
 
        case Op_builtin:
-               print_func(fp, "%s [arg_count = %ld]\n", getfname(pc->builtin),
+               print_func(fp, "%s [arg_count = %ld]\n", getfname(pc->builtin, 
false),
                                                pc->expr_count);
                break;
 
@@ -4034,9 +4049,14 @@ print_instruction(INSTRUCTION *pc, Func_print 
print_func, FILE *fp, int in_dump)
                break;
 
        case Op_rule:
-               print_func(fp, "[in_rule = %s] [source_file = %s]\n",
+               print_func(fp, "[in_rule = %s] [source_file = %s]",
                                ruletab[pc->in_rule],
                                pc->source_file ? pc->source_file : "cmd. 
line");
+               if (pc[3].nexti != NULL) {
+                       print_func(fp, "[ns_list = %p]\n", pc[3].nexti);
+                       print_ns_list(pc[3].nexti, print_func, fp, in_dump);
+               } else
+                       print_func(fp, "\n");
                break;
 
        case Op_lint:
@@ -4130,6 +4150,18 @@ print_code(INSTRUCTION *pc, void *x)
        return 0;
 }
 
+/* print_ns_list --- print the list of namespaces */
+
+static void
+print_ns_list(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump)
+{
+       for (; pc != NULL; pc = pc->nexti) {
+               print_instruction(pc, print_func, fp, in_dump);
+               if (pc->comment != NULL)
+                       print_instruction(pc->comment, print_func, fp, in_dump);
+       }
+}
+
 /* do_dump_instructions --- dump command */
 
 int
@@ -5574,7 +5606,7 @@ do_eval(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
                return false;
        }
 
-       f = lookup("@eval");
+       f = lookup("@eval", false);
        assert(f != NULL);
        if (this_func == NULL) {        /* in main */
                /* do a function call */
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 270bdf2..ef83d89 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -21,6 +21,27 @@
        * gawktexi.in: Some small indexing fixes. Thanks to Antonio
        Giovanni Colombo for pointing them out.
 
+2019-01-02         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in: A few more fixes w.r.t. namespaces. Thanks to
+       Antonio Giovanni Colombo for pointing out the problems.
+
+2018-12-31         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in: A few fixes w.r.t. namespaces. Thanks to
+       Antonio Giovanni Colombo for pointing out the problems.
+
+2018-12-18         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in: Added more indexing to the debugger chapter.
+       Add more indexing to namespaces chapter, too.
+
+2018-12-12         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in: Clean up some FIXMEs and other improvements.
+       * gawk.1: Mention that files read with -f and -i and command
+       line segments all implicitly start with @namespace "awk".
+
 2018-12-18         Arnold D. Robbins     <address@hidden>
 
        * gawktexi.in: Added more indexing to the debugger chapter.
@@ -403,6 +424,15 @@
        * gawkexti.in: Remove sentence indicating that isarray is deprecated
        and recommending typeof instead.
 
+2017-10-16         Arnold D. Robbins     <address@hidden>
+
+       * awkcard.in: Add @namespaces to Execution section.
+
+2017-10-12         Arnold D. Robbins     <address@hidden>
+
+       * gawk.1: Documents namespaces.
+       * awkcard.in: Ditto.
+
 2017-10-10         Arnold D. Robbins     <address@hidden>
 
        * gawktexi.in (Readfile Function): Fix the code for the naive
@@ -511,6 +541,11 @@
 
        * texinfo.tex: Updated.
 
+2017-08-02         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespace Summary): Add summary to namespace
+       chapter.
+
 2017-08-01         Arnold D. Robbins     <address@hidden>
 
        * gawktexi.in: Update with info about DJGPP port now
@@ -520,6 +555,8 @@
 
        * gawktexi.in (Type Functions): Improve the example
        for untyped variables.
+       (Extension Exercises): Remove the exercise that talks
+       about namespaces, since it's no longer relevant.
 
 2017-07-28         Arnold D. Robbins     <address@hidden>
 
@@ -527,15 +564,60 @@
        inplace.awk; should have done that when it was first
        added. Oops.
 
+2017-07-26         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): More edits.
+
 2017-07-21         Arnold D. Robbins     <address@hidden>
 
        * gawktexi.in: Fix a spelling error.
        * wordlist: Update with more words.
 
+       Done also for namespace material.
+
+2017-07-20         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Extension Sample Inplace): Rework to use the
+       "inplace" namespace.
+
+       * gawktexi.in (Namespace And Features): Renamed from
+       `Namespace Misc' and reworked.
+       (Symbol table by name): Add note about namespace and
+       component name rules with xref to section in Namespaces chapter.
+
+2017-07-19         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): Cleanup, new section on naming rules
+       added.
+
+2017-07-17         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): Revised password suite example.
+       (Symbol table by name): Add entries for namespace versions
+       of lookup and update routines.
+
+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.
+
 2017-07-02         Arnold D. Robbins     <address@hidden>
 
        * texinfo.tex: Pull in latest from Texinfo SVN.
 
+2017-06-30         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): Move to later in the book.
+
+2017-06-23         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): More minor doc edits.
+
 2017-06-19         Andrew J. Schorr     <address@hidden>
 
        * gawktexi.in (Memory Allocation Functions and Convenience Macros):
@@ -548,11 +630,42 @@
 2017-06-15         Arnold D. Robbins     <address@hidden>
 
        * gawktexi.in: Expand tab characters.
+       * gawktexi.in (Namespaces): Further minor doc edits, including
+       hyphenation hint.
+
+2017-06-13         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): Document that reserved words and
+       predefined functions can be namespace names but can be in
+       the second part of a fully qualified name. (Design decision
+       change.)
+
+2017-06-11         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): Document that reserved words and
+       predefined functions can't be namespace names. Reformat the
+       input a little bit.
+
+2017-06-06         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): Further clarifications. Move to
+       `::' as the namespace separator.
 
 2017-06-05         Andrew J. Schorr     <address@hidden>
 
        * gawktexi.in (Checking for MPFR): Fix typo.
 
+2017-06-02         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in (Namespaces): Fixes in passwd.awk example. Document
+       that indirect calls with an unadorned name assume "awk" namespace.
+
+2017-05-30         Arnold D. Robbins     <address@hidden>
+
+       * gawktexi.in: Initial doc on namespaces. Serves as a design
+       right now.
+       * gawktexi.in: More doc added.
+
 2017-05-30         Arnold D. Robbins     <address@hidden>
 
        * gawktexi.in: Document PROCINFO["argv"].
diff --git a/doc/awkcard.in b/doc/awkcard.in
index d4df342..1a6b72f 100644
--- a/doc/awkcard.in
+++ b/doc/awkcard.in
@@ -47,7 +47,8 @@
 .ES
 .in +.2i
 .nf
-\*(FRAction Statements        9
+\*(FRAcknowledgements 9
+Action Statements     9
 Arrays        7
 Awk Program Execution 5
 Bit Manipulation Functions (\*(GK)    17
@@ -70,6 +71,7 @@ Input Control        13
 Internationalization (\*(GK)  18
 Lines And Statements  4
 Localization (\*(GK)  12
+Namespaces    12
 Numeric Functions     15
 Output Control        13
 Pattern Elements      8
@@ -88,9 +90,6 @@ Variables    5\*(CX
 .sp .4
 .TD
 .fi
-\*(CD\*(FRArnold Robbins wrote this reference card.
-We thank
-Brian Kernighan and Michael Brennan who reviewed it.
 .sp .4
 .SL
 .sp .4
@@ -446,7 +445,9 @@ and optional function definitions.
 .sp .5
        \*(CB\*(address@hidden "\*(FIfilename\*(FC"
 .br
-       \*(address@hidden "\*(FIfilename\*(FC"\*(CD
+       \*(address@hidden "\*(FIfilename\*(FC"
+.br
+       \*(address@hidden "\*(FInamespace\*(FC"\*(CD
 .br
        \*(FIpattern\*(FC       { \*(FIaction statements\*(FC }\*(FR
 .br
@@ -523,7 +524,7 @@ T}
 \*(CL\*(FCBINMODE\fP   T{
 Controls ``binary'' mode for all file I/O.  Values of 1, 2, or 3,
 indicate input, output, or all files, respectively, should use binary
-I/O.  \*(CR(Not \*(NK.)  \*(CLApplies only to non-POSIX systems.
+I/O.  \*(CR(Not \*(NK.)  \*(CLOnly for non-POSIX systems.
 \*(CBFor \*(GK, string values of \*(FC"r"\fP, or \*(FC"w"\fP specify
 that input files, or output files, respectively, should use binary I/O.
 Use \*(FC"rw"\fP or \*(FC"wr"\fP for all files.\*(CX
@@ -967,6 +968,14 @@ lp8 lp8 lp8 lp8.
 \*(FC\e"\fP~double quote~\*(FC\e/\fP~forward slash\*(CX
 .TE
 .EB "\s+2\f(HBESCAPE SEQUENCES\*(FR\s0"
+.sp
+.\" --- Acknowledgements
+.ES
+.fi
+\*(CD\*(FRArnold Robbins wrote this reference card.
+We thank
+Brian Kernighan and Michael Brennan who reviewed it.\*(CX
+.EB "\s+2\f(HBACKNOWLEDGMENTS\*(FR\s0"
 .BT
 
 .\" --- Records
@@ -1276,6 +1285,26 @@ Usable only with the \*(FC|&\*(FR two-way I/O operator.
 Similar, but use UDP/IP instead of TCP/IP.\*(CL
 .in -.2i
 .EB "\s+2\f(HBSPECIAL FILENAMES\*(FR\s0"
+.sp .5
+.\" --- Namespaces
+.ES
+.fi
+\*(CDA
+\*(FIqualified name\fP
+consists of a two simple identifiers joined by a double colon
+(\*(FC::\fP).
+The left identifier is the namespace and the right one
+is the variable within it.
+All non-qualified names are treated as if in the
+``current'' namespace; the default namespace is \*(FCawk\fP.
+However, simple identifiers consisting solely of upper-case
+letters are forced into the
+\*(FCawk\fP
+namespace.
+You change the current namespace with an
+\*(address@hidden "\*(FIname\^\*(FC"\*(FR
+directive.\*(CB
+.EB "\s+2\f(HBNAMESPACES\*(FR\s0"
 
 .BT
 
diff --git a/doc/gawk.1 b/doc/gawk.1
index 4964cb3..4b188ae 100644
--- a/doc/gawk.1
+++ b/doc/gawk.1
@@ -13,7 +13,7 @@
 .              if \w'\(rq' .ds rq "\(rq
 .      \}
 .\}
-.TH GAWK 1 "Nov 29 2018" "Free Software Foundation" "Utility Commands"
+.TH GAWK 1 "Dec 12 2018" "Free Software Foundation" "Utility Commands"
 .SH NAME
 gawk \- pattern scanning and processing language
 .SH SYNOPSIS
@@ -132,6 +132,9 @@ Multiple
 (or
 .BR \-\^\-file )
 options may be used.
+Files read with
+.B \-f
+are treated as if they begin with an implict address@hidden "awk"\fR statement.
 .TP
 .PD 0
 .BI \-F " fs"
@@ -253,6 +256,9 @@ and
 options) with source code entered on the command line.
 It is intended primarily for medium to large \*(AK programs used
 in shell scripts.
+Each argument supplied via
+.B \-e
+is treated as if it begins with an implict address@hidden "awk"\fR statement.
 .TP
 .PD 0
 .BI "\-E " file
@@ -310,6 +316,9 @@ be made after appending the
 suffix.  The file will be loaded only
 once (i.e., duplicates are eliminated), and the code does not constitute
 the main program source.
+Files read with
+.B \-i
+are treated as if they begin with an implict address@hidden "awk"\fR statement.
 .TP
 .PD 0
 .BI "\-l " lib
@@ -577,9 +586,11 @@ pattern-action statements,
 and optional function definitions.
 .RS
 .PP
address@hidden "\fIfilename\fB"
address@hidden "\fIfilename\^\fB"
 .br
address@hidden "\fIfilename\fB"
address@hidden "\fIfilename\^\fB"
+.br
address@hidden "\fIname\^\fB"
 .br
 \fIpattern\fB  { \fIaction statements\fB }\fR
 .br
@@ -1520,6 +1531,37 @@ You can do this by creating an element in the subarray 
and then
 deleting it with the
 .B delete
 statement.
+.SS Namespaces
+.I Gawk
+provides a simple
+.I namespace
+facility to help work around the fact that all variables in
+AWK are global.
+.PP
+A
+.I "qualified name"
+consists of a two simple identifiers joined by a double colon
+.RB ( :: ).
+The left-hand identifier represents the namespace and the right-hand
+identifier is the variable within it.
+All simple (non-qualified) names are considered to be in the
+``current'' namespace; the default namespace is
+.BR awk .
+However, simple identifiers consisting solely of upper-case
+letters are forced into the
+.B awk
+namespace, even if the current namespace is different.
+.PP
+You change the current namespace with an
address@hidden "\fIname\^\fB"\fR
+directive.
+.PP
+The standard predefined builtin function names may not be used as
+namespace names.  The names of additional functions provided by
+.I gawk
+may be used as namespace names or as simple identifiers in other
+namespaces.
+For more details, see \*(EP.
 .SS Variable Typing And Conversion
 .PP
 Variables and fields
@@ -1668,7 +1710,7 @@ regular expression constants.  Thus,
 .B /a\e52b/
 is equivalent to
 .BR /a\e*b/ .
-.SS "Regexp Constants"
+.SS Regexp Constants
 A regular expression constant is a sequence of characters enclosed
 between forward slashes (like
 .BR /value/ ).
diff --git a/doc/gawk.info b/doc/gawk.info
index 35d1f56..6ecfd8a 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -88,6 +88,7 @@ in (a) below.  A copy of the license is included in the 
section entitled
 * Internationalization::           Getting 'gawk' to speak your
                                    language.
 * Debugger::                       The 'gawk' debugger.
+* Namespaces::                     How namespaces work in 'gawk'.
 * Arbitrary Precision Arithmetic:: Arbitrary precision arithmetic with
                                    'gawk'.
 * Dynamic Extensions::             Adding new built-in functions to
@@ -522,6 +523,15 @@ in (a) below.  A copy of the license is included in the 
section entitled
 * Readline Support::                    Readline support.
 * Limitations::                         Limitations and future plans.
 * Debugging Summary::                   Debugging summary.
+* Global Namespace::                    The global namespace in standard 'awk'.
+* Qualified Names::                     How to qualify names with a namespace.
+* Default Namespace::                   The default namespace.
+* Changing The Namespace::              How to change the namespace.
+* Naming Rules::                        Namespace and Component Naming Rules.
+* Internal Name Management::            How names are stored internally.
+* Namespace Example::                   An example of code using a namespace.
+* Namespace And Features::              Namespaces and other 'gawk' features.
+* Namespace Summary::                   Summarizing namespaces.
 * Computer Arithmetic::                 A quick intro to computer math.
 * Math Definitions::                    Defining terms used.
 * MPFR features::                       The MPFR features in 'gawk'.
@@ -1098,6 +1108,10 @@ in *note Sample Programs::, should be of interest.
 
         - *note Debugger::, describes the 'gawk' debugger.
 
+        - *note Namespaces::, describes how 'gawk' allows variables
+          and/or functions of the same name to be in different
+          namespaces.
+
         - *note Arbitrary Precision Arithmetic::, describes advanced
           arithmetic facilities.
 
@@ -2481,6 +2495,10 @@ The following list describes options mandated by the 
POSIX standard:
      the 'awk' program consists of the concatenation of the contents of
      each specified SOURCE-FILE.
 
+     Files named with '-i' are treated as if they had '@namespace "awk"'
+     at their beginning.  *Note Changing The Namespace::, for more
+     information.
+
 '-v VAR=VAL'
 '--assign VAR=VAL'
      Set the variable VAR to the value VAL _before_ execution of the
@@ -2577,15 +2595,19 @@ The following list describes options mandated by the 
POSIX standard:
      character (even if it doesn't).  This makes building the total
      program easier.
 
-          CAUTION: At the moment, there is no requirement that each
-          PROGRAM-TEXT be a full syntactic unit.  I.e., the following
-          currently works:
+          CAUTION: Prior to version 5.0, there was no requirement that
+          each PROGRAM-TEXT be a full syntactic unit.  I.e., the
+          following worked:
 
                $ gawk -e 'BEGIN { a = 5 ;' -e 'print a }'
                -| 5
 
-          However, this could change in the future, so it's not a good
-          idea to rely upon this feature.
+          However, this is no longer true.  If you have any scripts that
+          rely upon this feature, you should revise them.
+
+          This is because each PROGRAM-TEXT is treated as if it had
+          '@namespace "awk"' at its beginning.  *Note Changing The
+          Namespace::, for more information.
 
 '-E' FILE
 '--exec' FILE
@@ -2634,6 +2656,10 @@ The following list describes options mandated by the 
POSIX standard:
      processing an '-i' argument, 'gawk' still expects to find the main
      source code via the '-f' option or on the command line.
 
+     Files named with '-i' are treated as if they had '@namespace "awk"'
+     at their beginning.  *Note Changing The Namespace::, for more
+     information.
+
 '-l' EXT
 '--load' EXT
      Load a dynamic extension named EXT.  Extensions are stored as
@@ -3257,6 +3283,10 @@ from web pages.
    The rules for finding a source file described in *note AWKPATH
 Variable:: also apply to files loaded with '@include'.
 
+   Finally, files included with '@include' are treated as if they had
+'@namespace "awk"' at their beginning.  *Note Changing The Namespace::,
+for more information.
+
 
 File: gawk.info,  Node: Loading Shared Libraries,  Next: Obsolete,  Prev: 
Include Files,  Up: Invoking Gawk
 
@@ -15311,6 +15341,10 @@ and '_pw_count'.
 conventions.  You are not required to write your programs this way--we
 merely recommend that you do so.
 
+   Beginning with version 5.0, 'gawk' provides a powerful mechanism for
+solving the problems described in this section: "namespaces".
+Namespaces and their use are described in detail in *note Namespaces::.
+
    ---------- Footnotes ----------
 
    (1) Although all the library routines could have been rewritten to
@@ -18239,6 +18273,10 @@ line of input data:
          close(outputfile)
      }
 
+   As a side note, this program does not follow our recommended
+convention of naming global variables with a leading capital letter.
+Doing that would make the program a little easier to follow.
+
 
 File: gawk.info,  Node: Wc Program,  Prev: Uniq Program,  Up: Clones
 
@@ -21610,7 +21648,7 @@ File: gawk.info,  Node: I18N Summary,  Prev: Gawk I18N, 
 Up: Internationalizatio
      translations for its messages.
 
 
-File: gawk.info,  Node: Debugger,  Next: Arbitrary Precision Arithmetic,  
Prev: Internationalization,  Up: Top
+File: gawk.info,  Node: Debugger,  Next: Namespaces,  Prev: 
Internationalization,  Up: Top
 
 14 Debugging 'awk' Programs
 ***************************
@@ -22687,9 +22725,389 @@ File: gawk.info,  Node: Debugging Summary,  Prev: 
Limitations,  Up: Debugger
      debugged, but occasionally it can.
 
 
-File: gawk.info,  Node: Arbitrary Precision Arithmetic,  Next: Dynamic 
Extensions,  Prev: Debugger,  Up: Top
+File: gawk.info,  Node: Namespaces,  Next: Arbitrary Precision Arithmetic,  
Prev: Debugger,  Up: Top
+
+15 Namespaces in 'gawk'
+***********************
+
+This major node describes a feature that is specific to 'gawk'.
+
+* Menu:
+
+* Global Namespace::            The global namespace in standard 'awk'.
+* Qualified Names::             How to qualify names with a namespace.
+* Default Namespace::           The default namespace.
+* Changing The Namespace::      How to change the namespace.
+* Naming Rules::                Namespace and Component Naming Rules.
+* Internal Name Management::    How names are stored internally.
+* Namespace Example::           An example of code using a namespace.
+* Namespace And Features::      Namespaces and other 'gawk' features.
+* Namespace Summary::           Summarizing namespaces.
+
+
+File: gawk.info,  Node: Global Namespace,  Next: Qualified Names,  Up: 
Namespaces
+
+15.1 Standard 'awk''s Single Namespace
+======================================
+
+In standard 'awk', there is a single, global, "namespace".  This means
+that _all_ function names and global variable names must be unique.  For
+example, two different 'awk' source files cannot both define a function
+named 'min()', or define the same identifier, used as a scalar in one
+and as an array in the other.
+
+   This situation is okay when programs are small, say a few hundred
+lines, or even a few thousand, but it prevents the development of
+reusable libraries of 'awk' functions, and can inadvertently cause
+independently-developed library files to accidentally step on each
+other's "private" global variables (*note Library Names::).
+
+   Most other programming languages solve this issue by providing some
+kind of namespace control: a way to say "this function is in namespace
+XXX, and that function is in namespace YYY."  (Of course, there is then
+still a single namespace for the namespaces, but the hope is that there
+are much fewer namespaces in use by any given program, and thus much
+less chance for collisions.)  These facilities are sometimes referred to
+as "packages" or "modules".
+
+   Starting with version 5.0, 'gawk' provides a simple mechanism to put
+functions and global variables into separate namespaces.
+
+
+File: gawk.info,  Node: Qualified Names,  Next: Default Namespace,  Prev: 
Global Namespace,  Up: Namespaces
+
+15.2 Qualified Names
+====================
+
+A "qualified name" is an identifier that includes a namespace name, the
+namespace separator '::', and a "component" name.  For example, one
+might have a function named 'posix::getpid()'.  Here, the namespace is
+'posix' and the function name within the namespace (the component) is
+'getpid()'.  The namespace and component names are separated by a
+double-colon.  Only one such separator is allowed in a qualified name.
+
+     NOTE: Unlike C++, the '::' is _not_ an operator.  No spaces are
+     allowed between the namespace name, the '::', and the component
+     name.
+
+   You must use qualified names from one namespace to access variables
+and functions in another.  This is especially important when using
+variable names to index the special 'SYMTAB' array (*note Auto-set::),
+and when making indirect function calls (*note Indirect Calls::).
+
+
+File: gawk.info,  Node: Default Namespace,  Next: Changing The Namespace,  
Prev: Qualified Names,  Up: Namespaces
+
+15.3 The Default Namespace
+==========================
+
+The default namespace, not surprisingly, is 'awk'.  All of the
+predefined 'awk' and 'gawk' variables are in this namespace, and thus
+have qualified names like 'awk::ARGC', 'awk::NF', and so on.
+
+   Furthermore, even when you have changed the namespace for your
+current source file (*note Changing The Namespace::), 'gawk' forces
+unqualified identifiers whose names are all uppercase letters to be in
+the 'awk' namespace.  This makes it possible for you to easily reference
+'gawk''s global variables from different namespaces.  It also keeps your
+code looking natural.
+
+
+File: gawk.info,  Node: Changing The Namespace,  Next: Naming Rules,  Prev: 
Default Namespace,  Up: Namespaces
+
+15.4 Changing The Namespace
+===========================
+
+In order to set the current namespace, use an '@namespace' directive at
+the top level of your program:
+
+     @namespace "passwd"
+
+     BEGIN { ... }
+     ...
+
+   After this directive, all simple non-completely-uppercase identifiers
+are placed into the 'passwd' namespace.
+
+   You can change the namespace multiple times within a single source
+file, although this is likely to become confusing if you do it too much.
+
+     NOTE: Association of unqualified identifiers to a namespace is
+     handled while 'gawk' parses your program, _before_ it starts to
+     run.  There is no concept of a "current" namespace once your
+     program starts executing.  Be sure you understand this.
+
+   Each source file for '-i' and '-f' starts out with an implicit
+'@namespace "awk"'.  Similarly, each chunk of command-line code supplied
+with '-e' has such an implicit initial statement (*note Options::).
+
+   Files included with '@include' (*note Include Files::) "push" and
+"pop" the current namespace.  That is, each '@include' saves the current
+namespace and starts over with an implicit '@namespace "awk"' which
+remains in effect until an explicit '@namespace' directive is seen.
+When 'gawk' finishes processing the included file, the saved namespace
+is restored and processing continues where it left off in the original
+file.
+
+   The use of '@namespace' has no influence upon the order of execution
+of 'BEGIN', 'BEGINFILE', 'END', and 'ENDFILE' rules.
+
+
+File: gawk.info,  Node: Naming Rules,  Next: Internal Name Management,  Prev: 
Changing The Namespace,  Up: Namespaces
+
+15.5 Namespace and Component Naming Rules
+=========================================
+
+A number of rules apply to the namespace and component names, as
+follows.
+
+   * It is a syntax error to use qualified names for function parameter
+     names.
+
+   * It is a syntax error to use any standard 'awk' reserved word (such
+     as 'if' or 'for'), or the name of any standard built-in function
+     (such as 'sin()' or 'gsub()') as either part of a qualified name.
+     Thus, the following produces a syntax error:
+
+          @namespace "example"
+
+          function gsub(str, pat, result) { ... }
+
+   * Outside the 'awk' namespace, the names of the additional 'gawk'
+     built-in functions (such as 'gensub()' or 'strftime()') _may_ be
+     used as component names.  The same set of names may be used as
+     namespace names, although this has the potential to be confusing.
+
+   * The additional 'gawk' built-in functions may still be called from
+     outside the 'awk' namespace by qualifying them.  For example,
+     'awk::systime()'.  Here is a somewhat silly example demonstrating
+     this rule and the previous one:
+
+          BEGIN {
+              print "in awk namespace, systime() =", systime()
+          }
+
+          @namespace "testing"
+
+          function systime()
+          {
+              print "in testing namespace, systime() =", awk::systime()
+          }
+
+          BEGIN {
+              systime()
+          }
+
+
+     When run, it produces output like this:
+
+          $ gawk -f systime.awk
+          -| in awk namespace, systime() = 1500488503
+          -| in testing namespace, systime() = 1500488503
+
+   * 'gawk' pre-defined variable names may be used: 'NF::NR' is valid,
+     if possibly not all that useful.
+
+
+File: gawk.info,  Node: Internal Name Management,  Next: Namespace Example,  
Prev: Naming Rules,  Up: Namespaces
+
+15.6 Internal Name Management
+=============================
+
+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"]' (*note
+Auto-set::), and for use in indirect function calls (*note Indirect
+Calls::).
+
+   In program code, to refer to variables and functions in the 'awk'
+namespace from another namespace, you must still use the 'awk::' prefix.
+For example:
+
+     @namespace "awk"          This is the default namespace
+
+     BEGIN {
+         Title = "My Report"   Qualified name is awk::Title
+     }
+
+     @namespace "report"       Now in report namespace
+
+     function compute()        This is really report::compute()
+     {
+         print awk::Title      But would be SYMTAB["Title"]
+         ...
+     }
+
+
+File: gawk.info,  Node: Namespace Example,  Next: Namespace And Features,  
Prev: Internal Name Management,  Up: Namespaces
+
+15.7 Namespace Example
+======================
+
+The following example is a revised version of the suite of routines
+developed in *note Passwd Functions::.  See there for an explanation of
+how the code works.
+
+   The formulation here, due mainly to Andrew Schorr, is rather elegant.
+All of the implementation functions and variables are in the 'passwd'
+namespace, whereas the main interface functions are defined in the 'awk'
+namespace.
+
+     # ns_passwd.awk --- access password file information
+
+     @namespace "passwd"
+
+     BEGIN {
+         # tailor this to suit your system
+         Awklib = "/usr/local/libexec/awk/"
+     }
+
+     function Init(    oldfs, oldrs, olddol0, pwcat, using_fw, using_fpat)
+     {
+         if (Inited)
+             return
+
+         oldfs = FS
+         oldrs = RS
+         olddol0 = $0
+         using_fw = (PROCINFO["FS"] == "FIELDWIDTHS")
+         using_fpat = (PROCINFO["FS"] == "FPAT")
+         FS = ":"
+         RS = "\n"
+
+         pwcat = Awklib "pwcat"
+         while ((pwcat | getline) > 0) {
+             Byname[$1] = $0
+             Byuid[$3] = $0
+             Bycount[++Total] = $0
+         }
+         close(pwcat)
+         Count = 0
+         Inited = 1
+         FS = oldfs
+         if (using_fw)
+             FIELDWIDTHS = FIELDWIDTHS
+         else if (using_fpat)
+             FPAT = FPAT
+         RS = oldrs
+         $0 = olddol0
+     }
+
+     function awk::getpwnam(name)
+     {
+         Init()
+         return Byname[name]
+     }
+
+     function awk::getpwuid(uid)
+     {
+         Init()
+         return Byuid[uid]
+     }
+
+     function awk::getpwent()
+     {
+         Init()
+         if (Count < Total)
+             return Bycount[++Count]
+         return ""
+     }
+
+     function awk::endpwent()
+     {
+         Count = 0
+     }
+
+   As you can see, this version also follows the convention mentioned in
+*note Library Names::, whereby global variable and function names start
+with a capital letter.
+
+   Here is a simple test program.  Since it's in a separate file,
+unadorned identifiers are sought for in the 'awk' namespace:
+
+     BEGIN {
+         while ((p = getpwent()) != "")
+             print p
+     }
+
+
+   Here's what happens when it's run:
+
+     $ gawk -f ns_passwd.awk -f testpasswd.awk
+     -| root:x:0:0:root:/root:/bin/bash
+     -| daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
+     -| bin:x:2:2:bin:/bin:/usr/sbin/nologin
+     -| sys:x:3:3:sys:/dev:/usr/sbin/nologin
+     ...
+
+
+File: gawk.info,  Node: Namespace And Features,  Next: Namespace Summary,  
Prev: Namespace Example,  Up: Namespaces
 
-15 Arithmetic and Arbitrary-Precision Arithmetic with 'gawk'
+15.8 Namespaces and Other 'gawk' Features
+=========================================
+
+This minor node looks briefly at how the namespace facility interacts
+with other important 'gawk' features.
+
+   The profiler and pretty-printer (*note Profiling::) have been
+enhanced to understand namespaces and the namespace naming rules
+presented in *note Naming Rules::.  In particular, the output groups
+functions in the same namespace together, and has '@namespace'
+directives in front of rules as necessary.  This allows component names
+to be simple identifiers, instead of using qualified identifiers
+everywhere.
+
+   Interaction with the debugger (*note Debugging::) has not had to
+change (at least as of this writing).  Some of the internal byte codes
+changed in order to accommodate namespaces, and the debugger's 'dump'
+command was adjusted to match.
+
+   The extension API (*note Dynamic Extensions::) has always allowed for
+placing functions into a different namespace, although this was not
+previously implemented.  However, the symbol lookup and symbol update
+routines did not have provision for including a namespace.  That has now
+been corrected (*note Symbol table by name::).  *Note Extension Sample
+Inplace::, for a nice example of an extension that leverages a namespace
+shared by cooperating 'awk' and C code.
+
+
+File: gawk.info,  Node: Namespace Summary,  Prev: Namespace And Features,  Up: 
Namespaces
+
+15.9 Summary
+============
+
+   * Standard 'awk' provides a single namespace for all global
+     identifiers (scalars, arrays, and functions).  This is limiting
+     when one wants to develop libraries of reusable functions or
+     function suites.
+
+   * 'gawk' provides multiple namespaces by using qualified names: names
+     consisting of a namespace name, a double colon, '::', and a
+     component name.  Namespace names might still possibly conflict, but
+     this is true of any language providing namespaces, modules, or
+     packages.
+
+   * The default namespace is 'awk'.  The rules for namespace and
+     component names are provided in *note Naming Rules::.  The rules
+     are designed in such a way as to make namespace-aware code continue
+     to look and work naturally while still providing the necessary
+     power and flexibility.
+
+   * Other parts of 'gawk' have been extended as necessary to integrate
+     namespaces smoothly with their operation.  This applies most
+     notably to the profiler / pretty-printer (*note Profiling::) and to
+     the extension facility (*note Dynamic Extensions::).
+
+   * Overall, the namespace facility was designed and implemented such
+     that backwards compatibility is paramount.  Programs that don't use
+     namespaces should see absolutely no difference in behavior when run
+     by a namespace-capable version of 'gawk'.
+
+
+File: gawk.info,  Node: Arbitrary Precision Arithmetic,  Next: Dynamic 
Extensions,  Prev: Namespaces,  Up: Top
+
+16 Arithmetic and Arbitrary-Precision Arithmetic with 'gawk'
 ************************************************************
 
 This major node introduces some basic concepts relating to how computers
@@ -22720,7 +23138,7 @@ are not quite in agreement.
 
 File: gawk.info,  Node: Computer Arithmetic,  Next: Math Definitions,  Up: 
Arbitrary Precision Arithmetic
 
-15.1 A General Description of Computer Arithmetic
+16.1 A General Description of Computer Arithmetic
 =================================================
 
 Until now, we have worked with data as either numbers or strings.
@@ -22791,7 +23209,7 @@ double-precision floating-point values occupy 64 bits.
 (Quadruple-precision floating point values also exist.  They occupy 128
 bits, but such numbers are not available in 'awk'.)  Floating-point
 values are always signed.  The possible ranges of values are shown in
-*note Table 15.1: table-numeric-ranges. and *note Table 15.2:
+*note Table 16.1: table-numeric-ranges. and *note Table 16.2:
 table-floating-point-ranges.
 
 Representation           Minimum value            Maximum value
@@ -22803,7 +23221,7 @@ integer
 64-bit unsigned          0                        18,446,744,073,709,551,615
 integer
 
-Table 15.1: Value ranges for integer representations
+Table 16.1: Value ranges for integer representations
 
 Representation              Minimum          Minimum finite   Maximum finite
                             positive         value            value
@@ -22816,7 +23234,7 @@ floating-point
 Quadruple-precision         3.362103e-4932   -1.189731e+4932  1.189731e+4932
 floating-point
 
-Table 15.2: Approximate value ranges for floating-point number
+Table 16.2: Approximate value ranges for floating-point number
 representations
 
    ---------- Footnotes ----------
@@ -22826,7 +23244,7 @@ representations
 
 File: gawk.info,  Node: Math Definitions,  Next: MPFR features,  Prev: 
Computer Arithmetic,  Up: Arbitrary Precision Arithmetic
 
-15.2 Other Stuff to Know
+16.2 Other Stuff to Know
 ========================
 
 The rest of this major node uses a number of terms.  Here are some
@@ -22906,7 +23324,7 @@ IEEE 754 types are 32-bit single precision, 64-bit 
double precision, and
 precision formats to allow greater precisions and larger exponent
 ranges.  ('awk' uses only the 64-bit double-precision format.)
 
-   *note Table 15.3: table-ieee-formats. lists the precision and
+   *note Table 16.3: table-ieee-formats. lists the precision and
 exponent field values for the basic IEEE 754 binary formats.
 
 Name           Total bits     Precision      Minimum        Maximum
@@ -22916,7 +23334,7 @@ Single         32             24             -126       
    +127
 Double         64             53             -1022          +1023
 Quadruple      128            113            -16382         +16383
 
-Table 15.3: Basic IEEE format values
+Table 16.3: Basic IEEE format values
 
      NOTE: The precision numbers include the implied leading one that
      gives them one extra bit of significand.
@@ -22929,7 +23347,7 @@ paraphrased, and for the examples.
 
 File: gawk.info,  Node: MPFR features,  Next: FP Math Caution,  Prev: Math 
Definitions,  Up: Arbitrary Precision Arithmetic
 
-15.3 Arbitrary-Precision Arithmetic Features in 'gawk'
+16.3 Arbitrary-Precision Arithmetic Features in 'gawk'
 ======================================================
 
 By default, 'gawk' uses the double-precision floating-point values
@@ -22967,7 +23385,7 @@ information.
 
 File: gawk.info,  Node: FP Math Caution,  Next: Arbitrary Precision Integers,  
Prev: MPFR features,  Up: Arbitrary Precision Arithmetic
 
-15.4 Floating-Point Arithmetic: Caveat Emptor!
+16.4 Floating-Point Arithmetic: Caveat Emptor!
 ==============================================
 
      Math class is tough!
@@ -23001,7 +23419,7 @@ in computer science.
 
 File: gawk.info,  Node: Inexactness of computations,  Next: Getting Accuracy,  
Up: FP Math Caution
 
-15.4.1 Floating-Point Arithmetic Is Not Exact
+16.4.1 Floating-Point Arithmetic Is Not Exact
 ---------------------------------------------
 
 Binary floating-point representations and arithmetic are inexact.
@@ -23022,7 +23440,7 @@ be sure of the number of significant decimal places in 
the final result.
 
 File: gawk.info,  Node: Inexact representation,  Next: Comparing FP Values,  
Up: Inexactness of computations
 
-15.4.1.1 Many Numbers Cannot Be Represented Exactly
+16.4.1.1 Many Numbers Cannot Be Represented Exactly
 ...................................................
 
 So, before you start to write any code, you should think about what you
@@ -23053,7 +23471,7 @@ previous example, produces an output identical to the 
input.
 
 File: gawk.info,  Node: Comparing FP Values,  Next: Errors accumulate,  Prev: 
Inexact representation,  Up: Inexactness of computations
 
-15.4.1.2 Be Careful Comparing Values
+16.4.1.2 Be Careful Comparing Values
 ....................................
 
 Because the underlying representation can be a little bit off from the
@@ -23084,7 +23502,7 @@ in case someone passes in a negative delta value.
 
 File: gawk.info,  Node: Errors accumulate,  Prev: Comparing FP Values,  Up: 
Inexactness of computations
 
-15.4.1.3 Errors Accumulate
+16.4.1.3 Errors Accumulate
 ..........................
 
 The loss of accuracy during a single computation with floating-point
@@ -23132,7 +23550,7 @@ representations yield an unexpected result:
 
 File: gawk.info,  Node: Getting Accuracy,  Next: Try To Round,  Prev: 
Inexactness of computations,  Up: FP Math Caution
 
-15.4.2 Getting the Accuracy You Need
+16.4.2 Getting the Accuracy You Need
 ------------------------------------
 
 Can arbitrary-precision arithmetic give exact results?  There are no
@@ -23193,7 +23611,7 @@ hand is often the correct approach in such situations.
 
 File: gawk.info,  Node: Try To Round,  Next: Setting precision,  Prev: Getting 
Accuracy,  Up: FP Math Caution
 
-15.4.3 Try a Few Extra Bits of Precision and Rounding
+16.4.3 Try a Few Extra Bits of Precision and Rounding
 -----------------------------------------------------
 
 Instead of arbitrary-precision floating-point arithmetic, often all you
@@ -23220,7 +23638,7 @@ iterations:
 
 File: gawk.info,  Node: Setting precision,  Next: Setting the rounding mode,  
Prev: Try To Round,  Up: FP Math Caution
 
-15.4.4 Setting the Precision
+16.4.4 Setting the Precision
 ----------------------------
 
 'gawk' uses a global working precision; it does not keep track of the
@@ -23229,7 +23647,7 @@ operation or calling a built-in function rounds the 
result to the
 current working precision.  The default working precision is 53 bits,
 which you can modify using the predefined variable 'PREC'.  You can also
 set the value to one of the predefined case-insensitive strings shown in
-*note Table 15.4: table-predefined-precision-strings, to emulate an IEEE
+*note Table 16.4: table-predefined-precision-strings, to emulate an IEEE
 754 binary format.
 
 'PREC'       IEEE 754 binary format
@@ -23240,7 +23658,7 @@ set the value to one of the predefined case-insensitive 
strings shown in
 '"quad"'     Basic 128-bit quadruple precision
 '"oct"'      256-bit octuple precision
 
-Table 15.4: Predefined precision strings for 'PREC'
+Table 16.4: Predefined precision strings for 'PREC'
 
    The following example illustrates the effects of changing precision
 on arithmetic operations:
@@ -23277,12 +23695,12 @@ on arithmetic operations:
 
 File: gawk.info,  Node: Setting the rounding mode,  Prev: Setting precision,  
Up: FP Math Caution
 
-15.4.5 Setting the Rounding Mode
+16.4.5 Setting the Rounding Mode
 --------------------------------
 
 The 'ROUNDMODE' variable provides program-level control over the
 rounding mode.  The correspondence between 'ROUNDMODE' and the IEEE
-rounding modes is shown in *note Table 15.5: table-gawk-rounding-modes.
+rounding modes is shown in *note Table 16.5: table-gawk-rounding-modes.
 
 Rounding mode                    IEEE name              'ROUNDMODE'
 ---------------------------------------------------------------------------
@@ -23292,10 +23710,10 @@ Round toward negative infinity   
'roundTowardNegative'  '"D"' or '"d"'
 Round toward zero                'roundTowardZero'      '"Z"' or '"z"'
 Round away from zero                                    '"A"' or '"a"'
 
-Table 15.5: 'gawk' rounding modes
+Table 16.5: 'gawk' rounding modes
 
    'ROUNDMODE' has the default value '"N"', which selects the IEEE 754
-rounding mode 'roundTiesToEven'.  In *note Table 15.5:
+rounding mode 'roundTiesToEven'.  In *note Table 16.5:
 table-gawk-rounding-modes, the value '"A"' selects rounding away from
 zero.  This is only available if your version of the MPFR library
 supports it; otherwise, setting 'ROUNDMODE' to '"A"' has no effect.
@@ -23387,7 +23805,7 @@ round halfway cases for 'printf'.
 
 File: gawk.info,  Node: Arbitrary Precision Integers,  Next: Checking for 
MPFR,  Prev: FP Math Caution,  Up: Arbitrary Precision Arithmetic
 
-15.5 Arbitrary-Precision Integer Arithmetic with 'gawk'
+16.5 Arbitrary-Precision Integer Arithmetic with 'gawk'
 =======================================================
 
 When given the '-M' option, 'gawk' performs all integer arithmetic using
@@ -23465,7 +23883,7 @@ Wolfram Web Resource
 
 File: gawk.info,  Node: Checking for MPFR,  Next: POSIX Floating Point 
Problems,  Prev: Arbitrary Precision Integers,  Up: Arbitrary Precision 
Arithmetic
 
-15.6 How To Check If MPFR Is Available
+16.6 How To Check If MPFR Is Available
 ======================================
 
 Occasionally, you might like to be able to check if 'gawk' was invoked
@@ -23506,7 +23924,7 @@ arbitrary-precision arithmetic is available:
 
 File: gawk.info,  Node: POSIX Floating Point Problems,  Next: Floating point 
summary,  Prev: Checking for MPFR,  Up: Arbitrary Precision Arithmetic
 
-15.7 Standards Versus Existing Practice
+16.7 Standards Versus Existing Practice
 =======================================
 
 Historically, 'awk' has converted any nonnumeric-looking string to the
@@ -23600,7 +24018,7 @@ described: '+inf', '-inf', '+nan', or '-nan'.  
Similarly, in POSIX mode,
 
 File: gawk.info,  Node: Floating point summary,  Prev: POSIX Floating Point 
Problems,  Up: Arbitrary Precision Arithmetic
 
-15.8 Summary
+16.8 Summary
 ============
 
    * Most computer arithmetic is done using either integers or
@@ -23653,7 +24071,7 @@ File: gawk.info,  Node: Floating point summary,  Prev: 
POSIX Floating Point Prob
 
 File: gawk.info,  Node: Dynamic Extensions,  Next: Language History,  Prev: 
Arbitrary Precision Arithmetic,  Up: Top
 
-16 Writing Extensions for 'gawk'
+17 Writing Extensions for 'gawk'
 ********************************
 
 It is possible to add new functions written in C or C++ to 'gawk' using
@@ -23687,7 +24105,7 @@ sample extensions are automatically built and installed 
when 'gawk' is.
 
 File: gawk.info,  Node: Extension Intro,  Next: Plugin License,  Up: Dynamic 
Extensions
 
-16.1 Introduction
+17.1 Introduction
 =================
 
 An "extension" (sometimes called a "plug-in") is a piece of external
@@ -23714,7 +24132,7 @@ and design.
 
 File: gawk.info,  Node: Plugin License,  Next: Extension Mechanism Outline,  
Prev: Extension Intro,  Up: Dynamic Extensions
 
-16.2 Extension Licensing
+17.2 Extension Licensing
 ========================
 
 Every dynamic extension must be distributed under a license that is
@@ -23734,12 +24152,12 @@ symbol exists in the global scope.  Something like 
this is enough:
 
 File: gawk.info,  Node: Extension Mechanism Outline,  Next: Extension API 
Description,  Prev: Plugin License,  Up: Dynamic Extensions
 
-16.3 How It Works at a High Level
+17.3 How It Works at a High Level
 =================================
 
 Communication between 'gawk' and an extension is two-way.  First, when
 an extension is loaded, 'gawk' passes it a pointer to a 'struct' whose
-fields are function pointers.  This is shown in *note Figure 16.1:
+fields are function pointers.  This is shown in *note Figure 17.1:
 figure-load-extension.
 
 [image src="api-figure1.png" alt="Loading the extension" text="              
            API
@@ -23767,12 +24185,12 @@ figure-load-extension.
 
     gawk Main Program Address Space              Extension"]
 
-Figure 16.1: Loading the extension
+Figure 17.1: Loading the extension
 
    The extension can call functions inside 'gawk' through these function
 pointers, at runtime, without needing (link-time) access to 'gawk''s
 symbols.  One of these function pointers is to a function for
-"registering" new functions.  This is shown in *note Figure 16.2:
+"registering" new functions.  This is shown in *note Figure 17.2:
 figure-register-new-function.
 
 [image src="api-figure2.png" alt="Registering a new Function" text="         
   register_ext_func({ \"chdir\", do_chdir, 1 });
@@ -23788,13 +24206,13 @@ figure-register-new-function.
 
     gawk Main Program Address Space              Extension"]
 
-Figure 16.2: Registering a new function
+Figure 17.2: Registering a new function
 
    In the other direction, the extension registers its new functions
 with 'gawk' by passing function pointers to the functions that provide
 the new feature ('do_chdir()', for example).  'gawk' associates the
 function pointer with a name and can then call it, using a defined
-calling convention.  This is shown in *note Figure 16.3:
+calling convention.  This is shown in *note Figure 17.3:
 figure-call-new-function.
 
 [image src="api-figure3.png" alt="Calling the new function" text="    BEGIN {
@@ -23811,7 +24229,7 @@ figure-call-new-function.
 
     gawk Main Program Address Space              Extension"]
 
-Figure 16.3: Calling the new function
+Figure 17.3: Calling the new function
 
    The 'do_XXX()' function, in turn, then uses the function pointers in
 the API 'struct' to do its work, such as updating variables or arrays,
@@ -23843,7 +24261,7 @@ Example::) and also in the 'testext.c' code for testing 
the APIs.
 
 File: gawk.info,  Node: Extension API Description,  Next: Finding Extensions,  
Prev: Extension Mechanism Outline,  Up: Dynamic Extensions
 
-16.4 API Description
+17.4 API Description
 ====================
 
 C or C++ code for an extension must include the header file 'gawkapi.h',
@@ -23875,7 +24293,7 @@ API in detail.
 
 File: gawk.info,  Node: Extension API Functions Introduction,  Next: General 
Data Types,  Up: Extension API Description
 
-16.4.1 Introduction
+17.4.1 Introduction
 -------------------
 
 Access to facilities within 'gawk' is achieved by calling through
@@ -23930,7 +24348,9 @@ operations:
 
    * The following types, macros, and/or functions are referenced in
      'gawkapi.h'.  For correct use, you must therefore include the
-     corresponding standard header file _before_ including 'gawkapi.h':
+     corresponding standard header file _before_ including 'gawkapi.h'.
+     The list of macros and related header files is shown in *note Table
+     17.1: table-api-std-headers.
 
      C entity                 Header file
      -------------------------------------------
@@ -23943,6 +24363,8 @@ operations:
      'size_t'                 '<sys/types.h>'
      'struct stat'            '<sys/stat.h>'
 
+     Table 17.1: Standard header files needed by API
+
      Due to portability concerns, especially to systems that are not
      fully standards-compliant, it is your responsibility to include the
      correct files in the correct way.  This requirement is necessary in
@@ -24009,7 +24431,7 @@ macros as if they were functions.
 
 File: gawk.info,  Node: General Data Types,  Next: Memory Allocation 
Functions,  Prev: Extension API Functions Introduction,  Up: Extension API 
Description
 
-16.4.2 General-Purpose Data Types
+17.4.2 General-Purpose Data Types
 ---------------------------------
 
      I have a true love/hate relationship with unions.
@@ -24209,7 +24631,7 @@ See also the entry for "Cookie" in the *note Glossary::.
 
 File: gawk.info,  Node: Memory Allocation Functions,  Next: Constructor 
Functions,  Prev: General Data Types,  Up: Extension API Description
 
-16.4.3 Memory Allocation Functions and Convenience Macros
+17.4.3 Memory Allocation Functions and Convenience Macros
 ---------------------------------------------------------
 
 The API provides a number of "memory allocation" functions for
@@ -24316,7 +24738,7 @@ Unix-like systems as well.
 
 File: gawk.info,  Node: Constructor Functions,  Next: Registration Functions,  
Prev: Memory Allocation Functions,  Up: Extension API Description
 
-16.4.4 Constructor Functions
+17.4.4 Constructor Functions
 ----------------------------
 
 The API provides a number of "constructor" functions for creating string
@@ -24391,7 +24813,7 @@ code would use them:
 
 File: gawk.info,  Node: Registration Functions,  Next: Printing Messages,  
Prev: Constructor Functions,  Up: Extension API Description
 
-16.4.5 Registration Functions
+17.4.5 Registration Functions
 -----------------------------
 
 This minor node describes the API functions for registering parts of
@@ -24409,7 +24831,7 @@ your extension with 'gawk'.
 
 File: gawk.info,  Node: Extension Functions,  Next: Exit Callback Functions,  
Up: Registration Functions
 
-16.4.5.1 Registering An Extension Function
+17.4.5.1 Registering An Extension Function
 ..........................................
 
 Extension functions are described by the following record:
@@ -24488,9 +24910,11 @@ register it with 'gawk' using this API function:
 
 'awk_bool_t add_ext_func(const char *name_space, awk_ext_func_t *func);'
      This function returns true upon success, false otherwise.  The
-     'name_space' parameter is currently not used; you should pass in an
-     empty string ('""').  The 'func' pointer is the address of a
-     'struct' representing your function, as just described.
+     'name_space' parameter is the namespace in which to place the
+     function (*note Namespaces::).  Use an empty string ('""') or
+     '"awk"' to place the function in the default 'awk' namespace.  The
+     'func' pointer is the address of a 'struct' representing your
+     function, as just described.
 
      'gawk' does not modify what 'func' points to, but the extension
      function itself receives this pointer and can modify what it points
@@ -24522,7 +24946,7 @@ A minimum number of arguments is required, and no more 
than a maximum is allowed
 
 File: gawk.info,  Node: Exit Callback Functions,  Next: Extension Version 
String,  Prev: Extension Functions,  Up: Registration Functions
 
-16.4.5.2 Registering An Exit Callback Function
+17.4.5.2 Registering An Exit Callback Function
 ..............................................
 
 An "exit callback" function is a function that 'gawk' calls before it
@@ -24552,7 +24976,7 @@ order--that is, in the reverse order in which they are 
registered with
 
 File: gawk.info,  Node: Extension Version String,  Next: Input Parsers,  Prev: 
Exit Callback Functions,  Up: Registration Functions
 
-16.4.5.3 Registering An Extension Version String
+17.4.5.3 Registering An Extension Version String
 ................................................
 
 You can register a version string that indicates the name and version of
@@ -24569,7 +24993,7 @@ invoked with the '--version' option.
 
 File: gawk.info,  Node: Input Parsers,  Next: Output Wrappers,  Prev: 
Extension Version String,  Up: Registration Functions
 
-16.4.5.4 Customized Input Parsers
+17.4.5.4 Customized Input Parsers
 .................................
 
 By default, 'gawk' reads text files as its input.  It uses the value of
@@ -24847,7 +25271,7 @@ example.
 
 File: gawk.info,  Node: Output Wrappers,  Next: Two-way processors,  Prev: 
Input Parsers,  Up: Registration Functions
 
-16.4.5.5 Customized Output Wrappers
+17.4.5.5 Customized Output Wrappers
 ...................................
 
 An "output wrapper" is the mirror image of an input parser.  It allows
@@ -24953,7 +25377,7 @@ just use normally.
 
 File: gawk.info,  Node: Two-way processors,  Prev: Output Wrappers,  Up: 
Registration Functions
 
-16.4.5.6 Customized Two-way Processors
+17.4.5.6 Customized Two-way Processors
 ......................................
 
 A "two-way processor" combines an input parser and an output wrapper for
@@ -25007,7 +25431,7 @@ and 'XXX_take_control_of()'.
 
 File: gawk.info,  Node: Printing Messages,  Next: Updating ERRNO,  Prev: 
Registration Functions,  Up: Extension API Description
 
-16.4.6 Printing Messages
+17.4.6 Printing Messages
 ------------------------
 
 You can print different kinds of warning messages from your extension,
@@ -25041,7 +25465,7 @@ the pity.
 
 File: gawk.info,  Node: Updating ERRNO,  Next: Requesting Values,  Prev: 
Printing Messages,  Up: Extension API Description
 
-16.4.7 Updating 'ERRNO'
+17.4.7 Updating 'ERRNO'
 -----------------------
 
 The following functions allow you to update the 'ERRNO' variable:
@@ -25062,7 +25486,7 @@ The following functions allow you to update the 'ERRNO' 
variable:
 
 File: gawk.info,  Node: Requesting Values,  Next: Accessing Parameters,  Prev: 
Updating ERRNO,  Up: Extension API Description
 
-16.4.8 Requesting Values
+17.4.8 Requesting Values
 ------------------------
 
 All of the functions that return values from 'gawk' work in the same
@@ -25072,7 +25496,7 @@ function returns true and fills in the 'awk_value_t' 
result.  Otherwise,
 the function returns false, and the 'val_type' member indicates the type
 of the actual value.  You may then print an error message or reissue the
 request for the actual value type, as appropriate.  This behavior is
-summarized in *note Table 16.1: table-value-types-returned.
+summarized in *note Table 17.2: table-value-types-returned.
 
                                      Type of Actual Value
 --------------------------------------------------------------------------
@@ -25088,12 +25512,12 @@ Requested   Array       false    false    false    
false   Array   false
             Value       false    false    false    false   false   false
             cookie
 
-Table 16.1: API value types returned
+Table 17.2: API value types returned
 
 
 File: gawk.info,  Node: Accessing Parameters,  Next: Symbol Table Access,  
Prev: Requesting Values,  Up: Extension API Description
 
-16.4.9 Accessing and Updating Parameters
+17.4.9 Accessing and Updating Parameters
 ----------------------------------------
 
 Two functions give you access to the arguments (parameters) passed to
@@ -25105,7 +25529,7 @@ your extension function.  They are:
      Fill in the 'awk_value_t' structure pointed to by 'result' with the
      'count'th argument.  Return true if the actual type matches
      'wanted', and false otherwise.  In the latter case,
-     'result->val_type' indicates the actual type (*note Table 16.1:
+     'result->val_type' indicates the actual type (*note Table 17.2:
      table-value-types-returned.).  Counts are zero-based--the first
      argument is numbered zero, the second one, and so on.  'wanted'
      indicates the type of value expected.
@@ -25119,7 +25543,7 @@ your extension function.  They are:
 
 File: gawk.info,  Node: Symbol Table Access,  Next: Array Manipulation,  Prev: 
Accessing Parameters,  Up: Extension API Description
 
-16.4.10 Symbol Table Access
+17.4.10 Symbol Table Access
 ---------------------------
 
 Two sets of routines provide access to global variables, and one set
@@ -25134,7 +25558,7 @@ allows you to create and release cached values.
 
 File: gawk.info,  Node: Symbol table by name,  Next: Symbol table by cookie,  
Up: Symbol Table Access
 
-16.4.10.1 Variable Access and Update by Name
+17.4.10.1 Variable Access and Update by Name
 ............................................
 
 The following routines provide the ability to access and update global
@@ -25151,7 +25575,19 @@ termed a "symbol table".  The functions are as follows:
      regular C string.  'wanted' indicates the type of value expected.
      Return true if the actual type matches 'wanted', and false
      otherwise.  In the latter case, 'result->val_type' indicates the
-     actual type (*note Table 16.1: table-value-types-returned.).
+     actual type (*note Table 17.2: table-value-types-returned.).
+
+'awk_bool_t sym_lookup_ns(const char *name,'
+'                         const char *name_space,'
+'                         awk_valtype_t wanted,'
+'                         awk_value_t *result);'
+     This is like 'sym_lookup()', but the 'name_space' parameter allows
+     you to specify which namespace 'name' is part of.  'name_space'
+     cannot be 'NULL'.  If it is '""' or '"awk"', then 'name' is
+     searched for in the default 'awk' namespace.
+
+     Note that 'namespace' is a C++ keyword.  For interoperability with
+     C++, you should avoid using that identifier in C code.
 
 'awk_bool_t sym_update(const char *name, awk_value_t *value);'
      Update the variable named by the string 'name', which is a regular
@@ -25163,14 +25599,30 @@ termed a "symbol table".  The functions are as 
follows:
      an array.  This routine cannot be used to update any of the
      predefined variables (such as 'ARGC' or 'NF').
 
+'awk_bool_t sym_update_ns(const char *name_space, const char *name, 
awk_value_t *value);'
+     This is like 'sym_update()', but the 'name_space' parameter allows
+     you to specify which namespace 'name' is part of.  'name_space'
+     cannot be 'NULL'.  If it is '""' or '"awk', then 'name' is searched
+     for in the default 'awk' namespace.
+
    An extension can look up the value of 'gawk''s special variables.
 However, with the exception of the 'PROCINFO' array, an extension cannot
 change any of those variables.
 
+   When searching for or updating variables outside the 'awk' namespace
+(*note Namespaces::), function and variable names must be simple
+identifiers.(1)  In addition, namespace names and variable and function
+names must follow the rules given in *note Naming Rules::.
+
+   ---------- Footnotes ----------
+
+   (1) Allowing both namespace plus identifier and 'foo::bar' would have
+been too confusing to document, and to code and test.
+
 
 File: gawk.info,  Node: Symbol table by cookie,  Next: Cached values,  Prev: 
Symbol table by name,  Up: Symbol Table Access
 
-16.4.10.2 Variable Access and Update by Cookie
+17.4.10.2 Variable Access and Update by Cookie
 ..............................................
 
 A "scalar cookie" is an opaque handle that provides access to a global
@@ -25284,7 +25736,7 @@ like this:
 
 File: gawk.info,  Node: Cached values,  Prev: Symbol table by cookie,  Up: 
Symbol Table Access
 
-16.4.10.3 Creating and Using Cached Values
+17.4.10.3 Creating and Using Cached Values
 ..........................................
 
 The routines in this minor node allow you to create and release cached
@@ -25382,7 +25834,7 @@ memory.
 
 File: gawk.info,  Node: Array Manipulation,  Next: Redirection API,  Prev: 
Symbol Table Access,  Up: Extension API Description
 
-16.4.11 Array Manipulation
+17.4.11 Array Manipulation
 --------------------------
 
 The primary data structure(1) in 'awk' is the associative array (*note
@@ -25409,7 +25861,7 @@ arrays of arrays (*note General Data Types::).
 
 File: gawk.info,  Node: Array Data Types,  Next: Array Functions,  Up: Array 
Manipulation
 
-16.4.11.1 Array Data Types
+17.4.11.1 Array Data Types
 ..........................
 
 The data types associated with arrays are as follows:
@@ -25476,7 +25928,7 @@ overuse this term.
 
 File: gawk.info,  Node: Array Functions,  Next: Flattening Arrays,  Prev: 
Array Data Types,  Up: Array Manipulation
 
-16.4.11.2 Array Functions
+17.4.11.2 Array Functions
 .........................
 
 The following functions relate to individual array elements:
@@ -25494,7 +25946,7 @@ The following functions relate to individual array 
elements:
      value of the element whose index is 'index'.  'wanted' specifies
      the type of value you wish to retrieve.  Return false if 'wanted'
      does not match the actual type or if 'index' is not in the array
-     (*note Table 16.1: table-value-types-returned.).
+     (*note Table 17.2: table-value-types-returned.).
 
      The value for 'index' can be numeric, in which case 'gawk' converts
      it to a string.  Using nonintegral values is possible, but requires
@@ -25566,7 +26018,7 @@ The following functions relate to individual array 
elements:
 
 File: gawk.info,  Node: Flattening Arrays,  Next: Creating Arrays,  Prev: 
Array Functions,  Up: Array Manipulation
 
-16.4.11.3 Working With All The Elements of an Array
+17.4.11.3 Working With All The Elements of an Array
 ...................................................
 
 To "flatten" an array is to create a structure that represents the full
@@ -25740,7 +26192,7 @@ return value to success, and returns:
 
 File: gawk.info,  Node: Creating Arrays,  Prev: Flattening Arrays,  Up: Array 
Manipulation
 
-16.4.11.4 How To Create and Populate Arrays
+17.4.11.4 How To Create and Populate Arrays
 ...........................................
 
 Besides working with arrays created by 'awk' code, you can create arrays
@@ -25879,7 +26331,7 @@ environment variable.)
 
 File: gawk.info,  Node: Redirection API,  Next: Extension API Variables,  
Prev: Array Manipulation,  Up: Extension API Description
 
-16.4.12 Accessing and Manipulating Redirections
+17.4.12 Accessing and Manipulating Redirections
 -----------------------------------------------
 
 The following function allows extensions to access and manipulate
@@ -25949,7 +26401,7 @@ I/O multiplexing and a socket library.
 
 File: gawk.info,  Node: Extension API Variables,  Next: Extension API 
Boilerplate,  Prev: Redirection API,  Up: Extension API Description
 
-16.4.13 API Variables
+17.4.13 API Variables
 ---------------------
 
 The API provides two sets of variables.  The first provides information
@@ -25967,7 +26419,7 @@ information about how 'gawk' was invoked.
 
 File: gawk.info,  Node: Extension Versioning,  Next: Extension GMP/MPFR 
Versioning,  Up: Extension API Variables
 
-16.4.13.1 API Version Constants and Variables
+17.4.13.1 API Version Constants and Variables
 .............................................
 
 The API provides both a "major" and a "minor" version number.  The API
@@ -25980,7 +26432,7 @@ API Version   C Preprocessor Define      enum constant
 Major         'gawk_api_major_version'   'GAWK_API_MAJOR_VERSION'
 Minor         'gawk_api_minor_version'   'GAWK_API_MINOR_VERSION'
 
-Table 16.2: gawk API version constants
+Table 17.3: gawk API version constants
 
    The minor version increases when new functions are added to the API.
 Such new functions are always added to the end of the API 'struct'.
@@ -26019,7 +26471,7 @@ Boilerplate::).
 
 File: gawk.info,  Node: Extension GMP/MPFR Versioning,  Next: Extension API 
Informational Variables,  Prev: Extension Versioning,  Up: Extension API 
Variables
 
-16.4.13.2 GMP and MPFR Version Information
+17.4.13.2 GMP and MPFR Version Information
 ..........................................
 
 The API also includes information about the versions of GMP and MPFR
@@ -26061,7 +26513,7 @@ match those of 'gawk' with the following macro:
 
 File: gawk.info,  Node: Extension API Informational Variables,  Prev: 
Extension GMP/MPFR Versioning,  Up: Extension API Variables
 
-16.4.13.3 Informational Variables
+17.4.13.3 Informational Variables
 .................................
 
 The API provides access to several variables that describe whether the
@@ -26096,7 +26548,7 @@ change during execution.
 
 File: gawk.info,  Node: Extension API Boilerplate,  Next: Changes from API V1, 
 Prev: Extension API Variables,  Up: Extension API Description
 
-16.4.14 Boilerplate Code
+17.4.14 Boilerplate Code
 ------------------------
 
 As mentioned earlier (*note Extension Mechanism Outline::), the function
@@ -26200,7 +26652,7 @@ does the following:
 
 File: gawk.info,  Node: Changes from API V1,  Prev: Extension API Boilerplate, 
 Up: Extension API Description
 
-16.4.15 Changes From Version 1 of the API
+17.4.15 Changes From Version 1 of the API
 -----------------------------------------
 
 The current API is _not_ binary compatible with version 1 of the API.
@@ -26242,7 +26694,7 @@ version 2 of the API:
 
 File: gawk.info,  Node: Finding Extensions,  Next: Extension Example,  Prev: 
Extension API Description,  Up: Dynamic Extensions
 
-16.5 How 'gawk' Finds Extensions
+17.5 How 'gawk' Finds Extensions
 ================================
 
 Compiled extensions have to be installed in a directory where 'gawk' can
@@ -26254,7 +26706,7 @@ compiled extensions.  *Note AWKLIBPATH Variable:: for 
more information.
 
 File: gawk.info,  Node: Extension Example,  Next: Extension Samples,  Prev: 
Finding Extensions,  Up: Dynamic Extensions
 
-16.6 Example: Some File Functions
+17.6 Example: Some File Functions
 =================================
 
      No matter where you go, there you are.
@@ -26275,7 +26727,7 @@ in an extension.
 
 File: gawk.info,  Node: Internal File Description,  Next: Internal File Ops,  
Up: Extension Example
 
-16.6.1 Using 'chdir()' and 'stat()'
+17.6.1 Using 'chdir()' and 'stat()'
 -----------------------------------
 
 This minor node shows how to use the new functions at the 'awk' level
@@ -26405,7 +26857,7 @@ Elements::):
 
 File: gawk.info,  Node: Internal File Ops,  Next: Using Internal File Ops,  
Prev: Internal File Description,  Up: Extension Example
 
-16.6.2 C Code for 'chdir()' and 'stat()'
+17.6.2 C Code for 'chdir()' and 'stat()'
 ----------------------------------------
 
 Here is the C code for these extensions.(1)
@@ -26748,7 +27200,7 @@ version.
 
 File: gawk.info,  Node: Using Internal File Ops,  Prev: Internal File Ops,  
Up: Extension Example
 
-16.6.3 Integrating the Extensions
+17.6.3 Integrating the Extensions
 ---------------------------------
 
 Now that the code is written, it must be possible to add it at runtime
@@ -26829,7 +27281,7 @@ file.  *Note gawkextlib:: for Internet links to the 
tools.
 
 File: gawk.info,  Node: Extension Samples,  Next: gawkextlib,  Prev: Extension 
Example,  Up: Dynamic Extensions
 
-16.7 The Sample Extensions in the 'gawk' Distribution
+17.7 The Sample Extensions in the 'gawk' Distribution
 =====================================================
 
 This minor node provides a brief overview of the sample extensions that
@@ -26859,7 +27311,7 @@ the extension API.
 
 File: gawk.info,  Node: Extension Sample File Functions,  Next: Extension 
Sample Fnmatch,  Up: Extension Samples
 
-16.7.1 File-Related Functions
+17.7.1 File-Related Functions
 -----------------------------
 
 The 'filefuncs' extension provides three different functions, as
@@ -27029,7 +27481,7 @@ the 'fts()' extension function.
 
 File: gawk.info,  Node: Extension Sample Fnmatch,  Next: Extension Sample 
Fork,  Prev: Extension Sample File Functions,  Up: Extension Samples
 
-16.7.2 Interface to 'fnmatch()'
+17.7.2 Interface to 'fnmatch()'
 -------------------------------
 
 This extension provides an interface to the C library 'fnmatch()'
@@ -27080,7 +27532,7 @@ Array element      Corresponding flag defined by 
'fnmatch()'
 
 File: gawk.info,  Node: Extension Sample Fork,  Next: Extension Sample 
Inplace,  Prev: Extension Sample Fnmatch,  Up: Extension Samples
 
-16.7.3 Interface to 'fork()', 'wait()', and 'waitpid()'
+17.7.3 Interface to 'fork()', 'wait()', and 'waitpid()'
 -------------------------------------------------------
 
 The 'fork' extension adds three functions, as follows:
@@ -27117,19 +27569,21 @@ The 'fork' extension adds three functions, as follows:
 
 File: gawk.info,  Node: Extension Sample Inplace,  Next: Extension Sample Ord, 
 Prev: Extension Sample Fork,  Up: Extension Samples
 
-16.7.4 Enabling In-Place File Editing
+17.7.4 Enabling In-Place File Editing
 -------------------------------------
 
 The 'inplace' extension emulates GNU 'sed''s '-i' option, which performs
 "in-place" editing of each input file.  It uses the bundled
-'inplace.awk' include file to invoke the extension properly:
+'inplace.awk' include file to invoke the extension properly.  This
+extension makes use of the namespace facility to place all the variables
+and functions in the 'inplace' namespace (*note Namespaces::):
 
      # inplace --- load and invoke the inplace extension.
 
      @load "inplace"
 
-     # Please set INPLACE_SUFFIX to make a backup copy.  For example, you may
-     # want to set INPLACE_SUFFIX to .bak on the command line or in a BEGIN 
rule.
+     # Please set inplace::suffix to make a backup copy.  For example, you may
+     # want to set inplace::suffix to .bak on the command line or in a BEGIN 
rule.
 
      # By default, each filename on the command line will be edited inplace.
      # But you can selectively disable this by adding an inplace=0 argument
@@ -27137,44 +27591,46 @@ The 'inplace' extension emulates GNU 'sed''s '-i' 
option, which performs
      # reenable it later on the commandline by putting inplace=1 before files
      # that you wish to be subject to inplace editing.
 
-     # N.B. We call inplace_end() in the BEGINFILE and END rules so that any
+     # N.B. We call inplace::end() in the BEGINFILE and END rules so that any
      # actions in an ENDFILE rule will be redirected as expected.
 
+     @namespace "inplace"
+
      BEGIN {
-         inplace = 1         # enabled by default
+         enable = 1         # enabled by default
      }
 
      BEGINFILE {
-         if (_inplace_filename != "")
-             inplace_end(_inplace_filename, INPLACE_SUFFIX)
-         if (inplace)
-             inplace_begin(_inplace_filename = FILENAME, INPLACE_SUFFIX)
+         if (filename != "")
+             end(filename, suffix)
+         if (enable)
+             begin(filename = FILENAME, suffix)
          else
-             _inplace_filename = ""
+             filename = ""
      }
 
      END {
-         if (_inplace_filename != "")
-             inplace_end(_inplace_filename, INPLACE_SUFFIX)
+         if (filename != "")
+             end(filename, suffix)
      }
 
    For each regular file that is processed, the extension redirects
 standard output to a temporary file configured to have the same owner
 and permissions as the original.  After the file has been processed, the
 extension restores standard output to its original destination.  If
-'INPLACE_SUFFIX' is not an empty string, the original file is linked to
+'inplace::suffix' is not an empty string, the original file is linked to
 a backup file name created by appending that suffix.  Finally, the
 temporary file is renamed to the original file name.
 
    Note that the use of this feature can be controlled by placing
-'inplace=0' on the command-line prior to listing files that should not
-be processed this way.  You can reenable inplace editing by adding an
-'inplace=1' argument prior to files that should be subject to inplace
-editing.
+'inplace::enable=0' on the command-line prior to listing files that
+should not be processed this way.  You can reenable inplace editing by
+adding an 'inplace::enable=1' argument prior to files that should be
+subject to inplace editing.
 
-   The '_inplace_filename' variable serves to keep track of the current
-filename so as to not invoke 'inplace_end()' before processing the first
-file.
+   The 'inplace::filename' variable serves to keep track of the current
+filename so as to not invoke 'inplace::end()' before processing the
+first file.
 
    If any error occurs, the extension issues a fatal error to terminate
 processing immediately without damaging the original file.
@@ -27185,7 +27641,7 @@ processing immediately without damaging the original 
file.
 
    To keep a backup copy of the original files, try this:
 
-     $ gawk -i inplace -v INPLACE_SUFFIX=.bak '{ gsub(/foo/, "bar") }
+     $ gawk -i inplace -v inplace::suffix=.bak '{ gsub(/foo/, "bar") }
      > { print }' file1 file2 file3
 
    Please note that, while the extension does attempt to preserve
@@ -27198,7 +27654,7 @@ signal is received, a temporary file may be left behind.
 
 File: gawk.info,  Node: Extension Sample Ord,  Next: Extension Sample Readdir, 
 Prev: Extension Sample Inplace,  Up: Extension Samples
 
-16.7.5 Character and Numeric values: 'ord()' and 'chr()'
+17.7.5 Character and Numeric values: 'ord()' and 'chr()'
 --------------------------------------------------------
 
 The 'ordchr' extension adds two functions, named 'ord()' and 'chr()', as
@@ -27225,7 +27681,7 @@ same name.  Here is an example:
 
 File: gawk.info,  Node: Extension Sample Readdir,  Next: Extension Sample 
Revout,  Prev: Extension Sample Ord,  Up: Extension Samples
 
-16.7.6 Reading Directories
+17.7.6 Reading Directories
 --------------------------
 
 The 'readdir' extension adds an input parser for directories.  The usage
@@ -27242,7 +27698,7 @@ number and the file name, separated by a forward slash 
character.  On
 systems where the directory entry contains the file type, the record has
 a third field (also separated by a slash), which is a single letter
 indicating the type of the file.  The letters and their corresponding
-file types are shown in *note Table 16.3: table-readdir-file-types.
+file types are shown in *note Table 17.4: table-readdir-file-types.
 
 Letter  File type
 --------------------------------------------------------------------------
@@ -27255,7 +27711,7 @@ Letter  File type
 's'     Socket
 'u'     Anything else (unknown)
 
-Table 16.3: File types returned by the 'readdir' extension
+Table 17.4: File types returned by the 'readdir' extension
 
    On systems without the file type information, the third field is
 always 'u'.
@@ -27275,7 +27731,7 @@ always 'u'.
 
 File: gawk.info,  Node: Extension Sample Revout,  Next: Extension Sample 
Rev2way,  Prev: Extension Sample Readdir,  Up: Extension Samples
 
-16.7.7 Reversing Output
+17.7.7 Reversing Output
 -----------------------
 
 The 'revoutput' extension adds a simple output wrapper that reverses the
@@ -27295,7 +27751,7 @@ unwary.  Here is an example:
 
 File: gawk.info,  Node: Extension Sample Rev2way,  Next: Extension Sample Read 
write array,  Prev: Extension Sample Revout,  Up: Extension Samples
 
-16.7.8 Two-Way I/O Example
+17.7.8 Two-Way I/O Example
 --------------------------
 
 The 'revtwoway' extension adds a simple two-way processor that reverses
@@ -27319,7 +27775,7 @@ to use it:
 
 File: gawk.info,  Node: Extension Sample Read write array,  Next: Extension 
Sample Readfile,  Prev: Extension Sample Rev2way,  Up: Extension Samples
 
-16.7.9 Dumping and Restoring an Array
+17.7.9 Dumping and Restoring an Array
 -------------------------------------
 
 The 'rwarray' extension adds two functions, named 'writea()' and
@@ -27366,7 +27822,7 @@ on systems with a different one, but this has not been 
tried.
 
 File: gawk.info,  Node: Extension Sample Readfile,  Next: Extension Sample 
Time,  Prev: Extension Sample Read write array,  Up: Extension Samples
 
-16.7.10 Reading an Entire File
+17.7.10 Reading an Entire File
 ------------------------------
 
 The 'readfile' extension adds a single function named 'readfile()', and
@@ -27399,7 +27855,7 @@ an input parser:
 
 File: gawk.info,  Node: Extension Sample Time,  Next: Extension Sample API 
Tests,  Prev: Extension Sample Readfile,  Up: Extension Samples
 
-16.7.11 Extension Time Functions
+17.7.11 Extension Time Functions
 --------------------------------
 
 The 'time' extension adds two functions, named 'gettimeofday()' and
@@ -27430,7 +27886,7 @@ The 'time' extension adds two functions, named 
'gettimeofday()' and
 
 File: gawk.info,  Node: Extension Sample API Tests,  Prev: Extension Sample 
Time,  Up: Extension Samples
 
-16.7.12 API Tests
+17.7.12 API Tests
 -----------------
 
 The 'testext' extension exercises parts of the extension API that are
@@ -27442,7 +27898,7 @@ code and runs the tests.  See the source file for more 
information.
 
 File: gawk.info,  Node: gawkextlib,  Next: Extension summary,  Prev: Extension 
Samples,  Up: Dynamic Extensions
 
-16.8 The 'gawkextlib' Project
+17.8 The 'gawkextlib' Project
 =============================
 
 The 'gawkextlib' (https://sourceforge.net/projects/gawkextlib/) project
@@ -27511,7 +27967,7 @@ project's website for more information.
 
 File: gawk.info,  Node: Extension summary,  Next: Extension Exercises,  Prev: 
gawkextlib,  Up: Dynamic Extensions
 
-16.9 Summary
+17.9 Summary
 ============
 
    * You can write extensions (sometimes called plug-ins) for 'gawk' in
@@ -27599,7 +28055,7 @@ File: gawk.info,  Node: Extension summary,  Next: 
Extension Exercises,  Prev: ga
 
 File: gawk.info,  Node: Extension Exercises,  Prev: Extension summary,  Up: 
Dynamic Extensions
 
-16.10 Exercises
+17.10 Exercises
 ===============
 
   1. Add functions to implement system calls such as 'chown()',
@@ -27620,12 +28076,7 @@ File: gawk.info,  Node: Extension Exercises,  Prev: 
Extension summary,  Up: Dyna
      writing the prompt?  Which reading mechanism should you replace,
      the one to get a record, or the one to read raw bytes?
 
-  3. (Hard.)  How would you provide namespaces in 'gawk', so that the
-     names of functions in different extensions don't conflict with each
-     other?  If you come up with a really good scheme, contact the
-     'gawk' maintainer to tell him about it.
-
-  4. Write a wrapper script that provides an interface similar to 'sed
+  3. Write a wrapper script that provides an interface similar to 'sed
      -i' for the "inplace" extension presented in *note Extension Sample
      Inplace::.
 
@@ -33098,13 +33549,13 @@ Index
 * - (hyphen), -- operator <1>:           Precedence.          (line  45)
 * - (hyphen), -= operator:               Assignment Ops.      (line 129)
 * - (hyphen), -= operator <1>:           Precedence.          (line  94)
-* - (hyphen), filenames beginning with:  Options.             (line  60)
+* - (hyphen), filenames beginning with:  Options.             (line  64)
 * - (hyphen), in bracket expressions:    Bracket Expressions. (line  25)
-* --assign option:                       Options.             (line  32)
-* --bignum option:                       Options.             (line 217)
-* --characters-as-bytes option:          Options.             (line  69)
-* --copyright option:                    Options.             (line  89)
-* --debug option:                        Options.             (line 108)
+* --assign option:                       Options.             (line  36)
+* --bignum option:                       Options.             (line 229)
+* --characters-as-bytes option:          Options.             (line  73)
+* --copyright option:                    Options.             (line  93)
+* --debug option:                        Options.             (line 112)
 * --disable-extensions configuration option: Additional Configuration Options.
                                                               (line   9)
 * --disable-lint configuration option:   Additional Configuration Options.
@@ -33113,81 +33564,81 @@ Index
                                                               (line  32)
 * --disable-nls configuration option:    Additional Configuration Options.
                                                               (line  37)
-* --dump-variables option:               Options.             (line  94)
+* --dump-variables option:               Options.             (line  98)
 * --dump-variables option, using for library functions: Library Names.
                                                               (line  45)
 * --enable-versioned-extension-dir configuration option: Additional 
Configuration Options.
                                                               (line  42)
-* --exec option:                         Options.             (line 139)
+* --exec option:                         Options.             (line 147)
 * --field-separator option:              Options.             (line  21)
 * --file option:                         Options.             (line  25)
-* --gen-pot option:                      Options.             (line 161)
+* --gen-pot option:                      Options.             (line 169)
 * --gen-pot option <1>:                  String Extraction.   (line   6)
 * --gen-pot option <2>:                  String Extraction.   (line   6)
-* --help option:                         Options.             (line 168)
-* --include option:                      Options.             (line 173)
+* --help option:                         Options.             (line 176)
+* --include option:                      Options.             (line 181)
 * --lint option:                         Command Line.        (line  20)
-* --lint option <1>:                     Options.             (line 198)
-* --lint-old option:                     Options.             (line 312)
-* --load option:                         Options.             (line 186)
-* --no-optimize option:                  Options.             (line 298)
-* --non-decimal-data option:             Options.             (line 223)
+* --lint option <1>:                     Options.             (line 210)
+* --lint-old option:                     Options.             (line 324)
+* --load option:                         Options.             (line 198)
+* --no-optimize option:                  Options.             (line 310)
+* --non-decimal-data option:             Options.             (line 235)
 * --non-decimal-data option <1>:         Nondecimal Data.     (line   6)
 * --non-decimal-data option, strtonum() function and: Nondecimal Data.
                                                               (line  35)
-* --optimize option:                     Options.             (line 248)
-* --posix option:                        Options.             (line 270)
-* --posix option, --traditional option and: Options.          (line 285)
-* --pretty-print option:                 Options.             (line 237)
-* --profile option:                      Options.             (line 258)
+* --optimize option:                     Options.             (line 260)
+* --posix option:                        Options.             (line 282)
+* --posix option, --traditional option and: Options.          (line 297)
+* --pretty-print option:                 Options.             (line 249)
+* --profile option:                      Options.             (line 270)
 * --profile option <1>:                  Profiling.           (line  12)
-* --re-interval option:                  Options.             (line 291)
-* --sandbox option:                      Options.             (line 303)
+* --re-interval option:                  Options.             (line 303)
+* --sandbox option:                      Options.             (line 315)
 * --sandbox option, disabling system() function: I/O Functions.
                                                               (line 128)
 * --sandbox option, input redirection with getline: Getline.  (line  19)
 * --sandbox option, output redirection with print, printf: Redirection.
                                                               (line   6)
-* --source option:                       Options.             (line 117)
-* --traditional option:                  Options.             (line  82)
-* --traditional option, --posix option and: Options.          (line 285)
-* --use-lc-numeric option:               Options.             (line 232)
-* --version option:                      Options.             (line 317)
-* -b option:                             Options.             (line  69)
-* -c option:                             Options.             (line  82)
-* -C option:                             Options.             (line  89)
-* -d option:                             Options.             (line  94)
-* -D option:                             Options.             (line 108)
-* -e option:                             Options.             (line 117)
-* -E option:                             Options.             (line 139)
-* -e option <1>:                         Options.             (line 353)
+* --source option:                       Options.             (line 121)
+* --traditional option:                  Options.             (line  86)
+* --traditional option, --posix option and: Options.          (line 297)
+* --use-lc-numeric option:               Options.             (line 244)
+* --version option:                      Options.             (line 329)
+* -b option:                             Options.             (line  73)
+* -c option:                             Options.             (line  86)
+* -C option:                             Options.             (line  93)
+* -d option:                             Options.             (line  98)
+* -D option:                             Options.             (line 112)
+* -e option:                             Options.             (line 121)
+* -E option:                             Options.             (line 147)
+* -e option <1>:                         Options.             (line 365)
 * -f option:                             Long.                (line  12)
 * -F option:                             Options.             (line  21)
 * -f option <1>:                         Options.             (line  25)
-* -F option, -Ft sets FS to TAB:         Options.             (line 325)
+* -F option, -Ft sets FS to TAB:         Options.             (line 337)
 * -F option, command-line:               Command Line Field Separator.
                                                               (line   6)
-* -f option, multiple uses:              Options.             (line 330)
-* -g option:                             Options.             (line 161)
-* -h option:                             Options.             (line 168)
-* -i option:                             Options.             (line 173)
-* -l option:                             Options.             (line 186)
-* -l option <1>:                         Options.             (line 198)
-* -L option:                             Options.             (line 312)
-* -M option:                             Options.             (line 217)
-* -n option:                             Options.             (line 223)
-* -N option:                             Options.             (line 232)
-* -o option:                             Options.             (line 237)
-* -O option:                             Options.             (line 248)
-* -p option:                             Options.             (line 258)
-* -P option:                             Options.             (line 270)
-* -r option:                             Options.             (line 291)
-* -s option:                             Options.             (line 298)
-* -S option:                             Options.             (line 303)
-* -v option:                             Options.             (line  32)
-* -V option:                             Options.             (line 317)
+* -f option, multiple uses:              Options.             (line 342)
+* -g option:                             Options.             (line 169)
+* -h option:                             Options.             (line 176)
+* -i option:                             Options.             (line 181)
+* -l option:                             Options.             (line 198)
+* -l option <1>:                         Options.             (line 210)
+* -L option:                             Options.             (line 324)
+* -M option:                             Options.             (line 229)
+* -n option:                             Options.             (line 235)
+* -N option:                             Options.             (line 244)
+* -o option:                             Options.             (line 249)
+* -O option:                             Options.             (line 260)
+* -p option:                             Options.             (line 270)
+* -P option:                             Options.             (line 282)
+* -r option:                             Options.             (line 303)
+* -s option:                             Options.             (line 310)
+* -S option:                             Options.             (line 315)
+* -v option:                             Options.             (line  36)
+* -V option:                             Options.             (line 329)
 * -v option <1>:                         Assignment Options.  (line  12)
-* -W option:                             Options.             (line  47)
+* -W option:                             Options.             (line  51)
 * . (period), regexp operator:           Regexp Operators.    (line  44)
 * .gmo files:                            Explaining gettext.  (line  42)
 * .gmo files, specifying directory of:   Explaining gettext.  (line  54)
@@ -33211,6 +33662,7 @@ Index
 * /inet4/... special files (gawk):       TCP/IP Networking.   (line   6)
 * /inet6/... special files (gawk):       TCP/IP Networking.   (line   6)
 * : (colon), ?: operator:                Precedence.          (line  91)
+* ::, namespace separator:               Qualified Names.     (line   6)
 * ; (semicolon), AWKPATH variable and:   PC Using.            (line  13)
 * ; (semicolon), separating rules:       Statements/Lines.    (line  90)
 * ; (semicolon), separating statements in actions: Statements/Lines.
@@ -33247,6 +33699,10 @@ Index
 * @include directive:                    Include Files.       (line   8)
 * @load directive:                       Loading Shared Libraries.
                                                               (line   8)
+* @namespace directive:                  Changing The Namespace.
+                                                              (line   6)
+* @namespace, no effect on BEGIN BEGINFILE, END, and ENDFILE: Changing The 
Namespace.
+                                                              (line  37)
 * [] (square brackets), regexp operator: Regexp Operators.    (line  56)
 * \ (backslash):                         Comments.            (line  50)
 * \ (backslash), as field separator:     Command Line Field Separator.
@@ -33485,9 +33941,14 @@ Index
 * atan2:                                 Numeric Functions.   (line  12)
 * automatic displays, in debugger:       Debugger Info.       (line  24)
 * awf (amazingly workable formatter) program: Glossary.       (line  23)
-* awk debugging, enabling:               Options.             (line 108)
+* awk debugging, enabling:               Options.             (line 112)
 * awk language, POSIX version:           Assignment Ops.      (line 138)
-* awk profiling, enabling:               Options.             (line 258)
+* awk namespace:                         Default Namespace.   (line   6)
+* awk namespace, identifier name storage: Internal Name Management.
+                                                              (line   6)
+* awk namespace, use for indirect function calls: Internal Name Management.
+                                                              (line   6)
+* awk profiling, enabling:               Options.             (line 270)
 * awk programs:                          Getting Started.     (line  12)
 * awk programs <1>:                      Executable Scripts.  (line   6)
 * awk programs <2>:                      Two Rules.           (line   6)
@@ -33501,8 +33962,8 @@ Index
 * awk programs, lengthy:                 Long.                (line   6)
 * awk programs, lengthy, assertions:     Assert Function.     (line   6)
 * awk programs, location of:             Options.             (line  25)
-* awk programs, location of <1>:         Options.             (line 139)
-* awk programs, location of <2>:         Options.             (line 173)
+* awk programs, location of <1>:         Options.             (line 147)
+* awk programs, location of <2>:         Options.             (line 181)
 * awk programs, one-line examples:       Very Simple.         (line  46)
 * awk programs, profiling:               Profiling.           (line   6)
 * awk programs, running:                 Running gawk.        (line   6)
@@ -33544,7 +34005,7 @@ Index
 * AWKPATH environment variable <1>:      PC Using.            (line  13)
 * awkprof.out file:                      Profiling.           (line   6)
 * awksed.awk program:                    Simple Sed.          (line  25)
-* awkvars.out file:                      Options.             (line  94)
+* awkvars.out file:                      Options.             (line  98)
 * b debugger command (alias for break):  Breakpoint Control.  (line  11)
 * backslash (\):                         Comments.            (line  50)
 * backslash (\), as field separator:     Command Line Field Separator.
@@ -33619,10 +34080,14 @@ Index
 * BEGIN pattern, pwcat program:          Passwd Functions.    (line 143)
 * BEGIN pattern, running awk programs and: Cut Program.       (line  63)
 * BEGIN pattern, TEXTDOMAIN variable and: Programmer i18n.    (line  60)
+* BEGIN, execution order not affected by @namespace: Changing The Namespace.
+                                                              (line  37)
 * BEGINFILE pattern:                     BEGINFILE/ENDFILE.   (line   6)
 * BEGINFILE pattern, Boolean patterns and: Expression Patterns.
                                                               (line  70)
 * beginfile() user-defined function:     Filetrans Function.  (line  62)
+* BEGINFILE, execution order not affected by @namespace: Changing The 
Namespace.
+                                                              (line  37)
 * Bentley, Jon:                          Glossary.            (line 204)
 * Benzinger, Michael:                    Contributors.        (line 100)
 * Berry, Karl:                           Acknowledgments.     (line  33)
@@ -33746,7 +34211,7 @@ Index
 * case sensitivity, regexps and:         Case-sensitivity.    (line   6)
 * case sensitivity, regexps and <1>:     User-modified.       (line  79)
 * case sensitivity, string comparisons and: User-modified.    (line  79)
-* CGI, awk scripts for:                  Options.             (line 139)
+* CGI, awk scripts for:                  Options.             (line 147)
 * character classes, See bracket expressions: Regexp Operators.
                                                               (line  56)
 * character lists in regular expressions: Bracket Expressions.
@@ -33806,7 +34271,7 @@ Index
 * command line, invoking awk from:       Command Line.        (line   6)
 * command line, option -f:               Long.                (line  12)
 * command line, options:                 Options.             (line   6)
-* command line, options, end of:         Options.             (line  55)
+* command line, options, end of:         Options.             (line  59)
 * command line, variables, assigning on: Assignment Options.  (line   6)
 * command-line options, processing:      Getopt Function.     (line   6)
 * command-line options, string extraction: String Extraction. (line   6)
@@ -33842,7 +34307,7 @@ Index
                                                               (line  59)
 * compatibility mode (gawk), octal numbers: Nondecimal-numbers.
                                                               (line  59)
-* compatibility mode (gawk), specifying: Options.             (line  82)
+* compatibility mode (gawk), specifying: Options.             (line  86)
 * compiled programs:                     Basic High Level.    (line  13)
 * compiled programs <1>:                 Glossary.            (line 216)
 * compiling gawk for Cygwin:             Cygwin.              (line   6)
@@ -33850,6 +34315,8 @@ Index
 * compiling gawk for VMS:                VMS Compilation.     (line   6)
 * compl:                                 Bitwise Functions.   (line  44)
 * complement, bitwise:                   Bitwise Functions.   (line  25)
+* component name:                        Qualified Names.     (line   6)
+* component names, naming rules:         Naming Rules.        (line   6)
 * compound statements, control statements and: Statements.    (line  10)
 * concatenating:                         Concatenation.       (line   9)
 * condition debugger command:            Breakpoint Control.  (line  54)
@@ -33902,11 +34369,13 @@ Index
 * cosine:                                Numeric Functions.   (line  16)
 * counting:                              Wc Program.          (line   6)
 * csh utility:                           Statements/Lines.    (line  43)
-* csh utility, POSIXLY_CORRECT environment variable: Options. (line 371)
+* csh utility, POSIXLY_CORRECT environment variable: Options. (line 383)
 * csh utility, |& operator, comparison with: Two-way I/O.     (line  27)
 * ctime() user-defined function:         Function Example.    (line  74)
 * Curreli, Marco:                        Contributors.        (line 147)
 * currency symbols, localization:        Explaining gettext.  (line 104)
+* current namespace, pushing and popping: Changing The Namespace.
+                                                              (line  29)
 * current system time:                   Time Functions.      (line  68)
 * custom.h file:                         Configuration Philosophy.
                                                               (line  30)
@@ -34101,6 +34570,8 @@ Index
 * debugger, history size:                Debugger Info.       (line  65)
 * debugger, how to start:                Debugger Invocation. (line   6)
 * debugger, instruction tracing:         Debugger Info.       (line  90)
+* debugger, interaction with namespaces: Namespace And Features.
+                                                              (line  17)
 * debugger, limitations:                 Limitations.         (line   6)
 * debugger, n command:                   Finding The Bug.     (line 105)
 * debugger, next command:                Finding The Bug.     (line 105)
@@ -34123,7 +34594,7 @@ Index
 * debugging gawk, bug reports:           Bugs.                (line   9)
 * debugging, example session:            Sample Debugging Session.
                                                               (line   6)
-* decimal point character, locale specific: Options.          (line 282)
+* decimal point character, locale specific: Options.          (line 294)
 * decrement operators:                   Increment Ops.       (line  35)
 * default keyword:                       Switch Statement.    (line   6)
 * Deifik, Scott:                         Acknowledgments.     (line  60)
@@ -34246,7 +34717,7 @@ Index
 * down debugger command:                 Execution Stack.     (line  23)
 * Drepper, Ulrich:                       Acknowledgments.     (line  52)
 * Duman, Patrice:                        Acknowledgments.     (line  75)
-* dump all variables of a program:       Options.             (line  94)
+* dump all variables of a program:       Options.             (line  98)
 * dump debugger command:                 Miscellaneous Debugger Commands.
                                                               (line   9)
 * dupword.awk program:                   Dupword Program.     (line  31)
@@ -34292,9 +34763,13 @@ Index
 * END pattern, operators and:            Using BEGIN/END.     (line  17)
 * END pattern, print statement and:      I/O And BEGIN/END.   (line  15)
 * END pattern, profiling and:            Profiling.           (line  62)
+* END, execution order not affected by @namespace: Changing The Namespace.
+                                                              (line  37)
 * ENDFILE pattern:                       BEGINFILE/ENDFILE.   (line   6)
 * ENDFILE pattern, Boolean patterns and: Expression Patterns. (line  70)
 * endfile() user-defined function:       Filetrans Function.  (line  62)
+* ENDFILE, execution order not affected by @namespace: Changing The Namespace.
+                                                              (line  37)
 * endgrent() function (C library):       Group Functions.     (line 213)
 * endgrent() user-defined function:      Group Functions.     (line 216)
 * endpwent() function (C library):       Passwd Functions.    (line 208)
@@ -34379,6 +34854,8 @@ Index
                                                               (line   6)
 * extension API version:                 Extension Versioning.
                                                               (line   6)
+* extension API, interaction with namespaces: Namespace And Features.
+                                                              (line  22)
 * extension API, version number:         Auto-set.            (line 287)
 * extension example:                     Extension Example.   (line   6)
 * extension registration:                Registration Functions.
@@ -34480,7 +34957,7 @@ Index
 * files, /inet6/... (gawk):              TCP/IP Networking.   (line   6)
 * files, awk programs in:                Long.                (line   6)
 * files, awkprof.out:                    Profiling.           (line   6)
-* files, awkvars.out:                    Options.             (line  94)
+* files, awkvars.out:                    Options.             (line  98)
 * files, closing:                        I/O Functions.       (line  10)
 * files, descriptors, See file descriptors: Special FD.       (line   6)
 * files, group:                          Group Functions.     (line   6)
@@ -34507,7 +34984,7 @@ Index
 * files, portable object template:       Explaining gettext.  (line  31)
 * files, portable object, converting to message object files: I18N Example.
                                                               (line  80)
-* files, portable object, generating:    Options.             (line 161)
+* files, portable object, generating:    Options.             (line 169)
 * files, processing, ARGIND variable and: Auto-set.           (line  50)
 * files, reading:                        Rewind Function.     (line   6)
 * files, reading, multiline records:     Multiple Line.       (line   6)
@@ -34577,7 +35054,7 @@ Index
 * FS variable, --field-separator option and: Options.         (line  21)
 * FS variable, as null string:           Single Character Fields.
                                                               (line  20)
-* FS variable, as TAB character:         Options.             (line 279)
+* FS variable, as TAB character:         Options.             (line 291)
 * FS variable, changing value of:        Field Separators.    (line  34)
 * FS variable, running awk programs and: Cut Program.         (line  63)
 * FS variable, setting from command line: Command Line Field Separator.
@@ -34667,7 +35144,7 @@ Index
 * gawk, ERRNO variable in <3>:           Auto-set.            (line  87)
 * gawk, ERRNO variable in <4>:           TCP/IP Networking.   (line  54)
 * gawk, escape sequences:                Escape Sequences.    (line 121)
-* gawk, extensions, disabling:           Options.             (line 270)
+* gawk, extensions, disabling:           Options.             (line 282)
 * gawk, features, adding:                Adding Code.         (line   6)
 * gawk, features, advanced:              Advanced Features.   (line   6)
 * gawk, field separators and:            User-modified.       (line  74)
@@ -34729,7 +35206,7 @@ Index
 * gawk, TEXTDOMAIN variable in:          User-modified.       (line 155)
 * gawk, timestamps:                      Time Functions.      (line   6)
 * gawk, uses for:                        Preface.             (line  34)
-* gawk, versions of, information about, printing: Options.    (line 317)
+* gawk, versions of, information about, printing: Options.    (line 329)
 * gawk, VMS version of:                  VMS Installation.    (line   6)
 * gawk, word-boundary operator:          GNU Regexp Operators.
                                                               (line  66)
@@ -34808,7 +35285,7 @@ Index
 * GNU Lesser General Public License:     Glossary.            (line 489)
 * GNU long options:                      Command Line.        (line  13)
 * GNU long options <1>:                  Options.             (line   6)
-* GNU long options, printing list of:    Options.             (line 168)
+* GNU long options, printing list of:    Options.             (line 176)
 * GNU Project:                           Manual History.      (line  11)
 * GNU Project <1>:                       Glossary.            (line 403)
 * GNU/Linux:                             Manual History.      (line  28)
@@ -34819,7 +35296,7 @@ Index
 * Gordon, Assaf:                         Contributors.        (line 108)
 * GPL (General Public License):          Manual History.      (line  11)
 * GPL (General Public License) <1>:      Glossary.            (line 394)
-* GPL (General Public License), printing: Options.            (line  89)
+* GPL (General Public License), printing: Options.            (line  93)
 * grcat program:                         Group Functions.     (line  16)
 * Grigera, Juan:                         Contributors.        (line  58)
 * group database, reading:               Group Functions.     (line   6)
@@ -34845,7 +35322,7 @@ Index
 * help debugger command:                 Miscellaneous Debugger Commands.
                                                               (line  67)
 * hexadecimal numbers:                   Nondecimal-numbers.  (line   6)
-* hexadecimal values, enabling interpretation of: Options.    (line 223)
+* hexadecimal values, enabling interpretation of: Options.    (line 235)
 * history expansion, in debugger:        Readline Support.    (line   6)
 * histsort.awk program:                  History Sorting.     (line  25)
 * Hughes, Phil:                          Acknowledgments.     (line  43)
@@ -34856,7 +35333,7 @@ Index
 * hyphen (-), -- operator <1>:           Precedence.          (line  45)
 * hyphen (-), -= operator:               Assignment Ops.      (line 129)
 * hyphen (-), -= operator <1>:           Precedence.          (line  94)
-* hyphen (-), filenames beginning with:  Options.             (line  60)
+* hyphen (-), filenames beginning with:  Options.             (line  64)
 * hyphen (-), in bracket expressions:    Bracket Expressions. (line  25)
 * i debugger command (alias for info):   Debugger Info.       (line  13)
 * id utility:                            Id Program.          (line   6)
@@ -34881,6 +35358,8 @@ Index
 * implementation issues, gawk, debugging: Compatibility Mode. (line   6)
 * implementation issues, gawk, limits:   Getline Notes.       (line  14)
 * implementation issues, gawk, limits <1>: Redirection.       (line 129)
+* implicit namespace:                    Changing The Namespace.
+                                                              (line  25)
 * in operator:                           Comparison Operators.
                                                               (line  11)
 * in operator <1>:                       Precedence.          (line  82)
@@ -35058,9 +35537,9 @@ Index
 * lint checking, array subscripts:       Uninitialized Subscripts.
                                                               (line  43)
 * lint checking, empty programs:         Command Line.        (line  16)
-* lint checking, issuing warnings:       Options.             (line 198)
+* lint checking, issuing warnings:       Options.             (line 210)
 * lint checking, POSIXLY_CORRECT environment variable: Options.
-                                                              (line 356)
+                                                              (line 368)
 * lint checking, undefined functions:    Pass By Value/Reference.
                                                               (line  85)
 * LINT variable:                         User-modified.       (line  90)
@@ -35073,10 +35552,10 @@ Index
 * list function definitions, in debugger: Debugger Info.      (line  30)
 * loading extensions, @load directive:   Loading Shared Libraries.
                                                               (line   8)
-* loading, extensions:                   Options.             (line 186)
+* loading, extensions:                   Options.             (line 198)
 * local variables, in a function:        Variable Scope.      (line   6)
 * locale categories:                     Explaining gettext.  (line  81)
-* locale decimal point character:        Options.             (line 282)
+* locale decimal point character:        Options.             (line 294)
 * locale, definition of:                 Locales.             (line   6)
 * localization:                          I18N and L10N.       (line   6)
 * localization, See internationalization, localization: I18N and L10N.
@@ -35143,6 +35622,7 @@ Index
 * minimum precision required by MPFR library: Auto-set.       (line 279)
 * mktime:                                Time Functions.      (line  25)
 * modifiers, in format specifiers:       Format Modifiers.    (line   6)
+* module, definition of:                 Global Namespace.    (line  18)
 * monetary information, localization:    Explaining gettext.  (line 104)
 * Moore, Duncan:                         Getline Notes.       (line  40)
 * MPFR, checking availability of:        Checking for MPFR.   (line   6)
@@ -35153,16 +35633,41 @@ Index
 * multiple-line records:                 Multiple Line.       (line   6)
 * n debugger command (alias for next):   Debugger Execution Control.
                                                               (line  43)
+* name management:                       Internal Name Management.
+                                                              (line   6)
 * names, arrays/variables:               Library Names.       (line   6)
 * names, functions:                      Definition Syntax.   (line  24)
 * names, functions <1>:                  Library Names.       (line   6)
 * namespace issues:                      Library Names.       (line   6)
 * namespace issues, functions:           Definition Syntax.   (line  24)
+* namespace names, naming rules:         Naming Rules.        (line   6)
+* namespace, awk:                        Default Namespace.   (line   6)
+* namespace, default:                    Default Namespace.   (line   6)
+* namespace, definition of:              Global Namespace.    (line   6)
+* namespace, example code:               Namespace Example.   (line   6)
+* namespace, implicit:                   Changing The Namespace.
+                                                              (line  25)
+* namespace, pushing and popping:        Changing The Namespace.
+                                                              (line  29)
+* namespace, standard awk, global:       Global Namespace.    (line   6)
+* namespaces, backwards compatibility:   Namespace Summary.   (line  28)
+* namespaces, changing:                  Changing The Namespace.
+                                                              (line   6)
+* namespaces, interaction with debugger: Namespace And Features.
+                                                              (line  17)
+* namespaces, interaction with extension API: Namespace And Features.
+                                                              (line  22)
+* namespaces, interaction with pretty printer: Namespace And Features.
+                                                              (line   9)
+* namespaces, interaction with profiler: Namespace And Features.
+                                                              (line   9)
+* namespaces, qualified names:           Qualified Names.     (line   6)
+* naming rules, namespaces and component names: Naming Rules. (line   6)
 * NetBSD:                                Glossary.            (line 746)
 * networks, programming:                 TCP/IP Networking.   (line   6)
 * networks, support for:                 Special Network.     (line   6)
 * newlines:                              Statements/Lines.    (line   6)
-* newlines <1>:                          Options.             (line 276)
+* newlines <1>:                          Options.             (line 288)
 * newlines <2>:                          Boolean Ops.         (line  69)
 * newlines, as record separators:        awk split records.   (line  12)
 * newlines, in dynamic regexps:          Computed Regexps.    (line  60)
@@ -35237,7 +35742,7 @@ Index
 * o debugger command (alias for option): Debugger Info.       (line  57)
 * obsolete features:                     Obsolete.            (line   6)
 * octal numbers:                         Nondecimal-numbers.  (line   6)
-* octal values, enabling interpretation of: Options.          (line 223)
+* octal values, enabling interpretation of: Options.          (line 235)
 * OFMT variable:                         OFMT.                (line  15)
 * OFMT variable <1>:                     Strings And Numbers. (line  56)
 * OFMT variable <2>:                     User-modified.       (line 107)
@@ -35285,13 +35790,13 @@ Index
                                                               (line  66)
 * option debugger command:               Debugger Info.       (line  57)
 * options, command-line:                 Options.             (line   6)
-* options, command-line, end of:         Options.             (line  55)
+* options, command-line, end of:         Options.             (line  59)
 * options, command-line, invoking awk:   Command Line.        (line   6)
 * options, command-line, processing:     Getopt Function.     (line   6)
 * options, deprecated:                   Obsolete.            (line   6)
 * options, long:                         Command Line.        (line  13)
 * options, long <1>:                     Options.             (line   6)
-* options, printing list of:             Options.             (line 168)
+* options, printing list of:             Options.             (line 176)
 * or:                                    Bitwise Functions.   (line  50)
 * OR bitwise operation:                  Bitwise Functions.   (line   6)
 * or Boolean-logic operator:             Boolean Ops.         (line   6)
@@ -35319,6 +35824,7 @@ Index
 * output, standard:                      Special FD.          (line   6)
 * p debugger command (alias for print):  Viewing And Changing Data.
                                                               (line  35)
+* package, definition of:                Global Namespace.    (line  18)
 * Papadopoulos, Panos:                   Contributors.        (line 131)
 * parent process ID of gawk process:     Auto-set.            (line 251)
 * parentheses (), in a profile:          Profiling.           (line 146)
@@ -35390,13 +35896,13 @@ Index
 * portability, NF variable, decrementing: Changing Fields.    (line 115)
 * portability, operators:                Increment Ops.       (line  60)
 * portability, operators, not in POSIX awk: Precedence.       (line  97)
-* portability, POSIXLY_CORRECT environment variable: Options. (line 376)
+* portability, POSIXLY_CORRECT environment variable: Options. (line 388)
 * portability, substr() function:        String Functions.    (line 518)
 * portable object files:                 Explaining gettext.  (line  37)
 * portable object files <1>:             Translator i18n.     (line   6)
 * portable object files, converting to message object files: I18N Example.
                                                               (line  80)
-* portable object files, generating:     Options.             (line 161)
+* portable object files, generating:     Options.             (line 169)
 * portable object template files:        Explaining gettext.  (line  31)
 * porting gawk:                          New Ports.           (line   6)
 * positional specifiers, printf statement: Format Modifiers.  (line  13)
@@ -35438,21 +35944,23 @@ Index
 * POSIX awk, regular expressions and:    Regexp Operators.    (line 161)
 * POSIX awk, timestamps and:             Time Functions.      (line   6)
 * POSIX awk, | I/O operator and:         Getline/Pipe.        (line  56)
-* POSIX mode:                            Options.             (line 270)
-* POSIX mode <1>:                        Options.             (line 356)
+* POSIX mode:                            Options.             (line 282)
+* POSIX mode <1>:                        Options.             (line 368)
 * POSIX, awk and:                        Preface.             (line  21)
 * POSIX, gawk extensions not included in: POSIX/GNU.          (line   6)
 * POSIX, programs, implementing in awk:  Clones.              (line   6)
-* POSIXLY_CORRECT environment variable:  Options.             (line 356)
+* POSIXLY_CORRECT environment variable:  Options.             (line 368)
 * PREC variable:                         User-modified.       (line 127)
 * precedence:                            Increment Ops.       (line  60)
 * precedence <1>:                        Precedence.          (line   6)
 * precedence, regexp operators:          Regexp Operators.    (line 156)
 * predefined variables:                  Built-in Variables.  (line   6)
-* predefined variables, -v option, setting with: Options.     (line  41)
+* predefined variables, -v option, setting with: Options.     (line  45)
 * predefined variables, conveying information: Auto-set.      (line   6)
 * predefined variables, user-modifiable: User-modified.       (line   6)
-* pretty printing:                       Options.             (line 235)
+* pretty printer, interaction with namespaces: Namespace And Features.
+                                                              (line   9)
+* pretty printing:                       Options.             (line 247)
 * pretty printing <1>:                   Profiling.           (line 222)
 * pretty-printing, profiling, difference with: Profiling.     (line 229)
 * print debugger command:                Viewing And Changing Data.
@@ -35488,7 +35996,7 @@ Index
 * printf statement, syntax of:           Basic Printf.        (line   6)
 * printing:                              Printing.            (line   6)
 * printing messages from extensions:     Printing Messages.   (line   6)
-* printing, list of options:             Options.             (line 168)
+* printing, list of options:             Options.             (line 176)
 * printing, mailing labels:              Labels Program.      (line   6)
 * printing, unduplicated lines of text:  Uniq Program.        (line   6)
 * printing, user information:            Id Program.          (line   6)
@@ -35507,6 +36015,8 @@ Index
 * PROCINFO array, user and group ID numbers and: Id Program.  (line  15)
 * PROCINFO, values of sorted_in:         Controlling Scanning.
                                                               (line  26)
+* profiler, interaction with namespaces: Namespace And Features.
+                                                              (line   9)
 * profiling awk programs:                Profiling.           (line   6)
 * profiling awk programs, dynamically:   Profiling.           (line 179)
 * profiling, pretty-printing, difference with: Profiling.     (line 229)
@@ -35538,6 +36048,8 @@ Index
 * q debugger command (alias for quit):   Miscellaneous Debugger Commands.
                                                               (line 100)
 * QSE awk:                               Other Versions.      (line 139)
+* qualified name, definition of:         Qualified Names.     (line   6)
+* qualified name, use of:                Qualified Names.     (line  17)
 * Quanstrom, Erik:                       Alarm Program.       (line   8)
 * question mark (?), ?: operator:        Precedence.          (line  91)
 * question mark (?), regexp operator:    Regexp Operators.    (line 111)
@@ -35631,7 +36143,7 @@ Index
                                                               (line  60)
 * regular expressions, gawk, command-line options: GNU Regexp Operators.
                                                               (line  73)
-* regular expressions, interval expressions and: Options.     (line 291)
+* regular expressions, interval expressions and: Options.     (line 303)
 * regular expressions, leftmost longest match: Leftmost Longest.
                                                               (line   6)
 * regular expressions, operators:        Regexp Usage.        (line  19)
@@ -35715,7 +36227,7 @@ Index
                                                               (line  68)
 * sample debugging session:              Sample Debugging Session.
                                                               (line   6)
-* sandbox mode:                          Options.             (line 303)
+* sandbox mode:                          Options.             (line 315)
 * save debugger options:                 Debugger Info.       (line  85)
 * scalar or array:                       Type Functions.      (line  11)
 * scalar values:                         Basic Data Typing.   (line  13)
@@ -35882,7 +36394,7 @@ Index
 * source code, jawk:                     Other Versions.      (line 121)
 * source code, libmawk:                  Other Versions.      (line 129)
 * source code, mawk:                     Other Versions.      (line  39)
-* source code, mixing:                   Options.             (line 117)
+* source code, mixing:                   Options.             (line 121)
 * source code, pawk:                     Other Versions.      (line  78)
 * source code, pawk (Python version):    Other Versions.      (line 133)
 * source code, QSE awk:                  Other Versions.      (line 139)
@@ -36044,7 +36556,7 @@ Index
 * translate string:                      I18N Functions.      (line  21)
 * translate.awk program:                 Translate Program.   (line  55)
 * treating files, as single records:     gawk split records.  (line  92)
-* troubleshooting, --non-decimal-data option: Options.        (line 223)
+* troubleshooting, --non-decimal-data option: Options.        (line 235)
 * troubleshooting, == operator:          Comparison Operators.
                                                               (line  37)
 * troubleshooting, awk uses FS not IFS:  Field Separators.    (line  29)
@@ -36075,7 +36587,7 @@ Index
 * troubleshooting, substr() function:    String Functions.    (line 505)
 * troubleshooting, system() function:    I/O Functions.       (line 128)
 * troubleshooting, typographical errors, global variables: Options.
-                                                              (line  99)
+                                                              (line 103)
 * true, logical:                         Truth Values.        (line   6)
 * Trueman, David:                        History.             (line  30)
 * Trueman, David <1>:                    Acknowledgments.     (line  47)
@@ -36119,6 +36631,7 @@ Index
 * unwatch debugger command:              Viewing And Changing Data.
                                                               (line  83)
 * up debugger command:                   Execution Stack.     (line  36)
+* uppercase names, namespace for:        Default Namespace.   (line  10)
 * user database, reading:                Passwd Functions.    (line   6)
 * user-defined functions:                User-defined.        (line   6)
 * user-defined, functions, counts, in a profile: Profiling.   (line 137)
@@ -36146,14 +36659,14 @@ Index
 * variables, getline command into, using <3>: Getline/Variable/Coprocess.
                                                               (line   6)
 * variables, global, for library functions: Library Names.    (line  11)
-* variables, global, printing list of:   Options.             (line  94)
+* variables, global, printing list of:   Options.             (line  98)
 * variables, initializing:               Using Variables.     (line  23)
 * variables, local to a function:        Variable Scope.      (line   6)
 * variables, predefined:                 Built-in Variables.  (line   6)
-* variables, predefined -v option, setting with: Options.     (line  41)
+* variables, predefined -v option, setting with: Options.     (line  45)
 * variables, predefined conveying information: Auto-set.      (line   6)
 * variables, private:                    Library Names.       (line  11)
-* variables, setting:                    Options.             (line  32)
+* variables, setting:                    Options.             (line  36)
 * variables, shadowing:                  Definition Syntax.   (line  77)
 * variables, types of:                   Assignment Ops.      (line  39)
 * variables, types of, comparison expressions and: Typing and Comparison.
@@ -36185,7 +36698,7 @@ Index
 * Wall, Larry:                           Array Intro.         (line   6)
 * Wall, Larry <1>:                       Future Extensions.   (line   6)
 * Wallin, Anders:                        Contributors.        (line 106)
-* warnings, issuing:                     Options.             (line 198)
+* warnings, issuing:                     Options.             (line 210)
 * watch debugger command:                Viewing And Changing Data.
                                                               (line  66)
 * watchpoint (debugger):                 Debugging Terms.     (line  42)
@@ -36201,7 +36714,7 @@ Index
 * whitespace, as field separators:       Default Field Splitting.
                                                               (line   6)
 * whitespace, functions, calling:        Calling Built-in.    (line  10)
-* whitespace, newlines as:               Options.             (line 276)
+* whitespace, newlines as:               Options.             (line 288)
 * Williams, Kent:                        Contributors.        (line  35)
 * Woehlke, Matthew:                      Contributors.        (line  82)
 * Woods, John:                           Contributors.        (line  28)
@@ -36231,582 +36744,594 @@ Index
 
 Tag Table:
 Node: Top1200
-Node: Foreword343320
-Node: Foreword447762
-Node: Preface49294
-Ref: Preface-Footnote-152153
-Ref: Preface-Footnote-252260
-Ref: Preface-Footnote-352494
-Node: History52636
-Node: Names54988
-Ref: Names-Footnote-156082
-Node: This Manual56229
-Ref: This Manual-Footnote-162714
-Node: Conventions62814
-Node: Manual History65169
-Ref: Manual History-Footnote-168166
-Ref: Manual History-Footnote-268207
-Node: How To Contribute68281
-Node: Acknowledgments69207
-Node: Getting Started74115
-Node: Running gawk76554
-Node: One-shot77744
-Node: Read Terminal79007
-Node: Long81000
-Node: Executable Scripts82513
-Ref: Executable Scripts-Footnote-185308
-Node: Comments85411
-Node: Quoting87895
-Node: DOS Quoting93412
-Node: Sample Data Files95468
-Node: Very Simple98063
-Node: Two Rules102965
-Node: More Complex104850
-Node: Statements/Lines107716
-Ref: Statements/Lines-Footnote-1112175
-Node: Other Features112440
-Node: When113376
-Ref: When-Footnote-1115130
-Node: Intro Summary115195
-Node: Invoking Gawk116079
-Node: Command Line117593
-Node: Options118391
-Ref: Options-Footnote-1134953
-Ref: Options-Footnote-2135184
-Node: Other Arguments135209
-Node: Naming Standard Input138156
-Node: Environment Variables139249
-Node: AWKPATH Variable139807
-Ref: AWKPATH Variable-Footnote-1143219
-Ref: AWKPATH Variable-Footnote-2143253
-Node: AWKLIBPATH Variable143514
-Node: Other Environment Variables145172
-Node: Exit Status148993
-Node: Include Files149670
-Node: Loading Shared Libraries153195
-Node: Obsolete154623
-Node: Undocumented155315
-Node: Invoking Summary155612
-Node: Regexp157272
-Node: Regexp Usage158726
-Node: Escape Sequences160763
-Node: Regexp Operators166995
-Ref: Regexp Operators-Footnote-1174411
-Ref: Regexp Operators-Footnote-2174558
-Node: Bracket Expressions174656
-Ref: table-char-classes177132
-Node: Leftmost Longest180458
-Node: Computed Regexps181761
-Node: GNU Regexp Operators185188
-Node: Case-sensitivity188867
-Ref: Case-sensitivity-Footnote-1191754
-Ref: Case-sensitivity-Footnote-2191989
-Node: Regexp Summary192097
-Node: Reading Files193563
-Node: Records195832
-Node: awk split records196907
-Node: gawk split records202182
-Ref: gawk split records-Footnote-1206768
-Node: Fields206805
-Node: Nonconstant Fields209546
-Ref: Nonconstant Fields-Footnote-1211782
-Node: Changing Fields211986
-Node: Field Separators218017
-Node: Default Field Splitting220715
-Node: Regexp Field Splitting221833
-Node: Single Character Fields225186
-Node: Command Line Field Separator226246
-Node: Full Line Fields229464
-Ref: Full Line Fields-Footnote-1230986
-Ref: Full Line Fields-Footnote-2231032
-Node: Field Splitting Summary231133
-Node: Constant Size233207
-Node: Fixed width data233939
-Node: Skipping intervening237406
-Node: Allowing trailing data238204
-Node: Fields with fixed data239241
-Node: Splitting By Content240759
-Ref: Splitting By Content-Footnote-1244409
-Node: Testing field creation244572
-Node: Multiple Line246197
-Ref: Multiple Line-Footnote-1252081
-Node: Getline252260
-Node: Plain Getline254729
-Node: Getline/Variable257370
-Node: Getline/File258521
-Node: Getline/Variable/File259909
-Ref: Getline/Variable/File-Footnote-1261514
-Node: Getline/Pipe261602
-Node: Getline/Variable/Pipe264309
-Node: Getline/Coprocess265444
-Node: Getline/Variable/Coprocess266711
-Node: Getline Notes267453
-Node: Getline Summary270250
-Ref: table-getline-variants270674
-Node: Read Timeout271422
-Ref: Read Timeout-Footnote-1275328
-Node: Retrying Input275386
-Node: Command-line directories276585
-Node: Input Summary277491
-Node: Input Exercises280663
-Node: Printing281391
-Node: Print283225
-Node: Print Examples284682
-Node: Output Separators287462
-Node: OFMT289479
-Node: Printf290835
-Node: Basic Printf291620
-Node: Control Letters293194
-Node: Format Modifiers298356
-Node: Printf Examples304371
-Node: Redirection306857
-Node: Special FD313698
-Ref: Special FD-Footnote-1316866
-Node: Special Files316940
-Node: Other Inherited Files317557
-Node: Special Network318558
-Node: Special Caveats319418
-Node: Close Files And Pipes320367
-Ref: table-close-pipe-return-values327274
-Ref: Close Files And Pipes-Footnote-1328087
-Ref: Close Files And Pipes-Footnote-2328235
-Node: Nonfatal328387
-Node: Output Summary330725
-Node: Output Exercises331947
-Node: Expressions332626
-Node: Values333814
-Node: Constants334492
-Node: Scalar Constants335183
-Ref: Scalar Constants-Footnote-1337708
-Node: Nondecimal-numbers337958
-Node: Regexp Constants340959
-Node: Using Constant Regexps341485
-Node: Standard Regexp Constants342107
-Node: Strong Regexp Constants345295
-Node: Variables348253
-Node: Using Variables348910
-Node: Assignment Options350820
-Node: Conversion353287
-Node: Strings And Numbers353811
-Ref: Strings And Numbers-Footnote-1356874
-Node: Locale influences conversions356983
-Ref: table-locale-affects359741
-Node: All Operators360359
-Node: Arithmetic Ops360988
-Node: Concatenation363494
-Ref: Concatenation-Footnote-1366341
-Node: Assignment Ops366448
-Ref: table-assign-ops371439
-Node: Increment Ops372752
-Node: Truth Values and Conditions376212
-Node: Truth Values377286
-Node: Typing and Comparison378334
-Node: Variable Typing379154
-Ref: Variable Typing-Footnote-1385617
-Ref: Variable Typing-Footnote-2385689
-Node: Comparison Operators385766
-Ref: table-relational-ops386185
-Node: POSIX String Comparison389680
-Ref: POSIX String Comparison-Footnote-1391375
-Ref: POSIX String Comparison-Footnote-2391514
-Node: Boolean Ops391598
-Ref: Boolean Ops-Footnote-1396080
-Node: Conditional Exp396172
-Node: Function Calls397908
-Node: Precedence401785
-Node: Locales405444
-Node: Expressions Summary407076
-Node: Patterns and Actions409649
-Node: Pattern Overview410769
-Node: Regexp Patterns412446
-Node: Expression Patterns412988
-Node: Ranges416769
-Node: BEGIN/END419877
-Node: Using BEGIN/END420638
-Ref: Using BEGIN/END-Footnote-1423374
-Node: I/O And BEGIN/END423480
-Node: BEGINFILE/ENDFILE425794
-Node: Empty428707
-Node: Using Shell Variables429024
-Node: Action Overview431298
-Node: Statements433623
-Node: If Statement435471
-Node: While Statement436966
-Node: Do Statement438994
-Node: For Statement440142
-Node: Switch Statement443313
-Node: Break Statement445699
-Node: Continue Statement447791
-Node: Next Statement449618
-Node: Nextfile Statement452001
-Node: Exit Statement454653
-Node: Built-in Variables457056
-Node: User-modified458189
-Node: Auto-set465956
-Ref: Auto-set-Footnote-1482763
-Ref: Auto-set-Footnote-2482969
-Node: ARGC and ARGV483025
-Node: Pattern Action Summary487238
-Node: Arrays489668
-Node: Array Basics490997
-Node: Array Intro491841
-Ref: figure-array-elements493816
-Ref: Array Intro-Footnote-1496520
-Node: Reference to Elements496648
-Node: Assigning Elements499112
-Node: Array Example499603
-Node: Scanning an Array501362
-Node: Controlling Scanning504384
-Ref: Controlling Scanning-Footnote-1509783
-Node: Numeric Array Subscripts510099
-Node: Uninitialized Subscripts512283
-Node: Delete513902
-Ref: Delete-Footnote-1516654
-Node: Multidimensional516711
-Node: Multiscanning519806
-Node: Arrays of Arrays521397
-Node: Arrays Summary526165
-Node: Functions528258
-Node: Built-in529296
-Node: Calling Built-in530377
-Node: Numeric Functions532373
-Ref: Numeric Functions-Footnote-1536401
-Ref: Numeric Functions-Footnote-2536758
-Ref: Numeric Functions-Footnote-3536806
-Node: String Functions537078
-Ref: String Functions-Footnote-1560936
-Ref: String Functions-Footnote-2561064
-Ref: String Functions-Footnote-3561312
-Node: Gory Details561399
-Ref: table-sub-escapes563190
-Ref: table-sub-proposed564709
-Ref: table-posix-sub566072
-Ref: table-gensub-escapes567613
-Ref: Gory Details-Footnote-1568436
-Node: I/O Functions568590
-Ref: table-system-return-values575058
-Ref: I/O Functions-Footnote-1577138
-Ref: I/O Functions-Footnote-2577286
-Node: Time Functions577406
-Ref: Time Functions-Footnote-1588077
-Ref: Time Functions-Footnote-2588145
-Ref: Time Functions-Footnote-3588303
-Ref: Time Functions-Footnote-4588414
-Ref: Time Functions-Footnote-5588526
-Ref: Time Functions-Footnote-6588753
-Node: Bitwise Functions589019
-Ref: table-bitwise-ops589613
-Ref: Bitwise Functions-Footnote-1595676
-Ref: Bitwise Functions-Footnote-2595849
-Node: Type Functions596040
-Node: I18N Functions598791
-Node: User-defined600442
-Node: Definition Syntax601247
-Ref: Definition Syntax-Footnote-1606934
-Node: Function Example607005
-Ref: Function Example-Footnote-1609927
-Node: Function Caveats609949
-Node: Calling A Function610467
-Node: Variable Scope611425
-Node: Pass By Value/Reference614419
-Node: Return Statement617918
-Node: Dynamic Typing620897
-Node: Indirect Calls621827
-Ref: Indirect Calls-Footnote-1632079
-Node: Functions Summary632207
-Node: Library Functions634912
-Ref: Library Functions-Footnote-1638519
-Ref: Library Functions-Footnote-2638662
-Node: Library Names638833
-Ref: Library Names-Footnote-1642293
-Ref: Library Names-Footnote-2642516
-Node: General Functions642602
-Node: Strtonum Function643705
-Node: Assert Function646727
-Node: Round Function650053
-Node: Cliff Random Function651593
-Node: Ordinal Functions652609
-Ref: Ordinal Functions-Footnote-1655672
-Ref: Ordinal Functions-Footnote-2655924
-Node: Join Function656134
-Ref: Join Function-Footnote-1657904
-Node: Getlocaltime Function658104
-Node: Readfile Function661846
-Node: Shell Quoting663823
-Node: Data File Management665224
-Node: Filetrans Function665856
-Node: Rewind Function669952
-Node: File Checking671862
-Ref: File Checking-Footnote-1673196
-Node: Empty Files673397
-Node: Ignoring Assigns675376
-Node: Getopt Function676926
-Ref: Getopt Function-Footnote-1688395
-Node: Passwd Functions688595
-Ref: Passwd Functions-Footnote-1697434
-Node: Group Functions697522
-Ref: Group Functions-Footnote-1705420
-Node: Walking Arrays705627
-Node: Library Functions Summary708635
-Node: Library Exercises710041
-Node: Sample Programs710506
-Node: Running Examples711276
-Node: Clones712004
-Node: Cut Program713228
-Node: Egrep Program723157
-Ref: Egrep Program-Footnote-1730669
-Node: Id Program730779
-Node: Split Program734459
-Ref: Split Program-Footnote-1737917
-Node: Tee Program738046
-Node: Uniq Program740836
-Node: Wc Program748262
-Ref: Wc Program-Footnote-1752517
-Node: Miscellaneous Programs752611
-Node: Dupword Program753824
-Node: Alarm Program755854
-Node: Translate Program760709
-Ref: Translate Program-Footnote-1765274
-Node: Labels Program765544
-Ref: Labels Program-Footnote-1768895
-Node: Word Sorting768979
-Node: History Sorting773051
-Node: Extract Program774886
-Node: Simple Sed782940
-Node: Igawk Program786014
-Ref: Igawk Program-Footnote-1800345
-Ref: Igawk Program-Footnote-2800547
-Ref: Igawk Program-Footnote-3800669
-Node: Anagram Program800784
-Node: Signature Program803846
-Node: Programs Summary805093
-Node: Programs Exercises806307
-Ref: Programs Exercises-Footnote-1810436
-Node: Advanced Features810527
-Node: Nondecimal Data812517
-Node: Array Sorting814108
-Node: Controlling Array Traversal814808
-Ref: Controlling Array Traversal-Footnote-1823176
-Node: Array Sorting Functions823294
-Ref: Array Sorting Functions-Footnote-1828385
-Node: Two-way I/O828581
-Ref: Two-way I/O-Footnote-1836302
-Ref: Two-way I/O-Footnote-2836489
-Node: TCP/IP Networking836571
-Node: Profiling839689
-Node: Advanced Features Summary848707
-Node: Internationalization850551
-Node: I18N and L10N852031
-Node: Explaining gettext852718
-Ref: Explaining gettext-Footnote-1858610
-Ref: Explaining gettext-Footnote-2858795
-Node: Programmer i18n858960
-Ref: Programmer i18n-Footnote-1863909
-Node: Translator i18n863958
-Node: String Extraction864752
-Ref: String Extraction-Footnote-1865884
-Node: Printf Ordering865970
-Ref: Printf Ordering-Footnote-1868756
-Node: I18N Portability868820
-Ref: I18N Portability-Footnote-1871276
-Node: I18N Example871339
-Ref: I18N Example-Footnote-1874614
-Ref: I18N Example-Footnote-2874687
-Node: Gawk I18N874796
-Node: I18N Summary875441
-Node: Debugger876782
-Node: Debugging877802
-Node: Debugging Concepts878243
-Node: Debugging Terms880052
-Node: Awk Debugging882627
-Ref: Awk Debugging-Footnote-1883572
-Node: Sample Debugging Session883704
-Node: Debugger Invocation884238
-Node: Finding The Bug885624
-Node: List of Debugger Commands892098
-Node: Breakpoint Control893431
-Node: Debugger Execution Control897125
-Node: Viewing And Changing Data900487
-Node: Execution Stack903861
-Node: Debugger Info905498
-Node: Miscellaneous Debugger Commands909569
-Node: Readline Support914631
-Node: Limitations915527
-Node: Debugging Summary917636
-Node: Arbitrary Precision Arithmetic918915
-Node: Computer Arithmetic920400
-Ref: table-numeric-ranges924166
-Ref: table-floating-point-ranges924659
-Ref: Computer Arithmetic-Footnote-1925317
-Node: Math Definitions925374
-Ref: table-ieee-formats928690
-Ref: Math Definitions-Footnote-1929293
-Node: MPFR features929398
-Node: FP Math Caution931116
-Ref: FP Math Caution-Footnote-1932188
-Node: Inexactness of computations932557
-Node: Inexact representation933517
-Node: Comparing FP Values934877
-Node: Errors accumulate936118
-Node: Getting Accuracy937551
-Node: Try To Round940261
-Node: Setting precision941160
-Ref: table-predefined-precision-strings941857
-Node: Setting the rounding mode943687
-Ref: table-gawk-rounding-modes944061
-Ref: Setting the rounding mode-Footnote-1947992
-Node: Arbitrary Precision Integers948171
-Ref: Arbitrary Precision Integers-Footnote-1951346
-Node: Checking for MPFR951495
-Node: POSIX Floating Point Problems952969
-Ref: POSIX Floating Point Problems-Footnote-1957254
-Node: Floating point summary957292
-Node: Dynamic Extensions959482
-Node: Extension Intro961035
-Node: Plugin License962301
-Node: Extension Mechanism Outline963098
-Ref: figure-load-extension963537
-Ref: figure-register-new-function965102
-Ref: figure-call-new-function966194
-Node: Extension API Description968256
-Node: Extension API Functions Introduction969898
-Node: General Data Types975438
-Ref: General Data Types-Footnote-1983799
-Node: Memory Allocation Functions984098
-Ref: Memory Allocation Functions-Footnote-1988308
-Node: Constructor Functions988407
-Node: Registration Functions991993
-Node: Extension Functions992678
-Node: Exit Callback Functions997893
-Node: Extension Version String999143
-Node: Input Parsers999806
-Node: Output Wrappers1012527
-Node: Two-way processors1017039
-Node: Printing Messages1019304
-Ref: Printing Messages-Footnote-11020475
-Node: Updating ERRNO1020628
-Node: Requesting Values1021367
-Ref: table-value-types-returned1022104
-Node: Accessing Parameters1023040
-Node: Symbol Table Access1024275
-Node: Symbol table by name1024787
-Node: Symbol table by cookie1026576
-Ref: Symbol table by cookie-Footnote-11030761
-Node: Cached values1030825
-Ref: Cached values-Footnote-11034361
-Node: Array Manipulation1034514
-Ref: Array Manipulation-Footnote-11035605
-Node: Array Data Types1035642
-Ref: Array Data Types-Footnote-11038300
-Node: Array Functions1038392
-Node: Flattening Arrays1042890
-Node: Creating Arrays1049866
-Node: Redirection API1054633
-Node: Extension API Variables1057466
-Node: Extension Versioning1058177
-Ref: gawk-api-version1058606
-Node: Extension GMP/MPFR Versioning1060337
-Node: Extension API Informational Variables1061965
-Node: Extension API Boilerplate1063038
-Node: Changes from API V11067012
-Node: Finding Extensions1068584
-Node: Extension Example1069143
-Node: Internal File Description1069941
-Node: Internal File Ops1074021
-Ref: Internal File Ops-Footnote-11085371
-Node: Using Internal File Ops1085511
-Ref: Using Internal File Ops-Footnote-11087894
-Node: Extension Samples1088168
-Node: Extension Sample File Functions1089697
-Node: Extension Sample Fnmatch1097346
-Node: Extension Sample Fork1098833
-Node: Extension Sample Inplace1100051
-Node: Extension Sample Ord1103268
-Node: Extension Sample Readdir1104104
-Ref: table-readdir-file-types1104993
-Node: Extension Sample Revout1105798
-Node: Extension Sample Rev2way1106387
-Node: Extension Sample Read write array1107127
-Node: Extension Sample Readfile1109069
-Node: Extension Sample Time1110164
-Node: Extension Sample API Tests1111512
-Node: gawkextlib1112004
-Node: Extension summary1114922
-Node: Extension Exercises1118624
-Node: Language History1120122
-Node: V7/SVR3.11121778
-Node: SVR41123930
-Node: POSIX1125364
-Node: BTL1126744
-Node: POSIX/GNU1127473
-Node: Feature History1133251
-Node: Common Extensions1149297
-Node: Ranges and Locales1150580
-Ref: Ranges and Locales-Footnote-11155196
-Ref: Ranges and Locales-Footnote-21155223
-Ref: Ranges and Locales-Footnote-31155458
-Node: Contributors1155679
-Node: History summary1161624
-Node: Installation1163004
-Node: Gawk Distribution1163948
-Node: Getting1164432
-Node: Extracting1165395
-Node: Distribution contents1167033
-Node: Unix Installation1173513
-Node: Quick Installation1174195
-Node: Shell Startup Files1176609
-Node: Additional Configuration Options1177698
-Node: Configuration Philosophy1179863
-Node: Non-Unix Installation1182232
-Node: PC Installation1182692
-Node: PC Binary Installation1183530
-Node: PC Compiling1183965
-Node: PC Using1185082
-Node: Cygwin1188635
-Node: MSYS1189734
-Node: VMS Installation1190235
-Node: VMS Compilation1191026
-Ref: VMS Compilation-Footnote-11192255
-Node: VMS Dynamic Extensions1192313
-Node: VMS Installation Details1193998
-Node: VMS Running1196251
-Node: VMS GNV1200530
-Node: VMS Old Gawk1201265
-Node: Bugs1201736
-Node: Bug address1202399
-Node: Usenet1205381
-Node: Maintainers1206385
-Node: Other Versions1207646
-Node: Installation summary1214560
-Node: Notes1215762
-Node: Compatibility Mode1216556
-Node: Additions1217338
-Node: Accessing The Source1218263
-Node: Adding Code1219700
-Node: New Ports1225919
-Node: Derived Files1230407
-Ref: Derived Files-Footnote-11236053
-Ref: Derived Files-Footnote-21236088
-Ref: Derived Files-Footnote-31236686
-Node: Future Extensions1236800
-Node: Implementation Limitations1237458
-Node: Extension Design1238641
-Node: Old Extension Problems1239785
-Ref: Old Extension Problems-Footnote-11241303
-Node: Extension New Mechanism Goals1241360
-Ref: Extension New Mechanism Goals-Footnote-11244724
-Node: Extension Other Design Decisions1244913
-Node: Extension Future Growth1247026
-Node: Notes summary1247862
-Node: Basic Concepts1249037
-Node: Basic High Level1249718
-Ref: figure-general-flow1250000
-Ref: figure-process-flow1250685
-Ref: Basic High Level-Footnote-11253986
-Node: Basic Data Typing1254171
-Node: Glossary1257499
-Node: Copying1289337
-Node: GNU Free Documentation License1326880
-Node: Index1352000
+Node: Foreword344048
+Node: Foreword448490
+Node: Preface50022
+Ref: Preface-Footnote-152881
+Ref: Preface-Footnote-252988
+Ref: Preface-Footnote-353222
+Node: History53364
+Node: Names55716
+Ref: Names-Footnote-156810
+Node: This Manual56957
+Ref: This Manual-Footnote-163596
+Node: Conventions63696
+Node: Manual History66051
+Ref: Manual History-Footnote-169048
+Ref: Manual History-Footnote-269089
+Node: How To Contribute69163
+Node: Acknowledgments70089
+Node: Getting Started74997
+Node: Running gawk77436
+Node: One-shot78626
+Node: Read Terminal79889
+Node: Long81882
+Node: Executable Scripts83395
+Ref: Executable Scripts-Footnote-186190
+Node: Comments86293
+Node: Quoting88777
+Node: DOS Quoting94294
+Node: Sample Data Files96350
+Node: Very Simple98945
+Node: Two Rules103847
+Node: More Complex105732
+Node: Statements/Lines108598
+Ref: Statements/Lines-Footnote-1113057
+Node: Other Features113322
+Node: When114258
+Ref: When-Footnote-1116012
+Node: Intro Summary116077
+Node: Invoking Gawk116961
+Node: Command Line118475
+Node: Options119273
+Ref: Options-Footnote-1136351
+Ref: Options-Footnote-2136582
+Node: Other Arguments136607
+Node: Naming Standard Input139554
+Node: Environment Variables140647
+Node: AWKPATH Variable141205
+Ref: AWKPATH Variable-Footnote-1144617
+Ref: AWKPATH Variable-Footnote-2144651
+Node: AWKLIBPATH Variable144912
+Node: Other Environment Variables146570
+Node: Exit Status150391
+Node: Include Files151068
+Node: Loading Shared Libraries154758
+Node: Obsolete156186
+Node: Undocumented156878
+Node: Invoking Summary157175
+Node: Regexp158835
+Node: Regexp Usage160289
+Node: Escape Sequences162326
+Node: Regexp Operators168558
+Ref: Regexp Operators-Footnote-1175974
+Ref: Regexp Operators-Footnote-2176121
+Node: Bracket Expressions176219
+Ref: table-char-classes178695
+Node: Leftmost Longest182021
+Node: Computed Regexps183324
+Node: GNU Regexp Operators186751
+Node: Case-sensitivity190430
+Ref: Case-sensitivity-Footnote-1193317
+Ref: Case-sensitivity-Footnote-2193552
+Node: Regexp Summary193660
+Node: Reading Files195126
+Node: Records197395
+Node: awk split records198470
+Node: gawk split records203745
+Ref: gawk split records-Footnote-1208331
+Node: Fields208368
+Node: Nonconstant Fields211109
+Ref: Nonconstant Fields-Footnote-1213345
+Node: Changing Fields213549
+Node: Field Separators219580
+Node: Default Field Splitting222278
+Node: Regexp Field Splitting223396
+Node: Single Character Fields226749
+Node: Command Line Field Separator227809
+Node: Full Line Fields231027
+Ref: Full Line Fields-Footnote-1232549
+Ref: Full Line Fields-Footnote-2232595
+Node: Field Splitting Summary232696
+Node: Constant Size234770
+Node: Fixed width data235502
+Node: Skipping intervening238969
+Node: Allowing trailing data239767
+Node: Fields with fixed data240804
+Node: Splitting By Content242322
+Ref: Splitting By Content-Footnote-1245972
+Node: Testing field creation246135
+Node: Multiple Line247760
+Ref: Multiple Line-Footnote-1253644
+Node: Getline253823
+Node: Plain Getline256292
+Node: Getline/Variable258933
+Node: Getline/File260084
+Node: Getline/Variable/File261472
+Ref: Getline/Variable/File-Footnote-1263077
+Node: Getline/Pipe263165
+Node: Getline/Variable/Pipe265872
+Node: Getline/Coprocess267007
+Node: Getline/Variable/Coprocess268274
+Node: Getline Notes269016
+Node: Getline Summary271813
+Ref: table-getline-variants272237
+Node: Read Timeout272985
+Ref: Read Timeout-Footnote-1276891
+Node: Retrying Input276949
+Node: Command-line directories278148
+Node: Input Summary279054
+Node: Input Exercises282226
+Node: Printing282954
+Node: Print284788
+Node: Print Examples286245
+Node: Output Separators289025
+Node: OFMT291042
+Node: Printf292398
+Node: Basic Printf293183
+Node: Control Letters294757
+Node: Format Modifiers299919
+Node: Printf Examples305934
+Node: Redirection308420
+Node: Special FD315261
+Ref: Special FD-Footnote-1318429
+Node: Special Files318503
+Node: Other Inherited Files319120
+Node: Special Network320121
+Node: Special Caveats320981
+Node: Close Files And Pipes321930
+Ref: table-close-pipe-return-values328837
+Ref: Close Files And Pipes-Footnote-1329650
+Ref: Close Files And Pipes-Footnote-2329798
+Node: Nonfatal329950
+Node: Output Summary332288
+Node: Output Exercises333510
+Node: Expressions334189
+Node: Values335377
+Node: Constants336055
+Node: Scalar Constants336746
+Ref: Scalar Constants-Footnote-1339271
+Node: Nondecimal-numbers339521
+Node: Regexp Constants342522
+Node: Using Constant Regexps343048
+Node: Standard Regexp Constants343670
+Node: Strong Regexp Constants346858
+Node: Variables349816
+Node: Using Variables350473
+Node: Assignment Options352383
+Node: Conversion354850
+Node: Strings And Numbers355374
+Ref: Strings And Numbers-Footnote-1358437
+Node: Locale influences conversions358546
+Ref: table-locale-affects361304
+Node: All Operators361922
+Node: Arithmetic Ops362551
+Node: Concatenation365057
+Ref: Concatenation-Footnote-1367904
+Node: Assignment Ops368011
+Ref: table-assign-ops373002
+Node: Increment Ops374315
+Node: Truth Values and Conditions377775
+Node: Truth Values378849
+Node: Typing and Comparison379897
+Node: Variable Typing380717
+Ref: Variable Typing-Footnote-1387180
+Ref: Variable Typing-Footnote-2387252
+Node: Comparison Operators387329
+Ref: table-relational-ops387748
+Node: POSIX String Comparison391243
+Ref: POSIX String Comparison-Footnote-1392938
+Ref: POSIX String Comparison-Footnote-2393077
+Node: Boolean Ops393161
+Ref: Boolean Ops-Footnote-1397643
+Node: Conditional Exp397735
+Node: Function Calls399471
+Node: Precedence403348
+Node: Locales407007
+Node: Expressions Summary408639
+Node: Patterns and Actions411212
+Node: Pattern Overview412332
+Node: Regexp Patterns414009
+Node: Expression Patterns414551
+Node: Ranges418332
+Node: BEGIN/END421440
+Node: Using BEGIN/END422201
+Ref: Using BEGIN/END-Footnote-1424937
+Node: I/O And BEGIN/END425043
+Node: BEGINFILE/ENDFILE427357
+Node: Empty430270
+Node: Using Shell Variables430587
+Node: Action Overview432861
+Node: Statements435186
+Node: If Statement437034
+Node: While Statement438529
+Node: Do Statement440557
+Node: For Statement441705
+Node: Switch Statement444876
+Node: Break Statement447262
+Node: Continue Statement449354
+Node: Next Statement451181
+Node: Nextfile Statement453564
+Node: Exit Statement456216
+Node: Built-in Variables458619
+Node: User-modified459752
+Node: Auto-set467519
+Ref: Auto-set-Footnote-1484326
+Ref: Auto-set-Footnote-2484532
+Node: ARGC and ARGV484588
+Node: Pattern Action Summary488801
+Node: Arrays491231
+Node: Array Basics492560
+Node: Array Intro493404
+Ref: figure-array-elements495379
+Ref: Array Intro-Footnote-1498083
+Node: Reference to Elements498211
+Node: Assigning Elements500675
+Node: Array Example501166
+Node: Scanning an Array502925
+Node: Controlling Scanning505947
+Ref: Controlling Scanning-Footnote-1511346
+Node: Numeric Array Subscripts511662
+Node: Uninitialized Subscripts513846
+Node: Delete515465
+Ref: Delete-Footnote-1518217
+Node: Multidimensional518274
+Node: Multiscanning521369
+Node: Arrays of Arrays522960
+Node: Arrays Summary527728
+Node: Functions529821
+Node: Built-in530859
+Node: Calling Built-in531940
+Node: Numeric Functions533936
+Ref: Numeric Functions-Footnote-1537964
+Ref: Numeric Functions-Footnote-2538321
+Ref: Numeric Functions-Footnote-3538369
+Node: String Functions538641
+Ref: String Functions-Footnote-1562499
+Ref: String Functions-Footnote-2562627
+Ref: String Functions-Footnote-3562875
+Node: Gory Details562962
+Ref: table-sub-escapes564753
+Ref: table-sub-proposed566272
+Ref: table-posix-sub567635
+Ref: table-gensub-escapes569176
+Ref: Gory Details-Footnote-1569999
+Node: I/O Functions570153
+Ref: table-system-return-values576621
+Ref: I/O Functions-Footnote-1578701
+Ref: I/O Functions-Footnote-2578849
+Node: Time Functions578969
+Ref: Time Functions-Footnote-1589640
+Ref: Time Functions-Footnote-2589708
+Ref: Time Functions-Footnote-3589866
+Ref: Time Functions-Footnote-4589977
+Ref: Time Functions-Footnote-5590089
+Ref: Time Functions-Footnote-6590316
+Node: Bitwise Functions590582
+Ref: table-bitwise-ops591176
+Ref: Bitwise Functions-Footnote-1597239
+Ref: Bitwise Functions-Footnote-2597412
+Node: Type Functions597603
+Node: I18N Functions600354
+Node: User-defined602005
+Node: Definition Syntax602810
+Ref: Definition Syntax-Footnote-1608497
+Node: Function Example608568
+Ref: Function Example-Footnote-1611490
+Node: Function Caveats611512
+Node: Calling A Function612030
+Node: Variable Scope612988
+Node: Pass By Value/Reference615982
+Node: Return Statement619481
+Node: Dynamic Typing622460
+Node: Indirect Calls623390
+Ref: Indirect Calls-Footnote-1633642
+Node: Functions Summary633770
+Node: Library Functions636475
+Ref: Library Functions-Footnote-1640082
+Ref: Library Functions-Footnote-2640225
+Node: Library Names640396
+Ref: Library Names-Footnote-1644063
+Ref: Library Names-Footnote-2644286
+Node: General Functions644372
+Node: Strtonum Function645475
+Node: Assert Function648497
+Node: Round Function651823
+Node: Cliff Random Function653363
+Node: Ordinal Functions654379
+Ref: Ordinal Functions-Footnote-1657442
+Ref: Ordinal Functions-Footnote-2657694
+Node: Join Function657904
+Ref: Join Function-Footnote-1659674
+Node: Getlocaltime Function659874
+Node: Readfile Function663616
+Node: Shell Quoting665593
+Node: Data File Management666994
+Node: Filetrans Function667626
+Node: Rewind Function671722
+Node: File Checking673632
+Ref: File Checking-Footnote-1674966
+Node: Empty Files675167
+Node: Ignoring Assigns677146
+Node: Getopt Function678696
+Ref: Getopt Function-Footnote-1690165
+Node: Passwd Functions690365
+Ref: Passwd Functions-Footnote-1699204
+Node: Group Functions699292
+Ref: Group Functions-Footnote-1707190
+Node: Walking Arrays707397
+Node: Library Functions Summary710405
+Node: Library Exercises711811
+Node: Sample Programs712276
+Node: Running Examples713046
+Node: Clones713774
+Node: Cut Program714998
+Node: Egrep Program724927
+Ref: Egrep Program-Footnote-1732439
+Node: Id Program732549
+Node: Split Program736229
+Ref: Split Program-Footnote-1739687
+Node: Tee Program739816
+Node: Uniq Program742606
+Node: Wc Program750227
+Ref: Wc Program-Footnote-1754482
+Node: Miscellaneous Programs754576
+Node: Dupword Program755789
+Node: Alarm Program757819
+Node: Translate Program762674
+Ref: Translate Program-Footnote-1767239
+Node: Labels Program767509
+Ref: Labels Program-Footnote-1770860
+Node: Word Sorting770944
+Node: History Sorting775016
+Node: Extract Program776851
+Node: Simple Sed784905
+Node: Igawk Program787979
+Ref: Igawk Program-Footnote-1802310
+Ref: Igawk Program-Footnote-2802512
+Ref: Igawk Program-Footnote-3802634
+Node: Anagram Program802749
+Node: Signature Program805811
+Node: Programs Summary807058
+Node: Programs Exercises808272
+Ref: Programs Exercises-Footnote-1812401
+Node: Advanced Features812492
+Node: Nondecimal Data814482
+Node: Array Sorting816073
+Node: Controlling Array Traversal816773
+Ref: Controlling Array Traversal-Footnote-1825141
+Node: Array Sorting Functions825259
+Ref: Array Sorting Functions-Footnote-1830350
+Node: Two-way I/O830546
+Ref: Two-way I/O-Footnote-1838267
+Ref: Two-way I/O-Footnote-2838454
+Node: TCP/IP Networking838536
+Node: Profiling841654
+Node: Advanced Features Summary850672
+Node: Internationalization852516
+Node: I18N and L10N853996
+Node: Explaining gettext854683
+Ref: Explaining gettext-Footnote-1860575
+Ref: Explaining gettext-Footnote-2860760
+Node: Programmer i18n860925
+Ref: Programmer i18n-Footnote-1865874
+Node: Translator i18n865923
+Node: String Extraction866717
+Ref: String Extraction-Footnote-1867849
+Node: Printf Ordering867935
+Ref: Printf Ordering-Footnote-1870721
+Node: I18N Portability870785
+Ref: I18N Portability-Footnote-1873241
+Node: I18N Example873304
+Ref: I18N Example-Footnote-1876579
+Ref: I18N Example-Footnote-2876652
+Node: Gawk I18N876761
+Node: I18N Summary877406
+Node: Debugger878747
+Node: Debugging879747
+Node: Debugging Concepts880188
+Node: Debugging Terms881997
+Node: Awk Debugging884572
+Ref: Awk Debugging-Footnote-1885517
+Node: Sample Debugging Session885649
+Node: Debugger Invocation886183
+Node: Finding The Bug887569
+Node: List of Debugger Commands894043
+Node: Breakpoint Control895376
+Node: Debugger Execution Control899070
+Node: Viewing And Changing Data902432
+Node: Execution Stack905806
+Node: Debugger Info907443
+Node: Miscellaneous Debugger Commands911514
+Node: Readline Support916576
+Node: Limitations917472
+Node: Debugging Summary919581
+Node: Namespaces920860
+Node: Global Namespace921678
+Node: Qualified Names923076
+Node: Default Namespace924075
+Node: Changing The Namespace924816
+Node: Naming Rules926430
+Node: Internal Name Management928278
+Node: Namespace Example929320
+Node: Namespace And Features931882
+Node: Namespace Summary933317
+Node: Arbitrary Precision Arithmetic934794
+Node: Computer Arithmetic936281
+Ref: table-numeric-ranges940047
+Ref: table-floating-point-ranges940540
+Ref: Computer Arithmetic-Footnote-1941198
+Node: Math Definitions941255
+Ref: table-ieee-formats944571
+Ref: Math Definitions-Footnote-1945174
+Node: MPFR features945279
+Node: FP Math Caution946997
+Ref: FP Math Caution-Footnote-1948069
+Node: Inexactness of computations948438
+Node: Inexact representation949398
+Node: Comparing FP Values950758
+Node: Errors accumulate951999
+Node: Getting Accuracy953432
+Node: Try To Round956142
+Node: Setting precision957041
+Ref: table-predefined-precision-strings957738
+Node: Setting the rounding mode959568
+Ref: table-gawk-rounding-modes959942
+Ref: Setting the rounding mode-Footnote-1963873
+Node: Arbitrary Precision Integers964052
+Ref: Arbitrary Precision Integers-Footnote-1967227
+Node: Checking for MPFR967376
+Node: POSIX Floating Point Problems968850
+Ref: POSIX Floating Point Problems-Footnote-1973135
+Node: Floating point summary973173
+Node: Dynamic Extensions975363
+Node: Extension Intro976916
+Node: Plugin License978182
+Node: Extension Mechanism Outline978979
+Ref: figure-load-extension979418
+Ref: figure-register-new-function980983
+Ref: figure-call-new-function982075
+Node: Extension API Description984137
+Node: Extension API Functions Introduction985779
+Ref: table-api-std-headers987615
+Node: General Data Types991480
+Ref: General Data Types-Footnote-1999841
+Node: Memory Allocation Functions1000140
+Ref: Memory Allocation Functions-Footnote-11004350
+Node: Constructor Functions1004449
+Node: Registration Functions1008035
+Node: Extension Functions1008720
+Node: Exit Callback Functions1014042
+Node: Extension Version String1015292
+Node: Input Parsers1015955
+Node: Output Wrappers1028676
+Node: Two-way processors1033188
+Node: Printing Messages1035453
+Ref: Printing Messages-Footnote-11036624
+Node: Updating ERRNO1036777
+Node: Requesting Values1037516
+Ref: table-value-types-returned1038253
+Node: Accessing Parameters1039189
+Node: Symbol Table Access1040424
+Node: Symbol table by name1040936
+Ref: Symbol table by name-Footnote-11043960
+Node: Symbol table by cookie1044088
+Ref: Symbol table by cookie-Footnote-11048273
+Node: Cached values1048337
+Ref: Cached values-Footnote-11051873
+Node: Array Manipulation1052026
+Ref: Array Manipulation-Footnote-11053117
+Node: Array Data Types1053154
+Ref: Array Data Types-Footnote-11055812
+Node: Array Functions1055904
+Node: Flattening Arrays1060402
+Node: Creating Arrays1067378
+Node: Redirection API1072145
+Node: Extension API Variables1074978
+Node: Extension Versioning1075689
+Ref: gawk-api-version1076118
+Node: Extension GMP/MPFR Versioning1077849
+Node: Extension API Informational Variables1079477
+Node: Extension API Boilerplate1080550
+Node: Changes from API V11084524
+Node: Finding Extensions1086096
+Node: Extension Example1086655
+Node: Internal File Description1087453
+Node: Internal File Ops1091533
+Ref: Internal File Ops-Footnote-11102883
+Node: Using Internal File Ops1103023
+Ref: Using Internal File Ops-Footnote-11105406
+Node: Extension Samples1105680
+Node: Extension Sample File Functions1107209
+Node: Extension Sample Fnmatch1114858
+Node: Extension Sample Fork1116345
+Node: Extension Sample Inplace1117563
+Node: Extension Sample Ord1120867
+Node: Extension Sample Readdir1121703
+Ref: table-readdir-file-types1122592
+Node: Extension Sample Revout1123397
+Node: Extension Sample Rev2way1123986
+Node: Extension Sample Read write array1124726
+Node: Extension Sample Readfile1126668
+Node: Extension Sample Time1127763
+Node: Extension Sample API Tests1129111
+Node: gawkextlib1129603
+Node: Extension summary1132521
+Node: Extension Exercises1136223
+Node: Language History1137465
+Node: V7/SVR3.11139121
+Node: SVR41141273
+Node: POSIX1142707
+Node: BTL1144087
+Node: POSIX/GNU1144816
+Node: Feature History1150594
+Node: Common Extensions1166640
+Node: Ranges and Locales1167923
+Ref: Ranges and Locales-Footnote-11172539
+Ref: Ranges and Locales-Footnote-21172566
+Ref: Ranges and Locales-Footnote-31172801
+Node: Contributors1173022
+Node: History summary1178967
+Node: Installation1180347
+Node: Gawk Distribution1181291
+Node: Getting1181775
+Node: Extracting1182738
+Node: Distribution contents1184376
+Node: Unix Installation1190856
+Node: Quick Installation1191538
+Node: Shell Startup Files1193952
+Node: Additional Configuration Options1195041
+Node: Configuration Philosophy1197206
+Node: Non-Unix Installation1199575
+Node: PC Installation1200035
+Node: PC Binary Installation1200873
+Node: PC Compiling1201308
+Node: PC Using1202425
+Node: Cygwin1205978
+Node: MSYS1207077
+Node: VMS Installation1207578
+Node: VMS Compilation1208369
+Ref: VMS Compilation-Footnote-11209598
+Node: VMS Dynamic Extensions1209656
+Node: VMS Installation Details1211341
+Node: VMS Running1213594
+Node: VMS GNV1217873
+Node: VMS Old Gawk1218608
+Node: Bugs1219079
+Node: Bug address1219742
+Node: Usenet1222724
+Node: Maintainers1223728
+Node: Other Versions1224989
+Node: Installation summary1231903
+Node: Notes1233105
+Node: Compatibility Mode1233899
+Node: Additions1234681
+Node: Accessing The Source1235606
+Node: Adding Code1237043
+Node: New Ports1243262
+Node: Derived Files1247750
+Ref: Derived Files-Footnote-11253396
+Ref: Derived Files-Footnote-21253431
+Ref: Derived Files-Footnote-31254029
+Node: Future Extensions1254143
+Node: Implementation Limitations1254801
+Node: Extension Design1255984
+Node: Old Extension Problems1257128
+Ref: Old Extension Problems-Footnote-11258646
+Node: Extension New Mechanism Goals1258703
+Ref: Extension New Mechanism Goals-Footnote-11262067
+Node: Extension Other Design Decisions1262256
+Node: Extension Future Growth1264369
+Node: Notes summary1265205
+Node: Basic Concepts1266380
+Node: Basic High Level1267061
+Ref: figure-general-flow1267343
+Ref: figure-process-flow1268028
+Ref: Basic High Level-Footnote-11271329
+Node: Basic Data Typing1271514
+Node: Glossary1274842
+Node: Copying1306680
+Node: GNU Free Documentation License1344223
+Node: Index1369343
 
 End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 5f304a1..5dd0433 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -459,6 +459,7 @@ particular records in a file and perform operations upon 
them.
 * Internationalization::           Getting @command{gawk} to speak your
                                    language.
 * Debugger::                       The @command{gawk} debugger.
+* Namespaces::                     How namespaces work in @command{gawk}.
 * Arbitrary Precision Arithmetic:: Arbitrary precision arithmetic with
                                    @command{gawk}.
 * Dynamic Extensions::             Adding new built-in functions to
@@ -894,6 +895,15 @@ particular records in a file and perform operations upon 
them.
 * Readline Support::                    Readline support.
 * Limitations::                         Limitations and future plans.
 * Debugging Summary::                   Debugging summary.
+* Global Namespace::                    The global namespace in standard 
@command{awk}.
+* Qualified Names::                     How to qualify names with a namespace.
+* Default Namespace::                   The default namespace.
+* Changing The Namespace::              How to change the namespace.
+* Naming Rules::                        Namespace and Component Naming Rules.
+* Internal Name Management::            How names are stored internally.
+* Namespace Example::                   An example of code using a namespace.
+* Namespace And Features::              Namespaces and other @command{gawk} 
features.
+* Namespace Summary::                   Summarizing namespaces.
 * Computer Arithmetic::                 A quick intro to computer math.
 * Math Definitions::                    Defining terms used.
 * MPFR features::                       The MPFR features in @command{gawk}.
@@ -1716,6 +1726,10 @@ messages into different languages at runtime.
 @ref{Debugger}, describes the @command{gawk} debugger.
 
 @item
address@hidden, describes how @command{gawk} allows variables and/or
+functions of the same name to be in different namespaces.
+
address@hidden
 @ref{Arbitrary Precision Arithmetic},
 describes advanced arithmetic facilities.
 
@@ -3826,6 +3840,9 @@ This option may be given multiple times; the @command{awk}
 program consists of the concatenation of the contents of
 each specified @var{source-file}.
 
+Files named with @option{-i} are treated as if they had @samp{@@namespace 
"awk"}
+at their beginning. @xref{Changing The Namespace}, for more information.
+
 @item -v @address@hidden
 @itemx --assign @address@hidden
 @cindex @option{-v} option
@@ -3971,8 +3988,9 @@ a newline character (even if it doesn't). This makes 
building
 the total program easier.
 
 @quotation CAUTION
-At the moment, there is no requirement that each @var{program-text}
-be a full syntactic unit. I.e., the following currently works:
+Prior to @value{PVERSION} 5.0, there was
+no requirement that each @var{program-text}
+be a full syntactic unit. I.e., the following worked:
 
 @example
 $ @kbd{gawk -e 'BEGIN @{ a = 5 ;' -e 'print a @}'}
@@ -3980,8 +3998,12 @@ $ @kbd{gawk -e 'BEGIN @{ a = 5 ;' -e 'print a @}'}
 @end example
 
 @noindent
-However, this could change in the future, so it's not a
-good idea to rely upon this feature.
+However, this is no longer true. If you have any scripts that
+rely upon this feature, you should revise them.
+
+This is because each @var{program-text} is treated as if it had
address@hidden@@namespace "awk"} at its beginning. @xref{Changing The 
Namespace},
+for more information.
 @end quotation
 
 @item @option{-E} @var{file}
@@ -4060,6 +4082,9 @@ input.  Thus, after processing an @option{-i} argument, 
@command{gawk}
 still expects to find the main source code via the @option{-f} option
 or on the command line.
 
+Files named with @option{-i} are treated as if they had @samp{@@namespace 
"awk"}
+at their beginning.  @xref{Changing The Namespace}, for more information.
+
 @item @option{-l} @var{ext}
 @itemx @option{--load} @var{ext}
 @cindex @option{-l} option
@@ -4847,6 +4872,10 @@ to be run from web pages.
 The rules for finding a source file described in @ref{AWKPATH Variable} also
 apply to files loaded with @code{@@include}.
 
+Finally, files included with @code{@@include}
+are treated as if they had @samp{@@namespace "awk"}
+at their beginning.  @xref{Changing The Namespace}, for more information.
+
 @node Loading Shared Libraries
 @section Loading Dynamic Extensions into Your Program
 
@@ -21823,6 +21852,11 @@ The conventions presented in this @value{SECTION} are 
exactly
 that: conventions. You are not required to write your programs this
 way---we merely recommend that you do so.
 
+Beginning with @value{PVERSION} 5.0, @command{gawk} provides
+a powerful mechanism for solving the problems described in this
+section: @dfn{namespaces}.  Namespaces and their use are described
+in detail in @ref{Namespaces}.
+
 @node General Functions
 @section General Programming
 
@@ -25721,12 +25755,9 @@ END @{
 @c endfile
 @end example
 
address@hidden FIXME: Include this?
address@hidden
-This program does not follow our recommended convention of naming
+As a side note, this program does not follow our recommended convention of 
naming
 global variables with a leading capital letter.  Doing that would
 make the program a little easier to follow.
address@hidden ignore
 
 @ifset FOR_PRINT
 The logic for choosing which lines to print represents a @dfn{state
@@ -27952,6 +27983,9 @@ It contains the following chapters:
 
 @itemize @value{BULLET}
 @item
address@hidden
+
address@hidden
 @ref{Advanced Features}
 
 @item
@@ -31683,6 +31717,447 @@ program being debugged, but occasionally it can.
 
 @end itemize
 
address@hidden name-spaces Name-space Name-spaces}
address@hidden Namespaces
address@hidden Namespaces in @command{gawk}
+
+This @value{CHAPTER} describes a feature that is specific to @command{gawk}.
+
address@hidden
+* Global Namespace::            The global namespace in standard @command{awk}.
+* Qualified Names::             How to qualify names with a namespace.
+* Default Namespace::           The default namespace.
+* Changing The Namespace::      How to change the namespace.
+* Naming Rules::                Namespace and Component Naming Rules.
+* Internal Name Management::    How names are stored internally.
+* Namespace Example::           An example of code using a namespace.
+* Namespace And Features::      Namespaces and other @command{gawk} features.
+* Namespace Summary::           Summarizing namespaces.
address@hidden menu
+
address@hidden Global Namespace
address@hidden Standard @command{awk}'s Single Namespace
+
address@hidden namespace, definition of
address@hidden namespace, standard @command{awk}, global
+In standard @command{awk}, there is a single, global, @dfn{namespace}.
+This means that @emph{all} function names and global variable names must
+be unique. For example, two different @command{awk} source files cannot
+both define a function named @code{min()}, or define the same identifier,
+used as a scalar in one and as an array in the other.
+
+This situation is okay when programs are small, say a few hundred
+lines, or even a few thousand, but it prevents the development of
+reusable libraries of @command{awk} functions, and can inadvertently
+cause independently-developed library files to accidentally step on each
+other's ``private'' global variables
+(@pxref{Library Names}).
+
address@hidden package, definition of
address@hidden module, definition of
+Most other programming languages solve this issue by providing some kind
+of namespace control: a way to say ``this function is in namespace @var{xxx},
+and that function is in namespace @var{yyy}.''  (Of course, there is then
+still a single namespace for the namespaces, but the hope is that there
+are much fewer namespaces in use by any given program, and thus much
+less chance for collisions.)  These facilities are sometimes referred
+to as @dfn{packages} or @dfn{modules}.
+
+Starting with @value{PVERSION} 5.0, @command{gawk} provides a
+simple mechanism to put functions and global variables into separate 
namespaces.
+
address@hidden Qualified Names
address@hidden Qualified Names
+
address@hidden qualified name, definition of
address@hidden namespaces, qualified names
address@hidden @code{::}, namespace separator
address@hidden component name
+A @dfn{qualified name} is an identifier that includes a namespace name,
+the namespace separator @code{::}, and a @dfn{component} name.  For example, 
one
+might have a function named @code{posix::getpid()}.  Here, the namespace
+is @code{posix} and the function name within the namespace (the component)
+is @code{getpid()}.  The namespace and component names are separated by
+a double-colon.  Only one such separator is allowed in a qualified name.
+
address@hidden NOTE
+Unlike C++, the @code{::} is @emph{not} an operator.  No spaces are
+allowed between the namespace name, the @code{::}, and the component name.
address@hidden quotation
+
address@hidden qualified name, use of
+You must use qualified names from one namespace to access variables
+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}).
+
address@hidden Default Namespace
address@hidden The Default Namespace
+
address@hidden namespace, default
address@hidden namespace, @code{awk}
address@hidden @code{awk} namespace
+The default namespace, not surprisingly, is @code{awk}.
+All of the predefined @command{awk} and @command{gawk} variables
+are in this namespace, and thus have qualified names like
address@hidden::ARGC}, @code{awk::NF}, and so on.
+
address@hidden uppercase names, namespace for
+Furthermore, even when you have changed the namespace for your
+current source file (@pxref{Changing The Namespace}), @command{gawk}
+forces unqualified identifiers whose names are all uppercase letters
+to be in the @code{awk} namespace.  This makes it possible for you to easily
+reference @command{gawk}'s global variables from different namespaces.
+It also keeps your code looking natural.
+
address@hidden Changing The Namespace
address@hidden Changing The Namespace
+
address@hidden namespaces, changing
address@hidden @code{@@namespace} directive
+In order to set the current namespace, use an @code{@@namespace} directive
+at the top level of your program:
+
address@hidden
+@@namespace "passwd"
+
+BEGIN @{ @dots{} @}
address@hidden
address@hidden example
+
+After this directive, all simple non-completely-uppercase identifiers are
+placed into the @code{passwd} namespace.
+
+You can change the namespace multiple times within a single
+source file, although this is likely to become confusing if you
+do it too much.
+
address@hidden NOTE
+Association of unqualified identifiers to a namespace is handled while
address@hidden parses your program, @emph{before} it starts to run.  There is
+no concept of a ``current'' namespace once your program starts executing.
+Be sure you understand this.
address@hidden quotation
+
address@hidden namespace, implicit
address@hidden implicit namespace
+Each source file for @option{-i} and @option{-f} starts out with
+an implicit @samp{@@namespace "awk"}.  Similarly, each chunk of
+command-line code supplied with @option{-e} has such an implicit
+initial statement (@pxref{Options}).
+
address@hidden current namespace, pushing and popping
address@hidden namespace, pushing and popping
+Files included with @code{@@include} (@pxref{Include Files}) ``push''
+and ``pop'' the current namespace. That is, each @code{@@include} saves
+the current namespace and starts over with an implicit @samp{@@namespace
+"awk"} which remains in effect until an explicit @code{@@namespace}
+directive is seen.  When @command{gawk} finishes processing the included
+file, the saved namespace is restored and processing continues where it
+left off in the original file.
+
address@hidden @code{@@namespace}, no effect on @code{BEGIN} @code{BEGINFILE}, 
@code{END}, and @code{ENDFILE}
address@hidden @code{BEGIN}, execution order not affected by @code{@@namespace}
address@hidden @code{BEGINFILE}, execution order not affected by 
@code{@@namespace}
address@hidden @code{END}, execution order not affected by @code{@@namespace}
address@hidden @code{ENDFILE}, execution order not affected by 
@code{@@namespace}
+The use of @code{@@namespace} has no influence upon the order of execution
+of @code{BEGIN}, @code{BEGINFILE}, @code{END}, and @code{ENDFILE} rules.
+
address@hidden Naming Rules
address@hidden Namespace and Component Naming Rules
+
address@hidden naming rules, namespaces and component names
address@hidden namespace names, naming rules
address@hidden component names, naming rules
+A number of rules apply to the namespace and component names, as follows.
+
address@hidden @bullet
address@hidden
+It is a syntax error to use qualified names for function parameter names.
+
address@hidden
+It is a syntax error to use any standard @command{awk} reserved word (such
+as @code{if} or @code{for}), or the name of any standard built-in function
+(such as @code{sin()} or @code{gsub()}) as either part of a qualified name.
+Thus, the following produces a syntax error:
+
address@hidden
+@@namespace "example"
+
+function gsub(str, pat, result) @{ @dots{} @}
address@hidden example
+
address@hidden
+Outside the @code{awk} namespace, the names of the additional @command{gawk}
+built-in functions (such as @code{gensub()} or @code{strftime()}) @emph{may}
+be used as component names.  The same set of names may be used as namespace
+names, although this has the potential to be confusing.
+
address@hidden
+The additional @command{gawk} built-in functions may still be called
+from outside the @code{awk} namespace by qualifying them. For example,
address@hidden::systime()}.  Here is a somewhat silly example demonstrating
+this rule and the previous one:
+
address@hidden
+BEGIN @{
+    print "in awk namespace, systime() =", systime()
address@hidden
+
+@@namespace "testing"
+
+function systime()
address@hidden
+    print "in testing namespace, systime() =", awk::systime()
address@hidden
+
+BEGIN @{
+    systime()
address@hidden
address@hidden example
+
address@hidden
+
+When run, it produces output like this:
+
address@hidden
+$ @kbd{gawk -f systime.awk}
address@hidden in awk namespace, systime() = 1500488503
address@hidden in testing namespace, systime() = 1500488503
address@hidden example
+
address@hidden
address@hidden pre-defined variable names may be used:
address@hidden::NR} is valid, if possibly not all that useful.
address@hidden itemize
+
address@hidden Internal Name Management
address@hidden Internal Name Management
+
address@hidden name management
address@hidden @code{awk} namespace, identifier name storage
address@hidden @code{awk} namespace, use for indirect function calls
+For backwards compatibility, all identifiers in the @code{awk} namespace
+are stored internally as unadorned identifiers (that is, without a
+leading @samp{awk::}).  This is mainly relevant
+when using such identifiers as indices for @code{SYMTAB}, @code{FUNCTAB},
+and @code{PROCINFO["identifiers"]} (@pxref{Auto-set}), and for use in
+indirect function calls (@pxref{Indirect Calls}).
+
+In program code, to refer to variables and functions in the @code{awk}
+namespace from another namespace, you must still use the @samp{awk::}
+prefix. For example:
+
address@hidden
+@@namespace "awk"          @ii{This is the default namespace}
+
+BEGIN @{
+    Title = "My Report"   @ii{Qualified name is} awk::Title
address@hidden
+
+@@namespace "report"       @ii{Now in} report @ii{namespace}
+
+function compute()        @ii{This is really} report::compute()
address@hidden
+    print awk::Title      @ii{But would be} SYMTAB["Title"]
+    @dots{}
address@hidden
address@hidden example
+
address@hidden Namespace Example
address@hidden Namespace Example
+
address@hidden namespace, example code
+The following example is a revised version of the suite of routines
+developed in @ref{Passwd Functions}. See there for an explanation
+of how the code works.
+
+The formulation here, due mainly to Andrew Schorr, is rather elegant.
+All of the implementation functions and variables are in the
address@hidden namespace, whereas the main interface functions are
+defined in the @code{awk} namespace.
+
address@hidden
address@hidden file eg/lib/ns_passwd.awk
+# ns_passwd.awk --- access password file information
address@hidden endfile
address@hidden
address@hidden file eg/lib/ns_passwd.awk
+#
+# Arnold Robbins, arnold@@skeeve.com, Public Domain
+# May 1993
+# Revised October 2000
+# Revised December 2010
+#
+# Reworked for namespaces June 2017, with help from
+# Andrew J.@: Schorr, aschorr@@telemetry-investments.com
address@hidden endfile
address@hidden ignore
address@hidden file eg/lib/ns_passwd.awk
+
+@@namespace "passwd"
+
+BEGIN @{
+    # tailor this to suit your system
+    Awklib = "/usr/local/libexec/awk/"
address@hidden
+
+function Init(    oldfs, oldrs, olddol0, pwcat, using_fw, using_fpat)
address@hidden
+    if (Inited)
+        return
+
+    oldfs = FS
+    oldrs = RS
+    olddol0 = $0
+    using_fw = (PROCINFO["FS"] == "FIELDWIDTHS")
+    using_fpat = (PROCINFO["FS"] == "FPAT")
+    FS = ":"
+    RS = "\n"
+
+    pwcat = Awklib "pwcat"
+    while ((pwcat | getline) > 0) @{
+        Byname[$1] = $0
+        Byuid[$3] = $0
+        Bycount[++Total] = $0
+    @}
+    close(pwcat)
+    Count = 0
+    Inited = 1
+    FS = oldfs
+    if (using_fw)
+        FIELDWIDTHS = FIELDWIDTHS
+    else if (using_fpat)
+        FPAT = FPAT
+    RS = oldrs
+    $0 = olddol0
address@hidden
+
+function awk::getpwnam(name)
address@hidden
+    Init()
+    return Byname[name]
address@hidden
+
+function awk::getpwuid(uid)
address@hidden
+    Init()
+    return Byuid[uid]
address@hidden
+
+function awk::getpwent()
address@hidden
+    Init()
+    if (Count < Total)
+        return Bycount[++Count]
+    return ""
address@hidden
+
+function awk::endpwent()
address@hidden
+    Count = 0
address@hidden
address@hidden endfile
address@hidden example
+
+As you can see, this version also follows the convention mentioned in
address@hidden Names}, whereby global variable and function names
+start with a capital letter.
+
+Here is a simple test program. Since it's in a separate file, unadorned
+identifiers are sought for in the @code{awk} namespace:
+
address@hidden
+BEGIN @{
+    while ((p = getpwent()) != "")
+        print p
address@hidden
address@hidden example
+
address@hidden
+
+Here's what happens when it's run:
+
address@hidden
+$ @kbd{gawk -f ns_passwd.awk -f testpasswd.awk}
address@hidden root:x:0:0:root:/root:/bin/bash
address@hidden daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
address@hidden bin:x:2:2:bin:/bin:/usr/sbin/nologin
address@hidden sys:x:3:3:sys:/dev:/usr/sbin/nologin
address@hidden
address@hidden example
+
address@hidden Namespace And Features
address@hidden Namespaces and Other @command{gawk} Features
+
+This @value{SECTION} looks briefly at how the namespace facility interacts
+with other important @command{gawk} features.
+
address@hidden namespaces, interaction with profiler
address@hidden namespaces, interaction with pretty printer
address@hidden profiler, interaction with namespaces
address@hidden pretty printer, interaction with namespaces
+The profiler and pretty-printer (@pxref{Profiling}) have been enhanced
+to understand namespaces and the namespace naming rules presented in
address@hidden Rules}.  In particular, the output groups functions in the same
+namespace together, and has @code{@@namespace} directives in front
+of rules as necessary. This allows component names to be
+simple identifiers, instead of using qualified identifiers everywhere.
+
address@hidden namespaces, interaction with debugger
address@hidden debugger, interaction with namespaces
+Interaction with the debugger (@pxref{Debugging}) has not had to change
+(at least as of this writing).  Some of the internal byte codes changed
+in order to accommodate namespaces, and the debugger's @code{dump} command
+was adjusted to match.
+
address@hidden namespaces, interaction with extension API
address@hidden extension API, interaction with namespaces
+The extension API (@pxref{Dynamic Extensions}) has always allowed for
+placing functions into a different namespace, although this was not
+previously implemented.  However, the symbol lookup and symbol update
+routines did not have provision for including a namespace. That has now
+been corrected (@pxref{Symbol table by name}).
address@hidden Sample Inplace}, for a nice example of an extension that
+leverages a namespace shared by cooperating @command{awk} and C code.
+
address@hidden Namespace Summary
address@hidden Summary
+
address@hidden @value{BULLET}
address@hidden
+Standard @command{awk} provides a single namespace for all global
+identifiers (scalars, arrays, and functions).  This is limiting when
+one wants to develop libraries of reusable functions or function suites.
+
address@hidden
address@hidden provides multiple namespaces by using qualified names:
+names consisting of a namespace name, a double colon, @code{::}, and a
+component name.  Namespace names might still possibly conflict, but this
+is true of any language providing namespaces, modules, or packages.
+
address@hidden
+The default namespace is @command{awk}. The rules for namespace and
+component names are provided in @ref{Naming Rules}. The rules are
+designed in such a way as to make namespace-aware code continue to
+look and work naturally while still providing the necessary power and
+flexibility.
+
address@hidden
+Other parts of @command{gawk} have been extended as necessary to integrate
+namespaces smoothly with their operation.  This applies most notably to
+the profiler / pretty-printer (@pxref{Profiling}) and to the extension
+facility (@pxref{Dynamic Extensions}).
+
address@hidden namespaces, backwards compatibility
address@hidden
+Overall, the namespace facility was designed and implemented such that
+backwards compatibility is paramount. Programs that don't use namespaces
+should see absolutely no difference in behavior when run by a namespace-capable
+version of @command{gawk}.
address@hidden itemize
+
 @node Arbitrary Precision Arithmetic
 @chapter Arithmetic and Arbitrary-Precision Arithmetic with @command{gawk}
 @cindex arbitrary precision
@@ -33273,9 +33748,11 @@ Some points about using the API:
 @item
 The following types, macros, and/or functions are referenced
 in @file{gawkapi.h}.  For correct use, you must therefore include the
-corresponding standard header file @emph{before} including @file{gawkapi.h}:
+corresponding standard header file @emph{before} including @file{gawkapi.h}.
+The list of macros and related header files is shown in 
@ref{table-api-std-headers}.
 
address@hidden FIXME: Make this is a float at some point.
address@hidden Table,table-api-std-headers
address@hidden header files needed by API}
 @multitable address@hidden()}, @code{memcpy()}} address@hidden<sys/types.h>}}
 @headitem C entity @tab Header file
 @item @code{EOF} @tab @code{<stdio.h>}
@@ -33287,6 +33764,7 @@ corresponding standard header file @emph{before} 
including @file{gawkapi.h}:
 @item @code{size_t} @tab @code{<sys/types.h>}
 @item @code{struct stat} @tab @code{<sys/stat.h>}
 @end multitable
address@hidden float
 
 Due to portability concerns, especially to systems that are not
 fully standards-compliant, it is your responsibility
@@ -33875,8 +34353,11 @@ it with @command{gawk} using this API function:
 @table @code
 @item awk_bool_t add_ext_func(const char *name_space, awk_ext_func_t *func);
 This function returns true upon success, false otherwise.
-The @code{name_space} parameter is currently not used; you should pass in an
-empty string (@code{""}).  The @code{func} pointer is the address of a
+The @code{name_space} parameter is the namespace in which to place
+the function (@pxref{Namespaces}).
+Use an empty string (@code{""}) or @code{"awk"} to place
+the function in the default @code{awk} namespace.
+The @code{func} pointer is the address of a
 @code{struct} representing your function, as just described.
 
 @command{gawk} does not modify what @code{func} points to, but the
@@ -34737,6 +35218,18 @@ Return true if the actual type matches @code{wanted}, 
and false otherwise.
 In the latter case, @code{result->val_type} indicates the actual type
 (@pxref{table-value-types-returned}).
 
address@hidden awk_bool_t sym_lookup_ns(const char *name,
address@hidden @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const char 
*name_space,
address@hidden @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ awk_valtype_t 
wanted,
address@hidden @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ awk_value_t 
*result);
+This is like @code{sym_lookup()}, but the @code{name_space} parameter allows 
you
+to specify which namespace @code{name} is part of.  @code{name_space} cannot be
address@hidden If it is @code{""} or @code{"awk"}, then @code{name} is searched
+for in the default @code{awk} namespace.
+
+Note that @code{namespace} is a C++ keyword. For interoperability with C++,
+you should avoid using that identifier in C code.
+
 @item awk_bool_t sym_update(const char *name, awk_value_t *value);
 Update the variable named by the string @code{name}, which is a regular
 C string.  The variable is added to @command{gawk}'s symbol table
@@ -34746,12 +35239,25 @@ Changing types (scalar to array or vice versa) of an 
existing variable
 is @emph{not} allowed, nor may this routine be used to update an array.
 This routine cannot be used to update any of the predefined
 variables (such as @code{ARGC} or @code{NF}).
+
address@hidden awk_bool_t sym_update_ns(const char *name_space, const char 
*name, awk_value_t *value);
+This is like @code{sym_update()}, but the @code{name_space} parameter allows 
you
+to specify which namespace @code{name} is part of.  @code{name_space} cannot be
address@hidden If it is @code{""} or @code{"awk}, then @code{name} is searched
+for in the default @code{awk} namespace.
 @end table
 
 An extension can look up the value of @command{gawk}'s special variables.
 However, with the exception of the @code{PROCINFO} array, an extension
 cannot change any of those variables.
 
+When searching for or updating variables outside the @code{awk} namespace
+(@pxref{Namespaces}), function and variable names must be simple
address@hidden both namespace plus identifier and
address@hidden::bar} would have been too confusing to document, and to code
+and test.} In addition, namespace names and variable and function names
+must follow the rules given in @ref{Naming Rules}.
+
 @node Symbol table by cookie
 @subsubsection Variable Access and Update by Cookie
 
@@ -36931,7 +37437,9 @@ else
 The @code{inplace} extension emulates GNU @command{sed}'s @option{-i} option,
 which performs ``in-place'' editing of each input file.
 It uses the bundled @file{inplace.awk} include file to invoke the extension
-properly:
+properly.  This extension makes use of the namespace facility to place
+all the variables and functions in the @code{inplace} namespace
+(@pxref{Namespaces}):
 
 @example
 @c file eg/lib/inplace.awk
@@ -36962,14 +37470,18 @@ properly:
 #
 # Andrew J. Schorr, aschorr@@telemetry-investments.com
 # January 2013
+#
+# Revised for namespaces
+# Arnold Robbins, arnold@@skeeve.com
+# July 2017
 @c endfile
 @end ignore
 @c file eg/lib/inplace.awk
 
 @@load "inplace"
 
-# Please set INPLACE_SUFFIX to make a backup copy.  For example, you may
-# want to set INPLACE_SUFFIX to .bak on the command line or in a BEGIN rule.
+# Please set inplace::suffix to make a backup copy.  For example, you may
+# want to set inplace::suffix to .bak on the command line or in a BEGIN rule.
 
 # By default, each filename on the command line will be edited inplace.
 # But you can selectively disable this by adding an inplace=0 argument
@@ -36977,31 +37489,33 @@ properly:
 # reenable it later on the commandline by putting inplace=1 before files
 # that you wish to be subject to inplace editing.
 
-# N.B. We call inplace_end() in the BEGINFILE and END rules so that any
+# N.B. We call inplace::end() in the BEGINFILE and END rules so that any
 # actions in an ENDFILE rule will be redirected as expected.
+
+@@namespace "inplace"
 @end group
 
 @group
 BEGIN @{
-    inplace = 1         # enabled by default
+    enable = 1         # enabled by default
 @}
 @end group
 
 @group
 BEGINFILE @{
-    if (_inplace_filename != "")
-        inplace_end(_inplace_filename, INPLACE_SUFFIX)
-    if (inplace)
-        inplace_begin(_inplace_filename = FILENAME, INPLACE_SUFFIX)
+    if (filename != "")
+        end(filename, suffix)
+    if (enable)
+        begin(filename = FILENAME, suffix)
     else
-        _inplace_filename = ""
+        filename = ""
 @}
 @end group
 
 @group
 END @{
-    if (_inplace_filename != "")
-        inplace_end(_inplace_filename, INPLACE_SUFFIX)
+    if (filename != "")
+        end(filename, suffix)
 @}
 @end group
 @c endfile
@@ -37011,17 +37525,18 @@ For each regular file that is processed, the 
extension redirects
 standard output to a temporary file configured to have the same owner
 and permissions as the original.  After the file has been processed,
 the extension restores standard output to its original destination.
-If @code{INPLACE_SUFFIX} is not an empty string, the original file is
+If @code{inplace::suffix} is not an empty string, the original file is
 linked to a backup @value{FN} created by appending that suffix.  Finally,
 the temporary file is renamed to the original @value{FN}.
 
-Note that the use of this feature can be controlled by placing @samp{inplace=0}
-on the command-line prior to listing files that should not be processed this
-way.  You can reenable inplace editing by adding an @samp{inplace=1} argument
-prior to files that should be subject to inplace editing.
+Note that the use of this feature can be controlled by placing
address@hidden::enable=0} on the command-line prior to listing files that
+should not be processed this way.  You can reenable inplace editing by adding
+an @samp{inplace::enable=1} argument prior to files that should be subject
+to inplace editing.
 
-The @code{_inplace_filename} variable serves to keep track of the
-current filename so as to not invoke @code{inplace_end()} before
+The @code{inplace::filename} variable serves to keep track of the
+current filename so as to not invoke @code{inplace::end()} before
 processing the first file.
 
 If any error occurs, the extension issues a fatal error to terminate
@@ -37036,7 +37551,7 @@ $ @kbd{gawk -i inplace '@{ gsub(/foo/, "bar") @}; @{ 
print @}' file1 file2 file3
 To keep a backup copy of the original files, try this:
 
 @example
-$ @kbd{gawk -i inplace -v INPLACE_SUFFIX=.bak '@{ gsub(/foo/, "bar") @}}
+$ @kbd{gawk -i inplace -v inplace::suffix=.bak '@{ gsub(/foo/, "bar") @}}
 > @address@hidden print @}' file1 file2 file3}
 @end example
 
@@ -37536,13 +38051,6 @@ Which reading mechanism should you replace, the one to 
get
 a record, or the one to read raw bytes?
 
 @item
-(Hard.)
-How would you provide namespaces in @command{gawk}, so that the
-names of functions in different extensions don't conflict with each other?
-If you come up with a really good scheme, contact the @command{gawk}
-maintainer to tell him about it.
-
address@hidden
 Write a wrapper script that provides an interface similar to
 @samp{sed -i} for the ``inplace'' extension presented in
 @ref{Extension Sample Inplace}.
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index 84618fd..b562fb5 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -454,6 +454,7 @@ particular records in a file and perform operations upon 
them.
 * Internationalization::           Getting @command{gawk} to speak your
                                    language.
 * Debugger::                       The @command{gawk} debugger.
+* Namespaces::                     How namespaces work in @command{gawk}.
 * Arbitrary Precision Arithmetic:: Arbitrary precision arithmetic with
                                    @command{gawk}.
 * Dynamic Extensions::             Adding new built-in functions to
@@ -889,6 +890,15 @@ particular records in a file and perform operations upon 
them.
 * Readline Support::                    Readline support.
 * Limitations::                         Limitations and future plans.
 * Debugging Summary::                   Debugging summary.
+* Global Namespace::                    The global namespace in standard 
@command{awk}.
+* Qualified Names::                     How to qualify names with a namespace.
+* Default Namespace::                   The default namespace.
+* Changing The Namespace::              How to change the namespace.
+* Naming Rules::                        Namespace and Component Naming Rules.
+* Internal Name Management::            How names are stored internally.
+* Namespace Example::                   An example of code using a namespace.
+* Namespace And Features::              Namespaces and other @command{gawk} 
features.
+* Namespace Summary::                   Summarizing namespaces.
 * Computer Arithmetic::                 A quick intro to computer math.
 * Math Definitions::                    Defining terms used.
 * MPFR features::                       The MPFR features in @command{gawk}.
@@ -1683,6 +1693,10 @@ messages into different languages at runtime.
 @ref{Debugger}, describes the @command{gawk} debugger.
 
 @item
address@hidden, describes how @command{gawk} allows variables and/or
+functions of the same name to be in different namespaces.
+
address@hidden
 @ref{Arbitrary Precision Arithmetic},
 describes advanced arithmetic facilities.
 
@@ -3736,6 +3750,9 @@ This option may be given multiple times; the @command{awk}
 program consists of the concatenation of the contents of
 each specified @var{source-file}.
 
+Files named with @option{-i} are treated as if they had @samp{@@namespace 
"awk"}
+at their beginning. @xref{Changing The Namespace}, for more information.
+
 @item -v @address@hidden
 @itemx --assign @address@hidden
 @cindex @option{-v} option
@@ -3881,8 +3898,9 @@ a newline character (even if it doesn't). This makes 
building
 the total program easier.
 
 @quotation CAUTION
-At the moment, there is no requirement that each @var{program-text}
-be a full syntactic unit. I.e., the following currently works:
+Prior to @value{PVERSION} 5.0, there was
+no requirement that each @var{program-text}
+be a full syntactic unit. I.e., the following worked:
 
 @example
 $ @kbd{gawk -e 'BEGIN @{ a = 5 ;' -e 'print a @}'}
@@ -3890,8 +3908,12 @@ $ @kbd{gawk -e 'BEGIN @{ a = 5 ;' -e 'print a @}'}
 @end example
 
 @noindent
-However, this could change in the future, so it's not a
-good idea to rely upon this feature.
+However, this is no longer true. If you have any scripts that
+rely upon this feature, you should revise them.
+
+This is because each @var{program-text} is treated as if it had
address@hidden@@namespace "awk"} at its beginning. @xref{Changing The 
Namespace},
+for more information.
 @end quotation
 
 @item @option{-E} @var{file}
@@ -3970,6 +3992,9 @@ input.  Thus, after processing an @option{-i} argument, 
@command{gawk}
 still expects to find the main source code via the @option{-f} option
 or on the command line.
 
+Files named with @option{-i} are treated as if they had @samp{@@namespace 
"awk"}
+at their beginning.  @xref{Changing The Namespace}, for more information.
+
 @item @option{-l} @var{ext}
 @itemx @option{--load} @var{ext}
 @cindex @option{-l} option
@@ -4757,6 +4782,10 @@ to be run from web pages.
 The rules for finding a source file described in @ref{AWKPATH Variable} also
 apply to files loaded with @code{@@include}.
 
+Finally, files included with @code{@@include}
+are treated as if they had @samp{@@namespace "awk"}
+at their beginning.  @xref{Changing The Namespace}, for more information.
+
 @node Loading Shared Libraries
 @section Loading Dynamic Extensions into Your Program
 
@@ -20866,6 +20895,11 @@ The conventions presented in this @value{SECTION} are 
exactly
 that: conventions. You are not required to write your programs this
 way---we merely recommend that you do so.
 
+Beginning with @value{PVERSION} 5.0, @command{gawk} provides
+a powerful mechanism for solving the problems described in this
+section: @dfn{namespaces}.  Namespaces and their use are described
+in detail in @ref{Namespaces}.
+
 @node General Functions
 @section General Programming
 
@@ -24734,12 +24768,9 @@ END @{
 @c endfile
 @end example
 
address@hidden FIXME: Include this?
address@hidden
-This program does not follow our recommended convention of naming
+As a side note, this program does not follow our recommended convention of 
naming
 global variables with a leading capital letter.  Doing that would
 make the program a little easier to follow.
address@hidden ignore
 
 @ifset FOR_PRINT
 The logic for choosing which lines to print represents a @dfn{state
@@ -26965,6 +26996,9 @@ It contains the following chapters:
 
 @itemize @value{BULLET}
 @item
address@hidden
+
address@hidden
 @ref{Advanced Features}
 
 @item
@@ -30696,6 +30730,447 @@ program being debugged, but occasionally it can.
 
 @end itemize
 
address@hidden name-spaces Name-space Name-spaces}
address@hidden Namespaces
address@hidden Namespaces in @command{gawk}
+
+This @value{CHAPTER} describes a feature that is specific to @command{gawk}.
+
address@hidden
+* Global Namespace::            The global namespace in standard @command{awk}.
+* Qualified Names::             How to qualify names with a namespace.
+* Default Namespace::           The default namespace.
+* Changing The Namespace::      How to change the namespace.
+* Naming Rules::                Namespace and Component Naming Rules.
+* Internal Name Management::    How names are stored internally.
+* Namespace Example::           An example of code using a namespace.
+* Namespace And Features::      Namespaces and other @command{gawk} features.
+* Namespace Summary::           Summarizing namespaces.
address@hidden menu
+
address@hidden Global Namespace
address@hidden Standard @command{awk}'s Single Namespace
+
address@hidden namespace, definition of
address@hidden namespace, standard @command{awk}, global
+In standard @command{awk}, there is a single, global, @dfn{namespace}.
+This means that @emph{all} function names and global variable names must
+be unique. For example, two different @command{awk} source files cannot
+both define a function named @code{min()}, or define the same identifier,
+used as a scalar in one and as an array in the other.
+
+This situation is okay when programs are small, say a few hundred
+lines, or even a few thousand, but it prevents the development of
+reusable libraries of @command{awk} functions, and can inadvertently
+cause independently-developed library files to accidentally step on each
+other's ``private'' global variables
+(@pxref{Library Names}).
+
address@hidden package, definition of
address@hidden module, definition of
+Most other programming languages solve this issue by providing some kind
+of namespace control: a way to say ``this function is in namespace @var{xxx},
+and that function is in namespace @var{yyy}.''  (Of course, there is then
+still a single namespace for the namespaces, but the hope is that there
+are much fewer namespaces in use by any given program, and thus much
+less chance for collisions.)  These facilities are sometimes referred
+to as @dfn{packages} or @dfn{modules}.
+
+Starting with @value{PVERSION} 5.0, @command{gawk} provides a
+simple mechanism to put functions and global variables into separate 
namespaces.
+
address@hidden Qualified Names
address@hidden Qualified Names
+
address@hidden qualified name, definition of
address@hidden namespaces, qualified names
address@hidden @code{::}, namespace separator
address@hidden component name
+A @dfn{qualified name} is an identifier that includes a namespace name,
+the namespace separator @code{::}, and a @dfn{component} name.  For example, 
one
+might have a function named @code{posix::getpid()}.  Here, the namespace
+is @code{posix} and the function name within the namespace (the component)
+is @code{getpid()}.  The namespace and component names are separated by
+a double-colon.  Only one such separator is allowed in a qualified name.
+
address@hidden NOTE
+Unlike C++, the @code{::} is @emph{not} an operator.  No spaces are
+allowed between the namespace name, the @code{::}, and the component name.
address@hidden quotation
+
address@hidden qualified name, use of
+You must use qualified names from one namespace to access variables
+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}).
+
address@hidden Default Namespace
address@hidden The Default Namespace
+
address@hidden namespace, default
address@hidden namespace, @code{awk}
address@hidden @code{awk} namespace
+The default namespace, not surprisingly, is @code{awk}.
+All of the predefined @command{awk} and @command{gawk} variables
+are in this namespace, and thus have qualified names like
address@hidden::ARGC}, @code{awk::NF}, and so on.
+
address@hidden uppercase names, namespace for
+Furthermore, even when you have changed the namespace for your
+current source file (@pxref{Changing The Namespace}), @command{gawk}
+forces unqualified identifiers whose names are all uppercase letters
+to be in the @code{awk} namespace.  This makes it possible for you to easily
+reference @command{gawk}'s global variables from different namespaces.
+It also keeps your code looking natural.
+
address@hidden Changing The Namespace
address@hidden Changing The Namespace
+
address@hidden namespaces, changing
address@hidden @code{@@namespace} directive
+In order to set the current namespace, use an @code{@@namespace} directive
+at the top level of your program:
+
address@hidden
+@@namespace "passwd"
+
+BEGIN @{ @dots{} @}
address@hidden
address@hidden example
+
+After this directive, all simple non-completely-uppercase identifiers are
+placed into the @code{passwd} namespace.
+
+You can change the namespace multiple times within a single
+source file, although this is likely to become confusing if you
+do it too much.
+
address@hidden NOTE
+Association of unqualified identifiers to a namespace is handled while
address@hidden parses your program, @emph{before} it starts to run.  There is
+no concept of a ``current'' namespace once your program starts executing.
+Be sure you understand this.
address@hidden quotation
+
address@hidden namespace, implicit
address@hidden implicit namespace
+Each source file for @option{-i} and @option{-f} starts out with
+an implicit @samp{@@namespace "awk"}.  Similarly, each chunk of
+command-line code supplied with @option{-e} has such an implicit
+initial statement (@pxref{Options}).
+
address@hidden current namespace, pushing and popping
address@hidden namespace, pushing and popping
+Files included with @code{@@include} (@pxref{Include Files}) ``push''
+and ``pop'' the current namespace. That is, each @code{@@include} saves
+the current namespace and starts over with an implicit @samp{@@namespace
+"awk"} which remains in effect until an explicit @code{@@namespace}
+directive is seen.  When @command{gawk} finishes processing the included
+file, the saved namespace is restored and processing continues where it
+left off in the original file.
+
address@hidden @code{@@namespace}, no effect on @code{BEGIN} @code{BEGINFILE}, 
@code{END}, and @code{ENDFILE}
address@hidden @code{BEGIN}, execution order not affected by @code{@@namespace}
address@hidden @code{BEGINFILE}, execution order not affected by 
@code{@@namespace}
address@hidden @code{END}, execution order not affected by @code{@@namespace}
address@hidden @code{ENDFILE}, execution order not affected by 
@code{@@namespace}
+The use of @code{@@namespace} has no influence upon the order of execution
+of @code{BEGIN}, @code{BEGINFILE}, @code{END}, and @code{ENDFILE} rules.
+
address@hidden Naming Rules
address@hidden Namespace and Component Naming Rules
+
address@hidden naming rules, namespaces and component names
address@hidden namespace names, naming rules
address@hidden component names, naming rules
+A number of rules apply to the namespace and component names, as follows.
+
address@hidden @bullet
address@hidden
+It is a syntax error to use qualified names for function parameter names.
+
address@hidden
+It is a syntax error to use any standard @command{awk} reserved word (such
+as @code{if} or @code{for}), or the name of any standard built-in function
+(such as @code{sin()} or @code{gsub()}) as either part of a qualified name.
+Thus, the following produces a syntax error:
+
address@hidden
+@@namespace "example"
+
+function gsub(str, pat, result) @{ @dots{} @}
address@hidden example
+
address@hidden
+Outside the @code{awk} namespace, the names of the additional @command{gawk}
+built-in functions (such as @code{gensub()} or @code{strftime()}) @emph{may}
+be used as component names.  The same set of names may be used as namespace
+names, although this has the potential to be confusing.
+
address@hidden
+The additional @command{gawk} built-in functions may still be called
+from outside the @code{awk} namespace by qualifying them. For example,
address@hidden::systime()}.  Here is a somewhat silly example demonstrating
+this rule and the previous one:
+
address@hidden
+BEGIN @{
+    print "in awk namespace, systime() =", systime()
address@hidden
+
+@@namespace "testing"
+
+function systime()
address@hidden
+    print "in testing namespace, systime() =", awk::systime()
address@hidden
+
+BEGIN @{
+    systime()
address@hidden
address@hidden example
+
address@hidden
+
+When run, it produces output like this:
+
address@hidden
+$ @kbd{gawk -f systime.awk}
address@hidden in awk namespace, systime() = 1500488503
address@hidden in testing namespace, systime() = 1500488503
address@hidden example
+
address@hidden
address@hidden pre-defined variable names may be used:
address@hidden::NR} is valid, if possibly not all that useful.
address@hidden itemize
+
address@hidden Internal Name Management
address@hidden Internal Name Management
+
address@hidden name management
address@hidden @code{awk} namespace, identifier name storage
address@hidden @code{awk} namespace, use for indirect function calls
+For backwards compatibility, all identifiers in the @code{awk} namespace
+are stored internally as unadorned identifiers (that is, without a
+leading @samp{awk::}).  This is mainly relevant
+when using such identifiers as indices for @code{SYMTAB}, @code{FUNCTAB},
+and @code{PROCINFO["identifiers"]} (@pxref{Auto-set}), and for use in
+indirect function calls (@pxref{Indirect Calls}).
+
+In program code, to refer to variables and functions in the @code{awk}
+namespace from another namespace, you must still use the @samp{awk::}
+prefix. For example:
+
address@hidden
+@@namespace "awk"          @ii{This is the default namespace}
+
+BEGIN @{
+    Title = "My Report"   @ii{Qualified name is} awk::Title
address@hidden
+
+@@namespace "report"       @ii{Now in} report @ii{namespace}
+
+function compute()        @ii{This is really} report::compute()
address@hidden
+    print awk::Title      @ii{But would be} SYMTAB["Title"]
+    @dots{}
address@hidden
address@hidden example
+
address@hidden Namespace Example
address@hidden Namespace Example
+
address@hidden namespace, example code
+The following example is a revised version of the suite of routines
+developed in @ref{Passwd Functions}. See there for an explanation
+of how the code works.
+
+The formulation here, due mainly to Andrew Schorr, is rather elegant.
+All of the implementation functions and variables are in the
address@hidden namespace, whereas the main interface functions are
+defined in the @code{awk} namespace.
+
address@hidden
address@hidden file eg/lib/ns_passwd.awk
+# ns_passwd.awk --- access password file information
address@hidden endfile
address@hidden
address@hidden file eg/lib/ns_passwd.awk
+#
+# Arnold Robbins, arnold@@skeeve.com, Public Domain
+# May 1993
+# Revised October 2000
+# Revised December 2010
+#
+# Reworked for namespaces June 2017, with help from
+# Andrew J.@: Schorr, aschorr@@telemetry-investments.com
address@hidden endfile
address@hidden ignore
address@hidden file eg/lib/ns_passwd.awk
+
+@@namespace "passwd"
+
+BEGIN @{
+    # tailor this to suit your system
+    Awklib = "/usr/local/libexec/awk/"
address@hidden
+
+function Init(    oldfs, oldrs, olddol0, pwcat, using_fw, using_fpat)
address@hidden
+    if (Inited)
+        return
+
+    oldfs = FS
+    oldrs = RS
+    olddol0 = $0
+    using_fw = (PROCINFO["FS"] == "FIELDWIDTHS")
+    using_fpat = (PROCINFO["FS"] == "FPAT")
+    FS = ":"
+    RS = "\n"
+
+    pwcat = Awklib "pwcat"
+    while ((pwcat | getline) > 0) @{
+        Byname[$1] = $0
+        Byuid[$3] = $0
+        Bycount[++Total] = $0
+    @}
+    close(pwcat)
+    Count = 0
+    Inited = 1
+    FS = oldfs
+    if (using_fw)
+        FIELDWIDTHS = FIELDWIDTHS
+    else if (using_fpat)
+        FPAT = FPAT
+    RS = oldrs
+    $0 = olddol0
address@hidden
+
+function awk::getpwnam(name)
address@hidden
+    Init()
+    return Byname[name]
address@hidden
+
+function awk::getpwuid(uid)
address@hidden
+    Init()
+    return Byuid[uid]
address@hidden
+
+function awk::getpwent()
address@hidden
+    Init()
+    if (Count < Total)
+        return Bycount[++Count]
+    return ""
address@hidden
+
+function awk::endpwent()
address@hidden
+    Count = 0
address@hidden
address@hidden endfile
address@hidden example
+
+As you can see, this version also follows the convention mentioned in
address@hidden Names}, whereby global variable and function names
+start with a capital letter.
+
+Here is a simple test program. Since it's in a separate file, unadorned
+identifiers are sought for in the @code{awk} namespace:
+
address@hidden
+BEGIN @{
+    while ((p = getpwent()) != "")
+        print p
address@hidden
address@hidden example
+
address@hidden
+
+Here's what happens when it's run:
+
address@hidden
+$ @kbd{gawk -f ns_passwd.awk -f testpasswd.awk}
address@hidden root:x:0:0:root:/root:/bin/bash
address@hidden daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
address@hidden bin:x:2:2:bin:/bin:/usr/sbin/nologin
address@hidden sys:x:3:3:sys:/dev:/usr/sbin/nologin
address@hidden
address@hidden example
+
address@hidden Namespace And Features
address@hidden Namespaces and Other @command{gawk} Features
+
+This @value{SECTION} looks briefly at how the namespace facility interacts
+with other important @command{gawk} features.
+
address@hidden namespaces, interaction with profiler
address@hidden namespaces, interaction with pretty printer
address@hidden profiler, interaction with namespaces
address@hidden pretty printer, interaction with namespaces
+The profiler and pretty-printer (@pxref{Profiling}) have been enhanced
+to understand namespaces and the namespace naming rules presented in
address@hidden Rules}.  In particular, the output groups functions in the same
+namespace together, and has @code{@@namespace} directives in front
+of rules as necessary. This allows component names to be
+simple identifiers, instead of using qualified identifiers everywhere.
+
address@hidden namespaces, interaction with debugger
address@hidden debugger, interaction with namespaces
+Interaction with the debugger (@pxref{Debugging}) has not had to change
+(at least as of this writing).  Some of the internal byte codes changed
+in order to accommodate namespaces, and the debugger's @code{dump} command
+was adjusted to match.
+
address@hidden namespaces, interaction with extension API
address@hidden extension API, interaction with namespaces
+The extension API (@pxref{Dynamic Extensions}) has always allowed for
+placing functions into a different namespace, although this was not
+previously implemented.  However, the symbol lookup and symbol update
+routines did not have provision for including a namespace. That has now
+been corrected (@pxref{Symbol table by name}).
address@hidden Sample Inplace}, for a nice example of an extension that
+leverages a namespace shared by cooperating @command{awk} and C code.
+
address@hidden Namespace Summary
address@hidden Summary
+
address@hidden @value{BULLET}
address@hidden
+Standard @command{awk} provides a single namespace for all global
+identifiers (scalars, arrays, and functions).  This is limiting when
+one wants to develop libraries of reusable functions or function suites.
+
address@hidden
address@hidden provides multiple namespaces by using qualified names:
+names consisting of a namespace name, a double colon, @code{::}, and a
+component name.  Namespace names might still possibly conflict, but this
+is true of any language providing namespaces, modules, or packages.
+
address@hidden
+The default namespace is @command{awk}. The rules for namespace and
+component names are provided in @ref{Naming Rules}. The rules are
+designed in such a way as to make namespace-aware code continue to
+look and work naturally while still providing the necessary power and
+flexibility.
+
address@hidden
+Other parts of @command{gawk} have been extended as necessary to integrate
+namespaces smoothly with their operation.  This applies most notably to
+the profiler / pretty-printer (@pxref{Profiling}) and to the extension
+facility (@pxref{Dynamic Extensions}).
+
address@hidden namespaces, backwards compatibility
address@hidden
+Overall, the namespace facility was designed and implemented such that
+backwards compatibility is paramount. Programs that don't use namespaces
+should see absolutely no difference in behavior when run by a namespace-capable
+version of @command{gawk}.
address@hidden itemize
+
 @node Arbitrary Precision Arithmetic
 @chapter Arithmetic and Arbitrary-Precision Arithmetic with @command{gawk}
 @cindex arbitrary precision
@@ -32247,9 +32722,11 @@ Some points about using the API:
 @item
 The following types, macros, and/or functions are referenced
 in @file{gawkapi.h}.  For correct use, you must therefore include the
-corresponding standard header file @emph{before} including @file{gawkapi.h}:
+corresponding standard header file @emph{before} including @file{gawkapi.h}.
+The list of macros and related header files is shown in 
@ref{table-api-std-headers}.
 
address@hidden FIXME: Make this is a float at some point.
address@hidden Table,table-api-std-headers
address@hidden header files needed by API}
 @multitable address@hidden()}, @code{memcpy()}} address@hidden<sys/types.h>}}
 @headitem C entity @tab Header file
 @item @code{EOF} @tab @code{<stdio.h>}
@@ -32261,6 +32738,7 @@ corresponding standard header file @emph{before} 
including @file{gawkapi.h}:
 @item @code{size_t} @tab @code{<sys/types.h>}
 @item @code{struct stat} @tab @code{<sys/stat.h>}
 @end multitable
address@hidden float
 
 Due to portability concerns, especially to systems that are not
 fully standards-compliant, it is your responsibility
@@ -32849,8 +33327,11 @@ it with @command{gawk} using this API function:
 @table @code
 @item awk_bool_t add_ext_func(const char *name_space, awk_ext_func_t *func);
 This function returns true upon success, false otherwise.
-The @code{name_space} parameter is currently not used; you should pass in an
-empty string (@code{""}).  The @code{func} pointer is the address of a
+The @code{name_space} parameter is the namespace in which to place
+the function (@pxref{Namespaces}).
+Use an empty string (@code{""}) or @code{"awk"} to place
+the function in the default @code{awk} namespace.
+The @code{func} pointer is the address of a
 @code{struct} representing your function, as just described.
 
 @command{gawk} does not modify what @code{func} points to, but the
@@ -33711,6 +34192,18 @@ Return true if the actual type matches @code{wanted}, 
and false otherwise.
 In the latter case, @code{result->val_type} indicates the actual type
 (@pxref{table-value-types-returned}).
 
address@hidden awk_bool_t sym_lookup_ns(const char *name,
address@hidden @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const char 
*name_space,
address@hidden @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ awk_valtype_t 
wanted,
address@hidden @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ awk_value_t 
*result);
+This is like @code{sym_lookup()}, but the @code{name_space} parameter allows 
you
+to specify which namespace @code{name} is part of.  @code{name_space} cannot be
address@hidden If it is @code{""} or @code{"awk"}, then @code{name} is searched
+for in the default @code{awk} namespace.
+
+Note that @code{namespace} is a C++ keyword. For interoperability with C++,
+you should avoid using that identifier in C code.
+
 @item awk_bool_t sym_update(const char *name, awk_value_t *value);
 Update the variable named by the string @code{name}, which is a regular
 C string.  The variable is added to @command{gawk}'s symbol table
@@ -33720,12 +34213,25 @@ Changing types (scalar to array or vice versa) of an 
existing variable
 is @emph{not} allowed, nor may this routine be used to update an array.
 This routine cannot be used to update any of the predefined
 variables (such as @code{ARGC} or @code{NF}).
+
address@hidden awk_bool_t sym_update_ns(const char *name_space, const char 
*name, awk_value_t *value);
+This is like @code{sym_update()}, but the @code{name_space} parameter allows 
you
+to specify which namespace @code{name} is part of.  @code{name_space} cannot be
address@hidden If it is @code{""} or @code{"awk}, then @code{name} is searched
+for in the default @code{awk} namespace.
 @end table
 
 An extension can look up the value of @command{gawk}'s special variables.
 However, with the exception of the @code{PROCINFO} array, an extension
 cannot change any of those variables.
 
+When searching for or updating variables outside the @code{awk} namespace
+(@pxref{Namespaces}), function and variable names must be simple
address@hidden both namespace plus identifier and
address@hidden::bar} would have been too confusing to document, and to code
+and test.} In addition, namespace names and variable and function names
+must follow the rules given in @ref{Naming Rules}.
+
 @node Symbol table by cookie
 @subsubsection Variable Access and Update by Cookie
 
@@ -35905,7 +36411,9 @@ else
 The @code{inplace} extension emulates GNU @command{sed}'s @option{-i} option,
 which performs ``in-place'' editing of each input file.
 It uses the bundled @file{inplace.awk} include file to invoke the extension
-properly:
+properly.  This extension makes use of the namespace facility to place
+all the variables and functions in the @code{inplace} namespace
+(@pxref{Namespaces}):
 
 @example
 @c file eg/lib/inplace.awk
@@ -35936,14 +36444,18 @@ properly:
 #
 # Andrew J. Schorr, aschorr@@telemetry-investments.com
 # January 2013
+#
+# Revised for namespaces
+# Arnold Robbins, arnold@@skeeve.com
+# July 2017
 @c endfile
 @end ignore
 @c file eg/lib/inplace.awk
 
 @@load "inplace"
 
-# Please set INPLACE_SUFFIX to make a backup copy.  For example, you may
-# want to set INPLACE_SUFFIX to .bak on the command line or in a BEGIN rule.
+# Please set inplace::suffix to make a backup copy.  For example, you may
+# want to set inplace::suffix to .bak on the command line or in a BEGIN rule.
 
 # By default, each filename on the command line will be edited inplace.
 # But you can selectively disable this by adding an inplace=0 argument
@@ -35951,31 +36463,33 @@ properly:
 # reenable it later on the commandline by putting inplace=1 before files
 # that you wish to be subject to inplace editing.
 
-# N.B. We call inplace_end() in the BEGINFILE and END rules so that any
+# N.B. We call inplace::end() in the BEGINFILE and END rules so that any
 # actions in an ENDFILE rule will be redirected as expected.
+
+@@namespace "inplace"
 @end group
 
 @group
 BEGIN @{
-    inplace = 1         # enabled by default
+    enable = 1         # enabled by default
 @}
 @end group
 
 @group
 BEGINFILE @{
-    if (_inplace_filename != "")
-        inplace_end(_inplace_filename, INPLACE_SUFFIX)
-    if (inplace)
-        inplace_begin(_inplace_filename = FILENAME, INPLACE_SUFFIX)
+    if (filename != "")
+        end(filename, suffix)
+    if (enable)
+        begin(filename = FILENAME, suffix)
     else
-        _inplace_filename = ""
+        filename = ""
 @}
 @end group
 
 @group
 END @{
-    if (_inplace_filename != "")
-        inplace_end(_inplace_filename, INPLACE_SUFFIX)
+    if (filename != "")
+        end(filename, suffix)
 @}
 @end group
 @c endfile
@@ -35985,17 +36499,18 @@ For each regular file that is processed, the 
extension redirects
 standard output to a temporary file configured to have the same owner
 and permissions as the original.  After the file has been processed,
 the extension restores standard output to its original destination.
-If @code{INPLACE_SUFFIX} is not an empty string, the original file is
+If @code{inplace::suffix} is not an empty string, the original file is
 linked to a backup @value{FN} created by appending that suffix.  Finally,
 the temporary file is renamed to the original @value{FN}.
 
-Note that the use of this feature can be controlled by placing @samp{inplace=0}
-on the command-line prior to listing files that should not be processed this
-way.  You can reenable inplace editing by adding an @samp{inplace=1} argument
-prior to files that should be subject to inplace editing.
+Note that the use of this feature can be controlled by placing
address@hidden::enable=0} on the command-line prior to listing files that
+should not be processed this way.  You can reenable inplace editing by adding
+an @samp{inplace::enable=1} argument prior to files that should be subject
+to inplace editing.
 
-The @code{_inplace_filename} variable serves to keep track of the
-current filename so as to not invoke @code{inplace_end()} before
+The @code{inplace::filename} variable serves to keep track of the
+current filename so as to not invoke @code{inplace::end()} before
 processing the first file.
 
 If any error occurs, the extension issues a fatal error to terminate
@@ -36010,7 +36525,7 @@ $ @kbd{gawk -i inplace '@{ gsub(/foo/, "bar") @}; @{ 
print @}' file1 file2 file3
 To keep a backup copy of the original files, try this:
 
 @example
-$ @kbd{gawk -i inplace -v INPLACE_SUFFIX=.bak '@{ gsub(/foo/, "bar") @}}
+$ @kbd{gawk -i inplace -v inplace::suffix=.bak '@{ gsub(/foo/, "bar") @}}
 > @address@hidden print @}' file1 file2 file3}
 @end example
 
@@ -36510,13 +37025,6 @@ Which reading mechanism should you replace, the one to 
get
 a record, or the one to read raw bytes?
 
 @item
-(Hard.)
-How would you provide namespaces in @command{gawk}, so that the
-names of functions in different extensions don't conflict with each other?
-If you come up with a really good scheme, contact the @command{gawk}
-maintainer to tell him about it.
-
address@hidden
 Write a wrapper script that provides an interface similar to
 @samp{sed -i} for the ``inplace'' extension presented in
 @ref{Extension Sample Inplace}.
diff --git a/doc/wordlist b/doc/wordlist
index f372990..d87a1b1 100644
--- a/doc/wordlist
+++ b/doc/wordlist
@@ -38,6 +38,7 @@ Automake
 Autotools
 Avahi
 Awk
+Awklib
 Awkstuff
 Ayalon
 BBBB
@@ -65,6 +66,9 @@ Broderick
 Buening
 Burridge
 BusyBox
+Bycount
+Byname
+Byuid
 CAKuGj
 CASEFOLD
 CC
@@ -251,6 +255,8 @@ Igawk
 Illumos
 Incrementing
 Inf
+Init
+Inited
 Inplace
 InstallingGNVPackages
 Internetworking
@@ -1091,6 +1097,7 @@ getgruser
 getline
 getlocaltime
 getopt
+getpid
 getpwent
 getpwnam
 getpwuid
@@ -1449,6 +1456,7 @@ nonwhitespace
 noone
 nr
 nroff
+ns
 nul
 num
 numfields
@@ -1794,6 +1802,7 @@ testbits
 testdir
 testext
 testff
+testpasswd
 tew
 tex
 texi
@@ -1973,6 +1982,7 @@ yearday
 ylwrap
 yourprog
 yxaay
+yyy
 zA
 zbcom
 zerofile
diff --git a/eval.c b/eval.c
index 34ba174..1dd0de4 100644
--- a/eval.c
+++ b/eval.c
@@ -330,6 +330,7 @@ static struct optypetab {
        { "Op_K_getline_redir", "getline" },
        { "Op_K_getline", "getline" },
        { "Op_K_nextfile", "nextfile" },
+       { "Op_K_namespace", "@namespace" },
        { "Op_builtin", NULL },
        { "Op_sub_builtin", NULL },
        { "Op_ext_builtin", NULL },
@@ -400,7 +401,7 @@ nodetype2str(NODETYPE type)
        return buf;
 }
 
-/* opcode2str --- convert a opcode type into a printable value */
+/* opcode2str --- convert an opcode type into a printable value */
 
 const char *
 opcode2str(OPCODE op)
@@ -411,6 +412,8 @@ opcode2str(OPCODE op)
        return NULL;
 }
 
+/* op2str --- convert an opcode type to corresponding operator or keyword */
+
 const char *
 op2str(OPCODE op)
 {
diff --git a/ext.c b/ext.c
index 7ed045c..b72360f 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;
@@ -99,12 +99,13 @@ is_valid_identifier(const char *name)
 /* make_builtin --- register name to be called as func with a builtin body */
 
 awk_bool_t
-make_builtin(const awk_ext_func_t *funcinfo)
+make_builtin(const char *name_space, const awk_ext_func_t *funcinfo)
 {
        NODE *symbol, *f;
        INSTRUCTION *b;
        const char *name = funcinfo->name;
        int count = funcinfo->max_expected_args;
+       const char *install_name;
 
        if (name == NULL || *name == '\0')
                fatal(_("make_builtin: missing function name"));
@@ -112,9 +113,33 @@ make_builtin(const awk_ext_func_t *funcinfo)
        if (! is_valid_identifier(name))
                return awk_false;
 
-       f = lookup(name);
+       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");
+               sprintf(buf, "%s::%s", name_space, name);
+               install_name = buf;
+
+               f = lookup(install_name, false);
+       }
 
        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);
@@ -126,8 +151,7 @@ make_builtin(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);
+       }
 
        if (count < 0)
                fatal(_("make_builtin: negative argument count for function 
`%s'"),
@@ -139,7 +163,7 @@ make_builtin(const awk_ext_func_t *funcinfo)
 
        /* NB: extension sub must return something */
 
-               symbol = install_symbol(estrdup(name, strlen(name)), 
Node_ext_func);
+       symbol = install_symbol(install_name, Node_ext_func);
        symbol->code_ptr = b;
        track_ext_func(name);
        return awk_true;
diff --git a/extension/ChangeLog b/extension/ChangeLog
index a1ad5ef..35b8297 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -203,6 +203,18 @@
 
        * Makefile.am: Update copyright year.
 
+2017-07-20         Arnold D. Robbins     <address@hidden>
+
+       * inplace.c: Move functions into "inplace" namespace and simplify
+       the names. Update all error messages accordingly.
+
+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-27         Arnold D. Robbins     <address@hidden>
 
        * Makfile.am (intdiv_la_LIBADD): Add LIBMPFR for Cygwin.
diff --git a/extension/inplace.c b/extension/inplace.c
index 516edc9..d2a0411 100644
--- a/extension/inplace.c
+++ b/extension/inplace.c
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2013-2015, 2018, the Free Software Foundation, Inc.
+ * Copyright (C) 2013-2015, 2017, 2018, the Free Software Foundation, Inc.
  *
  * This file is part of GAWK, the GNU implementation of the
  * AWK Programming Language.
@@ -128,13 +128,13 @@ do_inplace_begin(int nargs, awk_value_t *result, struct 
awk_ext_func *unused)
        fflush(stdout);
 
        if (state.tname)
-               fatal(ext_id, _("inplace_begin: in-place editing already 
active"));
+               fatal(ext_id, _("inplace::begin: in-place editing already 
active"));
 
        if (nargs != 2)
-               fatal(ext_id, _("inplace_begin: expects 2 arguments but called 
with %d"), nargs);
+               fatal(ext_id, _("inplace::begin: expects 2 arguments but called 
with %d"), nargs);
 
        if (! get_argument(0, AWK_STRING, &filename))
-               fatal(ext_id, _("inplace_begin: cannot retrieve 1st argument as 
a string filename"));
+               fatal(ext_id, _("inplace::begin: cannot retrieve 1st argument 
as a string filename"));
 
        /*
         * N.B. In the current implementation, the 2nd suffix arg is not used
@@ -142,21 +142,21 @@ do_inplace_begin(int nargs, awk_value_t *result, struct 
awk_ext_func *unused)
         */
 
        if (invalid_filename(&filename.str_value)) {
-               warning(ext_id, _("inplace_begin: disabling in-place editing 
for invalid FILENAME `%s'"),
+               warning(ext_id, _("inplace::begin: disabling in-place editing 
for invalid FILENAME `%s'"),
                        filename.str_value.str);
                unset_ERRNO();
                return make_number(-1, result);
        }
 
        if (stat(filename.str_value.str, & sbuf) < 0) {
-               warning(ext_id, _("inplace_begin: Cannot stat `%s' (%s)"),
+               warning(ext_id, _("inplace::begin: Cannot stat `%s' (%s)"),
                        filename.str_value.str, strerror(errno));
                update_ERRNO_int(errno);
                return make_number(-1, result);
        }
 
        if (! S_ISREG(sbuf.st_mode)) {
-               warning(ext_id, _("inplace_begin: `%s' is not a regular file"),
+               warning(ext_id, _("inplace::begin: `%s' is not a regular file"),
                        filename.str_value.str);
                unset_ERRNO();
                return make_number(-1, result);
@@ -167,7 +167,7 @@ do_inplace_begin(int nargs, awk_value_t *result, struct 
awk_ext_func *unused)
        sprintf(state.tname, "%s.gawk.XXXXXX", filename.str_value.str);
 
        if ((fd = mkstemp(state.tname)) < 0)
-               fatal(ext_id, _("inplace_begin: mkstemp(`%s') failed (%s)"),
+               fatal(ext_id, _("inplace::begin: mkstemp(`%s') failed (%s)"),
                        state.tname, strerror(errno));
 
        /* N.B. chown/chmod should be more portable than fchown/fchmod */
@@ -179,20 +179,20 @@ do_inplace_begin(int nargs, awk_value_t *result, struct 
awk_ext_func *unused)
        }
 
        if (chmod(state.tname, sbuf.st_mode) < 0)
-               fatal(ext_id, _("inplace_begin: chmod failed (%s)"),
+               fatal(ext_id, _("inplace::begin: chmod failed (%s)"),
                        strerror(errno));
 
        fflush(stdout);
        /* N.B. fgetpos fails when stdout is a tty */
        state.posrc = fgetpos(stdout, &state.pos);
        if ((state.default_stdout = dup(STDOUT_FILENO)) < 0)
-               fatal(ext_id, _("inplace_begin: dup(stdout) failed (%s)"),
+               fatal(ext_id, _("inplace::begin: dup(stdout) failed (%s)"),
                        strerror(errno));
        if (dup2(fd, STDOUT_FILENO) < 0)
-               fatal(ext_id, _("inplace_begin: dup2(%d, stdout) failed (%s)"),
+               fatal(ext_id, _("inplace::begin: dup2(%d, stdout) failed (%s)"),
                        fd, strerror(errno));
        if (close(fd) < 0)
-               fatal(ext_id, _("inplace_begin: close(%d) failed (%s)"),
+               fatal(ext_id, _("inplace::begin: close(%d) failed (%s)"),
                        fd, strerror(errno));
        rewind(stdout);
        return make_number(0, result);
@@ -208,30 +208,30 @@ do_inplace_end(int nargs, awk_value_t *result, struct 
awk_ext_func *unused)
        assert(result != NULL);
 
        if (nargs != 2)
-               fatal(ext_id, _("inplace_end: expects 2 arguments but called 
with %d"), nargs);
+               fatal(ext_id, _("inplace::end: expects 2 arguments but called 
with %d"), nargs);
 
        if (! get_argument(0, AWK_STRING, &filename))
-               fatal(ext_id, _("inplace_end: cannot retrieve 1st argument as a 
string filename"));
+               fatal(ext_id, _("inplace::end: cannot retrieve 1st argument as 
a string filename"));
 
        if (! get_argument(1, AWK_STRING, &suffix))
                suffix.str_value.str = NULL;
 
        if (! state.tname) {
                if (! invalid_filename(&filename.str_value))
-                       warning(ext_id, _("inplace_end: in-place editing not 
active"));
+                       warning(ext_id, _("inplace::end: in-place editing not 
active"));
                return make_number(0, result);
        }
 
        fflush(stdout);
        if (dup2(state.default_stdout, STDOUT_FILENO) < 0)
-               fatal(ext_id, _("inplace_end: dup2(%d, stdout) failed (%s)"),
+               fatal(ext_id, _("inplace::end: dup2(%d, stdout) failed (%s)"),
                        state.default_stdout, strerror(errno));
        if (close(state.default_stdout) < 0)
-               fatal(ext_id, _("inplace_end: close(%d) failed (%s)"),
+               fatal(ext_id, _("inplace::end: close(%d) failed (%s)"),
                        state.default_stdout, strerror(errno));
        state.default_stdout = -1;
        if (state.posrc == 0 && fsetpos(stdout, &state.pos) < 0)
-               fatal(ext_id, _("inplace_end: fsetpos(stdout) failed (%s)"),
+               fatal(ext_id, _("inplace::end: fsetpos(stdout) failed (%s)"),
                        strerror(errno));
 
        if (suffix.str_value.str && suffix.str_value.str[0]) {
@@ -254,7 +254,7 @@ do_inplace_end(int nargs, awk_value_t *result, struct 
awk_ext_func *unused)
 #endif
 
        if (rename(state.tname, filename.str_value.str) < 0)
-               fatal(ext_id, _("inplace_end: rename(`%s', `%s') failed (%s)"),
+               fatal(ext_id, _("inplace::end: rename(`%s', `%s') failed (%s)"),
                        state.tname, filename.str_value.str, strerror(errno));
        gawk_free(state.tname);
        state.tname = NULL;
@@ -262,8 +262,8 @@ do_inplace_end(int nargs, awk_value_t *result, struct 
awk_ext_func *unused)
 }
 
 static awk_ext_func_t func_table[] = {
-       { "inplace_begin", do_inplace_begin, 2, 2, awk_false, NULL },
-       { "inplace_end", do_inplace_end, 2, 2, awk_false, NULL },
+       { "begin", do_inplace_begin, 2, 2, awk_false, NULL },
+       { "end", do_inplace_end, 2, 2, awk_false, NULL },
 };
 
 static awk_bool_t init_inplace(void)
@@ -276,4 +276,4 @@ static awk_bool_t (*init_func)(void) = init_inplace;
 
 /* define the dl_load function using the boilerplate macro */
 
-dl_load_func(func_table, inplace, "")
+dl_load_func(func_table, inplace, "inplace")
diff --git a/extension/testext.c b/extension/testext.c
index 6629296..b911ec9 100644
--- a/extension/testext.c
+++ b/extension/testext.c
@@ -3,7 +3,7 @@
  */
 
 /*
- * Copyright (C) 2012, 2013, 2014, 2015, 2018
+ * Copyright (C) 2012, 2013, 2014, 2015, 2017, 2018
  * 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 037ca43..3227d55 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -40,6 +40,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.
@@ -372,17 +373,19 @@ api_unset_ERRNO(awk_ext_id_t id)
 
 static awk_bool_t
 api_add_ext_func(awk_ext_id_t id,
-               const char *namespace,
+               const char *name_space,
                awk_ext_func_t *func)
 {
        (void) id;
-       (void) namespace;
 
        if (func == NULL)
                return awk_false;
 
+       if (name_space == NULL)
+               fatal(_("add_ext_func: received NULL name_space parameter"));
+
 #ifdef DYNAMIC
-       return make_builtin(func);
+       return make_builtin(name_space, func);
 #else
        return awk_false;
 #endif
@@ -747,6 +750,7 @@ node_to_awk_value(NODE *node, awk_value_t *val, 
awk_valtype_t wanted)
 
 static awk_bool_t
 api_sym_lookup(awk_ext_id_t id,
+               const char *name_space,
                const char *name,
                awk_valtype_t wanted,
                awk_value_t *result)
@@ -758,7 +762,12 @@ api_sym_lookup(awk_ext_id_t id,
        if (   name == NULL
            || *name == '\0'
            || result == NULL
-           || (node = lookup(name)) == 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 */
@@ -791,6 +800,7 @@ api_sym_lookup_scalar(awk_ext_id_t id,
 
 static awk_bool_t
 api_sym_update(awk_ext_id_t id,
+               const char *name_space,
                const char *name,
                awk_value_t *value)
 {
@@ -799,7 +809,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) {
@@ -818,22 +831,21 @@ api_sym_update(awk_ext_id_t id,
                return awk_false;
        }
 
-       node = lookup(name);
+       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);
                }
 
@@ -845,11 +857,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);
@@ -1581,3 +1596,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/gawkapi.h b/gawkapi.h
index 478c43d..3db8990 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -623,6 +623,7 @@ typedef struct gawk_api {
         *      }
         */
        awk_bool_t (*api_sym_lookup)(awk_ext_id_t id,
+                               const char *name_space,
                                const char *name,
                                awk_valtype_t wanted,
                                awk_value_t *result);
@@ -634,6 +635,7 @@ typedef struct gawk_api {
         * Such an attempt returns false.
         */
        awk_bool_t (*api_sym_update)(awk_ext_id_t id,
+                               const char *name_space,
                                const char *name,
                                awk_value_t *value);
 
@@ -867,11 +869,17 @@ typedef struct gawk_api {
 #define awk_atexit(funcp, arg0)        (api->api_awk_atexit(ext_id, funcp, 
arg0))
 
 #define sym_lookup(name, wanted, result) \
-       (api->api_sym_lookup(ext_id, name, wanted, result))
+       sym_lookup_ns("", name, wanted, result)
+#define sym_update(name, value) \
+       sym_update_ns("", name, value)
+
+#define sym_lookup_ns(name_space, name, wanted, result) \
+       (api->api_sym_lookup(ext_id, name_space, name, wanted, result))
+#define sym_update_ns(name_space, name, value) \
+       (api->api_sym_update(ext_id, name_space, name, value))
+
 #define sym_lookup_scalar(scalar_cookie, wanted, result) \
        (api->api_sym_lookup_scalar(ext_id, scalar_cookie, wanted, result))
-#define sym_update(name, value) \
-       (api->api_sym_update(ext_id, name, value))
 #define sym_update_scalar(scalar_cookie, value) \
        (api->api_sym_update_scalar)(ext_id, scalar_cookie, value)
 
diff --git a/interpret.h b/interpret.h
index 1451f68..82329e8 100644
--- a/interpret.h
+++ b/interpret.h
@@ -1114,7 +1114,7 @@ match_re:
                                        ni = setup_frame(pc);
                                        JUMPTO(ni);     /* Op_func */
                                }
-                               f = lookup(t1->stptr);
+                               f = lookup(t1->stptr, true);
                        }
 
                        if (f == NULL) {
@@ -1178,7 +1178,7 @@ match_re:
                        /* retrieve function definition node */
                        f = pc->func_body;
                        if (f == NULL) {
-                               f = lookup(pc->func_name);
+                               f = lookup(pc->func_name, true);
                                if (f == NULL || (f->type != Node_func && 
f->type != Node_ext_func))
                                        fatal(_("function `%s' not defined"), 
pc->func_name);
                                pc->func_body = f;     /* save for next call */
diff --git a/main.c b/main.c
index 45cae61..03a96f3 100644
--- a/main.c
+++ b/main.c
@@ -398,9 +398,10 @@ main(int argc, char **argv)
        init_fields();
 
        /* Now process the pre-assignments */
+       int dash_v_errs = 0;    // bad stuff for -v
        for (i = 0; i <= numassigns; i++) {
                if (preassigns[i].type == PRE_ASSIGN)
-                       (void) arg_assign(preassigns[i].val, true);
+                       dash_v_errs += (arg_assign(preassigns[i].val, true) == 
false);
                else    /* PRE_ASSIGN_FS */
                        cmdline_fs(preassigns[i].val);
                efree(preassigns[i].val);
@@ -464,12 +465,17 @@ main(int argc, char **argv)
        setlocale(LC_NUMERIC, "C");
 #endif
        /* Read in the program */
-       if (parse_program(& code_block) != 0)
+       if (parse_program(& code_block) != 0 || dash_v_errs > 0)
                exit(EXIT_FAILURE);
 
        if (do_intl)
                exit(EXIT_SUCCESS);
 
+       if (current_namespace != awk_namespace) {
+               efree((char *) current_namespace);
+               current_namespace = awk_namespace;
+       }
+
        install_builtins();
 
        if (do_lint)
@@ -514,6 +520,7 @@ main(int argc, char **argv)
                interpret(code_block);
 
        if (do_pretty_print) {
+               current_namespace = awk_namespace;
                dump_prog(code_block);
                dump_funcs();
        }
@@ -1145,7 +1152,7 @@ arg_assign(char *arg, bool initing)
                badvar = true;
        else
                for (cp2 = arg+1; *cp2; cp2++)
-                       if (! is_identchar((unsigned char) *cp2)) {
+                       if (! is_identchar((unsigned char) *cp2) && *cp2 != 
':') {
                                badvar = true;
                                break;
                        }
@@ -1163,11 +1170,16 @@ arg_assign(char *arg, bool initing)
 
        // Assigning a string or typed regex
 
+       if (! validate_qualified_name(arg)) {
+               badvar = true;
+               goto done;
+       }
+
        if (check_special(arg) >= 0)
                fatal(_("cannot use gawk builtin `%s' as variable name"), arg);
 
        if (! initing) {
-               var = lookup(arg);
+               var = lookup(arg, false);
                if (var != NULL && var->type == Node_func)
                        fatal(_("cannot use function `%s' as variable name"), 
arg);
        }
diff --git a/pc/Makefile.tst b/pc/Makefile.tst
index 8611bce..de66b87 100644
--- a/pc/Makefile.tst
+++ b/pc/Makefile.tst
@@ -149,10 +149,10 @@ BASIC_TESTS = \
        callparam childin clobber closebad clsflnam compare compare2 \
        concat1 concat2 concat3 concat4 concat5 convfmt \
        datanonl defref delargv delarpm2 delarprm delfunc dfamb1 dfastress 
dynlj \
-       eofsplit exit2 exitval1 exitval2 exitval3 fcall_exit fcall_exit2 \
-       fldchg fldchgnf fldterm fnamedat fnarray fnarray2 fnaryscl fnasgnm 
fnmisc \
-       fordel forref forsimp fsbs fsnul1 fsrs fsspcoln fstabplus funsemnl \
-       funsmnam funstack \
+       eofsplit eofsrc1 exit2 exitval1 exitval2 exitval3 \
+       fcall_exit fcall_exit2 fldchg fldchgnf fldterm fnamedat fnarray 
fnarray2 \
+       fnaryscl fnasgnm fnmisc fordel forref forsimp fsbs fsnul1 fsrs fsspcoln 
\
+       fstabplus funsemnl funsmnam funstack \
        getline getline2 getline3 getline4 getline5 getlnbuf getnr2tb getnr2tm \
        gsubasgn gsubtest gsubtst2 gsubtst3 gsubtst4 gsubtst5 gsubtst6 gsubtst7 
\
        gsubtst8 \
@@ -201,18 +201,19 @@ GAWK_EXT_TESTS = \
        incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 include include2 \
        indirectbuiltin indirectcall indirectcall2 intarray isarrayunset \
        lint lintexp lintindex lintint lintlength lintold lintset lintwarn \
-       mixed1 mktime manyfiles match1 match2 match3 mbstr1 mbstr2 muldimposix \
+       manyfiles match1 match2 match3 mbstr1 mbstr2 mixed1 mktime muldimposix \
        nastyparm negtime next nondec nondec2 nonfatal1 nonfatal2 nonfatal3 \
+       nsbad nsbad_cmd nsindirect1 nsindirect2 nsprof1 nsprof2 \
        patsplit posix printfbad1 printfbad2 printfbad3 printfbad4 printhuge \
        procinfs profile0 profile1 profile2 profile3 profile4 profile5 profile6 
\
        profile7 profile8 profile9 profile10 pty1 pty2 \
        rebuf regnul1 regnul2 regx8bit reginttrad reint reint2 rsgetline 
rsglstdin \
        rsstart1 rsstart2 rsstart3 rstest6 \
        shadow shadowbuiltin sortfor sortfor2 sortu sourcesplit 
split_after_fpat \
-       splitarg4 strftime strftfld strtonum strtonum1 switch2 symtab1 symtab2 \
+       splitarg4 strftfld strftime strtonum strtonum1 switch2 symtab1 symtab2 \
        symtab3 symtab4 symtab5 symtab6 symtab7 symtab8 symtab9 symtab10 \
-       typedregex1 typedregex2 typedregex3 typeof1 typeof2 typeof3 typeof4 \
-       typeof5 timeout \
+       timeout typedregex1 typedregex2 typedregex3 typeof1 typeof2 typeof3 \
+       typeof4 typeof5 \
        watchpoint1
 
 ARRAYDEBUG_TESTS = arrdbg
@@ -261,7 +262,9 @@ NEED_NONDEC = mpfrbigint2 nondec2 intarray forcenum
 NEED_POSIX = printf0 posix2008sub paramasfunc1 paramasfunc2 muldimposix
 
 # List of tests that need --pretty-print
-NEED_PRETTY = profile4 profile5 profile8 profile9 profile10
+NEED_PRETTY = nsprof1 nsprof2 \
+       profile4 profile5 profile8 profile9 profile10
+
 
 # List of tests that need --re-interval
 NEED_RE_INTERVAL = gsubtst3 reint reint2
@@ -919,7 +922,7 @@ inplace2::
        @echo $@
        @cp "$(srcdir)"/inplace.1.in address@hidden
        @cp "$(srcdir)"/inplace.2.in address@hidden
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
@@ -930,8 +933,8 @@ inplace3::
        @echo $@
        @cp "$(srcdir)"/inplace.1.in address@hidden
        @cp "$(srcdir)"/inplace.2.in address@hidden
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "Before"} {gsub(/bar/, "foo"); print} END 
{print "After"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >>_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "Before"} {gsub(/bar/, "foo"); print} END 
{print "After"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >>_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
@@ -1094,6 +1097,16 @@ sourcesplit:
        @AWKPATH="$(srcdir)" $(AWK) --source='BEGIN { a = 5;' --source='print a 
}' >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+eofsrc1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f "$(srcdir)"/address@hidden -f 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsbad_cmd:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -v foo:bar=3 -v foo:::blat=4 1 /dev/null 
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 # Use [:] in the regexp to keep MSYS from converting the /'s to \'s.
 nonfatal1:
        @echo $@
@@ -2738,11 +2751,6 @@ lintwarn:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
-mktime:
-       @echo $@
-       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
-       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
-
 match1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -2772,6 +2780,11 @@ mbstr2:
        AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+mktime:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 muldimposix:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --posix >_$@ 2>&1 || 
echo EXIT CODE: $$? >>_$@
@@ -2809,6 +2822,31 @@ nonfatal3:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+nsbad:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsindirect1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsindirect2:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsprof1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --pretty-print=_$@ >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsprof2:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --pretty-print=_$@ >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 patsplit:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -3007,6 +3045,12 @@ symtab10:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --debug < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+timeout:
+       @echo $@
+       @echo Expect $@ to fail with DJGPP and MinGW.
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 typedregex1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -3047,12 +3091,6 @@ typeof5:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
-timeout:
-       @echo $@
-       @echo Expect $@ to fail with DJGPP and MinGW.
-       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
-       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
-
 double1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
diff --git a/profile.c b/profile.c
index 3041545..3d954d3 100644
--- a/profile.c
+++ b/profile.c
@@ -41,6 +41,9 @@ static void pp_push(int type, char *s, int flag, INSTRUCTION 
*comment);
 static NODE *pp_pop(void);
 static void print_comment(INSTRUCTION *pc, long in);
 const char *redir2str(int redirtype);
+static void pp_namespace(const char *name, INSTRUCTION *comment);
+static void pp_namespace_list(INSTRUCTION *list);
+static char *adjust_namespace(char *name, bool *malloced);
 
 #define pp_str vname
 #define pp_len sub.nodep.reserved
@@ -236,17 +239,24 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
                switch (pc->opcode) {
                case Op_rule:
                        /*
-                        * Rules are three instructions long.
+                        * Rules are four instructions long.
                         * See append_rule in awkgram.y.
                         * The first has the Rule Op Code, nexti etc.
                         * The second, (pc + 1) has firsti and lasti:
                         *      the first/last ACTION instructions for this 
rule.
                         * The third has first_line and last_line:
                         *      the first and last source line numbers.
+                        * The fourth holds the namespace name if there is one.
+                        *      (there should be one if we're in this file)
+                        * This can actually be a list in reverse order if
+                        * there were several @namespace directives one
+                        * after the other.
                         */
                        source = pc->source_file;
                        rule = pc->in_rule;
 
+                       pp_namespace_list(pc[3].nexti);
+
                        if (rule != Rule) {
                                /* Allow for pre-non-rule-block comment  */
                                if (pc->nexti != (pc+1)->firsti
@@ -348,9 +358,12 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
                        case Node_var:
                        case Node_var_new:
                        case Node_var_array:
-                               if (m->vname != NULL)
-                                       pp_push(pc->opcode, m->vname, 
DONT_FREE, pc->comment);
-                               else
+                               if (m->vname != NULL) {
+                                       bool malloced = false;
+                                       char *name = adjust_namespace(m->vname, 
& malloced);
+
+                                       pp_push(pc->opcode, name, malloced ? 
CAN_FREE : DONT_FREE, pc->comment);
+                               } else
                                        fatal(_("internal error: %s with null 
vname"),
                                                        nodetype2str(m->type));
                                break;
@@ -628,9 +641,10 @@ cleanup:
                case Op_ext_builtin:
                {
                        const char *fname;
-                       if (pc->opcode == Op_builtin)
-                               fname = getfname(pc->builtin);
-                       else
+                       if (pc->opcode == Op_builtin) {
+                               bool prepend_awk = (current_namespace != 
awk_namespace && strcmp(current_namespace, "awk") != 0);
+                               fname = getfname(pc->builtin, prepend_awk);
+                       } else
                                fname = (pc + 1)->func_name;
                        if (fname != NULL) {
                                if (pc->expr_count > 0) {
@@ -752,9 +766,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 = "@";
@@ -771,7 +786,10 @@ cleanup:
                                t1 = pp_pop();  /* indirect var */
                                pp_free(t1);
                        }
+
                        pp_push(pc->opcode, str, CAN_FREE, pc->comment);
+                       if (malloced)
+                               efree((void *) fname);
                }
                        break;
 
@@ -1940,6 +1958,8 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
                        fprintf(prof_fp, _("\n\t# Functions, listed 
alphabetically\n"));
        }
 
+       pp_namespace_list(pc[3].nexti);
+
        fp = pc->nexti->nexti;
        func = pc->func_body;
        fprintf(prof_fp, "\n");
@@ -1949,7 +1969,12 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED)
                print_comment(pc->comment, -1); /* -1 ==> don't indent */
 
        indent(pc->nexti->exec_count);
-       fprintf(prof_fp, "%s %s(", op2str(Op_K_function), func->vname);
+       
+       bool malloced = false;
+       char *name = adjust_namespace(func->vname, & malloced);
+       fprintf(prof_fp, "%s %s(", op2str(Op_K_function), name);
+       if (malloced)
+               free(name);
        pcount = func->param_cnt;
        func_params = func->fparms;
        for (j = 0; j < pcount; j++) {
@@ -1994,3 +2019,76 @@ redir2str(int redirtype)
                fatal(_("redir2str: unknown redirection type %d"), redirtype);
        return redirtab[redirtype];
 }
+
+/* pp_namespace --- print @namespace directive */
+
+static void
+pp_namespace(const char *name, INSTRUCTION *comment)
+{
+       // Don't print the initial address@hidden "awk"' unless
+       // @namespace was used at some point in the program
+       if (! namespace_changed)
+               return;
+
+       if (strcmp(current_namespace, name) == 0)
+               return;
+
+       current_namespace = name;
+
+       if (do_profile)
+               indent(SPACEOVER);
+
+       fprintf(prof_fp, "@namespace \"%s\"", name);
+
+       if (comment != NULL) {
+               putc('\t', prof_fp);
+               print_comment(comment, 0);
+               putc('\n', prof_fp);
+       } else
+               fprintf(prof_fp, "\n\n");
+}
+
+/* pp_namespace_list --- print the list, back to front, using recursion */
+
+static void
+pp_namespace_list(INSTRUCTION *list)
+{
+       if (list == NULL)
+               return;
+
+       pp_namespace_list(list->nexti);
+       pp_namespace(list->ns_name, list->comment);
+}
+
+/* adjust_namespace --- remove leading namespace or add leading awk:: */
+
+static char *
+adjust_namespace(char *name, bool *malloced)
+{
+       *malloced = false;
+
+       // unadorned name from symbol table, add awk:: if not in awk:: n.s.
+       if (strchr(name, ':') == NULL &&
+           current_namespace != awk_namespace &&       // can be equal if 
namespace never changed
+           strcmp(current_namespace, "awk") != 0) {
+               char *buf;
+               size_t len = 5 + strlen(name) + 1;
+
+               emalloc(buf, char *, len, "adjust_namespace");
+               sprintf(buf, "awk::%s", name);
+               *malloced = true;
+
+               return buf;
+       }
+
+       // qualifed name, remove <ns>:: if in that n.s.
+       size_t len = strlen(current_namespace);
+
+       if (strncmp(current_namespace, name, len) == 0) {
+               char *ret = name + len + 2;
+
+               return ret;
+       }
+
+       return name;
+}
diff --git a/symbol.c b/symbol.c
index 9f8af3a..fc598da 100644
--- a/symbol.c
+++ b/symbol.c
@@ -39,6 +39,7 @@ static void (*install_func)(NODE *) = NULL;
 static NODE *make_symbol(const char *name, NODETYPE type);
 static NODE *install(const char *name, NODE *parm, NODETYPE type);
 static void free_bcpool(INSTRUCTION_POOL *pl);
+static const char *fix_up_namespace(const char *name, bool *malloced);
 
 static AWK_CONTEXT *curr_ctxt = NULL;
 static int ctxt_level;
@@ -88,12 +89,13 @@ install_symbol(const char *name, NODETYPE type)
  */
 
 NODE *
-lookup(const char *name)
+lookup(const char *name, bool do_qualify)
 {
        NODE *n;
        NODE *tmp;
        NODE *tables[5];        /* manual init below, for z/OS */
        int i;
+       bool malloced = false;
 
        /* ``It's turtles, all the way down.'' */
        tables[0] = param_table;        /* parameters shadow everything */
@@ -102,7 +104,13 @@ lookup(const char *name)
        tables[3] = symbol_table;       /* then globals */
        tables[4] = NULL;
 
-       tmp = make_string(name, strlen(name));
+       if (do_qualify)
+               name = fix_up_namespace(name, & malloced);
+
+       if (malloced)
+               tmp = make_str_node(name, strlen(name), ALREADY_MALLOCED);
+       else
+               tmp = make_string(name, strlen(name));
 
        n = NULL;
        for (i = 0; tables[i] != NULL; i++) {
@@ -303,8 +311,19 @@ install(const char *name, NODE *parm, NODETYPE type)
        NODE *table;
        NODE *n_name;
        NODE *prev;
+       bool malloced = false;
+
+       if (type == Node_param_list) {
+               n_name = make_string(name, strlen(name));
+       } else {
+               name = fix_up_namespace(name, & malloced);
+
+               if (malloced)
+                       n_name = make_str_node(name, strlen(name), 
ALREADY_MALLOCED);
+               else
+                       n_name = make_string(name, strlen(name));
+       }
 
-       n_name = make_string(name, strlen(name));
        table = symbol_table;
 
        if (type == Node_param_list) {
@@ -946,3 +965,62 @@ free_bcpool(INSTRUCTION_POOL *pl)
        for (i = 0; i < MAX_INSTRUCTION_ALLOC; i++)
                free_bc_mempool(& pl->pool[i], i + 1);
 }
+
+/* is_all_upper --- return true if name is all uppercase letters */
+
+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;
+}
+
+/* fix_up_namespace --- qualify / dequalify a simple name */
+
+static const char *
+fix_up_namespace(const char *name, bool *malloced)
+{
+       static char awk_ns[] = "awk::";
+       const size_t awk_ns_len = sizeof(awk_ns) - 1;   // don't include 
trailing \0
+       char *cp;
+
+       assert(malloced != NULL);
+       *malloced = false;
+
+       // first, check if it's qualified
+       if ((cp = strchr(name, ':')) != NULL) {
+               // does it start with awk:: ?
+               if (strncmp(name, awk_ns, awk_ns_len) == 0)
+                       return cp + 2;  // just trailing part
+
+               // otherwise it's fully qualified, not in the awk n.s.
+               return name;
+       }
+
+       // not fully qualified
+       if (current_namespace == awk_namespace || is_all_upper(name))
+               return name;    // put it into awk namespace
+
+       // make it fully qualified
+       size_t len = strlen(current_namespace) + 2 + strlen(name) + 1;
+       char *buf = NULL;
+
+       emalloc(buf, char *, len, "fix_up_namespace");
+       sprintf(buf, "%s::%s", current_namespace, name);
+       *malloced = true;
+
+       return buf;
+}
diff --git a/test/ChangeLog b/test/ChangeLog
index 7f17f72..812f3fa 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -17,6 +17,15 @@
        * Makefile.am (EXTRA_DIST): New test: dfacheck1.
        * dfacheck1.awk, dfacheck1.in, dfacheck1.ok: New files.
 
+2018-12-12         Arnold D. Robbins     <address@hidden>
+
+       * nsprof2.awk: Add extra @namespace lines for testing.
+       * nsprof2.ok: Adjusted.
+
+2018-12-06         Arnold D. Robbins     <address@hidden>
+
+       * nsprof2.awk, nsprof2.ok: Updated after code changes.
+
 2018-11-28         Arnold D. Robbins     <address@hidden>
 
        * profile11.ok: Updated after code change.
@@ -488,6 +497,40 @@
        * inplace1.ok, inplace2.ok, inplace3.ok: Update after
        adding license to inplace.awk.
 
+2017-07-26         Arnold D. Robbins     <address@hidden>
+
+       * Makefile.am (nsbad_cmd, nsindirect1, nsindirect2): New tests.
+       * nsbad_cmd.ok, nsindirect1.awk, nsindirect1.ok, nsindirect2.awk,
+       nsindirect2.ok: New files.
+
+2017-07-26         Arnold D. Robbins     <address@hidden>
+
+       * Makefile.am (nsbad): New test.
+       * nsbad.awk, nsbad.ok: New files.
+
+2017-07-20         Arnold D. Robbins     <address@hidden>
+
+       * Makefile.am (inplace1, inplace2, inplace3): Update to use
+       inplace::suffix instead of INPLACE_SUFFIX.
+       * inplace1.ok, inplace2.ok, inplace3.ok: Update after code
+       changes.
+
+2017-07-07         Arnold D. Robbins     <address@hidden>
+
+       * Makefile.am (eofsrc1): New test.
+       * eofsrc1a.awk, eofsrc1b.awk, eofsrc1.ok: New files.
+       * unterm.ok: Updated after code change.
+
+2017-07-01         Arnold D. Robbins     <address@hidden>
+
+       * Makefile.am (nsprof2): New test.
+       * nsprof2.awk, nsprof2.ok: New files.
+
+2017-06-30         Arnold D. Robbins     <address@hidden>
+
+       * Makefile.am (nsprof1): New test.
+       * nsprof1.awk, nsprof1.ok: New files.
+
 2017-06-27         Arnold D. Robbins     <address@hidden>
 
        * Makefile.am (mbprintf5): Skip this test on Cygwin.
@@ -502,6 +545,10 @@
        * Makefile.am (mbprintf5): New test.
        * mbprintf5.awk, mbprintf5.in, mbprintf5.ok: New files.
 
+2017-05-30         Arnold D. Robbins     <address@hidden>
+
+       * sourceplit.ok: Revise to match changed code.
+
 2017-05-24         Andrew J. Schorr     <address@hidden>
 
        * fwtest8.ok: Fix field number in error message, thanks to a bug
diff --git a/test/Makefile.am b/test/Makefile.am
index b4f50ce..0ffad9a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -262,6 +262,9 @@ EXTRA_DIST = \
        dynlj.ok \
        eofsplit.awk \
        eofsplit.ok \
+       eofsrc1a.awk \
+       eofsrc1b.awk \
+       eofsrc1.ok \
        errno.awk \
        errno.in \
        errno.ok \
@@ -767,6 +770,17 @@ EXTRA_DIST = \
        noparms.ok \
        nors.in \
        nors.ok \
+       nsbad.awk \
+       nsbad.ok \
+       nsbad_cmd.ok \
+       nsindirect1.awk \
+       nsindirect1.ok \
+       nsindirect2.awk \
+       nsindirect2.ok \
+       nsprof1.awk \
+       nsprof1.ok \
+       nsprof2.awk \
+       nsprof2.ok \
        nulinsrc.awk \
        nulinsrc.ok \
        nulrsend.awk \
@@ -1258,10 +1272,10 @@ BASIC_TESTS = \
        callparam childin clobber closebad clsflnam compare compare2 \
        concat1 concat2 concat3 concat4 concat5 convfmt \
        datanonl defref delargv delarpm2 delarprm delfunc dfamb1 dfastress 
dynlj \
-       eofsplit exit2 exitval1 exitval2 exitval3 fcall_exit fcall_exit2 \
-       fldchg fldchgnf fldterm fnamedat fnarray fnarray2 fnaryscl fnasgnm 
fnmisc \
-       fordel forref forsimp fsbs fsnul1 fsrs fsspcoln fstabplus funsemnl \
-       funsmnam funstack \
+       eofsplit eofsrc1 exit2 exitval1 exitval2 exitval3 \
+       fcall_exit fcall_exit2 fldchg fldchgnf fldterm fnamedat fnarray 
fnarray2 \
+       fnaryscl fnasgnm fnmisc fordel forref forsimp fsbs fsnul1 fsrs fsspcoln 
\
+       fstabplus funsemnl funsmnam funstack \
        getline getline2 getline3 getline4 getline5 getlnbuf getnr2tb getnr2tm \
        gsubasgn gsubtest gsubtst2 gsubtst3 gsubtst4 gsubtst5 gsubtst6 gsubtst7 
\
        gsubtst8 \
@@ -1311,19 +1325,20 @@ GAWK_EXT_TESTS = \
        incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 include include2 \
        indirectbuiltin indirectcall indirectcall2 intarray isarrayunset \
        lint lintexp lintindex lintint lintlength lintold lintset lintwarn \
-       mixed1 mktime manyfiles match1 match2 match3 mbstr1 mbstr2 muldimposix \
+       manyfiles match1 match2 match3 mbstr1 mbstr2 mixed1 mktime muldimposix \
        nastyparm negtime next nondec nondec2 nonfatal1 nonfatal2 nonfatal3 \
+       nsbad nsbad_cmd nsindirect1 nsindirect2 nsprof1 nsprof2 \
        patsplit posix printfbad1 printfbad2 printfbad3 printfbad4 printhuge \
        procinfs profile0 profile1 profile2 profile3 profile4 profile5 profile6 
\
        profile7 profile8 profile9 profile10 profile11 pty1 pty2 \
        rebuf regnul1 regnul2 regx8bit reginttrad reint reint2 rsgetline 
rsglstdin \
        rsstart1 rsstart2 rsstart3 rstest6 \
        shadow shadowbuiltin sortfor sortfor2 sortu sourcesplit 
split_after_fpat \
-       splitarg4 strftime strftfld strtonum strtonum1 switch2 symtab1 symtab2 \
+       splitarg4 strftfld strftime strtonum strtonum1 switch2 symtab1 symtab2 \
        symtab3 symtab4 symtab5 symtab6 symtab7 symtab8 symtab9 symtab10 \
-       typedregex1 typedregex2 typedregex3 typedregex4 \
+       timeout typedregex1 typedregex2 typedregex3 typedregex4 \
        typeof1 typeof2 typeof3 typeof4 typeof5 \
-       timeout watchpoint1
+       watchpoint1
 
 ARRAYDEBUG_TESTS = arrdbg
 
@@ -1372,7 +1387,8 @@ NEED_NONDEC = mpfrbigint2 nondec2 intarray forcenum
 NEED_POSIX = printf0 posix2008sub paramasfunc1 paramasfunc2 muldimposix
 
 # List of tests that need --pretty-print
-NEED_PRETTY = profile4 profile5 profile8 profile9 profile10 profile11
+NEED_PRETTY = nsprof1 nsprof2 \
+       profile4 profile5 profile8 profile9 profile10 profile11
 
 # List of tests that need --re-interval
 NEED_RE_INTERVAL = gsubtst3 reint reint2
@@ -2031,7 +2047,7 @@ inplace2::
        @echo $@
        @cp "$(srcdir)"/inplace.1.in address@hidden
        @cp "$(srcdir)"/inplace.2.in address@hidden
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
@@ -2042,8 +2058,8 @@ inplace3::
        @echo $@
        @cp "$(srcdir)"/inplace.1.in address@hidden
        @cp "$(srcdir)"/inplace.2.in address@hidden
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "Before"} {gsub(/bar/, "foo"); print} END 
{print "After"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >>_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "Before"} {gsub(/bar/, "foo"); print} END 
{print "After"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >>_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
@@ -2199,6 +2215,17 @@ sourcesplit:
        @AWKPATH="$(srcdir)" $(AWK) --source='BEGIN { a = 5;' --source='print a 
}' >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+eofsrc1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f "$(srcdir)"/address@hidden -f 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsbad_cmd:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -v foo:bar=3 -v foo:::blat=4 1 /dev/null 
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+
 # Use [:] in the regexp to keep MSYS from converting the /'s to \'s.
 nonfatal1:
        @echo $@
diff --git a/test/Makefile.in b/test/Makefile.in
index b6adabd..c244c7a 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -520,6 +520,9 @@ EXTRA_DIST = \
        dynlj.ok \
        eofsplit.awk \
        eofsplit.ok \
+       eofsrc1a.awk \
+       eofsrc1b.awk \
+       eofsrc1.ok \
        errno.awk \
        errno.in \
        errno.ok \
@@ -1025,6 +1028,17 @@ EXTRA_DIST = \
        noparms.ok \
        nors.in \
        nors.ok \
+       nsbad.awk \
+       nsbad.ok \
+       nsbad_cmd.ok \
+       nsindirect1.awk \
+       nsindirect1.ok \
+       nsindirect2.awk \
+       nsindirect2.ok \
+       nsprof1.awk \
+       nsprof1.ok \
+       nsprof2.awk \
+       nsprof2.ok \
        nulinsrc.awk \
        nulinsrc.ok \
        nulrsend.awk \
@@ -1516,10 +1530,10 @@ BASIC_TESTS = \
        callparam childin clobber closebad clsflnam compare compare2 \
        concat1 concat2 concat3 concat4 concat5 convfmt \
        datanonl defref delargv delarpm2 delarprm delfunc dfamb1 dfastress 
dynlj \
-       eofsplit exit2 exitval1 exitval2 exitval3 fcall_exit fcall_exit2 \
-       fldchg fldchgnf fldterm fnamedat fnarray fnarray2 fnaryscl fnasgnm 
fnmisc \
-       fordel forref forsimp fsbs fsnul1 fsrs fsspcoln fstabplus funsemnl \
-       funsmnam funstack \
+       eofsplit eofsrc1 exit2 exitval1 exitval2 exitval3 \
+       fcall_exit fcall_exit2 fldchg fldchgnf fldterm fnamedat fnarray 
fnarray2 \
+       fnaryscl fnasgnm fnmisc fordel forref forsimp fsbs fsnul1 fsrs fsspcoln 
\
+       fstabplus funsemnl funsmnam funstack \
        getline getline2 getline3 getline4 getline5 getlnbuf getnr2tb getnr2tm \
        gsubasgn gsubtest gsubtst2 gsubtst3 gsubtst4 gsubtst5 gsubtst6 gsubtst7 
\
        gsubtst8 \
@@ -1569,19 +1583,20 @@ GAWK_EXT_TESTS = \
        incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 include include2 \
        indirectbuiltin indirectcall indirectcall2 intarray isarrayunset \
        lint lintexp lintindex lintint lintlength lintold lintset lintwarn \
-       mixed1 mktime manyfiles match1 match2 match3 mbstr1 mbstr2 muldimposix \
+       manyfiles match1 match2 match3 mbstr1 mbstr2 mixed1 mktime muldimposix \
        nastyparm negtime next nondec nondec2 nonfatal1 nonfatal2 nonfatal3 \
+       nsbad nsbad_cmd nsindirect1 nsindirect2 nsprof1 nsprof2 \
        patsplit posix printfbad1 printfbad2 printfbad3 printfbad4 printhuge \
        procinfs profile0 profile1 profile2 profile3 profile4 profile5 profile6 
\
        profile7 profile8 profile9 profile10 profile11 pty1 pty2 \
        rebuf regnul1 regnul2 regx8bit reginttrad reint reint2 rsgetline 
rsglstdin \
        rsstart1 rsstart2 rsstart3 rstest6 \
        shadow shadowbuiltin sortfor sortfor2 sortu sourcesplit 
split_after_fpat \
-       splitarg4 strftime strftfld strtonum strtonum1 switch2 symtab1 symtab2 \
+       splitarg4 strftfld strftime strtonum strtonum1 switch2 symtab1 symtab2 \
        symtab3 symtab4 symtab5 symtab6 symtab7 symtab8 symtab9 symtab10 \
-       typedregex1 typedregex2 typedregex3 typedregex4 \
+       timeout typedregex1 typedregex2 typedregex3 typedregex4 \
        typeof1 typeof2 typeof3 typeof4 typeof5 \
-       timeout watchpoint1
+       watchpoint1
 
 ARRAYDEBUG_TESTS = arrdbg
 EXTRA_TESTS = inftest regtest ignrcas3 
@@ -1629,7 +1644,8 @@ NEED_NONDEC = mpfrbigint2 nondec2 intarray forcenum
 NEED_POSIX = printf0 posix2008sub paramasfunc1 paramasfunc2 muldimposix
 
 # List of tests that need --pretty-print
-NEED_PRETTY = profile4 profile5 profile8 profile9 profile10 profile11
+NEED_PRETTY = nsprof1 nsprof2 \
+       profile4 profile5 profile8 profile9 profile10 profile11
 
 # List of tests that need --re-interval
 NEED_RE_INTERVAL = gsubtst3 reint reint2
@@ -2479,7 +2495,7 @@ inplace2::
        @echo $@
        @cp "$(srcdir)"/inplace.1.in address@hidden
        @cp "$(srcdir)"/inplace.2.in address@hidden
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
@@ -2490,8 +2506,8 @@ inplace3::
        @echo $@
        @cp "$(srcdir)"/inplace.1.in address@hidden
        @cp "$(srcdir)"/inplace.2.in address@hidden
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
-       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
INPLACE_SUFFIX=.bak 'BEGIN {print "Before"} {gsub(/bar/, "foo"); print} END 
{print "After"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >>_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END 
{print "after"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v 
inplace::suffix=.bak 'BEGIN {print "Before"} {gsub(/bar/, "foo"); print} END 
{print "After"}' address@hidden - address@hidden < "$(srcdir)"/inplace.in >>_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
        @-$(CMP) "$(srcdir)"/address@hidden address@hidden && rm -f 
address@hidden
@@ -2645,6 +2661,16 @@ sourcesplit:
        @AWKPATH="$(srcdir)" $(AWK) --source='BEGIN { a = 5;' --source='print a 
}' >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+eofsrc1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f "$(srcdir)"/address@hidden -f 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsbad_cmd:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -v foo:bar=3 -v foo:::blat=4 1 /dev/null 
>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 # Use [:] in the regexp to keep MSYS from converting the /'s to \'s.
 nonfatal1:
        @echo $@
@@ -4285,11 +4311,6 @@ lintwarn:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
-mktime:
-       @echo $@
-       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
-       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
-
 match1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -4317,6 +4338,11 @@ mbstr2:
        AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+mktime:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 muldimposix:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --posix >_$@ 2>&1 || 
echo EXIT CODE: $$? >>_$@
@@ -4352,6 +4378,31 @@ nonfatal3:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+nsbad:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsindirect1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsindirect2:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsprof1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --pretty-print=_$@ >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsprof2:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --pretty-print=_$@ >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 patsplit:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -4554,6 +4605,11 @@ symtab10:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --debug < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+timeout:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 typedregex1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -4594,11 +4650,6 @@ typeof5:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
-timeout:
-       @echo $@
-       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
-       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
-
 double1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 9ad8ade..7163b4a 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1606,11 +1606,6 @@ lintwarn:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --lint >_$@ 2>&1 || echo 
EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
-mktime:
-       @echo $@
-       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
-       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
-
 match1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -1638,6 +1633,11 @@ mbstr2:
        AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+mktime:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 muldimposix:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --posix >_$@ 2>&1 || 
echo EXIT CODE: $$? >>_$@
@@ -1673,6 +1673,31 @@ nonfatal3:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+nsbad:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsindirect1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsindirect2:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsprof1:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --pretty-print=_$@ >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
+nsprof2:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --pretty-print=_$@ >_$@ 
2>&1 || echo EXIT CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 patsplit:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -1875,6 +1900,11 @@ symtab10:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  --debug < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
+timeout:
+       @echo $@
+       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
+       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
+
 typedregex1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
@@ -1915,11 +1945,6 @@ typeof5:
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  < 
"$(srcdir)"/address@hidden >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
 
-timeout:
-       @echo $@
-       @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
-       @-$(CMP) "$(srcdir)"/address@hidden _$@ && rm -f _$@
-
 double1:
        @echo $@
        @AWKPATH="$(srcdir)" $(AWK) -f address@hidden  >_$@ 2>&1 || echo EXIT 
CODE: $$? >>_$@
diff --git a/test/eofsrc1.ok b/test/eofsrc1.ok
new file mode 100644
index 0000000..64d85b3
--- /dev/null
+++ b/test/eofsrc1.ok
@@ -0,0 +1,3 @@
+gawk: ./eofsrc1a.awk:2: (END OF FILE)
+gawk: ./eofsrc1a.awk:2: ^ source files / command-line arguments must contain 
complete functions or rules
+EXIT CODE: 1
diff --git a/test/eofsrc1a.awk b/test/eofsrc1a.awk
new file mode 100644
index 0000000..55143c2
--- /dev/null
+++ b/test/eofsrc1a.awk
@@ -0,0 +1,2 @@
+BEGIN {
+       n = 5
diff --git a/test/eofsrc1b.awk b/test/eofsrc1b.awk
new file mode 100644
index 0000000..0dad216
--- /dev/null
+++ b/test/eofsrc1b.awk
@@ -0,0 +1,2 @@
+       print n
+}
diff --git a/test/inplace1.ok b/test/inplace1.ok
index 730d775..753079b 100644
--- a/test/inplace1.ok
+++ b/test/inplace1.ok
@@ -1,5 +1,5 @@
 before
-gawk: inplace:47: warning: inplace_begin: disabling in-place editing for 
invalid FILENAME `-'
+gawk: inplace:53: warning: inplace::begin: disabling in-place editing for 
invalid FILENAME `-'
 stdin start
 is bar replaced?
 stdin end
diff --git a/test/inplace2.ok b/test/inplace2.ok
index 730d775..753079b 100644
--- a/test/inplace2.ok
+++ b/test/inplace2.ok
@@ -1,5 +1,5 @@
 before
-gawk: inplace:47: warning: inplace_begin: disabling in-place editing for 
invalid FILENAME `-'
+gawk: inplace:53: warning: inplace::begin: disabling in-place editing for 
invalid FILENAME `-'
 stdin start
 is bar replaced?
 stdin end
diff --git a/test/inplace3.ok b/test/inplace3.ok
index 815cd1c..7802a0c 100644
--- a/test/inplace3.ok
+++ b/test/inplace3.ok
@@ -1,11 +1,11 @@
 before
-gawk: inplace:47: warning: inplace_begin: disabling in-place editing for 
invalid FILENAME `-'
+gawk: inplace:53: warning: inplace::begin: disabling in-place editing for 
invalid FILENAME `-'
 stdin start
 is bar replaced?
 stdin end
 after
 Before
-gawk: inplace:47: warning: inplace_begin: disabling in-place editing for 
invalid FILENAME `-'
+gawk: inplace:53: warning: inplace::begin: disabling in-place editing for 
invalid FILENAME `-'
 stdin start
 is foo replaced?
 stdin end
diff --git a/test/nsbad.awk b/test/nsbad.awk
new file mode 100644
index 0000000..825bb35
--- /dev/null
+++ b/test/nsbad.awk
@@ -0,0 +1,15 @@
address@hidden "1foo"
address@hidden "for"
address@hidden "42f"
address@hidden "ab#d"
+
+BEGIN {
+       foo75::bar = 57
+       if::junk = 1
+       foo::match = 3
+}
+
address@hidden "foo"
+function gsub () {
+       print "foo::gsub"
+}
diff --git a/test/nsbad.ok b/test/nsbad.ok
new file mode 100644
index 0000000..dfa228a
--- /dev/null
+++ b/test/nsbad.ok
@@ -0,0 +1,13 @@
+gawk: nsbad.awk:1: error: namespace name `1foo' must meet identifier naming 
rules
+gawk: nsbad.awk:2: error: using reserved identifier `for' as a namespace is 
not allowed
+gawk: nsbad.awk:3: error: namespace name `42f' must meet identifier naming 
rules
+gawk: nsbad.awk:4: error: namespace name `ab#d' must meet identifier naming 
rules
+gawk: nsbad.awk:8: error: using reserved identifier `if' as a namespace is not 
allowed
+gawk: nsbad.awk:8:     if::junk = 1
+gawk: nsbad.awk:8:              ^ syntax error
+gawk: nsbad.awk:9: error: using reserved identifier `match' as second 
component of a qualified name is not allowed
+gawk: nsbad.awk:9:     foo::match = 3
+gawk: nsbad.awk:9:                ^ syntax error
+gawk: nsbad.awk:13: function gsub () {
+gawk: nsbad.awk:13:          ^ `gsub' is a built-in function, it cannot be 
redefined
+EXIT CODE: 1
diff --git a/test/nsbad_cmd.ok b/test/nsbad_cmd.ok
new file mode 100644
index 0000000..cbca6ea
--- /dev/null
+++ b/test/nsbad_cmd.ok
@@ -0,0 +1,3 @@
+gawk: error: identifier foo:bar: namespace separator is two colons, not one
+gawk: error: qualified identifier `foo:::blat' is badly formed
+EXIT CODE: 1
diff --git a/test/nsindirect1.awk b/test/nsindirect1.awk
new file mode 100644
index 0000000..d04863f
--- /dev/null
+++ b/test/nsindirect1.awk
@@ -0,0 +1,13 @@
address@hidden "test"
+
+BEGIN {
+       bar = 3
+}
+
address@hidden "awk"
+
+BEGIN {
+       print "before change, direct =", test::bar, "indirect =", 
SYMTAB["test::bar"]
+       SYMTAB["test::bar"] = 4
+       print "after change, direct =", test::bar, "indirect =", 
SYMTAB["test::bar"]
+}
diff --git a/test/nsindirect1.ok b/test/nsindirect1.ok
new file mode 100644
index 0000000..ab2e31b
--- /dev/null
+++ b/test/nsindirect1.ok
@@ -0,0 +1,2 @@
+before change, direct = 3 indirect = 3
+after change, direct = 4 indirect = 4
diff --git a/test/nsindirect2.awk b/test/nsindirect2.awk
new file mode 100644
index 0000000..8017e8f
--- /dev/null
+++ b/test/nsindirect2.awk
@@ -0,0 +1,44 @@
+BEGIN {
+       stftime::gensub = 3     # should be OK, not related to indirect calls
+}
+
+
+BEGIN { base_time = systime() }        # in awk namespace
+
address@hidden "testing"
+
+function strftime(mesg)
+{
+       printf("strftime(%s) - this is not the function you are looking for\n",
+               mesg)
+       return 0
+}
+
+BEGIN {
+       strftime("from 'testing'")
+       gensub = "gensub"
+       print "gensub =", gensub
+}
+
+function systime()
+{
+       return awk::base_time
+}
+
+BEGIN {
+       st = "systime"
+       now[1] = @st()
+
+       st = "awk::systime"
+       now[2] = @st()
+
+       st = "testing::systime"
+       now[3] = @st()
+
+       for (i = 1; i <= 3; i++) {
+               if (now[i] == awk::base_time || now[i] == awk::base_time + 1)
+                       printf "iteration %d, got good result from systime\n", i
+               else
+                       printf "iteration %d, got bad result from systime, now 
%d, base_time %d\n", i, now, awk::base_time
+       }
+}
diff --git a/test/nsindirect2.ok b/test/nsindirect2.ok
new file mode 100644
index 0000000..9b71cd9
--- /dev/null
+++ b/test/nsindirect2.ok
@@ -0,0 +1,5 @@
+strftime() - this is not the function you are looking for
+gensub = gensub
+iteration 1, got good result from systime
+iteration 2, got good result from systime
+iteration 3, got good result from systime
diff --git a/test/nsprof1.awk b/test/nsprof1.awk
new file mode 100644
index 0000000..46be5bc
--- /dev/null
+++ b/test/nsprof1.awk
@@ -0,0 +1,16 @@
address@hidden "foo"
+
+BEGIN {
+       a = 5
+       a++
+       print a
+}
+
+/foo/ { print "bar" }
+
address@hidden "stuff"
+
+function stuff()
+{
+       print "stuff"
+}
diff --git a/test/nsprof1.ok b/test/nsprof1.ok
new file mode 100644
index 0000000..eacc270
--- /dev/null
+++ b/test/nsprof1.ok
@@ -0,0 +1,19 @@
address@hidden "foo"
+
+BEGIN {
+       a = 5
+       a++
+       print a
+}
+
+/foo/ {
+       print "bar"
+}
+
address@hidden "stuff"
+
+
+function stuff()
+{
+       print "stuff"
+}
diff --git a/test/nsprof2.awk b/test/nsprof2.awk
new file mode 100644
index 0000000..9c7da57
--- /dev/null
+++ b/test/nsprof2.awk
@@ -0,0 +1,74 @@
+# passwd.awk --- access password file information
+#
+# Arnold Robbins, address@hidden, Public Domain
+# May 1993
+# Revised October 2000
+# Revised December 2010
+# Revised July 2017
+
address@hidden "foo"    # this is foo
+
address@hidden "bar"    # this is bar
+
address@hidden "passwd" # move to passwd namespace
+
+BEGIN {
+    # tailor this to suit your system
+    Awklib = "/usr/local/libexec/awk/"
+}
+
+function Init(    oldfs, oldrs, olddol0, pwcat, using_fw, using_fpat)
+{
+    if (Inited)
+        return
+
+    oldfs = FS
+    oldrs = RS
+    olddol0 = $0
+    using_fw = (PROCINFO["FS"] == "FIELDWIDTHS")
+    using_fpat = (PROCINFO["FS"] == "FPAT")
+    FS = ":"
+    RS = "\n"
+
+    pwcat = Awklib "pwcat"
+    while ((pwcat | getline) > 0) {
+        Byname[$1] = $0
+        Byuid[$3] = $0
+        Bycount[++Total] = $0
+    }
+    close(pwcat)
+    Count = 0
+    Inited = 1
+    FS = oldfs
+    if (using_fw)
+        FIELDWIDTHS = FIELDWIDTHS
+    else if (using_fpat)
+        FPAT = FPAT
+    RS = oldrs
+    $0 = olddol0
+}
+
+function awk::getpwnam(name)
+{
+    Init()
+    return Byname[name]
+}
+
+function awk::getpwuid(uid)
+{
+    Init()
+    return Byuid[uid]
+}
+
+function awk::getpwent()
+{
+    Init()
+    if (Count < Total)
+        return Bycount[++Count]
+    return ""
+}
+
+function awk::endpwent()
+{
+    Count = 0
+}
diff --git a/test/nsprof2.ok b/test/nsprof2.ok
new file mode 100644
index 0000000..1bb7882
--- /dev/null
+++ b/test/nsprof2.ok
@@ -0,0 +1,75 @@
+# passwd.awk --- access password file information
+#
+# Arnold Robbins, address@hidden, Public Domain
+# May 1993
+# Revised October 2000
+# Revised December 2010
+# Revised July 2017
address@hidden "foo"    # this is foo
+
address@hidden "bar"    # this is bar
+
address@hidden "passwd" # move to passwd namespace
+
+BEGIN {
+       # tailor this to suit your system
+       Awklib = "/usr/local/libexec/awk/"
+}
+
+
+function awk::endpwent()
+{
+       Count = 0
+}
+
+function awk::getpwent()
+{
+       Init()
+       if (Count < Total) {
+               return Bycount[++Count]
+       }
+       return ""
+}
+
+function awk::getpwnam(name)
+{
+       Init()
+       return Byname[name]
+}
+
+function awk::getpwuid(uid)
+{
+       Init()
+       return Byuid[uid]
+}
+
+function Init(oldfs, oldrs, olddol0, pwcat, using_fw, using_fpat)
+{
+       if (Inited) {
+               return 
+       }
+       oldfs = awk::FS
+       oldrs = awk::RS
+       olddol0 = $0
+       using_fw = (awk::PROCINFO["FS"] == "FIELDWIDTHS")
+       using_fpat = (awk::PROCINFO["FS"] == "FPAT")
+       awk::FS = ":"
+       awk::RS = "\n"
+       pwcat = Awklib "pwcat"
+       while ((pwcat | getline) > 0) {
+               Byname[$1] = $0
+               Byuid[$3] = $0
+               Bycount[++Total] = $0
+       }
+       close(pwcat)
+       Count = 0
+       Inited = 1
+       awk::FS = oldfs
+       if (using_fw) {
+               awk::FIELDWIDTHS = awk::FIELDWIDTHS
+       } else if (using_fpat) {
+               awk::FPAT = awk::FPAT
+       }
+       awk::RS = oldrs
+       $0 = olddol0
+}
diff --git a/test/sourcesplit.ok b/test/sourcesplit.ok
index 7ed6ff8..c883f51 100644
--- a/test/sourcesplit.ok
+++ b/test/sourcesplit.ok
@@ -1 +1,3 @@
-5
+gawk: cmd. line:1: BEGIN { a = 5;
+gawk: cmd. line:1:               ^ unexpected newline or end of string
+EXIT CODE: 1
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
diff --git a/test/unterm.ok b/test/unterm.ok
index 760d370..399f626 100644
--- a/test/unterm.ok
+++ b/test/unterm.ok
@@ -1,5 +1,5 @@
 gawk: unterm.awk:1: 
BEGIN{x=".........................................................................................................................................................................................................................................................}
 gawk: unterm.awk:1:         ^ unterminated string
-gawk: unterm.awk:1: 
BEGIN{x=".........................................................................................................................................................................................................................................................}
-gawk: unterm.awk:1:         ^ syntax error
+gawk: unterm.awk:1: (END OF FILE)
+gawk: unterm.awk:1:         ^ source files / command-line arguments must 
contain complete functions or rules
 EXIT CODE: 1

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

Summary of changes:
 ChangeLog                   |  266 +++++
 NEWS                        |    7 +
 TODO                        |   15 -
 array.c                     |    2 +-
 awk.h                       |   19 +-
 awkgram.c                   | 2370 ++++++++++++++++++++++++-------------------
 awkgram.y                   |  310 +++++-
 awklib/eg/lib/inplace.awk   |   28 +-
 awklib/eg/lib/ns_passwd.awk |   72 ++
 command.c                   |    2 +-
 command.y                   |    2 +-
 debug.c                     |   42 +-
 doc/ChangeLog               |  113 +++
 doc/awkcard.in              |   41 +-
 doc/gawk.1                  |   50 +-
 doc/gawk.info               | 2157 ++++++++++++++++++++++++---------------
 doc/gawk.texi               |  586 ++++++++++-
 doc/gawktexi.in             |  586 ++++++++++-
 doc/wordlist                |   10 +
 eval.c                      |    5 +-
 ext.c                       |   36 +-
 extension/ChangeLog         |   12 +
 extension/inplace.c         |   44 +-
 extension/testext.c         |   28 +-
 gawkapi.c                   |   65 +-
 gawkapi.h                   |   14 +-
 interpret.h                 |    4 +-
 main.c                      |   20 +-
 pc/Makefile.tst             |   84 +-
 profile.c                   |  116 ++-
 symbol.c                    |   84 +-
 test/ChangeLog              |   47 +
 test/Makefile.am            |   51 +-
 test/Makefile.in            |   95 +-
 test/Maketests              |   45 +-
 test/eofsrc1.ok             |    3 +
 test/eofsrc1a.awk           |    2 +
 test/eofsrc1b.awk           |    2 +
 test/inplace1.ok            |    2 +-
 test/inplace2.ok            |    2 +-
 test/inplace3.ok            |    4 +-
 test/nsbad.awk              |   15 +
 test/nsbad.ok               |   13 +
 test/nsbad_cmd.ok           |    3 +
 test/nsindirect1.awk        |   13 +
 test/nsindirect1.ok         |    2 +
 test/nsindirect2.awk        |   44 +
 test/nsindirect2.ok         |    5 +
 test/nsprof1.awk            |   16 +
 test/nsprof1.ok             |   19 +
 test/nsprof2.awk            |   74 ++
 test/nsprof2.ok             |   75 ++
 test/sourcesplit.ok         |    4 +-
 test/testext.ok             |    3 +
 test/unterm.ok              |    4 +-
 55 files changed, 5595 insertions(+), 2138 deletions(-)
 create mode 100644 awklib/eg/lib/ns_passwd.awk
 create mode 100644 test/eofsrc1.ok
 create mode 100644 test/eofsrc1a.awk
 create mode 100644 test/eofsrc1b.awk
 create mode 100644 test/nsbad.awk
 create mode 100644 test/nsbad.ok
 create mode 100644 test/nsbad_cmd.ok
 create mode 100644 test/nsindirect1.awk
 create mode 100644 test/nsindirect1.ok
 create mode 100644 test/nsindirect2.awk
 create mode 100644 test/nsindirect2.ok
 create mode 100644 test/nsprof1.awk
 create mode 100644 test/nsprof1.ok
 create mode 100644 test/nsprof2.awk
 create mode 100644 test/nsprof2.ok


hooks/post-receive
-- 
gawk



reply via email to

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