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.c97
-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, 1016 deletions
diff --git a/ChangeLog b/ChangeLog
index a8079e05..5c539e19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -26,6 +26,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.
@@ -44,6 +60,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
@@ -170,6 +239,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.
@@ -1338,6 +1437,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
@@ -1348,6 +1486,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 e16bf9e9..1e2d7af3 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -3,6 +3,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 376076d9..ba5dbdf5 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
@@ -4169,6 +4171,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.
@@ -5440,7 +5443,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.
@@ -5877,7 +5884,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
=================================
@@ -5956,7 +5963,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
@@ -5971,9 +5979,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
@@ -5996,7 +6031,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
@@ -6069,7 +6104,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
@@ -10364,6 +10399,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
@@ -10412,6 +10452,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.
@@ -10522,6 +10566,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::.
@@ -22876,6 +22924,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.
@@ -22936,6 +22985,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
@@ -24142,7 +24194,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
--------------------------
@@ -24627,9 +24679,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
@@ -24646,7 +24761,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
@@ -24695,7 +24810,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
@@ -24730,7 +24845,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
@@ -32247,9 +32362,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)
@@ -32443,7 +32558,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)
@@ -32466,7 +32581,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)
@@ -32474,9 +32589,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.
@@ -32484,7 +32601,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.
@@ -32525,8 +32642,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)
@@ -32641,7 +32758,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)
@@ -32722,7 +32839,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)
@@ -32790,9 +32907,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.
@@ -32842,7 +32959,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)
@@ -32892,7 +33009,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)
@@ -32927,7 +33044,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.
@@ -32959,7 +33076,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.
@@ -32967,14 +33084,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)
@@ -33066,7 +33183,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.
@@ -33361,7 +33478,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)
@@ -33374,7 +33491,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)
@@ -33423,7 +33540,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.
@@ -33432,9 +33549,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.
@@ -33548,7 +33665,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)
@@ -33714,24 +33831,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)
@@ -33866,6 +33983,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)
@@ -33889,7 +34007,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)
@@ -33915,9 +34033,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)
@@ -33937,7 +34055,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)
@@ -34020,7 +34138,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.
@@ -34182,9 +34300,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)
@@ -34361,10 +34479,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)
@@ -34454,560 +34572,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-161648
-Node: Conventions61748
-Node: Manual History64086
-Ref: Manual History-Footnote-167068
-Ref: Manual History-Footnote-267109
-Node: How To Contribute67183
-Node: Acknowledgments68312
-Node: Getting Started73117
-Node: Running gawk75550
-Node: One-shot76740
-Node: Read Terminal77988
-Node: Long80015
-Node: Executable Scripts81531
-Ref: Executable Scripts-Footnote-184320
-Node: Comments84423
-Node: Quoting86905
-Node: DOS Quoting92429
-Node: Sample Data Files93104
-Node: Very Simple95699
-Node: Two Rules100597
-Node: More Complex102483
-Node: Statements/Lines105345
-Ref: Statements/Lines-Footnote-1109800
-Node: Other Features110065
-Node: When110996
-Ref: When-Footnote-1112750
-Node: Intro Summary112815
-Node: Invoking Gawk113698
-Node: Command Line115212
-Node: Options116010
-Ref: Options-Footnote-1131814
-Ref: Options-Footnote-2132043
-Node: Other Arguments132068
-Node: Naming Standard Input135016
-Node: Environment Variables136109
-Node: AWKPATH Variable136667
-Ref: AWKPATH Variable-Footnote-1140080
-Ref: AWKPATH Variable-Footnote-2140125
-Node: AWKLIBPATH Variable140385
-Node: Other Environment Variables141641
-Node: Exit Status145129
-Node: Include Files145805
-Node: Loading Shared Libraries149402
-Node: Obsolete150829
-Node: Undocumented151526
-Node: Invoking Summary151793
-Node: Regexp153457
-Node: Regexp Usage154911
-Node: Escape Sequences156948
-Node: Regexp Operators163189
-Ref: Regexp Operators-Footnote-1170615
-Ref: Regexp Operators-Footnote-2170762
-Node: Bracket Expressions170860
-Ref: table-char-classes172875
-Node: Leftmost Longest175799
-Node: Computed Regexps177101
-Node: GNU Regexp Operators180498
-Node: Case-sensitivity184171
-Ref: Case-sensitivity-Footnote-1187056
-Ref: Case-sensitivity-Footnote-2187291
-Node: Regexp Summary187399
-Node: Reading Files188866
-Node: Records190960
-Node: awk split records191693
-Node: gawk split records196608
-Ref: gawk split records-Footnote-1201152
-Node: Fields201189
-Ref: Fields-Footnote-1203965
-Node: Nonconstant Fields204051
-Ref: Nonconstant Fields-Footnote-1206294
-Node: Changing Fields206498
-Node: Field Separators212427
-Node: Default Field Splitting215132
-Node: Regexp Field Splitting216249
-Node: Single Character Fields219599
-Node: Command Line Field Separator220658
-Node: Full Line Fields223870
-Ref: Full Line Fields-Footnote-1225387
-Ref: Full Line Fields-Footnote-2225433
-Node: Field Splitting Summary225534
-Node: Constant Size227608
-Node: Splitting By Content232197
-Ref: Splitting By Content-Footnote-1236191
-Node: Multiple Line236354
-Ref: Multiple Line-Footnote-1242240
-Node: Getline242419
-Node: Plain Getline244631
-Node: Getline/Variable247271
-Node: Getline/File248419
-Node: Getline/Variable/File249803
-Ref: Getline/Variable/File-Footnote-1251406
-Node: Getline/Pipe251493
-Node: Getline/Variable/Pipe254176
-Node: Getline/Coprocess255307
-Node: Getline/Variable/Coprocess256559
-Node: Getline Notes257298
-Node: Getline Summary260090
-Ref: table-getline-variants260502
-Node: Read Timeout261331
-Ref: Read Timeout-Footnote-1265156
-Node: Command-line directories265214
-Node: Input Summary266119
-Node: Input Exercises269420
-Node: Printing270148
-Node: Print271925
-Node: Print Examples273382
-Node: Output Separators276161
-Node: OFMT278179
-Node: Printf279533
-Node: Basic Printf280318
-Node: Control Letters281888
-Node: Format Modifiers285871
-Node: Printf Examples291880
-Node: Redirection294366
-Node: Special FD301207
-Ref: Special FD-Footnote-1304367
-Node: Special Files304441
-Node: Other Inherited Files305058
-Node: Special Network306058
-Node: Special Caveats306920
-Node: Close Files And Pipes307871
-Ref: Close Files And Pipes-Footnote-1315053
-Ref: Close Files And Pipes-Footnote-2315201
-Node: Output Summary315351
-Node: Output Exercises316349
-Node: Expressions317029
-Node: Values318214
-Node: Constants318892
-Node: Scalar Constants319583
-Ref: Scalar Constants-Footnote-1320442
-Node: Nondecimal-numbers320692
-Node: Regexp Constants323710
-Node: Using Constant Regexps324235
-Node: Variables327378
-Node: Using Variables328033
-Node: Assignment Options329944
-Node: Conversion331819
-Node: Strings And Numbers332343
-Ref: Strings And Numbers-Footnote-1335408
-Node: Locale influences conversions335517
-Ref: table-locale-affects338264
-Node: All Operators338852
-Node: Arithmetic Ops339482
-Node: Concatenation341987
-Ref: Concatenation-Footnote-1344806
-Node: Assignment Ops344912
-Ref: table-assign-ops349891
-Node: Increment Ops351163
-Node: Truth Values and Conditions354601
-Node: Truth Values355686
-Node: Typing and Comparison356735
-Node: Variable Typing357545
-Node: Comparison Operators361198
-Ref: table-relational-ops361608
-Node: POSIX String Comparison365103
-Ref: POSIX String Comparison-Footnote-1366175
-Node: Boolean Ops366313
-Ref: Boolean Ops-Footnote-1370792
-Node: Conditional Exp370883
-Node: Function Calls372610
-Node: Precedence376490
-Node: Locales380151
-Node: Expressions Summary381783
-Node: Patterns and Actions384343
-Node: Pattern Overview385463
-Node: Regexp Patterns387142
-Node: Expression Patterns387685
-Node: Ranges391395
-Node: BEGIN/END394501
-Node: Using BEGIN/END395262
-Ref: Using BEGIN/END-Footnote-1397996
-Node: I/O And BEGIN/END398102
-Node: BEGINFILE/ENDFILE400416
-Node: Empty403317
-Node: Using Shell Variables403634
-Node: Action Overview405907
-Node: Statements408233
-Node: If Statement410081
-Node: While Statement411576
-Node: Do Statement413605
-Node: For Statement414749
-Node: Switch Statement417906
-Node: Break Statement420288
-Node: Continue Statement422329
-Node: Next Statement424156
-Node: Nextfile Statement426537
-Node: Exit Statement429167
-Node: Built-in Variables431570
-Node: User-modified432703
-Ref: User-modified-Footnote-1440384
-Node: Auto-set440446
-Ref: Auto-set-Footnote-1454138
-Ref: Auto-set-Footnote-2454343
-Node: ARGC and ARGV454399
-Node: Pattern Action Summary458617
-Node: Arrays461044
-Node: Array Basics462373
-Node: Array Intro463217
-Ref: figure-array-elements465181
-Ref: Array Intro-Footnote-1467707
-Node: Reference to Elements467835
-Node: Assigning Elements470287
-Node: Array Example470778
-Node: Scanning an Array472536
-Node: Controlling Scanning475552
-Ref: Controlling Scanning-Footnote-1480748
-Node: Numeric Array Subscripts481064
-Node: Uninitialized Subscripts483249
-Node: Delete484866
-Ref: Delete-Footnote-1487609
-Node: Multidimensional487666
-Node: Multiscanning490763
-Node: Arrays of Arrays492352
-Node: Arrays Summary497111
-Node: Functions499203
-Node: Built-in500102
-Node: Calling Built-in501180
-Node: Numeric Functions503171
-Ref: Numeric Functions-Footnote-1507990
-Ref: Numeric Functions-Footnote-2508347
-Ref: Numeric Functions-Footnote-3508395
-Node: String Functions508667
-Ref: String Functions-Footnote-1532142
-Ref: String Functions-Footnote-2532271
-Ref: String Functions-Footnote-3532519
-Node: Gory Details532606
-Ref: table-sub-escapes534387
-Ref: table-sub-proposed535907
-Ref: table-posix-sub537271
-Ref: table-gensub-escapes538807
-Ref: Gory Details-Footnote-1539639
-Node: I/O Functions539790
-Ref: I/O Functions-Footnote-1547008
-Node: Time Functions547155
-Ref: Time Functions-Footnote-1557643
-Ref: Time Functions-Footnote-2557711
-Ref: Time Functions-Footnote-3557869
-Ref: Time Functions-Footnote-4557980
-Ref: Time Functions-Footnote-5558092
-Ref: Time Functions-Footnote-6558319
-Node: Bitwise Functions558585
-Ref: table-bitwise-ops559147
-Ref: Bitwise Functions-Footnote-1563456
-Node: Type Functions563625
-Node: I18N Functions564776
-Node: User-defined566421
-Node: Definition Syntax567226
-Ref: Definition Syntax-Footnote-1572633
-Node: Function Example572704
-Ref: Function Example-Footnote-1575623
-Node: Function Caveats575645
-Node: Calling A Function576163
-Node: Variable Scope577121
-Node: Pass By Value/Reference580109
-Node: Return Statement583604
-Node: Dynamic Typing586585
-Node: Indirect Calls587514
-Ref: Indirect Calls-Footnote-1598816
-Node: Functions Summary598944
-Node: Library Functions601646
-Ref: Library Functions-Footnote-1605255
-Ref: Library Functions-Footnote-2605398
-Node: Library Names605569
-Ref: Library Names-Footnote-1609023
-Ref: Library Names-Footnote-2609246
-Node: General Functions609332
-Node: Strtonum Function610435
-Node: Assert Function613457
-Node: Round Function616781
-Node: Cliff Random Function618322
-Node: Ordinal Functions619338
-Ref: Ordinal Functions-Footnote-1622401
-Ref: Ordinal Functions-Footnote-2622653
-Node: Join Function622864
-Ref: Join Function-Footnote-1624633
-Node: Getlocaltime Function624833
-Node: Readfile Function628577
-Node: Shell Quoting630547
-Node: Data File Management631948
-Node: Filetrans Function632580
-Node: Rewind Function636636
-Node: File Checking638023
-Ref: File Checking-Footnote-1639355
-Node: Empty Files639556
-Node: Ignoring Assigns641535
-Node: Getopt Function643086
-Ref: Getopt Function-Footnote-1654548
-Node: Passwd Functions654748
-Ref: Passwd Functions-Footnote-1663585
-Node: Group Functions663673
-Ref: Group Functions-Footnote-1671567
-Node: Walking Arrays671780
-Node: Library Functions Summary673383
-Node: Library Exercises674784
-Node: Sample Programs676064
-Node: Running Examples676834
-Node: Clones677562
-Node: Cut Program678786
-Node: Egrep Program688505
-Ref: Egrep Program-Footnote-1696003
-Node: Id Program696113
-Node: Split Program699758
-Ref: Split Program-Footnote-1703206
-Node: Tee Program703334
-Node: Uniq Program706123
-Node: Wc Program713542
-Ref: Wc Program-Footnote-1717792
-Node: Miscellaneous Programs717886
-Node: Dupword Program719099
-Node: Alarm Program721130
-Node: Translate Program725934
-Ref: Translate Program-Footnote-1730499
-Node: Labels Program730769
-Ref: Labels Program-Footnote-1734120
-Node: Word Sorting734204
-Node: History Sorting738275
-Node: Extract Program740111
-Node: Simple Sed747636
-Node: Igawk Program750704
-Ref: Igawk Program-Footnote-1765028
-Ref: Igawk Program-Footnote-2765229
-Ref: Igawk Program-Footnote-3765351
-Node: Anagram Program765466
-Node: Signature Program768523
-Node: Programs Summary769770
-Node: Programs Exercises770963
-Ref: Programs Exercises-Footnote-1775094
-Node: Advanced Features775185
-Node: Nondecimal Data777133
-Node: Array Sorting778723
-Node: Controlling Array Traversal779420
-Ref: Controlling Array Traversal-Footnote-1787753
-Node: Array Sorting Functions787871
-Ref: Array Sorting Functions-Footnote-1791760
-Node: Two-way I/O791956
-Ref: Two-way I/O-Footnote-1796901
-Ref: Two-way I/O-Footnote-2797087
-Node: TCP/IP Networking797169
-Node: Profiling800042
-Node: Advanced Features Summary808319
-Node: Internationalization810252
-Node: I18N and L10N811732
-Node: Explaining gettext812418
-Ref: Explaining gettext-Footnote-1817443
-Ref: Explaining gettext-Footnote-2817627
-Node: Programmer i18n817792
-Ref: Programmer i18n-Footnote-1822658
-Node: Translator i18n822707
-Node: String Extraction823501
-Ref: String Extraction-Footnote-1824632
-Node: Printf Ordering824718
-Ref: Printf Ordering-Footnote-1827504
-Node: I18N Portability827568
-Ref: I18N Portability-Footnote-1830023
-Node: I18N Example830086
-Ref: I18N Example-Footnote-1832889
-Node: Gawk I18N832961
-Node: I18N Summary833599
-Node: Debugger834938
-Node: Debugging835960
-Node: Debugging Concepts836401
-Node: Debugging Terms838254
-Node: Awk Debugging840826
-Node: Sample Debugging Session841720
-Node: Debugger Invocation842240
-Node: Finding The Bug843624
-Node: List of Debugger Commands850099
-Node: Breakpoint Control851432
-Node: Debugger Execution Control855128
-Node: Viewing And Changing Data858492
-Node: Execution Stack861870
-Node: Debugger Info863507
-Node: Miscellaneous Debugger Commands867524
-Node: Readline Support872553
-Node: Limitations873445
-Node: Debugging Summary875559
-Node: Arbitrary Precision Arithmetic876727
-Node: Computer Arithmetic878143
-Ref: table-numeric-ranges881741
-Ref: Computer Arithmetic-Footnote-1882600
-Node: Math Definitions882657
-Ref: table-ieee-formats885945
-Ref: Math Definitions-Footnote-1886549
-Node: MPFR features886654
-Node: FP Math Caution888325
-Ref: FP Math Caution-Footnote-1889375
-Node: Inexactness of computations889744
-Node: Inexact representation890703
-Node: Comparing FP Values892060
-Node: Errors accumulate893142
-Node: Getting Accuracy894575
-Node: Try To Round897237
-Node: Setting precision898136
-Ref: table-predefined-precision-strings898820
-Node: Setting the rounding mode900609
-Ref: table-gawk-rounding-modes900973
-Ref: Setting the rounding mode-Footnote-1904428
-Node: Arbitrary Precision Integers904607
-Ref: Arbitrary Precision Integers-Footnote-1909506
-Node: POSIX Floating Point Problems909655
-Ref: POSIX Floating Point Problems-Footnote-1913528
-Node: Floating point summary913566
-Node: Dynamic Extensions915760
-Node: Extension Intro917312
-Node: Plugin License918578
-Node: Extension Mechanism Outline919375
-Ref: figure-load-extension919803
-Ref: figure-register-new-function921283
-Ref: figure-call-new-function922287
-Node: Extension API Description924273
-Node: Extension API Functions Introduction925723
-Node: General Data Types930547
-Ref: General Data Types-Footnote-1936286
-Node: Memory Allocation Functions936585
-Ref: Memory Allocation Functions-Footnote-1939424
-Node: Constructor Functions939520
-Node: Registration Functions941254
-Node: Extension Functions941939
-Node: Exit Callback Functions944236
-Node: Extension Version String945484
-Node: Input Parsers946149
-Node: Output Wrappers956028
-Node: Two-way processors960543
-Node: Printing Messages962747
-Ref: Printing Messages-Footnote-1963823
-Node: Updating `ERRNO'963975
-Node: Requesting Values964715
-Ref: table-value-types-returned965443
-Node: Accessing Parameters966400
-Node: Symbol Table Access967631
-Node: Symbol table by name968145
-Node: Symbol table by cookie970126
-Ref: Symbol table by cookie-Footnote-1974270
-Node: Cached values974333
-Ref: Cached values-Footnote-1977832
-Node: Array Manipulation977923
-Ref: Array Manipulation-Footnote-1979021
-Node: Array Data Types979058
-Ref: Array Data Types-Footnote-1981713
-Node: Array Functions981805
-Node: Flattening Arrays985659
-Node: Creating Arrays992551
-Node: Extension API Variables997322
-Node: Extension Versioning997958
-Node: Extension API Informational Variables999859
-Node: Extension API Boilerplate1000924
-Node: Finding Extensions1004733
-Node: Extension Example1005293
-Node: Internal File Description1006065
-Node: Internal File Ops1010132
-Ref: Internal File Ops-Footnote-11021802
-Node: Using Internal File Ops1021942
-Ref: Using Internal File Ops-Footnote-11024325
-Node: Extension Samples1024598
-Node: Extension Sample File Functions1026124
-Node: Extension Sample Fnmatch1033762
-Node: Extension Sample Fork1035253
-Node: Extension Sample Inplace1036468
-Node: Extension Sample Ord1038143
-Node: Extension Sample Readdir1038979
-Ref: table-readdir-file-types1039855
-Node: Extension Sample Revout1040666
-Node: Extension Sample Rev2way1041256
-Node: Extension Sample Read write array1041996
-Node: Extension Sample Readfile1043936
-Node: Extension Sample Time1045031
-Node: Extension Sample API Tests1046380
-Node: gawkextlib1046871
-Node: Extension summary1049529
-Node: Extension Exercises1053218
-Node: Language History1053940
-Node: V7/SVR3.11055596
-Node: SVR41057777
-Node: POSIX1059222
-Node: BTL1060611
-Node: POSIX/GNU1061345
-Node: Feature History1066969
-Node: Common Extensions1080067
-Node: Ranges and Locales1081391
-Ref: Ranges and Locales-Footnote-11086009
-Ref: Ranges and Locales-Footnote-21086036
-Ref: Ranges and Locales-Footnote-31086270
-Node: Contributors1086491
-Node: History summary1092032
-Node: Installation1093402
-Node: Gawk Distribution1094348
-Node: Getting1094832
-Node: Extracting1095655
-Node: Distribution contents1097290
-Node: Unix Installation1103355
-Node: Quick Installation1104038
-Node: Shell Startup Files1106449
-Node: Additional Configuration Options1107528
-Node: Configuration Philosophy1109267
-Node: Non-Unix Installation1111636
-Node: PC Installation1112094
-Node: PC Binary Installation1113413
-Node: PC Compiling1115261
-Ref: PC Compiling-Footnote-11118282
-Node: PC Testing1118391
-Node: PC Using1119567
-Node: Cygwin1123682
-Node: MSYS1124505
-Node: VMS Installation1125005
-Node: VMS Compilation1125797
-Ref: VMS Compilation-Footnote-11127019
-Node: VMS Dynamic Extensions1127077
-Node: VMS Installation Details1128761
-Node: VMS Running1131013
-Node: VMS GNV1133849
-Node: VMS Old Gawk1134583
-Node: Bugs1135053
-Node: Other Versions1138936
-Node: Installation summary1145364
-Node: Notes1146420
-Node: Compatibility Mode1147285
-Node: Additions1148067
-Node: Accessing The Source1148992
-Node: Adding Code1150428
-Node: New Ports1156593
-Node: Derived Files1161075
-Ref: Derived Files-Footnote-11166550
-Ref: Derived Files-Footnote-21166584
-Ref: Derived Files-Footnote-31167180
-Node: Future Extensions1167294
-Node: Implementation Limitations1167900
-Node: Extension Design1169148
-Node: Old Extension Problems1170302
-Ref: Old Extension Problems-Footnote-11171819
-Node: Extension New Mechanism Goals1171876
-Ref: Extension New Mechanism Goals-Footnote-11175236
-Node: Extension Other Design Decisions1175425
-Node: Extension Future Growth1177533
-Node: Old Extension Mechanism1178369
-Node: Notes summary1180131
-Node: Basic Concepts1181317
-Node: Basic High Level1181998
-Ref: figure-general-flow1182270
-Ref: figure-process-flow1182869
-Ref: Basic High Level-Footnote-11186098
-Node: Basic Data Typing1186283
-Node: Glossary1189611
-Node: Copying1214769
-Node: GNU Free Documentation License1252325
-Node: Index1277461
+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-161808
+Node: Conventions61908
+Node: Manual History64246
+Ref: Manual History-Footnote-167228
+Ref: Manual History-Footnote-267269
+Node: How To Contribute67343
+Node: Acknowledgments68472
+Node: Getting Started73277
+Node: Running gawk75710
+Node: One-shot76900
+Node: Read Terminal78148
+Node: Long80175
+Node: Executable Scripts81691
+Ref: Executable Scripts-Footnote-184480
+Node: Comments84583
+Node: Quoting87065
+Node: DOS Quoting92589
+Node: Sample Data Files93264
+Node: Very Simple95859
+Node: Two Rules100757
+Node: More Complex102643
+Node: Statements/Lines105505
+Ref: Statements/Lines-Footnote-1109960
+Node: Other Features110225
+Node: When111156
+Ref: When-Footnote-1112910
+Node: Intro Summary112975
+Node: Invoking Gawk113858
+Node: Command Line115372
+Node: Options116170
+Ref: Options-Footnote-1131974
+Ref: Options-Footnote-2132203
+Node: Other Arguments132228
+Node: Naming Standard Input135176
+Node: Environment Variables136269
+Node: AWKPATH Variable136827
+Ref: AWKPATH Variable-Footnote-1140240
+Ref: AWKPATH Variable-Footnote-2140285
+Node: AWKLIBPATH Variable140545
+Node: Other Environment Variables141801
+Node: Exit Status145289
+Node: Include Files145965
+Node: Loading Shared Libraries149562
+Node: Obsolete150989
+Node: Undocumented151686
+Node: Invoking Summary151953
+Node: Regexp153617
+Node: Regexp Usage155071
+Node: Escape Sequences157108
+Node: Regexp Operators163349
+Ref: Regexp Operators-Footnote-1170775
+Ref: Regexp Operators-Footnote-2170922
+Node: Bracket Expressions171020
+Ref: table-char-classes173035
+Node: Leftmost Longest175959
+Node: Computed Regexps177261
+Node: GNU Regexp Operators180658
+Node: Case-sensitivity184331
+Ref: Case-sensitivity-Footnote-1187216
+Ref: Case-sensitivity-Footnote-2187451
+Node: Regexp Summary187559
+Node: Reading Files189026
+Node: Records191189
+Node: awk split records191922
+Node: gawk split records196837
+Ref: gawk split records-Footnote-1201381
+Node: Fields201418
+Ref: Fields-Footnote-1204194
+Node: Nonconstant Fields204280
+Ref: Nonconstant Fields-Footnote-1206523
+Node: Changing Fields206727
+Node: Field Separators212656
+Node: Default Field Splitting215361
+Node: Regexp Field Splitting216478
+Node: Single Character Fields219828
+Node: Command Line Field Separator220887
+Node: Full Line Fields224099
+Ref: Full Line Fields-Footnote-1225616
+Ref: Full Line Fields-Footnote-2225662
+Node: Field Splitting Summary225763
+Node: Constant Size227837
+Node: Splitting By Content232426
+Ref: Splitting By Content-Footnote-1236420
+Node: Multiple Line236583
+Ref: Multiple Line-Footnote-1242469
+Node: Getline242648
+Node: Plain Getline245132
+Node: Getline/Variable247772
+Node: Getline/File248920
+Node: Getline/Variable/File250304
+Ref: Getline/Variable/File-Footnote-1251907
+Node: Getline/Pipe251994
+Node: Getline/Variable/Pipe254677
+Node: Getline/Coprocess255808
+Node: Getline/Variable/Coprocess257060
+Node: Getline Notes257799
+Node: Getline Summary260591
+Ref: table-getline-variants261003
+Node: Read Timeout261832
+Ref: Read Timeout-Footnote-1265723
+Node: Retrying Input265781
+Node: Command-line directories266976
+Node: Input Summary267883
+Node: Input Exercises271184
+Node: Printing271912
+Node: Print273689
+Node: Print Examples275146
+Node: Output Separators277925
+Node: OFMT279943
+Node: Printf281297
+Node: Basic Printf282082
+Node: Control Letters283652
+Node: Format Modifiers287635
+Node: Printf Examples293644
+Node: Redirection296130
+Node: Special FD302971
+Ref: Special FD-Footnote-1306131
+Node: Special Files306205
+Node: Other Inherited Files306822
+Node: Special Network307822
+Node: Special Caveats308684
+Node: Close Files And Pipes309635
+Ref: Close Files And Pipes-Footnote-1316817
+Ref: Close Files And Pipes-Footnote-2316965
+Node: Output Summary317115
+Node: Output Exercises318113
+Node: Expressions318793
+Node: Values319978
+Node: Constants320656
+Node: Scalar Constants321347
+Ref: Scalar Constants-Footnote-1322206
+Node: Nondecimal-numbers322456
+Node: Regexp Constants325474
+Node: Using Constant Regexps325999
+Node: Variables329142
+Node: Using Variables329797
+Node: Assignment Options331708
+Node: Conversion333583
+Node: Strings And Numbers334107
+Ref: Strings And Numbers-Footnote-1337172
+Node: Locale influences conversions337281
+Ref: table-locale-affects340028
+Node: All Operators340616
+Node: Arithmetic Ops341246
+Node: Concatenation343751
+Ref: Concatenation-Footnote-1346570
+Node: Assignment Ops346676
+Ref: table-assign-ops351655
+Node: Increment Ops352927
+Node: Truth Values and Conditions356365
+Node: Truth Values357450
+Node: Typing and Comparison358499
+Node: Variable Typing359309
+Node: Comparison Operators362962
+Ref: table-relational-ops363372
+Node: POSIX String Comparison366867
+Ref: POSIX String Comparison-Footnote-1367939
+Node: Boolean Ops368077
+Ref: Boolean Ops-Footnote-1372556
+Node: Conditional Exp372647
+Node: Function Calls374374
+Node: Precedence378254
+Node: Locales381915
+Node: Expressions Summary383547
+Node: Patterns and Actions386107
+Node: Pattern Overview387227
+Node: Regexp Patterns388906
+Node: Expression Patterns389449
+Node: Ranges393159
+Node: BEGIN/END396265
+Node: Using BEGIN/END397026
+Ref: Using BEGIN/END-Footnote-1399760
+Node: I/O And BEGIN/END399866
+Node: BEGINFILE/ENDFILE402180
+Node: Empty405081
+Node: Using Shell Variables405398
+Node: Action Overview407671
+Node: Statements409997
+Node: If Statement411845
+Node: While Statement413340
+Node: Do Statement415369
+Node: For Statement416513
+Node: Switch Statement419670
+Node: Break Statement422052
+Node: Continue Statement424093
+Node: Next Statement425920
+Node: Nextfile Statement428301
+Node: Exit Statement430931
+Node: Built-in Variables433334
+Node: User-modified434467
+Ref: User-modified-Footnote-1442148
+Node: Auto-set442210
+Ref: Auto-set-Footnote-1456426
+Ref: Auto-set-Footnote-2456631
+Node: ARGC and ARGV456687
+Node: Pattern Action Summary460905
+Node: Arrays463332
+Node: Array Basics464661
+Node: Array Intro465505
+Ref: figure-array-elements467469
+Ref: Array Intro-Footnote-1469995
+Node: Reference to Elements470123
+Node: Assigning Elements472575
+Node: Array Example473066
+Node: Scanning an Array474824
+Node: Controlling Scanning477840
+Ref: Controlling Scanning-Footnote-1483036
+Node: Numeric Array Subscripts483352
+Node: Uninitialized Subscripts485537
+Node: Delete487154
+Ref: Delete-Footnote-1489897
+Node: Multidimensional489954
+Node: Multiscanning493051
+Node: Arrays of Arrays494640
+Node: Arrays Summary499399
+Node: Functions501491
+Node: Built-in502390
+Node: Calling Built-in503468
+Node: Numeric Functions505459
+Ref: Numeric Functions-Footnote-1510278
+Ref: Numeric Functions-Footnote-2510635
+Ref: Numeric Functions-Footnote-3510683
+Node: String Functions510955
+Ref: String Functions-Footnote-1534430
+Ref: String Functions-Footnote-2534559
+Ref: String Functions-Footnote-3534807
+Node: Gory Details534894
+Ref: table-sub-escapes536675
+Ref: table-sub-proposed538195
+Ref: table-posix-sub539559
+Ref: table-gensub-escapes541095
+Ref: Gory Details-Footnote-1541927
+Node: I/O Functions542078
+Ref: I/O Functions-Footnote-1549296
+Node: Time Functions549443
+Ref: Time Functions-Footnote-1559931
+Ref: Time Functions-Footnote-2559999
+Ref: Time Functions-Footnote-3560157
+Ref: Time Functions-Footnote-4560268
+Ref: Time Functions-Footnote-5560380
+Ref: Time Functions-Footnote-6560607
+Node: Bitwise Functions560873
+Ref: table-bitwise-ops561435
+Ref: Bitwise Functions-Footnote-1565744
+Node: Type Functions565913
+Node: I18N Functions567064
+Node: User-defined568709
+Node: Definition Syntax569514
+Ref: Definition Syntax-Footnote-1574921
+Node: Function Example574992
+Ref: Function Example-Footnote-1577911
+Node: Function Caveats577933
+Node: Calling A Function578451
+Node: Variable Scope579409
+Node: Pass By Value/Reference582397
+Node: Return Statement585892
+Node: Dynamic Typing588873
+Node: Indirect Calls589802
+Ref: Indirect Calls-Footnote-1601104
+Node: Functions Summary601232
+Node: Library Functions603934
+Ref: Library Functions-Footnote-1607543
+Ref: Library Functions-Footnote-2607686
+Node: Library Names607857
+Ref: Library Names-Footnote-1611311
+Ref: Library Names-Footnote-2611534
+Node: General Functions611620
+Node: Strtonum Function612723
+Node: Assert Function615745
+Node: Round Function619069
+Node: Cliff Random Function620610
+Node: Ordinal Functions621626
+Ref: Ordinal Functions-Footnote-1624689
+Ref: Ordinal Functions-Footnote-2624941
+Node: Join Function625152
+Ref: Join Function-Footnote-1626921
+Node: Getlocaltime Function627121
+Node: Readfile Function630865
+Node: Shell Quoting632835
+Node: Data File Management634236
+Node: Filetrans Function634868
+Node: Rewind Function638924
+Node: File Checking640311
+Ref: File Checking-Footnote-1641643
+Node: Empty Files641844
+Node: Ignoring Assigns643823
+Node: Getopt Function645374
+Ref: Getopt Function-Footnote-1656836
+Node: Passwd Functions657036
+Ref: Passwd Functions-Footnote-1665873
+Node: Group Functions665961
+Ref: Group Functions-Footnote-1673855
+Node: Walking Arrays674068
+Node: Library Functions Summary675671
+Node: Library Exercises677072
+Node: Sample Programs678352
+Node: Running Examples679122
+Node: Clones679850
+Node: Cut Program681074
+Node: Egrep Program690793
+Ref: Egrep Program-Footnote-1698291
+Node: Id Program698401
+Node: Split Program702046
+Ref: Split Program-Footnote-1705494
+Node: Tee Program705622
+Node: Uniq Program708411
+Node: Wc Program715830
+Ref: Wc Program-Footnote-1720080
+Node: Miscellaneous Programs720174
+Node: Dupword Program721387
+Node: Alarm Program723418
+Node: Translate Program728222
+Ref: Translate Program-Footnote-1732787
+Node: Labels Program733057
+Ref: Labels Program-Footnote-1736408
+Node: Word Sorting736492
+Node: History Sorting740563
+Node: Extract Program742399
+Node: Simple Sed749924
+Node: Igawk Program752992
+Ref: Igawk Program-Footnote-1767316
+Ref: Igawk Program-Footnote-2767517
+Ref: Igawk Program-Footnote-3767639
+Node: Anagram Program767754
+Node: Signature Program770811
+Node: Programs Summary772058
+Node: Programs Exercises773251
+Ref: Programs Exercises-Footnote-1777382
+Node: Advanced Features777473
+Node: Nondecimal Data779421
+Node: Array Sorting781011
+Node: Controlling Array Traversal781708
+Ref: Controlling Array Traversal-Footnote-1790041
+Node: Array Sorting Functions790159
+Ref: Array Sorting Functions-Footnote-1794048
+Node: Two-way I/O794244
+Ref: Two-way I/O-Footnote-1799189
+Ref: Two-way I/O-Footnote-2799375
+Node: TCP/IP Networking799457
+Node: Profiling802330
+Node: Advanced Features Summary810607
+Node: Internationalization812540
+Node: I18N and L10N814020
+Node: Explaining gettext814706
+Ref: Explaining gettext-Footnote-1819731
+Ref: Explaining gettext-Footnote-2819915
+Node: Programmer i18n820080
+Ref: Programmer i18n-Footnote-1824946
+Node: Translator i18n824995
+Node: String Extraction825789
+Ref: String Extraction-Footnote-1826920
+Node: Printf Ordering827006
+Ref: Printf Ordering-Footnote-1829792
+Node: I18N Portability829856
+Ref: I18N Portability-Footnote-1832311
+Node: I18N Example832374
+Ref: I18N Example-Footnote-1835177
+Node: Gawk I18N835249
+Node: I18N Summary835887
+Node: Debugger837226
+Node: Debugging838248
+Node: Debugging Concepts838689
+Node: Debugging Terms840542
+Node: Awk Debugging843114
+Node: Sample Debugging Session844008
+Node: Debugger Invocation844528
+Node: Finding The Bug845912
+Node: List of Debugger Commands852387
+Node: Breakpoint Control853720
+Node: Debugger Execution Control857416
+Node: Viewing And Changing Data860780
+Node: Execution Stack864158
+Node: Debugger Info865795
+Node: Miscellaneous Debugger Commands869812
+Node: Readline Support874841
+Node: Limitations875733
+Node: Debugging Summary877847
+Node: Arbitrary Precision Arithmetic879015
+Node: Computer Arithmetic880431
+Ref: table-numeric-ranges884029
+Ref: Computer Arithmetic-Footnote-1884888
+Node: Math Definitions884945
+Ref: table-ieee-formats888233
+Ref: Math Definitions-Footnote-1888837
+Node: MPFR features888942
+Node: FP Math Caution890613
+Ref: FP Math Caution-Footnote-1891663
+Node: Inexactness of computations892032
+Node: Inexact representation892991
+Node: Comparing FP Values894348
+Node: Errors accumulate895430
+Node: Getting Accuracy896863
+Node: Try To Round899525
+Node: Setting precision900424
+Ref: table-predefined-precision-strings901108
+Node: Setting the rounding mode902897
+Ref: table-gawk-rounding-modes903261
+Ref: Setting the rounding mode-Footnote-1906716
+Node: Arbitrary Precision Integers906895
+Ref: Arbitrary Precision Integers-Footnote-1911794
+Node: POSIX Floating Point Problems911943
+Ref: POSIX Floating Point Problems-Footnote-1915816
+Node: Floating point summary915854
+Node: Dynamic Extensions918048
+Node: Extension Intro919600
+Node: Plugin License920866
+Node: Extension Mechanism Outline921663
+Ref: figure-load-extension922091
+Ref: figure-register-new-function923571
+Ref: figure-call-new-function924575
+Node: Extension API Description926561
+Node: Extension API Functions Introduction928095
+Node: General Data Types932967
+Ref: General Data Types-Footnote-1938706
+Node: Memory Allocation Functions939005
+Ref: Memory Allocation Functions-Footnote-1941844
+Node: Constructor Functions941940
+Node: Registration Functions943674
+Node: Extension Functions944359
+Node: Exit Callback Functions946656
+Node: Extension Version String947904
+Node: Input Parsers948569
+Node: Output Wrappers958448
+Node: Two-way processors962963
+Node: Printing Messages965167
+Ref: Printing Messages-Footnote-1966243
+Node: Updating `ERRNO'966395
+Node: Requesting Values967135
+Ref: table-value-types-returned967863
+Node: Accessing Parameters968820
+Node: Symbol Table Access970051
+Node: Symbol table by name970565
+Node: Symbol table by cookie972546
+Ref: Symbol table by cookie-Footnote-1976690
+Node: Cached values976753
+Ref: Cached values-Footnote-1980252
+Node: Array Manipulation980343
+Ref: Array Manipulation-Footnote-1981433
+Node: Array Data Types981470
+Ref: Array Data Types-Footnote-1984125
+Node: Array Functions984217
+Node: Flattening Arrays988071
+Node: Creating Arrays994963
+Node: Redirection API999734
+Node: Extension API Variables1002505
+Node: Extension Versioning1003138
+Node: Extension API Informational Variables1005039
+Node: Extension API Boilerplate1006104
+Node: Finding Extensions1009913
+Node: Extension Example1010473
+Node: Internal File Description1011245
+Node: Internal File Ops1015312
+Ref: Internal File Ops-Footnote-11026982
+Node: Using Internal File Ops1027122
+Ref: Using Internal File Ops-Footnote-11029505
+Node: Extension Samples1029778
+Node: Extension Sample File Functions1031304
+Node: Extension Sample Fnmatch1038942
+Node: Extension Sample Fork1040433
+Node: Extension Sample Inplace1041648
+Node: Extension Sample Ord1043323
+Node: Extension Sample Readdir1044159
+Ref: table-readdir-file-types1045035
+Node: Extension Sample Revout1045846
+Node: Extension Sample Rev2way1046436
+Node: Extension Sample Read write array1047176
+Node: Extension Sample Readfile1049116
+Node: Extension Sample Time1050211
+Node: Extension Sample API Tests1051560
+Node: gawkextlib1052051
+Node: Extension summary1054709
+Node: Extension Exercises1058398
+Node: Language History1059120
+Node: V7/SVR3.11060776
+Node: SVR41062957
+Node: POSIX1064402
+Node: BTL1065791
+Node: POSIX/GNU1066525
+Node: Feature History1072149
+Node: Common Extensions1085247
+Node: Ranges and Locales1086571
+Ref: Ranges and Locales-Footnote-11091189
+Ref: Ranges and Locales-Footnote-21091216
+Ref: Ranges and Locales-Footnote-31091450
+Node: Contributors1091671
+Node: History summary1097212
+Node: Installation1098582
+Node: Gawk Distribution1099528
+Node: Getting1100012
+Node: Extracting1100835
+Node: Distribution contents1102470
+Node: Unix Installation1108535
+Node: Quick Installation1109218
+Node: Shell Startup Files1111629
+Node: Additional Configuration Options1112708
+Node: Configuration Philosophy1114447
+Node: Non-Unix Installation1116816
+Node: PC Installation1117274
+Node: PC Binary Installation1118593
+Node: PC Compiling1120441
+Ref: PC Compiling-Footnote-11123462
+Node: PC Testing1123571
+Node: PC Using1124747
+Node: Cygwin1128862
+Node: MSYS1129685
+Node: VMS Installation1130185
+Node: VMS Compilation1130977
+Ref: VMS Compilation-Footnote-11132199
+Node: VMS Dynamic Extensions1132257
+Node: VMS Installation Details1133941
+Node: VMS Running1136193
+Node: VMS GNV1139029
+Node: VMS Old Gawk1139763
+Node: Bugs1140233
+Node: Other Versions1144116
+Node: Installation summary1150544
+Node: Notes1151600
+Node: Compatibility Mode1152465
+Node: Additions1153247
+Node: Accessing The Source1154172
+Node: Adding Code1155608
+Node: New Ports1161773
+Node: Derived Files1166255
+Ref: Derived Files-Footnote-11171730
+Ref: Derived Files-Footnote-21171764
+Ref: Derived Files-Footnote-31172360
+Node: Future Extensions1172474
+Node: Implementation Limitations1173080
+Node: Extension Design1174328
+Node: Old Extension Problems1175482
+Ref: Old Extension Problems-Footnote-11176999
+Node: Extension New Mechanism Goals1177056
+Ref: Extension New Mechanism Goals-Footnote-11180416
+Node: Extension Other Design Decisions1180605
+Node: Extension Future Growth1182713
+Node: Old Extension Mechanism1183549
+Node: Notes summary1185311
+Node: Basic Concepts1186497
+Node: Basic High Level1187178
+Ref: figure-general-flow1187450
+Ref: figure-process-flow1188049
+Ref: Basic High Level-Footnote-11191278
+Node: Basic Data Typing1191463
+Node: Glossary1194791
+Node: Copying1219949
+Node: GNU Free Documentation License1257505
+Node: Index1282641

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index facb8b0a..cbc0bd04 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
@@ -6337,6 +6339,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.
@@ -8144,6 +8147,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.
@@ -8796,7 +8804,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
@@ -8806,6 +8815,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
@@ -14944,6 +14982,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}
@@ -15012,6 +15055,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.
@@ -15151,6 +15198,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}.
@@ -31730,6 +31782,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
@@ -31805,6 +31858,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:
@@ -33769,6 +33826,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 87655ef7..95ed8586 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
@@ -6121,6 +6123,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.
@@ -7745,6 +7748,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.
@@ -8397,7 +8405,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
@@ -8407,6 +8416,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
@@ -14273,6 +14311,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}
@@ -14341,6 +14384,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.
@@ -14480,6 +14527,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}.
@@ -30823,6 +30875,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
@@ -30898,6 +30951,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:
@@ -32862,6 +32919,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 06f31929..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,15 +788,16 @@ 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) {
elem->parent_array = array;
elem->vname = estrdup(index->str_value.str,
index->str_value.len);
- make_aname(elem);
}
+ if (array->astore != NULL)
+ (*array->astore)(array, tmp);
+ unref(tmp);
return awk_true;
}
@@ -1035,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.
*/
@@ -1120,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