summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog61
-rw-r--r--TODO5
-rw-r--r--awk.h4
-rw-r--r--builtin.c37
-rw-r--r--doc/ChangeLog16
-rw-r--r--doc/gawk.info1193
-rw-r--r--doc/gawk.texi83
-rw-r--r--doc/gawktexi.in83
-rw-r--r--io.c142
-rw-r--r--missing_d/ChangeLog6
-rw-r--r--missing_d/getaddrinfo.c16
-rw-r--r--missing_d/getaddrinfo.h2
-rw-r--r--test/ChangeLog31
-rw-r--r--test/Makefile.am7
-rw-r--r--test/Makefile.in22
-rw-r--r--test/Maketests15
-rw-r--r--test/nonfatal1.awk6
-rw-r--r--test/nonfatal1.ok2
-rw-r--r--test/nonfatal2.awk5
-rw-r--r--test/nonfatal2.ok1
-rw-r--r--test/nonfatal3.awk6
-rw-r--r--test/nonfatal3.ok1
22 files changed, 1132 insertions, 612 deletions
diff --git a/ChangeLog b/ChangeLog
index 98431620..cc15ccbf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2015-03-08 Arnold D. Robbins <arnold@skeeve.com>
+
+ * io.c (devopen): Change the logic such that if nonfatal is true
+ for the socket, don't do retries. Also clean up the formatting
+ some. At strictopen, check if errno is ENOENT and if so, propagate
+ the error from getaddrinfo() up to the caller. Add explanatory
+ comments.
+
+2015-02-28 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * io.c (pty_vs_pipe): Remove check for NULL PROCINFO_node, since
+ this is now checked inside in_PROCINFO.
+
+2015-02-27 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * io.c (socketopen): New parameter hard_error; set it if
+ getaddrinfo() fails. Change fatals to warnings.
+ (devopen): Pass in address of boolean hard_error variable
+ and stop trying to open the file if hard_error is true.
+ Save and restore errno around call to socketopen() and
+ use restored errno if open() fails at strictopen.
+
2015-02-27 Arnold D. Robbins <arnold@skeeve.com>
* symbol.c (check_param_names): Fix argument order in memset() call.
@@ -33,6 +55,29 @@
* profile.c (pprint): Restore printing of count for rules.
Bug report by Hermann Peifer.
+2015-02-08 Arnold D. Robbins <arnold@skeeve.com>
+
+ * io.c: Make it "NONFATAL" everywhere.
+
+2015-02-08 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * awk.h (RED_NON_FATAL): Removed.
+ (redirect): Add new failure_fatal parameter.
+ (is_non_fatal_redirect): Add declaration.
+ * builtin.c (efwrite): Rework check for non-fatal.
+ (do_printf): Adjust calls to redirect.
+ (do_print_rec): Ditto. Move check for redirection error up.
+ * io.c (redflags2str): Remove RED_NON_FATAL.
+ (redirect): Add new failure_fatal parameter. Simplify the code.
+ (is_non_fatal_redirect): New function.
+ (do_getline_redir): Adjust calls to redirect.
+
+2014-12-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awk.h (is_non_fatal_std): Declare new function.
+ * io.c (is_non_fatal_std): New function.
+ * builtin.c (efwrite): Call it.
+
2015-02-07 Arnold D. Robbins <arnold@skeeve.com>
* regcomp.c, regex.c, regex.h, regex_internal.c, regex_internal.h,
@@ -140,6 +185,22 @@
* profile.c (pprint): Be sure to set ip2 in all paths
through the code. Thanks to GCC 4.9 for the warning.
+2014-12-20 Arnold D. Robbins <arnold@skeeve.com>
+
+ Enable non-fatal output on per-file or global basis,
+ via PROCINFO.
+
+ * awk.h (RED_NON_FATAL): New redirection flag.
+ * builtin.c (efwrite): If RED_NON_FATAL set, just set ERRNO and return.
+ (do_printf): Check errflg and if set, set ERRNO and return.
+ (do_print): Ditto.
+ (do_print_rec): Ditto.
+ * io.c (redflags2str): Update table.
+ (redirect): Check for global PROCINFO["nonfatal"] or for
+ PROCINFO[file, "nonfatal"] and don't fail on open if set.
+ Add RED_NON_FATAL to flags.
+ (in_PROCINFO): Make smarter and more general.
+
2014-12-12 Stephen Davies <sdavies@sdc.com.au>
Improve comment handling in pretty printing.
diff --git a/TODO b/TODO
index 3670f126..65aa0f15 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-Sun Sep 28 22:19:10 IDT 2014
+Wed Dec 24 20:41:38 IST 2014
============================
There were too many files tracking different thoughts and ideas for
@@ -44,9 +44,6 @@ Minor New Features
Consider relaxing the strictness of --posix.
- Make it possible to put print/printf + redirections into
- an expression.
-
? Add an optional base to strtonum, allowing 2-36.
? Optional third argument for index indicating where to start the
diff --git a/awk.h b/awk.h
index 799295b5..7a44c1d0 100644
--- a/awk.h
+++ b/awk.h
@@ -1482,7 +1482,7 @@ extern void register_two_way_processor(awk_two_way_processor_t *processor);
extern void set_FNR(void);
extern void set_NR(void);
-extern struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg);
+extern struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal);
extern NODE *do_close(int nargs);
extern int flush_io(void);
extern int close_io(bool *stdio_problem);
@@ -1494,6 +1494,8 @@ extern NODE *do_getline(int intovar, IOBUF *iop);
extern struct redirect *getredirect(const char *str, int len);
extern bool inrec(IOBUF *iop, int *errcode);
extern int nextfile(IOBUF **curfile, bool skipping);
+extern bool is_non_fatal_std(FILE *fp);
+extern bool is_non_fatal_redirect(const char *str);
/* main.c */
extern int arg_assign(char *arg, bool initing);
extern int is_std_var(const char *var);
diff --git a/builtin.c b/builtin.c
index 38a974fc..37f5ffc7 100644
--- a/builtin.c
+++ b/builtin.c
@@ -129,10 +129,14 @@ wrerror:
if (fp == stdout && errno == EPIPE)
gawk_exit(EXIT_FATAL);
+
/* otherwise die verbosely */
- fatal(_("%s to \"%s\" failed (%s)"), from,
- rp ? rp->value : _("standard output"),
- errno ? strerror(errno) : _("reason unknown"));
+ if ((rp != NULL) ? is_non_fatal_redirect(rp->value) : is_non_fatal_std(fp))
+ update_ERRNO_int(errno);
+ else
+ fatal(_("%s to \"%s\" failed (%s)"), from,
+ rp ? rp->value : _("standard output"),
+ errno ? strerror(errno) : _("reason unknown"));
}
/* do_exp --- exponential function */
@@ -1639,7 +1643,7 @@ do_printf(int nargs, int redirtype)
FILE *fp = NULL;
NODE *tmp;
struct redirect *rp = NULL;
- int errflg; /* not used, sigh */
+ int errflg = 0;
NODE *redir_exp = NULL;
if (nargs == 0) {
@@ -1650,7 +1654,7 @@ do_printf(int nargs, int redirtype)
redir_exp = TOP();
if (redir_exp->type != Node_val)
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp));
- rp = redirect(redir_exp, redirtype, & errflg);
+ rp = redirect(redir_exp, redirtype, & errflg, true);
DEREF(redir_exp);
decr_sp();
}
@@ -1663,9 +1667,13 @@ do_printf(int nargs, int redirtype)
redir_exp = PEEK(nargs);
if (redir_exp->type != Node_val)
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp));
- rp = redirect(redir_exp, redirtype, & errflg);
+ rp = redirect(redir_exp, redirtype, & errflg, true);
if (rp != NULL)
fp = rp->output.fp;
+ else if (errflg) {
+ update_ERRNO_int(errflg);
+ return;
+ }
} else if (do_debug) /* only the debugger can change the default output */
fp = output_fp;
else
@@ -2078,7 +2086,7 @@ void
do_print(int nargs, int redirtype)
{
struct redirect *rp = NULL;
- int errflg; /* not used, sigh */
+ int errflg = 0;
FILE *fp = NULL;
int i;
NODE *redir_exp = NULL;
@@ -2090,9 +2098,13 @@ do_print(int nargs, int redirtype)
redir_exp = PEEK(nargs);
if (redir_exp->type != Node_val)
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp));
- rp = redirect(redir_exp, redirtype, & errflg);
+ rp = redirect(redir_exp, redirtype, & errflg, true);
if (rp != NULL)
fp = rp->output.fp;
+ else if (errflg) {
+ update_ERRNO_int(errflg);
+ return;
+ }
} else if (do_debug) /* only the debugger can change the default output */
fp = output_fp;
else
@@ -2148,13 +2160,13 @@ do_print_rec(int nargs, int redirtype)
FILE *fp = NULL;
NODE *f0;
struct redirect *rp = NULL;
- int errflg; /* not used, sigh */
+ int errflg = 0;
NODE *redir_exp = NULL;
assert(nargs == 0);
if (redirtype != 0) {
redir_exp = TOP();
- rp = redirect(redir_exp, redirtype, & errflg);
+ rp = redirect(redir_exp, redirtype, & errflg, true);
if (rp != NULL)
fp = rp->output.fp;
DEREF(redir_exp);
@@ -2162,6 +2174,11 @@ do_print_rec(int nargs, int redirtype)
} else
fp = output_fp;
+ if (errflg) {
+ update_ERRNO_int(errflg);
+ return;
+ }
+
if (fp == NULL)
return;
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 6ed6b7bc..b58699a4 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-08 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in: Briefly describe that nonfatal I/O overrides
+ GAWK_SOCK_RETRIES, in the env var part and in the nonfatal I/O
+ part.
+
2015-03-01 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in: Change quotes to @dfn for pseudorandom.
@@ -54,6 +60,7 @@
2015-02-08 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in: O'Reilly fixes.
+ Make non-fatal i/o use "NONFATAL".
2015-02-06 Arnold D. Robbins <arnold@skeeve.com>
@@ -114,12 +121,21 @@
* gawkinet.texi: Fix capitalization in document title.
* gawktexi.in: Here we go again: Starting on more O'Reilly fixes.
+2014-12-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in: Add info that nonfatal I/O works with stdout and
+ stderr. Revise version info and what was added when.
+
2014-12-26 Antonio Giovanni Colombo <azc100@gmail.com>
* gawktexi.in (Glossary): Really sort the items.
2014-12-24 Arnold D. Robbins <arnold@skeeve.com>
+ * gawktexi.in: Start documenting nonfatal output.
+
+2014-12-24 Arnold D. Robbins <arnold@skeeve.com>
+
* gawktexi.in: Add one more paragraph to new foreword.
* gawktexi.in: Fix exponentiation in TeX mode. Thanks to
Marco Curreli by way of Antonio Giovanni Colombo.
diff --git a/doc/gawk.info b/doc/gawk.info
index 82641494..7e548a8e 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -246,6 +246,7 @@ entitled "GNU Free Documentation License".
* Special Caveats:: Things to watch out for.
* Close Files And Pipes:: Closing Input and Output Files and
Pipes.
+* Nonfatal:: Enabling Nonfatal Output.
* Output Summary:: Output summary.
* Output Exercises:: Exercises.
* Values:: Constants, Variables, and Regular
@@ -3013,7 +3014,8 @@ used by regular users:
`GAWK_SOCK_RETRIES'
Controls the number of times `gawk' attempts to retry a two-way
TCP/IP (socket) connection before giving up. *Note TCP/IP
- Networking::.
+ Networking::. Note that when nonfatal I/O is enabled (*note
+ Nonfatal::), `gawk' only tries to open a TCP/IP socket once.
`POSIXLY_CORRECT'
Causes `gawk' to switch to POSIX-compatibility mode, disabling all
@@ -6128,6 +6130,7 @@ function.
`gawk' allows access to inherited file
descriptors.
* Close Files And Pipes:: Closing Input and Output Files and Pipes.
+* Nonfatal:: Enabling Nonfatal Output.
* Output Summary:: Output summary.
* Output Exercises:: Exercises.
@@ -7041,7 +7044,7 @@ that `gawk' provides:
behavior.

-File: gawk.info, Node: Close Files And Pipes, Next: Output Summary, Prev: Special Files, Up: Printing
+File: gawk.info, Node: Close Files And Pipes, Next: Nonfatal, Prev: Special Files, Up: Printing
5.9 Closing Input and Output Redirections
=========================================
@@ -7210,9 +7213,68 @@ call. See the system manual pages for information on how to decode this
value.

-File: gawk.info, Node: Output Summary, Next: Output Exercises, Prev: Close Files And Pipes, Up: Printing
+File: gawk.info, Node: Nonfatal, Next: Output Summary, Prev: Close Files And Pipes, Up: Printing
-5.10 Summary
+5.10 Enabling Nonfatal Output
+=============================
+
+This minor node describes a `gawk'-specific feature.
+
+ In standard `awk', output with `print' or `printf' to a nonexistent
+file, or some other I/O error (such as filling up the disk) is a fatal
+error.
+
+ $ gawk 'BEGIN { print "hi" > "/no/such/file" }'
+ error--> gawk: cmd. line:1: fatal: can't redirect to `/no/such/file' (No such file or directory)
+
+ `gawk' makes it possible to detect that an error has occurred,
+allowing you to possibly recover from the error, or at least print an
+error message of your choosing before exiting. You can do this in one
+of two ways:
+
+ * For all output files, by assigning any value to
+ `PROCINFO["NONFATAL"]'.
+
+ * On a per-file basis, by assigning any value to `PROCINFO[FILENAME,
+ "NONFATAL"]'. Here, FILENAME is the name of the file to which you
+ wish output to be nonfatal.
+
+ Once you have enabled nonfatal output, you must check `ERRNO' after
+every relevant `print' or `printf' statement to see if something went
+wrong. It is also a good idea to initialize `ERRNO' to zero before
+attempting the output. For example:
+
+ $ gawk '
+ > BEGIN {
+ > PROCINFO["NONFATAL"] = 1
+ > ERRNO = 0
+ > print "hi" > "/no/such/file"
+ > if (ERRNO) {
+ > print("Output failed:", ERRNO) > "/dev/stderr"
+ > exit 1
+ > }
+ > }'
+ error--> Output failed: No such file or directory
+
+ Here, `gawk' did not produce a fatal error; instead it let the `awk'
+program code detect the problem and handle it.
+
+ This mechanism works also for standard output and standard error.
+For standard output, you may use `PROCINFO["-", "NONFATAL"]' or
+`PROCINFO["/dev/stdout", "NONFATAL"]'. For standard error, use
+`PROCINFO["/dev/stderr", "NONFATAL"]'.
+
+ When attempting to open a TCP/IP socket (*note TCP/IP Networking::),
+`gawk' tries multiple times. The `GAWK_SOCK_RETRIES' environment
+variable (*note Other Environment Variables::) allows you to override
+`gawk''s builtin default number of attempts. However, once nonfatal
+I/O is enabled for a given socket, `gawk' only retries once, relying on
+`awk'-level code to notice that there was a problem.
+
+
+File: gawk.info, Node: Output Summary, Next: Output Exercises, Prev: Nonfatal, Up: Printing
+
+5.11 Summary
============
* The `print' statement prints comma-separated expressions. Each
@@ -7234,11 +7296,16 @@ File: gawk.info, Node: Output Summary, Next: Output Exercises, Prev: Close Fi
For coprocesses, it is possible to close only one direction of the
communications.
+ * Normally errors with `print' or `printf' are fatal. `gawk' lets
+ you make output errors be nonfatal either for all files or on a
+ per-file basis. You must then check for errors after every
+ relevant output statement.
+

File: gawk.info, Node: Output Exercises, Prev: Output Summary, Up: Printing
-5.11 Exercises
+5.12 Exercises
==============
1. Rewrite the program:
@@ -26479,6 +26546,9 @@ the current version of `gawk'.
- Directories on the command line produce a warning and are
skipped (*note Command-line directories::)
+ - Output with `print' and `printf' need not be fatal (*note
+ Nonfatal::)
+
* New keywords:
- The `BEGINFILE' and `ENDFILE' special patterns (*note
@@ -26994,6 +27064,8 @@ in POSIX `awk', in the order they were added to `gawk'.
* The maximum number of hexdecimal digits in `\x' escapes is now two.
*Note Escape Sequences::.
+ * Nonfatal output with `print' and `printf'. *Note Nonfatal::.
+
* Support for MirBSD was removed.

@@ -34667,560 +34739,561 @@ Index

Tag Table:
Node: Top1204
-Node: Foreword342225
-Node: Foreword446669
-Node: Preface48200
-Ref: Preface-Footnote-151071
-Ref: Preface-Footnote-251178
-Ref: Preface-Footnote-351411
-Node: History51553
-Node: Names53904
-Ref: Names-Footnote-154998
-Node: This Manual55144
-Ref: This Manual-Footnote-161644
-Node: Conventions61744
-Node: Manual History64081
-Ref: Manual History-Footnote-167074
-Ref: Manual History-Footnote-267115
-Node: How To Contribute67189
-Node: Acknowledgments68318
-Node: Getting Started73184
-Node: Running gawk75623
-Node: One-shot76813
-Node: Read Terminal78077
-Node: Long80108
-Node: Executable Scripts81621
-Ref: Executable Scripts-Footnote-184410
-Node: Comments84513
-Node: Quoting86995
-Node: DOS Quoting92513
-Node: Sample Data Files93188
-Node: Very Simple95783
-Node: Two Rules100682
-Node: More Complex102568
-Node: Statements/Lines105430
-Ref: Statements/Lines-Footnote-1109885
-Node: Other Features110150
-Node: When111086
-Ref: When-Footnote-1112840
-Node: Intro Summary112905
-Node: Invoking Gawk113789
-Node: Command Line115303
-Node: Options116101
-Ref: Options-Footnote-1131896
-Ref: Options-Footnote-2132125
-Node: Other Arguments132150
-Node: Naming Standard Input135098
-Node: Environment Variables136191
-Node: AWKPATH Variable136749
-Ref: AWKPATH Variable-Footnote-1140156
-Ref: AWKPATH Variable-Footnote-2140201
-Node: AWKLIBPATH Variable140461
-Node: Other Environment Variables141717
-Node: Exit Status145235
-Node: Include Files145911
-Node: Loading Shared Libraries149500
-Node: Obsolete150927
-Node: Undocumented151619
-Node: Invoking Summary151886
-Node: Regexp153549
-Node: Regexp Usage155003
-Node: Escape Sequences157040
-Node: Regexp Operators163269
-Ref: Regexp Operators-Footnote-1170679
-Ref: Regexp Operators-Footnote-2170826
-Node: Bracket Expressions170924
-Ref: table-char-classes172939
-Node: Leftmost Longest175881
-Node: Computed Regexps177183
-Node: GNU Regexp Operators180612
-Node: Case-sensitivity184284
-Ref: Case-sensitivity-Footnote-1187169
-Ref: Case-sensitivity-Footnote-2187404
-Node: Regexp Summary187512
-Node: Reading Files188979
-Node: Records191072
-Node: awk split records191805
-Node: gawk split records196734
-Ref: gawk split records-Footnote-1201273
-Node: Fields201310
-Ref: Fields-Footnote-1204088
-Node: Nonconstant Fields204174
-Ref: Nonconstant Fields-Footnote-1206412
-Node: Changing Fields206615
-Node: Field Separators212546
-Node: Default Field Splitting215250
-Node: Regexp Field Splitting216367
-Node: Single Character Fields219717
-Node: Command Line Field Separator220776
-Node: Full Line Fields223993
-Ref: Full Line Fields-Footnote-1225514
-Ref: Full Line Fields-Footnote-2225560
-Node: Field Splitting Summary225661
-Node: Constant Size227735
-Node: Splitting By Content232318
-Ref: Splitting By Content-Footnote-1236283
-Node: Multiple Line236446
-Ref: Multiple Line-Footnote-1242327
-Node: Getline242506
-Node: Plain Getline244713
-Node: Getline/Variable247353
-Node: Getline/File248502
-Node: Getline/Variable/File249887
-Ref: Getline/Variable/File-Footnote-1251490
-Node: Getline/Pipe251577
-Node: Getline/Variable/Pipe254255
-Node: Getline/Coprocess255386
-Node: Getline/Variable/Coprocess256650
-Node: Getline Notes257389
-Node: Getline Summary260183
-Ref: table-getline-variants260595
-Node: Read Timeout261424
-Ref: Read Timeout-Footnote-1265261
-Node: Command-line directories265319
-Node: Input Summary266224
-Node: Input Exercises269609
-Node: Printing270337
-Node: Print272114
-Node: Print Examples273571
-Node: Output Separators276350
-Node: OFMT278368
-Node: Printf279723
-Node: Basic Printf280508
-Node: Control Letters282080
-Node: Format Modifiers286065
-Node: Printf Examples292071
-Node: Redirection294557
-Node: Special FD301395
-Ref: Special FD-Footnote-1304561
-Node: Special Files304635
-Node: Other Inherited Files305252
-Node: Special Network306252
-Node: Special Caveats307114
-Node: Close Files And Pipes308063
-Ref: Close Files And Pipes-Footnote-1315254
-Ref: Close Files And Pipes-Footnote-2315402
-Node: Output Summary315552
-Node: Output Exercises316550
-Node: Expressions317230
-Node: Values318419
-Node: Constants319096
-Node: Scalar Constants319787
-Ref: Scalar Constants-Footnote-1320649
-Node: Nondecimal-numbers320899
-Node: Regexp Constants323909
-Node: Using Constant Regexps324435
-Node: Variables327598
-Node: Using Variables328255
-Node: Assignment Options330166
-Node: Conversion332041
-Node: Strings And Numbers332565
-Ref: Strings And Numbers-Footnote-1335630
-Node: Locale influences conversions335739
-Ref: table-locale-affects338485
-Node: All Operators339077
-Node: Arithmetic Ops339706
-Node: Concatenation342211
-Ref: Concatenation-Footnote-1345030
-Node: Assignment Ops345137
-Ref: table-assign-ops350116
-Node: Increment Ops351426
-Node: Truth Values and Conditions354857
-Node: Truth Values355940
-Node: Typing and Comparison356989
-Node: Variable Typing357805
-Node: Comparison Operators361472
-Ref: table-relational-ops361882
-Node: POSIX String Comparison365377
-Ref: POSIX String Comparison-Footnote-1366449
-Node: Boolean Ops366588
-Ref: Boolean Ops-Footnote-1371066
-Node: Conditional Exp371157
-Node: Function Calls372895
-Node: Precedence376775
-Node: Locales380435
-Node: Expressions Summary382067
-Node: Patterns and Actions384638
-Node: Pattern Overview385758
-Node: Regexp Patterns387437
-Node: Expression Patterns387980
-Node: Ranges391760
-Node: BEGIN/END394867
-Node: Using BEGIN/END395628
-Ref: Using BEGIN/END-Footnote-1398364
-Node: I/O And BEGIN/END398470
-Node: BEGINFILE/ENDFILE400785
-Node: Empty403682
-Node: Using Shell Variables403999
-Node: Action Overview406272
-Node: Statements408598
-Node: If Statement410446
-Node: While Statement411941
-Node: Do Statement413969
-Node: For Statement415117
-Node: Switch Statement418275
-Node: Break Statement420657
-Node: Continue Statement422750
-Node: Next Statement424577
-Node: Nextfile Statement426958
-Node: Exit Statement429586
-Node: Built-in Variables431997
-Node: User-modified433130
-Ref: User-modified-Footnote-1440764
-Node: Auto-set440826
-Ref: Auto-set-Footnote-1454535
-Ref: Auto-set-Footnote-2454740
-Node: ARGC and ARGV454796
-Node: Pattern Action Summary459014
-Node: Arrays461447
-Node: Array Basics462776
-Node: Array Intro463620
-Ref: figure-array-elements465554
-Ref: Array Intro-Footnote-1468174
-Node: Reference to Elements468302
-Node: Assigning Elements470764
-Node: Array Example471255
-Node: Scanning an Array473014
-Node: Controlling Scanning476034
-Ref: Controlling Scanning-Footnote-1481428
-Node: Numeric Array Subscripts481744
-Node: Uninitialized Subscripts483929
-Node: Delete485546
-Ref: Delete-Footnote-1488295
-Node: Multidimensional488352
-Node: Multiscanning491449
-Node: Arrays of Arrays493038
-Node: Arrays Summary497792
-Node: Functions499883
-Node: Built-in500922
-Node: Calling Built-in502000
-Node: Numeric Functions503995
-Ref: Numeric Functions-Footnote-1508813
-Ref: Numeric Functions-Footnote-2509170
-Ref: Numeric Functions-Footnote-3509218
-Node: String Functions509490
-Ref: String Functions-Footnote-1532991
-Ref: String Functions-Footnote-2533120
-Ref: String Functions-Footnote-3533368
-Node: Gory Details533455
-Ref: table-sub-escapes535236
-Ref: table-sub-proposed536751
-Ref: table-posix-sub538113
-Ref: table-gensub-escapes539650
-Ref: Gory Details-Footnote-1540483
-Node: I/O Functions540634
-Ref: I/O Functions-Footnote-1547870
-Node: Time Functions548017
-Ref: Time Functions-Footnote-1558526
-Ref: Time Functions-Footnote-2558594
-Ref: Time Functions-Footnote-3558752
-Ref: Time Functions-Footnote-4558863
-Ref: Time Functions-Footnote-5558975
-Ref: Time Functions-Footnote-6559202
-Node: Bitwise Functions559468
-Ref: table-bitwise-ops560030
-Ref: Bitwise Functions-Footnote-1564358
-Node: Type Functions564530
-Node: I18N Functions565682
-Node: User-defined567329
-Node: Definition Syntax568134
-Ref: Definition Syntax-Footnote-1573793
-Node: Function Example573864
-Ref: Function Example-Footnote-1576785
-Node: Function Caveats576807
-Node: Calling A Function577325
-Node: Variable Scope578283
-Node: Pass By Value/Reference581276
-Node: Return Statement584773
-Node: Dynamic Typing587752
-Node: Indirect Calls588681
-Ref: Indirect Calls-Footnote-1598546
-Node: Functions Summary598674
-Node: Library Functions601376
-Ref: Library Functions-Footnote-1604984
-Ref: Library Functions-Footnote-2605127
-Node: Library Names605298
-Ref: Library Names-Footnote-1608756
-Ref: Library Names-Footnote-2608979
-Node: General Functions609065
-Node: Strtonum Function610168
-Node: Assert Function613190
-Node: Round Function616514
-Node: Cliff Random Function618055
-Node: Ordinal Functions619071
-Ref: Ordinal Functions-Footnote-1622134
-Ref: Ordinal Functions-Footnote-2622386
-Node: Join Function622597
-Ref: Join Function-Footnote-1624367
-Node: Getlocaltime Function624567
-Node: Readfile Function628311
-Node: Shell Quoting630283
-Node: Data File Management631684
-Node: Filetrans Function632316
-Node: Rewind Function636412
-Node: File Checking637798
-Ref: File Checking-Footnote-1639131
-Node: Empty Files639332
-Node: Ignoring Assigns641311
-Node: Getopt Function642861
-Ref: Getopt Function-Footnote-1654325
-Node: Passwd Functions654525
-Ref: Passwd Functions-Footnote-1663365
-Node: Group Functions663453
-Ref: Group Functions-Footnote-1671350
-Node: Walking Arrays671555
-Node: Library Functions Summary674561
-Node: Library Exercises675963
-Node: Sample Programs677243
-Node: Running Examples678013
-Node: Clones678741
-Node: Cut Program679965
-Node: Egrep Program689685
-Ref: Egrep Program-Footnote-1697188
-Node: Id Program697298
-Node: Split Program700974
-Ref: Split Program-Footnote-1704428
-Node: Tee Program704556
-Node: Uniq Program707345
-Node: Wc Program714764
-Ref: Wc Program-Footnote-1719014
-Node: Miscellaneous Programs719108
-Node: Dupword Program720321
-Node: Alarm Program722352
-Node: Translate Program727157
-Ref: Translate Program-Footnote-1731720
-Node: Labels Program731990
-Ref: Labels Program-Footnote-1735341
-Node: Word Sorting735425
-Node: History Sorting739495
-Node: Extract Program741330
-Node: Simple Sed748854
-Node: Igawk Program751924
-Ref: Igawk Program-Footnote-1766250
-Ref: Igawk Program-Footnote-2766451
-Ref: Igawk Program-Footnote-3766573
-Node: Anagram Program766688
-Node: Signature Program769749
-Node: Programs Summary770996
-Node: Programs Exercises772217
-Ref: Programs Exercises-Footnote-1776348
-Node: Advanced Features776439
-Node: Nondecimal Data778421
-Node: Array Sorting780011
-Node: Controlling Array Traversal780711
-Ref: Controlling Array Traversal-Footnote-1789077
-Node: Array Sorting Functions789195
-Ref: Array Sorting Functions-Footnote-1793081
-Node: Two-way I/O793277
-Ref: Two-way I/O-Footnote-1798222
-Ref: Two-way I/O-Footnote-2798408
-Node: TCP/IP Networking798490
-Node: Profiling801362
-Node: Advanced Features Summary809633
-Node: Internationalization811566
-Node: I18N and L10N813046
-Node: Explaining gettext813732
-Ref: Explaining gettext-Footnote-1818757
-Ref: Explaining gettext-Footnote-2818941
-Node: Programmer i18n819106
-Ref: Programmer i18n-Footnote-1823982
-Node: Translator i18n824031
-Node: String Extraction824825
-Ref: String Extraction-Footnote-1825956
-Node: Printf Ordering826042
-Ref: Printf Ordering-Footnote-1828828
-Node: I18N Portability828892
-Ref: I18N Portability-Footnote-1831348
-Node: I18N Example831411
-Ref: I18N Example-Footnote-1834214
-Node: Gawk I18N834286
-Node: I18N Summary834930
-Node: Debugger836270
-Node: Debugging837292
-Node: Debugging Concepts837733
-Node: Debugging Terms839543
-Node: Awk Debugging842115
-Node: Sample Debugging Session843021
-Node: Debugger Invocation843555
-Node: Finding The Bug844940
-Node: List of Debugger Commands851419
-Node: Breakpoint Control852751
-Node: Debugger Execution Control856428
-Node: Viewing And Changing Data859787
-Node: Execution Stack863163
-Node: Debugger Info864798
-Node: Miscellaneous Debugger Commands868843
-Node: Readline Support873844
-Node: Limitations874738
-Node: Debugging Summary876853
-Node: Arbitrary Precision Arithmetic878027
-Node: Computer Arithmetic879443
-Ref: table-numeric-ranges883042
-Ref: Computer Arithmetic-Footnote-1883566
-Node: Math Definitions883623
-Ref: table-ieee-formats886918
-Ref: Math Definitions-Footnote-1887522
-Node: MPFR features887627
-Node: FP Math Caution889298
-Ref: FP Math Caution-Footnote-1890348
-Node: Inexactness of computations890717
-Node: Inexact representation891676
-Node: Comparing FP Values893034
-Node: Errors accumulate894116
-Node: Getting Accuracy895548
-Node: Try To Round898252
-Node: Setting precision899151
-Ref: table-predefined-precision-strings899835
-Node: Setting the rounding mode901664
-Ref: table-gawk-rounding-modes902028
-Ref: Setting the rounding mode-Footnote-1905480
-Node: Arbitrary Precision Integers905659
-Ref: Arbitrary Precision Integers-Footnote-1910557
-Node: POSIX Floating Point Problems910706
-Ref: POSIX Floating Point Problems-Footnote-1914585
-Node: Floating point summary914623
-Node: Dynamic Extensions916810
-Node: Extension Intro918362
-Node: Plugin License919627
-Node: Extension Mechanism Outline920424
-Ref: figure-load-extension920852
-Ref: figure-register-new-function922332
-Ref: figure-call-new-function923336
-Node: Extension API Description925323
-Node: Extension API Functions Introduction926773
-Node: General Data Types931594
-Ref: General Data Types-Footnote-1937494
-Node: Memory Allocation Functions937793
-Ref: Memory Allocation Functions-Footnote-1940632
-Node: Constructor Functions940731
-Node: Registration Functions942470
-Node: Extension Functions943155
-Node: Exit Callback Functions945452
-Node: Extension Version String946700
-Node: Input Parsers947363
-Node: Output Wrappers957238
-Node: Two-way processors961751
-Node: Printing Messages964014
-Ref: Printing Messages-Footnote-1965090
-Node: Updating `ERRNO'965242
-Node: Requesting Values965982
-Ref: table-value-types-returned966709
-Node: Accessing Parameters967666
-Node: Symbol Table Access968900
-Node: Symbol table by name969414
-Node: Symbol table by cookie971434
-Ref: Symbol table by cookie-Footnote-1975579
-Node: Cached values975642
-Ref: Cached values-Footnote-1979138
-Node: Array Manipulation979229
-Ref: Array Manipulation-Footnote-1980327
-Node: Array Data Types980364
-Ref: Array Data Types-Footnote-1983019
-Node: Array Functions983111
-Node: Flattening Arrays986970
-Node: Creating Arrays993872
-Node: Extension API Variables998643
-Node: Extension Versioning999279
-Node: Extension API Informational Variables1001170
-Node: Extension API Boilerplate1002235
-Node: Finding Extensions1006044
-Node: Extension Example1006604
-Node: Internal File Description1007376
-Node: Internal File Ops1011443
-Ref: Internal File Ops-Footnote-11023194
-Node: Using Internal File Ops1023334
-Ref: Using Internal File Ops-Footnote-11025717
-Node: Extension Samples1025990
-Node: Extension Sample File Functions1027518
-Node: Extension Sample Fnmatch1035199
-Node: Extension Sample Fork1036687
-Node: Extension Sample Inplace1037902
-Node: Extension Sample Ord1039578
-Node: Extension Sample Readdir1040414
-Ref: table-readdir-file-types1041291
-Node: Extension Sample Revout1042102
-Node: Extension Sample Rev2way1042691
-Node: Extension Sample Read write array1043431
-Node: Extension Sample Readfile1045371
-Node: Extension Sample Time1046466
-Node: Extension Sample API Tests1047814
-Node: gawkextlib1048305
-Node: Extension summary1050983
-Node: Extension Exercises1054672
-Node: Language History1055394
-Node: V7/SVR3.11057050
-Node: SVR41059203
-Node: POSIX1060637
-Node: BTL1062018
-Node: POSIX/GNU1062749
-Node: Feature History1068494
-Node: Common Extensions1082220
-Node: Ranges and Locales1083592
-Ref: Ranges and Locales-Footnote-11088211
-Ref: Ranges and Locales-Footnote-21088238
-Ref: Ranges and Locales-Footnote-31088473
-Node: Contributors1088694
-Node: History summary1094234
-Node: Installation1095613
-Node: Gawk Distribution1096559
-Node: Getting1097043
-Node: Extracting1097866
-Node: Distribution contents1099503
-Node: Unix Installation1105605
-Node: Quick Installation1106288
-Node: Shell Startup Files1108699
-Node: Additional Configuration Options1109778
-Node: Configuration Philosophy1111582
-Node: Non-Unix Installation1113951
-Node: PC Installation1114409
-Node: PC Binary Installation1115729
-Node: PC Compiling1117577
-Ref: PC Compiling-Footnote-11120598
-Node: PC Testing1120707
-Node: PC Using1121883
-Node: Cygwin1125998
-Node: MSYS1126768
-Node: VMS Installation1127269
-Node: VMS Compilation1128061
-Ref: VMS Compilation-Footnote-11129290
-Node: VMS Dynamic Extensions1129348
-Node: VMS Installation Details1131032
-Node: VMS Running1133283
-Node: VMS GNV1136123
-Node: VMS Old Gawk1136858
-Node: Bugs1137328
-Node: Other Versions1141217
-Node: Installation summary1147651
-Node: Notes1148710
-Node: Compatibility Mode1149575
-Node: Additions1150357
-Node: Accessing The Source1151282
-Node: Adding Code1152717
-Node: New Ports1158874
-Node: Derived Files1163356
-Ref: Derived Files-Footnote-11168831
-Ref: Derived Files-Footnote-21168865
-Ref: Derived Files-Footnote-31169461
-Node: Future Extensions1169575
-Node: Implementation Limitations1170181
-Node: Extension Design1171429
-Node: Old Extension Problems1172583
-Ref: Old Extension Problems-Footnote-11174100
-Node: Extension New Mechanism Goals1174157
-Ref: Extension New Mechanism Goals-Footnote-11177517
-Node: Extension Other Design Decisions1177706
-Node: Extension Future Growth1179814
-Node: Old Extension Mechanism1180650
-Node: Notes summary1182412
-Node: Basic Concepts1183598
-Node: Basic High Level1184279
-Ref: figure-general-flow1184551
-Ref: figure-process-flow1185150
-Ref: Basic High Level-Footnote-11188379
-Node: Basic Data Typing1188564
-Node: Glossary1191892
-Node: Copying1223821
-Node: GNU Free Documentation License1261377
-Node: Index1286513
+Node: Foreword342291
+Node: Foreword446735
+Node: Preface48266
+Ref: Preface-Footnote-151137
+Ref: Preface-Footnote-251244
+Ref: Preface-Footnote-351477
+Node: History51619
+Node: Names53970
+Ref: Names-Footnote-155064
+Node: This Manual55210
+Ref: This Manual-Footnote-161710
+Node: Conventions61810
+Node: Manual History64147
+Ref: Manual History-Footnote-167140
+Ref: Manual History-Footnote-267181
+Node: How To Contribute67255
+Node: Acknowledgments68384
+Node: Getting Started73250
+Node: Running gawk75689
+Node: One-shot76879
+Node: Read Terminal78143
+Node: Long80174
+Node: Executable Scripts81687
+Ref: Executable Scripts-Footnote-184476
+Node: Comments84579
+Node: Quoting87061
+Node: DOS Quoting92579
+Node: Sample Data Files93254
+Node: Very Simple95849
+Node: Two Rules100748
+Node: More Complex102634
+Node: Statements/Lines105496
+Ref: Statements/Lines-Footnote-1109951
+Node: Other Features110216
+Node: When111152
+Ref: When-Footnote-1112906
+Node: Intro Summary112971
+Node: Invoking Gawk113855
+Node: Command Line115369
+Node: Options116167
+Ref: Options-Footnote-1131962
+Ref: Options-Footnote-2132191
+Node: Other Arguments132216
+Node: Naming Standard Input135164
+Node: Environment Variables136257
+Node: AWKPATH Variable136815
+Ref: AWKPATH Variable-Footnote-1140222
+Ref: AWKPATH Variable-Footnote-2140267
+Node: AWKLIBPATH Variable140527
+Node: Other Environment Variables141783
+Node: Exit Status145414
+Node: Include Files146090
+Node: Loading Shared Libraries149679
+Node: Obsolete151106
+Node: Undocumented151798
+Node: Invoking Summary152065
+Node: Regexp153728
+Node: Regexp Usage155182
+Node: Escape Sequences157219
+Node: Regexp Operators163448
+Ref: Regexp Operators-Footnote-1170858
+Ref: Regexp Operators-Footnote-2171005
+Node: Bracket Expressions171103
+Ref: table-char-classes173118
+Node: Leftmost Longest176060
+Node: Computed Regexps177362
+Node: GNU Regexp Operators180791
+Node: Case-sensitivity184463
+Ref: Case-sensitivity-Footnote-1187348
+Ref: Case-sensitivity-Footnote-2187583
+Node: Regexp Summary187691
+Node: Reading Files189158
+Node: Records191251
+Node: awk split records191984
+Node: gawk split records196913
+Ref: gawk split records-Footnote-1201452
+Node: Fields201489
+Ref: Fields-Footnote-1204267
+Node: Nonconstant Fields204353
+Ref: Nonconstant Fields-Footnote-1206591
+Node: Changing Fields206794
+Node: Field Separators212725
+Node: Default Field Splitting215429
+Node: Regexp Field Splitting216546
+Node: Single Character Fields219896
+Node: Command Line Field Separator220955
+Node: Full Line Fields224172
+Ref: Full Line Fields-Footnote-1225693
+Ref: Full Line Fields-Footnote-2225739
+Node: Field Splitting Summary225840
+Node: Constant Size227914
+Node: Splitting By Content232497
+Ref: Splitting By Content-Footnote-1236462
+Node: Multiple Line236625
+Ref: Multiple Line-Footnote-1242506
+Node: Getline242685
+Node: Plain Getline244892
+Node: Getline/Variable247532
+Node: Getline/File248681
+Node: Getline/Variable/File250066
+Ref: Getline/Variable/File-Footnote-1251669
+Node: Getline/Pipe251756
+Node: Getline/Variable/Pipe254434
+Node: Getline/Coprocess255565
+Node: Getline/Variable/Coprocess256829
+Node: Getline Notes257568
+Node: Getline Summary260362
+Ref: table-getline-variants260774
+Node: Read Timeout261603
+Ref: Read Timeout-Footnote-1265440
+Node: Command-line directories265498
+Node: Input Summary266403
+Node: Input Exercises269788
+Node: Printing270516
+Node: Print272351
+Node: Print Examples273808
+Node: Output Separators276587
+Node: OFMT278605
+Node: Printf279960
+Node: Basic Printf280745
+Node: Control Letters282317
+Node: Format Modifiers286302
+Node: Printf Examples292308
+Node: Redirection294794
+Node: Special FD301632
+Ref: Special FD-Footnote-1304798
+Node: Special Files304872
+Node: Other Inherited Files305489
+Node: Special Network306489
+Node: Special Caveats307351
+Node: Close Files And Pipes308300
+Ref: Close Files And Pipes-Footnote-1315485
+Ref: Close Files And Pipes-Footnote-2315633
+Node: Nonfatal315783
+Node: Output Summary318108
+Node: Output Exercises319329
+Node: Expressions320009
+Node: Values321198
+Node: Constants321875
+Node: Scalar Constants322566
+Ref: Scalar Constants-Footnote-1323428
+Node: Nondecimal-numbers323678
+Node: Regexp Constants326688
+Node: Using Constant Regexps327214
+Node: Variables330377
+Node: Using Variables331034
+Node: Assignment Options332945
+Node: Conversion334820
+Node: Strings And Numbers335344
+Ref: Strings And Numbers-Footnote-1338409
+Node: Locale influences conversions338518
+Ref: table-locale-affects341264
+Node: All Operators341856
+Node: Arithmetic Ops342485
+Node: Concatenation344990
+Ref: Concatenation-Footnote-1347809
+Node: Assignment Ops347916
+Ref: table-assign-ops352895
+Node: Increment Ops354205
+Node: Truth Values and Conditions357636
+Node: Truth Values358719
+Node: Typing and Comparison359768
+Node: Variable Typing360584
+Node: Comparison Operators364251
+Ref: table-relational-ops364661
+Node: POSIX String Comparison368156
+Ref: POSIX String Comparison-Footnote-1369228
+Node: Boolean Ops369367
+Ref: Boolean Ops-Footnote-1373845
+Node: Conditional Exp373936
+Node: Function Calls375674
+Node: Precedence379554
+Node: Locales383214
+Node: Expressions Summary384846
+Node: Patterns and Actions387417
+Node: Pattern Overview388537
+Node: Regexp Patterns390216
+Node: Expression Patterns390759
+Node: Ranges394539
+Node: BEGIN/END397646
+Node: Using BEGIN/END398407
+Ref: Using BEGIN/END-Footnote-1401143
+Node: I/O And BEGIN/END401249
+Node: BEGINFILE/ENDFILE403564
+Node: Empty406461
+Node: Using Shell Variables406778
+Node: Action Overview409051
+Node: Statements411377
+Node: If Statement413225
+Node: While Statement414720
+Node: Do Statement416748
+Node: For Statement417896
+Node: Switch Statement421054
+Node: Break Statement423436
+Node: Continue Statement425529
+Node: Next Statement427356
+Node: Nextfile Statement429737
+Node: Exit Statement432365
+Node: Built-in Variables434776
+Node: User-modified435909
+Ref: User-modified-Footnote-1443543
+Node: Auto-set443605
+Ref: Auto-set-Footnote-1457314
+Ref: Auto-set-Footnote-2457519
+Node: ARGC and ARGV457575
+Node: Pattern Action Summary461793
+Node: Arrays464226
+Node: Array Basics465555
+Node: Array Intro466399
+Ref: figure-array-elements468333
+Ref: Array Intro-Footnote-1470953
+Node: Reference to Elements471081
+Node: Assigning Elements473543
+Node: Array Example474034
+Node: Scanning an Array475793
+Node: Controlling Scanning478813
+Ref: Controlling Scanning-Footnote-1484207
+Node: Numeric Array Subscripts484523
+Node: Uninitialized Subscripts486708
+Node: Delete488325
+Ref: Delete-Footnote-1491074
+Node: Multidimensional491131
+Node: Multiscanning494228
+Node: Arrays of Arrays495817
+Node: Arrays Summary500571
+Node: Functions502662
+Node: Built-in503701
+Node: Calling Built-in504779
+Node: Numeric Functions506774
+Ref: Numeric Functions-Footnote-1511592
+Ref: Numeric Functions-Footnote-2511949
+Ref: Numeric Functions-Footnote-3511997
+Node: String Functions512269
+Ref: String Functions-Footnote-1535770
+Ref: String Functions-Footnote-2535899
+Ref: String Functions-Footnote-3536147
+Node: Gory Details536234
+Ref: table-sub-escapes538015
+Ref: table-sub-proposed539530
+Ref: table-posix-sub540892
+Ref: table-gensub-escapes542429
+Ref: Gory Details-Footnote-1543262
+Node: I/O Functions543413
+Ref: I/O Functions-Footnote-1550649
+Node: Time Functions550796
+Ref: Time Functions-Footnote-1561305
+Ref: Time Functions-Footnote-2561373
+Ref: Time Functions-Footnote-3561531
+Ref: Time Functions-Footnote-4561642
+Ref: Time Functions-Footnote-5561754
+Ref: Time Functions-Footnote-6561981
+Node: Bitwise Functions562247
+Ref: table-bitwise-ops562809
+Ref: Bitwise Functions-Footnote-1567137
+Node: Type Functions567309
+Node: I18N Functions568461
+Node: User-defined570108
+Node: Definition Syntax570913
+Ref: Definition Syntax-Footnote-1576572
+Node: Function Example576643
+Ref: Function Example-Footnote-1579564
+Node: Function Caveats579586
+Node: Calling A Function580104
+Node: Variable Scope581062
+Node: Pass By Value/Reference584055
+Node: Return Statement587552
+Node: Dynamic Typing590531
+Node: Indirect Calls591460
+Ref: Indirect Calls-Footnote-1601325
+Node: Functions Summary601453
+Node: Library Functions604155
+Ref: Library Functions-Footnote-1607763
+Ref: Library Functions-Footnote-2607906
+Node: Library Names608077
+Ref: Library Names-Footnote-1611535
+Ref: Library Names-Footnote-2611758
+Node: General Functions611844
+Node: Strtonum Function612947
+Node: Assert Function615969
+Node: Round Function619293
+Node: Cliff Random Function620834
+Node: Ordinal Functions621850
+Ref: Ordinal Functions-Footnote-1624913
+Ref: Ordinal Functions-Footnote-2625165
+Node: Join Function625376
+Ref: Join Function-Footnote-1627146
+Node: Getlocaltime Function627346
+Node: Readfile Function631090
+Node: Shell Quoting633062
+Node: Data File Management634463
+Node: Filetrans Function635095
+Node: Rewind Function639191
+Node: File Checking640577
+Ref: File Checking-Footnote-1641910
+Node: Empty Files642111
+Node: Ignoring Assigns644090
+Node: Getopt Function645640
+Ref: Getopt Function-Footnote-1657104
+Node: Passwd Functions657304
+Ref: Passwd Functions-Footnote-1666144
+Node: Group Functions666232
+Ref: Group Functions-Footnote-1674129
+Node: Walking Arrays674334
+Node: Library Functions Summary677340
+Node: Library Exercises678742
+Node: Sample Programs680022
+Node: Running Examples680792
+Node: Clones681520
+Node: Cut Program682744
+Node: Egrep Program692464
+Ref: Egrep Program-Footnote-1699967
+Node: Id Program700077
+Node: Split Program703753
+Ref: Split Program-Footnote-1707207
+Node: Tee Program707335
+Node: Uniq Program710124
+Node: Wc Program717543
+Ref: Wc Program-Footnote-1721793
+Node: Miscellaneous Programs721887
+Node: Dupword Program723100
+Node: Alarm Program725131
+Node: Translate Program729936
+Ref: Translate Program-Footnote-1734499
+Node: Labels Program734769
+Ref: Labels Program-Footnote-1738120
+Node: Word Sorting738204
+Node: History Sorting742274
+Node: Extract Program744109
+Node: Simple Sed751633
+Node: Igawk Program754703
+Ref: Igawk Program-Footnote-1769029
+Ref: Igawk Program-Footnote-2769230
+Ref: Igawk Program-Footnote-3769352
+Node: Anagram Program769467
+Node: Signature Program772528
+Node: Programs Summary773775
+Node: Programs Exercises774996
+Ref: Programs Exercises-Footnote-1779127
+Node: Advanced Features779218
+Node: Nondecimal Data781200
+Node: Array Sorting782790
+Node: Controlling Array Traversal783490
+Ref: Controlling Array Traversal-Footnote-1791856
+Node: Array Sorting Functions791974
+Ref: Array Sorting Functions-Footnote-1795860
+Node: Two-way I/O796056
+Ref: Two-way I/O-Footnote-1801001
+Ref: Two-way I/O-Footnote-2801187
+Node: TCP/IP Networking801269
+Node: Profiling804141
+Node: Advanced Features Summary812412
+Node: Internationalization814345
+Node: I18N and L10N815825
+Node: Explaining gettext816511
+Ref: Explaining gettext-Footnote-1821536
+Ref: Explaining gettext-Footnote-2821720
+Node: Programmer i18n821885
+Ref: Programmer i18n-Footnote-1826761
+Node: Translator i18n826810
+Node: String Extraction827604
+Ref: String Extraction-Footnote-1828735
+Node: Printf Ordering828821
+Ref: Printf Ordering-Footnote-1831607
+Node: I18N Portability831671
+Ref: I18N Portability-Footnote-1834127
+Node: I18N Example834190
+Ref: I18N Example-Footnote-1836993
+Node: Gawk I18N837065
+Node: I18N Summary837709
+Node: Debugger839049
+Node: Debugging840071
+Node: Debugging Concepts840512
+Node: Debugging Terms842322
+Node: Awk Debugging844894
+Node: Sample Debugging Session845800
+Node: Debugger Invocation846334
+Node: Finding The Bug847719
+Node: List of Debugger Commands854198
+Node: Breakpoint Control855530
+Node: Debugger Execution Control859207
+Node: Viewing And Changing Data862566
+Node: Execution Stack865942
+Node: Debugger Info867577
+Node: Miscellaneous Debugger Commands871622
+Node: Readline Support876623
+Node: Limitations877517
+Node: Debugging Summary879632
+Node: Arbitrary Precision Arithmetic880806
+Node: Computer Arithmetic882222
+Ref: table-numeric-ranges885821
+Ref: Computer Arithmetic-Footnote-1886345
+Node: Math Definitions886402
+Ref: table-ieee-formats889697
+Ref: Math Definitions-Footnote-1890301
+Node: MPFR features890406
+Node: FP Math Caution892077
+Ref: FP Math Caution-Footnote-1893127
+Node: Inexactness of computations893496
+Node: Inexact representation894455
+Node: Comparing FP Values895813
+Node: Errors accumulate896895
+Node: Getting Accuracy898327
+Node: Try To Round901031
+Node: Setting precision901930
+Ref: table-predefined-precision-strings902614
+Node: Setting the rounding mode904443
+Ref: table-gawk-rounding-modes904807
+Ref: Setting the rounding mode-Footnote-1908259
+Node: Arbitrary Precision Integers908438
+Ref: Arbitrary Precision Integers-Footnote-1913336
+Node: POSIX Floating Point Problems913485
+Ref: POSIX Floating Point Problems-Footnote-1917364
+Node: Floating point summary917402
+Node: Dynamic Extensions919589
+Node: Extension Intro921141
+Node: Plugin License922406
+Node: Extension Mechanism Outline923203
+Ref: figure-load-extension923631
+Ref: figure-register-new-function925111
+Ref: figure-call-new-function926115
+Node: Extension API Description928102
+Node: Extension API Functions Introduction929552
+Node: General Data Types934373
+Ref: General Data Types-Footnote-1940273
+Node: Memory Allocation Functions940572
+Ref: Memory Allocation Functions-Footnote-1943411
+Node: Constructor Functions943510
+Node: Registration Functions945249
+Node: Extension Functions945934
+Node: Exit Callback Functions948231
+Node: Extension Version String949479
+Node: Input Parsers950142
+Node: Output Wrappers960017
+Node: Two-way processors964530
+Node: Printing Messages966793
+Ref: Printing Messages-Footnote-1967869
+Node: Updating `ERRNO'968021
+Node: Requesting Values968761
+Ref: table-value-types-returned969488
+Node: Accessing Parameters970445
+Node: Symbol Table Access971679
+Node: Symbol table by name972193
+Node: Symbol table by cookie974213
+Ref: Symbol table by cookie-Footnote-1978358
+Node: Cached values978421
+Ref: Cached values-Footnote-1981917
+Node: Array Manipulation982008
+Ref: Array Manipulation-Footnote-1983106
+Node: Array Data Types983143
+Ref: Array Data Types-Footnote-1985798
+Node: Array Functions985890
+Node: Flattening Arrays989749
+Node: Creating Arrays996651
+Node: Extension API Variables1001422
+Node: Extension Versioning1002058
+Node: Extension API Informational Variables1003949
+Node: Extension API Boilerplate1005014
+Node: Finding Extensions1008823
+Node: Extension Example1009383
+Node: Internal File Description1010155
+Node: Internal File Ops1014222
+Ref: Internal File Ops-Footnote-11025973
+Node: Using Internal File Ops1026113
+Ref: Using Internal File Ops-Footnote-11028496
+Node: Extension Samples1028769
+Node: Extension Sample File Functions1030297
+Node: Extension Sample Fnmatch1037978
+Node: Extension Sample Fork1039466
+Node: Extension Sample Inplace1040681
+Node: Extension Sample Ord1042357
+Node: Extension Sample Readdir1043193
+Ref: table-readdir-file-types1044070
+Node: Extension Sample Revout1044881
+Node: Extension Sample Rev2way1045470
+Node: Extension Sample Read write array1046210
+Node: Extension Sample Readfile1048150
+Node: Extension Sample Time1049245
+Node: Extension Sample API Tests1050593
+Node: gawkextlib1051084
+Node: Extension summary1053762
+Node: Extension Exercises1057451
+Node: Language History1058173
+Node: V7/SVR3.11059829
+Node: SVR41061982
+Node: POSIX1063416
+Node: BTL1064797
+Node: POSIX/GNU1065528
+Node: Feature History1071364
+Node: Common Extensions1085158
+Node: Ranges and Locales1086530
+Ref: Ranges and Locales-Footnote-11091149
+Ref: Ranges and Locales-Footnote-21091176
+Ref: Ranges and Locales-Footnote-31091411
+Node: Contributors1091632
+Node: History summary1097172
+Node: Installation1098551
+Node: Gawk Distribution1099497
+Node: Getting1099981
+Node: Extracting1100804
+Node: Distribution contents1102441
+Node: Unix Installation1108543
+Node: Quick Installation1109226
+Node: Shell Startup Files1111637
+Node: Additional Configuration Options1112716
+Node: Configuration Philosophy1114520
+Node: Non-Unix Installation1116889
+Node: PC Installation1117347
+Node: PC Binary Installation1118667
+Node: PC Compiling1120515
+Ref: PC Compiling-Footnote-11123536
+Node: PC Testing1123645
+Node: PC Using1124821
+Node: Cygwin1128936
+Node: MSYS1129706
+Node: VMS Installation1130207
+Node: VMS Compilation1130999
+Ref: VMS Compilation-Footnote-11132228
+Node: VMS Dynamic Extensions1132286
+Node: VMS Installation Details1133970
+Node: VMS Running1136221
+Node: VMS GNV1139061
+Node: VMS Old Gawk1139796
+Node: Bugs1140266
+Node: Other Versions1144155
+Node: Installation summary1150589
+Node: Notes1151648
+Node: Compatibility Mode1152513
+Node: Additions1153295
+Node: Accessing The Source1154220
+Node: Adding Code1155655
+Node: New Ports1161812
+Node: Derived Files1166294
+Ref: Derived Files-Footnote-11171769
+Ref: Derived Files-Footnote-21171803
+Ref: Derived Files-Footnote-31172399
+Node: Future Extensions1172513
+Node: Implementation Limitations1173119
+Node: Extension Design1174367
+Node: Old Extension Problems1175521
+Ref: Old Extension Problems-Footnote-11177038
+Node: Extension New Mechanism Goals1177095
+Ref: Extension New Mechanism Goals-Footnote-11180455
+Node: Extension Other Design Decisions1180644
+Node: Extension Future Growth1182752
+Node: Old Extension Mechanism1183588
+Node: Notes summary1185350
+Node: Basic Concepts1186536
+Node: Basic High Level1187217
+Ref: figure-general-flow1187489
+Ref: figure-process-flow1188088
+Ref: Basic High Level-Footnote-11191317
+Node: Basic Data Typing1191502
+Node: Glossary1194830
+Node: Copying1226759
+Node: GNU Free Documentation License1264315
+Node: Index1289451

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 2b49c245..615330d1 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -633,6 +633,7 @@ particular records in a file and perform operations upon them.
* Special Caveats:: Things to watch out for.
* Close Files And Pipes:: Closing Input and Output Files and
Pipes.
+* Nonfatal:: Enabling Nonfatal Output.
* Output Summary:: Output summary.
* Output Exercises:: Exercises.
* Values:: Constants, Variables, and Regular
@@ -4549,6 +4550,8 @@ wait for input before returning with an error.
Controls the number of times @command{gawk} attempts to
retry a two-way TCP/IP (socket) connection before giving up.
@xref{TCP/IP Networking}.
+Note that when nonfatal I/O is enabled (@pxref{Nonfatal}),
+@command{gawk} only tries to open a TCP/IP socket once.
@item POSIXLY_CORRECT
Causes @command{gawk} to switch to POSIX-compatibility
@@ -8935,6 +8938,7 @@ and discusses the @code{close()} built-in function.
@command{gawk} allows access to inherited file
descriptors.
* Close Files And Pipes:: Closing Input and Output Files and Pipes.
+* Nonfatal:: Enabling Nonfatal Output.
* Output Summary:: Output summary.
* Output Exercises:: Exercises.
@end menu
@@ -10441,6 +10445,71 @@ when closing a pipe.
@end ifnotdocbook
+@node Nonfatal
+@section Enabling Nonfatal Output
+
+This @value{SECTION} describes a @command{gawk}-specific feature.
+
+In standard @command{awk}, output with @code{print} or @code{printf}
+to a nonexistent file, or some other I/O error (such as filling up the
+disk) is a fatal error.
+
+@example
+$ @kbd{gawk 'BEGIN @{ print "hi" > "/no/such/file" @}'}
+@error{} gawk: cmd. line:1: fatal: can't redirect to `/no/such/file' (No such file or directory)
+@end example
+
+@command{gawk} makes it possible to detect that an error has
+occurred, allowing you to possibly recover from the error, or
+at least print an error message of your choosing before exiting.
+You can do this in one of two ways:
+
+@itemize @bullet
+@item
+For all output files, by assigning any value to @code{PROCINFO["NONFATAL"]}.
+
+@item
+On a per-file basis, by assigning any value to
+@code{PROCINFO[@var{filename}, "NONFATAL"]}.
+Here, @var{filename} is the name of the file to which
+you wish output to be nonfatal.
+@end itemize
+
+Once you have enabled nonfatal output, you must check @code{ERRNO}
+after every relevant @code{print} or @code{printf} statement to
+see if something went wrong. It is also a good idea to initialize
+@code{ERRNO} to zero before attempting the output. For example:
+
+@example
+$ @kbd{gawk '}
+> @kbd{BEGIN @{}
+> @kbd{ PROCINFO["NONFATAL"] = 1}
+> @kbd{ ERRNO = 0}
+> @kbd{ print "hi" > "/no/such/file"}
+> @kbd{ if (ERRNO) @{}
+> @kbd{ print("Output failed:", ERRNO) > "/dev/stderr"}
+> @kbd{ exit 1}
+> @kbd{ @}}
+> @kbd{@}'}
+@error{} Output failed: No such file or directory
+@end example
+
+Here, @command{gawk} did not produce a fatal error; instead
+it let the @command{awk} program code detect the problem and handle it.
+
+This mechanism works also for standard output and standard error.
+For standard output, you may use @code{PROCINFO["-", "NONFATAL"]}
+or @code{PROCINFO["/dev/stdout", "NONFATAL"]}. For standard error, use
+@code{PROCINFO["/dev/stderr", "NONFATAL"]}.
+
+When attempting to open a TCP/IP socket (@pxref{TCP/IP Networking}),
+@command{gawk} tries multiple times. The @env{GAWK_SOCK_RETRIES}
+environment variable (@pxref{Other Environment Variables}) allows you to
+override @command{gawk}'s builtin default number of attempts. However,
+once nonfatal I/O is enabled for a given socket, @command{gawk} only
+retries once, relying on @command{awk}-level code to notice that there
+was a problem.
+
@node Output Summary
@section Summary
@@ -10469,6 +10538,12 @@ Use @code{close()} to close open file, pipe, and coprocess redirections.
For coprocesses, it is possible to close only one direction of the
communications.
+@item
+Normally errors with @code{print} or @code{printf} are fatal.
+@command{gawk} lets you make output errors be nonfatal either for
+all files or on a per-file basis. You must then check for errors
+after every relevant output statement.
+
@end itemize
@c EXCLUDE START
@@ -35703,6 +35778,10 @@ Indirect function calls
@item
Directories on the command line produce a warning and are skipped
(@pxref{Command-line directories})
+
+@item
+Output with @code{print} and @code{printf} need not be fatal
+(@pxref{Nonfatal})
@end itemize
@item
@@ -36582,6 +36661,10 @@ is now two.
@xref{Escape Sequences}.
@item
+Nonfatal output with @code{print} and @code{printf}.
+@xref{Nonfatal}.
+
+@item
Support for MirBSD was removed.
@end itemize
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index 713f354f..8612876e 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -628,6 +628,7 @@ particular records in a file and perform operations upon them.
* Special Caveats:: Things to watch out for.
* Close Files And Pipes:: Closing Input and Output Files and
Pipes.
+* Nonfatal:: Enabling Nonfatal Output.
* Output Summary:: Output summary.
* Output Exercises:: Exercises.
* Values:: Constants, Variables, and Regular
@@ -4460,6 +4461,8 @@ wait for input before returning with an error.
Controls the number of times @command{gawk} attempts to
retry a two-way TCP/IP (socket) connection before giving up.
@xref{TCP/IP Networking}.
+Note that when nonfatal I/O is enabled (@pxref{Nonfatal}),
+@command{gawk} only tries to open a TCP/IP socket once.
@item POSIXLY_CORRECT
Causes @command{gawk} to switch to POSIX-compatibility
@@ -8535,6 +8538,7 @@ and discusses the @code{close()} built-in function.
@command{gawk} allows access to inherited file
descriptors.
* Close Files And Pipes:: Closing Input and Output Files and Pipes.
+* Nonfatal:: Enabling Nonfatal Output.
* Output Summary:: Output summary.
* Output Exercises:: Exercises.
@end menu
@@ -9937,6 +9941,71 @@ when closing a pipe.
@end sidebar
+@node Nonfatal
+@section Enabling Nonfatal Output
+
+This @value{SECTION} describes a @command{gawk}-specific feature.
+
+In standard @command{awk}, output with @code{print} or @code{printf}
+to a nonexistent file, or some other I/O error (such as filling up the
+disk) is a fatal error.
+
+@example
+$ @kbd{gawk 'BEGIN @{ print "hi" > "/no/such/file" @}'}
+@error{} gawk: cmd. line:1: fatal: can't redirect to `/no/such/file' (No such file or directory)
+@end example
+
+@command{gawk} makes it possible to detect that an error has
+occurred, allowing you to possibly recover from the error, or
+at least print an error message of your choosing before exiting.
+You can do this in one of two ways:
+
+@itemize @bullet
+@item
+For all output files, by assigning any value to @code{PROCINFO["NONFATAL"]}.
+
+@item
+On a per-file basis, by assigning any value to
+@code{PROCINFO[@var{filename}, "NONFATAL"]}.
+Here, @var{filename} is the name of the file to which
+you wish output to be nonfatal.
+@end itemize
+
+Once you have enabled nonfatal output, you must check @code{ERRNO}
+after every relevant @code{print} or @code{printf} statement to
+see if something went wrong. It is also a good idea to initialize
+@code{ERRNO} to zero before attempting the output. For example:
+
+@example
+$ @kbd{gawk '}
+> @kbd{BEGIN @{}
+> @kbd{ PROCINFO["NONFATAL"] = 1}
+> @kbd{ ERRNO = 0}
+> @kbd{ print "hi" > "/no/such/file"}
+> @kbd{ if (ERRNO) @{}
+> @kbd{ print("Output failed:", ERRNO) > "/dev/stderr"}
+> @kbd{ exit 1}
+> @kbd{ @}}
+> @kbd{@}'}
+@error{} Output failed: No such file or directory
+@end example
+
+Here, @command{gawk} did not produce a fatal error; instead
+it let the @command{awk} program code detect the problem and handle it.
+
+This mechanism works also for standard output and standard error.
+For standard output, you may use @code{PROCINFO["-", "NONFATAL"]}
+or @code{PROCINFO["/dev/stdout", "NONFATAL"]}. For standard error, use
+@code{PROCINFO["/dev/stderr", "NONFATAL"]}.
+
+When attempting to open a TCP/IP socket (@pxref{TCP/IP Networking}),
+@command{gawk} tries multiple times. The @env{GAWK_SOCK_RETRIES}
+environment variable (@pxref{Other Environment Variables}) allows you to
+override @command{gawk}'s builtin default number of attempts. However,
+once nonfatal I/O is enabled for a given socket, @command{gawk} only
+retries once, relying on @command{awk}-level code to notice that there
+was a problem.
+
@node Output Summary
@section Summary
@@ -9965,6 +10034,12 @@ Use @code{close()} to close open file, pipe, and coprocess redirections.
For coprocesses, it is possible to close only one direction of the
communications.
+@item
+Normally errors with @code{print} or @code{printf} are fatal.
+@command{gawk} lets you make output errors be nonfatal either for
+all files or on a per-file basis. You must then check for errors
+after every relevant output statement.
+
@end itemize
@c EXCLUDE START
@@ -34794,6 +34869,10 @@ Indirect function calls
@item
Directories on the command line produce a warning and are skipped
(@pxref{Command-line directories})
+
+@item
+Output with @code{print} and @code{printf} need not be fatal
+(@pxref{Nonfatal})
@end itemize
@item
@@ -35673,6 +35752,10 @@ is now two.
@xref{Escape Sequences}.
@item
+Nonfatal output with @code{print} and @code{printf}.
+@xref{Nonfatal}.
+
+@item
Support for MirBSD was removed.
@end itemize
diff --git a/io.c b/io.c
index 1d15d887..55c5d3a5 100644
--- a/io.c
+++ b/io.c
@@ -261,7 +261,6 @@ struct recmatch {
static int iop_close(IOBUF *iop);
-struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg);
static void close_one(void);
static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how);
#ifndef PIPES_SIMULATED
@@ -727,7 +726,7 @@ redflags2str(int flags)
/* redirect --- Redirection for printf and print commands */
struct redirect *
-redirect(NODE *redir_exp, int redirtype, int *errflg)
+redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal)
{
struct redirect *rp;
char *str;
@@ -892,6 +891,12 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
(void) flush_io();
os_restore_mode(fileno(stdin));
+ /*
+ * Don't check failure_fatal; see input pipe below.
+ * Note that the failure happens upon failure to fork,
+ * using a non-existant program will still succeed the
+ * popen().
+ */
if ((rp->output.fp = popen(str, binmode("w"))) == NULL)
fatal(_("can't open pipe `%s' for output (%s)"),
str, strerror(errno));
@@ -927,13 +932,11 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
case redirect_twoway:
direction = "to/from";
if (! two_way_open(str, rp)) {
-#ifdef HAVE_SOCKETS
- if (inetfile(str, NULL)) {
+ if (! failure_fatal || is_non_fatal_redirect(str)) {
*errflg = errno;
/* do not free rp, saving it for reuse (save_rp = rp) */
return NULL;
} else
-#endif
fatal(_("can't open two way pipe `%s' for input/output (%s)"),
str, strerror(errno));
}
@@ -1009,11 +1012,14 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
* can return -1. For output to file,
* complain. The shell will complain on
* a bad command to a pipe.
+ *
+ * 12/2014: Take nonfatal settings in PROCINFO into account.
*/
if (errflg != NULL)
*errflg = errno;
- if ( redirtype == redirect_output
- || redirtype == redirect_append) {
+ if (failure_fatal && ! is_non_fatal_redirect(str) &&
+ (redirtype == redirect_output
+ || redirtype == redirect_append)) {
/* multiple messages make life easier for translators */
if (*direction == 'f')
fatal(_("can't redirect from `%s' (%s)"),
@@ -1058,6 +1064,36 @@ getredirect(const char *str, int len)
return NULL;
}
+/* is_non_fatal_std --- return true if fp is stdout/stderr and nonfatal */
+
+bool
+is_non_fatal_std(FILE *fp)
+{
+ static const char nonfatal[] = "NONFATAL";
+
+ if (in_PROCINFO(nonfatal, NULL, NULL))
+ return true;
+
+ /* yucky logic. sigh. */
+ if (fp == stdout) {
+ return ( in_PROCINFO("-", nonfatal, NULL) != NULL
+ || in_PROCINFO("/dev/stdout", nonfatal, NULL) != NULL);
+ } else if (fp == stderr) {
+ return (in_PROCINFO("/dev/stderr", nonfatal, NULL) != NULL);
+ }
+
+ return false;
+}
+
+/* is_non_fatal_redirect --- return true if redirected I/O should be nonfatal */
+
+bool
+is_non_fatal_redirect(const char *str)
+{
+ return in_PROCINFO("NONFATAL", NULL, NULL) != NULL
+ || in_PROCINFO(str, "NONFATAL", NULL) != NULL;
+}
+
/* close_one --- temporarily close an open file to re-use the fd */
static void
@@ -1430,7 +1466,7 @@ str2mode(const char *mode)
static int
socketopen(int family, int type, const char *localpname,
- const char *remotepname, const char *remotehostname)
+ const char *remotepname, const char *remotehostname, bool *hard_error)
{
struct addrinfo *lres, *lres0;
struct addrinfo lhints;
@@ -1449,8 +1485,11 @@ socketopen(int family, int type, const char *localpname,
lerror = getaddrinfo(NULL, localpname, & lhints, & lres);
if (lerror) {
- if (strcmp(localpname, "0") != 0)
- fatal(_("local port %s invalid in `/inet'"), localpname);
+ if (strcmp(localpname, "0") != 0) {
+ warning(_("local port %s invalid in `/inet'"), localpname);
+ *hard_error = true;
+ return INVALID_HANDLE;
+ }
lres0 = NULL;
lres = & lhints;
} else
@@ -1468,7 +1507,9 @@ socketopen(int family, int type, const char *localpname,
if (rerror) {
if (lres0 != NULL)
freeaddrinfo(lres0);
- fatal(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname);
+ warning(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname);
+ *hard_error = true;
+ return INVALID_HANDLE;
}
rres0 = rres;
socket_fd = INVALID_HANDLE;
@@ -1577,6 +1618,7 @@ devopen(const char *name, const char *mode)
char *ptr;
int flag = 0;
struct inet_socket_info isi;
+ int save_errno = 0;
if (strcmp(name, "-") == 0)
return fileno(stdin);
@@ -1619,6 +1661,14 @@ devopen(const char *name, const char *mode)
goto strictopen;
} else if (inetfile(name, & isi)) {
#ifdef HAVE_SOCKETS
+#define DEFAULT_RETRIES 20
+ static unsigned long def_retries = DEFAULT_RETRIES;
+ static bool first_time = true;
+ unsigned long retries = 0;
+ static long msleep = 1000;
+ bool hard_error = false;
+ bool non_fatal = is_non_fatal_redirect(name);
+
cp = (char *) name;
/* socketopen requires NUL-terminated strings */
@@ -1626,13 +1676,6 @@ devopen(const char *name, const char *mode)
cp[isi.remotehost.offset+isi.remotehost.len] = '\0';
/* remoteport comes last, so already NUL-terminated */
- {
-#define DEFAULT_RETRIES 20
- static unsigned long def_retries = DEFAULT_RETRIES;
- static bool first_time = true;
- unsigned long retries = 0;
- static long msleep = 1000;
-
if (first_time) {
char *cp, *end;
unsigned long count = 0;
@@ -1658,25 +1701,41 @@ devopen(const char *name, const char *mode)
msleep *= 1000;
}
}
- retries = def_retries;
+ /*
+ * PROCINFO["NONFATAL"] or PROCINFO[name, "NONFATAL"] overrrides
+ * GAWK_SOCK_RETRIES. The explicit code in the program carries
+ * a bigger stick than the environment variable does.
+ */
+ retries = non_fatal ? 1 : def_retries;
+ errno = 0;
do {
- openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset, name+isi.remoteport.offset, name+isi.remotehost.offset);
+ openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset,
+ name+isi.remoteport.offset, name+isi.remotehost.offset,
+ & hard_error);
retries--;
- } while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0);
- }
+ } while (openfd == INVALID_HANDLE && ! hard_error && retries > 0 && usleep(msleep) == 0);
+ save_errno = errno;
- /* restore original name string */
- cp[isi.localport.offset+isi.localport.len] = '/';
- cp[isi.remotehost.offset+isi.remotehost.len] = '/';
+ /* restore original name string */
+ cp[isi.localport.offset+isi.localport.len] = '/';
+ cp[isi.remotehost.offset+isi.remotehost.len] = '/';
#else /* ! HAVE_SOCKETS */
- fatal(_("TCP/IP communications are not supported"));
+ fatal(_("TCP/IP communications are not supported"));
#endif /* HAVE_SOCKETS */
}
strictopen:
- if (openfd == INVALID_HANDLE)
+ if (openfd == INVALID_HANDLE) {
openfd = open(name, flag, 0666);
+ /*
+ * ENOENT means there is no such name in the filesystem.
+ * Therefore it's ok to propagate up the error from
+ * getaddrinfo() that's in save_errno.
+ */
+ if (openfd == INVALID_HANDLE && errno == ENOENT && save_errno)
+ errno = save_errno;
+ }
#if defined(__EMX__) || defined(__MINGW32__)
if (openfd == INVALID_HANDLE && errno == EACCES) {
/* On OS/2 and Windows directory access via open() is
@@ -2421,7 +2480,7 @@ do_getline_redir(int into_variable, enum redirval redirtype)
assert(redirtype != redirect_none);
redir_exp = TOP();
- rp = redirect(redir_exp, redirtype, & redir_error);
+ rp = redirect(redir_exp, redirtype, & redir_error, false);
DEREF(redir_exp);
decr_sp();
if (rp == NULL) {
@@ -3656,8 +3715,10 @@ pty_vs_pipe(const char *command)
#ifdef HAVE_TERMIOS_H
NODE *val;
- if (PROCINFO_node == NULL)
- return false;
+ /*
+ * N.B. No need to check for NULL PROCINFO_node, since the
+ * in_PROCINFO function now checks that for us.
+ */
val = in_PROCINFO(command, "pty", NULL);
if (val) {
if ((val->flags & MAYBE_NUM) != 0)
@@ -3799,12 +3860,21 @@ in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx)
NODE *r, *sub = NULL;
NODE *subsep = SUBSEP_node->var_value;
+ if (PROCINFO_node == NULL || (pidx1 == NULL && pidx2 == NULL))
+ return NULL;
+
/* full_idx is in+out parameter */
if (full_idx)
sub = *full_idx;
- str_len = strlen(pidx1) + subsep->stlen + strlen(pidx2);
+ if (pidx1 != NULL && pidx2 == NULL)
+ str_len = strlen(pidx1);
+ else if (pidx1 == NULL && pidx2 != NULL)
+ str_len = strlen(pidx2);
+ else
+ str_len = strlen(pidx1) + subsep->stlen + strlen(pidx2);
+
if (sub == NULL) {
emalloc(str, char *, str_len + 1, "in_PROCINFO");
sub = make_str_node(str, str_len, ALREADY_MALLOCED);
@@ -3818,8 +3888,14 @@ in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx)
sub->stlen = str_len;
}
- sprintf(sub->stptr, "%s%.*s%s", pidx1, (int)subsep->stlen,
- subsep->stptr, pidx2);
+ if (pidx1 != NULL && pidx2 == NULL)
+ strcpy(sub->stptr, pidx1);
+ else if (pidx1 == NULL && pidx2 != NULL)
+ strcpy(sub->stptr, pidx2);
+ else
+ sprintf(sub->stptr, "%s%.*s%s", pidx1, (int)subsep->stlen,
+ subsep->stptr, pidx2);
+
r = in_array(PROCINFO_node, sub);
if (! full_idx)
unref(sub);
diff --git a/missing_d/ChangeLog b/missing_d/ChangeLog
index 70fbde64..89dbdb4d 100644
--- a/missing_d/ChangeLog
+++ b/missing_d/ChangeLog
@@ -1,3 +1,9 @@
+2015-02-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * getaddrinfo.h (gai_strerror): Add declaration.
+ * getaddrinfo.c (gai_strerror): New function.
+ (getaddrinfo): Return errno values instead of just -1.
+
2014-04-08 Arnold D. Robbins <arnold@skeeve.com>
* 4.1.1: Release tar ball made.
diff --git a/missing_d/getaddrinfo.c b/missing_d/getaddrinfo.c
index 677f27d0..f24ac598 100644
--- a/missing_d/getaddrinfo.c
+++ b/missing_d/getaddrinfo.c
@@ -12,6 +12,8 @@
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
+#include <errno.h>
+#include <string.h> /* strerror */
#include "getaddrinfo.h"
@@ -29,12 +31,12 @@ getaddrinfo(const char *hostname, const char *portname,
{
struct addrinfo *out;
if (res == NULL)
- return -1;
+ return EINVAL;
out = (struct addrinfo *) malloc(sizeof(*out));
if (out == NULL) {
*res = NULL;
- return -1;
+ return ENOMEM;
}
memset(out, '\0', sizeof(*out));
@@ -42,7 +44,7 @@ getaddrinfo(const char *hostname, const char *portname,
if (out->ai_addr == NULL) {
free(out);
*res = NULL;
- return -1;
+ return ENOMEM;
}
out->ai_socktype = SOCK_STREAM;
@@ -78,7 +80,7 @@ getaddrinfo(const char *hostname, const char *portname,
= ((struct in_addr *)he->h_addr_list[0])->s_addr;
} else {
freeaddrinfo(out);
- return -1;
+ return EADDRNOTAVAIL;
}
} else {
if (!(out->ai_flags & AI_PASSIVE))
@@ -109,4 +111,10 @@ getaddrinfo(const char *hostname, const char *portname,
return 0;
}
+
+const char *
+gai_strerror(int errcode)
+{
+ return strerror(errcode);
+}
#endif
diff --git a/missing_d/getaddrinfo.h b/missing_d/getaddrinfo.h
index 3d816c93..873d67df 100644
--- a/missing_d/getaddrinfo.h
+++ b/missing_d/getaddrinfo.h
@@ -29,3 +29,5 @@ void freeaddrinfo(struct xaddrinfo * res);
int getaddrinfo(const char * hostname, const char * portname,
struct xaddrinfo * hints, struct xaddrinfo ** res);
+
+const char *gai_strerror(int errcode);
diff --git a/test/ChangeLog b/test/ChangeLog
index a5c77c69..2652429f 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -3,6 +3,27 @@
* charasbytes.awk, ofs1.awk, range1.awk, sortglos.awk,
sortglos.in: Remove execute permission.
+2015-03-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * nonfatal1.awk: Do not print ERRNO, since the value appears to be
+ platform-dependent. Instead, print (ERRNO != "").
+ * nonfatal1.ok: Update.
+
+2015-02-28 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (EXTRA_DIST): Add nonfatal3.{awk,ok}.
+ (GAWK_EXT_TESTS): Add nonfatal3.
+ * nonfatal1.awk: Replace "ti10/357" with "local:host/25", since
+ "local:host" should be a universally bad hostname due to the
+ invalid ":" character.
+ * nonfatal1.ok: Update.
+ * nonfatal3.{awk,ok}: New test for connecting to a TCP port where
+ nobody is listening.
+
+2015-02-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ * nonfatal1.ok: Update after code changes.
+
2015-02-26 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (EXTRA_DIST): Add profile0.in which got forgotten
@@ -18,6 +39,16 @@
* Makefile.am (profile0): New test.
* profile0.awk, profile0.in, profile0.ok: New files.
+2015-02-08 Arnold D. Robbins <arnold@skeeve.com>
+
+ * nonfatal1.awk, nonfatal2.awk: String is now "NONFATAL".
+
+2015-02-06 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (nonfatal1, nonfatal2): New tests.
+ * nonfatal1.awk, nonfatal1.ok: New files.
+ * nonfatal2.awk, nonfatal2.ok: New files.
+
2015-02-01 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (paramasfunc1, paramasfunc2): Now need --posix.
diff --git a/test/Makefile.am b/test/Makefile.am
index e752865a..15656ce6 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -599,6 +599,12 @@ EXTRA_DIST = \
nondec.ok \
nondec2.awk \
nondec2.ok \
+ nonfatal1.awk \
+ nonfatal1.ok \
+ nonfatal2.awk \
+ nonfatal2.ok \
+ nonfatal3.awk \
+ nonfatal3.ok \
nonl.awk \
nonl.ok \
noparms.awk \
@@ -1047,6 +1053,7 @@ GAWK_EXT_TESTS = \
lint lintold lintwarn \
manyfiles match1 match2 match3 mbstr1 \
nastyparm next nondec nondec2 \
+ nonfatal1 nonfatal2 nonfatal3 \
patsplit posix printfbad1 printfbad2 printfbad3 printfbad4 printhuge procinfs \
profile0 profile1 profile2 profile3 profile4 profile5 profile6 profile7 \
profile8 pty1 \
diff --git a/test/Makefile.in b/test/Makefile.in
index 0c00973c..87f9bf56 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -856,6 +856,12 @@ EXTRA_DIST = \
nondec.ok \
nondec2.awk \
nondec2.ok \
+ nonfatal1.awk \
+ nonfatal1.ok \
+ nonfatal2.awk \
+ nonfatal2.ok \
+ nonfatal3.awk \
+ nonfatal3.ok \
nonl.awk \
nonl.ok \
noparms.awk \
@@ -1303,6 +1309,7 @@ GAWK_EXT_TESTS = \
lint lintold lintwarn \
manyfiles match1 match2 match3 mbstr1 \
nastyparm next nondec nondec2 \
+ nonfatal1 nonfatal2 nonfatal3 \
patsplit posix printfbad1 printfbad2 printfbad3 printfbad4 printhuge procinfs \
profile0 profile1 profile2 profile3 profile4 profile5 profile6 profile7 \
profile8 pty1 \
@@ -3636,6 +3643,21 @@ nondec:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+nonfatal1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nonfatal2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nonfatal3:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
patsplit:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/Maketests b/test/Maketests
index adf95cc5..a2937451 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1152,6 +1152,21 @@ nondec:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+nonfatal1:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nonfatal2:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+nonfatal3:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
patsplit:
@echo $@
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
diff --git a/test/nonfatal1.awk b/test/nonfatal1.awk
new file mode 100644
index 00000000..a9228f3a
--- /dev/null
+++ b/test/nonfatal1.awk
@@ -0,0 +1,6 @@
+BEGIN {
+ PROCINFO["NONFATAL"]
+ # note that ":" is not a valid hostname character
+ print |& "/inet/tcp/0/local:host/25"
+ print (ERRNO != "")
+}
diff --git a/test/nonfatal1.ok b/test/nonfatal1.ok
new file mode 100644
index 00000000..51583f2c
--- /dev/null
+++ b/test/nonfatal1.ok
@@ -0,0 +1,2 @@
+gawk: nonfatal1.awk:4: warning: remote host and port information (local:host, 25) invalid
+1
diff --git a/test/nonfatal2.awk b/test/nonfatal2.awk
new file mode 100644
index 00000000..fedbba43
--- /dev/null
+++ b/test/nonfatal2.awk
@@ -0,0 +1,5 @@
+BEGIN {
+ PROCINFO["NONFATAL"] = 1
+ print > "/dev/no/such/file"
+ print ERRNO
+}
diff --git a/test/nonfatal2.ok b/test/nonfatal2.ok
new file mode 100644
index 00000000..ddc88691
--- /dev/null
+++ b/test/nonfatal2.ok
@@ -0,0 +1 @@
+No such file or directory
diff --git a/test/nonfatal3.awk b/test/nonfatal3.awk
new file mode 100644
index 00000000..eace9aec
--- /dev/null
+++ b/test/nonfatal3.awk
@@ -0,0 +1,6 @@
+BEGIN {
+ PROCINFO["NONFATAL"]
+ # valid host but bogus port
+ print |& "/inet/tcp/0/localhost/0"
+ print ERRNO
+}
diff --git a/test/nonfatal3.ok b/test/nonfatal3.ok
new file mode 100644
index 00000000..5d5be35a
--- /dev/null
+++ b/test/nonfatal3.ok
@@ -0,0 +1 @@
+Connection refused