aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xChangeLog266
-rw-r--r--NEWS7
-rw-r--r--TODO15
-rw-r--r--array.c2
-rw-r--r--awk.h19
-rw-r--r--awkgram.c2370
-rw-r--r--awkgram.y310
-rw-r--r--awklib/eg/lib/inplace.awk28
-rw-r--r--awklib/eg/lib/ns_passwd.awk72
-rw-r--r--command.c2
-rw-r--r--command.y2
-rw-r--r--debug.c42
-rw-r--r--doc/ChangeLog113
-rw-r--r--doc/awkcard.in41
-rw-r--r--doc/gawk.150
-rw-r--r--doc/gawk.info2157
-rw-r--r--doc/gawk.texi586
-rw-r--r--doc/gawktexi.in586
-rw-r--r--doc/wordlist10
-rw-r--r--eval.c5
-rw-r--r--ext.c36
-rw-r--r--extension/ChangeLog12
-rw-r--r--extension/inplace.c44
-rw-r--r--extension/testext.c28
-rw-r--r--gawkapi.c65
-rw-r--r--gawkapi.h14
-rw-r--r--interpret.h4
-rw-r--r--main.c20
-rw-r--r--pc/Makefile.tst84
-rw-r--r--profile.c116
-rw-r--r--symbol.c84
-rw-r--r--test/ChangeLog47
-rw-r--r--test/Makefile.am51
-rw-r--r--test/Makefile.in95
-rw-r--r--test/Maketests45
-rw-r--r--test/eofsrc1.ok3
-rw-r--r--test/eofsrc1a.awk2
-rw-r--r--test/eofsrc1b.awk2
-rw-r--r--test/inplace1.ok2
-rw-r--r--test/inplace2.ok2
-rw-r--r--test/inplace3.ok4
-rw-r--r--test/nsbad.awk15
-rw-r--r--test/nsbad.ok13
-rw-r--r--test/nsbad_cmd.ok3
-rw-r--r--test/nsindirect1.awk13
-rw-r--r--test/nsindirect1.ok2
-rw-r--r--test/nsindirect2.awk44
-rw-r--r--test/nsindirect2.ok5
-rw-r--r--test/nsprof1.awk16
-rw-r--r--test/nsprof1.ok19
-rw-r--r--test/nsprof2.awk74
-rw-r--r--test/nsprof2.ok75
-rw-r--r--test/sourcesplit.ok4
-rw-r--r--test/testext.ok3
-rw-r--r--test/unterm.ok4
55 files changed, 5595 insertions, 2138 deletions
diff --git a/ChangeLog b/ChangeLog
index 11b57fea..5f04e8ab 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 <arnold@skeeve.com>
+
+ 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
+
+ * NEWS: Updated some.
+
+2018-12-12 Arnold D. Robbins <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * awkgram.y (set_namespace): Change return type void, adjust
+ all return statements.
+ [@namespace]: 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 <arnold@skeeve.com>
+
+ 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 <arnold@skeeve.com>
+
+ 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 <arnold@skeeve.com>
+
+ * awkgram.y [direct_func_call]: Save full variable name for
+ indirect calls too.
+
2017-07-17 Arnold D. Robbins <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
+
+ 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 <arnold@skeeve.com>
+
+ 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 <arnold@skeeve.com>
* awk.h (is_letter): Add declaration.
@@ -1138,6 +1286,17 @@
2017-07-07 Arnold D. Robbins <arnold@skeeve.com>
+ * 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 <arnold@skeeve.com>
+
* 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * 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 `@namespace 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * awkgram.y (nextc): Force -e chunks to be syntactic units.
+ Needed for namespaces to work correctly.
+
2017-05-30 Arnold D. Robbins <arnold@skeeve.com>
* NEWS: Mention PROCINFO["argv"].
diff --git a/NEWS b/NEWS
index 25a5a6a4..e5f34f88 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 6bade179..b621ab6b 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 f2e64f6b..34b7076a 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 d6aaf6eb..bac788b3 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 993dfc4c..aa86581c 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",
- "$@1", "regexp", "$@2", "typed_regexp", "a_slash", "statements",
- "statement_term", "statement", "non_compound_stmt", "$@3", "simple_stmt",
- "$@4", "$@5", "opt_simple_stmt", "case_statements", "case_statement",
- "case_value", "print", "print_expression_list", "output_redir", "$@6",
- "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", "$@1", "regexp", "$@2",
+ "typed_regexp", "a_slash", "statements", "statement_term", "statement",
+ "non_compound_stmt", "$@3", "simple_stmt", "$@4", "$@5",
+ "opt_simple_stmt", "case_statements", "case_statement", "case_value",
+ "print", "print_expression_list", "output_redir", "$@6", "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 e0af4c1a..49ac3ef6 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 6771bc45..68dad92e 100644
--- a/awklib/eg/lib/inplace.awk
+++ b/awklib/eg/lib/inplace.awk
@@ -21,11 +21,15 @@
#
# Andrew J. Schorr, aschorr@telemetry-investments.com
# January 2013
+#
+# Revised for namespaces
+# Arnold Robbins, arnold@skeeve.com
+# 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.
+@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)
}
diff --git a/awklib/eg/lib/ns_passwd.awk b/awklib/eg/lib/ns_passwd.awk
new file mode 100644
index 00000000..b9b6bce5
--- /dev/null
+++ b/awklib/eg/lib/ns_passwd.awk
@@ -0,0 +1,72 @@
+# ns_passwd.awk --- access password file information
+#
+# 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
+
+@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
+}
diff --git a/command.c b/command.c
index c8ee1632..b076530d 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 58880dee..553a7c3c 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 6c6a59f5..f8aa6adf 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 270bdf2c..ef83d893 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * gawktexi.in: Added more indexing to the debugger chapter.
+ Add more indexing to namespaces chapter, too.
+
+2018-12-12 Arnold D. Robbins <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
+
+ * awkcard.in: Add @namespaces to Execution section.
+
+2017-10-12 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawk.1: Documents namespaces.
+ * awkcard.in: Ditto.
+
2017-10-10 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in (Readfile Function): Fix the code for the naive
@@ -511,6 +541,11 @@
* texinfo.tex: Updated.
+2017-08-02 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Namespace Summary): Add summary to namespace
+ chapter.
+
2017-08-01 Arnold D. Robbins <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
@@ -527,15 +564,60 @@
inplace.awk; should have done that when it was first
added. Oops.
+2017-07-26 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Namespaces): More edits.
+
2017-07-21 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in: Fix a spelling error.
* wordlist: Update with more words.
+ Done also for namespace material.
+
+2017-07-20 Arnold D. Robbins <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * gawktexi.in (Namespaces): Cleanup, new section on naming rules
+ added.
+
+2017-07-17 Arnold D. Robbins <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * gawktexi.in (Namespaces): More updates.
+
2017-07-02 Arnold D. Robbins <arnold@skeeve.com>
* texinfo.tex: Pull in latest from Texinfo SVN.
+2017-06-30 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Namespaces): Move to later in the book.
+
+2017-06-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Namespaces): More minor doc edits.
+
2017-06-19 Andrew J. Schorr <aschorr@telemetry-investments.com>
* gawktexi.in (Memory Allocation Functions and Convenience Macros):
@@ -548,11 +630,42 @@
2017-06-15 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in: Expand tab characters.
+ * gawktexi.in (Namespaces): Further minor doc edits, including
+ hyphenation hint.
+
+2017-06-13 Arnold D. Robbins <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * gawktexi.in (Namespaces): Further clarifications. Move to
+ `::' as the namespace separator.
2017-06-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
* gawktexi.in (Checking for MPFR): Fix typo.
+2017-06-02 Arnold D. Robbins <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * gawktexi.in: Initial doc on namespaces. Serves as a design
+ right now.
+ * gawktexi.in: More doc added.
+
2017-05-30 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in: Document PROCINFO["argv"].
diff --git a/doc/awkcard.in b/doc/awkcard.in
index d4df3427..1a6b72f5 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\*(FC@include "\*(FIfilename\*(FC"
.br
- \*(FC@load "\*(FIfilename\*(FC"\*(CD
+ \*(FC@load "\*(FIfilename\*(FC"
+.br
+ \*(FC@namespace "\*(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
+\*(FC@namespace "\*(FIname\^\*(FC"\*(FR
+directive.\*(CB
+.EB "\s+2\f(HBNAMESPACES\*(FR\s0"
.BT
diff --git a/doc/gawk.1 b/doc/gawk.1
index 4964cb3d..4b188aef 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 \fB@namespace "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 \fB@namespace "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 \fB@namespace "awk"\fR statement.
.TP
.PD 0
.BI "\-l " lib
@@ -577,9 +586,11 @@ pattern-action statements,
and optional function definitions.
.RS
.PP
-\fB@include "\fIfilename\fB"
+\fB@include "\fIfilename\^\fB"
.br
-\fB@load "\fIfilename\fB"
+\fB@load "\fIfilename\^\fB"
+.br
+\fB@namespace "\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
+\fB@namespace "\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 35d1f56f..6ecfd8a1 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.
@@ -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.
@@ -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.
@@ -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 5f304a1b..5dd04337 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
+@ref{Namespaces}, describes how @command{gawk} allows variables and/or
+functions of the same name to be in different namespaces.
+
+@item
@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 @var{var}=@var{val}
@itemx --assign @var{var}=@var{val}
@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
+@samp{@@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
-@c FIXME: Include this?
-@ignore
-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.
-@end 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
+@ref{Namespaces}
+
+@item
@ref{Advanced Features}
@item
@@ -31683,6 +31717,447 @@ program being debugged, but occasionally it can.
@end itemize
+@hyphenation{name-space name-spaces Name-space Name-spaces}
+@node Namespaces
+@chapter Namespaces in @command{gawk}
+
+This @value{CHAPTER} describes a feature that is specific to @command{gawk}.
+
+@menu
+* 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.
+@end menu
+
+@node Global Namespace
+@section Standard @command{awk}'s Single Namespace
+
+@cindex namespace, definition of
+@cindex 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}).
+
+@cindex package, definition of
+@cindex 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.
+
+@node Qualified Names
+@section Qualified Names
+
+@cindex qualified name, definition of
+@cindex namespaces, qualified names
+@cindex @code{::}, namespace separator
+@cindex 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.
+
+@quotation NOTE
+Unlike C++, the @code{::} is @emph{not} an operator. No spaces are
+allowed between the namespace name, the @code{::}, and the component name.
+@end quotation
+
+@cindex 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}).
+
+@node Default Namespace
+@section The Default Namespace
+
+@cindex namespace, default
+@cindex namespace, @code{awk}
+@cindex @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
+@code{awk::ARGC}, @code{awk::NF}, and so on.
+
+@cindex 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.
+
+@node Changing The Namespace
+@section Changing The Namespace
+
+@cindex namespaces, changing
+@cindex @code{@@namespace} directive
+In order to set the current namespace, use an @code{@@namespace} directive
+at the top level of your program:
+
+@example
+@@namespace "passwd"
+
+BEGIN @{ @dots{} @}
+@dots{}
+@end 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.
+
+@quotation NOTE
+Association of unqualified identifiers to a namespace is handled while
+@command{gawk} 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.
+@end quotation
+
+@cindex namespace, implicit
+@cindex 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}).
+
+@cindex current namespace, pushing and popping
+@cindex 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.
+
+@cindex @code{@@namespace}, no effect on @code{BEGIN} @code{BEGINFILE}, @code{END}, and @code{ENDFILE}
+@cindex @code{BEGIN}, execution order not affected by @code{@@namespace}
+@cindex @code{BEGINFILE}, execution order not affected by @code{@@namespace}
+@cindex @code{END}, execution order not affected by @code{@@namespace}
+@cindex @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.
+
+@node Naming Rules
+@section Namespace and Component Naming Rules
+
+@cindex naming rules, namespaces and component names
+@cindex namespace names, naming rules
+@cindex component names, naming rules
+A number of rules apply to the namespace and component names, as follows.
+
+@itemize @bullet
+@item
+It is a syntax error to use qualified names for function parameter names.
+
+@item
+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:
+
+@example
+@@namespace "example"
+
+function gsub(str, pat, result) @{ @dots{} @}
+@end example
+
+@item
+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.
+
+@item
+The additional @command{gawk} built-in functions may still be called
+from outside the @code{awk} namespace by qualifying them. For example,
+@code{awk::systime()}. Here is a somewhat silly example demonstrating
+this rule and the previous one:
+
+@example
+BEGIN @{
+ print "in awk namespace, systime() =", systime()
+@}
+
+@@namespace "testing"
+
+function systime()
+@{
+ print "in testing namespace, systime() =", awk::systime()
+@}
+
+BEGIN @{
+ systime()
+@}
+@end example
+
+@noindent
+
+When run, it produces output like this:
+
+@example
+$ @kbd{gawk -f systime.awk}
+@print{} in awk namespace, systime() = 1500488503
+@print{} in testing namespace, systime() = 1500488503
+@end example
+
+@item
+@command{gawk} pre-defined variable names may be used:
+@code{NF::NR} is valid, if possibly not all that useful.
+@end itemize
+
+@node Internal Name Management
+@section Internal Name Management
+
+@cindex name management
+@cindex @code{awk} namespace, identifier name storage
+@cindex @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:
+
+@example
+@@namespace "awk" @ii{This is the default namespace}
+
+BEGIN @{
+ Title = "My Report" @ii{Qualified name is} awk::Title
+@}
+
+@@namespace "report" @ii{Now in} report @ii{namespace}
+
+function compute() @ii{This is really} report::compute()
+@{
+ print awk::Title @ii{But would be} SYMTAB["Title"]
+ @dots{}
+@}
+@end example
+
+@node Namespace Example
+@section Namespace Example
+
+@cindex 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
+@code{passwd} namespace, whereas the main interface functions are
+defined in the @code{awk} namespace.
+
+@example
+@c file eg/lib/ns_passwd.awk
+# ns_passwd.awk --- access password file information
+@c endfile
+@ignore
+@c 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
+@c endfile
+@end ignore
+@c file eg/lib/ns_passwd.awk
+
+@@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
+@}
+@c endfile
+@end example
+
+As you can see, this version also follows the convention mentioned in
+@ref{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 @code{awk} namespace:
+
+@example
+BEGIN @{
+ while ((p = getpwent()) != "")
+ print p
+@}
+@end example
+
+@noindent
+
+Here's what happens when it's run:
+
+@example
+$ @kbd{gawk -f ns_passwd.awk -f testpasswd.awk}
+@print{} root:x:0:0:root:/root:/bin/bash
+@print{} daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
+@print{} bin:x:2:2:bin:/bin:/usr/sbin/nologin
+@print{} sys:x:3:3:sys:/dev:/usr/sbin/nologin
+@dots{}
+@end example
+
+@node Namespace And Features
+@section Namespaces and Other @command{gawk} Features
+
+This @value{SECTION} looks briefly at how the namespace facility interacts
+with other important @command{gawk} features.
+
+@cindex namespaces, interaction with profiler
+@cindex namespaces, interaction with pretty printer
+@cindex profiler, interaction with namespaces
+@cindex 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
+@ref{Naming 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.
+
+@cindex namespaces, interaction with debugger
+@cindex 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.
+
+@cindex namespaces, interaction with extension API
+@cindex 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}).
+@xref{Extension Sample Inplace}, for a nice example of an extension that
+leverages a namespace shared by cooperating @command{awk} and C code.
+
+@node Namespace Summary
+@section Summary
+
+@itemize @value{BULLET}
+@item
+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.
+
+@item
+@command{gawk} 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.
+
+@item
+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.
+
+@item
+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}).
+
+@cindex namespaces, backwards compatibility
+@item
+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}.
+@end 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}.
-@c FIXME: Make this is a float at some point.
+@float Table,table-api-std-headers
+@caption{Standard header files needed by API}
@multitable {@code{memset()}, @code{memcpy()}} {@code{<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
+@end 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}).
+@item awk_bool_t sym_lookup_ns(const char *name,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const char *name_space,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ awk_valtype_t wanted,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ 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
+@code{NULL}. 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}).
+
+@item 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
+@code{NULL}. 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
+identifiers.@footnote{Allowing both namespace plus identifier and
+@code{foo::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
+@samp{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 @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") @}}
> @kbd{@{ 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.
-
-@item
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 84618fd6..b562fb56 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
+@ref{Namespaces}, describes how @command{gawk} allows variables and/or
+functions of the same name to be in different namespaces.
+
+@item
@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 @var{var}=@var{val}
@itemx --assign @var{var}=@var{val}
@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
+@samp{@@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
-@c FIXME: Include this?
-@ignore
-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.
-@end 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
+@ref{Namespaces}
+
+@item
@ref{Advanced Features}
@item
@@ -30696,6 +30730,447 @@ program being debugged, but occasionally it can.
@end itemize
+@hyphenation{name-space name-spaces Name-space Name-spaces}
+@node Namespaces
+@chapter Namespaces in @command{gawk}
+
+This @value{CHAPTER} describes a feature that is specific to @command{gawk}.
+
+@menu
+* 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.
+@end menu
+
+@node Global Namespace
+@section Standard @command{awk}'s Single Namespace
+
+@cindex namespace, definition of
+@cindex 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}).
+
+@cindex package, definition of
+@cindex 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.
+
+@node Qualified Names
+@section Qualified Names
+
+@cindex qualified name, definition of
+@cindex namespaces, qualified names
+@cindex @code{::}, namespace separator
+@cindex 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.
+
+@quotation NOTE
+Unlike C++, the @code{::} is @emph{not} an operator. No spaces are
+allowed between the namespace name, the @code{::}, and the component name.
+@end quotation
+
+@cindex 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}).
+
+@node Default Namespace
+@section The Default Namespace
+
+@cindex namespace, default
+@cindex namespace, @code{awk}
+@cindex @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
+@code{awk::ARGC}, @code{awk::NF}, and so on.
+
+@cindex 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.
+
+@node Changing The Namespace
+@section Changing The Namespace
+
+@cindex namespaces, changing
+@cindex @code{@@namespace} directive
+In order to set the current namespace, use an @code{@@namespace} directive
+at the top level of your program:
+
+@example
+@@namespace "passwd"
+
+BEGIN @{ @dots{} @}
+@dots{}
+@end 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.
+
+@quotation NOTE
+Association of unqualified identifiers to a namespace is handled while
+@command{gawk} 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.
+@end quotation
+
+@cindex namespace, implicit
+@cindex 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}).
+
+@cindex current namespace, pushing and popping
+@cindex 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.
+
+@cindex @code{@@namespace}, no effect on @code{BEGIN} @code{BEGINFILE}, @code{END}, and @code{ENDFILE}
+@cindex @code{BEGIN}, execution order not affected by @code{@@namespace}
+@cindex @code{BEGINFILE}, execution order not affected by @code{@@namespace}
+@cindex @code{END}, execution order not affected by @code{@@namespace}
+@cindex @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.
+
+@node Naming Rules
+@section Namespace and Component Naming Rules
+
+@cindex naming rules, namespaces and component names
+@cindex namespace names, naming rules
+@cindex component names, naming rules
+A number of rules apply to the namespace and component names, as follows.
+
+@itemize @bullet
+@item
+It is a syntax error to use qualified names for function parameter names.
+
+@item
+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:
+
+@example
+@@namespace "example"
+
+function gsub(str, pat, result) @{ @dots{} @}
+@end example
+
+@item
+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.
+
+@item
+The additional @command{gawk} built-in functions may still be called
+from outside the @code{awk} namespace by qualifying them. For example,
+@code{awk::systime()}. Here is a somewhat silly example demonstrating
+this rule and the previous one:
+
+@example
+BEGIN @{
+ print "in awk namespace, systime() =", systime()
+@}
+
+@@namespace "testing"
+
+function systime()
+@{
+ print "in testing namespace, systime() =", awk::systime()
+@}
+
+BEGIN @{
+ systime()
+@}
+@end example
+
+@noindent
+
+When run, it produces output like this:
+
+@example
+$ @kbd{gawk -f systime.awk}
+@print{} in awk namespace, systime() = 1500488503
+@print{} in testing namespace, systime() = 1500488503
+@end example
+
+@item
+@command{gawk} pre-defined variable names may be used:
+@code{NF::NR} is valid, if possibly not all that useful.
+@end itemize
+
+@node Internal Name Management
+@section Internal Name Management
+
+@cindex name management
+@cindex @code{awk} namespace, identifier name storage
+@cindex @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:
+
+@example
+@@namespace "awk" @ii{This is the default namespace}
+
+BEGIN @{
+ Title = "My Report" @ii{Qualified name is} awk::Title
+@}
+
+@@namespace "report" @ii{Now in} report @ii{namespace}
+
+function compute() @ii{This is really} report::compute()
+@{
+ print awk::Title @ii{But would be} SYMTAB["Title"]
+ @dots{}
+@}
+@end example
+
+@node Namespace Example
+@section Namespace Example
+
+@cindex 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
+@code{passwd} namespace, whereas the main interface functions are
+defined in the @code{awk} namespace.
+
+@example
+@c file eg/lib/ns_passwd.awk
+# ns_passwd.awk --- access password file information
+@c endfile
+@ignore
+@c 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
+@c endfile
+@end ignore
+@c file eg/lib/ns_passwd.awk
+
+@@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
+@}
+@c endfile
+@end example
+
+As you can see, this version also follows the convention mentioned in
+@ref{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 @code{awk} namespace:
+
+@example
+BEGIN @{
+ while ((p = getpwent()) != "")
+ print p
+@}
+@end example
+
+@noindent
+
+Here's what happens when it's run:
+
+@example
+$ @kbd{gawk -f ns_passwd.awk -f testpasswd.awk}
+@print{} root:x:0:0:root:/root:/bin/bash
+@print{} daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
+@print{} bin:x:2:2:bin:/bin:/usr/sbin/nologin
+@print{} sys:x:3:3:sys:/dev:/usr/sbin/nologin
+@dots{}
+@end example
+
+@node Namespace And Features
+@section Namespaces and Other @command{gawk} Features
+
+This @value{SECTION} looks briefly at how the namespace facility interacts
+with other important @command{gawk} features.
+
+@cindex namespaces, interaction with profiler
+@cindex namespaces, interaction with pretty printer
+@cindex profiler, interaction with namespaces
+@cindex 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
+@ref{Naming 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.
+
+@cindex namespaces, interaction with debugger
+@cindex 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.
+
+@cindex namespaces, interaction with extension API
+@cindex 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}).
+@xref{Extension Sample Inplace}, for a nice example of an extension that
+leverages a namespace shared by cooperating @command{awk} and C code.
+
+@node Namespace Summary
+@section Summary
+
+@itemize @value{BULLET}
+@item
+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.
+
+@item
+@command{gawk} 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.
+
+@item
+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.
+
+@item
+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}).
+
+@cindex namespaces, backwards compatibility
+@item
+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}.
+@end 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}.
-@c FIXME: Make this is a float at some point.
+@float Table,table-api-std-headers
+@caption{Standard header files needed by API}
@multitable {@code{memset()}, @code{memcpy()}} {@code{<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
+@end 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}).
+@item awk_bool_t sym_lookup_ns(const char *name,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const char *name_space,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ awk_valtype_t wanted,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ 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
+@code{NULL}. 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}).
+
+@item 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
+@code{NULL}. 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
+identifiers.@footnote{Allowing both namespace plus identifier and
+@code{foo::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
+@samp{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 @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") @}}
> @kbd{@{ 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.
-
-@item
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 f3729905..d87a1b1b 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 34ba174c..1dd0de4e 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 7ed045c5..b72360ff 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 a1ad5efa..35b82970 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -203,6 +203,18 @@
* Makefile.am: Update copyright year.
+2017-07-20 Arnold D. Robbins <arnold@skeeve.com>
+
+ * inplace.c: Move functions into "inplace" namespace and simplify
+ the names. Update all error messages accordingly.
+
+2017-07-13 Arnold D. Robbins <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
* Makfile.am (intdiv_la_LIBADD): Add LIBMPFR for Cygwin.
diff --git a/extension/inplace.c b/extension/inplace.c
index 516edc97..d2a04118 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 6629296a..b911ec93 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 037ca430..3227d55f 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 478c43da..3db8990a 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 1451f683..82329e85 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 45cae61d..03a96f30 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 8611bce8..de66b877 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 _$@.1
@cp "$(srcdir)"/inplace.2.in _$@.2
- @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(srcdir)"/inplace.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
@-$(CMP) "$(srcdir)"/$@.1.ok _$@.1 && rm -f _$@.1
@-$(CMP) "$(srcdir)"/$@.1.bak.ok _$@.1.bak && rm -f _$@.1.bak
@@ -930,8 +933,8 @@ inplace3::
@echo $@
@cp "$(srcdir)"/inplace.1.in _$@.1
@cp "$(srcdir)"/inplace.2.in _$@.2
- @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(srcdir)"/inplace.in >>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
@-$(CMP) "$(srcdir)"/$@.1.ok _$@.1 && rm -f _$@.1
@-$(CMP) "$(srcdir)"/$@.1.bak.ok _$@.1.bak && rm -f _$@.1.bak
@@ -1094,6 +1097,16 @@ sourcesplit:
@AWKPATH="$(srcdir)" $(AWK) --source='BEGIN { a = 5;' --source='print a }' >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+eofsrc1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f "$(srcdir)"/$@a.awk -f "$(srcdir)"/$@b.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && 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)"/$@.ok _$@ && 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 $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-mktime:
- @echo $@
- @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
- @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-
match1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -2772,6 +2780,11 @@ mbstr2:
AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mktime:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
muldimposix:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -2809,6 +2822,31 @@ nonfatal3:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+nsbad:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsindirect1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsindirect2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsprof1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --pretty-print=_$@ >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsprof2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --pretty-print=_$@ >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
patsplit:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -3007,6 +3045,12 @@ symtab10:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --debug < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+timeout:
+ @echo $@
+ @echo Expect $@ to fail with DJGPP and MinGW.
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
typedregex1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -3047,12 +3091,6 @@ typeof5:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-timeout:
- @echo $@
- @echo Expect $@ to fail with DJGPP and MinGW.
- @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
- @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-
double1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/profile.c b/profile.c
index 3041545a..3d954d30 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 `@namespace "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 9f8af3a0..fc598da5 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 7f17f725..812f3faf 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 <arnold@skeeve.com>
+
+ * nsprof2.awk: Add extra @namespace lines for testing.
+ * nsprof2.ok: Adjusted.
+
+2018-12-06 Arnold D. Robbins <arnold@skeeve.com>
+
+ * nsprof2.awk, nsprof2.ok: Updated after code changes.
+
2018-11-28 Arnold D. Robbins <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * Makefile.am (nsbad): New test.
+ * nsbad.awk, nsbad.ok: New files.
+
+2017-07-20 Arnold D. Robbins <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * 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 <arnold@skeeve.com>
+
+ * Makefile.am (nsprof2): New test.
+ * nsprof2.awk, nsprof2.ok: New files.
+
+2017-06-30 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (nsprof1): New test.
+ * nsprof1.awk, nsprof1.ok: New files.
+
2017-06-27 Arnold D. Robbins <arnold@skeeve.com>
* 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 <arnold@skeeve.com>
+
+ * sourceplit.ok: Revise to match changed code.
+
2017-05-24 Andrew J. Schorr <aschorr@telemetry-investments.com>
* fwtest8.ok: Fix field number in error message, thanks to a bug
diff --git a/test/Makefile.am b/test/Makefile.am
index b4f50cec..0ffad9ad 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 _$@.1
@cp "$(srcdir)"/inplace.2.in _$@.2
- @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(srcdir)"/inplace.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
@-$(CMP) "$(srcdir)"/$@.1.ok _$@.1 && rm -f _$@.1
@-$(CMP) "$(srcdir)"/$@.1.bak.ok _$@.1.bak && rm -f _$@.1.bak
@@ -2042,8 +2058,8 @@ inplace3::
@echo $@
@cp "$(srcdir)"/inplace.1.in _$@.1
@cp "$(srcdir)"/inplace.2.in _$@.2
- @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(srcdir)"/inplace.in >>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
@-$(CMP) "$(srcdir)"/$@.1.ok _$@.1 && rm -f _$@.1
@-$(CMP) "$(srcdir)"/$@.1.bak.ok _$@.1.bak && rm -f _$@.1.bak
@@ -2199,6 +2215,17 @@ sourcesplit:
@AWKPATH="$(srcdir)" $(AWK) --source='BEGIN { a = 5;' --source='print a }' >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+eofsrc1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f "$(srcdir)"/$@a.awk -f "$(srcdir)"/$@b.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && 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)"/$@.ok _$@ && 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 b6adabdd..c244c7af 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 _$@.1
@cp "$(srcdir)"/inplace.2.in _$@.2
- @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(srcdir)"/inplace.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
@-$(CMP) "$(srcdir)"/$@.1.ok _$@.1 && rm -f _$@.1
@-$(CMP) "$(srcdir)"/$@.1.bak.ok _$@.1.bak && rm -f _$@.1.bak
@@ -2490,8 +2506,8 @@ inplace3::
@echo $@
@cp "$(srcdir)"/inplace.1.in _$@.1
@cp "$(srcdir)"/inplace.2.in _$@.2
- @AWKPATH="$(srcdir)"/../awklib/eg/lib $(AWK) -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(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"}' _$@.1 - _$@.2 < "$(srcdir)"/inplace.in >>_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
@-$(CMP) "$(srcdir)"/$@.1.ok _$@.1 && rm -f _$@.1
@-$(CMP) "$(srcdir)"/$@.1.bak.ok _$@.1.bak && rm -f _$@.1.bak
@@ -2645,6 +2661,16 @@ sourcesplit:
@AWKPATH="$(srcdir)" $(AWK) --source='BEGIN { a = 5;' --source='print a }' >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+eofsrc1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f "$(srcdir)"/$@a.awk -f "$(srcdir)"/$@b.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && 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)"/$@.ok _$@ && 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 $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-mktime:
- @echo $@
- @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
- @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-
match1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -4317,6 +4338,11 @@ mbstr2:
AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mktime:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
muldimposix:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -4352,6 +4378,31 @@ nonfatal3:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+nsbad:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsindirect1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsindirect2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsprof1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --pretty-print=_$@ >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsprof2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --pretty-print=_$@ >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
patsplit:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -4554,6 +4605,11 @@ symtab10:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --debug < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+timeout:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
typedregex1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -4594,11 +4650,6 @@ typeof5:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-timeout:
- @echo $@
- @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
- @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-
double1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index 9ad8ade9..7163b4ab 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1606,11 +1606,6 @@ lintwarn:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-mktime:
- @echo $@
- @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
- @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-
match1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1638,6 +1633,11 @@ mbstr2:
AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mktime:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
muldimposix:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1673,6 +1673,31 @@ nonfatal3:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+nsbad:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsindirect1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsindirect2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsprof1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --pretty-print=_$@ >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nsprof2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --pretty-print=_$@ >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
patsplit:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1875,6 +1900,11 @@ symtab10:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk --debug < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+timeout:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
typedregex1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@@ -1915,11 +1945,6 @@ typeof5:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-timeout:
- @echo $@
- @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
- @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
-
double1:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/eofsrc1.ok b/test/eofsrc1.ok
new file mode 100644
index 00000000..64d85b33
--- /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 00000000..55143c2b
--- /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 00000000..0dad2163
--- /dev/null
+++ b/test/eofsrc1b.awk
@@ -0,0 +1,2 @@
+ print n
+}
diff --git a/test/inplace1.ok b/test/inplace1.ok
index 730d7754..753079b3 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 730d7754..753079b3 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 815cd1c7..7802a0c8 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 00000000..825bb35c
--- /dev/null
+++ b/test/nsbad.awk
@@ -0,0 +1,15 @@
+@namespace "1foo"
+@namespace "for"
+@namespace "42f"
+@namespace "ab#d"
+
+BEGIN {
+ foo75::bar = 57
+ if::junk = 1
+ foo::match = 3
+}
+
+@namespace "foo"
+function gsub () {
+ print "foo::gsub"
+}
diff --git a/test/nsbad.ok b/test/nsbad.ok
new file mode 100644
index 00000000..dfa228a7
--- /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 00000000..cbca6ea0
--- /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 00000000..d04863f5
--- /dev/null
+++ b/test/nsindirect1.awk
@@ -0,0 +1,13 @@
+@namespace "test"
+
+BEGIN {
+ bar = 3
+}
+
+@namespace "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 00000000..ab2e31ba
--- /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 00000000..8017e8f7
--- /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
+
+@namespace "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 00000000..9b71cd92
--- /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 00000000..46be5bc9
--- /dev/null
+++ b/test/nsprof1.awk
@@ -0,0 +1,16 @@
+@namespace "foo"
+
+BEGIN {
+ a = 5
+ a++
+ print a
+}
+
+/foo/ { print "bar" }
+
+@namespace "stuff"
+
+function stuff()
+{
+ print "stuff"
+}
diff --git a/test/nsprof1.ok b/test/nsprof1.ok
new file mode 100644
index 00000000..eacc2707
--- /dev/null
+++ b/test/nsprof1.ok
@@ -0,0 +1,19 @@
+@namespace "foo"
+
+BEGIN {
+ a = 5
+ a++
+ print a
+}
+
+/foo/ {
+ print "bar"
+}
+
+@namespace "stuff"
+
+
+function stuff()
+{
+ print "stuff"
+}
diff --git a/test/nsprof2.awk b/test/nsprof2.awk
new file mode 100644
index 00000000..9c7da57e
--- /dev/null
+++ b/test/nsprof2.awk
@@ -0,0 +1,74 @@
+# passwd.awk --- access password file information
+#
+# Arnold Robbins, arnold@skeeve.com, Public Domain
+# May 1993
+# Revised October 2000
+# Revised December 2010
+# Revised July 2017
+
+@namespace "foo" # this is foo
+
+@namespace "bar" # this is bar
+
+@namespace "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 00000000..1bb78822
--- /dev/null
+++ b/test/nsprof2.ok
@@ -0,0 +1,75 @@
+# passwd.awk --- access password file information
+#
+# Arnold Robbins, arnold@skeeve.com, Public Domain
+# May 1993
+# Revised October 2000
+# Revised December 2010
+# Revised July 2017
+@namespace "foo" # this is foo
+
+@namespace "bar" # this is bar
+
+@namespace "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 7ed6ff82..c883f51c 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 897a7336..fbc3c263 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 760d3703..399f626a 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