diff options
-rw-r--r-- | ChangeLog | 176 | ||||
-rw-r--r-- | awk.h | 2 | ||||
-rw-r--r-- | awkgram.c | 721 | ||||
-rw-r--r-- | awkgram.y | 3 | ||||
-rw-r--r-- | configh.in | 6 | ||||
-rwxr-xr-x | configure | 5 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | doc/ChangeLog | 19 | ||||
-rw-r--r-- | doc/gawk.1 | 45 | ||||
-rw-r--r-- | doc/gawk.info | 1340 | ||||
-rw-r--r-- | doc/gawk.texi | 115 | ||||
-rw-r--r-- | doc/gawktexi.in | 115 | ||||
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | extension/ChangeLog | 170 | ||||
-rw-r--r-- | extension/testext.c | 193 | ||||
-rw-r--r-- | gawkapi.c | 97 | ||||
-rw-r--r-- | gawkapi.h | 40 | ||||
-rw-r--r-- | io.c | 160 | ||||
-rw-r--r-- | test/ChangeLog | 32 | ||||
-rw-r--r-- | test/Makefile.am | 31 | ||||
-rw-r--r-- | test/Makefile.in | 36 | ||||
-rw-r--r-- | test/Maketests | 5 | ||||
-rw-r--r-- | test/defvar.awk | 3 | ||||
-rw-r--r-- | test/defvar.ok | 5 | ||||
-rw-r--r-- | test/errno.awk | 10 | ||||
-rw-r--r-- | test/errno.in | 3 | ||||
-rw-r--r-- | test/errno.ok | 3 | ||||
-rw-r--r-- | test/getfile.awk | 35 | ||||
-rw-r--r-- | test/getfile.ok | 17 | ||||
-rw-r--r-- | test/testext.ok | 6 | ||||
-rw-r--r-- | test/timeout.awk | 26 | ||||
-rw-r--r-- | test/timeout.ok | 12 |
32 files changed, 2424 insertions, 1016 deletions
@@ -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 @@ -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); @@ -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; @@ -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; @@ -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 @@ -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. @@ -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 @@ -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); @@ -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 */ @@ -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)) @@ -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 |