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 | 1342 | ||||
-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 | 96 | ||||
-rw-r--r-- | gawkapi.h | 40 | ||||
-rw-r--r-- | io.c | 161 | ||||
-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, 2426 insertions, 1016 deletions
@@ -174,6 +174,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. @@ -192,6 +208,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 @@ -334,6 +403,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. @@ -1502,6 +1601,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 @@ -1512,6 +1650,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, bool failure_fatal); +extern struct redirect *redirect_string(const char *redir_exp_str, size_t redir_exp_len, bool not_string_flag, int redirtype, int *errflg, int extfd, bool failure_fatal); extern NODE *do_close(int nargs); extern int flush_io(void); extern int close_io(bool *stdio_problem); @@ -1503,6 +1504,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); @@ -184,6 +184,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; @@ -202,7 +203,7 @@ extern double fmod(double x, double y); #define YYSTYPE INSTRUCTION * -#line 206 "awkgram.c" /* yacc.c:339 */ +#line 207 "awkgram.c" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -356,7 +357,7 @@ int yyparse (void); /* Copy the second part of user declarations. */ -#line 360 "awkgram.c" /* yacc.c:358 */ +#line 361 "awkgram.c" /* yacc.c:358 */ #ifdef short # undef short @@ -658,25 +659,25 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 205, 205, 207, 212, 213, 217, 229, 234, 245, - 251, 257, 266, 274, 276, 281, 289, 291, 297, 305, - 315, 345, 359, 373, 381, 392, 404, 406, 408, 414, - 422, 423, 427, 462, 461, 495, 497, 502, 508, 536, - 541, 542, 546, 548, 550, 557, 647, 689, 731, 844, - 851, 858, 868, 877, 886, 895, 906, 922, 921, 945, - 957, 957, 1055, 1055, 1088, 1118, 1124, 1125, 1131, 1132, - 1139, 1144, 1156, 1170, 1172, 1180, 1185, 1187, 1195, 1197, - 1206, 1207, 1215, 1220, 1220, 1231, 1235, 1243, 1244, 1247, - 1249, 1254, 1255, 1264, 1265, 1270, 1275, 1281, 1283, 1285, - 1292, 1293, 1299, 1300, 1305, 1307, 1312, 1314, 1322, 1327, - 1336, 1343, 1345, 1347, 1363, 1373, 1380, 1382, 1387, 1389, - 1391, 1399, 1401, 1406, 1408, 1413, 1415, 1417, 1467, 1469, - 1471, 1473, 1475, 1477, 1479, 1481, 1495, 1500, 1505, 1530, - 1536, 1538, 1540, 1542, 1544, 1546, 1551, 1555, 1587, 1589, - 1595, 1601, 1614, 1615, 1616, 1621, 1626, 1630, 1634, 1649, - 1662, 1667, 1704, 1733, 1734, 1740, 1741, 1746, 1748, 1755, - 1772, 1789, 1791, 1798, 1803, 1811, 1821, 1833, 1842, 1846, - 1850, 1854, 1858, 1862, 1865, 1867, 1871, 1875, 1879 + 0, 206, 206, 208, 213, 214, 218, 230, 235, 246, + 252, 258, 267, 275, 277, 282, 290, 292, 298, 306, + 316, 346, 360, 374, 382, 393, 405, 407, 409, 415, + 423, 424, 428, 463, 462, 496, 498, 503, 509, 537, + 542, 543, 547, 549, 551, 558, 648, 690, 732, 845, + 852, 859, 869, 878, 887, 896, 907, 923, 922, 946, + 958, 958, 1056, 1056, 1089, 1119, 1125, 1126, 1132, 1133, + 1140, 1145, 1157, 1171, 1173, 1181, 1186, 1188, 1196, 1198, + 1207, 1208, 1216, 1221, 1221, 1232, 1236, 1244, 1245, 1248, + 1250, 1255, 1256, 1265, 1266, 1271, 1276, 1282, 1284, 1286, + 1293, 1294, 1300, 1301, 1306, 1308, 1313, 1315, 1323, 1328, + 1337, 1344, 1346, 1348, 1364, 1374, 1381, 1383, 1388, 1390, + 1392, 1400, 1402, 1407, 1409, 1414, 1416, 1418, 1468, 1470, + 1472, 1474, 1476, 1478, 1480, 1482, 1496, 1501, 1506, 1531, + 1537, 1539, 1541, 1543, 1545, 1547, 1552, 1556, 1588, 1590, + 1596, 1602, 1615, 1616, 1617, 1622, 1627, 1631, 1635, 1650, + 1663, 1668, 1705, 1734, 1735, 1741, 1742, 1747, 1749, 1756, + 1773, 1790, 1792, 1799, 1804, 1812, 1822, 1834, 1843, 1847, + 1851, 1855, 1859, 1863, 1866, 1868, 1872, 1876, 1880 }; #endif @@ -1849,24 +1850,24 @@ yyreduce: switch (yyn) { case 3: -#line 208 "awkgram.y" /* yacc.c:1646 */ +#line 209 "awkgram.y" /* yacc.c:1646 */ { rule = 0; yyerrok; } -#line 1858 "awkgram.c" /* yacc.c:1646 */ +#line 1859 "awkgram.c" /* yacc.c:1646 */ break; case 5: -#line 214 "awkgram.y" /* yacc.c:1646 */ +#line 215 "awkgram.y" /* yacc.c:1646 */ { next_sourcefile(); } -#line 1866 "awkgram.c" /* yacc.c:1646 */ +#line 1867 "awkgram.c" /* yacc.c:1646 */ break; case 6: -#line 218 "awkgram.y" /* yacc.c:1646 */ +#line 219 "awkgram.y" /* yacc.c:1646 */ { rule = 0; /* @@ -1875,20 +1876,20 @@ yyreduce: */ /* yyerrok; */ } -#line 1879 "awkgram.c" /* yacc.c:1646 */ +#line 1880 "awkgram.c" /* yacc.c:1646 */ break; case 7: -#line 230 "awkgram.y" /* yacc.c:1646 */ +#line 231 "awkgram.y" /* yacc.c:1646 */ { (void) append_rule((yyvsp[-1]), (yyvsp[0])); first_rule = false; } -#line 1888 "awkgram.c" /* yacc.c:1646 */ +#line 1889 "awkgram.c" /* yacc.c:1646 */ break; case 8: -#line 235 "awkgram.y" /* yacc.c:1646 */ +#line 236 "awkgram.y" /* yacc.c:1646 */ { if (rule != Rule) { msg(_("%s blocks must have an action part"), ruletab[rule]); @@ -1899,41 +1900,41 @@ yyreduce: } else /* pattern rule with non-empty pattern */ (void) append_rule((yyvsp[-1]), NULL); } -#line 1903 "awkgram.c" /* yacc.c:1646 */ +#line 1904 "awkgram.c" /* yacc.c:1646 */ break; case 9: -#line 246 "awkgram.y" /* yacc.c:1646 */ +#line 247 "awkgram.y" /* yacc.c:1646 */ { in_function = NULL; (void) mk_function((yyvsp[-1]), (yyvsp[0])); yyerrok; } -#line 1913 "awkgram.c" /* yacc.c:1646 */ +#line 1914 "awkgram.c" /* yacc.c:1646 */ break; case 10: -#line 252 "awkgram.y" /* yacc.c:1646 */ +#line 253 "awkgram.y" /* yacc.c:1646 */ { want_source = false; at_seen = false; yyerrok; } -#line 1923 "awkgram.c" /* yacc.c:1646 */ +#line 1924 "awkgram.c" /* yacc.c:1646 */ break; case 11: -#line 258 "awkgram.y" /* yacc.c:1646 */ +#line 259 "awkgram.y" /* yacc.c:1646 */ { want_source = false; at_seen = false; yyerrok; } -#line 1933 "awkgram.c" /* yacc.c:1646 */ +#line 1934 "awkgram.c" /* yacc.c:1646 */ break; case 12: -#line 267 "awkgram.y" /* yacc.c:1646 */ +#line 268 "awkgram.y" /* yacc.c:1646 */ { if (include_source((yyvsp[0])) < 0) YYABORT; @@ -1941,23 +1942,23 @@ yyreduce: bcfree((yyvsp[0])); (yyval) = NULL; } -#line 1945 "awkgram.c" /* yacc.c:1646 */ +#line 1946 "awkgram.c" /* yacc.c:1646 */ break; case 13: -#line 275 "awkgram.y" /* yacc.c:1646 */ +#line 276 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 1951 "awkgram.c" /* yacc.c:1646 */ +#line 1952 "awkgram.c" /* yacc.c:1646 */ break; case 14: -#line 277 "awkgram.y" /* yacc.c:1646 */ +#line 278 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 1957 "awkgram.c" /* yacc.c:1646 */ +#line 1958 "awkgram.c" /* yacc.c:1646 */ break; case 15: -#line 282 "awkgram.y" /* yacc.c:1646 */ +#line 283 "awkgram.y" /* yacc.c:1646 */ { if (load_library((yyvsp[0])) < 0) YYABORT; @@ -1965,23 +1966,23 @@ yyreduce: bcfree((yyvsp[0])); (yyval) = NULL; } -#line 1969 "awkgram.c" /* yacc.c:1646 */ +#line 1970 "awkgram.c" /* yacc.c:1646 */ break; case 16: -#line 290 "awkgram.y" /* yacc.c:1646 */ +#line 291 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 1975 "awkgram.c" /* yacc.c:1646 */ +#line 1976 "awkgram.c" /* yacc.c:1646 */ break; case 17: -#line 292 "awkgram.y" /* yacc.c:1646 */ +#line 293 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 1981 "awkgram.c" /* yacc.c:1646 */ +#line 1982 "awkgram.c" /* yacc.c:1646 */ break; case 18: -#line 297 "awkgram.y" /* yacc.c:1646 */ +#line 298 "awkgram.y" /* yacc.c:1646 */ { rule = Rule; if (comment != NULL) { @@ -1990,11 +1991,11 @@ yyreduce: } else (yyval) = NULL; } -#line 1994 "awkgram.c" /* yacc.c:1646 */ +#line 1995 "awkgram.c" /* yacc.c:1646 */ break; case 19: -#line 306 "awkgram.y" /* yacc.c:1646 */ +#line 307 "awkgram.y" /* yacc.c:1646 */ { rule = Rule; if (comment != NULL) { @@ -2003,11 +2004,11 @@ yyreduce: } else (yyval) = (yyvsp[0]); } -#line 2007 "awkgram.c" /* yacc.c:1646 */ +#line 2008 "awkgram.c" /* yacc.c:1646 */ break; case 20: -#line 316 "awkgram.y" /* yacc.c:1646 */ +#line 317 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *tp; @@ -2037,11 +2038,11 @@ yyreduce: (yyval) = list_append(list_merge((yyvsp[-3]), (yyvsp[0])), tp); rule = Rule; } -#line 2041 "awkgram.c" /* yacc.c:1646 */ +#line 2042 "awkgram.c" /* yacc.c:1646 */ break; case 21: -#line 346 "awkgram.y" /* yacc.c:1646 */ +#line 347 "awkgram.y" /* yacc.c:1646 */ { static int begin_seen = 0; @@ -2055,11 +2056,11 @@ yyreduce: check_comment(); (yyval) = (yyvsp[0]); } -#line 2059 "awkgram.c" /* yacc.c:1646 */ +#line 2060 "awkgram.c" /* yacc.c:1646 */ break; case 22: -#line 360 "awkgram.y" /* yacc.c:1646 */ +#line 361 "awkgram.y" /* yacc.c:1646 */ { static int end_seen = 0; @@ -2073,11 +2074,11 @@ yyreduce: check_comment(); (yyval) = (yyvsp[0]); } -#line 2077 "awkgram.c" /* yacc.c:1646 */ +#line 2078 "awkgram.c" /* yacc.c:1646 */ break; case 23: -#line 374 "awkgram.y" /* yacc.c:1646 */ +#line 375 "awkgram.y" /* yacc.c:1646 */ { func_first = false; (yyvsp[0])->in_rule = rule = BEGINFILE; @@ -2085,11 +2086,11 @@ yyreduce: check_comment(); (yyval) = (yyvsp[0]); } -#line 2089 "awkgram.c" /* yacc.c:1646 */ +#line 2090 "awkgram.c" /* yacc.c:1646 */ break; case 24: -#line 382 "awkgram.y" /* yacc.c:1646 */ +#line 383 "awkgram.y" /* yacc.c:1646 */ { func_first = false; (yyvsp[0])->in_rule = rule = ENDFILE; @@ -2097,11 +2098,11 @@ yyreduce: check_comment(); (yyval) = (yyvsp[0]); } -#line 2101 "awkgram.c" /* yacc.c:1646 */ +#line 2102 "awkgram.c" /* yacc.c:1646 */ break; case 25: -#line 393 "awkgram.y" /* yacc.c:1646 */ +#line 394 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip; if ((yyvsp[-3]) == NULL) @@ -2110,42 +2111,42 @@ yyreduce: ip = (yyvsp[-3]); (yyval) = ip; } -#line 2114 "awkgram.c" /* yacc.c:1646 */ +#line 2115 "awkgram.c" /* yacc.c:1646 */ break; case 26: -#line 405 "awkgram.y" /* yacc.c:1646 */ +#line 406 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2120 "awkgram.c" /* yacc.c:1646 */ +#line 2121 "awkgram.c" /* yacc.c:1646 */ break; case 27: -#line 407 "awkgram.y" /* yacc.c:1646 */ +#line 408 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2126 "awkgram.c" /* yacc.c:1646 */ +#line 2127 "awkgram.c" /* yacc.c:1646 */ break; case 28: -#line 409 "awkgram.y" /* yacc.c:1646 */ +#line 410 "awkgram.y" /* yacc.c:1646 */ { yyerror(_("`%s' is a built-in function, it cannot be redefined"), tokstart); YYABORT; } -#line 2136 "awkgram.c" /* yacc.c:1646 */ +#line 2137 "awkgram.c" /* yacc.c:1646 */ break; case 29: -#line 415 "awkgram.y" /* yacc.c:1646 */ +#line 416 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); at_seen = false; } -#line 2145 "awkgram.c" /* yacc.c:1646 */ +#line 2146 "awkgram.c" /* yacc.c:1646 */ break; case 32: -#line 428 "awkgram.y" /* yacc.c:1646 */ +#line 429 "awkgram.y" /* yacc.c:1646 */ { /* * treat any comments between BOF and the first function @@ -2172,17 +2173,17 @@ yyreduce: /* $4 already free'd in install_function */ (yyval) = (yyvsp[-5]); } -#line 2176 "awkgram.c" /* yacc.c:1646 */ +#line 2177 "awkgram.c" /* yacc.c:1646 */ break; case 33: -#line 462 "awkgram.y" /* yacc.c:1646 */ +#line 463 "awkgram.y" /* yacc.c:1646 */ { want_regexp = true; } -#line 2182 "awkgram.c" /* yacc.c:1646 */ +#line 2183 "awkgram.c" /* yacc.c:1646 */ break; case 34: -#line 464 "awkgram.y" /* yacc.c:1646 */ +#line 465 "awkgram.y" /* yacc.c:1646 */ { NODE *n, *exp; char *re; @@ -2211,28 +2212,28 @@ yyreduce: (yyval)->opcode = Op_match_rec; (yyval)->memory = n; } -#line 2215 "awkgram.c" /* yacc.c:1646 */ +#line 2216 "awkgram.c" /* yacc.c:1646 */ break; case 35: -#line 496 "awkgram.y" /* yacc.c:1646 */ +#line 497 "awkgram.y" /* yacc.c:1646 */ { bcfree((yyvsp[0])); } -#line 2221 "awkgram.c" /* yacc.c:1646 */ +#line 2222 "awkgram.c" /* yacc.c:1646 */ break; case 37: -#line 502 "awkgram.y" /* yacc.c:1646 */ +#line 503 "awkgram.y" /* yacc.c:1646 */ { if (comment != NULL) { (yyval) = list_create(comment); comment = NULL; } else (yyval) = NULL; } -#line 2232 "awkgram.c" /* yacc.c:1646 */ +#line 2233 "awkgram.c" /* yacc.c:1646 */ break; case 38: -#line 509 "awkgram.y" /* yacc.c:1646 */ +#line 510 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[0]) == NULL) { if (comment == NULL) @@ -2260,40 +2261,40 @@ yyreduce: } yyerrok; } -#line 2264 "awkgram.c" /* yacc.c:1646 */ +#line 2265 "awkgram.c" /* yacc.c:1646 */ break; case 39: -#line 537 "awkgram.y" /* yacc.c:1646 */ +#line 538 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2270 "awkgram.c" /* yacc.c:1646 */ +#line 2271 "awkgram.c" /* yacc.c:1646 */ break; case 42: -#line 547 "awkgram.y" /* yacc.c:1646 */ +#line 548 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2276 "awkgram.c" /* yacc.c:1646 */ +#line 2277 "awkgram.c" /* yacc.c:1646 */ break; case 43: -#line 549 "awkgram.y" /* yacc.c:1646 */ +#line 550 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 2282 "awkgram.c" /* yacc.c:1646 */ +#line 2283 "awkgram.c" /* yacc.c:1646 */ break; case 44: -#line 551 "awkgram.y" /* yacc.c:1646 */ +#line 552 "awkgram.y" /* yacc.c:1646 */ { if (do_pretty_print) (yyval) = list_prepend((yyvsp[0]), instruction(Op_exec_count)); else (yyval) = (yyvsp[0]); } -#line 2293 "awkgram.c" /* yacc.c:1646 */ +#line 2294 "awkgram.c" /* yacc.c:1646 */ break; case 45: -#line 558 "awkgram.y" /* yacc.c:1646 */ +#line 559 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *dflt, *curr = NULL, *cexp, *cstmt; INSTRUCTION *ip, *nextc, *tbreak; @@ -2383,11 +2384,11 @@ yyreduce: break_allowed--; fix_break_continue(ip, tbreak, NULL); } -#line 2387 "awkgram.c" /* yacc.c:1646 */ +#line 2388 "awkgram.c" /* yacc.c:1646 */ break; case 46: -#line 648 "awkgram.y" /* yacc.c:1646 */ +#line 649 "awkgram.y" /* yacc.c:1646 */ { /* * ----------------- @@ -2429,11 +2430,11 @@ yyreduce: continue_allowed--; fix_break_continue(ip, tbreak, tcont); } -#line 2433 "awkgram.c" /* yacc.c:1646 */ +#line 2434 "awkgram.c" /* yacc.c:1646 */ break; case 47: -#line 690 "awkgram.y" /* yacc.c:1646 */ +#line 691 "awkgram.y" /* yacc.c:1646 */ { /* * ----------------- @@ -2475,11 +2476,11 @@ yyreduce: } /* else $1 and $4 are NULLs */ } -#line 2479 "awkgram.c" /* yacc.c:1646 */ +#line 2480 "awkgram.c" /* yacc.c:1646 */ break; case 48: -#line 732 "awkgram.y" /* yacc.c:1646 */ +#line 733 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip; char *var_name = (yyvsp[-5])->lextok; @@ -2592,44 +2593,44 @@ regular_loop: break_allowed--; continue_allowed--; } -#line 2596 "awkgram.c" /* yacc.c:1646 */ +#line 2597 "awkgram.c" /* yacc.c:1646 */ break; case 49: -#line 845 "awkgram.y" /* yacc.c:1646 */ +#line 846 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_for_loop((yyvsp[-11]), (yyvsp[-9]), (yyvsp[-6]), (yyvsp[-3]), (yyvsp[0])); break_allowed--; continue_allowed--; } -#line 2607 "awkgram.c" /* yacc.c:1646 */ +#line 2608 "awkgram.c" /* yacc.c:1646 */ break; case 50: -#line 852 "awkgram.y" /* yacc.c:1646 */ +#line 853 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_for_loop((yyvsp[-10]), (yyvsp[-8]), (INSTRUCTION *) NULL, (yyvsp[-3]), (yyvsp[0])); break_allowed--; continue_allowed--; } -#line 2618 "awkgram.c" /* yacc.c:1646 */ +#line 2619 "awkgram.c" /* yacc.c:1646 */ break; case 51: -#line 859 "awkgram.y" /* yacc.c:1646 */ +#line 860 "awkgram.y" /* yacc.c:1646 */ { if (do_pretty_print) (yyval) = list_prepend((yyvsp[0]), instruction(Op_exec_count)); else (yyval) = (yyvsp[0]); } -#line 2629 "awkgram.c" /* yacc.c:1646 */ +#line 2630 "awkgram.c" /* yacc.c:1646 */ break; case 52: -#line 869 "awkgram.y" /* yacc.c:1646 */ +#line 870 "awkgram.y" /* yacc.c:1646 */ { if (! break_allowed) error_ln((yyvsp[-1])->source_line, @@ -2638,11 +2639,11 @@ regular_loop: (yyval) = list_create((yyvsp[-1])); } -#line 2642 "awkgram.c" /* yacc.c:1646 */ +#line 2643 "awkgram.c" /* yacc.c:1646 */ break; case 53: -#line 878 "awkgram.y" /* yacc.c:1646 */ +#line 879 "awkgram.y" /* yacc.c:1646 */ { if (! continue_allowed) error_ln((yyvsp[-1])->source_line, @@ -2651,11 +2652,11 @@ regular_loop: (yyval) = list_create((yyvsp[-1])); } -#line 2655 "awkgram.c" /* yacc.c:1646 */ +#line 2656 "awkgram.c" /* yacc.c:1646 */ break; case 54: -#line 887 "awkgram.y" /* yacc.c:1646 */ +#line 888 "awkgram.y" /* yacc.c:1646 */ { /* if inside function (rule = 0), resolve context at run-time */ if (rule && rule != Rule) @@ -2664,11 +2665,11 @@ regular_loop: (yyvsp[-1])->target_jmp = ip_rec; (yyval) = list_create((yyvsp[-1])); } -#line 2668 "awkgram.c" /* yacc.c:1646 */ +#line 2669 "awkgram.c" /* yacc.c:1646 */ break; case 55: -#line 896 "awkgram.y" /* yacc.c:1646 */ +#line 897 "awkgram.y" /* yacc.c:1646 */ { /* if inside function (rule = 0), resolve context at run-time */ if (rule == BEGIN || rule == END || rule == ENDFILE) @@ -2679,11 +2680,11 @@ regular_loop: (yyvsp[-1])->target_endfile = ip_endfile; (yyval) = list_create((yyvsp[-1])); } -#line 2683 "awkgram.c" /* yacc.c:1646 */ +#line 2684 "awkgram.c" /* yacc.c:1646 */ break; case 56: -#line 907 "awkgram.y" /* yacc.c:1646 */ +#line 908 "awkgram.y" /* yacc.c:1646 */ { /* Initialize the two possible jump targets, the actual target * is resolved at run-time. @@ -2698,20 +2699,20 @@ regular_loop: } else (yyval) = list_append((yyvsp[-1]), (yyvsp[-2])); } -#line 2702 "awkgram.c" /* yacc.c:1646 */ +#line 2703 "awkgram.c" /* yacc.c:1646 */ break; case 57: -#line 922 "awkgram.y" /* yacc.c:1646 */ +#line 923 "awkgram.y" /* yacc.c:1646 */ { if (! in_function) yyerror(_("`return' used outside function context")); } -#line 2711 "awkgram.c" /* yacc.c:1646 */ +#line 2712 "awkgram.c" /* yacc.c:1646 */ break; case 58: -#line 925 "awkgram.y" /* yacc.c:1646 */ +#line 926 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-1]) == NULL) { (yyval) = list_create((yyvsp[-3])); @@ -2732,17 +2733,17 @@ regular_loop: (yyval) = list_append((yyvsp[-1]), (yyvsp[-3])); } } -#line 2736 "awkgram.c" /* yacc.c:1646 */ +#line 2737 "awkgram.c" /* yacc.c:1646 */ break; case 60: -#line 957 "awkgram.y" /* yacc.c:1646 */ +#line 958 "awkgram.y" /* yacc.c:1646 */ { in_print = true; in_parens = 0; } -#line 2742 "awkgram.c" /* yacc.c:1646 */ +#line 2743 "awkgram.c" /* yacc.c:1646 */ break; case 61: -#line 958 "awkgram.y" /* yacc.c:1646 */ +#line 959 "awkgram.y" /* yacc.c:1646 */ { /* * Optimization: plain `print' has no expression list, so $3 is null. @@ -2839,17 +2840,17 @@ regular_print: } } } -#line 2843 "awkgram.c" /* yacc.c:1646 */ +#line 2844 "awkgram.c" /* yacc.c:1646 */ break; case 62: -#line 1055 "awkgram.y" /* yacc.c:1646 */ +#line 1056 "awkgram.y" /* yacc.c:1646 */ { sub_counter = 0; } -#line 2849 "awkgram.c" /* yacc.c:1646 */ +#line 2850 "awkgram.c" /* yacc.c:1646 */ break; case 63: -#line 1056 "awkgram.y" /* yacc.c:1646 */ +#line 1057 "awkgram.y" /* yacc.c:1646 */ { char *arr = (yyvsp[-2])->lextok; @@ -2882,11 +2883,11 @@ regular_print: (yyval) = list_append(list_append((yyvsp[0]), (yyvsp[-2])), (yyvsp[-3])); } } -#line 2886 "awkgram.c" /* yacc.c:1646 */ +#line 2887 "awkgram.c" /* yacc.c:1646 */ break; case 64: -#line 1093 "awkgram.y" /* yacc.c:1646 */ +#line 1094 "awkgram.y" /* yacc.c:1646 */ { static bool warned = false; char *arr = (yyvsp[-1])->lextok; @@ -2912,52 +2913,52 @@ regular_print: fatal(_("`delete' is not allowed with FUNCTAB")); } } -#line 2916 "awkgram.c" /* yacc.c:1646 */ +#line 2917 "awkgram.c" /* yacc.c:1646 */ break; case 65: -#line 1119 "awkgram.y" /* yacc.c:1646 */ +#line 1120 "awkgram.y" /* yacc.c:1646 */ { (yyval) = optimize_assignment((yyvsp[0])); } -#line 2922 "awkgram.c" /* yacc.c:1646 */ +#line 2923 "awkgram.c" /* yacc.c:1646 */ break; case 66: -#line 1124 "awkgram.y" /* yacc.c:1646 */ +#line 1125 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2928 "awkgram.c" /* yacc.c:1646 */ +#line 2929 "awkgram.c" /* yacc.c:1646 */ break; case 67: -#line 1126 "awkgram.y" /* yacc.c:1646 */ +#line 1127 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2934 "awkgram.c" /* yacc.c:1646 */ +#line 2935 "awkgram.c" /* yacc.c:1646 */ break; case 68: -#line 1131 "awkgram.y" /* yacc.c:1646 */ +#line 1132 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2940 "awkgram.c" /* yacc.c:1646 */ +#line 2941 "awkgram.c" /* yacc.c:1646 */ break; case 69: -#line 1133 "awkgram.y" /* yacc.c:1646 */ +#line 1134 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-1]) == NULL) (yyval) = list_create((yyvsp[0])); else (yyval) = list_prepend((yyvsp[-1]), (yyvsp[0])); } -#line 2951 "awkgram.c" /* yacc.c:1646 */ +#line 2952 "awkgram.c" /* yacc.c:1646 */ break; case 70: -#line 1140 "awkgram.y" /* yacc.c:1646 */ +#line 1141 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2957 "awkgram.c" /* yacc.c:1646 */ +#line 2958 "awkgram.c" /* yacc.c:1646 */ break; case 71: -#line 1145 "awkgram.y" /* yacc.c:1646 */ +#line 1146 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *casestmt = (yyvsp[0]); if ((yyvsp[0]) == NULL) @@ -2969,11 +2970,11 @@ regular_print: bcfree((yyvsp[-2])); (yyval) = (yyvsp[-4]); } -#line 2973 "awkgram.c" /* yacc.c:1646 */ +#line 2974 "awkgram.c" /* yacc.c:1646 */ break; case 72: -#line 1157 "awkgram.y" /* yacc.c:1646 */ +#line 1158 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *casestmt = (yyvsp[0]); if ((yyvsp[0]) == NULL) @@ -2984,17 +2985,17 @@ regular_print: (yyvsp[-3])->case_stmt = casestmt; (yyval) = (yyvsp[-3]); } -#line 2988 "awkgram.c" /* yacc.c:1646 */ +#line 2989 "awkgram.c" /* yacc.c:1646 */ break; case 73: -#line 1171 "awkgram.y" /* yacc.c:1646 */ +#line 1172 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2994 "awkgram.c" /* yacc.c:1646 */ +#line 2995 "awkgram.c" /* yacc.c:1646 */ break; case 74: -#line 1173 "awkgram.y" /* yacc.c:1646 */ +#line 1174 "awkgram.y" /* yacc.c:1646 */ { NODE *n = (yyvsp[0])->memory; (void) force_number(n); @@ -3002,71 +3003,71 @@ regular_print: bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 3006 "awkgram.c" /* yacc.c:1646 */ +#line 3007 "awkgram.c" /* yacc.c:1646 */ break; case 75: -#line 1181 "awkgram.y" /* yacc.c:1646 */ +#line 1182 "awkgram.y" /* yacc.c:1646 */ { bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 3015 "awkgram.c" /* yacc.c:1646 */ +#line 3016 "awkgram.c" /* yacc.c:1646 */ break; case 76: -#line 1186 "awkgram.y" /* yacc.c:1646 */ +#line 1187 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3021 "awkgram.c" /* yacc.c:1646 */ +#line 3022 "awkgram.c" /* yacc.c:1646 */ break; case 77: -#line 1188 "awkgram.y" /* yacc.c:1646 */ +#line 1189 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_push_re; (yyval) = (yyvsp[0]); } -#line 3030 "awkgram.c" /* yacc.c:1646 */ +#line 3031 "awkgram.c" /* yacc.c:1646 */ break; case 78: -#line 1196 "awkgram.y" /* yacc.c:1646 */ +#line 1197 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3036 "awkgram.c" /* yacc.c:1646 */ +#line 3037 "awkgram.c" /* yacc.c:1646 */ break; case 79: -#line 1198 "awkgram.y" /* yacc.c:1646 */ +#line 1199 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3042 "awkgram.c" /* yacc.c:1646 */ +#line 3043 "awkgram.c" /* yacc.c:1646 */ break; case 81: -#line 1208 "awkgram.y" /* yacc.c:1646 */ +#line 1209 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3050 "awkgram.c" /* yacc.c:1646 */ +#line 3051 "awkgram.c" /* yacc.c:1646 */ break; case 82: -#line 1215 "awkgram.y" /* yacc.c:1646 */ +#line 1216 "awkgram.y" /* yacc.c:1646 */ { in_print = false; in_parens = 0; (yyval) = NULL; } -#line 3060 "awkgram.c" /* yacc.c:1646 */ +#line 3061 "awkgram.c" /* yacc.c:1646 */ break; case 83: -#line 1220 "awkgram.y" /* yacc.c:1646 */ +#line 1221 "awkgram.y" /* yacc.c:1646 */ { in_print = false; in_parens = 0; } -#line 3066 "awkgram.c" /* yacc.c:1646 */ +#line 3067 "awkgram.c" /* yacc.c:1646 */ break; case 84: -#line 1221 "awkgram.y" /* yacc.c:1646 */ +#line 1222 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-2])->redir_type == redirect_twoway && (yyvsp[0])->lasti->opcode == Op_K_getline_redir @@ -3074,136 +3075,136 @@ regular_print: yyerror(_("multistage two-way pipelines don't work")); (yyval) = list_prepend((yyvsp[0]), (yyvsp[-2])); } -#line 3078 "awkgram.c" /* yacc.c:1646 */ +#line 3079 "awkgram.c" /* yacc.c:1646 */ break; case 85: -#line 1232 "awkgram.y" /* yacc.c:1646 */ +#line 1233 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_condition((yyvsp[-3]), (yyvsp[-5]), (yyvsp[0]), NULL, NULL); } -#line 3086 "awkgram.c" /* yacc.c:1646 */ +#line 3087 "awkgram.c" /* yacc.c:1646 */ break; case 86: -#line 1237 "awkgram.y" /* yacc.c:1646 */ +#line 1238 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_condition((yyvsp[-6]), (yyvsp[-8]), (yyvsp[-3]), (yyvsp[-2]), (yyvsp[0])); } -#line 3094 "awkgram.c" /* yacc.c:1646 */ +#line 3095 "awkgram.c" /* yacc.c:1646 */ break; case 91: -#line 1254 "awkgram.y" /* yacc.c:1646 */ +#line 1255 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3100 "awkgram.c" /* yacc.c:1646 */ +#line 3101 "awkgram.c" /* yacc.c:1646 */ break; case 92: -#line 1256 "awkgram.y" /* yacc.c:1646 */ +#line 1257 "awkgram.y" /* yacc.c:1646 */ { bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 3109 "awkgram.c" /* yacc.c:1646 */ +#line 3110 "awkgram.c" /* yacc.c:1646 */ break; case 93: -#line 1264 "awkgram.y" /* yacc.c:1646 */ +#line 1265 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3115 "awkgram.c" /* yacc.c:1646 */ +#line 3116 "awkgram.c" /* yacc.c:1646 */ break; case 94: -#line 1266 "awkgram.y" /* yacc.c:1646 */ +#line 1267 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3121 "awkgram.c" /* yacc.c:1646 */ +#line 3122 "awkgram.c" /* yacc.c:1646 */ break; case 95: -#line 1271 "awkgram.y" /* yacc.c:1646 */ +#line 1272 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->param_count = 0; (yyval) = list_create((yyvsp[0])); } -#line 3130 "awkgram.c" /* yacc.c:1646 */ +#line 3131 "awkgram.c" /* yacc.c:1646 */ break; case 96: -#line 1276 "awkgram.y" /* yacc.c:1646 */ +#line 1277 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->param_count = (yyvsp[-2])->lasti->param_count + 1; (yyval) = list_append((yyvsp[-2]), (yyvsp[0])); yyerrok; } -#line 3140 "awkgram.c" /* yacc.c:1646 */ +#line 3141 "awkgram.c" /* yacc.c:1646 */ break; case 97: -#line 1282 "awkgram.y" /* yacc.c:1646 */ +#line 1283 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3146 "awkgram.c" /* yacc.c:1646 */ +#line 3147 "awkgram.c" /* yacc.c:1646 */ break; case 98: -#line 1284 "awkgram.y" /* yacc.c:1646 */ +#line 1285 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3152 "awkgram.c" /* yacc.c:1646 */ +#line 3153 "awkgram.c" /* yacc.c:1646 */ break; case 99: -#line 1286 "awkgram.y" /* yacc.c:1646 */ +#line 1287 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-2]); } -#line 3158 "awkgram.c" /* yacc.c:1646 */ +#line 3159 "awkgram.c" /* yacc.c:1646 */ break; case 100: -#line 1292 "awkgram.y" /* yacc.c:1646 */ +#line 1293 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3164 "awkgram.c" /* yacc.c:1646 */ +#line 3165 "awkgram.c" /* yacc.c:1646 */ break; case 101: -#line 1294 "awkgram.y" /* yacc.c:1646 */ +#line 1295 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3170 "awkgram.c" /* yacc.c:1646 */ +#line 3171 "awkgram.c" /* yacc.c:1646 */ break; case 102: -#line 1299 "awkgram.y" /* yacc.c:1646 */ +#line 1300 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3176 "awkgram.c" /* yacc.c:1646 */ +#line 3177 "awkgram.c" /* yacc.c:1646 */ break; case 103: -#line 1301 "awkgram.y" /* yacc.c:1646 */ +#line 1302 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3182 "awkgram.c" /* yacc.c:1646 */ +#line 3183 "awkgram.c" /* yacc.c:1646 */ break; case 104: -#line 1306 "awkgram.y" /* yacc.c:1646 */ +#line 1307 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_expression_list(NULL, (yyvsp[0])); } -#line 3188 "awkgram.c" /* yacc.c:1646 */ +#line 3189 "awkgram.c" /* yacc.c:1646 */ break; case 105: -#line 1308 "awkgram.y" /* yacc.c:1646 */ +#line 1309 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); yyerrok; } -#line 3197 "awkgram.c" /* yacc.c:1646 */ +#line 3198 "awkgram.c" /* yacc.c:1646 */ break; case 106: -#line 1313 "awkgram.y" /* yacc.c:1646 */ +#line 1314 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3203 "awkgram.c" /* yacc.c:1646 */ +#line 3204 "awkgram.c" /* yacc.c:1646 */ break; case 107: -#line 1315 "awkgram.y" /* yacc.c:1646 */ +#line 1316 "awkgram.y" /* yacc.c:1646 */ { /* * Returning the expression list instead of NULL lets @@ -3211,52 +3212,52 @@ regular_print: */ (yyval) = (yyvsp[-1]); } -#line 3215 "awkgram.c" /* yacc.c:1646 */ +#line 3216 "awkgram.c" /* yacc.c:1646 */ break; case 108: -#line 1323 "awkgram.y" /* yacc.c:1646 */ +#line 1324 "awkgram.y" /* yacc.c:1646 */ { /* Ditto */ (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); } -#line 3224 "awkgram.c" /* yacc.c:1646 */ +#line 3225 "awkgram.c" /* yacc.c:1646 */ break; case 109: -#line 1328 "awkgram.y" /* yacc.c:1646 */ +#line 1329 "awkgram.y" /* yacc.c:1646 */ { /* Ditto */ (yyval) = (yyvsp[-2]); } -#line 3233 "awkgram.c" /* yacc.c:1646 */ +#line 3234 "awkgram.c" /* yacc.c:1646 */ break; case 110: -#line 1337 "awkgram.y" /* yacc.c:1646 */ +#line 1338 "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 3244 "awkgram.c" /* yacc.c:1646 */ +#line 3245 "awkgram.c" /* yacc.c:1646 */ break; case 111: -#line 1344 "awkgram.y" /* yacc.c:1646 */ +#line 1345 "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 112: -#line 1346 "awkgram.y" /* yacc.c:1646 */ +#line 1347 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3256 "awkgram.c" /* yacc.c:1646 */ +#line 3257 "awkgram.c" /* yacc.c:1646 */ break; case 113: -#line 1348 "awkgram.y" /* yacc.c:1646 */ +#line 1349 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-2])->lasti->opcode == Op_match_rec) warning_ln((yyvsp[-1])->source_line, @@ -3272,11 +3273,11 @@ regular_print: (yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), (yyvsp[-1])); } } -#line 3276 "awkgram.c" /* yacc.c:1646 */ +#line 3277 "awkgram.c" /* yacc.c:1646 */ break; case 114: -#line 1364 "awkgram.y" /* yacc.c:1646 */ +#line 1365 "awkgram.y" /* yacc.c:1646 */ { if (do_lint_old) warning_ln((yyvsp[-1])->source_line, @@ -3286,91 +3287,91 @@ regular_print: (yyvsp[-1])->expr_count = 1; (yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), (yyvsp[-1])); } -#line 3290 "awkgram.c" /* yacc.c:1646 */ +#line 3291 "awkgram.c" /* yacc.c:1646 */ break; case 115: -#line 1374 "awkgram.y" /* yacc.c:1646 */ +#line 1375 "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 3301 "awkgram.c" /* yacc.c:1646 */ +#line 3302 "awkgram.c" /* yacc.c:1646 */ break; case 116: -#line 1381 "awkgram.y" /* yacc.c:1646 */ +#line 1382 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_condition((yyvsp[-4]), (yyvsp[-3]), (yyvsp[-2]), (yyvsp[-1]), (yyvsp[0])); } -#line 3307 "awkgram.c" /* yacc.c:1646 */ +#line 3308 "awkgram.c" /* yacc.c:1646 */ break; case 117: -#line 1383 "awkgram.y" /* yacc.c:1646 */ +#line 1384 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3313 "awkgram.c" /* yacc.c:1646 */ +#line 3314 "awkgram.c" /* yacc.c:1646 */ break; case 118: -#line 1388 "awkgram.y" /* yacc.c:1646 */ +#line 1389 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3319 "awkgram.c" /* yacc.c:1646 */ +#line 3320 "awkgram.c" /* yacc.c:1646 */ break; case 119: -#line 1390 "awkgram.y" /* yacc.c:1646 */ +#line 1391 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3325 "awkgram.c" /* yacc.c:1646 */ +#line 3326 "awkgram.c" /* yacc.c:1646 */ break; case 120: -#line 1392 "awkgram.y" /* yacc.c:1646 */ +#line 1393 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_assign_quotient; (yyval) = (yyvsp[0]); } -#line 3334 "awkgram.c" /* yacc.c:1646 */ +#line 3335 "awkgram.c" /* yacc.c:1646 */ break; case 121: -#line 1400 "awkgram.y" /* yacc.c:1646 */ +#line 1401 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3340 "awkgram.c" /* yacc.c:1646 */ +#line 3341 "awkgram.c" /* yacc.c:1646 */ break; case 122: -#line 1402 "awkgram.y" /* yacc.c:1646 */ +#line 1403 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3346 "awkgram.c" /* yacc.c:1646 */ +#line 3347 "awkgram.c" /* yacc.c:1646 */ break; case 123: -#line 1407 "awkgram.y" /* yacc.c:1646 */ +#line 1408 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3352 "awkgram.c" /* yacc.c:1646 */ +#line 3353 "awkgram.c" /* yacc.c:1646 */ break; case 124: -#line 1409 "awkgram.y" /* yacc.c:1646 */ +#line 1410 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3358 "awkgram.c" /* yacc.c:1646 */ +#line 3359 "awkgram.c" /* yacc.c:1646 */ break; case 125: -#line 1414 "awkgram.y" /* yacc.c:1646 */ +#line 1415 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3364 "awkgram.c" /* yacc.c:1646 */ +#line 3365 "awkgram.c" /* yacc.c:1646 */ break; case 126: -#line 1416 "awkgram.y" /* yacc.c:1646 */ +#line 1417 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3370 "awkgram.c" /* yacc.c:1646 */ +#line 3371 "awkgram.c" /* yacc.c:1646 */ break; case 127: -#line 1418 "awkgram.y" /* yacc.c:1646 */ +#line 1419 "awkgram.y" /* yacc.c:1646 */ { int count = 2; bool is_simple_var = false; @@ -3417,47 +3418,47 @@ regular_print: max_args = count; } } -#line 3421 "awkgram.c" /* yacc.c:1646 */ +#line 3422 "awkgram.c" /* yacc.c:1646 */ break; case 129: -#line 1470 "awkgram.y" /* yacc.c:1646 */ +#line 1471 "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 130: -#line 1472 "awkgram.y" /* yacc.c:1646 */ +#line 1473 "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 131: -#line 1474 "awkgram.y" /* yacc.c:1646 */ +#line 1475 "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 132: -#line 1476 "awkgram.y" /* yacc.c:1646 */ +#line 1477 "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 133: -#line 1478 "awkgram.y" /* yacc.c:1646 */ +#line 1479 "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 134: -#line 1480 "awkgram.y" /* yacc.c:1646 */ +#line 1481 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3457 "awkgram.c" /* yacc.c:1646 */ +#line 3458 "awkgram.c" /* yacc.c:1646 */ break; case 135: -#line 1482 "awkgram.y" /* yacc.c:1646 */ +#line 1483 "awkgram.y" /* yacc.c:1646 */ { /* * In BEGINFILE/ENDFILE, allow `getline [var] < file' @@ -3471,29 +3472,29 @@ regular_print: _("non-redirected `getline' undefined inside END action")); (yyval) = mk_getline((yyvsp[-2]), (yyvsp[-1]), (yyvsp[0]), redirect_input); } -#line 3475 "awkgram.c" /* yacc.c:1646 */ +#line 3476 "awkgram.c" /* yacc.c:1646 */ break; case 136: -#line 1496 "awkgram.y" /* yacc.c:1646 */ +#line 1497 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postincrement; (yyval) = mk_assignment((yyvsp[-1]), NULL, (yyvsp[0])); } -#line 3484 "awkgram.c" /* yacc.c:1646 */ +#line 3485 "awkgram.c" /* yacc.c:1646 */ break; case 137: -#line 1501 "awkgram.y" /* yacc.c:1646 */ +#line 1502 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postdecrement; (yyval) = mk_assignment((yyvsp[-1]), NULL, (yyvsp[0])); } -#line 3493 "awkgram.c" /* yacc.c:1646 */ +#line 3494 "awkgram.c" /* yacc.c:1646 */ break; case 138: -#line 1506 "awkgram.y" /* yacc.c:1646 */ +#line 1507 "awkgram.y" /* yacc.c:1646 */ { if (do_lint_old) { warning_ln((yyvsp[-1])->source_line, @@ -3513,64 +3514,64 @@ regular_print: (yyval) = list_append(list_merge(t, (yyvsp[0])), (yyvsp[-1])); } } -#line 3517 "awkgram.c" /* yacc.c:1646 */ +#line 3518 "awkgram.c" /* yacc.c:1646 */ break; case 139: -#line 1531 "awkgram.y" /* yacc.c:1646 */ +#line 1532 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_getline((yyvsp[-1]), (yyvsp[0]), (yyvsp[-3]), (yyvsp[-2])->redir_type); bcfree((yyvsp[-2])); } -#line 3526 "awkgram.c" /* yacc.c:1646 */ +#line 3527 "awkgram.c" /* yacc.c:1646 */ break; case 140: -#line 1537 "awkgram.y" /* yacc.c:1646 */ +#line 1538 "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 141: -#line 1539 "awkgram.y" /* yacc.c:1646 */ +#line 1540 "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 142: -#line 1541 "awkgram.y" /* yacc.c:1646 */ +#line 1542 "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 143: -#line 1543 "awkgram.y" /* yacc.c:1646 */ +#line 1544 "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 144: -#line 1545 "awkgram.y" /* yacc.c:1646 */ +#line 1546 "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 145: -#line 1547 "awkgram.y" /* yacc.c:1646 */ +#line 1548 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3562 "awkgram.c" /* yacc.c:1646 */ +#line 3563 "awkgram.c" /* yacc.c:1646 */ break; case 146: -#line 1552 "awkgram.y" /* yacc.c:1646 */ +#line 1553 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3570 "awkgram.c" /* yacc.c:1646 */ +#line 3571 "awkgram.c" /* yacc.c:1646 */ break; case 147: -#line 1556 "awkgram.y" /* yacc.c:1646 */ +#line 1557 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[0])->opcode == Op_match_rec) { (yyvsp[0])->opcode = Op_nomatch; @@ -3602,37 +3603,37 @@ regular_print: } } } -#line 3606 "awkgram.c" /* yacc.c:1646 */ +#line 3607 "awkgram.c" /* yacc.c:1646 */ break; case 148: -#line 1588 "awkgram.y" /* yacc.c:1646 */ +#line 1589 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3612 "awkgram.c" /* yacc.c:1646 */ +#line 3613 "awkgram.c" /* yacc.c:1646 */ break; case 149: -#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 3622 "awkgram.c" /* yacc.c:1646 */ +#line 3623 "awkgram.c" /* yacc.c:1646 */ break; case 150: -#line 1596 "awkgram.y" /* yacc.c:1646 */ +#line 1597 "awkgram.y" /* yacc.c:1646 */ { (yyval) = snode((yyvsp[-1]), (yyvsp[-3])); if ((yyval) == NULL) YYABORT; } -#line 3632 "awkgram.c" /* yacc.c:1646 */ +#line 3633 "awkgram.c" /* yacc.c:1646 */ break; case 151: -#line 1602 "awkgram.y" /* yacc.c:1646 */ +#line 1603 "awkgram.y" /* yacc.c:1646 */ { static bool warned = false; @@ -3645,45 +3646,45 @@ regular_print: if ((yyval) == NULL) YYABORT; } -#line 3649 "awkgram.c" /* yacc.c:1646 */ +#line 3650 "awkgram.c" /* yacc.c:1646 */ break; case 154: -#line 1617 "awkgram.y" /* yacc.c:1646 */ +#line 1618 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[-1])->opcode = Op_preincrement; (yyval) = mk_assignment((yyvsp[0]), NULL, (yyvsp[-1])); } -#line 3658 "awkgram.c" /* yacc.c:1646 */ +#line 3659 "awkgram.c" /* yacc.c:1646 */ break; case 155: -#line 1622 "awkgram.y" /* yacc.c:1646 */ +#line 1623 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[-1])->opcode = Op_predecrement; (yyval) = mk_assignment((yyvsp[0]), NULL, (yyvsp[-1])); } -#line 3667 "awkgram.c" /* yacc.c:1646 */ +#line 3668 "awkgram.c" /* yacc.c:1646 */ break; case 156: -#line 1627 "awkgram.y" /* yacc.c:1646 */ +#line 1628 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3675 "awkgram.c" /* yacc.c:1646 */ +#line 3676 "awkgram.c" /* yacc.c:1646 */ break; case 157: -#line 1631 "awkgram.y" /* yacc.c:1646 */ +#line 1632 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3683 "awkgram.c" /* yacc.c:1646 */ +#line 3684 "awkgram.c" /* yacc.c:1646 */ break; case 158: -#line 1635 "awkgram.y" /* yacc.c:1646 */ +#line 1636 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[0])->lasti->opcode == Op_push_i && ((yyvsp[0])->lasti->memory->flags & (STRCUR|STRING)) == 0 @@ -3698,11 +3699,11 @@ regular_print: (yyval) = list_append((yyvsp[0]), (yyvsp[-1])); } } -#line 3702 "awkgram.c" /* yacc.c:1646 */ +#line 3703 "awkgram.c" /* yacc.c:1646 */ break; case 159: -#line 1650 "awkgram.y" /* yacc.c:1646 */ +#line 1651 "awkgram.y" /* yacc.c:1646 */ { /* * was: $$ = $2 @@ -3712,20 +3713,20 @@ regular_print: (yyvsp[-1])->memory = make_number(0.0); (yyval) = list_append((yyvsp[0]), (yyvsp[-1])); } -#line 3716 "awkgram.c" /* yacc.c:1646 */ +#line 3717 "awkgram.c" /* yacc.c:1646 */ break; case 160: -#line 1663 "awkgram.y" /* yacc.c:1646 */ +#line 1664 "awkgram.y" /* yacc.c:1646 */ { func_use((yyvsp[0])->lasti->func_name, FUNC_USE); (yyval) = (yyvsp[0]); } -#line 3725 "awkgram.c" /* yacc.c:1646 */ +#line 3726 "awkgram.c" /* yacc.c:1646 */ break; case 161: -#line 1668 "awkgram.y" /* yacc.c:1646 */ +#line 1669 "awkgram.y" /* yacc.c:1646 */ { /* indirect function call */ INSTRUCTION *f, *t; @@ -3759,11 +3760,11 @@ regular_print: (yyval) = list_prepend((yyvsp[0]), t); at_seen = false; } -#line 3763 "awkgram.c" /* yacc.c:1646 */ +#line 3764 "awkgram.c" /* yacc.c:1646 */ break; case 162: -#line 1705 "awkgram.y" /* yacc.c:1646 */ +#line 1706 "awkgram.y" /* yacc.c:1646 */ { NODE *n; @@ -3788,49 +3789,49 @@ regular_print: (yyval) = list_append(t, (yyvsp[-3])); } } -#line 3792 "awkgram.c" /* yacc.c:1646 */ +#line 3793 "awkgram.c" /* yacc.c:1646 */ break; case 163: -#line 1733 "awkgram.y" /* yacc.c:1646 */ +#line 1734 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3798 "awkgram.c" /* yacc.c:1646 */ +#line 3799 "awkgram.c" /* yacc.c:1646 */ break; case 164: -#line 1735 "awkgram.y" /* yacc.c:1646 */ +#line 1736 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3804 "awkgram.c" /* yacc.c:1646 */ +#line 3805 "awkgram.c" /* yacc.c:1646 */ break; case 165: -#line 1740 "awkgram.y" /* yacc.c:1646 */ +#line 1741 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3810 "awkgram.c" /* yacc.c:1646 */ +#line 3811 "awkgram.c" /* yacc.c:1646 */ break; case 166: -#line 1742 "awkgram.y" /* yacc.c:1646 */ +#line 1743 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3816 "awkgram.c" /* yacc.c:1646 */ +#line 3817 "awkgram.c" /* yacc.c:1646 */ break; case 167: -#line 1747 "awkgram.y" /* yacc.c:1646 */ +#line 1748 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3822 "awkgram.c" /* yacc.c:1646 */ +#line 3823 "awkgram.c" /* yacc.c:1646 */ break; case 168: -#line 1749 "awkgram.y" /* yacc.c:1646 */ +#line 1750 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_merge((yyvsp[-1]), (yyvsp[0])); } -#line 3830 "awkgram.c" /* yacc.c:1646 */ +#line 3831 "awkgram.c" /* yacc.c:1646 */ break; case 169: -#line 1756 "awkgram.y" /* yacc.c:1646 */ +#line 1757 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip = (yyvsp[0])->lasti; int count = ip->sub_count; /* # of SUBSEP-seperated expressions */ @@ -3844,11 +3845,11 @@ regular_print: sub_counter++; /* count # of dimensions */ (yyval) = (yyvsp[0]); } -#line 3848 "awkgram.c" /* yacc.c:1646 */ +#line 3849 "awkgram.c" /* yacc.c:1646 */ break; case 170: -#line 1773 "awkgram.y" /* yacc.c:1646 */ +#line 1774 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *t = (yyvsp[-1]); if ((yyvsp[-1]) == NULL) { @@ -3862,31 +3863,31 @@ regular_print: (yyvsp[0])->sub_count = count_expressions(&t, false); (yyval) = list_append(t, (yyvsp[0])); } -#line 3866 "awkgram.c" /* yacc.c:1646 */ +#line 3867 "awkgram.c" /* yacc.c:1646 */ break; case 171: -#line 1790 "awkgram.y" /* yacc.c:1646 */ +#line 1791 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3872 "awkgram.c" /* yacc.c:1646 */ +#line 3873 "awkgram.c" /* yacc.c:1646 */ break; case 172: -#line 1792 "awkgram.y" /* yacc.c:1646 */ +#line 1793 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_merge((yyvsp[-1]), (yyvsp[0])); } -#line 3880 "awkgram.c" /* yacc.c:1646 */ +#line 3881 "awkgram.c" /* yacc.c:1646 */ break; case 173: -#line 1799 "awkgram.y" /* yacc.c:1646 */ +#line 1800 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3886 "awkgram.c" /* yacc.c:1646 */ +#line 3887 "awkgram.c" /* yacc.c:1646 */ break; case 174: -#line 1804 "awkgram.y" /* yacc.c:1646 */ +#line 1805 "awkgram.y" /* yacc.c:1646 */ { char *var_name = (yyvsp[0])->lextok; @@ -3894,22 +3895,22 @@ regular_print: (yyvsp[0])->memory = variable((yyvsp[0])->source_line, var_name, Node_var_new); (yyval) = list_create((yyvsp[0])); } -#line 3898 "awkgram.c" /* yacc.c:1646 */ +#line 3899 "awkgram.c" /* yacc.c:1646 */ break; case 175: -#line 1812 "awkgram.y" /* yacc.c:1646 */ +#line 1813 "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 3909 "awkgram.c" /* yacc.c:1646 */ +#line 3910 "awkgram.c" /* yacc.c:1646 */ break; case 176: -#line 1822 "awkgram.y" /* yacc.c:1646 */ +#line 1823 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip = (yyvsp[0])->nexti; if (ip->opcode == Op_push @@ -3921,73 +3922,73 @@ regular_print: } else (yyval) = (yyvsp[0]); } -#line 3925 "awkgram.c" /* yacc.c:1646 */ +#line 3926 "awkgram.c" /* yacc.c:1646 */ break; case 177: -#line 1834 "awkgram.y" /* yacc.c:1646 */ +#line 1835 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_append((yyvsp[-1]), (yyvsp[-2])); if ((yyvsp[0]) != NULL) mk_assignment((yyvsp[-1]), NULL, (yyvsp[0])); } -#line 3935 "awkgram.c" /* yacc.c:1646 */ +#line 3936 "awkgram.c" /* yacc.c:1646 */ break; case 178: -#line 1843 "awkgram.y" /* yacc.c:1646 */ +#line 1844 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postincrement; } -#line 3943 "awkgram.c" /* yacc.c:1646 */ +#line 3944 "awkgram.c" /* yacc.c:1646 */ break; case 179: -#line 1847 "awkgram.y" /* yacc.c:1646 */ +#line 1848 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postdecrement; } -#line 3951 "awkgram.c" /* yacc.c:1646 */ +#line 3952 "awkgram.c" /* yacc.c:1646 */ break; case 180: -#line 1850 "awkgram.y" /* yacc.c:1646 */ +#line 1851 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3957 "awkgram.c" /* yacc.c:1646 */ +#line 3958 "awkgram.c" /* yacc.c:1646 */ break; case 182: -#line 1858 "awkgram.y" /* yacc.c:1646 */ +#line 1859 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3963 "awkgram.c" /* yacc.c:1646 */ +#line 3964 "awkgram.c" /* yacc.c:1646 */ break; case 183: -#line 1862 "awkgram.y" /* yacc.c:1646 */ +#line 1863 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3969 "awkgram.c" /* yacc.c:1646 */ +#line 3970 "awkgram.c" /* yacc.c:1646 */ break; case 186: -#line 1871 "awkgram.y" /* yacc.c:1646 */ +#line 1872 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3975 "awkgram.c" /* yacc.c:1646 */ +#line 3976 "awkgram.c" /* yacc.c:1646 */ break; case 187: -#line 1875 "awkgram.y" /* yacc.c:1646 */ +#line 1876 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); yyerrok; } -#line 3981 "awkgram.c" /* yacc.c:1646 */ +#line 3982 "awkgram.c" /* yacc.c:1646 */ break; case 188: -#line 1879 "awkgram.y" /* yacc.c:1646 */ +#line 1880 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3987 "awkgram.c" /* yacc.c:1646 */ +#line 3988 "awkgram.c" /* yacc.c:1646 */ break; -#line 3991 "awkgram.c" /* yacc.c:1646 */ +#line 3992 "awkgram.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -4215,7 +4216,7 @@ yyreturn: #endif return yyresult; } -#line 1881 "awkgram.y" /* yacc.c:1906 */ +#line 1882 "awkgram.y" /* yacc.c:1906 */ struct token { @@ -4724,7 +4725,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; @@ -144,6 +144,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; @@ -2386,7 +2387,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; @@ -168,6 +168,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 @@ -293,6 +296,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 @@ -10323,9 +10323,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 7c922ccf..a6972ab2 100644 --- a/configure.ac +++ b/configure.ac @@ -269,9 +269,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 92e95a0b..56b2d7f2 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -138,6 +138,25 @@ * gawktexi.in: Add info that nonfatal I/O works with stdout and stderr. Revise version info and what was added when. +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 3e12596d..95788ec2 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. @@ -558,6 +559,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 @@ -4178,6 +4180,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. @@ -5448,7 +5451,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. @@ -5886,7 +5893,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 ================================= @@ -5965,7 +5972,8 @@ a per-command or per-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 @@ -5980,9 +5988,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 @@ -6005,7 +6040,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 @@ -6079,7 +6114,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 @@ -10440,6 +10475,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 @@ -10488,6 +10528,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. @@ -10598,6 +10642,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::. @@ -22973,6 +23021,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. @@ -23033,6 +23082,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 @@ -24244,7 +24296,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 -------------------------- @@ -24729,9 +24781,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 @@ -24748,7 +24863,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 @@ -24797,7 +24912,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 @@ -24832,7 +24947,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 @@ -32540,9 +32655,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) @@ -32736,7 +32851,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) @@ -32759,7 +32874,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) @@ -32767,9 +32882,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. @@ -32777,7 +32894,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. @@ -32818,8 +32935,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) @@ -32934,7 +33051,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) @@ -33015,7 +33132,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) @@ -33083,9 +33200,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. @@ -33135,7 +33252,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) @@ -33185,7 +33302,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) @@ -33220,7 +33337,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. @@ -33252,7 +33369,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. @@ -33260,14 +33377,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) @@ -33359,7 +33476,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. @@ -33654,7 +33771,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 258) * McPhee, Patrick: Contributors. (line 100) * message object files: Explaining gettext. (line 42) @@ -33667,7 +33784,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) @@ -33716,7 +33833,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. @@ -33725,9 +33842,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. @@ -33841,7 +33958,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) @@ -34007,24 +34124,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) @@ -34159,6 +34276,7 @@ Index * relational operators, See comparison operators: Typing and Comparison. (line 9) * replace in string: String Functions. (line 409) +* retrying input: Retrying Input. (line 6) * return debugger command: Debugger Execution Control. (line 54) * return statement, user-defined functions: Return Statement. (line 6) @@ -34182,7 +34300,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 71) @@ -34208,9 +34326,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) @@ -34230,7 +34348,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) @@ -34313,7 +34431,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 139) * sidebar, Escape Sequences for Metacharacters: Escape Sequences. @@ -34475,9 +34593,9 @@ Index * substr: String Functions. (line 482) * substring: String Functions. (line 482) * 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 107) @@ -34654,10 +34772,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) @@ -34747,561 +34865,563 @@ Index Tag Table: Node: Top1204 -Node: Foreword342291 -Node: Foreword446735 -Node: Preface48266 -Ref: Preface-Footnote-151137 -Ref: Preface-Footnote-251244 -Ref: Preface-Footnote-351477 -Node: History51619 -Node: Names53970 -Ref: Names-Footnote-155064 -Node: This Manual55210 -Ref: This Manual-Footnote-161710 -Node: Conventions61810 -Node: Manual History64147 -Ref: Manual History-Footnote-167140 -Ref: Manual History-Footnote-267181 -Node: How To Contribute67255 -Node: Acknowledgments68384 -Node: Getting Started73250 -Node: Running gawk75689 -Node: One-shot76879 -Node: Read Terminal78143 -Node: Long80174 -Node: Executable Scripts81687 -Ref: Executable Scripts-Footnote-184476 -Node: Comments84579 -Node: Quoting87061 -Node: DOS Quoting92579 -Node: Sample Data Files93254 -Node: Very Simple95849 -Node: Two Rules100748 -Node: More Complex102634 -Node: Statements/Lines105496 -Ref: Statements/Lines-Footnote-1109951 -Node: Other Features110216 -Node: When111152 -Ref: When-Footnote-1112906 -Node: Intro Summary112971 -Node: Invoking Gawk113855 -Node: Command Line115369 -Node: Options116167 -Ref: Options-Footnote-1131962 -Ref: Options-Footnote-2132191 -Node: Other Arguments132216 -Node: Naming Standard Input135164 -Node: Environment Variables136257 -Node: AWKPATH Variable136815 -Ref: AWKPATH Variable-Footnote-1140222 -Ref: AWKPATH Variable-Footnote-2140267 -Node: AWKLIBPATH Variable140527 -Node: Other Environment Variables141783 -Node: Exit Status145414 -Node: Include Files146090 -Node: Loading Shared Libraries149679 -Node: Obsolete151106 -Node: Undocumented151798 -Node: Invoking Summary152065 -Node: Regexp153728 -Node: Regexp Usage155182 -Node: Escape Sequences157219 -Node: Regexp Operators163448 -Ref: Regexp Operators-Footnote-1170858 -Ref: Regexp Operators-Footnote-2171005 -Node: Bracket Expressions171103 -Ref: table-char-classes173118 -Node: Leftmost Longest176060 -Node: Computed Regexps177362 -Node: GNU Regexp Operators180791 -Node: Case-sensitivity184463 -Ref: Case-sensitivity-Footnote-1187348 -Ref: Case-sensitivity-Footnote-2187583 -Node: Regexp Summary187691 -Node: Reading Files189158 -Node: Records191251 -Node: awk split records191984 -Node: gawk split records196913 -Ref: gawk split records-Footnote-1201452 -Node: Fields201489 -Ref: Fields-Footnote-1204267 -Node: Nonconstant Fields204353 -Ref: Nonconstant Fields-Footnote-1206591 -Node: Changing Fields206794 -Node: Field Separators212725 -Node: Default Field Splitting215429 -Node: Regexp Field Splitting216546 -Node: Single Character Fields219896 -Node: Command Line Field Separator220955 -Node: Full Line Fields224172 -Ref: Full Line Fields-Footnote-1225693 -Ref: Full Line Fields-Footnote-2225739 -Node: Field Splitting Summary225840 -Node: Constant Size227914 -Node: Splitting By Content232493 -Ref: Splitting By Content-Footnote-1236458 -Node: Multiple Line236621 -Ref: Multiple Line-Footnote-1242502 -Node: Getline242681 -Node: Plain Getline244888 -Node: Getline/Variable247528 -Node: Getline/File248677 -Node: Getline/Variable/File250062 -Ref: Getline/Variable/File-Footnote-1251665 -Node: Getline/Pipe251752 -Node: Getline/Variable/Pipe254430 -Node: Getline/Coprocess255561 -Node: Getline/Variable/Coprocess256825 -Node: Getline Notes257564 -Node: Getline Summary260358 -Ref: table-getline-variants260770 -Node: Read Timeout261599 -Ref: Read Timeout-Footnote-1265436 -Node: Command-line directories265494 -Node: Input Summary266399 -Node: Input Exercises269784 -Node: Printing270512 -Node: Print272347 -Node: Print Examples273804 -Node: Output Separators276583 -Node: OFMT278601 -Node: Printf279956 -Node: Basic Printf280741 -Node: Control Letters282313 -Node: Format Modifiers286298 -Node: Printf Examples292304 -Node: Redirection294790 -Node: Special FD301628 -Ref: Special FD-Footnote-1304794 -Node: Special Files304868 -Node: Other Inherited Files305485 -Node: Special Network306485 -Node: Special Caveats307347 -Node: Close Files And Pipes308296 -Ref: Close Files And Pipes-Footnote-1315481 -Ref: Close Files And Pipes-Footnote-2315629 -Node: Nonfatal315779 -Node: Output Summary318104 -Node: Output Exercises319325 -Node: Expressions320005 -Node: Values321194 -Node: Constants321871 -Node: Scalar Constants322562 -Ref: Scalar Constants-Footnote-1323424 -Node: Nondecimal-numbers323674 -Node: Regexp Constants326684 -Node: Using Constant Regexps327210 -Node: Variables330373 -Node: Using Variables331030 -Node: Assignment Options332941 -Node: Conversion334816 -Node: Strings And Numbers335340 -Ref: Strings And Numbers-Footnote-1338405 -Node: Locale influences conversions338514 -Ref: table-locale-affects341260 -Node: All Operators341852 -Node: Arithmetic Ops342481 -Node: Concatenation344986 -Ref: Concatenation-Footnote-1347805 -Node: Assignment Ops347912 -Ref: table-assign-ops352891 -Node: Increment Ops354201 -Node: Truth Values and Conditions357632 -Node: Truth Values358715 -Node: Typing and Comparison359764 -Node: Variable Typing360580 -Node: Comparison Operators364247 -Ref: table-relational-ops364657 -Node: POSIX String Comparison368152 -Ref: POSIX String Comparison-Footnote-1369224 -Node: Boolean Ops369363 -Ref: Boolean Ops-Footnote-1373841 -Node: Conditional Exp373932 -Node: Function Calls375670 -Node: Precedence379550 -Node: Locales383210 -Node: Expressions Summary384842 -Node: Patterns and Actions387413 -Node: Pattern Overview388533 -Node: Regexp Patterns390212 -Node: Expression Patterns390755 -Node: Ranges394535 -Node: BEGIN/END397642 -Node: Using BEGIN/END398403 -Ref: Using BEGIN/END-Footnote-1401139 -Node: I/O And BEGIN/END401245 -Node: BEGINFILE/ENDFILE403560 -Node: Empty406457 -Node: Using Shell Variables406774 -Node: Action Overview409047 -Node: Statements411373 -Node: If Statement413221 -Node: While Statement414716 -Node: Do Statement416744 -Node: For Statement417892 -Node: Switch Statement421050 -Node: Break Statement423432 -Node: Continue Statement425525 -Node: Next Statement427352 -Node: Nextfile Statement429733 -Node: Exit Statement432361 -Node: Built-in Variables434772 -Node: User-modified435905 -Ref: User-modified-Footnote-1443539 -Node: Auto-set443601 -Ref: Auto-set-Footnote-1457310 -Ref: Auto-set-Footnote-2457515 -Node: ARGC and ARGV457571 -Node: Pattern Action Summary461789 -Node: Arrays464222 -Node: Array Basics465551 -Node: Array Intro466395 -Ref: figure-array-elements468332 -Ref: Array Intro-Footnote-1470955 -Node: Reference to Elements471083 -Node: Assigning Elements473545 -Node: Array Example474036 -Node: Scanning an Array475795 -Node: Controlling Scanning478818 -Ref: Controlling Scanning-Footnote-1484212 -Node: Numeric Array Subscripts484528 -Node: Uninitialized Subscripts486713 -Node: Delete488330 -Ref: Delete-Footnote-1491079 -Node: Multidimensional491136 -Node: Multiscanning494233 -Node: Arrays of Arrays495822 -Node: Arrays Summary500576 -Node: Functions502667 -Node: Built-in503706 -Node: Calling Built-in504784 -Node: Numeric Functions506779 -Ref: Numeric Functions-Footnote-1511597 -Ref: Numeric Functions-Footnote-2511954 -Ref: Numeric Functions-Footnote-3512002 -Node: String Functions512274 -Ref: String Functions-Footnote-1535775 -Ref: String Functions-Footnote-2535904 -Ref: String Functions-Footnote-3536152 -Node: Gory Details536239 -Ref: table-sub-escapes538020 -Ref: table-sub-proposed539535 -Ref: table-posix-sub540897 -Ref: table-gensub-escapes542434 -Ref: Gory Details-Footnote-1543267 -Node: I/O Functions543418 -Ref: I/O Functions-Footnote-1550654 -Node: Time Functions550801 -Ref: Time Functions-Footnote-1561310 -Ref: Time Functions-Footnote-2561378 -Ref: Time Functions-Footnote-3561536 -Ref: Time Functions-Footnote-4561647 -Ref: Time Functions-Footnote-5561759 -Ref: Time Functions-Footnote-6561986 -Node: Bitwise Functions562252 -Ref: table-bitwise-ops562814 -Ref: Bitwise Functions-Footnote-1567142 -Node: Type Functions567314 -Node: I18N Functions568466 -Node: User-defined570113 -Node: Definition Syntax570918 -Ref: Definition Syntax-Footnote-1576577 -Node: Function Example576648 -Ref: Function Example-Footnote-1579569 -Node: Function Caveats579591 -Node: Calling A Function580109 -Node: Variable Scope581067 -Node: Pass By Value/Reference584060 -Node: Return Statement587557 -Node: Dynamic Typing590536 -Node: Indirect Calls591465 -Ref: Indirect Calls-Footnote-1601330 -Node: Functions Summary601458 -Node: Library Functions604160 -Ref: Library Functions-Footnote-1607768 -Ref: Library Functions-Footnote-2607911 -Node: Library Names608082 -Ref: Library Names-Footnote-1611540 -Ref: Library Names-Footnote-2611763 -Node: General Functions611849 -Node: Strtonum Function612952 -Node: Assert Function615974 -Node: Round Function619298 -Node: Cliff Random Function620839 -Node: Ordinal Functions621855 -Ref: Ordinal Functions-Footnote-1624918 -Ref: Ordinal Functions-Footnote-2625170 -Node: Join Function625381 -Ref: Join Function-Footnote-1627151 -Node: Getlocaltime Function627351 -Node: Readfile Function631095 -Node: Shell Quoting633067 -Node: Data File Management634468 -Node: Filetrans Function635100 -Node: Rewind Function639196 -Node: File Checking640582 -Ref: File Checking-Footnote-1641915 -Node: Empty Files642116 -Node: Ignoring Assigns644095 -Node: Getopt Function645645 -Ref: Getopt Function-Footnote-1657109 -Node: Passwd Functions657309 -Ref: Passwd Functions-Footnote-1666149 -Node: Group Functions666237 -Ref: Group Functions-Footnote-1674134 -Node: Walking Arrays674339 -Node: Library Functions Summary677345 -Node: Library Exercises678747 -Node: Sample Programs680027 -Node: Running Examples680797 -Node: Clones681525 -Node: Cut Program682749 -Node: Egrep Program692469 -Ref: Egrep Program-Footnote-1699972 -Node: Id Program700082 -Node: Split Program703758 -Ref: Split Program-Footnote-1707212 -Node: Tee Program707340 -Node: Uniq Program710129 -Node: Wc Program717548 -Ref: Wc Program-Footnote-1721798 -Node: Miscellaneous Programs721892 -Node: Dupword Program723105 -Node: Alarm Program725136 -Node: Translate Program729941 -Ref: Translate Program-Footnote-1734504 -Node: Labels Program734774 -Ref: Labels Program-Footnote-1738125 -Node: Word Sorting738209 -Node: History Sorting742279 -Node: Extract Program744114 -Node: Simple Sed751638 -Node: Igawk Program754708 -Ref: Igawk Program-Footnote-1769034 -Ref: Igawk Program-Footnote-2769235 -Ref: Igawk Program-Footnote-3769357 -Node: Anagram Program769472 -Node: Signature Program772533 -Node: Programs Summary773780 -Node: Programs Exercises775001 -Ref: Programs Exercises-Footnote-1779132 -Node: Advanced Features779223 -Node: Nondecimal Data781205 -Node: Array Sorting782795 -Node: Controlling Array Traversal783495 -Ref: Controlling Array Traversal-Footnote-1791861 -Node: Array Sorting Functions791979 -Ref: Array Sorting Functions-Footnote-1795865 -Node: Two-way I/O796061 -Ref: Two-way I/O-Footnote-1801006 -Ref: Two-way I/O-Footnote-2801192 -Node: TCP/IP Networking801274 -Node: Profiling804146 -Node: Advanced Features Summary812417 -Node: Internationalization814350 -Node: I18N and L10N815830 -Node: Explaining gettext816516 -Ref: Explaining gettext-Footnote-1821541 -Ref: Explaining gettext-Footnote-2821725 -Node: Programmer i18n821890 -Ref: Programmer i18n-Footnote-1826766 -Node: Translator i18n826815 -Node: String Extraction827609 -Ref: String Extraction-Footnote-1828740 -Node: Printf Ordering828826 -Ref: Printf Ordering-Footnote-1831612 -Node: I18N Portability831676 -Ref: I18N Portability-Footnote-1834132 -Node: I18N Example834195 -Ref: I18N Example-Footnote-1836998 -Node: Gawk I18N837070 -Node: I18N Summary837714 -Node: Debugger839054 -Node: Debugging840076 -Node: Debugging Concepts840517 -Node: Debugging Terms842327 -Node: Awk Debugging844899 -Node: Sample Debugging Session845805 -Node: Debugger Invocation846339 -Node: Finding The Bug847724 -Node: List of Debugger Commands854203 -Node: Breakpoint Control855535 -Node: Debugger Execution Control859212 -Node: Viewing And Changing Data862571 -Node: Execution Stack865947 -Node: Debugger Info867582 -Node: Miscellaneous Debugger Commands871627 -Node: Readline Support876628 -Node: Limitations877522 -Node: Debugging Summary879637 -Node: Arbitrary Precision Arithmetic880811 -Node: Computer Arithmetic882227 -Ref: table-numeric-ranges885804 -Ref: Computer Arithmetic-Footnote-1886328 -Node: Math Definitions886385 -Ref: table-ieee-formats889680 -Ref: Math Definitions-Footnote-1890284 -Node: MPFR features890389 -Node: FP Math Caution892060 -Ref: FP Math Caution-Footnote-1893110 -Node: Inexactness of computations893479 -Node: Inexact representation894438 -Node: Comparing FP Values895796 -Node: Errors accumulate896878 -Node: Getting Accuracy898310 -Node: Try To Round901014 -Node: Setting precision901913 -Ref: table-predefined-precision-strings902597 -Node: Setting the rounding mode904426 -Ref: table-gawk-rounding-modes904790 -Ref: Setting the rounding mode-Footnote-1908242 -Node: Arbitrary Precision Integers908421 -Ref: Arbitrary Precision Integers-Footnote-1913319 -Node: POSIX Floating Point Problems913468 -Ref: POSIX Floating Point Problems-Footnote-1917347 -Node: Floating point summary917385 -Node: Dynamic Extensions919572 -Node: Extension Intro921124 -Node: Plugin License922389 -Node: Extension Mechanism Outline923186 -Ref: figure-load-extension923614 -Ref: figure-register-new-function925094 -Ref: figure-call-new-function926098 -Node: Extension API Description928085 -Node: Extension API Functions Introduction929535 -Node: General Data Types934356 -Ref: General Data Types-Footnote-1940256 -Node: Memory Allocation Functions940555 -Ref: Memory Allocation Functions-Footnote-1943394 -Node: Constructor Functions943493 -Node: Registration Functions945232 -Node: Extension Functions945917 -Node: Exit Callback Functions948214 -Node: Extension Version String949462 -Node: Input Parsers950125 -Node: Output Wrappers960000 -Node: Two-way processors964513 -Node: Printing Messages966776 -Ref: Printing Messages-Footnote-1967852 -Node: Updating `ERRNO'968004 -Node: Requesting Values968744 -Ref: table-value-types-returned969471 -Node: Accessing Parameters970428 -Node: Symbol Table Access971662 -Node: Symbol table by name972176 -Node: Symbol table by cookie974196 -Ref: Symbol table by cookie-Footnote-1978341 -Node: Cached values978404 -Ref: Cached values-Footnote-1981900 -Node: Array Manipulation981991 -Ref: Array Manipulation-Footnote-1983089 -Node: Array Data Types983126 -Ref: Array Data Types-Footnote-1985781 -Node: Array Functions985873 -Node: Flattening Arrays989732 -Node: Creating Arrays996634 -Node: Extension API Variables1001405 -Node: Extension Versioning1002041 -Node: Extension API Informational Variables1003932 -Node: Extension API Boilerplate1004997 -Node: Finding Extensions1008806 -Node: Extension Example1009366 -Node: Internal File Description1010138 -Node: Internal File Ops1014205 -Ref: Internal File Ops-Footnote-11025956 -Node: Using Internal File Ops1026096 -Ref: Using Internal File Ops-Footnote-11028479 -Node: Extension Samples1028752 -Node: Extension Sample File Functions1030280 -Node: Extension Sample Fnmatch1037961 -Node: Extension Sample Fork1039449 -Node: Extension Sample Inplace1040664 -Node: Extension Sample Ord1042750 -Node: Extension Sample Readdir1043586 -Ref: table-readdir-file-types1044463 -Node: Extension Sample Revout1045274 -Node: Extension Sample Rev2way1045863 -Node: Extension Sample Read write array1046603 -Node: Extension Sample Readfile1048543 -Node: Extension Sample Time1049638 -Node: Extension Sample API Tests1050986 -Node: gawkextlib1051477 -Node: Extension summary1054155 -Node: Extension Exercises1057844 -Node: Language History1058566 -Node: V7/SVR3.11060222 -Node: SVR41062375 -Node: POSIX1063809 -Node: BTL1065190 -Node: POSIX/GNU1065921 -Node: Feature History1071757 -Node: Common Extensions1085551 -Node: Ranges and Locales1086923 -Ref: Ranges and Locales-Footnote-11091542 -Ref: Ranges and Locales-Footnote-21091569 -Ref: Ranges and Locales-Footnote-31091804 -Node: Contributors1092025 -Node: History summary1097565 -Node: Installation1098944 -Node: Gawk Distribution1099890 -Node: Getting1100374 -Node: Extracting1101197 -Node: Distribution contents1102834 -Node: Unix Installation1108936 -Node: Quick Installation1109619 -Node: Shell Startup Files1112030 -Node: Additional Configuration Options1113109 -Node: Configuration Philosophy1114913 -Node: Non-Unix Installation1117282 -Node: PC Installation1117740 -Node: PC Binary Installation1119060 -Node: PC Compiling1120908 -Ref: PC Compiling-Footnote-11123929 -Node: PC Testing1124038 -Node: PC Using1125214 -Node: Cygwin1129329 -Node: MSYS1130099 -Node: VMS Installation1130600 -Node: VMS Compilation1131392 -Ref: VMS Compilation-Footnote-11132621 -Node: VMS Dynamic Extensions1132679 -Node: VMS Installation Details1134363 -Node: VMS Running1136614 -Node: VMS GNV1139454 -Node: VMS Old Gawk1140189 -Node: Bugs1140659 -Node: Other Versions1144548 -Node: Installation summary1150982 -Node: Notes1152041 -Node: Compatibility Mode1152906 -Node: Additions1153688 -Node: Accessing The Source1154613 -Node: Adding Code1156048 -Node: New Ports1162205 -Node: Derived Files1166687 -Ref: Derived Files-Footnote-11172162 -Ref: Derived Files-Footnote-21172196 -Ref: Derived Files-Footnote-31172792 -Node: Future Extensions1172906 -Node: Implementation Limitations1173512 -Node: Extension Design1174760 -Node: Old Extension Problems1175914 -Ref: Old Extension Problems-Footnote-11177431 -Node: Extension New Mechanism Goals1177488 -Ref: Extension New Mechanism Goals-Footnote-11180848 -Node: Extension Other Design Decisions1181037 -Node: Extension Future Growth1183145 -Node: Old Extension Mechanism1183981 -Node: Notes summary1185743 -Node: Basic Concepts1186929 -Node: Basic High Level1187610 -Ref: figure-general-flow1187882 -Ref: figure-process-flow1188481 -Ref: Basic High Level-Footnote-11191710 -Node: Basic Data Typing1191895 -Node: Glossary1195223 -Node: Copying1227152 -Node: GNU Free Documentation License1264708 -Node: Index1289844 +Node: Foreword342451 +Node: Foreword446895 +Node: Preface48426 +Ref: Preface-Footnote-151297 +Ref: Preface-Footnote-251404 +Ref: Preface-Footnote-351637 +Node: History51779 +Node: Names54130 +Ref: Names-Footnote-155224 +Node: This Manual55370 +Ref: This Manual-Footnote-161870 +Node: Conventions61970 +Node: Manual History64307 +Ref: Manual History-Footnote-167300 +Ref: Manual History-Footnote-267341 +Node: How To Contribute67415 +Node: Acknowledgments68544 +Node: Getting Started73410 +Node: Running gawk75849 +Node: One-shot77039 +Node: Read Terminal78303 +Node: Long80334 +Node: Executable Scripts81847 +Ref: Executable Scripts-Footnote-184636 +Node: Comments84739 +Node: Quoting87221 +Node: DOS Quoting92739 +Node: Sample Data Files93414 +Node: Very Simple96009 +Node: Two Rules100908 +Node: More Complex102794 +Node: Statements/Lines105656 +Ref: Statements/Lines-Footnote-1110111 +Node: Other Features110376 +Node: When111312 +Ref: When-Footnote-1113066 +Node: Intro Summary113131 +Node: Invoking Gawk114015 +Node: Command Line115529 +Node: Options116327 +Ref: Options-Footnote-1132122 +Ref: Options-Footnote-2132351 +Node: Other Arguments132376 +Node: Naming Standard Input135324 +Node: Environment Variables136417 +Node: AWKPATH Variable136975 +Ref: AWKPATH Variable-Footnote-1140382 +Ref: AWKPATH Variable-Footnote-2140427 +Node: AWKLIBPATH Variable140687 +Node: Other Environment Variables141943 +Node: Exit Status145574 +Node: Include Files146250 +Node: Loading Shared Libraries149839 +Node: Obsolete151266 +Node: Undocumented151958 +Node: Invoking Summary152225 +Node: Regexp153888 +Node: Regexp Usage155342 +Node: Escape Sequences157379 +Node: Regexp Operators163608 +Ref: Regexp Operators-Footnote-1171018 +Ref: Regexp Operators-Footnote-2171165 +Node: Bracket Expressions171263 +Ref: table-char-classes173278 +Node: Leftmost Longest176220 +Node: Computed Regexps177522 +Node: GNU Regexp Operators180951 +Node: Case-sensitivity184623 +Ref: Case-sensitivity-Footnote-1187508 +Ref: Case-sensitivity-Footnote-2187743 +Node: Regexp Summary187851 +Node: Reading Files189318 +Node: Records191480 +Node: awk split records192213 +Node: gawk split records197142 +Ref: gawk split records-Footnote-1201681 +Node: Fields201718 +Ref: Fields-Footnote-1204496 +Node: Nonconstant Fields204582 +Ref: Nonconstant Fields-Footnote-1206820 +Node: Changing Fields207023 +Node: Field Separators212954 +Node: Default Field Splitting215658 +Node: Regexp Field Splitting216775 +Node: Single Character Fields220125 +Node: Command Line Field Separator221184 +Node: Full Line Fields224401 +Ref: Full Line Fields-Footnote-1225922 +Ref: Full Line Fields-Footnote-2225968 +Node: Field Splitting Summary226069 +Node: Constant Size228143 +Node: Splitting By Content232722 +Ref: Splitting By Content-Footnote-1236687 +Node: Multiple Line236850 +Ref: Multiple Line-Footnote-1242731 +Node: Getline242910 +Node: Plain Getline245389 +Node: Getline/Variable248029 +Node: Getline/File249178 +Node: Getline/Variable/File250563 +Ref: Getline/Variable/File-Footnote-1252166 +Node: Getline/Pipe252253 +Node: Getline/Variable/Pipe254931 +Node: Getline/Coprocess256062 +Node: Getline/Variable/Coprocess257326 +Node: Getline Notes258065 +Node: Getline Summary260859 +Ref: table-getline-variants261271 +Node: Read Timeout262100 +Ref: Read Timeout-Footnote-1266003 +Node: Retrying Input266061 +Node: Command-line directories267256 +Node: Input Summary268163 +Node: Input Exercises271548 +Node: Printing272276 +Node: Print274111 +Node: Print Examples275568 +Node: Output Separators278347 +Node: OFMT280365 +Node: Printf281720 +Node: Basic Printf282505 +Node: Control Letters284077 +Node: Format Modifiers288062 +Node: Printf Examples294068 +Node: Redirection296554 +Node: Special FD303392 +Ref: Special FD-Footnote-1306558 +Node: Special Files306632 +Node: Other Inherited Files307249 +Node: Special Network308249 +Node: Special Caveats309111 +Node: Close Files And Pipes310060 +Ref: Close Files And Pipes-Footnote-1317245 +Ref: Close Files And Pipes-Footnote-2317393 +Node: Nonfatal317543 +Node: Output Summary319868 +Node: Output Exercises321089 +Node: Expressions321769 +Node: Values322958 +Node: Constants323635 +Node: Scalar Constants324326 +Ref: Scalar Constants-Footnote-1325188 +Node: Nondecimal-numbers325438 +Node: Regexp Constants328448 +Node: Using Constant Regexps328974 +Node: Variables332137 +Node: Using Variables332794 +Node: Assignment Options334705 +Node: Conversion336580 +Node: Strings And Numbers337104 +Ref: Strings And Numbers-Footnote-1340169 +Node: Locale influences conversions340278 +Ref: table-locale-affects343024 +Node: All Operators343616 +Node: Arithmetic Ops344245 +Node: Concatenation346750 +Ref: Concatenation-Footnote-1349569 +Node: Assignment Ops349676 +Ref: table-assign-ops354655 +Node: Increment Ops355965 +Node: Truth Values and Conditions359396 +Node: Truth Values360479 +Node: Typing and Comparison361528 +Node: Variable Typing362344 +Node: Comparison Operators366011 +Ref: table-relational-ops366421 +Node: POSIX String Comparison369916 +Ref: POSIX String Comparison-Footnote-1370988 +Node: Boolean Ops371127 +Ref: Boolean Ops-Footnote-1375605 +Node: Conditional Exp375696 +Node: Function Calls377434 +Node: Precedence381314 +Node: Locales384974 +Node: Expressions Summary386606 +Node: Patterns and Actions389177 +Node: Pattern Overview390297 +Node: Regexp Patterns391976 +Node: Expression Patterns392519 +Node: Ranges396299 +Node: BEGIN/END399406 +Node: Using BEGIN/END400167 +Ref: Using BEGIN/END-Footnote-1402903 +Node: I/O And BEGIN/END403009 +Node: BEGINFILE/ENDFILE405324 +Node: Empty408221 +Node: Using Shell Variables408538 +Node: Action Overview410811 +Node: Statements413137 +Node: If Statement414985 +Node: While Statement416480 +Node: Do Statement418508 +Node: For Statement419656 +Node: Switch Statement422814 +Node: Break Statement425196 +Node: Continue Statement427289 +Node: Next Statement429116 +Node: Nextfile Statement431497 +Node: Exit Statement434125 +Node: Built-in Variables436536 +Node: User-modified437669 +Ref: User-modified-Footnote-1445303 +Node: Auto-set445365 +Ref: Auto-set-Footnote-1459598 +Ref: Auto-set-Footnote-2459803 +Node: ARGC and ARGV459859 +Node: Pattern Action Summary464077 +Node: Arrays466510 +Node: Array Basics467839 +Node: Array Intro468683 +Ref: figure-array-elements470620 +Ref: Array Intro-Footnote-1473243 +Node: Reference to Elements473371 +Node: Assigning Elements475833 +Node: Array Example476324 +Node: Scanning an Array478083 +Node: Controlling Scanning481106 +Ref: Controlling Scanning-Footnote-1486500 +Node: Numeric Array Subscripts486816 +Node: Uninitialized Subscripts489001 +Node: Delete490618 +Ref: Delete-Footnote-1493367 +Node: Multidimensional493424 +Node: Multiscanning496521 +Node: Arrays of Arrays498110 +Node: Arrays Summary502864 +Node: Functions504955 +Node: Built-in505994 +Node: Calling Built-in507072 +Node: Numeric Functions509067 +Ref: Numeric Functions-Footnote-1513885 +Ref: Numeric Functions-Footnote-2514242 +Ref: Numeric Functions-Footnote-3514290 +Node: String Functions514562 +Ref: String Functions-Footnote-1538063 +Ref: String Functions-Footnote-2538192 +Ref: String Functions-Footnote-3538440 +Node: Gory Details538527 +Ref: table-sub-escapes540308 +Ref: table-sub-proposed541823 +Ref: table-posix-sub543185 +Ref: table-gensub-escapes544722 +Ref: Gory Details-Footnote-1545555 +Node: I/O Functions545706 +Ref: I/O Functions-Footnote-1552942 +Node: Time Functions553089 +Ref: Time Functions-Footnote-1563598 +Ref: Time Functions-Footnote-2563666 +Ref: Time Functions-Footnote-3563824 +Ref: Time Functions-Footnote-4563935 +Ref: Time Functions-Footnote-5564047 +Ref: Time Functions-Footnote-6564274 +Node: Bitwise Functions564540 +Ref: table-bitwise-ops565102 +Ref: Bitwise Functions-Footnote-1569430 +Node: Type Functions569602 +Node: I18N Functions570754 +Node: User-defined572401 +Node: Definition Syntax573206 +Ref: Definition Syntax-Footnote-1578865 +Node: Function Example578936 +Ref: Function Example-Footnote-1581857 +Node: Function Caveats581879 +Node: Calling A Function582397 +Node: Variable Scope583355 +Node: Pass By Value/Reference586348 +Node: Return Statement589845 +Node: Dynamic Typing592824 +Node: Indirect Calls593753 +Ref: Indirect Calls-Footnote-1603618 +Node: Functions Summary603746 +Node: Library Functions606448 +Ref: Library Functions-Footnote-1610056 +Ref: Library Functions-Footnote-2610199 +Node: Library Names610370 +Ref: Library Names-Footnote-1613828 +Ref: Library Names-Footnote-2614051 +Node: General Functions614137 +Node: Strtonum Function615240 +Node: Assert Function618262 +Node: Round Function621586 +Node: Cliff Random Function623127 +Node: Ordinal Functions624143 +Ref: Ordinal Functions-Footnote-1627206 +Ref: Ordinal Functions-Footnote-2627458 +Node: Join Function627669 +Ref: Join Function-Footnote-1629439 +Node: Getlocaltime Function629639 +Node: Readfile Function633383 +Node: Shell Quoting635355 +Node: Data File Management636756 +Node: Filetrans Function637388 +Node: Rewind Function641484 +Node: File Checking642870 +Ref: File Checking-Footnote-1644203 +Node: Empty Files644404 +Node: Ignoring Assigns646383 +Node: Getopt Function647933 +Ref: Getopt Function-Footnote-1659397 +Node: Passwd Functions659597 +Ref: Passwd Functions-Footnote-1668437 +Node: Group Functions668525 +Ref: Group Functions-Footnote-1676422 +Node: Walking Arrays676627 +Node: Library Functions Summary679633 +Node: Library Exercises681035 +Node: Sample Programs682315 +Node: Running Examples683085 +Node: Clones683813 +Node: Cut Program685037 +Node: Egrep Program694757 +Ref: Egrep Program-Footnote-1702260 +Node: Id Program702370 +Node: Split Program706046 +Ref: Split Program-Footnote-1709500 +Node: Tee Program709628 +Node: Uniq Program712417 +Node: Wc Program719836 +Ref: Wc Program-Footnote-1724086 +Node: Miscellaneous Programs724180 +Node: Dupword Program725393 +Node: Alarm Program727424 +Node: Translate Program732229 +Ref: Translate Program-Footnote-1736792 +Node: Labels Program737062 +Ref: Labels Program-Footnote-1740413 +Node: Word Sorting740497 +Node: History Sorting744567 +Node: Extract Program746402 +Node: Simple Sed753926 +Node: Igawk Program756996 +Ref: Igawk Program-Footnote-1771322 +Ref: Igawk Program-Footnote-2771523 +Ref: Igawk Program-Footnote-3771645 +Node: Anagram Program771760 +Node: Signature Program774821 +Node: Programs Summary776068 +Node: Programs Exercises777289 +Ref: Programs Exercises-Footnote-1781420 +Node: Advanced Features781511 +Node: Nondecimal Data783493 +Node: Array Sorting785083 +Node: Controlling Array Traversal785783 +Ref: Controlling Array Traversal-Footnote-1794149 +Node: Array Sorting Functions794267 +Ref: Array Sorting Functions-Footnote-1798153 +Node: Two-way I/O798349 +Ref: Two-way I/O-Footnote-1803294 +Ref: Two-way I/O-Footnote-2803480 +Node: TCP/IP Networking803562 +Node: Profiling806434 +Node: Advanced Features Summary814705 +Node: Internationalization816638 +Node: I18N and L10N818118 +Node: Explaining gettext818804 +Ref: Explaining gettext-Footnote-1823829 +Ref: Explaining gettext-Footnote-2824013 +Node: Programmer i18n824178 +Ref: Programmer i18n-Footnote-1829054 +Node: Translator i18n829103 +Node: String Extraction829897 +Ref: String Extraction-Footnote-1831028 +Node: Printf Ordering831114 +Ref: Printf Ordering-Footnote-1833900 +Node: I18N Portability833964 +Ref: I18N Portability-Footnote-1836420 +Node: I18N Example836483 +Ref: I18N Example-Footnote-1839286 +Node: Gawk I18N839358 +Node: I18N Summary840002 +Node: Debugger841342 +Node: Debugging842364 +Node: Debugging Concepts842805 +Node: Debugging Terms844615 +Node: Awk Debugging847187 +Node: Sample Debugging Session848093 +Node: Debugger Invocation848627 +Node: Finding The Bug850012 +Node: List of Debugger Commands856491 +Node: Breakpoint Control857823 +Node: Debugger Execution Control861500 +Node: Viewing And Changing Data864859 +Node: Execution Stack868235 +Node: Debugger Info869870 +Node: Miscellaneous Debugger Commands873915 +Node: Readline Support878916 +Node: Limitations879810 +Node: Debugging Summary881925 +Node: Arbitrary Precision Arithmetic883099 +Node: Computer Arithmetic884515 +Ref: table-numeric-ranges888092 +Ref: Computer Arithmetic-Footnote-1888616 +Node: Math Definitions888673 +Ref: table-ieee-formats891968 +Ref: Math Definitions-Footnote-1892572 +Node: MPFR features892677 +Node: FP Math Caution894348 +Ref: FP Math Caution-Footnote-1895398 +Node: Inexactness of computations895767 +Node: Inexact representation896726 +Node: Comparing FP Values898084 +Node: Errors accumulate899166 +Node: Getting Accuracy900598 +Node: Try To Round903302 +Node: Setting precision904201 +Ref: table-predefined-precision-strings904885 +Node: Setting the rounding mode906714 +Ref: table-gawk-rounding-modes907078 +Ref: Setting the rounding mode-Footnote-1910530 +Node: Arbitrary Precision Integers910709 +Ref: Arbitrary Precision Integers-Footnote-1915607 +Node: POSIX Floating Point Problems915756 +Ref: POSIX Floating Point Problems-Footnote-1919635 +Node: Floating point summary919673 +Node: Dynamic Extensions921860 +Node: Extension Intro923412 +Node: Plugin License924677 +Node: Extension Mechanism Outline925474 +Ref: figure-load-extension925902 +Ref: figure-register-new-function927382 +Ref: figure-call-new-function928386 +Node: Extension API Description930373 +Node: Extension API Functions Introduction931907 +Node: General Data Types936776 +Ref: General Data Types-Footnote-1942676 +Node: Memory Allocation Functions942975 +Ref: Memory Allocation Functions-Footnote-1945814 +Node: Constructor Functions945913 +Node: Registration Functions947652 +Node: Extension Functions948337 +Node: Exit Callback Functions950634 +Node: Extension Version String951882 +Node: Input Parsers952545 +Node: Output Wrappers962420 +Node: Two-way processors966933 +Node: Printing Messages969196 +Ref: Printing Messages-Footnote-1970272 +Node: Updating `ERRNO'970424 +Node: Requesting Values971164 +Ref: table-value-types-returned971891 +Node: Accessing Parameters972848 +Node: Symbol Table Access974082 +Node: Symbol table by name974596 +Node: Symbol table by cookie976616 +Ref: Symbol table by cookie-Footnote-1980761 +Node: Cached values980824 +Ref: Cached values-Footnote-1984320 +Node: Array Manipulation984411 +Ref: Array Manipulation-Footnote-1985501 +Node: Array Data Types985538 +Ref: Array Data Types-Footnote-1988193 +Node: Array Functions988285 +Node: Flattening Arrays992144 +Node: Creating Arrays999046 +Node: Redirection API1003817 +Node: Extension API Variables1006588 +Node: Extension Versioning1007221 +Node: Extension API Informational Variables1009112 +Node: Extension API Boilerplate1010177 +Node: Finding Extensions1013986 +Node: Extension Example1014546 +Node: Internal File Description1015318 +Node: Internal File Ops1019385 +Ref: Internal File Ops-Footnote-11031136 +Node: Using Internal File Ops1031276 +Ref: Using Internal File Ops-Footnote-11033659 +Node: Extension Samples1033932 +Node: Extension Sample File Functions1035460 +Node: Extension Sample Fnmatch1043141 +Node: Extension Sample Fork1044629 +Node: Extension Sample Inplace1045844 +Node: Extension Sample Ord1047930 +Node: Extension Sample Readdir1048766 +Ref: table-readdir-file-types1049643 +Node: Extension Sample Revout1050454 +Node: Extension Sample Rev2way1051043 +Node: Extension Sample Read write array1051783 +Node: Extension Sample Readfile1053723 +Node: Extension Sample Time1054818 +Node: Extension Sample API Tests1056166 +Node: gawkextlib1056657 +Node: Extension summary1059335 +Node: Extension Exercises1063024 +Node: Language History1063746 +Node: V7/SVR3.11065402 +Node: SVR41067555 +Node: POSIX1068989 +Node: BTL1070370 +Node: POSIX/GNU1071101 +Node: Feature History1076937 +Node: Common Extensions1090731 +Node: Ranges and Locales1092103 +Ref: Ranges and Locales-Footnote-11096722 +Ref: Ranges and Locales-Footnote-21096749 +Ref: Ranges and Locales-Footnote-31096984 +Node: Contributors1097205 +Node: History summary1102745 +Node: Installation1104124 +Node: Gawk Distribution1105070 +Node: Getting1105554 +Node: Extracting1106377 +Node: Distribution contents1108014 +Node: Unix Installation1114116 +Node: Quick Installation1114799 +Node: Shell Startup Files1117210 +Node: Additional Configuration Options1118289 +Node: Configuration Philosophy1120093 +Node: Non-Unix Installation1122462 +Node: PC Installation1122920 +Node: PC Binary Installation1124240 +Node: PC Compiling1126088 +Ref: PC Compiling-Footnote-11129109 +Node: PC Testing1129218 +Node: PC Using1130394 +Node: Cygwin1134509 +Node: MSYS1135279 +Node: VMS Installation1135780 +Node: VMS Compilation1136572 +Ref: VMS Compilation-Footnote-11137801 +Node: VMS Dynamic Extensions1137859 +Node: VMS Installation Details1139543 +Node: VMS Running1141794 +Node: VMS GNV1144634 +Node: VMS Old Gawk1145369 +Node: Bugs1145839 +Node: Other Versions1149728 +Node: Installation summary1156162 +Node: Notes1157221 +Node: Compatibility Mode1158086 +Node: Additions1158868 +Node: Accessing The Source1159793 +Node: Adding Code1161228 +Node: New Ports1167385 +Node: Derived Files1171867 +Ref: Derived Files-Footnote-11177342 +Ref: Derived Files-Footnote-21177376 +Ref: Derived Files-Footnote-31177972 +Node: Future Extensions1178086 +Node: Implementation Limitations1178692 +Node: Extension Design1179940 +Node: Old Extension Problems1181094 +Ref: Old Extension Problems-Footnote-11182611 +Node: Extension New Mechanism Goals1182668 +Ref: Extension New Mechanism Goals-Footnote-11186028 +Node: Extension Other Design Decisions1186217 +Node: Extension Future Growth1188325 +Node: Old Extension Mechanism1189161 +Node: Notes summary1190923 +Node: Basic Concepts1192109 +Node: Basic High Level1192790 +Ref: figure-general-flow1193062 +Ref: figure-process-flow1193661 +Ref: Basic High Level-Footnote-11196890 +Node: Basic Data Typing1197075 +Node: Glossary1200403 +Node: Copying1232332 +Node: GNU Free Documentation License1269888 +Node: Index1295024 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index 8005fe3f..68d35876 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -604,6 +604,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. @@ -945,6 +946,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 @@ -6327,6 +6329,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. @@ -8112,6 +8115,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. @@ -8767,7 +8775,8 @@ on a per-command or per-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 @@ -8777,6 +8786,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 @@ -14928,6 +14966,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} @@ -14996,6 +15039,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. @@ -15135,6 +15182,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}. @@ -31571,6 +31623,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 @@ -31646,6 +31699,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: @@ -33616,6 +33673,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 88e854a5..6991f8a8 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -599,6 +599,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. @@ -940,6 +941,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 @@ -6111,6 +6113,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. @@ -7712,6 +7715,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. @@ -8367,7 +8375,8 @@ on a per-command or per-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 @@ -8377,6 +8386,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 @@ -14256,6 +14294,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} @@ -14324,6 +14367,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. @@ -14463,6 +14510,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}. @@ -30662,6 +30714,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 @@ -30737,6 +30790,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: @@ -32707,6 +32764,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 5d8c7b8a..334c97af 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -34,11 +34,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 @@ -210,6 +278,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,7 +788,6 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, tmp = awk_value_to_node(index); aptr = assoc_lookup(array, tmp); - unref(tmp); unref(*aptr); elem = *aptr = awk_value_to_node(value); if (elem->type == Node_var_array) { @@ -791,6 +795,9 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, elem->vname = estrdup(index->str_value.str, index->str_value.len); } + if (array->astore != NULL) + (*array->astore)(array, tmp); + unref(tmp); return awk_true; } @@ -1034,6 +1041,90 @@ api_release_value(awk_ext_id_t id, awk_value_cookie_t value) return awk_true; } +/* api_get_file --- return a handle to an existing or newly opened file */ + +static awk_bool_t +api_get_file(awk_ext_id_t id, const char *name, size_t namelen, const char *filetype, int fd, const awk_input_buf_t **ibufp, const awk_output_buf_t **obufp) +{ + const struct redirect *f; + int flag; /* not used, sigh */ + enum redirval redirtype; + + if ((name == NULL) || (namelen == 0)) { + if (curfile == NULL) { + if (nextfile(& curfile, false) <= 0) + return awk_false; + { + INSTRUCTION *pc = main_beginfile; + /* save execution state */ + int save_rule = currule; + char *save_source = source; + + while (1) { + if (!pc) + fatal(_("cannot find end of BEGINFILE rule")); + if (pc->opcode == Op_after_beginfile) + break; + pc = pc->nexti; + } + pc->opcode = Op_stop; + (void) (*interpret)(main_beginfile); + pc->opcode = Op_after_beginfile; + after_beginfile(& curfile); + /* restore execution state */ + currule = save_rule; + source = save_source; + } + } + *ibufp = &curfile->public; + *obufp = NULL; + return awk_true; + } + redirtype = redirect_none; + switch (filetype[0]) { + case '<': + if (filetype[1] == '\0') + redirtype = redirect_input; + break; + case '>': + switch (filetype[1]) { + case '\0': + redirtype = redirect_output; + break; + case '>': + if (filetype[2] == '\0') + redirtype = redirect_append; + break; + } + break; + case '|': + if (filetype[2] == '\0') { + switch (filetype[1]) { + case '>': + redirtype = redirect_pipe; + break; + case '<': + redirtype = redirect_pipein; + break; + case '&': + redirtype = redirect_twoway; + break; + } + } + break; + } + if (redirtype == redirect_none) { + warning(_("cannot open unrecognized file type `%s' for `%s'"), + filetype, name); + return awk_false; + } + if ((f = redirect_string(name, namelen, 0, redirtype, &flag, fd, false)) == NULL) + return awk_false; + *ibufp = f->iop ? & f->iop->public : NULL; + *obufp = f->output.fp ? & f->output : NULL; + return awk_true; +} + /* * Register a version string for this extension with gawk. */ @@ -1119,6 +1210,9 @@ gawk_api_t api_impl = { calloc, realloc, free, + + /* Find/open a file */ + api_get_file, }; /* init_ext_api --- init the extension API */ @@ -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)) @@ -271,7 +271,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); @@ -595,7 +595,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); @@ -726,10 +727,10 @@ redflags2str(int flags) /* redirect --- Redirection for printf and print commands */ struct redirect * -redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) +redirect_string(const char *str, size_t explen, bool not_string, + int redirtype, int *errflg, int extfd, bool failure_fatal) { struct redirect *rp; - char *str; int tflag = 0; int outflag = 0; const char *direction = "to"; @@ -778,18 +779,16 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) 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); @@ -827,8 +826,8 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) #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))) { @@ -839,23 +838,25 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) 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; @@ -887,6 +888,10 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) 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(); @@ -906,6 +911,10 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) 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)"), @@ -913,7 +922,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) 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) */ @@ -930,8 +939,14 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) } 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)) { if (! failure_fatal || is_non_fatal_redirect(str)) { *errflg = errno; /* do not free rp, saving it for reuse (save_rp = rp) */ @@ -948,7 +963,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) 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)) @@ -1050,6 +1065,15 @@ redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) return rp; } +struct redirect * +redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) +{ + 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, failure_fatal); +} + /* getredirect --- find the struct redirect for this file or pipe */ struct redirect * @@ -1758,16 +1782,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) @@ -2227,17 +2251,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; @@ -2254,10 +2304,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); @@ -2275,10 +2336,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; } @@ -2499,7 +2566,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) { @@ -2549,7 +2616,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) @@ -3442,10 +3509,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 @@ -3489,8 +3590,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; @@ -3564,6 +3667,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 28c479d6..69b5b60d 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -112,6 +112,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. @@ -146,6 +174,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 d2cd0ddd..2d3e353d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -178,6 +178,8 @@ EXTRA_DIST = \ dbugeval.ok \ defref.awk \ defref.ok \ + defvar.awk \ + defvar.ok \ delargv.awk \ delargv.ok \ delarpm2.awk \ @@ -212,6 +214,9 @@ EXTRA_DIST = \ dynlj.ok \ eofsplit.awk \ eofsplit.ok \ + errno.awk \ + errno.in \ + errno.ok \ exit.ok \ exit.sh \ exit2.awk \ @@ -340,6 +345,8 @@ EXTRA_DIST = \ gensub.ok \ gensub2.awk \ gensub2.ok \ + getfile.awk \ + getfile.ok \ getline.awk \ getline.in \ getline.ok \ @@ -948,6 +955,8 @@ EXTRA_DIST = \ testext.ok \ time.awk \ time.ok \ + timeout.awk \ + timeout.ok \ tradanch.awk \ tradanch.in \ tradanch.ok \ @@ -1047,7 +1056,7 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ backw badargs beginfile1 beginfile2 binmode1 charasbytes \ - colonwarn clos1way crlf dbugeval delsub devfd devfd1 devfd2 dumpvars exit \ + colonwarn clos1way crlf dbugeval delsub devfd devfd1 devfd2 dumpvars errno exit \ fieldwdth fpat1 fpat2 fpat3 fpat4 fpatnull fsfwfs funlen \ functab1 functab2 functab3 fwtest fwtest2 fwtest3 \ genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops \ @@ -1065,7 +1074,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 @@ -1082,7 +1092,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: @@ -1341,6 +1351,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 >_$@ @@ -1934,6 +1949,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 cf8093b8..5a3f5b0d 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -435,6 +435,8 @@ EXTRA_DIST = \ dbugeval.ok \ defref.awk \ defref.ok \ + defvar.awk \ + defvar.ok \ delargv.awk \ delargv.ok \ delarpm2.awk \ @@ -469,6 +471,9 @@ EXTRA_DIST = \ dynlj.ok \ eofsplit.awk \ eofsplit.ok \ + errno.awk \ + errno.in \ + errno.ok \ exit.ok \ exit.sh \ exit2.awk \ @@ -597,6 +602,8 @@ EXTRA_DIST = \ gensub.ok \ gensub2.awk \ gensub2.ok \ + getfile.awk \ + getfile.ok \ getline.awk \ getline.in \ getline.ok \ @@ -1205,6 +1212,8 @@ EXTRA_DIST = \ testext.ok \ time.awk \ time.ok \ + timeout.awk \ + timeout.ok \ tradanch.awk \ tradanch.in \ tradanch.ok \ @@ -1303,7 +1312,7 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ backw badargs beginfile1 beginfile2 binmode1 charasbytes \ - colonwarn clos1way crlf dbugeval delsub devfd devfd1 devfd2 dumpvars exit \ + colonwarn clos1way crlf dbugeval delsub devfd devfd1 devfd2 dumpvars errno exit \ fieldwdth fpat1 fpat2 fpat3 fpat4 fpatnull fsfwfs funlen \ functab1 functab2 functab3 fwtest fwtest2 fwtest3 \ genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops \ @@ -1321,7 +1330,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 @@ -1335,7 +1345,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 @@ -1779,6 +1789,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 >_$@ @@ -2371,6 +2386,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.; \ @@ -3797,6 +3822,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 5011fb1f..703e91e1 100644 --- a/test/Maketests +++ b/test/Maketests @@ -1297,6 +1297,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 |