aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog176
-rw-r--r--awk.h2
-rw-r--r--awkgram.c721
-rw-r--r--awkgram.y3
-rw-r--r--configh.in6
-rwxr-xr-xconfigure5
-rw-r--r--configure.ac5
-rw-r--r--doc/ChangeLog19
-rw-r--r--doc/gawk.145
-rw-r--r--doc/gawk.info1340
-rw-r--r--doc/gawk.texi115
-rw-r--r--doc/gawktexi.in115
-rw-r--r--eval.c4
-rw-r--r--extension/ChangeLog170
-rw-r--r--extension/testext.c193
-rw-r--r--gawkapi.c96
-rw-r--r--gawkapi.h40
-rw-r--r--io.c160
-rw-r--r--test/ChangeLog32
-rw-r--r--test/Makefile.am31
-rw-r--r--test/Makefile.in36
-rw-r--r--test/Maketests5
-rw-r--r--test/defvar.awk3
-rw-r--r--test/defvar.ok5
-rw-r--r--test/errno.awk10
-rw-r--r--test/errno.in3
-rw-r--r--test/errno.ok3
-rw-r--r--test/getfile.awk35
-rw-r--r--test/getfile.ok17
-rw-r--r--test/testext.ok6
-rw-r--r--test/timeout.awk26
-rw-r--r--test/timeout.ok12
32 files changed, 2424 insertions, 1015 deletions
diff --git a/ChangeLog b/ChangeLog
index 75a049da..5a9f4b4a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -33,6 +33,22 @@
* builtin.c (do_length): Update comment.
* main.c (init_vars): Just call load_procinfo() and `load_environ()'.
+2015-01-08 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ Revert changes to API deferred variable creation -- these variables
+ should be created when lookup is called, not when update is called.
+ * awk.h (variable_create): Remove function declaration.
+ * awkgram.y (variable_create): Remove function.
+ (variable): Restore variable_create functionality inline.
+ * gawkapi.c (api_sym_update): Revert to using install_symbol, since the
+ deferred variable check should be done when lookup is called, not here.
+
+2015-01-07 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.c (api_set_array_element): Remove stray call to
+ make_aname. I cannot see what purpose this served. Maybe I am
+ missing something.
+
2015-01-07 Arnold D. Robbins <arnold@skeeve.com>
* configure.ac: Update debug flags if developing.
@@ -51,6 +67,59 @@
(do_add_scrfile): Set it on -l.
(process_deferred): Check it also.
+2015-01-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.c (api_sym_update): If copying a subarray, must update
+ the parent_array pointer. Also, call the astore hook if non-NULL.
+ (api_set_array_element): Call the astore hook if non-NULL.
+
+2015-01-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * awk.h (variable_create): Now takes a 3rd argument to tell caller
+ whether this is a deferred variable.
+ * awkgram.y (variable_create): Return indicator of whether this is
+ a deferred variable in a newly added 3rd arg.
+ (variable): Pass 3rd arg to variable_create.
+ * gawkapi.c (api_sym_update): If we triggered the creation of a deferred
+ variable, we must merge the extension's array elements into the deffered
+ array, not the other way around. The ENVIRON array has special funcs
+ to call setenv and unsetenv.
+
+2015-01-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * awk.h (variable_create): Declare new function.
+ * awkgram.y (variable_create): New function to create a variable
+ taking the deferred variable list into consideration.
+ (variable): Call new function variable_create if the variable is
+ not found.
+ * gawkapi.c (api_sym_update): If an array is being created, then
+ call new function variable_create instead of install_symbol. If this
+ is the first reference to a deferred variable, than the new array
+ may contain elements that must be merged into the array provided by
+ the extension.
+
+2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * io.c (wait_any): If the `interesting' argument is non-zero, then we
+ must not return until that child process has exited, since the caller
+ gawk_pclose depends on our returning its exit status. So in that case,
+ do not pass WNOHANG to waitpid.
+
+2015-01-04 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h: Fix another comment typo.
+
+2015-01-04 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h: Fix typo in comment.
+
+2015-01-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h (gawk_api): Modify api_get_file to remove the typelen
+ argument.
+ (get_file): Remove typelen argument from the macro.
+ * gawkapi.c (api_get_file): Remove typelen argument.
+
2014-12-24 Arnold D. Robbins <arnold@skeeve.com>
* profile.c (pprint): Be sure to set ip2 in all paths
@@ -177,6 +246,36 @@
and a it's a Node_val set to Nnull_string, return AWK_UNDEFINED instead
of AWK_NUMBER 0.
+2014-11-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * awk.h (redirect_string): First argument should be const. Add a new
+ extfd argument to enable extensions to create files with pre-opened
+ file descriptors.
+ (after_beginfile): Declare function used in both eval.c and gawkapi.c.
+ * eval.c (after_beginfile): Remove extern declaration now in awk.h.
+ * gawkapi.c (api_get_file): Implement API changes to return
+ awk_input_buf_t and/or awk_output_buf_t info, as well as accept an
+ fd for inserting an opened file into the table.
+ * gawkapi.h (gawk_api): Modify the api_get_file declaration to
+ return awk_bool_t and add 3 new arguments -- a file descriptor
+ for inserting an already opened file, and awk_input_buf_t and
+ awk_output_buf_t to return info about both input and output.
+ (get_file): Add new arguments to the macro.
+ * io.c (redirect_string): First arg should be const, and add a new
+ extfd arg so extensions can pass in a file that has already been
+ opened by the extension. Use the passed-in fd when appropriate,
+ and pass it into two_way_open.
+ (redirect): Pass new fd -1 arg to redirect_string.
+ (two_way_open): Accept new extension fd parameter and open it
+ as a socket.
+
+2014-11-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * io.c (retryable): New function to indicate whether I/O can be
+ retried for this file instead of throwing a hard error.
+ (get_a_record) Check whether this file is configured for retryable
+ I/O before returning nonstandard -2.
+
2014-11-03 Norihiro Tanaka <noritnk@kcn.ne.jp>
* re.c (research): Use dfa superset to improve matching speed.
@@ -1345,6 +1444,45 @@
* io.c (get_a_record): Change `min' to `MIN' for consistency with
other files and general practice.
+2013-07-07 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * configure.ac (AC_CHECK_FUNCS): Check for sigprocmask.
+ * io.c (wait_any): If sigprocmask is available, block signals instead
+ of ignoring them temporarily.
+
+2013-07-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h (gawk_api): Document that the api_get_file function will not
+ access the file type and length arguments if the file name is empty.
+
+2013-07-04 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * configure.ac (AC_CHECK_FUNCS): Add a check for waitpid.
+ * io.c (wait_any): Enhance comment to explain why we loop reaping all
+ exited children when the argument is zero. When available, use waitpid
+ with WNOHANG to avoid blocking. Remove my previous incorrect patch to
+ exit after reaping the first child. The function is intended to
+ wait for all children, since we are not careful about reaping children
+ as soon as they die.
+
+2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h (gawk_api): Remove unused api_lookup_file hook.
+ (lookup_file): Remove associated macro.
+ * gawkapi.c (api_lookup_file): Remove unused function.
+ (api_impl): Remove unused api_lookup_file hook.
+
+2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * awkgram.y (main_beginfile): Declare new global INSTRUCTION *.
+ (parse_program): Set main_beginfile to point to the BEGINFILE
+ instruction block.
+ * gawkapi.c (api_get_file): After nextfile starts a new file,
+ we need to run the BEGINFILE actions. We retrieve the
+ instruction pointer from main_beginfile and execute it until
+ we reach the Op_after_beginfile opcode. We then run after_beginfile
+ manually and restore the value of currule and source.
+
2013-07-04 Andrew J. Schorr <aschorr@telemetry-investments.com>
* gawkapi.h (awk_element_t): Add comment indicating that the array
@@ -1355,6 +1493,44 @@
force_string redundant, since node_to_awk_value does that internally
when we request a string.
+2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * eval.c (update_ERRNO_string): Set PROCINFO["errno"] to 0.
+ * io.c (inrec): Since get_a_record may now return -2, be sure
+ to throw an error in that case as well.
+ (wait_any): Fix what appears to be a bug. The old logic repeatedly
+ called wait until it failed. When a process has multiple children,
+ this causes it to stall until all of them have exited. Instead,
+ we now exit the function after the first successful wait call.
+ (do_getline_redir, do_getline): Handle case where get_a_record
+ returns -2.
+ (errno_io_retry): New function to decide whether an I/O operation should
+ be retried.
+ (get_a_record): When read returns an error, call errno_io_retry to
+ decide whether the operation should be retried. If so, return -2
+ instead of setting the IOP_AT_EOF flag.
+
+2013-07-01 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * eval.c (update_ERRNO_int, unset_ERRNO): Update PROCINFO["errno"].
+
+2013-06-30 Andrew J. Schorr <aschorr@telemetry-investments.com>
+ * awk.h (redirect_string): Declare new function that provides API access
+ to the redirection mechanism.
+ * gawkapi.h (GAWK_API_MINOR_VERSION): Bump from 0 to 1 since 2 new
+ hooks were added to the api.
+ (gawk_api_t): Add 2 new functions api_lookup_file and api_get_file.
+ (lookup_file, get_file): New macros to wrap the new API functions.
+ * gawkapi.c (curfile): Declare this extern, since it is needed
+ by lookup_file and get_flie.
+ (api_lookup_file): Find an open file using curfile or getredirect().
+ (api_get_file): Find or open a file using curfile or redirect_string().
+ (api_impl): Add api_lookup_file and api_get_file.
+ * io.c (redirect_string): Renamed from redirect and changed arguments
+ to take a string instead of a 'NODE *'. This allows it to be called
+ through the API's new get_file hook.
+ (redirect): Now implemented by calling redirect_string backend function.
+
2013-07-04 Arnold D. Robbins <arnold@skeeve.com>
* builtin.c (format_tree): Fixes for %c with multibyte characters
diff --git a/awk.h b/awk.h
index 74cc3c21..52a43c99 100644
--- a/awk.h
+++ b/awk.h
@@ -1483,6 +1483,7 @@ 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_string(const char *redir_exp_str, size_t redir_exp_len, int not_string_flag, int redirtype, int *errflg, int extfd);
extern NODE *do_close(int nargs);
extern int flush_io(void);
extern int close_io(bool *stdio_problem);
@@ -1501,6 +1502,7 @@ extern int is_off_limits_var(const char *var);
extern char *estrdup(const char *str, size_t len);
extern void update_global_values();
extern long getenv_long(const char *name);
+extern void after_beginfile(IOBUF **curfile);
/* mpfr.c */
extern void set_PREC(void);
diff --git a/awkgram.c b/awkgram.c
index 6cc78686..770c96d2 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -183,6 +183,7 @@ static INSTRUCTION *ip_atexit = NULL;
static INSTRUCTION *ip_end;
static INSTRUCTION *ip_endfile;
static INSTRUCTION *ip_beginfile;
+INSTRUCTION *main_beginfile;
static INSTRUCTION *comment = NULL;
static INSTRUCTION *program_comment = NULL;
@@ -201,7 +202,7 @@ extern double fmod(double x, double y);
#define YYSTYPE INSTRUCTION *
-#line 205 "awkgram.c" /* yacc.c:339 */
+#line 206 "awkgram.c" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
@@ -355,7 +356,7 @@ int yyparse (void);
/* Copy the second part of user declarations. */
-#line 359 "awkgram.c" /* yacc.c:358 */
+#line 360 "awkgram.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -657,25 +658,25 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 204, 204, 206, 211, 212, 216, 228, 233, 244,
- 250, 255, 263, 271, 273, 278, 286, 288, 294, 302,
- 312, 342, 356, 370, 378, 389, 401, 403, 405, 411,
- 416, 417, 421, 456, 455, 489, 491, 496, 502, 530,
- 535, 536, 540, 542, 544, 551, 641, 683, 725, 838,
- 845, 852, 862, 871, 880, 889, 900, 916, 915, 939,
- 951, 951, 1049, 1049, 1082, 1112, 1118, 1119, 1125, 1126,
- 1133, 1138, 1150, 1164, 1166, 1174, 1179, 1181, 1189, 1191,
- 1200, 1201, 1209, 1214, 1214, 1225, 1229, 1237, 1238, 1241,
- 1243, 1248, 1249, 1258, 1259, 1264, 1269, 1275, 1277, 1279,
- 1286, 1287, 1293, 1294, 1299, 1301, 1306, 1308, 1316, 1321,
- 1330, 1337, 1339, 1341, 1357, 1367, 1374, 1376, 1381, 1383,
- 1385, 1393, 1395, 1400, 1402, 1407, 1409, 1411, 1461, 1463,
- 1465, 1467, 1469, 1471, 1473, 1475, 1489, 1494, 1499, 1524,
- 1530, 1532, 1534, 1536, 1538, 1540, 1545, 1549, 1581, 1583,
- 1589, 1595, 1608, 1609, 1610, 1615, 1620, 1624, 1628, 1643,
- 1656, 1661, 1697, 1715, 1716, 1722, 1723, 1728, 1730, 1737,
- 1754, 1771, 1773, 1780, 1785, 1793, 1803, 1815, 1824, 1828,
- 1832, 1836, 1840, 1844, 1847, 1849, 1853, 1857, 1861
+ 0, 205, 205, 207, 212, 213, 217, 229, 234, 245,
+ 251, 256, 264, 272, 274, 279, 287, 289, 295, 303,
+ 313, 343, 357, 371, 379, 390, 402, 404, 406, 412,
+ 417, 418, 422, 457, 456, 490, 492, 497, 503, 531,
+ 536, 537, 541, 543, 545, 552, 642, 684, 726, 839,
+ 846, 853, 863, 872, 881, 890, 901, 917, 916, 940,
+ 952, 952, 1050, 1050, 1083, 1113, 1119, 1120, 1126, 1127,
+ 1134, 1139, 1151, 1165, 1167, 1175, 1180, 1182, 1190, 1192,
+ 1201, 1202, 1210, 1215, 1215, 1226, 1230, 1238, 1239, 1242,
+ 1244, 1249, 1250, 1259, 1260, 1265, 1270, 1276, 1278, 1280,
+ 1287, 1288, 1294, 1295, 1300, 1302, 1307, 1309, 1317, 1322,
+ 1331, 1338, 1340, 1342, 1358, 1368, 1375, 1377, 1382, 1384,
+ 1386, 1394, 1396, 1401, 1403, 1408, 1410, 1412, 1462, 1464,
+ 1466, 1468, 1470, 1472, 1474, 1476, 1490, 1495, 1500, 1525,
+ 1531, 1533, 1535, 1537, 1539, 1541, 1546, 1550, 1582, 1584,
+ 1590, 1596, 1609, 1610, 1611, 1616, 1621, 1625, 1629, 1644,
+ 1657, 1662, 1698, 1716, 1717, 1723, 1724, 1729, 1731, 1738,
+ 1755, 1772, 1774, 1781, 1786, 1794, 1804, 1816, 1825, 1829,
+ 1833, 1837, 1841, 1845, 1848, 1850, 1854, 1858, 1862
};
#endif
@@ -1848,24 +1849,24 @@ yyreduce:
switch (yyn)
{
case 3:
-#line 207 "awkgram.y" /* yacc.c:1646 */
+#line 208 "awkgram.y" /* yacc.c:1646 */
{
rule = 0;
yyerrok;
}
-#line 1857 "awkgram.c" /* yacc.c:1646 */
+#line 1858 "awkgram.c" /* yacc.c:1646 */
break;
case 5:
-#line 213 "awkgram.y" /* yacc.c:1646 */
+#line 214 "awkgram.y" /* yacc.c:1646 */
{
next_sourcefile();
}
-#line 1865 "awkgram.c" /* yacc.c:1646 */
+#line 1866 "awkgram.c" /* yacc.c:1646 */
break;
case 6:
-#line 217 "awkgram.y" /* yacc.c:1646 */
+#line 218 "awkgram.y" /* yacc.c:1646 */
{
rule = 0;
/*
@@ -1874,20 +1875,20 @@ yyreduce:
*/
/* yyerrok; */
}
-#line 1878 "awkgram.c" /* yacc.c:1646 */
+#line 1879 "awkgram.c" /* yacc.c:1646 */
break;
case 7:
-#line 229 "awkgram.y" /* yacc.c:1646 */
+#line 230 "awkgram.y" /* yacc.c:1646 */
{
(void) append_rule((yyvsp[-1]), (yyvsp[0]));
first_rule = false;
}
-#line 1887 "awkgram.c" /* yacc.c:1646 */
+#line 1888 "awkgram.c" /* yacc.c:1646 */
break;
case 8:
-#line 234 "awkgram.y" /* yacc.c:1646 */
+#line 235 "awkgram.y" /* yacc.c:1646 */
{
if (rule != Rule) {
msg(_("%s blocks must have an action part"), ruletab[rule]);
@@ -1898,39 +1899,39 @@ yyreduce:
} else /* pattern rule with non-empty pattern */
(void) append_rule((yyvsp[-1]), NULL);
}
-#line 1902 "awkgram.c" /* yacc.c:1646 */
+#line 1903 "awkgram.c" /* yacc.c:1646 */
break;
case 9:
-#line 245 "awkgram.y" /* yacc.c:1646 */
+#line 246 "awkgram.y" /* yacc.c:1646 */
{
in_function = NULL;
(void) mk_function((yyvsp[-1]), (yyvsp[0]));
yyerrok;
}
-#line 1912 "awkgram.c" /* yacc.c:1646 */
+#line 1913 "awkgram.c" /* yacc.c:1646 */
break;
case 10:
-#line 251 "awkgram.y" /* yacc.c:1646 */
+#line 252 "awkgram.y" /* yacc.c:1646 */
{
want_source = false;
yyerrok;
}
-#line 1921 "awkgram.c" /* yacc.c:1646 */
+#line 1922 "awkgram.c" /* yacc.c:1646 */
break;
case 11:
-#line 256 "awkgram.y" /* yacc.c:1646 */
+#line 257 "awkgram.y" /* yacc.c:1646 */
{
want_source = false;
yyerrok;
}
-#line 1930 "awkgram.c" /* yacc.c:1646 */
+#line 1931 "awkgram.c" /* yacc.c:1646 */
break;
case 12:
-#line 264 "awkgram.y" /* yacc.c:1646 */
+#line 265 "awkgram.y" /* yacc.c:1646 */
{
if (include_source((yyvsp[0])) < 0)
YYABORT;
@@ -1938,23 +1939,23 @@ yyreduce:
bcfree((yyvsp[0]));
(yyval) = NULL;
}
-#line 1942 "awkgram.c" /* yacc.c:1646 */
+#line 1943 "awkgram.c" /* yacc.c:1646 */
break;
case 13:
-#line 272 "awkgram.y" /* yacc.c:1646 */
+#line 273 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 1948 "awkgram.c" /* yacc.c:1646 */
+#line 1949 "awkgram.c" /* yacc.c:1646 */
break;
case 14:
-#line 274 "awkgram.y" /* yacc.c:1646 */
+#line 275 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 1954 "awkgram.c" /* yacc.c:1646 */
+#line 1955 "awkgram.c" /* yacc.c:1646 */
break;
case 15:
-#line 279 "awkgram.y" /* yacc.c:1646 */
+#line 280 "awkgram.y" /* yacc.c:1646 */
{
if (load_library((yyvsp[0])) < 0)
YYABORT;
@@ -1962,23 +1963,23 @@ yyreduce:
bcfree((yyvsp[0]));
(yyval) = NULL;
}
-#line 1966 "awkgram.c" /* yacc.c:1646 */
+#line 1967 "awkgram.c" /* yacc.c:1646 */
break;
case 16:
-#line 287 "awkgram.y" /* yacc.c:1646 */
+#line 288 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 1972 "awkgram.c" /* yacc.c:1646 */
+#line 1973 "awkgram.c" /* yacc.c:1646 */
break;
case 17:
-#line 289 "awkgram.y" /* yacc.c:1646 */
+#line 290 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 1978 "awkgram.c" /* yacc.c:1646 */
+#line 1979 "awkgram.c" /* yacc.c:1646 */
break;
case 18:
-#line 294 "awkgram.y" /* yacc.c:1646 */
+#line 295 "awkgram.y" /* yacc.c:1646 */
{
rule = Rule;
if (comment != NULL) {
@@ -1987,11 +1988,11 @@ yyreduce:
} else
(yyval) = NULL;
}
-#line 1991 "awkgram.c" /* yacc.c:1646 */
+#line 1992 "awkgram.c" /* yacc.c:1646 */
break;
case 19:
-#line 303 "awkgram.y" /* yacc.c:1646 */
+#line 304 "awkgram.y" /* yacc.c:1646 */
{
rule = Rule;
if (comment != NULL) {
@@ -2000,11 +2001,11 @@ yyreduce:
} else
(yyval) = (yyvsp[0]);
}
-#line 2004 "awkgram.c" /* yacc.c:1646 */
+#line 2005 "awkgram.c" /* yacc.c:1646 */
break;
case 20:
-#line 313 "awkgram.y" /* yacc.c:1646 */
+#line 314 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *tp;
@@ -2034,11 +2035,11 @@ yyreduce:
(yyval) = list_append(list_merge((yyvsp[-3]), (yyvsp[0])), tp);
rule = Rule;
}
-#line 2038 "awkgram.c" /* yacc.c:1646 */
+#line 2039 "awkgram.c" /* yacc.c:1646 */
break;
case 21:
-#line 343 "awkgram.y" /* yacc.c:1646 */
+#line 344 "awkgram.y" /* yacc.c:1646 */
{
static int begin_seen = 0;
@@ -2052,11 +2053,11 @@ yyreduce:
check_comment();
(yyval) = (yyvsp[0]);
}
-#line 2056 "awkgram.c" /* yacc.c:1646 */
+#line 2057 "awkgram.c" /* yacc.c:1646 */
break;
case 22:
-#line 357 "awkgram.y" /* yacc.c:1646 */
+#line 358 "awkgram.y" /* yacc.c:1646 */
{
static int end_seen = 0;
@@ -2070,11 +2071,11 @@ yyreduce:
check_comment();
(yyval) = (yyvsp[0]);
}
-#line 2074 "awkgram.c" /* yacc.c:1646 */
+#line 2075 "awkgram.c" /* yacc.c:1646 */
break;
case 23:
-#line 371 "awkgram.y" /* yacc.c:1646 */
+#line 372 "awkgram.y" /* yacc.c:1646 */
{
func_first = false;
(yyvsp[0])->in_rule = rule = BEGINFILE;
@@ -2082,11 +2083,11 @@ yyreduce:
check_comment();
(yyval) = (yyvsp[0]);
}
-#line 2086 "awkgram.c" /* yacc.c:1646 */
+#line 2087 "awkgram.c" /* yacc.c:1646 */
break;
case 24:
-#line 379 "awkgram.y" /* yacc.c:1646 */
+#line 380 "awkgram.y" /* yacc.c:1646 */
{
func_first = false;
(yyvsp[0])->in_rule = rule = ENDFILE;
@@ -2094,11 +2095,11 @@ yyreduce:
check_comment();
(yyval) = (yyvsp[0]);
}
-#line 2098 "awkgram.c" /* yacc.c:1646 */
+#line 2099 "awkgram.c" /* yacc.c:1646 */
break;
case 25:
-#line 390 "awkgram.y" /* yacc.c:1646 */
+#line 391 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *ip;
if ((yyvsp[-3]) == NULL)
@@ -2107,39 +2108,39 @@ yyreduce:
ip = (yyvsp[-3]);
(yyval) = ip;
}
-#line 2111 "awkgram.c" /* yacc.c:1646 */
+#line 2112 "awkgram.c" /* yacc.c:1646 */
break;
case 26:
-#line 402 "awkgram.y" /* yacc.c:1646 */
+#line 403 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2117 "awkgram.c" /* yacc.c:1646 */
+#line 2118 "awkgram.c" /* yacc.c:1646 */
break;
case 27:
-#line 404 "awkgram.y" /* yacc.c:1646 */
+#line 405 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2123 "awkgram.c" /* yacc.c:1646 */
+#line 2124 "awkgram.c" /* yacc.c:1646 */
break;
case 28:
-#line 406 "awkgram.y" /* yacc.c:1646 */
+#line 407 "awkgram.y" /* yacc.c:1646 */
{
yyerror(_("`%s' is a built-in function, it cannot be redefined"),
tokstart);
YYABORT;
}
-#line 2133 "awkgram.c" /* yacc.c:1646 */
+#line 2134 "awkgram.c" /* yacc.c:1646 */
break;
case 29:
-#line 412 "awkgram.y" /* yacc.c:1646 */
+#line 413 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2139 "awkgram.c" /* yacc.c:1646 */
+#line 2140 "awkgram.c" /* yacc.c:1646 */
break;
case 32:
-#line 422 "awkgram.y" /* yacc.c:1646 */
+#line 423 "awkgram.y" /* yacc.c:1646 */
{
/*
* treat any comments between BOF and the first function
@@ -2166,17 +2167,17 @@ yyreduce:
/* $4 already free'd in install_function */
(yyval) = (yyvsp[-5]);
}
-#line 2170 "awkgram.c" /* yacc.c:1646 */
+#line 2171 "awkgram.c" /* yacc.c:1646 */
break;
case 33:
-#line 456 "awkgram.y" /* yacc.c:1646 */
+#line 457 "awkgram.y" /* yacc.c:1646 */
{ want_regexp = true; }
-#line 2176 "awkgram.c" /* yacc.c:1646 */
+#line 2177 "awkgram.c" /* yacc.c:1646 */
break;
case 34:
-#line 458 "awkgram.y" /* yacc.c:1646 */
+#line 459 "awkgram.y" /* yacc.c:1646 */
{
NODE *n, *exp;
char *re;
@@ -2205,28 +2206,28 @@ yyreduce:
(yyval)->opcode = Op_match_rec;
(yyval)->memory = n;
}
-#line 2209 "awkgram.c" /* yacc.c:1646 */
+#line 2210 "awkgram.c" /* yacc.c:1646 */
break;
case 35:
-#line 490 "awkgram.y" /* yacc.c:1646 */
+#line 491 "awkgram.y" /* yacc.c:1646 */
{ bcfree((yyvsp[0])); }
-#line 2215 "awkgram.c" /* yacc.c:1646 */
+#line 2216 "awkgram.c" /* yacc.c:1646 */
break;
case 37:
-#line 496 "awkgram.y" /* yacc.c:1646 */
+#line 497 "awkgram.y" /* yacc.c:1646 */
{
if (comment != NULL) {
(yyval) = list_create(comment);
comment = NULL;
} else (yyval) = NULL;
}
-#line 2226 "awkgram.c" /* yacc.c:1646 */
+#line 2227 "awkgram.c" /* yacc.c:1646 */
break;
case 38:
-#line 503 "awkgram.y" /* yacc.c:1646 */
+#line 504 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[0]) == NULL) {
if (comment == NULL)
@@ -2254,40 +2255,40 @@ yyreduce:
}
yyerrok;
}
-#line 2258 "awkgram.c" /* yacc.c:1646 */
+#line 2259 "awkgram.c" /* yacc.c:1646 */
break;
case 39:
-#line 531 "awkgram.y" /* yacc.c:1646 */
+#line 532 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2264 "awkgram.c" /* yacc.c:1646 */
+#line 2265 "awkgram.c" /* yacc.c:1646 */
break;
case 42:
-#line 541 "awkgram.y" /* yacc.c:1646 */
+#line 542 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2270 "awkgram.c" /* yacc.c:1646 */
+#line 2271 "awkgram.c" /* yacc.c:1646 */
break;
case 43:
-#line 543 "awkgram.y" /* yacc.c:1646 */
+#line 544 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 2276 "awkgram.c" /* yacc.c:1646 */
+#line 2277 "awkgram.c" /* yacc.c:1646 */
break;
case 44:
-#line 545 "awkgram.y" /* yacc.c:1646 */
+#line 546 "awkgram.y" /* yacc.c:1646 */
{
if (do_pretty_print)
(yyval) = list_prepend((yyvsp[0]), instruction(Op_exec_count));
else
(yyval) = (yyvsp[0]);
}
-#line 2287 "awkgram.c" /* yacc.c:1646 */
+#line 2288 "awkgram.c" /* yacc.c:1646 */
break;
case 45:
-#line 552 "awkgram.y" /* yacc.c:1646 */
+#line 553 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *dflt, *curr = NULL, *cexp, *cstmt;
INSTRUCTION *ip, *nextc, *tbreak;
@@ -2377,11 +2378,11 @@ yyreduce:
break_allowed--;
fix_break_continue(ip, tbreak, NULL);
}
-#line 2381 "awkgram.c" /* yacc.c:1646 */
+#line 2382 "awkgram.c" /* yacc.c:1646 */
break;
case 46:
-#line 642 "awkgram.y" /* yacc.c:1646 */
+#line 643 "awkgram.y" /* yacc.c:1646 */
{
/*
* -----------------
@@ -2423,11 +2424,11 @@ yyreduce:
continue_allowed--;
fix_break_continue(ip, tbreak, tcont);
}
-#line 2427 "awkgram.c" /* yacc.c:1646 */
+#line 2428 "awkgram.c" /* yacc.c:1646 */
break;
case 47:
-#line 684 "awkgram.y" /* yacc.c:1646 */
+#line 685 "awkgram.y" /* yacc.c:1646 */
{
/*
* -----------------
@@ -2469,11 +2470,11 @@ yyreduce:
} /* else
$1 and $4 are NULLs */
}
-#line 2473 "awkgram.c" /* yacc.c:1646 */
+#line 2474 "awkgram.c" /* yacc.c:1646 */
break;
case 48:
-#line 726 "awkgram.y" /* yacc.c:1646 */
+#line 727 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *ip;
char *var_name = (yyvsp[-5])->lextok;
@@ -2586,44 +2587,44 @@ regular_loop:
break_allowed--;
continue_allowed--;
}
-#line 2590 "awkgram.c" /* yacc.c:1646 */
+#line 2591 "awkgram.c" /* yacc.c:1646 */
break;
case 49:
-#line 839 "awkgram.y" /* yacc.c:1646 */
+#line 840 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = mk_for_loop((yyvsp[-11]), (yyvsp[-9]), (yyvsp[-6]), (yyvsp[-3]), (yyvsp[0]));
break_allowed--;
continue_allowed--;
}
-#line 2601 "awkgram.c" /* yacc.c:1646 */
+#line 2602 "awkgram.c" /* yacc.c:1646 */
break;
case 50:
-#line 846 "awkgram.y" /* yacc.c:1646 */
+#line 847 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = mk_for_loop((yyvsp[-10]), (yyvsp[-8]), (INSTRUCTION *) NULL, (yyvsp[-3]), (yyvsp[0]));
break_allowed--;
continue_allowed--;
}
-#line 2612 "awkgram.c" /* yacc.c:1646 */
+#line 2613 "awkgram.c" /* yacc.c:1646 */
break;
case 51:
-#line 853 "awkgram.y" /* yacc.c:1646 */
+#line 854 "awkgram.y" /* yacc.c:1646 */
{
if (do_pretty_print)
(yyval) = list_prepend((yyvsp[0]), instruction(Op_exec_count));
else
(yyval) = (yyvsp[0]);
}
-#line 2623 "awkgram.c" /* yacc.c:1646 */
+#line 2624 "awkgram.c" /* yacc.c:1646 */
break;
case 52:
-#line 863 "awkgram.y" /* yacc.c:1646 */
+#line 864 "awkgram.y" /* yacc.c:1646 */
{
if (! break_allowed)
error_ln((yyvsp[-1])->source_line,
@@ -2632,11 +2633,11 @@ regular_loop:
(yyval) = list_create((yyvsp[-1]));
}
-#line 2636 "awkgram.c" /* yacc.c:1646 */
+#line 2637 "awkgram.c" /* yacc.c:1646 */
break;
case 53:
-#line 872 "awkgram.y" /* yacc.c:1646 */
+#line 873 "awkgram.y" /* yacc.c:1646 */
{
if (! continue_allowed)
error_ln((yyvsp[-1])->source_line,
@@ -2645,11 +2646,11 @@ regular_loop:
(yyval) = list_create((yyvsp[-1]));
}
-#line 2649 "awkgram.c" /* yacc.c:1646 */
+#line 2650 "awkgram.c" /* yacc.c:1646 */
break;
case 54:
-#line 881 "awkgram.y" /* yacc.c:1646 */
+#line 882 "awkgram.y" /* yacc.c:1646 */
{
/* if inside function (rule = 0), resolve context at run-time */
if (rule && rule != Rule)
@@ -2658,11 +2659,11 @@ regular_loop:
(yyvsp[-1])->target_jmp = ip_rec;
(yyval) = list_create((yyvsp[-1]));
}
-#line 2662 "awkgram.c" /* yacc.c:1646 */
+#line 2663 "awkgram.c" /* yacc.c:1646 */
break;
case 55:
-#line 890 "awkgram.y" /* yacc.c:1646 */
+#line 891 "awkgram.y" /* yacc.c:1646 */
{
/* if inside function (rule = 0), resolve context at run-time */
if (rule == BEGIN || rule == END || rule == ENDFILE)
@@ -2673,11 +2674,11 @@ regular_loop:
(yyvsp[-1])->target_endfile = ip_endfile;
(yyval) = list_create((yyvsp[-1]));
}
-#line 2677 "awkgram.c" /* yacc.c:1646 */
+#line 2678 "awkgram.c" /* yacc.c:1646 */
break;
case 56:
-#line 901 "awkgram.y" /* yacc.c:1646 */
+#line 902 "awkgram.y" /* yacc.c:1646 */
{
/* Initialize the two possible jump targets, the actual target
* is resolved at run-time.
@@ -2692,20 +2693,20 @@ regular_loop:
} else
(yyval) = list_append((yyvsp[-1]), (yyvsp[-2]));
}
-#line 2696 "awkgram.c" /* yacc.c:1646 */
+#line 2697 "awkgram.c" /* yacc.c:1646 */
break;
case 57:
-#line 916 "awkgram.y" /* yacc.c:1646 */
+#line 917 "awkgram.y" /* yacc.c:1646 */
{
if (! in_function)
yyerror(_("`return' used outside function context"));
}
-#line 2705 "awkgram.c" /* yacc.c:1646 */
+#line 2706 "awkgram.c" /* yacc.c:1646 */
break;
case 58:
-#line 919 "awkgram.y" /* yacc.c:1646 */
+#line 920 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[-1]) == NULL) {
(yyval) = list_create((yyvsp[-3]));
@@ -2726,17 +2727,17 @@ regular_loop:
(yyval) = list_append((yyvsp[-1]), (yyvsp[-3]));
}
}
-#line 2730 "awkgram.c" /* yacc.c:1646 */
+#line 2731 "awkgram.c" /* yacc.c:1646 */
break;
case 60:
-#line 951 "awkgram.y" /* yacc.c:1646 */
+#line 952 "awkgram.y" /* yacc.c:1646 */
{ in_print = true; in_parens = 0; }
-#line 2736 "awkgram.c" /* yacc.c:1646 */
+#line 2737 "awkgram.c" /* yacc.c:1646 */
break;
case 61:
-#line 952 "awkgram.y" /* yacc.c:1646 */
+#line 953 "awkgram.y" /* yacc.c:1646 */
{
/*
* Optimization: plain `print' has no expression list, so $3 is null.
@@ -2833,17 +2834,17 @@ regular_print:
}
}
}
-#line 2837 "awkgram.c" /* yacc.c:1646 */
+#line 2838 "awkgram.c" /* yacc.c:1646 */
break;
case 62:
-#line 1049 "awkgram.y" /* yacc.c:1646 */
+#line 1050 "awkgram.y" /* yacc.c:1646 */
{ sub_counter = 0; }
-#line 2843 "awkgram.c" /* yacc.c:1646 */
+#line 2844 "awkgram.c" /* yacc.c:1646 */
break;
case 63:
-#line 1050 "awkgram.y" /* yacc.c:1646 */
+#line 1051 "awkgram.y" /* yacc.c:1646 */
{
char *arr = (yyvsp[-2])->lextok;
@@ -2876,11 +2877,11 @@ regular_print:
(yyval) = list_append(list_append((yyvsp[0]), (yyvsp[-2])), (yyvsp[-3]));
}
}
-#line 2880 "awkgram.c" /* yacc.c:1646 */
+#line 2881 "awkgram.c" /* yacc.c:1646 */
break;
case 64:
-#line 1087 "awkgram.y" /* yacc.c:1646 */
+#line 1088 "awkgram.y" /* yacc.c:1646 */
{
static bool warned = false;
char *arr = (yyvsp[-1])->lextok;
@@ -2906,52 +2907,52 @@ regular_print:
fatal(_("`delete' is not allowed with FUNCTAB"));
}
}
-#line 2910 "awkgram.c" /* yacc.c:1646 */
+#line 2911 "awkgram.c" /* yacc.c:1646 */
break;
case 65:
-#line 1113 "awkgram.y" /* yacc.c:1646 */
+#line 1114 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = optimize_assignment((yyvsp[0])); }
-#line 2916 "awkgram.c" /* yacc.c:1646 */
+#line 2917 "awkgram.c" /* yacc.c:1646 */
break;
case 66:
-#line 1118 "awkgram.y" /* yacc.c:1646 */
+#line 1119 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2922 "awkgram.c" /* yacc.c:1646 */
+#line 2923 "awkgram.c" /* yacc.c:1646 */
break;
case 67:
-#line 1120 "awkgram.y" /* yacc.c:1646 */
+#line 1121 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2928 "awkgram.c" /* yacc.c:1646 */
+#line 2929 "awkgram.c" /* yacc.c:1646 */
break;
case 68:
-#line 1125 "awkgram.y" /* yacc.c:1646 */
+#line 1126 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2934 "awkgram.c" /* yacc.c:1646 */
+#line 2935 "awkgram.c" /* yacc.c:1646 */
break;
case 69:
-#line 1127 "awkgram.y" /* yacc.c:1646 */
+#line 1128 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[-1]) == NULL)
(yyval) = list_create((yyvsp[0]));
else
(yyval) = list_prepend((yyvsp[-1]), (yyvsp[0]));
}
-#line 2945 "awkgram.c" /* yacc.c:1646 */
+#line 2946 "awkgram.c" /* yacc.c:1646 */
break;
case 70:
-#line 1134 "awkgram.y" /* yacc.c:1646 */
+#line 1135 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2951 "awkgram.c" /* yacc.c:1646 */
+#line 2952 "awkgram.c" /* yacc.c:1646 */
break;
case 71:
-#line 1139 "awkgram.y" /* yacc.c:1646 */
+#line 1140 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *casestmt = (yyvsp[0]);
if ((yyvsp[0]) == NULL)
@@ -2963,11 +2964,11 @@ regular_print:
bcfree((yyvsp[-2]));
(yyval) = (yyvsp[-4]);
}
-#line 2967 "awkgram.c" /* yacc.c:1646 */
+#line 2968 "awkgram.c" /* yacc.c:1646 */
break;
case 72:
-#line 1151 "awkgram.y" /* yacc.c:1646 */
+#line 1152 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *casestmt = (yyvsp[0]);
if ((yyvsp[0]) == NULL)
@@ -2978,17 +2979,17 @@ regular_print:
(yyvsp[-3])->case_stmt = casestmt;
(yyval) = (yyvsp[-3]);
}
-#line 2982 "awkgram.c" /* yacc.c:1646 */
+#line 2983 "awkgram.c" /* yacc.c:1646 */
break;
case 73:
-#line 1165 "awkgram.y" /* yacc.c:1646 */
+#line 1166 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2988 "awkgram.c" /* yacc.c:1646 */
+#line 2989 "awkgram.c" /* yacc.c:1646 */
break;
case 74:
-#line 1167 "awkgram.y" /* yacc.c:1646 */
+#line 1168 "awkgram.y" /* yacc.c:1646 */
{
NODE *n = (yyvsp[0])->memory;
(void) force_number(n);
@@ -2996,71 +2997,71 @@ regular_print:
bcfree((yyvsp[-1]));
(yyval) = (yyvsp[0]);
}
-#line 3000 "awkgram.c" /* yacc.c:1646 */
+#line 3001 "awkgram.c" /* yacc.c:1646 */
break;
case 75:
-#line 1175 "awkgram.y" /* yacc.c:1646 */
+#line 1176 "awkgram.y" /* yacc.c:1646 */
{
bcfree((yyvsp[-1]));
(yyval) = (yyvsp[0]);
}
-#line 3009 "awkgram.c" /* yacc.c:1646 */
+#line 3010 "awkgram.c" /* yacc.c:1646 */
break;
case 76:
-#line 1180 "awkgram.y" /* yacc.c:1646 */
+#line 1181 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3015 "awkgram.c" /* yacc.c:1646 */
+#line 3016 "awkgram.c" /* yacc.c:1646 */
break;
case 77:
-#line 1182 "awkgram.y" /* yacc.c:1646 */
+#line 1183 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->opcode = Op_push_re;
(yyval) = (yyvsp[0]);
}
-#line 3024 "awkgram.c" /* yacc.c:1646 */
+#line 3025 "awkgram.c" /* yacc.c:1646 */
break;
case 78:
-#line 1190 "awkgram.y" /* yacc.c:1646 */
+#line 1191 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3030 "awkgram.c" /* yacc.c:1646 */
+#line 3031 "awkgram.c" /* yacc.c:1646 */
break;
case 79:
-#line 1192 "awkgram.y" /* yacc.c:1646 */
+#line 1193 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3036 "awkgram.c" /* yacc.c:1646 */
+#line 3037 "awkgram.c" /* yacc.c:1646 */
break;
case 81:
-#line 1202 "awkgram.y" /* yacc.c:1646 */
+#line 1203 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = (yyvsp[-1]);
}
-#line 3044 "awkgram.c" /* yacc.c:1646 */
+#line 3045 "awkgram.c" /* yacc.c:1646 */
break;
case 82:
-#line 1209 "awkgram.y" /* yacc.c:1646 */
+#line 1210 "awkgram.y" /* yacc.c:1646 */
{
in_print = false;
in_parens = 0;
(yyval) = NULL;
}
-#line 3054 "awkgram.c" /* yacc.c:1646 */
+#line 3055 "awkgram.c" /* yacc.c:1646 */
break;
case 83:
-#line 1214 "awkgram.y" /* yacc.c:1646 */
+#line 1215 "awkgram.y" /* yacc.c:1646 */
{ in_print = false; in_parens = 0; }
-#line 3060 "awkgram.c" /* yacc.c:1646 */
+#line 3061 "awkgram.c" /* yacc.c:1646 */
break;
case 84:
-#line 1215 "awkgram.y" /* yacc.c:1646 */
+#line 1216 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[-2])->redir_type == redirect_twoway
&& (yyvsp[0])->lasti->opcode == Op_K_getline_redir
@@ -3068,136 +3069,136 @@ regular_print:
yyerror(_("multistage two-way pipelines don't work"));
(yyval) = list_prepend((yyvsp[0]), (yyvsp[-2]));
}
-#line 3072 "awkgram.c" /* yacc.c:1646 */
+#line 3073 "awkgram.c" /* yacc.c:1646 */
break;
case 85:
-#line 1226 "awkgram.y" /* yacc.c:1646 */
+#line 1227 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = mk_condition((yyvsp[-3]), (yyvsp[-5]), (yyvsp[0]), NULL, NULL);
}
-#line 3080 "awkgram.c" /* yacc.c:1646 */
+#line 3081 "awkgram.c" /* yacc.c:1646 */
break;
case 86:
-#line 1231 "awkgram.y" /* yacc.c:1646 */
+#line 1232 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = mk_condition((yyvsp[-6]), (yyvsp[-8]), (yyvsp[-3]), (yyvsp[-2]), (yyvsp[0]));
}
-#line 3088 "awkgram.c" /* yacc.c:1646 */
+#line 3089 "awkgram.c" /* yacc.c:1646 */
break;
case 91:
-#line 1248 "awkgram.y" /* yacc.c:1646 */
+#line 1249 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3094 "awkgram.c" /* yacc.c:1646 */
+#line 3095 "awkgram.c" /* yacc.c:1646 */
break;
case 92:
-#line 1250 "awkgram.y" /* yacc.c:1646 */
+#line 1251 "awkgram.y" /* yacc.c:1646 */
{
bcfree((yyvsp[-1]));
(yyval) = (yyvsp[0]);
}
-#line 3103 "awkgram.c" /* yacc.c:1646 */
+#line 3104 "awkgram.c" /* yacc.c:1646 */
break;
case 93:
-#line 1258 "awkgram.y" /* yacc.c:1646 */
+#line 1259 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3109 "awkgram.c" /* yacc.c:1646 */
+#line 3110 "awkgram.c" /* yacc.c:1646 */
break;
case 94:
-#line 1260 "awkgram.y" /* yacc.c:1646 */
+#line 1261 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3115 "awkgram.c" /* yacc.c:1646 */
+#line 3116 "awkgram.c" /* yacc.c:1646 */
break;
case 95:
-#line 1265 "awkgram.y" /* yacc.c:1646 */
+#line 1266 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->param_count = 0;
(yyval) = list_create((yyvsp[0]));
}
-#line 3124 "awkgram.c" /* yacc.c:1646 */
+#line 3125 "awkgram.c" /* yacc.c:1646 */
break;
case 96:
-#line 1270 "awkgram.y" /* yacc.c:1646 */
+#line 1271 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->param_count = (yyvsp[-2])->lasti->param_count + 1;
(yyval) = list_append((yyvsp[-2]), (yyvsp[0]));
yyerrok;
}
-#line 3134 "awkgram.c" /* yacc.c:1646 */
+#line 3135 "awkgram.c" /* yacc.c:1646 */
break;
case 97:
-#line 1276 "awkgram.y" /* yacc.c:1646 */
+#line 1277 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3140 "awkgram.c" /* yacc.c:1646 */
+#line 3141 "awkgram.c" /* yacc.c:1646 */
break;
case 98:
-#line 1278 "awkgram.y" /* yacc.c:1646 */
+#line 1279 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 3146 "awkgram.c" /* yacc.c:1646 */
+#line 3147 "awkgram.c" /* yacc.c:1646 */
break;
case 99:
-#line 1280 "awkgram.y" /* yacc.c:1646 */
+#line 1281 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-2]); }
-#line 3152 "awkgram.c" /* yacc.c:1646 */
+#line 3153 "awkgram.c" /* yacc.c:1646 */
break;
case 100:
-#line 1286 "awkgram.y" /* yacc.c:1646 */
+#line 1287 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3158 "awkgram.c" /* yacc.c:1646 */
+#line 3159 "awkgram.c" /* yacc.c:1646 */
break;
case 101:
-#line 1288 "awkgram.y" /* yacc.c:1646 */
+#line 1289 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3164 "awkgram.c" /* yacc.c:1646 */
+#line 3165 "awkgram.c" /* yacc.c:1646 */
break;
case 102:
-#line 1293 "awkgram.y" /* yacc.c:1646 */
+#line 1294 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3170 "awkgram.c" /* yacc.c:1646 */
+#line 3171 "awkgram.c" /* yacc.c:1646 */
break;
case 103:
-#line 1295 "awkgram.y" /* yacc.c:1646 */
+#line 1296 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3176 "awkgram.c" /* yacc.c:1646 */
+#line 3177 "awkgram.c" /* yacc.c:1646 */
break;
case 104:
-#line 1300 "awkgram.y" /* yacc.c:1646 */
+#line 1301 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_expression_list(NULL, (yyvsp[0])); }
-#line 3182 "awkgram.c" /* yacc.c:1646 */
+#line 3183 "awkgram.c" /* yacc.c:1646 */
break;
case 105:
-#line 1302 "awkgram.y" /* yacc.c:1646 */
+#line 1303 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
yyerrok;
}
-#line 3191 "awkgram.c" /* yacc.c:1646 */
+#line 3192 "awkgram.c" /* yacc.c:1646 */
break;
case 106:
-#line 1307 "awkgram.y" /* yacc.c:1646 */
+#line 1308 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3197 "awkgram.c" /* yacc.c:1646 */
+#line 3198 "awkgram.c" /* yacc.c:1646 */
break;
case 107:
-#line 1309 "awkgram.y" /* yacc.c:1646 */
+#line 1310 "awkgram.y" /* yacc.c:1646 */
{
/*
* Returning the expression list instead of NULL lets
@@ -3205,52 +3206,52 @@ regular_print:
*/
(yyval) = (yyvsp[-1]);
}
-#line 3209 "awkgram.c" /* yacc.c:1646 */
+#line 3210 "awkgram.c" /* yacc.c:1646 */
break;
case 108:
-#line 1317 "awkgram.y" /* yacc.c:1646 */
+#line 1318 "awkgram.y" /* yacc.c:1646 */
{
/* Ditto */
(yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
}
-#line 3218 "awkgram.c" /* yacc.c:1646 */
+#line 3219 "awkgram.c" /* yacc.c:1646 */
break;
case 109:
-#line 1322 "awkgram.y" /* yacc.c:1646 */
+#line 1323 "awkgram.y" /* yacc.c:1646 */
{
/* Ditto */
(yyval) = (yyvsp[-2]);
}
-#line 3227 "awkgram.c" /* yacc.c:1646 */
+#line 3228 "awkgram.c" /* yacc.c:1646 */
break;
case 110:
-#line 1331 "awkgram.y" /* yacc.c:1646 */
+#line 1332 "awkgram.y" /* yacc.c:1646 */
{
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 3238 "awkgram.c" /* yacc.c:1646 */
+#line 3239 "awkgram.c" /* yacc.c:1646 */
break;
case 111:
-#line 1338 "awkgram.y" /* yacc.c:1646 */
+#line 1339 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3244 "awkgram.c" /* yacc.c:1646 */
+#line 3245 "awkgram.c" /* yacc.c:1646 */
break;
case 112:
-#line 1340 "awkgram.y" /* yacc.c:1646 */
+#line 1341 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3250 "awkgram.c" /* yacc.c:1646 */
+#line 3251 "awkgram.c" /* yacc.c:1646 */
break;
case 113:
-#line 1342 "awkgram.y" /* yacc.c:1646 */
+#line 1343 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[-2])->lasti->opcode == Op_match_rec)
warning_ln((yyvsp[-1])->source_line,
@@ -3266,11 +3267,11 @@ regular_print:
(yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), (yyvsp[-1]));
}
}
-#line 3270 "awkgram.c" /* yacc.c:1646 */
+#line 3271 "awkgram.c" /* yacc.c:1646 */
break;
case 114:
-#line 1358 "awkgram.y" /* yacc.c:1646 */
+#line 1359 "awkgram.y" /* yacc.c:1646 */
{
if (do_lint_old)
warning_ln((yyvsp[-1])->source_line,
@@ -3280,91 +3281,91 @@ regular_print:
(yyvsp[-1])->expr_count = 1;
(yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), (yyvsp[-1]));
}
-#line 3284 "awkgram.c" /* yacc.c:1646 */
+#line 3285 "awkgram.c" /* yacc.c:1646 */
break;
case 115:
-#line 1368 "awkgram.y" /* yacc.c:1646 */
+#line 1369 "awkgram.y" /* yacc.c:1646 */
{
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 3295 "awkgram.c" /* yacc.c:1646 */
+#line 3296 "awkgram.c" /* yacc.c:1646 */
break;
case 116:
-#line 1375 "awkgram.y" /* yacc.c:1646 */
+#line 1376 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_condition((yyvsp[-4]), (yyvsp[-3]), (yyvsp[-2]), (yyvsp[-1]), (yyvsp[0])); }
-#line 3301 "awkgram.c" /* yacc.c:1646 */
+#line 3302 "awkgram.c" /* yacc.c:1646 */
break;
case 117:
-#line 1377 "awkgram.y" /* yacc.c:1646 */
+#line 1378 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3307 "awkgram.c" /* yacc.c:1646 */
+#line 3308 "awkgram.c" /* yacc.c:1646 */
break;
case 118:
-#line 1382 "awkgram.y" /* yacc.c:1646 */
+#line 1383 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3313 "awkgram.c" /* yacc.c:1646 */
+#line 3314 "awkgram.c" /* yacc.c:1646 */
break;
case 119:
-#line 1384 "awkgram.y" /* yacc.c:1646 */
+#line 1385 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3319 "awkgram.c" /* yacc.c:1646 */
+#line 3320 "awkgram.c" /* yacc.c:1646 */
break;
case 120:
-#line 1386 "awkgram.y" /* yacc.c:1646 */
+#line 1387 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->opcode = Op_assign_quotient;
(yyval) = (yyvsp[0]);
}
-#line 3328 "awkgram.c" /* yacc.c:1646 */
+#line 3329 "awkgram.c" /* yacc.c:1646 */
break;
case 121:
-#line 1394 "awkgram.y" /* yacc.c:1646 */
+#line 1395 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3334 "awkgram.c" /* yacc.c:1646 */
+#line 3335 "awkgram.c" /* yacc.c:1646 */
break;
case 122:
-#line 1396 "awkgram.y" /* yacc.c:1646 */
+#line 1397 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3340 "awkgram.c" /* yacc.c:1646 */
+#line 3341 "awkgram.c" /* yacc.c:1646 */
break;
case 123:
-#line 1401 "awkgram.y" /* yacc.c:1646 */
+#line 1402 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3346 "awkgram.c" /* yacc.c:1646 */
+#line 3347 "awkgram.c" /* yacc.c:1646 */
break;
case 124:
-#line 1403 "awkgram.y" /* yacc.c:1646 */
+#line 1404 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3352 "awkgram.c" /* yacc.c:1646 */
+#line 3353 "awkgram.c" /* yacc.c:1646 */
break;
case 125:
-#line 1408 "awkgram.y" /* yacc.c:1646 */
+#line 1409 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3358 "awkgram.c" /* yacc.c:1646 */
+#line 3359 "awkgram.c" /* yacc.c:1646 */
break;
case 126:
-#line 1410 "awkgram.y" /* yacc.c:1646 */
+#line 1411 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3364 "awkgram.c" /* yacc.c:1646 */
+#line 3365 "awkgram.c" /* yacc.c:1646 */
break;
case 127:
-#line 1412 "awkgram.y" /* yacc.c:1646 */
+#line 1413 "awkgram.y" /* yacc.c:1646 */
{
int count = 2;
bool is_simple_var = false;
@@ -3411,47 +3412,47 @@ regular_print:
max_args = count;
}
}
-#line 3415 "awkgram.c" /* yacc.c:1646 */
+#line 3416 "awkgram.c" /* yacc.c:1646 */
break;
case 129:
-#line 1464 "awkgram.y" /* yacc.c:1646 */
+#line 1465 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3421 "awkgram.c" /* yacc.c:1646 */
+#line 3422 "awkgram.c" /* yacc.c:1646 */
break;
case 130:
-#line 1466 "awkgram.y" /* yacc.c:1646 */
+#line 1467 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3427 "awkgram.c" /* yacc.c:1646 */
+#line 3428 "awkgram.c" /* yacc.c:1646 */
break;
case 131:
-#line 1468 "awkgram.y" /* yacc.c:1646 */
+#line 1469 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3433 "awkgram.c" /* yacc.c:1646 */
+#line 3434 "awkgram.c" /* yacc.c:1646 */
break;
case 132:
-#line 1470 "awkgram.y" /* yacc.c:1646 */
+#line 1471 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3439 "awkgram.c" /* yacc.c:1646 */
+#line 3440 "awkgram.c" /* yacc.c:1646 */
break;
case 133:
-#line 1472 "awkgram.y" /* yacc.c:1646 */
+#line 1473 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3445 "awkgram.c" /* yacc.c:1646 */
+#line 3446 "awkgram.c" /* yacc.c:1646 */
break;
case 134:
-#line 1474 "awkgram.y" /* yacc.c:1646 */
+#line 1475 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3451 "awkgram.c" /* yacc.c:1646 */
+#line 3452 "awkgram.c" /* yacc.c:1646 */
break;
case 135:
-#line 1476 "awkgram.y" /* yacc.c:1646 */
+#line 1477 "awkgram.y" /* yacc.c:1646 */
{
/*
* In BEGINFILE/ENDFILE, allow `getline [var] < file'
@@ -3465,29 +3466,29 @@ regular_print:
_("non-redirected `getline' undefined inside END action"));
(yyval) = mk_getline((yyvsp[-2]), (yyvsp[-1]), (yyvsp[0]), redirect_input);
}
-#line 3469 "awkgram.c" /* yacc.c:1646 */
+#line 3470 "awkgram.c" /* yacc.c:1646 */
break;
case 136:
-#line 1490 "awkgram.y" /* yacc.c:1646 */
+#line 1491 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->opcode = Op_postincrement;
(yyval) = mk_assignment((yyvsp[-1]), NULL, (yyvsp[0]));
}
-#line 3478 "awkgram.c" /* yacc.c:1646 */
+#line 3479 "awkgram.c" /* yacc.c:1646 */
break;
case 137:
-#line 1495 "awkgram.y" /* yacc.c:1646 */
+#line 1496 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->opcode = Op_postdecrement;
(yyval) = mk_assignment((yyvsp[-1]), NULL, (yyvsp[0]));
}
-#line 3487 "awkgram.c" /* yacc.c:1646 */
+#line 3488 "awkgram.c" /* yacc.c:1646 */
break;
case 138:
-#line 1500 "awkgram.y" /* yacc.c:1646 */
+#line 1501 "awkgram.y" /* yacc.c:1646 */
{
if (do_lint_old) {
warning_ln((yyvsp[-1])->source_line,
@@ -3507,64 +3508,64 @@ regular_print:
(yyval) = list_append(list_merge(t, (yyvsp[0])), (yyvsp[-1]));
}
}
-#line 3511 "awkgram.c" /* yacc.c:1646 */
+#line 3512 "awkgram.c" /* yacc.c:1646 */
break;
case 139:
-#line 1525 "awkgram.y" /* yacc.c:1646 */
+#line 1526 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = mk_getline((yyvsp[-1]), (yyvsp[0]), (yyvsp[-3]), (yyvsp[-2])->redir_type);
bcfree((yyvsp[-2]));
}
-#line 3520 "awkgram.c" /* yacc.c:1646 */
+#line 3521 "awkgram.c" /* yacc.c:1646 */
break;
case 140:
-#line 1531 "awkgram.y" /* yacc.c:1646 */
+#line 1532 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3526 "awkgram.c" /* yacc.c:1646 */
+#line 3527 "awkgram.c" /* yacc.c:1646 */
break;
case 141:
-#line 1533 "awkgram.y" /* yacc.c:1646 */
+#line 1534 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3532 "awkgram.c" /* yacc.c:1646 */
+#line 3533 "awkgram.c" /* yacc.c:1646 */
break;
case 142:
-#line 1535 "awkgram.y" /* yacc.c:1646 */
+#line 1536 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3538 "awkgram.c" /* yacc.c:1646 */
+#line 3539 "awkgram.c" /* yacc.c:1646 */
break;
case 143:
-#line 1537 "awkgram.y" /* yacc.c:1646 */
+#line 1538 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3544 "awkgram.c" /* yacc.c:1646 */
+#line 3545 "awkgram.c" /* yacc.c:1646 */
break;
case 144:
-#line 1539 "awkgram.y" /* yacc.c:1646 */
+#line 1540 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3550 "awkgram.c" /* yacc.c:1646 */
+#line 3551 "awkgram.c" /* yacc.c:1646 */
break;
case 145:
-#line 1541 "awkgram.y" /* yacc.c:1646 */
+#line 1542 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3556 "awkgram.c" /* yacc.c:1646 */
+#line 3557 "awkgram.c" /* yacc.c:1646 */
break;
case 146:
-#line 1546 "awkgram.y" /* yacc.c:1646 */
+#line 1547 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_create((yyvsp[0]));
}
-#line 3564 "awkgram.c" /* yacc.c:1646 */
+#line 3565 "awkgram.c" /* yacc.c:1646 */
break;
case 147:
-#line 1550 "awkgram.y" /* yacc.c:1646 */
+#line 1551 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[0])->opcode == Op_match_rec) {
(yyvsp[0])->opcode = Op_nomatch;
@@ -3596,37 +3597,37 @@ regular_print:
}
}
}
-#line 3600 "awkgram.c" /* yacc.c:1646 */
+#line 3601 "awkgram.c" /* yacc.c:1646 */
break;
case 148:
-#line 1582 "awkgram.y" /* yacc.c:1646 */
+#line 1583 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 3606 "awkgram.c" /* yacc.c:1646 */
+#line 3607 "awkgram.c" /* yacc.c:1646 */
break;
case 149:
-#line 1584 "awkgram.y" /* yacc.c:1646 */
+#line 1585 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = snode((yyvsp[-1]), (yyvsp[-3]));
if ((yyval) == NULL)
YYABORT;
}
-#line 3616 "awkgram.c" /* yacc.c:1646 */
+#line 3617 "awkgram.c" /* yacc.c:1646 */
break;
case 150:
-#line 1590 "awkgram.y" /* yacc.c:1646 */
+#line 1591 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = snode((yyvsp[-1]), (yyvsp[-3]));
if ((yyval) == NULL)
YYABORT;
}
-#line 3626 "awkgram.c" /* yacc.c:1646 */
+#line 3627 "awkgram.c" /* yacc.c:1646 */
break;
case 151:
-#line 1596 "awkgram.y" /* yacc.c:1646 */
+#line 1597 "awkgram.y" /* yacc.c:1646 */
{
static bool warned = false;
@@ -3639,45 +3640,45 @@ regular_print:
if ((yyval) == NULL)
YYABORT;
}
-#line 3643 "awkgram.c" /* yacc.c:1646 */
+#line 3644 "awkgram.c" /* yacc.c:1646 */
break;
case 154:
-#line 1611 "awkgram.y" /* yacc.c:1646 */
+#line 1612 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[-1])->opcode = Op_preincrement;
(yyval) = mk_assignment((yyvsp[0]), NULL, (yyvsp[-1]));
}
-#line 3652 "awkgram.c" /* yacc.c:1646 */
+#line 3653 "awkgram.c" /* yacc.c:1646 */
break;
case 155:
-#line 1616 "awkgram.y" /* yacc.c:1646 */
+#line 1617 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[-1])->opcode = Op_predecrement;
(yyval) = mk_assignment((yyvsp[0]), NULL, (yyvsp[-1]));
}
-#line 3661 "awkgram.c" /* yacc.c:1646 */
+#line 3662 "awkgram.c" /* yacc.c:1646 */
break;
case 156:
-#line 1621 "awkgram.y" /* yacc.c:1646 */
+#line 1622 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_create((yyvsp[0]));
}
-#line 3669 "awkgram.c" /* yacc.c:1646 */
+#line 3670 "awkgram.c" /* yacc.c:1646 */
break;
case 157:
-#line 1625 "awkgram.y" /* yacc.c:1646 */
+#line 1626 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_create((yyvsp[0]));
}
-#line 3677 "awkgram.c" /* yacc.c:1646 */
+#line 3678 "awkgram.c" /* yacc.c:1646 */
break;
case 158:
-#line 1629 "awkgram.y" /* yacc.c:1646 */
+#line 1630 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[0])->lasti->opcode == Op_push_i
&& ((yyvsp[0])->lasti->memory->flags & (STRCUR|STRING)) == 0
@@ -3692,11 +3693,11 @@ regular_print:
(yyval) = list_append((yyvsp[0]), (yyvsp[-1]));
}
}
-#line 3696 "awkgram.c" /* yacc.c:1646 */
+#line 3697 "awkgram.c" /* yacc.c:1646 */
break;
case 159:
-#line 1644 "awkgram.y" /* yacc.c:1646 */
+#line 1645 "awkgram.y" /* yacc.c:1646 */
{
/*
* was: $$ = $2
@@ -3706,20 +3707,20 @@ regular_print:
(yyvsp[-1])->memory = make_number(0.0);
(yyval) = list_append((yyvsp[0]), (yyvsp[-1]));
}
-#line 3710 "awkgram.c" /* yacc.c:1646 */
+#line 3711 "awkgram.c" /* yacc.c:1646 */
break;
case 160:
-#line 1657 "awkgram.y" /* yacc.c:1646 */
+#line 1658 "awkgram.y" /* yacc.c:1646 */
{
func_use((yyvsp[0])->lasti->func_name, FUNC_USE);
(yyval) = (yyvsp[0]);
}
-#line 3719 "awkgram.c" /* yacc.c:1646 */
+#line 3720 "awkgram.c" /* yacc.c:1646 */
break;
case 161:
-#line 1662 "awkgram.y" /* yacc.c:1646 */
+#line 1663 "awkgram.y" /* yacc.c:1646 */
{
/* indirect function call */
INSTRUCTION *f, *t;
@@ -3752,11 +3753,11 @@ regular_print:
(yyval) = list_prepend((yyvsp[0]), t);
}
-#line 3756 "awkgram.c" /* yacc.c:1646 */
+#line 3757 "awkgram.c" /* yacc.c:1646 */
break;
case 162:
-#line 1698 "awkgram.y" /* yacc.c:1646 */
+#line 1699 "awkgram.y" /* yacc.c:1646 */
{
param_sanity((yyvsp[-1]));
(yyvsp[-3])->opcode = Op_func_call;
@@ -3770,49 +3771,49 @@ regular_print:
(yyval) = list_append(t, (yyvsp[-3]));
}
}
-#line 3774 "awkgram.c" /* yacc.c:1646 */
+#line 3775 "awkgram.c" /* yacc.c:1646 */
break;
case 163:
-#line 1715 "awkgram.y" /* yacc.c:1646 */
+#line 1716 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3780 "awkgram.c" /* yacc.c:1646 */
+#line 3781 "awkgram.c" /* yacc.c:1646 */
break;
case 164:
-#line 1717 "awkgram.y" /* yacc.c:1646 */
+#line 1718 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3786 "awkgram.c" /* yacc.c:1646 */
+#line 3787 "awkgram.c" /* yacc.c:1646 */
break;
case 165:
-#line 1722 "awkgram.y" /* yacc.c:1646 */
+#line 1723 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3792 "awkgram.c" /* yacc.c:1646 */
+#line 3793 "awkgram.c" /* yacc.c:1646 */
break;
case 166:
-#line 1724 "awkgram.y" /* yacc.c:1646 */
+#line 1725 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 3798 "awkgram.c" /* yacc.c:1646 */
+#line 3799 "awkgram.c" /* yacc.c:1646 */
break;
case 167:
-#line 1729 "awkgram.y" /* yacc.c:1646 */
+#line 1730 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3804 "awkgram.c" /* yacc.c:1646 */
+#line 3805 "awkgram.c" /* yacc.c:1646 */
break;
case 168:
-#line 1731 "awkgram.y" /* yacc.c:1646 */
+#line 1732 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_merge((yyvsp[-1]), (yyvsp[0]));
}
-#line 3812 "awkgram.c" /* yacc.c:1646 */
+#line 3813 "awkgram.c" /* yacc.c:1646 */
break;
case 169:
-#line 1738 "awkgram.y" /* yacc.c:1646 */
+#line 1739 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *ip = (yyvsp[0])->lasti;
int count = ip->sub_count; /* # of SUBSEP-seperated expressions */
@@ -3826,11 +3827,11 @@ regular_print:
sub_counter++; /* count # of dimensions */
(yyval) = (yyvsp[0]);
}
-#line 3830 "awkgram.c" /* yacc.c:1646 */
+#line 3831 "awkgram.c" /* yacc.c:1646 */
break;
case 170:
-#line 1755 "awkgram.y" /* yacc.c:1646 */
+#line 1756 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *t = (yyvsp[-1]);
if ((yyvsp[-1]) == NULL) {
@@ -3844,31 +3845,31 @@ regular_print:
(yyvsp[0])->sub_count = count_expressions(&t, false);
(yyval) = list_append(t, (yyvsp[0]));
}
-#line 3848 "awkgram.c" /* yacc.c:1646 */
+#line 3849 "awkgram.c" /* yacc.c:1646 */
break;
case 171:
-#line 1772 "awkgram.y" /* yacc.c:1646 */
+#line 1773 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3854 "awkgram.c" /* yacc.c:1646 */
+#line 3855 "awkgram.c" /* yacc.c:1646 */
break;
case 172:
-#line 1774 "awkgram.y" /* yacc.c:1646 */
+#line 1775 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_merge((yyvsp[-1]), (yyvsp[0]));
}
-#line 3862 "awkgram.c" /* yacc.c:1646 */
+#line 3863 "awkgram.c" /* yacc.c:1646 */
break;
case 173:
-#line 1781 "awkgram.y" /* yacc.c:1646 */
+#line 1782 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 3868 "awkgram.c" /* yacc.c:1646 */
+#line 3869 "awkgram.c" /* yacc.c:1646 */
break;
case 174:
-#line 1786 "awkgram.y" /* yacc.c:1646 */
+#line 1787 "awkgram.y" /* yacc.c:1646 */
{
char *var_name = (yyvsp[0])->lextok;
@@ -3876,22 +3877,22 @@ regular_print:
(yyvsp[0])->memory = variable((yyvsp[0])->source_line, var_name, Node_var_new);
(yyval) = list_create((yyvsp[0]));
}
-#line 3880 "awkgram.c" /* yacc.c:1646 */
+#line 3881 "awkgram.c" /* yacc.c:1646 */
break;
case 175:
-#line 1794 "awkgram.y" /* yacc.c:1646 */
+#line 1795 "awkgram.y" /* yacc.c:1646 */
{
char *arr = (yyvsp[-1])->lextok;
(yyvsp[-1])->memory = variable((yyvsp[-1])->source_line, arr, Node_var_new);
(yyvsp[-1])->opcode = Op_push_array;
(yyval) = list_prepend((yyvsp[0]), (yyvsp[-1]));
}
-#line 3891 "awkgram.c" /* yacc.c:1646 */
+#line 3892 "awkgram.c" /* yacc.c:1646 */
break;
case 176:
-#line 1804 "awkgram.y" /* yacc.c:1646 */
+#line 1805 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *ip = (yyvsp[0])->nexti;
if (ip->opcode == Op_push
@@ -3903,73 +3904,73 @@ regular_print:
} else
(yyval) = (yyvsp[0]);
}
-#line 3907 "awkgram.c" /* yacc.c:1646 */
+#line 3908 "awkgram.c" /* yacc.c:1646 */
break;
case 177:
-#line 1816 "awkgram.y" /* yacc.c:1646 */
+#line 1817 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_append((yyvsp[-1]), (yyvsp[-2]));
if ((yyvsp[0]) != NULL)
mk_assignment((yyvsp[-1]), NULL, (yyvsp[0]));
}
-#line 3917 "awkgram.c" /* yacc.c:1646 */
+#line 3918 "awkgram.c" /* yacc.c:1646 */
break;
case 178:
-#line 1825 "awkgram.y" /* yacc.c:1646 */
+#line 1826 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->opcode = Op_postincrement;
}
-#line 3925 "awkgram.c" /* yacc.c:1646 */
+#line 3926 "awkgram.c" /* yacc.c:1646 */
break;
case 179:
-#line 1829 "awkgram.y" /* yacc.c:1646 */
+#line 1830 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->opcode = Op_postdecrement;
}
-#line 3933 "awkgram.c" /* yacc.c:1646 */
+#line 3934 "awkgram.c" /* yacc.c:1646 */
break;
case 180:
-#line 1832 "awkgram.y" /* yacc.c:1646 */
+#line 1833 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3939 "awkgram.c" /* yacc.c:1646 */
+#line 3940 "awkgram.c" /* yacc.c:1646 */
break;
case 182:
-#line 1840 "awkgram.y" /* yacc.c:1646 */
+#line 1841 "awkgram.y" /* yacc.c:1646 */
{ yyerrok; }
-#line 3945 "awkgram.c" /* yacc.c:1646 */
+#line 3946 "awkgram.c" /* yacc.c:1646 */
break;
case 183:
-#line 1844 "awkgram.y" /* yacc.c:1646 */
+#line 1845 "awkgram.y" /* yacc.c:1646 */
{ yyerrok; }
-#line 3951 "awkgram.c" /* yacc.c:1646 */
+#line 3952 "awkgram.c" /* yacc.c:1646 */
break;
case 186:
-#line 1853 "awkgram.y" /* yacc.c:1646 */
+#line 1854 "awkgram.y" /* yacc.c:1646 */
{ yyerrok; }
-#line 3957 "awkgram.c" /* yacc.c:1646 */
+#line 3958 "awkgram.c" /* yacc.c:1646 */
break;
case 187:
-#line 1857 "awkgram.y" /* yacc.c:1646 */
+#line 1858 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); yyerrok; }
-#line 3963 "awkgram.c" /* yacc.c:1646 */
+#line 3964 "awkgram.c" /* yacc.c:1646 */
break;
case 188:
-#line 1861 "awkgram.y" /* yacc.c:1646 */
+#line 1862 "awkgram.y" /* yacc.c:1646 */
{ yyerrok; }
-#line 3969 "awkgram.c" /* yacc.c:1646 */
+#line 3970 "awkgram.c" /* yacc.c:1646 */
break;
-#line 3973 "awkgram.c" /* yacc.c:1646 */
+#line 3974 "awkgram.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -4197,7 +4198,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 1863 "awkgram.y" /* yacc.c:1906 */
+#line 1864 "awkgram.y" /* yacc.c:1906 */
struct token {
@@ -4706,7 +4707,7 @@ parse_program(INSTRUCTION **pcode)
ip_newfile = ip_rec = ip_atexit = ip_beginfile = ip_endfile = NULL;
else {
ip_endfile = instruction(Op_no_op);
- ip_beginfile = instruction(Op_no_op);
+ main_beginfile = ip_beginfile = instruction(Op_no_op);
ip_rec = instruction(Op_get_record); /* target for `next', also ip_newfile */
ip_newfile = bcalloc(Op_newfile, 2, 0); /* target for `nextfile' */
ip_newfile->target_jmp = ip_end;
diff --git a/awkgram.y b/awkgram.y
index 5e3bade9..44be7824 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -143,6 +143,7 @@ static INSTRUCTION *ip_atexit = NULL;
static INSTRUCTION *ip_end;
static INSTRUCTION *ip_endfile;
static INSTRUCTION *ip_beginfile;
+INSTRUCTION *main_beginfile;
static INSTRUCTION *comment = NULL;
static INSTRUCTION *program_comment = NULL;
@@ -2368,7 +2369,7 @@ parse_program(INSTRUCTION **pcode)
ip_newfile = ip_rec = ip_atexit = ip_beginfile = ip_endfile = NULL;
else {
ip_endfile = instruction(Op_no_op);
- ip_beginfile = instruction(Op_no_op);
+ main_beginfile = ip_beginfile = instruction(Op_no_op);
ip_rec = instruction(Op_get_record); /* target for `next', also ip_newfile */
ip_newfile = bcalloc(Op_newfile, 2, 0); /* target for `nextfile' */
ip_newfile->target_jmp = ip_end;
diff --git a/configh.in b/configh.in
index 301fa21a..7e001f8e 100644
--- a/configh.in
+++ b/configh.in
@@ -171,6 +171,9 @@
/* Define to 1 if you have the `setsid' function. */
#undef HAVE_SETSID
+/* Define to 1 if you have the `sigprocmask' function. */
+#undef HAVE_SIGPROCMASK
+
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
@@ -296,6 +299,9 @@
/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP
+/* Define to 1 if you have the `waitpid' function. */
+#undef HAVE_WAITPID
+
/* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H
diff --git a/configure b/configure
index 93862b34..cb7cf42b 100755
--- a/configure
+++ b/configure
@@ -10284,9 +10284,10 @@ esac
for ac_func in atexit btowc fmod getgrent getgroups grantpt \
isascii iswctype iswlower iswupper mbrlen \
memcmp memcpy memcpy_ulong memmove memset \
- memset_ulong mkstemp posix_openpt setenv setlocale setsid snprintf strchr \
+ memset_ulong mkstemp posix_openpt setenv setlocale setsid sigprocmask \
+ snprintf strchr \
strerror strftime strcasecmp strncasecmp strcoll strtod strtoul \
- system tmpfile towlower towupper tzset usleep wcrtomb \
+ system tmpfile towlower towupper tzset usleep waitpid wcrtomb \
wcscoll wctype
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
diff --git a/configure.ac b/configure.ac
index fc0f93ba..c6b4dd76 100644
--- a/configure.ac
+++ b/configure.ac
@@ -273,9 +273,10 @@ esac
AC_CHECK_FUNCS(atexit btowc fmod getgrent getgroups grantpt \
isascii iswctype iswlower iswupper mbrlen \
memcmp memcpy memcpy_ulong memmove memset \
- memset_ulong mkstemp posix_openpt setenv setlocale setsid snprintf strchr \
+ memset_ulong mkstemp posix_openpt setenv setlocale setsid sigprocmask \
+ snprintf strchr \
strerror strftime strcasecmp strncasecmp strcoll strtod strtoul \
- system tmpfile towlower towupper tzset usleep wcrtomb \
+ system tmpfile towlower towupper tzset usleep waitpid wcrtomb \
wcscoll wctype)
dnl this check is for both mbrtowc and the mbstate_t type, which is good
AC_FUNC_MBRTOWC
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 020057bb..5dd32735 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -7,6 +7,25 @@
* gawkinet.texi: Fix capitalization in document title.
* gawktexi.in: Here we again: Starting on more O'Reilly fixes.
+2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawktexi.in: Improve get_file documentation.
+
+2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawktexi.in: Replace "Retrying I/O" with "Retrying Input", since this
+ feature pertains to input, not output.
+
+2015-01-04 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawktexi.in: Document the get_file API function.
+
+2015-01-04 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawk.1: Document new features PROCINFO["errno"] and
+ PROCINFO["input", "RETRY"], and new getline return value of -2.
+ * gawktexi.in: Ditto.
+
2014-12-26 Antonio Giovanni Colombo <azc100@gmail.com>
* gawktexi.in (Glossary): Really sort the items.
diff --git a/doc/gawk.1 b/doc/gawk.1
index 3d5d1812..b425c24c 100644
--- a/doc/gawk.1
+++ b/doc/gawk.1
@@ -942,6 +942,15 @@ then
will contain
a string describing the error.
The value is subject to translation in non-English locales.
+If the string in
+.B ERRNO
+corresponds to a system error in the
+.IR errno (3)
+variable, then the numeric value can be found in
+.B PROCINFO["errno"].
+For non-system errors,
+.B PROCINFO["errno"]
+will be zero.
.TP
.B FIELDWIDTHS
A whitespace separated list of field widths. When set,
@@ -1103,6 +1112,13 @@ system call.
The default time format string for
.BR strftime() .
.TP
+\fBPROCINFO["errno"]\fP
+The value of
+.IR errno (3)
+when
+.BR ERRNO
+is set to the associated error message.
+.TP
\fBPROCINFO["euid"]\fP
The value of the
.IR geteuid (2)
@@ -1221,6 +1237,28 @@ where
is a redirection string or a filename. A value of zero or
less than zero means no timeout.
.TP
+\fBPROCINFO["input", "RETRY"]\fP
+If an I/O error that may be retried occurs when reading data from
+.IR input ,
+and this array entry exists, then
+.BR getline
+will return -2 instead of following the default behavior of returning -1
+and configuring
+.IR input
+to return no further data.
+An I/O error that may be retried is one where
+.IR errno (3)
+has the value
+.IR EAGAIN ,
+.IR EWOULDBLOCK ,
+.IR EINTR ,
+or
+.IR ETIMEDOUT .
+This may be useful in conjunction with
+\fBPROCINFO["input", "READ_TIMEOUT"]\fP
+or situations where a file descriptor has been configured to behave in a
+non-blocking fashion.
+.TP
\fBPROCINFO["mpfr_version"]\fP
The version of the GNU MPFR library used for arbitrary precision
number support in
@@ -2289,6 +2327,13 @@ below.)
The
.B getline
command returns 1 on success, 0 on end of file, and \-1 on an error.
+If the
+.IR errno (3)
+value indicates that the I/O operation may be retried,
+and \fBPROCINFO["input", "RETRY"]\fP
+is set, then \-2 will be returned instead of \-1, and further calls to
+.B getline
+may be attempted.
Upon an error,
.B ERRNO
is set to a string describing the problem.
diff --git a/doc/gawk.info b/doc/gawk.info
index fe51de53..10085b35 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -217,6 +217,7 @@ entitled "GNU Free Documentation License".
`getline'.
* Getline Summary:: Summary of `getline' Variants.
* Read Timeout:: Reading input with a timeout.
+* Retrying Input:: Retrying input after certain errors.
* Command-line directories:: What happens if you put a directory on
the command line.
* Input Summary:: Input summary.
@@ -557,6 +558,7 @@ entitled "GNU Free Documentation License".
* Array Functions:: Functions for working with arrays.
* Flattening Arrays:: How to flatten arrays.
* Creating Arrays:: How to create and populate arrays.
+* Redirection API:: How to access and manipulate redirections.
* Extension API Variables:: Variables provided by the API.
* Extension Versioning:: API Version information.
* Extension API Informational Variables:: Variables providing information about
@@ -4167,6 +4169,7 @@ have to be named on the `awk' command line (*note Getline::).
* Getline:: Reading files under explicit program control
using the `getline' function.
* Read Timeout:: Reading input with a timeout.
+* Retrying Input:: Retrying input after certain errors.
* Command-line directories:: What happens if you put a directory on the
command line.
* Input Summary:: Input summary.
@@ -5438,7 +5441,11 @@ how `awk' works.
encounters the end of the file. If there is some error in getting a
record, such as a file that cannot be opened, then `getline' returns
-1. In this case, `gawk' sets the variable `ERRNO' to a string
-describing the error that occurred.
+describing the error that occurred. If the `errno' variable indicates
+that the I/O operation may be retried, and `PROCINFO["input", "RETRY"]'
+is set, then -2 will be returned instead of -1, and further calls to
+`getline' may be attemped. *Note Retrying Input::, for further
+information about this feature.
In the following examples, COMMAND stands for a string value that
represents a shell command.
@@ -5875,7 +5882,7 @@ VAR
Table 4.1: `getline' variants and what they set

-File: gawk.info, Node: Read Timeout, Next: Command-line directories, Prev: Getline, Up: Reading Files
+File: gawk.info, Node: Read Timeout, Next: Retrying Input, Prev: Getline, Up: Reading Files
4.10 Reading Input with a Timeout
=================================
@@ -5954,7 +5961,8 @@ a per command or connection basis.
`gawk' considers a timeout event to be an error even though the
attempt to read from the underlying device may succeed in a later
attempt. This is a limitation, and it also means that you cannot use
-this to multiplex input from two or more sources.
+this to multiplex input from two or more sources. *Note Retrying
+Input::, for a way to enable later I/O attempts to succeed.
Assigning a timeout value prevents read operations from blocking
indefinitely. But bear in mind that there are other ways `gawk' can
@@ -5969,9 +5977,36 @@ writing.
(1) This assumes that standard input is the keyboard.

-File: gawk.info, Node: Command-line directories, Next: Input Summary, Prev: Read Timeout, Up: Reading Files
+File: gawk.info, Node: Retrying Input, Next: Command-line directories, Prev: Read Timeout, Up: Reading Files
-4.11 Directories on the Command Line
+4.11 Retrying Reads After Certain Input Errors
+==============================================
+
+This minor node describes a feature that is specific to `gawk'.
+
+ When `gawk' encounters an error while reading input, it will by
+default return -1 from getline, and subsequent attempts to read from
+that file will result in an end-of-file indication. However, you may
+optionally instruct `gawk' to allow I/O to be retried when certain
+errors are encountered by setting setting a special element in the
+`PROCINFO' array (*note Auto-set::):
+
+ PROCINFO["input_name", "RETRY"]
+
+ When set, this causes `gawk' to check the value of the system
+`errno' variable when an I/O error occurs. If `errno' indicates a
+subsequent I/O attempt may succeed, `getline' will instead return -2 and
+further calls to `getline' may succeed. This applies to `errno' values
+EAGAIN, EWOULDBLOCK, EINTR, or ETIMEDOUT.
+
+ This feature is useful in conjunction with `PROCINFO["input_name",
+"READ_TIMEOUT"]' or situations where a file descriptor has been
+configured to behave in a non-blocking fashion.
+
+
+File: gawk.info, Node: Command-line directories, Next: Input Summary, Prev: Retrying Input, Up: Reading Files
+
+4.12 Directories on the Command Line
====================================
According to the POSIX standard, files named on the `awk' command line
@@ -5994,7 +6029,7 @@ usable data from an `awk' program.

File: gawk.info, Node: Input Summary, Next: Input Exercises, Prev: Command-line directories, Up: Reading Files
-4.12 Summary
+4.13 Summary
============
* Input is split into records based on the value of `RS'. The
@@ -6067,7 +6102,7 @@ File: gawk.info, Node: Input Summary, Next: Input Exercises, Prev: Command-li

File: gawk.info, Node: Input Exercises, Prev: Input Summary, Up: Reading Files
-4.13 Exercises
+4.14 Exercises
==============
1. Using the `FIELDWIDTHS' variable (*note Constant Size::), write a
@@ -10362,6 +10397,11 @@ Options::), they are not special:
`getline' returning -1. You are, of course, free to clear it
yourself before doing an I/O operation.
+ If the value of `ERRNO' corresponds to a system error in the C
+ `errno' variable, then `PROCINFO["errno"]' will be set to the value
+ of `errno'. For non-system errors, `PROCINFO["errno"]' will be
+ zero.
+
`FILENAME'
The name of the current input file. When no data files are listed
on the command line, `awk' reads from the standard input and
@@ -10410,6 +10450,10 @@ Options::), they are not special:
`PROCINFO["egid"]'
The value of the `getegid()' system call.
+ `PROCINFO["errno"]'
+ The value of the C `errno' variable when `ERRNO' is set to
+ the associated error message.
+
`PROCINFO["euid"]'
The value of the `geteuid()' system call.
@@ -10520,6 +10564,10 @@ Options::), they are not special:
open input file, pipe, or coprocess. *Note Read Timeout::,
for more information.
+ * It may be used to indicate that input may be retried when it
+ fails due to certain errors. *Note Retrying Input::, for
+ more information.
+
* It may be used to cause coprocesses to communicate over
pseudo-ttys instead of through two-way pipes; this is
discussed further in *note Two-way I/O::.
@@ -22874,6 +22922,7 @@ describes the API in detail.
* Symbol Table Access:: Functions for accessing global
variables.
* Array Manipulation:: Functions for working with arrays.
+* Redirection API:: How to access and manipulate redirections.
* Extension API Variables:: Variables provided by the API.
* Extension API Boilerplate:: Boilerplate code for using the API.
@@ -22934,6 +22983,9 @@ operations:
- Flattening an array for easy C style looping over all its
indices and elements
+ * Accessing and manipulating redirections.
+
+
Some points about using the API:
* The following types, macros, and/or functions are referenced in
@@ -24140,7 +24192,7 @@ using `release_value()'.
`double' to store.

-File: gawk.info, Node: Array Manipulation, Next: Extension API Variables, Prev: Symbol Table Access, Up: Extension API Description
+File: gawk.info, Node: Array Manipulation, Next: Redirection API, Prev: Symbol Table Access, Up: Extension API Description
16.4.11 Array Manipulation
--------------------------
@@ -24625,9 +24677,72 @@ array:
environment variable.)

-File: gawk.info, Node: Extension API Variables, Next: Extension API Boilerplate, Prev: Array Manipulation, Up: Extension API Description
-
-16.4.12 API Variables
+File: gawk.info, Node: Redirection API, Next: Extension API Variables, Prev: Array Manipulation, Up: Extension API Description
+
+16.4.12 Accessing and Manipulating Redirections
+-----------------------------------------------
+
+The following function allows extensions to access and manipulate
+redirections.
+
+`awk_bool_t get_file(const char *name,'
+` size_t name_len,'
+` const char *filetype,'
+` int fd,'
+` const awk_input_buf_t **ibufp,'
+` const awk_output_buf_t **obufp);'
+ Look up a file in `gawk''s internal redirection table. If `name'
+ is NULL or `name_len' is 0, it returns data for the currently open
+ input file corresponding to `FILENAME' (and it will not access the
+ `filetype' argument, so that may be undefined). If the file is
+ not already open, it tries to open it. The `filetype' argument
+ must be NUL-terminated and should be one of:
+ `>'
+ A file opened for output.
+
+ `>>'
+ A file opened for append.
+
+ `<'
+ A file opened for input.
+
+ `|>'
+ A pipe opened for output.
+
+ `|<'
+ A pipe opened for input.
+
+ `|&'
+ A two-way coprocess.
+ On error, a `false' value is returned. Otherwise, the return
+ status is `true', and additional information about the redirection
+ is returned in the `ibufp' and `obufp' pointers. For input
+ redirections, the `*ibufp' value should be non-NULL, and `*obufp'
+ should be NULL. For output redirections, the `*obufp' value
+ should be non-NULL, and `*ibufp' should be NULL. For two-way
+ coprocesses, both values should be non-NULL. In the usual case,
+ the extension is interested in `(*ibufp)->fd' and/or
+ `fileno((*obufp)->fp)'. If the file is not already open, and the
+ fd argument is non-negative, `gawk' will use that file descriptor
+ instead of opening the file in the usual way. If the fd is
+ non-negative, but the file exists already, `gawk' ignores the fd
+ and returns the existing file. It is the caller's responsibility
+ to notice that neither the fd in the returned `awk_input_buf_t'
+ nor the fd in the returned `awk_output_buf_t' matches the
+ requested value. Note that supplying a file descriptor is
+ currently NOT supported for pipes. It should work for input,
+ output, append, and two-way (coprocess) sockets. If `filetype' is
+ two-way, we assume that it is a socket! Note that in the two-way
+ case, the input and output file descriptors may differ. To check
+ for success, one must check whether either matches.
+
+ It is anticipated that this API function will be used to implement
+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
---------------------
The API provides two sets of variables. The first provides information
@@ -24644,7 +24759,7 @@ information about how `gawk' was invoked.

File: gawk.info, Node: Extension Versioning, Next: Extension API Informational Variables, Up: Extension API Variables
-16.4.12.1 API Version Constants and Variables
+16.4.13.1 API Version Constants and Variables
.............................................
The API provides both a "major" and a "minor" version number. The API
@@ -24693,7 +24808,7 @@ Boilerplate::).

File: gawk.info, Node: Extension API Informational Variables, Prev: Extension Versioning, Up: Extension API Variables
-16.4.12.2 Informational Variables
+16.4.13.2 Informational Variables
.................................
The API provides access to several variables that describe whether the
@@ -24728,7 +24843,7 @@ not change during execution.

File: gawk.info, Node: Extension API Boilerplate, Prev: Extension API Variables, Up: Extension API Description
-16.4.13 Boilerplate Code
+16.4.14 Boilerplate Code
------------------------
As mentioned earlier (*note Extension Mechanism Outline::), the function
@@ -32245,9 +32360,9 @@ Index
(line 143)
* dark corner, exit statement: Exit Statement. (line 30)
* dark corner, field separators: Full Line Fields. (line 22)
-* dark corner, FILENAME variable <1>: Auto-set. (line 104)
+* dark corner, FILENAME variable <1>: Auto-set. (line 109)
* dark corner, FILENAME variable: Getline Notes. (line 19)
-* dark corner, FNR/NR variables: Auto-set. (line 328)
+* dark corner, FNR/NR variables: Auto-set. (line 341)
* dark corner, format-control characters: Control Letters. (line 18)
* dark corner, FS as null string: Single Character Fields.
(line 20)
@@ -32441,7 +32556,7 @@ Index
* differences in awk and gawk, FIELDWIDTHS variable: User-modified.
(line 37)
* differences in awk and gawk, FPAT variable: User-modified. (line 43)
-* differences in awk and gawk, FUNCTAB variable: Auto-set. (line 130)
+* differences in awk and gawk, FUNCTAB variable: Auto-set. (line 135)
* differences in awk and gawk, function arguments (gawk): Calling Built-in.
(line 16)
* differences in awk and gawk, getline command: Getline. (line 19)
@@ -32464,7 +32579,7 @@ Index
(line 263)
* differences in awk and gawk, print/printf statements: Format Modifiers.
(line 13)
-* differences in awk and gawk, PROCINFO array: Auto-set. (line 144)
+* differences in awk and gawk, PROCINFO array: Auto-set. (line 149)
* differences in awk and gawk, read timeouts: Read Timeout. (line 6)
* differences in awk and gawk, record separators: awk split records.
(line 125)
@@ -32472,9 +32587,11 @@ Index
(line 43)
* differences in awk and gawk, regular expressions: Case-sensitivity.
(line 26)
+* differences in awk and gawk, retrying input: Retrying Input.
+ (line 6)
* differences in awk and gawk, RS/RT variables: gawk split records.
(line 58)
-* differences in awk and gawk, RT variable: Auto-set. (line 279)
+* differences in awk and gawk, RT variable: Auto-set. (line 292)
* differences in awk and gawk, single-character fields: Single Character Fields.
(line 6)
* differences in awk and gawk, split() function: String Functions.
@@ -32482,7 +32599,7 @@ Index
* differences in awk and gawk, strings: Scalar Constants. (line 20)
* differences in awk and gawk, strings, storing: gawk split records.
(line 77)
-* differences in awk and gawk, SYMTAB variable: Auto-set. (line 283)
+* differences in awk and gawk, SYMTAB variable: Auto-set. (line 296)
* differences in awk and gawk, TEXTDOMAIN variable: User-modified.
(line 151)
* differences in awk and gawk, trunc-mod operation: Arithmetic Ops.
@@ -32523,8 +32640,8 @@ Index
* dynamically loaded extensions: Dynamic Extensions. (line 6)
* e debugger command (alias for enable): Breakpoint Control. (line 73)
* EBCDIC: Ordinal Functions. (line 45)
-* effective group ID of gawk user: Auto-set. (line 149)
-* effective user ID of gawk user: Auto-set. (line 153)
+* effective group ID of gawk user: Auto-set. (line 154)
+* effective user ID of gawk user: Auto-set. (line 162)
* egrep utility <1>: Egrep Program. (line 6)
* egrep utility: Bracket Expressions. (line 26)
* egrep.awk program: Egrep Program. (line 54)
@@ -32639,7 +32756,7 @@ Index
(line 6)
* extension API version: Extension Versioning.
(line 6)
-* extension API, version number: Auto-set. (line 246)
+* extension API, version number: Auto-set. (line 255)
* extension example: Extension Example. (line 6)
* extension registration: Registration Functions.
(line 6)
@@ -32720,7 +32837,7 @@ Index
* file names, distinguishing: Auto-set. (line 56)
* file names, in compatibility mode: Special Caveats. (line 9)
* file names, standard streams in gawk: Special FD. (line 48)
-* FILENAME variable <1>: Auto-set. (line 104)
+* FILENAME variable <1>: Auto-set. (line 109)
* FILENAME variable: Reading Files. (line 6)
* FILENAME variable, getline, setting with: Getline Notes. (line 19)
* filenames, assignments as: Ignoring Assigns. (line 6)
@@ -32788,9 +32905,9 @@ Index
* flush buffered output: I/O Functions. (line 28)
* fnmatch() extension function: Extension Sample Fnmatch.
(line 12)
-* FNR variable <1>: Auto-set. (line 114)
+* FNR variable <1>: Auto-set. (line 119)
* FNR variable: Records. (line 6)
-* FNR variable, changing: Auto-set. (line 328)
+* FNR variable, changing: Auto-set. (line 341)
* for statement: For Statement. (line 6)
* for statement, looping over arrays: Scanning an Array. (line 20)
* fork() extension function: Extension Sample Fork.
@@ -32840,7 +32957,7 @@ Index
* FSF (Free Software Foundation): Manual History. (line 6)
* fts() extension function: Extension Sample File Functions.
(line 61)
-* FUNCTAB array: Auto-set. (line 130)
+* FUNCTAB array: Auto-set. (line 135)
* function calls: Function Calls. (line 6)
* function calls, indirect: Indirect Calls. (line 6)
* function calls, indirect, @-notation for: Indirect Calls. (line 47)
@@ -32890,7 +33007,7 @@ Index
* G-d: Acknowledgments. (line 94)
* Garfinkle, Scott: Contributors. (line 34)
* gawk program, dynamic profiling: Profiling. (line 178)
-* gawk version: Auto-set. (line 221)
+* gawk version: Auto-set. (line 230)
* gawk, ARGIND variable in: Other Arguments. (line 15)
* gawk, awk and <1>: This Manual. (line 14)
* gawk, awk and: Preface. (line 21)
@@ -32925,7 +33042,7 @@ Index
* gawk, FPAT variable in <1>: User-modified. (line 43)
* gawk, FPAT variable in: Splitting By Content.
(line 25)
-* gawk, FUNCTAB array in: Auto-set. (line 130)
+* gawk, FUNCTAB array in: Auto-set. (line 135)
* gawk, function arguments and: Calling Built-in. (line 16)
* gawk, hexadecimal numbers and: Nondecimal-numbers. (line 42)
* gawk, IGNORECASE variable in <1>: Array Sorting Functions.
@@ -32957,7 +33074,7 @@ Index
* gawk, predefined variables and: Built-in Variables. (line 14)
* gawk, PROCINFO array in <1>: Two-way I/O. (line 99)
* gawk, PROCINFO array in <2>: Time Functions. (line 47)
-* gawk, PROCINFO array in: Auto-set. (line 144)
+* gawk, PROCINFO array in: Auto-set. (line 149)
* gawk, regexp constants and: Using Constant Regexps.
(line 28)
* gawk, regular expressions, case sensitivity: Case-sensitivity.
@@ -32965,14 +33082,14 @@ Index
* gawk, regular expressions, operators: GNU Regexp Operators.
(line 6)
* gawk, regular expressions, precedence: Regexp Operators. (line 161)
-* gawk, RT variable in <1>: Auto-set. (line 279)
+* gawk, RT variable in <1>: Auto-set. (line 292)
* gawk, RT variable in <2>: Multiple Line. (line 129)
* gawk, RT variable in: awk split records. (line 125)
* gawk, See Also awk: Preface. (line 34)
* gawk, source code, obtaining: Getting. (line 6)
* gawk, splitting fields and: Constant Size. (line 87)
* gawk, string-translation functions: I18N Functions. (line 6)
-* gawk, SYMTAB array in: Auto-set. (line 283)
+* gawk, SYMTAB array in: Auto-set. (line 296)
* gawk, TEXTDOMAIN variable in: User-modified. (line 151)
* gawk, timestamps: Time Functions. (line 6)
* gawk, uses for: Preface. (line 34)
@@ -33064,7 +33181,7 @@ Index
* Grigera, Juan: Contributors. (line 57)
* group database, reading: Group Functions. (line 6)
* group file: Group Functions. (line 6)
-* group ID of gawk user: Auto-set. (line 194)
+* group ID of gawk user: Auto-set. (line 203)
* groups, information about: Group Functions. (line 6)
* gsub <1>: String Functions. (line 140)
* gsub: Using Constant Regexps.
@@ -33359,7 +33476,7 @@ Index
* mawk utility <3>: Concatenation. (line 36)
* mawk utility <4>: Getline/Pipe. (line 62)
* mawk utility: Escape Sequences. (line 120)
-* maximum precision supported by MPFR library: Auto-set. (line 235)
+* maximum precision supported by MPFR library: Auto-set. (line 244)
* McIlroy, Doug: Glossary. (line 177)
* McPhee, Patrick: Contributors. (line 100)
* message object files: Explaining gettext. (line 42)
@@ -33372,7 +33489,7 @@ Index
* messages from extensions: Printing Messages. (line 6)
* metacharacters in regular expressions: Regexp Operators. (line 6)
* metacharacters, escape sequences for: Escape Sequences. (line 139)
-* minimum precision supported by MPFR library: Auto-set. (line 238)
+* minimum precision supported by MPFR library: Auto-set. (line 247)
* mktime: Time Functions. (line 25)
* modifiers, in format specifiers: Format Modifiers. (line 6)
* monetary information, localization: Explaining gettext. (line 104)
@@ -33421,7 +33538,7 @@ Index
(line 47)
* nexti debugger command: Debugger Execution Control.
(line 49)
-* NF variable <1>: Auto-set. (line 119)
+* NF variable <1>: Auto-set. (line 124)
* NF variable: Fields. (line 33)
* NF variable, decrementing: Changing Fields. (line 107)
* ni debugger command (alias for nexti): Debugger Execution Control.
@@ -33430,9 +33547,9 @@ Index
* non-existent array elements: Reference to Elements.
(line 23)
* not Boolean-logic operator: Boolean Ops. (line 6)
-* NR variable <1>: Auto-set. (line 139)
+* NR variable <1>: Auto-set. (line 144)
* NR variable: Records. (line 6)
-* NR variable, changing: Auto-set. (line 328)
+* NR variable, changing: Auto-set. (line 341)
* null strings <1>: Basic Data Typing. (line 26)
* null strings <2>: Truth Values. (line 6)
* null strings <3>: Regexp Field Splitting.
@@ -33546,7 +33663,7 @@ Index
* p debugger command (alias for print): Viewing And Changing Data.
(line 36)
* Papadopoulos, Panos: Contributors. (line 128)
-* parent process ID of gawk process: Auto-set. (line 203)
+* parent process ID of gawk process: Auto-set. (line 212)
* parentheses (), in a profile: Profiling. (line 146)
* parentheses (), regexp operator: Regexp Operators. (line 81)
* password file: Passwd Functions. (line 16)
@@ -33712,24 +33829,24 @@ Index
* printing, unduplicated lines of text: Uniq Program. (line 6)
* printing, user information: Id Program. (line 6)
* private variables: Library Names. (line 11)
-* process group idIDof gawk process: Auto-set. (line 197)
-* process ID of gawk process: Auto-set. (line 200)
+* process group idIDof gawk process: Auto-set. (line 206)
+* process ID of gawk process: Auto-set. (line 209)
* processes, two-way communications with: Two-way I/O. (line 6)
* processing data: Basic High Level. (line 6)
* PROCINFO array <1>: Passwd Functions. (line 6)
* PROCINFO array <2>: Time Functions. (line 47)
-* PROCINFO array: Auto-set. (line 144)
+* PROCINFO array: Auto-set. (line 149)
* PROCINFO array, and communications via ptys: Two-way I/O. (line 99)
* PROCINFO array, and group membership: Group Functions. (line 6)
* PROCINFO array, and user and group ID numbers: Id Program. (line 15)
* PROCINFO array, testing the field splitting: Passwd Functions.
(line 154)
-* PROCINFO array, uses: Auto-set. (line 256)
+* PROCINFO array, uses: Auto-set. (line 265)
* PROCINFO, values of sorted_in: Controlling Scanning.
(line 26)
* profiling awk programs: Profiling. (line 6)
* profiling awk programs, dynamically: Profiling. (line 178)
-* program identifiers: Auto-set. (line 162)
+* program identifiers: Auto-set. (line 171)
* program, definition of: Getting Started. (line 21)
* programming conventions, --non-decimal-data option: Nondecimal Data.
(line 35)
@@ -33864,6 +33981,7 @@ Index
* relational operators, See comparison operators: Typing and Comparison.
(line 9)
* replace in string: String Functions. (line 408)
+* retrying input: Retrying Input. (line 6)
* return debugger command: Debugger Execution Control.
(line 54)
* return statement, user-defined functions: Return Statement. (line 6)
@@ -33887,7 +34005,7 @@ Index
* right shift: Bitwise Functions. (line 53)
* right shift, bitwise: Bitwise Functions. (line 32)
* Ritchie, Dennis: Basic Data Typing. (line 54)
-* RLENGTH variable: Auto-set. (line 266)
+* RLENGTH variable: Auto-set. (line 279)
* RLENGTH variable, match() function and: String Functions. (line 228)
* Robbins, Arnold <1>: Future Extensions. (line 6)
* Robbins, Arnold <2>: Bugs. (line 70)
@@ -33913,9 +34031,9 @@ Index
* RS variable: awk split records. (line 12)
* RS variable, multiline records and: Multiple Line. (line 17)
* rshift: Bitwise Functions. (line 53)
-* RSTART variable: Auto-set. (line 272)
+* RSTART variable: Auto-set. (line 285)
* RSTART variable, match() function and: String Functions. (line 228)
-* RT variable <1>: Auto-set. (line 279)
+* RT variable <1>: Auto-set. (line 292)
* RT variable <2>: Multiple Line. (line 129)
* RT variable: awk split records. (line 125)
* Rubin, Paul <1>: Contributors. (line 15)
@@ -33935,7 +34053,7 @@ Index
* scanning arrays: Scanning an Array. (line 6)
* scanning multidimensional arrays: Multiscanning. (line 11)
* Schorr, Andrew <1>: Contributors. (line 133)
-* Schorr, Andrew <2>: Auto-set. (line 311)
+* Schorr, Andrew <2>: Auto-set. (line 324)
* Schorr, Andrew: Acknowledgments. (line 60)
* Schreiber, Bert: Acknowledgments. (line 38)
* Schreiber, Rita: Acknowledgments. (line 38)
@@ -34018,7 +34136,7 @@ Index
(line 106)
* sidebar, Changing FS Does Not Affect the Fields: Full Line Fields.
(line 14)
-* sidebar, Changing NR and FNR: Auto-set. (line 326)
+* sidebar, Changing NR and FNR: Auto-set. (line 339)
* sidebar, Controlling Output Buffering with system(): I/O Functions.
(line 138)
* sidebar, Escape Sequences for Metacharacters: Escape Sequences.
@@ -34180,9 +34298,9 @@ Index
* substr: String Functions. (line 481)
* substring: String Functions. (line 481)
* Sumner, Andrew: Other Versions. (line 68)
-* supplementary groups of gawk process: Auto-set. (line 251)
+* supplementary groups of gawk process: Auto-set. (line 260)
* switch statement: Switch Statement. (line 6)
-* SYMTAB array: Auto-set. (line 283)
+* SYMTAB array: Auto-set. (line 296)
* syntactic ambiguity: /= operator vs. /=.../ regexp constant: Assignment Ops.
(line 148)
* system: I/O Functions. (line 106)
@@ -34359,10 +34477,10 @@ Index
* variables, uninitialized, as array subscripts: Uninitialized Subscripts.
(line 6)
* variables, user-defined: Variables. (line 6)
-* version of gawk: Auto-set. (line 221)
-* version of gawk extension API: Auto-set. (line 246)
-* version of GNU MP library: Auto-set. (line 232)
-* version of GNU MPFR library: Auto-set. (line 228)
+* version of gawk: Auto-set. (line 230)
+* version of gawk extension API: Auto-set. (line 255)
+* version of GNU MP library: Auto-set. (line 241)
+* version of GNU MPFR library: Auto-set. (line 237)
* vertical bar (|): Regexp Operators. (line 70)
* vertical bar (|), | operator (I/O) <1>: Precedence. (line 65)
* vertical bar (|), | operator (I/O): Getline/Pipe. (line 9)
@@ -34452,560 +34570,562 @@ 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-154997
-Node: This Manual55143
-Ref: This Manual-Footnote-161643
-Node: Conventions61743
-Node: Manual History64080
-Ref: Manual History-Footnote-167073
-Ref: Manual History-Footnote-267114
-Node: How To Contribute67188
-Node: Acknowledgments68317
-Node: Getting Started73134
-Node: Running gawk75573
-Node: One-shot76763
-Node: Read Terminal78027
-Node: Long80058
-Node: Executable Scripts81571
-Ref: Executable Scripts-Footnote-184360
-Node: Comments84463
-Node: Quoting86945
-Node: DOS Quoting92463
-Node: Sample Data Files93138
-Node: Very Simple95733
-Node: Two Rules100632
-Node: More Complex102518
-Node: Statements/Lines105380
-Ref: Statements/Lines-Footnote-1109835
-Node: Other Features110100
-Node: When111031
-Ref: When-Footnote-1112785
-Node: Intro Summary112850
-Node: Invoking Gawk113733
-Node: Command Line115247
-Node: Options116045
-Ref: Options-Footnote-1131849
-Ref: Options-Footnote-2132078
-Node: Other Arguments132103
-Node: Naming Standard Input135051
-Node: Environment Variables136144
-Node: AWKPATH Variable136702
-Ref: AWKPATH Variable-Footnote-1140115
-Ref: AWKPATH Variable-Footnote-2140160
-Node: AWKLIBPATH Variable140420
-Node: Other Environment Variables141676
-Node: Exit Status145164
-Node: Include Files145840
-Node: Loading Shared Libraries149437
-Node: Obsolete150864
-Node: Undocumented151561
-Node: Invoking Summary151828
-Node: Regexp153492
-Node: Regexp Usage154946
-Node: Escape Sequences156983
-Node: Regexp Operators163224
-Ref: Regexp Operators-Footnote-1170650
-Ref: Regexp Operators-Footnote-2170797
-Node: Bracket Expressions170895
-Ref: table-char-classes172910
-Node: Leftmost Longest175834
-Node: Computed Regexps177136
-Node: GNU Regexp Operators180533
-Node: Case-sensitivity184206
-Ref: Case-sensitivity-Footnote-1187091
-Ref: Case-sensitivity-Footnote-2187326
-Node: Regexp Summary187434
-Node: Reading Files188901
-Node: Records190995
-Node: awk split records191728
-Node: gawk split records196643
-Ref: gawk split records-Footnote-1201187
-Node: Fields201224
-Ref: Fields-Footnote-1204000
-Node: Nonconstant Fields204086
-Ref: Nonconstant Fields-Footnote-1206329
-Node: Changing Fields206533
-Node: Field Separators212462
-Node: Default Field Splitting215167
-Node: Regexp Field Splitting216284
-Node: Single Character Fields219634
-Node: Command Line Field Separator220693
-Node: Full Line Fields223905
-Ref: Full Line Fields-Footnote-1225422
-Ref: Full Line Fields-Footnote-2225468
-Node: Field Splitting Summary225569
-Node: Constant Size227643
-Node: Splitting By Content232232
-Ref: Splitting By Content-Footnote-1236226
-Node: Multiple Line236389
-Ref: Multiple Line-Footnote-1242275
-Node: Getline242454
-Node: Plain Getline244666
-Node: Getline/Variable247306
-Node: Getline/File248454
-Node: Getline/Variable/File249838
-Ref: Getline/Variable/File-Footnote-1251441
-Node: Getline/Pipe251528
-Node: Getline/Variable/Pipe254211
-Node: Getline/Coprocess255342
-Node: Getline/Variable/Coprocess256594
-Node: Getline Notes257333
-Node: Getline Summary260125
-Ref: table-getline-variants260537
-Node: Read Timeout261366
-Ref: Read Timeout-Footnote-1265190
-Node: Command-line directories265248
-Node: Input Summary266153
-Node: Input Exercises269454
-Node: Printing270182
-Node: Print271959
-Node: Print Examples273416
-Node: Output Separators276195
-Node: OFMT278213
-Node: Printf279567
-Node: Basic Printf280352
-Node: Control Letters281922
-Node: Format Modifiers285905
-Node: Printf Examples291914
-Node: Redirection294400
-Node: Special FD301241
-Ref: Special FD-Footnote-1304401
-Node: Special Files304475
-Node: Other Inherited Files305092
-Node: Special Network306092
-Node: Special Caveats306954
-Node: Close Files And Pipes307905
-Ref: Close Files And Pipes-Footnote-1315087
-Ref: Close Files And Pipes-Footnote-2315235
-Node: Output Summary315385
-Node: Output Exercises316383
-Node: Expressions317063
-Node: Values318248
-Node: Constants318926
-Node: Scalar Constants319617
-Ref: Scalar Constants-Footnote-1320476
-Node: Nondecimal-numbers320726
-Node: Regexp Constants323744
-Node: Using Constant Regexps324269
-Node: Variables327412
-Node: Using Variables328067
-Node: Assignment Options329978
-Node: Conversion331853
-Node: Strings And Numbers332377
-Ref: Strings And Numbers-Footnote-1335442
-Node: Locale influences conversions335551
-Ref: table-locale-affects338298
-Node: All Operators338886
-Node: Arithmetic Ops339516
-Node: Concatenation342021
-Ref: Concatenation-Footnote-1344840
-Node: Assignment Ops344946
-Ref: table-assign-ops349925
-Node: Increment Ops351197
-Node: Truth Values and Conditions354635
-Node: Truth Values355720
-Node: Typing and Comparison356769
-Node: Variable Typing357579
-Node: Comparison Operators361232
-Ref: table-relational-ops361642
-Node: POSIX String Comparison365137
-Ref: POSIX String Comparison-Footnote-1366209
-Node: Boolean Ops366347
-Ref: Boolean Ops-Footnote-1370826
-Node: Conditional Exp370917
-Node: Function Calls372644
-Node: Precedence376524
-Node: Locales380185
-Node: Expressions Summary381817
-Node: Patterns and Actions384377
-Node: Pattern Overview385497
-Node: Regexp Patterns387176
-Node: Expression Patterns387719
-Node: Ranges391429
-Node: BEGIN/END394535
-Node: Using BEGIN/END395296
-Ref: Using BEGIN/END-Footnote-1398030
-Node: I/O And BEGIN/END398136
-Node: BEGINFILE/ENDFILE400450
-Node: Empty403351
-Node: Using Shell Variables403668
-Node: Action Overview405941
-Node: Statements408267
-Node: If Statement410115
-Node: While Statement411610
-Node: Do Statement413639
-Node: For Statement414783
-Node: Switch Statement417940
-Node: Break Statement420322
-Node: Continue Statement422363
-Node: Next Statement424190
-Node: Nextfile Statement426571
-Node: Exit Statement429201
-Node: Built-in Variables431604
-Node: User-modified432737
-Ref: User-modified-Footnote-1440418
-Node: Auto-set440480
-Ref: Auto-set-Footnote-1454172
-Ref: Auto-set-Footnote-2454377
-Node: ARGC and ARGV454433
-Node: Pattern Action Summary458651
-Node: Arrays461078
-Node: Array Basics462407
-Node: Array Intro463251
-Ref: figure-array-elements465215
-Ref: Array Intro-Footnote-1467741
-Node: Reference to Elements467869
-Node: Assigning Elements470321
-Node: Array Example470812
-Node: Scanning an Array472570
-Node: Controlling Scanning475586
-Ref: Controlling Scanning-Footnote-1480782
-Node: Numeric Array Subscripts481098
-Node: Uninitialized Subscripts483283
-Node: Delete484900
-Ref: Delete-Footnote-1487643
-Node: Multidimensional487700
-Node: Multiscanning490797
-Node: Arrays of Arrays492386
-Node: Arrays Summary497145
-Node: Functions499237
-Node: Built-in500136
-Node: Calling Built-in501214
-Node: Numeric Functions503205
-Ref: Numeric Functions-Footnote-1508024
-Ref: Numeric Functions-Footnote-2508381
-Ref: Numeric Functions-Footnote-3508429
-Node: String Functions508701
-Ref: String Functions-Footnote-1532176
-Ref: String Functions-Footnote-2532305
-Ref: String Functions-Footnote-3532553
-Node: Gory Details532640
-Ref: table-sub-escapes534421
-Ref: table-sub-proposed535941
-Ref: table-posix-sub537305
-Ref: table-gensub-escapes538841
-Ref: Gory Details-Footnote-1539673
-Node: I/O Functions539824
-Ref: I/O Functions-Footnote-1547042
-Node: Time Functions547189
-Ref: Time Functions-Footnote-1557677
-Ref: Time Functions-Footnote-2557745
-Ref: Time Functions-Footnote-3557903
-Ref: Time Functions-Footnote-4558014
-Ref: Time Functions-Footnote-5558126
-Ref: Time Functions-Footnote-6558353
-Node: Bitwise Functions558619
-Ref: table-bitwise-ops559181
-Ref: Bitwise Functions-Footnote-1563490
-Node: Type Functions563659
-Node: I18N Functions564810
-Node: User-defined566455
-Node: Definition Syntax567260
-Ref: Definition Syntax-Footnote-1572667
-Node: Function Example572738
-Ref: Function Example-Footnote-1575657
-Node: Function Caveats575679
-Node: Calling A Function576197
-Node: Variable Scope577155
-Node: Pass By Value/Reference580143
-Node: Return Statement583638
-Node: Dynamic Typing586619
-Node: Indirect Calls587548
-Ref: Indirect Calls-Footnote-1598850
-Node: Functions Summary598978
-Node: Library Functions601680
-Ref: Library Functions-Footnote-1605289
-Ref: Library Functions-Footnote-2605432
-Node: Library Names605603
-Ref: Library Names-Footnote-1609057
-Ref: Library Names-Footnote-2609280
-Node: General Functions609366
-Node: Strtonum Function610469
-Node: Assert Function613491
-Node: Round Function616815
-Node: Cliff Random Function618356
-Node: Ordinal Functions619372
-Ref: Ordinal Functions-Footnote-1622435
-Ref: Ordinal Functions-Footnote-2622687
-Node: Join Function622898
-Ref: Join Function-Footnote-1624667
-Node: Getlocaltime Function624867
-Node: Readfile Function628611
-Node: Shell Quoting630581
-Node: Data File Management631982
-Node: Filetrans Function632614
-Node: Rewind Function636670
-Node: File Checking638057
-Ref: File Checking-Footnote-1639389
-Node: Empty Files639590
-Node: Ignoring Assigns641569
-Node: Getopt Function643120
-Ref: Getopt Function-Footnote-1654582
-Node: Passwd Functions654782
-Ref: Passwd Functions-Footnote-1663619
-Node: Group Functions663707
-Ref: Group Functions-Footnote-1671601
-Node: Walking Arrays671814
-Node: Library Functions Summary673417
-Node: Library Exercises674818
-Node: Sample Programs676098
-Node: Running Examples676868
-Node: Clones677596
-Node: Cut Program678820
-Node: Egrep Program688539
-Ref: Egrep Program-Footnote-1696037
-Node: Id Program696147
-Node: Split Program699792
-Ref: Split Program-Footnote-1703240
-Node: Tee Program703368
-Node: Uniq Program706157
-Node: Wc Program713576
-Ref: Wc Program-Footnote-1717826
-Node: Miscellaneous Programs717920
-Node: Dupword Program719133
-Node: Alarm Program721164
-Node: Translate Program725968
-Ref: Translate Program-Footnote-1730533
-Node: Labels Program730803
-Ref: Labels Program-Footnote-1734154
-Node: Word Sorting734238
-Node: History Sorting738309
-Node: Extract Program740145
-Node: Simple Sed747670
-Node: Igawk Program750738
-Ref: Igawk Program-Footnote-1765062
-Ref: Igawk Program-Footnote-2765263
-Ref: Igawk Program-Footnote-3765385
-Node: Anagram Program765500
-Node: Signature Program768557
-Node: Programs Summary769804
-Node: Programs Exercises770997
-Ref: Programs Exercises-Footnote-1775128
-Node: Advanced Features775219
-Node: Nondecimal Data777167
-Node: Array Sorting778757
-Node: Controlling Array Traversal779454
-Ref: Controlling Array Traversal-Footnote-1787787
-Node: Array Sorting Functions787905
-Ref: Array Sorting Functions-Footnote-1791794
-Node: Two-way I/O791990
-Ref: Two-way I/O-Footnote-1796935
-Ref: Two-way I/O-Footnote-2797121
-Node: TCP/IP Networking797203
-Node: Profiling800076
-Node: Advanced Features Summary808353
-Node: Internationalization810286
-Node: I18N and L10N811766
-Node: Explaining gettext812452
-Ref: Explaining gettext-Footnote-1817477
-Ref: Explaining gettext-Footnote-2817661
-Node: Programmer i18n817826
-Ref: Programmer i18n-Footnote-1822692
-Node: Translator i18n822741
-Node: String Extraction823535
-Ref: String Extraction-Footnote-1824666
-Node: Printf Ordering824752
-Ref: Printf Ordering-Footnote-1827538
-Node: I18N Portability827602
-Ref: I18N Portability-Footnote-1830057
-Node: I18N Example830120
-Ref: I18N Example-Footnote-1832923
-Node: Gawk I18N832995
-Node: I18N Summary833633
-Node: Debugger834972
-Node: Debugging835994
-Node: Debugging Concepts836435
-Node: Debugging Terms838288
-Node: Awk Debugging840860
-Node: Sample Debugging Session841754
-Node: Debugger Invocation842274
-Node: Finding The Bug843658
-Node: List of Debugger Commands850133
-Node: Breakpoint Control851466
-Node: Debugger Execution Control855162
-Node: Viewing And Changing Data858526
-Node: Execution Stack861904
-Node: Debugger Info863541
-Node: Miscellaneous Debugger Commands867558
-Node: Readline Support872587
-Node: Limitations873479
-Node: Debugging Summary875593
-Node: Arbitrary Precision Arithmetic876761
-Node: Computer Arithmetic878177
-Ref: table-numeric-ranges881775
-Ref: Computer Arithmetic-Footnote-1882634
-Node: Math Definitions882691
-Ref: table-ieee-formats885979
-Ref: Math Definitions-Footnote-1886583
-Node: MPFR features886688
-Node: FP Math Caution888359
-Ref: FP Math Caution-Footnote-1889409
-Node: Inexactness of computations889778
-Node: Inexact representation890737
-Node: Comparing FP Values892094
-Node: Errors accumulate893176
-Node: Getting Accuracy894609
-Node: Try To Round897271
-Node: Setting precision898170
-Ref: table-predefined-precision-strings898854
-Node: Setting the rounding mode900643
-Ref: table-gawk-rounding-modes901007
-Ref: Setting the rounding mode-Footnote-1904462
-Node: Arbitrary Precision Integers904641
-Ref: Arbitrary Precision Integers-Footnote-1909540
-Node: POSIX Floating Point Problems909689
-Ref: POSIX Floating Point Problems-Footnote-1913562
-Node: Floating point summary913600
-Node: Dynamic Extensions915794
-Node: Extension Intro917346
-Node: Plugin License918612
-Node: Extension Mechanism Outline919409
-Ref: figure-load-extension919837
-Ref: figure-register-new-function921317
-Ref: figure-call-new-function922321
-Node: Extension API Description924307
-Node: Extension API Functions Introduction925757
-Node: General Data Types930581
-Ref: General Data Types-Footnote-1936320
-Node: Memory Allocation Functions936619
-Ref: Memory Allocation Functions-Footnote-1939458
-Node: Constructor Functions939554
-Node: Registration Functions941288
-Node: Extension Functions941973
-Node: Exit Callback Functions944270
-Node: Extension Version String945518
-Node: Input Parsers946183
-Node: Output Wrappers956062
-Node: Two-way processors960577
-Node: Printing Messages962781
-Ref: Printing Messages-Footnote-1963857
-Node: Updating `ERRNO'964009
-Node: Requesting Values964749
-Ref: table-value-types-returned965477
-Node: Accessing Parameters966434
-Node: Symbol Table Access967665
-Node: Symbol table by name968179
-Node: Symbol table by cookie970160
-Ref: Symbol table by cookie-Footnote-1974304
-Node: Cached values974367
-Ref: Cached values-Footnote-1977866
-Node: Array Manipulation977957
-Ref: Array Manipulation-Footnote-1979055
-Node: Array Data Types979092
-Ref: Array Data Types-Footnote-1981747
-Node: Array Functions981839
-Node: Flattening Arrays985693
-Node: Creating Arrays992585
-Node: Extension API Variables997356
-Node: Extension Versioning997992
-Node: Extension API Informational Variables999893
-Node: Extension API Boilerplate1000958
-Node: Finding Extensions1004767
-Node: Extension Example1005327
-Node: Internal File Description1006099
-Node: Internal File Ops1010166
-Ref: Internal File Ops-Footnote-11021836
-Node: Using Internal File Ops1021976
-Ref: Using Internal File Ops-Footnote-11024359
-Node: Extension Samples1024632
-Node: Extension Sample File Functions1026158
-Node: Extension Sample Fnmatch1033796
-Node: Extension Sample Fork1035287
-Node: Extension Sample Inplace1036502
-Node: Extension Sample Ord1038177
-Node: Extension Sample Readdir1039013
-Ref: table-readdir-file-types1039889
-Node: Extension Sample Revout1040700
-Node: Extension Sample Rev2way1041290
-Node: Extension Sample Read write array1042030
-Node: Extension Sample Readfile1043970
-Node: Extension Sample Time1045065
-Node: Extension Sample API Tests1046414
-Node: gawkextlib1046905
-Node: Extension summary1049563
-Node: Extension Exercises1053252
-Node: Language History1053974
-Node: V7/SVR3.11055630
-Node: SVR41057811
-Node: POSIX1059256
-Node: BTL1060645
-Node: POSIX/GNU1061379
-Node: Feature History1067003
-Node: Common Extensions1080101
-Node: Ranges and Locales1081425
-Ref: Ranges and Locales-Footnote-11086043
-Ref: Ranges and Locales-Footnote-21086070
-Ref: Ranges and Locales-Footnote-31086304
-Node: Contributors1086525
-Node: History summary1092066
-Node: Installation1093436
-Node: Gawk Distribution1094382
-Node: Getting1094866
-Node: Extracting1095689
-Node: Distribution contents1097324
-Node: Unix Installation1103389
-Node: Quick Installation1104072
-Node: Shell Startup Files1106483
-Node: Additional Configuration Options1107562
-Node: Configuration Philosophy1109301
-Node: Non-Unix Installation1111670
-Node: PC Installation1112128
-Node: PC Binary Installation1113447
-Node: PC Compiling1115295
-Ref: PC Compiling-Footnote-11118316
-Node: PC Testing1118425
-Node: PC Using1119601
-Node: Cygwin1123716
-Node: MSYS1124539
-Node: VMS Installation1125039
-Node: VMS Compilation1125831
-Ref: VMS Compilation-Footnote-11127053
-Node: VMS Dynamic Extensions1127111
-Node: VMS Installation Details1128795
-Node: VMS Running1131047
-Node: VMS GNV1133883
-Node: VMS Old Gawk1134617
-Node: Bugs1135087
-Node: Other Versions1138970
-Node: Installation summary1145398
-Node: Notes1146454
-Node: Compatibility Mode1147319
-Node: Additions1148101
-Node: Accessing The Source1149026
-Node: Adding Code1150462
-Node: New Ports1156627
-Node: Derived Files1161109
-Ref: Derived Files-Footnote-11166584
-Ref: Derived Files-Footnote-21166618
-Ref: Derived Files-Footnote-31167214
-Node: Future Extensions1167328
-Node: Implementation Limitations1167934
-Node: Extension Design1169182
-Node: Old Extension Problems1170336
-Ref: Old Extension Problems-Footnote-11171853
-Node: Extension New Mechanism Goals1171910
-Ref: Extension New Mechanism Goals-Footnote-11175270
-Node: Extension Other Design Decisions1175459
-Node: Extension Future Growth1177567
-Node: Old Extension Mechanism1178403
-Node: Notes summary1180165
-Node: Basic Concepts1181351
-Node: Basic High Level1182032
-Ref: figure-general-flow1182304
-Ref: figure-process-flow1182903
-Ref: Basic High Level-Footnote-11186132
-Node: Basic Data Typing1186317
-Node: Glossary1189645
-Node: Copying1214803
-Node: GNU Free Documentation License1252359
-Node: Index1277495
+Node: Foreword342385
+Node: Foreword446829
+Node: Preface48360
+Ref: Preface-Footnote-151231
+Ref: Preface-Footnote-251338
+Ref: Preface-Footnote-351571
+Node: History51713
+Node: Names54064
+Ref: Names-Footnote-155157
+Node: This Manual55303
+Ref: This Manual-Footnote-161803
+Node: Conventions61903
+Node: Manual History64240
+Ref: Manual History-Footnote-167233
+Ref: Manual History-Footnote-267274
+Node: How To Contribute67348
+Node: Acknowledgments68477
+Node: Getting Started73294
+Node: Running gawk75733
+Node: One-shot76923
+Node: Read Terminal78187
+Node: Long80218
+Node: Executable Scripts81731
+Ref: Executable Scripts-Footnote-184520
+Node: Comments84623
+Node: Quoting87105
+Node: DOS Quoting92623
+Node: Sample Data Files93298
+Node: Very Simple95893
+Node: Two Rules100792
+Node: More Complex102678
+Node: Statements/Lines105540
+Ref: Statements/Lines-Footnote-1109995
+Node: Other Features110260
+Node: When111191
+Ref: When-Footnote-1112945
+Node: Intro Summary113010
+Node: Invoking Gawk113893
+Node: Command Line115407
+Node: Options116205
+Ref: Options-Footnote-1132009
+Ref: Options-Footnote-2132238
+Node: Other Arguments132263
+Node: Naming Standard Input135211
+Node: Environment Variables136304
+Node: AWKPATH Variable136862
+Ref: AWKPATH Variable-Footnote-1140275
+Ref: AWKPATH Variable-Footnote-2140320
+Node: AWKLIBPATH Variable140580
+Node: Other Environment Variables141836
+Node: Exit Status145324
+Node: Include Files146000
+Node: Loading Shared Libraries149597
+Node: Obsolete151024
+Node: Undocumented151721
+Node: Invoking Summary151988
+Node: Regexp153652
+Node: Regexp Usage155106
+Node: Escape Sequences157143
+Node: Regexp Operators163384
+Ref: Regexp Operators-Footnote-1170810
+Ref: Regexp Operators-Footnote-2170957
+Node: Bracket Expressions171055
+Ref: table-char-classes173070
+Node: Leftmost Longest175994
+Node: Computed Regexps177296
+Node: GNU Regexp Operators180693
+Node: Case-sensitivity184366
+Ref: Case-sensitivity-Footnote-1187251
+Ref: Case-sensitivity-Footnote-2187486
+Node: Regexp Summary187594
+Node: Reading Files189061
+Node: Records191224
+Node: awk split records191957
+Node: gawk split records196872
+Ref: gawk split records-Footnote-1201416
+Node: Fields201453
+Ref: Fields-Footnote-1204229
+Node: Nonconstant Fields204315
+Ref: Nonconstant Fields-Footnote-1206558
+Node: Changing Fields206762
+Node: Field Separators212691
+Node: Default Field Splitting215396
+Node: Regexp Field Splitting216513
+Node: Single Character Fields219863
+Node: Command Line Field Separator220922
+Node: Full Line Fields224134
+Ref: Full Line Fields-Footnote-1225651
+Ref: Full Line Fields-Footnote-2225697
+Node: Field Splitting Summary225798
+Node: Constant Size227872
+Node: Splitting By Content232461
+Ref: Splitting By Content-Footnote-1236455
+Node: Multiple Line236618
+Ref: Multiple Line-Footnote-1242504
+Node: Getline242683
+Node: Plain Getline245167
+Node: Getline/Variable247807
+Node: Getline/File248955
+Node: Getline/Variable/File250339
+Ref: Getline/Variable/File-Footnote-1251942
+Node: Getline/Pipe252029
+Node: Getline/Variable/Pipe254712
+Node: Getline/Coprocess255843
+Node: Getline/Variable/Coprocess257095
+Node: Getline Notes257834
+Node: Getline Summary260626
+Ref: table-getline-variants261038
+Node: Read Timeout261867
+Ref: Read Timeout-Footnote-1265757
+Node: Retrying Input265815
+Node: Command-line directories267010
+Node: Input Summary267917
+Node: Input Exercises271218
+Node: Printing271946
+Node: Print273723
+Node: Print Examples275180
+Node: Output Separators277959
+Node: OFMT279977
+Node: Printf281331
+Node: Basic Printf282116
+Node: Control Letters283686
+Node: Format Modifiers287669
+Node: Printf Examples293678
+Node: Redirection296164
+Node: Special FD303005
+Ref: Special FD-Footnote-1306165
+Node: Special Files306239
+Node: Other Inherited Files306856
+Node: Special Network307856
+Node: Special Caveats308718
+Node: Close Files And Pipes309669
+Ref: Close Files And Pipes-Footnote-1316851
+Ref: Close Files And Pipes-Footnote-2316999
+Node: Output Summary317149
+Node: Output Exercises318147
+Node: Expressions318827
+Node: Values320012
+Node: Constants320690
+Node: Scalar Constants321381
+Ref: Scalar Constants-Footnote-1322240
+Node: Nondecimal-numbers322490
+Node: Regexp Constants325508
+Node: Using Constant Regexps326033
+Node: Variables329176
+Node: Using Variables329831
+Node: Assignment Options331742
+Node: Conversion333617
+Node: Strings And Numbers334141
+Ref: Strings And Numbers-Footnote-1337206
+Node: Locale influences conversions337315
+Ref: table-locale-affects340062
+Node: All Operators340650
+Node: Arithmetic Ops341280
+Node: Concatenation343785
+Ref: Concatenation-Footnote-1346604
+Node: Assignment Ops346710
+Ref: table-assign-ops351689
+Node: Increment Ops352961
+Node: Truth Values and Conditions356399
+Node: Truth Values357484
+Node: Typing and Comparison358533
+Node: Variable Typing359343
+Node: Comparison Operators362996
+Ref: table-relational-ops363406
+Node: POSIX String Comparison366901
+Ref: POSIX String Comparison-Footnote-1367973
+Node: Boolean Ops368111
+Ref: Boolean Ops-Footnote-1372590
+Node: Conditional Exp372681
+Node: Function Calls374408
+Node: Precedence378288
+Node: Locales381949
+Node: Expressions Summary383581
+Node: Patterns and Actions386141
+Node: Pattern Overview387261
+Node: Regexp Patterns388940
+Node: Expression Patterns389483
+Node: Ranges393193
+Node: BEGIN/END396299
+Node: Using BEGIN/END397060
+Ref: Using BEGIN/END-Footnote-1399794
+Node: I/O And BEGIN/END399900
+Node: BEGINFILE/ENDFILE402214
+Node: Empty405115
+Node: Using Shell Variables405432
+Node: Action Overview407705
+Node: Statements410031
+Node: If Statement411879
+Node: While Statement413374
+Node: Do Statement415403
+Node: For Statement416547
+Node: Switch Statement419704
+Node: Break Statement422086
+Node: Continue Statement424127
+Node: Next Statement425954
+Node: Nextfile Statement428335
+Node: Exit Statement430965
+Node: Built-in Variables433368
+Node: User-modified434501
+Ref: User-modified-Footnote-1442182
+Node: Auto-set442244
+Ref: Auto-set-Footnote-1456460
+Ref: Auto-set-Footnote-2456665
+Node: ARGC and ARGV456721
+Node: Pattern Action Summary460939
+Node: Arrays463366
+Node: Array Basics464695
+Node: Array Intro465539
+Ref: figure-array-elements467503
+Ref: Array Intro-Footnote-1470029
+Node: Reference to Elements470157
+Node: Assigning Elements472609
+Node: Array Example473100
+Node: Scanning an Array474858
+Node: Controlling Scanning477874
+Ref: Controlling Scanning-Footnote-1483070
+Node: Numeric Array Subscripts483386
+Node: Uninitialized Subscripts485571
+Node: Delete487188
+Ref: Delete-Footnote-1489931
+Node: Multidimensional489988
+Node: Multiscanning493085
+Node: Arrays of Arrays494674
+Node: Arrays Summary499433
+Node: Functions501525
+Node: Built-in502424
+Node: Calling Built-in503502
+Node: Numeric Functions505493
+Ref: Numeric Functions-Footnote-1510312
+Ref: Numeric Functions-Footnote-2510669
+Ref: Numeric Functions-Footnote-3510717
+Node: String Functions510989
+Ref: String Functions-Footnote-1534464
+Ref: String Functions-Footnote-2534593
+Ref: String Functions-Footnote-3534841
+Node: Gory Details534928
+Ref: table-sub-escapes536709
+Ref: table-sub-proposed538229
+Ref: table-posix-sub539593
+Ref: table-gensub-escapes541129
+Ref: Gory Details-Footnote-1541961
+Node: I/O Functions542112
+Ref: I/O Functions-Footnote-1549330
+Node: Time Functions549477
+Ref: Time Functions-Footnote-1559965
+Ref: Time Functions-Footnote-2560033
+Ref: Time Functions-Footnote-3560191
+Ref: Time Functions-Footnote-4560302
+Ref: Time Functions-Footnote-5560414
+Ref: Time Functions-Footnote-6560641
+Node: Bitwise Functions560907
+Ref: table-bitwise-ops561469
+Ref: Bitwise Functions-Footnote-1565778
+Node: Type Functions565947
+Node: I18N Functions567098
+Node: User-defined568743
+Node: Definition Syntax569548
+Ref: Definition Syntax-Footnote-1574955
+Node: Function Example575026
+Ref: Function Example-Footnote-1577945
+Node: Function Caveats577967
+Node: Calling A Function578485
+Node: Variable Scope579443
+Node: Pass By Value/Reference582431
+Node: Return Statement585926
+Node: Dynamic Typing588907
+Node: Indirect Calls589836
+Ref: Indirect Calls-Footnote-1601138
+Node: Functions Summary601266
+Node: Library Functions603968
+Ref: Library Functions-Footnote-1607577
+Ref: Library Functions-Footnote-2607720
+Node: Library Names607891
+Ref: Library Names-Footnote-1611345
+Ref: Library Names-Footnote-2611568
+Node: General Functions611654
+Node: Strtonum Function612757
+Node: Assert Function615779
+Node: Round Function619103
+Node: Cliff Random Function620644
+Node: Ordinal Functions621660
+Ref: Ordinal Functions-Footnote-1624723
+Ref: Ordinal Functions-Footnote-2624975
+Node: Join Function625186
+Ref: Join Function-Footnote-1626955
+Node: Getlocaltime Function627155
+Node: Readfile Function630899
+Node: Shell Quoting632869
+Node: Data File Management634270
+Node: Filetrans Function634902
+Node: Rewind Function638958
+Node: File Checking640345
+Ref: File Checking-Footnote-1641677
+Node: Empty Files641878
+Node: Ignoring Assigns643857
+Node: Getopt Function645408
+Ref: Getopt Function-Footnote-1656870
+Node: Passwd Functions657070
+Ref: Passwd Functions-Footnote-1665907
+Node: Group Functions665995
+Ref: Group Functions-Footnote-1673889
+Node: Walking Arrays674102
+Node: Library Functions Summary675705
+Node: Library Exercises677106
+Node: Sample Programs678386
+Node: Running Examples679156
+Node: Clones679884
+Node: Cut Program681108
+Node: Egrep Program690827
+Ref: Egrep Program-Footnote-1698325
+Node: Id Program698435
+Node: Split Program702080
+Ref: Split Program-Footnote-1705528
+Node: Tee Program705656
+Node: Uniq Program708445
+Node: Wc Program715864
+Ref: Wc Program-Footnote-1720114
+Node: Miscellaneous Programs720208
+Node: Dupword Program721421
+Node: Alarm Program723452
+Node: Translate Program728256
+Ref: Translate Program-Footnote-1732821
+Node: Labels Program733091
+Ref: Labels Program-Footnote-1736442
+Node: Word Sorting736526
+Node: History Sorting740597
+Node: Extract Program742433
+Node: Simple Sed749958
+Node: Igawk Program753026
+Ref: Igawk Program-Footnote-1767350
+Ref: Igawk Program-Footnote-2767551
+Ref: Igawk Program-Footnote-3767673
+Node: Anagram Program767788
+Node: Signature Program770845
+Node: Programs Summary772092
+Node: Programs Exercises773285
+Ref: Programs Exercises-Footnote-1777416
+Node: Advanced Features777507
+Node: Nondecimal Data779455
+Node: Array Sorting781045
+Node: Controlling Array Traversal781742
+Ref: Controlling Array Traversal-Footnote-1790075
+Node: Array Sorting Functions790193
+Ref: Array Sorting Functions-Footnote-1794082
+Node: Two-way I/O794278
+Ref: Two-way I/O-Footnote-1799223
+Ref: Two-way I/O-Footnote-2799409
+Node: TCP/IP Networking799491
+Node: Profiling802364
+Node: Advanced Features Summary810641
+Node: Internationalization812574
+Node: I18N and L10N814054
+Node: Explaining gettext814740
+Ref: Explaining gettext-Footnote-1819765
+Ref: Explaining gettext-Footnote-2819949
+Node: Programmer i18n820114
+Ref: Programmer i18n-Footnote-1824980
+Node: Translator i18n825029
+Node: String Extraction825823
+Ref: String Extraction-Footnote-1826954
+Node: Printf Ordering827040
+Ref: Printf Ordering-Footnote-1829826
+Node: I18N Portability829890
+Ref: I18N Portability-Footnote-1832345
+Node: I18N Example832408
+Ref: I18N Example-Footnote-1835211
+Node: Gawk I18N835283
+Node: I18N Summary835921
+Node: Debugger837260
+Node: Debugging838282
+Node: Debugging Concepts838723
+Node: Debugging Terms840576
+Node: Awk Debugging843148
+Node: Sample Debugging Session844042
+Node: Debugger Invocation844562
+Node: Finding The Bug845946
+Node: List of Debugger Commands852421
+Node: Breakpoint Control853754
+Node: Debugger Execution Control857450
+Node: Viewing And Changing Data860814
+Node: Execution Stack864192
+Node: Debugger Info865829
+Node: Miscellaneous Debugger Commands869846
+Node: Readline Support874875
+Node: Limitations875767
+Node: Debugging Summary877881
+Node: Arbitrary Precision Arithmetic879049
+Node: Computer Arithmetic880465
+Ref: table-numeric-ranges884063
+Ref: Computer Arithmetic-Footnote-1884922
+Node: Math Definitions884979
+Ref: table-ieee-formats888267
+Ref: Math Definitions-Footnote-1888871
+Node: MPFR features888976
+Node: FP Math Caution890647
+Ref: FP Math Caution-Footnote-1891697
+Node: Inexactness of computations892066
+Node: Inexact representation893025
+Node: Comparing FP Values894382
+Node: Errors accumulate895464
+Node: Getting Accuracy896897
+Node: Try To Round899559
+Node: Setting precision900458
+Ref: table-predefined-precision-strings901142
+Node: Setting the rounding mode902931
+Ref: table-gawk-rounding-modes903295
+Ref: Setting the rounding mode-Footnote-1906750
+Node: Arbitrary Precision Integers906929
+Ref: Arbitrary Precision Integers-Footnote-1911828
+Node: POSIX Floating Point Problems911977
+Ref: POSIX Floating Point Problems-Footnote-1915850
+Node: Floating point summary915888
+Node: Dynamic Extensions918082
+Node: Extension Intro919634
+Node: Plugin License920900
+Node: Extension Mechanism Outline921697
+Ref: figure-load-extension922125
+Ref: figure-register-new-function923605
+Ref: figure-call-new-function924609
+Node: Extension API Description926595
+Node: Extension API Functions Introduction928129
+Node: General Data Types933001
+Ref: General Data Types-Footnote-1938740
+Node: Memory Allocation Functions939039
+Ref: Memory Allocation Functions-Footnote-1941878
+Node: Constructor Functions941974
+Node: Registration Functions943708
+Node: Extension Functions944393
+Node: Exit Callback Functions946690
+Node: Extension Version String947938
+Node: Input Parsers948603
+Node: Output Wrappers958482
+Node: Two-way processors962997
+Node: Printing Messages965201
+Ref: Printing Messages-Footnote-1966277
+Node: Updating `ERRNO'966429
+Node: Requesting Values967169
+Ref: table-value-types-returned967897
+Node: Accessing Parameters968854
+Node: Symbol Table Access970085
+Node: Symbol table by name970599
+Node: Symbol table by cookie972580
+Ref: Symbol table by cookie-Footnote-1976724
+Node: Cached values976787
+Ref: Cached values-Footnote-1980286
+Node: Array Manipulation980377
+Ref: Array Manipulation-Footnote-1981467
+Node: Array Data Types981504
+Ref: Array Data Types-Footnote-1984159
+Node: Array Functions984251
+Node: Flattening Arrays988105
+Node: Creating Arrays994997
+Node: Redirection API999768
+Node: Extension API Variables1002539
+Node: Extension Versioning1003172
+Node: Extension API Informational Variables1005073
+Node: Extension API Boilerplate1006138
+Node: Finding Extensions1009947
+Node: Extension Example1010507
+Node: Internal File Description1011279
+Node: Internal File Ops1015346
+Ref: Internal File Ops-Footnote-11027016
+Node: Using Internal File Ops1027156
+Ref: Using Internal File Ops-Footnote-11029539
+Node: Extension Samples1029812
+Node: Extension Sample File Functions1031338
+Node: Extension Sample Fnmatch1038976
+Node: Extension Sample Fork1040467
+Node: Extension Sample Inplace1041682
+Node: Extension Sample Ord1043357
+Node: Extension Sample Readdir1044193
+Ref: table-readdir-file-types1045069
+Node: Extension Sample Revout1045880
+Node: Extension Sample Rev2way1046470
+Node: Extension Sample Read write array1047210
+Node: Extension Sample Readfile1049150
+Node: Extension Sample Time1050245
+Node: Extension Sample API Tests1051594
+Node: gawkextlib1052085
+Node: Extension summary1054743
+Node: Extension Exercises1058432
+Node: Language History1059154
+Node: V7/SVR3.11060810
+Node: SVR41062991
+Node: POSIX1064436
+Node: BTL1065825
+Node: POSIX/GNU1066559
+Node: Feature History1072183
+Node: Common Extensions1085281
+Node: Ranges and Locales1086605
+Ref: Ranges and Locales-Footnote-11091223
+Ref: Ranges and Locales-Footnote-21091250
+Ref: Ranges and Locales-Footnote-31091484
+Node: Contributors1091705
+Node: History summary1097246
+Node: Installation1098616
+Node: Gawk Distribution1099562
+Node: Getting1100046
+Node: Extracting1100869
+Node: Distribution contents1102504
+Node: Unix Installation1108569
+Node: Quick Installation1109252
+Node: Shell Startup Files1111663
+Node: Additional Configuration Options1112742
+Node: Configuration Philosophy1114481
+Node: Non-Unix Installation1116850
+Node: PC Installation1117308
+Node: PC Binary Installation1118627
+Node: PC Compiling1120475
+Ref: PC Compiling-Footnote-11123496
+Node: PC Testing1123605
+Node: PC Using1124781
+Node: Cygwin1128896
+Node: MSYS1129719
+Node: VMS Installation1130219
+Node: VMS Compilation1131011
+Ref: VMS Compilation-Footnote-11132233
+Node: VMS Dynamic Extensions1132291
+Node: VMS Installation Details1133975
+Node: VMS Running1136227
+Node: VMS GNV1139063
+Node: VMS Old Gawk1139797
+Node: Bugs1140267
+Node: Other Versions1144150
+Node: Installation summary1150578
+Node: Notes1151634
+Node: Compatibility Mode1152499
+Node: Additions1153281
+Node: Accessing The Source1154206
+Node: Adding Code1155642
+Node: New Ports1161807
+Node: Derived Files1166289
+Ref: Derived Files-Footnote-11171764
+Ref: Derived Files-Footnote-21171798
+Ref: Derived Files-Footnote-31172394
+Node: Future Extensions1172508
+Node: Implementation Limitations1173114
+Node: Extension Design1174362
+Node: Old Extension Problems1175516
+Ref: Old Extension Problems-Footnote-11177033
+Node: Extension New Mechanism Goals1177090
+Ref: Extension New Mechanism Goals-Footnote-11180450
+Node: Extension Other Design Decisions1180639
+Node: Extension Future Growth1182747
+Node: Old Extension Mechanism1183583
+Node: Notes summary1185345
+Node: Basic Concepts1186531
+Node: Basic High Level1187212
+Ref: figure-general-flow1187484
+Ref: figure-process-flow1188083
+Ref: Basic High Level-Footnote-11191312
+Node: Basic Data Typing1191497
+Node: Glossary1194825
+Node: Copying1219983
+Node: GNU Free Documentation License1257539
+Node: Index1282675

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 035d1476..6f5aacea 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -603,6 +603,7 @@ particular records in a file and perform operations upon them.
@code{getline}.
* Getline Summary:: Summary of @code{getline} Variants.
* Read Timeout:: Reading input with a timeout.
+* Retrying Input:: Retrying input after certain errors.
* Command-line directories:: What happens if you put a directory on
the command line.
* Input Summary:: Input summary.
@@ -943,6 +944,7 @@ particular records in a file and perform operations upon them.
* Array Functions:: Functions for working with arrays.
* Flattening Arrays:: How to flatten arrays.
* Creating Arrays:: How to create and populate arrays.
+* Redirection API:: How to access and manipulate redirections.
* Extension API Variables:: Variables provided by the API.
* Extension Versioning:: API Version information.
* Extension API Informational Variables:: Variables providing information about
@@ -6343,6 +6345,7 @@ used with it do not have to be named on the @command{awk} command line
* Getline:: Reading files under explicit program control
using the @code{getline} function.
* Read Timeout:: Reading input with a timeout.
+* Retrying Input:: Retrying input after certain errors.
* Command-line directories:: What happens if you put a directory on the
command line.
* Input Summary:: Input summary.
@@ -8150,6 +8153,11 @@ it encounters the end of the file. If there is some error in getting
a record, such as a file that cannot be opened, then @code{getline}
returns @minus{}1. In this case, @command{gawk} sets the variable
@code{ERRNO} to a string describing the error that occurred.
+If the @code{errno} variable indicates that the I/O operation may be
+retried, and @code{PROCINFO["input", "RETRY"]} is set, then @minus{}2
+will be returned instead of @minus{}1, and further calls to @code{getline}
+may be attemped. @DBXREF{Retrying Input} for further information about
+this feature.
In the following examples, @var{command} stands for a string value that
represents a shell command.
@@ -8802,7 +8810,8 @@ on a per command or connection basis.
the attempt to read from the underlying device may
succeed in a later attempt. This is a limitation, and it also
means that you cannot use this to multiplex input from
-two or more sources.
+two or more sources. @DBXREF{Retrying Input} for a way to enable
+later I/O attempts to succeed.
Assigning a timeout value prevents read operations from
blocking indefinitely. But bear in mind that there are other ways
@@ -8812,6 +8821,35 @@ a connection before it can start reading any data,
or the attempt to open a FIFO special file for reading can block
indefinitely until some other process opens it for writing.
+@node Retrying Input
+@section Retrying Reads After Certain Input Errors
+@cindex retrying input
+
+@cindex differences in @command{awk} and @command{gawk}, retrying input
+This @value{SECTION} describes a feature that is specific to @command{gawk}.
+
+When @command{gawk} encounters an error while reading input, it will by default
+return @minus{}1 from getline, and subsequent attempts to read from that file
+will result in an end-of-file indication. However, you may optionally instruct
+@command{gawk} to allow I/O to be retried when certain errors are encountered
+by setting setting a special element
+in the @code{PROCINFO} array (@pxref{Auto-set}):
+
+@example
+PROCINFO["input_name", "RETRY"]
+@end example
+
+When set, this causes @command{gawk} to check the value of the system
+@code{errno} variable when an I/O error occurs. If @code{errno} indicates
+a subsequent I/O attempt may succeed, @code{getline} will instead return
+@minus{}2 and
+further calls to @code{getline} may succeed. This applies to @code{errno}
+values EAGAIN, EWOULDBLOCK, EINTR, or ETIMEDOUT.
+
+This feature is useful in conjunction with
+@code{PROCINFO["input_name", "READ_TIMEOUT"]} or situations where a file
+descriptor has been configured to behave in a non-blocking fashion.
+
@node Command-line directories
@section Directories on the Command Line
@cindex differences in @command{awk} and @command{gawk}, command-line directories
@@ -14950,6 +14988,11 @@ value to be meaningful when an I/O operation returns a failure value,
such as @code{getline} returning @minus{}1. You are, of course, free
to clear it yourself before doing an I/O operation.
+If the value of @code{ERRNO} corresponds to a system error in the C
+@code{errno} variable, then @code{PROCINFO["errno"]} will be set to the value
+of @code{errno}. For non-system errors, @code{PROCINFO["errno"]} will
+be zero.
+
@cindex @code{FILENAME} variable
@cindex dark corner, @code{FILENAME} variable
@item @code{FILENAME}
@@ -15018,6 +15061,10 @@ are guaranteed to be available:
@item PROCINFO["egid"]
The value of the @code{getegid()} system call.
+@item PROCINFO["errno"]
+The value of the C @code{errno} variable when @code{ERRNO} is set to
+the associated error message.
+
@item PROCINFO["euid"]
@cindex effective user ID of @command{gawk} user
The value of the @code{geteuid()} system call.
@@ -15157,6 +15204,11 @@ open input file, pipe, or coprocess.
@DBXREF{Read Timeout} for more information.
@item
+It may be used to indicate that input may be retried when it fails due to
+certain errors.
+@DBXREF{Retrying Input} for more information.
+
+@item
It may be used to cause coprocesses to communicate over pseudo-ttys
instead of through two-way pipes; this is discussed further in
@ref{Two-way I/O}.
@@ -31736,6 +31788,7 @@ This (rather large) @value{SECTION} describes the API in detail.
* Symbol Table Access:: Functions for accessing global
variables.
* Array Manipulation:: Functions for working with arrays.
+* Redirection API:: How to access and manipulate redirections.
* Extension API Variables:: Variables provided by the API.
* Extension API Boilerplate:: Boilerplate code for using the API.
@end menu
@@ -31811,6 +31864,10 @@ Clearing an array
@item
Flattening an array for easy C style looping over all its indices and elements
@end itemize
+
+@item
+Accessing and manipulating redirections.
+
@end itemize
Some points about using the API:
@@ -33775,6 +33832,62 @@ $ @kbd{AWKLIBPATH=$PWD ./gawk -f subarray.awk}
(@DBXREF{Finding Extensions} for more information on the
@env{AWKLIBPATH} environment variable.)
+@node Redirection API
+@subsection Accessing and Manipulating Redirections
+
+The following function allows extensions to access and manipulate redirections.
+
+@table @code
+@item awk_bool_t get_file(const char *name,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ size_t name_len,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const char *filetype,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ int fd,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const awk_input_buf_t **ibufp,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const awk_output_buf_t **obufp);
+Look up a file in @command{gawk}'s internal redirection table. If @code{name} is NULL or @code{name_len} is 0, it returns
+data for the currently open input file corresponding to @code{FILENAME}
+(and it will not access the @code{filetype} argument, so that may be
+undefined).
+If the file is not already open, it tries to open it.
+The @code{filetype} argument must be NUL-terminated and should be one of:
+@table @code
+@item >
+A file opened for output.
+@item >>
+A file opened for append.
+@item <
+A file opened for input.
+@item |>
+A pipe opened for output.
+@item |<
+A pipe opened for input.
+@item |&
+A two-way coprocess.
+@end table
+On error, a @code{false} value is returned. Otherwise, the return status
+is @code{true}, and additional information about the redirection is
+returned in the @code{ibufp} and @code{obufp} pointers. For input redirections,
+the @code{*ibufp} value should be non-NULL, and @code{*obufp} should be NULL.
+For output redirections,
+the @code{*obufp} value should be non-NULL, and @code{*ibufp} should be NULL.
+For two-way coprocesses, both values should be non-NULL. In the usual case,
+the extension is interested in @code{(*ibufp)->fd} and/or @code{fileno((*obufp)->fp)}.
+If the file is not already open, and the fd argument is non-negative,
+@command{gawk} will use that file descriptor instead of opening the file
+in the usual way. If the fd is non-negative, but the file exists
+already, @command{gawk} ignores the fd and returns the existing file. It is
+the caller's responsibility to notice that neither the fd in the returned
+@code{awk_input_buf_t} nor the fd in the returned @code{awk_output_buf_t} matches the requested value. Note that
+supplying a file descriptor is currently NOT supported for pipes.
+It should work for input, output, append, and two-way (coprocess)
+sockets. If @code{filetype} is two-way, we assume that it is a socket!
+Note that in the two-way case, the input and output file descriptors
+may differ. To check for success, one must check whether either matches.
+@end table
+
+It is anticipated that this API function will be used to implement I/O
+multiplexing and a socket library.
+
@node Extension API Variables
@subsection API Variables
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index 8034a6b6..daf38adf 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -598,6 +598,7 @@ particular records in a file and perform operations upon them.
@code{getline}.
* Getline Summary:: Summary of @code{getline} Variants.
* Read Timeout:: Reading input with a timeout.
+* Retrying Input:: Retrying input after certain errors.
* Command-line directories:: What happens if you put a directory on
the command line.
* Input Summary:: Input summary.
@@ -938,6 +939,7 @@ particular records in a file and perform operations upon them.
* Array Functions:: Functions for working with arrays.
* Flattening Arrays:: How to flatten arrays.
* Creating Arrays:: How to create and populate arrays.
+* Redirection API:: How to access and manipulate redirections.
* Extension API Variables:: Variables provided by the API.
* Extension Versioning:: API Version information.
* Extension API Informational Variables:: Variables providing information about
@@ -6127,6 +6129,7 @@ used with it do not have to be named on the @command{awk} command line
* Getline:: Reading files under explicit program control
using the @code{getline} function.
* Read Timeout:: Reading input with a timeout.
+* Retrying Input:: Retrying input after certain errors.
* Command-line directories:: What happens if you put a directory on the
command line.
* Input Summary:: Input summary.
@@ -7751,6 +7754,11 @@ it encounters the end of the file. If there is some error in getting
a record, such as a file that cannot be opened, then @code{getline}
returns @minus{}1. In this case, @command{gawk} sets the variable
@code{ERRNO} to a string describing the error that occurred.
+If the @code{errno} variable indicates that the I/O operation may be
+retried, and @code{PROCINFO["input", "RETRY"]} is set, then @minus{}2
+will be returned instead of @minus{}1, and further calls to @code{getline}
+may be attemped. @DBXREF{Retrying Input} for further information about
+this feature.
In the following examples, @var{command} stands for a string value that
represents a shell command.
@@ -8403,7 +8411,8 @@ on a per command or connection basis.
the attempt to read from the underlying device may
succeed in a later attempt. This is a limitation, and it also
means that you cannot use this to multiplex input from
-two or more sources.
+two or more sources. @DBXREF{Retrying Input} for a way to enable
+later I/O attempts to succeed.
Assigning a timeout value prevents read operations from
blocking indefinitely. But bear in mind that there are other ways
@@ -8413,6 +8422,35 @@ a connection before it can start reading any data,
or the attempt to open a FIFO special file for reading can block
indefinitely until some other process opens it for writing.
+@node Retrying Input
+@section Retrying Reads After Certain Input Errors
+@cindex retrying input
+
+@cindex differences in @command{awk} and @command{gawk}, retrying input
+This @value{SECTION} describes a feature that is specific to @command{gawk}.
+
+When @command{gawk} encounters an error while reading input, it will by default
+return @minus{}1 from getline, and subsequent attempts to read from that file
+will result in an end-of-file indication. However, you may optionally instruct
+@command{gawk} to allow I/O to be retried when certain errors are encountered
+by setting setting a special element
+in the @code{PROCINFO} array (@pxref{Auto-set}):
+
+@example
+PROCINFO["input_name", "RETRY"]
+@end example
+
+When set, this causes @command{gawk} to check the value of the system
+@code{errno} variable when an I/O error occurs. If @code{errno} indicates
+a subsequent I/O attempt may succeed, @code{getline} will instead return
+@minus{}2 and
+further calls to @code{getline} may succeed. This applies to @code{errno}
+values EAGAIN, EWOULDBLOCK, EINTR, or ETIMEDOUT.
+
+This feature is useful in conjunction with
+@code{PROCINFO["input_name", "READ_TIMEOUT"]} or situations where a file
+descriptor has been configured to behave in a non-blocking fashion.
+
@node Command-line directories
@section Directories on the Command Line
@cindex differences in @command{awk} and @command{gawk}, command-line directories
@@ -14279,6 +14317,11 @@ value to be meaningful when an I/O operation returns a failure value,
such as @code{getline} returning @minus{}1. You are, of course, free
to clear it yourself before doing an I/O operation.
+If the value of @code{ERRNO} corresponds to a system error in the C
+@code{errno} variable, then @code{PROCINFO["errno"]} will be set to the value
+of @code{errno}. For non-system errors, @code{PROCINFO["errno"]} will
+be zero.
+
@cindex @code{FILENAME} variable
@cindex dark corner, @code{FILENAME} variable
@item @code{FILENAME}
@@ -14347,6 +14390,10 @@ are guaranteed to be available:
@item PROCINFO["egid"]
The value of the @code{getegid()} system call.
+@item PROCINFO["errno"]
+The value of the C @code{errno} variable when @code{ERRNO} is set to
+the associated error message.
+
@item PROCINFO["euid"]
@cindex effective user ID of @command{gawk} user
The value of the @code{geteuid()} system call.
@@ -14486,6 +14533,11 @@ open input file, pipe, or coprocess.
@DBXREF{Read Timeout} for more information.
@item
+It may be used to indicate that input may be retried when it fails due to
+certain errors.
+@DBXREF{Retrying Input} for more information.
+
+@item
It may be used to cause coprocesses to communicate over pseudo-ttys
instead of through two-way pipes; this is discussed further in
@ref{Two-way I/O}.
@@ -30829,6 +30881,7 @@ This (rather large) @value{SECTION} describes the API in detail.
* Symbol Table Access:: Functions for accessing global
variables.
* Array Manipulation:: Functions for working with arrays.
+* Redirection API:: How to access and manipulate redirections.
* Extension API Variables:: Variables provided by the API.
* Extension API Boilerplate:: Boilerplate code for using the API.
@end menu
@@ -30904,6 +30957,10 @@ Clearing an array
@item
Flattening an array for easy C style looping over all its indices and elements
@end itemize
+
+@item
+Accessing and manipulating redirections.
+
@end itemize
Some points about using the API:
@@ -32868,6 +32925,62 @@ $ @kbd{AWKLIBPATH=$PWD ./gawk -f subarray.awk}
(@DBXREF{Finding Extensions} for more information on the
@env{AWKLIBPATH} environment variable.)
+@node Redirection API
+@subsection Accessing and Manipulating Redirections
+
+The following function allows extensions to access and manipulate redirections.
+
+@table @code
+@item awk_bool_t get_file(const char *name,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ size_t name_len,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const char *filetype,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ int fd,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const awk_input_buf_t **ibufp,
+@itemx @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ const awk_output_buf_t **obufp);
+Look up a file in @command{gawk}'s internal redirection table. If @code{name} is NULL or @code{name_len} is 0, it returns
+data for the currently open input file corresponding to @code{FILENAME}
+(and it will not access the @code{filetype} argument, so that may be
+undefined).
+If the file is not already open, it tries to open it.
+The @code{filetype} argument must be NUL-terminated and should be one of:
+@table @code
+@item >
+A file opened for output.
+@item >>
+A file opened for append.
+@item <
+A file opened for input.
+@item |>
+A pipe opened for output.
+@item |<
+A pipe opened for input.
+@item |&
+A two-way coprocess.
+@end table
+On error, a @code{false} value is returned. Otherwise, the return status
+is @code{true}, and additional information about the redirection is
+returned in the @code{ibufp} and @code{obufp} pointers. For input redirections,
+the @code{*ibufp} value should be non-NULL, and @code{*obufp} should be NULL.
+For output redirections,
+the @code{*obufp} value should be non-NULL, and @code{*ibufp} should be NULL.
+For two-way coprocesses, both values should be non-NULL. In the usual case,
+the extension is interested in @code{(*ibufp)->fd} and/or @code{fileno((*obufp)->fp)}.
+If the file is not already open, and the fd argument is non-negative,
+@command{gawk} will use that file descriptor instead of opening the file
+in the usual way. If the fd is non-negative, but the file exists
+already, @command{gawk} ignores the fd and returns the existing file. It is
+the caller's responsibility to notice that neither the fd in the returned
+@code{awk_input_buf_t} nor the fd in the returned @code{awk_output_buf_t} matches the requested value. Note that
+supplying a file descriptor is currently NOT supported for pipes.
+It should work for input, output, append, and two-way (coprocess)
+sockets. If @code{filetype} is two-way, we assume that it is a socket!
+Note that in the two-way case, the input and output file descriptors
+may differ. To check for success, one must check whether either matches.
+@end table
+
+It is anticipated that this API function will be used to implement I/O
+multiplexing and a socket library.
+
@node Extension API Variables
@subsection API Variables
diff --git a/eval.c b/eval.c
index 95992704..3fe7f58a 100644
--- a/eval.c
+++ b/eval.c
@@ -25,7 +25,6 @@
#include "awk.h"
-extern void after_beginfile(IOBUF **curfile);
extern double pow(double x, double y);
extern double modf(double x, double *yp);
extern double fmod(double x, double y);
@@ -1026,6 +1025,7 @@ update_ERRNO_int(int errcode)
{
char *cp;
+ update_PROCINFO_num("errno", errcode);
if (errcode) {
cp = strerror(errcode);
cp = gettext(cp);
@@ -1040,6 +1040,7 @@ update_ERRNO_int(int errcode)
void
update_ERRNO_string(const char *string)
{
+ update_PROCINFO_num("errno", 0);
unref(ERRNO_node->var_value);
ERRNO_node->var_value = make_string(string, strlen(string));
}
@@ -1049,6 +1050,7 @@ update_ERRNO_string(const char *string)
void
unset_ERRNO(void)
{
+ update_PROCINFO_num("errno", 0);
unref(ERRNO_node->var_value);
ERRNO_node->var_value = dupnode(Nnull_string);
}
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 582a3440..8a6dfd93 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -2,11 +2,79 @@
* testext.c (var_test): Adjust for PROCINFO now being there.
+2015-01-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * testext.c (test_deferred): New function to help with testing
+ of deferred variable instantiation.
+ (do_get_file): Remove unused variable array.
+ (func_table): Add test_deferred.
+
+2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * testext.c (test_get_file): Fix error message.
+ (do_get_file): Implement new function providing low-level access
+ to the get_file API.
+ (func_table): Add "get_file" -> do_get_file.
+ (init_testext): If TESTEXT_QUIET has been set to a numeric value,
+ return quietly.
+
+2015-01-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * testext.c (test_get_file): The get_file hook no longer takes a
+ typelen argument.
+
+2015-01-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ Remove the select extension, since it will be part of gawkextlib.
+ * select.c, siglist.h: Deleted.
+ * Makefile.am (pkgextension_LTLIBRARIES): Remove select.la.
+ (select_la_SOURCES, select_la_LDFLAGS, select_la_LIBADD): Remove.
+ (EXTRA_DIST): Remove siglist.h.
+ * configure.ac (AC_CHECK_HEADERS): Remove signal.h.
+ (AC_CHECK_FUNCS): Remove fcntl, kill, sigaction, and sigprocmask.
+
+2014-12-14 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ Remove the errno extension, since it is now part of gawkextlib.
+ * errno.c, errlist.h: Deleted.
+ * Makefile.am (pkgextension_LTLIBRARIES): Remove errno.la.
+ (errno_la_SOURCES, errno_la_LDFLAGS, errno_la_LIBADD): Remove.
+ (EXTRA_DIST): Remove errlist.h.
+
2014-11-23 Arnold D. Robbins <arnold@skeeve.com>
* inplace.c (do_inplace_begin): Jump through hoops to silence
GCC warnings about return value of chown.
+2014-11-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (do_input_fd): New function to return the input file
+ descriptor associated with a file/command.
+ (do_output_fd): New function to return the output file descriptor
+ associated with a file/command.
+ (func_table): Add new functions "input_fd" and "output_fd".
+ * testext.c (test_get_file): Do not use __func__, since it is a C99
+ feature, and gawk does not assume C99.
+
+2014-11-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * errno.c (do_errno2name, do_name2errno): Remove unused variable 'str'.
+ * select.c (do_signal): Remove unused variable 'override'.
+ (grabfd): New helper function to map a gawk file to the appropriate
+ fd for use in the arguments to selectd.
+ (do_select): get_file has 3 new arguments and returns info about both
+ the input and output buf.
+ (do_set_non_blocking): Support changes to get_file API.
+ * testext.c (test_get_file): New test function to check that extension
+ file creation via the get_file API is working.
+
+2014-11-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (set_retry): New function to set PROCINFO[<name>, "RETRY"].
+ (do_set_non_blocking): If called with a file name as opposed to a file
+ descriptor, call the set_retry function to configure PROCINFO to tell
+ io.c to retry I/O for temporary failures.
+
2014-10-12 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (uninstall-so): Remove *.lib too, per suggestion
@@ -178,6 +246,108 @@
* gawkdirfd.h (FAKE_FD_VALUE): Move definition up in the file to give
clean compile on MinGW.
+2013-07-07 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * configure.ac (AC_CHECK_FUNCS): Check for fcntl.
+ * select.c (set_non_blocking): Check that fcntl and O_NONBLOCK are
+ available.
+
+2013-07-07 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (signal_handler): On platforms lacking sigaction, reset
+ the signal handler each time a signal is trapped to protect in case
+ the system resets it to default.
+
+2013-07-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (signal_result): New function to set result string from
+ signal function and detect when we need to roll back.
+ (do_signal): Now takes an optional 3rd override argument. Instead
+ of returning -1 or 0, we now return information about the previously
+ installed signal handler: default, ignore, trap, or unknown. An
+ empty string is returned on error. If it is an unknown handler,
+ and override is not non-zero, we roll back the handler and return "".
+
+2013-07-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (set_non_blocking): Do not attempt F_SETFL if F_GETFL fails.
+ (do_set_non_blocking): Add support for case when called with a single
+ "" argument.
+
+2013-07-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (do_signal): If sigaction is unavailable, fall back to
+ signal and hope that it does the right thing.
+
+2013-07-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * configure.ac (AC_CHECK_FUNCS): Add kill and sigprocmask.
+ * select.c (get_signal_number): Change error messages since now may
+ be called by "kill" as well as "select_signal".
+ (do_signal): Add a lint warning if there are more than 2 args.
+ (do_kill): Add new function to send a signal.
+ (do_select): Support platforms where sigprocmask is not available.
+ There will be a race condition on such platforms, but that is not
+ easily avoided.
+
+2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (do_select): Now that the API flatten_array call has been
+ patched to ensure that the index values are strings, we can remove
+ the code to check for the AWK_NUMBER case.
+
+2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (do_select): Do not treat a numeric command value as a
+ file descriptor unless the command type is empty.
+
+2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (EXTRA_DIST): Add errlist.h and siglist.h.
+
+2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (set_non_blocking): New helper function to call fcntl.
+ (do_set_non_blocking): Add support for the case where there's a single
+ integer fd argument.
+
+2013-07-01 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * select.c (do_set_non_blocking): Implement new set_non_blocking
+ function.
+ (func_table): Add set_non_blocking.
+
+2013-07-01 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * errlist.h: New file containing a list of all the errno values I could
+ find.
+ * errno.c: Implement a new errno extension providing strerror,
+ errno2name, and name2errno.
+ * Makefile.am (pkgextension_LTLIBRARIES): Add errno.la.
+ (errno_la_SOURCES, errno_la_LDFLAGS, errno_la_LIBADD): Build new errno
+ extension.
+ * select.c (ext_version): Fix version string.
+ * siglist.h: Update to newest glibc version.
+
+2013-07-01 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * siglist.h: New file copied from glibc to provide a mapping between
+ signal number and name.
+ * select.c: Add a new "select_signal" function and provide support
+ for trapping signals.
+ (do_select): Add support for a 5th argument to contain an array
+ of returned signals. Improve the argument processing, and add
+ better warning messages.
+
+2013-06-30 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (pkgextension_LTLIBRARIES): Add select.la.
+ (select_la_SOURCES, select_la_LDFLAGS, select_la_LIBADD): Build new
+ select extension.
+ * configure.ac (AC_CHECK_HEADERS): Add signal.h.
+ (AC_CHECK_FUNCS): Add sigaction.
+ * select.c: Implement the new select extension.
+
2013-06-10 Arnold D. Robbins <arnold@skeeve.com>
* configure.ac (AC_HEADER_MAJOR): New macro added.
diff --git a/extension/testext.c b/extension/testext.c
index 4a1e7032..8a906c67 100644
--- a/extension/testext.c
+++ b/extension/testext.c
@@ -37,6 +37,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <fcntl.h>
#include "gawkapi.h"
@@ -373,6 +374,73 @@ out:
return result;
}
+static awk_value_t *
+test_deferred(int nargs, awk_value_t *result)
+{
+ awk_value_t arr;
+ awk_value_t index, value;
+ const struct nval {
+ const char *name;
+ double val;
+ } seed[] = {
+ { "fubar", 9.0, },
+ { "rumpus", -5.0, },
+ };
+ struct nval sysval[] = {
+ { "uid", getuid(), },
+ { "api_major", GAWK_API_MAJOR_VERSION, },
+ };
+ size_t i;
+
+ assert(result != NULL);
+ make_number(0.0, result);
+
+ if (nargs != 0) {
+ printf("test_deferred: nargs not right (%d should be 0)\n", nargs);
+ goto out;
+ }
+
+ if (! sym_lookup("PROCINFO", AWK_ARRAY, & arr)) {
+ printf("test_deferred: %d: sym_lookup failed\n", __LINE__);
+ goto out;
+ }
+
+ for (i = 0; i < sizeof(seed)/sizeof(seed[0]); i++) {
+ make_const_string(seed[i].name, strlen(seed[i].name), & index);
+ make_number(seed[i].val, & value);
+ if (! set_array_element(arr.array_cookie, & index, & value)) {
+ printf("test_deferred: %d: set_array_element(%s) failed\n", __LINE__, seed[i].name);
+ goto out;
+ }
+ }
+
+ /* test that it still contains the values we loaded */
+ for (i = 0; i < sizeof(seed)/sizeof(seed[0]); i++) {
+ make_const_string(seed[i].name, strlen(seed[i].name), & index);
+ make_null_string(& value);
+ if (! get_array_element(arr.array_cookie, &index, AWK_NUMBER, & value)) {
+ printf("test_deferred: %d: get_array_element(%s) failed\n", __LINE__, seed[i].name);
+ goto out;
+ }
+ printf("%s = %g\n", seed[i].name, value.num_value);
+ }
+
+ /* check a few automatically-supplied values */
+ for (i = 0; i < sizeof(sysval)/sizeof(sysval[0]); i++) {
+ make_const_string(sysval[i].name, strlen(sysval[i].name), & index);
+ make_null_string(& value);
+ if (! get_array_element(arr.array_cookie, &index, AWK_NUMBER, & value)) {
+ printf("test_deferred: %d: get_array_element(%s) failed\n", __LINE__, sysval[i].name);
+ goto out;
+ }
+ printf("%s matches %d\n", sysval[i].name, (value.num_value == sysval[i].val));
+ }
+
+ make_number(1.0, result);
+out:
+ return result;
+}
+
/*
BEGIN {
for (i = 1; i <= 10; i++)
@@ -710,6 +778,7 @@ BEGIN {
ret = test_indirect_vars() # should get correct value of NR
printf("test_indirect_var() return %d\n", ret)
delete ARGV[1]
+ print ""
}
*/
@@ -742,6 +811,124 @@ out:
return result;
}
+/*
+BEGIN {
+ outfile = "testexttmp.txt"
+ alias = ".test.alias"
+ print "line 1" > outfile
+ print "line 2" > outfile
+ print "line 3" > outfile
+ close(outfile)
+ ret = test_get_file(outfile, alias)
+ printf "test_get_file returned %d\n", ret
+ nr = 0
+ while ((getline < alias) > 0)
+ printf "File [%s] nr [%s]: %s\n", alias, ++nr, $0
+ close(alias)
+ system("rm " outfile)
+ print ""
+}
+*/
+
+/* test_get_file --- test that we can create a file */
+
+static awk_value_t *
+test_get_file(int nargs, awk_value_t *result)
+{
+ awk_value_t filename, alias;
+ int fd;
+ const awk_input_buf_t *ibuf;
+ const awk_output_buf_t *obuf;
+
+ if (nargs != 2) {
+ printf("%s: nargs not right (%d should be 2)\n", "test_get_file", nargs);
+ return make_number(-1.0, result);
+ }
+
+ if (! get_argument(0, AWK_STRING, & filename)) {
+ printf("%s: cannot get first arg\n", "test_get_file");
+ return make_number(-1.0, result);
+ }
+ if (! get_argument(1, AWK_STRING, & alias)) {
+ printf("%s: cannot get second arg\n", "test_get_file");
+ return make_number(-1.0, result);
+ }
+ if ((fd = open(filename.str_value.str, O_RDONLY)) < 0) {
+ printf("%s: open(%s) failed\n", "test_get_file", filename.str_value.str);
+ return make_number(-1.0, result);
+ }
+ if (! get_file(alias.str_value.str, strlen(alias.str_value.str), "<", fd, &ibuf, &obuf)) {
+ printf("%s: get_file(%s) failed\n", "test_get_file", alias.str_value.str);
+ return make_number(-1.0, result);
+ }
+ if (! ibuf || ibuf->fd != fd) {
+ printf("%s: get_file(%s) returned fd %d instead of %d\n", "test_get_file", alias.str_value.str, ibuf ? ibuf->fd : -1, fd);
+ return make_number(-1.0, result);
+ }
+ return make_number(0.0, result);
+}
+
+/* do_get_file --- provide access to get_file API */
+
+static awk_value_t *
+do_get_file(int nargs, awk_value_t *result)
+{
+ awk_value_t filename, filetype, fd, res;
+ const awk_input_buf_t *ibuf;
+ const awk_output_buf_t *obuf;
+
+ if (nargs != 4) {
+ printf("%s: nargs not right (%d should be 4)\n", "get_file", nargs);
+ return make_number(-1.0, result);
+ }
+
+ if (! get_argument(0, AWK_STRING, & filename)) {
+ printf("%s: cannot get first arg\n", "get_file");
+ return make_number(-1.0, result);
+ }
+ if (! get_argument(1, AWK_STRING, & filetype)) {
+ printf("%s: cannot get second arg\n", "get_file");
+ return make_number(-1.0, result);
+ }
+ if (! get_argument(2, AWK_NUMBER, & fd)) {
+ printf("%s: cannot get third arg\n", "get_file");
+ return make_number(-1.0, result);
+ }
+ if (! get_argument(3, AWK_ARRAY, & res)) {
+ printf("%s: cannot get fourth arg\n", "get_file");
+ return make_number(-1.0, result);
+ }
+ clear_array(res.array_cookie);
+
+ if (! get_file(filename.str_value.str, strlen(filename.str_value.str), filetype.str_value.str, fd.num_value, &ibuf, &obuf)) {
+ printf("%s: get_file(%s, %s, %d) failed\n", "get_file", filename.str_value.str, filetype.str_value.str, (int)(fd.num_value));
+ return make_number(0.0, result);
+ }
+
+ if (ibuf) {
+ awk_value_t idx, val;
+ set_array_element(res.array_cookie,
+ make_const_string("input", 5, & idx),
+ make_number(ibuf->fd, & val));
+ if (ibuf->name)
+ set_array_element(res.array_cookie,
+ make_const_string("input_name", 10, & idx),
+ make_const_string(ibuf->name, strlen(ibuf->name), & val));
+ }
+ if (obuf) {
+ awk_value_t idx, val;
+ set_array_element(res.array_cookie,
+ make_const_string("output", 6, & idx),
+ make_number(obuf->fp ? fileno(obuf->fp) : -1,
+ & val));
+ if (obuf->name)
+ set_array_element(res.array_cookie,
+ make_const_string("output_name", 11, & idx),
+ make_const_string(obuf->name, strlen(obuf->name), & val));
+ }
+ return make_number(1.0, result);
+}
+
/* fill_in_array --- fill in a new array */
static void
@@ -829,6 +1016,7 @@ static awk_ext_func_t func_table[] = {
{ "dump_array_and_delete", dump_array_and_delete, 2 },
{ "try_modify_environ", try_modify_environ, 0 },
{ "var_test", var_test, 1 },
+ { "test_deferred", test_deferred, 0 },
{ "test_errno", test_errno, 0 },
{ "test_array_size", test_array_size, 1 },
{ "test_array_elem", test_array_elem, 2 },
@@ -837,6 +1025,8 @@ static awk_ext_func_t func_table[] = {
{ "test_scalar", test_scalar, 1 },
{ "test_scalar_reserved", test_scalar_reserved, 0 },
{ "test_indirect_vars", test_indirect_vars, 0 },
+ { "test_get_file", test_get_file, 2 },
+ { "get_file", do_get_file, 4 },
};
/* init_testext --- additional initialization function */
@@ -847,6 +1037,9 @@ static awk_bool_t init_testext(void)
static const char message[] = "hello, world"; /* of course */
static const char message2[] = "i am a scalar";
+ if (sym_lookup("TESTEXT_QUIET", AWK_NUMBER, & value))
+ return awk_true;
+
/* add at_exit functions */
awk_atexit(at_exit0, NULL);
awk_atexit(at_exit1, & data_for_1);
diff --git a/gawkapi.c b/gawkapi.c
index fc6e159a..f8d04986 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -25,6 +25,11 @@
#include "awk.h"
+/* Declare some globals used by api_get_file: */
+extern IOBUF *curfile;
+extern INSTRUCTION *main_beginfile;
+extern int currule;
+
static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted);
/*
@@ -783,7 +788,6 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
tmp = awk_value_to_node(index);
aptr = assoc_lookup(array, tmp);
- unref(tmp);
unref(*aptr);
elem = *aptr = awk_value_to_node(value);
if (elem->type == Node_var_array) {
@@ -791,6 +795,9 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
elem->vname = estrdup(index->str_value.str,
index->str_value.len);
}
+ if (array->astore != NULL)
+ (*array->astore)(array, tmp);
+ unref(tmp);
return awk_true;
}
@@ -1034,6 +1041,90 @@ api_release_value(awk_ext_id_t id, awk_value_cookie_t value)
return awk_true;
}
+/* api_get_file --- return a handle to an existing or newly opened file */
+
+static awk_bool_t
+api_get_file(awk_ext_id_t id, const char *name, size_t namelen, const char *filetype, int fd, const awk_input_buf_t **ibufp, const awk_output_buf_t **obufp)
+{
+ const struct redirect *f;
+ int flag; /* not used, sigh */
+ enum redirval redirtype;
+
+ if ((name == NULL) || (namelen == 0)) {
+ if (curfile == NULL) {
+ if (nextfile(& curfile, false) <= 0)
+ return awk_false;
+ {
+ INSTRUCTION *pc = main_beginfile;
+ /* save execution state */
+ int save_rule = currule;
+ char *save_source = source;
+
+ while (1) {
+ if (!pc)
+ fatal(_("cannot find end of BEGINFILE rule"));
+ if (pc->opcode == Op_after_beginfile)
+ break;
+ pc = pc->nexti;
+ }
+ pc->opcode = Op_stop;
+ (void) (*interpret)(main_beginfile);
+ pc->opcode = Op_after_beginfile;
+ after_beginfile(& curfile);
+ /* restore execution state */
+ currule = save_rule;
+ source = save_source;
+ }
+ }
+ *ibufp = &curfile->public;
+ *obufp = NULL;
+ return awk_true;
+ }
+ redirtype = redirect_none;
+ switch (filetype[0]) {
+ case '<':
+ if (filetype[1] == '\0')
+ redirtype = redirect_input;
+ break;
+ case '>':
+ switch (filetype[1]) {
+ case '\0':
+ redirtype = redirect_output;
+ break;
+ case '>':
+ if (filetype[2] == '\0')
+ redirtype = redirect_append;
+ break;
+ }
+ break;
+ case '|':
+ if (filetype[2] == '\0') {
+ switch (filetype[1]) {
+ case '>':
+ redirtype = redirect_pipe;
+ break;
+ case '<':
+ redirtype = redirect_pipein;
+ break;
+ case '&':
+ redirtype = redirect_twoway;
+ break;
+ }
+ }
+ break;
+ }
+ if (redirtype == redirect_none) {
+ warning(_("cannot open unrecognized file type `%s' for `%s'"),
+ filetype, name);
+ return awk_false;
+ }
+ if ((f = redirect_string(name, namelen, 0, redirtype, &flag, fd)) == NULL)
+ return awk_false;
+ *ibufp = f->iop ? & f->iop->public : NULL;
+ *obufp = f->output.fp ? & f->output : NULL;
+ return awk_true;
+}
+
/*
* Register a version string for this extension with gawk.
*/
@@ -1119,6 +1210,9 @@ gawk_api_t api_impl = {
calloc,
realloc,
free,
+
+ /* Find/open a file */
+ api_get_file,
};
/* init_ext_api --- init the extension API */
diff --git a/gawkapi.h b/gawkapi.h
index d8215450..cdf81cc8 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -263,7 +263,7 @@ typedef struct awk_two_way_processor {
/* Current version of the API. */
enum {
GAWK_API_MAJOR_VERSION = 1,
- GAWK_API_MINOR_VERSION = 1
+ GAWK_API_MINOR_VERSION = 2
};
/* A number of typedefs related to different types of values. */
@@ -504,7 +504,7 @@ typedef struct gawk_api {
awk_value_t *result);
/*
- * Convert a paramter that was undefined into an array
+ * Convert a parameter that was undefined into an array
* (provide call-by-reference for arrays). Returns false
* if count is too big, or if the argument's type is
* not undefined.
@@ -674,6 +674,39 @@ typedef struct gawk_api {
void *(*api_calloc)(size_t nmemb, size_t size);
void *(*api_realloc)(void *ptr, size_t size);
void (*api_free)(void *ptr);
+
+ /*
+ * Look up a file. If the name is NULL or name_len is 0, it returns
+ * data for the currently open input file corresponding to FILENAME
+ * (and it will not access the filetype argument, so that may be
+ * undefined).
+ * If the file is not already open, it tries to open it.
+ * The "filetype" argument should be one of:
+ * ">", ">>", "<", "|>", "|<", and "|&"
+ * If the file is not already open, and the fd argument is non-negative,
+ * gawk will use that file descriptor instead of opening the file
+ * in the usual way. If the fd is non-negative, but the file exists
+ * already, gawk ignores the fd and returns the existing file. It is
+ * the caller's responsibility to notice that the fd in the returned
+ * awk_input_buf_t does not match the requested value. Note that
+ * supplying a file descriptor is currently NOT supported for pipes.
+ * It should work for input, output, append, and two-way (coprocess)
+ * sockets. If the filetype is two-way, we assume that it is a socket!
+ * Note that in the two-way case, the input and output file descriptors
+ * may differ. To check for success, one must check that either of
+ * them matches.
+ */
+ awk_bool_t (*api_get_file)(awk_ext_id_t id,
+ const char *name,
+ size_t name_len,
+ const char *filetype,
+ int fd,
+ /*
+ * Return values (on success, one or both should
+ * be non-NULL):
+ */
+ const awk_input_buf_t **ibufp,
+ const awk_output_buf_t **obufp);
} gawk_api_t;
#ifndef GAWK /* these are not for the gawk code itself! */
@@ -756,6 +789,9 @@ typedef struct gawk_api {
#define release_value(value) \
(api->api_release_value(ext_id, value))
+#define get_file(name, namelen, filetype, fd, ibuf, obuf) \
+ (api->api_get_file(ext_id, name, namelen, filetype, fd, ibuf, obuf))
+
#define register_ext_version(version) \
(api->api_register_ext_version(ext_id, version))
diff --git a/io.c b/io.c
index 1d15d887..f849f839 100644
--- a/io.c
+++ b/io.c
@@ -272,7 +272,7 @@ static IOBUF *iop_alloc(int fd, const char *name, int errno_val);
static IOBUF *iop_finish(IOBUF *iop);
static int gawk_pclose(struct redirect *rp);
static int str2mode(const char *mode);
-static int two_way_open(const char *str, struct redirect *rp);
+static int two_way_open(const char *str, struct redirect *rp, int extfd);
static int pty_vs_pipe(const char *command);
static void find_input_parser(IOBUF *iop);
static bool find_output_wrapper(awk_output_buf_t *outbuf);
@@ -596,7 +596,8 @@ inrec(IOBUF *iop, int *errcode)
else
cnt = get_a_record(& begin, iop, errcode);
- if (cnt == EOF) {
+ /* Note that get_a_record may return -2 when I/O would block */
+ if (cnt < 0) {
retval = false;
} else {
INCREMENT_REC(NR);
@@ -727,10 +728,9 @@ redflags2str(int flags)
/* redirect --- Redirection for printf and print commands */
struct redirect *
-redirect(NODE *redir_exp, int redirtype, int *errflg)
+redirect_string(const char *str, size_t explen, int not_string, int redirtype, int *errflg, int extfd)
{
struct redirect *rp;
- char *str;
int tflag = 0;
int outflag = 0;
const char *direction = "to";
@@ -779,18 +779,16 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
default:
cant_happen();
}
- if (do_lint && (redir_exp->flags & STRCUR) == 0)
+ if (do_lint && not_string)
lintwarn(_("expression in `%s' redirection only has numeric value"),
what);
- redir_exp = force_string(redir_exp);
- str = redir_exp->stptr;
if (str == NULL || *str == '\0')
fatal(_("expression for `%s' redirection has null string value"),
what);
- if (do_lint && (strncmp(str, "0", redir_exp->stlen) == 0
- || strncmp(str, "1", redir_exp->stlen) == 0))
+ if (do_lint && (strncmp(str, "0", explen) == 0
+ || strncmp(str, "1", explen) == 0))
lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"),
str, what);
@@ -828,8 +826,8 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
#endif /* PIPES_SIMULATED */
/* now check for a match */
- if (strlen(rp->value) == redir_exp->stlen
- && memcmp(rp->value, str, redir_exp->stlen) == 0
+ if (strlen(rp->value) == explen
+ && memcmp(rp->value, str, explen) == 0
&& ((rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY)) == tflag
|| (outflag != 0
&& (rp->flag & (RED_FILE|RED_WRITE)) == outflag))) {
@@ -840,23 +838,25 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
if (do_lint && rpflag != newflag)
lintwarn(
_("unnecessary mixing of `>' and `>>' for file `%.*s'"),
- (int) redir_exp->stlen, rp->value);
+ (int) explen, rp->value);
break;
}
}
if (rp == NULL) {
+ char *newstr;
new_rp = true;
if (save_rp != NULL) {
rp = save_rp;
efree(rp->value);
} else
emalloc(rp, struct redirect *, sizeof(struct redirect), "redirect");
- emalloc(str, char *, redir_exp->stlen + 1, "redirect");
- memcpy(str, redir_exp->stptr, redir_exp->stlen);
- str[redir_exp->stlen] = '\0';
- rp->value = str;
+ emalloc(newstr, char *, explen + 1, "redirect");
+ memcpy(newstr, str, explen);
+ newstr[explen] = '\0';
+ str = newstr;
+ rp->value = newstr;
rp->flag = tflag;
init_output_wrapper(& rp->output);
rp->output.name = str;
@@ -888,6 +888,10 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
mode = binmode("a");
break;
case redirect_pipe:
+ if (extfd >= 0) {
+ warning(_("get_file cannot create pipe `%s' with fd %d"), str, extfd);
+ return NULL;
+ }
/* synchronize output before new pipe */
(void) flush_io();
@@ -901,6 +905,10 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
rp->flag |= RED_NOBUF;
break;
case redirect_pipein:
+ if (extfd >= 0) {
+ warning(_("get_file cannot create pipe `%s' with fd %d"), str, extfd);
+ return NULL;
+ }
direction = "from";
if (gawk_popen(str, rp) == NULL)
fatal(_("can't open pipe `%s' for input (%s)"),
@@ -908,7 +916,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
break;
case redirect_input:
direction = "from";
- fd = devopen(str, binmode("r"));
+ fd = (extfd >= 0) ? extfd : devopen(str, binmode("r"));
if (fd == INVALID_HANDLE && errno == EISDIR) {
*errflg = EISDIR;
/* do not free rp, saving it for reuse (save_rp = rp) */
@@ -925,8 +933,14 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
}
break;
case redirect_twoway:
+#ifndef HAVE_SOCKETS
+ if (extfd >= 0) {
+ warning(_("get_file socket creation not supported on this platform for `%s' with fd %d"), str, extfd);
+ return NULL;
+ }
+#endif
direction = "to/from";
- if (! two_way_open(str, rp)) {
+ if (! two_way_open(str, rp, extfd)) {
#ifdef HAVE_SOCKETS
if (inetfile(str, NULL)) {
*errflg = errno;
@@ -945,7 +959,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
if (mode != NULL) {
errno = 0;
rp->output.mode = mode;
- fd = devopen(str, mode);
+ fd = (extfd >= 0) ? extfd : devopen(str, mode);
if (fd > INVALID_HANDLE) {
if (fd == fileno(stdin))
@@ -1044,6 +1058,15 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
return rp;
}
+struct redirect *
+redirect(NODE *redir_exp, int redirtype, int *errflg)
+{
+ int not_string = ((redir_exp->flags & STRCUR) == 0);
+ redir_exp = force_string(redir_exp);
+ return redirect_string(redir_exp->stptr, redir_exp->stlen, not_string,
+ redirtype, errflg, -1);
+}
+
/* getredirect --- find the struct redirect for this file or pipe */
struct redirect *
@@ -1699,16 +1722,16 @@ strictopen:
/* two_way_open --- open a two way communications channel */
static int
-two_way_open(const char *str, struct redirect *rp)
+two_way_open(const char *str, struct redirect *rp, int extfd)
{
static bool no_ptys = false;
#ifdef HAVE_SOCKETS
/* case 1: socket */
- if (inetfile(str, NULL)) {
+ if (extfd >= 0 || inetfile(str, NULL)) {
int fd, newfd;
- fd = devopen(str, "rw");
+ fd = (extfd >= 0) ? extfd : devopen(str, "rw");
if (fd == INVALID_HANDLE)
return false;
if ((BINMODE & BINMODE_OUTPUT) != 0)
@@ -2168,17 +2191,43 @@ use_pipes:
#ifndef PIPES_SIMULATED /* real pipes */
-/* wait_any --- wait for a child process, close associated pipe */
+/*
+ * wait_any --- if the argument pid is 0, wait for all child processes that
+ * have exited. We loop to make sure to reap all children that have exited to
+ * minimize the risk of running out of process slots. Since we don't process
+ * SIGCHLD, we do not immediately reap exited children. So when we get here,
+ * we want to reap any that have piled up.
+ *
+ * Note: on platforms that do not support waitpid with WNOHANG, when called with
+ * a zero argument, this function will hang until all children have exited.
+ *
+ * AJS, 2013-07-07: I do not see why we need to ignore signals during this
+ * function. This function just waits and updates the pid and status fields.
+ * I don't see why that should interfere with any signal handlers. But I am
+ * reluctant to remove this protection. So I changed to use sigprocmask to
+ * block signals instead to avoid interfering with installed signal handlers.
+ */
static int
wait_any(int interesting) /* pid of interest, if any */
{
- RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int);
int pid;
int status = 0;
struct redirect *redp;
+#ifdef HAVE_SIGPROCMASK
+ sigset_t set, oldset;
+
+ /* I have no idea why we are blocking signals during this function... */
+ sigemptyset(& set);
+ sigaddset(& set, SIGINT);
+ sigaddset(& set, SIGHUP);
+ sigaddset(& set, SIGQUIT);
+ sigprocmask(SIG_BLOCK, & set, & oldset);
+#else
+ RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int);
istat = signal(SIGINT, SIG_IGN);
+#endif
#ifdef __MINGW32__
if (interesting < 0) {
status = -1;
@@ -2195,10 +2244,21 @@ wait_any(int interesting) /* pid of interest, if any */
}
}
#else
+#ifndef HAVE_SIGPROCMASK
hstat = signal(SIGHUP, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
+#endif
for (;;) {
-# ifdef HAVE_SYS_WAIT_H /* POSIX compatible sys/wait.h */
+# if defined(HAVE_WAITPID) && defined(WNOHANG)
+ /*
+ * N.B. If the caller wants status for a specific child process
+ * (i.e. interesting is non-zero), then we must hang until we
+ * get exit status for that child.
+ */
+ if ((pid = waitpid(-1, & status, (interesting ? 0 : WNOHANG))) == 0)
+ /* No children have exited */
+ break;
+# elif defined(HAVE_SYS_WAIT_H) /* POSIX compatible sys/wait.h */
pid = wait(& status);
# else
pid = wait((union wait *) & status);
@@ -2216,10 +2276,16 @@ wait_any(int interesting) /* pid of interest, if any */
if (pid == -1 && errno == ECHILD)
break;
}
+#ifndef HAVE_SIGPROCMASK
signal(SIGHUP, hstat);
signal(SIGQUIT, qstat);
#endif
+#endif
+#ifndef HAVE_SIGPROCMASK
signal(SIGINT, istat);
+#else
+ sigprocmask(SIG_SETMASK, & oldset, NULL);
+#endif
return status;
}
@@ -2440,7 +2506,7 @@ do_getline_redir(int into_variable, enum redirval redirtype)
if (errcode != 0) {
if (! do_traditional && (errcode != -1))
update_ERRNO_int(errcode);
- return make_number((AWKNUM) -1.0);
+ return make_number((AWKNUM) cnt);
}
if (cnt == EOF) {
@@ -2490,7 +2556,7 @@ do_getline(int into_variable, IOBUF *iop)
update_ERRNO_int(errcode);
if (into_variable)
(void) POP_ADDRESS();
- return make_number((AWKNUM) -1.0);
+ return make_number((AWKNUM) cnt);
}
if (cnt == EOF)
@@ -3383,10 +3449,44 @@ find_longest_terminator:
return REC_OK;
}
+/* return true if PROCINFO[<filename>, "RETRY"] exists */
+static inline int
+retryable(IOBUF *iop)
+{
+ return PROCINFO_node && in_PROCINFO(iop->public.name, "RETRY", NULL);
+}
+
+/* Does the I/O error indicate that the operation should be retried later? */
+
+static inline int
+errno_io_retry(void)
+{
+ switch (errno) {
+#ifdef EAGAIN
+ case EAGAIN:
+#endif
+#ifdef EWOULDBLOCK
+#if !defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)
+ case EWOULDBLOCK:
+#endif
+#endif
+#ifdef EINTR
+ case EINTR:
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+#endif
+ return 1;
+ default:
+ return 0;
+ }
+}
+
/*
* get_a_record --- read a record from IOP into out,
* return length of EOF, set RT.
* Note that errcode is never NULL, and the caller initializes *errcode to 0.
+ * If I/O would block, return -2.
*/
static int
@@ -3430,8 +3530,10 @@ get_a_record(char **out, /* pointer to pointer to data */
iop->flag |= IOP_AT_EOF;
return EOF;
} else if (iop->count == -1) {
- iop->flag |= IOP_AT_EOF;
*errcode = errno;
+ if (errno_io_retry() && retryable(iop))
+ return -2;
+ iop->flag |= IOP_AT_EOF;
return EOF;
} else {
iop->dataend = iop->buf + iop->count;
@@ -3505,6 +3607,8 @@ get_a_record(char **out, /* pointer to pointer to data */
iop->count = iop->public.read_func(iop->public.fd, iop->dataend, amt_to_read);
if (iop->count == -1) {
*errcode = errno;
+ if (errno_io_retry() && retryable(iop))
+ return -2;
iop->flag |= IOP_AT_EOF;
break;
} else if (iop->count == 0) {
diff --git a/test/ChangeLog b/test/ChangeLog
index 19105027..c859a7bb 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -28,6 +28,34 @@
* testext.ok: Adjust for code changes.
+2015-01-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (EXTRA_DIST): Add defvar.awk and defvar.ok.
+ (SHLIB_TESTS): Add defvar.
+ (defvar): New test.
+ * defvar.awk, defvar.ok: New files.
+
+2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (EXTRA_DIST): Add getfile.awk and getfile.ok.
+ (SHLIB_TESTS): Add getfile.
+ (getfile): New test.
+ * getfile.awk, getfile.ok: New files.
+
+2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (EXTRA_DIST): Add timeout.awk and timeout.ok.
+ (BASIC_TESTS): Remove errno.
+ (GAWK_EXT_TESTS): Add errno and timeout.
+ * timeout.awk, timeout.ok: New files.
+
+2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * Makefile.am (EXTRA_DIST): Add errno.awk, errno.in, and errno.ok.
+ (BASIC_TESTS): Add errno.
+ (errno): New test.
+ * errno.awk, errno.in, errno.ok: New files.
+
2014-12-24 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (badbuild): New test.
@@ -62,6 +90,10 @@
* mbprintf4.awk: Add record and line number for debugging.
* mpprint4.ok: Adjust.
+2014-11-06 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * testext.ok: Add results from new test_get_file test.
+
2014-11-02 Arnold D. Robbins <arnold@skeeve.com>
* Makefile.am (profile7): New test.
diff --git a/test/Makefile.am b/test/Makefile.am
index 8f501b56..438efd93 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -174,6 +174,8 @@ EXTRA_DIST = \
dbugeval.ok \
defref.awk \
defref.ok \
+ defvar.awk \
+ defvar.ok \
delargv.awk \
delargv.ok \
delarpm2.awk \
@@ -208,6 +210,9 @@ EXTRA_DIST = \
dynlj.ok \
eofsplit.awk \
eofsplit.ok \
+ errno.awk \
+ errno.in \
+ errno.ok \
exit.ok \
exit.sh \
exit2.awk \
@@ -334,6 +339,8 @@ EXTRA_DIST = \
gensub.ok \
gensub2.awk \
gensub2.ok \
+ getfile.awk \
+ getfile.ok \
getline.awk \
getline.in \
getline.ok \
@@ -927,6 +934,8 @@ EXTRA_DIST = \
testext.ok \
time.awk \
time.ok \
+ timeout.awk \
+ timeout.ok \
tradanch.awk \
tradanch.in \
tradanch.ok \
@@ -1025,7 +1034,7 @@ UNIX_TESTS = \
GAWK_EXT_TESTS = \
aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \
backw badargs beginfile1 beginfile2 binmode1 charasbytes \
- colonwarn clos1way dbugeval delsub devfd devfd1 devfd2 dumpvars exit \
+ colonwarn clos1way dbugeval delsub devfd devfd1 devfd2 dumpvars errno exit \
fieldwdth fpat1 fpat2 fpat3 fpatnull fsfwfs funlen \
functab1 functab2 functab3 fwtest fwtest2 fwtest3 \
genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops \
@@ -1042,7 +1051,8 @@ GAWK_EXT_TESTS = \
rsstart2 rsstart3 rstest6 shadow sortfor sortu split_after_fpat \
splitarg4 strftime \
strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \
- symtab7 symtab8 symtab9
+ symtab7 symtab8 symtab9 \
+ timeout
EXTRA_TESTS = inftest regtest
@@ -1059,7 +1069,7 @@ LOCALE_CHARSET_TESTS = \
mbprintf1 mbprintf2 mbprintf3 mbprintf4 rebt8b2 rtlenmb sort1 sprintfc
SHLIB_TESTS = \
- fnmatch filefuncs fork fork2 fts functab4 inplace1 inplace2 inplace3 \
+ defvar fnmatch filefuncs fork fork2 fts functab4 getfile inplace1 inplace2 inplace3 \
ordchr ordchr2 readdir readfile readfile2 revout revtwoway rwarray testext time
# List of the tests which should be run with --lint option:
@@ -1318,6 +1328,11 @@ devfd::
@$(AWK) 1 /dev/fd/4 /dev/fd/5 4<"$(srcdir)"/devfd.in4 5<"$(srcdir)"/devfd.in5 >_$@ 2>&1 || echo EXIT CODE: $$? >> _$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+errno:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
fflush::
@echo $@
@"$(srcdir)"/fflush.sh >_$@
@@ -1900,6 +1915,16 @@ testext::
@$(AWK) -f ./testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ testext.awk
+defvar:
+ @echo $@
+ @$(AWK) -v TESTEXT_QUIET=1 -ltestext -f $(srcdir)/$@.awk $(srcdir)/$@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+getfile:
+ @echo $@
+ @$(AWK) -v TESTEXT_QUIET=1 -ltestext -f $(srcdir)/$@.awk $(srcdir)/$@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
readdir:
@if [ "`uname`" = Linux ] && [ "`stat -f . 2>/dev/null | awk 'NR == 2 { print $$NF }'`" = nfs ]; then \
echo This test may fail on GNU/Linux systems when run on an NFS filesystem.; \
diff --git a/test/Makefile.in b/test/Makefile.in
index d4097f3d..e6abf971 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -421,6 +421,8 @@ EXTRA_DIST = \
dbugeval.ok \
defref.awk \
defref.ok \
+ defvar.awk \
+ defvar.ok \
delargv.awk \
delargv.ok \
delarpm2.awk \
@@ -455,6 +457,9 @@ EXTRA_DIST = \
dynlj.ok \
eofsplit.awk \
eofsplit.ok \
+ errno.awk \
+ errno.in \
+ errno.ok \
exit.ok \
exit.sh \
exit2.awk \
@@ -581,6 +586,8 @@ EXTRA_DIST = \
gensub.ok \
gensub2.awk \
gensub2.ok \
+ getfile.awk \
+ getfile.ok \
getline.awk \
getline.in \
getline.ok \
@@ -1174,6 +1181,8 @@ EXTRA_DIST = \
testext.ok \
time.awk \
time.ok \
+ timeout.awk \
+ timeout.ok \
tradanch.awk \
tradanch.in \
tradanch.ok \
@@ -1271,7 +1280,7 @@ UNIX_TESTS = \
GAWK_EXT_TESTS = \
aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \
backw badargs beginfile1 beginfile2 binmode1 charasbytes \
- colonwarn clos1way dbugeval delsub devfd devfd1 devfd2 dumpvars exit \
+ colonwarn clos1way dbugeval delsub devfd devfd1 devfd2 dumpvars errno exit \
fieldwdth fpat1 fpat2 fpat3 fpatnull fsfwfs funlen \
functab1 functab2 functab3 fwtest fwtest2 fwtest3 \
genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops \
@@ -1288,7 +1297,8 @@ GAWK_EXT_TESTS = \
rsstart2 rsstart3 rstest6 shadow sortfor sortu split_after_fpat \
splitarg4 strftime \
strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \
- symtab7 symtab8 symtab9
+ symtab7 symtab8 symtab9 \
+ timeout
EXTRA_TESTS = inftest regtest
INET_TESTS = inetdayu inetdayt inetechu inetecht
@@ -1302,7 +1312,7 @@ LOCALE_CHARSET_TESTS = \
mbprintf1 mbprintf2 mbprintf3 mbprintf4 rebt8b2 rtlenmb sort1 sprintfc
SHLIB_TESTS = \
- fnmatch filefuncs fork fork2 fts functab4 inplace1 inplace2 inplace3 \
+ defvar fnmatch filefuncs fork fork2 fts functab4 getfile inplace1 inplace2 inplace3 \
ordchr ordchr2 readdir readfile readfile2 revout revtwoway rwarray testext time
@@ -1744,6 +1754,11 @@ devfd::
@$(AWK) 1 /dev/fd/4 /dev/fd/5 4<"$(srcdir)"/devfd.in4 5<"$(srcdir)"/devfd.in5 >_$@ 2>&1 || echo EXIT CODE: $$? >> _$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+errno:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
fflush::
@echo $@
@"$(srcdir)"/fflush.sh >_$@
@@ -2325,6 +2340,16 @@ testext::
@$(AWK) -f ./testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ testext.awk
+defvar:
+ @echo $@
+ @$(AWK) -v TESTEXT_QUIET=1 -ltestext -f $(srcdir)/$@.awk $(srcdir)/$@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
+getfile:
+ @echo $@
+ @$(AWK) -v TESTEXT_QUIET=1 -ltestext -f $(srcdir)/$@.awk $(srcdir)/$@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
readdir:
@if [ "`uname`" = Linux ] && [ "`stat -f . 2>/dev/null | awk 'NR == 2 { print $$NF }'`" = nfs ]; then \
echo This test may fail on GNU/Linux systems when run on an NFS filesystem.; \
@@ -3711,6 +3736,11 @@ symtab7:
@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 5c4c40f9..be10addd 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -1267,6 +1267,11 @@ symtab7:
@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/defvar.awk b/test/defvar.awk
new file mode 100644
index 00000000..444b81c9
--- /dev/null
+++ b/test/defvar.awk
@@ -0,0 +1,3 @@
+BEGIN {
+ print "test_deferred returns", test_deferred()
+}
diff --git a/test/defvar.ok b/test/defvar.ok
new file mode 100644
index 00000000..4c85427e
--- /dev/null
+++ b/test/defvar.ok
@@ -0,0 +1,5 @@
+fubar = 9
+rumpus = -5
+uid matches 1
+api_major matches 1
+test_deferred returns 1
diff --git a/test/errno.awk b/test/errno.awk
new file mode 100644
index 00000000..bcb77614
--- /dev/null
+++ b/test/errno.awk
@@ -0,0 +1,10 @@
+BEGIN {
+ # check that PROCINFO["errno"] is working properly
+ getline
+ if (close(FILENAME)) {
+ print "Error `" ERRNO "' closing input file"
+ print "errno =", PROCINFO["errno"]
+ }
+ getline < (FILENAME "/bogus")
+ print (PROCINFO["errno"] > 0), ERRNO
+}
diff --git a/test/errno.in b/test/errno.in
new file mode 100644
index 00000000..a92d664b
--- /dev/null
+++ b/test/errno.in
@@ -0,0 +1,3 @@
+line 1
+line 2
+line 3
diff --git a/test/errno.ok b/test/errno.ok
new file mode 100644
index 00000000..181afdaf
--- /dev/null
+++ b/test/errno.ok
@@ -0,0 +1,3 @@
+Error `close of redirection that was never opened' closing input file
+errno = 0
+1 Not a directory
diff --git a/test/getfile.awk b/test/getfile.awk
new file mode 100644
index 00000000..6ee783f6
--- /dev/null
+++ b/test/getfile.awk
@@ -0,0 +1,35 @@
+function basename(x) {
+ return gensub(/^.*\//, "", 1, x)
+}
+
+BEGIN {
+ print "BEGIN"
+
+ cmd = "echo hello; echo goodbye"
+ rc = get_file(cmd, "<<", -1, res)
+ print "expected error result", rc, ERRNO
+ print "get_file returned", get_file(cmd, "|<", -1, res)
+ print "input_name", basename(res["input_name"])
+ print (cmd | getline x)
+ print x
+
+ # check that calling get_file on "" triggers the BEGINFILE rule
+ print "get_file returned", get_file("", "", -1, res)
+ print "input_name", basename(res["input_name"])
+ print "end BEGIN"
+}
+
+BEGINFILE {
+ printf "BEGINFILE (%s) ERRNO (%s)\n", basename(FILENAME), ERRNO
+}
+
+ENDFILE {
+ printf "ENDFILE (%s) ERRNO (%s)\n", basename(FILENAME), ERRNO
+}
+
+END {
+ print "END"
+ print (cmd | getline x)
+ print x
+ print close(cmd)
+}
diff --git a/test/getfile.ok b/test/getfile.ok
new file mode 100644
index 00000000..92c915f2
--- /dev/null
+++ b/test/getfile.ok
@@ -0,0 +1,17 @@
+BEGIN
+gawk: ./getfile.awk:9: warning: cannot open unrecognized file type `<<' for `echo hello; echo goodbye'
+get_file: get_file(echo hello; echo goodbye, <<, -1) failed
+expected error result 0
+get_file returned 1
+input_name echo hello; echo goodbye
+1
+hello
+BEGINFILE (getfile.awk) ERRNO ()
+get_file returned 1
+input_name getfile.awk
+end BEGIN
+ENDFILE (getfile.awk) ERRNO ()
+END
+1
+goodbye
+0
diff --git a/test/testext.ok b/test/testext.ok
index a828ecb2..9dae010f 100644
--- a/test/testext.ok
+++ b/test/testext.ok
@@ -69,6 +69,12 @@ test_scalar_reserved: could not update new_value2 for ARGC - pass
test_indirect_var: sym_lookup of NR passed
test_indirect_var: value of NR is 3
test_indirect_var() return 1
+
+test_get_file returned 0
+File [.test.alias] nr [1]: line 1
+File [.test.alias] nr [2]: line 2
+File [.test.alias] nr [3]: line 3
+
answer_num = 42
message_string = hello, world
new_array["hello"] = "world"
diff --git a/test/timeout.awk b/test/timeout.awk
new file mode 100644
index 00000000..ccf4537d
--- /dev/null
+++ b/test/timeout.awk
@@ -0,0 +1,26 @@
+BEGIN {
+ cmd = "echo hello; sleep 1; echo goodbye"
+
+ print "With timeouts"
+ PROCINFO[cmd, "READ_TIMEOUT"] = 300
+ while ((rc = (cmd | getline x)) > 0)
+ print x
+ if (rc < 0)
+ print rc, (PROCINFO["errno"] != 0), (ERRNO != "")
+ print (close(cmd) != 0)
+
+ PROCINFO[cmd, "RETRY"]
+ print ""
+ print "With timeouts and retries"
+ while (((rc = (cmd | getline x)) > 0) || (rc == -2)) {
+ if (rc > 0) {
+ print x
+ n = 0
+ }
+ else
+ print ++n, "timed out; trying again"
+ }
+ if (rc < 0)
+ print rc, (PROCINFO["errno"] != 0), (ERRNO != "")
+ print (close(cmd) != 0)
+}
diff --git a/test/timeout.ok b/test/timeout.ok
new file mode 100644
index 00000000..a388747b
--- /dev/null
+++ b/test/timeout.ok
@@ -0,0 +1,12 @@
+With timeouts
+hello
+-1 1 1
+1
+
+With timeouts and retries
+hello
+1 timed out; trying again
+2 timed out; trying again
+3 timed out; trying again
+goodbye
+0