diff options
-rw-r--r-- | ChangeLog | 176 | ||||
-rw-r--r-- | awk.h | 2 | ||||
-rw-r--r-- | awkgram.c | 721 | ||||
-rw-r--r-- | awkgram.y | 3 | ||||
-rw-r--r-- | configh.in | 6 | ||||
-rwxr-xr-x | configure | 5 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | doc/ChangeLog | 19 | ||||
-rw-r--r-- | doc/gawk.1 | 45 | ||||
-rw-r--r-- | doc/gawk.info | 1340 | ||||
-rw-r--r-- | doc/gawk.texi | 115 | ||||
-rw-r--r-- | doc/gawktexi.in | 115 | ||||
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | extension/ChangeLog | 170 | ||||
-rw-r--r-- | extension/testext.c | 193 | ||||
-rw-r--r-- | gawkapi.c | 96 | ||||
-rw-r--r-- | gawkapi.h | 40 | ||||
-rw-r--r-- | io.c | 160 | ||||
-rw-r--r-- | test/ChangeLog | 32 | ||||
-rw-r--r-- | test/Makefile.am | 31 | ||||
-rw-r--r-- | test/Makefile.in | 36 | ||||
-rw-r--r-- | test/Maketests | 5 | ||||
-rw-r--r-- | test/defvar.awk | 3 | ||||
-rw-r--r-- | test/defvar.ok | 5 | ||||
-rw-r--r-- | test/errno.awk | 10 | ||||
-rw-r--r-- | test/errno.in | 3 | ||||
-rw-r--r-- | test/errno.ok | 3 | ||||
-rw-r--r-- | test/getfile.awk | 35 | ||||
-rw-r--r-- | test/getfile.ok | 17 | ||||
-rw-r--r-- | test/testext.ok | 6 | ||||
-rw-r--r-- | test/timeout.awk | 26 | ||||
-rw-r--r-- | test/timeout.ok | 12 |
32 files changed, 2424 insertions, 1015 deletions
@@ -70,6 +70,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. @@ -88,6 +104,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 @@ -214,6 +283,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. @@ -1382,6 +1481,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 @@ -1392,6 +1530,44 @@ force_string redundant, since node_to_awk_value does that internally when we request a string. +2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * eval.c (update_ERRNO_string): Set PROCINFO["errno"] to 0. + * io.c (inrec): Since get_a_record may now return -2, be sure + to throw an error in that case as well. + (wait_any): Fix what appears to be a bug. The old logic repeatedly + called wait until it failed. When a process has multiple children, + this causes it to stall until all of them have exited. Instead, + we now exit the function after the first successful wait call. + (do_getline_redir, do_getline): Handle case where get_a_record + returns -2. + (errno_io_retry): New function to decide whether an I/O operation should + be retried. + (get_a_record): When read returns an error, call errno_io_retry to + decide whether the operation should be retried. If so, return -2 + instead of setting the IOP_AT_EOF flag. + +2013-07-01 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * eval.c (update_ERRNO_int, unset_ERRNO): Update PROCINFO["errno"]. + +2013-06-30 Andrew J. Schorr <aschorr@telemetry-investments.com> + * awk.h (redirect_string): Declare new function that provides API access + to the redirection mechanism. + * gawkapi.h (GAWK_API_MINOR_VERSION): Bump from 0 to 1 since 2 new + hooks were added to the api. + (gawk_api_t): Add 2 new functions api_lookup_file and api_get_file. + (lookup_file, get_file): New macros to wrap the new API functions. + * gawkapi.c (curfile): Declare this extern, since it is needed + by lookup_file and get_flie. + (api_lookup_file): Find an open file using curfile or getredirect(). + (api_get_file): Find or open a file using curfile or redirect_string(). + (api_impl): Add api_lookup_file and api_get_file. + * io.c (redirect_string): Renamed from redirect and changed arguments + to take a string instead of a 'NODE *'. This allows it to be called + through the API's new get_file hook. + (redirect): Now implemented by calling redirect_string backend function. + 2013-07-04 Arnold D. Robbins <arnold@skeeve.com> * builtin.c (format_tree): Fixes for %c with multibyte characters @@ -1483,6 +1483,7 @@ extern void set_FNR(void); extern void set_NR(void); extern struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg); +extern struct redirect *redirect_string(const char *redir_exp_str, size_t redir_exp_len, int not_string_flag, int redirtype, int *errflg, int extfd); extern NODE *do_close(int nargs); extern int flush_io(void); extern int close_io(bool *stdio_problem); @@ -1501,6 +1502,7 @@ extern int is_off_limits_var(const char *var); extern char *estrdup(const char *str, size_t len); extern void update_global_values(); extern long getenv_long(const char *name); +extern void after_beginfile(IOBUF **curfile); /* mpfr.c */ extern void set_PREC(void); @@ -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; @@ -171,6 +171,9 @@ /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID +/* Define to 1 if you have the `sigprocmask' function. */ +#undef HAVE_SIGPROCMASK + /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF @@ -296,6 +299,9 @@ /* Define to 1 if you have the `usleep' function. */ #undef HAVE_USLEEP +/* Define to 1 if you have the `waitpid' function. */ +#undef HAVE_WAITPID + /* Define to 1 if you have the <wchar.h> header file. */ #undef HAVE_WCHAR_H @@ -10294,9 +10294,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 548a3ce3..8662ca2b 100644 --- a/configure.ac +++ b/configure.ac @@ -273,9 +273,10 @@ esac AC_CHECK_FUNCS(atexit btowc fmod getgrent getgroups grantpt \ isascii iswctype iswlower iswupper mbrlen \ memcmp memcpy memcpy_ulong memmove memset \ - memset_ulong mkstemp posix_openpt setenv setlocale setsid snprintf strchr \ + memset_ulong mkstemp posix_openpt setenv setlocale setsid sigprocmask \ + snprintf strchr \ strerror strftime strcasecmp strncasecmp strcoll strtod strtoul \ - system tmpfile towlower towupper tzset usleep wcrtomb \ + system tmpfile towlower towupper tzset usleep waitpid wcrtomb \ wcscoll wctype) dnl this check is for both mbrtowc and the mbstate_t type, which is good AC_FUNC_MBRTOWC diff --git a/doc/ChangeLog b/doc/ChangeLog index 22636fe7..9b7d31db 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -42,6 +42,25 @@ * gawkinet.texi: Fix capitalization in document title. * gawktexi.in: Here we again: Starting on more O'Reilly fixes. +2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in: Improve get_file documentation. + +2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in: Replace "Retrying I/O" with "Retrying Input", since this + feature pertains to input, not output. + +2015-01-04 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in: Document the get_file API function. + +2015-01-04 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawk.1: Document new features PROCINFO["errno"] and + PROCINFO["input", "RETRY"], and new getline return value of -2. + * gawktexi.in: Ditto. + 2014-12-26 Antonio Giovanni Colombo <azc100@gmail.com> * gawktexi.in (Glossary): Really sort the items. @@ -942,6 +942,15 @@ then will contain a string describing the error. The value is subject to translation in non-English locales. +If the string in +.B ERRNO +corresponds to a system error in the +.IR errno (3) +variable, then the numeric value can be found in +.B PROCINFO["errno"]. +For non-system errors, +.B PROCINFO["errno"] +will be zero. .TP .B FIELDWIDTHS A whitespace separated list of field widths. When set, @@ -1103,6 +1112,13 @@ system call. The default time format string for .BR strftime() . .TP +\fBPROCINFO["errno"]\fP +The value of +.IR errno (3) +when +.BR ERRNO +is set to the associated error message. +.TP \fBPROCINFO["euid"]\fP The value of the .IR geteuid (2) @@ -1221,6 +1237,28 @@ where is a redirection string or a filename. A value of zero or less than zero means no timeout. .TP +\fBPROCINFO["input", "RETRY"]\fP +If an I/O error that may be retried occurs when reading data from +.IR input , +and this array entry exists, then +.BR getline +will return -2 instead of following the default behavior of returning -1 +and configuring +.IR input +to return no further data. +An I/O error that may be retried is one where +.IR errno (3) +has the value +.IR EAGAIN , +.IR EWOULDBLOCK , +.IR EINTR , +or +.IR ETIMEDOUT . +This may be useful in conjunction with +\fBPROCINFO["input", "READ_TIMEOUT"]\fP +or situations where a file descriptor has been configured to behave in a +non-blocking fashion. +.TP \fBPROCINFO["mpfr_version"]\fP The version of the GNU MPFR library used for arbitrary precision number support in @@ -2289,6 +2327,13 @@ below.) The .B getline command returns 1 on success, 0 on end of file, and \-1 on an error. +If the +.IR errno (3) +value indicates that the I/O operation may be retried, +and \fBPROCINFO["input", "RETRY"]\fP +is set, then \-2 will be returned instead of \-1, and further calls to +.B getline +may be attempted. Upon an error, .B ERRNO is set to a string describing the problem. diff --git a/doc/gawk.info b/doc/gawk.info index 0329a038..15f5d978 100644 --- a/doc/gawk.info +++ b/doc/gawk.info @@ -217,6 +217,7 @@ entitled "GNU Free Documentation License". `getline'. * Getline Summary:: Summary of `getline' Variants. * Read Timeout:: Reading input with a timeout. +* Retrying Input:: Retrying input after certain errors. * Command-line directories:: What happens if you put a directory on the command line. * Input Summary:: Input summary. @@ -557,6 +558,7 @@ entitled "GNU Free Documentation License". * Array Functions:: Functions for working with arrays. * Flattening Arrays:: How to flatten arrays. * Creating Arrays:: How to create and populate arrays. +* Redirection API:: How to access and manipulate redirections. * Extension API Variables:: Variables provided by the API. * Extension Versioning:: API Version information. * Extension API Informational Variables:: Variables providing information about @@ -4170,6 +4172,7 @@ have to be named on the `awk' command line (*note Getline::). * Getline:: Reading files under explicit program control using the `getline' function. * Read Timeout:: Reading input with a timeout. +* Retrying Input:: Retrying input after certain errors. * Command-line directories:: What happens if you put a directory on the command line. * Input Summary:: Input summary. @@ -5440,7 +5443,11 @@ how `awk' works. encounters the end of the file. If there is some error in getting a record, such as a file that cannot be opened, then `getline' returns -1. In this case, `gawk' sets the variable `ERRNO' to a string -describing the error that occurred. +describing the error that occurred. If the `errno' variable indicates +that the I/O operation may be retried, and `PROCINFO["input", "RETRY"]' +is set, then -2 will be returned instead of -1, and further calls to +`getline' may be attemped. *Note Retrying Input::, for further +information about this feature. In the following examples, COMMAND stands for a string value that represents a shell command. @@ -5878,7 +5885,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 ================================= @@ -5957,7 +5964,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 @@ -5972,9 +5980,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 @@ -5997,7 +6032,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 @@ -6071,7 +6106,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 @@ -10367,6 +10402,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 @@ -10415,6 +10455,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. @@ -10525,6 +10569,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::. @@ -22899,6 +22947,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. @@ -22959,6 +23008,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 @@ -24165,7 +24217,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 -------------------------- @@ -24650,9 +24702,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 @@ -24669,7 +24784,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 @@ -24718,7 +24833,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 @@ -24753,7 +24868,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 @@ -32417,9 +32532,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) @@ -32613,7 +32728,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) @@ -32636,7 +32751,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) @@ -32644,9 +32759,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. @@ -32654,7 +32771,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 152) * differences in awk and gawk, trunc-mod operation: Arithmetic Ops. @@ -32695,8 +32812,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) @@ -32811,7 +32928,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) @@ -32892,7 +33009,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) @@ -32960,9 +33077,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. @@ -33012,7 +33129,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) @@ -33062,7 +33179,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) @@ -33097,7 +33214,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. @@ -33129,7 +33246,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. @@ -33137,14 +33254,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 152) * gawk, timestamps: Time Functions. (line 6) * gawk, uses for: Preface. (line 34) @@ -33236,7 +33353,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. @@ -33531,7 +33648,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) @@ -33544,7 +33661,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) @@ -33593,7 +33710,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. @@ -33602,9 +33719,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. @@ -33718,7 +33835,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) @@ -33884,24 +34001,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) @@ -34036,6 +34153,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) @@ -34059,7 +34177,7 @@ Index * right shift: Bitwise Functions. (line 53) * right shift, bitwise: Bitwise Functions. (line 32) * Ritchie, Dennis: Basic Data Typing. (line 54) -* RLENGTH variable: Auto-set. (line 266) +* RLENGTH variable: Auto-set. (line 279) * RLENGTH variable, match() function and: String Functions. (line 228) * Robbins, Arnold <1>: Future Extensions. (line 6) * Robbins, Arnold <2>: Bugs. (line 70) @@ -34085,9 +34203,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) @@ -34107,7 +34225,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) @@ -34190,7 +34308,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. @@ -34352,9 +34470,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) @@ -34531,10 +34649,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) @@ -34624,560 +34742,562 @@ Index Tag Table: Node: Top1204 -Node: Foreword342225 -Node: Foreword446669 -Node: Preface48200 -Ref: Preface-Footnote-151071 -Ref: Preface-Footnote-251178 -Ref: Preface-Footnote-351411 -Node: History51553 -Node: Names53904 -Ref: Names-Footnote-154997 -Node: This Manual55143 -Ref: This Manual-Footnote-161643 -Node: Conventions61743 -Node: Manual History64080 -Ref: Manual History-Footnote-167073 -Ref: Manual History-Footnote-267114 -Node: How To Contribute67188 -Node: Acknowledgments68317 -Node: Getting Started73134 -Node: Running gawk75573 -Node: One-shot76763 -Node: Read Terminal78027 -Node: Long80058 -Node: Executable Scripts81571 -Ref: Executable Scripts-Footnote-184360 -Node: Comments84463 -Node: Quoting86945 -Node: DOS Quoting92463 -Node: Sample Data Files93138 -Node: Very Simple95733 -Node: Two Rules100632 -Node: More Complex102518 -Node: Statements/Lines105380 -Ref: Statements/Lines-Footnote-1109835 -Node: Other Features110100 -Node: When111036 -Ref: When-Footnote-1112790 -Node: Intro Summary112855 -Node: Invoking Gawk113739 -Node: Command Line115253 -Node: Options116051 -Ref: Options-Footnote-1131846 -Ref: Options-Footnote-2132075 -Node: Other Arguments132100 -Node: Naming Standard Input135048 -Node: Environment Variables136141 -Node: AWKPATH Variable136699 -Ref: AWKPATH Variable-Footnote-1140106 -Ref: AWKPATH Variable-Footnote-2140151 -Node: AWKLIBPATH Variable140411 -Node: Other Environment Variables141667 -Node: Exit Status145185 -Node: Include Files145861 -Node: Loading Shared Libraries149450 -Node: Obsolete150877 -Node: Undocumented151569 -Node: Invoking Summary151836 -Node: Regexp153499 -Node: Regexp Usage154953 -Node: Escape Sequences156990 -Node: Regexp Operators163230 -Ref: Regexp Operators-Footnote-1170640 -Ref: Regexp Operators-Footnote-2170787 -Node: Bracket Expressions170885 -Ref: table-char-classes172900 -Node: Leftmost Longest175842 -Node: Computed Regexps177144 -Node: GNU Regexp Operators180573 -Node: Case-sensitivity184245 -Ref: Case-sensitivity-Footnote-1187130 -Ref: Case-sensitivity-Footnote-2187365 -Node: Regexp Summary187473 -Node: Reading Files188940 -Node: Records191033 -Node: awk split records191766 -Node: gawk split records196695 -Ref: gawk split records-Footnote-1201234 -Node: Fields201271 -Ref: Fields-Footnote-1204049 -Node: Nonconstant Fields204135 -Ref: Nonconstant Fields-Footnote-1206373 -Node: Changing Fields206576 -Node: Field Separators212507 -Node: Default Field Splitting215211 -Node: Regexp Field Splitting216328 -Node: Single Character Fields219678 -Node: Command Line Field Separator220737 -Node: Full Line Fields223954 -Ref: Full Line Fields-Footnote-1225475 -Ref: Full Line Fields-Footnote-2225521 -Node: Field Splitting Summary225622 -Node: Constant Size227696 -Node: Splitting By Content232279 -Ref: Splitting By Content-Footnote-1236244 -Node: Multiple Line236407 -Ref: Multiple Line-Footnote-1242288 -Node: Getline242467 -Node: Plain Getline244674 -Node: Getline/Variable247314 -Node: Getline/File248463 -Node: Getline/Variable/File249848 -Ref: Getline/Variable/File-Footnote-1251451 -Node: Getline/Pipe251538 -Node: Getline/Variable/Pipe254216 -Node: Getline/Coprocess255347 -Node: Getline/Variable/Coprocess256611 -Node: Getline Notes257350 -Node: Getline Summary260144 -Ref: table-getline-variants260556 -Node: Read Timeout261385 -Ref: Read Timeout-Footnote-1265222 -Node: Command-line directories265280 -Node: Input Summary266185 -Node: Input Exercises269570 -Node: Printing270298 -Node: Print272075 -Node: Print Examples273532 -Node: Output Separators276311 -Node: OFMT278329 -Node: Printf279684 -Node: Basic Printf280469 -Node: Control Letters282041 -Node: Format Modifiers286026 -Node: Printf Examples292036 -Node: Redirection294522 -Node: Special FD301360 -Ref: Special FD-Footnote-1304526 -Node: Special Files304600 -Node: Other Inherited Files305217 -Node: Special Network306217 -Node: Special Caveats307079 -Node: Close Files And Pipes308028 -Ref: Close Files And Pipes-Footnote-1315219 -Ref: Close Files And Pipes-Footnote-2315367 -Node: Output Summary315517 -Node: Output Exercises316515 -Node: Expressions317195 -Node: Values318384 -Node: Constants319061 -Node: Scalar Constants319752 -Ref: Scalar Constants-Footnote-1320614 -Node: Nondecimal-numbers320864 -Node: Regexp Constants323874 -Node: Using Constant Regexps324400 -Node: Variables327563 -Node: Using Variables328220 -Node: Assignment Options330131 -Node: Conversion332006 -Node: Strings And Numbers332530 -Ref: Strings And Numbers-Footnote-1335595 -Node: Locale influences conversions335704 -Ref: table-locale-affects338450 -Node: All Operators339042 -Node: Arithmetic Ops339671 -Node: Concatenation342176 -Ref: Concatenation-Footnote-1344995 -Node: Assignment Ops345102 -Ref: table-assign-ops350081 -Node: Increment Ops351391 -Node: Truth Values and Conditions354822 -Node: Truth Values355905 -Node: Typing and Comparison356954 -Node: Variable Typing357770 -Node: Comparison Operators361437 -Ref: table-relational-ops361847 -Node: POSIX String Comparison365342 -Ref: POSIX String Comparison-Footnote-1366414 -Node: Boolean Ops366553 -Ref: Boolean Ops-Footnote-1371031 -Node: Conditional Exp371122 -Node: Function Calls372860 -Node: Precedence376740 -Node: Locales380400 -Node: Expressions Summary382032 -Node: Patterns and Actions384603 -Node: Pattern Overview385723 -Node: Regexp Patterns387402 -Node: Expression Patterns387945 -Node: Ranges391654 -Node: BEGIN/END394761 -Node: Using BEGIN/END395522 -Ref: Using BEGIN/END-Footnote-1398258 -Node: I/O And BEGIN/END398364 -Node: BEGINFILE/ENDFILE400679 -Node: Empty403576 -Node: Using Shell Variables403893 -Node: Action Overview406166 -Node: Statements408492 -Node: If Statement410340 -Node: While Statement411835 -Node: Do Statement413863 -Node: For Statement415011 -Node: Switch Statement418169 -Node: Break Statement420551 -Node: Continue Statement422592 -Node: Next Statement424419 -Node: Nextfile Statement426800 -Node: Exit Statement429428 -Node: Built-in Variables431839 -Node: User-modified432972 -Ref: User-modified-Footnote-1440675 -Node: Auto-set440737 -Ref: Auto-set-Footnote-1454446 -Ref: Auto-set-Footnote-2454651 -Node: ARGC and ARGV454707 -Node: Pattern Action Summary458925 -Node: Arrays461358 -Node: Array Basics462687 -Node: Array Intro463531 -Ref: figure-array-elements465465 -Ref: Array Intro-Footnote-1468085 -Node: Reference to Elements468213 -Node: Assigning Elements470675 -Node: Array Example471166 -Node: Scanning an Array472925 -Node: Controlling Scanning475945 -Ref: Controlling Scanning-Footnote-1481339 -Node: Numeric Array Subscripts481655 -Node: Uninitialized Subscripts483840 -Node: Delete485457 -Ref: Delete-Footnote-1488206 -Node: Multidimensional488263 -Node: Multiscanning491360 -Node: Arrays of Arrays492949 -Node: Arrays Summary497703 -Node: Functions499794 -Node: Built-in500833 -Node: Calling Built-in501911 -Node: Numeric Functions503906 -Ref: Numeric Functions-Footnote-1508724 -Ref: Numeric Functions-Footnote-2509081 -Ref: Numeric Functions-Footnote-3509129 -Node: String Functions509401 -Ref: String Functions-Footnote-1532902 -Ref: String Functions-Footnote-2533031 -Ref: String Functions-Footnote-3533279 -Node: Gory Details533366 -Ref: table-sub-escapes535147 -Ref: table-sub-proposed536662 -Ref: table-posix-sub538024 -Ref: table-gensub-escapes539561 -Ref: Gory Details-Footnote-1540394 -Node: I/O Functions540545 -Ref: I/O Functions-Footnote-1547781 -Node: Time Functions547928 -Ref: Time Functions-Footnote-1558437 -Ref: Time Functions-Footnote-2558505 -Ref: Time Functions-Footnote-3558663 -Ref: Time Functions-Footnote-4558774 -Ref: Time Functions-Footnote-5558886 -Ref: Time Functions-Footnote-6559113 -Node: Bitwise Functions559379 -Ref: table-bitwise-ops559941 -Ref: Bitwise Functions-Footnote-1564253 -Node: Type Functions564425 -Node: I18N Functions565576 -Node: User-defined567221 -Node: Definition Syntax568026 -Ref: Definition Syntax-Footnote-1573658 -Node: Function Example573729 -Ref: Function Example-Footnote-1576648 -Node: Function Caveats576670 -Node: Calling A Function577188 -Node: Variable Scope578146 -Node: Pass By Value/Reference581134 -Node: Return Statement584629 -Node: Dynamic Typing587610 -Node: Indirect Calls588539 -Ref: Indirect Calls-Footnote-1599841 -Node: Functions Summary599969 -Node: Library Functions602671 -Ref: Library Functions-Footnote-1606280 -Ref: Library Functions-Footnote-2606423 -Node: Library Names606594 -Ref: Library Names-Footnote-1610048 -Ref: Library Names-Footnote-2610271 -Node: General Functions610357 -Node: Strtonum Function611460 -Node: Assert Function614482 -Node: Round Function617806 -Node: Cliff Random Function619347 -Node: Ordinal Functions620363 -Ref: Ordinal Functions-Footnote-1623426 -Ref: Ordinal Functions-Footnote-2623678 -Node: Join Function623889 -Ref: Join Function-Footnote-1625658 -Node: Getlocaltime Function625858 -Node: Readfile Function629602 -Node: Shell Quoting631572 -Node: Data File Management632973 -Node: Filetrans Function633605 -Node: Rewind Function637661 -Node: File Checking639048 -Ref: File Checking-Footnote-1640380 -Node: Empty Files640581 -Node: Ignoring Assigns642560 -Node: Getopt Function644111 -Ref: Getopt Function-Footnote-1655573 -Node: Passwd Functions655773 -Ref: Passwd Functions-Footnote-1664610 -Node: Group Functions664698 -Ref: Group Functions-Footnote-1672592 -Node: Walking Arrays672805 -Node: Library Functions Summary674408 -Node: Library Exercises675809 -Node: Sample Programs677089 -Node: Running Examples677859 -Node: Clones678587 -Node: Cut Program679811 -Node: Egrep Program689530 -Ref: Egrep Program-Footnote-1697028 -Node: Id Program697138 -Node: Split Program700783 -Ref: Split Program-Footnote-1704231 -Node: Tee Program704359 -Node: Uniq Program707148 -Node: Wc Program714567 -Ref: Wc Program-Footnote-1718817 -Node: Miscellaneous Programs718911 -Node: Dupword Program720124 -Node: Alarm Program722155 -Node: Translate Program726959 -Ref: Translate Program-Footnote-1731524 -Node: Labels Program731794 -Ref: Labels Program-Footnote-1735145 -Node: Word Sorting735229 -Node: History Sorting739300 -Node: Extract Program741136 -Node: Simple Sed748661 -Node: Igawk Program751729 -Ref: Igawk Program-Footnote-1766053 -Ref: Igawk Program-Footnote-2766254 -Ref: Igawk Program-Footnote-3766376 -Node: Anagram Program766491 -Node: Signature Program769548 -Node: Programs Summary770795 -Node: Programs Exercises771988 -Ref: Programs Exercises-Footnote-1776119 -Node: Advanced Features776210 -Node: Nondecimal Data778158 -Node: Array Sorting779748 -Node: Controlling Array Traversal780445 -Ref: Controlling Array Traversal-Footnote-1788778 -Node: Array Sorting Functions788896 -Ref: Array Sorting Functions-Footnote-1792785 -Node: Two-way I/O792981 -Ref: Two-way I/O-Footnote-1797926 -Ref: Two-way I/O-Footnote-2798112 -Node: TCP/IP Networking798194 -Node: Profiling801067 -Node: Advanced Features Summary809344 -Node: Internationalization811277 -Node: I18N and L10N812757 -Node: Explaining gettext813443 -Ref: Explaining gettext-Footnote-1818468 -Ref: Explaining gettext-Footnote-2818652 -Node: Programmer i18n818817 -Ref: Programmer i18n-Footnote-1823683 -Node: Translator i18n823732 -Node: String Extraction824526 -Ref: String Extraction-Footnote-1825657 -Node: Printf Ordering825743 -Ref: Printf Ordering-Footnote-1828529 -Node: I18N Portability828593 -Ref: I18N Portability-Footnote-1831048 -Node: I18N Example831111 -Ref: I18N Example-Footnote-1833914 -Node: Gawk I18N833986 -Node: I18N Summary834624 -Node: Debugger835963 -Node: Debugging836985 -Node: Debugging Concepts837426 -Node: Debugging Terms839279 -Node: Awk Debugging841851 -Node: Sample Debugging Session842745 -Node: Debugger Invocation843265 -Node: Finding The Bug844649 -Node: List of Debugger Commands851124 -Node: Breakpoint Control852457 -Node: Debugger Execution Control856153 -Node: Viewing And Changing Data859517 -Node: Execution Stack862895 -Node: Debugger Info864532 -Node: Miscellaneous Debugger Commands868549 -Node: Readline Support873578 -Node: Limitations874470 -Node: Debugging Summary876584 -Node: Arbitrary Precision Arithmetic877752 -Node: Computer Arithmetic879168 -Ref: table-numeric-ranges882766 -Ref: Computer Arithmetic-Footnote-1883625 -Node: Math Definitions883682 -Ref: table-ieee-formats886970 -Ref: Math Definitions-Footnote-1887574 -Node: MPFR features887679 -Node: FP Math Caution889350 -Ref: FP Math Caution-Footnote-1890400 -Node: Inexactness of computations890769 -Node: Inexact representation891728 -Node: Comparing FP Values893085 -Node: Errors accumulate894167 -Node: Getting Accuracy895600 -Node: Try To Round898262 -Node: Setting precision899161 -Ref: table-predefined-precision-strings899845 -Node: Setting the rounding mode901634 -Ref: table-gawk-rounding-modes901998 -Ref: Setting the rounding mode-Footnote-1905453 -Node: Arbitrary Precision Integers905632 -Ref: Arbitrary Precision Integers-Footnote-1910532 -Node: POSIX Floating Point Problems910681 -Ref: POSIX Floating Point Problems-Footnote-1914554 -Node: Floating point summary914592 -Node: Dynamic Extensions916786 -Node: Extension Intro918338 -Node: Plugin License919604 -Node: Extension Mechanism Outline920401 -Ref: figure-load-extension920829 -Ref: figure-register-new-function922309 -Ref: figure-call-new-function923313 -Node: Extension API Description925299 -Node: Extension API Functions Introduction926749 -Node: General Data Types931573 -Ref: General Data Types-Footnote-1937312 -Node: Memory Allocation Functions937611 -Ref: Memory Allocation Functions-Footnote-1940450 -Node: Constructor Functions940546 -Node: Registration Functions942280 -Node: Extension Functions942965 -Node: Exit Callback Functions945262 -Node: Extension Version String946510 -Node: Input Parsers947175 -Node: Output Wrappers957054 -Node: Two-way processors961569 -Node: Printing Messages963773 -Ref: Printing Messages-Footnote-1964849 -Node: Updating `ERRNO'965001 -Node: Requesting Values965741 -Ref: table-value-types-returned966469 -Node: Accessing Parameters967426 -Node: Symbol Table Access968657 -Node: Symbol table by name969171 -Node: Symbol table by cookie971152 -Ref: Symbol table by cookie-Footnote-1975296 -Node: Cached values975359 -Ref: Cached values-Footnote-1978858 -Node: Array Manipulation978949 -Ref: Array Manipulation-Footnote-1980047 -Node: Array Data Types980084 -Ref: Array Data Types-Footnote-1982739 -Node: Array Functions982831 -Node: Flattening Arrays986685 -Node: Creating Arrays993577 -Node: Extension API Variables998348 -Node: Extension Versioning998984 -Node: Extension API Informational Variables1000885 -Node: Extension API Boilerplate1001950 -Node: Finding Extensions1005759 -Node: Extension Example1006319 -Node: Internal File Description1007091 -Node: Internal File Ops1011158 -Ref: Internal File Ops-Footnote-11022828 -Node: Using Internal File Ops1022968 -Ref: Using Internal File Ops-Footnote-11025351 -Node: Extension Samples1025624 -Node: Extension Sample File Functions1027150 -Node: Extension Sample Fnmatch1034788 -Node: Extension Sample Fork1036279 -Node: Extension Sample Inplace1037494 -Node: Extension Sample Ord1039169 -Node: Extension Sample Readdir1040005 -Ref: table-readdir-file-types1040881 -Node: Extension Sample Revout1041692 -Node: Extension Sample Rev2way1042282 -Node: Extension Sample Read write array1043022 -Node: Extension Sample Readfile1044962 -Node: Extension Sample Time1046057 -Node: Extension Sample API Tests1047406 -Node: gawkextlib1047897 -Node: Extension summary1050555 -Node: Extension Exercises1054244 -Node: Language History1054966 -Node: V7/SVR3.11056622 -Node: SVR41058803 -Node: POSIX1060248 -Node: BTL1061637 -Node: POSIX/GNU1062371 -Node: Feature History1067995 -Node: Common Extensions1081093 -Node: Ranges and Locales1082417 -Ref: Ranges and Locales-Footnote-11087035 -Ref: Ranges and Locales-Footnote-21087062 -Ref: Ranges and Locales-Footnote-31087296 -Node: Contributors1087517 -Node: History summary1093058 -Node: Installation1094428 -Node: Gawk Distribution1095374 -Node: Getting1095858 -Node: Extracting1096681 -Node: Distribution contents1098316 -Node: Unix Installation1104381 -Node: Quick Installation1105064 -Node: Shell Startup Files1107475 -Node: Additional Configuration Options1108554 -Node: Configuration Philosophy1110293 -Node: Non-Unix Installation1112662 -Node: PC Installation1113120 -Node: PC Binary Installation1114439 -Node: PC Compiling1116287 -Ref: PC Compiling-Footnote-11119308 -Node: PC Testing1119417 -Node: PC Using1120593 -Node: Cygwin1124708 -Node: MSYS1125531 -Node: VMS Installation1126031 -Node: VMS Compilation1126823 -Ref: VMS Compilation-Footnote-11128045 -Node: VMS Dynamic Extensions1128103 -Node: VMS Installation Details1129787 -Node: VMS Running1132039 -Node: VMS GNV1134875 -Node: VMS Old Gawk1135609 -Node: Bugs1136079 -Node: Other Versions1139962 -Node: Installation summary1146386 -Node: Notes1147442 -Node: Compatibility Mode1148307 -Node: Additions1149089 -Node: Accessing The Source1150014 -Node: Adding Code1151449 -Node: New Ports1157606 -Node: Derived Files1162088 -Ref: Derived Files-Footnote-11167563 -Ref: Derived Files-Footnote-21167597 -Ref: Derived Files-Footnote-31168193 -Node: Future Extensions1168307 -Node: Implementation Limitations1168913 -Node: Extension Design1170161 -Node: Old Extension Problems1171315 -Ref: Old Extension Problems-Footnote-11172832 -Node: Extension New Mechanism Goals1172889 -Ref: Extension New Mechanism Goals-Footnote-11176249 -Node: Extension Other Design Decisions1176438 -Node: Extension Future Growth1178546 -Node: Old Extension Mechanism1179382 -Node: Notes summary1181144 -Node: Basic Concepts1182330 -Node: Basic High Level1183011 -Ref: figure-general-flow1183283 -Ref: figure-process-flow1183882 -Ref: Basic High Level-Footnote-11187111 -Node: Basic Data Typing1187296 -Node: Glossary1190624 -Node: Copying1222553 -Node: GNU Free Documentation License1260109 -Node: Index1285245 +Node: Foreword342385 +Node: Foreword446829 +Node: Preface48360 +Ref: Preface-Footnote-151231 +Ref: Preface-Footnote-251338 +Ref: Preface-Footnote-351571 +Node: History51713 +Node: Names54064 +Ref: Names-Footnote-155157 +Node: This Manual55303 +Ref: This Manual-Footnote-161803 +Node: Conventions61903 +Node: Manual History64240 +Ref: Manual History-Footnote-167233 +Ref: Manual History-Footnote-267274 +Node: How To Contribute67348 +Node: Acknowledgments68477 +Node: Getting Started73294 +Node: Running gawk75733 +Node: One-shot76923 +Node: Read Terminal78187 +Node: Long80218 +Node: Executable Scripts81731 +Ref: Executable Scripts-Footnote-184520 +Node: Comments84623 +Node: Quoting87105 +Node: DOS Quoting92623 +Node: Sample Data Files93298 +Node: Very Simple95893 +Node: Two Rules100792 +Node: More Complex102678 +Node: Statements/Lines105540 +Ref: Statements/Lines-Footnote-1109995 +Node: Other Features110260 +Node: When111196 +Ref: When-Footnote-1112950 +Node: Intro Summary113015 +Node: Invoking Gawk113899 +Node: Command Line115413 +Node: Options116211 +Ref: Options-Footnote-1132006 +Ref: Options-Footnote-2132235 +Node: Other Arguments132260 +Node: Naming Standard Input135208 +Node: Environment Variables136301 +Node: AWKPATH Variable136859 +Ref: AWKPATH Variable-Footnote-1140266 +Ref: AWKPATH Variable-Footnote-2140311 +Node: AWKLIBPATH Variable140571 +Node: Other Environment Variables141827 +Node: Exit Status145345 +Node: Include Files146021 +Node: Loading Shared Libraries149610 +Node: Obsolete151037 +Node: Undocumented151729 +Node: Invoking Summary151996 +Node: Regexp153659 +Node: Regexp Usage155113 +Node: Escape Sequences157150 +Node: Regexp Operators163390 +Ref: Regexp Operators-Footnote-1170800 +Ref: Regexp Operators-Footnote-2170947 +Node: Bracket Expressions171045 +Ref: table-char-classes173060 +Node: Leftmost Longest176002 +Node: Computed Regexps177304 +Node: GNU Regexp Operators180733 +Node: Case-sensitivity184405 +Ref: Case-sensitivity-Footnote-1187290 +Ref: Case-sensitivity-Footnote-2187525 +Node: Regexp Summary187633 +Node: Reading Files189100 +Node: Records191262 +Node: awk split records191995 +Node: gawk split records196924 +Ref: gawk split records-Footnote-1201463 +Node: Fields201500 +Ref: Fields-Footnote-1204278 +Node: Nonconstant Fields204364 +Ref: Nonconstant Fields-Footnote-1206602 +Node: Changing Fields206805 +Node: Field Separators212736 +Node: Default Field Splitting215440 +Node: Regexp Field Splitting216557 +Node: Single Character Fields219907 +Node: Command Line Field Separator220966 +Node: Full Line Fields224183 +Ref: Full Line Fields-Footnote-1225704 +Ref: Full Line Fields-Footnote-2225750 +Node: Field Splitting Summary225851 +Node: Constant Size227925 +Node: Splitting By Content232508 +Ref: Splitting By Content-Footnote-1236473 +Node: Multiple Line236636 +Ref: Multiple Line-Footnote-1242517 +Node: Getline242696 +Node: Plain Getline245175 +Node: Getline/Variable247815 +Node: Getline/File248964 +Node: Getline/Variable/File250349 +Ref: Getline/Variable/File-Footnote-1251952 +Node: Getline/Pipe252039 +Node: Getline/Variable/Pipe254717 +Node: Getline/Coprocess255848 +Node: Getline/Variable/Coprocess257112 +Node: Getline Notes257851 +Node: Getline Summary260645 +Ref: table-getline-variants261057 +Node: Read Timeout261886 +Ref: Read Timeout-Footnote-1265789 +Node: Retrying Input265847 +Node: Command-line directories267042 +Node: Input Summary267949 +Node: Input Exercises271334 +Node: Printing272062 +Node: Print273839 +Node: Print Examples275296 +Node: Output Separators278075 +Node: OFMT280093 +Node: Printf281448 +Node: Basic Printf282233 +Node: Control Letters283805 +Node: Format Modifiers287790 +Node: Printf Examples293800 +Node: Redirection296286 +Node: Special FD303124 +Ref: Special FD-Footnote-1306290 +Node: Special Files306364 +Node: Other Inherited Files306981 +Node: Special Network307981 +Node: Special Caveats308843 +Node: Close Files And Pipes309792 +Ref: Close Files And Pipes-Footnote-1316983 +Ref: Close Files And Pipes-Footnote-2317131 +Node: Output Summary317281 +Node: Output Exercises318279 +Node: Expressions318959 +Node: Values320148 +Node: Constants320825 +Node: Scalar Constants321516 +Ref: Scalar Constants-Footnote-1322378 +Node: Nondecimal-numbers322628 +Node: Regexp Constants325638 +Node: Using Constant Regexps326164 +Node: Variables329327 +Node: Using Variables329984 +Node: Assignment Options331895 +Node: Conversion333770 +Node: Strings And Numbers334294 +Ref: Strings And Numbers-Footnote-1337359 +Node: Locale influences conversions337468 +Ref: table-locale-affects340214 +Node: All Operators340806 +Node: Arithmetic Ops341435 +Node: Concatenation343940 +Ref: Concatenation-Footnote-1346759 +Node: Assignment Ops346866 +Ref: table-assign-ops351845 +Node: Increment Ops353155 +Node: Truth Values and Conditions356586 +Node: Truth Values357669 +Node: Typing and Comparison358718 +Node: Variable Typing359534 +Node: Comparison Operators363201 +Ref: table-relational-ops363611 +Node: POSIX String Comparison367106 +Ref: POSIX String Comparison-Footnote-1368178 +Node: Boolean Ops368317 +Ref: Boolean Ops-Footnote-1372795 +Node: Conditional Exp372886 +Node: Function Calls374624 +Node: Precedence378504 +Node: Locales382164 +Node: Expressions Summary383796 +Node: Patterns and Actions386367 +Node: Pattern Overview387487 +Node: Regexp Patterns389166 +Node: Expression Patterns389709 +Node: Ranges393418 +Node: BEGIN/END396525 +Node: Using BEGIN/END397286 +Ref: Using BEGIN/END-Footnote-1400022 +Node: I/O And BEGIN/END400128 +Node: BEGINFILE/ENDFILE402443 +Node: Empty405340 +Node: Using Shell Variables405657 +Node: Action Overview407930 +Node: Statements410256 +Node: If Statement412104 +Node: While Statement413599 +Node: Do Statement415627 +Node: For Statement416775 +Node: Switch Statement419933 +Node: Break Statement422315 +Node: Continue Statement424356 +Node: Next Statement426183 +Node: Nextfile Statement428564 +Node: Exit Statement431192 +Node: Built-in Variables433603 +Node: User-modified434736 +Ref: User-modified-Footnote-1442439 +Node: Auto-set442501 +Ref: Auto-set-Footnote-1456734 +Ref: Auto-set-Footnote-2456939 +Node: ARGC and ARGV456995 +Node: Pattern Action Summary461213 +Node: Arrays463646 +Node: Array Basics464975 +Node: Array Intro465819 +Ref: figure-array-elements467753 +Ref: Array Intro-Footnote-1470373 +Node: Reference to Elements470501 +Node: Assigning Elements472963 +Node: Array Example473454 +Node: Scanning an Array475213 +Node: Controlling Scanning478233 +Ref: Controlling Scanning-Footnote-1483627 +Node: Numeric Array Subscripts483943 +Node: Uninitialized Subscripts486128 +Node: Delete487745 +Ref: Delete-Footnote-1490494 +Node: Multidimensional490551 +Node: Multiscanning493648 +Node: Arrays of Arrays495237 +Node: Arrays Summary499991 +Node: Functions502082 +Node: Built-in503121 +Node: Calling Built-in504199 +Node: Numeric Functions506194 +Ref: Numeric Functions-Footnote-1511012 +Ref: Numeric Functions-Footnote-2511369 +Ref: Numeric Functions-Footnote-3511417 +Node: String Functions511689 +Ref: String Functions-Footnote-1535190 +Ref: String Functions-Footnote-2535319 +Ref: String Functions-Footnote-3535567 +Node: Gory Details535654 +Ref: table-sub-escapes537435 +Ref: table-sub-proposed538950 +Ref: table-posix-sub540312 +Ref: table-gensub-escapes541849 +Ref: Gory Details-Footnote-1542682 +Node: I/O Functions542833 +Ref: I/O Functions-Footnote-1550069 +Node: Time Functions550216 +Ref: Time Functions-Footnote-1560725 +Ref: Time Functions-Footnote-2560793 +Ref: Time Functions-Footnote-3560951 +Ref: Time Functions-Footnote-4561062 +Ref: Time Functions-Footnote-5561174 +Ref: Time Functions-Footnote-6561401 +Node: Bitwise Functions561667 +Ref: table-bitwise-ops562229 +Ref: Bitwise Functions-Footnote-1566541 +Node: Type Functions566713 +Node: I18N Functions567864 +Node: User-defined569509 +Node: Definition Syntax570314 +Ref: Definition Syntax-Footnote-1575946 +Node: Function Example576017 +Ref: Function Example-Footnote-1578936 +Node: Function Caveats578958 +Node: Calling A Function579476 +Node: Variable Scope580434 +Node: Pass By Value/Reference583422 +Node: Return Statement586917 +Node: Dynamic Typing589898 +Node: Indirect Calls590827 +Ref: Indirect Calls-Footnote-1602129 +Node: Functions Summary602257 +Node: Library Functions604959 +Ref: Library Functions-Footnote-1608568 +Ref: Library Functions-Footnote-2608711 +Node: Library Names608882 +Ref: Library Names-Footnote-1612336 +Ref: Library Names-Footnote-2612559 +Node: General Functions612645 +Node: Strtonum Function613748 +Node: Assert Function616770 +Node: Round Function620094 +Node: Cliff Random Function621635 +Node: Ordinal Functions622651 +Ref: Ordinal Functions-Footnote-1625714 +Ref: Ordinal Functions-Footnote-2625966 +Node: Join Function626177 +Ref: Join Function-Footnote-1627946 +Node: Getlocaltime Function628146 +Node: Readfile Function631890 +Node: Shell Quoting633860 +Node: Data File Management635261 +Node: Filetrans Function635893 +Node: Rewind Function639949 +Node: File Checking641336 +Ref: File Checking-Footnote-1642668 +Node: Empty Files642869 +Node: Ignoring Assigns644848 +Node: Getopt Function646399 +Ref: Getopt Function-Footnote-1657861 +Node: Passwd Functions658061 +Ref: Passwd Functions-Footnote-1666898 +Node: Group Functions666986 +Ref: Group Functions-Footnote-1674880 +Node: Walking Arrays675093 +Node: Library Functions Summary676696 +Node: Library Exercises678097 +Node: Sample Programs679377 +Node: Running Examples680147 +Node: Clones680875 +Node: Cut Program682099 +Node: Egrep Program691818 +Ref: Egrep Program-Footnote-1699316 +Node: Id Program699426 +Node: Split Program703071 +Ref: Split Program-Footnote-1706519 +Node: Tee Program706647 +Node: Uniq Program709436 +Node: Wc Program716855 +Ref: Wc Program-Footnote-1721105 +Node: Miscellaneous Programs721199 +Node: Dupword Program722412 +Node: Alarm Program724443 +Node: Translate Program729247 +Ref: Translate Program-Footnote-1733812 +Node: Labels Program734082 +Ref: Labels Program-Footnote-1737433 +Node: Word Sorting737517 +Node: History Sorting741588 +Node: Extract Program743424 +Node: Simple Sed750949 +Node: Igawk Program754017 +Ref: Igawk Program-Footnote-1768341 +Ref: Igawk Program-Footnote-2768542 +Ref: Igawk Program-Footnote-3768664 +Node: Anagram Program768779 +Node: Signature Program771836 +Node: Programs Summary773083 +Node: Programs Exercises774276 +Ref: Programs Exercises-Footnote-1778407 +Node: Advanced Features778498 +Node: Nondecimal Data780446 +Node: Array Sorting782036 +Node: Controlling Array Traversal782733 +Ref: Controlling Array Traversal-Footnote-1791066 +Node: Array Sorting Functions791184 +Ref: Array Sorting Functions-Footnote-1795073 +Node: Two-way I/O795269 +Ref: Two-way I/O-Footnote-1800214 +Ref: Two-way I/O-Footnote-2800400 +Node: TCP/IP Networking800482 +Node: Profiling803355 +Node: Advanced Features Summary811632 +Node: Internationalization813565 +Node: I18N and L10N815045 +Node: Explaining gettext815731 +Ref: Explaining gettext-Footnote-1820756 +Ref: Explaining gettext-Footnote-2820940 +Node: Programmer i18n821105 +Ref: Programmer i18n-Footnote-1825971 +Node: Translator i18n826020 +Node: String Extraction826814 +Ref: String Extraction-Footnote-1827945 +Node: Printf Ordering828031 +Ref: Printf Ordering-Footnote-1830817 +Node: I18N Portability830881 +Ref: I18N Portability-Footnote-1833336 +Node: I18N Example833399 +Ref: I18N Example-Footnote-1836202 +Node: Gawk I18N836274 +Node: I18N Summary836912 +Node: Debugger838251 +Node: Debugging839273 +Node: Debugging Concepts839714 +Node: Debugging Terms841567 +Node: Awk Debugging844139 +Node: Sample Debugging Session845033 +Node: Debugger Invocation845553 +Node: Finding The Bug846937 +Node: List of Debugger Commands853412 +Node: Breakpoint Control854745 +Node: Debugger Execution Control858441 +Node: Viewing And Changing Data861805 +Node: Execution Stack865183 +Node: Debugger Info866820 +Node: Miscellaneous Debugger Commands870837 +Node: Readline Support875866 +Node: Limitations876758 +Node: Debugging Summary878872 +Node: Arbitrary Precision Arithmetic880040 +Node: Computer Arithmetic881456 +Ref: table-numeric-ranges885054 +Ref: Computer Arithmetic-Footnote-1885913 +Node: Math Definitions885970 +Ref: table-ieee-formats889258 +Ref: Math Definitions-Footnote-1889862 +Node: MPFR features889967 +Node: FP Math Caution891638 +Ref: FP Math Caution-Footnote-1892688 +Node: Inexactness of computations893057 +Node: Inexact representation894016 +Node: Comparing FP Values895373 +Node: Errors accumulate896455 +Node: Getting Accuracy897888 +Node: Try To Round900550 +Node: Setting precision901449 +Ref: table-predefined-precision-strings902133 +Node: Setting the rounding mode903922 +Ref: table-gawk-rounding-modes904286 +Ref: Setting the rounding mode-Footnote-1907741 +Node: Arbitrary Precision Integers907920 +Ref: Arbitrary Precision Integers-Footnote-1912820 +Node: POSIX Floating Point Problems912969 +Ref: POSIX Floating Point Problems-Footnote-1916842 +Node: Floating point summary916880 +Node: Dynamic Extensions919074 +Node: Extension Intro920626 +Node: Plugin License921892 +Node: Extension Mechanism Outline922689 +Ref: figure-load-extension923117 +Ref: figure-register-new-function924597 +Ref: figure-call-new-function925601 +Node: Extension API Description927587 +Node: Extension API Functions Introduction929121 +Node: General Data Types933993 +Ref: General Data Types-Footnote-1939732 +Node: Memory Allocation Functions940031 +Ref: Memory Allocation Functions-Footnote-1942870 +Node: Constructor Functions942966 +Node: Registration Functions944700 +Node: Extension Functions945385 +Node: Exit Callback Functions947682 +Node: Extension Version String948930 +Node: Input Parsers949595 +Node: Output Wrappers959474 +Node: Two-way processors963989 +Node: Printing Messages966193 +Ref: Printing Messages-Footnote-1967269 +Node: Updating `ERRNO'967421 +Node: Requesting Values968161 +Ref: table-value-types-returned968889 +Node: Accessing Parameters969846 +Node: Symbol Table Access971077 +Node: Symbol table by name971591 +Node: Symbol table by cookie973572 +Ref: Symbol table by cookie-Footnote-1977716 +Node: Cached values977779 +Ref: Cached values-Footnote-1981278 +Node: Array Manipulation981369 +Ref: Array Manipulation-Footnote-1982459 +Node: Array Data Types982496 +Ref: Array Data Types-Footnote-1985151 +Node: Array Functions985243 +Node: Flattening Arrays989097 +Node: Creating Arrays995989 +Node: Redirection API1000760 +Node: Extension API Variables1003531 +Node: Extension Versioning1004164 +Node: Extension API Informational Variables1006065 +Node: Extension API Boilerplate1007130 +Node: Finding Extensions1010939 +Node: Extension Example1011499 +Node: Internal File Description1012271 +Node: Internal File Ops1016338 +Ref: Internal File Ops-Footnote-11028008 +Node: Using Internal File Ops1028148 +Ref: Using Internal File Ops-Footnote-11030531 +Node: Extension Samples1030804 +Node: Extension Sample File Functions1032330 +Node: Extension Sample Fnmatch1039968 +Node: Extension Sample Fork1041459 +Node: Extension Sample Inplace1042674 +Node: Extension Sample Ord1044349 +Node: Extension Sample Readdir1045185 +Ref: table-readdir-file-types1046061 +Node: Extension Sample Revout1046872 +Node: Extension Sample Rev2way1047462 +Node: Extension Sample Read write array1048202 +Node: Extension Sample Readfile1050142 +Node: Extension Sample Time1051237 +Node: Extension Sample API Tests1052586 +Node: gawkextlib1053077 +Node: Extension summary1055735 +Node: Extension Exercises1059424 +Node: Language History1060146 +Node: V7/SVR3.11061802 +Node: SVR41063983 +Node: POSIX1065428 +Node: BTL1066817 +Node: POSIX/GNU1067551 +Node: Feature History1073175 +Node: Common Extensions1086273 +Node: Ranges and Locales1087597 +Ref: Ranges and Locales-Footnote-11092215 +Ref: Ranges and Locales-Footnote-21092242 +Ref: Ranges and Locales-Footnote-31092476 +Node: Contributors1092697 +Node: History summary1098238 +Node: Installation1099608 +Node: Gawk Distribution1100554 +Node: Getting1101038 +Node: Extracting1101861 +Node: Distribution contents1103496 +Node: Unix Installation1109561 +Node: Quick Installation1110244 +Node: Shell Startup Files1112655 +Node: Additional Configuration Options1113734 +Node: Configuration Philosophy1115473 +Node: Non-Unix Installation1117842 +Node: PC Installation1118300 +Node: PC Binary Installation1119619 +Node: PC Compiling1121467 +Ref: PC Compiling-Footnote-11124488 +Node: PC Testing1124597 +Node: PC Using1125773 +Node: Cygwin1129888 +Node: MSYS1130711 +Node: VMS Installation1131211 +Node: VMS Compilation1132003 +Ref: VMS Compilation-Footnote-11133225 +Node: VMS Dynamic Extensions1133283 +Node: VMS Installation Details1134967 +Node: VMS Running1137219 +Node: VMS GNV1140055 +Node: VMS Old Gawk1140789 +Node: Bugs1141259 +Node: Other Versions1145142 +Node: Installation summary1151566 +Node: Notes1152622 +Node: Compatibility Mode1153487 +Node: Additions1154269 +Node: Accessing The Source1155194 +Node: Adding Code1156629 +Node: New Ports1162786 +Node: Derived Files1167268 +Ref: Derived Files-Footnote-11172743 +Ref: Derived Files-Footnote-21172777 +Ref: Derived Files-Footnote-31173373 +Node: Future Extensions1173487 +Node: Implementation Limitations1174093 +Node: Extension Design1175341 +Node: Old Extension Problems1176495 +Ref: Old Extension Problems-Footnote-11178012 +Node: Extension New Mechanism Goals1178069 +Ref: Extension New Mechanism Goals-Footnote-11181429 +Node: Extension Other Design Decisions1181618 +Node: Extension Future Growth1183726 +Node: Old Extension Mechanism1184562 +Node: Notes summary1186324 +Node: Basic Concepts1187510 +Node: Basic High Level1188191 +Ref: figure-general-flow1188463 +Ref: figure-process-flow1189062 +Ref: Basic High Level-Footnote-11192291 +Node: Basic Data Typing1192476 +Node: Glossary1195804 +Node: Copying1227733 +Node: GNU Free Documentation License1265289 +Node: Index1290425 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index 457a20f2..cc215c6a 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -603,6 +603,7 @@ particular records in a file and perform operations upon them. @code{getline}. * Getline Summary:: Summary of @code{getline} Variants. * Read Timeout:: Reading input with a timeout. +* Retrying Input:: Retrying input after certain errors. * Command-line directories:: What happens if you put a directory on the command line. * Input Summary:: Input summary. @@ -943,6 +944,7 @@ particular records in a file and perform operations upon them. * Array Functions:: Functions for working with arrays. * Flattening Arrays:: How to flatten arrays. * Creating Arrays:: How to create and populate arrays. +* Redirection API:: How to access and manipulate redirections. * Extension API Variables:: Variables provided by the API. * Extension Versioning:: API Version information. * Extension API Informational Variables:: Variables providing information about @@ -6318,6 +6320,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. @@ -8103,6 +8106,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. @@ -8758,7 +8766,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 @@ -8768,6 +8777,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 @@ -14841,6 +14879,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} @@ -14909,6 +14952,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. @@ -15048,6 +15095,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}. @@ -31465,6 +31517,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 @@ -31540,6 +31593,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: @@ -33504,6 +33561,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 64a4ef28..b7134716 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -598,6 +598,7 @@ particular records in a file and perform operations upon them. @code{getline}. * Getline Summary:: Summary of @code{getline} Variants. * Read Timeout:: Reading input with a timeout. +* Retrying Input:: Retrying input after certain errors. * Command-line directories:: What happens if you put a directory on the command line. * Input Summary:: Input summary. @@ -938,6 +939,7 @@ particular records in a file and perform operations upon them. * Array Functions:: Functions for working with arrays. * Flattening Arrays:: How to flatten arrays. * Creating Arrays:: How to create and populate arrays. +* Redirection API:: How to access and manipulate redirections. * Extension API Variables:: Variables provided by the API. * Extension Versioning:: API Version information. * Extension API Informational Variables:: Variables providing information about @@ -6102,6 +6104,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. @@ -7703,6 +7706,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. @@ -8358,7 +8366,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 @@ -8368,6 +8377,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 @@ -14169,6 +14207,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} @@ -14237,6 +14280,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. @@ -14376,6 +14423,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}. @@ -30557,6 +30609,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 @@ -30632,6 +30685,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: @@ -32596,6 +32653,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 e30ad593..9ecd2697 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -10,11 +10,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 @@ -186,6 +254,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)) == 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)) @@ -272,7 +272,7 @@ static IOBUF *iop_alloc(int fd, const char *name, int errno_val); static IOBUF *iop_finish(IOBUF *iop); static int gawk_pclose(struct redirect *rp); static int str2mode(const char *mode); -static int two_way_open(const char *str, struct redirect *rp); +static int two_way_open(const char *str, struct redirect *rp, int extfd); static int pty_vs_pipe(const char *command); static void find_input_parser(IOBUF *iop); static bool find_output_wrapper(awk_output_buf_t *outbuf); @@ -596,7 +596,8 @@ inrec(IOBUF *iop, int *errcode) else cnt = get_a_record(& begin, iop, errcode); - if (cnt == EOF) { + /* Note that get_a_record may return -2 when I/O would block */ + if (cnt < 0) { retval = false; } else { INCREMENT_REC(NR); @@ -727,10 +728,9 @@ redflags2str(int flags) /* redirect --- Redirection for printf and print commands */ struct redirect * -redirect(NODE *redir_exp, int redirtype, int *errflg) +redirect_string(const char *str, size_t explen, int not_string, int redirtype, int *errflg, int extfd) { struct redirect *rp; - char *str; int tflag = 0; int outflag = 0; const char *direction = "to"; @@ -779,18 +779,16 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) default: cant_happen(); } - if (do_lint && (redir_exp->flags & STRCUR) == 0) + if (do_lint && not_string) lintwarn(_("expression in `%s' redirection only has numeric value"), what); - redir_exp = force_string(redir_exp); - str = redir_exp->stptr; if (str == NULL || *str == '\0') fatal(_("expression for `%s' redirection has null string value"), what); - if (do_lint && (strncmp(str, "0", redir_exp->stlen) == 0 - || strncmp(str, "1", redir_exp->stlen) == 0)) + if (do_lint && (strncmp(str, "0", explen) == 0 + || strncmp(str, "1", explen) == 0)) lintwarn(_("filename `%s' for `%s' redirection may be result of logical expression"), str, what); @@ -828,8 +826,8 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) #endif /* PIPES_SIMULATED */ /* now check for a match */ - if (strlen(rp->value) == redir_exp->stlen - && memcmp(rp->value, str, redir_exp->stlen) == 0 + if (strlen(rp->value) == explen + && memcmp(rp->value, str, explen) == 0 && ((rp->flag & ~(RED_NOBUF|RED_EOF|RED_PTY)) == tflag || (outflag != 0 && (rp->flag & (RED_FILE|RED_WRITE)) == outflag))) { @@ -840,23 +838,25 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) if (do_lint && rpflag != newflag) lintwarn( _("unnecessary mixing of `>' and `>>' for file `%.*s'"), - (int) redir_exp->stlen, rp->value); + (int) explen, rp->value); break; } } if (rp == NULL) { + char *newstr; new_rp = true; if (save_rp != NULL) { rp = save_rp; efree(rp->value); } else emalloc(rp, struct redirect *, sizeof(struct redirect), "redirect"); - emalloc(str, char *, redir_exp->stlen + 1, "redirect"); - memcpy(str, redir_exp->stptr, redir_exp->stlen); - str[redir_exp->stlen] = '\0'; - rp->value = str; + emalloc(newstr, char *, explen + 1, "redirect"); + memcpy(newstr, str, explen); + newstr[explen] = '\0'; + str = newstr; + rp->value = newstr; rp->flag = tflag; init_output_wrapper(& rp->output); rp->output.name = str; @@ -888,6 +888,10 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) mode = binmode("a"); break; case redirect_pipe: + if (extfd >= 0) { + warning(_("get_file cannot create pipe `%s' with fd %d"), str, extfd); + return NULL; + } /* synchronize output before new pipe */ (void) flush_io(); @@ -901,6 +905,10 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) rp->flag |= RED_NOBUF; break; case redirect_pipein: + if (extfd >= 0) { + warning(_("get_file cannot create pipe `%s' with fd %d"), str, extfd); + return NULL; + } direction = "from"; if (gawk_popen(str, rp) == NULL) fatal(_("can't open pipe `%s' for input (%s)"), @@ -908,7 +916,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) break; case redirect_input: direction = "from"; - fd = devopen(str, binmode("r")); + fd = (extfd >= 0) ? extfd : devopen(str, binmode("r")); if (fd == INVALID_HANDLE && errno == EISDIR) { *errflg = EISDIR; /* do not free rp, saving it for reuse (save_rp = rp) */ @@ -925,8 +933,14 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) } break; case redirect_twoway: +#ifndef HAVE_SOCKETS + if (extfd >= 0) { + warning(_("get_file socket creation not supported on this platform for `%s' with fd %d"), str, extfd); + return NULL; + } +#endif direction = "to/from"; - if (! two_way_open(str, rp)) { + if (! two_way_open(str, rp, extfd)) { #ifdef HAVE_SOCKETS if (inetfile(str, NULL)) { *errflg = errno; @@ -945,7 +959,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) if (mode != NULL) { errno = 0; rp->output.mode = mode; - fd = devopen(str, mode); + fd = (extfd >= 0) ? extfd : devopen(str, mode); if (fd > INVALID_HANDLE) { if (fd == fileno(stdin)) @@ -1044,6 +1058,15 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) return rp; } +struct redirect * +redirect(NODE *redir_exp, int redirtype, int *errflg) +{ + int not_string = ((redir_exp->flags & STRCUR) == 0); + redir_exp = force_string(redir_exp); + return redirect_string(redir_exp->stptr, redir_exp->stlen, not_string, + redirtype, errflg, -1); +} + /* getredirect --- find the struct redirect for this file or pipe */ struct redirect * @@ -1699,16 +1722,16 @@ strictopen: /* two_way_open --- open a two way communications channel */ static int -two_way_open(const char *str, struct redirect *rp) +two_way_open(const char *str, struct redirect *rp, int extfd) { static bool no_ptys = false; #ifdef HAVE_SOCKETS /* case 1: socket */ - if (inetfile(str, NULL)) { + if (extfd >= 0 || inetfile(str, NULL)) { int fd, newfd; - fd = devopen(str, "rw"); + fd = (extfd >= 0) ? extfd : devopen(str, "rw"); if (fd == INVALID_HANDLE) return false; if ((BINMODE & BINMODE_OUTPUT) != 0) @@ -2168,17 +2191,43 @@ use_pipes: #ifndef PIPES_SIMULATED /* real pipes */ -/* wait_any --- wait for a child process, close associated pipe */ +/* + * wait_any --- if the argument pid is 0, wait for all child processes that + * have exited. We loop to make sure to reap all children that have exited to + * minimize the risk of running out of process slots. Since we don't process + * SIGCHLD, we do not immediately reap exited children. So when we get here, + * we want to reap any that have piled up. + * + * Note: on platforms that do not support waitpid with WNOHANG, when called with + * a zero argument, this function will hang until all children have exited. + * + * AJS, 2013-07-07: I do not see why we need to ignore signals during this + * function. This function just waits and updates the pid and status fields. + * I don't see why that should interfere with any signal handlers. But I am + * reluctant to remove this protection. So I changed to use sigprocmask to + * block signals instead to avoid interfering with installed signal handlers. + */ static int wait_any(int interesting) /* pid of interest, if any */ { - RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int); int pid; int status = 0; struct redirect *redp; +#ifdef HAVE_SIGPROCMASK + sigset_t set, oldset; + + /* I have no idea why we are blocking signals during this function... */ + sigemptyset(& set); + sigaddset(& set, SIGINT); + sigaddset(& set, SIGHUP); + sigaddset(& set, SIGQUIT); + sigprocmask(SIG_BLOCK, & set, & oldset); +#else + RETSIGTYPE (*hstat)(int), (*istat)(int), (*qstat)(int); istat = signal(SIGINT, SIG_IGN); +#endif #ifdef __MINGW32__ if (interesting < 0) { status = -1; @@ -2195,10 +2244,21 @@ wait_any(int interesting) /* pid of interest, if any */ } } #else +#ifndef HAVE_SIGPROCMASK hstat = signal(SIGHUP, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); +#endif for (;;) { -# ifdef HAVE_SYS_WAIT_H /* POSIX compatible sys/wait.h */ +# if defined(HAVE_WAITPID) && defined(WNOHANG) + /* + * N.B. If the caller wants status for a specific child process + * (i.e. interesting is non-zero), then we must hang until we + * get exit status for that child. + */ + if ((pid = waitpid(-1, & status, (interesting ? 0 : WNOHANG))) == 0) + /* No children have exited */ + break; +# elif defined(HAVE_SYS_WAIT_H) /* POSIX compatible sys/wait.h */ pid = wait(& status); # else pid = wait((union wait *) & status); @@ -2216,10 +2276,16 @@ wait_any(int interesting) /* pid of interest, if any */ if (pid == -1 && errno == ECHILD) break; } +#ifndef HAVE_SIGPROCMASK signal(SIGHUP, hstat); signal(SIGQUIT, qstat); #endif +#endif +#ifndef HAVE_SIGPROCMASK signal(SIGINT, istat); +#else + sigprocmask(SIG_SETMASK, & oldset, NULL); +#endif return status; } @@ -2440,7 +2506,7 @@ do_getline_redir(int into_variable, enum redirval redirtype) if (errcode != 0) { if (! do_traditional && (errcode != -1)) update_ERRNO_int(errcode); - return make_number((AWKNUM) -1.0); + return make_number((AWKNUM) cnt); } if (cnt == EOF) { @@ -2490,7 +2556,7 @@ do_getline(int into_variable, IOBUF *iop) update_ERRNO_int(errcode); if (into_variable) (void) POP_ADDRESS(); - return make_number((AWKNUM) -1.0); + return make_number((AWKNUM) cnt); } if (cnt == EOF) @@ -3383,10 +3449,44 @@ find_longest_terminator: return REC_OK; } +/* return true if PROCINFO[<filename>, "RETRY"] exists */ +static inline int +retryable(IOBUF *iop) +{ + return PROCINFO_node && in_PROCINFO(iop->public.name, "RETRY", NULL); +} + +/* Does the I/O error indicate that the operation should be retried later? */ + +static inline int +errno_io_retry(void) +{ + switch (errno) { +#ifdef EAGAIN + case EAGAIN: +#endif +#ifdef EWOULDBLOCK +#if !defined(EAGAIN) || (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif +#endif +#ifdef EINTR + case EINTR: +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: +#endif + return 1; + default: + return 0; + } +} + /* * get_a_record --- read a record from IOP into out, * return length of EOF, set RT. * Note that errcode is never NULL, and the caller initializes *errcode to 0. + * If I/O would block, return -2. */ static int @@ -3430,8 +3530,10 @@ get_a_record(char **out, /* pointer to pointer to data */ iop->flag |= IOP_AT_EOF; return EOF; } else if (iop->count == -1) { - iop->flag |= IOP_AT_EOF; *errcode = errno; + if (errno_io_retry() && retryable(iop)) + return -2; + iop->flag |= IOP_AT_EOF; return EOF; } else { iop->dataend = iop->buf + iop->count; @@ -3505,6 +3607,8 @@ get_a_record(char **out, /* pointer to pointer to data */ iop->count = iop->public.read_func(iop->public.fd, iop->dataend, amt_to_read); if (iop->count == -1) { *errcode = errno; + if (errno_io_retry() && retryable(iop)) + return -2; iop->flag |= IOP_AT_EOF; break; } else if (iop->count == 0) { diff --git a/test/ChangeLog b/test/ChangeLog index e9d5620a..4d332e49 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -41,6 +41,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. @@ -75,6 +103,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 c4c0b8b3..873b0a7c 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -176,6 +176,8 @@ EXTRA_DIST = \ dbugeval.ok \ defref.awk \ defref.ok \ + defvar.awk \ + defvar.ok \ delargv.awk \ delargv.ok \ delarpm2.awk \ @@ -210,6 +212,9 @@ EXTRA_DIST = \ dynlj.ok \ eofsplit.awk \ eofsplit.ok \ + errno.awk \ + errno.in \ + errno.ok \ exit.ok \ exit.sh \ exit2.awk \ @@ -336,6 +341,8 @@ EXTRA_DIST = \ gensub.ok \ gensub2.awk \ gensub2.ok \ + getfile.awk \ + getfile.ok \ getline.awk \ getline.in \ getline.ok \ @@ -933,6 +940,8 @@ EXTRA_DIST = \ testext.ok \ time.awk \ time.ok \ + timeout.awk \ + timeout.ok \ tradanch.awk \ tradanch.in \ tradanch.ok \ @@ -1032,7 +1041,7 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ backw badargs beginfile1 beginfile2 binmode1 charasbytes \ - colonwarn clos1way dbugeval delsub devfd devfd1 devfd2 dumpvars exit \ + colonwarn clos1way dbugeval delsub devfd devfd1 devfd2 dumpvars errno exit \ fieldwdth fpat1 fpat2 fpat3 fpatnull fsfwfs funlen \ functab1 functab2 functab3 fwtest fwtest2 fwtest3 \ genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops \ @@ -1049,7 +1058,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 @@ -1066,7 +1076,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: @@ -1325,6 +1335,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 >_$@ @@ -1907,6 +1922,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 212cb779..09de6713 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -433,6 +433,8 @@ EXTRA_DIST = \ dbugeval.ok \ defref.awk \ defref.ok \ + defvar.awk \ + defvar.ok \ delargv.awk \ delargv.ok \ delarpm2.awk \ @@ -467,6 +469,9 @@ EXTRA_DIST = \ dynlj.ok \ eofsplit.awk \ eofsplit.ok \ + errno.awk \ + errno.in \ + errno.ok \ exit.ok \ exit.sh \ exit2.awk \ @@ -593,6 +598,8 @@ EXTRA_DIST = \ gensub.ok \ gensub2.awk \ gensub2.ok \ + getfile.awk \ + getfile.ok \ getline.awk \ getline.in \ getline.ok \ @@ -1190,6 +1197,8 @@ EXTRA_DIST = \ testext.ok \ time.awk \ time.ok \ + timeout.awk \ + timeout.ok \ tradanch.awk \ tradanch.in \ tradanch.ok \ @@ -1288,7 +1297,7 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ backw badargs beginfile1 beginfile2 binmode1 charasbytes \ - colonwarn clos1way dbugeval delsub devfd devfd1 devfd2 dumpvars exit \ + colonwarn clos1way dbugeval delsub devfd devfd1 devfd2 dumpvars errno exit \ fieldwdth fpat1 fpat2 fpat3 fpatnull fsfwfs funlen \ functab1 functab2 functab3 fwtest fwtest2 fwtest3 \ genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops \ @@ -1305,7 +1314,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 @@ -1319,7 +1329,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 @@ -1763,6 +1773,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 >_$@ @@ -2344,6 +2359,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.; \ @@ -3745,6 +3770,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 f3639b0f..b25bba42 100644 --- a/test/Maketests +++ b/test/Maketests @@ -1272,6 +1272,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 |