diff options
186 files changed, 20937 insertions, 10020 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..154d2afb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,108 @@ +# +# CMakeLists.txt --- CMake input file for gawk +# +# Copyright (C) 2013 +# the Free Software Foundation, Inc. +# +# This file is part of GAWK, the GNU implementation of the +# AWK Programming Language. +# +# GAWK is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GAWK is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# + +## process this file with CMake to produce Makefile + +cmake_minimum_required (VERSION 2.6) +project (gawk C) + +include(cmake/configure.cmake) + +set (EXTRA_LIBS "") + +if (${HAVE_MPFR}) + set (EXTRA_LIBS ${EXTRA_LIBS} mpfr gmp) +endif () +if (${HAVE_LIBREADLINE}) + set (EXTRA_LIBS ${EXTRA_LIBS} readline) +endif () +if (${DYNAMIC}) + set (EXTRA_LIBS ${EXTRA_LIBS} ${CMAKE_DL_LIBS} ) +endif () + +include_directories(${CMAKE_SOURCE_DIR}) + +if(WIN32 OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + # This is enough to build with MinGW in a native Windows environment + # and also with a cross-compiler on OpenSuSE 12.2. + # On Ubuntu 12.04 patches to gawk's source code are needed: + # - insert #include <windows.h> at the top of awk.h + # - remove function execvp from pc/gawkmisc.pc + DefineConfigHValue(HAVE_SETENV 1) + DefineConfigHValue(HAVE_USLEEP 1) + DefineConfigHValue(STDC_HEADERS 1) + DefineConfigHValue(HAVE_STRINGIZE 1) + include_directories(${CMAKE_SOURCE_DIR}/missing_d) + DefineConfigHValue(HAVE_MKSTEMP 1) + set (EXTRA_LIBS ${EXTRA_LIBS} ws2_32) + # TODO: Eli Zaretskii remined me that the generated + # settings in config.h should be the same as those in + # pc/config.h. With these settings and DYNAMIC=1 + # it looks like functions in dynamic libs (extensions) can + # be invoked on Windows. + DefineConfigHValue(HAVE_GETSYSTEMTIMEASFILETIME 1) + set (GAWK_SOURCES ${GAWK_SOURCES} regex.c pc/getid.c pc/gawkmisc.pc pc/popen.c) + include_directories(${CMAKE_SOURCE_DIR}/pc) +endif() + +set (GAWK_SOURCES ${GAWK_SOURCES} + array.c + builtin.c + cint_array.c + command.c + debug.c + dfa.c + eval.c + ext.c + field.c + floatcomp.c + gawkapi.c + gawkmisc.c + int_array.c + io.c + main.c + mpfr.c + msg.c + node.c + profile.c + random.c + re.c + replace.c + str_array.c + symbol.c + version.c +) + +add_executable (gawk ${GAWK_SOURCES} ${BISON_awkgram_OUTPUTS}) +target_link_libraries (gawk m ${EXTRA_LIBS}) +install(PROGRAMS ${CMAKE_BINARY_DIR}/gawk${CMAKE_EXECUTABLE_SUFFIX} DESTINATION bin) + +# Beware: before building the extension, -DGAWK gets undefined. +add_subdirectory(extension) +enable_testing() +add_subdirectory(test) +add_subdirectory(doc) +include(InstallRequiredSystemLibraries) +set(CPACK_PACKAGING_INSTALL_PREFIX /usr) +include(cmake/package.cmake) @@ -2,6 +2,17 @@ * dfa.c: Sync with GNU grep. +2016-07-03 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * field.c (rebuild_record): Revert warning message regarding flags, + since I'm not yet totally confident that it is invalid to have FIELD + and MALLOC set at the same time. + +2016-07-03 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * field.c (rebuild_record): Do not turn off the STRING flag when + copying a FIELD node, and issue a warning if MALLOC is enabled. + 2016-07-01 Arnold D. Robbins <arnold@skeeve.com> * array.c (value_info): Print something reasonable when stfmt @@ -22,6 +33,86 @@ * awkgram.y (dump_vars): Allow "-" to mean print to stdout. Thanks to Hermann Peifer for the reports. +2016-06-30 Arnold D. Robbins <arnold@skeeve.com> + + * node.c (r_force_number): Coding style change. + +2016-06-30 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awk.h (STFMT_UNUSED): New define indicating that the string + representation does not depend on CONVFMT or OFMT. + (force_string): Use STFMT_UNUSED to improve code clarity. + * array.c (value_info): Fix stfmt logic. + * builtin.c (do_print): Use STFMT_UNUSED to improve code clarity. + * field.c (set_record): Ditto. + * gawkapi.c (api_sym_update_scalar): Ditto. + * int_array.c (is_integer): Check stfmt equals STFMT_UNUSED before + bothering to inspect the string. + * mpfr.c (mpg_format_val): Use STFMT_UNUSED to improve code clarity. + Remove buggy cast to char in stfmt assignment. + * node.c (r_format_val): Ditto. + * str_array.c (str_lookup): Use STFMT_UNUSED to improve code clarity. + * symbol.c (check_param_names): Ditto. + +2016-06-29 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * node.c (r_force_number): Optimize by trimming leading and trailing + white space before we inspect the string contents. + (get_ieee_magic_val): Must terminate the string with '\0' before + calling strtod. + +2016-06-27 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawkapi.h (awk_string): Add comment about the potential lack of + NUL-termination. + +2016-06-27 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awk.h: Add a comment regarding the potential lack of NUL-termination + for Node_val strings. + +2016-06-27 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * node.c (r_format_val): Do not free stptr unless STRCUR is set. + This is safer than testing for non-NULL stptr, since, for example, + pp_number copies a node and calls r_format_val, but does not bother + to set stptr to NULL beforehand. + +2016-06-26 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * node.c (r_force_number): When checking for trailing spaces, protect + against running off the end of the string. + * mpfr.c (force_mpnum): Ditto. + +2016-06-26 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * builtin.c (do_print): There's actually no reason to test whether a + value is a number, since the STRCUR flag and stfmt value contain all + the necessary info, as in awk.h:force_string. + +2016-06-26 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * builtin.c (do_print): Do not use OFMT to print strnum values. We + accomplish this by calling format_val for a NUMBER only + if there is no string currently available, or if stfmt equals + neither -1 nor OFMTidx. + +2016-06-26 Arnold D. Robbins <arnold@skeeve.com> + + * awk.h: Edit some comments. Add others. Minor coding style changes. + * builtin.c (format_tree): Restore a comment. + (do_mktime): Restore saving/restoring of byte after format string. + (do_sub): Coding style. Use %.*s in warning message. + (nondec2awknum): Restore saving/restoring of byte after string value + being converted. + * eval.c: Minor coding style edits. + * int_array.c (is_integer): Fix order of checks for not + updating string value: check length == 0 before testing values. + Coding style edits. + * mpfr.c (do_mpfr_strtonum): Coding style edits. + * node.c (r_force_number): Restore saving/restoring of byte after + string value being converted. Edit comments some. + 2016-06-26 Arnold D. Robbins <arnold@skeeve.com> Repair change of 2015-08-25 to handling of MAYBE_NUM. @@ -32,6 +123,22 @@ Thanks to Andrew Schorr for reporting the problem. A test case will eventually be merged into master. + Only in stable and master. + +2016-06-20 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * builtin.c (do_strftime): Call fixtype before checking flags for + STRING type. + (do_print): Call fixtype before checking whether argument is a NUMBER. + * eval.c (set_BINMODE): Call fixtype before checking value type. + No need to call force_number if the flags say it's a number. + (r_get_field): Fix lint check for non-numeric argument. + * io.c (redirect): Call fixtype before checking whether it's a string. + +2016-06-18 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * node.c (r_force_number): Fix typo in comment. + 2016-06-16 Arnold D. Robbins <arnold@skeeve.com> * awk.h: Add comment headers for several functions. @@ -42,10 +149,110 @@ * config.sub: Update from GNULIB. +2016-06-14 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awk.h (boolval): New inline function to standardize testing whether + a node's value is true. + * builtin.c (do_strftime): Use boolval to handle 3rd argument. + * eval.c (set_IGNORECASE, eval_condition): Use new boolval function. + * io.c (pty_vs_pipe): Use new boolval function. + +2016-06-14 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * builtin.c (do_strftime): Fix handling of 3rd argument to work + as a standard boolean: non-null or non-zero. + +2016-06-14 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawkapi.c (node_to_awk_value): When caller requests AWK_SCALAR + or AWK_UNDEFINED, we need to call fixtype before we check the type. + +2016-06-13 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awkgram.y: Eliminate STRCUR tests. Must use STRING to test whether + a scalar is a string. + +2016-06-12 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awk.h: Improve comment about STRING and NUMBER type assignment. + (nondec2awknum): Add endptr argument. + (fixtype): New inline function to clarify a scalar's type. + * array.c (sort_up_value_type): Call fixtype before checking the value + types. + * awkgram.y (yylex): Pass NULL endptr argument to nondec2awknum. + (valinfo): Remove dead tests: either STRING or NUMBER or both + must be set, so there's no reason to continue with checks for NUMCUR or + STRCUR. + * builtin.c (do_exp, do_int, do_log, do_sqrt, do_sin, do_cos, do_srand): + Fix lint check for non-numeric argument. + (do_string): Fix lint check for 1st and 2nd args being strings. + (do_length): Fix assert to allow for Node_typedregex. + Fix lint check for non-string argument. + (format_tree): Fix type detection for '%c' arguments. + (do_strftime): Fix lint check for non-numeric 2nd argument and + lint check for non-string 1st argument. + (do_mktime): Fix lint check for non-string argument. Eliminate useless + logic to save and restore terminating NUL. + (do_system, do_tolower, do_toupper): Fix lint check for non-string + argument. + (do_atan2, do_lshift, do_rshift, do_and, do_or, do_xor, do_compl, + do_intdiv): Fix lint checks for non-numeric args. + (do_sub): Attempt to clean up treatment of 3rd argument to gensub + despite vague documentation of expected behavior. + (do_strnum): Fix bug in number detection logic, and pass new endptr + arg to nondec2awknum. + (nondec2awknum): Add endptr argument so caller can detect how much + of the string was consumed. Eliminate unnecessary logic to save + and restore terminating NUL char. + (do_typeof): Use a switch to specify which cases are supported, and + issue a warning message when a corrupt type is detected. + * debug.c (print_memory): At least one of NUMBER and STRING should + be set, so no need to check for NUMCUR or STRCUR in addition. + * eval.c (cmp_nodes): Use fixtype function to fix arg types. + (set_IGNORECASE): Fix logic for acting on value type. Note that + setting IGNORECASE to a string value of "0" with NUMCUR set now enables + ignorecase, so that's a subtle change in behavior that seems to match + the docs. + (set_LINT): Try to clean up configuration logic based on type. + * ext.c (get_argument): Remove unused variable pcount. + * gawkapi.c (node_to_awk_value): Remove pointless test for NUMCUR + after calling force_number. Similarly, no need to test for STRCUR + after calling force_string. + * int_array.c (is_integer): Reject cases where a string value is + present that will not be correctly regenerated from the integer; + in particular, this could happen where blank space padding is present, + leading zeroes are present, or for hex or octal values. + Also fix some bugs where a strnum was converted to a NUMBER without + turning off the STRING bit. + * io.c (redirect_string): Make lint warning message more accurate. + (redirect): Change not_string test to use STRING bit, not STRCUR. + (pty_vs_pipe): Use fixtype to correct logic for detecting whether a + value is anumber. + * mpfr.c (mpg_force_number): If NUMCUR is set, there's no need to + test is_mpg_number. If it's not, the NODE is corrupt and we've got + bigger problems. Fix flag manipulation logic. Always set NUMCUR and + clear MAYBE_NUM, + (set_PREC): Fix logic using fixtype function. + (do_mpfr_atan2, do_mpfr_intdiv): Fix lint check for non-numeric + arguments. + (do_mpfr_func, do_mpfr_int, do_mpfr_compl, get_intval, do_mpfr_srand): + Fix lint check for non-numeric argument. + (do_mpfr_strtonum): Use fixtype and stop testing for NUMCUR bit. + * node.c (r_force_number): Eliminate pointless save and restore of + terminating NUL char. Always set NUMCUR and clear MAYBE_NUM, and + convert STRING to NUMBER if appropriate, fixing bugs in flag + manipulations. For non-decimal data, need to consider whether there + is trailing non-numeric data in deciding whether a MAYBE_NUM should + be converted to a NUMBER, so take advantage of new endptr arg + to nondec2awknum. + 2016-06-14 Arnold D. Robbins <arnold@skeeve.com> * builtin.c (do_sub): Fix sub for long runs of backslashes. Thanks to Mike Brennan for the report. + + Unrelated: + * ext.c (get_argument): Remove unused variable pcount. 2016-06-10 Arnold D. Robbins <arnold@skeeve.com> @@ -82,6 +289,16 @@ optional sign. (r_force_number): Use it. Thanks to Mike Brennan for the report. +2016-05-30 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawkapi.h (awk_ext_func_t): Rename num_expected_args to + max_expected_args, and explain in the comment that it doesn't really + matter. + * ext.c (make_builtin): Replace num_expected_args with + max_expected_args. + (get_argument): Do not check whether the argument number exceeds + the maximum expected by the function. + 2016-05-30 Arnold D. Robbins <arnold@skeeve.com> * main.c (arg_assign): Fully bracket ifdefs around call @@ -130,6 +347,13 @@ (api_set_argument): Pass (NODE *) returned by get_argument to get_array_argument. +2016-05-25 Manuel Collado <mcollado2011@gmail.com>. + + * gawkapi.c (api_nonfatal): New function. + (api_impl): Include it. + * gawkapi.h (struct gawk_api): Add api_nonfatal member. + (nonfatal): New macro. + 2016-05-12 Arnold Robbins <arnold@skeeve.com> * str_array.c (str_lookup): Remove MAYBE_NUM from subscript flags. @@ -142,12 +366,20 @@ call to system. * io.c (redirect, gawk_popen [PIPES_SIMULATED]): Same. - 2016-05-12 Eli Zaretskii <eliz@gnu.org> * nonposix.h: Add prototypes for Posix functions emulated in pc/* files. +2016-05-09 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * interpret.h (r_interpret): Op_ext_builtin. No need to test whether + op == Op_ext_builtin, since we wouldn't be here otherwise. + +2016-05-03 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * builtin.c (format_tree): Do not waste a byte at the end of a string. + 2016-05-03 Andrew J. Schorr <aschorr@telemetry-investments.com> * builtin.c (format_tree): After the string has been rendered, use @@ -223,6 +455,15 @@ 'system' differently under --traditional, as the low 8 bits are the most interesting. +2016-04-06 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_printf): Allow a write to the closed write-end of + a two-way pipe to be nonfatal if NONFATAL is set for it. + (do_print): Ditto. + (do_print_rec): Ditto. + * io.c (do_getline_redir): Same thing for reading from a closed + read end of a two-way pipe. Fatal error. + 2016-04-04 Arnold D. Robbins <arnold@skeeve.com> * builtin.c (do_fflush): Add warning for flush to two-way @@ -240,12 +481,54 @@ read end of a two-way pipe. Fatal error. * NEWS: Updated. +2016-03-27 Stephen Davies <sdavies@sdc.com.au> + + * awkgram.y (get_comment): Strip CRs from comment. Strip + off trailing newlines. + +2016-03-21 Arnold D. Robbins <arnold@skeeve.com> + + * profile.c (pprint): Improve handling of comment after + and if statement without an else. + +2016-03-19 Arnold D. Robbins <arnold@skeeve.com> + + Considerable improvements to handling of comments when pretty + printing, particularly for end-of-line comments. + + * awkgram.y (prior_comment, comment_to_save): New variables. + (add_pending_comment): New function. + (grammar): Jump through lots more hoops to capture comments. + Due to shift-reduce parsing, there can be up to two comments + captured and waiting to be saved; be sure to get them both and + at the right times. This is difficult since comments have no + real syntactic exisitence. Call add_pending_comment on most of + the simple statements. + (get_comment): Save a pre-existing comment in prior_comment. + (split_comment): Use comment_to_save instead of `comment'. + * profile.c (end_line): Change to return the instruction after + the comment that gets printed; adjust return type. + (pprint): Add skip_comment static variable. Adjust logic for + skipping an end-of-line comment; only do it if skip_comment is + true. This is set to true in places where we can't use the + return value from end_line(). Call end_line() in many more places. + (pp_func): Handle end-of-line comments after a function header. + +2016-03-17 Arnold D. Robbins <arnold@skeeve.com> + + * debug.c (print_instruction): For Op_comment, improve notation as + to whether it's a full comment or an end of line comment. + 2016-03-14 Arnold D. Robbins <arnold@skeeve.com> * io.c (socketopen): For SOCK_DGRAM, set read_len to sizeof remote_addr. Makes UDP more or less work again. Thanks to Juergen Kahrs for the fix. +2016-03-11 Arnold D. Robbins <arnold@skeeve.com> + + * debug.c (print_instruction): Normalize printing of comment dump. + 2016-03-10 Arnold D. Robbins <arnold@skeeve.com> * builtin.c (do_system): Further improvements. Catch core dump @@ -277,6 +560,11 @@ * debug.c (print_instruction): Improvements in instruction dump for if and else. +2016-03-01 Arnold D. Robbins <arnold@skeeve.com> + + * debug.c (print_instruction): For Op_comment, add notation as + to whether it's a full comment or an end of line comment. + 2016-02-29 Arnold D. Robbins <arnold@skeeve.com> * profile.c (pp_list): Handle the case of nargs equal to zero. @@ -325,6 +613,43 @@ * README, NEWS: Updated to reflect use of Texinfo 6.1. + Unrelated: + + * configure.ac: Switch to AC_PROG_CC_C99 to enable C99 + compilation and features. + * dfa.c: Sync with GNU grep, go back to C99 style declarations + at point of use. + +2016-02-05 Arnold D. Robbins <arnold@skeeve.com> + + Make optimization (constant folding and tail call recursion) + be on by default. + + * awkgram.y (common_exp): Only do concatenation of two strings(!) + * main.c (do_optimize): Init to true. + (optab): Add new -s/--no-optimize option. + (usage): Update message to include it. + (parse_args): Parse it. Set do_optimize to false if pretty + printing or profiling. + * NEWS: Updated. + +2016-01-28 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (SUBDIRS): Include extras. Otherwise dist does + doesn't work. + +2016-01-27 Arnold D. Robbins <arnold@skeeve.com> + + * configure.ac (GAWK_AC_AIX_TWEAK): Remove call. + * configure: Regenerated. + * io.c (GAWK_AIX): Check _AIX instead. + * custom.h (_AIX): Add define of _XOPEN_SOURCE_EXTENDED. + + Unrelated: + + * configure.ac: Remove old stuff for ISC Unix, no longer needed. + * configure: Regenerated. + 2016-01-25 John E. Malmberg <wb8tyw@qsl.net> * io.c (redirect): Need to call close_one more than once after @@ -386,6 +711,12 @@ * ChangeLog: Cleanup spurious extra whitespace. +2016-01-03 Arnold D. Robbins <arnold@skeeve.com> + + * configure.ac (GAWK_AC_LINUX_ALPHA): Remove call. + * configure: Regenerated. + * NEWS: Document removal of support for GNU/Linux on Alpha. + 2016-01-02 Arnold D. Robbins <arnold@skeeve.com> * dfa.c (add_utf8_anychar): Minor change in declaration of @@ -398,6 +729,11 @@ empty else part for pretty printing. Bug report by ziyunfei <446240525@qq.com>. +2015-12-20 Arnold D. Robbins <arnold@skeeve.com> + + * io.c (nonfatal): New static constant string. + * is_non_fatal, is_non_fatal_redirect: Use it. + 2015-12-16 Arnold D. Robbins <arnold@skeeve.com> * io.c (two_way_open): Remove unneeded close of slave in the @@ -435,6 +771,12 @@ * dfa.c: Sync with GNU grep. +2015-10-25 Arnold D. Robbins <arnold@skeeve.com> + + * awkgram.y (yylex): Fix invalid write problems. + Reported by Hanno Boeck <hanno@hboeck.de>. + Only appeared in master. Harumph. + 2015-10-16 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (SUBDIRS): Fix ordering so that @@ -561,6 +903,98 @@ * dfa.h, dfa.c: Sync with GNU grep. +2015-06-29 Arnold D. Robbins <arnold@skeeve.com> + + * awkgram.y (yylex): If gawk extension function is found as + a function in a user-defined function body, treat it normally. + Makes eval "print and(a, 1)" work in the debugger again. + Thanks, yet again, to Hermann Peifer. + * interpret.h (r_interpret): Op_subscript. UPREF if the + element value is a typed regexp. Thanks to Hermann Peifer. + +2015-06-28 Arnold D. Robbins <arnold@skeeve.com> + + Improve memory tracking of typed regexps. + + * awkgram.y (make_regnode): Set valref to 1. + * interpret.h (r_interpret): Have Op_push_re upref typed regexp. + * builtin.c (do_typeof): OK to deref typed regex. + * awk.h (force_string): Do dupnode on the regexp text. + +2015-06-26 Arnold D. Robbins <arnold@skeeve.com> + + Remove support for old-style extensions. + + * awk.h (Node_old_ext_func, Op_old_ext_func): Removed. + Remove all uses throughout the code. + (load_old_ext, make_old_builtin): Remove declarations. + * ext.c (load_old_ext, make_old_builtin): Removed. + * awkgram.y (tokentab): Remove "extension" entry. + * eval.c (Node_old_ext_funci, Op_old_ext_func): Remove from tables. + * interpret.h (interpret): Remove stuff for old extensions. + + Unrelated: + + * builtin.c (do_typeof): Add support for strnum, distinguish + untyped from unassigned, use "string" and "number". Thanks to + Hermann Peifer for suggesting inclusion of strnum. + +2015-06-25 Arnold D. Robbins <arnold@skeeve.com> + + Further work straightening out memory management for typeof. + + * awk.h (DEREF): Add an assert. + * builtin.c (do_typeof): Add comments, cases where not to deref. + * debug.c (print_instruction): Add Op_push_arg_untyped. + * interpret.h (r_interpret): Additional comments / tweaks for + Op_push_arg_untyped. + + Unrelated. Make `x = @/foo/ ; print x' print something. + + * builtin.c (do_print): Check for Node_typedregex and handle it. + Needed for adding test code. + + Unrelated. Typo fix. + + * debug.c (initialize_watch_item): Dupnode the right thing. + +2015-06-22 Arnold D. Robbins <arnold@skeeve.com> + + * awkgram.y (snode): Make isarray not scalarize untyped parameters + also. + * profile.c (pprint): Add Op_push_arg_untyped. + + Improve debugger support for typed regexps. + Thanks to Hermann Peifer for the bug report. + + * awkgram.y (valinfo): Add support for Node_typedregex. + * debug.c (watchpoint_triggerred): Handle Node_typedregex. + (initialize_watch_item): Ditto. + (print_memory): Ditto. + + Fix typeof to work on subarrays. Thanks, yet again, to + Hermann Peifer for the bug report. + + * builtin.c (do_typeof): Don't deref Node_var_array. + +2015-06-21 Arnold D. Robbins <arnold@skeeve.com> + + Fixes for typeof - Don't let typeof change an untyped variable + into a scalar. + + * awk.h (opcodeval): Add Op_push_arg_untyped. + * awkgram.y (snode): Separate out case for do_typeof, use + Op_push_arg_untyped. + * builtin.c (do_typeof): Arg will be equal to Nnull_string + if it's untyped. + * eval.c (optypes): Add Op_push_arg_untyped. + * interpret.h (r_interpret): Add Op_push_arg_untyped handling. + +2015-06-19 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_isarray): Minor edit to lint warning. + * TODO: Updated. + 2015-06-14 Arnold D. Robbins <arnold@skeeve.com> * regcomp.c, regex_internal.h, regexec.c: Sync with GLIBC. @@ -574,6 +1008,16 @@ * regex_internal.h: Clean up defines for non-GCC for attribute; essentially sync it with GLIBC. +2015-06-12 Arnold D. Robbins <arnold@skeeve.com> + + * awkgram.y: Finish converting "hard" regex to "typed" regex. + +2015-05-31 Arnold D. Robbins <arnold@skeeve.com> + + * field.c (posix_def_parse_field): Removed. It's no longer + needed after updates to the POSIX standard. Thanks to + Michael Klement <michael.klement@usa.net> for pointing this out. + 2015-05-26 Paul Eggert <eggert@Penguin.CS.UCLA.EDU> * floatcomp.c (count_trailing_zeros): New function. @@ -598,6 +1042,17 @@ * symbol.c (load_symbols): Plug minor memory leak by calling unref(tmp) on "identifiers" string after assoc_lookup is done with it. +2015-05-15 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * main.c (load_procinfo_argv): New function to save argv array values + in PROCINFO["argv"][0..argc-1]. + (load_procinfo): Call load_procinfo_argv. + +2015-05-11 Arnold D. Robbins <arnold@skeeve.com> + + * awk.h, awkgram.y, builtin.c, eval.c profile.c, re.c: + Change Node_hardregex to Node_typedregex everywhere. + 2015-05-05 Arnold D. Robbins <arnold@skeeve.com> * awkgram.y (yylex): Yet Another Fix for parsing bracket @@ -608,6 +1063,14 @@ * config.guess, config.sub: Get latest versions. + Make profiling for hard regexes work. + + * profile.c (pp_string_or_hard_regex): Renamed from pp_string. + Add bool param for hard regex and add @ if so. + (pp_string): New function, calls pp_string_or_hard_regex. + (pp_hard_regex): New function, calls pp_string_or_hard_regex. + (pprint): Adjust to print a hard regex correctly. + 2015-05-01 Arnold D. Robbins <arnold@skeeve.com> * awkgram.y: Make sure values are not null in param list. @@ -632,6 +1095,11 @@ 2015-04-28 Arnold D. Robbins <arnold@skeeve.com> + * builtin.c (isarray): Add lint warning that isarray() + is deprecated. + +2015-04-28 Arnold D. Robbins <arnold@skeeve.com> + * awkgram.y (yylex): Rework the bracket handling from zero. Thanks to Michal Jaegermann for yet another test case. @@ -664,6 +1132,21 @@ 2015-04-16 Arnold D. Robbins <arnold@skeeve.com> + Let parameter names shadow the names of gawk additional built-ins. + Make it actually work. + + * awkgram.y (want_param_names): Now an enum, there are three states. + (grammar): Set states properly. + (yylex): Improve checking logic. + +2015-04-16 Arnold D. Robbins <arnold@skeeve.com> + + * configure.ac: Updated by autoupdate. + * configure, aclocal.m4: Regenerated. + * io.c, main.c, profile.c: Removed use of RETSIGTYPE. + +2015-04-16 Arnold D. Robbins <arnold@skeeve.com> + * builtin.c (do_strftime): Use a double for the timestamp and check that the value is within range for a time_t. @@ -677,6 +1160,14 @@ * NEWS: Updated. +2015-04-15 Arnold D. Robbins <arnold@skeeve.com> + + Let parameter names shadow the names of gawk additional built-ins. + + * awkgram.y (want_param_names): New variable. + (yylex): Check it before returning a built-in token. + (grammar): Set and clear it in the right places. + 2015-04-14 Arnold D. Robbins <arnold@skeeve.com> * builtin.c (do_strftime): Restore checking for negative result and @@ -690,6 +1181,23 @@ Unrelated: * builtin.c (call_sub): Fix for indirect gensub, 3 args now works. + Unrelated: + + * builtin.c (do_sub): Improve some variable names for readability + and add / expand some comments. + + Unrelated: + + * builtin.c (call_sub, call_match, call_split_func): Allow for + regex to be Node_hardregex. + +2015-04-14 Andrew J. Schorr <aschorr@telemetry-investments.com> + Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_sub): Make computations smarter; initial len + to malloc, test for final amount after all matches done and + need to copy in the final part of the original string. + 2015-04-13 Arnold D. Robbins <arnold@skeeve.com> * regcomp.c (analyze): Prevent malloc(0). @@ -711,6 +1219,15 @@ * Makefile.am (efence): Make this link again. Thanks to Michal Jaegermann for pointing out the problem. +2015-04-09 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awkgram.y (yyerror): Rationalize buffer size computations. Remove + old valgrind workarounds. + * debug.c (gprintf): Rationalize buffer size computations. + (serialize_subscript): Ditto. + * io.c (iop_finish): Rationalize buffer size computations. + * profile.c (pp_string): Correct space allocation computation. + 2015-04-08 John E. Malmberg <wb8tyw@qsl.net> * custom.h: VMS shares some code paths with ZOS_USS in @@ -752,6 +1269,27 @@ Thanks to Andrew Schorr for finding the problem and supplying initial code; I did it slightly differently. +2015-04-03 Arnold D. Robbins <arnold@skeeve.com> + + * awk.h (force_string): If hard_regex, return string text of the regex. + (force_string, force_number): If hard_regex, return Nnull_string. + * awkgram.y: Fix ~ and !~ with @/.../. + * eval.c (setup_frame): Handle a hard regex. + * re.c (avoid_dfa): Ditto. + +2015-04-02 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * NEWS: Rename div to intdiv. + +2015-04-02 Arnold D. Robbins <arnold@skeeve.com> + + Rename div() to intdiv(). + + * builtin.c (do_intdiv): Renamed from do_div. + * mfpr.c (do_mpfr_intdiv): Renamed from do_mpfr_div. + * awk.h: Update declarations. + * awkgram.y (tokentab, snode): Revise accordingly. + 2015-03-31 Arnold D. Robbins <arnold@skeeve.com> * awk.h (call_sub): Renamed from call_sub_func. @@ -768,6 +1306,12 @@ the buitin function expects. * eval.c (r_get_field): Make extern. +2015-03-27 Arnold D. Robbins <arnold@skeeve.com> + + * io.c (redirect): Change not_string from int to bool. + * gawkapi.c (api_get_file): Minor stylistic improvements. + * NEWS: Updated for retryable I/O and new API function. + 2015-03-24 Arnold D. Robbins <arnold@skeeve.com> * awkgram.y (make_regnode): Make extern. @@ -782,6 +1326,10 @@ * interpret.h (r_interpret): When Op_K_exit has an argument of Nnull_string, do not update exit_val, since no value was supplied. +2015-03-24 Arnold D. Robbins <arnold@skeeve.com> + + * awk.h, gawkapi.c, io.c: Minor code reformatting. + 2015-03-20 Arnold D. Robbins <arnold@skeeve.com> Start on fixing indirect calls of builtins. @@ -793,6 +1341,24 @@ * interpret.h (r_interpret): If calling do_sub, do it through call_sub_func(). +2015-03-19 Arnold D. Robbins <arnold@skeeve.com> + + * re.c (re_update): Handle hard regex - for sub/gsub/gensub. + * awkgram.y (grammar): Add support for hard_regex with ~ and !~; + allowed only on the right hand side. + (mk_rexp): Handle a hard regex. + +2015-03-18 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_typeof): Be smarter about checking for uninitialized + values; can now detect and return "untyped" for such values. + * awkgram.y (yylex): Collect @/.../ entirely in the lexer and return + a new terminal (HARD_REGEX). + (regexp): Reverted to just a regular awk regexp constant. + (hard_regexp): New nonterminal, can be used only in direct + assignment and as an argument in function call. New set of nonterminals + for function call expression lists. More work still to do. + 2015-03-18 Arnold D. Robbins <arnold@skeeve.com> * config.guess, config.sub: Updated, from libtool 2.4.6. @@ -807,6 +1373,26 @@ * re.c (regexflags2str): Removed. It was redundant. + * io.c (devopen): Change the logic such that if nonfatal is true + for the socket, don't do retries. Also clean up the formatting + some. At strictopen, check if errno is ENOENT and if so, propagate + the error from getaddrinfo() up to the caller. Add explanatory + comments. + +2015-02-28 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * io.c (pty_vs_pipe): Remove check for NULL PROCINFO_node, since + this is now checked inside in_PROCINFO. + +2015-02-27 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * io.c (socketopen): New parameter hard_error; set it if + getaddrinfo() fails. Change fatals to warnings. + (devopen): Pass in address of boolean hard_error variable + and stop trying to open the file if hard_error is true. + Save and restore errno around call to socketopen() and + use restored errno if open() fails at strictopen. + 2015-02-27 Arnold D. Robbins <arnold@skeeve.com> * symbol.c (check_param_names): Fix argument order in memset() call. @@ -814,6 +1400,20 @@ a long-standing problem where `-lm' was used twice in the final compilation line. +2015-02-27 Arnold D. Robbins <arnold@skeeve.com> + + Start on making regexp a real type. + + * awk.h (Node_hardregex): New node type. + (do_typeof): Add declaration. + * awkgram.y: Make @/.../ a hard regex. + (tokentab): New entry for typeof() function. + (snode): Try to handle typeof(). + (make_regnode): Handle Node_hardregex. + * builtin.c (do_typeof): New function. + * eval.c (nodetypes): Add Node_hardregex. + * re.c (re_update): Check for hardregex too in assert. + 2015-02-24 Arnold D. Robbins <arnold@skeeve.com> * POSIX.STD: Update copyright year. @@ -837,6 +1437,34 @@ * gawkapi.h: Fix spelling error in comment. +2015-02-10 Arnold D. Robbins <arnold@skeeve.com> + + * profile.c (pprint): Restore printing of count for rules. + Bug report by Hermann Peifer. + +2015-02-08 Arnold D. Robbins <arnold@skeeve.com> + + * io.c: Make it "NONFATAL" everywhere. + +2015-02-08 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awk.h (RED_NON_FATAL): Removed. + (redirect): Add new failure_fatal parameter. + (is_non_fatal_redirect): Add declaration. + * builtin.c (efwrite): Rework check for non-fatal. + (do_printf): Adjust calls to redirect. + (do_print_rec): Ditto. Move check for redirection error up. + * io.c (redflags2str): Remove RED_NON_FATAL. + (redirect): Add new failure_fatal parameter. Simplify the code. + (is_non_fatal_redirect): New function. + (do_getline_redir): Adjust calls to redirect. + +2014-12-27 Arnold D. Robbins <arnold@skeeve.com> + + * awk.h (is_non_fatal_std): Declare new function. + * io.c (is_non_fatal_std): New function. + * builtin.c (efwrite): Call it. + 2015-02-07 Arnold D. Robbins <arnold@skeeve.com> * regcomp.c, regex.c, regex.h, regex_internal.c, regex_internal.h, @@ -899,6 +1527,11 @@ * command.c: Ditto. * NEWS: Note same. +2015-01-16 Stephen Davies <sdavies@sdc.com.au> + + * awkgram.y (rule): Set first_rule to false. Catches more cases + for gathering comments. Thanks to Hermann Peifer for the test case. + 2015-01-15 Arnold D. Robbins <arnold@skeeve.com> * dfa.h, dfa.c: Sync with grep. Mainly copyright updates. @@ -916,6 +1549,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. @@ -934,6 +1583,124 @@ (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 + through the code. Thanks to GCC 4.9 for the warning. + +2014-12-18 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_sub): Do not waste a byte at the end of a string. + +2014-12-14 Arnold D. Robbins <arnold@skeeve.com> + + * awkgram.y (yyerror): Do not waste a byte at the end of a string. + * builtin.c (do_match): Ditto. + * command.y (append_statement): Ditto. + * debug.c (gprintf, serialize): Ditto. + * field.c (set_FIELDWIDTHS): Ditto. + * io.c.c (grow_iop_buffer): Ditto. + * profile.c (pp_string, pp_group3): Ditto. + +2014-12-14 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * array.c (concat_exp): Do not waste a byte at the end of a string. + * awkgram.y (common_exp): Ditto. + * builtin.c (do_substr): Ditto. + * eval.c (set_OFS): Ditto. + * field.c (rebuild_record): Ditto. + * gawkapi.h (r_make_string): Ditto. + * interpret.h (r_interpret): Ditto for Op_assign_concat. + * node.c (r_format_val, r_dupnode, make_str_node, str2wstr, wstr2str): + Ditto. + * re.c (make_regexp): Ditto. + +2014-12-20 Arnold D. Robbins <arnold@skeeve.com> + + Enable non-fatal output on per-file or global basis, + via PROCINFO. + + * awk.h (RED_NON_FATAL): New redirection flag. + * builtin.c (efwrite): If RED_NON_FATAL set, just set ERRNO and return. + (do_printf): Check errflg and if set, set ERRNO and return. + (do_print): Ditto. + (do_print_rec): Ditto. + * io.c (redflags2str): Update table. + (redirect): Check for global PROCINFO["nonfatal"] or for + PROCINFO[file, "nonfatal"] and don't fail on open if set. + Add RED_NON_FATAL to flags. + (in_PROCINFO): Make smarter and more general. + +2014-12-12 Stephen Davies <sdavies@sdc.com.au> + + Improve comment handling in pretty printing. + + * awk.h (comment_type): New field in the node. + (EOL_COMMENT, FULL_COMMENT): New defines. + * awkgram.y (block_comment): New variable. + (check_comment): New function. + (grammar): Add code to handle comments as needed. + (get_comment): Now takes a flag indicating kind of comment. + (yylex): Collect comments appropriately. + (append_rule): Ditto. + * profile.c (pprint): Smarten up comment handling. + Have printing \n take comments into account. + (end_line): New function. + (pp_func): Better handling of function comments. + 2014-12-10 Arnold D. Robbins <arnold@skeeve.com> * dfa.c: Sync with GNU grep. @@ -1038,6 +1805,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. @@ -1060,6 +1857,16 @@ (is_unary_minus): New function. (pp_concat): Add checks for unary minus; needs to be parenthesized. +2014-10-30 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * NEWS: Mention installation of /etc/profile.d/gawk.{csh,sh}. + +2014-10-29 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * configure.ac (AC_CONFIG_FILES): Add extras/Makefile. + * Makefile.am (SUBDIRS): Add extras. + * extras: Add new subdirectory. + 2014-10-29 Arnold D. Robbins <arnold@skeeve.com> * dfa.c: Sync with GNU grep. Again, again. @@ -1121,12 +1928,35 @@ * profile.c (pprint): Fix typo in header. Sheesh. + Unrelated: + + * awkgram.y (mk_program): Add a comment that we don't need to + clear the comment* variables. + 2014-10-04 Arnold D. Robbins <arnold@skeeve.com> * profile.c (pp_string_fp): Fix breaklines case to actually output the current letter. This broke at gawk 4.0.0. Sigh. Thanks to Bert Bos (bert@w3.org) for the report. +2014-10-03 Stephen Davies <sdavies@sdc.com.au> + + * awkgram.y (program_comment): Renamed from comment0. + (function_comment): Renamed from commentf. + +2014-10-02 Arnold D. Robbins <arnold@skeeve.com> + + * awkgram.y, profile.c: Minor white space cleanups. + +2014-10-01 Arnold D. Robbins <arnold@skeeve.com> + + Fix a few compile warnings: + + * awkgram.y (split_comment): Make static. + General: Remove some unused variables, clean up some whitepace nits. + + * profile.c (indent): Add some braces to turn off compiler warnings. + 2014-09-29 Andrew J. Schorr <aschorr@telemetry-investments.com> * main.c (main): In optlist, it should say "h", not "h:", since there @@ -1199,6 +2029,45 @@ since use of isalnum() let non-ASCII letters slip through into identifiers. +2014-09-13 Stephen Davies <sdavies@sdc.com.au> + + When doing pretty-printing (but not profiling), include the original + comments in the output. + + General rules: + + Pretty printing: + - Do NOT indent by a tab + - Do NOT print the header comments ("# BEGIN rules", etc.) + - DO print the comments that are in the program + + Profiling: + - DO indent by a tab + - DO print the header comments + - Do NOT print the program's original comments + + * awkgram.y (comment0, commentf): New varibles that are pointers to + program and function comments. + (get_comment): New function that retrieves consecutive comment lines + and empty lines as a unit). + (split_comment): New function: iff first block in the program is a + function and it is predeeded by comments, take the last non-blank + line as function comment and any preceeding lines as program comment.) + + Following token rules were changed to handle comments: + + * awkgram.y (pattern, LEX_BEGIN, LEX_END, LEX_BEGINFILE, LEX_ENDFILE, + action, function_prologue, statements): Update to handle comments. + + Following functions were changed to handle comments: + + * awkgram.y (mk_program, mk_function, allow_newline and yylex): Update + to handle comments. (Also fixed typo in case '\\'.) + + * profile.c (print_comment): New function to format comment printing. + (indent, pprint, dump_prog, pp_func): Changed to handle comments and + the revised indentation rules. + 2014-09-07 Arnold D. Robbins <arnold@skeeve.com> * awk.h: Move libsigsegv stuff to ... @@ -1260,6 +2129,27 @@ * regcomp.c, regex_internal.c: Sync with GBLIC. Why not. + Unrelated: + + Remove support for MirBSD. It uglified the code too much + for no discernable gain. + + * configure.ac: Remove check for MirBSD and define of + LIBC_IS_BORKED. + * dfa.c: Remove code depending on LIBC_IS_BORKED. + * main.c: Ditto. + * regcomp.c: Ditto. + * NEWS: Updated. + +2014-08-24 Arnold D. Robbins <arnold@skeeve.com> + + * regex.h: Remove underscores in names of parameters in function + declarations. Tweak names as neeeded. + +2014-08-20 Arnold D. Robbins <arnold@skeeve.com> + + * node.c (parse_escape): Max of 2 digits after \x. + 2014-08-18 Arnold D. Robbins <arnold@skeeve.com> * symbol.c: General formatting cleanup. @@ -1284,6 +2174,13 @@ at how much to allocate. This came up in an email discussion with Tom Dickey about mawk's gsub(). +2014-08-12 Juergen Kahrs <jkahrs@users.sourceforge.net> + + * cmake/configure.cmake: + * cmake/package.cmake: Copyright update. + * README.cmake: + * README_d/README.cmake: Moved file. + 2014-08-12 Arnold D. Robbins <arnold@skeeve.com> OFS being set should rebuild $0 using previous OFS if $0 @@ -1355,6 +2252,12 @@ * awk.h (cleanup_mpfr): Add declaration. * main.c (main): Add call to `cleanup_mpfr'. + Fix memory leak: + + * mpfr.c (do_mpfr_div): Add unref to denominator and numerator + to not leak memory. Thanks to Katie Wasserman <katie@wass.net> + for isolating the problem to that routine. + 2014-07-25 Arnold D. Robbins <arnold@skeeve.com> * main.c (main): Add a warning message if -M is used and gawk was @@ -1377,6 +2280,21 @@ 2014-07-10 Arnold D. Robbins <arnold@skeeve.com> + New `div()' function to do integer division and remainder; + mainly useful for use with GMP integers. Thanks to + Katie Wasserman <katie@wass.net> for the suggestion. + + * awk.h (do_div, do_mpfr_div): Declare new functions. + * builtin.c (do_div): New function. + * mpfr.c (do_mpfr_div): New function. + * awkgram.y (tokentab): New entry. + (snode): Add check for do_div/do_mpfr_div to make 3rd arg + be an array. + * NEWS: Updated. + * TODO: Updated. + +2014-07-10 Arnold D. Robbins <arnold@skeeve.com> + * awkgram.y (check_for_bad): New routine to do the fatal message, with smarter checking. (nextc): Call it as appropriate. @@ -1391,6 +2309,13 @@ for bad characters in the source program. (yylex): Adjust calls. +2014-06-24 Arnold D. Robbins <arnold@skeeve.com> + + * main.c (main): The --pretty-print option no longer runs the + program. This removes the need for the GAWK_NO_PP_RUN environment var. + * NEWS: Updated. + * TODO: Updated. + 2014-06-22 Paul Eggert <eggert@penguin.cs.ucla.edu> Bring in from GNULIB: @@ -1511,6 +2436,13 @@ been moved into the inetfile() function. (two_way_open): Update args to inetfile(). +2014-04-20 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_rand): Make calls to random() in predictable + order to avoid order of evaluation differences amongst compilers. + Thanks to Anders Magnusson <ragge@ludd.ltu.se> (of the PCC team) + for the suggestion. + 2014-04-18 Arnold D. Robbins <arnold@skeeve.com> * configure.ac: Change adding of -export-dynamic for GCC to be @@ -1877,6 +2809,11 @@ * main.c (main): Ignore SIGPIPE. See the comment in the code. Thanks to Alan Broder for reporting the issue. + Unrelated: + + * rand.c (do_rand): Fix computation and loop checking against + 1.0 to use do..while. + 2013-10-16 Arnold D. Robbins <arnold@skeeve.com> Make -O work again. Turns out that C99 bool variables @@ -1894,6 +2831,11 @@ * re.c (resetup): Add a comment about the joy of syntax bits. + Unrelated: + + * builtin.c (do_rand): If result is exactly 1.0, keep trying. + Thanks to Nelson Beebe. + 2013-10-10 Arnold D. Robbins <arnold@skeeve.com> * dfa.c (lex): Sync with GNU grep. Handle multibyte \s and \S. @@ -1913,6 +2855,13 @@ * dfa.c: Sync with GNU grep. +2013-09-25 Arnold D. Robbins <arnold@skeeve.com> + + * builtin.c (do_rand): Make the result more random by calling + random() twice. See the comment in the code. Thanks to + Bob Jewett <jewett@bill.scs.agilent.com> for the report and + the fix. + 2013-09-24 Arnold D. Robbins <arnold@skeeve.com> * debug.c (find_rule): Handle case where lineno is zero. Can happen @@ -1994,6 +2943,12 @@ * regcomp.c, regex.h, regex_internal.h: Sync with GLIBC. +2013-08-22 Arnold D. Robbins <arnold@skeeve.com> + + * str_array.c (env_store): If the new value being stored is NULL, + pass in "" instead. Avoids core dump on Mac OS X. + Thanks to Hermann Peifer for the bug report. + 2013-08-20 Arnold D. Robbins <arnold@skeeve.com> * nonposix.h: New file. Contains FAKE_FD_VALUE. @@ -2002,6 +2957,16 @@ 2013-08-18 Arnold D. Robbins <arnold@skeeve.com> + Reflect updates to ENVIRON into the real environment. + + * awk.h (init_env_array): Add declaration. + * main.c (load_environ): Call init_env_array. + * str_array.c (env_remove, env_store, env_clear, init_env_array): + New functions. + (env_array_func): New array vtable. + +2013-08-18 Arnold D. Robbins <arnold@skeeve.com> + * array.c (force_array): Set symbol->xarray to NULL before initing the array if it was Node_var_new. (null_array): Restore assert, undoing change of 2013-05-27. @@ -2010,6 +2975,24 @@ * debug.c (print_memory): Fix whitespace / indentation. +2013-08-02 Arnold D. Robbins <arnold@skeeve.com> + + * awkgram.y (append_rule): Add attempt to insert any comment + before a rule. Commented out at the moment. + +2013-07-30 Arnold D. Robbins <arnold@skeeve.com> + + * awk.h (enum opcodeval): Add Op_comment. + * awkgram.y (comment): New variable to hold comment text. + (statement): Add saved comments to lists being built. + (allow_newline): Save comment text if necessary. Append if have + existing text. + (yylex): Ditto. + * debug.c (print_instruction): Handle Op_comment. + * eval.c (optypes): Add entry for Op_comment. + * interpret.h (r_interpret): Ditto. + * profile.c (pprint): For Op_comment, print the comment text. + 2013-07-24 Arnold D. Robbins <arnold@skeeve.com> * io.c (FAKE_FD_VALUE): Move definition from here ... @@ -2020,6 +3003,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 @@ -2030,6 +3052,45 @@ force_string redundant, since node_to_awk_value does that internally when we request a string. +2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * eval.c (update_ERRNO_string): Set PROCINFO["errno"] to 0. + * io.c (inrec): Since get_a_record may now return -2, be sure + to throw an error in that case as well. + (wait_any): Fix what appears to be a bug. The old logic repeatedly + called wait until it failed. When a process has multiple children, + this causes it to stall until all of them have exited. Instead, + we now exit the function after the first successful wait call. + (do_getline_redir, do_getline): Handle case where get_a_record + returns -2. + (errno_io_retry): New function to decide whether an I/O operation should + be retried. + (get_a_record): When read returns an error, call errno_io_retry to + decide whether the operation should be retried. If so, return -2 + instead of setting the IOP_AT_EOF flag. + +2013-07-01 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * eval.c (update_ERRNO_int, unset_ERRNO): Update PROCINFO["errno"]. + +2013-06-30 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * awk.h (redirect_string): Declare new function that provides API access + to the redirection mechanism. + * gawkapi.h (GAWK_API_MINOR_VERSION): Bump from 0 to 1 since 2 new + hooks were added to the api. + (gawk_api_t): Add 2 new functions api_lookup_file and api_get_file. + (lookup_file, get_file): New macros to wrap the new API functions. + * gawkapi.c (curfile): Declare this extern, since it is needed + by lookup_file and get_flie. + (api_lookup_file): Find an open file using curfile or getredirect(). + (api_get_file): Find or open a file using curfile or redirect_string(). + (api_impl): Add api_lookup_file and api_get_file. + * io.c (redirect_string): Renamed from redirect and changed arguments + to take a string instead of a 'NODE *'. This allows it to be called + through the API's new get_file hook. + (redirect): Now implemented by calling redirect_string backend function. + 2013-07-04 Arnold D. Robbins <arnold@skeeve.com> * builtin.c (format_tree): Fixes for %c with multibyte characters diff --git a/Makefile.am b/Makefile.am index 4ddd8ff4..0bc2143e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,7 +75,7 @@ if ENABLE_EXTENSIONS SUBDIRS += extension endif -SUBDIRS += doc awklib po test +SUBDIRS += extras doc awklib po test # what to make and install bin_PROGRAMS = gawk diff --git a/Makefile.in b/Makefile.in index 7a2ccd3b..5585046e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -118,14 +118,14 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/arch.m4 \ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ - $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lcmessage.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \ - $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/mpfr.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/noreturn.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/socket.m4 \ - $(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/mpfr.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/noreturn.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \ + $(top_srcdir)/m4/socket.m4 $(top_srcdir)/m4/ulonglong.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ @@ -262,9 +262,9 @@ am__define_uniq_tagged_files = \ ETAGS = etags CTAGS = ctags CSCOPE = cscope -DIST_SUBDIRS = . extension doc awklib po test +DIST_SUBDIRS = . extension extras doc awklib po test am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/configh.in ABOUT-NLS \ - AUTHORS COPYING ChangeLog INSTALL NEWS README awkgram.c \ + AUTHORS COPYING ChangeLog INSTALL NEWS README TODO awkgram.c \ command.c compile config.guess config.rpath config.sub depcomp \ install-sh missing mkinstalldirs ylwrap DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -487,7 +487,7 @@ EXTRA_DIST = \ # # Build in awklib after in doc, since we want to extract # sample files if doc/gawk.texi changed. -SUBDIRS = . $(am__append_1) doc awklib po test +SUBDIRS = . $(am__append_1) extras doc awklib po test include_HEADERS = gawkapi.h # sources for both gawk and dgawk @@ -5,6 +5,82 @@ are permitted in any medium without royalty provided the copyright notice and this notice are preserved. +Changes from 4.1.x to 4.2.0 +--------------------------- + +1. If not in POSIX mode, changes to ENVIRON are reflected into + gawk's environment, affecting any programs run by system() + or for piped redirections. This can also affect built-in routines, such + as mktime(), which is typically influenced by the TZ environment variable. + +2. The series of numbers returned by rand() should now be "more + random" than previously. Gawk's rand() remains repeatable; you will + get the same series of numbers each time you call rand() repeatedly, + but this will be a different series than previously. + +3. The --pretty-print option no longer runs the program too. + +4. The igawk script and igawk.1 man page are no longer installed by + `make install'. They have been obsolete since gawk 4.0.0. + +5. Gawk now has a `intdiv()' function to perform integer division; this is + primarily useful for the -M option to avoid MPFR division when all + values involved are integers. + +6. Gawk can now be built with CMake. This is an alternative build + system for those who may want it; gawk is not going to switch off + use of the autotools anytime soon, if ever. + +7. Gawk now processes a maximum of two hexadecimal digits in \x + escape sequences inside strings. + +8. Setting PROCINFO["redirection", "NONFATAL"] to true makes I/O + errors for "redirection" not fatal, setting ERRNO. Setting + PROCINFO["NONFATAL"] makes all I/O nonfatal. + +9. MirBSD is no longer supported. + +10. Pretty printing now preserves comments and places them into the + pretty-printed file. + +11. `make install' now installs shell startup files + $sysconfdir/profile.d/gawk.{csh,sh} containing shell functions to + manipulate the AWKPATH and AWKLIBPATH environment variables. On a Fedora + system, these files belong in /etc/profile.d, but the appropriate location + may be different on other platforms. + +12. Gawk now supports retryable I/O via PROCINFO[input-file, "RETRY"]; see + the manual. + +13. The API minor version has been increased to 2; the get_file() + API provides access to open redirections. Also see the manual. + +14. Revisions in the POSIX standard remove the special case for POSIX + mode when FS = " " where newline was not a field separator. The code + and doc have been updated. + +15. Gawk now supports strongly typed regexp constants. Such constants + look like @/.../. You can assign them to variables, pass them to + functions, use them in ~, !~ and the case part of a switch statement. + More details are provided in the manual. + +16. The new typeof() function can be used to indicate if a variable or + array element is an array, regexp, string or number. The isarray() + function is deprecated in favor of typeof(). + +17. As promised when 4.1 was released, the old extension mechanism, + using the `extension' function, is now gone. + +18. Support for GNU/Linux on Alpha systems has been removed. + +19. Optimizations are now enabled by default. Use the new -s/--no-optimize + option(s) to disable them. Pretty printing and profiling automatically + disable optimizations so that the output program is the same as the + original input program. + +20. The extension API now provides a mechanism for generating nonfatal + error messages. + Changes from 4.1.3 to 4.1.4 --------------------------- diff --git a/README_d/ChangeLog b/README_d/ChangeLog index 1896fbf8..f61846ec 100644 --- a/README_d/ChangeLog +++ b/README_d/ChangeLog @@ -18,6 +18,10 @@ * README.macosx: New file. +2014-08-12 Juergen Kahrs <jkahrs@users.sourceforge.net> + + * README.cmake: Moved file from top-level to here. + 2014-04-08 Arnold D. Robbins <arnold@skeeve.com> * 4.1.1: Release tar ball made. diff --git a/README_d/README.cmake b/README_d/README.cmake new file mode 100644 index 00000000..b291d1be --- /dev/null +++ b/README_d/README.cmake @@ -0,0 +1,95 @@ +CMake is a build automation system + http://en.wikipedia.org/wiki/Cmake + +We try to use it as a replacement for the established GNU build system. +This attempt is currently only experimental. If you wonder why anyone +should do this, read + + Why the KDE project switched to CMake -- and how + http://lwn.net/Articles/188693/ + Escape from GNU Autohell! + http://www.shlomifish.org/open-source/anti/autohell + +- How can I get GNU Awk compiled with CMake as fast as possible ? + git clone git://git.savannah.gnu.org/gawk.git + cd gawk + git checkout cmake + mkdir build + cd build + cmake .. + make + ./gawk --version + make test +Notice that this git-checkout allows you to read the source code, +track the cmake branch and get updates. You will not be able to +commit anything. + +- How can I use git to contribute source code ? +You need an account at Savannah. Read this to understand the first steps: + http://savannah.gnu.org/maintenance/UsingGit + README.git +Use your account there to register your public ssh key at Savannah. +Then you are ready to checkout. Remember that (when cloning) you are +setting up your own local repository and make sure you configure it +properly. + git clone ssh://my_account_name@git.sv.gnu.org/srv/git/gawk.git + git config --global user.name "first-name last-name" + git config --global user.email First.Last@email.com + git config --global color.ui auto + +- What is the current status of the cmake branch ? +It has just begun, pre-alpha, unclear if it will ever be taken up +by the maintainer. We want to study if using CMake with such a +basic tool like gawk is feasible and if it easier to use than +the GNU build system. + +- Where can I find a tutorial on CMake basics ? +Use the "official tutorial": + http://www.cmake.org/cmake/help/cmake_tutorial.html + +- Where is the reference of all commands and variables ? +Depending on the CMake version you use, select one of these: + http://www.cmake.org/cmake/help/v2.8.10/cmake.html + +- How can I cross-compile ? +Proceed in the same way as explained above for native compilation, +but use a different build directory. When using CMake, do this: + cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain_mingw32.cmake .. +Write a new Toolchain file for your cross-compiler and use it. + +- How can I build an installable file ? +Use "make package". The exact kind of installable file depends on your +operating system and defaults to TGZ. + +- Can I build an executable that runs on any Win32 platform ? +Yes, there are two ways of doing this. +In both cases you need a MinGW compiler and the NSIS package builder +installed on the host that shall do the build. + http://sourceforge.net/projects/mingw + http://sourceforge.net/projects/nsis +When installed properly, the NSIS tool can even build an installer file +(a single .exe file that unpacks, registers and installs the gawk executable +and several other files). +1. way: native build on a Win32 platform + http://www.cmake.org/cmake/help/runningcmake.html + After clicking "Configure" select the MinGW option with the default native compiler + In the build directory, the command "mingw32-make" will build the gawk.exe + The command "mingw32-make package" will build installer file +2. way: build with cross-compiler on a Linux platform like Ubuntu 12.04 LTS + Proceed as describe above for cross-compilers. + The command "make ; make package" will build gawk.exe and the installer file + +- How can I run test cases ? +You can run all the test cases that are defined in test/Makefile.am. +These test case scripts were not changed, but the way they are invoked has +been adapted to CMake habits. +See http://cmake.org/Wiki/CMake/Testing_With_CTest#Simple_Testing + cmake .. + make + make test # run all test cases + ctest -N # list all test cases but don't run them + ctest -R BASIC # run all test cases belonging to group BASIC + ctest -R MPFR # run all test cases belonging to group MPFR + ctest -E SHLIB.filefunc # run all tests, except the SHLIB.filefunc test case +Remember that running test cases is possible only after a native build. + @@ -0,0 +1,165 @@ +Fri Jun 19 12:44:56 IDT 2015 +============================ + +There were too many files tracking different thoughts and ideas for +things to do, or consider doing. This file merges them into one. As +tasks are completed, they should be removed. + +This file should exist only in the master branch or branches based off +of it for development, but not in the stable branch. This may require some +careful work with Git. + +TODO +==== + +Minor Cleanups and Code Improvements +------------------------------------ + + API: + ??? #if !defined(GAWK) && !defined(GAWK_OMIT_CONVENIENCE_MACROS) + + ?? Add debugger commands to reference card + + Look at function order within files. + + Consider removing use of and/or need for the protos.h file. + + Recheck if gnulib regex can be dropped in + + Fully synchronize whitespace tests (for \s, \S in Unicode + environment) with those of GNU grep. + + See if something like b = a "" can be optimized to not do + a concatenation, but instead just set STRCUR on a. + +Minor New Features +------------------ + + Enable command line source text in the debugger. + + Enhance extension/fork.c waitpid to allow the caller to specify + the options. And add an optional array argument to wait and + waitpid in which to return exit status information. + + Consider relaxing the strictness of --posix. + + ? Add an optional base to strtonum, allowing 2-36. + + ? Optional third argument for index indicating where to start the + search. + +Major New Features +------------------ + + Think about how to generalize indirect access. Manuel Collado + suggests things like + + foo = 5 + @"foo" += 4 + + Also needed: + + Indirect through array elements, not just scalar variables + + Add ability to do decimal arithmetic. + + Rework management of array index storage. (Partially DONE.) + + Consider using an atom table for all string array indices. + + DBM storage of awk arrays. Try to allow multiple dbm packages. + + ?? A RECLEN variable for fixed-length record input. PROCINFO["RS"] + would be "RS" or "RECLEN" depending upon what's in use. + *** Could this be done as an extension? + + ?? Use a new or improved dfa and/or regex library. + + Rewrite in C++. + +Things To Think About That May Never Happen +------------------------------------------- + + Consider making shadowed variables a warning and not + a fatal warning when --lint=fatal. + + Similar for extra parameters in a function call. + + Look at code coverage tools, like S2E: https://s2e.epfl.ch/ + + Try running with diehard. See http://www.diehard-software.org, + https://github.com/emeryberger/DieHard + + Implement namespaces. Arnold suggested the following in an email: + - Extend the definition of an 'identifier' to include "." as a valid + character although an identifier can't start with it. + - Extension libraries install functions and global variables with names + that have a "." in them: XML.parse(), XML.name, whatever. + - Awk code can read/write such variables and call such functions, + but they cannot define such functions + function XML.foo() { .. } # error + or create a variable with such a name if it doesn't exist. This would + be a run-time error, not a parse-time error. + - This last rule may be too restrictive. + I don't want to get into fancy rules a la perl and file-scope visibility + etc, I'd like to keep things simple. But how we design this is going + to be very important. + + Include a sample rpm spec file in a new packaging subdirectory. + (Really needed?) + + Patch lexer for @include and @load to make quotes optional. + (Really needed?) + + Add a lint check if the return value of a function is used but + the function did not supply a value. + + Consider making gawk output +nan for NaN values so that it + will accept its own output as input. + NOTE: Investigated this. GLIBC formats NaN as '-nan' + and -NaN as 'nan'. Dealing with this is not simple. + + Enhance FIELDWIDTHS with some way to indicate "the rest of the record". + E.g., a length of 0 or -1 or something. Maybe "n"? + + Review the bash source script for working with shared libraries in + order to nuke the use of libtool. [ Partially started in the + dead-branches/nolibtool branch. ] + +Things That We Decided We Will Never Do +======================================= + + Consider moving var_value info into Node_var itself to reduce + memory usage. This would break all uses of get_lhs in the + code. It's too sweeping a change. + + Add macros for working with flags instead of using & and | + directly. + + FIX regular field splitting to use FPAT algorithm. + Note: Looked at this. Not sure it's with the trouble: + If it ain't broke... + + Scope IDs for IPv6 addresses + + Gnulib + + Make FIELDWIDTHS be an array? + + "Do an optimization pass over parse tree?" + This isn't relevant now that we are using a byte code engine. + + "Consider integrating Fred Fish's DBUG library into gawk." + I did this once as an experiment. But I don't see a lot of value + to this at this stage of the development. Stepping through things + in a debugger is generally enough. Also, I would have to try to + track down the latest version of this. + + "Make awk '/foo/' files... run at egrep speeds" (How?) + This has been on the list since the early days (gawk 1.x or early + 2.x). But I am not sure how to really do this, nor have I done + timings, nor does there seem to be any real demand for this. + + Change from dlopen to using the libltdl library (i.e. lt_dlopen). + This may support more platforms. If we move off of libtool + then this is the wrong direction. @@ -1155,7 +1155,6 @@ m4_include([m4/codeset.m4]) m4_include([m4/gettext.m4]) m4_include([m4/iconv.m4]) m4_include([m4/intlmacosx.m4]) -m4_include([m4/isc-posix.m4]) m4_include([m4/lcmessage.m4]) m4_include([m4/lib-ld.m4]) m4_include([m4/lib-link.m4]) @@ -417,7 +417,7 @@ concat_exp(int nargs, bool do_subsep) } len += (nargs - 1) * subseplen; - emalloc(str, char *, len + 2, "concat_exp"); + emalloc(str, char *, len + 1, "concat_exp"); r = args_array[nargs]; memcpy(str, r->stptr, r->stlen); @@ -704,7 +704,14 @@ value_info(NODE *n) if ((n->flags & (STRING|STRCUR)) == STRCUR) { fprintf(output_fp, "]["); fprintf(output_fp, "stfmt=%d, ", n->stfmt); - fprintf(output_fp, "CONVFMT=\"%s\"", n->stfmt <= -1 ? "<unused>" + /* + * If not STFMT_UNUSED, could be CONVFMT or OFMT if last + * used in a print statement. If immutable, could be that it + * was originally set as a string, or it's a number that has + * an integer value. + */ + fprintf(output_fp, "FMT=\"%s\"", + n->stfmt == STFMT_UNUSED ? "<unused>" : fmt_list[n->stfmt]->stptr); } @@ -1157,17 +1164,8 @@ sort_up_value_type(const void *p1, const void *p2) } /* two scalars */ - /* 2. Resolve MAYBE_NUM, so that have only NUMBER or STRING */ - if ((n1->flags & MAYBE_NUM) != 0) - (void) force_number(n1); - if ((n2->flags & MAYBE_NUM) != 0) - (void) force_number(n2); - - /* 2.5. Resolve INTIND, so that is STRING, and not NUMBER */ - if ((n1->flags & INTIND) != 0) - (void) force_string(n1); - if ((n2->flags & INTIND) != 0) - (void) force_string(n2); + (void) fixtype(n1); + (void) fixtype(n2); if ((n1->flags & NUMBER) != 0 && (n2->flags & NUMBER) != 0) { return cmp_numbers(n1, n2); @@ -264,6 +264,7 @@ typedef enum nodevals { Node_val, /* node is a value - type in flags */ Node_regex, /* a regexp, text, compiled, flags, etc */ Node_dynregex, /* a dynamic regexp */ + Node_typedregex, /* like Node_regex, but is a real type */ /* symbol table values */ Node_var, /* scalar variable, lnode is value */ @@ -272,7 +273,6 @@ typedef enum nodevals { Node_param_list, /* lnode is a variable, rnode is more list */ Node_func, /* lnode is param. list, rnode is body */ Node_ext_func, /* extension function, code_ptr is builtin code */ - Node_old_ext_func, /* extension function, code_ptr is builtin code */ Node_builtin_func, /* built-in function, main use is for FUNCTAB */ Node_array_ref, /* array passed by ref as parameter */ @@ -392,8 +392,11 @@ typedef struct exp_node { /* type = Node_val */ /* - * STRING and NUMBER are mutually exclusive. They represent the - * type of a value as assigned. + * STRING and NUMBER are mutually exclusive, except for the special + * case of an uninitialized value, represented internally by + * Nnull_string. They represent the type of a value as assigned. + * Nnull_string has both STRING and NUMBER attributes, but all other + * scalar values should have precisely one of these bits set. * * STRCUR and NUMCUR are not mutually exclusive. They represent that * the particular type of value is up to date. For example, @@ -408,7 +411,8 @@ typedef struct exp_node { * * MAYBE_NUM is the joker. It means "this is string data, but * the user may have really wanted it to be a number. If we have - * to guess, like in a comparison, turn it into a number." + * to guess, like in a comparison, turn it into a number if the string + * is indeed numeric." * For example, gawk -v a=42 .... * Here, `a' gets STRING|STRCUR|MAYBE_NUM and then when used where * a number is needed, it gets turned into a NUMBER and STRING @@ -472,6 +476,13 @@ typedef struct exp_node { #define re_cnt flags /* Node_val */ +/* + * Note that the string in stptr may not be NUL-terminated, but it is + * guaranteed to have at least one extra byte that may be temporarily set + * to '\0'. This is helpful when calling functions such as strtod that require + * a NUL-terminated argument. In particular, field values $n for n > 0 and + * n < NF will not have a NUL terminator, since they point into the $0 buffer. + */ #define stptr sub.val.sp #define stlen sub.val.slen #define valref sub.val.sref @@ -486,6 +497,16 @@ typedef struct exp_node { #define numbr sub.val.fltnum #endif +/* + * If stfmt is set to STFMT_UNUSED, it means that the string representation + * stored in stptr is not a function of the value of CONVFMT or OFMT. That + * indicates that either the string value was explicitly assigned, or it + * was converted from a NUMBER that has an integer value. When stfmt is not + * set to STFMT_UNUSED, it is an offset into the fmt_list array of distinct + * CONVFMT and OFMT node pointers. + */ +#define STFMT_UNUSED -1 + /* Node_arrayfor */ #define for_list sub.nodep.r.av #define for_list_size sub.nodep.reflags @@ -548,6 +569,11 @@ typedef struct exp_node { #define adepth sub.nodep.l.ll #define alevel sub.nodep.x.xl +/* Op_comment */ +#define comment_type sub.val.idx +#define EOL_COMMENT 1 +#define FULL_COMMENT 2 + /* --------------------------------lint warning types----------------------------*/ typedef enum lintvals { LINT_illegal, @@ -646,7 +672,6 @@ typedef enum opcodeval { Op_builtin, Op_sub_builtin, /* sub, gsub and gensub */ Op_ext_builtin, - Op_old_ext_builtin, /* temporary */ Op_in_array, /* boolean test of membership in array */ /* function call instruction */ @@ -655,6 +680,7 @@ typedef enum opcodeval { Op_push, /* scalar variable */ Op_push_arg, /* variable type (scalar or array) argument to built-in */ + Op_push_arg_untyped, /* like Op_push_arg, but for typeof */ Op_push_i, /* number, string */ Op_push_re, /* regex */ Op_push_array, @@ -682,6 +708,7 @@ typedef enum opcodeval { Op_func, + Op_comment, /* for pretty printing */ Op_exec_count, Op_breakpoint, Op_lint, @@ -1195,6 +1222,7 @@ extern void r_unref(NODE *tmp); static inline void DEREF(NODE *r) { + assert(r->valref > 0); if (--r->valref == 0) r_unref(r); } @@ -1331,6 +1359,7 @@ extern NODE *do_aoption(int nargs); extern NODE *do_asort(int nargs); extern NODE *do_asorti(int nargs); extern unsigned long (*hash)(const char *s, size_t len, unsigned long hsize, size_t *code); +extern void init_env_array(NODE *env_node); /* awkgram.c */ extern NODE *variable(int location, char *name, NODETYPE type); extern int parse_program(INSTRUCTION **pcode); @@ -1393,10 +1422,12 @@ extern NODE *do_or(int nargs); extern NODE *do_xor(int nargs); extern NODE *do_compl(int nargs); extern NODE *do_strtonum(int nargs); -extern AWKNUM nondec2awknum(char *str, size_t len); +extern AWKNUM nondec2awknum(char *str, size_t len, char **endptr); extern NODE *do_dcgettext(int nargs); extern NODE *do_dcngettext(int nargs); extern NODE *do_bindtextdomain(int nargs); +extern NODE *do_intdiv(int nargs); +extern NODE *do_typeof(int nargs); extern int strncasecmpmbs(const unsigned char *, const unsigned char *, size_t); /* eval.c */ @@ -1435,10 +1466,8 @@ extern NODE **r_get_field(NODE *n, Func_ptr *assign, bool reference); /* ext.c */ extern NODE *do_ext(int nargs); void load_ext(const char *lib_name); /* temporary */ -extern NODE *load_old_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj); extern void close_extensions(void); #ifdef DYNAMIC -extern void make_old_builtin(const char *, NODE *(*)(int), int); extern awk_bool_t make_builtin(const awk_ext_func_t *); extern NODE *get_argument(int); extern NODE *get_actual_argument(NODE *, int, bool); @@ -1500,7 +1529,10 @@ extern void register_two_way_processor(awk_two_way_processor_t *processor); 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(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal); +extern struct redirect *redirect_string(const char *redir_exp_str, + size_t redir_exp_len, bool not_string_flag, int redirtype, + int *errflg, int extfd, bool failure_fatal); extern NODE *do_close(int nargs); extern int flush_io(void); extern int close_io(bool *stdio_problem); @@ -1515,6 +1547,8 @@ extern NODE *do_getline(int intovar, IOBUF *iop); extern struct redirect *getredirect(const char *str, int len); extern bool inrec(IOBUF *iop, int *errcode); extern int nextfile(IOBUF **curfile, bool skipping); +extern bool is_non_fatal_std(FILE *fp); +extern bool is_non_fatal_redirect(const char *str); /* main.c */ extern int arg_assign(char *arg, bool initing); extern int is_std_var(const char *var); @@ -1522,6 +1556,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); @@ -1538,6 +1573,7 @@ extern NODE *do_mpfr_compl(int); extern NODE *do_mpfr_cos(int); extern NODE *do_mpfr_exp(int); extern NODE *do_mpfr_int(int); +extern NODE *do_mpfr_intdiv(int); extern NODE *do_mpfr_log(int); extern NODE *do_mpfr_lshift(int); extern NODE *do_mpfr_or(int); @@ -1768,8 +1804,11 @@ dupnode(NODE *n) static inline NODE * force_string(NODE *s) { + if (s->type == Node_typedregex) + return dupnode(s->re_exp); + if ((s->flags & STRCUR) != 0 - && (s->stfmt == -1 || s->stfmt == CONVFMTidx) + && (s->stfmt == STFMT_UNUSED || s->stfmt == CONVFMTidx) ) return s; return format_val(CONVFMT, CONVFMTidx, s); @@ -1794,11 +1833,59 @@ unref(NODE *r) static inline NODE * force_number(NODE *n) { + if (n->type == Node_typedregex) + return Nnull_string; + return (n->flags & NUMCUR) != 0 ? n : str2number(n); } #endif /* GAWKDEBUG */ + +/* fixtype --- make a node decide if it's a number or a string */ + +/* + * In certain contexts, the true type of a scalar value matters, and we + * must ascertain whether it is a NUMBER or a STRING. In such situations, + * please use this function to resolve the type. + * + * It is safe to assume that the return value will be the same NODE, + * since force_number on a MAYBE_NUM should always return the same NODE, + * and force_string on an INTIND should as well. + * + * There is no way to handle a Node_typedregex correctly, so we ignore + * that case. + */ + +static inline NODE * +fixtype(NODE *n) +{ + assert(n->type == Node_val || n->type == Node_typedregex); + if (n->type == Node_val) { + if ((n->flags & MAYBE_NUM) != 0) + return force_number(n); + if ((n->flags & INTIND) != 0) + return force_string(n); + } + return n; +} + +/* boolval --- return true/false based on awk's criteria */ + +/* + * In awk, a value is considered to be true if it is nonzero _or_ + * non-null. Otherwise, the value is false. + */ + +static inline int +boolval(NODE *t) +{ + (void) fixtype(t); + if ((t->flags & NUMBER) != 0) + return ! iszero(t); + return (t->stlen > 0); +} + /* emalloc_real --- malloc with error checking */ static inline void * @@ -123,10 +123,17 @@ static void check_funcs(void); static ssize_t read_one_line(int fd, void *buffer, size_t count); static int one_line_close(int fd); +static void split_comment(void); +static void check_comment(void); static bool at_seen = false; static bool want_source = false; static bool want_regexp = false; /* lexical scanning kludge */ +static enum { + FUNC_HEADER, + FUNC_BODY, + DONT_CHECK +} want_param_names = DONT_CHECK; /* ditto */ static char *in_function; /* parsing kludge */ static int rule = 0; @@ -181,17 +188,29 @@ 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 *prior_comment = NULL; +static INSTRUCTION *comment_to_save = NULL; +static INSTRUCTION *program_comment = NULL; +static INSTRUCTION *function_comment = NULL; +static INSTRUCTION *block_comment = NULL; + +static bool func_first = true; +static bool first_rule = true; static inline INSTRUCTION *list_create(INSTRUCTION *x); static inline INSTRUCTION *list_append(INSTRUCTION *l, INSTRUCTION *x); static inline INSTRUCTION *list_prepend(INSTRUCTION *l, INSTRUCTION *x); static inline INSTRUCTION *list_merge(INSTRUCTION *l1, INSTRUCTION *l2); +static inline INSTRUCTION *add_pending_comment(INSTRUCTION *stmt); extern double fmod(double x, double y); #define YYSTYPE INSTRUCTION * -#line 195 "awkgram.c" /* yacc.c:339 */ +#line 214 "awkgram.c" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -229,51 +248,52 @@ extern int yydebug; FILENAME = 261, YNUMBER = 262, YSTRING = 263, - RELOP = 264, - IO_OUT = 265, - IO_IN = 266, - ASSIGNOP = 267, - ASSIGN = 268, - MATCHOP = 269, - CONCAT_OP = 270, - SUBSCRIPT = 271, - LEX_BEGIN = 272, - LEX_END = 273, - LEX_IF = 274, - LEX_ELSE = 275, - LEX_RETURN = 276, - LEX_DELETE = 277, - LEX_SWITCH = 278, - LEX_CASE = 279, - LEX_DEFAULT = 280, - LEX_WHILE = 281, - LEX_DO = 282, - LEX_FOR = 283, - LEX_BREAK = 284, - LEX_CONTINUE = 285, - LEX_PRINT = 286, - LEX_PRINTF = 287, - LEX_NEXT = 288, - LEX_EXIT = 289, - LEX_FUNCTION = 290, - LEX_BEGINFILE = 291, - LEX_ENDFILE = 292, - LEX_GETLINE = 293, - LEX_NEXTFILE = 294, - LEX_IN = 295, - LEX_AND = 296, - LEX_OR = 297, - INCREMENT = 298, - DECREMENT = 299, - LEX_BUILTIN = 300, - LEX_LENGTH = 301, - LEX_EOF = 302, - LEX_INCLUDE = 303, - LEX_EVAL = 304, - LEX_LOAD = 305, - NEWLINE = 306, - SLASH_BEFORE_EQUAL = 307, - UNARY = 308 + TYPED_REGEXP = 264, + RELOP = 265, + IO_OUT = 266, + IO_IN = 267, + ASSIGNOP = 268, + ASSIGN = 269, + MATCHOP = 270, + CONCAT_OP = 271, + SUBSCRIPT = 272, + LEX_BEGIN = 273, + LEX_END = 274, + LEX_IF = 275, + LEX_ELSE = 276, + LEX_RETURN = 277, + LEX_DELETE = 278, + LEX_SWITCH = 279, + LEX_CASE = 280, + LEX_DEFAULT = 281, + LEX_WHILE = 282, + LEX_DO = 283, + LEX_FOR = 284, + LEX_BREAK = 285, + LEX_CONTINUE = 286, + LEX_PRINT = 287, + LEX_PRINTF = 288, + LEX_NEXT = 289, + LEX_EXIT = 290, + LEX_FUNCTION = 291, + LEX_BEGINFILE = 292, + LEX_ENDFILE = 293, + LEX_GETLINE = 294, + LEX_NEXTFILE = 295, + LEX_IN = 296, + LEX_AND = 297, + LEX_OR = 298, + INCREMENT = 299, + DECREMENT = 300, + LEX_BUILTIN = 301, + LEX_LENGTH = 302, + LEX_EOF = 303, + LEX_INCLUDE = 304, + LEX_EVAL = 305, + LEX_LOAD = 306, + NEWLINE = 307, + SLASH_BEFORE_EQUAL = 308, + UNARY = 309 }; #endif /* Tokens. */ @@ -283,51 +303,52 @@ extern int yydebug; #define FILENAME 261 #define YNUMBER 262 #define YSTRING 263 -#define RELOP 264 -#define IO_OUT 265 -#define IO_IN 266 -#define ASSIGNOP 267 -#define ASSIGN 268 -#define MATCHOP 269 -#define CONCAT_OP 270 -#define SUBSCRIPT 271 -#define LEX_BEGIN 272 -#define LEX_END 273 -#define LEX_IF 274 -#define LEX_ELSE 275 -#define LEX_RETURN 276 -#define LEX_DELETE 277 -#define LEX_SWITCH 278 -#define LEX_CASE 279 -#define LEX_DEFAULT 280 -#define LEX_WHILE 281 -#define LEX_DO 282 -#define LEX_FOR 283 -#define LEX_BREAK 284 -#define LEX_CONTINUE 285 -#define LEX_PRINT 286 -#define LEX_PRINTF 287 -#define LEX_NEXT 288 -#define LEX_EXIT 289 -#define LEX_FUNCTION 290 -#define LEX_BEGINFILE 291 -#define LEX_ENDFILE 292 -#define LEX_GETLINE 293 -#define LEX_NEXTFILE 294 -#define LEX_IN 295 -#define LEX_AND 296 -#define LEX_OR 297 -#define INCREMENT 298 -#define DECREMENT 299 -#define LEX_BUILTIN 300 -#define LEX_LENGTH 301 -#define LEX_EOF 302 -#define LEX_INCLUDE 303 -#define LEX_EVAL 304 -#define LEX_LOAD 305 -#define NEWLINE 306 -#define SLASH_BEFORE_EQUAL 307 -#define UNARY 308 +#define TYPED_REGEXP 264 +#define RELOP 265 +#define IO_OUT 266 +#define IO_IN 267 +#define ASSIGNOP 268 +#define ASSIGN 269 +#define MATCHOP 270 +#define CONCAT_OP 271 +#define SUBSCRIPT 272 +#define LEX_BEGIN 273 +#define LEX_END 274 +#define LEX_IF 275 +#define LEX_ELSE 276 +#define LEX_RETURN 277 +#define LEX_DELETE 278 +#define LEX_SWITCH 279 +#define LEX_CASE 280 +#define LEX_DEFAULT 281 +#define LEX_WHILE 282 +#define LEX_DO 283 +#define LEX_FOR 284 +#define LEX_BREAK 285 +#define LEX_CONTINUE 286 +#define LEX_PRINT 287 +#define LEX_PRINTF 288 +#define LEX_NEXT 289 +#define LEX_EXIT 290 +#define LEX_FUNCTION 291 +#define LEX_BEGINFILE 292 +#define LEX_ENDFILE 293 +#define LEX_GETLINE 294 +#define LEX_NEXTFILE 295 +#define LEX_IN 296 +#define LEX_AND 297 +#define LEX_OR 298 +#define INCREMENT 299 +#define DECREMENT 300 +#define LEX_BUILTIN 301 +#define LEX_LENGTH 302 +#define LEX_EOF 303 +#define LEX_INCLUDE 304 +#define LEX_EVAL 305 +#define LEX_LOAD 306 +#define NEWLINE 307 +#define SLASH_BEFORE_EQUAL 308 +#define UNARY 309 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED @@ -345,7 +366,7 @@ int yyparse (void); /* Copy the second part of user declarations. */ -#line 349 "awkgram.c" /* yacc.c:358 */ +#line 370 "awkgram.c" /* yacc.c:358 */ #ifdef short # undef short @@ -587,21 +608,21 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 1155 +#define YYLAST 1236 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 75 +#define YYNTOKENS 76 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 65 +#define YYNNTS 70 /* YYNRULES -- Number of rules. */ -#define YYNRULES 188 +#define YYNRULES 203 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 335 +#define YYNSTATES 350 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 308 +#define YYMAXUTOK 309 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -613,16 +634,16 @@ static const yytype_uint8 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 63, 2, 2, 66, 62, 2, 2, - 67, 68, 60, 58, 55, 59, 2, 61, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 54, 74, - 56, 2, 57, 53, 69, 2, 2, 2, 2, 2, + 2, 2, 2, 64, 2, 2, 67, 63, 2, 2, + 68, 69, 61, 59, 56, 60, 2, 62, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 55, 75, + 57, 2, 58, 54, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 70, 2, 71, 65, 2, 2, 2, 2, 2, + 2, 71, 2, 72, 66, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 72, 2, 73, 2, 2, 2, 2, + 2, 2, 2, 73, 2, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -640,32 +661,34 @@ static const yytype_uint8 yytranslate[] = 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 64 + 45, 46, 47, 48, 49, 50, 51, 52, 53, 65 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 194, 194, 196, 201, 202, 206, 218, 222, 233, - 239, 245, 254, 262, 264, 269, 277, 279, 285, 286, - 288, 314, 325, 336, 342, 351, 361, 363, 365, 371, - 379, 380, 384, 403, 402, 436, 438, 443, 444, 457, - 462, 463, 467, 469, 471, 478, 568, 610, 652, 765, - 772, 779, 789, 798, 807, 816, 827, 843, 842, 866, - 878, 878, 976, 976, 1009, 1039, 1045, 1046, 1052, 1053, - 1060, 1065, 1077, 1091, 1093, 1101, 1106, 1108, 1116, 1118, - 1127, 1128, 1136, 1141, 1141, 1152, 1156, 1164, 1165, 1168, - 1170, 1175, 1176, 1185, 1186, 1191, 1196, 1205, 1207, 1209, - 1216, 1217, 1223, 1224, 1229, 1231, 1236, 1238, 1246, 1251, - 1260, 1267, 1269, 1271, 1287, 1297, 1304, 1306, 1311, 1313, - 1315, 1323, 1325, 1330, 1332, 1337, 1339, 1341, 1391, 1393, - 1395, 1397, 1399, 1401, 1403, 1405, 1419, 1424, 1429, 1454, - 1460, 1462, 1464, 1466, 1468, 1470, 1475, 1479, 1511, 1513, - 1519, 1525, 1538, 1539, 1540, 1545, 1550, 1554, 1558, 1573, - 1586, 1591, 1628, 1657, 1658, 1664, 1665, 1670, 1672, 1679, - 1696, 1713, 1715, 1722, 1727, 1735, 1745, 1757, 1766, 1770, - 1774, 1778, 1782, 1786, 1789, 1791, 1795, 1799, 1803 + 0, 213, 213, 215, 220, 221, 225, 237, 242, 253, + 260, 266, 275, 283, 285, 290, 298, 300, 306, 314, + 324, 354, 368, 382, 390, 401, 413, 415, 417, 423, + 431, 432, 436, 436, 482, 481, 515, 537, 539, 544, + 554, 601, 606, 607, 611, 613, 615, 622, 712, 754, + 796, 909, 916, 923, 934, 944, 954, 964, 976, 993, + 992, 1017, 1029, 1029, 1128, 1128, 1162, 1193, 1202, 1203, + 1209, 1210, 1217, 1222, 1234, 1248, 1250, 1258, 1263, 1265, + 1273, 1282, 1284, 1293, 1294, 1302, 1307, 1307, 1318, 1322, + 1330, 1331, 1334, 1336, 1341, 1342, 1351, 1352, 1357, 1362, + 1371, 1373, 1375, 1382, 1383, 1389, 1390, 1395, 1397, 1402, + 1404, 1412, 1417, 1426, 1427, 1432, 1434, 1439, 1441, 1449, + 1454, 1462, 1463, 1468, 1475, 1479, 1481, 1483, 1496, 1513, + 1523, 1530, 1532, 1537, 1539, 1541, 1549, 1551, 1556, 1558, + 1563, 1565, 1567, 1623, 1625, 1627, 1629, 1631, 1633, 1635, + 1637, 1651, 1656, 1661, 1686, 1692, 1694, 1696, 1698, 1700, + 1702, 1707, 1711, 1743, 1745, 1751, 1757, 1770, 1771, 1772, + 1777, 1782, 1786, 1790, 1805, 1818, 1823, 1860, 1889, 1890, + 1896, 1897, 1902, 1904, 1911, 1928, 1945, 1947, 1954, 1959, + 1967, 1977, 1989, 1998, 2002, 2006, 2010, 2014, 2018, 2021, + 2023, 2027, 2031, 2035 }; #endif @@ -675,30 +698,32 @@ static const yytype_uint16 yyrline[] = static const char *const yytname[] = { "$end", "error", "$undefined", "FUNC_CALL", "NAME", "REGEXP", - "FILENAME", "YNUMBER", "YSTRING", "RELOP", "IO_OUT", "IO_IN", "ASSIGNOP", - "ASSIGN", "MATCHOP", "CONCAT_OP", "SUBSCRIPT", "LEX_BEGIN", "LEX_END", - "LEX_IF", "LEX_ELSE", "LEX_RETURN", "LEX_DELETE", "LEX_SWITCH", - "LEX_CASE", "LEX_DEFAULT", "LEX_WHILE", "LEX_DO", "LEX_FOR", "LEX_BREAK", - "LEX_CONTINUE", "LEX_PRINT", "LEX_PRINTF", "LEX_NEXT", "LEX_EXIT", - "LEX_FUNCTION", "LEX_BEGINFILE", "LEX_ENDFILE", "LEX_GETLINE", - "LEX_NEXTFILE", "LEX_IN", "LEX_AND", "LEX_OR", "INCREMENT", "DECREMENT", - "LEX_BUILTIN", "LEX_LENGTH", "LEX_EOF", "LEX_INCLUDE", "LEX_EVAL", - "LEX_LOAD", "NEWLINE", "SLASH_BEFORE_EQUAL", "'?'", "':'", "','", "'<'", - "'>'", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "UNARY", "'^'", "'$'", - "'('", "')'", "'@'", "'['", "']'", "'{'", "'}'", "';'", "$accept", - "program", "rule", "source", "library", "pattern", "action", "func_name", - "lex_builtin", "function_prologue", "regexp", "$@1", "a_slash", - "statements", "statement_term", "statement", "non_compound_stmt", "$@2", - "simple_stmt", "$@3", "$@4", "opt_simple_stmt", "case_statements", - "case_statement", "case_value", "print", "print_expression_list", - "output_redir", "$@5", "if_statement", "nls", "opt_nls", "input_redir", - "opt_param_list", "param_list", "opt_exp", "opt_expression_list", - "expression_list", "exp", "assign_operator", "relop_or_less", "a_relop", - "common_exp", "simp_exp", "simp_exp_nc", "non_post_simp_exp", - "func_call", "direct_func_call", "opt_variable", "delete_subscript_list", - "delete_subscript", "delete_exp_list", "bracketed_exp_list", "subscript", - "subscript_list", "simple_variable", "variable", "opt_incdec", "l_brace", - "r_brace", "r_paren", "opt_semi", "semi", "colon", "comma", YY_NULLPTR + "FILENAME", "YNUMBER", "YSTRING", "TYPED_REGEXP", "RELOP", "IO_OUT", + "IO_IN", "ASSIGNOP", "ASSIGN", "MATCHOP", "CONCAT_OP", "SUBSCRIPT", + "LEX_BEGIN", "LEX_END", "LEX_IF", "LEX_ELSE", "LEX_RETURN", "LEX_DELETE", + "LEX_SWITCH", "LEX_CASE", "LEX_DEFAULT", "LEX_WHILE", "LEX_DO", + "LEX_FOR", "LEX_BREAK", "LEX_CONTINUE", "LEX_PRINT", "LEX_PRINTF", + "LEX_NEXT", "LEX_EXIT", "LEX_FUNCTION", "LEX_BEGINFILE", "LEX_ENDFILE", + "LEX_GETLINE", "LEX_NEXTFILE", "LEX_IN", "LEX_AND", "LEX_OR", + "INCREMENT", "DECREMENT", "LEX_BUILTIN", "LEX_LENGTH", "LEX_EOF", + "LEX_INCLUDE", "LEX_EVAL", "LEX_LOAD", "NEWLINE", "SLASH_BEFORE_EQUAL", + "'?'", "':'", "','", "'<'", "'>'", "'+'", "'-'", "'*'", "'/'", "'%'", + "'!'", "UNARY", "'^'", "'$'", "'('", "')'", "'@'", "'['", "']'", "'{'", + "'}'", "';'", "$accept", "program", "rule", "source", "library", + "pattern", "action", "func_name", "lex_builtin", "function_prologue", + "$@1", "regexp", "$@2", "typed_regexp", "a_slash", "statements", + "statement_term", "statement", "non_compound_stmt", "$@3", "simple_stmt", + "$@4", "$@5", "opt_simple_stmt", "case_statements", "case_statement", + "case_value", "print", "print_expression_list", "output_redir", "$@6", + "if_statement", "nls", "opt_nls", "input_redir", "opt_param_list", + "param_list", "opt_exp", "opt_expression_list", "expression_list", + "opt_fcall_expression_list", "fcall_expression_list", "fcall_exp", "exp", + "assign_operator", "relop_or_less", "a_relop", "common_exp", "simp_exp", + "simp_exp_nc", "non_post_simp_exp", "func_call", "direct_func_call", + "opt_variable", "delete_subscript_list", "delete_subscript", + "delete_exp_list", "bracketed_exp_list", "subscript", "subscript_list", + "simple_variable", "variable", "opt_incdec", "l_brace", "r_brace", + "r_paren", "opt_semi", "semi", "colon", "comma", YY_NULLPTR }; #endif @@ -712,60 +737,61 @@ static const yytype_uint16 yytoknum[] = 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 63, 58, 44, 60, 62, 43, 45, - 42, 47, 37, 33, 308, 94, 36, 40, 41, 64, - 91, 93, 123, 125, 59 + 305, 306, 307, 308, 63, 58, 44, 60, 62, 43, + 45, 42, 47, 37, 33, 309, 94, 36, 40, 41, + 64, 91, 93, 123, 125, 59 }; # endif -#define YYPACT_NINF -273 +#define YYPACT_NINF -275 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-273))) + (!!((Yystate) == (-275))) -#define YYTABLE_NINF -104 +#define YYTABLE_NINF -115 #define yytable_value_is_error(Yytable_value) \ - (!!((Yytable_value) == (-104))) + (!!((Yytable_value) == (-115))) /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int16 yypact[] = { - -273, 376, -273, -273, -27, -21, -273, -273, -273, -273, - 157, -273, -273, 11, 11, 11, -5, -3, -273, -273, - -273, 1019, 1019, -273, 1019, 1065, 821, 116, -273, -20, - 1, -273, -273, 35, 758, 992, 252, 296, -273, -273, - -273, -273, 233, 789, 821, -273, 2, -273, -273, -273, - -273, -273, 63, 54, -273, 69, -273, -273, -273, 789, - 789, 127, 87, 115, 87, 87, 1019, 131, -273, -273, - 55, 295, 40, 47, -273, 83, -273, -273, -273, 35, - -273, 83, -273, 151, -273, -273, 1019, 132, 1019, 1019, - 1019, 83, -273, -273, -273, 1019, 124, 252, 1019, 1019, - 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, - -273, -273, -273, -273, 152, 1019, 100, 16, 1034, 37, - -273, -273, -273, 43, 1019, -273, 100, 100, 295, -273, - -273, -273, 1019, 83, -273, 137, 867, -273, -273, 75, - -19, -273, 77, -19, 35, -273, 596, -273, -273, 123, - -273, 141, 175, 1098, 1019, 161, 11, -26, -26, 87, - 87, 87, 87, -26, -26, 87, 87, 87, 87, -273, - 1034, -273, -273, -273, -273, 100, 65, 252, -273, -273, - 1034, -273, 132, -273, 1034, -273, -273, -273, -273, -273, - 104, -273, 26, 118, 119, 83, 121, -19, -19, -273, - -273, -19, 1019, -19, 83, -273, -273, -19, -273, -273, - 1034, -273, 117, 83, 1019, 1034, -273, 83, -273, 112, - -273, 1019, 1019, -273, 188, 1019, 1019, 710, 900, -273, - -273, -273, -19, 1034, -273, -273, -273, 642, 596, 83, - -273, -273, 1034, -273, -273, -273, 295, -19, -21, 126, - 295, 295, 169, -13, -273, 117, -273, 821, 186, -273, - -273, -273, 83, -273, -273, 13, -273, -273, -273, 83, - 83, 139, 132, 83, 55, -273, -273, 710, -273, -273, - 1, 710, 1019, 100, 743, 137, 1019, 192, -273, -273, - 295, 83, 286, 83, 992, 83, 44, 83, 710, 83, - 946, 710, -273, 247, 154, -273, 156, -273, -273, 946, - 100, -273, -273, -273, 226, 228, -273, 154, -273, 83, - -273, 100, 83, -273, -273, 83, -273, 83, 710, -273, - 448, 710, -273, 522, -273 + -275, 376, -275, -275, -12, -9, -275, -275, -275, -275, + 171, -275, -275, 44, 44, 44, 5, 40, -275, -275, + -275, 1139, 1139, -275, 1139, 1166, 869, 27, -275, -18, + 2, -275, -275, 89, 884, 1065, 192, 214, -275, -275, + -275, -275, 248, 795, 869, -275, 10, -275, -275, -275, + -275, -275, 116, 82, -275, 115, -275, -275, -275, 795, + 795, 166, 107, 104, 107, 107, 1139, 117, -275, -275, + 15, 349, 23, 45, -275, 125, -275, -275, -275, 89, + -275, 125, -275, 178, -275, -275, 1092, 172, 1139, 1139, + 1139, 125, -275, -275, -275, 1139, 146, 192, 1139, 1139, + 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, 1139, + -275, 181, -275, -275, 173, 1139, -275, -275, -275, 128, + 73, -275, 1107, 14, 1107, -275, -275, -275, -275, 1139, + -275, 128, 128, 349, -275, -275, -275, 1139, 125, -275, + 152, 916, -275, -275, 16, 92, -275, 20, 92, 89, + -275, 599, -275, -275, -275, 148, -275, 124, 22, 1048, + 1139, 199, 44, 265, 265, 107, 107, 107, 107, 265, + 265, 107, 107, 107, 107, -275, -275, 1107, -275, 1092, + 842, -275, 43, 192, -275, -275, 1107, -275, 172, -275, + 1107, -275, -275, -275, -275, -275, 133, -275, 41, 144, + 145, 125, 147, 92, 92, -275, -275, 92, 1139, 92, + 125, -275, -275, 92, -275, -275, 1107, -275, 151, 125, + 1139, 1107, -275, -275, -275, -275, -275, -275, 128, 76, + -275, 1139, 1139, -275, 224, 1139, 1139, 715, 949, -275, + -275, -275, 92, 1107, -275, -275, -275, 646, 599, 125, + -275, -275, 1107, 125, -275, 49, 349, 92, -9, 160, + 349, 349, 206, 113, -275, 151, -275, 869, 225, -275, + 169, -275, -275, -275, -275, -275, 125, -275, -275, 11, + -275, -275, -275, 125, 125, 179, 172, 125, 15, -275, + -275, 715, -275, -275, 2, 715, 1139, 128, 762, 152, + 1139, 219, -275, -275, 349, 125, 275, 125, 1065, 125, + 112, 125, 715, 125, 997, 715, -275, 261, 205, -275, + 191, -275, -275, 997, 128, -275, -275, -275, 271, 272, + -275, -275, 205, -275, 125, -275, 128, 125, -275, -275, + 125, -275, 125, 715, -275, 449, 715, -275, 524, -275 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -773,64 +799,65 @@ static const yytype_int16 yypact[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 2, 0, 1, 6, 0, 174, 156, 157, 21, 22, - 0, 23, 24, 163, 0, 0, 0, 151, 5, 87, - 36, 0, 0, 35, 0, 0, 0, 0, 3, 0, - 0, 146, 33, 4, 19, 117, 125, 126, 128, 152, - 160, 176, 153, 0, 0, 171, 0, 175, 27, 26, - 30, 31, 0, 0, 28, 91, 164, 154, 155, 0, - 0, 0, 159, 153, 158, 147, 0, 180, 153, 106, - 0, 104, 0, 0, 161, 89, 186, 7, 8, 40, - 37, 89, 9, 0, 88, 121, 0, 0, 0, 0, - 0, 89, 122, 124, 123, 0, 0, 127, 0, 0, + 2, 0, 1, 6, 0, 189, 171, 172, 21, 22, + 0, 23, 24, 178, 0, 0, 0, 166, 5, 90, + 38, 0, 0, 37, 0, 0, 0, 0, 3, 0, + 0, 161, 34, 4, 19, 132, 140, 141, 143, 167, + 175, 191, 168, 0, 0, 186, 0, 190, 27, 26, + 30, 31, 0, 0, 28, 94, 179, 169, 170, 0, + 0, 0, 174, 168, 173, 162, 0, 195, 168, 109, + 0, 107, 0, 0, 176, 92, 201, 7, 8, 42, + 39, 92, 9, 0, 91, 136, 0, 0, 0, 0, + 0, 92, 137, 139, 138, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 119, 118, 136, 137, 0, 0, 0, 0, 104, 0, - 173, 172, 29, 0, 0, 135, 0, 0, 0, 178, - 179, 177, 107, 89, 183, 0, 0, 148, 14, 0, - 0, 17, 0, 0, 90, 181, 0, 41, 34, 113, - 114, 111, 112, 0, 0, 115, 163, 133, 134, 130, - 131, 132, 129, 144, 145, 141, 142, 143, 140, 120, - 110, 162, 170, 97, 95, 0, 0, 92, 149, 150, - 108, 188, 0, 109, 105, 13, 10, 16, 11, 39, - 0, 57, 0, 0, 0, 89, 0, 0, 0, 78, - 79, 0, 100, 0, 89, 38, 51, 0, 60, 44, - 65, 37, 184, 89, 0, 20, 139, 89, 98, 0, - 138, 0, 100, 62, 0, 0, 0, 0, 66, 52, - 53, 54, 0, 101, 55, 182, 59, 0, 0, 89, - 185, 42, 116, 32, 99, 96, 0, 0, 165, 0, - 0, 0, 0, 174, 67, 0, 56, 0, 82, 80, - 43, 25, 89, 58, 63, 0, 167, 169, 64, 89, - 89, 0, 0, 89, 0, 83, 61, 0, 166, 168, - 0, 0, 0, 0, 0, 81, 0, 85, 68, 46, - 0, 89, 0, 89, 84, 89, 0, 89, 0, 89, - 66, 0, 70, 0, 0, 69, 0, 47, 48, 66, - 0, 86, 73, 76, 0, 0, 77, 0, 187, 89, - 45, 0, 89, 75, 74, 89, 37, 89, 0, 37, - 0, 0, 50, 0, 49 + 134, 133, 151, 152, 0, 0, 117, 36, 122, 0, + 0, 115, 121, 0, 107, 188, 187, 29, 32, 0, + 150, 0, 0, 0, 193, 194, 192, 110, 92, 198, + 0, 0, 163, 14, 0, 0, 17, 0, 0, 93, + 196, 0, 43, 35, 127, 128, 129, 125, 126, 0, + 0, 130, 178, 148, 149, 145, 146, 147, 144, 159, + 160, 156, 157, 158, 155, 124, 135, 123, 177, 118, + 0, 185, 0, 95, 164, 165, 111, 203, 0, 112, + 108, 13, 10, 16, 11, 41, 0, 59, 0, 0, + 0, 92, 0, 0, 0, 81, 82, 0, 103, 0, + 92, 40, 53, 0, 62, 46, 67, 39, 199, 92, + 0, 20, 154, 119, 120, 116, 100, 98, 0, 0, + 153, 0, 103, 64, 0, 0, 0, 0, 68, 54, + 55, 56, 0, 104, 57, 197, 61, 0, 0, 92, + 200, 44, 131, 92, 101, 0, 0, 0, 180, 0, + 0, 0, 0, 189, 69, 0, 58, 0, 85, 83, + 0, 45, 25, 33, 102, 99, 92, 60, 65, 0, + 182, 184, 66, 92, 92, 0, 0, 92, 0, 86, + 63, 0, 181, 183, 0, 0, 0, 0, 0, 84, + 0, 88, 70, 48, 0, 92, 0, 92, 87, 92, + 0, 92, 0, 92, 68, 0, 72, 0, 0, 71, + 0, 49, 50, 68, 0, 89, 75, 78, 0, 0, + 79, 80, 0, 202, 92, 47, 0, 92, 77, 76, + 92, 39, 92, 0, 39, 0, 0, 52, 0, 51 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -273, -273, -273, -273, -273, -273, 208, -273, -273, -273, - -64, -273, -273, -202, 71, -58, -273, -273, -218, -273, - -273, -272, -273, -273, -273, -273, -273, -273, -273, -273, - 50, 76, -273, -273, -273, 19, -54, -23, -1, -273, - -273, -273, -44, 39, -273, 224, -273, -11, 94, -273, - -273, -7, -38, -273, -273, -73, -2, -273, -28, -231, - -46, -273, -25, -57, 85 + -275, -275, -275, -275, -275, -275, 252, -275, -275, -275, + -275, -33, -275, -80, -275, -213, 100, -144, -275, -275, + -231, -275, -275, -274, -275, -275, -275, -275, -275, -275, + -275, -275, 7, 62, -275, -275, -275, 54, -275, -43, + 1, -275, -23, -1, -275, -275, -275, -13, 17, -275, + 263, -275, 8, 127, -275, -275, 21, -36, -275, -275, + -78, -2, -275, -27, -230, -65, -275, -15, -38, -94 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 28, 140, 143, 29, 77, 53, 54, 30, - 31, 83, 32, 146, 78, 205, 206, 222, 207, 237, - 248, 255, 296, 305, 317, 208, 258, 276, 286, 209, - 144, 145, 125, 175, 176, 232, 116, 117, 210, 115, - 94, 95, 35, 36, 37, 38, 39, 40, 55, 264, - 265, 266, 45, 46, 47, 41, 42, 131, 211, 212, - 137, 239, 213, 319, 136 + -1, 1, 28, 145, 148, 29, 77, 53, 54, 30, + 182, 31, 83, 118, 32, 151, 78, 211, 212, 232, + 213, 247, 258, 265, 310, 319, 332, 214, 268, 290, + 300, 215, 149, 150, 130, 228, 229, 242, 269, 70, + 119, 120, 121, 216, 115, 94, 95, 35, 36, 37, + 38, 39, 40, 55, 278, 279, 280, 45, 46, 47, + 41, 42, 136, 217, 218, 142, 249, 219, 334, 141 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -838,306 +865,325 @@ static const yytype_int16 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { - 34, 80, 80, 70, 81, 126, 127, 260, 121, 238, - 254, 56, 57, 58, 150, 5, 74, 132, 120, 63, - 63, 119, 63, 68, 135, 71, -103, 272, 310, 278, - 223, 19, 19, 63, 100, 101, 102, 321, 132, 103, - 43, 138, 118, 118, 173, 302, 139, 174, 141, 44, - 74, 33, 75, 142, 76, 76, 132, 44, 118, 118, - 62, 64, 59, 65, 60, 128, 218, -103, 303, 304, - 171, 133, 44, 75, 97, 320, 185, 25, 187, 79, - 178, 179, 254, 44, -103, 149, 84, 151, 152, 153, - -103, 254, 133, 224, 155, 19, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 172, 220, - 133, -93, 122, 244, 170, 81, 245, -89, 81, 4, - 133, 123, 63, 134, 330, 124, -12, 333, -15, 217, - 4, 180, 85, -94, 19, 184, 5, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, -12, - 85, -15, 103, 215, 56, 86, 148, 147, 112, 113, - 48, 49, 156, 177, 72, 169, 73, 154, 134, 252, - -104, 221, 81, 81, 129, 130, 81, 182, 81, 92, - 93, 87, 81, 259, 85, 225, 226, 240, 228, 86, - 79, 76, 249, 79, 268, 271, 275, 92, 93, 283, - 262, 233, 50, 51, 269, 270, 282, 81, 318, 181, - 267, 186, 295, 242, 188, 87, 88, -104, -104, 287, - 246, 233, 81, 289, 250, 251, 52, 267, 285, 204, - 273, 92, 93, 323, 274, 324, 118, 291, 82, 316, - 308, 247, 294, 311, 297, 110, 111, 79, 79, 67, - 216, 79, 288, 79, 312, 313, 71, 79, 279, 293, - 325, 219, 0, 0, 322, 0, 0, 299, 229, 230, - 332, 227, 231, 334, 234, 327, 112, 113, 236, 0, - 235, 290, 79, 292, 63, 114, 0, 0, 0, 241, - 0, 0, 63, 243, 0, 85, 0, 79, 0, 20, - 86, 0, 0, 256, 85, 314, 315, 0, 23, 86, - 98, 99, 100, 101, 102, 261, 0, 103, 263, 0, - 0, 0, 0, 0, 0, 0, 87, 88, 89, 0, - 0, 0, 0, 97, 0, 87, 88, 89, 277, 90, - 0, 0, 92, 93, 0, 280, 281, 0, 90, 284, - 0, 92, 93, 0, 104, 105, 106, 107, 108, 0, - 76, 109, 0, 134, 0, 0, 0, 298, 0, 300, - 0, 301, 306, 307, 0, 309, 2, 3, 0, 4, - 5, 0, 0, 6, 7, 0, 0, 0, 0, 0, - 0, 0, 0, 8, 9, 326, 0, 0, 328, 0, - 0, 329, 0, 331, 0, 0, 0, 0, 0, 0, - 0, 10, 11, 12, 13, 0, 0, 0, 0, 14, - 15, 16, 17, 18, 0, 0, 0, 19, 20, 0, - 0, 0, 0, 0, 21, 22, 0, 23, 0, 24, - 0, 0, 25, 26, 0, 27, 0, 0, -18, 189, - -18, 4, 5, 0, 0, 6, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 190, 0, 191, - 192, 193, -72, -72, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 0, 0, 0, 13, 203, 0, 0, - 0, 14, 15, 16, 17, 0, 0, 0, 0, -72, - 20, 0, 0, 0, 0, 0, 21, 22, 0, 23, - 0, 24, 0, 0, 25, 26, 0, 61, 0, 0, - 75, -72, 76, 189, 0, 4, 5, 0, 0, 6, - 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 190, 0, 191, 192, 193, -71, -71, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 0, 0, 0, - 13, 203, 0, 0, 0, 14, 15, 16, 17, 0, - 0, 0, 0, -71, 20, 0, 0, 0, 0, 0, - 21, 22, 0, 23, 0, 24, 0, 0, 25, 26, - 0, 61, 0, 0, 75, -71, 76, 189, 0, 4, + 34, 123, 80, 80, 248, 140, 154, 264, 33, 156, + 126, 56, 57, 58, 81, 137, 137, 191, 271, 63, + 63, 193, 63, 68, 143, 71, 180, 125, 292, 144, + 4, 175, 85, 63, 19, 74, 79, 86, 62, 64, + 324, 65, 122, 124, 226, 233, 146, 227, 5, 336, + 274, 147, 97, 275, 178, 75, 43, 76, 122, 122, + 131, 132, 44, 87, 88, 133, 184, 185, -12, 74, + 138, 138, -15, 59, 179, 75, 72, 254, 73, 92, + 93, 44, 44, 264, 139, 155, 181, 157, 158, 159, + 335, -12, 264, 262, 161, -15, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 60, 234, + 230, 25, -96, 316, 177, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 63, 345, 138, + 81, 348, 138, 81, 85, 255, 186, 317, 318, 86, + 190, 84, -114, 152, 19, -97, 183, 301, 112, 113, + 128, 303, 79, 160, 286, 79, 223, 225, 85, 221, + 56, 134, 135, 253, 19, 87, 127, 76, 322, 4, + 137, 325, 129, 103, 48, 49, 5, 19, 122, 122, + -106, 92, 93, 153, 44, 162, -92, 176, 81, 81, + 117, 276, 81, 188, 81, 283, 284, 139, 81, 347, + 187, 231, 349, 250, 270, 92, 93, 243, 297, -115, + 79, 79, 235, 236, 79, 238, 79, 50, 51, 252, + 79, -106, 281, 299, 288, 138, 76, 81, 259, 282, + 256, 243, 305, 285, 260, 261, 289, 331, -106, 311, + 309, 52, 81, 281, -106, 192, 124, 296, 194, 79, + 287, 98, 99, 100, 101, 102, -115, -115, 103, 337, + 333, 110, 111, 237, 79, 210, 71, 302, 326, 327, + 117, 342, 245, 104, 105, 106, 107, 108, 338, 339, + 109, 251, 82, 307, 330, 85, 257, 308, 67, 222, + 86, 313, 112, 113, 340, 304, 0, 306, 63, 0, + 293, 114, 0, 239, 240, 0, 63, 241, 0, 244, + 0, 272, 0, 246, 20, 273, 87, 88, 89, 0, + 328, 329, 0, 23, 0, 97, 100, 101, 102, 90, + 0, 103, 92, 93, 0, 0, 0, 0, 291, 0, + 0, 0, 266, 0, 0, 294, 295, 0, 0, 298, + 76, 0, 0, 0, 0, 0, 0, 277, 0, 85, + 0, 0, 0, 0, 86, 0, 0, 312, 0, 314, + 0, 315, 320, 321, 0, 323, 2, 3, 0, 4, 5, 0, 0, 6, 7, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 190, 0, 191, 192, 193, - 0, 0, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 0, 0, 0, 13, 203, 0, 0, 0, 14, - 15, 16, 17, 69, 0, 4, 5, 0, 20, 6, - 7, 0, -102, 0, 21, 22, 0, 23, 0, 24, - 0, 0, 25, 26, 0, 61, 0, 0, 75, 204, - 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, - 0, 0, 0, -102, 20, 0, 0, 0, 0, 0, - 21, 22, 0, 23, 0, 24, 0, 0, 25, 257, - -102, 61, 0, 4, 5, 0, -102, 6, 7, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, - 0, 191, 192, 193, 0, 0, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 0, 4, 5, 13, 203, - 6, 7, 0, 14, 15, 16, 17, 0, 0, 0, - 0, 0, 20, 0, 0, 0, 0, 85, 21, 22, - 0, 23, 86, 24, 0, 0, 25, 26, 0, 61, - 0, 13, 75, 0, 76, 0, 14, 15, 16, 17, - 69, 0, 4, 5, 0, 20, 6, 7, 87, 88, + 87, 88, 89, 0, 8, 9, 341, 0, 0, 343, + 0, 0, 344, 90, 346, 0, 92, 93, 0, 0, + 0, 0, 10, 11, 12, 13, 0, 0, 139, 0, + 14, 15, 16, 17, 18, 0, 0, 0, 19, 20, + 0, 0, 0, 0, 0, 21, 22, 0, 23, 0, + 24, 0, 0, 25, 26, 0, 27, 0, 0, -18, + 195, -18, 4, 5, 0, 0, 6, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, + 0, 197, 198, 199, -74, -74, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 0, 0, 0, 13, 209, + 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, + 0, -74, 20, 0, 0, 0, 0, 0, 21, 22, + 0, 23, 0, 24, 0, 0, 25, 26, 0, 61, + 0, 0, 75, -74, 76, 195, 0, 4, 5, 0, + 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 196, 0, 197, 198, 199, -73, + -73, 200, 201, 202, 203, 204, 205, 206, 207, 208, + 0, 0, 0, 13, 209, 0, 0, 0, 14, 15, + 16, 17, 0, 0, 0, 0, -73, 20, 0, 0, + 0, 0, 0, 21, 22, 0, 23, 0, 24, 0, + 0, 25, 26, 0, 61, 0, 0, 75, -73, 76, + 195, 0, 4, 5, 0, 0, 6, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, + 0, 197, 198, 199, 0, 0, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 0, 0, 0, 13, 209, + 0, 0, 0, 14, 15, 16, 17, 69, 0, 4, + 5, 0, 20, 6, 7, 0, 0, -105, 21, 22, + 0, 23, 0, 24, 0, 0, 25, 26, 0, 61, + 0, 0, 75, 210, 76, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 14, 15, 16, 17, 0, 0, 0, 0, -105, 20, + 0, 0, 0, 0, 0, 21, 22, 0, 23, 0, + 24, 0, 0, 25, 267, -105, 61, 0, 4, 5, + 0, -105, 6, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 196, 0, 197, 198, 199, + 0, 0, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 0, 0, 0, 13, 209, 0, 0, 0, 14, + 15, 16, 17, 0, 0, 4, 5, 0, 20, 6, + 7, 0, 0, 0, 21, 22, 0, 23, 0, 24, + 0, 0, 25, 26, 0, 61, 0, 0, 75, 0, + 76, 0, 0, 0, 0, 0, 116, 0, 4, 5, + 0, 13, 6, 7, 117, 0, 14, 15, 16, 17, + 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, + 0, 21, 22, 0, 23, 0, 24, 0, 0, 25, + 26, 0, 61, 0, 13, 0, 0, 76, 0, 14, + 15, 16, 17, 224, 0, 4, 5, 0, 20, 6, + 7, 117, 0, 0, 21, 22, 0, 23, 0, 24, + 0, 0, 25, 26, -113, 61, 0, 0, 0, 0, + 69, 0, 4, 5, 0, 0, 6, 7, 0, 0, + 0, 13, 0, 0, 0, 0, 14, 15, 16, 17, + 0, 0, 0, 0, 85, 20, 0, 0, 0, 86, + 0, 21, 22, 0, 23, 0, 24, 0, 13, 25, + 26, 0, 61, 14, 15, 16, 17, 189, 0, 4, + 5, 0, 20, 6, 7, 87, 88, 89, 21, 22, + 0, 23, 0, 24, 0, 0, 25, 26, 90, 61, + 91, 92, 93, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 263, 0, 13, 6, 7, 0, 0, + 14, 15, 16, 17, 0, 0, 0, 0, 0, 20, + 0, 0, 198, 0, 0, 21, 22, 0, 23, 0, + 24, 205, 206, 25, 26, 0, 61, 0, 13, 0, + 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, + 4, 5, 20, 0, 6, 7, 0, 0, 21, 22, + 0, 23, 0, 24, 0, 0, 25, 26, 0, 61, + 198, 0, 0, 0, 0, 0, 0, 0, 0, 205, + 206, 0, 0, 0, 0, 0, 13, 0, 0, 0, + 0, 14, 15, 16, 17, 0, 0, 0, 0, 0, + 20, 0, 0, 0, 0, 0, 21, 22, 85, 23, + 0, 24, 0, 86, 25, 26, 0, 61, 4, 5, + 0, 0, 6, 7, 0, 0, 0, 96, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, + 88, 89, 0, 0, 0, 4, 5, 0, 0, 6, + 7, 117, 90, 220, 13, 92, 93, 0, 0, 14, + 15, 16, 17, 0, 0, 0, 0, 85, 20, 0, + 0, 0, 86, 0, 21, 22, 0, 23, 0, 24, + 0, 13, 25, 26, 0, 61, 14, 15, 16, 17, + 0, 0, 4, 5, 0, 20, 6, 7, 87, 88, 89, 21, 22, 0, 23, 0, 24, 0, 0, 25, - 26, 90, 61, 91, 92, 93, 0, 76, 0, 0, - 0, 0, 69, 0, 4, 5, 0, 13, 6, 7, - 0, 0, 14, 15, 16, 17, 0, 0, 0, 0, - 0, 20, 0, 0, 0, 0, 0, 21, 22, 0, - 23, 0, 24, 0, 0, 25, 26, -102, 61, 13, - 0, 0, 0, 0, 14, 15, 16, 17, 183, 0, - 4, 5, 0, 20, 6, 7, 0, 0, 0, 21, - 22, 0, 23, 0, 24, 0, 0, 25, 26, 0, - 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4, 253, 13, 0, 6, 7, 0, + 26, 90, 61, 0, 92, 93, 0, 0, 0, 4, + 5, 0, 0, 6, 7, 0, 0, 0, 13, 0, + 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, + 0, 0, 20, 0, 0, 0, 0, 0, 21, 22, + 0, 23, 0, 24, 0, 0, 25, 26, 0, 61, 14, 15, 16, 17, 0, 0, 0, 0, 0, 20, - 0, 0, 192, 0, 0, 21, 22, 0, 23, 0, - 24, 199, 200, 25, 26, 0, 61, 0, 13, 0, - 0, 0, 0, 14, 15, 16, 17, 0, 0, 4, - 5, 0, 20, 6, 7, 0, 0, 0, 21, 22, - 0, 23, 0, 24, 0, 0, 25, 26, 192, 61, - 0, 0, 0, 0, 0, 0, 0, 199, 200, 0, - 0, 0, 0, 0, 13, 0, 0, 0, 0, 14, - 15, 16, 17, 0, 0, 4, 5, 0, 20, 6, - 7, 0, 0, 96, 21, 22, 0, 23, 0, 24, - 0, 0, 25, 26, 0, 61, 0, 0, 0, 0, - 0, 0, 4, 5, 0, 0, 6, 7, 0, 0, - 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, - 0, 0, 0, 85, 20, 0, 0, 0, 86, 0, - 21, 22, 0, 23, 0, 24, 0, 13, 25, 26, - 0, 61, 14, 15, 16, 17, 0, 0, 4, 5, - 0, 20, 6, 7, 87, 88, 89, 21, 22, 0, - 23, 0, 24, 0, 0, 25, 26, 90, 61, 0, - 92, 93, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 85, 14, 15, - 16, 17, 86, 0, 0, 0, 0, 20, 0, 0, - 0, 0, 0, 21, 22, 0, 23, 0, 24, 0, - 0, 25, 66, 0, 61, 0, 0, 0, 87, 88, - 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 90, 214, 0, 92, 93 + 0, 0, 0, 0, 0, 21, 22, 0, 23, 0, + 24, 0, 0, 25, 66, 0, 61 }; static const yytype_int16 yycheck[] = { - 1, 29, 30, 26, 29, 59, 60, 238, 46, 211, - 228, 13, 14, 15, 87, 4, 27, 1, 16, 21, - 22, 44, 24, 25, 70, 26, 10, 40, 300, 16, - 4, 51, 51, 35, 60, 61, 62, 309, 1, 65, - 67, 1, 43, 44, 1, 1, 6, 4, 1, 70, - 61, 1, 72, 6, 74, 74, 1, 70, 59, 60, - 21, 22, 67, 24, 67, 66, 1, 51, 24, 25, - 116, 55, 70, 72, 35, 306, 1, 66, 1, 29, - 126, 127, 300, 70, 68, 86, 51, 88, 89, 90, - 74, 309, 55, 67, 95, 51, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 71, 182, - 55, 68, 49, 1, 115, 140, 4, 73, 143, 3, - 55, 67, 124, 68, 326, 56, 51, 329, 51, 175, - 3, 132, 9, 68, 51, 136, 4, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 74, - 9, 74, 65, 154, 156, 14, 5, 81, 43, 44, - 3, 4, 38, 124, 48, 13, 50, 91, 68, 227, - 9, 67, 197, 198, 43, 44, 201, 40, 203, 56, - 57, 40, 207, 237, 9, 67, 67, 212, 67, 14, - 140, 74, 4, 143, 68, 26, 10, 56, 57, 272, - 246, 202, 45, 46, 250, 251, 67, 232, 54, 133, - 248, 140, 20, 214, 143, 40, 41, 56, 57, 277, - 221, 222, 247, 281, 225, 226, 69, 265, 274, 73, - 255, 56, 57, 7, 257, 7, 237, 283, 30, 303, - 298, 222, 286, 301, 290, 12, 13, 197, 198, 25, - 156, 201, 280, 203, 7, 8, 257, 207, 265, 284, - 317, 176, -1, -1, 310, -1, -1, 292, 197, 198, - 328, 195, 201, 331, 203, 321, 43, 44, 207, -1, - 204, 282, 232, 284, 286, 52, -1, -1, -1, 213, - -1, -1, 294, 217, -1, 9, -1, 247, -1, 52, - 14, -1, -1, 232, 9, 58, 59, -1, 61, 14, - 58, 59, 60, 61, 62, 239, -1, 65, 247, -1, - -1, -1, -1, -1, -1, -1, 40, 41, 42, -1, - -1, -1, -1, 294, -1, 40, 41, 42, 262, 53, - -1, -1, 56, 57, -1, 269, 270, -1, 53, 273, - -1, 56, 57, -1, 58, 59, 60, 61, 62, -1, - 74, 65, -1, 68, -1, -1, -1, 291, -1, 293, - -1, 295, 296, 297, -1, 299, 0, 1, -1, 3, + 1, 44, 29, 30, 217, 70, 86, 238, 1, 87, + 46, 13, 14, 15, 29, 1, 1, 1, 248, 21, + 22, 1, 24, 25, 1, 26, 120, 17, 17, 6, + 3, 111, 10, 35, 52, 27, 29, 15, 21, 22, + 314, 24, 43, 44, 1, 4, 1, 4, 4, 323, + 1, 6, 35, 4, 119, 73, 68, 75, 59, 60, + 59, 60, 71, 41, 42, 66, 131, 132, 52, 61, + 56, 56, 52, 68, 1, 73, 49, 1, 51, 57, + 58, 71, 71, 314, 69, 86, 72, 88, 89, 90, + 320, 75, 323, 237, 95, 75, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 68, 68, + 188, 67, 69, 1, 115, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 129, 341, 56, + 145, 344, 56, 148, 10, 229, 137, 25, 26, 15, + 141, 52, 69, 81, 52, 69, 129, 291, 44, 45, + 68, 295, 145, 91, 41, 148, 179, 180, 10, 160, + 162, 44, 45, 228, 52, 41, 50, 75, 312, 3, + 1, 315, 57, 66, 3, 4, 4, 52, 179, 180, + 11, 57, 58, 5, 71, 39, 74, 14, 203, 204, + 9, 256, 207, 41, 209, 260, 261, 69, 213, 343, + 138, 68, 346, 218, 247, 57, 58, 208, 286, 10, + 203, 204, 68, 68, 207, 68, 209, 46, 47, 220, + 213, 52, 258, 288, 267, 56, 75, 242, 4, 69, + 231, 232, 297, 27, 235, 236, 11, 317, 69, 304, + 21, 70, 257, 279, 75, 145, 247, 68, 148, 242, + 265, 59, 60, 61, 62, 63, 57, 58, 66, 324, + 55, 13, 14, 201, 257, 74, 267, 294, 7, 8, + 9, 336, 210, 59, 60, 61, 62, 63, 7, 7, + 66, 219, 30, 298, 317, 10, 232, 300, 25, 162, + 15, 306, 44, 45, 332, 296, -1, 298, 300, -1, + 279, 53, -1, 203, 204, -1, 308, 207, -1, 209, + -1, 249, -1, 213, 53, 253, 41, 42, 43, -1, + 59, 60, -1, 62, -1, 308, 61, 62, 63, 54, + -1, 66, 57, 58, -1, -1, -1, -1, 276, -1, + -1, -1, 242, -1, -1, 283, 284, -1, -1, 287, + 75, -1, -1, -1, -1, -1, -1, 257, -1, 10, + -1, -1, -1, -1, 15, -1, -1, 305, -1, 307, + -1, 309, 310, 311, -1, 313, 0, 1, -1, 3, 4, -1, -1, 7, 8, -1, -1, -1, -1, -1, - -1, -1, -1, 17, 18, 319, -1, -1, 322, -1, - -1, 325, -1, 327, -1, -1, -1, -1, -1, -1, - -1, 35, 36, 37, 38, -1, -1, -1, -1, 43, - 44, 45, 46, 47, -1, -1, -1, 51, 52, -1, - -1, -1, -1, -1, 58, 59, -1, 61, -1, 63, - -1, -1, 66, 67, -1, 69, -1, -1, 72, 1, - 74, 3, 4, -1, -1, 7, 8, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 19, -1, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, -1, -1, -1, 38, 39, -1, -1, - -1, 43, 44, 45, 46, -1, -1, -1, -1, 51, - 52, -1, -1, -1, -1, -1, 58, 59, -1, 61, - -1, 63, -1, -1, 66, 67, -1, 69, -1, -1, - 72, 73, 74, 1, -1, 3, 4, -1, -1, 7, - 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 19, -1, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, -1, -1, -1, - 38, 39, -1, -1, -1, 43, 44, 45, 46, -1, - -1, -1, -1, 51, 52, -1, -1, -1, -1, -1, - 58, 59, -1, 61, -1, 63, -1, -1, 66, 67, - -1, 69, -1, -1, 72, 73, 74, 1, -1, 3, - 4, -1, -1, 7, 8, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 19, -1, 21, 22, 23, - -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, - 34, -1, -1, -1, 38, 39, -1, -1, -1, 43, - 44, 45, 46, 1, -1, 3, 4, -1, 52, 7, - 8, -1, 10, -1, 58, 59, -1, 61, -1, 63, - -1, -1, 66, 67, -1, 69, -1, -1, 72, 73, - 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 38, -1, -1, -1, -1, 43, 44, 45, 46, -1, - -1, -1, -1, 51, 52, -1, -1, -1, -1, -1, - 58, 59, -1, 61, -1, 63, -1, -1, 66, 67, - 68, 69, -1, 3, 4, -1, 74, 7, 8, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, - -1, 21, 22, 23, -1, -1, 26, 27, 28, 29, - 30, 31, 32, 33, 34, -1, 3, 4, 38, 39, - 7, 8, -1, 43, 44, 45, 46, -1, -1, -1, - -1, -1, 52, -1, -1, -1, -1, 9, 58, 59, - -1, 61, 14, 63, -1, -1, 66, 67, -1, 69, - -1, 38, 72, -1, 74, -1, 43, 44, 45, 46, - 1, -1, 3, 4, -1, 52, 7, 8, 40, 41, - 42, 58, 59, -1, 61, -1, 63, -1, -1, 66, - 67, 53, 69, 55, 56, 57, -1, 74, -1, -1, - -1, -1, 1, -1, 3, 4, -1, 38, 7, 8, - -1, -1, 43, 44, 45, 46, -1, -1, -1, -1, - -1, 52, -1, -1, -1, -1, -1, 58, 59, -1, - 61, -1, 63, -1, -1, 66, 67, 68, 69, 38, - -1, -1, -1, -1, 43, 44, 45, 46, 1, -1, - 3, 4, -1, 52, 7, 8, -1, -1, -1, 58, - 59, -1, 61, -1, 63, -1, -1, 66, 67, -1, - 69, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 3, 4, 38, -1, 7, 8, -1, - 43, 44, 45, 46, -1, -1, -1, -1, -1, 52, - -1, -1, 22, -1, -1, 58, 59, -1, 61, -1, - 63, 31, 32, 66, 67, -1, 69, -1, 38, -1, - -1, -1, -1, 43, 44, 45, 46, -1, -1, 3, - 4, -1, 52, 7, 8, -1, -1, -1, 58, 59, - -1, 61, -1, 63, -1, -1, 66, 67, 22, 69, - -1, -1, -1, -1, -1, -1, -1, 31, 32, -1, - -1, -1, -1, -1, 38, -1, -1, -1, -1, 43, - 44, 45, 46, -1, -1, 3, 4, -1, 52, 7, - 8, -1, -1, 11, 58, 59, -1, 61, -1, 63, - -1, -1, 66, 67, -1, 69, -1, -1, -1, -1, - -1, -1, 3, 4, -1, -1, 7, 8, -1, -1, - 38, -1, -1, -1, -1, 43, 44, 45, 46, -1, - -1, -1, -1, 9, 52, -1, -1, -1, 14, -1, - 58, 59, -1, 61, -1, 63, -1, 38, 66, 67, - -1, 69, 43, 44, 45, 46, -1, -1, 3, 4, - -1, 52, 7, 8, 40, 41, 42, 58, 59, -1, - 61, -1, 63, -1, -1, 66, 67, 53, 69, -1, - 56, 57, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 9, 43, 44, - 45, 46, 14, -1, -1, -1, -1, 52, -1, -1, - -1, -1, -1, 58, 59, -1, 61, -1, 63, -1, - -1, 66, 67, -1, 69, -1, -1, -1, 40, 41, - 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 53, 54, -1, 56, 57 + 41, 42, 43, -1, 18, 19, 334, -1, -1, 337, + -1, -1, 340, 54, 342, -1, 57, 58, -1, -1, + -1, -1, 36, 37, 38, 39, -1, -1, 69, -1, + 44, 45, 46, 47, 48, -1, -1, -1, 52, 53, + -1, -1, -1, -1, -1, 59, 60, -1, 62, -1, + 64, -1, -1, 67, 68, -1, 70, -1, -1, 73, + 1, 75, 3, 4, -1, -1, 7, 8, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, + -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, -1, -1, -1, 39, 40, + -1, -1, -1, 44, 45, 46, 47, -1, -1, -1, + -1, 52, 53, -1, -1, -1, -1, -1, 59, 60, + -1, 62, -1, 64, -1, -1, 67, 68, -1, 70, + -1, -1, 73, 74, 75, 1, -1, 3, 4, -1, + -1, 7, 8, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 20, -1, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + -1, -1, -1, 39, 40, -1, -1, -1, 44, 45, + 46, 47, -1, -1, -1, -1, 52, 53, -1, -1, + -1, -1, -1, 59, 60, -1, 62, -1, 64, -1, + -1, 67, 68, -1, 70, -1, -1, 73, 74, 75, + 1, -1, 3, 4, -1, -1, 7, 8, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, + -1, 22, 23, 24, -1, -1, 27, 28, 29, 30, + 31, 32, 33, 34, 35, -1, -1, -1, 39, 40, + -1, -1, -1, 44, 45, 46, 47, 1, -1, 3, + 4, -1, 53, 7, 8, -1, -1, 11, 59, 60, + -1, 62, -1, 64, -1, -1, 67, 68, -1, 70, + -1, -1, 73, 74, 75, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, + 44, 45, 46, 47, -1, -1, -1, -1, 52, 53, + -1, -1, -1, -1, -1, 59, 60, -1, 62, -1, + 64, -1, -1, 67, 68, 69, 70, -1, 3, 4, + -1, 75, 7, 8, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 20, -1, 22, 23, 24, + -1, -1, 27, 28, 29, 30, 31, 32, 33, 34, + 35, -1, -1, -1, 39, 40, -1, -1, -1, 44, + 45, 46, 47, -1, -1, 3, 4, -1, 53, 7, + 8, -1, -1, -1, 59, 60, -1, 62, -1, 64, + -1, -1, 67, 68, -1, 70, -1, -1, 73, -1, + 75, -1, -1, -1, -1, -1, 1, -1, 3, 4, + -1, 39, 7, 8, 9, -1, 44, 45, 46, 47, + -1, -1, -1, -1, -1, 53, -1, -1, -1, -1, + -1, 59, 60, -1, 62, -1, 64, -1, -1, 67, + 68, -1, 70, -1, 39, -1, -1, 75, -1, 44, + 45, 46, 47, 1, -1, 3, 4, -1, 53, 7, + 8, 9, -1, -1, 59, 60, -1, 62, -1, 64, + -1, -1, 67, 68, 69, 70, -1, -1, -1, -1, + 1, -1, 3, 4, -1, -1, 7, 8, -1, -1, + -1, 39, -1, -1, -1, -1, 44, 45, 46, 47, + -1, -1, -1, -1, 10, 53, -1, -1, -1, 15, + -1, 59, 60, -1, 62, -1, 64, -1, 39, 67, + 68, -1, 70, 44, 45, 46, 47, 1, -1, 3, + 4, -1, 53, 7, 8, 41, 42, 43, 59, 60, + -1, 62, -1, 64, -1, -1, 67, 68, 54, 70, + 56, 57, 58, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 3, 4, -1, 39, 7, 8, -1, -1, + 44, 45, 46, 47, -1, -1, -1, -1, -1, 53, + -1, -1, 23, -1, -1, 59, 60, -1, 62, -1, + 64, 32, 33, 67, 68, -1, 70, -1, 39, -1, + -1, -1, -1, 44, 45, 46, 47, -1, -1, -1, + 3, 4, 53, -1, 7, 8, -1, -1, 59, 60, + -1, 62, -1, 64, -1, -1, 67, 68, -1, 70, + 23, -1, -1, -1, -1, -1, -1, -1, -1, 32, + 33, -1, -1, -1, -1, -1, 39, -1, -1, -1, + -1, 44, 45, 46, 47, -1, -1, -1, -1, -1, + 53, -1, -1, -1, -1, -1, 59, 60, 10, 62, + -1, 64, -1, 15, 67, 68, -1, 70, 3, 4, + -1, -1, 7, 8, -1, -1, -1, 12, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, + 42, 43, -1, -1, -1, 3, 4, -1, -1, 7, + 8, 9, 54, 55, 39, 57, 58, -1, -1, 44, + 45, 46, 47, -1, -1, -1, -1, 10, 53, -1, + -1, -1, 15, -1, 59, 60, -1, 62, -1, 64, + -1, 39, 67, 68, -1, 70, 44, 45, 46, 47, + -1, -1, 3, 4, -1, 53, 7, 8, 41, 42, + 43, 59, 60, -1, 62, -1, 64, -1, -1, 67, + 68, 54, 70, -1, 57, 58, -1, -1, -1, 3, + 4, -1, -1, 7, 8, -1, -1, -1, 39, -1, + -1, -1, -1, 44, 45, 46, 47, -1, -1, -1, + -1, -1, 53, -1, -1, -1, -1, -1, 59, 60, + -1, 62, -1, 64, -1, -1, 67, 68, -1, 70, + 44, 45, 46, 47, -1, -1, -1, -1, -1, 53, + -1, -1, -1, -1, -1, 59, 60, -1, 62, -1, + 64, -1, -1, 67, 68, -1, 70 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 76, 0, 1, 3, 4, 7, 8, 17, 18, - 35, 36, 37, 38, 43, 44, 45, 46, 47, 51, - 52, 58, 59, 61, 63, 66, 67, 69, 77, 80, - 84, 85, 87, 105, 113, 117, 118, 119, 120, 121, - 122, 130, 131, 67, 70, 127, 128, 129, 3, 4, - 45, 46, 69, 82, 83, 123, 131, 131, 131, 67, - 67, 69, 118, 131, 118, 118, 67, 120, 131, 1, - 112, 113, 48, 50, 122, 72, 74, 81, 89, 105, - 133, 137, 81, 86, 51, 9, 14, 40, 41, 42, - 53, 55, 56, 57, 115, 116, 11, 118, 58, 59, - 60, 61, 62, 65, 58, 59, 60, 61, 62, 65, - 12, 13, 43, 44, 52, 114, 111, 112, 113, 112, - 16, 127, 49, 67, 56, 107, 111, 111, 113, 43, - 44, 132, 1, 55, 68, 135, 139, 135, 1, 6, - 78, 1, 6, 79, 105, 106, 88, 106, 5, 113, - 130, 113, 113, 113, 106, 113, 38, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 13, - 113, 135, 71, 1, 4, 108, 109, 118, 135, 135, - 113, 106, 40, 1, 113, 1, 89, 1, 89, 1, - 19, 21, 22, 23, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 39, 73, 90, 91, 93, 100, 104, - 113, 133, 134, 137, 54, 113, 123, 135, 1, 139, - 130, 67, 92, 4, 67, 67, 67, 106, 67, 89, - 89, 89, 110, 113, 89, 106, 89, 94, 88, 136, - 137, 106, 113, 106, 1, 4, 113, 110, 95, 4, - 113, 113, 90, 4, 93, 96, 89, 67, 101, 111, - 134, 106, 135, 89, 124, 125, 126, 127, 68, 135, - 135, 26, 40, 137, 112, 10, 102, 106, 16, 126, - 106, 106, 67, 130, 106, 135, 103, 90, 133, 90, - 113, 135, 113, 137, 117, 20, 97, 135, 106, 137, - 106, 106, 1, 24, 25, 98, 106, 106, 90, 106, - 96, 90, 7, 8, 58, 59, 85, 99, 54, 138, - 134, 96, 135, 7, 7, 138, 106, 135, 106, 106, - 88, 106, 90, 88, 90 + 0, 77, 0, 1, 3, 4, 7, 8, 18, 19, + 36, 37, 38, 39, 44, 45, 46, 47, 48, 52, + 53, 59, 60, 62, 64, 67, 68, 70, 78, 81, + 85, 87, 90, 108, 119, 123, 124, 125, 126, 127, + 128, 136, 137, 68, 71, 133, 134, 135, 3, 4, + 46, 47, 70, 83, 84, 129, 137, 137, 137, 68, + 68, 70, 124, 137, 124, 124, 68, 126, 137, 1, + 115, 119, 49, 51, 128, 73, 75, 82, 92, 108, + 139, 143, 82, 88, 52, 10, 15, 41, 42, 43, + 54, 56, 57, 58, 121, 122, 12, 124, 59, 60, + 61, 62, 63, 66, 59, 60, 61, 62, 63, 66, + 13, 14, 44, 45, 53, 120, 1, 9, 89, 116, + 117, 118, 119, 115, 119, 17, 133, 50, 68, 57, + 110, 116, 116, 119, 44, 45, 138, 1, 56, 69, + 141, 145, 141, 1, 6, 79, 1, 6, 80, 108, + 109, 91, 109, 5, 89, 119, 136, 119, 119, 119, + 109, 119, 39, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 89, 14, 119, 141, 1, + 145, 72, 86, 124, 141, 141, 119, 109, 41, 1, + 119, 1, 92, 1, 92, 1, 20, 22, 23, 24, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 40, + 74, 93, 94, 96, 103, 107, 119, 139, 140, 143, + 55, 119, 129, 118, 1, 118, 1, 4, 111, 112, + 136, 68, 95, 4, 68, 68, 68, 109, 68, 92, + 92, 92, 113, 119, 92, 109, 92, 97, 91, 142, + 143, 109, 119, 141, 1, 145, 119, 113, 98, 4, + 119, 119, 93, 4, 96, 99, 92, 68, 104, 114, + 115, 140, 109, 109, 1, 4, 141, 92, 130, 131, + 132, 133, 69, 141, 141, 27, 41, 143, 115, 11, + 105, 109, 17, 132, 109, 109, 68, 136, 109, 141, + 106, 93, 139, 93, 119, 141, 119, 143, 123, 21, + 100, 141, 109, 143, 109, 109, 1, 25, 26, 101, + 109, 109, 93, 109, 99, 93, 7, 8, 59, 60, + 87, 89, 102, 55, 144, 140, 99, 141, 7, 7, + 144, 109, 141, 109, 109, 91, 109, 93, 91, 93 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 75, 76, 76, 76, 76, 76, 77, 77, 77, - 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, - 80, 80, 80, 80, 80, 81, 82, 82, 82, 82, - 83, 83, 84, 86, 85, 87, 87, 88, 88, 88, - 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, - 90, 90, 91, 91, 91, 91, 91, 92, 91, 91, - 94, 93, 95, 93, 93, 93, 96, 96, 97, 97, - 97, 98, 98, 99, 99, 99, 99, 99, 100, 100, - 101, 101, 102, 103, 102, 104, 104, 105, 105, 106, - 106, 107, 107, 108, 108, 109, 109, 109, 109, 109, - 110, 110, 111, 111, 112, 112, 112, 112, 112, 112, - 113, 113, 113, 113, 113, 113, 113, 113, 114, 114, - 114, 115, 115, 116, 116, 117, 117, 117, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 119, - 119, 119, 119, 119, 119, 119, 120, 120, 120, 120, - 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, - 121, 121, 122, 123, 123, 124, 124, 125, 125, 126, - 127, 128, 128, 129, 130, 130, 131, 131, 132, 132, - 132, 133, 134, 135, 136, 136, 137, 138, 139 + 0, 76, 77, 77, 77, 77, 77, 78, 78, 78, + 78, 78, 79, 79, 79, 80, 80, 80, 81, 81, + 81, 81, 81, 81, 81, 82, 83, 83, 83, 83, + 84, 84, 86, 85, 88, 87, 89, 90, 90, 91, + 91, 91, 92, 92, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 94, 94, 94, 94, 94, 95, + 94, 94, 97, 96, 98, 96, 96, 96, 99, 99, + 100, 100, 100, 101, 101, 102, 102, 102, 102, 102, + 102, 103, 103, 104, 104, 105, 106, 105, 107, 107, + 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, + 112, 112, 112, 113, 113, 114, 114, 115, 115, 115, + 115, 115, 115, 116, 116, 117, 117, 117, 117, 117, + 117, 118, 118, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 120, 120, 120, 121, 121, 122, 122, + 123, 123, 123, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, + 125, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 127, 127, 128, 129, 129, + 130, 130, 131, 131, 132, 133, 134, 134, 135, 136, + 136, 137, 137, 138, 138, 138, 139, 140, 141, 142, + 142, 143, 144, 145 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -1146,22 +1192,24 @@ static const yytype_uint8 yyr2[] = 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 4, 4, 1, 2, 1, 1, 2, 1, 0, 1, 4, 1, 1, 1, 1, 5, 1, 1, 1, 2, - 1, 1, 6, 0, 3, 1, 1, 0, 2, 2, - 1, 2, 2, 3, 1, 9, 6, 8, 8, 12, - 11, 1, 2, 2, 2, 2, 3, 0, 4, 2, - 0, 4, 0, 4, 4, 1, 0, 1, 0, 2, - 2, 5, 4, 1, 2, 2, 1, 1, 1, 1, - 1, 3, 0, 0, 3, 6, 9, 1, 2, 0, - 1, 0, 2, 0, 1, 1, 3, 1, 2, 3, - 0, 1, 0, 1, 1, 3, 1, 2, 3, 3, - 3, 3, 3, 3, 3, 3, 5, 1, 1, 1, - 2, 1, 1, 1, 1, 1, 1, 2, 1, 3, - 3, 3, 3, 3, 3, 3, 2, 2, 5, 4, - 3, 3, 3, 3, 3, 3, 1, 2, 3, 4, - 4, 1, 1, 1, 2, 2, 1, 1, 2, 2, - 1, 2, 4, 0, 1, 0, 2, 1, 2, 1, - 3, 1, 2, 2, 1, 2, 1, 3, 1, 1, - 0, 2, 2, 1, 0, 1, 1, 1, 2 + 1, 1, 0, 7, 0, 3, 1, 1, 1, 0, + 2, 2, 1, 2, 2, 3, 1, 9, 6, 8, + 8, 12, 11, 1, 2, 2, 2, 2, 3, 0, + 4, 2, 0, 4, 0, 4, 4, 1, 0, 1, + 0, 2, 2, 5, 4, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 3, 0, 0, 3, 6, 9, + 1, 2, 0, 1, 0, 2, 0, 1, 1, 3, + 1, 2, 3, 0, 1, 0, 1, 1, 3, 1, + 2, 3, 3, 0, 1, 1, 3, 1, 2, 3, + 3, 1, 1, 3, 3, 3, 3, 3, 3, 3, + 3, 5, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 2, 1, 3, 3, 3, 3, 3, 3, + 3, 2, 2, 5, 4, 3, 3, 3, 3, 3, + 3, 1, 2, 3, 4, 4, 1, 1, 1, 2, + 2, 1, 1, 2, 2, 1, 2, 4, 0, 1, + 0, 2, 1, 2, 1, 3, 1, 2, 2, 1, + 2, 1, 3, 1, 1, 0, 2, 2, 1, 0, + 1, 1, 1, 2 }; @@ -1838,24 +1886,24 @@ yyreduce: switch (yyn) { case 3: -#line 197 "awkgram.y" /* yacc.c:1646 */ +#line 216 "awkgram.y" /* yacc.c:1646 */ { rule = 0; yyerrok; } -#line 1847 "awkgram.c" /* yacc.c:1646 */ +#line 1895 "awkgram.c" /* yacc.c:1646 */ break; case 5: -#line 203 "awkgram.y" /* yacc.c:1646 */ +#line 222 "awkgram.y" /* yacc.c:1646 */ { next_sourcefile(); } -#line 1855 "awkgram.c" /* yacc.c:1646 */ +#line 1903 "awkgram.c" /* yacc.c:1646 */ break; case 6: -#line 207 "awkgram.y" /* yacc.c:1646 */ +#line 226 "awkgram.y" /* yacc.c:1646 */ { rule = 0; /* @@ -1864,19 +1912,20 @@ yyreduce: */ /* yyerrok; */ } -#line 1868 "awkgram.c" /* yacc.c:1646 */ +#line 1916 "awkgram.c" /* yacc.c:1646 */ break; case 7: -#line 219 "awkgram.y" /* yacc.c:1646 */ +#line 238 "awkgram.y" /* yacc.c:1646 */ { (void) append_rule((yyvsp[-1]), (yyvsp[0])); + first_rule = false; } -#line 1876 "awkgram.c" /* yacc.c:1646 */ +#line 1925 "awkgram.c" /* yacc.c:1646 */ break; case 8: -#line 223 "awkgram.y" /* yacc.c:1646 */ +#line 243 "awkgram.y" /* yacc.c:1646 */ { if (rule != Rule) { msg(_("%s blocks must have an action part"), ruletab[rule]); @@ -1887,41 +1936,42 @@ yyreduce: } else /* pattern rule with non-empty pattern */ (void) append_rule((yyvsp[-1]), NULL); } -#line 1891 "awkgram.c" /* yacc.c:1646 */ +#line 1940 "awkgram.c" /* yacc.c:1646 */ break; case 9: -#line 234 "awkgram.y" /* yacc.c:1646 */ +#line 254 "awkgram.y" /* yacc.c:1646 */ { in_function = NULL; (void) mk_function((yyvsp[-1]), (yyvsp[0])); + want_param_names = DONT_CHECK; yyerrok; } -#line 1901 "awkgram.c" /* yacc.c:1646 */ +#line 1951 "awkgram.c" /* yacc.c:1646 */ break; case 10: -#line 240 "awkgram.y" /* yacc.c:1646 */ +#line 261 "awkgram.y" /* yacc.c:1646 */ { want_source = false; at_seen = false; yyerrok; } -#line 1911 "awkgram.c" /* yacc.c:1646 */ +#line 1961 "awkgram.c" /* yacc.c:1646 */ break; case 11: -#line 246 "awkgram.y" /* yacc.c:1646 */ +#line 267 "awkgram.y" /* yacc.c:1646 */ { want_source = false; at_seen = false; yyerrok; } -#line 1921 "awkgram.c" /* yacc.c:1646 */ +#line 1971 "awkgram.c" /* yacc.c:1646 */ break; case 12: -#line 255 "awkgram.y" /* yacc.c:1646 */ +#line 276 "awkgram.y" /* yacc.c:1646 */ { if (include_source((yyvsp[0])) < 0) YYABORT; @@ -1929,23 +1979,23 @@ yyreduce: bcfree((yyvsp[0])); (yyval) = NULL; } -#line 1933 "awkgram.c" /* yacc.c:1646 */ +#line 1983 "awkgram.c" /* yacc.c:1646 */ break; case 13: -#line 263 "awkgram.y" /* yacc.c:1646 */ +#line 284 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 1939 "awkgram.c" /* yacc.c:1646 */ +#line 1989 "awkgram.c" /* yacc.c:1646 */ break; case 14: -#line 265 "awkgram.y" /* yacc.c:1646 */ +#line 286 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 1945 "awkgram.c" /* yacc.c:1646 */ +#line 1995 "awkgram.c" /* yacc.c:1646 */ break; case 15: -#line 270 "awkgram.y" /* yacc.c:1646 */ +#line 291 "awkgram.y" /* yacc.c:1646 */ { if (load_library((yyvsp[0])) < 0) YYABORT; @@ -1953,35 +2003,49 @@ yyreduce: bcfree((yyvsp[0])); (yyval) = NULL; } -#line 1957 "awkgram.c" /* yacc.c:1646 */ +#line 2007 "awkgram.c" /* yacc.c:1646 */ break; case 16: -#line 278 "awkgram.y" /* yacc.c:1646 */ +#line 299 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 1963 "awkgram.c" /* yacc.c:1646 */ +#line 2013 "awkgram.c" /* yacc.c:1646 */ break; case 17: -#line 280 "awkgram.y" /* yacc.c:1646 */ +#line 301 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 1969 "awkgram.c" /* yacc.c:1646 */ +#line 2019 "awkgram.c" /* yacc.c:1646 */ break; case 18: -#line 285 "awkgram.y" /* yacc.c:1646 */ - { (yyval) = NULL; rule = Rule; } -#line 1975 "awkgram.c" /* yacc.c:1646 */ +#line 306 "awkgram.y" /* yacc.c:1646 */ + { + rule = Rule; + if (comment != NULL) { + (yyval) = list_create(comment); + comment = NULL; + } else + (yyval) = NULL; + } +#line 2032 "awkgram.c" /* yacc.c:1646 */ break; case 19: -#line 287 "awkgram.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[0]); rule = Rule; } -#line 1981 "awkgram.c" /* yacc.c:1646 */ +#line 315 "awkgram.y" /* yacc.c:1646 */ + { + rule = Rule; + if (comment != NULL) { + (yyval) = list_prepend((yyvsp[0]), comment); + comment = NULL; + } else + (yyval) = (yyvsp[0]); + } +#line 2045 "awkgram.c" /* yacc.c:1646 */ break; case 20: -#line 289 "awkgram.y" /* yacc.c:1646 */ +#line 325 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *tp; @@ -2004,127 +2068,176 @@ yyreduce: ((yyvsp[-3])->nexti + 1)->condpair_left = (yyvsp[-3])->lasti; ((yyvsp[-3])->nexti + 1)->condpair_right = (yyvsp[0])->lasti; } - (yyval) = list_append(list_merge((yyvsp[-3]), (yyvsp[0])), tp); + if (comment != NULL) { + (yyval) = list_append(list_merge(list_prepend((yyvsp[-3]), comment), (yyvsp[0])), tp); + comment = NULL; + } else + (yyval) = list_append(list_merge((yyvsp[-3]), (yyvsp[0])), tp); rule = Rule; } -#line 2011 "awkgram.c" /* yacc.c:1646 */ +#line 2079 "awkgram.c" /* yacc.c:1646 */ break; case 21: -#line 315 "awkgram.y" /* yacc.c:1646 */ +#line 355 "awkgram.y" /* yacc.c:1646 */ { static int begin_seen = 0; + + func_first = false; if (do_lint_old && ++begin_seen == 2) warning_ln((yyvsp[0])->source_line, _("old awk does not support multiple `BEGIN' or `END' rules")); (yyvsp[0])->in_rule = rule = BEGIN; (yyvsp[0])->source_file = source; + check_comment(); (yyval) = (yyvsp[0]); } -#line 2026 "awkgram.c" /* yacc.c:1646 */ +#line 2097 "awkgram.c" /* yacc.c:1646 */ break; case 22: -#line 326 "awkgram.y" /* yacc.c:1646 */ +#line 369 "awkgram.y" /* yacc.c:1646 */ { static int end_seen = 0; + + func_first = false; if (do_lint_old && ++end_seen == 2) warning_ln((yyvsp[0])->source_line, _("old awk does not support multiple `BEGIN' or `END' rules")); (yyvsp[0])->in_rule = rule = END; (yyvsp[0])->source_file = source; + check_comment(); (yyval) = (yyvsp[0]); } -#line 2041 "awkgram.c" /* yacc.c:1646 */ +#line 2115 "awkgram.c" /* yacc.c:1646 */ break; case 23: -#line 337 "awkgram.y" /* yacc.c:1646 */ +#line 383 "awkgram.y" /* yacc.c:1646 */ { + func_first = false; (yyvsp[0])->in_rule = rule = BEGINFILE; (yyvsp[0])->source_file = source; + check_comment(); (yyval) = (yyvsp[0]); } -#line 2051 "awkgram.c" /* yacc.c:1646 */ +#line 2127 "awkgram.c" /* yacc.c:1646 */ break; case 24: -#line 343 "awkgram.y" /* yacc.c:1646 */ +#line 391 "awkgram.y" /* yacc.c:1646 */ { + func_first = false; (yyvsp[0])->in_rule = rule = ENDFILE; (yyvsp[0])->source_file = source; + check_comment(); (yyval) = (yyvsp[0]); } -#line 2061 "awkgram.c" /* yacc.c:1646 */ +#line 2139 "awkgram.c" /* yacc.c:1646 */ break; case 25: -#line 352 "awkgram.y" /* yacc.c:1646 */ +#line 402 "awkgram.y" /* yacc.c:1646 */ { + INSTRUCTION *ip; if ((yyvsp[-3]) == NULL) - (yyval) = list_create(instruction(Op_no_op)); + ip = list_create(instruction(Op_no_op)); else - (yyval) = (yyvsp[-3]); + ip = (yyvsp[-3]); + (yyval) = ip; } -#line 2072 "awkgram.c" /* yacc.c:1646 */ +#line 2152 "awkgram.c" /* yacc.c:1646 */ break; case 26: -#line 362 "awkgram.y" /* yacc.c:1646 */ +#line 414 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2078 "awkgram.c" /* yacc.c:1646 */ +#line 2158 "awkgram.c" /* yacc.c:1646 */ break; case 27: -#line 364 "awkgram.y" /* yacc.c:1646 */ +#line 416 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2084 "awkgram.c" /* yacc.c:1646 */ +#line 2164 "awkgram.c" /* yacc.c:1646 */ break; case 28: -#line 366 "awkgram.y" /* yacc.c:1646 */ +#line 418 "awkgram.y" /* yacc.c:1646 */ { yyerror(_("`%s' is a built-in function, it cannot be redefined"), tokstart); YYABORT; } -#line 2094 "awkgram.c" /* yacc.c:1646 */ +#line 2174 "awkgram.c" /* yacc.c:1646 */ break; case 29: -#line 372 "awkgram.y" /* yacc.c:1646 */ +#line 424 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); at_seen = false; } -#line 2103 "awkgram.c" /* yacc.c:1646 */ +#line 2183 "awkgram.c" /* yacc.c:1646 */ break; case 32: -#line 385 "awkgram.y" /* yacc.c:1646 */ +#line 436 "awkgram.y" /* yacc.c:1646 */ + { want_param_names = FUNC_HEADER; } +#line 2189 "awkgram.c" /* yacc.c:1646 */ + break; + + case 33: +#line 437 "awkgram.y" /* yacc.c:1646 */ { - (yyvsp[-5])->source_file = source; - if (install_function((yyvsp[-4])->lextok, (yyvsp[-5]), (yyvsp[-2])) < 0) + /* + * treat any comments between BOF and the first function + * definition (with no intervening BEGIN etc block) as + * program comments. Special kludge: iff there are more + * than one such comments, treat the last as a function + * comment. + */ + if (prior_comment != NULL) { + comment_to_save = prior_comment; + prior_comment = NULL; + } else if (comment != NULL) { + comment_to_save = comment; + comment = NULL; + } else + comment_to_save = NULL; + + if (comment_to_save != NULL && func_first + && strstr(comment_to_save->memory->stptr, "\n\n") != NULL) + split_comment(); + + /* save any other pre-function comment as function comment */ + if (comment_to_save != NULL) { + function_comment = comment_to_save; + comment_to_save = NULL; + } + func_first = false; + (yyvsp[-6])->source_file = source; + if (install_function((yyvsp[-5])->lextok, (yyvsp[-6]), (yyvsp[-2])) < 0) YYABORT; - in_function = (yyvsp[-4])->lextok; - (yyvsp[-4])->lextok = NULL; - bcfree((yyvsp[-4])); - /* $4 already free'd in install_function */ - (yyval) = (yyvsp[-5]); + in_function = (yyvsp[-5])->lextok; + (yyvsp[-5])->lextok = NULL; + bcfree((yyvsp[-5])); + /* $5 already free'd in install_function */ + (yyval) = (yyvsp[-6]); + want_param_names = FUNC_BODY; } -#line 2118 "awkgram.c" /* yacc.c:1646 */ +#line 2231 "awkgram.c" /* yacc.c:1646 */ break; - case 33: -#line 403 "awkgram.y" /* yacc.c:1646 */ + case 34: +#line 482 "awkgram.y" /* yacc.c:1646 */ { want_regexp = true; } -#line 2124 "awkgram.c" /* yacc.c:1646 */ +#line 2237 "awkgram.c" /* yacc.c:1646 */ break; - case 34: -#line 405 "awkgram.y" /* yacc.c:1646 */ + case 35: +#line 484 "awkgram.y" /* yacc.c:1646 */ { NODE *n, *exp; char *re; @@ -2153,69 +2266,136 @@ yyreduce: (yyval)->opcode = Op_match_rec; (yyval)->memory = n; } -#line 2157 "awkgram.c" /* yacc.c:1646 */ +#line 2270 "awkgram.c" /* yacc.c:1646 */ break; - case 35: -#line 437 "awkgram.y" /* yacc.c:1646 */ - { bcfree((yyvsp[0])); } -#line 2163 "awkgram.c" /* yacc.c:1646 */ + case 36: +#line 516 "awkgram.y" /* yacc.c:1646 */ + { + NODE *n, *exp; + char *re; + size_t len; + + re = (yyvsp[0])->lextok; + (yyvsp[0])->lextok = NULL; + len = strlen(re); + + exp = make_str_node(re, len, ALREADY_MALLOCED); + n = make_regnode(Node_typedregex, exp); + if (n == NULL) { + unref(exp); + YYABORT; + } + (yyval) = (yyvsp[0]); + (yyval)->opcode = Op_push_re; + (yyval)->memory = n; + } +#line 2294 "awkgram.c" /* yacc.c:1646 */ break; case 37: -#line 443 "awkgram.y" /* yacc.c:1646 */ - { (yyval) = NULL; } -#line 2169 "awkgram.c" /* yacc.c:1646 */ +#line 538 "awkgram.y" /* yacc.c:1646 */ + { bcfree((yyvsp[0])); } +#line 2300 "awkgram.c" /* yacc.c:1646 */ break; - case 38: -#line 445 "awkgram.y" /* yacc.c:1646 */ + case 39: +#line 544 "awkgram.y" /* yacc.c:1646 */ { - if ((yyvsp[0]) == NULL) - (yyval) = (yyvsp[-1]); - else { + if (prior_comment != NULL) { + (yyval) = list_create(prior_comment); + prior_comment = NULL; + } else if (comment != NULL) { + (yyval) = list_create(comment); + comment = NULL; + } else + (yyval) = NULL; + } +#line 2315 "awkgram.c" /* yacc.c:1646 */ + break; + + case 40: +#line 555 "awkgram.y" /* yacc.c:1646 */ + { + if ((yyvsp[0]) == NULL) { + if (prior_comment != NULL) { + (yyval) = list_append((yyvsp[-1]), prior_comment); + prior_comment = NULL; + if (comment != NULL) { + (yyval) = list_append((yyval), comment); + comment = NULL; + } + } else if (comment != NULL) { + (yyval) = list_append((yyvsp[-1]), comment); + comment = NULL; + } else + (yyval) = (yyvsp[-1]); + } else { add_lint((yyvsp[0]), LINT_no_effect); - if ((yyvsp[-1]) == NULL) - (yyval) = (yyvsp[0]); - else + if ((yyvsp[-1]) == NULL) { + if (prior_comment != NULL) { + (yyval) = list_append((yyvsp[0]), prior_comment); + prior_comment = NULL; + if (comment != NULL) { + (yyval) = list_append((yyval), comment); + comment = NULL; + } + } else if (comment != NULL) { + (yyval) = list_append((yyvsp[0]), comment); + comment = NULL; + } else + (yyval) = (yyvsp[0]); + } else { + if (prior_comment != NULL) { + list_append((yyvsp[0]), prior_comment); + prior_comment = NULL; + if (comment != NULL) { + list_append((yyvsp[0]), comment); + comment = NULL; + } + } else if (comment != NULL) { + list_append((yyvsp[0]), comment); + comment = NULL; + } (yyval) = list_merge((yyvsp[-1]), (yyvsp[0])); + } } - yyerrok; + yyerrok; } -#line 2186 "awkgram.c" /* yacc.c:1646 */ +#line 2366 "awkgram.c" /* yacc.c:1646 */ break; - case 39: -#line 458 "awkgram.y" /* yacc.c:1646 */ + case 41: +#line 602 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2192 "awkgram.c" /* yacc.c:1646 */ +#line 2372 "awkgram.c" /* yacc.c:1646 */ break; - case 42: -#line 468 "awkgram.y" /* yacc.c:1646 */ + case 44: +#line 612 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2198 "awkgram.c" /* yacc.c:1646 */ +#line 2378 "awkgram.c" /* yacc.c:1646 */ break; - case 43: -#line 470 "awkgram.y" /* yacc.c:1646 */ + case 45: +#line 614 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 2204 "awkgram.c" /* yacc.c:1646 */ +#line 2384 "awkgram.c" /* yacc.c:1646 */ break; - case 44: -#line 472 "awkgram.y" /* yacc.c:1646 */ + case 46: +#line 616 "awkgram.y" /* yacc.c:1646 */ { if (do_pretty_print) (yyval) = list_prepend((yyvsp[0]), instruction(Op_exec_count)); else (yyval) = (yyvsp[0]); } -#line 2215 "awkgram.c" /* yacc.c:1646 */ +#line 2395 "awkgram.c" /* yacc.c:1646 */ break; - case 45: -#line 479 "awkgram.y" /* yacc.c:1646 */ + case 47: +#line 623 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *dflt, *curr = NULL, *cexp, *cstmt; INSTRUCTION *ip, *nextc, *tbreak; @@ -2236,7 +2416,7 @@ yyreduce: } /* else curr = NULL; */ - for(; curr != NULL; curr = nextc) { + for (; curr != NULL; curr = nextc) { INSTRUCTION *caseexp = curr->case_exp; INSTRUCTION *casestmt = curr->case_stmt; @@ -2305,11 +2485,11 @@ yyreduce: break_allowed--; fix_break_continue(ip, tbreak, NULL); } -#line 2309 "awkgram.c" /* yacc.c:1646 */ +#line 2489 "awkgram.c" /* yacc.c:1646 */ break; - case 46: -#line 569 "awkgram.y" /* yacc.c:1646 */ + case 48: +#line 713 "awkgram.y" /* yacc.c:1646 */ { /* * ----------------- @@ -2351,11 +2531,11 @@ yyreduce: continue_allowed--; fix_break_continue(ip, tbreak, tcont); } -#line 2355 "awkgram.c" /* yacc.c:1646 */ +#line 2535 "awkgram.c" /* yacc.c:1646 */ break; - case 47: -#line 611 "awkgram.y" /* yacc.c:1646 */ + case 49: +#line 755 "awkgram.y" /* yacc.c:1646 */ { /* * ----------------- @@ -2397,11 +2577,11 @@ yyreduce: } /* else $1 and $4 are NULLs */ } -#line 2401 "awkgram.c" /* yacc.c:1646 */ +#line 2581 "awkgram.c" /* yacc.c:1646 */ break; - case 48: -#line 653 "awkgram.y" /* yacc.c:1646 */ + case 50: +#line 797 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip; char *var_name = (yyvsp[-5])->lextok; @@ -2514,70 +2694,73 @@ regular_loop: break_allowed--; continue_allowed--; } -#line 2518 "awkgram.c" /* yacc.c:1646 */ +#line 2698 "awkgram.c" /* yacc.c:1646 */ break; - case 49: -#line 766 "awkgram.y" /* yacc.c:1646 */ + case 51: +#line 910 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_for_loop((yyvsp[-11]), (yyvsp[-9]), (yyvsp[-6]), (yyvsp[-3]), (yyvsp[0])); break_allowed--; continue_allowed--; } -#line 2529 "awkgram.c" /* yacc.c:1646 */ +#line 2709 "awkgram.c" /* yacc.c:1646 */ break; - case 50: -#line 773 "awkgram.y" /* yacc.c:1646 */ + case 52: +#line 917 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_for_loop((yyvsp[-10]), (yyvsp[-8]), (INSTRUCTION *) NULL, (yyvsp[-3]), (yyvsp[0])); break_allowed--; continue_allowed--; } -#line 2540 "awkgram.c" /* yacc.c:1646 */ +#line 2720 "awkgram.c" /* yacc.c:1646 */ break; - case 51: -#line 780 "awkgram.y" /* yacc.c:1646 */ + case 53: +#line 924 "awkgram.y" /* yacc.c:1646 */ { if (do_pretty_print) (yyval) = list_prepend((yyvsp[0]), instruction(Op_exec_count)); else (yyval) = (yyvsp[0]); + (yyval) = add_pending_comment((yyval)); } -#line 2551 "awkgram.c" /* yacc.c:1646 */ +#line 2732 "awkgram.c" /* yacc.c:1646 */ break; - case 52: -#line 790 "awkgram.y" /* yacc.c:1646 */ + case 54: +#line 935 "awkgram.y" /* yacc.c:1646 */ { if (! break_allowed) error_ln((yyvsp[-1])->source_line, _("`break' is not allowed outside a loop or switch")); (yyvsp[-1])->target_jmp = NULL; (yyval) = list_create((yyvsp[-1])); + (yyval) = add_pending_comment((yyval)); } -#line 2564 "awkgram.c" /* yacc.c:1646 */ +#line 2746 "awkgram.c" /* yacc.c:1646 */ break; - case 53: -#line 799 "awkgram.y" /* yacc.c:1646 */ + case 55: +#line 945 "awkgram.y" /* yacc.c:1646 */ { if (! continue_allowed) error_ln((yyvsp[-1])->source_line, _("`continue' is not allowed outside a loop")); (yyvsp[-1])->target_jmp = NULL; (yyval) = list_create((yyvsp[-1])); + (yyval) = add_pending_comment((yyval)); } -#line 2577 "awkgram.c" /* yacc.c:1646 */ +#line 2760 "awkgram.c" /* yacc.c:1646 */ break; - case 54: -#line 808 "awkgram.y" /* yacc.c:1646 */ + case 56: +#line 955 "awkgram.y" /* yacc.c:1646 */ { /* if inside function (rule = 0), resolve context at run-time */ if (rule && rule != Rule) @@ -2585,12 +2768,13 @@ regular_loop: _("`next' used in %s action"), ruletab[rule]); (yyvsp[-1])->target_jmp = ip_rec; (yyval) = list_create((yyvsp[-1])); + (yyval) = add_pending_comment((yyval)); } -#line 2590 "awkgram.c" /* yacc.c:1646 */ +#line 2774 "awkgram.c" /* yacc.c:1646 */ break; - case 55: -#line 817 "awkgram.y" /* yacc.c:1646 */ + case 57: +#line 965 "awkgram.y" /* yacc.c:1646 */ { /* if inside function (rule = 0), resolve context at run-time */ if (rule == BEGIN || rule == END || rule == ENDFILE) @@ -2600,12 +2784,13 @@ regular_loop: (yyvsp[-1])->target_newfile = ip_newfile; (yyvsp[-1])->target_endfile = ip_endfile; (yyval) = list_create((yyvsp[-1])); + (yyval) = add_pending_comment((yyval)); } -#line 2605 "awkgram.c" /* yacc.c:1646 */ +#line 2790 "awkgram.c" /* yacc.c:1646 */ break; - case 56: -#line 828 "awkgram.y" /* yacc.c:1646 */ + case 58: +#line 977 "awkgram.y" /* yacc.c:1646 */ { /* Initialize the two possible jump targets, the actual target * is resolved at run-time. @@ -2619,21 +2804,22 @@ regular_loop: (yyval)->nexti->memory = dupnode(Nnull_string); } else (yyval) = list_append((yyvsp[-1]), (yyvsp[-2])); + (yyval) = add_pending_comment((yyval)); } -#line 2624 "awkgram.c" /* yacc.c:1646 */ +#line 2810 "awkgram.c" /* yacc.c:1646 */ break; - case 57: -#line 843 "awkgram.y" /* yacc.c:1646 */ + case 59: +#line 993 "awkgram.y" /* yacc.c:1646 */ { if (! in_function) yyerror(_("`return' used outside function context")); } -#line 2633 "awkgram.c" /* yacc.c:1646 */ +#line 2819 "awkgram.c" /* yacc.c:1646 */ break; - case 58: -#line 846 "awkgram.y" /* yacc.c:1646 */ + case 60: +#line 996 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-1]) == NULL) { (yyval) = list_create((yyvsp[-3])); @@ -2653,18 +2839,19 @@ regular_loop: (yyval) = list_append((yyvsp[-1]), (yyvsp[-3])); } + (yyval) = add_pending_comment((yyval)); } -#line 2658 "awkgram.c" /* yacc.c:1646 */ +#line 2845 "awkgram.c" /* yacc.c:1646 */ break; - case 60: -#line 878 "awkgram.y" /* yacc.c:1646 */ + case 62: +#line 1029 "awkgram.y" /* yacc.c:1646 */ { in_print = true; in_parens = 0; } -#line 2664 "awkgram.c" /* yacc.c:1646 */ +#line 2851 "awkgram.c" /* yacc.c:1646 */ break; - case 61: -#line 879 "awkgram.y" /* yacc.c:1646 */ + case 63: +#line 1030 "awkgram.y" /* yacc.c:1646 */ { /* * Optimization: plain `print' has no expression list, so $3 is null. @@ -2760,18 +2947,19 @@ regular_print: } } } + (yyval) = add_pending_comment((yyval)); } -#line 2765 "awkgram.c" /* yacc.c:1646 */ +#line 2953 "awkgram.c" /* yacc.c:1646 */ break; - case 62: -#line 976 "awkgram.y" /* yacc.c:1646 */ + case 64: +#line 1128 "awkgram.y" /* yacc.c:1646 */ { sub_counter = 0; } -#line 2771 "awkgram.c" /* yacc.c:1646 */ +#line 2959 "awkgram.c" /* yacc.c:1646 */ break; - case 63: -#line 977 "awkgram.y" /* yacc.c:1646 */ + case 65: +#line 1129 "awkgram.y" /* yacc.c:1646 */ { char *arr = (yyvsp[-2])->lextok; @@ -2803,12 +2991,13 @@ regular_print: (yyvsp[-3])->expr_count = sub_counter; (yyval) = list_append(list_append((yyvsp[0]), (yyvsp[-2])), (yyvsp[-3])); } + (yyval) = add_pending_comment((yyval)); } -#line 2808 "awkgram.c" /* yacc.c:1646 */ +#line 2997 "awkgram.c" /* yacc.c:1646 */ break; - case 64: -#line 1014 "awkgram.y" /* yacc.c:1646 */ + case 66: +#line 1167 "awkgram.y" /* yacc.c:1646 */ { static bool warned = false; char *arr = (yyvsp[-1])->lextok; @@ -2833,53 +3022,57 @@ regular_print: else if ((yyvsp[-1])->memory == func_table) fatal(_("`delete' is not allowed with FUNCTAB")); } + (yyval) = add_pending_comment((yyval)); } -#line 2838 "awkgram.c" /* yacc.c:1646 */ +#line 3028 "awkgram.c" /* yacc.c:1646 */ break; - case 65: -#line 1040 "awkgram.y" /* yacc.c:1646 */ - { (yyval) = optimize_assignment((yyvsp[0])); } -#line 2844 "awkgram.c" /* yacc.c:1646 */ + case 67: +#line 1194 "awkgram.y" /* yacc.c:1646 */ + { + (yyval) = optimize_assignment((yyvsp[0])); + (yyval) = add_pending_comment((yyval)); + } +#line 3037 "awkgram.c" /* yacc.c:1646 */ break; - case 66: -#line 1045 "awkgram.y" /* yacc.c:1646 */ + case 68: +#line 1202 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2850 "awkgram.c" /* yacc.c:1646 */ +#line 3043 "awkgram.c" /* yacc.c:1646 */ break; - case 67: -#line 1047 "awkgram.y" /* yacc.c:1646 */ + case 69: +#line 1204 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2856 "awkgram.c" /* yacc.c:1646 */ +#line 3049 "awkgram.c" /* yacc.c:1646 */ break; - case 68: -#line 1052 "awkgram.y" /* yacc.c:1646 */ + case 70: +#line 1209 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2862 "awkgram.c" /* yacc.c:1646 */ +#line 3055 "awkgram.c" /* yacc.c:1646 */ break; - case 69: -#line 1054 "awkgram.y" /* yacc.c:1646 */ + case 71: +#line 1211 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-1]) == NULL) (yyval) = list_create((yyvsp[0])); else (yyval) = list_prepend((yyvsp[-1]), (yyvsp[0])); } -#line 2873 "awkgram.c" /* yacc.c:1646 */ +#line 3066 "awkgram.c" /* yacc.c:1646 */ break; - case 70: -#line 1061 "awkgram.y" /* yacc.c:1646 */ + case 72: +#line 1218 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2879 "awkgram.c" /* yacc.c:1646 */ +#line 3072 "awkgram.c" /* yacc.c:1646 */ break; - case 71: -#line 1066 "awkgram.y" /* yacc.c:1646 */ + case 73: +#line 1223 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *casestmt = (yyvsp[0]); if ((yyvsp[0]) == NULL) @@ -2891,11 +3084,11 @@ regular_print: bcfree((yyvsp[-2])); (yyval) = (yyvsp[-4]); } -#line 2895 "awkgram.c" /* yacc.c:1646 */ +#line 3088 "awkgram.c" /* yacc.c:1646 */ break; - case 72: -#line 1078 "awkgram.y" /* yacc.c:1646 */ + case 74: +#line 1235 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *casestmt = (yyvsp[0]); if ((yyvsp[0]) == NULL) @@ -2906,17 +3099,17 @@ regular_print: (yyvsp[-3])->case_stmt = casestmt; (yyval) = (yyvsp[-3]); } -#line 2910 "awkgram.c" /* yacc.c:1646 */ +#line 3103 "awkgram.c" /* yacc.c:1646 */ break; - case 73: -#line 1092 "awkgram.y" /* yacc.c:1646 */ + case 75: +#line 1249 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2916 "awkgram.c" /* yacc.c:1646 */ +#line 3109 "awkgram.c" /* yacc.c:1646 */ break; - case 74: -#line 1094 "awkgram.y" /* yacc.c:1646 */ + case 76: +#line 1251 "awkgram.y" /* yacc.c:1646 */ { NODE *n = (yyvsp[0])->memory; (void) force_number(n); @@ -2924,71 +3117,84 @@ regular_print: bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 2928 "awkgram.c" /* yacc.c:1646 */ +#line 3121 "awkgram.c" /* yacc.c:1646 */ break; - case 75: -#line 1102 "awkgram.y" /* yacc.c:1646 */ + case 77: +#line 1259 "awkgram.y" /* yacc.c:1646 */ { bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 2937 "awkgram.c" /* yacc.c:1646 */ +#line 3130 "awkgram.c" /* yacc.c:1646 */ break; - case 76: -#line 1107 "awkgram.y" /* yacc.c:1646 */ + case 78: +#line 1264 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2943 "awkgram.c" /* yacc.c:1646 */ +#line 3136 "awkgram.c" /* yacc.c:1646 */ break; - case 77: -#line 1109 "awkgram.y" /* yacc.c:1646 */ + case 79: +#line 1266 "awkgram.y" /* yacc.c:1646 */ { + if ((yyvsp[0])->memory->type == Node_regex) + (yyvsp[0])->opcode = Op_push_re; + else + (yyvsp[0])->opcode = Op_push; + (yyval) = (yyvsp[0]); + } +#line 3148 "awkgram.c" /* yacc.c:1646 */ + break; + + case 80: +#line 1274 "awkgram.y" /* yacc.c:1646 */ + { + assert((yyvsp[0])->memory->type == Node_typedregex); (yyvsp[0])->opcode = Op_push_re; (yyval) = (yyvsp[0]); } -#line 2952 "awkgram.c" /* yacc.c:1646 */ +#line 3158 "awkgram.c" /* yacc.c:1646 */ break; - case 78: -#line 1117 "awkgram.y" /* yacc.c:1646 */ + case 81: +#line 1283 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2958 "awkgram.c" /* yacc.c:1646 */ +#line 3164 "awkgram.c" /* yacc.c:1646 */ break; - case 79: -#line 1119 "awkgram.y" /* yacc.c:1646 */ + case 82: +#line 1285 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2964 "awkgram.c" /* yacc.c:1646 */ +#line 3170 "awkgram.c" /* yacc.c:1646 */ break; - case 81: -#line 1129 "awkgram.y" /* yacc.c:1646 */ + case 84: +#line 1295 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 2972 "awkgram.c" /* yacc.c:1646 */ +#line 3178 "awkgram.c" /* yacc.c:1646 */ break; - case 82: -#line 1136 "awkgram.y" /* yacc.c:1646 */ + case 85: +#line 1302 "awkgram.y" /* yacc.c:1646 */ { in_print = false; in_parens = 0; (yyval) = NULL; } -#line 2982 "awkgram.c" /* yacc.c:1646 */ +#line 3188 "awkgram.c" /* yacc.c:1646 */ break; - case 83: -#line 1141 "awkgram.y" /* yacc.c:1646 */ + case 86: +#line 1307 "awkgram.y" /* yacc.c:1646 */ { in_print = false; in_parens = 0; } -#line 2988 "awkgram.c" /* yacc.c:1646 */ +#line 3194 "awkgram.c" /* yacc.c:1646 */ break; - case 84: -#line 1142 "awkgram.y" /* yacc.c:1646 */ + case 87: +#line 1308 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-2])->redir_type == redirect_twoway && (yyvsp[0])->lasti->opcode == Op_K_getline_redir @@ -2996,63 +3202,63 @@ regular_print: yyerror(_("multistage two-way pipelines don't work")); (yyval) = list_prepend((yyvsp[0]), (yyvsp[-2])); } -#line 3000 "awkgram.c" /* yacc.c:1646 */ +#line 3206 "awkgram.c" /* yacc.c:1646 */ break; - case 85: -#line 1153 "awkgram.y" /* yacc.c:1646 */ + case 88: +#line 1319 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_condition((yyvsp[-3]), (yyvsp[-5]), (yyvsp[0]), NULL, NULL); } -#line 3008 "awkgram.c" /* yacc.c:1646 */ +#line 3214 "awkgram.c" /* yacc.c:1646 */ break; - case 86: -#line 1158 "awkgram.y" /* yacc.c:1646 */ + case 89: +#line 1324 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_condition((yyvsp[-6]), (yyvsp[-8]), (yyvsp[-3]), (yyvsp[-2]), (yyvsp[0])); } -#line 3016 "awkgram.c" /* yacc.c:1646 */ +#line 3222 "awkgram.c" /* yacc.c:1646 */ break; - case 91: -#line 1175 "awkgram.y" /* yacc.c:1646 */ + case 94: +#line 1341 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3022 "awkgram.c" /* yacc.c:1646 */ +#line 3228 "awkgram.c" /* yacc.c:1646 */ break; - case 92: -#line 1177 "awkgram.y" /* yacc.c:1646 */ + case 95: +#line 1343 "awkgram.y" /* yacc.c:1646 */ { bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 3031 "awkgram.c" /* yacc.c:1646 */ +#line 3237 "awkgram.c" /* yacc.c:1646 */ break; - case 93: -#line 1185 "awkgram.y" /* yacc.c:1646 */ + case 96: +#line 1351 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3037 "awkgram.c" /* yacc.c:1646 */ +#line 3243 "awkgram.c" /* yacc.c:1646 */ break; - case 94: -#line 1187 "awkgram.y" /* yacc.c:1646 */ - { (yyval) = (yyvsp[0]) ; } -#line 3043 "awkgram.c" /* yacc.c:1646 */ + case 97: +#line 1353 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = (yyvsp[0]); } +#line 3249 "awkgram.c" /* yacc.c:1646 */ break; - case 95: -#line 1192 "awkgram.y" /* yacc.c:1646 */ + case 98: +#line 1358 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->param_count = 0; (yyval) = list_create((yyvsp[0])); } -#line 3052 "awkgram.c" /* yacc.c:1646 */ +#line 3258 "awkgram.c" /* yacc.c:1646 */ break; - case 96: -#line 1197 "awkgram.y" /* yacc.c:1646 */ + case 99: +#line 1363 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-2]) != NULL && (yyvsp[0]) != NULL) { (yyvsp[0])->param_count = (yyvsp[-2])->lasti->param_count + 1; @@ -3061,74 +3267,74 @@ regular_print: } else (yyval) = NULL; } -#line 3065 "awkgram.c" /* yacc.c:1646 */ +#line 3271 "awkgram.c" /* yacc.c:1646 */ break; - case 97: -#line 1206 "awkgram.y" /* yacc.c:1646 */ + case 100: +#line 1372 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3071 "awkgram.c" /* yacc.c:1646 */ +#line 3277 "awkgram.c" /* yacc.c:1646 */ break; - case 98: -#line 1208 "awkgram.y" /* yacc.c:1646 */ + case 101: +#line 1374 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3077 "awkgram.c" /* yacc.c:1646 */ +#line 3283 "awkgram.c" /* yacc.c:1646 */ break; - case 99: -#line 1210 "awkgram.y" /* yacc.c:1646 */ + case 102: +#line 1376 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-2]); } -#line 3083 "awkgram.c" /* yacc.c:1646 */ +#line 3289 "awkgram.c" /* yacc.c:1646 */ break; - case 100: -#line 1216 "awkgram.y" /* yacc.c:1646 */ + case 103: +#line 1382 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3089 "awkgram.c" /* yacc.c:1646 */ +#line 3295 "awkgram.c" /* yacc.c:1646 */ break; - case 101: -#line 1218 "awkgram.y" /* yacc.c:1646 */ + case 104: +#line 1384 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3095 "awkgram.c" /* yacc.c:1646 */ +#line 3301 "awkgram.c" /* yacc.c:1646 */ break; - case 102: -#line 1223 "awkgram.y" /* yacc.c:1646 */ + case 105: +#line 1389 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3101 "awkgram.c" /* yacc.c:1646 */ +#line 3307 "awkgram.c" /* yacc.c:1646 */ break; - case 103: -#line 1225 "awkgram.y" /* yacc.c:1646 */ + case 106: +#line 1391 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3107 "awkgram.c" /* yacc.c:1646 */ +#line 3313 "awkgram.c" /* yacc.c:1646 */ break; - case 104: -#line 1230 "awkgram.y" /* yacc.c:1646 */ + case 107: +#line 1396 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_expression_list(NULL, (yyvsp[0])); } -#line 3113 "awkgram.c" /* yacc.c:1646 */ +#line 3319 "awkgram.c" /* yacc.c:1646 */ break; - case 105: -#line 1232 "awkgram.y" /* yacc.c:1646 */ + case 108: +#line 1398 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); yyerrok; } -#line 3122 "awkgram.c" /* yacc.c:1646 */ +#line 3328 "awkgram.c" /* yacc.c:1646 */ break; - case 106: -#line 1237 "awkgram.y" /* yacc.c:1646 */ + case 109: +#line 1403 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3128 "awkgram.c" /* yacc.c:1646 */ +#line 3334 "awkgram.c" /* yacc.c:1646 */ break; - case 107: -#line 1239 "awkgram.y" /* yacc.c:1646 */ + case 110: +#line 1405 "awkgram.y" /* yacc.c:1646 */ { /* * Returning the expression list instead of NULL lets @@ -3136,58 +3342,159 @@ regular_print: */ (yyval) = (yyvsp[-1]); } -#line 3140 "awkgram.c" /* yacc.c:1646 */ +#line 3346 "awkgram.c" /* yacc.c:1646 */ break; - case 108: -#line 1247 "awkgram.y" /* yacc.c:1646 */ + case 111: +#line 1413 "awkgram.y" /* yacc.c:1646 */ { /* Ditto */ (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); } -#line 3149 "awkgram.c" /* yacc.c:1646 */ +#line 3355 "awkgram.c" /* yacc.c:1646 */ break; - case 109: -#line 1252 "awkgram.y" /* yacc.c:1646 */ + case 112: +#line 1418 "awkgram.y" /* yacc.c:1646 */ { /* Ditto */ (yyval) = (yyvsp[-2]); } -#line 3158 "awkgram.c" /* yacc.c:1646 */ +#line 3364 "awkgram.c" /* yacc.c:1646 */ break; - case 110: -#line 1261 "awkgram.y" /* yacc.c:1646 */ + case 113: +#line 1426 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = NULL; } +#line 3370 "awkgram.c" /* yacc.c:1646 */ + break; + + case 114: +#line 1428 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = (yyvsp[0]); } +#line 3376 "awkgram.c" /* yacc.c:1646 */ + break; + + case 115: +#line 1433 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = mk_expression_list(NULL, (yyvsp[0])); } +#line 3382 "awkgram.c" /* yacc.c:1646 */ + break; + + case 116: +#line 1435 "awkgram.y" /* yacc.c:1646 */ + { + (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); + yyerrok; + } +#line 3391 "awkgram.c" /* yacc.c:1646 */ + break; + + case 117: +#line 1440 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = NULL; } +#line 3397 "awkgram.c" /* yacc.c:1646 */ + break; + + case 118: +#line 1442 "awkgram.y" /* yacc.c:1646 */ + { + /* + * Returning the expression list instead of NULL lets + * snode get a list of arguments that it can count. + */ + (yyval) = (yyvsp[-1]); + } +#line 3409 "awkgram.c" /* yacc.c:1646 */ + break; + + case 119: +#line 1450 "awkgram.y" /* yacc.c:1646 */ + { + /* Ditto */ + (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); + } +#line 3418 "awkgram.c" /* yacc.c:1646 */ + break; + + case 120: +#line 1455 "awkgram.y" /* yacc.c:1646 */ + { + /* Ditto */ + (yyval) = (yyvsp[-2]); + } +#line 3427 "awkgram.c" /* yacc.c:1646 */ + break; + + case 121: +#line 1462 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = (yyvsp[0]); } +#line 3433 "awkgram.c" /* yacc.c:1646 */ + break; + + case 122: +#line 1463 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = list_create((yyvsp[0])); } +#line 3439 "awkgram.c" /* yacc.c:1646 */ + break; + + case 123: +#line 1469 "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 3169 "awkgram.c" /* yacc.c:1646 */ +#line 3450 "awkgram.c" /* yacc.c:1646 */ break; - case 111: -#line 1268 "awkgram.y" /* yacc.c:1646 */ + case 124: +#line 1476 "awkgram.y" /* yacc.c:1646 */ + { + (yyval) = mk_assignment((yyvsp[-2]), list_create((yyvsp[0])), (yyvsp[-1])); + } +#line 3458 "awkgram.c" /* yacc.c:1646 */ + break; + + case 125: +#line 1480 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3175 "awkgram.c" /* yacc.c:1646 */ +#line 3464 "awkgram.c" /* yacc.c:1646 */ break; - case 112: -#line 1270 "awkgram.y" /* yacc.c:1646 */ + case 126: +#line 1482 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3181 "awkgram.c" /* yacc.c:1646 */ +#line 3470 "awkgram.c" /* yacc.c:1646 */ break; - case 113: -#line 1272 "awkgram.y" /* yacc.c:1646 */ + case 127: +#line 1484 "awkgram.y" /* yacc.c:1646 */ + { + if ((yyvsp[-2])->lasti->opcode == Op_match_rec) + warning_ln((yyvsp[-1])->source_line, + _("regular expression on left of `~' or `!~' operator")); + + assert((yyvsp[0])->opcode == Op_push_re + && (yyvsp[0])->memory->type == Node_typedregex); + /* RHS is @/.../ */ + (yyvsp[-1])->memory = (yyvsp[0])->memory; + bcfree((yyvsp[0])); + (yyval) = list_append((yyvsp[-2]), (yyvsp[-1])); + } +#line 3487 "awkgram.c" /* yacc.c:1646 */ + break; + + case 128: +#line 1497 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-2])->lasti->opcode == Op_match_rec) warning_ln((yyvsp[-1])->source_line, _("regular expression on left of `~' or `!~' operator")); if ((yyvsp[0])->lasti == (yyvsp[0])->nexti && (yyvsp[0])->nexti->opcode == Op_match_rec) { + /* RHS is /.../ */ (yyvsp[-1])->memory = (yyvsp[0])->nexti->memory; bcfree((yyvsp[0])->nexti); /* Op_match_rec */ bcfree((yyvsp[0])); /* Op_list */ @@ -3197,11 +3504,11 @@ regular_print: (yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), (yyvsp[-1])); } } -#line 3201 "awkgram.c" /* yacc.c:1646 */ +#line 3508 "awkgram.c" /* yacc.c:1646 */ break; - case 114: -#line 1288 "awkgram.y" /* yacc.c:1646 */ + case 129: +#line 1514 "awkgram.y" /* yacc.c:1646 */ { if (do_lint_old) warning_ln((yyvsp[-1])->source_line, @@ -3211,91 +3518,91 @@ regular_print: (yyvsp[-1])->expr_count = 1; (yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), (yyvsp[-1])); } -#line 3215 "awkgram.c" /* yacc.c:1646 */ +#line 3522 "awkgram.c" /* yacc.c:1646 */ break; - case 115: -#line 1298 "awkgram.y" /* yacc.c:1646 */ + case 130: +#line 1524 "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 3226 "awkgram.c" /* yacc.c:1646 */ +#line 3533 "awkgram.c" /* yacc.c:1646 */ break; - case 116: -#line 1305 "awkgram.y" /* yacc.c:1646 */ + case 131: +#line 1531 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_condition((yyvsp[-4]), (yyvsp[-3]), (yyvsp[-2]), (yyvsp[-1]), (yyvsp[0])); } -#line 3232 "awkgram.c" /* yacc.c:1646 */ +#line 3539 "awkgram.c" /* yacc.c:1646 */ break; - case 117: -#line 1307 "awkgram.y" /* yacc.c:1646 */ + case 132: +#line 1533 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3238 "awkgram.c" /* yacc.c:1646 */ +#line 3545 "awkgram.c" /* yacc.c:1646 */ break; - case 118: -#line 1312 "awkgram.y" /* yacc.c:1646 */ + case 133: +#line 1538 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3244 "awkgram.c" /* yacc.c:1646 */ +#line 3551 "awkgram.c" /* yacc.c:1646 */ break; - case 119: -#line 1314 "awkgram.y" /* yacc.c:1646 */ + case 134: +#line 1540 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3250 "awkgram.c" /* yacc.c:1646 */ +#line 3557 "awkgram.c" /* yacc.c:1646 */ break; - case 120: -#line 1316 "awkgram.y" /* yacc.c:1646 */ + case 135: +#line 1542 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_assign_quotient; (yyval) = (yyvsp[0]); } -#line 3259 "awkgram.c" /* yacc.c:1646 */ +#line 3566 "awkgram.c" /* yacc.c:1646 */ break; - case 121: -#line 1324 "awkgram.y" /* yacc.c:1646 */ + case 136: +#line 1550 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3265 "awkgram.c" /* yacc.c:1646 */ +#line 3572 "awkgram.c" /* yacc.c:1646 */ break; - case 122: -#line 1326 "awkgram.y" /* yacc.c:1646 */ + case 137: +#line 1552 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3271 "awkgram.c" /* yacc.c:1646 */ +#line 3578 "awkgram.c" /* yacc.c:1646 */ break; - case 123: -#line 1331 "awkgram.y" /* yacc.c:1646 */ + case 138: +#line 1557 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3277 "awkgram.c" /* yacc.c:1646 */ +#line 3584 "awkgram.c" /* yacc.c:1646 */ break; - case 124: -#line 1333 "awkgram.y" /* yacc.c:1646 */ + case 139: +#line 1559 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3283 "awkgram.c" /* yacc.c:1646 */ +#line 3590 "awkgram.c" /* yacc.c:1646 */ break; - case 125: -#line 1338 "awkgram.y" /* yacc.c:1646 */ + case 140: +#line 1564 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3289 "awkgram.c" /* yacc.c:1646 */ +#line 3596 "awkgram.c" /* yacc.c:1646 */ break; - case 126: -#line 1340 "awkgram.y" /* yacc.c:1646 */ + case 141: +#line 1566 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3295 "awkgram.c" /* yacc.c:1646 */ +#line 3602 "awkgram.c" /* yacc.c:1646 */ break; - case 127: -#line 1342 "awkgram.y" /* yacc.c:1646 */ + case 142: +#line 1568 "awkgram.y" /* yacc.c:1646 */ { int count = 2; bool is_simple_var = false; @@ -3321,10 +3628,15 @@ regular_print: NODE *n2 = (yyvsp[0])->nexti->memory; size_t nlen; + // 1.5 "" # can't fold this if program mucks with CONVFMT. + // See test #12 in test/posix.awk. + if ((n1->flags & (NUMBER|NUMINT)) != 0 || (n2->flags & (NUMBER|NUMINT)) != 0) + goto plain_concat; + n1 = force_string(n1); n2 = force_string(n2); nlen = n1->stlen + n2->stlen; - erealloc(n1->stptr, char *, nlen + 2, "constant fold"); + erealloc(n1->stptr, char *, nlen + 1, "constant fold"); memcpy(n1->stptr + n1->stlen, n2->stptr, n2->stlen); n1->stlen = nlen; n1->stptr[nlen] = '\0'; @@ -3335,6 +3647,7 @@ regular_print: bcfree((yyvsp[0])); (yyval) = (yyvsp[-1]); } else { + plain_concat: (yyval) = list_append(list_merge((yyvsp[-1]), (yyvsp[0])), instruction(Op_concat)); (yyval)->lasti->concat_flag = (is_simple_var ? CSVAR : 0); (yyval)->lasti->expr_count = count; @@ -3342,47 +3655,47 @@ regular_print: max_args = count; } } -#line 3346 "awkgram.c" /* yacc.c:1646 */ +#line 3659 "awkgram.c" /* yacc.c:1646 */ break; - case 129: -#line 1394 "awkgram.y" /* yacc.c:1646 */ + case 144: +#line 1626 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3352 "awkgram.c" /* yacc.c:1646 */ +#line 3665 "awkgram.c" /* yacc.c:1646 */ break; - case 130: -#line 1396 "awkgram.y" /* yacc.c:1646 */ + case 145: +#line 1628 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3358 "awkgram.c" /* yacc.c:1646 */ +#line 3671 "awkgram.c" /* yacc.c:1646 */ break; - case 131: -#line 1398 "awkgram.y" /* yacc.c:1646 */ + case 146: +#line 1630 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3364 "awkgram.c" /* yacc.c:1646 */ +#line 3677 "awkgram.c" /* yacc.c:1646 */ break; - case 132: -#line 1400 "awkgram.y" /* yacc.c:1646 */ + case 147: +#line 1632 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3370 "awkgram.c" /* yacc.c:1646 */ +#line 3683 "awkgram.c" /* yacc.c:1646 */ break; - case 133: -#line 1402 "awkgram.y" /* yacc.c:1646 */ + case 148: +#line 1634 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3376 "awkgram.c" /* yacc.c:1646 */ +#line 3689 "awkgram.c" /* yacc.c:1646 */ break; - case 134: -#line 1404 "awkgram.y" /* yacc.c:1646 */ + case 149: +#line 1636 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3382 "awkgram.c" /* yacc.c:1646 */ +#line 3695 "awkgram.c" /* yacc.c:1646 */ break; - case 135: -#line 1406 "awkgram.y" /* yacc.c:1646 */ + case 150: +#line 1638 "awkgram.y" /* yacc.c:1646 */ { /* * In BEGINFILE/ENDFILE, allow `getline [var] < file' @@ -3396,29 +3709,29 @@ regular_print: _("non-redirected `getline' undefined inside END action")); (yyval) = mk_getline((yyvsp[-2]), (yyvsp[-1]), (yyvsp[0]), redirect_input); } -#line 3400 "awkgram.c" /* yacc.c:1646 */ +#line 3713 "awkgram.c" /* yacc.c:1646 */ break; - case 136: -#line 1420 "awkgram.y" /* yacc.c:1646 */ + case 151: +#line 1652 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postincrement; (yyval) = mk_assignment((yyvsp[-1]), NULL, (yyvsp[0])); } -#line 3409 "awkgram.c" /* yacc.c:1646 */ +#line 3722 "awkgram.c" /* yacc.c:1646 */ break; - case 137: -#line 1425 "awkgram.y" /* yacc.c:1646 */ + case 152: +#line 1657 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postdecrement; (yyval) = mk_assignment((yyvsp[-1]), NULL, (yyvsp[0])); } -#line 3418 "awkgram.c" /* yacc.c:1646 */ +#line 3731 "awkgram.c" /* yacc.c:1646 */ break; - case 138: -#line 1430 "awkgram.y" /* yacc.c:1646 */ + case 153: +#line 1662 "awkgram.y" /* yacc.c:1646 */ { if (do_lint_old) { warning_ln((yyvsp[-1])->source_line, @@ -3438,64 +3751,64 @@ regular_print: (yyval) = list_append(list_merge(t, (yyvsp[0])), (yyvsp[-1])); } } -#line 3442 "awkgram.c" /* yacc.c:1646 */ +#line 3755 "awkgram.c" /* yacc.c:1646 */ break; - case 139: -#line 1455 "awkgram.y" /* yacc.c:1646 */ + case 154: +#line 1687 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_getline((yyvsp[-1]), (yyvsp[0]), (yyvsp[-3]), (yyvsp[-2])->redir_type); bcfree((yyvsp[-2])); } -#line 3451 "awkgram.c" /* yacc.c:1646 */ +#line 3764 "awkgram.c" /* yacc.c:1646 */ break; - case 140: -#line 1461 "awkgram.y" /* yacc.c:1646 */ + case 155: +#line 1693 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3457 "awkgram.c" /* yacc.c:1646 */ +#line 3770 "awkgram.c" /* yacc.c:1646 */ break; - case 141: -#line 1463 "awkgram.y" /* yacc.c:1646 */ + case 156: +#line 1695 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3463 "awkgram.c" /* yacc.c:1646 */ +#line 3776 "awkgram.c" /* yacc.c:1646 */ break; - case 142: -#line 1465 "awkgram.y" /* yacc.c:1646 */ + case 157: +#line 1697 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3469 "awkgram.c" /* yacc.c:1646 */ +#line 3782 "awkgram.c" /* yacc.c:1646 */ break; - case 143: -#line 1467 "awkgram.y" /* yacc.c:1646 */ + case 158: +#line 1699 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3475 "awkgram.c" /* yacc.c:1646 */ +#line 3788 "awkgram.c" /* yacc.c:1646 */ break; - case 144: -#line 1469 "awkgram.y" /* yacc.c:1646 */ + case 159: +#line 1701 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3481 "awkgram.c" /* yacc.c:1646 */ +#line 3794 "awkgram.c" /* yacc.c:1646 */ break; - case 145: -#line 1471 "awkgram.y" /* yacc.c:1646 */ + case 160: +#line 1703 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3487 "awkgram.c" /* yacc.c:1646 */ +#line 3800 "awkgram.c" /* yacc.c:1646 */ break; - case 146: -#line 1476 "awkgram.y" /* yacc.c:1646 */ + case 161: +#line 1708 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3495 "awkgram.c" /* yacc.c:1646 */ +#line 3808 "awkgram.c" /* yacc.c:1646 */ break; - case 147: -#line 1480 "awkgram.y" /* yacc.c:1646 */ + case 162: +#line 1712 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[0])->opcode == Op_match_rec) { (yyvsp[0])->opcode = Op_nomatch; @@ -3509,7 +3822,7 @@ regular_print: && ((yyvsp[0])->nexti->memory->flags & (MPFN|MPZN)) == 0 ) { NODE *n = (yyvsp[0])->nexti->memory; - if ((n->flags & (STRCUR|STRING)) != 0) { + if ((n->flags & STRING) != 0) { n->numbr = (AWKNUM) (n->stlen == 0); n->flags &= ~(STRCUR|STRING); n->flags |= (NUMCUR|NUMBER); @@ -3527,37 +3840,37 @@ regular_print: } } } -#line 3531 "awkgram.c" /* yacc.c:1646 */ +#line 3844 "awkgram.c" /* yacc.c:1646 */ break; - case 148: -#line 1512 "awkgram.y" /* yacc.c:1646 */ + case 163: +#line 1744 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3537 "awkgram.c" /* yacc.c:1646 */ +#line 3850 "awkgram.c" /* yacc.c:1646 */ break; - case 149: -#line 1514 "awkgram.y" /* yacc.c:1646 */ + case 164: +#line 1746 "awkgram.y" /* yacc.c:1646 */ { (yyval) = snode((yyvsp[-1]), (yyvsp[-3])); if ((yyval) == NULL) YYABORT; } -#line 3547 "awkgram.c" /* yacc.c:1646 */ +#line 3860 "awkgram.c" /* yacc.c:1646 */ break; - case 150: -#line 1520 "awkgram.y" /* yacc.c:1646 */ + case 165: +#line 1752 "awkgram.y" /* yacc.c:1646 */ { (yyval) = snode((yyvsp[-1]), (yyvsp[-3])); if ((yyval) == NULL) YYABORT; } -#line 3557 "awkgram.c" /* yacc.c:1646 */ +#line 3870 "awkgram.c" /* yacc.c:1646 */ break; - case 151: -#line 1526 "awkgram.y" /* yacc.c:1646 */ + case 166: +#line 1758 "awkgram.y" /* yacc.c:1646 */ { static bool warned = false; @@ -3570,48 +3883,48 @@ regular_print: if ((yyval) == NULL) YYABORT; } -#line 3574 "awkgram.c" /* yacc.c:1646 */ +#line 3887 "awkgram.c" /* yacc.c:1646 */ break; - case 154: -#line 1541 "awkgram.y" /* yacc.c:1646 */ + case 169: +#line 1773 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[-1])->opcode = Op_preincrement; (yyval) = mk_assignment((yyvsp[0]), NULL, (yyvsp[-1])); } -#line 3583 "awkgram.c" /* yacc.c:1646 */ +#line 3896 "awkgram.c" /* yacc.c:1646 */ break; - case 155: -#line 1546 "awkgram.y" /* yacc.c:1646 */ + case 170: +#line 1778 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[-1])->opcode = Op_predecrement; (yyval) = mk_assignment((yyvsp[0]), NULL, (yyvsp[-1])); } -#line 3592 "awkgram.c" /* yacc.c:1646 */ +#line 3905 "awkgram.c" /* yacc.c:1646 */ break; - case 156: -#line 1551 "awkgram.y" /* yacc.c:1646 */ + case 171: +#line 1783 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3600 "awkgram.c" /* yacc.c:1646 */ +#line 3913 "awkgram.c" /* yacc.c:1646 */ break; - case 157: -#line 1555 "awkgram.y" /* yacc.c:1646 */ + case 172: +#line 1787 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3608 "awkgram.c" /* yacc.c:1646 */ +#line 3921 "awkgram.c" /* yacc.c:1646 */ break; - case 158: -#line 1559 "awkgram.y" /* yacc.c:1646 */ + case 173: +#line 1791 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[0])->lasti->opcode == Op_push_i - && ((yyvsp[0])->lasti->memory->flags & (STRCUR|STRING)) == 0 + && ((yyvsp[0])->lasti->memory->flags & STRING) == 0 ) { NODE *n = (yyvsp[0])->lasti->memory; (void) force_number(n); @@ -3623,11 +3936,11 @@ regular_print: (yyval) = list_append((yyvsp[0]), (yyvsp[-1])); } } -#line 3627 "awkgram.c" /* yacc.c:1646 */ +#line 3940 "awkgram.c" /* yacc.c:1646 */ break; - case 159: -#line 1574 "awkgram.y" /* yacc.c:1646 */ + case 174: +#line 1806 "awkgram.y" /* yacc.c:1646 */ { /* * was: $$ = $2 @@ -3637,20 +3950,20 @@ regular_print: (yyvsp[-1])->memory = make_number(0.0); (yyval) = list_append((yyvsp[0]), (yyvsp[-1])); } -#line 3641 "awkgram.c" /* yacc.c:1646 */ +#line 3954 "awkgram.c" /* yacc.c:1646 */ break; - case 160: -#line 1587 "awkgram.y" /* yacc.c:1646 */ + case 175: +#line 1819 "awkgram.y" /* yacc.c:1646 */ { func_use((yyvsp[0])->lasti->func_name, FUNC_USE); (yyval) = (yyvsp[0]); } -#line 3650 "awkgram.c" /* yacc.c:1646 */ +#line 3963 "awkgram.c" /* yacc.c:1646 */ break; - case 161: -#line 1592 "awkgram.y" /* yacc.c:1646 */ + case 176: +#line 1824 "awkgram.y" /* yacc.c:1646 */ { /* indirect function call */ INSTRUCTION *f, *t; @@ -3684,18 +3997,18 @@ regular_print: (yyval) = list_prepend((yyvsp[0]), t); at_seen = false; } -#line 3688 "awkgram.c" /* yacc.c:1646 */ +#line 4001 "awkgram.c" /* yacc.c:1646 */ break; - case 162: -#line 1629 "awkgram.y" /* yacc.c:1646 */ + case 177: +#line 1861 "awkgram.y" /* yacc.c:1646 */ { NODE *n; if (! at_seen) { n = lookup((yyvsp[-3])->func_name); if (n != NULL && n->type != Node_func - && n->type != Node_ext_func && n->type != Node_old_ext_func) { + && n->type != Node_ext_func) { error_ln((yyvsp[-3])->source_line, _("attempt to use non-function `%s' in function call"), (yyvsp[-3])->func_name); @@ -3713,49 +4026,49 @@ regular_print: (yyval) = list_append(t, (yyvsp[-3])); } } -#line 3717 "awkgram.c" /* yacc.c:1646 */ +#line 4030 "awkgram.c" /* yacc.c:1646 */ break; - case 163: -#line 1657 "awkgram.y" /* yacc.c:1646 */ + case 178: +#line 1889 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3723 "awkgram.c" /* yacc.c:1646 */ +#line 4036 "awkgram.c" /* yacc.c:1646 */ break; - case 164: -#line 1659 "awkgram.y" /* yacc.c:1646 */ + case 179: +#line 1891 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3729 "awkgram.c" /* yacc.c:1646 */ +#line 4042 "awkgram.c" /* yacc.c:1646 */ break; - case 165: -#line 1664 "awkgram.y" /* yacc.c:1646 */ + case 180: +#line 1896 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3735 "awkgram.c" /* yacc.c:1646 */ +#line 4048 "awkgram.c" /* yacc.c:1646 */ break; - case 166: -#line 1666 "awkgram.y" /* yacc.c:1646 */ + case 181: +#line 1898 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3741 "awkgram.c" /* yacc.c:1646 */ +#line 4054 "awkgram.c" /* yacc.c:1646 */ break; - case 167: -#line 1671 "awkgram.y" /* yacc.c:1646 */ + case 182: +#line 1903 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3747 "awkgram.c" /* yacc.c:1646 */ +#line 4060 "awkgram.c" /* yacc.c:1646 */ break; - case 168: -#line 1673 "awkgram.y" /* yacc.c:1646 */ + case 183: +#line 1905 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_merge((yyvsp[-1]), (yyvsp[0])); } -#line 3755 "awkgram.c" /* yacc.c:1646 */ +#line 4068 "awkgram.c" /* yacc.c:1646 */ break; - case 169: -#line 1680 "awkgram.y" /* yacc.c:1646 */ + case 184: +#line 1912 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip = (yyvsp[0])->lasti; int count = ip->sub_count; /* # of SUBSEP-seperated expressions */ @@ -3769,11 +4082,11 @@ regular_print: sub_counter++; /* count # of dimensions */ (yyval) = (yyvsp[0]); } -#line 3773 "awkgram.c" /* yacc.c:1646 */ +#line 4086 "awkgram.c" /* yacc.c:1646 */ break; - case 170: -#line 1697 "awkgram.y" /* yacc.c:1646 */ + case 185: +#line 1929 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *t = (yyvsp[-1]); if ((yyvsp[-1]) == NULL) { @@ -3787,31 +4100,31 @@ regular_print: (yyvsp[0])->sub_count = count_expressions(&t, false); (yyval) = list_append(t, (yyvsp[0])); } -#line 3791 "awkgram.c" /* yacc.c:1646 */ +#line 4104 "awkgram.c" /* yacc.c:1646 */ break; - case 171: -#line 1714 "awkgram.y" /* yacc.c:1646 */ + case 186: +#line 1946 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3797 "awkgram.c" /* yacc.c:1646 */ +#line 4110 "awkgram.c" /* yacc.c:1646 */ break; - case 172: -#line 1716 "awkgram.y" /* yacc.c:1646 */ + case 187: +#line 1948 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_merge((yyvsp[-1]), (yyvsp[0])); } -#line 3805 "awkgram.c" /* yacc.c:1646 */ +#line 4118 "awkgram.c" /* yacc.c:1646 */ break; - case 173: -#line 1723 "awkgram.y" /* yacc.c:1646 */ + case 188: +#line 1955 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3811 "awkgram.c" /* yacc.c:1646 */ +#line 4124 "awkgram.c" /* yacc.c:1646 */ break; - case 174: -#line 1728 "awkgram.y" /* yacc.c:1646 */ + case 189: +#line 1960 "awkgram.y" /* yacc.c:1646 */ { char *var_name = (yyvsp[0])->lextok; @@ -3819,22 +4132,22 @@ regular_print: (yyvsp[0])->memory = variable((yyvsp[0])->source_line, var_name, Node_var_new); (yyval) = list_create((yyvsp[0])); } -#line 3823 "awkgram.c" /* yacc.c:1646 */ +#line 4136 "awkgram.c" /* yacc.c:1646 */ break; - case 175: -#line 1736 "awkgram.y" /* yacc.c:1646 */ + case 190: +#line 1968 "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 3834 "awkgram.c" /* yacc.c:1646 */ +#line 4147 "awkgram.c" /* yacc.c:1646 */ break; - case 176: -#line 1746 "awkgram.y" /* yacc.c:1646 */ + case 191: +#line 1978 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip = (yyvsp[0])->nexti; if (ip->opcode == Op_push @@ -3846,73 +4159,73 @@ regular_print: } else (yyval) = (yyvsp[0]); } -#line 3850 "awkgram.c" /* yacc.c:1646 */ +#line 4163 "awkgram.c" /* yacc.c:1646 */ break; - case 177: -#line 1758 "awkgram.y" /* yacc.c:1646 */ + case 192: +#line 1990 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_append((yyvsp[-1]), (yyvsp[-2])); if ((yyvsp[0]) != NULL) mk_assignment((yyvsp[-1]), NULL, (yyvsp[0])); } -#line 3860 "awkgram.c" /* yacc.c:1646 */ +#line 4173 "awkgram.c" /* yacc.c:1646 */ break; - case 178: -#line 1767 "awkgram.y" /* yacc.c:1646 */ + case 193: +#line 1999 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postincrement; } -#line 3868 "awkgram.c" /* yacc.c:1646 */ +#line 4181 "awkgram.c" /* yacc.c:1646 */ break; - case 179: -#line 1771 "awkgram.y" /* yacc.c:1646 */ + case 194: +#line 2003 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postdecrement; } -#line 3876 "awkgram.c" /* yacc.c:1646 */ +#line 4189 "awkgram.c" /* yacc.c:1646 */ break; - case 180: -#line 1774 "awkgram.y" /* yacc.c:1646 */ + case 195: +#line 2006 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3882 "awkgram.c" /* yacc.c:1646 */ +#line 4195 "awkgram.c" /* yacc.c:1646 */ break; - case 182: -#line 1782 "awkgram.y" /* yacc.c:1646 */ + case 197: +#line 2014 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3888 "awkgram.c" /* yacc.c:1646 */ +#line 4201 "awkgram.c" /* yacc.c:1646 */ break; - case 183: -#line 1786 "awkgram.y" /* yacc.c:1646 */ + case 198: +#line 2018 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3894 "awkgram.c" /* yacc.c:1646 */ +#line 4207 "awkgram.c" /* yacc.c:1646 */ break; - case 186: -#line 1795 "awkgram.y" /* yacc.c:1646 */ + case 201: +#line 2027 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3900 "awkgram.c" /* yacc.c:1646 */ +#line 4213 "awkgram.c" /* yacc.c:1646 */ break; - case 187: -#line 1799 "awkgram.y" /* yacc.c:1646 */ + case 202: +#line 2031 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); yyerrok; } -#line 3906 "awkgram.c" /* yacc.c:1646 */ +#line 4219 "awkgram.c" /* yacc.c:1646 */ break; - case 188: -#line 1803 "awkgram.y" /* yacc.c:1646 */ + case 203: +#line 2035 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3912 "awkgram.c" /* yacc.c:1646 */ +#line 4225 "awkgram.c" /* yacc.c:1646 */ break; -#line 3916 "awkgram.c" /* yacc.c:1646 */ +#line 4229 "awkgram.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -4140,7 +4453,7 @@ yyreturn: #endif return yyresult; } -#line 1805 "awkgram.y" /* yacc.c:1906 */ +#line 2037 "awkgram.y" /* yacc.c:1906 */ struct token { @@ -4217,9 +4530,6 @@ static const struct token tokentab[] = { {"eval", Op_symbol, LEX_EVAL, 0, 0, 0}, {"exit", Op_K_exit, LEX_EXIT, 0, 0, 0}, {"exp", Op_builtin, LEX_BUILTIN, A(1), do_exp, MPF(exp)}, -#ifdef DYNAMIC -{"extension", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2)|A(3), do_ext, 0}, -#endif {"fflush", Op_builtin, LEX_BUILTIN, A(0)|A(1), do_fflush, 0}, {"for", Op_K_for, LEX_FOR, BREAK|CONTINUE, 0, 0}, {"func", Op_func, LEX_FUNCTION, NOT_POSIX|NOT_OLD, 0, 0}, @@ -4232,6 +4542,7 @@ static const struct token tokentab[] = { {"include", Op_symbol, LEX_INCLUDE, GAWKX, 0, 0}, {"index", Op_builtin, LEX_BUILTIN, A(2), do_index, 0}, {"int", Op_builtin, LEX_BUILTIN, A(1), do_int, MPF(int)}, +{"intdiv", Op_builtin, LEX_BUILTIN, GAWKX|A(3), do_intdiv, MPF(intdiv)}, {"isarray", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_isarray, 0}, {"length", Op_builtin, LEX_LENGTH, A(0)|A(1), do_length, 0}, {"load", Op_symbol, LEX_LOAD, GAWKX, 0, 0}, @@ -4265,6 +4576,7 @@ static const struct token tokentab[] = { {"systime", Op_builtin, LEX_BUILTIN, GAWKX|A(0), do_systime, 0}, {"tolower", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_tolower, 0}, {"toupper", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_toupper, 0}, +{"typeof", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_typeof, 0}, {"while", Op_K_while, LEX_WHILE, BREAK|CONTINUE, 0, 0}, {"xor", Op_builtin, LEX_BUILTIN, GAWKX, do_xor, MPF(xor)}, }; @@ -4440,7 +4752,6 @@ yyerror(const char *m, ...) char *buf; int count; static char end_of_file_line[] = "(END OF FILE)"; - char save; print_included_from(); @@ -4471,25 +4782,17 @@ yyerror(const char *m, ...) bp = thisline + strlen(thisline); } - /* - * Saving and restoring *bp keeps valgrind happy, - * since the guts of glibc uses strlen, even though - * we're passing an explict precision. Sigh. - * - * 8/2003: We may not need this anymore. - */ - save = *bp; - *bp = '\0'; - msg("%.*s", (int) (bp - thisline), thisline); - *bp = save; va_start(args, m); if (mesg == NULL) mesg = m; - count = (bp - thisline) + strlen(mesg) + 2 + 1; - emalloc(buf, char *, count, "yyerror"); + count = strlen(mesg) + 1; + if (lexptr != NULL) + count += (lexeme - thisline) + 2; + emalloc(buf, char *, count+1, "yyerror"); + memset(buf, 0, count+1); bp = buf; @@ -4571,6 +4874,11 @@ mk_program() cp = end_block; else cp = list_merge(begin_block, end_block); + if (program_comment != NULL) { + (void) list_prepend(cp, program_comment); + } + if (comment != NULL) + (void) list_append(cp, comment); (void) list_append(cp, ip_atexit); (void) list_append(cp, instruction(Op_stop)); @@ -4603,6 +4911,12 @@ mk_program() if (begin_block != NULL) cp = list_merge(begin_block, cp); + if (program_comment != NULL) { + (void) list_prepend(cp, program_comment); + } + if (comment != NULL) { + (void) list_append(cp, comment); + } (void) list_append(cp, ip_atexit); (void) list_append(cp, instruction(Op_stop)); @@ -4610,6 +4924,10 @@ out: /* delete the Op_list, not needed */ tmp = cp->nexti; bcfree(cp); + /* these variables are not used again but zap them anyway. */ + comment = NULL; + function_comment = NULL; + program_comment = NULL; return tmp; #undef begin_block @@ -4636,7 +4954,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; @@ -5107,7 +5425,7 @@ get_src_buf() lexend = lexptr + n; if (n == 0) { static bool warned = false; - if (do_lint && newfile && ! warned){ + if (do_lint && newfile && ! warned) { warned = true; sourceline = 0; lintwarn(_("source file `%s' is empty"), source); @@ -5198,7 +5516,7 @@ again: mbstate_t tmp_state; size_t mbclen; - for (idx = 0 ; lexptr + idx < lexend ; idx++) { + for (idx = 0; lexptr + idx < lexend; idx++) { tmp_state = cur_mbstate; mbclen = mbrlen(lexptr, idx + 1, &tmp_state); @@ -5255,6 +5573,122 @@ pushback(void) (! lexeof && lexptr && lexptr > lexptr_begin ? lexptr-- : lexptr); } +/* check_comment --- check for block comment */ + +void +check_comment(void) +{ + if (comment != NULL) { + if (first_rule) { + program_comment = comment; + } else + block_comment = comment; + comment = NULL; + } + first_rule = false; +} + +/* + * get_comment --- collect comment text. + * Flag = EOL_COMMENT for end-of-line comments. + * Flag = FULL_COMMENT for self-contained comments. + */ + +int +get_comment(int flag) +{ + int c; + int sl; + tok = tokstart; + tokadd('#'); + sl = sourceline; + char *p1; + char *p2; + + while (true) { + while ((c = nextc(false)) != '\n' && c != END_FILE) { + /* ignore \r characters */ + if (c != '\r') + tokadd(c); + } + if (flag == EOL_COMMENT) { + /* comment at end of line. */ + if (c == '\n') + tokadd(c); + break; + } + if (c == '\n') { + tokadd(c); + sourceline++; + do { + c = nextc(false); + if (c == '\n') { + sourceline++; + tokadd(c); + } + } while (isspace(c) && c != END_FILE); + if (c == END_FILE) + break; + else if (c != '#') { + pushback(); + sourceline--; + break; + } else + tokadd(c); + } else + break; + } + + if (comment != NULL) + prior_comment = comment; + + /* remove any trailing blank lines (consecutive \n) from comment */ + p1 = tok - 1; + p2 = tok - 2; + while (*p1 == '\n' && *p2 == '\n') { + p1--; + p2--; + tok--; + } + + comment = bcalloc(Op_comment, 1, sl); + comment->source_file = source; + comment->memory = make_str_node(tokstart, tok - tokstart, 0); + comment->memory->comment_type = flag; + + return c; +} + +/* split_comment --- split initial comment text into program and function parts */ + +static void +split_comment(void) +{ + char *p; + int l; + NODE *n; + + p = comment_to_save->memory->stptr; + l = comment_to_save->memory->stlen - 3; + /* have at least two comments so split at last blank line (\n\n) */ + while (l >= 0) { + if (p[l] == '\n' && p[l+1] == '\n') { + function_comment = comment_to_save; + n = function_comment->memory; + function_comment->memory = make_str_node(p + l + 2, n->stlen - l - 2, 0); + /* create program comment */ + program_comment = bcalloc(Op_comment, 1, sourceline); + program_comment->source_file = comment_to_save->source_file; + p[l + 2] = 0; + program_comment->memory = make_str_node(p, l + 2, 0); + comment_to_save = NULL; + freenode(n); + break; + } + else + l--; + } +} /* allow_newline --- allow newline after &&, ||, ? and : */ @@ -5270,8 +5704,13 @@ allow_newline(void) break; } if (c == '#') { - while ((c = nextc(false)) != '\n' && c != END_FILE) - continue; + if (do_pretty_print && ! do_profile) { + /* collect comment byte code iff doing pretty print but not profiling. */ + c = get_comment(EOL_COMMENT); + } else { + while ((c = nextc(false)) != '\n' && c != END_FILE) + continue; + } if (c == END_FILE) { pushback(); break; @@ -5294,7 +5733,8 @@ allow_newline(void) * removes the warnings. */ -static int newline_eof() +static int +newline_eof() { /* NB: a newline at end does not start a source line. */ if (lasttok != NEWLINE) { @@ -5332,6 +5772,7 @@ yylex(void) bool inhex = false; bool intlstr = false; AWKNUM d; + bool collecting_typed_regexp = false; #define GET_INSTRUCTION(op) bcalloc(op, 1, sourceline) @@ -5366,6 +5807,7 @@ yylex(void) lexeme = lexptr; thisline = NULL; +collect_regexp: if (want_regexp) { int in_brack = 0; /* count brackets, [[:alnum:]] allowed */ int b_index = -1; @@ -5452,7 +5894,13 @@ end_regexp: peek); } } - return lasttok = REGEXP; + if (collecting_typed_regexp) { + collecting_typed_regexp = false; + lasttok = TYPED_REGEXP; + } else + lasttok = REGEXP; + + return lasttok; case '\n': pushback(); yyerror(_("unterminated regexp")); @@ -5488,21 +5936,42 @@ retry: return lasttok = NEWLINE; case '#': /* it's a comment */ - while ((c = nextc(false)) != '\n') { + if (do_pretty_print && ! do_profile) { + /* + * Collect comment byte code iff doing pretty print + * but not profiling. + */ + if (lasttok == NEWLINE || lasttok == 0) + c = get_comment(FULL_COMMENT); + else + c = get_comment(EOL_COMMENT); + if (c == END_FILE) return lasttok = NEWLINE_EOF; + } else { + while ((c = nextc(false)) != '\n') { + if (c == END_FILE) + return lasttok = NEWLINE_EOF; + } } sourceline++; return lasttok = NEWLINE; case '@': + c = nextc(true); + if (c == '/') { + want_regexp = true; + collecting_typed_regexp = true; + goto collect_regexp; + } + pushback(); at_seen = true; return lasttok = '@'; case '\\': #ifdef RELAXED_CONTINUATION /* - * This code puports to allow comments and/or whitespace + * This code purports to allow comments and/or whitespace * after the `\' at the end of a line used for continuation. * Use it at your own risk. We think it's a bad idea, which * is why it's not on by default. @@ -5519,9 +5988,13 @@ retry: lintwarn( _("use of `\\ #...' line continuation is not portable")); } - while ((c = nextc(false)) != '\n') - if (c == END_FILE) - break; + if (do_pretty_print && ! do_profile) + c = get_comment(EOL_COMMENT); + else { + while ((c = nextc(false)) != '\n') + if (c == END_FILE) + break; + } } pushback(); } @@ -5737,7 +6210,7 @@ retry: lastline = sourceline; return lasttok = c; } - did_newline++; + did_newline = true; --lexptr; /* pick up } next time */ return lasttok = NEWLINE; @@ -5949,7 +6422,7 @@ retry: } #endif if (base != 10) - d = nondec2awknum(tokstart, strlen(tokstart)); + d = nondec2awknum(tokstart, strlen(tokstart), NULL); else d = atof(tokstart); yylval->memory = make_number(d); @@ -6035,6 +6508,33 @@ retry: && lasttok != '@') goto out; + /* allow parameter names to shadow the names of gawk extension built-ins */ + if ((tokentab[mid].flags & GAWKX) != 0) { + NODE *f; + + switch (want_param_names) { + case FUNC_HEADER: + /* in header, defining parameter names */ + goto out; + case FUNC_BODY: + /* in body, name must be in symbol table for it to be a parameter */ + if ((f = lookup(tokstart)) != NULL) { + if (f->type == Node_builtin_func) + break; + else + goto out; + } + /* else + fall through */ + case DONT_CHECK: + /* regular code */ + break; + default: + cant_happen(); + break; + } + } + if (do_lint) { if ((tokentab[mid].flags & GAWKX) != 0 && (warntab[mid] & GAWKX) == 0) { lintwarn(_("`%s' is a gawk extension"), @@ -6294,7 +6794,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) } #ifdef HAVE_MPFR - /* N.B.: There isn't any special processing for an alternate function below */ + /* N.B.: If necessary, add special processing for alternate builtin, below */ if (do_mpfr && tokentab[idx].ptr2) r->builtin = tokentab[idx].ptr2; else @@ -6319,10 +6819,19 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push) arg->nexti->opcode = Op_push_arg; /* argument may be array */ } - } else if (r->builtin == do_isarray) { + } else if (r->builtin == do_isarray || r->builtin == do_typeof) { arg = subn->nexti; if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push) - arg->nexti->opcode = Op_push_arg; /* argument may be array */ + arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */ + } else if (r->builtin == do_intdiv +#ifdef HAVE_MPFR + || r->builtin == MPF(intdiv) +#endif + ) { + arg = subn->nexti->lasti->nexti->lasti->nexti; /* 3rd arg list */ + ip = arg->lasti; + if (ip->opcode == Op_push) + ip->opcode = Op_push_array; } else if (r->builtin == do_match) { static bool warned = false; @@ -6399,7 +6908,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) } else if (do_intl /* --gen-po */ && r->builtin == do_dcgettext /* dcgettext(...) */ && subn->nexti->lasti->opcode == Op_push_i /* 1st arg is constant */ - && (subn->nexti->lasti->memory->flags & STRCUR) != 0) { /* it's a string constant */ + && (subn->nexti->lasti->memory->flags & STRING) != 0) { /* it's a string constant */ /* ala xgettext, dcgettext("some string" ...) dumps the string */ NODE *str = subn->nexti->lasti->memory; @@ -6411,9 +6920,9 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) } else if (do_intl /* --gen-po */ && r->builtin == do_dcngettext /* dcngettext(...) */ && subn->nexti->lasti->opcode == Op_push_i /* 1st arg is constant */ - && (subn->nexti->lasti->memory->flags & STRCUR) != 0 /* it's a string constant */ + && (subn->nexti->lasti->memory->flags & STRING) != 0 /* it's a string constant */ && subn->nexti->lasti->nexti->lasti->opcode == Op_push_i /* 2nd arg is constant too */ - && (subn->nexti->lasti->nexti->lasti->memory->flags & STRCUR) != 0) { /* it's a string constant */ + && (subn->nexti->lasti->nexti->lasti->memory->flags & STRING) != 0) { /* it's a string constant */ /* ala xgettext, dcngettext("some string", "some plural" ...) dumps the string */ NODE *str1 = subn->nexti->lasti->memory; NODE *str2 = subn->nexti->lasti->nexti->lasti->memory; @@ -6508,6 +7017,8 @@ valinfo(NODE *n, Func_print print_func, FILE *fp) { if (n == Nnull_string) print_func(fp, "uninitialized scalar\n"); + else if (n->type == Node_typedregex) + print_func(fp, "@/%.*s/\n", n->re_exp->stlen, n->re_exp->stptr); else if ((n->flags & STRING) != 0) { pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false); print_func(fp, "\n"); @@ -6520,18 +7031,6 @@ valinfo(NODE *n, Func_print print_func, FILE *fp) else #endif print_func(fp, "%.17g\n", n->numbr); - } else if ((n->flags & STRCUR) != 0) { - pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false); - print_func(fp, "\n"); - } else if ((n->flags & NUMCUR) != 0) { -#ifdef HAVE_MPFR - if (is_mpg_float(n)) - print_func(fp, "%s\n", mpg_fmt("%.17R*g", ROUND_MODE, n->mpg_numbr)); - else if (is_mpg_integer(n)) - print_func(fp, "%s\n", mpg_fmt("%Zd", n->mpg_i)); - else -#endif - print_func(fp, "%.17g\n", n->numbr); } else print_func(fp, "?? flags %s\n", flags2str(n->flags)); } @@ -6620,6 +7119,14 @@ mk_function(INSTRUCTION *fi, INSTRUCTION *def) (t + 1)->tail_call = true; } + /* add any pre-function comment to start of action for profile.c */ + + if (function_comment != NULL) { + function_comment->source_line = 0; + (void) list_prepend(def, function_comment); + function_comment = NULL; + } + /* add an implicit return at end; * also used by 'return' command in debugger */ @@ -6886,7 +7393,7 @@ make_regnode(int type, NODE *exp) n->type = type; n->re_cnt = 1; - if (type == Node_regex) { + if (type == Node_regex || type == Node_typedregex) { n->re_reg = make_regexp(exp->stptr, exp->stlen, false, true, false); if (n->re_reg == NULL) { freenode(n); @@ -6894,6 +7401,7 @@ make_regnode(int type, NODE *exp) } n->re_exp = exp; n->re_flags = CONSTANT; + n->valref = 1; } return n; } @@ -6909,6 +7417,8 @@ mk_rexp(INSTRUCTION *list) ip = list->nexti; if (ip == list->lasti && ip->opcode == Op_match_rec) ip->opcode = Op_push_re; + else if (ip == list->lasti && ip->opcode == Op_push_re) + ; /* do nothing --- @/.../ */ else { ip = instruction(Op_push_re); ip->memory = make_regnode(Node_dynregex, NULL); @@ -7324,7 +7834,11 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action) (rp + 1)->lasti = action->lasti; (rp + 2)->first_line = pattern->source_line; (rp + 2)->last_line = lastline; - ip = list_prepend(action, rp); + if (block_comment != NULL) { + ip = list_prepend(list_prepend(action, block_comment), rp); + block_comment = NULL; + } else + ip = list_prepend(action, rp); } else { rp = bcalloc(Op_rule, 3, 0); @@ -7366,7 +7880,6 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action) action), tp); } - } list_append(rule_list, rp + 1); @@ -7936,6 +8449,26 @@ list_merge(INSTRUCTION *l1, INSTRUCTION *l2) return l1; } +/* add_pending_comment --- add a pending comment to a statement */ + +static inline INSTRUCTION * +add_pending_comment(INSTRUCTION *stmt) +{ + INSTRUCTION *ret = stmt; + + if (prior_comment != NULL) { + if (function_comment != prior_comment) + ret = list_append(stmt, prior_comment); + prior_comment = NULL; + } else if (comment != NULL && comment->memory->comment_type == EOL_COMMENT) { + if (function_comment != comment) + ret = list_append(stmt, comment); + comment = NULL; + } + + return ret; +} + /* See if name is a special token. */ int @@ -83,10 +83,17 @@ static void check_funcs(void); static ssize_t read_one_line(int fd, void *buffer, size_t count); static int one_line_close(int fd); +static void split_comment(void); +static void check_comment(void); static bool at_seen = false; static bool want_source = false; static bool want_regexp = false; /* lexical scanning kludge */ +static enum { + FUNC_HEADER, + FUNC_BODY, + DONT_CHECK +} want_param_names = DONT_CHECK; /* ditto */ static char *in_function; /* parsing kludge */ static int rule = 0; @@ -141,11 +148,23 @@ 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 *prior_comment = NULL; +static INSTRUCTION *comment_to_save = NULL; +static INSTRUCTION *program_comment = NULL; +static INSTRUCTION *function_comment = NULL; +static INSTRUCTION *block_comment = NULL; + +static bool func_first = true; +static bool first_rule = true; static inline INSTRUCTION *list_create(INSTRUCTION *x); static inline INSTRUCTION *list_append(INSTRUCTION *l, INSTRUCTION *x); static inline INSTRUCTION *list_prepend(INSTRUCTION *l, INSTRUCTION *x); static inline INSTRUCTION *list_merge(INSTRUCTION *l1, INSTRUCTION *l2); +static inline INSTRUCTION *add_pending_comment(INSTRUCTION *stmt); extern double fmod(double x, double y); @@ -153,7 +172,7 @@ extern double fmod(double x, double y); %} %token FUNC_CALL NAME REGEXP FILENAME -%token YNUMBER YSTRING +%token YNUMBER YSTRING TYPED_REGEXP %token RELOP IO_OUT IO_IN %token ASSIGNOP ASSIGN MATCHOP CONCAT_OP %token SUBSCRIPT @@ -181,7 +200,7 @@ extern double fmod(double x, double y); %left MATCHOP %nonassoc RELOP '<' '>' IO_IN IO_OUT %left CONCAT_OP -%left YSTRING YNUMBER +%left YSTRING YNUMBER TYPED_REGEXP %left '+' '-' %left '*' '/' '%' %right '!' UNARY @@ -218,6 +237,7 @@ rule : pattern action { (void) append_rule($1, $2); + first_rule = false; } | pattern statement_term { @@ -234,6 +254,7 @@ rule { in_function = NULL; (void) mk_function($1, $2); + want_param_names = DONT_CHECK; yyerrok; } | '@' LEX_INCLUDE source statement_term @@ -282,9 +303,24 @@ library pattern : /* empty */ - { $$ = NULL; rule = Rule; } + { + rule = Rule; + if (comment != NULL) { + $$ = list_create(comment); + comment = NULL; + } else + $$ = NULL; + } | exp - { $$ = $1; rule = Rule; } + { + rule = Rule; + if (comment != NULL) { + $$ = list_prepend($1, comment); + comment = NULL; + } else + $$ = $1; + } + | exp ',' opt_nls exp { INSTRUCTION *tp; @@ -308,41 +344,55 @@ pattern ($1->nexti + 1)->condpair_left = $1->lasti; ($1->nexti + 1)->condpair_right = $4->lasti; } - $$ = list_append(list_merge($1, $4), tp); + if (comment != NULL) { + $$ = list_append(list_merge(list_prepend($1, comment), $4), tp); + comment = NULL; + } else + $$ = list_append(list_merge($1, $4), tp); rule = Rule; } | LEX_BEGIN { static int begin_seen = 0; + + func_first = false; if (do_lint_old && ++begin_seen == 2) warning_ln($1->source_line, _("old awk does not support multiple `BEGIN' or `END' rules")); $1->in_rule = rule = BEGIN; $1->source_file = source; + check_comment(); $$ = $1; } | LEX_END { static int end_seen = 0; + + func_first = false; if (do_lint_old && ++end_seen == 2) warning_ln($1->source_line, _("old awk does not support multiple `BEGIN' or `END' rules")); $1->in_rule = rule = END; $1->source_file = source; + check_comment(); $$ = $1; } | LEX_BEGINFILE { + func_first = false; $1->in_rule = rule = BEGINFILE; $1->source_file = source; + check_comment(); $$ = $1; } | LEX_ENDFILE { + func_first = false; $1->in_rule = rule = ENDFILE; $1->source_file = source; + check_comment(); $$ = $1; } ; @@ -350,10 +400,12 @@ pattern action : l_brace statements r_brace opt_semi opt_nls { + INSTRUCTION *ip; if ($2 == NULL) - $$ = list_create(instruction(Op_no_op)); + ip = list_create(instruction(Op_no_op)); else - $$ = $2; + ip = $2; + $$ = ip; } ; @@ -381,16 +433,43 @@ lex_builtin ; function_prologue - : LEX_FUNCTION func_name '(' opt_param_list r_paren opt_nls + : LEX_FUNCTION func_name '(' { want_param_names = FUNC_HEADER; } opt_param_list r_paren opt_nls { + /* + * treat any comments between BOF and the first function + * definition (with no intervening BEGIN etc block) as + * program comments. Special kludge: iff there are more + * than one such comments, treat the last as a function + * comment. + */ + if (prior_comment != NULL) { + comment_to_save = prior_comment; + prior_comment = NULL; + } else if (comment != NULL) { + comment_to_save = comment; + comment = NULL; + } else + comment_to_save = NULL; + + if (comment_to_save != NULL && func_first + && strstr(comment_to_save->memory->stptr, "\n\n") != NULL) + split_comment(); + + /* save any other pre-function comment as function comment */ + if (comment_to_save != NULL) { + function_comment = comment_to_save; + comment_to_save = NULL; + } + func_first = false; $1->source_file = source; - if (install_function($2->lextok, $1, $4) < 0) + if (install_function($2->lextok, $1, $5) < 0) YYABORT; in_function = $2->lextok; $2->lextok = NULL; bcfree($2); - /* $4 already free'd in install_function */ + /* $5 already free'd in install_function */ $$ = $1; + want_param_names = FUNC_BODY; } ; @@ -432,6 +511,28 @@ regexp } ; +typed_regexp + : TYPED_REGEXP + { + NODE *n, *exp; + char *re; + size_t len; + + re = $1->lextok; + $1->lextok = NULL; + len = strlen(re); + + exp = make_str_node(re, len, ALREADY_MALLOCED); + n = make_regnode(Node_typedregex, exp); + if (n == NULL) { + unref(exp); + YYABORT; + } + $$ = $1; + $$->opcode = Op_push_re; + $$->memory = n; + } + a_slash : '/' { bcfree($1); } @@ -440,19 +541,62 @@ a_slash statements : /* empty */ - { $$ = NULL; } + { + if (prior_comment != NULL) { + $$ = list_create(prior_comment); + prior_comment = NULL; + } else if (comment != NULL) { + $$ = list_create(comment); + comment = NULL; + } else + $$ = NULL; + } | statements statement { - if ($2 == NULL) - $$ = $1; - else { + if ($2 == NULL) { + if (prior_comment != NULL) { + $$ = list_append($1, prior_comment); + prior_comment = NULL; + if (comment != NULL) { + $$ = list_append($$, comment); + comment = NULL; + } + } else if (comment != NULL) { + $$ = list_append($1, comment); + comment = NULL; + } else + $$ = $1; + } else { add_lint($2, LINT_no_effect); - if ($1 == NULL) - $$ = $2; - else + if ($1 == NULL) { + if (prior_comment != NULL) { + $$ = list_append($2, prior_comment); + prior_comment = NULL; + if (comment != NULL) { + $$ = list_append($$, comment); + comment = NULL; + } + } else if (comment != NULL) { + $$ = list_append($2, comment); + comment = NULL; + } else + $$ = $2; + } else { + if (prior_comment != NULL) { + list_append($2, prior_comment); + prior_comment = NULL; + if (comment != NULL) { + list_append($2, comment); + comment = NULL; + } + } else if (comment != NULL) { + list_append($2, comment); + comment = NULL; + } $$ = list_merge($1, $2); + } } - yyerrok; + yyerrok; } | statements error { $$ = NULL; } @@ -496,7 +640,7 @@ statement } /* else curr = NULL; */ - for(; curr != NULL; curr = nextc) { + for (; curr != NULL; curr = nextc) { INSTRUCTION *caseexp = curr->case_exp; INSTRUCTION *casestmt = curr->case_stmt; @@ -782,6 +926,7 @@ regular_loop: $$ = list_prepend($1, instruction(Op_exec_count)); else $$ = $1; + $$ = add_pending_comment($$); } ; @@ -793,6 +938,7 @@ non_compound_stmt _("`break' is not allowed outside a loop or switch")); $1->target_jmp = NULL; $$ = list_create($1); + $$ = add_pending_comment($$); } | LEX_CONTINUE statement_term @@ -802,6 +948,7 @@ non_compound_stmt _("`continue' is not allowed outside a loop")); $1->target_jmp = NULL; $$ = list_create($1); + $$ = add_pending_comment($$); } | LEX_NEXT statement_term @@ -812,6 +959,7 @@ non_compound_stmt _("`next' used in %s action"), ruletab[rule]); $1->target_jmp = ip_rec; $$ = list_create($1); + $$ = add_pending_comment($$); } | LEX_NEXTFILE statement_term { @@ -823,6 +971,7 @@ non_compound_stmt $1->target_newfile = ip_newfile; $1->target_endfile = ip_endfile; $$ = list_create($1); + $$ = add_pending_comment($$); } | LEX_EXIT opt_exp statement_term { @@ -838,6 +987,7 @@ non_compound_stmt $$->nexti->memory = dupnode(Nnull_string); } else $$ = list_append($2, $1); + $$ = add_pending_comment($$); } | LEX_RETURN { @@ -862,6 +1012,7 @@ non_compound_stmt $$ = list_append($3, $1); } + $$ = add_pending_comment($$); } | simple_stmt statement_term ; @@ -971,6 +1122,7 @@ regular_print: } } } + $$ = add_pending_comment($$); } | LEX_DELETE NAME { sub_counter = 0; } delete_subscript_list @@ -1005,6 +1157,7 @@ regular_print: $1->expr_count = sub_counter; $$ = list_append(list_append($4, $2), $1); } + $$ = add_pending_comment($$); } | LEX_DELETE '(' NAME ')' /* @@ -1035,9 +1188,13 @@ regular_print: else if ($3->memory == func_table) fatal(_("`delete' is not allowed with FUNCTAB")); } + $$ = add_pending_comment($$); } | exp - { $$ = optimize_assignment($1); } + { + $$ = optimize_assignment($1); + $$ = add_pending_comment($$); + } ; opt_simple_stmt @@ -1107,6 +1264,15 @@ case_value { $$ = $1; } | regexp { + if ($1->memory->type == Node_regex) + $1->opcode = Op_push_re; + else + $1->opcode = Op_push; + $$ = $1; + } + | typed_regexp + { + assert($1->memory->type == Node_typedregex); $1->opcode = Op_push_re; $$ = $1; } @@ -1184,7 +1350,7 @@ opt_param_list : /* empty */ { $$ = NULL; } | param_list - { $$ = $1 ; } + { $$ = $1; } ; param_list @@ -1255,6 +1421,48 @@ expression_list } ; +opt_fcall_expression_list + : /* empty */ + { $$ = NULL; } + | fcall_expression_list + { $$ = $1; } + ; + +fcall_expression_list + : fcall_exp + { $$ = mk_expression_list(NULL, $1); } + | fcall_expression_list comma fcall_exp + { + $$ = mk_expression_list($1, $3); + yyerrok; + } + | error + { $$ = NULL; } + | fcall_expression_list error + { + /* + * Returning the expression list instead of NULL lets + * snode get a list of arguments that it can count. + */ + $$ = $1; + } + | fcall_expression_list error fcall_exp + { + /* Ditto */ + $$ = mk_expression_list($1, $3); + } + | fcall_expression_list comma error + { + /* Ditto */ + $$ = $1; + } + ; + +fcall_exp + : exp { $$ = $1; } + | typed_regexp { $$ = list_create($1); } + ; + /* Expressions, not including the comma operator. */ exp : variable assign_operator exp %prec ASSIGNOP @@ -1264,10 +1472,27 @@ exp _("regular expression on right of assignment")); $$ = mk_assignment($1, $3, $2); } + | variable ASSIGN typed_regexp %prec ASSIGNOP + { + $$ = mk_assignment($1, list_create($3), $2); + } | exp LEX_AND exp { $$ = mk_boolean($1, $3, $2); } | exp LEX_OR exp { $$ = mk_boolean($1, $3, $2); } + | exp MATCHOP typed_regexp + { + if ($1->lasti->opcode == Op_match_rec) + warning_ln($2->source_line, + _("regular expression on left of `~' or `!~' operator")); + + assert($3->opcode == Op_push_re + && $3->memory->type == Node_typedregex); + /* RHS is @/.../ */ + $2->memory = $3->memory; + bcfree($3); + $$ = list_append($1, $2); + } | exp MATCHOP exp { if ($1->lasti->opcode == Op_match_rec) @@ -1275,6 +1500,7 @@ exp _("regular expression on left of `~' or `!~' operator")); if ($3->lasti == $3->nexti && $3->nexti->opcode == Op_match_rec) { + /* RHS is /.../ */ $2->memory = $3->nexti->memory; bcfree($3->nexti); /* Op_match_rec */ bcfree($3); /* Op_list */ @@ -1364,10 +1590,15 @@ common_exp NODE *n2 = $2->nexti->memory; size_t nlen; + // 1.5 "" # can't fold this if program mucks with CONVFMT. + // See test #12 in test/posix.awk. + if ((n1->flags & (NUMBER|NUMINT)) != 0 || (n2->flags & (NUMBER|NUMINT)) != 0) + goto plain_concat; + n1 = force_string(n1); n2 = force_string(n2); nlen = n1->stlen + n2->stlen; - erealloc(n1->stptr, char *, nlen + 2, "constant fold"); + erealloc(n1->stptr, char *, nlen + 1, "constant fold"); memcpy(n1->stptr + n1->stlen, n2->stptr, n2->stlen); n1->stlen = nlen; n1->stptr[nlen] = '\0'; @@ -1378,6 +1609,7 @@ common_exp bcfree($2); $$ = $1; } else { + plain_concat: $$ = list_append(list_merge($1, $2), instruction(Op_concat)); $$->lasti->concat_flag = (is_simple_var ? CSVAR : 0); $$->lasti->expr_count = count; @@ -1490,7 +1722,7 @@ non_post_simp_exp && ($2->nexti->memory->flags & (MPFN|MPZN)) == 0 ) { NODE *n = $2->nexti->memory; - if ((n->flags & (STRCUR|STRING)) != 0) { + if ((n->flags & STRING) != 0) { n->numbr = (AWKNUM) (n->stlen == 0); n->flags &= ~(STRCUR|STRING); n->flags |= (NUMCUR|NUMBER); @@ -1510,13 +1742,13 @@ non_post_simp_exp } | '(' exp r_paren { $$ = $2; } - | LEX_BUILTIN '(' opt_expression_list r_paren + | LEX_BUILTIN '(' opt_fcall_expression_list r_paren { $$ = snode($3, $1); if ($$ == NULL) YYABORT; } - | LEX_LENGTH '(' opt_expression_list r_paren + | LEX_LENGTH '(' opt_fcall_expression_list r_paren { $$ = snode($3, $1); if ($$ == NULL) @@ -1558,7 +1790,7 @@ non_post_simp_exp | '-' simp_exp %prec UNARY { if ($2->lasti->opcode == Op_push_i - && ($2->lasti->memory->flags & (STRCUR|STRING)) == 0 + && ($2->lasti->memory->flags & STRING) == 0 ) { NODE *n = $2->lasti->memory; (void) force_number(n); @@ -1625,14 +1857,14 @@ func_call ; direct_func_call - : FUNC_CALL '(' opt_expression_list r_paren + : FUNC_CALL '(' opt_fcall_expression_list r_paren { NODE *n; if (! at_seen) { n = lookup($1->func_name); if (n != NULL && n->type != Node_func - && n->type != Node_ext_func && n->type != Node_old_ext_func) { + && n->type != Node_ext_func) { error_ln($1->source_line, _("attempt to use non-function `%s' in function call"), $1->func_name); @@ -1878,9 +2110,6 @@ static const struct token tokentab[] = { {"eval", Op_symbol, LEX_EVAL, 0, 0, 0}, {"exit", Op_K_exit, LEX_EXIT, 0, 0, 0}, {"exp", Op_builtin, LEX_BUILTIN, A(1), do_exp, MPF(exp)}, -#ifdef DYNAMIC -{"extension", Op_builtin, LEX_BUILTIN, GAWKX|A(1)|A(2)|A(3), do_ext, 0}, -#endif {"fflush", Op_builtin, LEX_BUILTIN, A(0)|A(1), do_fflush, 0}, {"for", Op_K_for, LEX_FOR, BREAK|CONTINUE, 0, 0}, {"func", Op_func, LEX_FUNCTION, NOT_POSIX|NOT_OLD, 0, 0}, @@ -1893,6 +2122,7 @@ static const struct token tokentab[] = { {"include", Op_symbol, LEX_INCLUDE, GAWKX, 0, 0}, {"index", Op_builtin, LEX_BUILTIN, A(2), do_index, 0}, {"int", Op_builtin, LEX_BUILTIN, A(1), do_int, MPF(int)}, +{"intdiv", Op_builtin, LEX_BUILTIN, GAWKX|A(3), do_intdiv, MPF(intdiv)}, {"isarray", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_isarray, 0}, {"length", Op_builtin, LEX_LENGTH, A(0)|A(1), do_length, 0}, {"load", Op_symbol, LEX_LOAD, GAWKX, 0, 0}, @@ -1926,6 +2156,7 @@ static const struct token tokentab[] = { {"systime", Op_builtin, LEX_BUILTIN, GAWKX|A(0), do_systime, 0}, {"tolower", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_tolower, 0}, {"toupper", Op_builtin, LEX_BUILTIN, NOT_OLD|A(1), do_toupper, 0}, +{"typeof", Op_builtin, LEX_BUILTIN, GAWKX|A(1), do_typeof, 0}, {"while", Op_K_while, LEX_WHILE, BREAK|CONTINUE, 0, 0}, {"xor", Op_builtin, LEX_BUILTIN, GAWKX, do_xor, MPF(xor)}, }; @@ -2101,7 +2332,6 @@ yyerror(const char *m, ...) char *buf; int count; static char end_of_file_line[] = "(END OF FILE)"; - char save; print_included_from(); @@ -2132,25 +2362,17 @@ yyerror(const char *m, ...) bp = thisline + strlen(thisline); } - /* - * Saving and restoring *bp keeps valgrind happy, - * since the guts of glibc uses strlen, even though - * we're passing an explict precision. Sigh. - * - * 8/2003: We may not need this anymore. - */ - save = *bp; - *bp = '\0'; - msg("%.*s", (int) (bp - thisline), thisline); - *bp = save; va_start(args, m); if (mesg == NULL) mesg = m; - count = (bp - thisline) + strlen(mesg) + 2 + 1; - emalloc(buf, char *, count, "yyerror"); + count = strlen(mesg) + 1; + if (lexptr != NULL) + count += (lexeme - thisline) + 2; + emalloc(buf, char *, count+1, "yyerror"); + memset(buf, 0, count+1); bp = buf; @@ -2232,6 +2454,11 @@ mk_program() cp = end_block; else cp = list_merge(begin_block, end_block); + if (program_comment != NULL) { + (void) list_prepend(cp, program_comment); + } + if (comment != NULL) + (void) list_append(cp, comment); (void) list_append(cp, ip_atexit); (void) list_append(cp, instruction(Op_stop)); @@ -2264,6 +2491,12 @@ mk_program() if (begin_block != NULL) cp = list_merge(begin_block, cp); + if (program_comment != NULL) { + (void) list_prepend(cp, program_comment); + } + if (comment != NULL) { + (void) list_append(cp, comment); + } (void) list_append(cp, ip_atexit); (void) list_append(cp, instruction(Op_stop)); @@ -2271,6 +2504,10 @@ out: /* delete the Op_list, not needed */ tmp = cp->nexti; bcfree(cp); + /* these variables are not used again but zap them anyway. */ + comment = NULL; + function_comment = NULL; + program_comment = NULL; return tmp; #undef begin_block @@ -2297,7 +2534,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; @@ -2768,7 +3005,7 @@ get_src_buf() lexend = lexptr + n; if (n == 0) { static bool warned = false; - if (do_lint && newfile && ! warned){ + if (do_lint && newfile && ! warned) { warned = true; sourceline = 0; lintwarn(_("source file `%s' is empty"), source); @@ -2859,7 +3096,7 @@ again: mbstate_t tmp_state; size_t mbclen; - for (idx = 0 ; lexptr + idx < lexend ; idx++) { + for (idx = 0; lexptr + idx < lexend; idx++) { tmp_state = cur_mbstate; mbclen = mbrlen(lexptr, idx + 1, &tmp_state); @@ -2916,6 +3153,122 @@ pushback(void) (! lexeof && lexptr && lexptr > lexptr_begin ? lexptr-- : lexptr); } +/* check_comment --- check for block comment */ + +void +check_comment(void) +{ + if (comment != NULL) { + if (first_rule) { + program_comment = comment; + } else + block_comment = comment; + comment = NULL; + } + first_rule = false; +} + +/* + * get_comment --- collect comment text. + * Flag = EOL_COMMENT for end-of-line comments. + * Flag = FULL_COMMENT for self-contained comments. + */ + +int +get_comment(int flag) +{ + int c; + int sl; + tok = tokstart; + tokadd('#'); + sl = sourceline; + char *p1; + char *p2; + + while (true) { + while ((c = nextc(false)) != '\n' && c != END_FILE) { + /* ignore \r characters */ + if (c != '\r') + tokadd(c); + } + if (flag == EOL_COMMENT) { + /* comment at end of line. */ + if (c == '\n') + tokadd(c); + break; + } + if (c == '\n') { + tokadd(c); + sourceline++; + do { + c = nextc(false); + if (c == '\n') { + sourceline++; + tokadd(c); + } + } while (isspace(c) && c != END_FILE); + if (c == END_FILE) + break; + else if (c != '#') { + pushback(); + sourceline--; + break; + } else + tokadd(c); + } else + break; + } + + if (comment != NULL) + prior_comment = comment; + + /* remove any trailing blank lines (consecutive \n) from comment */ + p1 = tok - 1; + p2 = tok - 2; + while (*p1 == '\n' && *p2 == '\n') { + p1--; + p2--; + tok--; + } + + comment = bcalloc(Op_comment, 1, sl); + comment->source_file = source; + comment->memory = make_str_node(tokstart, tok - tokstart, 0); + comment->memory->comment_type = flag; + + return c; +} + +/* split_comment --- split initial comment text into program and function parts */ + +static void +split_comment(void) +{ + char *p; + int l; + NODE *n; + + p = comment_to_save->memory->stptr; + l = comment_to_save->memory->stlen - 3; + /* have at least two comments so split at last blank line (\n\n) */ + while (l >= 0) { + if (p[l] == '\n' && p[l+1] == '\n') { + function_comment = comment_to_save; + n = function_comment->memory; + function_comment->memory = make_str_node(p + l + 2, n->stlen - l - 2, 0); + /* create program comment */ + program_comment = bcalloc(Op_comment, 1, sourceline); + program_comment->source_file = comment_to_save->source_file; + p[l + 2] = 0; + program_comment->memory = make_str_node(p, l + 2, 0); + comment_to_save = NULL; + freenode(n); + break; + } + else + l--; + } +} /* allow_newline --- allow newline after &&, ||, ? and : */ @@ -2931,8 +3284,13 @@ allow_newline(void) break; } if (c == '#') { - while ((c = nextc(false)) != '\n' && c != END_FILE) - continue; + if (do_pretty_print && ! do_profile) { + /* collect comment byte code iff doing pretty print but not profiling. */ + c = get_comment(EOL_COMMENT); + } else { + while ((c = nextc(false)) != '\n' && c != END_FILE) + continue; + } if (c == END_FILE) { pushback(); break; @@ -2955,7 +3313,8 @@ allow_newline(void) * removes the warnings. */ -static int newline_eof() +static int +newline_eof() { /* NB: a newline at end does not start a source line. */ if (lasttok != NEWLINE) { @@ -2993,6 +3352,7 @@ yylex(void) bool inhex = false; bool intlstr = false; AWKNUM d; + bool collecting_typed_regexp = false; #define GET_INSTRUCTION(op) bcalloc(op, 1, sourceline) @@ -3027,6 +3387,7 @@ yylex(void) lexeme = lexptr; thisline = NULL; +collect_regexp: if (want_regexp) { int in_brack = 0; /* count brackets, [[:alnum:]] allowed */ int b_index = -1; @@ -3113,7 +3474,13 @@ end_regexp: peek); } } - return lasttok = REGEXP; + if (collecting_typed_regexp) { + collecting_typed_regexp = false; + lasttok = TYPED_REGEXP; + } else + lasttok = REGEXP; + + return lasttok; case '\n': pushback(); yyerror(_("unterminated regexp")); @@ -3149,21 +3516,42 @@ retry: return lasttok = NEWLINE; case '#': /* it's a comment */ - while ((c = nextc(false)) != '\n') { + if (do_pretty_print && ! do_profile) { + /* + * Collect comment byte code iff doing pretty print + * but not profiling. + */ + if (lasttok == NEWLINE || lasttok == 0) + c = get_comment(FULL_COMMENT); + else + c = get_comment(EOL_COMMENT); + if (c == END_FILE) return lasttok = NEWLINE_EOF; + } else { + while ((c = nextc(false)) != '\n') { + if (c == END_FILE) + return lasttok = NEWLINE_EOF; + } } sourceline++; return lasttok = NEWLINE; case '@': + c = nextc(true); + if (c == '/') { + want_regexp = true; + collecting_typed_regexp = true; + goto collect_regexp; + } + pushback(); at_seen = true; return lasttok = '@'; case '\\': #ifdef RELAXED_CONTINUATION /* - * This code puports to allow comments and/or whitespace + * This code purports to allow comments and/or whitespace * after the `\' at the end of a line used for continuation. * Use it at your own risk. We think it's a bad idea, which * is why it's not on by default. @@ -3180,9 +3568,13 @@ retry: lintwarn( _("use of `\\ #...' line continuation is not portable")); } - while ((c = nextc(false)) != '\n') - if (c == END_FILE) - break; + if (do_pretty_print && ! do_profile) + c = get_comment(EOL_COMMENT); + else { + while ((c = nextc(false)) != '\n') + if (c == END_FILE) + break; + } } pushback(); } @@ -3398,7 +3790,7 @@ retry: lastline = sourceline; return lasttok = c; } - did_newline++; + did_newline = true; --lexptr; /* pick up } next time */ return lasttok = NEWLINE; @@ -3610,7 +4002,7 @@ retry: } #endif if (base != 10) - d = nondec2awknum(tokstart, strlen(tokstart)); + d = nondec2awknum(tokstart, strlen(tokstart), NULL); else d = atof(tokstart); yylval->memory = make_number(d); @@ -3696,6 +4088,33 @@ retry: && lasttok != '@') goto out; + /* allow parameter names to shadow the names of gawk extension built-ins */ + if ((tokentab[mid].flags & GAWKX) != 0) { + NODE *f; + + switch (want_param_names) { + case FUNC_HEADER: + /* in header, defining parameter names */ + goto out; + case FUNC_BODY: + /* in body, name must be in symbol table for it to be a parameter */ + if ((f = lookup(tokstart)) != NULL) { + if (f->type == Node_builtin_func) + break; + else + goto out; + } + /* else + fall through */ + case DONT_CHECK: + /* regular code */ + break; + default: + cant_happen(); + break; + } + } + if (do_lint) { if ((tokentab[mid].flags & GAWKX) != 0 && (warntab[mid] & GAWKX) == 0) { lintwarn(_("`%s' is a gawk extension"), @@ -3955,7 +4374,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) } #ifdef HAVE_MPFR - /* N.B.: There isn't any special processing for an alternate function below */ + /* N.B.: If necessary, add special processing for alternate builtin, below */ if (do_mpfr && tokentab[idx].ptr2) r->builtin = tokentab[idx].ptr2; else @@ -3980,10 +4399,19 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push) arg->nexti->opcode = Op_push_arg; /* argument may be array */ } - } else if (r->builtin == do_isarray) { + } else if (r->builtin == do_isarray || r->builtin == do_typeof) { arg = subn->nexti; if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push) - arg->nexti->opcode = Op_push_arg; /* argument may be array */ + arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */ + } else if (r->builtin == do_intdiv +#ifdef HAVE_MPFR + || r->builtin == MPF(intdiv) +#endif + ) { + arg = subn->nexti->lasti->nexti->lasti->nexti; /* 3rd arg list */ + ip = arg->lasti; + if (ip->opcode == Op_push) + ip->opcode = Op_push_array; } else if (r->builtin == do_match) { static bool warned = false; @@ -4060,7 +4488,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) } else if (do_intl /* --gen-po */ && r->builtin == do_dcgettext /* dcgettext(...) */ && subn->nexti->lasti->opcode == Op_push_i /* 1st arg is constant */ - && (subn->nexti->lasti->memory->flags & STRCUR) != 0) { /* it's a string constant */ + && (subn->nexti->lasti->memory->flags & STRING) != 0) { /* it's a string constant */ /* ala xgettext, dcgettext("some string" ...) dumps the string */ NODE *str = subn->nexti->lasti->memory; @@ -4072,9 +4500,9 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) } else if (do_intl /* --gen-po */ && r->builtin == do_dcngettext /* dcngettext(...) */ && subn->nexti->lasti->opcode == Op_push_i /* 1st arg is constant */ - && (subn->nexti->lasti->memory->flags & STRCUR) != 0 /* it's a string constant */ + && (subn->nexti->lasti->memory->flags & STRING) != 0 /* it's a string constant */ && subn->nexti->lasti->nexti->lasti->opcode == Op_push_i /* 2nd arg is constant too */ - && (subn->nexti->lasti->nexti->lasti->memory->flags & STRCUR) != 0) { /* it's a string constant */ + && (subn->nexti->lasti->nexti->lasti->memory->flags & STRING) != 0) { /* it's a string constant */ /* ala xgettext, dcngettext("some string", "some plural" ...) dumps the string */ NODE *str1 = subn->nexti->lasti->memory; NODE *str2 = subn->nexti->lasti->nexti->lasti->memory; @@ -4169,6 +4597,8 @@ valinfo(NODE *n, Func_print print_func, FILE *fp) { if (n == Nnull_string) print_func(fp, "uninitialized scalar\n"); + else if (n->type == Node_typedregex) + print_func(fp, "@/%.*s/\n", n->re_exp->stlen, n->re_exp->stptr); else if ((n->flags & STRING) != 0) { pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false); print_func(fp, "\n"); @@ -4181,18 +4611,6 @@ valinfo(NODE *n, Func_print print_func, FILE *fp) else #endif print_func(fp, "%.17g\n", n->numbr); - } else if ((n->flags & STRCUR) != 0) { - pp_string_fp(print_func, fp, n->stptr, n->stlen, '"', false); - print_func(fp, "\n"); - } else if ((n->flags & NUMCUR) != 0) { -#ifdef HAVE_MPFR - if (is_mpg_float(n)) - print_func(fp, "%s\n", mpg_fmt("%.17R*g", ROUND_MODE, n->mpg_numbr)); - else if (is_mpg_integer(n)) - print_func(fp, "%s\n", mpg_fmt("%Zd", n->mpg_i)); - else -#endif - print_func(fp, "%.17g\n", n->numbr); } else print_func(fp, "?? flags %s\n", flags2str(n->flags)); } @@ -4281,6 +4699,14 @@ mk_function(INSTRUCTION *fi, INSTRUCTION *def) (t + 1)->tail_call = true; } + /* add any pre-function comment to start of action for profile.c */ + + if (function_comment != NULL) { + function_comment->source_line = 0; + (void) list_prepend(def, function_comment); + function_comment = NULL; + } + /* add an implicit return at end; * also used by 'return' command in debugger */ @@ -4547,7 +4973,7 @@ make_regnode(int type, NODE *exp) n->type = type; n->re_cnt = 1; - if (type == Node_regex) { + if (type == Node_regex || type == Node_typedregex) { n->re_reg = make_regexp(exp->stptr, exp->stlen, false, true, false); if (n->re_reg == NULL) { freenode(n); @@ -4555,6 +4981,7 @@ make_regnode(int type, NODE *exp) } n->re_exp = exp; n->re_flags = CONSTANT; + n->valref = 1; } return n; } @@ -4570,6 +4997,8 @@ mk_rexp(INSTRUCTION *list) ip = list->nexti; if (ip == list->lasti && ip->opcode == Op_match_rec) ip->opcode = Op_push_re; + else if (ip == list->lasti && ip->opcode == Op_push_re) + ; /* do nothing --- @/.../ */ else { ip = instruction(Op_push_re); ip->memory = make_regnode(Node_dynregex, NULL); @@ -4985,7 +5414,11 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action) (rp + 1)->lasti = action->lasti; (rp + 2)->first_line = pattern->source_line; (rp + 2)->last_line = lastline; - ip = list_prepend(action, rp); + if (block_comment != NULL) { + ip = list_prepend(list_prepend(action, block_comment), rp); + block_comment = NULL; + } else + ip = list_prepend(action, rp); } else { rp = bcalloc(Op_rule, 3, 0); @@ -5027,7 +5460,6 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action) action), tp); } - } list_append(rule_list, rp + 1); @@ -5597,6 +6029,26 @@ list_merge(INSTRUCTION *l1, INSTRUCTION *l2) return l1; } +/* add_pending_comment --- add a pending comment to a statement */ + +static inline INSTRUCTION * +add_pending_comment(INSTRUCTION *stmt) +{ + INSTRUCTION *ret = stmt; + + if (prior_comment != NULL) { + if (function_comment != prior_comment) + ret = list_append(stmt, prior_comment); + prior_comment = NULL; + } else if (comment != NULL && comment->memory->comment_type == EOL_COMMENT) { + if (function_comment != comment) + ret = list_append(stmt, comment); + comment = NULL; + } + + return ret; +} + /* See if name is a special token. */ int diff --git a/awklib/Makefile.am b/awklib/Makefile.am index 73f91f05..902c1937 100644 --- a/awklib/Makefile.am +++ b/awklib/Makefile.am @@ -39,7 +39,6 @@ AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) pkgdatadir = $(datadir)/awk pkglibexecdir = $(libexecdir)/awk -bin_SCRIPTS = igawk pkglibexec_PROGRAMS = pwcat grcat AUXAWK = passwd.awk group.awk nodist_grcat_SOURCES = grcat.c @@ -47,7 +46,7 @@ nodist_pwcat_SOURCES = pwcat.c CLEANFILES = $(nodist_grcat_SOURCES) $(nodist_pwcat_SOURCES) -all: $(srcdir)/stamp-eg $(AUXPROGS) igawk $(AUXAWK) +all: $(srcdir)/stamp-eg $(AUXPROGS) $(AUXAWK) install-exec-hook: $(AUXAWK) $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) @@ -59,10 +58,9 @@ install-exec-hook: $(AUXAWK) # pkglibexecdir and pkgdatadir are removed in the top level Makefile's uninstall uninstall-local: rm -fr $(DESTDIR)$(pkglibexecdir)/* $(DESTDIR)$(pkgdatadir)/* - rm -f $(DESTDIR)$(bindir)/igawk clean-local: - rm -f $(AUXAWK) igawk *.exe + rm -f $(AUXAWK) *.exe rm -fr eg.old rm -fr grcat.dSYM pwcat.dSYM @@ -85,9 +83,6 @@ grcat.c: $(srcdir)/eg/lib/grcat.c $(srcdir)/eg/lib/pwcat.c $(srcdir)/eg/lib/grcat.c $(srcdir)/eg/prog/igawk.sh \ $(srcdir)/eg/lib/passwdawk.in $(srcdir)/eg/lib/groupawk.in: stamp-eg; @: -igawk: $(srcdir)/eg/prog/igawk.sh - cp $(srcdir)/eg/prog/igawk.sh $@ ; chmod 755 $@ - passwd.awk: $(srcdir)/eg/lib/passwdawk.in sed 's;/usr/local/libexec/awk;$(pkglibexecdir);' < $(srcdir)/eg/lib/passwdawk.in > passwd.awk diff --git a/awklib/Makefile.in b/awklib/Makefile.in index b96dbe1b..597ba20b 100644 --- a/awklib/Makefile.in +++ b/awklib/Makefile.in @@ -37,7 +37,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # - VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ @@ -116,14 +115,14 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/arch.m4 \ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ - $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lcmessage.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \ - $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/mpfr.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/noreturn.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/socket.m4 \ - $(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/mpfr.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/noreturn.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \ + $(top_srcdir)/m4/socket.m4 $(top_srcdir)/m4/ulonglong.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) @@ -131,7 +130,7 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -am__installdirs = "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(bindir)" +am__installdirs = "$(DESTDIR)$(pkglibexecdir)" PROGRAMS = $(pkglibexec_PROGRAMS) nodist_grcat_OBJECTS = grcat.$(OBJEXT) grcat_OBJECTS = $(nodist_grcat_OBJECTS) @@ -139,34 +138,6 @@ grcat_LDADD = $(LDADD) nodist_pwcat_OBJECTS = pwcat.$(OBJEXT) pwcat_OBJECTS = $(nodist_pwcat_OBJECTS) pwcat_LDADD = $(LDADD) -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -SCRIPTS = $(bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -361,7 +332,6 @@ EXTRA_DIST = ChangeLog ChangeLog.0 extract.awk eg $(srcdir)/stamp-eg # Get config.h from the build directory and custom.h from the source directory. AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -bin_SCRIPTS = igawk AUXAWK = passwd.awk group.awk nodist_grcat_SOURCES = grcat.c nodist_pwcat_SOURCES = pwcat.c @@ -449,41 +419,6 @@ grcat$(EXEEXT): $(grcat_OBJECTS) $(grcat_DEPENDENCIES) $(EXTRA_grcat_DEPENDENCIE pwcat$(EXEEXT): $(pwcat_OBJECTS) $(pwcat_DEPENDENCIES) $(EXTRA_pwcat_DEPENDENCIES) @rm -f pwcat$(EXEEXT) $(AM_V_CCLD)$(LINK) $(pwcat_OBJECTS) $(pwcat_LDADD) $(LIBS) -install-binSCRIPTS: $(bin_SCRIPTS) - @$(NORMAL_INSTALL) - @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ - done | \ - sed -e 'p;s,.*/,,;n' \ - -e 'h;s|.*|.|' \ - -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ - $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ - { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ - if ($$2 == $$4) { files[d] = files[d] " " $$1; \ - if (++n[d] == $(am__install_max)) { \ - print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ - else { print "f", d "/" $$4, $$1 } } \ - END { for (d in files) print "f", d, files[d] }' | \ - while read type dir files; do \ - if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ - test -z "$$files" || { \ - echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ - $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ - } \ - ; done - -uninstall-binSCRIPTS: - @$(NORMAL_UNINSTALL) - @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ - files=`for p in $$list; do echo "$$p"; done | \ - sed -e 's,.*/,,;$(transform)'`; \ - dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -592,9 +527,9 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile $(PROGRAMS) $(SCRIPTS) +all-am: Makefile $(PROGRAMS) installdirs: - for dir in "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(bindir)"; do \ + for dir in "$(DESTDIR)$(pkglibexecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -657,7 +592,7 @@ install-dvi: install-dvi-am install-dvi-am: -install-exec-am: install-binSCRIPTS install-pkglibexecPROGRAMS +install-exec-am: install-pkglibexecPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am @@ -697,8 +632,7 @@ ps: ps-am ps-am: -uninstall-am: uninstall-binSCRIPTS uninstall-local \ - uninstall-pkglibexecPROGRAMS +uninstall-am: uninstall-local uninstall-pkglibexecPROGRAMS .MAKE: install-am install-exec-am install-strip @@ -706,22 +640,21 @@ uninstall-am: uninstall-binSCRIPTS uninstall-local \ clean-local clean-pkglibexecPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-binSCRIPTS install-data \ - install-data-am install-dvi install-dvi-am install-exec \ - install-exec-am install-exec-hook install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-pkglibexecPROGRAMS install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ - ps ps-am tags tags-am uninstall uninstall-am \ - uninstall-binSCRIPTS uninstall-local \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-exec-hook \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am \ + install-pkglibexecPROGRAMS install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-local \ uninstall-pkglibexecPROGRAMS .PRECIOUS: Makefile -all: $(srcdir)/stamp-eg $(AUXPROGS) igawk $(AUXAWK) +all: $(srcdir)/stamp-eg $(AUXPROGS) $(AUXAWK) install-exec-hook: $(AUXAWK) $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) @@ -733,10 +666,9 @@ install-exec-hook: $(AUXAWK) # pkglibexecdir and pkgdatadir are removed in the top level Makefile's uninstall uninstall-local: rm -fr $(DESTDIR)$(pkglibexecdir)/* $(DESTDIR)$(pkgdatadir)/* - rm -f $(DESTDIR)$(bindir)/igawk clean-local: - rm -f $(AUXAWK) igawk *.exe + rm -f $(AUXAWK) *.exe rm -fr eg.old rm -fr grcat.dSYM pwcat.dSYM @@ -759,9 +691,6 @@ grcat.c: $(srcdir)/eg/lib/grcat.c $(srcdir)/eg/lib/pwcat.c $(srcdir)/eg/lib/grcat.c $(srcdir)/eg/prog/igawk.sh \ $(srcdir)/eg/lib/passwdawk.in $(srcdir)/eg/lib/groupawk.in: stamp-eg; @: -igawk: $(srcdir)/eg/prog/igawk.sh - cp $(srcdir)/eg/prog/igawk.sh $@ ; chmod 755 $@ - passwd.awk: $(srcdir)/eg/lib/passwdawk.in sed 's;/usr/local/libexec/awk;$(pkglibexecdir);' < $(srcdir)/eg/lib/passwdawk.in > passwd.awk diff --git a/awklib/eg/lib/intdiv.awk b/awklib/eg/lib/intdiv.awk new file mode 100644 index 00000000..dbc553b0 --- /dev/null +++ b/awklib/eg/lib/intdiv.awk @@ -0,0 +1,20 @@ +# intdiv --- do integer division + +# +# Arnold Robbins, arnold@skeeve.com, Public Domain +# July, 2014 +# +# Name changed from div() to intdiv() +# April, 2015 + +function intdiv(numerator, denominator, result) +{ + split("", result) + + numerator = int(numerator) + denominator = int(denominator) + result["quotient"] = int(numerator / denominator) + result["remainder"] = int(numerator % denominator) + + return 0.0 +} diff --git a/awklib/eg/prog/pi.awk b/awklib/eg/prog/pi.awk new file mode 100644 index 00000000..e1b5bc4f --- /dev/null +++ b/awklib/eg/prog/pi.awk @@ -0,0 +1,18 @@ +# pi.awk --- compute the digits of pi +# +# Katie Wasserman, katie@wass.net +# August 2014 + +BEGIN { + digits = 100000 + two = 2 * 10 ^ digits + pi = two + for (m = digits * 4; m > 0; --m) { + d = m * 2 + 1 + x = pi * m + intdiv(x, d, result) + pi = result["quotient"] + pi = pi + two + } + print pi +} @@ -129,10 +129,14 @@ wrerror: if (fp == stdout && errno == EPIPE) gawk_exit(EXIT_FATAL); + /* otherwise die verbosely */ - fatal(_("%s to \"%s\" failed (%s)"), from, - rp ? rp->value : _("standard output"), - errno ? strerror(errno) : _("reason unknown")); + if ((rp != NULL) ? is_non_fatal_redirect(rp->value) : is_non_fatal_std(fp)) + update_ERRNO_int(errno); + else + fatal(_("%s to \"%s\" failed (%s)"), from, + rp ? rp->value : _("standard output"), + errno ? strerror(errno) : _("reason unknown")); } /* do_exp --- exponential function */ @@ -144,7 +148,7 @@ do_exp(int nargs) double d, res; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("exp: received non-numeric argument")); d = force_number(tmp)->numbr; DEREF(tmp); @@ -350,9 +354,9 @@ do_index(int nargs) POP_TWO_SCALARS(s1, s2); if (do_lint) { - if ((s1->flags & (STRING|STRCUR)) == 0) + if ((fixtype(s1)->flags & STRING) == 0) lintwarn(_("index: received non-string first argument")); - if ((s2->flags & (STRING|STRCUR)) == 0) + if ((fixtype(s2)->flags & STRING) == 0) lintwarn(_("index: received non-string second argument")); } @@ -465,7 +469,7 @@ do_int(int nargs) double d; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("int: received non-numeric argument")); d = force_number(tmp)->numbr; d = double_to_int(d); @@ -480,6 +484,12 @@ do_isarray(int nargs) { NODE *tmp; int ret = 1; + static bool warned = false; + + if (do_lint && ! warned) { + warned = true; + lintwarn(_("`isarray' is deprecated. Use `typeof' instead")); + } tmp = POP(); if (tmp->type != Node_var_array) { @@ -522,9 +532,9 @@ do_length(int nargs) return make_number(size); } - assert(tmp->type == Node_val); + assert(tmp->type == Node_val || tmp->type == Node_typedregex); - if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0) + if (do_lint && (fixtype(tmp)->flags & STRING) == 0) lintwarn(_("length: received non-string argument")); tmp = force_string(tmp); @@ -553,7 +563,7 @@ do_log(int nargs) double d, arg; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("log: received non-numeric argument")); arg = force_number(tmp)->numbr; if (arg < 0.0) @@ -712,7 +722,7 @@ format_tree( emalloc(obuf, char *, INITIAL_OUT_SIZE, "format_tree"); obufout = obuf; osiz = INITIAL_OUT_SIZE; - ofre = osiz - 2; + ofre = osiz - 1; cur_arg = 1; @@ -1039,8 +1049,7 @@ check_pos: need_format = false; parse_next_arg(); /* user input that looks numeric is numeric */ - if ((arg->flags & (MAYBE_NUM|NUMBER)) == MAYBE_NUM) - (void) force_number(arg); + fixtype(arg); if ((arg->flags & NUMBER) != 0) { uval = get_number_uj(arg); if (gawk_mb_cur_max > 1) { @@ -1574,7 +1583,7 @@ mpf1: bchunk(s0, s1 - s0); olen_final = obufout - obuf; if (ofre > 0) - erealloc(obuf, char *, olen_final + 2, "format_tree"); + erealloc(obuf, char *, olen_final + 1, "format_tree"); r = make_str_node(obuf, olen_final, ALREADY_MALLOCED); obuf = NULL; out: @@ -1645,7 +1654,7 @@ do_printf(int nargs, int redirtype) FILE *fp = NULL; NODE *tmp; struct redirect *rp = NULL; - int errflg; /* not used, sigh */ + int errflg = 0; NODE *redir_exp = NULL; if (nargs == 0) { @@ -1656,7 +1665,7 @@ do_printf(int nargs, int redirtype) redir_exp = TOP(); if (redir_exp->type != Node_val) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp)); - rp = redirect(redir_exp, redirtype, & errflg); + rp = redirect(redir_exp, redirtype, & errflg, true); DEREF(redir_exp); decr_sp(); } @@ -1669,14 +1678,22 @@ do_printf(int nargs, int redirtype) redir_exp = PEEK(nargs); if (redir_exp->type != Node_val) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp)); - rp = redirect(redir_exp, redirtype, & errflg); + rp = redirect(redir_exp, redirtype, & errflg, true); if (rp != NULL) { if ((rp->flag & RED_TWOWAY) != 0 && rp->output.fp == NULL) { + if (is_non_fatal_redirect(redir_exp->stptr)) { + update_ERRNO_int(EBADF); + return; + } (void) close_rp(rp, CLOSE_ALL); fatal(_("printf: attempt to write to closed write end of two-way pipe")); } fp = rp->output.fp; } + else if (errflg) { + update_ERRNO_int(errflg); + return; + } } else if (do_debug) /* only the debugger can change the default output */ fp = output_fp; else @@ -1709,7 +1726,7 @@ do_sqrt(int nargs) double arg; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("sqrt: received non-numeric argument")); arg = (double) force_number(tmp)->numbr; DEREF(tmp); @@ -1850,7 +1867,7 @@ do_substr(int nargs) * way to do things. */ memset(& mbs, 0, sizeof(mbs)); - emalloc(substr, char *, (length * gawk_mb_cur_max) + 2, "do_substr"); + emalloc(substr, char *, (length * gawk_mb_cur_max) + 1, "do_substr"); wp = t1->wstptr + indx; for (cp = substr; length > 0; length--) { result = wcrtomb(cp, *wp, & mbs); @@ -1899,7 +1916,7 @@ do_strftime(int nargs) unref(sub); if (val != NULL) { - if (do_lint && (val->flags & STRING) == 0) + if (do_lint && (fixtype(val)->flags & STRING) == 0) lintwarn(_("strftime: format value in PROCINFO[\"strftime\"] has numeric type")); val = force_string(val); format = val->stptr; @@ -1913,16 +1930,13 @@ do_strftime(int nargs) if (nargs == 3) { t3 = POP_SCALAR(); - if ((t3->flags & (NUMCUR|NUMBER)) != 0) - do_gmt = (t3->numbr != 0); - else - do_gmt = (t3->stlen > 0); + do_gmt = boolval(t3); DEREF(t3); } if (nargs >= 2) { t2 = POP_SCALAR(); - if (do_lint && (t2->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(t2)->flags & NUMBER) == 0) lintwarn(_("strftime: received non-numeric second argument")); (void) force_number(t2); clock_val = get_number_d(t2); @@ -1948,7 +1962,7 @@ do_strftime(int nargs) } tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0) + if (do_lint && (fixtype(tmp)->flags & STRING) == 0) lintwarn(_("strftime: received non-string first argument")); t1 = force_string(tmp); @@ -2024,7 +2038,7 @@ do_mktime(int nargs) char save; t1 = POP_SCALAR(); - if (do_lint && (t1->flags & (STRING|STRCUR)) == 0) + if (do_lint && (fixtype(t1)->flags & STRING) == 0) lintwarn(_("mktime: received non-string argument")); t1 = force_string(t1); @@ -2082,7 +2096,7 @@ do_system(int nargs) (void) flush_io(); /* so output is synchronous with gawk's */ tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (STRING|STRCUR)) == 0) + if (do_lint && (fixtype(tmp)->flags & STRING) == 0) lintwarn(_("system: received non-string argument")); cmd = force_string(tmp)->stptr; @@ -2146,7 +2160,7 @@ void do_print(int nargs, int redirtype) { struct redirect *rp = NULL; - int errflg; /* not used, sigh */ + int errflg = 0; FILE *fp = NULL; int i; NODE *redir_exp = NULL; @@ -2158,14 +2172,22 @@ do_print(int nargs, int redirtype) redir_exp = PEEK(nargs); if (redir_exp->type != Node_val) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(redir_exp)); - rp = redirect(redir_exp, redirtype, & errflg); + rp = redirect(redir_exp, redirtype, & errflg, true); if (rp != NULL) { if ((rp->flag & RED_TWOWAY) != 0 && rp->output.fp == NULL) { + if (is_non_fatal_redirect(redir_exp->stptr)) { + update_ERRNO_int(EBADF); + return; + } (void) close_rp(rp, CLOSE_ALL); fatal(_("print: attempt to write to closed write end of two-way pipe")); } fp = rp->output.fp; } + else if (errflg) { + update_ERRNO_int(errflg); + return; + } } else if (do_debug) /* only the debugger can change the default output */ fp = output_fp; else @@ -2179,12 +2201,11 @@ do_print(int nargs, int redirtype) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(tmp)); } - if ((tmp->flags & (NUMBER|STRING)) == NUMBER) { - if (OFMTidx == CONVFMTidx) - args_array[i] = force_string(tmp); - else - args_array[i] = format_val(OFMT, OFMTidx, tmp); - } + if (tmp->type == Node_typedregex) + args_array[i] = force_string(tmp); + else if (!((tmp->flags & STRCUR) != 0 + && (tmp->stfmt == STFMT_UNUSED || tmp->stfmt == OFMTidx))) + args_array[i] = format_val(OFMT, OFMTidx, tmp); } if (redir_exp != NULL) { @@ -2221,15 +2242,19 @@ do_print_rec(int nargs, int redirtype) FILE *fp = NULL; NODE *f0; struct redirect *rp = NULL; - int errflg; /* not used, sigh */ + int errflg = 0; NODE *redir_exp = NULL; assert(nargs == 0); if (redirtype != 0) { redir_exp = TOP(); - rp = redirect(redir_exp, redirtype, & errflg); + rp = redirect(redir_exp, redirtype, & errflg, true); if (rp != NULL) { if ((rp->flag & RED_TWOWAY) != 0 && rp->output.fp == NULL) { + if (is_non_fatal_redirect(redir_exp->stptr)) { + update_ERRNO_int(EBADF); + return; + } (void) close_rp(rp, CLOSE_ALL); fatal(_("print: attempt to write to closed write end of two-way pipe")); } @@ -2240,6 +2265,11 @@ do_print_rec(int nargs, int redirtype) } else fp = output_fp; + if (errflg) { + update_ERRNO_int(errflg); + return; + } + if (fp == NULL) return; @@ -2333,7 +2363,7 @@ do_tolower(int nargs) NODE *t1, *t2; t1 = POP_SCALAR(); - if (do_lint && (t1->flags & (STRING|STRCUR)) == 0) + if (do_lint && (fixtype(t1)->flags & STRING) == 0) lintwarn(_("tolower: received non-string argument")); t1 = force_string(t1); t2 = make_string(t1->stptr, t1->stlen); @@ -2364,7 +2394,7 @@ do_toupper(int nargs) NODE *t1, *t2; t1 = POP_SCALAR(); - if (do_lint && (t1->flags & (STRING|STRCUR)) == 0) + if (do_lint && (fixtype(t1)->flags & STRING) == 0) lintwarn(_("toupper: received non-string argument")); t1 = force_string(t1); t2 = make_string(t1->stptr, t1->stlen); @@ -2397,9 +2427,9 @@ do_atan2(int nargs) POP_TWO_SCALARS(t1, t2); if (do_lint) { - if ((t1->flags & (NUMCUR|NUMBER)) == 0) + if ((fixtype(t1)->flags & NUMBER) == 0) lintwarn(_("atan2: received non-numeric first argument")); - if ((t2->flags & (NUMCUR|NUMBER)) == 0) + if ((fixtype(t2)->flags & NUMBER) == 0) lintwarn(_("atan2: received non-numeric second argument")); } d1 = force_number(t1)->numbr; @@ -2418,7 +2448,7 @@ do_sin(int nargs) double d; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("sin: received non-numeric argument")); d = sin((double) force_number(tmp)->numbr); DEREF(tmp); @@ -2434,7 +2464,7 @@ do_cos(int nargs) double d; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("cos: received non-numeric argument")); d = cos((double) force_number(tmp)->numbr); DEREF(tmp); @@ -2453,6 +2483,8 @@ static char *const state = (char *const) istate; NODE * do_rand(int nargs ATTRIBUTE_UNUSED) { + double tmprand; +#define RAND_DIVISOR ((double)GAWK_RANDOM_MAX+1.0) if (firstrand) { (void) initstate((unsigned) 1, state, SIZEOF_STATE); /* don't need to srandom(1), initstate() does it for us. */ @@ -2464,7 +2496,66 @@ do_rand(int nargs ATTRIBUTE_UNUSED) * * 0 <= n < 1 */ - return make_number((AWKNUM) (random() % GAWK_RANDOM_MAX) / GAWK_RANDOM_MAX); + /* + * Date: Wed, 28 Aug 2013 17:52:46 -0700 + * From: Bob Jewett <jewett@bill.scs.agilent.com> + * + * Call random() twice to fill in more bits in the value + * of the double. Also, there is a bug in random() such + * that when the values of successive values are combined + * like (rand1*rand2)^2, (rand3*rand4)^2, ... the + * resulting time series is not white noise. The + * following also seems to fix that bug. + * + * The add/subtract 0.5 keeps small bits from filling + * below 2^-53 in the double, not that anyone should be + * looking down there. + * + * Date: Wed, 25 Sep 2013 10:45:38 -0600 (MDT) + * From: "Nelson H. F. Beebe" <beebe@math.utah.edu> + * (4) The code is typical of many published fragments for converting + * from integer to floating-point, and I discuss the serious pitfalls + * in my book, because it leads to platform-dependent behavior at the + * end points of the interval [0,1] + * + * (5) the documentation in the gawk info node says + * + * `rand()' + * Return a random number. The values of `rand()' are uniformly + * distributed between zero and one. The value could be zero but is + * never one.(1) + * + * The division by RAND_DIVISOR may not guarantee that 1.0 is never + * returned: the programmer forgot the platform-dependent issue of + * rounding. + * + * For points 4 and 5, the safe way is a loop: + * + * double + * rand(void) // return value in [0.0, 1.0) + * { + * value = internal_rand(); + * + * while (value == 1.0) + * value = internal_rand(); + * + * return (value); + * } + */ + + do { + long d1, d2; + /* + * Do the calls in predictable order to avoid + * compiler differences in order of evaluation. + */ + d1 = random(); + d2 = random(); + tmprand = 0.5 + ( (d1/RAND_DIVISOR + d2) / RAND_DIVISOR ); + tmprand -= 0.5; + } while (tmprand == 1.0); + + return make_number((AWKNUM) tmprand); } /* do_srand --- seed the random number generator */ @@ -2487,7 +2578,7 @@ do_srand(int nargs) srandom((unsigned int) (save_seed = (long) time((time_t *) 0))); else { tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("srand: received non-numeric argument")); srandom((unsigned int) (save_seed = (long) force_number(tmp)->numbr)); DEREF(tmp); @@ -2577,7 +2668,7 @@ do_match(int nargs) sprintf(buff, "%d", ii); ilen = strlen(buff); - amt = ilen + subseplen + strlen("length") + 2; + amt = ilen + subseplen + strlen("length") + 1; if (oldamt == 0) { emalloc(buf, char *, amt, "do_match"); @@ -2751,56 +2842,48 @@ do_sub(int nargs, unsigned int flags) int ampersands; int matches = 0; Regexp *rp; - NODE *s; /* subst. pattern */ - NODE *t; /* string to make sub. in; $0 if none given */ + NODE *rep_node; /* replacement text */ + NODE *target; /* string to make sub. in; $0 if none given */ NODE *tmp; NODE **lhs = NULL; long how_many = 1; /* one substitution for sub, also gensub default */ - int global; + bool global; long current; bool lastmatchnonzero; char *mb_indices = NULL; if ((flags & GENSUB) != 0) { double d; - NODE *t1; + NODE *glob_flag; tmp = PEEK(3); rp = re_update(tmp); - t = POP_STRING(); /* original string */ + target = POP_STRING(); /* original string */ - t1 = POP_SCALAR(); /* value of global flag */ - if ((t1->flags & (STRCUR|STRING)) != 0) { - if (t1->stlen > 0 && (t1->stptr[0] == 'g' || t1->stptr[0] == 'G')) - how_many = -1; - else { - (void) force_number(t1); - d = get_number_d(t1); - if ((t1->flags & NUMCUR) != 0) - goto set_how_many; - - warning(_("gensub: third argument `%.*s' treated as 1"), - (int) t1->stlen, t1->stptr); - how_many = 1; - } - } else { - (void) force_number(t1); - d = get_number_d(t1); -set_how_many: + glob_flag = POP_SCALAR(); /* value of global flag */ + if ( (glob_flag->flags & STRING) != 0 + && glob_flag->stlen > 0 + && (glob_flag->stptr[0] == 'g' || glob_flag->stptr[0] == 'G')) + how_many = -1; + else { + (void) force_number(glob_flag); + d = get_number_d(glob_flag); if (d < 1) how_many = 1; else if (d < LONG_MAX) how_many = d; else how_many = LONG_MAX; - if (d <= 0) - warning(_("gensub: third argument %g treated as 1"), d); + if (d <= 0) { + (void) force_string(glob_flag); + warning(_("gensub: third argument `%.*s' treated as 1"), + (int) glob_flag->stlen, + glob_flag->stptr); + } } - DEREF(t1); - + DEREF(glob_flag); } else { - /* take care of regexp early, in case re_update is fatal */ tmp = PEEK(2); @@ -2812,30 +2895,30 @@ set_how_many: /* original string */ if ((flags & LITERAL) != 0) - t = POP_STRING(); + target = POP_STRING(); else { lhs = POP_ADDRESS(); - t = force_string(*lhs); + target = force_string(*lhs); } } global = (how_many == -1); - s = POP_STRING(); /* replacement text */ + rep_node = POP_STRING(); /* replacement text */ decr_sp(); /* regexp, already updated above */ /* do the search early to avoid work on non-match */ - if (research(rp, t->stptr, 0, t->stlen, RE_NEED_START) == -1 || - RESTART(rp, t->stptr) > t->stlen) + if (research(rp, target->stptr, 0, target->stlen, RE_NEED_START) == -1 || + RESTART(rp, target->stptr) > target->stlen) goto done; - t->flags |= STRING; + target->flags |= STRING; - text = t->stptr; - textlen = t->stlen; + text = target->stptr; + textlen = target->stlen; - repl = s->stptr; - replend = repl + s->stlen; + repl = rep_node->stptr; + replend = repl + rep_node->stlen; repllen = replend - repl; ampersands = 0; @@ -2853,6 +2936,7 @@ set_how_many: index_multibyte_buffer(repl, mb_indices, repllen); } + /* compute length of replacement string, number of ampersands */ for (scan = repl; scan < replend; scan++) { if ((gawk_mb_cur_max == 1 || (repllen > 0 && mb_indices[scan - repl] == 1)) && (*scan == '&')) { @@ -2899,24 +2983,32 @@ set_how_many: lastmatchnonzero = false; - /* guesstimate how much room to allocate; +2 forces > 0 */ - buflen = textlen + (ampersands + 1) * repllen + 2; - emalloc(buf, char *, buflen + 2, "do_sub"); + /* guesstimate how much room to allocate; +1 forces > 0 */ + buflen = textlen + (ampersands + 1) * repllen + 1; + emalloc(buf, char *, buflen + 1, "do_sub"); buf[buflen] = '\0'; - buf[buflen + 1] = '\0'; bp = buf; for (current = 1;; current++) { matches++; - matchstart = t->stptr + RESTART(rp, t->stptr); - matchend = t->stptr + REEND(rp, t->stptr); + matchstart = target->stptr + RESTART(rp, target->stptr); + matchend = target->stptr + REEND(rp, target->stptr); /* * create the result, copying in parts of the original - * string + * string. note that length of replacement string can + * vary since ampersand is actual text of regexp match. */ - len = matchstart - text + repllen - + ampersands * (matchend - matchstart); + + /* + * add 1 to len to handle "empty" case where + * matchend == matchstart and we force a match on a single + * char. Use 'matchend - text' instead of 'matchstart - text' + * because we may not actually make any substitution depending + * on the 'global' and 'how_many' values. + */ + len = matchend - text + repllen + + ampersands * (matchend - matchstart) + 1; sofar = bp - buf; while (buflen < (sofar + len + 1)) { buflen *= 2; @@ -2963,13 +3055,13 @@ set_how_many: if (flags & GENSUB) { /* gensub, behave sanely */ if (isdigit((unsigned char) scan[1])) { int dig = scan[1] - '0'; - if (dig < NUMSUBPATS(rp, t->stptr) && SUBPATSTART(rp, tp->stptr, dig) != -1) { + if (dig < NUMSUBPATS(rp, target->stptr) && SUBPATSTART(rp, tp->stptr, dig) != -1) { char *start, *end; - start = t->stptr - + SUBPATSTART(rp, t->stptr, dig); - end = t->stptr - + SUBPATEND(rp, t->stptr, dig); + start = target->stptr + + SUBPATSTART(rp, target->stptr, dig); + end = target->stptr + + SUBPATEND(rp, target->stptr, dig); for (cp = start; cp < end; cp++) *bp++ = *cp; @@ -3025,19 +3117,29 @@ set_how_many: textlen = text + textlen - matchend; text = matchend; +#if 0 + if (bp - buf > sofar + len) + fprintf(stderr, "debug: len = %zu, but used %ld\n", len, (long)((bp - buf) - (long)sofar)); +#endif + if ((current >= how_many && ! global) || ((long) textlen <= 0 && matchstart == matchend) - || research(rp, t->stptr, text - t->stptr, textlen, RE_NEED_START) == -1) + || research(rp, target->stptr, text - target->stptr, textlen, RE_NEED_START) == -1) break; } sofar = bp - buf; - if (buflen - sofar - textlen - 1) { - buflen = sofar + textlen + 2; + if (buflen < (sofar + textlen + 1)) { + buflen = sofar + textlen + 1; erealloc(buf, char *, buflen, "do_sub"); bp = buf + sofar; } - for (scan = matchend; scan < text + textlen; scan++) + /* + * Note that text == matchend, since that assignment is made before + * exiting the 'for' loop above. Thus we copy in the rest of the + * original string. + */ + for (scan = text; scan < text + textlen; scan++) *bp++ = *scan; *bp = '\0'; textlen = bp - buf; @@ -3046,7 +3148,7 @@ set_how_many: efree(mb_indices); done: - DEREF(s); + DEREF(rep_node); if ((matches == 0 || (flags & LITERAL) != 0) && buf != NULL) { efree(buf); @@ -3056,18 +3158,18 @@ done: if (flags & GENSUB) { if (matches > 0) { /* return the result string */ - DEREF(t); + DEREF(target); assert(buf != NULL); return make_str_node(buf, textlen, ALREADY_MALLOCED); } /* return the original string */ - return t; + return target; } /* For a string literal, must not change the original string. */ if ((flags & LITERAL) != 0) - DEREF(t); + DEREF(target); else if (matches > 0) { unref(*lhs); *lhs = make_str_node(buf, textlen, ALREADY_MALLOCED); @@ -3106,7 +3208,8 @@ call_sub(const char *name, int nargs) * push replace * push $0 */ - regex = make_regnode(Node_regex, regex); + if (regex->type != Node_typedregex) + regex = make_regnode(Node_regex, regex); PUSH(regex); PUSH(replace); lhs = r_get_field(zero, (Func_ptr *) 0, true); @@ -3130,7 +3233,8 @@ call_sub(const char *name, int nargs) * nargs++ * } */ - regex = make_regnode(Node_regex, regex); + if (regex->type != Node_typedregex) + regex = make_regnode(Node_regex, regex); PUSH(regex); PUSH(replace); PUSH(glob_flag); @@ -3167,7 +3271,8 @@ call_match(int nargs) /* Don't need to pop the string just to push it back ... */ - regex = make_regnode(Node_regex, regex); + if (regex->type != Node_typedregex) + regex = make_regnode(Node_regex, regex); PUSH(regex); if (array) @@ -3195,7 +3300,8 @@ call_split_func(const char *name, int nargs) if (nargs >= 3) { regex = POP_STRING(); - regex = make_regnode(Node_regex, regex); + if (regex->type != Node_typedregex) + regex = make_regnode(Node_regex, regex); } else { if (name[0] == 's') { regex = make_regnode(Node_regex, FS_node->var_value); @@ -3238,9 +3344,9 @@ do_lshift(int nargs) POP_TWO_SCALARS(s1, s2); if (do_lint) { - if ((s1->flags & (NUMCUR|NUMBER)) == 0) + if ((fixtype(s1)->flags & NUMBER) == 0) lintwarn(_("lshift: received non-numeric first argument")); - if ((s2->flags & (NUMCUR|NUMBER)) == 0) + if ((fixtype(s2)->flags & NUMBER) == 0) lintwarn(_("lshift: received non-numeric second argument")); } val = force_number(s1)->numbr; @@ -3275,9 +3381,9 @@ do_rshift(int nargs) POP_TWO_SCALARS(s1, s2); if (do_lint) { - if ((s1->flags & (NUMCUR|NUMBER)) == 0) + if ((fixtype(s1)->flags & NUMBER) == 0) lintwarn(_("rshift: received non-numeric first argument")); - if ((s2->flags & (NUMCUR|NUMBER)) == 0) + if ((fixtype(s2)->flags & NUMBER) == 0) lintwarn(_("rshift: received non-numeric second argument")); } val = force_number(s1)->numbr; @@ -3317,7 +3423,7 @@ do_and(int nargs) for (i = 1; nargs > 0; nargs--, i++) { s1 = POP_SCALAR(); - if (do_lint && (s1->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(s1)->flags & NUMBER) == 0) lintwarn(_("and: argument %d is non-numeric"), i); val = force_number(s1)->numbr; @@ -3349,7 +3455,7 @@ do_or(int nargs) for (i = 1; nargs > 0; nargs--, i++) { s1 = POP_SCALAR(); - if (do_lint && (s1->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(s1)->flags & NUMBER) == 0) lintwarn(_("or: argument %d is non-numeric"), i); val = force_number(s1)->numbr; @@ -3381,7 +3487,7 @@ do_xor(int nargs) res = 0; /* silence compiler warning */ for (i = 1; nargs > 0; nargs--, i++) { s1 = POP_SCALAR(); - if (do_lint && (s1->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(s1)->flags & NUMBER) == 0) lintwarn(_("xor: argument %d is non-numeric"), i); val = force_number(s1)->numbr; @@ -3410,7 +3516,7 @@ do_compl(int nargs) uintmax_t uval; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("compl: received non-numeric argument")); d = force_number(tmp)->numbr; DEREF(tmp); @@ -3435,11 +3541,11 @@ do_strtonum(int nargs) NODE *tmp; AWKNUM d; - tmp = POP_SCALAR(); - if ((tmp->flags & (NUMBER|NUMCUR)) != 0) - d = (AWKNUM) force_number(tmp)->numbr; + tmp = fixtype(POP_SCALAR()); + if ((tmp->flags & NUMBER) != 0) + d = (AWKNUM) tmp->numbr; else if (get_numbase(tmp->stptr, use_lc_numeric) != 10) - d = nondec2awknum(tmp->stptr, tmp->stlen); + d = nondec2awknum(tmp->stptr, tmp->stlen, NULL); else d = (AWKNUM) force_number(tmp)->numbr; @@ -3456,7 +3562,7 @@ do_strtonum(int nargs) */ AWKNUM -nondec2awknum(char *str, size_t len) +nondec2awknum(char *str, size_t len, char **endptr) { AWKNUM retval = 0.0; char save; @@ -3468,8 +3574,11 @@ nondec2awknum(char *str, size_t len) * User called strtonum("0x") or some such, * so just quit early. */ - if (len <= 2) + if (len <= 2) { + if (endptr) + *endptr = start; return (AWKNUM) 0.0; + } for (str += 2, len -= 2; len > 0; len--, str++) { switch (*str) { @@ -3502,14 +3611,21 @@ nondec2awknum(char *str, size_t len) val = *str - 'A' + 10; break; default: + if (endptr) + *endptr = str; goto done; } retval = (retval * 16) + val; } + if (endptr) + *endptr = str; } else if (*str == '0') { for (; len > 0; len--) { - if (! isdigit((unsigned char) *str)) + if (! isdigit((unsigned char) *str)) { + if (endptr) + *endptr = str; goto done; + } else if (*str == '8' || *str == '9') { str = start; goto decimal; @@ -3517,11 +3633,13 @@ nondec2awknum(char *str, size_t len) retval = (retval * 8) + (*str - '0'); str++; } + if (endptr) + *endptr = str; } else { decimal: save = str[len]; str[len] = '\0'; - retval = strtod(str, NULL); + retval = strtod(str, endptr); str[len] = save; } done: @@ -3757,6 +3875,128 @@ do_bindtextdomain(int nargs) return make_string(the_result, strlen(the_result)); } +/* do_intdiv --- do integer division, return quotient and remainder in dest array */ + +/* + * We define the semantics as: + * numerator = int(numerator) + * denominator = int(denonmator) + * quotient = int(numerator / denomator) + * remainder = int(numerator % denomator) + */ + +NODE * +do_intdiv(int nargs) +{ + NODE *numerator, *denominator, *result; + double num, denom, quotient, remainder; + NODE *sub, **lhs; + + result = POP_PARAM(); + if (result->type != Node_var_array) + fatal(_("intdiv: third argument is not an array")); + assoc_clear(result); + + denominator = POP_SCALAR(); + numerator = POP_SCALAR(); + + if (do_lint) { + if ((fixtype(numerator)->flags & NUMBER) == 0) + lintwarn(_("intdiv: received non-numeric first argument")); + if ((fixtype(denominator)->flags & NUMBER) == 0) + lintwarn(_("intdiv: received non-numeric second argument")); + } + + (void) force_number(numerator); + (void) force_number(denominator); + num = double_to_int(get_number_d(numerator)); + denom = double_to_int(get_number_d(denominator)); + + if (denom == 0.0) + fatal(_("intdiv: division by zero attempted")); + + quotient = double_to_int(num / denom); + /* + * FIXME: This code is duplicated, factor it out to a + * separate function. + */ +#ifdef HAVE_FMOD + remainder = fmod(num, denom); +#else /* ! HAVE_FMOD */ + (void) modf(num / denom, & remainder); + remainder = num - remainder * denom; +#endif /* ! HAVE_FMOD */ + remainder = double_to_int(remainder); + + sub = make_string("quotient", 8); + lhs = assoc_lookup(result, sub); + unref(*lhs); + *lhs = make_number((AWKNUM) quotient); + + sub = make_string("remainder", 9); + lhs = assoc_lookup(result, sub); + unref(*lhs); + *lhs = make_number((AWKNUM) remainder); + + return make_number((AWKNUM) 0.0); +} + +/* do_typeof --- return a string with the type of the arg */ + +NODE * +do_typeof(int nargs) +{ + NODE *arg; + char *res = "unknown"; + bool deref = true; + + arg = POP(); + switch (arg->type) { + case Node_var_array: + /* Node_var_array is never UPREF'ed */ + res = "array"; + deref = false; + break; + case Node_typedregex: + res = "regexp"; + break; + case Node_val: + case Node_var: + switch (arg->flags & (STRING|NUMBER|MAYBE_NUM)) { + case STRING: + res = "string"; + break; + case NUMBER: + res = "number"; + break; + case STRING|MAYBE_NUM: + res = "strnum"; + break; + case NUMBER|STRING: + if (arg == Nnull_string) { + res = "unassigned"; + break; + } + /* fall through */ + default: + warning(_("typeof detected invalid flags combination `%s'; please file a bug report."), flags2str(arg->flags)); + break; + } + break; + case Node_var_new: + res = "untyped"; + deref = false; + break; + default: + fatal(_("typeof: unknown argument type `%s'"), + nodetype2str(arg->type)); + break; + } + + if (deref) + DEREF(arg); + return make_string(res, strlen(res)); +} /* mbc_byte_count --- return number of bytes for corresponding numchars multibyte characters */ diff --git a/cmake/Toolchain_clang.cmake b/cmake/Toolchain_clang.cmake new file mode 100644 index 00000000..89353570 --- /dev/null +++ b/cmake/Toolchain_clang.cmake @@ -0,0 +1,19 @@ +# http://www.cmake.org/Wiki/CmakeMingw +# http://www.cmake.org/Wiki/CMake_Cross_Compiling#The_toolchain_file + +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Generic) + +# which compilers to use for C and C++ +SET(CMAKE_C_COMPILER /usr/bin/clang) + +# here is the target environment located +SET(CMAKE_FIND_ROOT_PATH /usr/lib64/clang/3.1) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/cmake/Toolchain_generic.cmake b/cmake/Toolchain_generic.cmake new file mode 100644 index 00000000..91ddc6e7 --- /dev/null +++ b/cmake/Toolchain_generic.cmake @@ -0,0 +1,21 @@ +# http://www.cmake.org/Wiki/CmakeMingw +# http://www.cmake.org/Wiki/CMake_Cross_Compiling#The_toolchain_file + +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Generic) + +# which compilers to use for C and C++ +# Settings for Ubuntu 12.04.1 LTS +SET(CMAKE_C_COMPILER /usr/bin/gcc) + +# here is the target environment located +# Settings for Ubuntu 12.04.1 LTS +SET(CMAKE_FIND_ROOT_PATH /usr/) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/cmake/Toolchain_mingw32.cmake b/cmake/Toolchain_mingw32.cmake new file mode 100644 index 00000000..bb885f2f --- /dev/null +++ b/cmake/Toolchain_mingw32.cmake @@ -0,0 +1,23 @@ +# http://www.cmake.org/Wiki/CmakeMingw +# http://www.cmake.org/Wiki/CMake_Cross_Compiling#The_toolchain_file + +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Windows) + +# which compilers to use for C and C++ +# Settings for Ubuntu 12.04.1 LTS +SET(CMAKE_C_COMPILER /usr/bin/i686-w64-mingw32-gcc) +SET(CMAKE_CXX_COMPILER /usr/bin/i686-w64-mingw32-g++) +SET(CMAKE_RC_COMPILER /usr/bin/i686-w64-mingw32-windres) + +# here is the target environment located +# Settings for Ubuntu 12.04.1 LTS +SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/cmake/Toolchain_s390.cmake b/cmake/Toolchain_s390.cmake new file mode 100644 index 00000000..e1cdcfff --- /dev/null +++ b/cmake/Toolchain_s390.cmake @@ -0,0 +1,20 @@ +# http://www.cmake.org/Wiki/CmakeMingw +# http://www.cmake.org/Wiki/CMake_Cross_Compiling#The_toolchain_file +# http://wiki.debian.org/EmdebianToolchain#Get_the_binaries + +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Generic) + +# which compilers to use for C and C++ +SET(CMAKE_C_COMPILER /usr/bin/s390-linux-gnu-gcc-4.4) + +# here is the target environment located +SET(CMAKE_FIND_ROOT_PATH /usr/s390-linux-gnu/) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/cmake/auk.ico b/cmake/auk.ico Binary files differnew file mode 100644 index 00000000..795ef1d9 --- /dev/null +++ b/cmake/auk.ico diff --git a/cmake/basictest b/cmake/basictest new file mode 100755 index 00000000..210ed224 --- /dev/null +++ b/cmake/basictest @@ -0,0 +1,553 @@ +#!/bin/sh + +# Use this for debugging the test cases. +# The resulting textual output will not destroy the test cases. +set -x +# After test case execution, the output can be found in +# build/Testing/Temporary/LastTest.log + +export PATH=$PATH:/c/MinGW/msys/1.0/bin +export GAWKEXE=$1 +export TESTCASE=$2 +TOPSRCDIR=$(dirname ${0})/.. +SRCDIR=${TOPSRCDIR}/test +export AWKPATH=${SRCDIR} +export AWKLIBPATH=$(dirname ${GAWKEXE})/extension/ +export LANG=C +# Is this shell running in a native MinGW shell (MSYS) ? +if test -n "$COMSPEC"; then + # Ignore all differences in white space. + COMPARE="diff -w" + PATH_SEPARATOR="\\" +else + # This is a shell running in Unix environment. + COMPARE="cmp" + PATH_SEPARATOR="/" +fi + +# This is the central function for executing a standard test case. +# Many of the more specialized test cases rely on this function. +function simple_test_case() { + local options=$1 # options passed to the gawk executable + local parameters=$2 # parameters passed to the test case script + cd ${SRCDIR} + if test -r ${TESTCASE}.in + # Any existing .in file will be redirected to standard input. + # The output redirection must be bound to the test script, otherwise + # the "set -x" logging would mix with the test case output. + then + ${pregawk} $GAWKEXE ${options} -f ${TESTCASE}.awk ${parameters} < ${TESTCASE}.in ${postgawk} > _${TESTCASE} 2>&1 + else + ${pregawk} $GAWKEXE ${options} -f ${TESTCASE}.awk ${parameters} ${postgawk} > _${TESTCASE} 2>&1 + fi || echo EXIT CODE: $? >> _${TESTCASE} + # Compare the expected (correct) output with the actual output. + ${COMPARE} ${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} + # If the comparison succeeds then remove the actual output. + # Else leave the actual output file untouched for later analysis. +} + +# Each test case that cannot be handle in the "standard way" shall +# be implemented as a function here. + +function lintold() { simple_test_case "--lint-old" "" ; } +function defref() { simple_test_case "--lint" "" ; } +function fmtspcl() { simple_test_case "--lint" "" ; } +function lintwarn() { simple_test_case "--lint" "" ; } +function noeffect() { simple_test_case "--lint" "" ; } +function nofmtch() { simple_test_case "--lint" "" ; } +function shadow() { simple_test_case "--lint" "" ; } +function uninit2() { simple_test_case "--lint" "" ; } +function uninit3() { simple_test_case "--lint" "" ; } +function uninit4() { simple_test_case "--lint" "" ; } +function uninit5() { simple_test_case "--lint" "" ; } +function uninitialized() { simple_test_case "--lint" "" ; } + +function regtest() { + echo 'Some of the output from regtest is very system specific, do not' + echo 'be distressed if your output differs from that distributed.' + echo 'Manual inspection is called for.' + AWK=$GAWKEXE ${SRCDIR}/regtest.sh +} + +function compare() { simple_test_case "" "0 1" ; } + +function inftest() { + echo This test is very machine specific... + $GAWKEXE -f ${SRCDIR}/inftest.awk | sed "s/inf/Inf/g" >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function getline2() { simple_test_case "" "getline2.awk getline2.awk" ; } + +function awkpath() { + AWKPATH="${SRCDIR}$(PATH_SEPARATOR)/lib" $GAWKEXE -f awkpath.awk >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function argtest() { simple_test_case "" "-x -y abc" ; } + +function badargs() { + $GAWKEXE -f 2>&1 | grep -v patchlevel >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function nonl() { simple_test_case "--lint" "/dev/null" ; } + +function poundbang() { +# The original poundbang test case looks a bit non-deterministic. +# This is a shortened version. + sed "s;/tmp/gawk;$GAWKEXE;" < ${SRCDIR}/poundbang.awk > ./_pbd.awk + chmod +x ./_pbd.awk + ./_pbd.awk ${SRCDIR}/poundbang.awk > _`basename ${TESTCASE}` ; + ${COMPARE} ${SRCDIR}/poundbang.awk _`basename ${TESTCASE}` && rm -f _`basename ${TESTCASE}` _pbd.awk +} + +function messages() { + $GAWKEXE -f ${SRCDIR}/messages.awk >_out2 2>_out3 + ${COMPARE} ${SRCDIR}/out1.ok _out1 && ${COMPARE} ${SRCDIR}/out2.ok _out2 && ${COMPARE} ${SRCDIR}/out3.ok _out3 && rm -f _out1 _out2 _out3 +} + +function argarray() { + case ${SRCDIR} in + .) : ;; + *) cp ${SRCDIR}/argarray.in . ;; + esac + TEST=test echo just a test | $GAWKEXE -f ${SRCDIR}/argarray.awk ./argarray.in - >_${TESTCASE} + case ${SRCDIR} in + .) : ;; + *) rm -f ./argarray.in ;; + esac + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + + +function localenl() { + ${SRCDIR}/${TESTCASE}.sh >_${TESTCASE} 2>/dev/null + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function mbprintf1() { + GAWKLOCALE=en_US.UTF-8 ; export GAWKLOCALE + LANG=en_US.UTF-8 + $GAWKEXE -f ${SRCDIR}/${TESTCASE}.awk ${SRCDIR}/${TESTCASE}.in >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >> _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function mbfw1() { + GAWKLOCALE=en_US.UTF-8 ; export GAWKLOCALE + LANG=en_US.UTF-8 + $GAWKEXE -f ${SRCDIR}/${TESTCASE}.awk ${SRCDIR}/${TESTCASE}.in >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >> _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function printfbad2() { + $GAWKEXE --lint -f ${SRCDIR}/${TESTCASE}.awk ${SRCDIR}/${TESTCASE}.in 2>&1 | sed "s;$SRCDIR/;;g" >_${TESTCASE} || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function beginfile1() { + AWKPATH=${SRCDIR} $GAWKEXE -f ${TESTCASE}.awk ${SRCDIR}/${TESTCASE}.awk . ./no/such/file Makefile >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function beginfile2() { + # This differs from the original, the pwd part is new. + # The re-direction is now bound to the .sh file. + # This way the output of "set -x" is not written to the script's output file. + ( cd ${SRCDIR} && LC_ALL=C AWK="$GAWKEXE" ${SRCDIR}/${TESTCASE}.sh ${SRCDIR}/${TESTCASE}.in > `pwd`/_${TESTCASE} 2>&1 ) + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok ${SRCDIR}/_${TESTCASE} && rm -f ${SRCDIR}/_${TESTCASE} +} + +function dumpvars() { + AWKPATH=${SRCDIR} $GAWKEXE --dump-variables 1 < ${SRCDIR}/${TESTCASE}.in >/dev/null 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + mv awkvars.out _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function manyfiles() { + rm -rf junk + mkdir junk + $GAWKEXE 'BEGIN { for (i = 1; i <= 1030; i++) print i, i}' >_${TESTCASE} + $GAWKEXE -f ${SRCDIR}/manyfiles.awk _${TESTCASE} _${TESTCASE} + wc -l junk/* | $GAWKEXE '$1 != 2' | wc -l | sed "s/ *//g" > _${TESTCASE} + rm -rf junk + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function exitval1() { + $GAWKEXE -f ${SRCDIR}/exitval1.awk >_${TESTCASE} 2>&1; echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function fsspcoln() { + $GAWKEXE -f ${SRCDIR}/${TESTCASE}.awk 'FS=[ :]+' ${SRCDIR}/${TESTCASE}.in >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function rsstart2() { + $GAWKEXE -f ${SRCDIR}/${TESTCASE}.awk ${SRCDIR}/rsstart1.in >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function rsstart3() { + head ${SRCDIR}/rsstart1.in | $GAWKEXE -f ${SRCDIR}/rsstart2.awk >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function strftime() { + echo This test could fail on slow machines or on a minute boundary, + echo so if it does, double check the actual results: + GAWKLOCALE=C; export GAWKLOCALE + TZ=GMT0; export TZ + (LC_ALL=C date) | $GAWKEXE -v OUTPUT=_${TESTCASE} -f ${SRCDIR}/strftime.awk + ${COMPARE} strftime.ok _${TESTCASE} && rm -f _${TESTCASE} strftime.ok || exit 0 +} + +function inplace1() { + cp ${SRCDIR}/inplace.1.in _${TESTCASE}.1 + cp ${SRCDIR}/inplace.2.in _${TESTCASE}.2 + AWKPATH=${SRCDIR}/../awklib/eg/lib $GAWKEXE -i inplace 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _${TESTCASE}.1 - _${TESTCASE}.2 < ${SRCDIR}/inplace.in >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.1.ok _${TESTCASE}.1 && rm -f _${TESTCASE}.1 + ${COMPARE} ${SRCDIR}/${TESTCASE}.2.ok _${TESTCASE}.2 && rm -f _${TESTCASE}.2 +} + +function inplace2() { + cp ${SRCDIR}/inplace.1.in _${TESTCASE}.1 + cp ${SRCDIR}/inplace.2.in _${TESTCASE}.2 + AWKPATH=${SRCDIR}/../awklib/eg/lib $GAWKEXE -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _${TESTCASE}.1 - _${TESTCASE}.2 < ${SRCDIR}/inplace.in >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.1.ok _${TESTCASE}.1 && rm -f _${TESTCASE}.1 + ${COMPARE} ${SRCDIR}/${TESTCASE}.1.bak.ok _${TESTCASE}.1.bak && rm -f _${TESTCASE}.1.bak + ${COMPARE} ${SRCDIR}/${TESTCASE}.2.ok _${TESTCASE}.2 && rm -f _${TESTCASE}.2 + ${COMPARE} ${SRCDIR}/${TESTCASE}.2.bak.ok _${TESTCASE}.2.bak && rm -f _${TESTCASE}.2.bak +} + +function inplace3() { + cp ${SRCDIR}/inplace.1.in _${TESTCASE}.1 + cp ${SRCDIR}/inplace.2.in _${TESTCASE}.2 + AWKPATH=${SRCDIR}/../awklib/eg/lib $GAWKEXE -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "before"} {gsub(/foo/, "bar"); print} END {print "after"}' _${TESTCASE}.1 - _${TESTCASE}.2 < ${SRCDIR}/inplace.in >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + AWKPATH=${SRCDIR}/../awklib/eg/lib $GAWKEXE -i inplace -v INPLACE_SUFFIX=.bak 'BEGIN {print "Before"} {gsub(/bar/, "foo"); print} END {print "After"}' _${TESTCASE}.1 - _${TESTCASE}.2 < ${SRCDIR}/inplace.in >>_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.1.ok _${TESTCASE}.1 && rm -f _${TESTCASE}.1 + ${COMPARE} ${SRCDIR}/${TESTCASE}.1.bak.ok _${TESTCASE}.1.bak && rm -f _${TESTCASE}.1.bak + ${COMPARE} ${SRCDIR}/${TESTCASE}.2.ok _${TESTCASE}.2 && rm -f _${TESTCASE}.2 + ${COMPARE} ${SRCDIR}/${TESTCASE}.2.bak.ok _${TESTCASE}.2.bak && rm -f _${TESTCASE}.2.bak +} + +function testext() { + $GAWKEXE ' /^(@load|BEGIN)/,/^}/' ${SRCDIR}/../extension/testext.c > testext.awk + $GAWKEXE -f ${TESTCASE}.awk > ${SRCDIR}/_${TESTCASE} 2>&1 || echo EXIT CODE: $? >> ${SRCDIR}/_${TESTCASE} + rm -f testext.awk + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok ${SRCDIR}/_${TESTCASE} && rm -f ${SRCDIR}/_${TESTCASE} +} + +function 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.; + echo If it does, try rerunning on an ext'[234]' filesystem. ; + fi + $GAWKEXE -f ${TESTCASE}.awk ${SRCDIR}/.. > ${SRCDIR}/_${TESTCASE} 2>&1 + ls -afli ${TOPSRCDIR} | sed 1d | $GAWKEXE -f ${SRCDIR}/readdir0.awk -v extout=${SRCDIR}/_${TESTCASE} > ${SRCDIR}/${TESTCASE}.ok + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok ${SRCDIR}/_${TESTCASE} && rm -f ${SRCDIR}/_${TESTCASE} ${SRCDIR}/${TESTCASE}.ok +} + +function ordchr2() { + $GAWKEXE -l ordchr 'BEGIN {print chr(ord("z"))}' >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function include2() { + AWKPATH=${SRCDIR} $GAWKEXE -i inclib 'BEGIN {print sandwich("a", "b", "c")}' >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function incdupe() { + AWKPATH=${SRCDIR} $GAWKEXE --lint -i inclib -i inclib.awk 'BEGIN {print sandwich("a", "b", "c")}' >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function incdupe2() { + AWKPATH=${SRCDIR} $GAWKEXE --lint -f inclib -f inclib.awk >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function incdupe3() { + AWKPATH=${SRCDIR} $GAWKEXE --lint -f hello -f hello.awk >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function incdupe4() { + AWKPATH=${SRCDIR} $GAWKEXE --lint -f hello -i hello.awk >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function incdupe5() { + AWKPATH=${SRCDIR} $GAWKEXE --lint -i hello -f hello.awk >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function incdupe6() { + AWKPATH=${SRCDIR} $GAWKEXE --lint -i inchello -f hello.awk >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function incdupe7() { + AWKPATH=${SRCDIR} $GAWKEXE --lint -f hello -i inchello >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +# TODO: The compare operation passes even when there are diffs. +function readfile() { + $GAWKEXE -l readfile 'BEGIN {printf "%s", readfile("Makefile")}' >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} Makefile _${TESTCASE} && rm -f _${TESTCASE} || cp -p Makefile ${TESTCASE}.ok +} + +function fts() { + if [ "`uname`" = IRIX ]; then \ + echo This test may fail on IRIX systems when run on an NFS filesystem.; \ + echo If it does, try rerunning on an xfs filesystem. ; \ + fi + simple_test_case "" "" +} + +function charasbytes() { + [ -z "$GAWKLOCALE" ] && GAWKLOCALE=en_US.UTF-8; \ + AWKPATH=${SRCDIR} $GAWKEXE -b -v BINMODE=2 -f ${TESTCASE}.awk ${SRCDIR}/${TESTCASE}.in | \ + od -c -t x1 | sed -e 's/ */ /g' -e 's/ *$//' >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function symtab6() { + $GAWKEXE -d__${TESTCASE} -f ${SRCDIR}/${TESTCASE}.awk + grep -v '^ENVIRON' __${TESTCASE} | grep -v '^PROCINFO' > _${TESTCASE} ; rm __${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function symtab8() { + $GAWKEXE -d__${TESTCASE} -f ${SRCDIR}/${TESTCASE}.awk ${SRCDIR}/${TESTCASE}.in >_${TESTCASE} + grep -v '^ENVIRON' __${TESTCASE} | grep -v '^PROCINFO' | grep -v '^FILENAME' >> _${TESTCASE} ; rm __${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function colonwarn() { + for i in 1 2 3 ; \ + do $GAWKEXE -f ${SRCDIR}/${TESTCASE}.awk $i < ${SRCDIR}/${TESTCASE}.in ; \ + done > _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function litoct() { + echo ab | $GAWKEXE --traditional -f ${SRCDIR}/litoct.awk >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function devfd() { + $GAWKEXE 1 /dev/fd/4 /dev/fd/5 4<${SRCDIR}/devfd.in4 5<${SRCDIR}/devfd.in5 >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >> _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function fflush() { + ${SRCDIR}/fflush.sh >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function mmap8k() { + $GAWKEXE '{ print }' ${SRCDIR}/mmap8k.in >_${TESTCASE} + ${COMPARE} ${SRCDIR}/mmap8k.in _${TESTCASE} && rm -f _${TESTCASE} || cp ${SRCDIR}/${TESTCASE}.in ${TESTCASE}.ok +} + +function pid() { + AWKPATH=${SRCDIR} AWK=$GAWKEXE ${SHELL} ${SRCDIR}/pid.sh $$ > _${TESTCASE} ; : + ${COMPARE} ${SRCDIR}/pid.ok _`basename ${TESTCASE}` && rm -f _${TESTCASE} +} + +function strftlng() { + TZ=UTC; export TZ; $GAWKEXE -f ${SRCDIR}/strftlng.awk >_${TESTCASE} + if ${COMPARE} ${SRCDIR}/strftlng.ok _${TESTCASE} >/dev/null 2>&1 ; then : ; else \ + TZ=UTC0; export TZ; $GAWKEXE -f ${SRCDIR}/strftlng.awk >_${TESTCASE} ; \ + fi + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function nors() { + echo A B C D E | tr -d '\12\15' | $GAWKEXE '{ print $NF }' - ${SRCDIR}/nors.in > _${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function fmtspcl() { + $GAWKEXE -v "sd=${SRCDIR}" 'BEGIN {pnan = sprintf("%g",sqrt(-1)); nnan = sprintf("%g",-sqrt(-1)); pinf = sprintf("%g",-log(0)); ninf = sprintf("%g",log(0))} {sub(/positive_nan/,pnan); sub(/negative_nan/,nnan); sub(/positive_infinity/,pinf); sub(/negative_infinity/,ninf); sub(/fmtspcl/,(sd"/fmtspcl")); print}' < ${SRCDIR}/fmtspcl.tok > ${TESTCASE}.ok 2>/dev/null + $GAWKEXE $AWKFLAGS -f ${SRCDIR}/fmtspcl.awk --lint >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + if test -z "$AWKFLAGS" ; then + ${COMPARE} ${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} + else + ${COMPARE} ${SRCDIR}/${TESTCASE}-mpfr.ok _${TESTCASE} && rm -f _${TESTCASE} + fi +} + +function pipeio2() { simple_test_case "-v SRCDIR=${SRCDIR}" "" ; } + +function arynocls() { + AWKPATH=${SRCDIR} $GAWKEXE -v INPUT=${SRCDIR}/arynocls.in -f arynocls.awk >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function inetechu() { + echo This test is for establishing UDP connections + $GAWKEXE 'BEGIN {print "" |& "/inet/udp/0/127.0.0.1/9"}' +} + +function inetecht() { + echo This test is for establishing TCP connections + $GAWKEXE 'BEGIN {print "" |& "/inet/tcp/0/127.0.0.1/9"}' +} + +function inetdayu() { + echo This test is for bidirectional UDP transmission + $GAWKEXE 'BEGIN { print "" |& "/inet/udp/0/127.0.0.1/13"; \ + "/inet/udp/0/127.0.0.1/13" |& getline; print $0}' +} + +function inetdayt() { + echo This test is for bidirectional TCP transmission + $GAWKEXE 'BEGIN { print "" |& "/inet/tcp/0/127.0.0.1/13"; \ + "/inet/tcp/0/127.0.0.1/13" |& getline; print $0}' +} + +function redfilnm() { simple_test_case "" "srcdir=${SRCDIR}" ; } + +function leaddig() { simple_test_case "-v x=2E" "" ; } +function longwrds() { simple_test_case "-vSORT=sort" "" ; } + +function gsubtst3() { + $GAWKEXE --re-interval -f ${SRCDIR}/${TESTCASE}.awk ${SRCDIR}/${TESTCASE}.in >_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function space() { + $GAWKEXE -f ' ' ${SRCDIR}/space.awk >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function rsnulbig() { + # Suppose that block size for pipe is at most 128kB: + $GAWKEXE 'BEGIN { for (i = 1; i <= 128*64+1; i++) print "abcdefgh123456\n" }' 2>&1 | \ + $GAWKEXE 'BEGIN { RS = ""; ORS = "\n\n" }; { print }' 2>&1 | \ + $GAWKEXE '/^[^a]/; END{ print NR }' >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function rsnulbig2() { + $GAWKEXE 'BEGIN { ORS = ""; n = "\n"; for (i = 1; i <= 10; i++) n = (n n); \ + for (i = 1; i <= 128; i++) print n; print "abc\n" }' 2>&1 | \ + $GAWKEXE 'BEGIN { RS = ""; ORS = "\n\n" };{ print }' 2>&1 | \ + $GAWKEXE '/^[^a]/; END { print NR }' >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function printf0() { simple_test_case "--posix" "" ; } + +function profile1() { + $GAWKEXE --pretty-print=ap-${TESTCASE}.out -f ${SRCDIR}/xref.awk ${SRCDIR}/dtdgport.awk > _${TESTCASE}.out1 + $GAWKEXE -f ap-${TESTCASE}.out ${SRCDIR}/dtdgport.awk > _${TESTCASE}.out2 ; rm ap-${TESTCASE}.out + ${COMPARE} _${TESTCASE}.out1 _${TESTCASE}.out2 && rm _${TESTCASE}.out[12] || { echo EXIT CODE: $$? >>_${TESTCASE} ; \ + cp $(srcdir)/dtdgport.awk > ${TESTCASE}.ok ; } +} + +function profile2() { + $GAWKEXE --profile=ap-${TESTCASE}.out -v sortcmd=sort -f ${SRCDIR}/xref.awk ${SRCDIR}/dtdgport.awk > /dev/null + sed 1,2d < ap-${TESTCASE}.out > _${TESTCASE}; rm ap-${TESTCASE}.out + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function profile3() { + $GAWKEXE --profile=ap-${TESTCASE}.out -f ${SRCDIR}/${TESTCASE}.awk > /dev/null + sed 1,2d < ap-${TESTCASE}.out > _${TESTCASE}; rm ap-${TESTCASE}.out + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function profile4() { + GAWK_NO_PP_RUN=1 $GAWKEXE --profile=ap-${TESTCASE}.out -f ${SRCDIR}/${TESTCASE}.awk > /dev/null + sed 1,2d < ap-${TESTCASE}.out > _${TESTCASE}; rm ap-${TESTCASE}.out + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function profile5() { + GAWK_NO_PP_RUN=1 $GAWKEXE --profile=ap-${TESTCASE}.out -f ${SRCDIR}/${TESTCASE}.awk > /dev/null + sed 1,2d < ap-${TESTCASE}.out > _${TESTCASE}; rm ap-${TESTCASE}.out + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function posix2008sub() { + $GAWKEXE --posix -f ${SRCDIR}/${TESTCASE}.awk > _${TESTCASE} 2>&1 + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function next() { + LC_ALL=${GAWKLOCALE:-C} LANG=${GAWKLOCALE:-C} AWK="$GAWKEXE" ${SRCDIR}/${TESTCASE}.sh > _${TESTCASE} 2>&1 + LC_ALL=C ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function exit() { + AWK="$GAWKEXE" ${SRCDIR}/${TESTCASE}.sh > _${TESTCASE} 2>&1 + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function mpfrexprange() { simple_test_case "-M -vPREC=53 " "" ; } +function mpfrrnd() { simple_test_case "-M -vPREC=53 " "" ; } +function mpfrnr() { simple_test_case "-M -vPREC=113" "" ; } +function mpfrbigint() { simple_test_case "-M " "" ; } + +function jarebug() { + ${SRCDIR}/${TESTCASE}.sh "$GAWKEXE" "${SRCDIR}/${TESTCASE}.awk" "${SRCDIR}/${TESTCASE}.in" "_${TESTCASE}" + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function rtlen() { + ${SRCDIR}/${TESTCASE}.sh >_${TESTCASE} || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function rtlen01() { + ${SRCDIR}/${TESTCASE}.sh >_${TESTCASE} || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function rtlenmb() { + GAWKLOCALE=en_US.UTF-8 ; export GAWKLOCALE + ${SRCDIR}/rtlen.sh >_${TESTCASE} || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function nondec2() { simple_test_case "--non-decimal-data -v a=0x1" "" ; } + +function nofile() { + $GAWKEXE '{}' no/such/file >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function binmode1() { + $GAWKEXE -v BINMODE=3 'BEGIN { print BINMODE }' >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function devfd1() { + $GAWKEXE -f ${SRCDIR}/${TESTCASE}.awk 4< ${SRCDIR}/devfd.in1 5< ${SRCDIR}/devfd.in2 >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +function devfd2() { + # The program text is the '1' which will print each record. How compact can you get? + $GAWKEXE 1 /dev/fd/4 /dev/fd/5 4< ${SRCDIR}/devfd.in1 5< ${SRCDIR}/devfd.in2 >_${TESTCASE} 2>&1 || echo EXIT CODE: $? >>_${TESTCASE} + ${COMPARE} ${SRCDIR}/${TESTCASE}.ok _${TESTCASE} && rm -f _${TESTCASE} +} + +# Is this test case implemented as a function ? +if [ "$( type -t $TESTCASE )" = "function" ] +then + $TESTCASE +else + # If no function exists, then treat the test case in standard way. + simple_test_case "" "" +fi + diff --git a/cmake/configure b/cmake/configure new file mode 100755 index 00000000..d375a81c --- /dev/null +++ b/cmake/configure @@ -0,0 +1,58 @@ +#!/bin/sh +# On 2013-05-14 Arnold wrote in an e-mail: + +# <QUOTE) +# I think that using CMake would be more palatable if there is also a simple +# configure wrapper that can be used by people who build distributions. This would +# mean things like +# +# configure CC=XXXX # XXXX in { gcc, clang, tcc } or native platform cc +# configure --prefix=/path/to/install +# +# And the few other current configure options like --with-whiny-user-strftime, +# --disable-nls, etc. I don't know if we need all the standard configure options, +# but I do want the ones I've added in configure.ac. +# </QUOTE) + + +# Anyone using this script still needs an out-of-source build directory. +if [ -f CMakeLists.txt ] ; then + echo "Your current working directory contains a file CMakeLists.txt, indicating" + echo "that this is a source directory. Create a new directory elsewhere, change into" + echo "this empty directory and try again." + echo " mkdir build" + echo " cd build" + echo " ../$0" + exit 1 +fi + +# TODO: Evaluate all the options and translate the options into CMake variables. +CC=$( which cc ) +PREFIX="" +SRCDIR=".." +WHINY="" + +for p in $@ +do + if [ ${p:0:3} = "CC=" ]; then CC=${p:3}; fi + if [ ${p:0:9} = "--prefix=" ]; then PREFIX=-DCMAKE_INSTALL_PREFIX=${p:9}; fi + if [ ${p:0:9} = "--srcdir=" ]; then SRCDIR=${p:9}; fi + if [ ${p:0:26} = "--with-whiny-user-strftime" ]; then WHINY=-DUSE_INCLUDED_STRFTIME=1; fi +done +CC=$( which $CC ) + +rm -f Toolchain.cmake +( + echo "set(CMAKE_C_COMPILER $CC)" + echo "set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)" + echo "set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)" + echo "set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)" +) > Toolchain.cmake + +if ! [ -f ${SRCDIR}/CMakeLists.txt ] ; then + echo "The source directory (${SRCDIR}) does not contain a file CMakeLists.txt." + exit 1 +fi + +cmake ${PREFIX} ${WHINY} -DCMAKE_TOOLCHAIN_FILE=Toolchain.cmake ${SRCDIR} + diff --git a/cmake/configure.cmake b/cmake/configure.cmake new file mode 100644 index 00000000..7dbe841c --- /dev/null +++ b/cmake/configure.cmake @@ -0,0 +1,300 @@ +# +# cmake/configure --- CMake input file for gawk +# +# Copyright (C) 2013-2014 +# the Free Software Foundation, Inc. +# +# This file is part of GAWK, the GNU implementation of the +# AWK Programming Language. +# +# GAWK is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GAWK is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# + +## process this file with CMake to produce Makefile + +option (USE_CONFIG_H "Generate a file config.h for inclusion into C source code" ON) +if (USE_CONFIG_H) + file( WRITE config.h "/* all settings defined by CMake. */\n\n" ) + ADD_DEFINITIONS (-D HAVE_CONFIG_H) + # Configure a header file to pass some of the CMake settings + # to the source code + # http://www.cmake.org/cmake/help/v2.8.8/cmake.html#command:configure_file + # CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.cmake.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h IMMEDIATE ) +else() + file( WRITE config.h "/* empty file, all settings defined by CMake. */" ) +endif() + +include(CheckIncludeFiles) +include(CheckIncludeFile) +include(CheckSymbolExists) +include(CheckFunctionExists) +include(CheckLibraryExists) +include(CheckTypeSize) +include(CheckStructHasMember) +INCLUDE(CheckCSourceCompiles) +include(CheckPrototypeDefinition) + +MACRO(DefineConfigH feature) +# message(STATUS feature=${feature}=${${feature}}) + if (${feature}) + if (${USE_CONFIG_H} STREQUAL ON) + FILE( APPEND config.h "#define ${feature} ${${feature}}\n") + else() + #ADD_DEFINITIONS (-D ${feature}) + ADD_DEFINITIONS (-D${feature}=${${feature}}) + endif () + endif () +ENDMACRO(DefineConfigH) + +MACRO(DefineConfigHValue feature value) + set(${feature} ${value}) + DefineConfigH(${feature}) +ENDMACRO(DefineConfigHValue) + +MACRO(DefineFunctionIfAvailable func feature) + check_function_exists("${func}" "${feature}") + DefineConfigH(${feature}) +ENDMACRO(DefineFunctionIfAvailable) + +MACRO(DefineHFileIfAvailable hfile feature) + check_include_file("${hfile}" "${feature}") + DefineConfigH(${feature}) +ENDMACRO(DefineHFileIfAvailable) + +MACRO(DefineTypeIfAvailable type feature) + check_type_size("${type}" "${feature}") + DefineConfigH(${feature}) +ENDMACRO(DefineTypeIfAvailable) + +MACRO(DefineSymbolIfAvailable symbol hfile feature) + check_symbol_exists("${symbol}" "${hfile}" "${feature}") + DefineConfigH(${feature}) +ENDMACRO(DefineSymbolIfAvailable) + +MACRO(DefineStructHasMemberIfAvailable struct member hfile feature) + check_struct_has_member("${struct}" "${member}" "${hfile}" "${feature}") + DefineConfigH(${feature}) +ENDMACRO(DefineStructHasMemberIfAvailable) + +MACRO(DefineLibraryIfAvailable lib func location feature) + check_library_exists("${lib}" "${func}" "${location}" "${feature}") + DefineConfigH(${feature}) +ENDMACRO(DefineLibraryIfAvailable) + +MACRO(DefineIfSourceCompiles source feature) + check_c_source_compiles( "${source}" "${feature}") + DefineConfigH(${feature}) +ENDMACRO(DefineIfSourceCompiles) + +FILE( READ configure.ac CONFIG_AUTOMAKE ) +STRING( REGEX MATCH "AC_INIT\\(\\[GNU Awk\\], ([0-9]+\\.[0-9]+\\.[0-9]+)" GAWK_AUTOMAKE_LINE_VERSION "${CONFIG_AUTOMAKE}") +STRING( REGEX REPLACE ".*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" GAWK_MAJOR_VERSION "${GAWK_AUTOMAKE_LINE_VERSION}") +STRING( REGEX REPLACE ".*[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" GAWK_MINOR_VERSION "${GAWK_AUTOMAKE_LINE_VERSION}") +STRING( REGEX REPLACE ".*[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" GAWK_BUGFIX_VERSION "${GAWK_AUTOMAKE_LINE_VERSION}") + +# The definition of the symbol GAWK cannot be passed in config.h +# because the extensions will fail to build. +add_definitions(-DGAWK) +DefineConfigHValue(_GL_ATTRIBUTE_PURE "__attribute__ ((__pure__))") +DefineConfigHValue(GAWK_VERSION "${GAWK_MAJOR_VERSION}.${GAWK_MINOR_VERSION}.${GAWK_BUGFIX_VERSION}") +DefineConfigHValue(VERSION \\"${GAWK_VERSION}\\") +DefineConfigHValue(PACKAGE \\"gawk\\") +DefineConfigHValue(PACKAGE_STRING \\"GNU Awk ${GAWK_VERSION}\\") +DefineConfigHValue(PACKAGE_TARNAME \\"gawk\\") +DefineConfigHValue(PACKAGE_URL \\"http://www.gnu.org/software/gawk/\\") +DefineConfigHValue(PACKAGE_VERSION \\"${GAWK_VERSION}\\") +DefineConfigHValue(DEFPATH \\"${CMAKE_BINARY_DIR}/awk\\") +DefineConfigHValue(DEFLIBPATH \\"${CMAKE_BINARY_DIR}/lib\\") +if (CMAKE_DL_LIBS) + message(STATUS "Found CMAKE_DL_LIBS:${CMAKE_DL_LIBS}") +else() + message(STATUS "Found no CMAKE_DL_LIBS") +endif() +if (CMAKE_SHARED_LIBRARY_SUFFIX) + DefineConfigHValue(DYNAMIC 1) + STRING( REGEX REPLACE "^(\\.)([a-zA-Z0-9])" "\\2" SHLIBEXT "${CMAKE_SHARED_LIBRARY_SUFFIX}") + DefineConfigHValue(SHLIBEXT \\"${SHLIBEXT}\\") + message(STATUS "Found SHLIBEXT: ${SHLIBEXT}") +else() + message(STATUS "Found no SHLIBEXT") +endif() +DefineTypeIfAvailable("unsigned int" SIZEOF_UNSIGNED_INT) +DefineTypeIfAvailable("unsigned long" SIZEOF_UNSIGNED_LONG) +#/* Define to 1 if *printf supports %F format */ +add_definitions(-D PRINTF_HAS_F_FORMAT) +#/* Define as the return type of signal handlers (`int' or `void'). */ +add_definitions(-D RETSIGTYPE=void) +#add_definitions(-D PIPES_SIMULATED) +check_prototype_definition(getpgrp "pid_t getpgrp(void)" "NULL" "unistd.h" GETPGRP_VOID) +DefineConfigH(GETPGRP_VOID) +#add_definitions(-D YYPARSE_PARAM) + +DefineFunctionIfAvailable(snprintf HAVE_SNPRINTF) +DefineFunctionIfAvailable(vprintf HAVE_VPRINTF) +DefineHFileIfAvailable(sys/types.h HAVE_SYS_TYPES_H) +DefineHFileIfAvailable(sys/stat.h HAVE_SYS_STAT_H) +DefineHFileIfAvailable(string.h HAVE_STRING_H) +DefineHFileIfAvailable(memory.h HAVE_MEMORY_H) +DefineHFileIfAvailable(strings.h HAVE_STRINGS_H) +DefineHFileIfAvailable(stdint.h HAVE_STDINT_H) +DefineHFileIfAvailable(inttypes.h HAVE_INTTYPES_H) +DefineHFileIfAvailable(stdlib.h HAVE_STDLIB_H) +DefineHFileIfAvailable(unistd.h HAVE_UNISTD_H) +FIND_PATH(INTL_INCLUDE_DIR libintl.h PATHS /usr/include /usr/local/include) +FIND_LIBRARY(INTL_LIBRARIES intl c PATHS /usr/lib/ /usr/local/lib) +DefineSymbolIfAvailable("CODESET" "langinfo.h" HAVE_LANGINFO_CODESET) +DefineSymbolIfAvailable("LC_MESSAGES" "locale.h" HAVE_LC_MESSAGES) +DefineTypeIfAvailable("_Bool" HAVE__BOOL) +if (${HAVE_GETTEXT} AND ${HAVE_DCGETTEXT} AND ${HAVE_LANGINFO_CODESET} AND ${HAVE_LC_MESSAGES}) + add_definitions(-D LOCALEDIR=\\"/usr/share/locale\\") + add_definitions(-D ENABLE_NLS) + ADD_SUBDIRECTORY( po ) +endif() +DefineHFileIfAvailable(stdbool.h HAVE_STDBOOL_H) +DefineHFileIfAvailable(sys/wait.h HAVE_SYS_WAIT_H) +DefineHFileIfAvailable(arpa/inet.h HAVE_ARPA_INET_H) +DefineHFileIfAvailable(fcntl.h HAVE_FCNTL_H) +DefineHFileIfAvailable(limits.h HAVE_LIMITS_H) +DefineHFileIfAvailable(locale.h HAVE_LOCALE_H) +DefineHFileIfAvailable(libintl.h HAVE_LIBINTL_H) +DefineHFileIfAvailable(mcheck.h HAVE_MCHECK_H) +DefineHFileIfAvailable(netdb.h HAVE_NETDB_H) +DefineHFileIfAvailable(netinet/in.h HAVE_NETINET_IN_H) +DefineHFileIfAvailable(stdarg.h HAVE_STDARG_H) +DefineHFileIfAvailable(stddef.h HAVE_STDDEF_H) +DefineHFileIfAvailable(sys/ioctl.h HAVE_SYS_IOCTL_H) +DefineHFileIfAvailable(sys/param.h HAVE_SYS_PARAM_H) +DefineHFileIfAvailable(sys/socket.h HAVE_SYS_SOCKET_H) +DefineHFileIfAvailable(sys/termios.h HAVE_TERMIOS_H) +DefineHFileIfAvailable(stropts.h HAVE_STROPTS_H) +DefineHFileIfAvailable(wchar.h HAVE_WCHAR_H) +DefineHFileIfAvailable(wctype.h HAVE_WCTYPE_H) +DefineTypeIfAvailable("long long int" HAVE_LONG_LONG_INT) +DefineTypeIfAvailable("unsigned long long int" HAVE_UNSIGNED_LONG_LONG_INT) +DefineTypeIfAvailable(intmax_t INTMAX_T) +DefineTypeIfAvailable(uintmax_t UINTMAX_T) +DefineTypeIfAvailable("time_t" TIME_T_IN_SYS_TYPES_H) +SET(CMAKE_EXTRA_INCLUDE_FILES wctype.h) +DefineTypeIfAvailable("wctype_t" HAVE_WCTYPE_T) +DefineTypeIfAvailable("wint_t" HAVE_WINT_T) +SET(CMAKE_EXTRA_INCLUDE_FILES) + +DefineStructHasMemberIfAvailable("struct sockaddr_storage" ss_family sys/socket.h HAVE_SOCKADDR_STORAGE) +DefineStructHasMemberIfAvailable("struct stat" st_blksize sys/stat.h HAVE_STRUCT_STAT_ST_BLKSIZE) +DefineStructHasMemberIfAvailable("struct stat" st_blksize sys/stat.h HAVE_ST_BLKSIZE) +DefineStructHasMemberIfAvailable("struct tm" tm_zone time.h HAVE_TM_ZONE) +DefineStructHasMemberIfAvailable("struct tm" tm_zone time.h HAVE_STRUCT_TM_TM_ZONE) + +DefineHFileIfAvailable(sys/time.h HAVE_SYS_TIME_H) +DefineFunctionIfAvailable(alarm HAVE_ALARM) +DefineFunctionIfAvailable(tzname HAVE_DECL_TZNAME) +DefineFunctionIfAvailable(mktime HAVE_MKTIME) +DefineFunctionIfAvailable(getaddrinfo HAVE_GETADDRINFO) +DefineFunctionIfAvailable(atexit HAVE_ATEXIT) +DefineFunctionIfAvailable(btowc HAVE_BTOWC) +DefineFunctionIfAvailable(fmod HAVE_FMOD) +DefineFunctionIfAvailable(isinf HAVE_ISINF) +DefineFunctionIfAvailable(ismod HAVE_ISMOD) +DefineFunctionIfAvailable(getgrent HAVE_GETGRENT) +DefineSymbolIfAvailable("getgroups" "unistd.h" HAVE_GETGROUPS) +if (${HAVE_GETGROUPS}) + check_prototype_definition(getgroups "int getgroups(int size, gid_t list[])" "NULL" "unistd.h" GETGROUPS_T) + if (${GETGROUPS_T}) + DefineConfigHValue(GETGROUPS_T gid_t) + else() + DefineConfigHValue(GETGROUPS_T int) + endif() +endif() + +DefineTypeIfAvailable("pid_t" PID_T) +DefineTypeIfAvailable("intmax_t" HAVE_INTMAX_T) +DefineFunctionIfAvailable(grantpt HAVE_GRANTPT) +DefineFunctionIfAvailable(isascii HAVE_ISASCII) +DefineFunctionIfAvailable(iswctype HAVE_ISWCTYPE) +DefineFunctionIfAvailable(iswlower HAVE_ISWLOWER) +DefineFunctionIfAvailable(iswupper HAVE_ISWUPPER) +DefineFunctionIfAvailable(mbrlen HAVE_MBRLEN) +DefineFunctionIfAvailable(memcmp HAVE_MEMCMP) +DefineFunctionIfAvailable(memcpy HAVE_MEMCPY) +DefineFunctionIfAvailable(memmove HAVE_MEMMOVE) +DefineFunctionIfAvailable(memset HAVE_MEMSET) +DefineFunctionIfAvailable(mkstemp HAVE_MKSTEMP) +DefineFunctionIfAvailable(posix_openpt HAVE_POSIX_OPENPT) +DefineFunctionIfAvailable(setenv HAVE_SETENV) +DefineFunctionIfAvailable(setlocale HAVE_SETLOCALE) +DefineFunctionIfAvailable(setsid HAVE_SETSID) +DefineFunctionIfAvailable(strchr HAVE_STRCHR) +DefineFunctionIfAvailable(strerror HAVE_STRERROR) +DefineFunctionIfAvailable(strftime HAVE_STRFTIME) +DefineFunctionIfAvailable(strncasecmp HAVE_STRNCASECMP) +DefineFunctionIfAvailable(strcoll HAVE_STRCOLL) +DefineFunctionIfAvailable(strtod HAVE_STRTOD) +DefineFunctionIfAvailable(strtoul HAVE_STRTOUL) +DefineFunctionIfAvailable(system HAVE_SYSTEM) +DefineFunctionIfAvailable(tmpfile HAVE_TMPFILE) +DefineFunctionIfAvailable(towlower HAVE_TOWLOWER) +DefineFunctionIfAvailable(towupper HAVE_TOWUPPER) +DefineFunctionIfAvailable(tzset HAVE_TZSET) +DefineFunctionIfAvailable(usleep HAVE_USLEEP) +DefineFunctionIfAvailable(wcrtomb HAVE_WCRTOMB) +DefineFunctionIfAvailable(wcscoll HAVE_WCSCOLL) +DefineFunctionIfAvailable(wctype HAVE_WCTYPE) +DefineFunctionIfAvailable(mbrtowc HAVE_MBRTOWC) + +add_definitions(-D HAVE_STRINGIZE) +add_definitions(-D _Noreturn=) + +find_package(BISON QUIET) +# If there is a bison installed on this platform, +if (${BISON_FOUND} STREQUAL "TRUE") + # then let bison generate awkgram.c. + BISON_TARGET(awkgram awkgram.y ${CMAKE_SOURCE_DIR}/awkgram.c) +else() + # otherwise use the existing awkgram.c. + set(BISON_awkgram_OUTPUTS ${CMAKE_SOURCE_DIR}/awkgram.c) +endif() + +find_package(Gettext REQUIRED) +if (GETTEXT_FOUND STREQUAL "TRUE") + include_directories(${GETTEXT_INCLUDE_DIR}) + DefineFunctionIfAvailable(gettext HAVE_GETTEXT) + DefineFunctionIfAvailable(dcgettext HAVE_DCGETTEXT) +else () + message( FATAL_ERROR "Gettext not found" ) +endif() + +find_package(LATEX) +include(GNUInstallDirs) +include(GetPrerequisites) + +# For some unknown reason the defines for the extensions +# are written into config.h only if they are implemented +# here and not in extension/CMakeLists.txt. +DefineLibraryIfAvailable(m sin "" HAVE_LIBM) +DefineLibraryIfAvailable(mpfr mpfr_add_si "" HAVE_MPFR) +DefineLibraryIfAvailable(c socket "" HAVE_SOCKETS) +DefineLibraryIfAvailable(readline readline "" HAVE_LIBREADLINE) +DefineFunctionIfAvailable(fnmatch HAVE_FNMATCH) +DefineHFileIfAvailable(fnmatch.h HAVE_FNMATCH_H) +DefineHFileIfAvailable(dirent.h HAVE_DIRENT_H) +DefineFunctionIfAvailable(dirfd HAVE_DIRFD) +DefineFunctionIfAvailable(getdtablesize HAVE_GETDTABLESIZE) +DefineFunctionIfAvailable(select HAVE_SELECT) +DefineFunctionIfAvailable(gettimeofday HAVE_GETTIMEOFDAY) +DefineHFileIfAvailable(sys/select.h HAVE_SYS_SELECT_H) +DefineFunctionIfAvailable(nanosleep HAVE_NANOSLEEP) +DefineHFileIfAvailable(time.h HAVE_TIME_H) +DefineFunctionIfAvailable(GetSystemTimeAsFileTime HAVE_GETSYSTEMTIMEASFILETIME) + diff --git a/cmake/docmaker b/cmake/docmaker new file mode 100755 index 00000000..4af7cee1 --- /dev/null +++ b/cmake/docmaker @@ -0,0 +1,100 @@ +#!/bin/sh + +# The first parameter is the target, the file to be built. +# All remaining parameters are dependencies (file names). +if [ $# -lt 1 ] ; then + echo " $0: Incorrect number ($#) of parameters passed: $*" + exit 1 +fi +OUTFILE=$1 +shift 1 +INFILES="$@" + +MAKEINFO="makeinfo --no-split --force" +TROFF="groff -t -Tps -U" +SEDME="sed -e \"s/^level0 restore/level0 restore flashme 100 72 moveto (Copyright `date '+%m-%d-%y %T'`, FSF, Inc. (all)) show/\" -e \"s/^\/level0 save def/\/level0 save def 30 -48 translate/\"" +SEDME2="sed '/%%Page: 10 10/,/0 Cg EP/d'" + +function BuildTarget() +{ + local OUTFILE=$1 + local INFILE="" + local COMMAND="" + + FILEBASE=${OUTFILE%.*} + case $OUTFILE in + *\.in | *\.1 | macros | cardfonts | colors | ad.block | setter.outline | \ + gawkinet.texi | rflashlight.eps | api-figure1.fig | api-figure2.fig | api-figure3.fig | \ + general-program.fig | process-flow.fig | statist.eps) + INFILE=$OUTFILE + ;; + *\.texi) + if [ $FILEBASE = gawk ] ; then + INFILE=gawktexi.in + else + INFILE=$OUTFILE.in + fi + COMMAND="awk -f sidebar.awk < $INFILE > $OUTFILE" + ;; + *\.dvi) + INFILE=$FILEBASE.texi + COMMAND="texi2dvi -q --clean $INFILE" + ;; + *\.info) + INFILE=$FILEBASE.texi + COMMAND="${MAKEINFO} $INFILE" + ;; + *\.ps) + if [ $FILEBASE = awkcard ] ; then + INFILE=awkcard.in + COMMAND="${TROFF} $* | ${SEDME} | cat setter.outline - | ${SEDME2} > awkcard.ps" + elif [ $FILEBASE = gawk.1 -o $FILEBASE = igawk.1 ] ; then + INFILE=$FILEBASE + COMMAND="groff -z -man $INFILE > $OUTFILE" + else + INFILE=$FILEBASE.dvi + COMMAND="dvips -q -o $OUTFILE $INFILE" + fi + ;; + *\.pdf) + INFILE=$FILEBASE.ps + COMMAND="ps2pdf -q $INFILE $OUTFILE" + ;; + *\.tr) + INFILE=$FILEBASE.in + COMMAND="sed 's:SRCDIR:.:' < $INFILE > $OUTFILE" + ;; + *\.nc) + INFILE=$FILEBASE.in + COMMAND="sed 's:SRCDIR:.:' < $INFILE > $OUTFILE" + COMMAND="${TROFF} $* | ${SEDME} | cat setter.outline - | ${SEDME2} > $FILEBASE.ps && touch $OUTFILE" + ;; + *) + echo " unknwon target $OUTFILE" + exit 1 + esac + + if [ ! -r "$INFILE" ] ; then + echo " $0: Cannot read input file $INFILE" + exit 1 + fi + + if [ -f "$OUTFILE" ] ; then + if [ "$INFILE" -ot "$OUTFILE" ] ; then + #printf " Target %15s is up-to-date\n" $OUTFILE + COMMAND="" + fi + fi + #echo " Generating $OUTFILE from $INFILE" + echo $COMMAND | sh -x + #echo "COMMAND=$COMMAND" +} + +# Build all dependencies first, then build the target. +for dep in $INFILES +do + #echo $OUTFILE depends on $dep + BuildTarget $dep +done +BuildTarget $OUTFILE + diff --git a/cmake/package.cmake b/cmake/package.cmake new file mode 100644 index 00000000..203a8c3b --- /dev/null +++ b/cmake/package.cmake @@ -0,0 +1,54 @@ +# +# cmake/package --- CMake input file for gawk +# +# Copyright (C) 2013-2014 +# the Free Software Foundation, Inc. +# +# This file is part of GAWK, the GNU implementation of the +# AWK Programming Language. +# +# GAWK is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GAWK is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# + +## process this file with CMake to produce Makefile + +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "This is GNU Awk ${GAWK_VERSION}") +set(CPACK_PACKAGE_VENDOR "GNU Project - Free Software Foundation (FSF)") +SET(CPACK_PACKAGE_NAME "gawk") +SET(CPACK_PACKAGE_VERSION "${GAWK_VERSION}") +SET(CPACK_PACKAGE_VERSION_MAJOR "${GAWK_MAJOR_VERSION}") +SET(CPACK_PACKAGE_VERSION_MINOR "${GAWK_MINOR_VERSION}") +SET(CPACK_PACKAGE_VERSION_PATCH "${GAWK_BUGFIX_VERSION}") +SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING") +SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README") +set(CPACK_PACKAGE_CONTACT "bug-gawk@gnu.org") + +IF (WIN32) + SET(CPACK_GENERATOR "NSIS") + set(CPACK_NSIS_INSTALL_ROOT "C:") + set(CPACK_NSIS_MENU_LINKS "http://www.gnu.org/software/gawk" "GNU Awk") + set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/cmake/auk.ico") + set(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}/cmake/auk.ico") + set(CPACK_NSIS_CONTACT "bug-gawk@gnu.org") + set(CPACK_NSIS_DISPLAY_NAME "GNU Awk") +ELSE() + SET(CPACK_PACKAGING_INSTALL_PREFIX /usr) + IF(NOT CPACK_GENERATOR) + SET(CPACK_GENERATOR "TGZ") + ENDIF() + message(STATUS "CPACK_GENERATOR set to ${CPACK_GENERATOR}") +ENDIF() + +INCLUDE(CPack) @@ -2515,7 +2515,7 @@ append_statement(CMDARG *stmt_list, char *stmt) len += strlen(a->a_string) + 1; /* 1 for ',' */ len += EVALSIZE; - emalloc(s, char *, (len + 2) * sizeof(char), "append_statement"); + emalloc(s, char *, (len + 1) * sizeof(char), "append_statement"); arg = mk_cmdarg(D_string); arg->a_string = s; arg->a_count = len; /* kludge */ @@ -2542,7 +2542,7 @@ append_statement(CMDARG *stmt_list, char *stmt) ssize = stmt_list->a_count; if (len > ssize - slen) { ssize = slen + len + EVALSIZE; - erealloc(s, char *, (ssize + 2) * sizeof(char), "append_statement"); + erealloc(s, char *, (ssize + 1) * sizeof(char), "append_statement"); stmt_list->a_string = s; stmt_list->a_count = ssize; } @@ -2554,7 +2554,7 @@ append_statement(CMDARG *stmt_list, char *stmt) } if (stmt == end_EVAL) - erealloc(stmt_list->a_string, char *, slen + 2, "append_statement"); + erealloc(stmt_list->a_string, char *, slen + 1, "append_statement"); return stmt_list; #undef EVALSIZE @@ -2927,7 +2927,7 @@ again: bool esc_seen = false; toklen = lexend - lexptr; - emalloc(str, char *, toklen + 2, "yylex"); + emalloc(str, char *, toklen + 1, "yylex"); p = str; while ((c = *++lexptr) != '"') { @@ -3139,7 +3139,7 @@ concat_args(CMDARG *arg, int count) arg = arg->next; } - emalloc(str, char *, len + 2, "concat_args"); + emalloc(str, char *, len + 1, "concat_args"); n = tmp[0]; memcpy(str, n->stptr, n->stlen); p = str + n->stlen; @@ -765,7 +765,7 @@ append_statement(CMDARG *stmt_list, char *stmt) len += strlen(a->a_string) + 1; /* 1 for ',' */ len += EVALSIZE; - emalloc(s, char *, (len + 2) * sizeof(char), "append_statement"); + emalloc(s, char *, (len + 1) * sizeof(char), "append_statement"); arg = mk_cmdarg(D_string); arg->a_string = s; arg->a_count = len; /* kludge */ @@ -792,7 +792,7 @@ append_statement(CMDARG *stmt_list, char *stmt) ssize = stmt_list->a_count; if (len > ssize - slen) { ssize = slen + len + EVALSIZE; - erealloc(s, char *, (ssize + 2) * sizeof(char), "append_statement"); + erealloc(s, char *, (ssize + 1) * sizeof(char), "append_statement"); stmt_list->a_string = s; stmt_list->a_count = ssize; } @@ -804,7 +804,7 @@ append_statement(CMDARG *stmt_list, char *stmt) } if (stmt == end_EVAL) - erealloc(stmt_list->a_string, char *, slen + 2, "append_statement"); + erealloc(stmt_list->a_string, char *, slen + 1, "append_statement"); return stmt_list; #undef EVALSIZE @@ -1177,7 +1177,7 @@ again: bool esc_seen = false; toklen = lexend - lexptr; - emalloc(str, char *, toklen + 2, "yylex"); + emalloc(str, char *, toklen + 1, "yylex"); p = str; while ((c = *++lexptr) != '"') { @@ -1389,7 +1389,7 @@ concat_args(CMDARG *arg, int count) arg = arg->next; } - emalloc(str, char *, len + 2, "concat_args"); + emalloc(str, char *, len + 1, "concat_args"); n = tmp[0]; memcpy(str, n->stptr, n->stlen); p = str + n->stlen; @@ -168,6 +168,9 @@ /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID +/* Define to 1 if you have the `sigprocmask' function. */ +#undef HAVE_SIGPROCMASK + /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF @@ -302,6 +305,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 @@ -332,9 +338,6 @@ /* enable severe portability problems */ #undef I_DONT_KNOW_WHAT_IM_DOING -/* libc is broken for regex handling */ -#undef LIBC_IS_BORKED - /* disable lint checks */ #undef NO_LINT @@ -362,9 +365,6 @@ /* Define to 1 if *printf supports %F format */ #undef PRINTF_HAS_F_FORMAT -/* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE - /* The size of `unsigned int', as computed by sizeof. */ #undef SIZEOF_UNSIGNED_INT @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for GNU Awk 4.1.3h. +# Generated by GNU Autoconf 2.69 for GNU Awk 4.1.60. # # Report bugs to <bug-gawk@gnu.org>. # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='GNU Awk' PACKAGE_TARNAME='gawk' -PACKAGE_VERSION='4.1.3h' -PACKAGE_STRING='GNU Awk 4.1.3h' +PACKAGE_VERSION='4.1.60' +PACKAGE_STRING='GNU Awk 4.1.60' PACKAGE_BUGREPORT='bug-gawk@gnu.org' PACKAGE_URL='http://www.gnu.org/software/gawk/' @@ -1328,7 +1328,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures GNU Awk 4.1.3h to adapt to many kinds of systems. +\`configure' configures GNU Awk 4.1.60 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1398,7 +1398,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of GNU Awk 4.1.3h:";; + short | recursive ) echo "Configuration of GNU Awk 4.1.60:";; esac cat <<\_ACEOF @@ -1517,7 +1517,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -GNU Awk configure 4.1.3h +GNU Awk configure 4.1.60 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2226,7 +2226,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by GNU Awk $as_me 4.1.3h, which was +It was created by GNU Awk $as_me 4.1.60, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3109,7 +3109,7 @@ fi # Define the identity of the package. PACKAGE='gawk' - VERSION='4.1.3h' + VERSION='4.1.60' cat >>confdefs.h <<_ACEOF @@ -4931,524 +4931,167 @@ else $as_echo "no, using $LN_S" >&6; } fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdbool.h> +#include <stdlib.h> +#include <wchar.h> +#include <stdio.h> -fi +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } +struct incomplete_array +{ + int datasize; + double data[]; +}; -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done +struct named_init { + int number; + const wchar_t *name; + double average; +}; -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ +typedef const char *ccp; -int -main () +static inline int +test_restrict (ccp restrict text) { -#ifndef __GNUC__ - choke me -#endif - - ; + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; return 0; } -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) { + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); - ; - return 0; + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); } -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ int main () { - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : + // Check bool. + _Bool success = false; -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; -int -main () -{ + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdarg.h> -#include <stdio.h> -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg + ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break + test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in +case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; @@ -5456,206 +5099,14 @@ $as_echo "none needed" >&6; } ;; { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac -if test "x$ac_cv_prog_cc_c89" != xno; then : +if test "x$ac_cv_prog_cc_c99" != xno; then : fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 -$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } -if ${am_cv_prog_cc_c_o+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF - # Make sure it works both with $CC and with simple cc. - # Following AC_PROG_CC_C_O, we do the test twice because some - # compilers refuse to overwrite an existing .o file with -o, - # though they will create one. - am_cv_prog_cc_c_o=yes - for am_i in 1 2; do - if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 - ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } \ - && test -f conftest2.$ac_objext; then - : OK - else - am_cv_prog_cc_c_o=no - break - fi - done - rm -f core conftest* - unset am_i -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 -$as_echo "$am_cv_prog_cc_c_o" >&6; } -if test "$am_cv_prog_cc_c_o" != yes; then - # Losing compiler, so override with the script. - # FIXME: It is wrong to rewrite CC. - # But if we don't then we get into trouble of one sort or another. - # A longer-term fix would be to have automake use am__CC in this case, - # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" - CC="$am_aux_dir/compile $CC" -fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named 'D' -- because '-MD' means "put the output - # in D". - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with - # Solaris 10 /bin/sh. - echo '/* dummy */' > sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with '-c' and '-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle '-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs. - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # After this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested. - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok '-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -5955,14 +5406,12 @@ $as_echo "$as_me: WARNING: unrecognized compiler environment" >&2;} esac fi # ac_cv_zos_uss = yes - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strerror in -lcposix" >&5 -$as_echo_n "checking for strerror in -lcposix... " >&6; } -if ${ac_cv_lib_cposix_strerror+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 +$as_echo_n "checking for library containing strerror... " >&6; } +if ${ac_cv_search_strerror+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcposix $LIBS" + ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -5981,22 +5430,37 @@ return strerror (); return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_cposix_strerror=yes -else - ac_cv_lib_cposix_strerror=no +for ac_lib in '' cposix; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_strerror=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cposix_strerror" >&5 -$as_echo "$ac_cv_lib_cposix_strerror" >&6; } -if test "x$ac_cv_lib_cposix_strerror" = xyes; then : - LIBS="$LIBS -lcposix" + conftest$ac_exeext + if ${ac_cv_search_strerror+:} false; then : + break fi +done +if ${ac_cv_search_strerror+:} false; then : +else + ac_cv_search_strerror=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 +$as_echo "$ac_cv_search_strerror" >&6; } +ac_res=$ac_cv_search_strerror +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +fi # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : @@ -6199,51 +5663,6 @@ rm -rf conftest* fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AIX compilation hacks" >&5 -$as_echo_n "checking for AIX compilation hacks... " >&6; } -if ${gawk_cv_aix_hack+:} false; then : - $as_echo_n "(cached) " >&6 -else - -if test -d /lpp -then - CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED=1 -DGAWK_AIX=1" - gawk_cv_aix_hack=yes -else - gawk_cv_aix_hack=no -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${gawk_cv_aix_hack}" >&5 -$as_echo "${gawk_cv_aix_hack}" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux/Alpha compilation hacks" >&5 -$as_echo_n "checking for Linux/Alpha compilation hacks... " >&6; } -if ${gawk_cv_linux_alpha_hack+:} false; then : - $as_echo_n "(cached) " >&6 -else - -if test "Linux" = "`uname`" && test "alpha" = "`uname -m`" -then - # this isn't necessarily always true, - # the vendor's compiler is also often found - if test "$GCC" = yes - then - CFLAGS="$CFLAGS -mieee" - gawk_cv_linux_alpha_hack=yes - else - gawk_cv_linux_alpha_hack=no - fi -else - gawk_cv_linux_alpha_hack=no -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${gawk_cv_linux_alpha_hack}" >&5 -$as_echo "${gawk_cv_linux_alpha_hack}" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we are using EBCDIC" >&5 $as_echo_n "checking if we are using EBCDIC... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6266,19 +5685,6 @@ rm -f conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_ebcdic" >&5 $as_echo "$use_ebcdic" >&6; } -if test "$ISC" = 1 # will be set by test for ISC -then - CFLAGS="$CFLAGS -D_SYSV3" -fi - -case $host_os in -mirbsd*) - -$as_echo "#define LIBC_IS_BORKED 1" >>confdefs.h - - ;; -esac - ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -8843,39 +8249,6 @@ _ACEOF fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 -$as_echo_n "checking return type of signal handlers... " >&6; } -if ${ac_cv_type_signal+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <sys/types.h> -#include <signal.h> - -int -main () -{ -return *(signal (0, 0)) (0) == 1; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_type_signal=int -else - ac_cv_type_signal=void -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 -$as_echo "$ac_cv_type_signal" >&6; } - -cat >>confdefs.h <<_ACEOF -#define RETSIGTYPE $ac_cv_type_signal -_ACEOF - - ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : @@ -10440,9 +9813,10 @@ esac for ac_func in __etoa_l 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` @@ -11497,7 +10871,7 @@ dylib) GAWKLIBEXT=so ;; # MacOS uses .dylib for shared libraries, but libtool us esac -ac_config_files="$ac_config_files Makefile awklib/Makefile doc/Makefile po/Makefile.in test/Makefile" +ac_config_files="$ac_config_files Makefile awklib/Makefile doc/Makefile extras/Makefile po/Makefile.in test/Makefile" if test "x$enable_extensions" = "xyes"; then @@ -11638,10 +11012,6 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${TEST_CROSS_COMPILE_TRUE}" && test -z "${TEST_CROSS_COMPILE_FALSE}"; then as_fn_error $? "conditional \"TEST_CROSS_COMPILE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -12047,7 +11417,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by GNU Awk $as_me 4.1.3h, which was +This file was extended by GNU Awk $as_me 4.1.60, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12115,7 +11485,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -GNU Awk config.status 4.1.3h +GNU Awk config.status 4.1.60 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -12257,6 +11627,7 @@ do "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "awklib/Makefile") CONFIG_FILES="$CONFIG_FILES awklib/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "extras/Makefile") CONFIG_FILES="$CONFIG_FILES extras/Makefile" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; diff --git a/configure.ac b/configure.ac index 36d2cd4f..bfe785db 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ dnl dnl Process this file with autoconf to produce a configure script. -AC_INIT([GNU Awk], 4.1.3h, bug-gawk@gnu.org, gawk) +AC_INIT([GNU Awk],[4.1.60],[bug-gawk@gnu.org],[gawk]) # This is a hack. Different versions of install on different systems # are just too different. Chuck it and use install-sh. @@ -39,7 +39,7 @@ then export INSTALL fi -AC_PREREQ(2.69) +AC_PREREQ([2.69]) AM_INIT_AUTOMAKE([1.15 dist-xz dist-lzip]) AC_CONFIG_MACRO_DIR([m4]) @@ -72,7 +72,7 @@ dnl checks for programs AC_PROG_EGREP AC_PROG_YACC AC_PROG_LN_S -AC_PROG_CC +AC_PROG_CC_C99 AC_PROG_CPP AC_OBJEXT @@ -110,10 +110,8 @@ AC_SUBST([pkgextensiondir], ['${pkglibdir}']) dnl checks for systems AC_ZOS_USS -AC_ISC_POSIX +AC_SEARCH_LIBS([strerror],[cposix]) AC_SYS_LARGEFILE -GAWK_AC_AIX_TWEAK -GAWK_AC_LINUX_ALPHA AC_MSG_CHECKING([if we are using EBCDIC]) AC_EGREP_CPP([gnu_gawk_in_ebcdic], @@ -125,19 +123,6 @@ gnu_gawk_in_ebcdic [use_ebcdic=no]) AC_MSG_RESULT([$use_ebcdic]) -if test "$ISC" = 1 # will be set by test for ISC -then -dnl need -D_SYSV3 for ISC - CFLAGS="$CFLAGS -D_SYSV3" -fi - -dnl check for systems where libc is borked for regex handling -case $host_os in -mirbsd*) - AC_DEFINE([LIBC_IS_BORKED], 1, [libc is broken for regex handling]) - ;; -esac - dnl Set the programming language for checks. Fortunately, dnl this only needs to be set once, since everything is in C. AC_LANG([C]) @@ -170,8 +155,7 @@ AM_CONDITIONAL([TEST_CROSS_COMPILE], [test "x$build_alias" != "x$host_alias"]) dnl checks for typedefs AC_TYPE_PID_T -AC_TYPE_SIGNAL -AC_SIZE_T +AC_TYPE_SIZE_T AC_TYPE_GETGROUPS AC_TYPE_LONG_LONG_INT AC_TYPE_UNSIGNED_LONG_LONG_INT @@ -181,30 +165,26 @@ AC_CHECK_TYPE(ssize_t, int) AC_CHECK_SIZEOF(unsigned int) AC_CHECK_SIZEOF(unsigned long) dnl see if time_t is defined in <sys/types.h> -AC_TRY_COMPILE([#include <sys/types.h>],[ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], [[ time_t foo; foo = 0; -], - AC_DEFINE(TIME_T_IN_SYS_TYPES_H, 1, - [some systems define this type here])) +]])],[AC_DEFINE(TIME_T_IN_SYS_TYPES_H, 1, + some systems define this type here)],[]) dnl check for wctype_t in <wctype.h> -AC_TRY_COMPILE([#include <wctype.h>],[ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <wctype.h>]], [[ wctype_t foo; foo = 0; -], - AC_DEFINE(HAVE_WCTYPE_T, 1, [systems should define this type here])) +]])],[AC_DEFINE(HAVE_WCTYPE_T, 1, systems should define this type here)],[]) dnl check for wint_t in <wctype.h> -AC_TRY_COMPILE([#include <wctype.h>],[ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <wctype.h>]], [[ wint_t foo; foo = 0; -], - AC_DEFINE(HAVE_WINT_T, 1, [systems should define this type here])) +]])],[AC_DEFINE(HAVE_WINT_T, 1, systems should define this type here)],[]) dnl check for sockaddr_storage -AC_TRY_COMPILE([#include <sys/types.h> -#include <sys/socket.h>],[ +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h> +#include <sys/socket.h>]], [[ struct sockaddr_storage foo; -], - AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1, [newer systems define this type here])) +]])],[AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1, newer systems define this type here)],[]) dnl Borrwed from rsync, thanks to to Jim Meyering. @@ -227,18 +207,18 @@ AC_DEFUN([TYPE_SOCKLEN_T], rsync_cv_socklen_t_equiv= for arg2 in "struct sockaddr" void; do for t in int size_t unsigned long "unsigned long"; do - AC_TRY_COMPILE([ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> #include <sys/socket.h> int getpeername (int, $arg2 *, $t *); - ],[ + ]], [[ $t len; getpeername(0,0,&len); - ],[ + ]])],[ rsync_cv_socklen_t_equiv="$t" break - ]) + ],[]) done done @@ -286,9 +266,10 @@ esac AC_CHECK_FUNCS(__etoa_l 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 @@ -420,6 +401,7 @@ AC_SUBST(GAWKLIBEXT) AC_CONFIG_FILES(Makefile awklib/Makefile doc/Makefile + extras/Makefile po/Makefile.in test/Makefile) if test "x$enable_extensions" = "xyes"; then @@ -60,6 +60,10 @@ #define _TZSET 1 #endif +#if defined(_AIX) +#define _XOPEN_SOURCE_EXTENDED 1 +#endif + /* Junk for dfa.[ch] */ /* The __pure__ attribute was added in gcc 2.96. */ #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) @@ -1736,6 +1736,8 @@ watchpoint_triggered(struct list_item *w) /* new != NULL */ if (t2->type == Node_val) w->cur_value = dupnode(t2); + else if (t2->type == Node_typedregex) + w->cur_value = dupnode(t2); else { w->flags |= CUR_IS_ARRAY; w->cur_size = (t2->type == Node_var_array) ? assoc_length(t2) : 0; @@ -1748,6 +1750,7 @@ watchpoint_triggered(struct list_item *w) w->flags |= CUR_IS_ARRAY; w->cur_size = assoc_length(t2); } else + /* works for Node_typedregex too */ w->cur_value = dupnode(t2); } @@ -1790,6 +1793,8 @@ initialize_watch_item(struct list_item *w) } else if (symbol->type == Node_var_array) { w->flags |= CUR_IS_ARRAY; w->cur_size = assoc_length(symbol); + } else if (symbol->type == Node_typedregex) { + w->cur_value = dupnode(symbol); } /* else can't happen */ } @@ -3699,22 +3704,14 @@ print_memory(NODE *m, NODE *func, Func_print print_func, FILE *fp) print_func(fp, "%g", m->numbr); } else if ((m->flags & STRING) != 0) pp_string_fp(print_func, fp, m->stptr, m->stlen, '"', false); - else if ((m->flags & NUMCUR) != 0) { -#ifdef HAVE_MPFR - if ((m->flags & MPFN) != 0) - print_func(fp, "%s", mpg_fmt("%R*g", ROUND_MODE, m->mpg_numbr)); - else if ((m->flags & MPZN) != 0) - print_func(fp, "%s", mpg_fmt("%Zd", m->mpg_i)); - else -#endif - print_func(fp, "%g", m->numbr); - } else if ((m->flags & STRCUR) != 0) - pp_string_fp(print_func, fp, m->stptr, m->stlen, '"', false); else print_func(fp, "-?-"); print_func(fp, " [%s]", flags2str(m->flags)); break; + case Node_typedregex: + print_func(fp, "@"); + /* fall through */ case Node_regex: pp_string_fp(print_func, fp, m->re_exp->stptr, m->re_exp->stlen, '/', false); break; @@ -4024,10 +4021,18 @@ print_instruction(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump) print_func(fp, " [do_reference = %s]\n", pc->do_reference ? "true" : "false"); break; - + + case Op_comment: + print_memory(pc->memory, func, print_func, fp); + fprintf(fp, " [comment_type = %s]\n", + pc->memory->comment_type == EOL_COMMENT ? + "EOL" : "FULL"); + break; + case Op_push_i: case Op_push: case Op_push_arg: + case Op_push_arg_untyped: case Op_push_param: case Op_push_array: case Op_push_re: @@ -4250,10 +4255,10 @@ gprintf(FILE *fp, const char *format, ...) #define GPRINTF_BUFSIZ 512 if (buf == NULL) { buflen = GPRINTF_BUFSIZ; - emalloc(buf, char *, (buflen + 2) * sizeof(char), "gprintf"); + emalloc(buf, char *, buflen * sizeof(char), "gprintf"); } else if (buflen - bl < GPRINTF_BUFSIZ/2) { buflen += GPRINTF_BUFSIZ; - erealloc(buf, char *, (buflen + 2) * sizeof(char), "gprintf"); + erealloc(buf, char *, buflen * sizeof(char), "gprintf"); } #undef GPRINTF_BUFSIZ @@ -4272,7 +4277,7 @@ gprintf(FILE *fp, const char *format, ...) /* enlarge buffer, and try again */ buflen *= 2; - erealloc(buf, char *, (buflen + 2) * sizeof(char), "gprintf"); + erealloc(buf, char *, buflen * sizeof(char), "gprintf"); } bl = 0; @@ -4312,7 +4317,7 @@ gprintf(FILE *fp, const char *format, ...) static int serialize_subscript(char *buf, int buflen, struct list_item *item) { - int bl = 0, nchar, i; + int bl, nchar, i; NODE *sub; nchar = snprintf(buf, buflen, "%d%c%d%c%s%c%d%c", @@ -4322,7 +4327,7 @@ serialize_subscript(char *buf, int buflen, struct list_item *item) return 0; else if (nchar >= buflen) /* need larger buffer */ return nchar; - bl += nchar; + bl = nchar; for (i = 0; i < item->num_subs; i++) { sub = item->subs[i]; nchar = snprintf(buf + bl, buflen - bl, "%lu%c%s%c", @@ -4401,7 +4406,7 @@ serialize(int type) if (buf == NULL) { /* first time */ buflen = SERIALIZE_BUFSIZ; - emalloc(buf, char *, buflen + 2, "serialize"); + emalloc(buf, char *, buflen + 1, "serialize"); } bl = 0; @@ -4410,7 +4415,7 @@ serialize(int type) if (buflen - bl < SERIALIZE_BUFSIZ/2) { enlarge_buffer: buflen *= 2; - erealloc(buf, char *, buflen + 2, "serialize"); + erealloc(buf, char *, buflen + 1, "serialize"); } #undef SERIALIZE_BUFSIZ @@ -4511,7 +4516,7 @@ enlarge_buffer: } if (nchar > 0) { /* non-empty commands list */ - nchar += (strlen("commands ") + 20 + strlen("end") + 2); /* 20 for cnum (an int) */ + nchar += (strlen("commands ") + 20 + strlen("end") + 1); /* 20 for cnum (an int) */ if (nchar > buflen - bl) { buflen = bl + nchar; erealloc(buf, char *, buflen + 3, "serialize"); @@ -77,14 +77,6 @@ is_blank (int c) } #endif /* GAWK */ -#ifdef LIBC_IS_BORKED -extern int gawk_mb_cur_max; -#undef MB_CUR_MAX -#define MB_CUR_MAX gawk_mb_cur_max -#undef mbrtowc -#define mbrtowc(a, b, c, d) (-1) -#endif - /* HPUX defines these as macros in sys/param.h. */ #ifdef setbit # undef setbit @@ -791,10 +783,6 @@ using_utf8 (void) wchar_t wc; mbstate_t mbs = { 0 }; utf8 = mbrtowc (&wc, "\xc4\x80", 2, &mbs) == 2 && wc == 0x100; -#ifdef LIBC_IS_BORKED - if (gawk_mb_cur_max == 1) - utf8 = 0; -#endif } return utf8; } @@ -3346,8 +3334,7 @@ dfainit (struct dfa *d) static bool _GL_ATTRIBUTE_PURE dfa_supported (struct dfa const *d) { - size_t i; - for (i = 0; i < d->tindex; i++) + for (size_t i = 0; i < d->tindex; i++) { switch (d->tokens[i]) { @@ -3801,18 +3788,15 @@ dfamust (struct dfa const *d) { must *mp = NULL; char const *result = ""; - size_t ri; size_t i; bool exact = false; bool begline = false; bool endline = false; - size_t rj; bool need_begline = false; bool need_endline = false; bool case_fold_unibyte = case_fold && MB_CUR_MAX == 1; - struct dfamust *dm; - for (ri = 0; ri < d->tindex; ++ri) + for (size_t ri = 0; ri < d->tindex; ++ri) { token t = d->tokens[ri]; switch (t) @@ -3987,7 +3971,7 @@ dfamust (struct dfa const *d) } } - rj = ri + 2; + size_t rj = ri + 2; if (d->tokens[ri + 1] == CAT) { for (; rj < d->tindex - 1; rj += 2) @@ -4016,7 +4000,7 @@ dfamust (struct dfa const *d) } done:; - dm = NULL; + struct dfamust *dm = NULL; if (*result) { dm = xmalloc (sizeof *dm); diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 00000000..e12f5de0 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,95 @@ +# +# doc/CMakeLists.txt --- CMake input file for gawk +# +# Copyright (C) 2013 +# the Free Software Foundation, Inc. +# +# This file is part of GAWK, the GNU implementation of the +# AWK Programming Language. +# +# GAWK is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GAWK is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# + +## process this file with CMake to produce Makefile + +MACRO(DocDependency outfile) + add_dependencies(doc ${outfile}) + add_custom_target( + ${outfile} + DEPENDS ${ARGN} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND ${CMAKE_SOURCE_DIR}/cmake/docmaker ${outfile} ${ARGN} + ) +ENDMACRO(DocDependency) + +find_program(TEXI2DVI_CONVERTER texi2dvi) +if (TEXI2DVI_CONVERTER) + add_custom_target(doc) + DocDependency(gawk.texi gawktexi.in rflashlight.eps api-figure1.fig api-figure2.fig api-figure3.fig general-program.fig process-flow.fig) + DocDependency(rflashlight.eps) + DocDependency(api-figure1.fig) + DocDependency(api-figure2.fig) + DocDependency(api-figure3.fig) + DocDependency(general-program.fig) + DocDependency(process-flow.fig) + DocDependency(gawk.dvi gawk.texi) + DocDependency(gawk.info gawk.texi) + DocDependency(gawkinet.dvi gawkinet.texi) + DocDependency(gawkinet.info gawkinet.texi) + DocDependency(gawkinet.texi statist.eps) + DocDependency(gawk.1.ps gawk.1) + DocDependency(igawk.1.ps igawk.1) + find_program(DVIPS_CONVERTER dvips) + if (DVIPS_CONVERTER) + DocDependency(gawk.ps gawk.dvi) + DocDependency(gawkinet.ps gawkinet.dvi) + find_program(PS2PDF_CONVERTER ps2pdf) + if (PS2PDF_CONVERTER) + DocDependency(gawk.1.pdf gawk.1.ps) + DocDependency(igawk.1.pdf igawk.1.ps) + DocDependency(gawk.pdf gawk.ps) + DocDependency(gawkinet.pdf gawkinet.ps) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gawk.1.pdf DESTINATION doc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/igawk.1.pdf DESTINATION doc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gawk.info DESTINATION doc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gawk.pdf DESTINATION doc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gawkinet.info DESTINATION doc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gawkinet.pdf DESTINATION doc) + + set(CARDSRC macros cardfonts colors awkcard.tr) + set(CARDSRC_N macros cardfonts no.colors awkcard.tr) + set(CARDFILES ${CARDSRC} ad.block awkcard.in setter.outline) + DocDependency(awkcard.tr awkcard.in) + DocDependency(awkcard.nc ${CARDFILES}) + DocDependency(awkcard.ps ${CARDFILES}) + DocDependency(awkcard.pdf awkcard.ps) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/awkcard.pdf DESTINATION doc) + + else() + message(WARNING "Found no ps2pdf tool; no doc will be generated") + install(CODE "MESSAGE(\"doc generated only in .ps files\")") + endif() + else() + message(WARNING "Found no dvips tool; no doc will be generated") + install(CODE "MESSAGE(\"doc generated only in .dvi files and man pages in .ps files\")") + endif() +else() + message(WARNING "Found no texi2dvi tool; no doc will be generated") + add_custom_command( + TARGET doc + COMMAND echo no doc generated because of missing texi2dvi + ) +endif() + diff --git a/doc/ChangeLog b/doc/ChangeLog index 32f4ecb5..abd8cdfe 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,13 @@ +2016-06-30 Arnold D. Robbins <arnold@skeeve.com> + + * gawk.1: Typo fix. Thanks to Antonio Giovanni Colombo + for noticing. + +2016-06-15 Arnold D. Robbins <arnold@skeeve.com> + + * gawk.1: Document typeof(), update modified date. + * awkcard.in: Document typeof(). + 2016-06-10 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Fix a typo, and replace hard-coded "section" with @@ -6,6 +16,15 @@ (UPDATE-MONTH, PATCHLEVEL): Update to current before release. * awkcard.in: Update version. +2016-05-30 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in: Replace num_expected_args with max_expected_args. + Explain what it's used for. + +2016-05-25 Manuel Collado <mcollado2011@gmail.com>. + + * gawktexi.in: Document new 'nonfatal' API function. + 2016-05-25 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Typo fix in extension section, thanks to @@ -22,6 +41,12 @@ out since 2001, index RFCs, change function name convention to match main gawktexi.in. Update the update month. +2016-04-06 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Two-way I/O): Document that writing to the closed + write end of a two way pipe or reading from the closed read end + can be made nonfatal. + 2016-04-04 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in, gawkinet.texi: Enable use of braces in @@ -32,6 +57,11 @@ * gawktexi.in (Two-way I/O): Document that closing the "from" end waits for the process to exit, so it's not such a great idea. +2016-03-27 Arnold D. Robbins <arnold@skeeve.com> + + * gawkinet.texi: Small update about end of line vs full + comments when pretty printing. + 2016-03-21 Arnold D. Robbins <arnold@skeeve.com> * gawkinet.texi: Update UDP client and discussion, update @@ -64,6 +94,8 @@ dlward134@gmail.com. Added an example of use of rewind(), also per suggestion from David Ward. * gawktexi.in: Update info about Texinfo versions. + * gawktexi.in (Limitations): Fix Heisenberg Physics example and + spelling of Heisenberg's name. Thanks to Hermann Peifer. 2016-02-14 Arnold D. Robbins <arnold@skeeve.com> @@ -73,6 +105,14 @@ Use @sup for superscripts where possible. * texinfo.tex: Updated. +2016-02-05 Arnold D. Robbins <arnold@skeeve.com> + + * gawk.texi: Document that optimization in now the default, + there are new -s/--no-optimize options and that + pretty-printing and profiling disable optimization. + * gawk.1: Ditto. + * awkcard.in: Ditto. + 2016-02-03 Andrew J. Schorr <aschorr@telemetry-investments.com> * gawktexi.in (Command-Line Options): Change wording of -M description @@ -105,17 +145,39 @@ * ChangeLog: Remove spurious whitespace. + Unrelated: + + * gawk.1: Restore text on PROCINFO["RETRY"] and fix up the + formatting while we're at it. Thanks to Andrew Schorr for + pointing out the problem. + 2016-01-13 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in (Array Sorting Functions): Add an example of using a function name with asort(). Response to bug report Stephane Goujet <stephane.goujet@wanadoo.fr>. +2016-01-06 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Finish documenting that --pretty-print + doesn't run the program. Thanks to Antonio + Giovanni Colombo for the report and patch. + +2016-01-03 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Document that GNU/Linux on Alpha is no + longer supported. + 2015-12-27 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Fix some @c endfile. Thanks to Antonio Giovanni Colombo for the report and patch. +2015-12-20 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Add PROCINFO["NONFATAL"] to the list for PROCINFO. + * gawk.1: Ditto. + 2015-12-18 Arnold D. Robbins <arnold@skeeve.com> * gawk.1: Update description of PROCINFO, and sort it properly. @@ -129,6 +191,11 @@ 2015-11-15 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Minor edits. + * gawk.1: Revise \x to maximum of two digits. + +2015-11-04 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (pdf-local): Remove igawk.1.pdf. Ooops. 2015-10-30 Arnold D. Robbins <arnold@skeeve.com> @@ -141,6 +208,10 @@ * gawk.1: Put commas outside quoting in regexps to avoid confusion. Thanks to Mike Frysinger <vapier@gentoo.org>. +2015-10-16 Arnold D. Robbins <arnold@skeeve.com> + + * awkcard.in: Fix tbl complaint. + 2015-10-07 Arnold D. Robbins <arnold@skeeve.com> * texinfo.tex: Updated to a working version. @@ -172,11 +243,26 @@ * gawktexi.in: Typo fixes in Appendix A. Thanks to Antonio Colombo. +2015-07-30 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Small typo fix; thanks to Antonio Colombo + for noticing. + 2015-07-01 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Update info on Quiktrim awk; thanks to Antonio Colombo for the pointer. +2015-06-30 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Limitations): Document that sometimes the + debugger can affect the program being run. + Thanks to Hermann Peifer for the test case. + +2015-06-26 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Update description of values returned by typeof. + 2015-06-19 Arnold D. Robbins <arnold@skeeve.com> * gawkinet.info: Fix an old arnold@gnu.org. @@ -202,6 +288,13 @@ * gawktexi.in: Add another pithy quote from Chet Ramey. Currently commented out. +2015-05-31 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Revised description of default field parsing + for POSIX. Newline is now a separator also. Thanks to + Michael Klement <michael.klement@usa.net> for pointing this out. + * gawk.1: Updated too. + 2015-05-30 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in (Bitwise Functions): Update results of testbits.awk. @@ -226,15 +319,33 @@ * gawktexi.in: Fix description of nextfile within a function. Sigh. +2015-05-15 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in (Undocumented): Describe the new PROCINFO["argv"] array. + 2015-05-14 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in (Bugs): Add that email should be in plain text and not in HTML. Sigh. +2015-05-11 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Add doc on conversions for strongly typed + regexp variables. + +2015-05-03 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Add initial documentation for strongly typed + regexps and for `typeof'. + 2015-04-29 Arnold D. Robbins <arnold@skeeve.com> * 4.1.2: Release tar ball made. +2015-04-16 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Undocumented): More info added. + 2015-04-08 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Update feature history section. @@ -256,6 +367,11 @@ * gawktexi.in: Fix a figure caption. Thanks to Antonio Colombo for pointing this out. + * gawktexi.in: Additional typo fix, also thanks to Antonio. + +2015-04-02 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in, gawk.1, awkcard.in: Name change: div() --> intdiv(). 2015-03-31 Arnold D. Robbins <arnold@skeeve.com> @@ -263,10 +379,17 @@ indirectly. Small additional fix relating to rand(). Thanks to Antonio Colombo. +2015-03-27 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Minor edits. + 2015-03-24 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Minor fixes from Antonio Colombo and new exercise in chapter 16. + * gawk.1: Minor edits. + * gawktexi.in: Edits in material on errno and retryable and get_file + API. 2015-03-17 Andrew J. Schorr <aschorr@telemetry-investments.com> @@ -280,6 +403,12 @@ Thanks to Nicholas Mills <nlmills@clemson.edu> for pointing out the issue. +2015-03-08 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Briefly describe that nonfatal I/O overrides + GAWK_SOCK_RETRIES, in the env var part and in the nonfatal I/O + part. + 2015-03-01 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Change quotes to @dfn for pseudorandom. @@ -336,6 +465,7 @@ 2015-02-08 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: O'Reilly fixes. + Make non-fatal i/o use "NONFATAL". 2015-02-06 Arnold D. Robbins <arnold@skeeve.com> @@ -344,6 +474,7 @@ 2015-02-04 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: O'Reilly fixes. + * gawktexi.in: Update various version-related bits of info. 2015-02-02 Arnold D. Robbins <arnold@skeeve.com> @@ -373,7 +504,7 @@ 2015-01-25 Arnold D. Robbins <arnold@skeeve.com> - * gawktexi.in: Fix a bad URL. + * gawktexi.in: Fix a bad URL. And another one. More O'Reilly fixes. 2015-01-23 Arnold D. Robbins <arnold@skeeve.com> @@ -395,12 +526,40 @@ * gawkinet.texi: Fix capitalization in document title. * gawktexi.in: Here we go again: Starting on more O'Reilly fixes. +2014-12-27 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Add info that nonfatal I/O works with stdout and + stderr. Revise version info and what was added when. + +2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in: Improve get_file documentation. + +2015-01-05 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in: Replace "Retrying I/O" with "Retrying Input", since this + feature pertains to input, not output. + +2015-01-04 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in: Document the get_file API function. + +2015-01-04 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawk.1: Document new features PROCINFO["errno"] and + PROCINFO["input", "RETRY"], and new getline return value of -2. + * gawktexi.in: Ditto. + 2014-12-26 Antonio Giovanni Colombo <azc100@gmail.com> * gawktexi.in (Glossary): Really sort the items. 2014-12-24 Arnold D. Robbins <arnold@skeeve.com> + * gawktexi.in: Start documenting nonfatal output. + +2014-12-24 Arnold D. Robbins <arnold@skeeve.com> + * gawktexi.in: Add one more paragraph to new foreword. * gawktexi.in: Fix exponentiation in TeX mode. Thanks to Marco Curreli by way of Antonio Giovanni Colombo. @@ -432,6 +591,11 @@ * gawktexi.in: Various minor fixes and updates. +2014-11-23 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Update that TZ env. var can influnce mktime + in running program. Thanks to Hermann Peifer. + 2014-11-19 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Update that RFC 4180 documents CSV data. @@ -445,6 +609,11 @@ * gawktexi.in: Comment out that I need an owner for awk.info. I may have found one or two people. +2014-10-29 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawktexi.in: Document new extras directory containing shell startup + files to manipulate AWKPATH and AWKLIBPATH environment variables. + 2014-10-28 Arnold D. Robbins <arnold@skeeve.com> * gawk.1: Clarification that debugger reads stdin. @@ -458,6 +627,7 @@ 2014-10-25 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Minor typo fixes. + Fix discussion of \x, per note from Antonio Colombo. 2014-10-17 Arnold D. Robbins <arnold@skeeve.com> @@ -499,10 +669,25 @@ * gawktexi.in: Pretty much done! + Unrelated: + + * gawktexi.in: Fix braino in awk version of div function. + Thanks to Katie Wasserman for the catch. + 2014-10-01 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: More fixes after reading through the MS. + Unrelated: + + * gawktexi.in: Add Katie Wasserman's program to compute + the digits of PI. + + Unrelated: + + * gawktexi.in: Document the differences between profiling + and pretty printing. + 2014-09-30 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: More fixes after reading through the MS. @@ -598,6 +783,10 @@ exercises. Remove use of LC_ALL in an example; doesn't seem to be needed anymore. + Unrelated: + + * gawktexi.in: Document that MirBSD is no longer supported. + 2014-08-25 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Exercises are excluded from print edition. @@ -631,6 +820,10 @@ * gawktexi.in: Starting on reviewer comments. Update acknowledgements. +2014-08-12 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Cause div.awk to get into the example files. + 2014-08-06 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Misc minor additions. @@ -645,6 +838,18 @@ * gawktexi.in: Fix doc for API get_record - errcode needs to be greater than zero. +2014-07-24 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Numeric Functions): For `div()', clarify + truncation is towards zero. Thanks to Michal Jaegermann + for pointing out the need to clarify this. + +2014-07-10 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Numeric Functions): Document new `div()' function. + (Arbitrary Precision Integers): Document raison d'etre for div(). + * gawk.1, awkcard.in: Document `div()'. + 2014-07-04 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in (Bracket Expressions): Add a note about how to @@ -655,6 +860,11 @@ * gawktexi.in: Update permissions on copyright page per latest maintain.texi. Add GPL to print version of book. +2014-06-24 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Document that --pretty-print no longer runs the + program. Remove mention of GAWK_NO_PP_RUN env var. + 2014-06-22 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Typo fixes and minor corrections. @@ -951,7 +1161,7 @@ 2013-12-26 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: More minor additions / fixes. - (Bugs): Add John Malmberg for VMS. + (Bugs): Add John Malmberg for VMS. Other minor edits. 2013-12-25 Arnold D. Robbins <arnold@skeeve.com> @@ -1025,6 +1235,11 @@ * gawktexi.in (FN, FFN, DF,DDF, PVERSION, CTL): Remove macros. They have no alternate versions and are just in the way. +2013-08-15 Arnold D. Robbins <arnold@skeeve.com> + + * gawk.1: Document that ENVIRON updates affect the environment. + * gawktexi.in: Ditto. + 2013-06-27 Arnold D. Robbins <arnold@skeeve.com> * texinfo.tex: Update from Karl, fixes a formating problem. diff --git a/doc/Makefile.am b/doc/Makefile.am index 5c585f1c..5eefaadf 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -26,7 +26,7 @@ info_TEXINFOS = gawk.texi gawkinet.texi -man_MANS = gawk.1 igawk.1 +man_MANS = gawk.1 EXTRA_DIST = ChangeLog ChangeLog.0 README.card ad.block setter.outline \ awkcard.in awkforai.txt texinfo.tex cardfonts \ @@ -50,7 +50,7 @@ EXTRA_DIST = ChangeLog ChangeLog.0 README.card ad.block setter.outline \ bc_notes # Get rid of generated files when cleaning -CLEANFILES = *.ps *.html *.dvi *~ awkcard.nc awkcard.tr gawk.pdf gawkinet.pdf awkcard.pdf gawk.1.pdf igawk.1.pdf +CLEANFILES = *.ps *.html *.dvi *~ awkcard.nc awkcard.tr gawk.pdf gawkinet.pdf awkcard.pdf gawk.1.pdf MAKEINFO = @MAKEINFO@ --no-split --force @@ -76,9 +76,9 @@ AWKCARD = awkcard.ps gawk.texi: $(srcdir)/gawktexi.in $(srcdir)/sidebar.awk awk -f $(srcdir)/sidebar.awk < $(srcdir)/gawktexi.in > gawk.texi -postscript: gawk.ps gawkinet.ps gawk.1.ps igawk.1.ps $(AWKCARD) +postscript: gawk.ps gawkinet.ps gawk.1.ps $(AWKCARD) -pdf-local: postscript gawk.pdf gawkinet.pdf awkcard.pdf gawk.1.pdf igawk.1.pdf +pdf-local: postscript gawk.pdf gawkinet.pdf awkcard.pdf gawk.1.pdf gawk.ps: gawk.dvi TEXINPUTS=$(srcdir): dvips -o gawk.ps gawk.dvi @@ -92,12 +92,6 @@ gawk.1.ps: gawk.1 gawk.1.pdf: gawk.1.ps ps2pdf gawk.1.ps gawk.1.pdf -igawk.1.ps: igawk.1 - -groff -man $(srcdir)/igawk.1 > igawk.1.ps - -igawk.1.pdf: igawk.1.ps - ps2pdf igawk.1.ps igawk.1.pdf - awkcard.tr: awkcard.in sed 's:SRCDIR:$(srcdir):' < $(srcdir)/awkcard.in > awkcard.tr diff --git a/doc/Makefile.in b/doc/Makefile.in index 577b4778..2fa1fac0 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -116,14 +116,14 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/arch.m4 \ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ - $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lcmessage.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \ - $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/mpfr.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/noreturn.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/socket.m4 \ - $(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/mpfr.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/noreturn.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \ + $(top_srcdir)/m4/socket.m4 $(top_srcdir)/m4/ulonglong.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) @@ -353,7 +353,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ info_TEXINFOS = gawk.texi gawkinet.texi -man_MANS = gawk.1 igawk.1 +man_MANS = gawk.1 EXTRA_DIST = ChangeLog ChangeLog.0 README.card ad.block setter.outline \ awkcard.in awkforai.txt texinfo.tex cardfonts \ api-figure1.eps api-figure1.fig api-figure1.pdf \ @@ -377,7 +377,7 @@ EXTRA_DIST = ChangeLog ChangeLog.0 README.card ad.block setter.outline \ # Get rid of generated files when cleaning -CLEANFILES = *.ps *.html *.dvi *~ awkcard.nc awkcard.tr gawk.pdf gawkinet.pdf awkcard.pdf gawk.1.pdf igawk.1.pdf +CLEANFILES = *.ps *.html *.dvi *~ awkcard.nc awkcard.tr gawk.pdf gawkinet.pdf awkcard.pdf gawk.1.pdf TROFF = groff -t -Tps -U SEDME = sed -e "s/^level0 restore/level0 restore flashme 100 72 moveto (Copyright `date '+%m-%d-%y %T'`, FSF, Inc. (all)) show/" \ -e "s/^\/level0 save def/\/level0 save def 30 -48 translate/" @@ -881,9 +881,9 @@ uninstall-man: uninstall-man1 gawk.texi: $(srcdir)/gawktexi.in $(srcdir)/sidebar.awk awk -f $(srcdir)/sidebar.awk < $(srcdir)/gawktexi.in > gawk.texi -postscript: gawk.ps gawkinet.ps gawk.1.ps igawk.1.ps $(AWKCARD) +postscript: gawk.ps gawkinet.ps gawk.1.ps $(AWKCARD) -pdf-local: postscript gawk.pdf gawkinet.pdf awkcard.pdf gawk.1.pdf igawk.1.pdf +pdf-local: postscript gawk.pdf gawkinet.pdf awkcard.pdf gawk.1.pdf gawk.ps: gawk.dvi TEXINPUTS=$(srcdir): dvips -o gawk.ps gawk.dvi @@ -897,12 +897,6 @@ gawk.1.ps: gawk.1 gawk.1.pdf: gawk.1.ps ps2pdf gawk.1.ps gawk.1.pdf -igawk.1.ps: igawk.1 - -groff -man $(srcdir)/igawk.1 > igawk.1.ps - -igawk.1.pdf: igawk.1.ps - ps2pdf igawk.1.ps igawk.1.pdf - awkcard.tr: awkcard.in sed 's:SRCDIR:$(srcdir):' < $(srcdir)/awkcard.in > awkcard.tr diff --git a/doc/awkcard.in b/doc/awkcard.in index e64f3944..0b377ee5 100644 --- a/doc/awkcard.in +++ b/doc/awkcard.in @@ -244,7 +244,7 @@ Overridden by \*(FC\-\^\-posix\*(FR. .TI "\*(FC\-c\*(FR, \*(FC\-\^\-traditional\*(FR Disable \*(GK-specific extensions. .TI "\*(FC\-C\*(FR, \*(FC\-\^\-copyright\*(FR -Print the short version of the GNU +Print the short GNU copyright information on \*(FCstdout\*(FR. .TI "\*(FC\-d\*(FR[\*(FIfile\*(FR], \*(FC\-\^\-dump-variables\*(FR[\*(FC=\*(FIfile\*(FR] Print a sorted list of global variables, @@ -292,7 +292,7 @@ Force use of the locale's decimal point character when parsing input data. Output a pretty printed version of the program to \*(FIfile\*(FR (default: \*(FCawkprof.out\*(FR). .TI "\*(FC\-O\*(FR, \*(FC\-\^\-optimize\*(FR -Enable some internal optimizations. +Enable internal optimizations (default is on). .TI "\*(FC\-p\*(FR[\*(FC\*(FIfile\*(FR], \*(FC\-\^\-profile\*(FR[\*(FC=\*(FIfile\*(FR] Send profiling data to \*(FIfile\*(FR (default: \*(FCawkprof.out\*(FR). @@ -300,6 +300,9 @@ The profile contains execution counts in the left margin of each statement in the program. .TI "\*(FC\-P\*(FR, \*(FC\-\^\-posix\*(FR Disable common and GNU extensions.\*(CB +.TI "\*(FC\-r\*(FR, \*(FC\-\^\-re\-interval\*(FR +Enable \*(FIinterval expressions\*(FR. +(Needed with \*(FC\-c\*(FR.) .in -4n .EB "\s+2\f(HBCOMMAND LINE ARGUMENTS (\*(GK\f(HB)\*(FR\s0" @@ -311,9 +314,8 @@ Disable common and GNU extensions.\*(CB .ES .fi .in +4n -.TI "\*(FC\-r\*(FR, \*(FC\-\^\-re\-interval\*(FR -Enable \*(FIinterval expressions\*(FR. -(Needed with \*(FC\-c\*(FR.) +.TI "\*(FC\-s\*(FR, \*(FC\-\^\-no\-optimize\*(FR +Disable internal optimizations. .TI "\*(FC\-S\*(FR, \*(FC\-\^\-sandbox\*(FR Disable the \*(FCsystem()\*(FR function, input redirection with \*(FCgetline\*(FR, @@ -1606,11 +1608,14 @@ may be used in place of .fi .TS expand; -l lw(2i). +l lw(1.9i). \*(CD\*(FCatan2(\*(FIy\*(FC, \*(FIx\*(FC)\*(FR The arctangent of \*(FIy/x\fP in radians. \*(FCcos(\*(FIexpr\*(FC)\*(FR The cosine of \*(FIexpr\fP, which is in radians. \*(FCexp(\*(FIexpr\*(FC)\*(FR The exponential function (\*(FIe \*(FC^ \*(FIx\*(FR). \*(FCint(\*(FIexpr\*(FC)\*(FR Truncate to integer. +\*(CB\*(FCintdiv(\*(FIn\*(FR\*(FC,\*(FI d\*(FR\*(FC,\*(FI r\*(FR\*(FC)\*(FR T{ +Return result of integer division in \*(FIr\*(FR.\*(CD +T} \*(FClog(\*(FIexpr\*(FC)\*(FR The natural logarithm function (base \*(FIe\^\*(FR). \*(FCrand()\fP A random number \*(FIN\fP such that 0 \(<= \*(FIN\fP < 1. \*(FCsin(\*(FIexpr\*(FC)\*(FR The sine of \*(FIexpr\fP, which is in radians. @@ -1882,7 +1887,12 @@ See the manual for details.\*(CB .ti -.2i \*(CD\*(FCisarray(\*(FIx\*(FC)\*(FR .br -Return true if \*(FIx\fP is an array, false otherwise.\*(CB +Return true if \*(FIx\fP is an array, false otherwise. +.br +.ti -.2i +\*(FCtypeof(\*(FIx\*(FC)\*(FR +.br +Return a string indicating the type of \*(FIx\fP.\*(CB .in -.2i .EB "\s+2\f(HBTYPE FUNCTIONS (\*(GK\f(HB)\*(FR\s0" .sp .5 @@ -13,7 +13,7 @@ . if \w'\(rq' .ds rq "\(rq . \} .\} -.TH GAWK 1 "Mar 7 2016" "Free Software Foundation" "Utility Commands" +.TH GAWK 1 "Jun 30 2016" "Free Software Foundation" "Utility Commands" .SH NAME gawk \- pattern scanning and processing language .SH SYNOPSIS @@ -405,17 +405,20 @@ is provided, uses a file named .B awkprof.out in the current directory. +Implies +.BR \-\^\-no\-optimize . .TP .PD 0 .B \-O .TP .PD .B \-\^\-optimize -Enable optimizations upon the internal representation of the program. +Enable +.IR gawk 's +default optimizations upon the internal representation of the program. Currently, this includes simple constant-folding, and tail call -elimination for recursive functions. The -.I gawk -maintainer hopes to add additional optimizations over time. +elimination for recursive functions. +This option is on by default. .TP .PD 0 \fB\-p\fR[\fIprof-file\fR] @@ -428,6 +431,8 @@ The default is .BR awkprof.out . The profile contains execution counts of each statement in the program in the left margin and function call counts for each user-defined function. +Implies +.BR \-\^\-no\-optimize . .TP .PD 0 .B \-P @@ -444,11 +449,6 @@ mode, with the following additional restrictions: escape sequences are not recognized. .TP \(bu -Only space and tab act as field separators when -.B FS -is set to a single space, newline does not. -.TP -\(bu You cannot continue lines after .B ? and @@ -493,6 +493,15 @@ They are enabled by default, but this option remains for use with .BR \-\^\-traditional . .TP .PD 0 +.B \-s +.TP +.PD +.B \-\^\-no\-optimize +Disable +.IR gawk 's +default optimizations upon the internal representation of the program. +.TP +.PD 0 .BI \-S .TP .PD @@ -785,9 +794,6 @@ In the special case that .B FS is a single space, fields are separated by runs of spaces and/or tabs and/or newlines. -(But see the section -.BR "POSIX COMPATIBILITY" , -below). .BR NOTE : The value of .B IGNORECASE @@ -918,11 +924,17 @@ An array containing the values of the current environment. The array is indexed by the environment variables, each element being the value of that variable (e.g., \fBENVIRON["HOME"]\fP might be \fB"/home/arnold"\fR). -Changing this array does not affect the environment seen by programs which +.sp +In POSIX mode, +changing this array does not affect the environment seen by programs which .I gawk spawns via redirection or the .B system() function. +Otherwise, +.I gawk +updates its real environment so that programs it spawns see +the changes. .TP .B ERRNO If a system error occurs either doing a redirection for @@ -936,6 +948,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, @@ -1093,6 +1114,13 @@ The value of the .IR getegid (2) system call. .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) @@ -1124,7 +1152,7 @@ knows about the identifiers after it has finished parsing the program; they are updated while the program runs. For each identifier, the value of the element is one of the following: .RS -.TP +.TP \w'\fB"extension"\fR'u+1n \fB"array"\fR The identifier is an array. .TP @@ -1207,6 +1235,14 @@ change .IR gawk 's behavior: .TP +\fBPROCINFO["NONFATAL"]\fR +If this exists, then I/O errors for all output redirections become nonfatal. +.TP +\fBPROCINFO["\fIoutput_name\fB", "NONFATAL"]\fR +Make output errors for +.I output_name +be nonfatal. +.TP \fBPROCINFO["\fIcommand\fB", "pty"]\fR Use a pseudo-tty for two-way communication with .I command @@ -1220,6 +1256,23 @@ where is a redirection string or a filename. A value of zero or less than zero means no timeout. .TP +\fBPROCINFO["\fIinput\^\fB", "RETRY"]\fR +If an I/O error that may be retried occurs when reading data from +.IR input , +and this array entry exists, then +.B 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 EAGAIN, EWOULDBLOCK, EINTR, or ETIMEDOUT. +This may be useful in conjunction with +\fBPROCINFO["\fIinput\^\fB", "READ_TIMEOUT"]\fR +or situations where a file descriptor has been configured to behave in a +non-blocking fashion. +.TP \fBPROCINFO["sorted_in"]\fP If this element exists in .BR PROCINFO , @@ -1240,7 +1293,9 @@ Supported values are \fB"@val_num_desc"\fR, and \fB"@unsorted"\fR. -The value can also be the name of any comparison function defined +The value can also be the name (as a +.IR string ) +of any comparison function defined as follows: .sp .in +5m @@ -1544,9 +1599,9 @@ Vertical tab. The character represented by the string of hexadecimal digits following the .BR \ex . -As in ISO C, all following hexadecimal digits are considered part of +Up to two +following hexadecimal digits are considered part of the escape sequence. -(This feature should tell us something about language design by committee.) E.g., \fB"\ex1B"\fR is the \s-1ASCII\s+1 \s-1ESC\s+1 (escape) character. .TP .BI \e ddd @@ -2291,6 +2346,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["\fIinput\^\fP", "RETRY"]\fR +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. @@ -2643,6 +2705,23 @@ The exponential function. .BI int( expr ) Truncate to integer. .TP +.BI intdiv( num ", " denom ", " result ) +Truncate +.I num +and +.I denom +to integers. Return the quotient of +.I num +divided by +.I denom +in \fIresult\fB["quotient"]\fR +and the remainder in +in \fIresult\fB["remainder"]\fR. +This is a +.I gawk +extension, primarily of value when working with +arbitrarily large integers. +.TP .BI log( expr ) The natural logarithm function. .TP @@ -3134,13 +3213,28 @@ bits. Return the bitwise XOR of the values provided in the argument list. There must be at least two. .PP -.SS Type Function +.SS Type Functions The following function is for use with multidimensional arrays. .TP \fBisarray(\fIx\fB)\fR Return true if .I x is an array, false otherwise. +.PP +You can tell the type of any variable or array element with the +following function: +.TP +\fBtypeof(\fIx\fB)\fR +Return a string indicating the type of +.IR x . +The string will be one of +\fB"array"\fP, +\fB"number"\fP, +\fB"regexp"\fP, +\fB"string"\fP, +\fB"strnum"\fP, +or +\fB"undefined"\fP. .SS Internationalization Functions The following functions may be used from within your AWK program for translating strings at run-time. @@ -3987,7 +4081,7 @@ We thank him. .SH COPYING PERMISSIONS Copyright \(co 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2007, 2009, -2010, 2011, 2012, 2013, 2014, 2016 +2010, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc. .PP Permission is granted to make and distribute verbatim copies of diff --git a/doc/gawk.info b/doc/gawk.info index e2869769..2a190873 100644 --- a/doc/gawk.info +++ b/doc/gawk.info @@ -175,6 +175,7 @@ in (a) below. A copy of the license is included in the section entitled * Computed Regexps:: Using Dynamic Regexps. * GNU Regexp Operators:: Operators specific to GNU software. * Case-sensitivity:: How to do case-insensitive matching. +* Strong Regexp Constants:: Strongly typed regexp constants. * Regexp Summary:: Regular expressions summary. * Records:: Controlling how data is split into records. @@ -217,6 +218,7 @@ in (a) below. A copy of the license is included in the section entitled '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. @@ -246,6 +248,7 @@ in (a) below. A copy of the license is included in the section entitled * Special Caveats:: Things to watch out for. * Close Files And Pipes:: Closing Input and Output Files and Pipes. +* Nonfatal:: Enabling Nonfatal Output. * Output Summary:: Output summary. * Output Exercises:: Exercises. * Values:: Constants, Variables, and Regular @@ -557,6 +560,7 @@ in (a) below. A copy of the license is included in the section entitled * 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 @@ -615,6 +619,7 @@ in (a) below. A copy of the license is included in the section entitled * Unix Installation:: Installing 'gawk' under various versions of Unix. * Quick Installation:: Compiling 'gawk' under Unix. +* Shell Startup Files:: Shell convenience functions. * Additional Configuration Options:: Other compile-time options. * Configuration Philosophy:: How it's all supposed to work. * Non-Unix Installation:: Installation on Other Operating @@ -2625,30 +2630,33 @@ The following list describes options mandated by the POSIX standard: '-o'[FILE] '--pretty-print'['='FILE] - Enable pretty-printing of 'awk' programs. By default, the output - program is created in a file named 'awkprof.out' (*note - Profiling::). The optional FILE argument allows you to specify a - different file name for the output. No space is allowed between - the '-o' and FILE, if FILE is supplied. + Enable pretty-printing of 'awk' programs. Implies '--no-optimize'. + By default, the output program is created in a file named + 'awkprof.out' (*note Profiling::). The optional FILE argument + allows you to specify a different file name for the output. No + space is allowed between the '-o' and FILE, if FILE is supplied. - NOTE: Due to the way 'gawk' has evolved, with this option your - program still executes. This will change in the next major - release, such that 'gawk' will only pretty-print the program - and not run it. + NOTE: In the past, this option would also execute your + program. This is no longer the case. '-O' '--optimize' - Enable some optimizations on the internal representation of the - program. At the moment, this includes just simple constant - folding. + Enable 'gawk''s default optimizations on the internal + representation of the program. At the moment, this includes simple + constant folding and tail recursion elimination in function calls. + + These optimizations are enabled by default. This option remains + primarily for backwards compatibilty. However, it may be used to + cancel the effect of an earlier '-s' option (see later in this + list). '-p'[FILE] '--profile'['='FILE] - Enable profiling of 'awk' programs (*note Profiling::). By - default, profiles are created in a file named 'awkprof.out'. The - optional FILE argument allows you to specify a different file name - for the profile file. No space is allowed between the '-p' and - FILE, if FILE is supplied. + Enable profiling of 'awk' programs (*note Profiling::). Implies + '--no-optimize'. By default, profiles are created in a file named + 'awkprof.out'. The optional FILE argument allows you to specify a + different file name for the profile file. No space is allowed + between the '-p' and FILE, if FILE is supplied. The profile contains execution counts for each statement in the program in the left margin, and function call counts for each @@ -2662,9 +2670,6 @@ The following list describes options mandated by the POSIX standard: in 'gawk' that are disabled by this option. Also, the following additional restrictions apply: - * Newlines do not act as whitespace to separate fields when 'FS' - is equal to a single space (*note Fields::). - * Newlines are not allowed after '?' or ':' (*note Conditional Exp::). @@ -2685,6 +2690,11 @@ The following list describes options mandated by the POSIX standard: remains (both for backward compatibility and for use in combination with '--traditional'). +'-s' +'--no-optimize' + Disable 'gawk''s default optimizations on the internal + representation of the program. + '-S' '--sandbox' Disable the 'system()' function, input redirections with 'getline', @@ -2933,6 +2943,9 @@ Since '.' is included at the beginning, 'gawk' searches first in the current directory and then in '/usr/local/share/awk'. In practice, this means that you will rarely need to change the value of 'AWKPATH'. + *Note Shell Startup Files::, for information on functions that help +to manipulate the 'AWKPATH' variable. + 'gawk' places the value of the search path that it used into 'ENVIRON["AWKPATH"]'. This provides access to the actual search path value from within an 'awk' program. @@ -2972,6 +2985,9 @@ empty value, 'gawk' uses a default path; this is typically '/usr/local/lib/gawk', although it can vary depending upon how 'gawk' was built. + *Note Shell Startup Files::, for information on functions that help +to manipulate the 'AWKLIBPATH' variable. + 'gawk' places the value of the search path that it used into 'ENVIRON["AWKLIBPATH"]'. This provides access to the actual search path value from within an 'awk' program. @@ -2998,7 +3014,8 @@ used by regular users: 'GAWK_SOCK_RETRIES' Controls the number of times 'gawk' attempts to retry a two-way TCP/IP (socket) connection before giving up. *Note TCP/IP - Networking::. + Networking::. Note that when nonfatal I/O is enabled (*note + Nonfatal::), 'gawk' only tries to open a TCP/IP socket once. 'POSIXLY_CORRECT' Causes 'gawk' to switch to POSIX-compatibility mode, disabling all @@ -3043,13 +3060,6 @@ change. The variables are: supposed to be differences, but occasionally theory and practice don't coordinate with each other.) -'GAWK_NO_PP_RUN' - When 'gawk' is invoked with the '--pretty-print' option, it will - not run the program if this environment variable exists. - - CAUTION: This variable will not survive into the next major - release. - 'GAWK_STACKSIZE' This specifies the amount by which 'gawk' should grow its internal evaluation stack, when needed. @@ -3314,6 +3324,7 @@ you specify more complicated classes of strings. * Computed Regexps:: Using Dynamic Regexps. * GNU Regexp Operators:: Operators specific to GNU software. * Case-sensitivity:: How to do case-insensitive matching. +* Strong Regexp Constants:: Strongly typed regexp constants. * Regexp Summary:: Regular expressions summary. @@ -3440,15 +3451,18 @@ sequences apply to both string constants and regexp constants: '\xHH...' The hexadecimal value HH, where HH stands for a sequence of - hexadecimal digits ('0'-'9', and either 'A'-'F' or 'a'-'f'). Like - the same construct in ISO C, the escape sequence continues until - the first nonhexadecimal digit is seen. (c.e.) However, using - more than two hexadecimal digits produces undefined results. (The - '\x' escape sequence is not allowed in POSIX 'awk'.) - - CAUTION: The next major release of 'gawk' will change, such - that a maximum of two hexadecimal digits following the '\x' - will be used. + hexadecimal digits ('0'-'9', and either 'A'-'F' or 'a'-'f'). A + maximum of two digts are allowed after the '\x'. Any further + hexadecimal digits are treated as simple letters or numbers. + (c.e.) (The '\x' escape sequence is not allowed in POSIX awk.) + + CAUTION: In ISO C, the escape sequence continues until the + first nonhexadecimal digit is seen. For many years, 'gawk' + would continue incorporating hexadecimal digits into the value + until a non-hexadecimal digit or the end of the string was + encountered. However, using more than two hexadecimal digits + produced undefined results. As of version 4.2, only two + digits are processed. '\/' A literal slash (necessary for regexp constants only). This @@ -4025,7 +4039,7 @@ No options default. -File: gawk.info, Node: Case-sensitivity, Next: Regexp Summary, Prev: GNU Regexp Operators, Up: Regexp +File: gawk.info, Node: Case-sensitivity, Next: Strong Regexp Constants, Prev: GNU Regexp Operators, Up: Regexp 3.8 Case Sensitivity in Matching ================================ @@ -4099,10 +4113,77 @@ and we don't recommend it. that 'gawk' does the right thing. -File: gawk.info, Node: Regexp Summary, Prev: Case-sensitivity, Up: Regexp +File: gawk.info, Node: Strong Regexp Constants, Next: Regexp Summary, Prev: Case-sensitivity, Up: Regexp -3.9 Summary -=========== +3.9 Strongly Typed Regexp Constants +=================================== + +This minor node describes a 'gawk'-specific feature. + + Regexp constants ('/.../') hold a strange position in the 'awk' +language. In most contexts, they act like an expression: '$0 ~ /.../'. +In other contexts, they denote only a regexp to be matched. In no case +are they really a "first class citizen" of the language. That is, you +cannot define a scalar variable whose type is "regexp" in the same sense +that you can define a variable to be a number or a string: + + num = 42 Numeric variable + str = "hi" String variable + re = /foo/ Wrong! re is the result of $0 ~ /foo/ + + For a number of more advanced use cases (described later on in this +Info file), it would be nice to have regexp constants that are "strongly +typed"; in other words, that denote a regexp useful for matching, and +not an expression. + + 'gawk' provides this feature. A strongly typed regexp constant looks +almost like a regular regexp constant, except that it is preceded by an +'@' sign: + + re = @/foo/ Regexp variable + + Strongly typed regexp constants _cannot_ be used eveywhere that a +regular regexp constant can, because this would make the language even +more confusing. Instead, you may use them only in certain contexts: + + * On the righthand side of the '~' and '!~' operators: 'some_var ~ + @/foo/' (*note Regexp Usage::). + + * In the 'case' part of a 'switch' statement (*note Switch + Statement::). + + * As an argument to one of the built-in functions that accept regexp + constants: 'gensub()', 'gsub()', 'match()', 'patsplit()', + 'split()', and 'sub()' (*note String Functions::). + + * As a parameter in a call to a user-defined function (*note + User-defined::). + + * On the righthand side of an assignment to a variable: 'some_var = + @/foo/'. In this case, the type of 'some_var' is regexp. + Additionally, 'some_var' can be used with '~' and '!~', passed to + one of the built-in functions listed above, or passed as a + parameter to a user-defined function. + + You may use the 'typeof()' built-in function (*note Type Functions::) +to determine if a variable or function parameter is a regexp variable. + + The true power of this feature comes from the ability to create +variables that have regexp type. Such variables can be passed on to +user-defined functions, without the confusing aspects of computed +regular expressions created from strings or string constants. They may +also be passed through indirect function calls (*note Indirect Calls::) +onto the built-in functions that accept regexp constants. + + When used in numeric conversions, strongly typed regexp variables +convert to zero. When used in string conversions, they convert to the +string value of the original regexp text. + + +File: gawk.info, Node: Regexp Summary, Prev: Strong Regexp Constants, Up: Regexp + +3.10 Summary +============ * Regular expressions describe sets of strings to be matched. In 'awk', regular expression constants are written enclosed between @@ -4135,6 +4216,9 @@ File: gawk.info, Node: Regexp Summary, Prev: Case-sensitivity, Up: Regexp sensitivity of regexp matching. In other 'awk' versions, use 'tolower()' or 'toupper()'. + * Strongly typed regexp constants ('@/.../') enable certain advanced + use cases to be described later on in the Info file. + File: gawk.info, Node: Reading Files, Next: Printing, Prev: Regexp, Up: Top @@ -4173,6 +4257,7 @@ 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. @@ -4434,7 +4519,7 @@ When 'awk' reads an input record, the record is automatically "parsed" or separated by the 'awk' utility into chunks called "fields". By default, fields are separated by "whitespace", like words in a line. Whitespace in 'awk' means any string of one or more spaces, TABs, or -newlines;(1) other characters that are considered whitespace by other +newlines; other characters that are considered whitespace by other languages (such as formfeed, vertical tab, etc.) are _not_ considered whitespace by 'awk'. @@ -4486,11 +4571,6 @@ record: -| Julie F -| Samuel A - ---------- Footnotes ---------- - - (1) In POSIX 'awk', newlines are not considered whitespace for -separating fields. - File: gawk.info, Node: Nonconstant Fields, Next: Changing Fields, Prev: Fields, Up: Reading Files @@ -5436,6 +5516,11 @@ 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. + If 'ERRNO' indicates that the I/O operation may be retried, and +'PROCINFO["INPUT", "RETRY"]' is set, then 'getline' returns -2 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. @@ -5871,7 +5956,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 ================================= @@ -5950,7 +6035,8 @@ 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 @@ -5964,9 +6050,36 @@ can block indefinitely until some other process opens it for 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 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, by default +'getline' returns -1, and subsequent attempts to read from that file +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 a special element in the 'PROCINFO' array (*note +Auto-set::): + + PROCINFO["INPUT_NAME", "RETRY"] = 1 + + When this element exists, 'gawk' checks the value of the system (C +language) 'errno' variable when an I/O error occurs. If 'errno' +indicates a subsequent I/O attempt may succeed, 'getline' instead +returns -2 and further calls to 'getline' may succeed. This applies to +the '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.11 Directories on the Command Line +4.12 Directories on the Command Line ==================================== According to the POSIX standard, files named on the 'awk' command line @@ -5989,7 +6102,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 @@ -6061,7 +6174,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 @@ -6111,6 +6224,7 @@ function. 'gawk' allows access to inherited file descriptors. * Close Files And Pipes:: Closing Input and Output Files and Pipes. +* Nonfatal:: Enabling Nonfatal Output. * Output Summary:: Output summary. * Output Exercises:: Exercises. @@ -7018,7 +7132,7 @@ that 'gawk' provides: behavior. -File: gawk.info, Node: Close Files And Pipes, Next: Output Summary, Prev: Special Files, Up: Printing +File: gawk.info, Node: Close Files And Pipes, Next: Nonfatal, Prev: Special Files, Up: Printing 5.9 Closing Input and Output Redirections ========================================= @@ -7186,9 +7300,68 @@ call. See the system manual pages for information on how to decode this value. -File: gawk.info, Node: Output Summary, Next: Output Exercises, Prev: Close Files And Pipes, Up: Printing +File: gawk.info, Node: Nonfatal, Next: Output Summary, Prev: Close Files And Pipes, Up: Printing -5.10 Summary +5.10 Enabling Nonfatal Output +============================= + +This minor node describes a 'gawk'-specific feature. + + In standard 'awk', output with 'print' or 'printf' to a nonexistent +file, or some other I/O error (such as filling up the disk) is a fatal +error. + + $ gawk 'BEGIN { print "hi" > "/no/such/file" }' + error-> gawk: cmd. line:1: fatal: can't redirect to `/no/such/file' (No such file or directory) + + 'gawk' makes it possible to detect that an error has occurred, +allowing you to possibly recover from the error, or at least print an +error message of your choosing before exiting. You can do this in one +of two ways: + + * For all output files, by assigning any value to + 'PROCINFO["NONFATAL"]'. + + * On a per-file basis, by assigning any value to 'PROCINFO[FILENAME, + "NONFATAL"]'. Here, FILENAME is the name of the file to which you + wish output to be nonfatal. + + Once you have enabled nonfatal output, you must check 'ERRNO' after +every relevant 'print' or 'printf' statement to see if something went +wrong. It is also a good idea to initialize 'ERRNO' to zero before +attempting the output. For example: + + $ gawk ' + > BEGIN { + > PROCINFO["NONFATAL"] = 1 + > ERRNO = 0 + > print "hi" > "/no/such/file" + > if (ERRNO) { + > print("Output failed:", ERRNO) > "/dev/stderr" + > exit 1 + > } + > }' + error-> Output failed: No such file or directory + + Here, 'gawk' did not produce a fatal error; instead it let the 'awk' +program code detect the problem and handle it. + + This mechanism works also for standard output and standard error. +For standard output, you may use 'PROCINFO["-", "NONFATAL"]' or +'PROCINFO["/dev/stdout", "NONFATAL"]'. For standard error, use +'PROCINFO["/dev/stderr", "NONFATAL"]'. + + When attempting to open a TCP/IP socket (*note TCP/IP Networking::), +'gawk' tries multiple times. The 'GAWK_SOCK_RETRIES' environment +variable (*note Other Environment Variables::) allows you to override +'gawk''s builtin default number of attempts. However, once nonfatal I/O +is enabled for a given socket, 'gawk' only retries once, relying on +'awk'-level code to notice that there was a problem. + + +File: gawk.info, Node: Output Summary, Next: Output Exercises, Prev: Nonfatal, Up: Printing + +5.11 Summary ============ * The 'print' statement prints comma-separated expressions. Each @@ -7210,10 +7383,15 @@ File: gawk.info, Node: Output Summary, Next: Output Exercises, Prev: Close Fi For coprocesses, it is possible to close only one direction of the communications. + * Normally errors with 'print' or 'printf' are fatal. 'gawk' lets + you make output errors be nonfatal either for all files or on a + per-file basis. You must then check for errors after every + relevant output statement. + File: gawk.info, Node: Output Exercises, Prev: Output Summary, Up: Printing -5.11 Exercises +5.12 Exercises ============== 1. Rewrite the program: @@ -10133,7 +10311,7 @@ each variable.) The default value is '" "', a string consisting of a single space. As a special exception, this value means that any sequence of - spaces, TABs, and/or newlines is a single separator.(1) It also + spaces, TABs, and/or newlines is a single separator. It also causes spaces, TABs, and newlines at the beginning and end of a record to be ignored. @@ -10230,10 +10408,6 @@ each variable.) Internationalization::). The default value of 'TEXTDOMAIN' is '"messages"'. - ---------- Footnotes ---------- - - (1) In POSIX 'awk', newline does not count as whitespace. - File: gawk.info, Node: Auto-set, Next: ARGC and ARGV, Prev: User-modified, Up: Built-in Variables @@ -10297,10 +10471,24 @@ they are not special: An associative array containing the values of the environment. The array indices are the environment variable names; the elements are the values of the particular environment variables. For example, - 'ENVIRON["HOME"]' might be '"/home/arnold"'. Changing this array - does not affect the environment passed on to any programs that - 'awk' may spawn via redirection or the 'system()' function. (In a - future version of 'gawk', it may do so.) + 'ENVIRON["HOME"]' might be '/home/arnold'. + + For POSIX 'awk', changing this array does not affect the + environment passed on to any programs that 'awk' may spawn via + redirection or the 'system()' function. + + However, beginning with version 4.2, if not in POSIX compatibility + mode, 'gawk' does update its own environment when 'ENVIRON' is + changed, thus changing the environment seen by programs that it + creates. You should therefore be especially careful if you modify + 'ENVIRON["PATH"]', which is the search path for finding executable + programs. + + This can also affect the running 'gawk' program, since some of the + built-in functions may pay attention to certain environment + variables. The most notable instance of this is 'mktime()' (*note + Time Functions::), which pays attention the value of the 'TZ' + environment variable on many systems. Some operating systems may not have environment variables. On such systems, the 'ENVIRON' array is empty (except for @@ -10323,6 +10511,11 @@ 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 @@ -10371,6 +10564,10 @@ 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. @@ -10469,6 +10666,14 @@ they are not special: The following elements allow you to change 'gawk''s behavior: + 'PROCINFO["NONFATAL"]' + If this element exists, then I/O errors for all output + redirections become nonfatal. *Note Nonfatal::. + + 'PROCINFO["OUTPUT_NAME", "NONFATAL"]' + Make output errors for OUTPUT_NAME be nonfatal. *Note + Nonfatal::. + 'PROCINFO["COMMAND", "pty"]' For two-way communication to COMMAND, use a pseudo-tty instead of setting up a two-way pipe. *Note Two-way I/O:: for more @@ -11870,6 +12075,21 @@ brackets ([ ]): truncated toward zero. For example, 'int(3)' is 3, 'int(3.9)' is 3, 'int(-3.9)' is -3, and 'int(-3)' is -3 as well. +'intdiv(NUMERATOR, DENOMINATOR, RESULT)' + Perform integer division, similar to the standard C function of the + same name. First, truncate 'numerator' and 'denominator' towards + zero, creating integer values. Clear the 'result' array, and then + set 'result["quotient"]' to the result of 'numerator / + denominator', truncated towards zero to an integer, and set + 'result["remainder"]' to the result of 'numerator % denominator', + truncated towards zero to an integer. This function is primarily + intended for use with arbitrary length integers; it avoids creating + MPFR arbitrary precision floating-point values (*note Arbitrary + Precision Integers::). + + This function is a 'gawk' extension. It is not available in + compatibility mode (*note Options::). + 'log(X)' Return the natural logarithm of X, if X is positive; otherwise, return 'NaN' ("not a number") on IEEE 754 systems. Additionally, @@ -13337,14 +13557,56 @@ File: gawk.info, Node: Type Functions, Next: I18N Functions, Prev: Bitwise Fu 9.1.7 Getting Type Information ------------------------------ -'gawk' provides a single function that lets you distinguish an array -from a scalar variable. This is necessary for writing code that -traverses every element of an array of arrays (*note Arrays of -Arrays::). +'gawk' provides two functions that lets you distinguish the type of a +variable. This is necessary for writing code that traverses every +element of an array of arrays (*note Arrays of Arrays::), and in other +contexts. 'isarray(X)' Return a true value if X is an array. Otherwise, return false. +'typeof(X)' + Return one of the following strings, depending upon the type of X: + + '"array"' + X is an array. + + '"regexp"' + X is a strongly typed regexp (*note Strong Regexp + Constants::). + + '"number"' + X is a number. + + '"string"' + X is a string. + + '"strnum"' + X is a string that might be a number, such as a field or the + result of calling 'split()'. (I.e., X has the STRNUM + attribute; *note Variable Typing::.) + + '"unassigned"' + X is a scalar variable that has not been assigned a value yet. + For example: + + BEGIN { + a[1] # creates a[1] but it has no assigned value + print typeof(a[1]) # scalar_u + } + + '"untyped"' + X has not yet been used yet at all; it can become a scalar or + an array. For example: + + BEGIN { + print typeof(x) # x never used --> untyped + mk_arr(x) + print typeof(x) # x now an array --> array + } + + function mk_arr(a) { a[1] = 1 } + 'isarray()' is meant for use in two circumstances. The first is when traversing a multidimensional array: you can test if an element is itself an array or not. The second is inside the body of a user-defined @@ -13358,6 +13620,14 @@ parameter is an array or not. that has not been previously used to 'isarray()', 'gawk' ends up turning it into a scalar. + The 'typeof()' function is general; it allows you to determine if a +variable or function parameter is a scalar, an array, or a strongly +typed regexp. + + 'isarray()' is deprecated; you should use 'typeof()' instead. You +should replace any existing uses of 'isarray(var)' in your code with +'typeof(var) == "array"'. + File: gawk.info, Node: I18N Functions, Prev: Type Functions, Up: Built-in @@ -19673,9 +19943,15 @@ case 'gawk' waits for the child process to exit, which may cause your program to hang. (Thus, this particular feature is of much less use in practice than being able to close the '"to"' end.) - CAUTION: It is a fatal error to write to the '"to"' end of a - two-way pipe which has been closed. It is also a fatal error to - read from the '"from"' end of a two-way pipe that has been closed. + CAUTION: Normally, it is a fatal error to write to the '"to"' end + of a two-way pipe which has been closed, and it is also a fatal + error to read from the '"from"' end of a two-way pipe that has been + closed. + + You may set 'PROCINFO["COMMAND", "NONFATAL"]' to make such + operations become nonfatal, in which case you then need to check + 'ERRNO' after each 'print', 'printf', or 'getline'. *Note + Nonfatal::, for more information. You may also use pseudo-ttys (ptys) for two-way communication instead of pipes, if your system supports them. This is done on a per-command @@ -19963,8 +20239,7 @@ output. They are as follows: you typed when you wrote it. This is because 'gawk' creates the profiled version by "pretty-printing" its internal representation of the program. The advantage to this is that 'gawk' can produce a standard -representation. The disadvantage is that all source code comments are -lost. Also, things such as: +representation. Also, things such as: /foo/ @@ -20023,8 +20298,36 @@ the 'Ctrl-\' key. called this way, 'gawk' "pretty-prints" the program into 'awkprof.out', without any execution counts. - NOTE: The '--pretty-print' option still runs your program. This - will change in the next major release. + NOTE: Once upon a time, the '--pretty-print' option would also run + your program. This is is no longer the case. + + There is a significant difference between the output created when +profiling, and that created when pretty-printing. Pretty-printed output +preserves the original comments that were in the program, although their +placement may not correspond exactly to their original locations in the +source code.(1) + + However, as a deliberate design decision, profiling output _omits_ +the original program's comments. This allows you to focus on the +execution count data and helps you avoid the temptation to use the +profiler for pretty-printing. + + Additionally, pretty-printed output does not have the leading +indentation that the profiling output does. This makes it easy to +pretty-print your code once development is completed, and then use the +result as the final version of your program. + + Because the internal representation of your program is formatted to +recreate an 'awk' program, profiling and pretty-printing automatically +disable 'gawk''s default optimizations. + + ---------- Footnotes ---------- + + (1) 'gawk' does the best it can to preserve the distinction between +comments at the end of a statement and comments on lines by themselves. +Due to implementation constraints, it does not always do so correctly, +particularly for 'switch' statements. The 'gawk' maintainers hope to +improve this in a subsequent release. File: gawk.info, Node: Advanced Features Summary, Prev: Profiling, Up: Advanced Features @@ -20065,8 +20368,7 @@ File: gawk.info, Node: Advanced Features Summary, Prev: Profiling, Up: Advanc 'USR1' signal while profiling causes 'gawk' to dump the profile and keep going, including a function call stack. - * You can also just "pretty-print" the program. This currently also - runs the program, but that will change in the next major release. + * You can also just "pretty-print" the program. File: gawk.info, Node: Internationalization, Next: Debugger, Prev: Advanced Features, Up: Top @@ -21744,6 +22046,62 @@ some limitations. A few that it's worth being aware of are: * The 'gawk' debugger only accepts source code supplied with the '-f' option. + One other point is worth disucssing. Conventional debuggers run in a +separate process (and thus address space) from the programs that they +debug (the "debuggee", if you will). + + The 'gawk' debugger is different; it is an integrated part of 'gawk' +itself. This makes it possible, in rare cases, for 'gawk' to become an +excellent demonstrator of Heisenberg Uncertainty physics, where the mere +act of observing something can change it. Consider the following:(1) + + $ cat test.awk + -| { print typeof($1), typeof($2) } + $ cat test.data + -| abc 123 + $ gawk -f test.awk test.data + -| strnum strnum + + This is all as expected: field data has the STRNUM attribute (*note +Variable Typing::). Now watch what happens when we run this program +under the debugger: + + $ gawk -D -f test.awk test.data + gawk> w $1 Set watchpoint on $1 + -| Watchpoint 1: $1 + gawk> w $2 Set watchpoint on $2 + -| Watchpoint 2: $2 + gawk> r Start the program + -| Starting program: + -| Stopping in Rule ... + -| Watchpoint 1: $1 Watchpoint fires + -| Old value: "" + -| New value: "abc" + -| main() at `test.awk':1 + -| 1 { print typeof($1), typeof($2) } + gawk> n Keep going ... + -| Watchpoint 2: $2 Watchpoint fires + -| Old value: "" + -| New value: "123" + -| main() at `test.awk':1 + -| 1 { print typeof($1), typeof($2) } + gawk> n Get result from typeof() + -| strnum number Result for $2 isn't right + -| Program exited normally with exit value: 0 + gawk> quit + + In this case, the act of comparing the new value of '$2' with the old +one caused 'gawk' to evaluate it and determine that it is indeed a +number, and this is reflected in the result of 'typeof()'. + + Cases like this where the debugger is not transparent to the +program's execution should be rare. If you encounter one, please report +it (*note Bugs::). + + ---------- Footnotes ---------- + + (1) Thanks to Hermann Peifer for this example. + File: gawk.info, Node: Debugging Summary, Prev: Limitations, Up: Debugger @@ -21772,6 +22130,9 @@ File: gawk.info, Node: Debugging Summary, Prev: Limitations, Up: Debugger it is used by the debugger to provide command-line history and editing. + * Usually, the debugger does not not affect the program being + debugged, but occasionally it can. + File: gawk.info, Node: Arbitrary Precision Arithmetic, Next: Dynamic Extensions, Prev: Debugger, Up: Top @@ -22505,6 +22866,62 @@ the following: gawk -M 'BEGIN { n = 13; print n % 2 }' + When dividing two arbitrary precision integers with either '/' or +'%', the result is typically an arbitrary precision floating point value +(unless the denominator evenly divides into the numerator). In order to +do integer division or remainder with arbitrary precision integers, use +the built-in 'intdiv()' function (*note Numeric Functions::). + + You can simulate the 'intdiv()' function in standard 'awk' using this +user-defined function: + + # intdiv --- do integer division + + function intdiv(numerator, denominator, result) + { + split("", result) + + numerator = int(numerator) + denominator = int(denominator) + result["quotient"] = int(numerator / denominator) + result["remainder"] = int(numerator % denominator) + + return 0.0 + } + + The following example program, contributed by Katie Wasserman, uses +'intdiv()' to compute the digits of pi to as many places as you choose +to set: + + # pi.awk --- compute the digits of pi + + BEGIN { + digits = 100000 + two = 2 * 10 ^ digits + pi = two + for (m = digits * 4; m > 0; --m) { + d = m * 2 + 1 + x = pi * m + intdiv(x, d, result) + pi = result["quotient"] + pi = pi + two + } + print pi + } + + When asked about the algorithm used, Katie replied: + + It's not that well known but it's not that obscure either. It's + Euler's modification to Newton's method for calculating pi. Take a + look at lines (23) - (25) here: + <http://mathworld.wolfram.com/PiFormulas.html>. + + The algorithm I wrote simply expands the multiply by 2 and works + from the innermost expression outwards. I used this to program HP + calculators because it's quite easy to modify for tiny memory + devices with smallish word sizes. See + <http://www.hpmuseum.org/cgi-sys/cgiwrap/hpmuseum/articles.cgi?read=899>. + ---------- Footnotes ---------- (1) Weisstein, Eric W. 'Sylvester's Sequence'. From MathWorld--A @@ -22867,6 +23284,7 @@ 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. @@ -22922,6 +23340,8 @@ 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 @@ -23279,7 +23699,7 @@ Extension functions are described by the following record: typedef struct awk_ext_func { const char *name; awk_value_t *(*function)(int num_actual_args, awk_value_t *result); - size_t num_expected_args; + size_t max_expected_args; } awk_ext_func_t; The fields are: @@ -23306,11 +23726,17 @@ Extension functions are described by the following record: The function must return the value of 'result'. This is for the convenience of the calling code inside 'gawk'. -'size_t num_expected_args;' - This is the number of arguments the function expects to receive. - Each extension function may decide what to do if the number of - arguments isn't what it expected. As with real 'awk' functions, it - is likely OK to ignore extra arguments. +'size_t max_expected_args;' + This is the maximum number of arguments the function expects to + receive. Each extension function may decide what to do if the + number of arguments isn't what it expected. As with real 'awk' + functions, it is likely OK to ignore extra arguments. This value + does not affect actual program execution. + + Extension functions should compare this value to the number of + actual arguments passed and possibly issue a lint warning if there + is an undesirable mismatch. Of course, if '--lint=fatal' is used, + this would cause the program to exit. Once you have a record representing your extension function, you register it with 'gawk' using this API function: @@ -23763,6 +24189,9 @@ extension ID received from 'gawk' when the extension was loaded:(1) 'void fatal(awk_ext_id_t id, const char *format, ...);' Print a message and then cause 'gawk' to exit immediately. +'void nonfatal(awk_ext_id_t id, const char *format, ...);' + Print a nonfatal error message. + 'void warning(awk_ext_id_t id, const char *format, ...);' Print a warning message. @@ -24127,7 +24556,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 -------------------------- @@ -24611,9 +25040,78 @@ array: environment variable.) -File: gawk.info, Node: Extension API Variables, Next: Extension API Boilerplate, Prev: Array Manipulation, Up: Extension API Description +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 zero, return data for the currently open + input file corresponding to 'FILENAME'. (This does not access the + 'filetype' argument, so that may be undefined). If the file is not + already open, attempt to open it. The 'filetype' argument must be + zero-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, return a 'false' value. Otherwise, return 'true', and + return additional information about the redirection 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 'fd' + is non-negative, but the file exists already, 'gawk' ignores '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. -16.4.12 API Variables + Note that supplying a file descriptor is currently _not_ supported + for pipes. However, supplying a file descriptor should work for + input, output, append, and two-way (coprocess) sockets. If + 'filetype' is two-way, 'gawk' assumes that it is a socket! Note + that in the two-way case, the input and output file descriptors may + differ. To check for success, you 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 @@ -24630,7 +25128,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 @@ -24682,7 +25180,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 @@ -24717,7 +25215,7 @@ 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 @@ -26045,15 +26543,17 @@ project. * GD graphics library extension + * MPFR library extension (this provides access to a number of MPFR + functions that 'gawk''s native MPFR support does not) + * PDF extension * PostgreSQL extension - * MPFR library extension (this provides access to a number of MPFR - functions that 'gawk''s native MPFR support does not) - * Redis extension + * Select extension + * XML parser extension, using the Expat (http://expat.sourceforge.net) XML parsing library @@ -26131,7 +26631,7 @@ File: gawk.info, Node: Extension summary, Next: Extension Exercises, Prev: ga exit callbacks, a version string, input parsers, output wrappers, and two-way processors) - * Printing fatal, warning, and "lint" warning messages + * Printing fatal, nonfatal, warning, and "lint" warning messages * Updating 'ERRNO', or unsetting it @@ -26466,6 +26966,9 @@ current version of 'gawk'. - Directories on the command line produce a warning and are skipped (*note Command-line directories::) + - Output with 'print' and 'printf' need not be fatal (*note + Nonfatal::) + * New keywords: - The 'BEGINFILE' and 'ENDFILE' special patterns (*note @@ -26515,6 +27018,9 @@ current version of 'gawk'. - The 'bindtextdomain()', 'dcgettext()', and 'dcngettext()' functions for internationalization (*note Programmer i18n::) + - The 'intdiv()' function for doing integer division and + remainder (*note Numeric Functions::) + * Changes and/or additions in the command-line options: - The 'AWKPATH' environment variable for specifying a path @@ -26525,16 +27031,16 @@ current version of 'gawk'. - The '-b', '-c', '-C', '-d', '-D', '-e', '-E', '-g', '-h', '-i', '-l', '-L', '-M', '-n', '-N', '-o', '-O', '-p', '-P', - '-r', '-S', '-t', and '-V' short options. Also, the ability - to use GNU-style long-named options that start with '--', and - the '--assign', '--bignum', '--characters-as-bytes', + '-r', '-s', '-S', '-t', and '-V' short options. Also, the + ability to use GNU-style long-named options that start with + '--', and the '--assign', '--bignum', '--characters-as-bytes', '--copyright', '--debug', '--dump-variables', '--exec', '--field-separator', '--file', '--gen-pot', '--help', '--include', '--lint', '--lint-old', '--load', - '--non-decimal-data', '--optimize', '--posix', - '--pretty-print', '--profile', '--re-interval', '--sandbox', - '--source', '--traditional', '--use-lc-numeric', and - '--version' long options (*note Options::). + '--non-decimal-data', '--optimize', '--no-optimize', + '--posix', '--pretty-print', '--profile', '--re-interval', + '--sandbox', '--source', '--traditional', '--use-lc-numeric', + and '--version' long options (*note Options::). * Support for the following obsolete systems was removed from the code and the documentation for 'gawk' version 4.0: @@ -26568,6 +27074,11 @@ current version of 'gawk'. - Ultrix + * Support for the following systems was removed from the code for + 'gawk' version 4.2: + + - MirBSD + File: gawk.info, Node: Feature History, Next: Common Extensions, Prev: POSIX/GNU, Up: Language History @@ -26959,6 +27470,34 @@ POSIX 'awk', in the order they were added to 'gawk'. * Support for Ultrix was removed. + Version 4.2 introduced the following changes: + + * Changes to 'ENVIRON' are reflected into 'gawk''s environment and + that of programs that it runs. *Note Auto-set::. + + * The '--pretty-print' option no longer runs the 'awk' program too. + *Note Options::. + + * The 'igawk' program and its manual page are no longer installed + when 'gawk' is built. *Note Igawk Program::. + + * The 'intdiv()' function. *Note Numeric Functions::. + + * The maximum number of hexadecimal digits in '\x' escapes is now + two. *Note Escape Sequences::. + + * Nonfatal output with 'print' and 'printf'. *Note Nonfatal::. + + * For many years, POSIX specified that default field splitting only + allowed spaces and tabs to separate fields, and this was how 'gawk' + behaved with '--posix'. As of 2013, the standard restored + historical behavior, and now default field splitting with '--posix' + also allows newlines to separate fields. + + * Support for MirBSD was removed. + + * Support for GNU/Linux on Alpha was removed. + File: gawk.info, Node: Common Extensions, Next: Ranges and Locales, Prev: Feature History, Up: Language History @@ -27477,7 +28016,9 @@ Various '.c', '.y', and '.h' files 'doc/igawk.1' The 'troff' source for a manual page describing the 'igawk' program - presented in *note Igawk Program::. + presented in *note Igawk Program::. (Since 'gawk' can do its own + '@include' processing, neither 'igawk' nor 'igawk.1' are + installed.) 'doc/Makefile.in' The input file used during the configuration process to generate @@ -27519,17 +28060,22 @@ Various '.c', '.y', and '.h' files contains a 'Makefile.in' file, which 'configure' uses to generate a 'Makefile'. 'Makefile.am' is used by GNU Automake to create 'Makefile.in'. The library functions from *note Library - Functions::, and the 'igawk' program from *note Igawk Program:: are - included as ready-to-use files in the 'gawk' distribution. They - are installed as part of the installation process. The rest of the - programs in this Info file are available in appropriate - subdirectories of 'awklib/eg'. + Functions::, are included as ready-to-use files in the 'gawk' + distribution. They are installed as part of the installation + process. The rest of the programs in this Info file are available + in appropriate subdirectories of 'awklib/eg'. 'extension/*' The source code, manual pages, and infrastructure files for the sample extensions included with 'gawk'. *Note Dynamic Extensions::, for more information. +'extras/*' + Additional non-essential files. Currently, this directory contains + some shell startup files to be installed in '/etc/profile.d' to aid + in manipulating the 'AWKPATH' and 'AWKLIBPATH' environment + variables. *Note Shell Startup Files::, for more information. + 'posix/*' Files needed for building 'gawk' on POSIX-compliant systems. @@ -27560,11 +28106,12 @@ for your system yourself. * Menu: * Quick Installation:: Compiling 'gawk' under Unix. +* Shell Startup Files:: Shell convenience functions. * Additional Configuration Options:: Other compile-time options. * Configuration Philosophy:: How it's all supposed to work. -File: gawk.info, Node: Quick Installation, Next: Additional Configuration Options, Up: Unix Installation +File: gawk.info, Node: Quick Installation, Next: Shell Startup Files, Up: Unix Installation B.2.1 Compiling 'gawk' for Unix-Like Systems -------------------------------------------- @@ -27619,9 +28166,42 @@ will be asked for your password, and you will have to have been set up previously as a user who is allowed to run the 'sudo' command. -File: gawk.info, Node: Additional Configuration Options, Next: Configuration Philosophy, Prev: Quick Installation, Up: Unix Installation +File: gawk.info, Node: Shell Startup Files, Next: Additional Configuration Options, Prev: Quick Installation, Up: Unix Installation + +B.2.2 Shell Startup Files +------------------------- + +The distribution contains shell startup files 'gawk.sh' and 'gawk.csh' +containing functions to aid in manipulating the 'AWKPATH' and +'AWKLIBPATH' environment variables. On a Fedora system, these files +should be installed in '/etc/profile.d'; on other platforms, the +appropriate location may be different. + +'gawkpath_default' + Reset the 'AWKPATH' environment variable to its default value. -B.2.2 Additional Configuration Options +'gawkpath_prepend' + Add the argument to the front of the 'AWKPATH' environment + variable. + +'gawkpath_append' + Add the argument to the end of the 'AWKPATH' environment variable. + +'gawklibpath_default' + Reset the 'AWKLIBPATH' environment variable to its default value. + +'gawklibpath_prepend' + Add the argument to the front of the 'AWKLIBPATH' environment + variable. + +'gawklibpath_append' + Add the argument to the end of the 'AWKLIBPATH' environment + variable. + + +File: gawk.info, Node: Additional Configuration Options, Next: Configuration Philosophy, Prev: Shell Startup Files, Up: Unix Installation + +B.2.3 Additional Configuration Options -------------------------------------- There are several additional options you may use on the 'configure' @@ -27665,7 +28245,7 @@ supplied by 'configure'. File: gawk.info, Node: Configuration Philosophy, Prev: Additional Configuration Options, Up: Unix Installation -B.2.3 The Configuration Process +B.2.4 The Configuration Process ------------------------------- This minor node is of interest only if you know something about using @@ -31656,20 +32236,21 @@ Index * --include option: Options. (line 159) * --lint option: Command Line. (line 20) * --lint option <1>: Options. (line 184) -* --lint-old option: Options. (line 294) +* --lint-old option: Options. (line 299) * --load option: Options. (line 172) +* --no-optimize option: Options. (line 285) * --non-decimal-data option: Options. (line 209) * --non-decimal-data option <1>: Nondecimal Data. (line 6) * --non-decimal-data option, strtonum() function and: Nondecimal Data. (line 35) -* --optimize option: Options. (line 236) -* --posix option: Options. (line 254) +* --optimize option: Options. (line 234) +* --posix option: Options. (line 257) * --posix option, --traditional option and: Options. (line 272) * --pretty-print option: Options. (line 223) -* --profile option: Options. (line 242) +* --profile option: Options. (line 245) * --profile option <1>: Profiling. (line 12) * --re-interval option: Options. (line 278) -* --sandbox option: Options. (line 285) +* --sandbox option: Options. (line 290) * --sandbox option, disabling system() function: I/O Functions. (line 129) * --sandbox option, input redirection with getline: Getline. (line 19) @@ -31679,7 +32260,7 @@ Index * --traditional option: Options. (line 82) * --traditional option, --posix option and: Options. (line 272) * --use-lc-numeric option: Options. (line 218) -* --version option: Options. (line 299) +* --version option: Options. (line 304) * --with-whiny-user-strftime configuration option: Additional Configuration Options. (line 37) * -b option: Options. (line 69) @@ -31689,31 +32270,32 @@ Index * -D option: Options. (line 108) * -e option: Options. (line 117) * -E option: Options. (line 125) -* -e option <1>: Options. (line 335) +* -e option <1>: Options. (line 340) * -f option: Long. (line 12) * -F option: Options. (line 21) * -f option <1>: Options. (line 25) -* -F option, -Ft sets FS to TAB: Options. (line 307) +* -F option, -Ft sets FS to TAB: Options. (line 312) * -F option, command-line: Command Line Field Separator. (line 6) -* -f option, multiple uses: Options. (line 312) +* -f option, multiple uses: Options. (line 317) * -g option: Options. (line 147) * -h option: Options. (line 154) * -i option: Options. (line 159) * -l option: Options. (line 172) * -l option <1>: Options. (line 184) -* -L option: Options. (line 294) +* -L option: Options. (line 299) * -M option: Options. (line 203) * -n option: Options. (line 209) * -N option: Options. (line 218) * -o option: Options. (line 223) -* -O option: Options. (line 236) -* -p option: Options. (line 242) -* -P option: Options. (line 254) +* -O option: Options. (line 234) +* -p option: Options. (line 245) +* -P option: Options. (line 257) * -r option: Options. (line 278) -* -S option: Options. (line 285) +* -s option: Options. (line 285) +* -S option: Options. (line 290) * -v option: Options. (line 32) -* -V option: Options. (line 299) +* -V option: Options. (line 304) * -v option <1>: Assignment Options. (line 12) * -W option: Options. (line 47) * . (period), regexp operator: Regexp Operators. (line 44) @@ -31786,16 +32368,16 @@ Index (line 6) * \ (backslash), in bracket expressions: Bracket Expressions. (line 25) * \ (backslash), in escape sequences: Escape Sequences. (line 6) -* \ (backslash), in escape sequences <1>: Escape Sequences. (line 100) +* \ (backslash), in escape sequences <1>: Escape Sequences. (line 103) * \ (backslash), in escape sequences, POSIX and: Escape Sequences. - (line 105) + (line 108) * \ (backslash), in regexp constants: Computed Regexps. (line 30) * \ (backslash), in shell commands: Quoting. (line 48) * \ (backslash), regexp operator: Regexp Operators. (line 18) -* \ (backslash), \" escape sequence: Escape Sequences. (line 82) +* \ (backslash), \" escape sequence: Escape Sequences. (line 85) * \ (backslash), \' operator (gawk): GNU Regexp Operators. (line 59) -* \ (backslash), \/ escape sequence: Escape Sequences. (line 73) +* \ (backslash), \/ escape sequence: Escape Sequences. (line 76) * \ (backslash), \< operator (gawk): GNU Regexp Operators. (line 33) * \ (backslash), \> operator (gawk): GNU Regexp Operators. @@ -32012,7 +32594,7 @@ Index * awf (amazingly workable formatter) program: Glossary. (line 24) * awk debugging, enabling: Options. (line 108) * awk language, POSIX version: Assignment Ops. (line 138) -* awk profiling, enabling: Options. (line 242) +* awk profiling, enabling: Options. (line 245) * awk programs: Getting Started. (line 12) * awk programs <1>: Executable Scripts. (line 6) * awk programs <2>: Two Rules. (line 6) @@ -32083,16 +32665,16 @@ Index (line 6) * backslash (\), in bracket expressions: Bracket Expressions. (line 25) * backslash (\), in escape sequences: Escape Sequences. (line 6) -* backslash (\), in escape sequences <1>: Escape Sequences. (line 100) +* backslash (\), in escape sequences <1>: Escape Sequences. (line 103) * backslash (\), in escape sequences, POSIX and: Escape Sequences. - (line 105) + (line 108) * backslash (\), in regexp constants: Computed Regexps. (line 30) * backslash (\), in shell commands: Quoting. (line 48) * backslash (\), regexp operator: Regexp Operators. (line 18) -* backslash (\), \" escape sequence: Escape Sequences. (line 82) +* backslash (\), \" escape sequence: Escape Sequences. (line 85) * backslash (\), \' operator (gawk): GNU Regexp Operators. (line 59) -* backslash (\), \/ escape sequence: Escape Sequences. (line 73) +* backslash (\), \/ escape sequence: Escape Sequences. (line 76) * backslash (\), \< operator (gawk): GNU Regexp Operators. (line 33) * backslash (\), \> operator (gawk): GNU Regexp Operators. @@ -32211,7 +32793,7 @@ Index * Brennan, Michael <5>: Other Versions. (line 6) * Brennan, Michael <6>: Other Versions. (line 48) * Brian Kernighan's awk: When. (line 21) -* Brian Kernighan's awk <1>: Escape Sequences. (line 109) +* Brian Kernighan's awk <1>: Escape Sequences. (line 112) * Brian Kernighan's awk <2>: GNU Regexp Operators. (line 85) * Brian Kernighan's awk <3>: Regexp Field Splitting. @@ -32419,7 +33001,7 @@ Index * cosine: Numeric Functions. (line 16) * counting: Wc Program. (line 6) * csh utility: Statements/Lines. (line 43) -* csh utility, POSIXLY_CORRECT environment variable: Options. (line 353) +* csh utility, POSIXLY_CORRECT environment variable: Options. (line 358) * csh utility, |& operator, comparison with: Two-way I/O. (line 27) * ctime() user-defined function: Function Example. (line 74) * currency symbols, localization: Explaining gettext. (line 104) @@ -32449,12 +33031,12 @@ Index * dark corner, CONVFMT variable: Strings And Numbers. (line 39) * dark corner, escape sequences: Other Arguments. (line 38) * dark corner, escape sequences, for metacharacters: Escape Sequences. - (line 141) + (line 144) * dark corner, exit statement: Exit Statement. (line 30) * dark corner, field separators: Full Line Fields. (line 22) * dark corner, FILENAME variable: Getline Notes. (line 19) -* dark corner, FILENAME variable <1>: Auto-set. (line 89) -* dark corner, FNR/NR variables: Auto-set. (line 313) +* dark corner, FILENAME variable <1>: Auto-set. (line 108) +* dark corner, FNR/NR variables: Auto-set. (line 344) * dark corner, format-control characters: Control Letters. (line 18) * dark corner, format-control characters <1>: Control Letters. (line 93) @@ -32649,12 +33231,12 @@ Index (line 132) * differences in awk and gawk, command-line directories: Command-line directories. (line 6) -* differences in awk and gawk, ERRNO variable: Auto-set. (line 73) +* differences in awk and gawk, ERRNO variable: Auto-set. (line 87) * differences in awk and gawk, error messages: Special FD. (line 19) * 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 115) +* differences in awk and gawk, FUNCTAB variable: Auto-set. (line 134) * differences in awk and gawk, function arguments (gawk): Calling Built-in. (line 16) * differences in awk and gawk, getline command: Getline. (line 19) @@ -32677,7 +33259,7 @@ Index (line 262) * differences in awk and gawk, print/printf statements: Format Modifiers. (line 13) -* differences in awk and gawk, PROCINFO array: Auto-set. (line 129) +* differences in awk and gawk, PROCINFO array: Auto-set. (line 148) * differences in awk and gawk, read timeouts: Read Timeout. (line 6) * differences in awk and gawk, record separators: awk split records. (line 124) @@ -32685,9 +33267,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 264) +* differences in awk and gawk, RT variable: Auto-set. (line 295) * differences in awk and gawk, single-character fields: Single Character Fields. (line 6) * differences in awk and gawk, split() function: String Functions. @@ -32695,7 +33279,7 @@ Index * differences in awk and gawk, strings: Scalar Constants. (line 20) * differences in awk and gawk, strings, storing: gawk split records. (line 76) -* differences in awk and gawk, SYMTAB variable: Auto-set. (line 268) +* differences in awk and gawk, SYMTAB variable: Auto-set. (line 299) * differences in awk and gawk, TEXTDOMAIN variable: User-modified. (line 152) * differences in awk and gawk, trunc-mod operation: Arithmetic Ops. @@ -32731,12 +33315,12 @@ Index * dump debugger command: Miscellaneous Debugger Commands. (line 9) * dupword.awk program: Dupword Program. (line 31) -* dynamic profiling: Profiling. (line 178) +* dynamic profiling: Profiling. (line 177) * 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 134) -* effective user ID of gawk user: Auto-set. (line 138) +* effective group ID of gawk user: Auto-set. (line 153) +* effective user ID of gawk user: Auto-set. (line 161) * egrep utility: Bracket Expressions. (line 34) * egrep utility <1>: Egrep Program. (line 6) * egrep.awk program: Egrep Program. (line 53) @@ -32790,14 +33374,14 @@ Index (line 11) * equals sign (=), == operator <1>: Precedence. (line 64) * EREs (Extended Regular Expressions): Bracket Expressions. (line 34) -* ERRNO variable: Auto-set. (line 73) +* ERRNO variable: Auto-set. (line 87) * ERRNO variable <1>: TCP/IP Networking. (line 54) * ERRNO variable, with BEGINFILE pattern: BEGINFILE/ENDFILE. (line 26) * ERRNO variable, with close() function: Close Files And Pipes. (line 140) * ERRNO variable, with getline command: Getline. (line 19) * error handling: Special FD. (line 19) -* error handling, ERRNO variable and: Auto-set. (line 73) +* error handling, ERRNO variable and: Auto-set. (line 87) * error output: Special FD. (line 6) * escape processing, gsub()/gensub()/sub() functions: Gory Details. (line 6) @@ -32838,7 +33422,7 @@ Index (line 102) * exp: Numeric Functions. (line 19) * expand utility: Very Simple. (line 73) -* Expat XML parser library: gawkextlib. (line 35) +* Expat XML parser library: gawkextlib. (line 37) * exponent: Numeric Functions. (line 19) * expressions: Expressions. (line 6) * expressions, as patterns: Expression Patterns. (line 6) @@ -32857,7 +33441,7 @@ Index (line 6) * extension API version: Extension Versioning. (line 6) -* extension API, version number: Auto-set. (line 223) +* extension API, version number: Auto-set. (line 246) * extension example: Extension Example. (line 6) * extension registration: Registration Functions. (line 6) @@ -32913,7 +33497,6 @@ Index * field separators, choice of: Field Separators. (line 50) * field separators, FIELDWIDTHS variable and: User-modified. (line 37) * field separators, FPAT variable and: User-modified. (line 43) -* field separators, POSIX and: Fields. (line 6) * field separators, regular expressions as: Field Separators. (line 50) * field separators, regular expressions as <1>: Regexp Field Splitting. (line 6) @@ -32941,7 +33524,7 @@ Index * file names, in compatibility mode: Special Caveats. (line 9) * file names, standard streams in gawk: Special FD. (line 48) * FILENAME variable: Reading Files. (line 6) -* FILENAME variable <1>: Auto-set. (line 89) +* FILENAME variable <1>: Auto-set. (line 108) * FILENAME variable, getline, setting with: Getline Notes. (line 19) * filenames, assignments as: Ignoring Assigns. (line 6) * files, .gmo: Explaining gettext. (line 42) @@ -33009,8 +33592,8 @@ Index * fnmatch() extension function: Extension Sample Fnmatch. (line 12) * FNR variable: Records. (line 6) -* FNR variable <1>: Auto-set. (line 99) -* FNR variable, changing: Auto-set. (line 313) +* FNR variable <1>: Auto-set. (line 118) +* FNR variable, changing: Auto-set. (line 344) * for statement: For Statement. (line 6) * for statement, looping over arrays: Scanning an Array. (line 20) * fork() extension function: Extension Sample Fork. @@ -33062,7 +33645,7 @@ Index * FSF (Free Software Foundation) <3>: Glossary. (line 405) * fts() extension function: Extension Sample File Functions. (line 60) -* FUNCTAB array: Auto-set. (line 115) +* FUNCTAB array: Auto-set. (line 134) * function calls: Function Calls. (line 6) * function calls, indirect: Indirect Calls. (line 6) * function calls, indirect, @-notation for: Indirect Calls. (line 47) @@ -33113,8 +33696,8 @@ Index * G., Daniel Richard: Acknowledgments. (line 60) * G., Daniel Richard <1>: Bugs. (line 73) * Garfinkle, Scott: Contributors. (line 35) -* gawk program, dynamic profiling: Profiling. (line 178) -* gawk version: Auto-set. (line 198) +* gawk program, dynamic profiling: Profiling. (line 177) +* gawk version: Auto-set. (line 221) * gawk, ARGIND variable in: Other Arguments. (line 15) * gawk, awk and: Preface. (line 21) * gawk, awk and <1>: This Manual. (line 14) @@ -33135,10 +33718,10 @@ Index * gawk, ERRNO variable in <1>: Close Files And Pipes. (line 140) * gawk, ERRNO variable in <2>: BEGINFILE/ENDFILE. (line 26) -* gawk, ERRNO variable in <3>: Auto-set. (line 73) +* gawk, ERRNO variable in <3>: Auto-set. (line 87) * gawk, ERRNO variable in <4>: TCP/IP Networking. (line 54) -* gawk, escape sequences: Escape Sequences. (line 118) -* gawk, extensions, disabling: Options. (line 254) +* gawk, escape sequences: Escape Sequences. (line 121) +* gawk, extensions, disabling: Options. (line 257) * gawk, features, adding: Adding Code. (line 6) * gawk, features, advanced: Advanced Features. (line 6) * gawk, field separators and: User-modified. (line 71) @@ -33150,7 +33733,7 @@ Index * gawk, FPAT variable in: Splitting By Content. (line 25) * gawk, FPAT variable in <1>: User-modified. (line 43) -* gawk, FUNCTAB array in: Auto-set. (line 115) +* gawk, FUNCTAB array in: Auto-set. (line 134) * gawk, function arguments and: Calling Built-in. (line 16) * gawk, hexadecimal numbers and: Nondecimal-numbers. (line 41) * gawk, IGNORECASE variable in: Case-sensitivity. (line 26) @@ -33180,9 +33763,9 @@ Index * gawk, octal numbers and: Nondecimal-numbers. (line 41) * gawk, OS/2 version of: PC Using. (line 17) * gawk, predefined variables and: Built-in Variables. (line 14) -* gawk, PROCINFO array in: Auto-set. (line 129) +* gawk, PROCINFO array in: Auto-set. (line 148) * gawk, PROCINFO array in <1>: Time Functions. (line 47) -* gawk, PROCINFO array in <2>: Two-way I/O. (line 108) +* gawk, PROCINFO array in <2>: Two-way I/O. (line 114) * gawk, regexp constants and: Using Constant Regexps. (line 28) * gawk, regular expressions, case sensitivity: Case-sensitivity. @@ -33192,21 +33775,27 @@ Index * gawk, regular expressions, precedence: Regexp Operators. (line 161) * gawk, RT variable in: awk split records. (line 124) * gawk, RT variable in <1>: Multiple Line. (line 130) -* gawk, RT variable in <2>: Auto-set. (line 264) +* gawk, RT variable in <2>: Auto-set. (line 295) * gawk, See Also awk: Preface. (line 34) * gawk, source code, obtaining: Getting. (line 6) * gawk, splitting fields and: Constant Size. (line 86) * gawk, string-translation functions: I18N Functions. (line 6) -* gawk, SYMTAB array in: Auto-set. (line 268) +* gawk, SYMTAB array in: Auto-set. (line 299) * gawk, TEXTDOMAIN variable in: User-modified. (line 152) * gawk, timestamps: Time Functions. (line 6) * gawk, uses for: Preface. (line 34) -* gawk, versions of, information about, printing: Options. (line 299) +* gawk, versions of, information about, printing: Options. (line 304) * gawk, VMS version of: VMS Installation. (line 6) * gawk, word-boundary operator: GNU Regexp Operators. (line 66) * gawkextlib: gawkextlib. (line 6) * gawkextlib project: gawkextlib. (line 6) +* gawklibpath_append shell function: Shell Startup Files. (line 29) +* gawklibpath_default shell function: Shell Startup Files. (line 22) +* gawklibpath_prepend shell function: Shell Startup Files. (line 25) +* gawkpath_append shell function: Shell Startup Files. (line 19) +* gawkpath_default shell function: Shell Startup Files. (line 12) +* gawkpath_prepend shell function: Shell Startup Files. (line 15) * General Public License (GPL): Glossary. (line 396) * General Public License, See GPL: Manual History. (line 11) * generate time values: Time Functions. (line 25) @@ -33260,7 +33849,7 @@ Index * gettext() function (C library): Explaining gettext. (line 63) * gettimeofday() extension function: Extension Sample Time. (line 12) -* git utility: gawkextlib. (line 29) +* git utility: gawkextlib. (line 31) * git utility <1>: Other Versions. (line 29) * git utility <2>: Accessing The Source. (line 10) @@ -33288,7 +33877,7 @@ Index * Grigera, Juan: Contributors. (line 58) * group database, reading: Group Functions. (line 6) * group file: Group Functions. (line 6) -* group ID of gawk user: Auto-set. (line 147) +* group ID of gawk user: Auto-set. (line 170) * groups, information about: Group Functions. (line 6) * gsub: Using Constant Regexps. (line 43) @@ -33310,7 +33899,7 @@ Index * history expansion, in debugger: Readline Support. (line 6) * histsort.awk program: History Sorting. (line 25) * Hughes, Phil: Acknowledgments. (line 43) -* HUP signal, for dynamic profiling: Profiling. (line 210) +* HUP signal, for dynamic profiling: Profiling. (line 209) * hyphen (-), - operator: Precedence. (line 51) * hyphen (-), - operator <1>: Precedence. (line 57) * hyphen (-), -- operator: Increment Ops. (line 48) @@ -33392,7 +33981,9 @@ Index * installing gawk: Installation. (line 6) * instruction tracing, in debugger: Debugger Info. (line 90) * int: Numeric Functions. (line 24) -* INT signal (MS-Windows): Profiling. (line 213) +* INT signal (MS-Windows): Profiling. (line 212) +* intdiv: Numeric Functions. (line 29) +* intdiv <1>: Numeric Functions. (line 29) * integer array indices: Numeric Array Subscripts. (line 31) * integers, arbitrary precision: Arbitrary Precision Integers. @@ -33448,7 +34039,7 @@ Index * Kernighan, Brian <8>: Other Versions. (line 13) * Kernighan, Brian <9>: Basic Data Typing. (line 54) * Kernighan, Brian <10>: Glossary. (line 206) -* kill command, dynamic profiling: Profiling. (line 187) +* kill command, dynamic profiling: Profiling. (line 186) * Knights, jedi: Undocumented. (line 6) * Kwok, Conrad: Contributors. (line 35) * l debugger command (alias for list): Miscellaneous Debugger Commands. @@ -33520,7 +34111,7 @@ Index * lint checking, empty programs: Command Line. (line 16) * lint checking, issuing warnings: Options. (line 184) * lint checking, POSIXLY_CORRECT environment variable: Options. - (line 338) + (line 343) * lint checking, undefined functions: Pass By Value/Reference. (line 85) * LINT variable: User-modified. (line 87) @@ -33541,9 +34132,9 @@ Index * localization: I18N and L10N. (line 6) * localization, See internationalization, localization: I18N and L10N. (line 6) -* log: Numeric Functions. (line 29) +* log: Numeric Functions. (line 44) * log files, timestamps in: Time Functions. (line 6) -* logarithm: Numeric Functions. (line 29) +* logarithm: Numeric Functions. (line 44) * logical false/true: Truth Values. (line 6) * logical operators, See Boolean expressions: Boolean Ops. (line 6) * login information: Passwd Functions. (line 16) @@ -33580,12 +34171,12 @@ Index (line 9) * matching, leftmost longest: Multiple Line. (line 26) * matching, null strings: String Functions. (line 537) -* mawk utility: Escape Sequences. (line 118) +* mawk utility: Escape Sequences. (line 121) * mawk utility <1>: Getline/Pipe. (line 62) * mawk utility <2>: Concatenation. (line 36) * mawk utility <3>: Nextfile Statement. (line 47) * mawk utility <4>: Other Versions. (line 48) -* maximum precision supported by MPFR library: Auto-set. (line 212) +* maximum precision supported by MPFR library: Auto-set. (line 235) * McIlroy, Doug: Glossary. (line 257) * McPhee, Patrick: Contributors. (line 101) * message object files: Explaining gettext. (line 42) @@ -33597,8 +34188,8 @@ Index (line 48) * messages from extensions: Printing Messages. (line 6) * metacharacters in regular expressions: Regexp Operators. (line 6) -* metacharacters, escape sequences for: Escape Sequences. (line 137) -* minimum precision required by MPFR library: Auto-set. (line 215) +* metacharacters, escape sequences for: Escape Sequences. (line 140) +* minimum precision required by MPFR library: Auto-set. (line 238) * mktime: Time Functions. (line 25) * modifiers, in format specifiers: Format Modifiers. (line 6) * monetary information, localization: Explaining gettext. (line 104) @@ -33618,10 +34209,8 @@ Index * networks, programming: TCP/IP Networking. (line 6) * networks, support for: Special Network. (line 6) * newlines: Statements/Lines. (line 6) -* newlines <1>: Options. (line 260) +* newlines <1>: Options. (line 263) * newlines <2>: Boolean Ops. (line 69) -* newlines, as field separators: Default Field Splitting. - (line 6) * newlines, as record separators: awk split records. (line 12) * newlines, in dynamic regexps: Computed Regexps. (line 60) * newlines, in regexp constants: Computed Regexps. (line 70) @@ -33648,7 +34237,7 @@ Index * nexti debugger command: Debugger Execution Control. (line 49) * NF variable: Fields. (line 33) -* NF variable <1>: Auto-set. (line 104) +* NF variable <1>: Auto-set. (line 123) * NF variable, decrementing: Changing Fields. (line 107) * ni debugger command (alias for nexti): Debugger Execution Control. (line 49) @@ -33657,8 +34246,8 @@ Index (line 23) * not Boolean-logic operator: Boolean Ops. (line 6) * NR variable: Records. (line 6) -* NR variable <1>: Auto-set. (line 124) -* NR variable, changing: Auto-set. (line 313) +* NR variable <1>: Auto-set. (line 143) +* NR variable, changing: Auto-set. (line 344) * null strings: awk split records. (line 114) * null strings <1>: Regexp Field Splitting. (line 43) @@ -33778,7 +34367,7 @@ Index * p debugger command (alias for print): Viewing And Changing Data. (line 35) * Papadopoulos, Panos: Contributors. (line 129) -* parent process ID of gawk process: Auto-set. (line 187) +* parent process ID of gawk process: Auto-set. (line 210) * parentheses (), in a profile: Profiling. (line 146) * parentheses (), regexp operator: Regexp Operators. (line 81) * password file: Passwd Functions. (line 16) @@ -33822,14 +34411,14 @@ Index * plus sign (+), += operator <1>: Precedence. (line 94) * plus sign (+), regexp operator: Regexp Operators. (line 105) * pointers to functions: Indirect Calls. (line 6) -* portability: Escape Sequences. (line 100) +* portability: Escape Sequences. (line 103) * portability, #! (executable scripts): Executable Scripts. (line 33) * portability, ** operator and: Arithmetic Ops. (line 81) * portability, **= operator and: Assignment Ops. (line 144) * portability, ARGV variable: Executable Scripts. (line 59) * portability, backslash continuation and: Statements/Lines. (line 30) * portability, backslash in escape sequences: Escape Sequences. - (line 105) + (line 108) * portability, close() function and: Close Files And Pipes. (line 81) * portability, data files as single record: gawk split records. @@ -33847,7 +34436,7 @@ Index * portability, NF variable, decrementing: Changing Fields. (line 115) * portability, operators: Increment Ops. (line 60) * portability, operators, not in POSIX awk: Precedence. (line 97) -* portability, POSIXLY_CORRECT environment variable: Options. (line 358) +* portability, POSIXLY_CORRECT environment variable: Options. (line 363) * portability, substr() function: String Functions. (line 513) * portable object files: Explaining gettext. (line 37) * portable object files <1>: Translator i18n. (line 6) @@ -33868,7 +34457,7 @@ Index * POSIX awk, < operator and: Getline/File. (line 26) * POSIX awk, arithmetic operators and: Arithmetic Ops. (line 30) * POSIX awk, backslashes in string constants: Escape Sequences. - (line 105) + (line 108) * POSIX awk, BEGIN/END patterns: I/O And BEGIN/END. (line 15) * POSIX awk, bracket expressions and: Bracket Expressions. (line 34) * POSIX awk, bracket expressions and, character classes: Bracket Expressions. @@ -33880,9 +34469,7 @@ Index * POSIX awk, continue statement and: Continue Statement. (line 44) * POSIX awk, CONVFMT variable and: User-modified. (line 30) * POSIX awk, date utility and: Time Functions. (line 253) -* POSIX awk, field separators and: Fields. (line 6) -* POSIX awk, field separators and <1>: Full Line Fields. (line 16) -* POSIX awk, FS variable and: User-modified. (line 60) +* POSIX awk, field separators and: Full Line Fields. (line 16) * POSIX awk, function keyword in: Definition Syntax. (line 99) * POSIX awk, functions and, gsub()/sub(): Gory Details. (line 90) * POSIX awk, functions and, length(): String Functions. (line 179) @@ -33897,12 +34484,12 @@ Index * POSIX awk, regular expressions and: Regexp Operators. (line 161) * POSIX awk, timestamps and: Time Functions. (line 6) * POSIX awk, | I/O operator and: Getline/Pipe. (line 56) -* POSIX mode: Options. (line 254) -* POSIX mode <1>: Options. (line 338) +* POSIX mode: Options. (line 257) +* POSIX mode <1>: Options. (line 343) * POSIX, awk and: Preface. (line 21) * POSIX, gawk extensions not included in: POSIX/GNU. (line 6) * POSIX, programs, implementing in awk: Clones. (line 6) -* POSIXLY_CORRECT environment variable: Options. (line 338) +* POSIXLY_CORRECT environment variable: Options. (line 343) * PREC variable: User-modified. (line 124) * precedence: Increment Ops. (line 60) * precedence <1>: Precedence. (line 6) @@ -33949,14 +34536,14 @@ 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 ID of gawk process: Auto-set. (line 181) -* process ID of gawk process: Auto-set. (line 184) +* process group ID of gawk process: Auto-set. (line 204) +* process ID of gawk process: Auto-set. (line 207) * processes, two-way communications with: Two-way I/O. (line 6) * processing data: Basic High Level. (line 6) -* PROCINFO array: Auto-set. (line 129) +* PROCINFO array: Auto-set. (line 148) * PROCINFO array <1>: Time Functions. (line 47) * PROCINFO array <2>: Passwd Functions. (line 6) -* PROCINFO array, and communications via ptys: Two-way I/O. (line 108) +* PROCINFO array, and communications via ptys: Two-way I/O. (line 114) * 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. @@ -33964,8 +34551,8 @@ Index * 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 150) +* profiling awk programs, dynamically: Profiling. (line 177) +* program identifiers: Auto-set. (line 173) * program, definition of: Getting Started. (line 21) * programming conventions, --non-decimal-data option: Nondecimal Data. (line 35) @@ -34001,7 +34588,7 @@ Index * QuikTrim Awk: Other Versions. (line 139) * quit debugger command: Miscellaneous Debugger Commands. (line 102) -* QUIT signal (MS-Windows): Profiling. (line 213) +* QUIT signal (MS-Windows): Profiling. (line 212) * quoting in gawk command lines: Long. (line 26) * quoting in gawk command lines, tricks for: Quoting. (line 91) * quoting, for small awk programs: Comments. (line 27) @@ -34010,12 +34597,12 @@ Index * Rakitzis, Byron: History Sorting. (line 25) * Ramey, Chet: Acknowledgments. (line 60) * Ramey, Chet <1>: General Data Types. (line 6) -* rand: Numeric Functions. (line 34) +* rand: Numeric Functions. (line 49) * random numbers, Cliff: Cliff Random Function. (line 6) * random numbers, rand()/srand() functions: Numeric Functions. - (line 34) -* random numbers, seed of: Numeric Functions. (line 64) + (line 49) +* random numbers, seed of: Numeric Functions. (line 79) * range expressions (regexps): Bracket Expressions. (line 6) * range patterns: Ranges. (line 6) * range patterns, line continuation and: Ranges. (line 64) @@ -34102,6 +34689,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) @@ -34125,7 +34713,7 @@ Index * right shift: Bitwise Functions. (line 54) * right shift, bitwise: Bitwise Functions. (line 32) * Ritchie, Dennis: Basic Data Typing. (line 54) -* RLENGTH variable: Auto-set. (line 251) +* RLENGTH variable: Auto-set. (line 282) * RLENGTH variable, match() function and: String Functions. (line 227) * Robbins, Arnold: Command Line Field Separator. (line 71) @@ -34151,11 +34739,11 @@ Index * RS variable <1>: User-modified. (line 133) * RS variable, multiline records and: Multiple Line. (line 17) * rshift: Bitwise Functions. (line 54) -* RSTART variable: Auto-set. (line 257) +* RSTART variable: Auto-set. (line 288) * RSTART variable, match() function and: String Functions. (line 227) * RT variable: awk split records. (line 124) * RT variable <1>: Multiple Line. (line 130) -* RT variable <2>: Auto-set. (line 264) +* RT variable <2>: Auto-set. (line 295) * Rubin, Paul: History. (line 30) * Rubin, Paul <1>: Contributors. (line 16) * rule, definition of: Getting Started. (line 21) @@ -34166,14 +34754,14 @@ Index (line 68) * sample debugging session: Sample Debugging Session. (line 6) -* sandbox mode: Options. (line 285) +* sandbox mode: Options. (line 290) * save debugger options: Debugger Info. (line 85) * scalar or array: Type Functions. (line 11) * scalar values: Basic Data Typing. (line 13) * scanning arrays: Scanning an Array. (line 6) * scanning multidimensional arrays: Multiscanning. (line 11) * Schorr, Andrew: Acknowledgments. (line 60) -* Schorr, Andrew <1>: Auto-set. (line 296) +* Schorr, Andrew <1>: Auto-set. (line 327) * Schorr, Andrew <2>: Contributors. (line 134) * Schreiber, Bert: Acknowledgments. (line 38) * Schreiber, Rita: Acknowledgments. (line 38) @@ -34192,7 +34780,7 @@ Index * sed utility: Full Line Fields. (line 22) * sed utility <1>: Simple Sed. (line 6) * sed utility <2>: Glossary. (line 16) -* seeding random number generator: Numeric Functions. (line 64) +* seeding random number generator: Numeric Functions. (line 79) * semicolon (;), AWKPATH variable and: PC Using. (line 10) * semicolon (;), separating statements in actions: Statements/Lines. (line 90) @@ -34204,7 +34792,6 @@ Index * separators, field <1>: User-modified. (line 113) * separators, field, FIELDWIDTHS variable and: User-modified. (line 37) * separators, field, FPAT variable and: User-modified. (line 43) -* separators, field, POSIX and: Fields. (line 6) * separators, for records: awk split records. (line 6) * separators, for records <1>: awk split records. (line 85) * separators, for records <2>: User-modified. (line 133) @@ -34256,14 +34843,14 @@ Index * sidebar, A Constant's Base Does Not Affect Its Value: Nondecimal-numbers. (line 63) * sidebar, Backslash Before Regular Characters: Escape Sequences. - (line 103) + (line 106) * sidebar, Changing FS Does Not Affect the Fields: Full Line Fields. (line 14) -* sidebar, Changing NR and FNR: Auto-set. (line 311) +* sidebar, Changing NR and FNR: Auto-set. (line 342) * sidebar, Controlling Output Buffering with system(): I/O Functions. (line 164) * sidebar, Escape Sequences for Metacharacters: Escape Sequences. - (line 135) + (line 138) * sidebar, FS and IGNORECASE: Field Splitting Summary. (line 37) * sidebar, Interactive Versus Noninteractive Buffering: I/O Functions. @@ -34285,19 +34872,19 @@ Index (line 130) * sidebar, Using \n in Bracket Expressions of Dynamic Regexps: Computed Regexps. (line 58) -* SIGHUP signal, for dynamic profiling: Profiling. (line 210) -* SIGINT signal (MS-Windows): Profiling. (line 213) -* signals, HUP/SIGHUP, for profiling: Profiling. (line 210) -* signals, INT/SIGINT (MS-Windows): Profiling. (line 213) -* signals, QUIT/SIGQUIT (MS-Windows): Profiling. (line 213) -* signals, USR1/SIGUSR1, for profiling: Profiling. (line 187) +* SIGHUP signal, for dynamic profiling: Profiling. (line 209) +* SIGINT signal (MS-Windows): Profiling. (line 212) +* signals, HUP/SIGHUP, for profiling: Profiling. (line 209) +* signals, INT/SIGINT (MS-Windows): Profiling. (line 212) +* signals, QUIT/SIGQUIT (MS-Windows): Profiling. (line 212) +* signals, USR1/SIGUSR1, for profiling: Profiling. (line 186) * signature program: Signature Program. (line 6) -* SIGQUIT signal (MS-Windows): Profiling. (line 213) -* SIGUSR1 signal, for dynamic profiling: Profiling. (line 187) +* SIGQUIT signal (MS-Windows): Profiling. (line 212) +* SIGUSR1 signal, for dynamic profiling: Profiling. (line 186) * silent debugger command: Debugger Execution Control. (line 10) -* sin: Numeric Functions. (line 75) -* sine: Numeric Functions. (line 75) +* sin: Numeric Functions. (line 90) +* sine: Numeric Functions. (line 90) * single quote ('): One-shot. (line 15) * single quote (') in gawk command lines: Long. (line 35) * single quote ('), in shell commands: Quoting. (line 48) @@ -34347,10 +34934,10 @@ Index * sprintf() function, OFMT variable and: User-modified. (line 113) * sprintf() function, print/printf statements and: Round Function. (line 6) -* sqrt: Numeric Functions. (line 78) +* sqrt: Numeric Functions. (line 93) * square brackets ([]), regexp operator: Regexp Operators. (line 56) -* square root: Numeric Functions. (line 78) -* srand: Numeric Functions. (line 82) +* square root: Numeric Functions. (line 93) +* srand: Numeric Functions. (line 97) * stack frame: Debugging Terms. (line 10) * Stallman, Richard: Manual History. (line 6) * Stallman, Richard <1>: Acknowledgments. (line 18) @@ -34422,9 +35009,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 228) +* supplementary groups of gawk process: Auto-set. (line 251) * switch statement: Switch Statement. (line 6) -* SYMTAB array: Auto-set. (line 268) +* SYMTAB array: Auto-set. (line 299) * syntactic ambiguity: /= operator vs. /=.../ regexp constant: Assignment Ops. (line 149) * system: I/O Functions. (line 107) @@ -34494,7 +35081,7 @@ Index (line 37) * troubleshooting, awk uses FS not IFS: Field Separators. (line 29) * troubleshooting, backslash before nonspecial character: Escape Sequences. - (line 105) + (line 108) * troubleshooting, division: Arithmetic Ops. (line 44) * troubleshooting, fatal errors, field widths, specifying: Constant Size. (line 22) @@ -34528,6 +35115,8 @@ Index * trunc-mod operation: Arithmetic Ops. (line 66) * truth values: Truth Values. (line 6) * type conversion: Strings And Numbers. (line 21) +* type, of variable: Type Functions. (line 14) +* typeof: Type Functions. (line 14) * u debugger command (alias for until): Debugger Execution Control. (line 82) * unassigned array elements: Reference to Elements. @@ -34550,7 +35139,7 @@ Index * uniq.awk program: Uniq Program. (line 65) * Unix: Glossary. (line 748) * Unix awk, backslashes in escape sequences: Escape Sequences. - (line 118) + (line 121) * Unix awk, close() function and: Close Files And Pipes. (line 132) * Unix awk, password files, field separators and: Command Line Field Separator. @@ -34570,10 +35159,11 @@ Index * user-modifiable variables: User-modified. (line 6) * users, information about, printing: Id Program. (line 6) * users, information about, retrieving: Passwd Functions. (line 16) -* USR1 signal, for dynamic profiling: Profiling. (line 187) +* USR1 signal, for dynamic profiling: Profiling. (line 186) * values, numeric: Basic Data Typing. (line 13) * values, string: Basic Data Typing. (line 13) * variable assignments and input files: Other Arguments. (line 26) +* variable type: Type Functions. (line 14) * variable typing: Typing and Comparison. (line 9) * variables: Other Features. (line 6) @@ -34604,10 +35194,10 @@ Index * variables, uninitialized, as array subscripts: Uninitialized Subscripts. (line 6) * variables, user-defined: Variables. (line 6) -* version of gawk: Auto-set. (line 198) -* version of gawk extension API: Auto-set. (line 223) -* version of GNU MP library: Auto-set. (line 206) -* version of GNU MPFR library: Auto-set. (line 208) +* version of gawk: Auto-set. (line 221) +* version of gawk extension API: Auto-set. (line 246) +* version of GNU MP library: Auto-set. (line 229) +* version of GNU MPFR library: Auto-set. (line 231) * vertical bar (|): Regexp Operators. (line 70) * vertical bar (|), | operator (I/O): Getline/Pipe. (line 10) * vertical bar (|), | operator (I/O) <1>: Precedence. (line 64) @@ -34644,7 +35234,7 @@ Index * whitespace, as field separators: Default Field Splitting. (line 6) * whitespace, functions, calling: Calling Built-in. (line 10) -* whitespace, newlines as: Options. (line 260) +* whitespace, newlines as: Options. (line 263) * Williams, Kent: Contributors. (line 35) * Woehlke, Matthew: Contributors. (line 80) * Woods, John: Contributors. (line 28) @@ -34674,562 +35264,567 @@ Index Tag Table: Node: Top1200 -Node: Foreword342138 -Node: Foreword446580 -Node: Preface48112 -Ref: Preface-Footnote-150984 -Ref: Preface-Footnote-251091 -Ref: Preface-Footnote-351325 -Node: History51467 -Node: Names53819 -Ref: Names-Footnote-154913 -Node: This Manual55060 -Ref: This Manual-Footnote-161545 -Node: Conventions61645 -Node: Manual History63999 -Ref: Manual History-Footnote-166994 -Ref: Manual History-Footnote-267035 -Node: How To Contribute67109 -Node: Acknowledgments68238 -Node: Getting Started73124 -Node: Running gawk75563 -Node: One-shot76753 -Node: Read Terminal78016 -Node: Long80048 -Node: Executable Scripts81561 -Ref: Executable Scripts-Footnote-184356 -Node: Comments84459 -Node: Quoting86943 -Node: DOS Quoting92460 -Node: Sample Data Files93135 -Node: Very Simple95730 -Node: Two Rules100632 -Node: More Complex102517 -Node: Statements/Lines105383 -Ref: Statements/Lines-Footnote-1109842 -Node: Other Features110107 -Node: When111043 -Ref: When-Footnote-1112797 -Node: Intro Summary112862 -Node: Invoking Gawk113746 -Node: Command Line115260 -Node: Options116058 -Ref: Options-Footnote-1131965 -Ref: Options-Footnote-2132195 -Node: Other Arguments132220 -Node: Naming Standard Input135167 -Node: Environment Variables136260 -Node: AWKPATH Variable136818 -Ref: AWKPATH Variable-Footnote-1140119 -Ref: AWKPATH Variable-Footnote-2140164 -Node: AWKLIBPATH Variable140425 -Node: Other Environment Variables141569 -Node: Exit Status145334 -Node: Include Files146011 -Node: Loading Shared Libraries149606 -Node: Obsolete151034 -Node: Undocumented151726 -Node: Invoking Summary152023 -Node: Regexp153683 -Node: Regexp Usage155137 -Node: Escape Sequences157174 -Node: Regexp Operators163188 -Ref: Regexp Operators-Footnote-1170604 -Ref: Regexp Operators-Footnote-2170751 -Node: Bracket Expressions170849 -Ref: table-char-classes173325 -Node: Leftmost Longest176462 -Node: Computed Regexps177765 -Node: GNU Regexp Operators181192 -Node: Case-sensitivity184871 -Ref: Case-sensitivity-Footnote-1187758 -Ref: Case-sensitivity-Footnote-2187993 -Node: Regexp Summary188101 -Node: Reading Files189567 -Node: Records191661 -Node: awk split records192394 -Node: gawk split records197325 -Ref: gawk split records-Footnote-1201865 -Node: Fields201902 -Ref: Fields-Footnote-1204682 -Node: Nonconstant Fields204768 -Ref: Nonconstant Fields-Footnote-1207004 -Node: Changing Fields207208 -Node: Field Separators213136 -Node: Default Field Splitting215834 -Node: Regexp Field Splitting216952 -Node: Single Character Fields220305 -Node: Command Line Field Separator221365 -Node: Full Line Fields224583 -Ref: Full Line Fields-Footnote-1226105 -Ref: Full Line Fields-Footnote-2226151 -Node: Field Splitting Summary226252 -Node: Constant Size228326 -Node: Splitting By Content232904 -Ref: Splitting By Content-Footnote-1236875 -Node: Multiple Line237038 -Ref: Multiple Line-Footnote-1242920 -Node: Getline243099 -Node: Plain Getline245303 -Node: Getline/Variable247942 -Node: Getline/File249091 -Node: Getline/Variable/File250477 -Ref: Getline/Variable/File-Footnote-1252080 -Node: Getline/Pipe252168 -Node: Getline/Variable/Pipe254873 -Node: Getline/Coprocess256006 -Node: Getline/Variable/Coprocess257271 -Node: Getline Notes258011 -Node: Getline Summary260806 -Ref: table-getline-variants261228 -Node: Read Timeout261976 -Ref: Read Timeout-Footnote-1265817 -Node: Command-line directories265875 -Node: Input Summary266779 -Node: Input Exercises269951 -Node: Printing270679 -Node: Print272455 -Node: Print Examples273912 -Node: Output Separators276692 -Node: OFMT278709 -Node: Printf280065 -Node: Basic Printf280850 -Node: Control Letters282424 -Node: Format Modifiers286412 -Node: Printf Examples292427 -Node: Redirection294913 -Node: Special FD301754 -Ref: Special FD-Footnote-1304922 -Node: Special Files304996 -Node: Other Inherited Files305613 -Node: Special Network306614 -Node: Special Caveats307474 -Node: Close Files And Pipes308423 -Ref: Close Files And Pipes-Footnote-1315616 -Ref: Close Files And Pipes-Footnote-2315764 -Node: Output Summary315915 -Node: Output Exercises316913 -Node: Expressions317592 -Node: Values318780 -Node: Constants319458 -Node: Scalar Constants320149 -Ref: Scalar Constants-Footnote-1321013 -Node: Nondecimal-numbers321263 -Node: Regexp Constants324276 -Node: Using Constant Regexps324802 -Node: Variables327965 -Node: Using Variables328622 -Node: Assignment Options330532 -Node: Conversion332405 -Node: Strings And Numbers332929 -Ref: Strings And Numbers-Footnote-1335992 -Node: Locale influences conversions336101 -Ref: table-locale-affects338859 -Node: All Operators339477 -Node: Arithmetic Ops340106 -Node: Concatenation342612 -Ref: Concatenation-Footnote-1345459 -Node: Assignment Ops345566 -Ref: table-assign-ops350557 -Node: Increment Ops351870 -Node: Truth Values and Conditions355330 -Node: Truth Values356404 -Node: Typing and Comparison357452 -Node: Variable Typing358272 -Node: Comparison Operators361896 -Ref: table-relational-ops362315 -Node: POSIX String Comparison365810 -Ref: POSIX String Comparison-Footnote-1366884 -Node: Boolean Ops367023 -Ref: Boolean Ops-Footnote-1371505 -Node: Conditional Exp371597 -Node: Function Calls373333 -Node: Precedence377210 -Node: Locales380869 -Node: Expressions Summary382501 -Node: Patterns and Actions385074 -Node: Pattern Overview386194 -Node: Regexp Patterns387871 -Node: Expression Patterns388413 -Node: Ranges392194 -Node: BEGIN/END395302 -Node: Using BEGIN/END396063 -Ref: Using BEGIN/END-Footnote-1398799 -Node: I/O And BEGIN/END398905 -Node: BEGINFILE/ENDFILE401219 -Node: Empty404126 -Node: Using Shell Variables404443 -Node: Action Overview406717 -Node: Statements409042 -Node: If Statement410890 -Node: While Statement412385 -Node: Do Statement414413 -Node: For Statement415561 -Node: Switch Statement418719 -Node: Break Statement421105 -Node: Continue Statement423197 -Node: Next Statement425024 -Node: Nextfile Statement427407 -Node: Exit Statement430059 -Node: Built-in Variables432462 -Node: User-modified433595 -Ref: User-modified-Footnote-1441220 -Node: Auto-set441282 -Ref: Auto-set-Footnote-1454372 -Ref: Auto-set-Footnote-2454578 -Node: ARGC and ARGV454634 -Node: Pattern Action Summary458847 -Node: Arrays461277 -Node: Array Basics462606 -Node: Array Intro463450 -Ref: figure-array-elements465425 -Ref: Array Intro-Footnote-1468129 -Node: Reference to Elements468257 -Node: Assigning Elements470721 -Node: Array Example471212 -Node: Scanning an Array472971 -Node: Controlling Scanning475993 -Ref: Controlling Scanning-Footnote-1481392 -Node: Numeric Array Subscripts481708 -Node: Uninitialized Subscripts483892 -Node: Delete485511 -Ref: Delete-Footnote-1488263 -Node: Multidimensional488320 -Node: Multiscanning491415 -Node: Arrays of Arrays493006 -Node: Arrays Summary497773 -Node: Functions499866 -Node: Built-in500904 -Node: Calling Built-in501985 -Node: Numeric Functions503981 -Ref: Numeric Functions-Footnote-1508009 -Ref: Numeric Functions-Footnote-2508366 -Ref: Numeric Functions-Footnote-3508414 -Node: String Functions508686 -Ref: String Functions-Footnote-1532190 -Ref: String Functions-Footnote-2532318 -Ref: String Functions-Footnote-3532566 -Node: Gory Details532653 -Ref: table-sub-escapes534444 -Ref: table-sub-proposed535963 -Ref: table-posix-sub537326 -Ref: table-gensub-escapes538867 -Ref: Gory Details-Footnote-1539690 -Node: I/O Functions539844 -Ref: table-system-return-values546426 -Ref: I/O Functions-Footnote-1548406 -Ref: I/O Functions-Footnote-2548554 -Node: Time Functions548674 -Ref: Time Functions-Footnote-1559179 -Ref: Time Functions-Footnote-2559247 -Ref: Time Functions-Footnote-3559405 -Ref: Time Functions-Footnote-4559516 -Ref: Time Functions-Footnote-5559628 -Ref: Time Functions-Footnote-6559855 -Node: Bitwise Functions560121 -Ref: table-bitwise-ops560715 -Ref: Bitwise Functions-Footnote-1565053 -Node: Type Functions565226 -Node: I18N Functions566382 -Node: User-defined568033 -Node: Definition Syntax568838 -Ref: Definition Syntax-Footnote-1574525 -Node: Function Example574596 -Ref: Function Example-Footnote-1577518 -Node: Function Caveats577540 -Node: Calling A Function578058 -Node: Variable Scope579016 -Node: Pass By Value/Reference582010 -Node: Return Statement585509 -Node: Dynamic Typing588488 -Node: Indirect Calls589418 -Ref: Indirect Calls-Footnote-1599669 -Node: Functions Summary599797 -Node: Library Functions602502 -Ref: Library Functions-Footnote-1606109 -Ref: Library Functions-Footnote-2606252 -Node: Library Names606423 -Ref: Library Names-Footnote-1609883 -Ref: Library Names-Footnote-2610106 -Node: General Functions610192 -Node: Strtonum Function611295 -Node: Assert Function614317 -Node: Round Function617643 -Node: Cliff Random Function619184 -Node: Ordinal Functions620200 -Ref: Ordinal Functions-Footnote-1623263 -Ref: Ordinal Functions-Footnote-2623515 -Node: Join Function623725 -Ref: Join Function-Footnote-1625495 -Node: Getlocaltime Function625695 -Node: Readfile Function629437 -Node: Shell Quoting631409 -Node: Data File Management632810 -Node: Filetrans Function633442 -Node: Rewind Function637538 -Node: File Checking639443 -Ref: File Checking-Footnote-1640777 -Node: Empty Files640978 -Node: Ignoring Assigns642957 -Node: Getopt Function644507 -Ref: Getopt Function-Footnote-1655976 -Node: Passwd Functions656176 -Ref: Passwd Functions-Footnote-1665015 -Node: Group Functions665103 -Ref: Group Functions-Footnote-1673000 -Node: Walking Arrays673207 -Node: Library Functions Summary676215 -Node: Library Exercises677621 -Node: Sample Programs678086 -Node: Running Examples678856 -Node: Clones679584 -Node: Cut Program680808 -Node: Egrep Program690737 -Ref: Egrep Program-Footnote-1698249 -Node: Id Program698359 -Node: Split Program702039 -Ref: Split Program-Footnote-1705498 -Node: Tee Program705627 -Node: Uniq Program708417 -Node: Wc Program715843 -Ref: Wc Program-Footnote-1720098 -Node: Miscellaneous Programs720192 -Node: Dupword Program721405 -Node: Alarm Program723435 -Node: Translate Program728290 -Ref: Translate Program-Footnote-1732855 -Node: Labels Program733125 -Ref: Labels Program-Footnote-1736476 -Node: Word Sorting736560 -Node: History Sorting740632 -Node: Extract Program742467 -Node: Simple Sed749996 -Node: Igawk Program753070 -Ref: Igawk Program-Footnote-1767401 -Ref: Igawk Program-Footnote-2767603 -Ref: Igawk Program-Footnote-3767725 -Node: Anagram Program767840 -Node: Signature Program770902 -Node: Programs Summary772149 -Node: Programs Exercises773363 -Ref: Programs Exercises-Footnote-1777492 -Node: Advanced Features777583 -Node: Nondecimal Data779573 -Node: Array Sorting781164 -Node: Controlling Array Traversal781864 -Ref: Controlling Array Traversal-Footnote-1790231 -Node: Array Sorting Functions790349 -Ref: Array Sorting Functions-Footnote-1795440 -Node: Two-way I/O795636 -Ref: Two-way I/O-Footnote-1801930 -Ref: Two-way I/O-Footnote-2802117 -Node: TCP/IP Networking802199 -Node: Profiling805317 -Node: Advanced Features Summary812856 -Node: Internationalization814792 -Node: I18N and L10N816272 -Node: Explaining gettext816959 -Ref: Explaining gettext-Footnote-1821982 -Ref: Explaining gettext-Footnote-2822167 -Node: Programmer i18n822332 -Ref: Programmer i18n-Footnote-1827187 -Node: Translator i18n827236 -Node: String Extraction828030 -Ref: String Extraction-Footnote-1829162 -Node: Printf Ordering829248 -Ref: Printf Ordering-Footnote-1832034 -Node: I18N Portability832098 -Ref: I18N Portability-Footnote-1834554 -Node: I18N Example834617 -Ref: I18N Example-Footnote-1837423 -Node: Gawk I18N837496 -Node: I18N Summary838141 -Node: Debugger839482 -Node: Debugging840504 -Node: Debugging Concepts840945 -Node: Debugging Terms842754 -Node: Awk Debugging845329 -Node: Sample Debugging Session846235 -Node: Debugger Invocation846769 -Node: Finding The Bug848155 -Node: List of Debugger Commands854633 -Node: Breakpoint Control855966 -Node: Debugger Execution Control859660 -Node: Viewing And Changing Data863022 -Node: Execution Stack866396 -Node: Debugger Info868033 -Node: Miscellaneous Debugger Commands872104 -Node: Readline Support877192 -Node: Limitations878088 -Node: Debugging Summary880197 -Node: Arbitrary Precision Arithmetic881370 -Node: Computer Arithmetic882786 -Ref: table-numeric-ranges886377 -Ref: Computer Arithmetic-Footnote-1887099 -Node: Math Definitions887156 -Ref: table-ieee-formats890470 -Ref: Math Definitions-Footnote-1891073 -Node: MPFR features891178 -Node: FP Math Caution892895 -Ref: FP Math Caution-Footnote-1893967 -Node: Inexactness of computations894336 -Node: Inexact representation895296 -Node: Comparing FP Values896656 -Node: Errors accumulate897738 -Node: Getting Accuracy899171 -Node: Try To Round901881 -Node: Setting precision902780 -Ref: table-predefined-precision-strings903477 -Node: Setting the rounding mode905307 -Ref: table-gawk-rounding-modes905681 -Ref: Setting the rounding mode-Footnote-1909089 -Node: Arbitrary Precision Integers909268 -Ref: Arbitrary Precision Integers-Footnote-1912252 -Node: POSIX Floating Point Problems912401 -Ref: POSIX Floating Point Problems-Footnote-1916283 -Node: Floating point summary916321 -Node: Dynamic Extensions918511 -Node: Extension Intro920064 -Node: Plugin License921330 -Node: Extension Mechanism Outline922127 -Ref: figure-load-extension922566 -Ref: figure-register-new-function924131 -Ref: figure-call-new-function925223 -Node: Extension API Description927285 -Node: Extension API Functions Introduction928733 -Node: General Data Types933545 -Ref: General Data Types-Footnote-1939500 -Node: Memory Allocation Functions939799 -Ref: Memory Allocation Functions-Footnote-1942644 -Node: Constructor Functions942743 -Node: Registration Functions944488 -Node: Extension Functions945173 -Node: Exit Callback Functions947472 -Node: Extension Version String948722 -Node: Input Parsers949385 -Node: Output Wrappers959267 -Node: Two-way processors963779 -Node: Printing Messages966044 -Ref: Printing Messages-Footnote-1967118 -Node: Updating ERRNO967271 -Node: Requesting Values968010 -Ref: table-value-types-returned968747 -Node: Accessing Parameters969630 -Node: Symbol Table Access970865 -Node: Symbol table by name971377 -Node: Symbol table by cookie973398 -Ref: Symbol table by cookie-Footnote-1977550 -Node: Cached values977614 -Ref: Cached values-Footnote-1981121 -Node: Array Manipulation981212 -Ref: Array Manipulation-Footnote-1982311 -Node: Array Data Types982348 -Ref: Array Data Types-Footnote-1985006 -Node: Array Functions985098 -Node: Flattening Arrays988956 -Node: Creating Arrays995864 -Node: Extension API Variables1000633 -Node: Extension Versioning1001269 -Ref: gawk-api-version1001706 -Node: Extension API Informational Variables1003462 -Node: Extension API Boilerplate1004526 -Node: Finding Extensions1008340 -Node: Extension Example1008899 -Node: Internal File Description1009697 -Node: Internal File Ops1013777 -Ref: Internal File Ops-Footnote-11025539 -Node: Using Internal File Ops1025679 -Ref: Using Internal File Ops-Footnote-11028062 -Node: Extension Samples1028336 -Node: Extension Sample File Functions1029865 -Node: Extension Sample Fnmatch1037514 -Node: Extension Sample Fork1039001 -Node: Extension Sample Inplace1040219 -Node: Extension Sample Ord1043429 -Node: Extension Sample Readdir1044265 -Ref: table-readdir-file-types1045154 -Node: Extension Sample Revout1045959 -Node: Extension Sample Rev2way1046548 -Node: Extension Sample Read write array1047288 -Node: Extension Sample Readfile1049230 -Node: Extension Sample Time1050325 -Node: Extension Sample API Tests1051673 -Node: gawkextlib1052165 -Node: Extension summary1054589 -Node: Extension Exercises1058281 -Node: Language History1059778 -Node: V7/SVR3.11061434 -Node: SVR41063586 -Node: POSIX1065020 -Node: BTL1066399 -Node: POSIX/GNU1067128 -Node: Feature History1072649 -Node: Common Extensions1085978 -Node: Ranges and Locales1087261 -Ref: Ranges and Locales-Footnote-11091877 -Ref: Ranges and Locales-Footnote-21091904 -Ref: Ranges and Locales-Footnote-31092139 -Node: Contributors1092360 -Node: History summary1097929 -Node: Installation1099309 -Node: Gawk Distribution1100253 -Node: Getting1100737 -Node: Extracting1101698 -Node: Distribution contents1103336 -Node: Unix Installation1109087 -Node: Quick Installation1109703 -Node: Additional Configuration Options1112130 -Node: Configuration Philosophy1113934 -Node: Non-Unix Installation1116303 -Node: PC Installation1116761 -Node: PC Binary Installation1118081 -Node: PC Compiling1119933 -Ref: PC Compiling-Footnote-11122957 -Node: PC Testing1123066 -Node: PC Using1124246 -Node: Cygwin1128360 -Node: MSYS1129130 -Node: VMS Installation1129631 -Node: VMS Compilation1130422 -Ref: VMS Compilation-Footnote-11131651 -Node: VMS Dynamic Extensions1131709 -Node: VMS Installation Details1133394 -Node: VMS Running1135647 -Node: VMS GNV1139926 -Node: VMS Old Gawk1140661 -Node: Bugs1141132 -Node: Other Versions1145329 -Node: Installation summary1151913 -Node: Notes1152971 -Node: Compatibility Mode1153836 -Node: Additions1154618 -Node: Accessing The Source1155543 -Node: Adding Code1156978 -Node: New Ports1163197 -Node: Derived Files1167685 -Ref: Derived Files-Footnote-11173170 -Ref: Derived Files-Footnote-21173205 -Ref: Derived Files-Footnote-31173803 -Node: Future Extensions1173917 -Node: Implementation Limitations1174575 -Node: Extension Design1175758 -Node: Old Extension Problems1176912 -Ref: Old Extension Problems-Footnote-11178430 -Node: Extension New Mechanism Goals1178487 -Ref: Extension New Mechanism Goals-Footnote-11181851 -Node: Extension Other Design Decisions1182040 -Node: Extension Future Growth1184153 -Node: Old Extension Mechanism1184989 -Node: Notes summary1186752 -Node: Basic Concepts1187934 -Node: Basic High Level1188615 -Ref: figure-general-flow1188897 -Ref: figure-process-flow1189582 -Ref: Basic High Level-Footnote-11192883 -Node: Basic Data Typing1193068 -Node: Glossary1196396 -Node: Copying1228342 -Node: GNU Free Documentation License1265881 -Node: Index1290999 +Node: Foreword342506 +Node: Foreword446948 +Node: Preface48480 +Ref: Preface-Footnote-151352 +Ref: Preface-Footnote-251459 +Ref: Preface-Footnote-351693 +Node: History51835 +Node: Names54187 +Ref: Names-Footnote-155281 +Node: This Manual55428 +Ref: This Manual-Footnote-161913 +Node: Conventions62013 +Node: Manual History64367 +Ref: Manual History-Footnote-167362 +Ref: Manual History-Footnote-267403 +Node: How To Contribute67477 +Node: Acknowledgments68606 +Node: Getting Started73492 +Node: Running gawk75931 +Node: One-shot77121 +Node: Read Terminal78384 +Node: Long80416 +Node: Executable Scripts81929 +Ref: Executable Scripts-Footnote-184724 +Node: Comments84827 +Node: Quoting87311 +Node: DOS Quoting92828 +Node: Sample Data Files93503 +Node: Very Simple96098 +Node: Two Rules101000 +Node: More Complex102885 +Node: Statements/Lines105751 +Ref: Statements/Lines-Footnote-1110210 +Node: Other Features110475 +Node: When111411 +Ref: When-Footnote-1113165 +Node: Intro Summary113230 +Node: Invoking Gawk114114 +Node: Command Line115628 +Node: Options116426 +Ref: Options-Footnote-1132524 +Ref: Options-Footnote-2132754 +Node: Other Arguments132779 +Node: Naming Standard Input135726 +Node: Environment Variables136819 +Node: AWKPATH Variable137377 +Ref: AWKPATH Variable-Footnote-1140788 +Ref: AWKPATH Variable-Footnote-2140833 +Node: AWKLIBPATH Variable141094 +Node: Other Environment Variables142351 +Node: Exit Status145989 +Node: Include Files146666 +Node: Loading Shared Libraries150261 +Node: Obsolete151689 +Node: Undocumented152381 +Node: Invoking Summary152678 +Node: Regexp154338 +Node: Regexp Usage155857 +Node: Escape Sequences157894 +Node: Regexp Operators164126 +Ref: Regexp Operators-Footnote-1171542 +Ref: Regexp Operators-Footnote-2171689 +Node: Bracket Expressions171787 +Ref: table-char-classes174263 +Node: Leftmost Longest177400 +Node: Computed Regexps178703 +Node: GNU Regexp Operators182130 +Node: Case-sensitivity185809 +Ref: Case-sensitivity-Footnote-1188705 +Ref: Case-sensitivity-Footnote-2188940 +Node: Strong Regexp Constants189048 +Node: Regexp Summary191990 +Node: Reading Files193596 +Node: Records195759 +Node: awk split records196492 +Node: gawk split records201423 +Ref: gawk split records-Footnote-1205963 +Node: Fields206000 +Node: Nonconstant Fields208741 +Ref: Nonconstant Fields-Footnote-1210977 +Node: Changing Fields211181 +Node: Field Separators217109 +Node: Default Field Splitting219807 +Node: Regexp Field Splitting220925 +Node: Single Character Fields224278 +Node: Command Line Field Separator225338 +Node: Full Line Fields228556 +Ref: Full Line Fields-Footnote-1230078 +Ref: Full Line Fields-Footnote-2230124 +Node: Field Splitting Summary230225 +Node: Constant Size232299 +Node: Splitting By Content236877 +Ref: Splitting By Content-Footnote-1240848 +Node: Multiple Line241011 +Ref: Multiple Line-Footnote-1246893 +Node: Getline247072 +Node: Plain Getline249538 +Node: Getline/Variable252177 +Node: Getline/File253326 +Node: Getline/Variable/File254712 +Ref: Getline/Variable/File-Footnote-1256315 +Node: Getline/Pipe256403 +Node: Getline/Variable/Pipe259108 +Node: Getline/Coprocess260241 +Node: Getline/Variable/Coprocess261506 +Node: Getline Notes262246 +Node: Getline Summary265041 +Ref: table-getline-variants265463 +Node: Read Timeout266211 +Ref: Read Timeout-Footnote-1270117 +Node: Retrying Input270175 +Node: Command-line directories271374 +Node: Input Summary272280 +Node: Input Exercises275452 +Node: Printing276180 +Node: Print278014 +Node: Print Examples279471 +Node: Output Separators282251 +Node: OFMT284268 +Node: Printf285624 +Node: Basic Printf286409 +Node: Control Letters287983 +Node: Format Modifiers291971 +Node: Printf Examples297986 +Node: Redirection300472 +Node: Special FD307313 +Ref: Special FD-Footnote-1310481 +Node: Special Files310555 +Node: Other Inherited Files311172 +Node: Special Network312173 +Node: Special Caveats313033 +Node: Close Files And Pipes313982 +Ref: Close Files And Pipes-Footnote-1321169 +Ref: Close Files And Pipes-Footnote-2321317 +Node: Nonfatal321468 +Node: Output Summary323793 +Node: Output Exercises325015 +Node: Expressions325694 +Node: Values326882 +Node: Constants327560 +Node: Scalar Constants328251 +Ref: Scalar Constants-Footnote-1329115 +Node: Nondecimal-numbers329365 +Node: Regexp Constants332378 +Node: Using Constant Regexps332904 +Node: Variables336067 +Node: Using Variables336724 +Node: Assignment Options338634 +Node: Conversion340507 +Node: Strings And Numbers341031 +Ref: Strings And Numbers-Footnote-1344094 +Node: Locale influences conversions344203 +Ref: table-locale-affects346961 +Node: All Operators347579 +Node: Arithmetic Ops348208 +Node: Concatenation350714 +Ref: Concatenation-Footnote-1353561 +Node: Assignment Ops353668 +Ref: table-assign-ops358659 +Node: Increment Ops359972 +Node: Truth Values and Conditions363432 +Node: Truth Values364506 +Node: Typing and Comparison365554 +Node: Variable Typing366374 +Node: Comparison Operators369998 +Ref: table-relational-ops370417 +Node: POSIX String Comparison373912 +Ref: POSIX String Comparison-Footnote-1374986 +Node: Boolean Ops375125 +Ref: Boolean Ops-Footnote-1379607 +Node: Conditional Exp379699 +Node: Function Calls381435 +Node: Precedence385312 +Node: Locales388971 +Node: Expressions Summary390603 +Node: Patterns and Actions393176 +Node: Pattern Overview394296 +Node: Regexp Patterns395973 +Node: Expression Patterns396515 +Node: Ranges400296 +Node: BEGIN/END403404 +Node: Using BEGIN/END404165 +Ref: Using BEGIN/END-Footnote-1406901 +Node: I/O And BEGIN/END407007 +Node: BEGINFILE/ENDFILE409321 +Node: Empty412228 +Node: Using Shell Variables412545 +Node: Action Overview414819 +Node: Statements417144 +Node: If Statement418992 +Node: While Statement420487 +Node: Do Statement422515 +Node: For Statement423663 +Node: Switch Statement426821 +Node: Break Statement429207 +Node: Continue Statement431299 +Node: Next Statement433126 +Node: Nextfile Statement435509 +Node: Exit Statement438161 +Node: Built-in Variables440564 +Node: User-modified441697 +Node: Auto-set449283 +Ref: Auto-set-Footnote-1463670 +Ref: Auto-set-Footnote-2463876 +Node: ARGC and ARGV463932 +Node: Pattern Action Summary468145 +Node: Arrays470575 +Node: Array Basics471904 +Node: Array Intro472748 +Ref: figure-array-elements474723 +Ref: Array Intro-Footnote-1477427 +Node: Reference to Elements477555 +Node: Assigning Elements480019 +Node: Array Example480510 +Node: Scanning an Array482269 +Node: Controlling Scanning485291 +Ref: Controlling Scanning-Footnote-1490690 +Node: Numeric Array Subscripts491006 +Node: Uninitialized Subscripts493190 +Node: Delete494809 +Ref: Delete-Footnote-1497561 +Node: Multidimensional497618 +Node: Multiscanning500713 +Node: Arrays of Arrays502304 +Node: Arrays Summary507071 +Node: Functions509164 +Node: Built-in510202 +Node: Calling Built-in511283 +Node: Numeric Functions513279 +Ref: Numeric Functions-Footnote-1518112 +Ref: Numeric Functions-Footnote-2518469 +Ref: Numeric Functions-Footnote-3518517 +Node: String Functions518789 +Ref: String Functions-Footnote-1542293 +Ref: String Functions-Footnote-2542421 +Ref: String Functions-Footnote-3542669 +Node: Gory Details542756 +Ref: table-sub-escapes544547 +Ref: table-sub-proposed546066 +Ref: table-posix-sub547429 +Ref: table-gensub-escapes548970 +Ref: Gory Details-Footnote-1549793 +Node: I/O Functions549947 +Ref: table-system-return-values556529 +Ref: I/O Functions-Footnote-1558509 +Ref: I/O Functions-Footnote-2558657 +Node: Time Functions558777 +Ref: Time Functions-Footnote-1569282 +Ref: Time Functions-Footnote-2569350 +Ref: Time Functions-Footnote-3569508 +Ref: Time Functions-Footnote-4569619 +Ref: Time Functions-Footnote-5569731 +Ref: Time Functions-Footnote-6569958 +Node: Bitwise Functions570224 +Ref: table-bitwise-ops570818 +Ref: Bitwise Functions-Footnote-1575156 +Node: Type Functions575329 +Node: I18N Functions577990 +Node: User-defined579641 +Node: Definition Syntax580446 +Ref: Definition Syntax-Footnote-1586133 +Node: Function Example586204 +Ref: Function Example-Footnote-1589126 +Node: Function Caveats589148 +Node: Calling A Function589666 +Node: Variable Scope590624 +Node: Pass By Value/Reference593618 +Node: Return Statement597117 +Node: Dynamic Typing600096 +Node: Indirect Calls601026 +Ref: Indirect Calls-Footnote-1611277 +Node: Functions Summary611405 +Node: Library Functions614110 +Ref: Library Functions-Footnote-1617717 +Ref: Library Functions-Footnote-2617860 +Node: Library Names618031 +Ref: Library Names-Footnote-1621491 +Ref: Library Names-Footnote-2621714 +Node: General Functions621800 +Node: Strtonum Function622903 +Node: Assert Function625925 +Node: Round Function629251 +Node: Cliff Random Function630792 +Node: Ordinal Functions631808 +Ref: Ordinal Functions-Footnote-1634871 +Ref: Ordinal Functions-Footnote-2635123 +Node: Join Function635333 +Ref: Join Function-Footnote-1637103 +Node: Getlocaltime Function637303 +Node: Readfile Function641045 +Node: Shell Quoting643017 +Node: Data File Management644418 +Node: Filetrans Function645050 +Node: Rewind Function649146 +Node: File Checking651051 +Ref: File Checking-Footnote-1652385 +Node: Empty Files652586 +Node: Ignoring Assigns654565 +Node: Getopt Function656115 +Ref: Getopt Function-Footnote-1667584 +Node: Passwd Functions667784 +Ref: Passwd Functions-Footnote-1676623 +Node: Group Functions676711 +Ref: Group Functions-Footnote-1684608 +Node: Walking Arrays684815 +Node: Library Functions Summary687823 +Node: Library Exercises689229 +Node: Sample Programs689694 +Node: Running Examples690464 +Node: Clones691192 +Node: Cut Program692416 +Node: Egrep Program702345 +Ref: Egrep Program-Footnote-1709857 +Node: Id Program709967 +Node: Split Program713647 +Ref: Split Program-Footnote-1717106 +Node: Tee Program717235 +Node: Uniq Program720025 +Node: Wc Program727451 +Ref: Wc Program-Footnote-1731706 +Node: Miscellaneous Programs731800 +Node: Dupword Program733013 +Node: Alarm Program735043 +Node: Translate Program739898 +Ref: Translate Program-Footnote-1744463 +Node: Labels Program744733 +Ref: Labels Program-Footnote-1748084 +Node: Word Sorting748168 +Node: History Sorting752240 +Node: Extract Program754075 +Node: Simple Sed761604 +Node: Igawk Program764678 +Ref: Igawk Program-Footnote-1779009 +Ref: Igawk Program-Footnote-2779211 +Ref: Igawk Program-Footnote-3779333 +Node: Anagram Program779448 +Node: Signature Program782510 +Node: Programs Summary783757 +Node: Programs Exercises784971 +Ref: Programs Exercises-Footnote-1789100 +Node: Advanced Features789191 +Node: Nondecimal Data791181 +Node: Array Sorting792772 +Node: Controlling Array Traversal793472 +Ref: Controlling Array Traversal-Footnote-1801839 +Node: Array Sorting Functions801957 +Ref: Array Sorting Functions-Footnote-1807048 +Node: Two-way I/O807244 +Ref: Two-way I/O-Footnote-1813794 +Ref: Two-way I/O-Footnote-2813981 +Node: TCP/IP Networking814063 +Node: Profiling817181 +Ref: Profiling-Footnote-1825674 +Node: Advanced Features Summary825997 +Node: Internationalization827841 +Node: I18N and L10N829321 +Node: Explaining gettext830008 +Ref: Explaining gettext-Footnote-1835031 +Ref: Explaining gettext-Footnote-2835216 +Node: Programmer i18n835381 +Ref: Programmer i18n-Footnote-1840236 +Node: Translator i18n840285 +Node: String Extraction841079 +Ref: String Extraction-Footnote-1842211 +Node: Printf Ordering842297 +Ref: Printf Ordering-Footnote-1845083 +Node: I18N Portability845147 +Ref: I18N Portability-Footnote-1847603 +Node: I18N Example847666 +Ref: I18N Example-Footnote-1850472 +Node: Gawk I18N850545 +Node: I18N Summary851190 +Node: Debugger852531 +Node: Debugging853553 +Node: Debugging Concepts853994 +Node: Debugging Terms855803 +Node: Awk Debugging858378 +Node: Sample Debugging Session859284 +Node: Debugger Invocation859818 +Node: Finding The Bug861204 +Node: List of Debugger Commands867682 +Node: Breakpoint Control869015 +Node: Debugger Execution Control872709 +Node: Viewing And Changing Data876071 +Node: Execution Stack879445 +Node: Debugger Info881082 +Node: Miscellaneous Debugger Commands885153 +Node: Readline Support890241 +Node: Limitations891137 +Ref: Limitations-Footnote-1895368 +Node: Debugging Summary895419 +Node: Arbitrary Precision Arithmetic896698 +Node: Computer Arithmetic898114 +Ref: table-numeric-ranges901705 +Ref: Computer Arithmetic-Footnote-1902427 +Node: Math Definitions902484 +Ref: table-ieee-formats905798 +Ref: Math Definitions-Footnote-1906401 +Node: MPFR features906506 +Node: FP Math Caution908223 +Ref: FP Math Caution-Footnote-1909295 +Node: Inexactness of computations909664 +Node: Inexact representation910624 +Node: Comparing FP Values911984 +Node: Errors accumulate913066 +Node: Getting Accuracy914499 +Node: Try To Round917209 +Node: Setting precision918108 +Ref: table-predefined-precision-strings918805 +Node: Setting the rounding mode920635 +Ref: table-gawk-rounding-modes921009 +Ref: Setting the rounding mode-Footnote-1924417 +Node: Arbitrary Precision Integers924596 +Ref: Arbitrary Precision Integers-Footnote-1929513 +Node: POSIX Floating Point Problems929662 +Ref: POSIX Floating Point Problems-Footnote-1933544 +Node: Floating point summary933582 +Node: Dynamic Extensions935772 +Node: Extension Intro937325 +Node: Plugin License938591 +Node: Extension Mechanism Outline939388 +Ref: figure-load-extension939827 +Ref: figure-register-new-function941392 +Ref: figure-call-new-function942484 +Node: Extension API Description944546 +Node: Extension API Functions Introduction946078 +Node: General Data Types950937 +Ref: General Data Types-Footnote-1956892 +Node: Memory Allocation Functions957191 +Ref: Memory Allocation Functions-Footnote-1960036 +Node: Constructor Functions960135 +Node: Registration Functions961880 +Node: Extension Functions962565 +Node: Exit Callback Functions965188 +Node: Extension Version String966438 +Node: Input Parsers967101 +Node: Output Wrappers976983 +Node: Two-way processors981495 +Node: Printing Messages983760 +Ref: Printing Messages-Footnote-1984931 +Node: Updating ERRNO985084 +Node: Requesting Values985823 +Ref: table-value-types-returned986560 +Node: Accessing Parameters987443 +Node: Symbol Table Access988678 +Node: Symbol table by name989190 +Node: Symbol table by cookie991211 +Ref: Symbol table by cookie-Footnote-1995363 +Node: Cached values995427 +Ref: Cached values-Footnote-1998934 +Node: Array Manipulation999025 +Ref: Array Manipulation-Footnote-11000116 +Node: Array Data Types1000153 +Ref: Array Data Types-Footnote-11002811 +Node: Array Functions1002903 +Node: Flattening Arrays1006761 +Node: Creating Arrays1013669 +Node: Redirection API1018438 +Node: Extension API Variables1021269 +Node: Extension Versioning1021902 +Ref: gawk-api-version1022339 +Node: Extension API Informational Variables1024095 +Node: Extension API Boilerplate1025159 +Node: Finding Extensions1028973 +Node: Extension Example1029532 +Node: Internal File Description1030330 +Node: Internal File Ops1034410 +Ref: Internal File Ops-Footnote-11046172 +Node: Using Internal File Ops1046312 +Ref: Using Internal File Ops-Footnote-11048695 +Node: Extension Samples1048969 +Node: Extension Sample File Functions1050498 +Node: Extension Sample Fnmatch1058147 +Node: Extension Sample Fork1059634 +Node: Extension Sample Inplace1060852 +Node: Extension Sample Ord1064062 +Node: Extension Sample Readdir1064898 +Ref: table-readdir-file-types1065787 +Node: Extension Sample Revout1066592 +Node: Extension Sample Rev2way1067181 +Node: Extension Sample Read write array1067921 +Node: Extension Sample Readfile1069863 +Node: Extension Sample Time1070958 +Node: Extension Sample API Tests1072306 +Node: gawkextlib1072798 +Node: Extension summary1075245 +Node: Extension Exercises1078947 +Node: Language History1080444 +Node: V7/SVR3.11082100 +Node: SVR41084252 +Node: POSIX1085686 +Node: BTL1087065 +Node: POSIX/GNU1087794 +Node: Feature History1093656 +Node: Common Extensions1108026 +Node: Ranges and Locales1109309 +Ref: Ranges and Locales-Footnote-11113925 +Ref: Ranges and Locales-Footnote-21113952 +Ref: Ranges and Locales-Footnote-31114187 +Node: Contributors1114408 +Node: History summary1119977 +Node: Installation1121357 +Node: Gawk Distribution1122301 +Node: Getting1122785 +Node: Extracting1123746 +Node: Distribution contents1125384 +Node: Unix Installation1131478 +Node: Quick Installation1132160 +Node: Shell Startup Files1134574 +Node: Additional Configuration Options1135652 +Node: Configuration Philosophy1137457 +Node: Non-Unix Installation1139826 +Node: PC Installation1140284 +Node: PC Binary Installation1141604 +Node: PC Compiling1143456 +Ref: PC Compiling-Footnote-11146480 +Node: PC Testing1146589 +Node: PC Using1147769 +Node: Cygwin1151883 +Node: MSYS1152653 +Node: VMS Installation1153154 +Node: VMS Compilation1153945 +Ref: VMS Compilation-Footnote-11155174 +Node: VMS Dynamic Extensions1155232 +Node: VMS Installation Details1156917 +Node: VMS Running1159170 +Node: VMS GNV1163449 +Node: VMS Old Gawk1164184 +Node: Bugs1164655 +Node: Other Versions1168852 +Node: Installation summary1175436 +Node: Notes1176494 +Node: Compatibility Mode1177359 +Node: Additions1178141 +Node: Accessing The Source1179066 +Node: Adding Code1180501 +Node: New Ports1186720 +Node: Derived Files1191208 +Ref: Derived Files-Footnote-11196693 +Ref: Derived Files-Footnote-21196728 +Ref: Derived Files-Footnote-31197326 +Node: Future Extensions1197440 +Node: Implementation Limitations1198098 +Node: Extension Design1199281 +Node: Old Extension Problems1200435 +Ref: Old Extension Problems-Footnote-11201953 +Node: Extension New Mechanism Goals1202010 +Ref: Extension New Mechanism Goals-Footnote-11205374 +Node: Extension Other Design Decisions1205563 +Node: Extension Future Growth1207676 +Node: Old Extension Mechanism1208512 +Node: Notes summary1210275 +Node: Basic Concepts1211457 +Node: Basic High Level1212138 +Ref: figure-general-flow1212420 +Ref: figure-process-flow1213105 +Ref: Basic High Level-Footnote-11216406 +Node: Basic Data Typing1216591 +Node: Glossary1219919 +Node: Copying1251865 +Node: GNU Free Documentation License1289404 +Node: Index1314522 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index 92cb57dc..a4a1e8d7 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -539,6 +539,7 @@ particular records in a file and perform operations upon them. * Computed Regexps:: Using Dynamic Regexps. * GNU Regexp Operators:: Operators specific to GNU software. * Case-sensitivity:: How to do case-insensitive matching. +* Strong Regexp Constants:: Strongly typed regexp constants. * Regexp Summary:: Regular expressions summary. * Records:: Controlling how data is split into records. @@ -581,6 +582,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. @@ -610,6 +612,7 @@ particular records in a file and perform operations upon them. * Special Caveats:: Things to watch out for. * Close Files And Pipes:: Closing Input and Output Files and Pipes. +* Nonfatal:: Enabling Nonfatal Output. * Output Summary:: Output summary. * Output Exercises:: Exercises. * Values:: Constants, Variables, and Regular @@ -921,6 +924,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 @@ -979,6 +983,7 @@ particular records in a file and perform operations upon them. * Unix Installation:: Installing @command{gawk} under various versions of Unix. * Quick Installation:: Compiling @command{gawk} under Unix. +* Shell Startup Files:: Shell convenience functions. * Additional Configuration Options:: Other compile-time options. * Configuration Philosophy:: How it's all supposed to work. * Non-Unix Installation:: Installation on Other Operating @@ -4055,6 +4060,7 @@ when parsing numeric input data (@pxref{Locales}). @cindex @option{-o} option @cindex @option{--pretty-print} option Enable pretty-printing of @command{awk} programs. +Implies @option{--no-optimize}. By default, the output program is created in a file named @file{awkprof.out} (@pxref{Profiling}). The optional @var{file} argument allows you to specify a different @@ -4063,18 +4069,22 @@ No space is allowed between the @option{-o} and @var{file}, if @var{file} is supplied. @quotation NOTE -Due to the way @command{gawk} has evolved, with this option -your program still executes. This will change in the -next major release, such that @command{gawk} will only -pretty-print the program and not run it. +In the past, this option would also execute your program. +This is no longer the case. @end quotation @item @option{-O} @itemx @option{--optimize} @cindex @option{--optimize} option @cindex @option{-O} option -Enable some optimizations on the internal representation of the program. -At the moment, this includes just simple constant folding. +Enable @command{gawk}'s default optimizations on the internal +representation of the program. At the moment, this includes simple +constant folding and tail recursion elimination in function calls. + +These optimizations are enabled by default. +This option remains primarily for backwards compatibilty. However, it may +be used to cancel the effect of an earlier @option{-s} option +(see later in this list). @item @option{-p}[@var{file}] @itemx @option{--profile}[@code{=}@var{file}] @@ -4083,6 +4093,7 @@ At the moment, this includes just simple constant folding. @cindex @command{awk} profiling, enabling Enable profiling of @command{awk} programs (@pxref{Profiling}). +Implies @option{--no-optimize}. By default, profiles are created in a file named @file{awkprof.out}. The optional @var{file} argument allows you to specify a different @value{FN} for the profile file. @@ -4112,11 +4123,6 @@ restrictions apply: @cindex newlines @cindex whitespace, newlines as @item -Newlines do not act as whitespace to separate fields when @code{FS} is -equal to a single space -(@pxref{Fields}). - -@item Newlines are not allowed after @samp{?} or @samp{:} (@pxref{Conditional Exp}). @@ -4154,6 +4160,13 @@ This is now @command{gawk}'s default behavior. Nevertheless, this option remains (both for backward compatibility and for use in combination with @option{--traditional}). +@item @option{-s} +@itemx @option{--no-optimize} +@cindex @option{--no-optimize} option +@cindex @option{-s} option +Disable @command{gawk}'s default optimizations on the internal +representation of the program. + @item @option{-S} @itemx @option{--sandbox} @cindex @option{-S} option @@ -4467,6 +4480,9 @@ searches first in the current directory and then in @file{/usr/local/share/awk}. In practice, this means that you will rarely need to change the value of @env{AWKPATH}. +@xref{Shell Startup Files}, for information on functions that help to +manipulate the @env{AWKPATH} variable. + @command{gawk} places the value of the search path that it used into @code{ENVIRON["AWKPATH"]}. This provides access to the actual search path value from within an @command{awk} program. @@ -4498,6 +4514,9 @@ an empty value, @command{gawk} uses a default path; this is typically @samp{/usr/local/lib/gawk}, although it can vary depending upon how @command{gawk} was built. +@xref{Shell Startup Files}, for information on functions that help to +manipulate the @env{AWKLIBPATH} variable. + @command{gawk} places the value of the search path that it used into @code{ENVIRON["AWKLIBPATH"]}. This provides access to the actual search path value from within an @command{awk} program. @@ -4525,6 +4544,8 @@ wait for input before returning with an error. Controls the number of times @command{gawk} attempts to retry a two-way TCP/IP (socket) connection before giving up. @xref{TCP/IP Networking}. +Note that when nonfatal I/O is enabled (@pxref{Nonfatal}), +@command{gawk} only tries to open a TCP/IP socket once. @item POSIXLY_CORRECT Causes @command{gawk} to switch to POSIX-compatibility @@ -4574,14 +4595,6 @@ two regexp matchers that @command{gawk} uses internally. (There aren't supposed to be differences, but occasionally theory and practice don't coordinate with each other.) -@item GAWK_NO_PP_RUN -When @command{gawk} is invoked with the @option{--pretty-print} option, -it will not run the program if this environment variable exists. - -@quotation CAUTION -This variable will not survive into the next major release. -@end quotation - @item GAWK_STACKSIZE This specifies the amount by which @command{gawk} should grow its internal evaluation stack, when needed. @@ -4879,6 +4892,32 @@ Similarly, you may use @code{print} or @code{printf} statements in the @var{init} and @var{increment} parts of a @code{for} loop. This is another long-undocumented ``feature'' of Unix @command{awk}. +@command{gawk} lets you use the names of built-in functions that are +@command{gawk} extensions as the names of parameters in user-defined functions. +This is intended to ``future-proof'' old code that happens to use +function names added by @command{gawk} after the code was written. +Standard @command{awk} built-in functions, such as @code{sin()} or +@code{substr()} are @emph{not} shadowed in this way. + +The @code{PROCINFO["argv"]} array contains all of the command-line arguments +(after glob expansion and redirection processing on platforms where that must +be done manually by the program) with subscripts ranging from 0 through +@code{argc} @minus{} 1. For example, @code{PROCINFO["argv"][0]} will contain +the name by which @command{gawk} was invoked. Here is an example of how this +feature may be used: + +@example +awk ' +BEGIN @{ + for (i = 0; i < length(PROCINFO["argv"]); i++) + print i, PROCINFO["argv"][i] +@}' +@end example + +Please note that this differs from the standard @code{ARGV} array which does +not include command-line arguments that have already been processed by +@command{gawk} (@pxref{ARGC and ARGV}). + @end ignore @node Invoking Summary @@ -4971,6 +5010,7 @@ regular expressions work, we present more complicated instances. * Computed Regexps:: Using Dynamic Regexps. * GNU Regexp Operators:: Operators specific to GNU software. * Case-sensitivity:: How to do case-insensitive matching. +* Strong Regexp Constants:: Strongly typed regexp constants. * Regexp Summary:: Regular expressions summary. @end menu @@ -5161,17 +5201,21 @@ between @samp{0} and @samp{7}. For example, the code for the ASCII ESC @item \x@var{hh}@dots{} The hexadecimal value @var{hh}, where @var{hh} stands for a sequence of hexadecimal digits (@samp{0}--@samp{9}, and either @samp{A}--@samp{F} -or @samp{a}--@samp{f}). Like the same construct -in ISO C, the escape sequence continues until the first nonhexadecimal -digit is seen. @value{COMMONEXT} -However, using more than two hexadecimal digits produces -undefined results. (The @samp{\x} escape sequence is not allowed in -POSIX @command{awk}.) +or @samp{a}--@samp{f}). A maximum of two digts are allowed after +the @samp{\x}. Any further hexadecimal digits are treated as simple +letters or numbers. @value{COMMONEXT} +(The @samp{\x} escape sequence is not allowed in POSIX awk.) @quotation CAUTION -The next major release of @command{gawk} will change, such -that a maximum of two hexadecimal digits following the -@samp{\x} will be used. +In ISO C, the escape sequence continues until the first nonhexadecimal +digit is seen. +For many years, @command{gawk} would continue incorporating +hexadecimal digits into the value until a non-hexadecimal digit +or the end of the string was encountered. +However, using more than two hexadecimal digits produced +undefined results. +As of @value{PVERSION} 4.2, only two digits +are processed. @end quotation @cindex @code{\} (backslash), @code{\/} escape sequence @@ -6227,6 +6271,89 @@ The value of @code{IGNORECASE} has no effect if @command{gawk} is in compatibility mode (@pxref{Options}). Case is always significant in compatibility mode. +@node Strong Regexp Constants +@section Strongly Typed Regexp Constants + +This @value{SECTION} describes a @command{gawk}-specific feature. + +Regexp constants (@code{/@dots{}/}) hold a strange position in the +@command{awk} language. In most contexts, they act like an expression: +@samp{$0 ~ /@dots{}/}. In other contexts, they denote only a regexp to +be matched. In no case are they really a ``first class citizen'' of the +language. That is, you cannot define a scalar variable whose type is +``regexp'' in the same sense that you can define a variable to be a +number or a string: + +@example +num = 42 @ii{Numeric variable} +str = "hi" @ii{String variable} +re = /foo/ @ii{Wrong!} re @ii{is the result of} $0 ~ /foo/ +@end example + +For a number of more advanced use cases (described later on in this +@value{DOCUMENT}), it would be nice to have regexp constants that +are @dfn{strongly typed}; in other words, that denote a regexp useful +for matching, and not an expression. + +@command{gawk} provides this feature. A strongly typed regexp constant +looks almost like a regular regexp constant, except that it is preceded +by an @samp{@@} sign: + +@example +re = @@/foo/ @ii{Regexp variable} +@end example + +Strongly typed regexp constants @emph{cannot} be used eveywhere that a +regular regexp constant can, because this would make the language even more +confusing. Instead, you may use them only in certain contexts: + +@itemize @bullet +@item +On the righthand side of the @samp{~} and @samp{!~} operators: @samp{some_var ~ @@/foo/} +(@pxref{Regexp Usage}). + +@item +In the @code{case} part of a @code{switch} statement +(@pxref{Switch Statement}). + +@item +As an argument to one of the built-in functions that accept regexp constants: +@code{gensub()}, +@code{gsub()}, +@code{match()}, +@code{patsplit()}, +@code{split()}, +and +@code{sub()} +(@pxref{String Functions}). + +@item +As a parameter in a call to a user-defined function +(@pxref{User-defined}). + +@item +On the righthand side of an assignment to a variable: @samp{some_var = @@/foo/}. +In this case, the type of @code{some_var} is regexp. Additionally, @code{some_var} +can be used with @samp{~} and @samp{!~}, passed to one of the built-in functions +listed above, or passed as a parameter to a user-defined function. +@end itemize + +You may use the @code{typeof()} built-in function +(@pxref{Type Functions}) +to determine if a variable or function parameter is +a regexp variable. + +The true power of this feature comes from the ability to create variables that +have regexp type. Such variables can be passed on to user-defined functions, +without the confusing aspects of computed regular expressions created from +strings or string constants. They may also be passed through indirect function +calls (@pxref{Indirect Calls}) +onto the built-in functions that accept regexp constants. + +When used in numeric conversions, strongly typed regexp variables convert +to zero. When used in string conversions, they convert to the string +value of the original regexp text. + @node Regexp Summary @section Summary @@ -6270,6 +6397,11 @@ treated as regular expressions). case sensitivity of regexp matching. In other @command{awk} versions, use @code{tolower()} or @code{toupper()}. +@item +Strongly typed regexp constants (@code{@@/.../}) enable +certain advanced use cases to be described later on in the +@value{DOCUMENT}. + @end itemize @@ -6317,6 +6449,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. @@ -6691,16 +6824,12 @@ Readfile} for another option. @cindex fields @cindex accessing fields @cindex fields, examining -@cindex POSIX @command{awk}, field separators and -@cindex field separators, POSIX and -@cindex separators, field, POSIX and When @command{awk} reads an input record, the record is automatically @dfn{parsed} or separated by the @command{awk} utility into chunks called @dfn{fields}. By default, fields are separated by @dfn{whitespace}, like words in a line. Whitespace in @command{awk} means any string of one or more spaces, -TABs, or newlines;@footnote{In POSIX @command{awk}, newlines are not -considered whitespace for separating fields.} other characters +TABs, or newlines; other characters that are considered whitespace by other languages (such as formfeed, vertical tab, etc.) are @emph{not} considered whitespace by @command{awk}. @@ -7145,7 +7274,6 @@ can massage it first with a separate @command{awk} program.) @node Default Field Splitting @subsection Whitespace Normally Separates Fields -@cindex newlines, as field separators @cindex whitespace, as field separators Fields are normally separated by whitespace sequences (spaces, TABs, and newlines), not by single spaces. Two spaces in a row do not @@ -8108,6 +8236,13 @@ 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 @code{ERRNO} indicates that the I/O operation may be +retried, and @code{PROCINFO["@var{input}", "RETRY"]} is set, +then @code{getline} returns @minus{}2 +instead of @minus{}1, and further calls to @code{getline} +may be attemped. @xref{Retrying Input} for further information about +this feature. + In the following examples, @var{command} stands for a string value that represents a shell command. @@ -8762,7 +8897,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. @xref{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 @@ -8772,6 +8908,36 @@ 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, by +default @code{getline} returns @minus{}1, and subsequent attempts to +read from that file 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 a special element in +the @code{PROCINFO} array (@pxref{Auto-set}): + +@example +PROCINFO["@var{input_name}", "RETRY"] = 1 +@end example + +When this element exists, @command{gawk} checks the value of the system +(C language) +@code{errno} variable when an I/O error occurs. If @code{errno} indicates +a subsequent I/O attempt may succeed, @code{getline} instead returns +@minus{}2 and +further calls to @code{getline} may succeed. This applies to the @code{errno} +values @code{EAGAIN}, @code{EWOULDBLOCK}, @code{EINTR}, or @code{ETIMEDOUT}. + +This feature is useful in conjunction with +@code{PROCINFO["@var{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 @@ -8933,6 +9099,7 @@ and discusses the @code{close()} built-in function. @command{gawk} allows access to inherited file descriptors. * Close Files And Pipes:: Closing Input and Output Files and Pipes. +* Nonfatal:: Enabling Nonfatal Output. * Output Summary:: Output summary. * Output Exercises:: Exercises. @end menu @@ -10438,6 +10605,70 @@ when closing a pipe. @end cartouche @end ifnotdocbook +@node Nonfatal +@section Enabling Nonfatal Output + +This @value{SECTION} describes a @command{gawk}-specific feature. + +In standard @command{awk}, output with @code{print} or @code{printf} +to a nonexistent file, or some other I/O error (such as filling up the +disk) is a fatal error. + +@example +$ @kbd{gawk 'BEGIN @{ print "hi" > "/no/such/file" @}'} +@error{} gawk: cmd. line:1: fatal: can't redirect to `/no/such/file' (No such file or directory) +@end example + +@command{gawk} makes it possible to detect that an error has +occurred, allowing you to possibly recover from the error, or +at least print an error message of your choosing before exiting. +You can do this in one of two ways: + +@itemize @bullet +@item +For all output files, by assigning any value to @code{PROCINFO["NONFATAL"]}. + +@item +On a per-file basis, by assigning any value to +@code{PROCINFO[@var{filename}, "NONFATAL"]}. +Here, @var{filename} is the name of the file to which +you wish output to be nonfatal. +@end itemize + +Once you have enabled nonfatal output, you must check @code{ERRNO} +after every relevant @code{print} or @code{printf} statement to +see if something went wrong. It is also a good idea to initialize +@code{ERRNO} to zero before attempting the output. For example: + +@example +$ @kbd{gawk '} +> @kbd{BEGIN @{} +> @kbd{ PROCINFO["NONFATAL"] = 1} +> @kbd{ ERRNO = 0} +> @kbd{ print "hi" > "/no/such/file"} +> @kbd{ if (ERRNO) @{} +> @kbd{ print("Output failed:", ERRNO) > "/dev/stderr"} +> @kbd{ exit 1} +> @kbd{ @}} +> @kbd{@}'} +@error{} Output failed: No such file or directory +@end example + +Here, @command{gawk} did not produce a fatal error; instead +it let the @command{awk} program code detect the problem and handle it. + +This mechanism works also for standard output and standard error. +For standard output, you may use @code{PROCINFO["-", "NONFATAL"]} +or @code{PROCINFO["/dev/stdout", "NONFATAL"]}. For standard error, use +@code{PROCINFO["/dev/stderr", "NONFATAL"]}. + +When attempting to open a TCP/IP socket (@pxref{TCP/IP Networking}), +@command{gawk} tries multiple times. The @env{GAWK_SOCK_RETRIES} +environment variable (@pxref{Other Environment Variables}) allows you to +override @command{gawk}'s builtin default number of attempts. However, +once nonfatal I/O is enabled for a given socket, @command{gawk} only +retries once, relying on @command{awk}-level code to notice that there +was a problem. @node Output Summary @section Summary @@ -10467,6 +10698,12 @@ Use @code{close()} to close open file, pipe, and coprocess redirections. For coprocesses, it is possible to close only one direction of the communications. +@item +Normally errors with @code{print} or @code{printf} are fatal. +@command{gawk} lets you make output errors be nonfatal either for +all files or on a per-file basis. You must then check for errors +after every relevant output statement. + @end itemize @c EXCLUDE START @@ -14570,12 +14807,11 @@ specify the behavior when @code{FS} is the null string. Nonetheless, some other versions of @command{awk} also treat @code{""} specially.) -@cindex POSIX @command{awk}, @code{FS} variable and The default value is @w{@code{" "}}, a string consisting of a single -space. As a special exception, this value means that any -sequence of spaces, TABs, and/or newlines is a single separator.@footnote{In -POSIX @command{awk}, newline does not count as whitespace.} It also causes -spaces, TABs, and newlines at the beginning and end of a record to be ignored. +space. As a special exception, this value means that any sequence of +spaces, TABs, and/or newlines is a single separator. It also causes +spaces, TABs, and newlines at the beginning and end of a record to +be ignored. You can set the value of @code{FS} on the command line using the @option{-F} option: @@ -14799,10 +15035,24 @@ opens the next file. An associative array containing the values of the environment. The array indices are the environment variable names; the elements are the values of the particular environment variables. For example, -@code{ENVIRON["HOME"]} might be @code{"/home/arnold"}. Changing this array -does not affect the environment passed on to any programs that -@command{awk} may spawn via redirection or the @code{system()} function. -(In a future version of @command{gawk}, it may do so.) +@code{ENVIRON["HOME"]} might be @code{/home/arnold}. + +For POSIX @command{awk}, changing this array does not affect the +environment passed on to any programs that @command{awk} may spawn via +redirection or the @code{system()} function. + +However, beginning with version 4.2, if not in POSIX +compatibility mode, @command{gawk} does update its own environment when +@code{ENVIRON} is changed, thus changing the environment seen by programs +that it creates. You should therefore be especially careful if you +modify @code{ENVIRON["PATH"]}, which is the search path for finding +executable programs. + +This can also affect the running @command{gawk} program, since some of the +built-in functions may pay attention to certain environment variables. +The most notable instance of this is @code{mktime()} (@pxref{Time +Functions}), which pays attention the value of the @env{TZ} environment +variable on many systems. Some operating systems may not have environment variables. On such systems, the @code{ENVIRON} array is empty (except for @@ -14836,6 +15086,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} @@ -14904,6 +15159,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. @@ -15027,6 +15286,14 @@ to test for these elements The following elements allow you to change @command{gawk}'s behavior: @table @code +@item PROCINFO["NONFATAL"] +If this element exists, then I/O errors for all output redirections become nonfatal. +@xref{Nonfatal}. + +@item PROCINFO["@var{output_name}", "NONFATAL"] +Make output errors for @var{output_name} be nonfatal. +@xref{Nonfatal}. + @item PROCINFO["@var{command}", "pty"] For two-way communication to @var{command}, use a pseudo-tty instead of setting up a two-way pipe. @@ -16948,6 +17215,23 @@ truncated toward zero. For example, @code{int(3)} is 3, @code{int(3.9)} is 3, @code{int(-3.9)} is @minus{}3, and @code{int(-3)} is @minus{}3 as well. +@item @code{intdiv(@var{numerator}, @var{denominator}, @var{result})} +@cindexawkfunc{intdiv} +@cindex intdiv +Perform integer division, similar to the standard C function of the +same name. First, truncate @code{numerator} and @code{denominator} +towards zero, creating integer values. Clear the @code{result} +array, and then set @code{result["quotient"]} to the result of +@samp{numerator / denominator}, truncated towards zero to an integer, +and set @code{result["remainder"]} to the result of @samp{numerator % +denominator}, truncated towards zero to an integer. This function is +primarily intended for use with arbitrary length integers; it avoids +creating MPFR arbitrary precision floating-point values (@pxref{Arbitrary +Precision Integers}). + +This function is a @code{gawk} extension. It is not available in +compatibility mode (@pxref{Options}). + @item @code{log(@var{x})} @cindexawkfunc{log} @cindex logarithm @@ -19226,16 +19510,70 @@ results of the @code{compl()}, @code{lshift()}, and @code{rshift()} functions. @node Type Functions @subsection Getting Type Information -@command{gawk} provides a single function that lets you distinguish -an array from a scalar variable. This is necessary for writing code +@command{gawk} provides two functions that lets you distinguish +the type of a variable. +This is necessary for writing code that traverses every element of an array of arrays -(@pxref{Arrays of Arrays}). +(@pxref{Arrays of Arrays}), and in other contexts. @table @code @cindexgawkfunc{isarray} @cindex scalar or array @item isarray(@var{x}) Return a true value if @var{x} is an array. Otherwise, return false. + +@cindexgawkfunc{typeof} +@cindex variable type +@cindex type, of variable +@item typeof(@var{x}) +Return one of the following strings, depending upon the type of @var{x}: + +@c nested table +@table @code +@item "array" +@var{x} is an array. + +@item "regexp" +@var{x} is a strongly typed regexp (@pxref{Strong Regexp Constants}). + +@item "number" +@var{x} is a number. + +@item "string" +@var{x} is a string. + +@item "strnum" +@var{x} is a string that might be a number, such as a field or +the result of calling @code{split()}. (I.e., @var{x} has the STRNUM +attribute; @pxref{Variable Typing}.) + +@item "unassigned" +@var{x} is a scalar variable that has not been assigned a value yet. +For example: + +@example +BEGIN @{ + a[1] # creates a[1] but it has no assigned value + print typeof(a[1]) # scalar_u +@} +@end example + +@item "untyped" +@var{x} has not yet been used yet at all; it can become a scalar or an +array. +For example: + +@example +BEGIN @{ + print typeof(x) # x never used --> untyped + mk_arr(x) + print typeof(x) # x now an array --> array +@} + +function mk_arr(a) @{ a[1] = 1 @} +@end example + +@end table @end table @code{isarray()} is meant for use in two circumstances. The first is when @@ -19253,6 +19591,14 @@ that has not been previously used to @code{isarray()}, @command{gawk} ends up turning it into a scalar. @end quotation +The @code{typeof()} function is general; it allows you to determine +if a variable or function parameter is a scalar, an array, or a strongly +typed regexp. + +@code{isarray()} is deprecated; you should use @code{typeof()} instead. +You should replace any existing uses of @samp{isarray(var)} in your +code with @samp{typeof(var) == "array"}. + @node I18N Functions @subsection String-Translation Functions @cindex @command{gawk}, string-translation functions @@ -27514,9 +27860,16 @@ your program to hang. (Thus, this particular feature is of much less use in practice than being able to close the @code{"to"} end.) @quotation CAUTION -It is a fatal error to write to the @code{"to"} end of a two-way -pipe which has been closed. It is also a fatal error to read +Normally, +it is a fatal error to write to the @code{"to"} end of a two-way +pipe which has been closed, and it is also a fatal error to read from the @code{"from"} end of a two-way pipe that has been closed. + +You may set @code{PROCINFO["@var{command}", "NONFATAL"]} to +make such operations become nonfatal, in which case you then need +to check @code{ERRNO} after each @code{print}, @code{printf}, +or @code{getline}. +@xref{Nonfatal}, for more information. @end quotation @cindex @command{gawk}, @code{PROCINFO} array in @@ -27900,8 +28253,7 @@ The profiled version of your program may not look exactly like what you typed when you wrote it. This is because @command{gawk} creates the profiled version by ``pretty-printing'' its internal representation of the program. The advantage to this is that @command{gawk} can produce -a standard representation. The disadvantage is that all source code -comments are lost. +a standard representation. Also, things such as: @example @@ -27995,10 +28347,35 @@ When called this way, @command{gawk} ``pretty-prints'' the program into @file{awkprof.out}, without any execution counts. @quotation NOTE -The @option{--pretty-print} option still runs your program. -This will change in the next major release. +Once upon a time, the @option{--pretty-print} option would also run +your program. This is is no longer the case. @end quotation +There is a significant difference between the output created when +profiling, and that created when pretty-printing. Pretty-printed output +preserves the original comments that were in the program, although their +placement may not correspond exactly to their original locations in the +source code.@footnote{@command{gawk} does the best it can to preserve +the distinction between comments at the end of a statement and comments +on lines by themselves. Due to implementation constraints, it does not +always do so correctly, particularly for @code{switch} statements. The +@command{gawk} maintainers hope to improve this in a subsequent +release.} + +However, as a deliberate design decision, profiling output @emph{omits} +the original program's comments. This allows you to focus on the +execution count data and helps you avoid the temptation to use the +profiler for pretty-printing. + +Additionally, pretty-printed output does not have the leading indentation +that the profiling output does. This makes it easy to pretty-print your +code once development is completed, and then use the result as the final +version of your program. + +Because the internal representation of your program is formatted to +recreate an @command{awk} program, profiling and pretty-printing +automatically disable @command{gawk}'s default optimizations. + @node Advanced Features Summary @section Summary @@ -28039,8 +28416,7 @@ you tune them more easily. Sending the @code{USR1} signal while profiling cause @command{gawk} to dump the profile and keep going, including a function call stack. @item -You can also just ``pretty-print'' the program. This currently also runs -the program, but that will change in the next major release. +You can also just ``pretty-print'' the program. @end itemize @@ -30210,6 +30586,65 @@ executing, short programs. The @command{gawk} debugger only accepts source code supplied with the @option{-f} option. @end itemize +One other point is worth disucssing. Conventional debuggers run in a +separate process (and thus address space) from the programs that they +debug (the @dfn{debuggee}, if you will). + +The @command{gawk} debugger is different; it is an integrated part +of @command{gawk} itself. This makes it possible, in rare cases, +for @command{gawk} to become an excellent demonstrator of Heisenberg +Uncertainty physics, where the mere act of observing something can change +it. Consider the following:@footnote{Thanks to Hermann Peifer for +this example.} + +@example +$ @kbd{cat test.awk} +@print{} @{ print typeof($1), typeof($2) @} +$ @kbd{cat test.data} +@print{} abc 123 +$ @kbd{gawk -f test.awk test.data} +@print{} strnum strnum +@end example + +This is all as expected: field data has the STRNUM attribute +(@pxref{Variable Typing}). Now watch what happens when we run +this program under the debugger: + +@example +$ @kbd{gawk -D -f test.awk test.data} +gawk> @kbd{w $1} @ii{Set watchpoint on} $1 +@print{} Watchpoint 1: $1 +gawk> @kbd{w $2} @ii{Set watchpoint on} $2 +@print{} Watchpoint 2: $2 +gawk> @kbd{r} @ii{Start the program} +@print{} Starting program: +@print{} Stopping in Rule ... +@print{} Watchpoint 1: $1 @ii{Watchpoint fires} +@print{} Old value: "" +@print{} New value: "abc" +@print{} main() at `test.awk':1 +@print{} 1 @{ print typeof($1), typeof($2) @} +gawk> @kbd{n} @ii{Keep going @dots{}} +@print{} Watchpoint 2: $2 @ii{Watchpoint fires} +@print{} Old value: "" +@print{} New value: "123" +@print{} main() at `test.awk':1 +@print{} 1 @{ print typeof($1), typeof($2) @} +gawk> @kbd{n} @ii{Get result from} typeof() +@print{} strnum number @ii{Result for} $2 @ii{isn't right} +@print{} Program exited normally with exit value: 0 +gawk> @kbd{quit} +@end example + +In this case, the act of comparing the new value of @code{$2} +with the old one caused @command{gawk} to evaluate it and determine that it +is indeed a number, and this is reflected in the result of +@code{typeof()}. + +Cases like this where the debugger is not transparent to the program's +execution should be rare. If you encounter one, please report it +(@pxref{Bugs}). + @ignore Look forward to a future release when these and other missing features may be added, and of course feel free to try to add them yourself! @@ -30246,6 +30681,10 @@ If the GNU Readline library is available when @command{gawk} is compiled, it is used by the debugger to provide command-line history and editing. +@item +Usually, the debugger does not not affect the +program being debugged, but occasionally it can. + @end itemize @node Arbitrary Precision Arithmetic @@ -31063,6 +31502,122 @@ to just use the following: gawk -M 'BEGIN @{ n = 13; print n % 2 @}' @end example +When dividing two arbitrary precision integers with either +@samp{/} or @samp{%}, the result is typically an arbitrary +precision floating point value (unless the denominator evenly +divides into the numerator). In order to do integer division +or remainder with arbitrary precision integers, use the built-in +@code{intdiv()} function (@pxref{Numeric Functions}). + +You can simulate the @code{intdiv()} function in standard @command{awk} +using this user-defined function: + +@example +@c file eg/lib/intdiv.awk +# intdiv --- do integer division + +@c endfile +@ignore +@c file eg/lib/intdiv.awk +# +# Arnold Robbins, arnold@@skeeve.com, Public Domain +# July, 2014 +# +# Name changed from div() to intdiv() +# April, 2015 + +@c endfile + +@end ignore +@c file eg/lib/intdiv.awk +function intdiv(numerator, denominator, result) +@{ + split("", result) + + numerator = int(numerator) + denominator = int(denominator) + result["quotient"] = int(numerator / denominator) + result["remainder"] = int(numerator % denominator) + + return 0.0 +@} +@c endfile +@end example + +The following example program, contributed by Katie Wasserman, +uses @code{intdiv()} to +compute the digits of @value{PI} to as many places as you +choose to set: + +@example +@c file eg/prog/pi.awk +# pi.awk --- compute the digits of pi +@c endfile +@c endfile +@ignore +@c file eg/prog/pi.awk +# +# Katie Wasserman, katie@@wass.net +# August 2014 +@c endfile +@end ignore +@c file eg/prog/pi.awk + +BEGIN @{ + digits = 100000 + two = 2 * 10 ^ digits + pi = two + for (m = digits * 4; m > 0; --m) @{ + d = m * 2 + 1 + x = pi * m + intdiv(x, d, result) + pi = result["quotient"] + pi = pi + two + @} + print pi +@} +@c endfile +@end example + +@ignore +Date: Wed, 20 Aug 2014 10:19:11 -0400 +To: arnold@skeeve.com +From: Katherine Wasserman <katie@wass.net> +Subject: Re: computation of digits of pi? + +Arnold, + +>The program that you sent to compute the digits of pi using div(). Is +>that some standard algorithm that every math student knows? If so, +>what's it called? + +It's not that well known but it's not that obscure either + +It's Euler's modification to Newton's method for calculating pi. + +Take a look at lines (23) - (25) here: http://mathworld.wolfram.com/PiFormulas.htm + +The algorithm I wrote simply expands the multiply by 2 and works from the innermost expression outwards. I used this to program HP calculators because it's quite easy to modify for tiny memory devices with smallish word sizes. + +http://www.hpmuseum.org/cgi-sys/cgiwrap/hpmuseum/articles.cgi?read=899 + +-Katie +@end ignore + +When asked about the algorithm used, Katie replied: + +@quotation +It's not that well known but it's not that obscure either. +It's Euler's modification to Newton's method for calculating pi. +Take a look at lines (23) - (25) here: @uref{http://mathworld.wolfram.com/PiFormulas.html}. + +The algorithm I wrote simply expands the multiply by 2 and works from +the innermost expression outwards. I used this to program HP calculators +because it's quite easy to modify for tiny memory devices with smallish +word sizes. See +@uref{http://www.hpmuseum.org/cgi-sys/cgiwrap/hpmuseum/articles.cgi?read=899}. +@end quotation + @node POSIX Floating Point Problems @section Standards Versus Existing Practice @@ -31462,6 +32017,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 @@ -31537,6 +32093,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: @@ -31925,7 +32485,7 @@ Extension functions are described by the following record: typedef struct awk_ext_func @{ @ @ @ @ const char *name; @ @ @ @ awk_value_t *(*function)(int num_actual_args, awk_value_t *result); -@ @ @ @ size_t num_expected_args; +@ @ @ @ size_t max_expected_args; @} awk_ext_func_t; @end example @@ -31957,11 +32517,17 @@ actual parameters were passed from the calling @command{awk} code. The function must return the value of @code{result}. This is for the convenience of the calling code inside @command{gawk}. -@item size_t num_expected_args; -This is the number of arguments the function expects to receive. +@item size_t max_expected_args; +This is the maximum number of arguments the function expects to receive. Each extension function may decide what to do if the number of arguments isn't what it expected. As with real @command{awk} functions, it -is likely OK to ignore extra arguments. +is likely OK to ignore extra arguments. This value does not affect +actual program execution. + +Extension functions should compare this value to the number of actual +arguments passed and possibly issue a lint warning if there is an +undesirable mismatch. Of course, if +@samp{--lint=fatal} is used, this would cause the program to exit. @end table Once you have a record representing your extension function, you register @@ -32464,6 +33030,9 @@ that parameter. More's the pity.} @item void fatal(awk_ext_id_t id, const char *format, ...); Print a message and then cause @command{gawk} to exit immediately. +@item void nonfatal(awk_ext_id_t id, const char *format, ...); +Print a nonfatal error message. + @item void warning(awk_ext_id_t id, const char *format, ...); Print a warning message. @@ -33507,6 +34076,75 @@ $ @kbd{AWKLIBPATH=$PWD ./gawk -f subarray.awk} (@xref{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 @code{NULL} or @code{name_len} is zero, return +data for the currently open input file corresponding to @code{FILENAME}. +(This does not access the @code{filetype} argument, so that may be undefined). +If the file is not already open, attempt to open it. +The @code{filetype} argument must be zero-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, return a @code{false} value. Otherwise, return +@code{true}, and return additional information about the redirection +in the @code{ibufp} and @code{obufp} pointers. For input +redirections, the @code{*ibufp} value should be non-@code{NULL}, +and @code{*obufp} should be @code{NULL}. For output redirections, +the @code{*obufp} value should be non-@code{NULL}, and @code{*ibufp} +should be @code{NULL}. For two-way coprocesses, both values should +be non-@code{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 @code{fd} argument is non-negative, @command{gawk} +will use that file descriptor instead of opening the file in the +usual way. If @code{fd} is non-negative, but the file exists already, +@command{gawk} ignores @code{fd} and returns the existing file. It is +the caller's responsibility to notice that neither the @code{fd} in +the returned @code{awk_input_buf_t} nor the @code{fd} in the returned +@code{awk_output_buf_t} matches the requested value. + +Note that supplying a file descriptor is currently @emph{not} supported +for pipes. However, supplying a file descriptor should work for input, +output, append, and two-way (coprocess) sockets. If @code{filetype} +is two-way, @command{gawk} assumes that it is a socket! Note that in +the two-way case, the input and output file descriptors may differ. +To check for success, you 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 @@ -35074,18 +35712,21 @@ As of this writing, there are seven extensions: GD graphics library extension @item +MPFR library extension +(this provides access to a number of MPFR functions that @command{gawk}'s +native MPFR support does not) + +@item PDF extension @item PostgreSQL extension @item -MPFR library extension -(this provides access to a number of MPFR functions that @command{gawk}'s -native MPFR support does not) +Redis extension @item -Redis extension +Select extension @item XML parser extension, using the @uref{http://expat.sourceforge.net, Expat} @@ -35185,7 +35826,7 @@ output wrappers, and two-way processors) @item -Printing fatal, warning, and ``lint'' warning messages +Printing fatal, nonfatal, warning, and ``lint'' warning messages @item Updating @code{ERRNO}, or unsetting it @@ -35714,6 +36355,10 @@ Indirect function calls @item Directories on the command line produce a warning and are skipped (@pxref{Command-line directories}) + +@item +Output with @code{print} and @code{printf} need not be fatal +(@pxref{Nonfatal}) @end itemize @item @@ -35801,6 +36446,11 @@ The @code{isarray()} function to check if a variable is an array or not The @code{bindtextdomain()}, @code{dcgettext()}, and @code{dcngettext()} functions for internationalization (@pxref{Programmer i18n}) + +@item +The @code{intdiv()} function for doing integer +division and remainder +(@pxref{Numeric Functions}) @end itemize @item @@ -35839,6 +36489,7 @@ The @option{-p}, @option{-P}, @option{-r}, +@option{-s}, @option{-S}, @option{-t}, and @@ -35863,6 +36514,7 @@ and the @option{--load}, @option{--non-decimal-data}, @option{--optimize}, +@option{--no-optimize}, @option{--posix}, @option{--pretty-print}, @option{--profile}, @@ -35933,6 +36585,16 @@ for @command{gawk} @value{PVERSION} 4.1: Ultrix @end itemize +@item +Support for the following systems was removed from the code +for @command{gawk} @value{PVERSION} 4.2: + +@c nested table +@itemize @value{MINUS} +@item +MirBSD +@end itemize + @end itemize @c XXX ADD MORE STUFF HERE @@ -36559,6 +37221,52 @@ Support for Ultrix was removed. @end itemize +Version 4.2 introduced the following changes: + +@itemize @bullet +@item +Changes to @code{ENVIRON} are reflected into @command{gawk}'s +environment and that of programs that it runs. +@xref{Auto-set}. + +@item +The @option{--pretty-print} option no longer runs the @command{awk} +program too. +@xref{Options}. + +@item +The @command{igawk} program and its manual page are no longer +installed when @command{gawk} is built. +@xref{Igawk Program}. + +@item +The @code{intdiv()} function. +@xref{Numeric Functions}. + +@item +The maximum number of hexadecimal digits in @samp{\x} escapes +is now two. +@xref{Escape Sequences}. + +@item +Nonfatal output with @code{print} and @code{printf}. +@xref{Nonfatal}. + +@item +For many years, POSIX specified that default field splitting +only allowed spaces and tabs to separate fields, and this was +how @command{gawk} behaved with @option{--posix}. As of 2013, +the standard restored historical behavior, and now default +field splitting with @option{--posix} also allows newlines to +separate fields. + +@item +Support for MirBSD was removed. + +@item +Support for GNU/Linux on Alpha was removed. +@end itemize + @c XXX ADD MORE STUFF HERE @end ifclear @@ -37226,6 +37934,8 @@ The generated Info file for The @command{troff} source for a manual page describing the @command{igawk} program presented in @ref{Igawk Program}. +(Since @command{gawk} can do its own @code{@@include} processing, +neither @command{igawk} nor @file{igawk.1} are installed.) @item doc/Makefile.in The input file used during the configuration process to generate the @@ -37270,8 +37980,6 @@ source file for this @value{DOCUMENT}. It also contains a @file{Makefile.in} fil @file{Makefile.am} is used by GNU Automake to create @file{Makefile.in}. The library functions from @ref{Library Functions}, -and the @command{igawk} program from -@ref{Igawk Program} are included as ready-to-use files in the @command{gawk} distribution. They are installed as part of the installation process. The rest of the programs in this @value{DOCUMENT} are available in appropriate @@ -37282,6 +37990,12 @@ The source code, manual pages, and infrastructure files for the sample extensions included with @command{gawk}. @xref{Dynamic Extensions}, for more information. +@item extras/* +Additional non-essential files. Currently, this directory contains some shell +startup files to be installed in @file{/etc/profile.d} to aid in manipulating +the @env{AWKPATH} and @env{AWKLIBPATH} environment variables. +@xref{Shell Startup Files}, for more information. + @item posix/* Files needed for building @command{gawk} on POSIX-compliant systems. @@ -37313,6 +38027,7 @@ to configure @command{gawk} for your system yourself. @menu * Quick Installation:: Compiling @command{gawk} under Unix. +* Shell Startup Files:: Shell convenience functions. * Additional Configuration Options:: Other compile-time options. * Configuration Philosophy:: How it's all supposed to work. @end menu @@ -37393,6 +38108,44 @@ is likely that you will be asked for your password, and you will have to have been set up previously as a user who is allowed to run the @command{sudo} command. +@node Shell Startup Files +@appendixsubsec Shell Startup Files + +The distribution contains shell startup files @file{gawk.sh} and +@file{gawk.csh} containing functions to aid in manipulating +the @env{AWKPATH} and @env{AWKLIBPATH} environment variables. +On a Fedora system, these files should be installed in @file{/etc/profile.d}; +on other platforms, the appropriate location may be different. + +@table @command + +@cindex @command{gawkpath_default} shell function +@item gawkpath_default +Reset the @env{AWKPATH} environment variable to its default value. + +@cindex @command{gawkpath_prepend} shell function +@item gawkpath_prepend +Add the argument to the front of the @env{AWKPATH} environment variable. + +@cindex @command{gawkpath_append} shell function +@item gawkpath_append +Add the argument to the end of the @env{AWKPATH} environment variable. + +@cindex @command{gawklibpath_default} shell function +@item gawklibpath_default +Reset the @env{AWKLIBPATH} environment variable to its default value. + +@cindex @command{gawklibpath_prepend} shell function +@item gawklibpath_prepend +Add the argument to the front of the @env{AWKLIBPATH} environment variable. + +@cindex @command{gawklibpath_append} shell function +@item gawklibpath_append +Add the argument to the end of the @env{AWKLIBPATH} environment variable. + +@end table + + @node Additional Configuration Options @appendixsubsec Additional Configuration Options @cindex @command{gawk}, configuring, options diff --git a/doc/gawktexi.in b/doc/gawktexi.in index d06fa4b9..e5177ca2 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -534,6 +534,7 @@ particular records in a file and perform operations upon them. * Computed Regexps:: Using Dynamic Regexps. * GNU Regexp Operators:: Operators specific to GNU software. * Case-sensitivity:: How to do case-insensitive matching. +* Strong Regexp Constants:: Strongly typed regexp constants. * Regexp Summary:: Regular expressions summary. * Records:: Controlling how data is split into records. @@ -576,6 +577,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. @@ -605,6 +607,7 @@ particular records in a file and perform operations upon them. * Special Caveats:: Things to watch out for. * Close Files And Pipes:: Closing Input and Output Files and Pipes. +* Nonfatal:: Enabling Nonfatal Output. * Output Summary:: Output summary. * Output Exercises:: Exercises. * Values:: Constants, Variables, and Regular @@ -916,6 +919,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 @@ -974,6 +978,7 @@ particular records in a file and perform operations upon them. * Unix Installation:: Installing @command{gawk} under various versions of Unix. * Quick Installation:: Compiling @command{gawk} under Unix. +* Shell Startup Files:: Shell convenience functions. * Additional Configuration Options:: Other compile-time options. * Configuration Philosophy:: How it's all supposed to work. * Non-Unix Installation:: Installation on Other Operating @@ -3966,6 +3971,7 @@ when parsing numeric input data (@pxref{Locales}). @cindex @option{-o} option @cindex @option{--pretty-print} option Enable pretty-printing of @command{awk} programs. +Implies @option{--no-optimize}. By default, the output program is created in a file named @file{awkprof.out} (@pxref{Profiling}). The optional @var{file} argument allows you to specify a different @@ -3974,18 +3980,22 @@ No space is allowed between the @option{-o} and @var{file}, if @var{file} is supplied. @quotation NOTE -Due to the way @command{gawk} has evolved, with this option -your program still executes. This will change in the -next major release, such that @command{gawk} will only -pretty-print the program and not run it. +In the past, this option would also execute your program. +This is no longer the case. @end quotation @item @option{-O} @itemx @option{--optimize} @cindex @option{--optimize} option @cindex @option{-O} option -Enable some optimizations on the internal representation of the program. -At the moment, this includes just simple constant folding. +Enable @command{gawk}'s default optimizations on the internal +representation of the program. At the moment, this includes simple +constant folding and tail recursion elimination in function calls. + +These optimizations are enabled by default. +This option remains primarily for backwards compatibilty. However, it may +be used to cancel the effect of an earlier @option{-s} option +(see later in this list). @item @option{-p}[@var{file}] @itemx @option{--profile}[@code{=}@var{file}] @@ -3994,6 +4004,7 @@ At the moment, this includes just simple constant folding. @cindex @command{awk} profiling, enabling Enable profiling of @command{awk} programs (@pxref{Profiling}). +Implies @option{--no-optimize}. By default, profiles are created in a file named @file{awkprof.out}. The optional @var{file} argument allows you to specify a different @value{FN} for the profile file. @@ -4023,11 +4034,6 @@ restrictions apply: @cindex newlines @cindex whitespace, newlines as @item -Newlines do not act as whitespace to separate fields when @code{FS} is -equal to a single space -(@pxref{Fields}). - -@item Newlines are not allowed after @samp{?} or @samp{:} (@pxref{Conditional Exp}). @@ -4065,6 +4071,13 @@ This is now @command{gawk}'s default behavior. Nevertheless, this option remains (both for backward compatibility and for use in combination with @option{--traditional}). +@item @option{-s} +@itemx @option{--no-optimize} +@cindex @option{--no-optimize} option +@cindex @option{-s} option +Disable @command{gawk}'s default optimizations on the internal +representation of the program. + @item @option{-S} @itemx @option{--sandbox} @cindex @option{-S} option @@ -4378,6 +4391,9 @@ searches first in the current directory and then in @file{/usr/local/share/awk}. In practice, this means that you will rarely need to change the value of @env{AWKPATH}. +@xref{Shell Startup Files}, for information on functions that help to +manipulate the @env{AWKPATH} variable. + @command{gawk} places the value of the search path that it used into @code{ENVIRON["AWKPATH"]}. This provides access to the actual search path value from within an @command{awk} program. @@ -4409,6 +4425,9 @@ an empty value, @command{gawk} uses a default path; this is typically @samp{/usr/local/lib/gawk}, although it can vary depending upon how @command{gawk} was built. +@xref{Shell Startup Files}, for information on functions that help to +manipulate the @env{AWKLIBPATH} variable. + @command{gawk} places the value of the search path that it used into @code{ENVIRON["AWKLIBPATH"]}. This provides access to the actual search path value from within an @command{awk} program. @@ -4436,6 +4455,8 @@ wait for input before returning with an error. Controls the number of times @command{gawk} attempts to retry a two-way TCP/IP (socket) connection before giving up. @xref{TCP/IP Networking}. +Note that when nonfatal I/O is enabled (@pxref{Nonfatal}), +@command{gawk} only tries to open a TCP/IP socket once. @item POSIXLY_CORRECT Causes @command{gawk} to switch to POSIX-compatibility @@ -4485,14 +4506,6 @@ two regexp matchers that @command{gawk} uses internally. (There aren't supposed to be differences, but occasionally theory and practice don't coordinate with each other.) -@item GAWK_NO_PP_RUN -When @command{gawk} is invoked with the @option{--pretty-print} option, -it will not run the program if this environment variable exists. - -@quotation CAUTION -This variable will not survive into the next major release. -@end quotation - @item GAWK_STACKSIZE This specifies the amount by which @command{gawk} should grow its internal evaluation stack, when needed. @@ -4790,6 +4803,32 @@ Similarly, you may use @code{print} or @code{printf} statements in the @var{init} and @var{increment} parts of a @code{for} loop. This is another long-undocumented ``feature'' of Unix @command{awk}. +@command{gawk} lets you use the names of built-in functions that are +@command{gawk} extensions as the names of parameters in user-defined functions. +This is intended to ``future-proof'' old code that happens to use +function names added by @command{gawk} after the code was written. +Standard @command{awk} built-in functions, such as @code{sin()} or +@code{substr()} are @emph{not} shadowed in this way. + +The @code{PROCINFO["argv"]} array contains all of the command-line arguments +(after glob expansion and redirection processing on platforms where that must +be done manually by the program) with subscripts ranging from 0 through +@code{argc} @minus{} 1. For example, @code{PROCINFO["argv"][0]} will contain +the name by which @command{gawk} was invoked. Here is an example of how this +feature may be used: + +@example +awk ' +BEGIN @{ + for (i = 0; i < length(PROCINFO["argv"]); i++) + print i, PROCINFO["argv"][i] +@}' +@end example + +Please note that this differs from the standard @code{ARGV} array which does +not include command-line arguments that have already been processed by +@command{gawk} (@pxref{ARGC and ARGV}). + @end ignore @node Invoking Summary @@ -4882,6 +4921,7 @@ regular expressions work, we present more complicated instances. * Computed Regexps:: Using Dynamic Regexps. * GNU Regexp Operators:: Operators specific to GNU software. * Case-sensitivity:: How to do case-insensitive matching. +* Strong Regexp Constants:: Strongly typed regexp constants. * Regexp Summary:: Regular expressions summary. @end menu @@ -5072,17 +5112,21 @@ between @samp{0} and @samp{7}. For example, the code for the ASCII ESC @item \x@var{hh}@dots{} The hexadecimal value @var{hh}, where @var{hh} stands for a sequence of hexadecimal digits (@samp{0}--@samp{9}, and either @samp{A}--@samp{F} -or @samp{a}--@samp{f}). Like the same construct -in ISO C, the escape sequence continues until the first nonhexadecimal -digit is seen. @value{COMMONEXT} -However, using more than two hexadecimal digits produces -undefined results. (The @samp{\x} escape sequence is not allowed in -POSIX @command{awk}.) +or @samp{a}--@samp{f}). A maximum of two digts are allowed after +the @samp{\x}. Any further hexadecimal digits are treated as simple +letters or numbers. @value{COMMONEXT} +(The @samp{\x} escape sequence is not allowed in POSIX awk.) @quotation CAUTION -The next major release of @command{gawk} will change, such -that a maximum of two hexadecimal digits following the -@samp{\x} will be used. +In ISO C, the escape sequence continues until the first nonhexadecimal +digit is seen. +For many years, @command{gawk} would continue incorporating +hexadecimal digits into the value until a non-hexadecimal digit +or the end of the string was encountered. +However, using more than two hexadecimal digits produced +undefined results. +As of @value{PVERSION} 4.2, only two digits +are processed. @end quotation @cindex @code{\} (backslash), @code{\/} escape sequence @@ -6011,6 +6055,89 @@ The value of @code{IGNORECASE} has no effect if @command{gawk} is in compatibility mode (@pxref{Options}). Case is always significant in compatibility mode. +@node Strong Regexp Constants +@section Strongly Typed Regexp Constants + +This @value{SECTION} describes a @command{gawk}-specific feature. + +Regexp constants (@code{/@dots{}/}) hold a strange position in the +@command{awk} language. In most contexts, they act like an expression: +@samp{$0 ~ /@dots{}/}. In other contexts, they denote only a regexp to +be matched. In no case are they really a ``first class citizen'' of the +language. That is, you cannot define a scalar variable whose type is +``regexp'' in the same sense that you can define a variable to be a +number or a string: + +@example +num = 42 @ii{Numeric variable} +str = "hi" @ii{String variable} +re = /foo/ @ii{Wrong!} re @ii{is the result of} $0 ~ /foo/ +@end example + +For a number of more advanced use cases (described later on in this +@value{DOCUMENT}), it would be nice to have regexp constants that +are @dfn{strongly typed}; in other words, that denote a regexp useful +for matching, and not an expression. + +@command{gawk} provides this feature. A strongly typed regexp constant +looks almost like a regular regexp constant, except that it is preceded +by an @samp{@@} sign: + +@example +re = @@/foo/ @ii{Regexp variable} +@end example + +Strongly typed regexp constants @emph{cannot} be used eveywhere that a +regular regexp constant can, because this would make the language even more +confusing. Instead, you may use them only in certain contexts: + +@itemize @bullet +@item +On the righthand side of the @samp{~} and @samp{!~} operators: @samp{some_var ~ @@/foo/} +(@pxref{Regexp Usage}). + +@item +In the @code{case} part of a @code{switch} statement +(@pxref{Switch Statement}). + +@item +As an argument to one of the built-in functions that accept regexp constants: +@code{gensub()}, +@code{gsub()}, +@code{match()}, +@code{patsplit()}, +@code{split()}, +and +@code{sub()} +(@pxref{String Functions}). + +@item +As a parameter in a call to a user-defined function +(@pxref{User-defined}). + +@item +On the righthand side of an assignment to a variable: @samp{some_var = @@/foo/}. +In this case, the type of @code{some_var} is regexp. Additionally, @code{some_var} +can be used with @samp{~} and @samp{!~}, passed to one of the built-in functions +listed above, or passed as a parameter to a user-defined function. +@end itemize + +You may use the @code{typeof()} built-in function +(@pxref{Type Functions}) +to determine if a variable or function parameter is +a regexp variable. + +The true power of this feature comes from the ability to create variables that +have regexp type. Such variables can be passed on to user-defined functions, +without the confusing aspects of computed regular expressions created from +strings or string constants. They may also be passed through indirect function +calls (@pxref{Indirect Calls}) +onto the built-in functions that accept regexp constants. + +When used in numeric conversions, strongly typed regexp variables convert +to zero. When used in string conversions, they convert to the string +value of the original regexp text. + @node Regexp Summary @section Summary @@ -6054,6 +6181,11 @@ treated as regular expressions). case sensitivity of regexp matching. In other @command{awk} versions, use @code{tolower()} or @code{toupper()}. +@item +Strongly typed regexp constants (@code{@@/.../}) enable +certain advanced use cases to be described later on in the +@value{DOCUMENT}. + @end itemize @@ -6101,6 +6233,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. @@ -6418,16 +6551,12 @@ Readfile} for another option. @cindex fields @cindex accessing fields @cindex fields, examining -@cindex POSIX @command{awk}, field separators and -@cindex field separators, POSIX and -@cindex separators, field, POSIX and When @command{awk} reads an input record, the record is automatically @dfn{parsed} or separated by the @command{awk} utility into chunks called @dfn{fields}. By default, fields are separated by @dfn{whitespace}, like words in a line. Whitespace in @command{awk} means any string of one or more spaces, -TABs, or newlines;@footnote{In POSIX @command{awk}, newlines are not -considered whitespace for separating fields.} other characters +TABs, or newlines; other characters that are considered whitespace by other languages (such as formfeed, vertical tab, etc.) are @emph{not} considered whitespace by @command{awk}. @@ -6841,7 +6970,6 @@ can massage it first with a separate @command{awk} program.) @node Default Field Splitting @subsection Whitespace Normally Separates Fields -@cindex newlines, as field separators @cindex whitespace, as field separators Fields are normally separated by whitespace sequences (spaces, TABs, and newlines), not by single spaces. Two spaces in a row do not @@ -7708,6 +7836,13 @@ 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 @code{ERRNO} indicates that the I/O operation may be +retried, and @code{PROCINFO["@var{input}", "RETRY"]} is set, +then @code{getline} returns @minus{}2 +instead of @minus{}1, and further calls to @code{getline} +may be attemped. @xref{Retrying Input} for further information about +this feature. + In the following examples, @var{command} stands for a string value that represents a shell command. @@ -8362,7 +8497,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. @xref{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 @@ -8372,6 +8508,36 @@ 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, by +default @code{getline} returns @minus{}1, and subsequent attempts to +read from that file 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 a special element in +the @code{PROCINFO} array (@pxref{Auto-set}): + +@example +PROCINFO["@var{input_name}", "RETRY"] = 1 +@end example + +When this element exists, @command{gawk} checks the value of the system +(C language) +@code{errno} variable when an I/O error occurs. If @code{errno} indicates +a subsequent I/O attempt may succeed, @code{getline} instead returns +@minus{}2 and +further calls to @code{getline} may succeed. This applies to the @code{errno} +values @code{EAGAIN}, @code{EWOULDBLOCK}, @code{EINTR}, or @code{ETIMEDOUT}. + +This feature is useful in conjunction with +@code{PROCINFO["@var{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 @@ -8533,6 +8699,7 @@ and discusses the @code{close()} built-in function. @command{gawk} allows access to inherited file descriptors. * Close Files And Pipes:: Closing Input and Output Files and Pipes. +* Nonfatal:: Enabling Nonfatal Output. * Output Summary:: Output summary. * Output Exercises:: Exercises. @end menu @@ -9934,6 +10101,70 @@ In POSIX mode (@pxref{Options}), @command{gawk} just returns zero when closing a pipe. @end sidebar +@node Nonfatal +@section Enabling Nonfatal Output + +This @value{SECTION} describes a @command{gawk}-specific feature. + +In standard @command{awk}, output with @code{print} or @code{printf} +to a nonexistent file, or some other I/O error (such as filling up the +disk) is a fatal error. + +@example +$ @kbd{gawk 'BEGIN @{ print "hi" > "/no/such/file" @}'} +@error{} gawk: cmd. line:1: fatal: can't redirect to `/no/such/file' (No such file or directory) +@end example + +@command{gawk} makes it possible to detect that an error has +occurred, allowing you to possibly recover from the error, or +at least print an error message of your choosing before exiting. +You can do this in one of two ways: + +@itemize @bullet +@item +For all output files, by assigning any value to @code{PROCINFO["NONFATAL"]}. + +@item +On a per-file basis, by assigning any value to +@code{PROCINFO[@var{filename}, "NONFATAL"]}. +Here, @var{filename} is the name of the file to which +you wish output to be nonfatal. +@end itemize + +Once you have enabled nonfatal output, you must check @code{ERRNO} +after every relevant @code{print} or @code{printf} statement to +see if something went wrong. It is also a good idea to initialize +@code{ERRNO} to zero before attempting the output. For example: + +@example +$ @kbd{gawk '} +> @kbd{BEGIN @{} +> @kbd{ PROCINFO["NONFATAL"] = 1} +> @kbd{ ERRNO = 0} +> @kbd{ print "hi" > "/no/such/file"} +> @kbd{ if (ERRNO) @{} +> @kbd{ print("Output failed:", ERRNO) > "/dev/stderr"} +> @kbd{ exit 1} +> @kbd{ @}} +> @kbd{@}'} +@error{} Output failed: No such file or directory +@end example + +Here, @command{gawk} did not produce a fatal error; instead +it let the @command{awk} program code detect the problem and handle it. + +This mechanism works also for standard output and standard error. +For standard output, you may use @code{PROCINFO["-", "NONFATAL"]} +or @code{PROCINFO["/dev/stdout", "NONFATAL"]}. For standard error, use +@code{PROCINFO["/dev/stderr", "NONFATAL"]}. + +When attempting to open a TCP/IP socket (@pxref{TCP/IP Networking}), +@command{gawk} tries multiple times. The @env{GAWK_SOCK_RETRIES} +environment variable (@pxref{Other Environment Variables}) allows you to +override @command{gawk}'s builtin default number of attempts. However, +once nonfatal I/O is enabled for a given socket, @command{gawk} only +retries once, relying on @command{awk}-level code to notice that there +was a problem. @node Output Summary @section Summary @@ -9963,6 +10194,12 @@ Use @code{close()} to close open file, pipe, and coprocess redirections. For coprocesses, it is possible to close only one direction of the communications. +@item +Normally errors with @code{print} or @code{printf} are fatal. +@command{gawk} lets you make output errors be nonfatal either for +all files or on a per-file basis. You must then check for errors +after every relevant output statement. + @end itemize @c EXCLUDE START @@ -13898,12 +14135,11 @@ specify the behavior when @code{FS} is the null string. Nonetheless, some other versions of @command{awk} also treat @code{""} specially.) -@cindex POSIX @command{awk}, @code{FS} variable and The default value is @w{@code{" "}}, a string consisting of a single -space. As a special exception, this value means that any -sequence of spaces, TABs, and/or newlines is a single separator.@footnote{In -POSIX @command{awk}, newline does not count as whitespace.} It also causes -spaces, TABs, and newlines at the beginning and end of a record to be ignored. +space. As a special exception, this value means that any sequence of +spaces, TABs, and/or newlines is a single separator. It also causes +spaces, TABs, and newlines at the beginning and end of a record to +be ignored. You can set the value of @code{FS} on the command line using the @option{-F} option: @@ -14127,10 +14363,24 @@ opens the next file. An associative array containing the values of the environment. The array indices are the environment variable names; the elements are the values of the particular environment variables. For example, -@code{ENVIRON["HOME"]} might be @code{"/home/arnold"}. Changing this array -does not affect the environment passed on to any programs that -@command{awk} may spawn via redirection or the @code{system()} function. -(In a future version of @command{gawk}, it may do so.) +@code{ENVIRON["HOME"]} might be @code{/home/arnold}. + +For POSIX @command{awk}, changing this array does not affect the +environment passed on to any programs that @command{awk} may spawn via +redirection or the @code{system()} function. + +However, beginning with version 4.2, if not in POSIX +compatibility mode, @command{gawk} does update its own environment when +@code{ENVIRON} is changed, thus changing the environment seen by programs +that it creates. You should therefore be especially careful if you +modify @code{ENVIRON["PATH"]}, which is the search path for finding +executable programs. + +This can also affect the running @command{gawk} program, since some of the +built-in functions may pay attention to certain environment variables. +The most notable instance of this is @code{mktime()} (@pxref{Time +Functions}), which pays attention the value of the @env{TZ} environment +variable on many systems. Some operating systems may not have environment variables. On such systems, the @code{ENVIRON} array is empty (except for @@ -14164,6 +14414,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} @@ -14232,6 +14487,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. @@ -14355,6 +14614,14 @@ to test for these elements The following elements allow you to change @command{gawk}'s behavior: @table @code +@item PROCINFO["NONFATAL"] +If this element exists, then I/O errors for all output redirections become nonfatal. +@xref{Nonfatal}. + +@item PROCINFO["@var{output_name}", "NONFATAL"] +Make output errors for @var{output_name} be nonfatal. +@xref{Nonfatal}. + @item PROCINFO["@var{command}", "pty"] For two-way communication to @var{command}, use a pseudo-tty instead of setting up a two-way pipe. @@ -16230,6 +16497,23 @@ truncated toward zero. For example, @code{int(3)} is 3, @code{int(3.9)} is 3, @code{int(-3.9)} is @minus{}3, and @code{int(-3)} is @minus{}3 as well. +@item @code{intdiv(@var{numerator}, @var{denominator}, @var{result})} +@cindexawkfunc{intdiv} +@cindex intdiv +Perform integer division, similar to the standard C function of the +same name. First, truncate @code{numerator} and @code{denominator} +towards zero, creating integer values. Clear the @code{result} +array, and then set @code{result["quotient"]} to the result of +@samp{numerator / denominator}, truncated towards zero to an integer, +and set @code{result["remainder"]} to the result of @samp{numerator % +denominator}, truncated towards zero to an integer. This function is +primarily intended for use with arbitrary length integers; it avoids +creating MPFR arbitrary precision floating-point values (@pxref{Arbitrary +Precision Integers}). + +This function is a @code{gawk} extension. It is not available in +compatibility mode (@pxref{Options}). + @item @code{log(@var{x})} @cindexawkfunc{log} @cindex logarithm @@ -18347,16 +18631,70 @@ results of the @code{compl()}, @code{lshift()}, and @code{rshift()} functions. @node Type Functions @subsection Getting Type Information -@command{gawk} provides a single function that lets you distinguish -an array from a scalar variable. This is necessary for writing code +@command{gawk} provides two functions that lets you distinguish +the type of a variable. +This is necessary for writing code that traverses every element of an array of arrays -(@pxref{Arrays of Arrays}). +(@pxref{Arrays of Arrays}), and in other contexts. @table @code @cindexgawkfunc{isarray} @cindex scalar or array @item isarray(@var{x}) Return a true value if @var{x} is an array. Otherwise, return false. + +@cindexgawkfunc{typeof} +@cindex variable type +@cindex type, of variable +@item typeof(@var{x}) +Return one of the following strings, depending upon the type of @var{x}: + +@c nested table +@table @code +@item "array" +@var{x} is an array. + +@item "regexp" +@var{x} is a strongly typed regexp (@pxref{Strong Regexp Constants}). + +@item "number" +@var{x} is a number. + +@item "string" +@var{x} is a string. + +@item "strnum" +@var{x} is a string that might be a number, such as a field or +the result of calling @code{split()}. (I.e., @var{x} has the STRNUM +attribute; @pxref{Variable Typing}.) + +@item "unassigned" +@var{x} is a scalar variable that has not been assigned a value yet. +For example: + +@example +BEGIN @{ + a[1] # creates a[1] but it has no assigned value + print typeof(a[1]) # scalar_u +@} +@end example + +@item "untyped" +@var{x} has not yet been used yet at all; it can become a scalar or an +array. +For example: + +@example +BEGIN @{ + print typeof(x) # x never used --> untyped + mk_arr(x) + print typeof(x) # x now an array --> array +@} + +function mk_arr(a) @{ a[1] = 1 @} +@end example + +@end table @end table @code{isarray()} is meant for use in two circumstances. The first is when @@ -18374,6 +18712,14 @@ that has not been previously used to @code{isarray()}, @command{gawk} ends up turning it into a scalar. @end quotation +The @code{typeof()} function is general; it allows you to determine +if a variable or function parameter is a scalar, an array, or a strongly +typed regexp. + +@code{isarray()} is deprecated; you should use @code{typeof()} instead. +You should replace any existing uses of @samp{isarray(var)} in your +code with @samp{typeof(var) == "array"}. + @node I18N Functions @subsection String-Translation Functions @cindex @command{gawk}, string-translation functions @@ -26605,9 +26951,16 @@ your program to hang. (Thus, this particular feature is of much less use in practice than being able to close the @code{"to"} end.) @quotation CAUTION -It is a fatal error to write to the @code{"to"} end of a two-way -pipe which has been closed. It is also a fatal error to read +Normally, +it is a fatal error to write to the @code{"to"} end of a two-way +pipe which has been closed, and it is also a fatal error to read from the @code{"from"} end of a two-way pipe that has been closed. + +You may set @code{PROCINFO["@var{command}", "NONFATAL"]} to +make such operations become nonfatal, in which case you then need +to check @code{ERRNO} after each @code{print}, @code{printf}, +or @code{getline}. +@xref{Nonfatal}, for more information. @end quotation @cindex @command{gawk}, @code{PROCINFO} array in @@ -26991,8 +27344,7 @@ The profiled version of your program may not look exactly like what you typed when you wrote it. This is because @command{gawk} creates the profiled version by ``pretty-printing'' its internal representation of the program. The advantage to this is that @command{gawk} can produce -a standard representation. The disadvantage is that all source code -comments are lost. +a standard representation. Also, things such as: @example @@ -27086,10 +27438,35 @@ When called this way, @command{gawk} ``pretty-prints'' the program into @file{awkprof.out}, without any execution counts. @quotation NOTE -The @option{--pretty-print} option still runs your program. -This will change in the next major release. +Once upon a time, the @option{--pretty-print} option would also run +your program. This is is no longer the case. @end quotation +There is a significant difference between the output created when +profiling, and that created when pretty-printing. Pretty-printed output +preserves the original comments that were in the program, although their +placement may not correspond exactly to their original locations in the +source code.@footnote{@command{gawk} does the best it can to preserve +the distinction between comments at the end of a statement and comments +on lines by themselves. Due to implementation constraints, it does not +always do so correctly, particularly for @code{switch} statements. The +@command{gawk} maintainers hope to improve this in a subsequent +release.} + +However, as a deliberate design decision, profiling output @emph{omits} +the original program's comments. This allows you to focus on the +execution count data and helps you avoid the temptation to use the +profiler for pretty-printing. + +Additionally, pretty-printed output does not have the leading indentation +that the profiling output does. This makes it easy to pretty-print your +code once development is completed, and then use the result as the final +version of your program. + +Because the internal representation of your program is formatted to +recreate an @command{awk} program, profiling and pretty-printing +automatically disable @command{gawk}'s default optimizations. + @node Advanced Features Summary @section Summary @@ -27130,8 +27507,7 @@ you tune them more easily. Sending the @code{USR1} signal while profiling cause @command{gawk} to dump the profile and keep going, including a function call stack. @item -You can also just ``pretty-print'' the program. This currently also runs -the program, but that will change in the next major release. +You can also just ``pretty-print'' the program. @end itemize @@ -29301,6 +29677,65 @@ executing, short programs. The @command{gawk} debugger only accepts source code supplied with the @option{-f} option. @end itemize +One other point is worth disucssing. Conventional debuggers run in a +separate process (and thus address space) from the programs that they +debug (the @dfn{debuggee}, if you will). + +The @command{gawk} debugger is different; it is an integrated part +of @command{gawk} itself. This makes it possible, in rare cases, +for @command{gawk} to become an excellent demonstrator of Heisenberg +Uncertainty physics, where the mere act of observing something can change +it. Consider the following:@footnote{Thanks to Hermann Peifer for +this example.} + +@example +$ @kbd{cat test.awk} +@print{} @{ print typeof($1), typeof($2) @} +$ @kbd{cat test.data} +@print{} abc 123 +$ @kbd{gawk -f test.awk test.data} +@print{} strnum strnum +@end example + +This is all as expected: field data has the STRNUM attribute +(@pxref{Variable Typing}). Now watch what happens when we run +this program under the debugger: + +@example +$ @kbd{gawk -D -f test.awk test.data} +gawk> @kbd{w $1} @ii{Set watchpoint on} $1 +@print{} Watchpoint 1: $1 +gawk> @kbd{w $2} @ii{Set watchpoint on} $2 +@print{} Watchpoint 2: $2 +gawk> @kbd{r} @ii{Start the program} +@print{} Starting program: +@print{} Stopping in Rule ... +@print{} Watchpoint 1: $1 @ii{Watchpoint fires} +@print{} Old value: "" +@print{} New value: "abc" +@print{} main() at `test.awk':1 +@print{} 1 @{ print typeof($1), typeof($2) @} +gawk> @kbd{n} @ii{Keep going @dots{}} +@print{} Watchpoint 2: $2 @ii{Watchpoint fires} +@print{} Old value: "" +@print{} New value: "123" +@print{} main() at `test.awk':1 +@print{} 1 @{ print typeof($1), typeof($2) @} +gawk> @kbd{n} @ii{Get result from} typeof() +@print{} strnum number @ii{Result for} $2 @ii{isn't right} +@print{} Program exited normally with exit value: 0 +gawk> @kbd{quit} +@end example + +In this case, the act of comparing the new value of @code{$2} +with the old one caused @command{gawk} to evaluate it and determine that it +is indeed a number, and this is reflected in the result of +@code{typeof()}. + +Cases like this where the debugger is not transparent to the program's +execution should be rare. If you encounter one, please report it +(@pxref{Bugs}). + @ignore Look forward to a future release when these and other missing features may be added, and of course feel free to try to add them yourself! @@ -29337,6 +29772,10 @@ If the GNU Readline library is available when @command{gawk} is compiled, it is used by the debugger to provide command-line history and editing. +@item +Usually, the debugger does not not affect the +program being debugged, but occasionally it can. + @end itemize @node Arbitrary Precision Arithmetic @@ -30154,6 +30593,122 @@ to just use the following: gawk -M 'BEGIN @{ n = 13; print n % 2 @}' @end example +When dividing two arbitrary precision integers with either +@samp{/} or @samp{%}, the result is typically an arbitrary +precision floating point value (unless the denominator evenly +divides into the numerator). In order to do integer division +or remainder with arbitrary precision integers, use the built-in +@code{intdiv()} function (@pxref{Numeric Functions}). + +You can simulate the @code{intdiv()} function in standard @command{awk} +using this user-defined function: + +@example +@c file eg/lib/intdiv.awk +# intdiv --- do integer division + +@c endfile +@ignore +@c file eg/lib/intdiv.awk +# +# Arnold Robbins, arnold@@skeeve.com, Public Domain +# July, 2014 +# +# Name changed from div() to intdiv() +# April, 2015 + +@c endfile + +@end ignore +@c file eg/lib/intdiv.awk +function intdiv(numerator, denominator, result) +@{ + split("", result) + + numerator = int(numerator) + denominator = int(denominator) + result["quotient"] = int(numerator / denominator) + result["remainder"] = int(numerator % denominator) + + return 0.0 +@} +@c endfile +@end example + +The following example program, contributed by Katie Wasserman, +uses @code{intdiv()} to +compute the digits of @value{PI} to as many places as you +choose to set: + +@example +@c file eg/prog/pi.awk +# pi.awk --- compute the digits of pi +@c endfile +@c endfile +@ignore +@c file eg/prog/pi.awk +# +# Katie Wasserman, katie@@wass.net +# August 2014 +@c endfile +@end ignore +@c file eg/prog/pi.awk + +BEGIN @{ + digits = 100000 + two = 2 * 10 ^ digits + pi = two + for (m = digits * 4; m > 0; --m) @{ + d = m * 2 + 1 + x = pi * m + intdiv(x, d, result) + pi = result["quotient"] + pi = pi + two + @} + print pi +@} +@c endfile +@end example + +@ignore +Date: Wed, 20 Aug 2014 10:19:11 -0400 +To: arnold@skeeve.com +From: Katherine Wasserman <katie@wass.net> +Subject: Re: computation of digits of pi? + +Arnold, + +>The program that you sent to compute the digits of pi using div(). Is +>that some standard algorithm that every math student knows? If so, +>what's it called? + +It's not that well known but it's not that obscure either + +It's Euler's modification to Newton's method for calculating pi. + +Take a look at lines (23) - (25) here: http://mathworld.wolfram.com/PiFormulas.htm + +The algorithm I wrote simply expands the multiply by 2 and works from the innermost expression outwards. I used this to program HP calculators because it's quite easy to modify for tiny memory devices with smallish word sizes. + +http://www.hpmuseum.org/cgi-sys/cgiwrap/hpmuseum/articles.cgi?read=899 + +-Katie +@end ignore + +When asked about the algorithm used, Katie replied: + +@quotation +It's not that well known but it's not that obscure either. +It's Euler's modification to Newton's method for calculating pi. +Take a look at lines (23) - (25) here: @uref{http://mathworld.wolfram.com/PiFormulas.html}. + +The algorithm I wrote simply expands the multiply by 2 and works from +the innermost expression outwards. I used this to program HP calculators +because it's quite easy to modify for tiny memory devices with smallish +word sizes. See +@uref{http://www.hpmuseum.org/cgi-sys/cgiwrap/hpmuseum/articles.cgi?read=899}. +@end quotation + @node POSIX Floating Point Problems @section Standards Versus Existing Practice @@ -30553,6 +31108,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 @@ -30628,6 +31184,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: @@ -31016,7 +31576,7 @@ Extension functions are described by the following record: typedef struct awk_ext_func @{ @ @ @ @ const char *name; @ @ @ @ awk_value_t *(*function)(int num_actual_args, awk_value_t *result); -@ @ @ @ size_t num_expected_args; +@ @ @ @ size_t max_expected_args; @} awk_ext_func_t; @end example @@ -31048,11 +31608,17 @@ actual parameters were passed from the calling @command{awk} code. The function must return the value of @code{result}. This is for the convenience of the calling code inside @command{gawk}. -@item size_t num_expected_args; -This is the number of arguments the function expects to receive. +@item size_t max_expected_args; +This is the maximum number of arguments the function expects to receive. Each extension function may decide what to do if the number of arguments isn't what it expected. As with real @command{awk} functions, it -is likely OK to ignore extra arguments. +is likely OK to ignore extra arguments. This value does not affect +actual program execution. + +Extension functions should compare this value to the number of actual +arguments passed and possibly issue a lint warning if there is an +undesirable mismatch. Of course, if +@samp{--lint=fatal} is used, this would cause the program to exit. @end table Once you have a record representing your extension function, you register @@ -31555,6 +32121,9 @@ that parameter. More's the pity.} @item void fatal(awk_ext_id_t id, const char *format, ...); Print a message and then cause @command{gawk} to exit immediately. +@item void nonfatal(awk_ext_id_t id, const char *format, ...); +Print a nonfatal error message. + @item void warning(awk_ext_id_t id, const char *format, ...); Print a warning message. @@ -32598,6 +33167,75 @@ $ @kbd{AWKLIBPATH=$PWD ./gawk -f subarray.awk} (@xref{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 @code{NULL} or @code{name_len} is zero, return +data for the currently open input file corresponding to @code{FILENAME}. +(This does not access the @code{filetype} argument, so that may be undefined). +If the file is not already open, attempt to open it. +The @code{filetype} argument must be zero-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, return a @code{false} value. Otherwise, return +@code{true}, and return additional information about the redirection +in the @code{ibufp} and @code{obufp} pointers. For input +redirections, the @code{*ibufp} value should be non-@code{NULL}, +and @code{*obufp} should be @code{NULL}. For output redirections, +the @code{*obufp} value should be non-@code{NULL}, and @code{*ibufp} +should be @code{NULL}. For two-way coprocesses, both values should +be non-@code{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 @code{fd} argument is non-negative, @command{gawk} +will use that file descriptor instead of opening the file in the +usual way. If @code{fd} is non-negative, but the file exists already, +@command{gawk} ignores @code{fd} and returns the existing file. It is +the caller's responsibility to notice that neither the @code{fd} in +the returned @code{awk_input_buf_t} nor the @code{fd} in the returned +@code{awk_output_buf_t} matches the requested value. + +Note that supplying a file descriptor is currently @emph{not} supported +for pipes. However, supplying a file descriptor should work for input, +output, append, and two-way (coprocess) sockets. If @code{filetype} +is two-way, @command{gawk} assumes that it is a socket! Note that in +the two-way case, the input and output file descriptors may differ. +To check for success, you 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 @@ -34165,18 +34803,21 @@ As of this writing, there are seven extensions: GD graphics library extension @item +MPFR library extension +(this provides access to a number of MPFR functions that @command{gawk}'s +native MPFR support does not) + +@item PDF extension @item PostgreSQL extension @item -MPFR library extension -(this provides access to a number of MPFR functions that @command{gawk}'s -native MPFR support does not) +Redis extension @item -Redis extension +Select extension @item XML parser extension, using the @uref{http://expat.sourceforge.net, Expat} @@ -34276,7 +34917,7 @@ output wrappers, and two-way processors) @item -Printing fatal, warning, and ``lint'' warning messages +Printing fatal, nonfatal, warning, and ``lint'' warning messages @item Updating @code{ERRNO}, or unsetting it @@ -34805,6 +35446,10 @@ Indirect function calls @item Directories on the command line produce a warning and are skipped (@pxref{Command-line directories}) + +@item +Output with @code{print} and @code{printf} need not be fatal +(@pxref{Nonfatal}) @end itemize @item @@ -34892,6 +35537,11 @@ The @code{isarray()} function to check if a variable is an array or not The @code{bindtextdomain()}, @code{dcgettext()}, and @code{dcngettext()} functions for internationalization (@pxref{Programmer i18n}) + +@item +The @code{intdiv()} function for doing integer +division and remainder +(@pxref{Numeric Functions}) @end itemize @item @@ -34930,6 +35580,7 @@ The @option{-p}, @option{-P}, @option{-r}, +@option{-s}, @option{-S}, @option{-t}, and @@ -34954,6 +35605,7 @@ and the @option{--load}, @option{--non-decimal-data}, @option{--optimize}, +@option{--no-optimize}, @option{--posix}, @option{--pretty-print}, @option{--profile}, @@ -35024,6 +35676,16 @@ for @command{gawk} @value{PVERSION} 4.1: Ultrix @end itemize +@item +Support for the following systems was removed from the code +for @command{gawk} @value{PVERSION} 4.2: + +@c nested table +@itemize @value{MINUS} +@item +MirBSD +@end itemize + @end itemize @c XXX ADD MORE STUFF HERE @@ -35650,6 +36312,52 @@ Support for Ultrix was removed. @end itemize +Version 4.2 introduced the following changes: + +@itemize @bullet +@item +Changes to @code{ENVIRON} are reflected into @command{gawk}'s +environment and that of programs that it runs. +@xref{Auto-set}. + +@item +The @option{--pretty-print} option no longer runs the @command{awk} +program too. +@xref{Options}. + +@item +The @command{igawk} program and its manual page are no longer +installed when @command{gawk} is built. +@xref{Igawk Program}. + +@item +The @code{intdiv()} function. +@xref{Numeric Functions}. + +@item +The maximum number of hexadecimal digits in @samp{\x} escapes +is now two. +@xref{Escape Sequences}. + +@item +Nonfatal output with @code{print} and @code{printf}. +@xref{Nonfatal}. + +@item +For many years, POSIX specified that default field splitting +only allowed spaces and tabs to separate fields, and this was +how @command{gawk} behaved with @option{--posix}. As of 2013, +the standard restored historical behavior, and now default +field splitting with @option{--posix} also allows newlines to +separate fields. + +@item +Support for MirBSD was removed. + +@item +Support for GNU/Linux on Alpha was removed. +@end itemize + @c XXX ADD MORE STUFF HERE @end ifclear @@ -36317,6 +37025,8 @@ The generated Info file for The @command{troff} source for a manual page describing the @command{igawk} program presented in @ref{Igawk Program}. +(Since @command{gawk} can do its own @code{@@include} processing, +neither @command{igawk} nor @file{igawk.1} are installed.) @item doc/Makefile.in The input file used during the configuration process to generate the @@ -36361,8 +37071,6 @@ source file for this @value{DOCUMENT}. It also contains a @file{Makefile.in} fil @file{Makefile.am} is used by GNU Automake to create @file{Makefile.in}. The library functions from @ref{Library Functions}, -and the @command{igawk} program from -@ref{Igawk Program} are included as ready-to-use files in the @command{gawk} distribution. They are installed as part of the installation process. The rest of the programs in this @value{DOCUMENT} are available in appropriate @@ -36373,6 +37081,12 @@ The source code, manual pages, and infrastructure files for the sample extensions included with @command{gawk}. @xref{Dynamic Extensions}, for more information. +@item extras/* +Additional non-essential files. Currently, this directory contains some shell +startup files to be installed in @file{/etc/profile.d} to aid in manipulating +the @env{AWKPATH} and @env{AWKLIBPATH} environment variables. +@xref{Shell Startup Files}, for more information. + @item posix/* Files needed for building @command{gawk} on POSIX-compliant systems. @@ -36404,6 +37118,7 @@ to configure @command{gawk} for your system yourself. @menu * Quick Installation:: Compiling @command{gawk} under Unix. +* Shell Startup Files:: Shell convenience functions. * Additional Configuration Options:: Other compile-time options. * Configuration Philosophy:: How it's all supposed to work. @end menu @@ -36484,6 +37199,44 @@ is likely that you will be asked for your password, and you will have to have been set up previously as a user who is allowed to run the @command{sudo} command. +@node Shell Startup Files +@appendixsubsec Shell Startup Files + +The distribution contains shell startup files @file{gawk.sh} and +@file{gawk.csh} containing functions to aid in manipulating +the @env{AWKPATH} and @env{AWKLIBPATH} environment variables. +On a Fedora system, these files should be installed in @file{/etc/profile.d}; +on other platforms, the appropriate location may be different. + +@table @command + +@cindex @command{gawkpath_default} shell function +@item gawkpath_default +Reset the @env{AWKPATH} environment variable to its default value. + +@cindex @command{gawkpath_prepend} shell function +@item gawkpath_prepend +Add the argument to the front of the @env{AWKPATH} environment variable. + +@cindex @command{gawkpath_append} shell function +@item gawkpath_append +Add the argument to the end of the @env{AWKPATH} environment variable. + +@cindex @command{gawklibpath_default} shell function +@item gawklibpath_default +Reset the @env{AWKLIBPATH} environment variable to its default value. + +@cindex @command{gawklibpath_prepend} shell function +@item gawklibpath_prepend +Add the argument to the front of the @env{AWKLIBPATH} environment variable. + +@cindex @command{gawklibpath_append} shell function +@item gawklibpath_append +Add the argument to the end of the @env{AWKLIBPATH} environment variable. + +@end table + + @node Additional Configuration Options @appendixsubsec Additional Configuration Options @cindex @command{gawk}, configuring, options @@ -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); @@ -235,13 +234,13 @@ static const char *const nodetypes[] = { "Node_val", "Node_regex", "Node_dynregex", + "Node_typedregex", "Node_var", "Node_var_array", "Node_var_new", "Node_param_list", "Node_func", "Node_ext_func", - "Node_old_ext_func", "Node_builtin_func", "Node_array_ref", "Node_array_tree", @@ -332,12 +331,12 @@ static struct optypetab { { "Op_builtin", NULL }, { "Op_sub_builtin", NULL }, { "Op_ext_builtin", NULL }, - { "Op_old_ext_builtin", NULL }, /* temporary */ { "Op_in_array", " in " }, { "Op_func_call", NULL }, { "Op_indirect_func_call", NULL }, { "Op_push", NULL }, { "Op_push_arg", NULL }, + { "Op_push_arg_untyped", NULL }, { "Op_push_i", NULL }, { "Op_push_re", NULL }, { "Op_push_array", NULL }, @@ -362,6 +361,7 @@ static struct optypetab { { "Op_after_beginfile", NULL }, { "Op_after_endfile", NULL }, { "Op_func", NULL }, + { "Op_comment", NULL }, { "Op_exec_count", NULL }, { "Op_breakpoint", NULL }, { "Op_lint", NULL }, @@ -582,14 +582,8 @@ cmp_nodes(NODE *t1, NODE *t2) if (t1 == t2) return 0; - if ((t1->flags & MAYBE_NUM) != 0) - (void) force_number(t1); - if ((t2->flags & MAYBE_NUM) != 0) - (void) force_number(t2); - if ((t1->flags & INTIND) != 0) - t1 = force_string(t1); - if ((t2->flags & INTIND) != 0) - t2 = force_string(t2); + (void) fixtype(t1); + (void) fixtype(t2); if ((t1->flags & NUMBER) != 0 && (t2->flags & NUMBER) != 0) return cmp_numbers(t1, t2); @@ -698,7 +692,6 @@ void set_IGNORECASE() { static bool warned = false; - NODE *n = IGNORECASE_node->var_value; if ((do_lint || do_traditional) && ! warned) { warned = true; @@ -707,19 +700,8 @@ set_IGNORECASE() load_casetable(); if (do_traditional) IGNORECASE = false; - else if ((n->flags & (NUMCUR|NUMBER)) != 0) - IGNORECASE = ! iszero(n); - else if ((n->flags & (STRING|STRCUR)) != 0) { - if ((n->flags & MAYBE_NUM) == 0) { - (void) force_string(n); - IGNORECASE = (n->stlen > 0); - } else { - (void) force_number(n); - IGNORECASE = ! iszero(n); - } - } else - IGNORECASE = false; /* shouldn't happen */ - + else + IGNORECASE = boolval(IGNORECASE_node->var_value); set_RS(); /* set_RS() calls set_FS() if need be, for us */ } @@ -730,7 +712,7 @@ set_BINMODE() { static bool warned = false; char *p; - NODE *v = BINMODE_node->var_value; + NODE *v = fixtype(BINMODE_node->var_value); if ((do_lint || do_traditional) && ! warned) { warned = true; @@ -739,7 +721,6 @@ set_BINMODE() if (do_traditional) BINMODE = TEXT_TRANSLATE; else if ((v->flags & NUMBER) != 0) { - (void) force_number(v); BINMODE = get_number_si(v); /* Make sure the value is rational. */ if (BINMODE < TEXT_TRANSLATE) @@ -827,9 +808,9 @@ set_OFS() new_ofs_len = OFS_node->var_value->stlen; if (OFS == NULL) - emalloc(OFS, char *, new_ofs_len + 2, "set_OFS"); + emalloc(OFS, char *, new_ofs_len + 1, "set_OFS"); else if (OFSlen < new_ofs_len) - erealloc(OFS, char *, new_ofs_len + 2, "set_OFS"); + erealloc(OFS, char *, new_ofs_len + 1, "set_OFS"); memcpy(OFS, OFS_node->var_value->stptr, OFS_node->var_value->stlen); OFSlen = new_ofs_len; @@ -947,49 +928,30 @@ set_LINT() { #ifndef NO_LINT int old_lint = do_lint; - NODE *n = LINT_node->var_value; - - if ((n->flags & (STRING|STRCUR)) != 0) { - if ((n->flags & MAYBE_NUM) == 0) { - const char *lintval; - size_t lintlen; - - n = force_string(LINT_node->var_value); - lintval = n->stptr; - lintlen = n->stlen; - if (lintlen > 0) { - do_flags |= DO_LINT_ALL; - if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0) - lintfunc = r_fatal; - else if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0) { - do_flags &= ~ DO_LINT_ALL; - do_flags |= DO_LINT_INVALID; - } else - lintfunc = warning; - } else { - do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); - lintfunc = warning; + NODE *n = fixtype(LINT_node->var_value); + + lintfunc = r_warning; /* reset to default */ + if ((n->flags & STRING) != 0) { + const char *lintval; + size_t lintlen; + + lintval = n->stptr; + lintlen = n->stlen; + if (lintlen > 0) { + do_flags |= DO_LINT_ALL; + if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0) + lintfunc = r_fatal; + else if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0) { + do_flags &= ~DO_LINT_ALL; + do_flags |= DO_LINT_INVALID; } } else { - (void) force_number(n); - if (! iszero(n)) - do_flags |= DO_LINT_ALL; - else - do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); - lintfunc = warning; - } - } else if ((n->flags & (NUMCUR|NUMBER)) != 0) { - (void) force_number(n); - if (! iszero(n)) - do_flags |= DO_LINT_ALL; - else do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); - lintfunc = warning; - } else - do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); /* shouldn't happen */ - - if (! do_lint) - lintfunc = warning; + } + } else if (! iszero(n)) + do_flags |= DO_LINT_ALL; + else + do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); /* explicitly use warning() here, in case lintfunc == r_fatal */ if (old_lint != do_lint && old_lint && ! do_lint) @@ -1025,6 +987,7 @@ update_ERRNO_int(int errcode) { char *cp; + update_PROCINFO_num("errno", errcode); if (errcode) { cp = strerror(errcode); cp = gettext(cp); @@ -1039,6 +1002,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)); } @@ -1048,6 +1012,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); } @@ -1189,7 +1154,7 @@ r_get_field(NODE *n, Func_ptr *assign, bool reference) if (assign) *assign = NULL; if (do_lint) { - if ((n->flags & NUMBER) == 0) { + if ((fixtype(n)->flags & NUMBER) == 0) { lintwarn(_("attempt to field reference from non-numeric value")); if (n->stlen == 0) lintwarn(_("attempt to field reference from null string")); @@ -1359,6 +1324,11 @@ setup_frame(INSTRUCTION *pc) r->var_value = m; break; + case Node_typedregex: + r->type = Node_var; + r->var_value = m; + break; + default: cant_happen(); } @@ -1538,15 +1508,7 @@ eval_condition(NODE *t) if (t == node_Boolean[true]) return true; - if ((t->flags & MAYBE_NUM) != 0) - force_number(t); - else if ((t->flags & INTIND) != 0) - force_string(t); - - if ((t->flags & NUMBER) != 0) - return ! iszero(t); - - return (t->stlen != 0); + return boolval(t); } /* cmp_scalars -- compare two nodes on the stack */ @@ -33,9 +33,6 @@ extern SRCFILE *srcfiles; #ifdef DYNAMIC -#define OLD_INIT_FUNC "dlload" -#define OLD_FINI_FUNC "dlunload" - #include <dlfcn.h> /* @@ -92,95 +89,6 @@ load_ext(const char *lib_name) lib_name, INIT_FUNC); } -/* do_ext --- load an extension at run-time: interface to load_ext */ - -NODE * -do_ext(int nargs) -{ - NODE *obj, *init = NULL, *fini = NULL, *ret = NULL; - SRCFILE *s; - char *init_func = NULL; - char *fini_func = NULL; - - if (nargs == 3) { - fini = POP_STRING(); - fini_func = fini->stptr; - } - if (nargs >= 2) { - init = POP_STRING(); - init_func = init->stptr; - } - obj = POP_STRING(); - - s = add_srcfile(SRC_EXTLIB, obj->stptr, srcfiles, NULL, NULL); - if (s != NULL) - ret = load_old_ext(s, init_func, fini_func, obj); - - DEREF(obj); - if (fini != NULL) - DEREF(fini); - if (init != NULL) - DEREF(init); - if (ret == NULL) - ret = dupnode(Nnull_string); - return ret; -} - -/* load_old_ext --- load an external library */ - -NODE * -load_old_ext(SRCFILE *s, const char *init_func, const char *fini_func, NODE *obj) -{ - NODE *(*func)(NODE *, void *); - NODE *tmp; - void *dl; - int flags = RTLD_LAZY; - int *gpl_compat; - const char *lib_name = s->fullpath; - - if (init_func == NULL || init_func[0] == '\0') - init_func = OLD_INIT_FUNC; - - if (fini_func == NULL || fini_func[0] == '\0') - fini_func = OLD_FINI_FUNC; - - if (do_sandbox) - fatal(_("extensions are not allowed in sandbox mode")); - - if (do_traditional || do_posix) - fatal(_("`extension' is a gawk extension")); - - if (lib_name == NULL) - fatal(_("extension: received NULL lib_name")); - - if ((dl = dlopen(lib_name, flags)) == NULL) - fatal(_("extension: cannot open library `%s' (%s)"), lib_name, - dlerror()); - - /* Per the GNU Coding standards */ - gpl_compat = (int *) dlsym(dl, "plugin_is_GPL_compatible"); - if (gpl_compat == NULL) - fatal(_("extension: library `%s': does not define `plugin_is_GPL_compatible' (%s)"), - lib_name, dlerror()); - func = (NODE *(*)(NODE *, void *)) dlsym(dl, init_func); - if (func == NULL) - fatal(_("extension: library `%s': cannot call function `%s' (%s)"), - lib_name, init_func, dlerror()); - - if (obj == NULL) { - obj = make_string(lib_name, strlen(lib_name)); - tmp = (*func)(obj, dl); - unref(tmp); - unref(obj); - tmp = NULL; - } else - tmp = (*func)(obj, dl); - - s->fini_func = (void (*)(void)) dlsym(dl, fini_func); - return tmp; -} - - /* make_builtin --- register name to be called as func with a builtin body */ awk_bool_t @@ -191,7 +99,7 @@ make_builtin(const awk_ext_func_t *funcinfo) const char *sp; char c; const char *name = funcinfo->name; - int count = funcinfo->num_expected_args; + int count = funcinfo->max_expected_args; sp = name; if (sp == NULL || *sp == '\0') @@ -238,75 +146,19 @@ make_builtin(const awk_ext_func_t *funcinfo) return awk_true; } -/* make_old_builtin --- register name to be called as func with a builtin body */ - -void -make_old_builtin(const char *name, NODE *(*func)(int), int count) /* temporary */ -{ - NODE *symbol, *f; - INSTRUCTION *b; - const char *sp; - char c; - - sp = name; - if (sp == NULL || *sp == '\0') - fatal(_("extension: missing function name")); - - if (! is_letter(*sp)) - fatal(_("extension: illegal character `%c' in function name `%s'"), *sp, name); - - for (sp++; (c = *sp++) != '\0';) { - if (! is_identchar(c)) - fatal(_("extension: illegal character `%c' in function name `%s'"), c, name); - } - - f = lookup(name); - - if (f != NULL) { - if (f->type == Node_func) { - /* user-defined function */ - fatal(_("extension: can't redefine function `%s'"), name); - } else if (f->type == Node_ext_func) { - /* multiple extension() calls etc. */ - if (do_lint) - lintwarn(_("extension: function `%s' already defined"), name); - return; - } else - /* variable name etc. */ - fatal(_("extension: function name `%s' previously defined"), name); - } else if (check_special(name) >= 0) - fatal(_("extension: can't use gawk built-in `%s' as function name"), name); - - if (count < 0) - fatal(_("make_builtin: negative argument count for function `%s'"), - name); - - b = bcalloc(Op_symbol, 1, 0); - b->builtin = func; - b->expr_count = count; - - /* NB: extension sub must return something */ - - symbol = install_symbol(estrdup(name, strlen(name)), Node_old_ext_func); - symbol->code_ptr = b; - track_ext_func(name); -} - - /* get_argument --- get the i'th argument of a dynamically linked function */ NODE * get_argument(int i) { NODE *t; - int arg_count, pcount; + int arg_count; INSTRUCTION *pc; pc = TOP()->code_ptr; /* Op_ext_builtin instruction */ - pcount = (pc + 1)->expr_count; /* max # of arguments */ arg_count = pc->expr_count; /* # of arguments supplied */ - if (i < 0 || i >= pcount || i >= arg_count) + if (i < 0 || i >= arg_count) return NULL; t = PEEK(arg_count - i); diff --git a/extension/CMakeLists.txt b/extension/CMakeLists.txt new file mode 100644 index 00000000..1bb4ceb1 --- /dev/null +++ b/extension/CMakeLists.txt @@ -0,0 +1,84 @@ +# +# extension/CMakeLists.txt --- CMake input file for gawk +# +# Copyright (C) 2013 +# the Free Software Foundation, Inc. +# +# This file is part of GAWK, the GNU implementation of the +# AWK Programming Language. +# +# GAWK is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GAWK is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# + +## process this file with CMake to produce Makefile + +# Remove the definition of GAWK because of gawkapi.h. +remove_definitions(-DGAWK) + +MACRO(BuildExtension name sources) + add_library (${name} MODULE ${sources} ${ARGN}) + target_link_libraries(${name} ${EXTRA_LIBS}) + set_target_properties(${name} PROPERTIES PREFIX "") + install(PROGRAMS ${CMAKE_BINARY_DIR}/extension/${name}${CMAKE_SHARED_LIBRARY_SUFFIX} DESTINATION lib) +ENDMACRO(BuildExtension) + +if (${HAVE_STRUCT_STAT_ST_BLKSIZE}) + BuildExtension(filefuncs filefuncs.c stack.c gawkfts.c) +else() + message(STATUS "extension filefuncs cannot be built because HAVE_STRUCT_STAT_ST_BLKSIZE is missing") +endif() + +if (HAVE_FNMATCH AND HAVE_FNMATCH_H) + BuildExtension(fnmatch fnmatch.c) +else() + message(STATUS "extension fnmatch cannot be built because function fnmatch or fnmatch.h is missing") +endif() + +if (${HAVE_SYS_WAIT_H}) + BuildExtension(fork fork.c) +else() + message(STATUS "extension fork cannot be built because HAVE_SYS_WAIT_H is missing") +endif() + +if (${HAVE_MKSTEMP}) + BuildExtension(inplace inplace.c) +else() + message(STATUS "extension inplace cannot be built because HAVE_MKSTEMP is missing") +endif() + +BuildExtension(ordchr ordchr.c) + +if (HAVE_DIRENT_H AND HAVE_DIRFD) + BuildExtension(readdir readdir.c) +else() + message(STATUS "extension readdir cannot be built because function readdir is missing") +endif() + +BuildExtension(readfile readfile.c) + +BuildExtension(revoutput revoutput.c) + +if (${HAVE_GETDTABLESIZE}) + BuildExtension(revtwoway revtwoway.c) +else() + message(STATUS "extension revtwoway cannot be built because function getdtablesize is missing") +endif() + +BuildExtension(rwarray rwarray.c) + +BuildExtension(time time.c) + +BuildExtension(testext testext.c) + diff --git a/extension/ChangeLog b/extension/ChangeLog index 71af2159..b7668fc7 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -7,6 +7,11 @@ where configure didn't work correctly. Thanks to Nelson Beebe. Update copyright year. +2016-05-26 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * filefuncs.c (func_table): Update "stat" to indicate that the + max # of expected args is 3, not 2. + 2016-01-27 Arnold D. Robbins <arnold@skeeve.com> * filefuncs.c (do_statvfs): Define out f_fsid on AIX. @@ -77,11 +82,19 @@ * 4.1.2: Release tar ball made. +2015-04-16 Arnold D. Robbins <arnold@skeeve.com> + + * configure.ac: Updated by autoupdate. + 2015-04-08 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am, filefuncs.c, inplace.3am, inplace.c: Update copyright years. +2015-03-27 Arnold D. Robbins <arnold@skeeve.com> + + * testext.c: Move test for deferred variables here. + 2015-03-18 Arnold D. Robbins <arnold@skeeve.com> * configure: Updated to libtool 2.4.6. @@ -118,11 +131,86 @@ * 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-12-14 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * readfile.c (read_file_to_buffer): Do not waste a byte at the end of + a string. + * rwarray.c (read_value): Ditto. + * rwarray0.c (read_value): Ditto. + 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 @@ -294,6 +382,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/configure.ac b/extension/configure.ac index a2191d33..b723a3c1 100644 --- a/extension/configure.ac +++ b/extension/configure.ac @@ -23,7 +23,7 @@ dnl dnl Process this file with autoconf to produce a configure script. -AC_INIT([GNU Awk Bundled Extensions], 4.1.3, bug-gawk@gnu.org, gawk-extensions) +AC_INIT([GNU Awk Bundled Extensions],[4.1.3],[bug-gawk@gnu.org],[gawk-extensions]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) @@ -42,7 +42,7 @@ AC_CHECK_MEMBERS([struct stat.st_blksize]) AM_PROG_AR AC_SYS_LARGEFILE AC_DISABLE_STATIC -AC_PROG_LIBTOOL +LT_INIT dnl AC_PROG_INSTALL AC_SUBST([pkgextensiondir], ['${libdir}/gawk']) diff --git a/extension/filefuncs.c b/extension/filefuncs.c index b33fcf1f..00387cf9 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -929,7 +929,7 @@ out: static awk_ext_func_t func_table[] = { { "chdir", do_chdir, 1 }, - { "stat", do_stat, 2 }, + { "stat", do_stat, 3 }, #ifndef __MINGW32__ { "fts", do_fts, 3 }, #endif diff --git a/extension/readfile.c b/extension/readfile.c index d4b4aef9..7673589f 100644 --- a/extension/readfile.c +++ b/extension/readfile.c @@ -82,8 +82,8 @@ read_file_to_buffer(int fd, const struct stat *sbuf) goto done; } - emalloc(text, char *, sbuf->st_size + 2, "do_readfile"); - memset(text, '\0', sbuf->st_size + 2); + emalloc(text, char *, sbuf->st_size + 1, "do_readfile"); + memset(text, '\0', sbuf->st_size + 1); if ((ret = read(fd, text, sbuf->st_size)) != sbuf->st_size) { update_ERRNO_int(errno); diff --git a/extension/rwarray.c b/extension/rwarray.c index 155cc47c..e751ea2c 100644 --- a/extension/rwarray.c +++ b/extension/rwarray.c @@ -457,8 +457,8 @@ read_value(FILE *fp, awk_value_t *value) len = ntohl(len); value->val_type = AWK_STRING; value->str_value.len = len; - value->str_value.str = gawk_malloc(len + 2); - memset(value->str_value.str, '\0', len + 2); + value->str_value.str = gawk_malloc(len + 1); + memset(value->str_value.str, '\0', len + 1); if (fread(value->str_value.str, 1, len, fp) != (ssize_t) len) { gawk_free(value->str_value.str); diff --git a/extension/rwarray0.c b/extension/rwarray0.c index e2de3cf5..ec3663cc 100644 --- a/extension/rwarray0.c +++ b/extension/rwarray0.c @@ -452,8 +452,8 @@ read_value(int fd, awk_value_t *value) len = ntohl(len); value->val_type = AWK_STRING; value->str_value.len = len; - value->str_value.str = malloc(len + 2); - memset(value->str_value.str, '\0', len + 2); + value->str_value.str = malloc(len + 1); + memset(value->str_value.str, '\0', len + 1); if (read(fd, value->str_value.str, len) != (ssize_t) len) { free(value->str_value.str); diff --git a/extension/testext.c b/extension/testext.c index 4a1e7032..e2ddbe87 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" @@ -374,6 +375,84 @@ out: } /* + * 3/2015: This test is no longer strictly necessary, + * since PROCINFO is no longer a deferred variable. + * But we leave it in for safety, anyway. + */ +/* +BEGIN { + print "test_deferred returns", test_deferred() + print "" +} +*/ +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++) test_array[i] = i + 2 @@ -710,6 +789,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 +822,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 +1027,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 +1036,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 +1048,10 @@ static awk_bool_t init_testext(void) static const char message[] = "hello, world"; /* of course */ static const char message2[] = "i am a scalar"; + /* This is used by the getfile test */ + if (sym_lookup("TESTEXT_QUIET", AWK_NUMBER, & value)) + return awk_true; + /* add at_exit functions */ awk_atexit(at_exit0, NULL); awk_atexit(at_exit1, & data_for_1); diff --git a/extras/ChangeLog b/extras/ChangeLog new file mode 100644 index 00000000..5f7d33ad --- /dev/null +++ b/extras/ChangeLog @@ -0,0 +1,3 @@ +2014-10-29 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * Makefile.am, gawk.sh, gawk.csh: New files. diff --git a/extras/Makefile.am b/extras/Makefile.am new file mode 100644 index 00000000..6a33ae04 --- /dev/null +++ b/extras/Makefile.am @@ -0,0 +1,29 @@ +# +# extras/Makefile.am --- automake input file for gawk +# +# Copyright (C) 2014 the Free Software Foundation, Inc. +# +# This file is part of GAWK, the GNU implementation of the +# AWK Programming Language. +# +# GAWK is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GAWK is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# + +## Process this file with automake to produce Makefile.in. + +profiledir = $(sysconfdir)/profile.d +profile_DATA = gawk.sh gawk.csh + +EXTRA_DIST = $(profile_DATA) diff --git a/extras/Makefile.in b/extras/Makefile.in new file mode 100644 index 00000000..befba005 --- /dev/null +++ b/extras/Makefile.in @@ -0,0 +1,528 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# extras/Makefile.am --- automake input file for gawk +# +# Copyright (C) 2014 the Free Software Foundation, Inc. +# +# This file is part of GAWK, the GNU implementation of the +# AWK Programming Language. +# +# GAWK is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GAWK is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = extras +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/arch.m4 \ + $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/mpfr.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/noreturn.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \ + $(top_srcdir)/m4/socket.m4 $(top_srcdir)/m4/ulonglong.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(profiledir)" +DATA = $(profile_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/mkinstalldirs \ + ChangeLog +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GAWKLIBEXT = @GAWKLIBEXT@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +HAVE_LIBSIGSEGV = @HAVE_LIBSIGSEGV@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMPFR = @LIBMPFR@ +LIBOBJS = @LIBOBJS@ +LIBREADLINE = @LIBREADLINE@ +LIBS = @LIBS@ +LIBSIGSEGV = @LIBSIGSEGV@ +LIBSIGSEGV_PREFIX = @LIBSIGSEGV_PREFIX@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBSIGSEGV = @LTLIBSIGSEGV@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +acl_shlibext = @acl_shlibext@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgextensiondir = @pkgextensiondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +profiledir = $(sysconfdir)/profile.d +profile_DATA = gawk.sh gawk.csh +EXTRA_DIST = $(profile_DATA) +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu extras/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu extras/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-profileDATA: $(profile_DATA) + @$(NORMAL_INSTALL) + @list='$(profile_DATA)'; test -n "$(profiledir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(profiledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(profiledir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(profiledir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(profiledir)" || exit $$?; \ + done + +uninstall-profileDATA: + @$(NORMAL_UNINSTALL) + @list='$(profile_DATA)'; test -n "$(profiledir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(profiledir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(profiledir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-profileDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-profileDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-profileDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags-am uninstall uninstall-am \ + uninstall-profileDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/extras/gawk.csh b/extras/gawk.csh new file mode 100644 index 00000000..583d5bcd --- /dev/null +++ b/extras/gawk.csh @@ -0,0 +1,11 @@ +alias gawkpath_default 'unsetenv AWKPATH; setenv AWKPATH `gawk -v x=AWKPATH "BEGIN {print ENVIRON[x]}"`' + +alias gawkpath_prepend 'if (! $?AWKPATH) setenv AWKPATH ""; if ($AWKPATH == "") then; unsetenv AWKPATH; setenv AWKPATH `gawk -v x=AWKPATH "BEGIN {print ENVIRON[x]}"`; endif; setenv AWKPATH "\!*"":$AWKPATH"' + +alias gawkpath_append 'if (! $?AWKPATH) setenv AWKPATH ""; if ($AWKPATH == "") then; unsetenv AWKPATH; setenv AWKPATH `gawk -v x=AWKPATH "BEGIN {print ENVIRON[x]}"`; endif; setenv AWKPATH "$AWKPATH"":\!*"' + +alias gawklibpath_default 'unsetenv AWKLIBPATH; setenv AWKLIBPATH `gawk -v x=AWKLIBPATH "BEGIN {print ENVIRON[x]}"`' + +alias gawklibpath_prepend 'if (! $?AWKLIBPATH) setenv AWKLIBPATH ""; if ($AWKLIBPATH == "") then; unsetenv AWKLIBPATH; setenv AWKLIBPATH `gawk -v x=AWKLIBPATH "BEGIN {print ENVIRON[x]}"`; endif; setenv AWKLIBPATH "\!*"":$AWKLIBPATH"' + +alias gawklibpath_append 'if (! $?AWKLIBPATH) setenv AWKLIBPATH ""; if ($AWKLIBPATH == "") then; unsetenv AWKLIBPATH; setenv AWKLIBPATH `gawk -v x=AWKLIBPATH "BEGIN {print ENVIRON[x]}"`; endif; setenv AWKLIBPATH "$AWKLIBPATH"":\!*"' diff --git a/extras/gawk.sh b/extras/gawk.sh new file mode 100644 index 00000000..c35471fa --- /dev/null +++ b/extras/gawk.sh @@ -0,0 +1,31 @@ +gawkpath_default () { + unset AWKPATH + export AWKPATH=`gawk 'BEGIN {print ENVIRON["AWKPATH"]}'` +} + +gawkpath_prepend () { + [ -z "$AWKPATH" ] && AWKPATH=`gawk 'BEGIN {print ENVIRON["AWKPATH"]}'` + export AWKPATH="$*:$AWKPATH" +} + +gawkpath_append () { + [ -z "$AWKPATH" ] && AWKPATH=`gawk 'BEGIN {print ENVIRON["AWKPATH"]}'` + export AWKPATH="$AWKPATH:$*" +} + +gawklibpath_default () { + unset AWKLIBPATH + export AWKLIBPATH=`gawk 'BEGIN {print ENVIRON["AWKLIBPATH"]}'` +} + +gawklibpath_prepend () { + [ -z "$AWKLIBPATH" ] && \ + AWKLIBPATH=`gawk 'BEGIN {print ENVIRON["AWKLIBPATH"]}'` + export AWKLIBPATH="$*:$AWKLIBPATH" +} + +gawklibpath_append () { + [ -z "$AWKLIBPATH" ] && \ + AWKLIBPATH=`gawk 'BEGIN {print ENVIRON["AWKLIBPATH"]}'` + export AWKLIBPATH="$AWKLIBPATH:$*" +} @@ -44,8 +44,6 @@ static long re_parse_field(long, char **, int, NODE *, Regexp *, Setfunc, NODE *, NODE *, bool); static long def_parse_field(long, char **, int, NODE *, Regexp *, Setfunc, NODE *, NODE *, bool); -static long posix_def_parse_field(long, char **, int, NODE *, - Regexp *, Setfunc, NODE *, NODE *, bool); static long null_parse_field(long, char **, int, NODE *, Regexp *, Setfunc, NODE *, NODE *, bool); static long sc_parse_field(long, char **, int, NODE *, @@ -163,7 +161,7 @@ rebuild_record() tlen += (NF - 1) * OFSlen; if ((long) tlen < 0) tlen = 0; - emalloc(ops, char *, tlen + 2, "rebuild_record"); + emalloc(ops, char *, tlen + 1, "rebuild_record"); cops = ops; ops[0] = '\0'; for (i = 1; i <= NF; i++) { @@ -218,7 +216,7 @@ rebuild_record() } } else { *n = *r; - n->flags &= ~(MALLOC|STRING); + n->flags &= ~MALLOC; } n->stptr = cops; @@ -290,7 +288,7 @@ set_record(const char *buf, int cnt) n->stlen = cnt; n->valref = 1; n->type = Node_val; - n->stfmt = -1; + n->stfmt = STFMT_UNUSED; n->flags = (STRING|STRCUR|MAYBE_NUM|FIELD); fields_arr[0] = n; @@ -538,75 +536,6 @@ def_parse_field(long up_to, /* parse only up to this field number */ } /* - * posix_def_parse_field --- default field parsing. - * - * This is called both from get_field() and from do_split() - * via (*parse_field)(). This variation is for when FS is a single space - * character. The only difference between this and def_parse_field() - * is that this one does not allow newlines to separate fields. - */ - -static long -posix_def_parse_field(long up_to, /* parse only up to this field number */ - char **buf, /* on input: string to parse; on output: point to start next */ - int len, - NODE *fs, - Regexp *rp ATTRIBUTE_UNUSED, - Setfunc set, /* routine to set the value of the parsed field */ - NODE *n, - NODE *dummy ATTRIBUTE_UNUSED, /* sep_arr not needed here: hence dummy */ - bool in_middle ATTRIBUTE_UNUSED) -{ - char *scan = *buf; - long nf = parse_high_water; - char *field; - char *end = scan + len; - char sav; - - if (up_to == UNLIMITED) - nf = 0; - if (len == 0) - return nf; - - /* - * Nasty special case. If FS set to "", return whole record - * as first field. This is not worth a separate function. - */ - if (fs->stlen == 0) { - (*set)(++nf, *buf, len, n); - *buf += len; - return nf; - } - - /* before doing anything save the char at *end */ - sav = *end; - /* because it will be destroyed now: */ - - *end = ' '; /* sentinel character */ - for (; nf < up_to; scan++) { - /* - * special case: fs is single space, strip leading whitespace - */ - while (scan < end && (*scan == ' ' || *scan == '\t')) - scan++; - if (scan >= end) - break; - field = scan; - while (*scan != ' ' && *scan != '\t') - scan++; - (*set)(++nf, field, (long)(scan - field), n); - if (scan == end) - break; - } - - /* everything done, restore original char at *end */ - *end = sav; - - *buf = scan; - return nf; -} - -/* * null_parse_field --- each character is a separate field * * This is called both from get_field() and from do_split() @@ -1020,10 +949,7 @@ do_split(int nargs) } } else if (fs->stlen == 1 && (sep->re_flags & CONSTANT) == 0) { if (fs->stptr[0] == ' ') { - if (do_posix) - parseit = posix_def_parse_field; - else - parseit = def_parse_field; + parseit = def_parse_field; } else parseit = sc_parse_field; } else { @@ -1138,7 +1064,7 @@ set_FIELDWIDTHS() FIELDWIDTHS[0] = 0; for (i = 1; ; i++) { unsigned long int tmp; - if (i + 2 >= fw_alloc) { + if (i + 1 >= fw_alloc) { fw_alloc *= 2; erealloc(FIELDWIDTHS, int *, fw_alloc * sizeof(int), "set_FIELDWIDTHS"); } @@ -1278,10 +1204,7 @@ choose_fs_function: } } } else { - if (do_posix) - parse_field = posix_def_parse_field; - else - parse_field = def_parse_field; + parse_field = def_parse_field; if (fs->stlen == 1) { if (fs->stptr[0] == ' ') @@ -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); /* @@ -193,6 +198,20 @@ api_fatal(awk_ext_id_t id, const char *format, ...) va_end(args); } +/* api_nonfatal --- print a non fatal error message */ + +static void +api_nonfatal(awk_ext_id_t id, const char *format, ...) +{ + va_list args; + + (void) id; + + va_start(args, format); + err(false, _("error: "), format, args); + va_end(args); +} + /* api_warning --- print a warning message */ static void @@ -411,24 +430,21 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) val->val_type = AWK_NUMBER; (void) force_number(node); - if ((node->flags & NUMCUR) != 0) { - val->num_value = get_number_d(node); - ret = awk_true; - } + val->num_value = get_number_d(node); + ret = awk_true; break; case AWK_STRING: val->val_type = AWK_STRING; (void) force_string(node); - if ((node->flags & STRCUR) != 0) { - val->str_value.str = node->stptr; - val->str_value.len = node->stlen; - ret = awk_true; - } + val->str_value.str = node->stptr; + val->str_value.len = node->stlen; + ret = awk_true; break; case AWK_SCALAR: + fixtype(node); if ((node->flags & NUMBER) != 0) { val->val_type = AWK_NUMBER; } else if ((node->flags & STRING) != 0) { @@ -440,6 +456,7 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) case AWK_UNDEFINED: /* return true and actual type for request of undefined */ + fixtype(node); if (node == Nnull_string) { val->val_type = AWK_UNDEFINED; ret = awk_true; @@ -668,7 +685,7 @@ api_sym_update_scalar(awk_ext_id_t id, /* make_str_node(s, l, ALREADY_MALLOCED): */ r->numbr = 0; r->flags = (MALLOC|STRING|STRCUR); - r->stfmt = -1; + r->stfmt = STFMT_UNUSED; r->stptr = value->str_value.str; r->stlen = value->str_value.len; return awk_true; @@ -782,7 +799,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) { @@ -790,6 +806,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; } @@ -1033,6 +1052,99 @@ 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) { + INSTRUCTION *pc; + int save_rule; + char *save_source; + + if (nextfile(& curfile, false) <= 0) + return awk_false; + + pc = main_beginfile; + /* save execution state */ + save_rule = currule; + save_source = source; + + for (;;) { + if (pc == NULL) + fatal(_("cannot find end of BEGINFILE rule")); + if (pc->opcode == Op_after_beginfile) + break; + pc = pc->nexti; + } + pc->opcode = Op_stop; + (void) (*interpret)(main_beginfile); + pc->opcode = Op_after_beginfile; + after_beginfile(& curfile); + /* restore execution state */ + currule = save_rule; + source = save_source; + } + *ibufp = &curfile->public; + *obufp = NULL; + + return awk_true; + } + + redirtype = redirect_none; + switch (filetype[0]) { + case '<': + if (filetype[1] == '\0') + redirtype = redirect_input; + break; + case '>': + switch (filetype[1]) { + case '\0': + redirtype = redirect_output; + break; + case '>': + if (filetype[2] == '\0') + redirtype = redirect_append; + break; + } + break; + case '|': + if (filetype[2] == '\0') { + switch (filetype[1]) { + case '>': + redirtype = redirect_pipe; + break; + case '<': + redirtype = redirect_pipein; + break; + case '&': + redirtype = redirect_twoway; + break; + } + } + break; + } + + if (redirtype == redirect_none) { + warning(_("cannot open unrecognized file type `%s' for `%s'"), + filetype, name); + return awk_false; + } + + if ((f = redirect_string(name, namelen, 0, redirtype, &flag, fd, false)) == NULL) + return awk_false; + + *ibufp = f->iop ? & f->iop->public : NULL; + *obufp = f->output.fp ? & f->output : NULL; + return awk_true; +} + /* * Register a version string for this extension with gawk. */ @@ -1118,6 +1230,12 @@ gawk_api_t api_impl = { calloc, realloc, free, + + /* Find/open a file */ + api_get_file, + + /* Print nonfatal error message */ + api_nonfatal, }; /* init_ext_api --- init the extension API */ @@ -261,7 +261,7 @@ typedef struct awk_two_way_processor { } awk_two_way_processor_t; #define gawk_api_major_version 1 -#define gawk_api_minor_version 1 +#define gawk_api_minor_version 2 /* Current version of the API. */ enum { @@ -278,6 +278,12 @@ enum { * The API deals exclusively with regular chars; these strings may * be multibyte encoded in the current locale's encoding and character * set. Gawk will convert internally to wide characters if necessary. + * + * Note that the string may not be terminated with a '\0' character. + * In particular, this happens for field values $n where n > 0 and n < NF, + * since the string points directly into the $0 buffer. All other strings, + * including those created by extensions, should be NUL-terminated. In general + * though, extension code should not assume that the string is NUL-terminated! */ typedef struct awk_string { char *str; /* data */ @@ -374,11 +380,15 @@ typedef struct awk_flat_array { * Each extension function may decide what to do if the number of * arguments isn't what it expected. Following awk functions, it * is likely OK to ignore extra arguments. + + * Note that the 'max_expected_args' value should be used by the + * extension function itself only to trigger a lint warning if more + * arguments are passed to the function. */ typedef struct awk_ext_func { const char *name; awk_value_t *(*function)(int num_actual_args, awk_value_t *result); - size_t num_expected_args; + size_t max_expected_args; } awk_ext_func_t; typedef void *awk_ext_id_t; /* opaque type for extension id */ @@ -507,7 +517,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. @@ -677,6 +687,43 @@ 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); + + /* Print nonfatal error message */ + void (*api_nonfatal)(awk_ext_id_t id, const char *format, ...); + } gawk_api_t; #ifndef GAWK /* these are not for the gawk code itself! */ @@ -698,6 +745,7 @@ typedef struct gawk_api { (api->api_set_argument(ext_id, count, new_array)) #define fatal api->api_fatal +#define nonfatal api->api_nonfatal #define warning api->api_warning #define lintwarn api->api_lintwarn @@ -759,6 +807,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)) @@ -794,7 +845,7 @@ r_make_string(const gawk_api_t *api, /* needed for emalloc */ result->str_value.len = length; if (duplicate) { - emalloc(cp, char *, length + 2, "r_make_string"); + emalloc(cp, char *, length + 1, "r_make_string"); memcpy(cp, string, length); cp[length] = '\0'; result->str_value.str = cp; diff --git a/hardregex.txt b/hardregex.txt new file mode 100644 index 00000000..557548c8 --- /dev/null +++ b/hardregex.txt @@ -0,0 +1,24 @@ +New variable type: "regexp", --> Node_hardregexp. (Need a better name). + +Syntax: @/.../ + +Use: + a = @/.../ # a now has type regexp + a = foo(1, "bar", @/.../) # pass a regex to user defined function + +New function: + t = typeof(exp) # "array", "regexp", "scalar" + # Open: "scalar" vs. "scalar_s" / "scalar_n" + +Obsolete function: + isarray(exp) + +Conversions: + r = @/.../ + s = r "" # what happens? becomes regex string? + s = r + 0 # what happens? treat as numeric 0? + +Why? + Allows passing regexes through user defined functions + Allows passing regexes through indirect funtion calls + In general, this is a gap in the language diff --git a/helpers/ChangeLog b/helpers/ChangeLog index 256ff0be..9802b287 100644 --- a/helpers/ChangeLog +++ b/helpers/ChangeLog @@ -33,6 +33,14 @@ * 4.1.2: Release tar ball made. +2015-04-09 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * testdfa.c (setup_pattern): Rationalize buffer size computations. + +2014-12-18 Arnold D. Robbins <arnold@skeeve.com> + + * testdfa.c (setup_pattern): Do not waste a byte at the end of a string. + 2014-09-04 Arnold D. Robbins <arnold@skeeve.com> * chlistref.awk: New file. Finds @ref{} to non-chapters. diff --git a/helpers/testdfa.c b/helpers/testdfa.c index 1e144bd7..4495e11a 100644 --- a/helpers/testdfa.c +++ b/helpers/testdfa.c @@ -372,10 +372,10 @@ setup_pattern(const char *pattern, size_t *len) { size_t is_multibyte = 0; int c, c2; - size_t buflen = 0; + size_t buflen; mbstate_t mbs; bool has_anchor = false; - char *buf = NULL; + char *buf; char *dest; const char *src, *end; @@ -391,21 +391,12 @@ setup_pattern(const char *pattern, size_t *len) * escaped characters translated, and generate the regex * from that. */ + buf = (char *) malloc(*len + 1); if (buf == NULL) { - buf = (char *) malloc(*len + 2); - if (buf == NULL) { - fprintf(stderr, "%s: malloc failed\n", __func__); - exit(EXIT_FAILURE); - } - buflen = *len; - } else if (*len > buflen) { - buf = (char *) realloc(buf, *len + 2); - if (buf == NULL) { - fprintf(stderr, "%s: realloc failed\n", __func__); - exit(EXIT_FAILURE); - } - buflen = *len; + fprintf(stderr, "%s: malloc failed\n", __func__); + exit(EXIT_FAILURE); } + buflen = *len; dest = buf; while (src < end) { diff --git a/int_array.c b/int_array.c index a8de3d55..e7913dea 100644 --- a/int_array.c +++ b/int_array.c @@ -89,6 +89,25 @@ is_integer(NODE *symbol, NODE *subs) if (subs == Nnull_string || do_mpfr) return NULL; + /* + * Protect against MAYBE_NUM values where the string may not regenerate + * correctly. There could be white space and/or a non-decimal value. + * If stfmt is not STFMT_UNUSED, it means that the string value was + * generated using CONVFMT or OFMT, so there is no info there. + */ + if ((subs->flags & STRCUR) != 0 && subs->stfmt == STFMT_UNUSED) { + char *cp = subs->stptr; + + if ( subs->stlen == 0 + || cp[0] == '0' + || isspace((unsigned char) cp[0]) + || isspace((unsigned char) cp[subs->stlen - 1]) + || ( subs->stlen >= 2 + && (cp[0] == '-' || cp[0] == '+') + && cp[1] == '0')) + return NULL; + } + if ((subs->flags & NUMINT) != 0) return & success_node; @@ -107,49 +126,51 @@ is_integer(NODE *symbol, NODE *subs) * a[-3]=1; print "-3" in a -- true */ - if ((subs->flags & (STRING|STRCUR)) != 0) { - char *cp = subs->stptr, *cpend, *ptr; - char save; - size_t len = subs->stlen; - - if (len == 0 || (! isdigit((unsigned char) *cp) && *cp != '-')) - return NULL; - if (len > 1 && - ((*cp == '0') /* "00", "011" .. */ - || (*cp == '-' && *(cp + 1) == '0') /* "-0", "-011" .. */ - ) - ) - return NULL; - if (len == 1 && *cp != '-') { /* single digit */ - subs->numbr = (long) (*cp - '0'); - if ((subs->flags & MAYBE_NUM) != 0) { - subs->flags &= ~MAYBE_NUM; - subs->flags |= NUMBER; - } - subs->flags |= (NUMCUR|NUMINT); - return & success_node; - } + /* must be a STRING */ + char *cp = subs->stptr, *cpend, *ptr; + char save; + size_t len = subs->stlen; - cpend = cp + len; - save = *cpend; - *cpend = '\0'; + if (len == 0 || (! isdigit((unsigned char) *cp) && *cp != '-')) + return NULL; - errno = 0; - l = strtol(cp, & ptr, 10); - *cpend = save; - if (errno != 0 || ptr != cpend) - return NULL; - subs->numbr = l; + if (len > 1 && + ((*cp == '0') /* "00", "011" .. */ + || (*cp == '-' && *(cp + 1) == '0') /* "-0", "-011" .. */ + ) + ) + return NULL; + if (len == 1 && *cp != '-') { /* single digit */ + subs->numbr = (long) (*cp - '0'); if ((subs->flags & MAYBE_NUM) != 0) { - subs->flags &= ~MAYBE_NUM; + subs->flags &= ~(MAYBE_NUM|STRING); subs->flags |= NUMBER; } - subs->flags |= NUMCUR; - if (l <= INT32_MAX && l >= INT32_MIN) { - subs->flags |= NUMINT; - return & success_node; - } + subs->flags |= (NUMCUR|NUMINT); + return & success_node; + } + + cpend = cp + len; + save = *cpend; + *cpend = '\0'; + + errno = 0; + l = strtol(cp, & ptr, 10); + *cpend = save; + if (errno != 0 || ptr != cpend) + return NULL; + + subs->numbr = l; + if ((subs->flags & MAYBE_NUM) != 0) { + subs->flags &= ~(MAYBE_NUM|STRING); + subs->flags |= NUMBER; } + subs->flags |= NUMCUR; + if (l <= INT32_MAX && l >= INT32_MIN) { + subs->flags |= NUMINT; + return & success_node; + } + return NULL; } diff --git a/interpret.h b/interpret.h index e9abdffb..3bb4532e 100644 --- a/interpret.h +++ b/interpret.h @@ -144,6 +144,7 @@ top: case Op_push: case Op_push_arg: + case Op_push_arg_untyped: { NODE *save_symbol; bool isparam = false; @@ -175,19 +176,23 @@ top: case Node_var_new: uninitialized_scalar: - m->type = Node_var; - m->var_value = dupnode(Nnull_string); + if (op != Op_push_arg_untyped) { + /* convert untyped to scalar */ + m->type = Node_var; + m->var_value = dupnode(Nnull_string); + } if (do_lint) lintwarn(isparam ? _("reference to uninitialized argument `%s'") : _("reference to uninitialized variable `%s'"), save_symbol->vname); - m = dupnode(Nnull_string); + if (op != Op_push_arg_untyped) + m = dupnode(Nnull_string); PUSH(m); break; case Node_var_array: - if (op == Op_push_arg) + if (op == Op_push_arg || op == Op_push_arg_untyped) PUSH(m); else fatal(_("attempt to use array `%s' in a scalar context"), @@ -263,7 +268,7 @@ uninitialized_scalar: r = r->var_value; } - if (r->type == Node_val) + if (r->type == Node_val || r->type == Node_typedregex) UPREF(r); PUSH(r); break; @@ -709,7 +714,7 @@ mod: if (t1 != t2 && t1->valref == 1 && (t1->flags & MPFN) == 0) { size_t nlen = t1->stlen + t2->stlen; - erealloc(t1->stptr, char *, nlen + 2, "r_interpret"); + erealloc(t1->stptr, char *, nlen + 1, "r_interpret"); memcpy(t1->stptr + t1->stlen, t2->stptr, t2->stlen); t1->stlen = nlen; t1->stptr[nlen] = '\0'; @@ -719,7 +724,7 @@ mod: size_t wlen = t1->wstlen + t2->wstlen; erealloc(t1->wstptr, wchar_t *, - sizeof(wchar_t) * (wlen + 2), "r_interpret"); + sizeof(wchar_t) * (wlen + 1), "r_interpret"); memcpy(t1->wstptr + t1->wstlen, t2->wstptr, t2->wstlen); t1->wstlen = wlen; t1->wstptr[wlen] = L'\0'; @@ -730,9 +735,10 @@ mod: size_t nlen = t1->stlen + t2->stlen; char *p; - emalloc(p, char *, nlen + 2, "r_interpret"); + emalloc(p, char *, nlen + 1, "r_interpret"); memcpy(p, t1->stptr, t1->stlen); memcpy(p + t1->stlen, t2->stptr, t2->stlen); + /* N.B. No NUL-termination required, since make_str_node will do it. */ unref(*lhs); t1 = *lhs = make_str_node(p, nlen, ALREADY_MALLOCED); } @@ -942,16 +948,12 @@ arrayfor: break; case Op_ext_builtin: - case Op_old_ext_builtin: { int arg_count = pc->expr_count; awk_value_t result; PUSH_CODE(pc); - if (op == Op_ext_builtin) - r = awk_value_to_node(pc->extfunc(arg_count, & result)); - else - r = pc->builtin(arg_count); + r = awk_value_to_node(pc->extfunc(arg_count, & result)); (void) POP_CODE(); while (arg_count-- > 0) { t1 = POP(); @@ -985,6 +987,8 @@ arrayfor: r = POP_STRING(); unref(m->re_exp); m->re_exp = r; + } else if (m->type == Node_typedregex) { + UPREF(m); } PUSH(m); break; @@ -1078,8 +1082,7 @@ match_re: PUSH(r); break; } else if (f->type != Node_func) { - if ( f->type == Node_ext_func - || f->type == Node_old_ext_func) { + if (f->type == Node_ext_func) { /* code copied from below, keep in sync */ INSTRUCTION *bc; char *fname = pc->func_name; @@ -1090,10 +1093,7 @@ match_re: bc = f->code_ptr; assert(bc->opcode == Op_symbol); - if (f->type == Node_ext_func) - npc[0].opcode = Op_ext_builtin; /* self modifying code */ - else - npc[0].opcode = Op_old_ext_builtin; /* self modifying code */ + npc[0].opcode = Op_ext_builtin; /* self modifying code */ npc[0].extfunc = bc->extfunc; npc[0].expr_count = arg_count; /* actual argument count */ npc[1] = pc[1]; @@ -1119,12 +1119,12 @@ match_re: f = pc->func_body; if (f == NULL) { f = lookup(pc->func_name); - if (f == NULL || (f->type != Node_func && f->type != Node_ext_func && f->type != Node_old_ext_func)) + if (f == NULL || (f->type != Node_func && f->type != Node_ext_func)) fatal(_("function `%s' not defined"), pc->func_name); pc->func_body = f; /* save for next call */ } - if (f->type == Node_ext_func || f->type == Node_old_ext_func) { + if (f->type == Node_ext_func) { /* keep in sync with indirect call code */ INSTRUCTION *bc; char *fname = pc->func_name; @@ -1132,10 +1132,7 @@ match_re: bc = f->code_ptr; assert(bc->opcode == Op_symbol); - if (f->type == Node_ext_func) - pc->opcode = Op_ext_builtin; /* self modifying code */ - else - pc->opcode = Op_old_ext_builtin; /* self modifying code */ + pc->opcode = Op_ext_builtin; /* self modifying code */ pc->extfunc = bc->extfunc; pc->expr_count = arg_count; /* actual argument count */ (pc + 1)->func_name = fname; /* name of the builtin */ @@ -1417,6 +1414,7 @@ match_re: case Op_K_if: case Op_K_else: case Op_cond_exp: + case Op_comment: break; default: @@ -191,7 +191,7 @@ #define setsid() /* nothing */ #endif /* HAVE_SETSID */ -#if defined(GAWK_AIX) +#if defined(_AIX) #undef TANDEM /* AIX defines this in one of its header files */ #endif @@ -264,7 +264,6 @@ struct recmatch { static int iop_close(IOBUF *iop); -struct redirect *redirect(NODE *redir_exp, int redirtype, int *errflg); static void close_one(void); static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type how); #ifndef PIPES_SIMULATED @@ -275,7 +274,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); @@ -323,6 +322,8 @@ static Regexp *RS_re_yes_case; /* regexp for RS when ignoring case */ static Regexp *RS_re_no_case; /* regexp for RS when not ignoring case */ static Regexp *RS_regexp; +static const char nonfatal[] = "NONFATAL"; + bool RS_is_null; extern NODE *ARGC_node; @@ -599,7 +600,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,13 +729,13 @@ redflags2str(int flags) return genflags2str(flags, redtab); } -/* redirect --- Redirection for printf and print commands */ +/* redirect_string --- Redirection for printf and print commands, use string info */ struct redirect * -redirect(NODE *redir_exp, int redirtype, int *errflg) +redirect_string(const char *str, size_t explen, bool not_string, + int redirtype, int *errflg, int extfd, bool failure_fatal) { struct redirect *rp; - char *str; int tflag = 0; int outflag = 0; const char *direction = "to"; @@ -782,18 +784,16 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) default: cant_happen(); } - if (do_lint && (redir_exp->flags & STRCUR) == 0) - lintwarn(_("expression in `%s' redirection only has numeric value"), + if (do_lint && not_string) + lintwarn(_("expression in `%s' redirection is a number"), 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); @@ -831,8 +831,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))) { @@ -843,23 +843,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; @@ -891,6 +893,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(); @@ -898,6 +904,12 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) #ifdef SIGPIPE signal(SIGPIPE, SIG_DFL); #endif + /* + * Don't check failure_fatal; see input pipe below. + * Note that the failure happens upon failure to fork, + * using a non-existant program will still succeed the + * popen(). + */ if ((rp->output.fp = popen(str, binmode("w"))) == NULL) fatal(_("can't open pipe `%s' for output (%s)"), str, strerror(errno)); @@ -910,6 +922,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)"), @@ -917,7 +933,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) */ @@ -934,15 +950,19 @@ 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)) { -#ifdef HAVE_SOCKETS - if (inetfile(str, NULL)) { + if (! two_way_open(str, rp, extfd)) { + if (! failure_fatal || is_non_fatal_redirect(str)) { *errflg = errno; /* do not free rp, saving it for reuse (save_rp = rp) */ return NULL; } else -#endif fatal(_("can't open two way pipe `%s' for input/output (%s)"), str, strerror(errno)); } @@ -954,7 +974,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)) @@ -1020,11 +1040,14 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) * can return -1. For output to file, * complain. The shell will complain on * a bad command to a pipe. + * + * 12/2014: Take nonfatal settings in PROCINFO into account. */ if (errflg != NULL) *errflg = errno; - if ( redirtype == redirect_output - || redirtype == redirect_append) { + if (failure_fatal && ! is_non_fatal_redirect(str) && + (redirtype == redirect_output + || redirtype == redirect_append)) { /* multiple messages make life easier for translators */ if (*direction == 'f') fatal(_("can't redirect from `%s' (%s)"), @@ -1055,6 +1078,18 @@ redirect(NODE *redir_exp, int redirtype, int *errflg) return rp; } +/* redirect --- Redirection for printf and print commands */ + +struct redirect * +redirect(NODE *redir_exp, int redirtype, int *errflg, bool failure_fatal) +{ + bool not_string = ((fixtype(redir_exp)->flags & STRING) == 0); + + redir_exp = force_string(redir_exp); + return redirect_string(redir_exp->stptr, redir_exp->stlen, not_string, + redirtype, errflg, -1, failure_fatal); +} + /* getredirect --- find the struct redirect for this file or pipe */ struct redirect * @@ -1069,6 +1104,34 @@ getredirect(const char *str, int len) return NULL; } +/* is_non_fatal_std --- return true if fp is stdout/stderr and nonfatal */ + +bool +is_non_fatal_std(FILE *fp) +{ + if (in_PROCINFO(nonfatal, NULL, NULL)) + return true; + + /* yucky logic. sigh. */ + if (fp == stdout) { + return ( in_PROCINFO("-", nonfatal, NULL) != NULL + || in_PROCINFO("/dev/stdout", nonfatal, NULL) != NULL); + } else if (fp == stderr) { + return (in_PROCINFO("/dev/stderr", nonfatal, NULL) != NULL); + } + + return false; +} + +/* is_non_fatal_redirect --- return true if redirected I/O should be nonfatal */ + +bool +is_non_fatal_redirect(const char *str) +{ + return in_PROCINFO(nonfatal, NULL, NULL) != NULL + || in_PROCINFO(str, nonfatal, NULL) != NULL; +} + /* close_one --- temporarily close an open file to re-use the fd */ static void @@ -1442,7 +1505,7 @@ str2mode(const char *mode) static int socketopen(int family, int type, const char *localpname, - const char *remotepname, const char *remotehostname) + const char *remotepname, const char *remotehostname, bool *hard_error) { struct addrinfo *lres, *lres0; struct addrinfo lhints; @@ -1461,8 +1524,11 @@ socketopen(int family, int type, const char *localpname, lerror = getaddrinfo(NULL, localpname, & lhints, & lres); if (lerror) { - if (strcmp(localpname, "0") != 0) - fatal(_("local port %s invalid in `/inet'"), localpname); + if (strcmp(localpname, "0") != 0) { + warning(_("local port %s invalid in `/inet'"), localpname); + *hard_error = true; + return INVALID_HANDLE; + } lres0 = NULL; lres = & lhints; } else @@ -1480,7 +1546,9 @@ socketopen(int family, int type, const char *localpname, if (rerror) { if (lres0 != NULL) freeaddrinfo(lres0); - fatal(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname); + warning(_("remote host and port information (%s, %s) invalid"), remotehostname, remotepname); + *hard_error = true; + return INVALID_HANDLE; } rres0 = rres; socket_fd = INVALID_HANDLE; @@ -1646,6 +1714,7 @@ devopen(const char *name, const char *mode) char *cp; int flag; struct inet_socket_info isi; + int save_errno = 0; openfd = devopen_simple(name, mode, false); if (openfd != INVALID_HANDLE) @@ -1657,6 +1726,14 @@ devopen(const char *name, const char *mode) goto strictopen; } else if (inetfile(name, & isi)) { #ifdef HAVE_SOCKETS +#define DEFAULT_RETRIES 20 + static unsigned long def_retries = DEFAULT_RETRIES; + static bool first_time = true; + unsigned long retries = 0; + static long msleep = 1000; + bool hard_error = false; + bool non_fatal = is_non_fatal_redirect(name); + cp = (char *) name; /* socketopen requires NUL-terminated strings */ @@ -1664,13 +1741,6 @@ devopen(const char *name, const char *mode) cp[isi.remotehost.offset+isi.remotehost.len] = '\0'; /* remoteport comes last, so already NUL-terminated */ - { -#define DEFAULT_RETRIES 20 - static unsigned long def_retries = DEFAULT_RETRIES; - static bool first_time = true; - unsigned long retries = 0; - static long msleep = 1000; - if (first_time) { char *cp, *end; unsigned long count = 0; @@ -1696,25 +1766,41 @@ devopen(const char *name, const char *mode) msleep *= 1000; } } - retries = def_retries; + /* + * PROCINFO["NONFATAL"] or PROCINFO[name, "NONFATAL"] overrrides + * GAWK_SOCK_RETRIES. The explicit code in the program carries + * a bigger stick than the environment variable does. + */ + retries = non_fatal ? 1 : def_retries; + errno = 0; do { - openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset, name+isi.remoteport.offset, name+isi.remotehost.offset); + openfd = socketopen(isi.family, isi.protocol, name+isi.localport.offset, + name+isi.remoteport.offset, name+isi.remotehost.offset, + & hard_error); retries--; - } while (openfd == INVALID_HANDLE && retries > 0 && usleep(msleep) == 0); - } + } while (openfd == INVALID_HANDLE && ! hard_error && retries > 0 && usleep(msleep) == 0); + save_errno = errno; - /* restore original name string */ - cp[isi.localport.offset+isi.localport.len] = '/'; - cp[isi.remotehost.offset+isi.remotehost.len] = '/'; + /* restore original name string */ + cp[isi.localport.offset+isi.localport.len] = '/'; + cp[isi.remotehost.offset+isi.remotehost.len] = '/'; #else /* ! HAVE_SOCKETS */ - fatal(_("TCP/IP communications are not supported")); + fatal(_("TCP/IP communications are not supported")); #endif /* HAVE_SOCKETS */ } strictopen: - if (openfd == INVALID_HANDLE) + if (openfd == INVALID_HANDLE) { openfd = open(name, flag, 0666); + /* + * ENOENT means there is no such name in the filesystem. + * Therefore it's ok to propagate up the error from + * getaddrinfo() that's in save_errno. + */ + if (openfd == INVALID_HANDLE && errno == ENOENT && save_errno) + errno = save_errno; + } #if defined(__EMX__) || defined(__MINGW32__) if (openfd == INVALID_HANDLE && errno == EACCES) { /* On OS/2 and Windows directory access via open() is @@ -1737,16 +1823,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) @@ -2217,17 +2303,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 + void (*hstat)(int), (*istat)(int), (*qstat)(int); istat = signal(SIGINT, SIG_IGN); +#endif #ifdef __MINGW32__ if (interesting < 0) { status = -1; @@ -2243,11 +2355,22 @@ wait_any(int interesting) /* pid of interest, if any */ break; } } -#else +#else /* ! __MINGW32__ */ +#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); @@ -2265,10 +2388,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 /* ! __MINGW32__ */ +#ifndef HAVE_SIGPROCMASK signal(SIGINT, istat); +#else + sigprocmask(SIG_SETMASK, & oldset, NULL); +#endif return status; } @@ -2479,7 +2608,7 @@ do_getline_redir(int into_variable, enum redirval redirtype) assert(redirtype != redirect_none); redir_exp = TOP(); - rp = redirect(redir_exp, redirtype, & redir_error); + rp = redirect(redir_exp, redirtype, & redir_error, false); DEREF(redir_exp); decr_sp(); if (rp == NULL) { @@ -2489,6 +2618,10 @@ do_getline_redir(int into_variable, enum redirval redirtype) } return make_number((AWKNUM) -1.0); } else if ((rp->flag & RED_TWOWAY) != 0 && rp->iop == NULL) { + if (is_non_fatal_redirect(redir_exp->stptr)) { + update_ERRNO_int(EBADF); + return make_number((AWKNUM) -1.0); + } (void) close_rp(rp, CLOSE_ALL); fatal(_("getline: attempt to read from closed read end of two-way pipe")); } @@ -2501,7 +2634,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) { @@ -2551,7 +2684,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) @@ -2615,6 +2748,7 @@ init_awkpath(path_info *pi) end++; len = end - start; if (len > 0) { + /* +2 is correct here; leave room for / */ emalloc(p, char *, len + 2, "init_awkpath"); memcpy(p, start, len); @@ -3069,7 +3203,7 @@ iop_finish(IOBUF *iop) lintwarn(_("data file `%s' is empty"), iop->public.name); iop->errcode = errno = 0; iop->count = iop->scanoff = 0; - emalloc(iop->buf, char *, iop->size += 2, "iop_finish"); + emalloc(iop->buf, char *, iop->size += 1, "iop_finish"); iop->off = iop->buf; iop->dataend = NULL; iop->end = iop->buf + iop->size; @@ -3101,10 +3235,10 @@ grow_iop_buffer(IOBUF *iop) size_t newsize; /* - * Lop off original extra two bytes, double the size, - * add them back. + * Lop off original extra byte, double the size, + * add it back. */ - newsize = ((iop->size - 2) * 2) + 2; + newsize = ((iop->size - 1) * 2) + 1; /* Check for overflow */ if (newsize <= iop->size) @@ -3112,7 +3246,7 @@ grow_iop_buffer(IOBUF *iop) /* Make sure there's room for a disk block */ if (newsize - valid < iop->readsize) - newsize += iop->readsize + 2; + newsize += iop->readsize + 1; /* Check for overflow, again */ if (newsize <= iop->size) @@ -3444,10 +3578,45 @@ find_longest_terminator: return REC_OK; } +/* retryable --- return true if PROCINFO[<filename>, "RETRY"] exists */ + +static inline int +retryable(IOBUF *iop) +{ + return PROCINFO_node && in_PROCINFO(iop->public.name, "RETRY", NULL); +} + +/* errno_io_retry --- 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 @@ -3491,8 +3660,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; @@ -3566,6 +3737,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) { @@ -3717,17 +3890,13 @@ pty_vs_pipe(const char *command) #ifdef HAVE_TERMIOS_H NODE *val; - if (PROCINFO_node == NULL) - return false; + /* + * N.B. No need to check for NULL PROCINFO_node, since the + * in_PROCINFO function now checks that for us. + */ val = in_PROCINFO(command, "pty", NULL); - if (val) { - if ((val->flags & MAYBE_NUM) != 0) - (void) force_number(val); - if ((val->flags & NUMBER) != 0) - return ! iszero(val); - else - return (val->stlen != 0); - } + if (val) + return boolval(val); #endif /* HAVE_TERMIOS_H */ return false; } @@ -3860,12 +4029,21 @@ in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx) NODE *r, *sub = NULL; NODE *subsep = SUBSEP_node->var_value; + if (PROCINFO_node == NULL || (pidx1 == NULL && pidx2 == NULL)) + return NULL; + /* full_idx is in+out parameter */ if (full_idx) sub = *full_idx; - str_len = strlen(pidx1) + subsep->stlen + strlen(pidx2); + if (pidx1 != NULL && pidx2 == NULL) + str_len = strlen(pidx1); + else if (pidx1 == NULL && pidx2 != NULL) + str_len = strlen(pidx2); + else + str_len = strlen(pidx1) + subsep->stlen + strlen(pidx2); + if (sub == NULL) { emalloc(str, char *, str_len + 1, "in_PROCINFO"); sub = make_str_node(str, str_len, ALREADY_MALLOCED); @@ -3879,8 +4057,14 @@ in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx) sub->stlen = str_len; } - sprintf(sub->stptr, "%s%.*s%s", pidx1, (int)subsep->stlen, - subsep->stptr, pidx2); + if (pidx1 != NULL && pidx2 == NULL) + strcpy(sub->stptr, pidx1); + else if (pidx1 == NULL && pidx2 != NULL) + strcpy(sub->stptr, pidx2); + else + sprintf(sub->stptr, "%s%.*s%s", pidx1, (int)subsep->stlen, + subsep->stptr, pidx2); + r = in_array(PROCINFO_node, sub); if (! full_idx) unref(sub); diff --git a/m4/ChangeLog b/m4/ChangeLog index d864fd37..afef3485 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -8,6 +8,14 @@ * po.m4: Upgrade to gettext-0.19.7. * progtest.m4: Upgrade to gettext-0.19.7. +2016-01-27 Arnold D. Robbins <arnold@skeeve.com> + + * arch.m4 (GAWK_AC_AIX_TWEAK): Remove definition. + +2016-01-03 Arnold D. Robbins <arnold@skeeve.com> + + * arch.m4 (GAWK_AC_LINUX_ALPHA): Remove definition. + 2015-09-11 Daniel Richard G. <skunk@iSKUNK.ORG> * arch.m4: Rework again. In particular, provide a wrapper @@ -47,6 +55,10 @@ * 4.1.2: Release tar ball made. +2015-04-16 Arnold D. Robbins <arnold@skeeve.com> + + * isc-posix.m4: Removed. No longer needed. + 2015-01-24 gettextize <bug-gnu-gettext@gnu.org> * iconv.m4: Upgrade to gettext-0.19.4. @@ -22,43 +22,6 @@ dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA dnl -dnl Check for AIX and add _XOPEN_SOURCE_EXTENDED -AC_DEFUN([GAWK_AC_AIX_TWEAK], [ -AC_MSG_CHECKING([for AIX compilation hacks]) -AC_CACHE_VAL(gawk_cv_aix_hack, [ -if test -d /lpp -then - CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED=1 -DGAWK_AIX=1" - gawk_cv_aix_hack=yes -else - gawk_cv_aix_hack=no -fi -])dnl -AC_MSG_RESULT([${gawk_cv_aix_hack}]) -])dnl - -dnl Check for Alpha Linux systems -AC_DEFUN([GAWK_AC_LINUX_ALPHA], [ -AC_MSG_CHECKING([for Linux/Alpha compilation hacks]) -AC_CACHE_VAL(gawk_cv_linux_alpha_hack, [ -if test "Linux" = "`uname`" && test "alpha" = "`uname -m`" -then - # this isn't necessarily always true, - # the vendor's compiler is also often found - if test "$GCC" = yes - then - CFLAGS="$CFLAGS -mieee" - gawk_cv_linux_alpha_hack=yes - else - gawk_cv_linux_alpha_hack=no - fi -else - gawk_cv_linux_alpha_hack=no -fi -])dnl -AC_MSG_RESULT([${gawk_cv_linux_alpha_hack}]) -])dnl - dnl Check for z/OS Unix Systems Services AC_DEFUN([AC_ZOS_USS], [ AC_MSG_CHECKING([for z/OS USS compilation]) diff --git a/m4/isc-posix.m4 b/m4/isc-posix.m4 deleted file mode 100644 index 74dc8f26..00000000 --- a/m4/isc-posix.m4 +++ /dev/null @@ -1,24 +0,0 @@ -# isc-posix.m4 serial 2 (gettext-0.11.2) -dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -# This file is not needed with autoconf-2.53 and newer. Remove it in 2005. - -# This test replaces the one in autoconf. -# Currently this macro should have the same name as the autoconf macro -# because gettext's gettext.m4 (distributed in the automake package) -# still uses it. Otherwise, the use in gettext.m4 makes autoheader -# give these diagnostics: -# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX -# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX - -undefine([AC_ISC_POSIX]) - -AC_DEFUN([AC_ISC_POSIX], - [ - dnl This test replaces the obsolescent AC_ISC_POSIX kludge. - AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) - ] -) @@ -58,7 +58,7 @@ static void init_args(int argc0, int argc, const char *argv0, char **argv); static void init_vars(void); static NODE *load_environ(void); static NODE *load_procinfo(void); -static RETSIGTYPE catchsig(int sig); +static void catchsig(int sig); #ifdef HAVE_LIBSIGSEGV static int catchsegv(void *fault_address, int serious); static void catchstackoverflow(int emergency, stackoverflow_context_t scp); @@ -147,7 +147,7 @@ static void set_locale_stuff(void); static bool stopped_early = false; int do_flags = false; -bool do_optimize = false; /* apply default optimizations */ +bool do_optimize = true; /* apply default optimizations */ static int do_nostalgia = false; /* provide a blast from the past */ static int do_binary = false; /* hands off my data! */ static int do_version = false; /* print version info */ @@ -193,6 +193,7 @@ static const struct option optab[] = { { "locale", required_argument, NULL, 'Z' }, #endif { "non-decimal-data", no_argument, NULL, 'n' }, + { "no-optimize", no_argument, NULL, 's' }, { "nostalgia", no_argument, & do_nostalgia, 1 }, { "optimize", no_argument, NULL, 'O' }, #if defined(YYDEBUG) || defined(GAWKDEBUG) @@ -294,22 +295,10 @@ main(int argc, char **argv) * this value once makes a speed difference. */ gawk_mb_cur_max = MB_CUR_MAX; -#ifdef LIBC_IS_BORKED -{ - const char *env_lc; - - env_lc = getenv("LC_ALL"); - if (env_lc == NULL) - env_lc = getenv("LANG"); - if (env_lc != NULL && env_lc[1] == '\0' && tolower(env_lc[0]) == 'c') - gawk_mb_cur_max = 1; -} -#endif /* init the cache for checking bytes if they're characters */ init_btowc_cache(); - if (do_nostalgia) nostalgia(); @@ -498,9 +487,8 @@ main(int argc, char **argv) if (do_debug) debug_prog(code_block); - else if (do_pretty_print && ! do_debug && getenv("GAWK_NO_PP_RUN") != NULL) - /* hack to run pretty printer only. need a better solution */ - ; + else if (do_pretty_print && ! do_profile) + ; /* run pretty printer only. */ else interpret(code_block); @@ -596,6 +584,7 @@ usage(int exitval, FILE *fp) fputs(_("\t-p[file]\t\t--profile[=file]\n"), fp); fputs(_("\t-P\t\t\t--posix\n"), fp); fputs(_("\t-r\t\t\t--re-interval\n"), fp); + fputs(_("\t-s\t\t\t--no-optimize\n"), fp); fputs(_("\t-S\t\t\t--sandbox\n"), fp); fputs(_("\t-t\t\t\t--lint-old\n"), fp); fputs(_("\t-V\t\t\t--version\n"), fp); @@ -898,9 +887,40 @@ load_environ() */ path_environ("AWKPATH", defpath); path_environ("AWKLIBPATH", deflibpath); + + /* set up array functions */ + init_env_array(ENVIRON_node); + return ENVIRON_node; } +static void +load_procinfo_argv() +{ + NODE *tmp; + NODE **aptr; + NODE *argv_array; + int i; + + tmp = make_string("argv", 4); + aptr = assoc_lookup(PROCINFO_node, tmp); + unref(tmp); + unref(*aptr); + getnode(argv_array); + memset(argv_array, '\0', sizeof(NODE)); /* valgrind wants this */ + null_array(argv_array); + *aptr = argv_array; + argv_array->parent_array = PROCINFO_node; + argv_array->vname = estrdup("argv", 4); + for (i = 0; d_argv[i] != NULL; i++) { + tmp = make_number(i); + aptr = assoc_lookup(argv_array, tmp); + unref(tmp); + unref(*aptr); + *aptr = make_string(d_argv[i], strlen(d_argv[i])); + } +} + /* load_procinfo --- populate the PROCINFO array */ static NODE * @@ -1000,6 +1020,7 @@ load_procinfo() groupset = NULL; } #endif + load_procinfo_argv(); return PROCINFO_node; } @@ -1170,7 +1191,7 @@ arg_assign(char *arg, bool initing) /* catchsig --- catch signals */ -static RETSIGTYPE +static void catchsig(int sig) { if (sig == SIGFPE) { @@ -1411,7 +1432,7 @@ parse_args(int argc, char **argv) /* * The + on the front tells GNU getopt not to rearrange argv. */ - const char *optlist = "+F:f:v:W;bcCd::D::e:E:ghi:l:L:nNo::Op::MPrStVYZ:"; + const char *optlist = "+F:f:v:W;bcCd::D::e:E:ghi:l:L:nNo::Op::MPrSstVYZ:"; int old_optind; int c; char *scan; @@ -1571,6 +1592,10 @@ parse_args(int argc, char **argv) do_flags |= DO_INTERVALS; break; + case 's': + do_optimize = false; + break; + case 'S': do_flags |= DO_SANDBOX; break; @@ -1645,6 +1670,8 @@ parse_args(int argc, char **argv) break; } out: + do_optimize = (do_optimize && ! do_pretty_print); + return; } diff --git a/missing_d/ChangeLog b/missing_d/ChangeLog index f21c8cd3..96e7a5d4 100644 --- a/missing_d/ChangeLog +++ b/missing_d/ChangeLog @@ -6,6 +6,12 @@ * 4.1.2: Release tar ball made. +2015-02-27 Arnold D. Robbins <arnold@skeeve.com> + + * getaddrinfo.h (gai_strerror): Add declaration. + * getaddrinfo.c (gai_strerror): New function. + (getaddrinfo): Return errno values instead of just -1. + 2014-04-08 Arnold D. Robbins <arnold@skeeve.com> * 4.1.1: Release tar ball made. diff --git a/missing_d/getaddrinfo.c b/missing_d/getaddrinfo.c index 677f27d0..f24ac598 100644 --- a/missing_d/getaddrinfo.c +++ b/missing_d/getaddrinfo.c @@ -12,6 +12,8 @@ #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif +#include <errno.h> +#include <string.h> /* strerror */ #include "getaddrinfo.h" @@ -29,12 +31,12 @@ getaddrinfo(const char *hostname, const char *portname, { struct addrinfo *out; if (res == NULL) - return -1; + return EINVAL; out = (struct addrinfo *) malloc(sizeof(*out)); if (out == NULL) { *res = NULL; - return -1; + return ENOMEM; } memset(out, '\0', sizeof(*out)); @@ -42,7 +44,7 @@ getaddrinfo(const char *hostname, const char *portname, if (out->ai_addr == NULL) { free(out); *res = NULL; - return -1; + return ENOMEM; } out->ai_socktype = SOCK_STREAM; @@ -78,7 +80,7 @@ getaddrinfo(const char *hostname, const char *portname, = ((struct in_addr *)he->h_addr_list[0])->s_addr; } else { freeaddrinfo(out); - return -1; + return EADDRNOTAVAIL; } } else { if (!(out->ai_flags & AI_PASSIVE)) @@ -109,4 +111,10 @@ getaddrinfo(const char *hostname, const char *portname, return 0; } + +const char * +gai_strerror(int errcode) +{ + return strerror(errcode); +} #endif diff --git a/missing_d/getaddrinfo.h b/missing_d/getaddrinfo.h index 3d816c93..873d67df 100644 --- a/missing_d/getaddrinfo.h +++ b/missing_d/getaddrinfo.h @@ -29,3 +29,5 @@ void freeaddrinfo(struct xaddrinfo * res); int getaddrinfo(const char * hostname, const char * portname, struct xaddrinfo * hints, struct xaddrinfo ** res); + +const char *gai_strerror(int errcode); @@ -327,7 +327,7 @@ force_mpnum(NODE *n, int do_nondec, int use_locale) IEEE_FMT(n->mpg_numbr, tval); done: /* trailing space is OK for NUMBER */ - while (isspace((unsigned char) *ptr)) + while (ptr < cpend && isspace((unsigned char) *ptr)) ptr++; *cpend = save; if (errno == 0 && ptr == cpend) @@ -341,20 +341,17 @@ done: static NODE * mpg_force_number(NODE *n) { - unsigned int newflags = 0; - - if (is_mpg_number(n) && (n->flags & NUMCUR) != 0) + if ((n->flags & NUMCUR) != 0) return n; - - if ((n->flags & MAYBE_NUM) != 0) { - n->flags &= ~MAYBE_NUM; - newflags = NUMBER; - } + n->flags |= NUMCUR; if (force_mpnum(n, (do_non_decimal_data && ! do_traditional), true)) { - n->flags |= newflags; - n->flags |= NUMCUR; - } + if ((n->flags & MAYBE_NUM) != 0) { + n->flags &= ~(MAYBE_NUM|STRING); + n->flags |= NUMBER; + } + } else + n->flags &= ~MAYBE_NUM; return n; } @@ -373,7 +370,7 @@ mpg_format_val(const char *format, int index, NODE *s) if (is_mpg_integer(s) || mpfr_integer_p(s->mpg_numbr)) { /* integral value, use %d */ r = format_tree("%d", 2, dummy, 2); - s->stfmt = -1; + s->stfmt = STFMT_UNUSED; } else { r = format_tree(format, fmt_list[index]->stlen, dummy, 2); assert(r != NULL); @@ -521,11 +518,9 @@ set_PREC() if (! do_mpfr) return; - val = PREC_node->var_value; - if ((val->flags & MAYBE_NUM) != 0) - force_number(val); + val = fixtype(PREC_node->var_value); - if ((val->flags & STRCUR) != 0) { + if ((val->flags & STRING) != 0) { int i, j; /* emulate IEEE-754 binary format */ @@ -675,9 +670,9 @@ do_mpfr_atan2(int nargs) t1 = POP_SCALAR(); if (do_lint) { - if ((t1->flags & (NUMCUR|NUMBER)) == 0) + if ((fixtype(t1)->flags & NUMBER) == 0) lintwarn(_("atan2: received non-numeric first argument")); - if ((t2->flags & (NUMCUR|NUMBER)) == 0) + if ((fixtype(t2)->flags & NUMBER) == 0) lintwarn(_("atan2: received non-numeric second argument")); } force_number(t1); @@ -707,7 +702,7 @@ do_mpfr_func(const char *name, int tval; t1 = POP_SCALAR(); - if (do_lint && (t1->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(t1)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), name); force_number(t1); @@ -773,7 +768,7 @@ do_mpfr_int(int nargs) NODE *tmp, *r; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("int: received non-numeric argument")); force_number(tmp); @@ -803,7 +798,7 @@ do_mpfr_compl(int nargs) mpz_ptr zptr; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("compl: received non-numeric argument")); force_number(tmp); @@ -851,7 +846,7 @@ get_intval(NODE *t1, int argnum, const char *op) { mpz_ptr pz; - if (do_lint && (t1->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(t1)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument #%d"), op, argnum); (void) force_number(t1); @@ -1076,25 +1071,22 @@ do_mpfr_strtonum(int nargs) { NODE *tmp, *r; - tmp = POP_SCALAR(); - if ((tmp->flags & (NUMBER|NUMCUR)) == 0) { + tmp = fixtype(POP_SCALAR()); + if ((tmp->flags & NUMBER) == 0) { r = mpg_integer(); /* will be changed to MPFR float if necessary in force_mpnum() */ r->stptr = tmp->stptr; r->stlen = tmp->stlen; force_mpnum(r, true, use_lc_numeric); r->stptr = NULL; r->stlen = 0; + } else if (is_mpg_float(tmp)) { + int tval; + r = mpg_float(); + tval = mpfr_set(r->mpg_numbr, tmp->mpg_numbr, ROUND_MODE); + IEEE_FMT(r->mpg_numbr, tval); } else { - (void) force_number(tmp); - if (is_mpg_float(tmp)) { - int tval; - r = mpg_float(); - tval = mpfr_set(r->mpg_numbr, tmp->mpg_numbr, ROUND_MODE); - IEEE_FMT(r->mpg_numbr, tval); - } else { - r = mpg_integer(); - mpz_set(r->mpg_i, tmp->mpg_i); - } + r = mpg_integer(); + mpz_set(r->mpg_i, tmp->mpg_i); } DEREF(tmp); @@ -1172,7 +1164,7 @@ do_mpfr_srand(int nargs) else { NODE *tmp; tmp = POP_SCALAR(); - if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) + if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("srand: received non-numeric argument")); force_number(tmp); if (is_mpg_float(tmp)) @@ -1186,6 +1178,95 @@ do_mpfr_srand(int nargs) return res; } +/* do_mpfr_intdiv --- do integer division, return quotient and remainder in dest array */ + +/* + * We define the semantics as: + * numerator = int(numerator) + * denominator = int(denonmator) + * quotient = int(numerator / denomator) + * remainder = int(numerator % denomator) + */ + +NODE * +do_mpfr_intdiv(int nargs) +{ + NODE *numerator, *denominator, *result; + NODE *num, *denom; + NODE *quotient, *remainder; + NODE *sub, **lhs; + + result = POP_PARAM(); + if (result->type != Node_var_array) + fatal(_("intdiv: third argument is not an array")); + assoc_clear(result); + + denominator = POP_SCALAR(); + numerator = POP_SCALAR(); + + if (do_lint) { + if ((fixtype(numerator)->flags & NUMBER) == 0) + lintwarn(_("intdiv: received non-numeric first argument")); + if ((fixtype(denominator)->flags & NUMBER) == 0) + lintwarn(_("intdiv: received non-numeric second argument")); + } + + (void) force_number(numerator); + (void) force_number(denominator); + + /* convert numerator and denominator to integer */ + if (is_mpg_integer(numerator)) { + num = mpg_integer(); + mpz_set(num->mpg_i, numerator->mpg_i); + } else { + if (! mpfr_number_p(numerator->mpg_numbr)) { + /* [+-]inf or NaN */ + return numerator; + } + + num = mpg_integer(); + mpfr_get_z(num->mpg_i, numerator->mpg_numbr, MPFR_RNDZ); + } + + if (is_mpg_integer(denominator)) { + denom = mpg_integer(); + mpz_set(denom->mpg_i, denominator->mpg_i); + } else { + if (! mpfr_number_p(denominator->mpg_numbr)) { + /* [+-]inf or NaN */ + return denominator; + } + + denom = mpg_integer(); + mpfr_get_z(denom->mpg_i, denominator->mpg_numbr, MPFR_RNDZ); + } + + if (mpz_sgn(denom->mpg_i) == 0) + fatal(_("intdiv: division by zero attempted")); + + quotient = mpg_integer(); + remainder = mpg_integer(); + + /* do the division */ + mpz_tdiv_qr(quotient->mpg_i, remainder->mpg_i, num->mpg_i, denom->mpg_i); + unref(num); + unref(denom); + unref(numerator); + unref(denominator); + + sub = make_string("quotient", 8); + lhs = assoc_lookup(result, sub); + unref(*lhs); + *lhs = quotient; + + sub = make_string("remainder", 9); + lhs = assoc_lookup(result, sub); + unref(*lhs); + *lhs = remainder; + + return make_number((AWKNUM) 0.0); +} + /* * mpg_tofloat --- convert an arbitrary-precision integer operand to * a float without loss of precision. It is assumed that the @@ -30,7 +30,7 @@ static int is_ieee_magic_val(const char *val); static NODE *r_make_number(double x); -static AWKNUM get_ieee_magic_val(const char *val); +static AWKNUM get_ieee_magic_val(char *val); extern NODE **fmt_list; /* declared in eval.c */ NODE *(*make_number)(double) = r_make_number; @@ -61,23 +61,35 @@ r_force_number(NODE *n) char *cpend; char save; char *ptr; - unsigned int newflags; extern double strtod(); if ((n->flags & NUMCUR) != 0) return n; - /* all the conditionals are an attempt to avoid the expensive strtod */ + /* + * We should always set NUMCUR and clear MAYBE_NUM, and we may possibly + * change STRING to NUMBER if MAYBE_NUM was set and it's a good numeric + * string. + */ - /* Note: only set NUMCUR if we actually convert some digits */ + /* All the conditionals are an attempt to avoid the expensive strtod */ + n->flags |= NUMCUR; n->numbr = 0.0; - if (n->stlen == 0) { - return n; - } + /* Trim leading white space, bailing out if there's nothing else */ + for (cp = n->stptr, cpend = cp + n->stlen; + cp < cpend && isspace((unsigned char) *cp); cp++) + continue; + + if (cp == cpend) + goto badnum; + + /* At this point, we know the string is not entirely white space */ + /* Trim trailing white space */ + while (isspace((unsigned char) cpend[-1])) + cpend--; - cp = n->stptr; /* * 2/2007: * POSIX, by way of severe language lawyering, seems to @@ -86,80 +98,52 @@ r_force_number(NODE *n) * This also allows hexadecimal floating point. Ugh. */ if (! do_posix) { - if (is_alpha((unsigned char) *cp)) { - return n; - } else if (n->stlen == 4 && is_ieee_magic_val(n->stptr)) { - if ((n->flags & MAYBE_NUM) != 0) - n->flags &= ~MAYBE_NUM; - n->flags |= NUMBER|NUMCUR; - n->flags &= ~STRING; - n->numbr = get_ieee_magic_val(n->stptr); - - return n; + if (is_alpha((unsigned char) *cp)) + goto badnum; + else if (cpend == cp+4 && is_ieee_magic_val(cp)) { + n->numbr = get_ieee_magic_val(cp); + goto goodnum; } /* else fall through */ } - /* else not POSIX, so + /* else POSIX, so fall through */ - cpend = cp + n->stlen; - while (cp < cpend && isspace((unsigned char) *cp)) - cp++; - - if ( cp == cpend /* only spaces, or */ - || (! do_posix /* not POSIXLY paranoid and */ + if ( (! do_posix /* not POSIXLY paranoid and */ && (is_alpha((unsigned char) *cp) /* letter, or */ /* CANNOT do non-decimal and saw 0x */ || (! do_non_decimal_data && is_hex(cp))))) { - return n; + goto badnum; } - if ((n->flags & MAYBE_NUM) != 0) { - newflags = NUMBER; - n->flags &= ~MAYBE_NUM; - } else - newflags = 0; - if (cpend - cp == 1) { /* only one character */ if (isdigit((unsigned char) *cp)) { /* it's a digit! */ n->numbr = (AWKNUM)(*cp - '0'); - n->flags |= newflags; - n->flags |= NUMCUR; - n->flags &= ~STRING; - if (cp == n->stptr) /* no leading spaces */ + if (n->stlen == 1) /* no white space */ n->flags |= NUMINT; + goto goodnum; } - return n; + goto badnum; } - if (do_non_decimal_data) { /* main.c assures false if do_posix */ - errno = 0; - if (! do_traditional && get_numbase(cp, true) != 10) { - n->numbr = nondec2awknum(cp, cpend - cp); - n->flags |= NUMCUR; - n->flags &= ~STRING; - ptr = cpend; - goto finish; - } + errno = 0; + if (do_non_decimal_data /* main.c assures false if do_posix */ + && ! do_traditional && get_numbase(cp, true) != 10) { + /* nondec2awknum() saves and restores the byte after the string itself */ + n->numbr = nondec2awknum(cp, cpend - cp, &ptr); + } else { + save = *cpend; + *cpend = '\0'; + n->numbr = (AWKNUM) strtod((const char *) cp, &ptr); + *cpend = save; } - errno = 0; - save = *cpend; - *cpend = '\0'; - n->numbr = (AWKNUM) strtod((const char *) cp, &ptr); - - /* POSIX says trailing space is OK for NUMBER */ - while (isspace((unsigned char) *ptr)) - ptr++; - *cpend = save; -finish: if (errno == 0) { - if (ptr == cpend) { - n->flags |= newflags; - n->flags |= NUMCUR; - } + if (ptr == cpend) + goto goodnum; /* else keep the leading numeric value without updating flags */ + /* fall through to badnum */ } else { errno = 0; /* @@ -168,8 +152,21 @@ finish: * We force the numeric value to 0 in such cases. */ n->numbr = 0; + /* + * Or should we accept it as a NUMBER even though strtod + * threw an error? + */ + /* fall through to badnum */ } +badnum: + n->flags &= ~MAYBE_NUM; + return n; +goodnum: + if ((n->flags & MAYBE_NUM) != 0) { + n->flags &= ~(MAYBE_NUM|STRING); + n->flags |= NUMBER; + } return n; } @@ -227,7 +224,7 @@ r_format_val(const char *format, int index, NODE *s) * Once upon a time, we just blindly did this: * sprintf(sp, format, s->numbr); * s->stlen = strlen(sp); - * s->stfmt = (char) index; + * s->stfmt = index; * but that's no good if, e.g., OFMT is %s. So we punt, * and just always format the value ourselves. */ @@ -242,7 +239,7 @@ r_format_val(const char *format, int index, NODE *s) if (val == s->numbr) { /* integral value, but outside range of %ld, use %.0f */ r = format_tree("%.0f", 4, dummy, 2); - s->stfmt = -1; + s->stfmt = STFMT_UNUSED; } else { r = format_tree(format, fmt_list[index]->stlen, dummy, 2); assert(r != NULL); @@ -269,15 +266,15 @@ r_format_val(const char *format, int index, NODE *s) (void) sprintf(sp, "%ld", num); s->stlen = strlen(sp); } - s->stfmt = -1; + s->stfmt = STFMT_UNUSED; if ((s->flags & INTIND) != 0) { s->flags &= ~(INTIND|NUMBER); s->flags |= STRING; } } - if (s->stptr != NULL) + if ((s->flags & STRCUR) != 0) efree(s->stptr); - emalloc(s->stptr, char *, s->stlen + 2, "format_val"); + emalloc(s->stptr, char *, s->stlen + 1, "format_val"); memcpy(s->stptr, sp, s->stlen + 1); no_malloc: s->flags |= STRCUR; @@ -315,12 +312,12 @@ r_dupnode(NODE *n) r->wstlen = 0; if ((n->flags & STRCUR) != 0) { - emalloc(r->stptr, char *, n->stlen + 2, "r_dupnode"); + emalloc(r->stptr, char *, n->stlen + 1, "r_dupnode"); memcpy(r->stptr, n->stptr, n->stlen); r->stptr[n->stlen] = '\0'; if ((n->flags & WSTRCUR) != 0) { r->wstlen = n->wstlen; - emalloc(r->wstptr, wchar_t *, sizeof(wchar_t) * (n->wstlen + 2), "r_dupnode"); + emalloc(r->wstptr, wchar_t *, sizeof(wchar_t) * (n->wstlen + 1), "r_dupnode"); memcpy(r->wstptr, n->wstptr, n->wstlen * sizeof(wchar_t)); r->wstptr[n->wstlen] = L'\0'; r->flags |= WSTRCUR; @@ -386,14 +383,14 @@ make_str_node(const char *s, size_t len, int flags) r->numbr = 0; r->flags = (MALLOC|STRING|STRCUR); r->valref = 1; - r->stfmt = -1; + r->stfmt = STFMT_UNUSED; r->wstptr = NULL; r->wstlen = 0; if ((flags & ALREADY_MALLOCED) != 0) r->stptr = (char *) s; else { - emalloc(r->stptr, char *, len + 2, "make_str_node"); + emalloc(r->stptr, char *, len + 1, "make_str_node"); memcpy(r->stptr, s, len); } r->stptr[len] = '\0'; @@ -570,9 +567,8 @@ parse_escape(const char **string_ptr) warning(_("no hex digits in `\\x' escape sequence")); return ('x'); } - i = j = 0; start = *string_ptr; - for (;; j++) { + for (i = j = 0; j < 2; j++) { /* do outside test to avoid multiple side effects */ c = *(*string_ptr)++; if (isxdigit(c)) { @@ -698,7 +694,7 @@ str2wstr(NODE *n, size_t **ptr) * realloc the wide string down in size. */ - emalloc(n->wstptr, wchar_t *, sizeof(wchar_t) * (n->stlen + 2), "str2wstr"); + emalloc(n->wstptr, wchar_t *, sizeof(wchar_t) * (n->stlen + 1), "str2wstr"); wsp = n->wstptr; /* @@ -788,7 +784,7 @@ str2wstr(NODE *n, size_t **ptr) n->flags |= WSTRCUR; #define ARBITRARY_AMOUNT_TO_GIVE_BACK 100 if (n->stlen - n->wstlen > ARBITRARY_AMOUNT_TO_GIVE_BACK) - erealloc(n->wstptr, wchar_t *, sizeof(wchar_t) * (n->wstlen + 2), "str2wstr"); + erealloc(n->wstptr, wchar_t *, sizeof(wchar_t) * (n->wstlen + 1), "str2wstr"); return n; } @@ -815,7 +811,7 @@ wstr2str(NODE *n) memset(& mbs, 0, sizeof(mbs)); length = n->wstlen; - emalloc(newval, char *, (length * gawk_mb_cur_max) + 2, "wstr2str"); + emalloc(newval, char *, (length * gawk_mb_cur_max) + 1, "wstr2str"); wp = n->wstptr; for (cp = newval; length > 0; length--) { @@ -941,14 +937,18 @@ is_ieee_magic_val(const char *val) /* get_ieee_magic_val --- return magic value for string */ static AWKNUM -get_ieee_magic_val(const char *val) +get_ieee_magic_val(char *val) { static bool first = true; static AWKNUM inf; static AWKNUM nan; + char save; char *ptr; + save = val[4]; + val[4] = '\0'; AWKNUM v = strtod(val, &ptr); + val[4] = save; if (val == ptr) { /* Older strtod implementations don't support inf or nan. */ if (first) { diff --git a/old-extension/ChangeLog b/old-extension/ChangeLog index 34da558f..3c91b7cd 100644 --- a/old-extension/ChangeLog +++ b/old-extension/ChangeLog @@ -1,3 +1,12 @@ +2015-04-09 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * bindarr.c (do_bind_array): Undo Arnold's change of 2014-12-18. + +2014-12-18 Arnold D. Robbins <arnold@skeeve.com> + + * bindarr.c (do_bind_array): Do not waste a byte at the end of a string. + * fileop.c (do_fread): Ditto. + 2014-01-07 Arnold D. Robbins <arnold@skeeve.com> * dbarray.awk: Use full name for lib to load in extension() call. diff --git a/old-extension/bindarr.c b/old-extension/bindarr.c index 60959903..41467425 100644 --- a/old-extension/bindarr.c +++ b/old-extension/bindarr.c @@ -235,7 +235,7 @@ do_bind_array(int nargs) } /* copy the array -- this is passed as the second argument to the functions */ - emalloc(aname, char *, strlen(t->vname) + 2, "do_bind_array"); + emalloc(aname, char *, 1 + strlen(symbol->vname) + 1, "do_bind_array"); aname[0] = '~'; /* any illegal character */ strcpy(& aname[1], symbol->vname); td = make_array(); diff --git a/old-extension/fileop.c b/old-extension/fileop.c index 86f62576..d76a7ded 100644 --- a/old-extension/fileop.c +++ b/old-extension/fileop.c @@ -55,7 +55,7 @@ do_fread(int nargs) force_number(arg); rlen = get_number_ui(arg); - emalloc(rbuf, char *, rlen + 2, "do_fread"); + emalloc(rbuf, char *, rlen + 1, "do_fread"); if ((count = fread(rbuf, 1, rlen, f->fp)) < rlen) { if (! feof(f->fp)) update_ERRNO_int(errno); diff --git a/pc/ChangeLog b/pc/ChangeLog index fb5283ca..dc38023f 100644 --- a/pc/ChangeLog +++ b/pc/ChangeLog @@ -64,6 +64,10 @@ avoid warnings about 'usleep' in newer versions of mingw.org's MinGW runtime. +2016-01-28 Arnold D. Robbins <arnold@skeeve.com> + + * config.h: Updated to current. + 2015-05-29 Arnold D. Robbins <arnold@skeeve.com> * Makefile.tst (negtime): Sync with mainline. diff --git a/pc/config.h b/pc/config.h index 7251f1d0..1131414e 100644 --- a/pc/config.h +++ b/pc/config.h @@ -201,6 +201,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. */ #ifdef __MINGW32__ #define HAVE_SNPRINTF 1 @@ -378,6 +381,9 @@ #define HAVE_USLEEP 1 #endif +/* Define to 1 if you have the `waitpid' function. */ +#undef HAVE_WAITPID + /* Define to 1 if you have the <wchar.h> header file. */ #ifdef __MINGW32__ #define HAVE_WCHAR_H 1 @@ -422,9 +428,6 @@ /* enable severe portability problems */ #undef I_DONT_KNOW_WHAT_IM_DOING -/* libc is broken for regex handling */ -#undef LIBC_IS_BORKED - /* disable lint checks */ #undef NO_LINT @@ -438,7 +441,7 @@ #define PACKAGE_NAME "GNU Awk" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU Awk 4.1.3h" +#define PACKAGE_STRING "GNU Awk 4.1.60" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "gawk" @@ -447,18 +450,11 @@ #define PACKAGE_URL "http://www.gnu.org/software/gawk/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "4.1.3h" +#define PACKAGE_VERSION "4.1.60" /* Define to 1 if *printf supports %F format */ #undef PRINTF_HAS_F_FORMAT -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -#if defined(__DJGPP__) || defined(__MINGW32__) -#include <limits.h> -#endif - /* The size of `unsigned int', as computed by sizeof. */ #if UINT_MAX == 65536 #define SIZEOF_UNSIGNED_INT 2 @@ -512,7 +508,7 @@ /* Version number of package */ -#define VERSION "4.1.3h" +#define VERSION "4.1.60" /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt new file mode 100644 index 00000000..cd930077 --- /dev/null +++ b/po/CMakeLists.txt @@ -0,0 +1,133 @@ +# Most of this copied from the repository of Stellarium +# http://sourceforge.net/projects/stellarium/ + +# Special targets for translations: +# +# translations +# Converts all PO files to GMO files. Note that it does *not* update +# the PO files or the PO templates -- in fact, these files are never +# updated automatically. +# +# generate-pot +# Re-creates all POT files unconditionally. +# +# update-po +# Updates all PO files unconditionally. Note that it takes care of +# updating the POT files. +# +# translations-<DOMAIN> +# generate-pot-<DOMAIN> +# update-po-<DOMAIN> +# Same as above, but only affect the files in the corresponding +# po/<DOMAIN> directory. (DOMAIN is actually the base name of the POT +# file in the subdirectory, but that should match the directory name +# anyway.) + +ADD_CUSTOM_TARGET(translations) +ADD_CUSTOM_TARGET(generate-pot) +ADD_CUSTOM_TARGET(update-po) + +# GETTEXT_CREATE_TRANSLATIONS(domain [DEFAULT_TARGET] lang1 ... langN) +# +# Creates custom build rules to create and install (G)MO files for the +# specified languages. If the DEFAULT_TARGET option is used, the +# translations will also be created when building the default target. +# +# "domain" is the translation domain, eg. "gawk". A POT file +# with the name ${domain}.pot must exist in the directory of the +# CMakeLists.txt file invoking the macro. +# +# This macro also creates the "translations-${domain}" and +# "update-po-${domain}" targets (see above for an explanation). +# +MACRO(GETTEXT_CREATE_TRANSLATIONS _domain _firstLang) + + SET(_gmoFiles) + GET_FILENAME_COMPONENT(_absPotFile ${_domain}.pot ABSOLUTE) + + # Update these PO files when building the "update-po-<DOMAIN>" and + # "update-po" targets. + ADD_CUSTOM_TARGET(update-po-${_domain}) + ADD_DEPENDENCIES(update-po update-po-${_domain}) + + # Make sure the POT file is updated before updating the PO files. + ADD_DEPENDENCIES(update-po-${_domain} generate-pot-${_domain}) + + SET(_addToAll) + IF(${_firstLang} STREQUAL "DEFAULT_TARGET") + SET(_addToAll "ALL") + SET(_firstLang) + ENDIF(${_firstLang} STREQUAL "DEFAULT_TARGET") + + FOREACH (_lang ${ARGN}) + GET_FILENAME_COMPONENT(_absFile ${_lang}.po ABSOLUTE) + FILE(RELATIVE_PATH _relFile ${PROJECT_SOURCE_DIR} ${_absFile}) + SET(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo) + + # Convert a PO file into a GMO file. + ADD_CUSTOM_COMMAND( + OUTPUT ${_gmoFile} + COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_absFile} + DEPENDS ${_absFile} + ) + + # Update the PO file unconditionally when building the + # "update-po-<DOMAIN>" target. Note that to see the file being + # processed, we have to run "cmake -E echo", because the + # COMMENT is not displayed by cmake... + ADD_CUSTOM_COMMAND( + TARGET update-po-${_domain} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "** Updating ${_relFile}" + COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} + --quiet --update -m --backup=none -s + ${_absFile} ${_absPotFile} + VERBATIM + ) + + INSTALL(FILES ${_gmoFile} DESTINATION share/locale/${_lang}/LC_MESSAGES RENAME ${_domain}.mo) + SET(_gmoFiles ${_gmoFiles} ${_gmoFile}) + + ENDFOREACH (_lang) + + # Create the GMO files when building the "translations-<DOMAIN>" and + # "translations" targets. + ADD_CUSTOM_TARGET(translations-${_domain} ${_addToAll} DEPENDS ${_gmoFiles}) + ADD_DEPENDENCIES(translations translations-${_domain}) + +ENDMACRO(GETTEXT_CREATE_TRANSLATIONS ) + +SET(gawk_DOMAIN gawk) +SET(gawk_POT ${gawk_DOMAIN}.pot) + +file(READ LINGUAS linguas) +string(REGEX REPLACE "\n" ";" linguas ${linguas}) +GETTEXT_CREATE_TRANSLATIONS(${gawk_DOMAIN} DEFAULT_TARGET ${linguas}) + +ADD_CUSTOM_TARGET( + generate-pot-${gawk_DOMAIN} + ${GETTEXT_XGETTEXT_EXECUTABLE} + -o ${CMAKE_CURRENT_SOURCE_DIR}/${gawk_POT} + -C + --keyword=_ + --keyword=N_ + --keyword=q_ + --keyword=translate:2 + --add-comments=TRANSLATORS: + --directory=${CMAKE_BINARY_DIR} + --directory=${CMAKE_SOURCE_DIR} + --output-dir=${CMAKE_BINARY_DIR} + --files-from=${CMAKE_CURRENT_SOURCE_DIR}/POTFILES.in + --copyright-holder=FSF + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMENT "Generating ${gawk_POT}" + VERBATIM +) +# TODO: It would be nice to just depend on the exact files in POTFILES.in +#file(READ ${CMAKE_CURRENT_SOURCE_DIR}/${gawk_POT} UiHeaders) +#ADD_DEPENDENCIES(generate-pot-${gawk_DOMAIN} UiHeaders) +#ADD_DEPENDENCIES(generate-pot-${gawk_DOMAIN} gawk_UIS_H) +# Make sure the UI headers are created first. +ADD_DEPENDENCIES(generate-pot-${gawk_DOMAIN} StelGuiLib) # ??? FIXME +# Generate this POT file when building the "generate-pot" target. +ADD_DEPENDENCIES(generate-pot generate-pot-${gawk_DOMAIN}) @@ -26,17 +26,20 @@ #include "awk.h" static void pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags); +static INSTRUCTION *end_line(INSTRUCTION *ip); static void pp_parenthesize(NODE *n); static void parenthesize(int type, NODE *left, NODE *right); static char *pp_list(int nargs, const char *paren, const char *delim); static char *pp_group3(const char *s1, const char *s2, const char *s3); static char *pp_concat(int nargs); +static char *pp_string_or_strong_regex(const char *in_str, size_t len, int delim, bool strong_regex); +static char *pp_strong_regex(const char *in_str, size_t len, int delim); static bool is_binary(int type); static bool is_scalar(int type); static int prec_level(int type); static void pp_push(int type, char *s, int flag); static NODE *pp_pop(void); -static void pp_free(NODE *n); +static void print_comment(INSTRUCTION *pc, long in); const char *redir2str(int redirtype); #define pp_str vname @@ -46,8 +49,8 @@ const char *redir2str(int redirtype); #define DONT_FREE 1 #define CAN_FREE 2 -static RETSIGTYPE dump_and_exit(int signum) ATTRIBUTE_NORETURN; -static RETSIGTYPE just_dump(int signum); +static void dump_and_exit(int signum) ATTRIBUTE_NORETURN; +static void just_dump(int signum); /* pretty printing related functions and variables */ @@ -123,10 +126,12 @@ indent(long count) { int i; - if (count == 0) - fprintf(prof_fp, "\t"); - else - fprintf(prof_fp, "%6ld ", count); + if (do_profile) { + if (count == 0) + fprintf(prof_fp, "\t"); + else + fprintf(prof_fp, "%6ld ", count); + } assert(indent_level >= 0); for (i = 0; i < indent_level; i++) @@ -196,52 +201,94 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags) NODE *t1; char *str; NODE *t2; - INSTRUCTION *ip; + INSTRUCTION *ip1; + INSTRUCTION *ip2; NODE *m; char *tmp; int rule; static int rule_count[MAXRULE]; + static bool skip_comment = false; for (pc = startp; pc != endp; pc = pc->nexti) { if (pc->source_line > 0) sourceline = pc->source_line; + /* skip leading EOL comment as it has already been printed */ + if (pc->opcode == Op_comment + && pc->memory->comment_type == EOL_COMMENT + && skip_comment) { + skip_comment = false; + continue; + } + skip_comment = false; + switch (pc->opcode) { case Op_rule: + /* + * Rules are three instructions long. + * See append_rule in awkgram.y. + * The first has the Rule Op Code, nexti etc. + * The second, (pc + 1) has firsti and lasti: + * the first/last ACTION instructions for this rule. + * The third has first_line and last_line: + * the first and last source line numbers. + */ source = pc->source_file; rule = pc->in_rule; if (rule != Rule) { - if (! rule_count[rule]++) - fprintf(prof_fp, _("\t# %s rule(s)\n\n"), ruletab[rule]); - fprintf(prof_fp, "\t%s {\n", ruletab[rule]); - ip = (pc + 1)->firsti; + /* Allow for pre-non-rule-block comment */ + if (pc->nexti != (pc +1)->firsti + && pc->nexti->opcode == Op_comment + && pc->nexti->memory->comment_type == FULL_COMMENT) + print_comment(pc->nexti, -1); + ip1 = (pc + 1)->firsti; + ip2 = (pc + 1)->lasti; + + if (do_profile) { + if (! rule_count[rule]++) + fprintf(prof_fp, _("\t# %s rule(s)\n\n"), ruletab[rule]); + indent(0); + } + fprintf(prof_fp, "%s {", ruletab[rule]); + end_line(pc); + skip_comment = true; } else { - if (! rule_count[rule]++) + if (do_profile && ! rule_count[rule]++) fprintf(prof_fp, _("\t# Rule(s)\n\n")); - ip = pc->nexti; - indent(ip->exec_count); - if (ip != (pc + 1)->firsti) { /* non-empty pattern */ - pprint(ip->nexti, (pc + 1)->firsti, NO_PPRINT_FLAGS); - t1 = pp_pop(); - fprintf(prof_fp, "%s {", t1->pp_str); - pp_free(t1); - ip = (pc + 1)->firsti; - - if (do_profile && ip->exec_count > 0) - fprintf(prof_fp, " # %ld", ip->exec_count); - - fprintf(prof_fp, "\n"); + ip1 = pc->nexti; + indent(ip1->exec_count); + if (ip1 != (pc + 1)->firsti) { /* non-empty pattern */ + pprint(ip1->nexti, (pc + 1)->firsti, NO_PPRINT_FLAGS); + /* Allow for case where the "pattern" is just a comment */ + if (ip1->nexti->nexti->nexti != (pc +1)->firsti + || ip1->nexti->opcode != Op_comment) { + t1 = pp_pop(); + fprintf(prof_fp, "%s {", t1->pp_str); + pp_free(t1); + } else + fprintf(prof_fp, "{"); + ip1 = (pc + 1)->firsti; + ip2 = (pc + 1)->lasti; + + if (do_profile && ip1->exec_count > 0) + fprintf(prof_fp, " # %ld", ip1->exec_count); + + end_line(ip1); + skip_comment = true; } else { fprintf(prof_fp, "{\n"); - ip = (pc + 1)->firsti; + ip1 = (pc + 1)->firsti; + ip2 = (pc + 1)->lasti; } - ip = ip->nexti; + ip1 = ip1->nexti; } indent_in(); - pprint(ip, (pc + 1)->lasti, NO_PPRINT_FLAGS); + pprint(ip1, ip2, NO_PPRINT_FLAGS); indent_out(); - fprintf(prof_fp, "\t}\n\n"); + if (do_profile) + indent(0); + fprintf(prof_fp, "}\n\n"); pc = (pc + 1)->lasti; break; @@ -280,6 +327,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags) case Op_push_array: case Op_push: case Op_push_arg: + case Op_push_arg_untyped: m = pc->memory; switch (m->type) { case Node_param_list: @@ -326,7 +374,7 @@ cleanup: pp_free(t2); pp_free(t1); if ((flags & IN_FOR_HEADER) == 0) - fprintf(prof_fp, "\n"); + pc = end_line(pc); break; default: @@ -452,7 +500,7 @@ cleanup: pp_free(t2); pp_free(t1); if ((flags & IN_FOR_HEADER) == 0) - fprintf(prof_fp, "\n"); + pc = end_line(pc); break; case Op_concat: @@ -473,7 +521,7 @@ cleanup: } else fprintf(prof_fp, "%s %s", op2str(Op_K_delete), array); if ((flags & IN_FOR_HEADER) == 0) - fprintf(prof_fp, "\n"); + pc = end_line(pc); pp_free(t1); } break; @@ -585,18 +633,21 @@ cleanup: fprintf(prof_fp, "%s%s", op2str(pc->opcode), tmp); efree(tmp); if ((flags & IN_FOR_HEADER) == 0) - fprintf(prof_fp, "\n"); + pc = end_line(pc); break; case Op_push_re: - if (pc->memory->type != Node_regex) + if (pc->memory->type != Node_regex && pc->memory->type != Node_typedregex) break; /* else fall through */ case Op_match_rec: { NODE *re = pc->memory->re_exp; - str = pp_string(re->stptr, re->stlen, '/'); + if (pc->memory->type == Node_regex) + str = pp_string(re->stptr, re->stlen, '/'); + else + str = pp_strong_regex(re->stptr, re->stlen, '/'); pp_push(pc->opcode, str, CAN_FREE); } break; @@ -618,6 +669,11 @@ cleanup: txt = t2->pp_str; str = pp_group3(txt, op2str(pc->opcode), restr); pp_free(t2); + } else if (m->type == Node_typedregex) { + NODE *re = m->re_exp; + restr = pp_strong_regex(re->stptr, re->stlen, '/'); + str = pp_group3(txt, op2str(pc->opcode), restr); + efree(restr); } else { NODE *re = m->re_exp; restr = pp_string(re->stptr, re->stlen, '/'); @@ -686,7 +742,8 @@ cleanup: case Op_K_break: case Op_K_nextfile: case Op_K_next: - fprintf(prof_fp, "%s\n", op2str(pc->opcode)); + fprintf(prof_fp, "%s", op2str(pc->opcode)); + pc = end_line(pc); break; case Op_K_return: @@ -694,8 +751,10 @@ cleanup: t1 = pp_pop(); if (is_binary(t1->type)) pp_parenthesize(t1); - if (pc->source_line > 0) /* don't print implicit 'return' at end of function */ - fprintf(prof_fp, "%s %s\n", op2str(pc->opcode), t1->pp_str); + if (pc->source_line > 0) { /* don't print implicit 'return' at end of function */ + fprintf(prof_fp, "%s %s", op2str(pc->opcode), t1->pp_str); + pc = end_line(pc); + } pp_free(t1); break; @@ -703,73 +762,78 @@ cleanup: t1 = pp_pop(); fprintf(prof_fp, "%s", t1->pp_str); if ((flags & IN_FOR_HEADER) == 0) - fprintf(prof_fp, "\n"); + pc = end_line(pc); pp_free(t1); break; case Op_line_range: - ip = pc + 1; - pprint(pc->nexti, ip->condpair_left, NO_PPRINT_FLAGS); - pprint(ip->condpair_left->nexti, ip->condpair_right, NO_PPRINT_FLAGS); + ip1 = pc + 1; + pprint(pc->nexti, ip1->condpair_left, NO_PPRINT_FLAGS); + pprint(ip1->condpair_left->nexti, ip1->condpair_right, NO_PPRINT_FLAGS); t2 = pp_pop(); t1 = pp_pop(); str = pp_group3(t1->pp_str, ", ", t2->pp_str); pp_free(t1); pp_free(t2); pp_push(Op_line_range, str, CAN_FREE); - pc = ip->condpair_right; + pc = ip1->condpair_right; break; case Op_K_while: - ip = pc + 1; - indent(ip->while_body->exec_count); + ip1 = pc + 1; + indent(ip1->while_body->exec_count); fprintf(prof_fp, "%s (", op2str(pc->opcode)); - pprint(pc->nexti, ip->while_body, NO_PPRINT_FLAGS); + pprint(pc->nexti, ip1->while_body, NO_PPRINT_FLAGS); t1 = pp_pop(); - fprintf(prof_fp, "%s) {\n", t1->pp_str); + fprintf(prof_fp, "%s) {", t1->pp_str); pp_free(t1); + ip1->while_body = end_line(ip1->while_body); indent_in(); - pprint(ip->while_body->nexti, pc->target_break, NO_PPRINT_FLAGS); + pprint(ip1->while_body->nexti, pc->target_break, NO_PPRINT_FLAGS); indent_out(); indent(SPACEOVER); - fprintf(prof_fp, "}\n"); - pc = pc->target_break; + fprintf(prof_fp, "}"); + pc = end_line(pc->target_break); break; case Op_K_do: - ip = pc + 1; + ip1 = pc + 1; indent(pc->nexti->exec_count); - fprintf(prof_fp, "%s {\n", op2str(pc->opcode)); + fprintf(prof_fp, "%s {", op2str(pc->opcode)); + end_line(pc->nexti); + skip_comment = true; indent_in(); - pprint(pc->nexti->nexti, ip->doloop_cond, NO_PPRINT_FLAGS); + pprint(pc->nexti->nexti, ip1->doloop_cond, NO_PPRINT_FLAGS); indent_out(); - pprint(ip->doloop_cond, pc->target_break, NO_PPRINT_FLAGS); + pprint(ip1->doloop_cond, pc->target_break, NO_PPRINT_FLAGS); indent(SPACEOVER); t1 = pp_pop(); - fprintf(prof_fp, "} %s (%s)\n", op2str(Op_K_while), t1->pp_str); + fprintf(prof_fp, "} %s (%s)", op2str(Op_K_while), t1->pp_str); pp_free(t1); + end_line(pc->target_break); + skip_comment = true; pc = pc->target_break; break; case Op_K_for: - ip = pc + 1; - indent(ip->forloop_body->exec_count); + ip1 = pc + 1; + indent(ip1->forloop_body->exec_count); fprintf(prof_fp, "%s (", op2str(pc->opcode)); /* If empty for looop header, print it a little more nicely. */ if ( pc->nexti->opcode == Op_no_op - && ip->forloop_cond == pc->nexti + && ip1->forloop_cond == pc->nexti && pc->target_continue->opcode == Op_jmp) { fprintf(prof_fp, ";;"); } else { - pprint(pc->nexti, ip->forloop_cond, IN_FOR_HEADER); + pprint(pc->nexti, ip1->forloop_cond, IN_FOR_HEADER); fprintf(prof_fp, "; "); - if (ip->forloop_cond->opcode == Op_no_op && - ip->forloop_cond->nexti == ip->forloop_body) + if (ip1->forloop_cond->opcode == Op_no_op && + ip1->forloop_cond->nexti == ip1->forloop_body) fprintf(prof_fp, "; "); else { - pprint(ip->forloop_cond, ip->forloop_body, IN_FOR_HEADER); + pprint(ip1->forloop_cond, ip1->forloop_body, IN_FOR_HEADER); t1 = pp_pop(); fprintf(prof_fp, "%s; ", t1->pp_str); pp_free(t1); @@ -777,12 +841,16 @@ cleanup: pprint(pc->target_continue, pc->target_break, IN_FOR_HEADER); } - fprintf(prof_fp, ") {\n"); + fprintf(prof_fp, ") {"); + end_line(ip1->forloop_body); + skip_comment = true; indent_in(); - pprint(ip->forloop_body->nexti, pc->target_continue, NO_PPRINT_FLAGS); + pprint(ip1->forloop_body->nexti, pc->target_continue, NO_PPRINT_FLAGS); indent_out(); indent(SPACEOVER); - fprintf(prof_fp, "}\n"); + fprintf(prof_fp, "}"); + end_line(pc->target_break); + skip_comment = true; pc = pc->target_break; break; @@ -791,35 +859,39 @@ cleanup: char *array; const char *item; - ip = pc + 1; + ip1 = pc + 1; t1 = pp_pop(); array = t1->pp_str; - m = ip->forloop_cond->array_var; + m = ip1->forloop_cond->array_var; if (m->type == Node_param_list) item = func_params[m->param_cnt].param; else item = m->vname; - indent(ip->forloop_body->exec_count); - fprintf(prof_fp, "%s (%s%s%s) {\n", op2str(Op_K_arrayfor), + indent(ip1->forloop_body->exec_count); + fprintf(prof_fp, "%s (%s%s%s) {", op2str(Op_K_arrayfor), item, op2str(Op_in_array), array); + end_line(ip1->forloop_body); + skip_comment = true; indent_in(); pp_free(t1); - pprint(ip->forloop_body->nexti, pc->target_break, NO_PPRINT_FLAGS); + pprint(ip1->forloop_body->nexti, pc->target_break, NO_PPRINT_FLAGS); indent_out(); indent(SPACEOVER); - fprintf(prof_fp, "}\n"); + fprintf(prof_fp, "}"); + end_line(pc->target_break); + skip_comment = true; pc = pc->target_break; } break; case Op_K_switch: - ip = pc + 1; + ip1 = pc + 1; fprintf(prof_fp, "%s (", op2str(pc->opcode)); - pprint(pc->nexti, ip->switch_start, NO_PPRINT_FLAGS); + pprint(pc->nexti, ip1->switch_start, NO_PPRINT_FLAGS); t1 = pp_pop(); fprintf(prof_fp, "%s) {\n", t1->pp_str); pp_free(t1); - pprint(ip->switch_start, ip->switch_end, NO_PPRINT_FLAGS); + pprint(ip1->switch_start, ip1->switch_end, NO_PPRINT_FLAGS); indent(SPACEOVER); fprintf(prof_fp, "}\n"); pc = pc->target_break; @@ -830,10 +902,13 @@ cleanup: indent(pc->stmt_start->exec_count); if (pc->opcode == Op_K_case) { t1 = pp_pop(); - fprintf(prof_fp, "%s %s:\n", op2str(pc->opcode), t1->pp_str); + fprintf(prof_fp, "%s %s:", op2str(pc->opcode), t1->pp_str); + pc = end_line(pc); pp_free(t1); - } else - fprintf(prof_fp, "%s:\n", op2str(pc->opcode)); + } else { + fprintf(prof_fp, "%s:", op2str(pc->opcode)); + pc = end_line(pc); + } indent_in(); pprint(pc->stmt_start->nexti, pc->stmt_end->nexti, NO_PPRINT_FLAGS); indent_out(); @@ -846,17 +921,22 @@ cleanup: fprintf(prof_fp, "%s) {", t1->pp_str); pp_free(t1); - ip = pc->branch_if; - if (ip->exec_count > 0) - fprintf(prof_fp, " # %ld", ip->exec_count); - fprintf(prof_fp, "\n"); + ip1 = pc->branch_if; + if (ip1->exec_count > 0) + fprintf(prof_fp, " # %ld", ip1->exec_count); + ip1 = end_line(ip1); indent_in(); - pprint(ip->nexti, pc->branch_else, NO_PPRINT_FLAGS); + pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS); indent_out(); pc = pc->branch_else; if (pc->nexti->opcode == Op_no_op) { /* no following else */ indent(SPACEOVER); - fprintf(prof_fp, "}\n"); + fprintf(prof_fp, "}"); + if (pc->nexti->nexti->opcode != Op_comment + || pc->nexti->nexti->memory->comment_type == FULL_COMMENT) + fprintf(prof_fp, "\n"); + /* else + It will be printed at the top. */ } /* * See next case; turn off the flag so that the @@ -885,13 +965,22 @@ cleanup: && pc->branch_end == pc->nexti->nexti->branch_else->lasti) { pprint(pc->nexti, pc->branch_end, IN_ELSE_IF); } else { - fprintf(prof_fp, "{\n"); + fprintf(prof_fp, "{"); + end_line(pc); + skip_comment = true; indent_in(); pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS); indent_out(); indent(SPACEOVER); - fprintf(prof_fp, "}\n"); + fprintf(prof_fp, "}"); + end_line(pc->branch_end); + skip_comment = true; } + /* + * Don't do end_line() here, we get multiple blank lines after + * the final else in a chain of else-ifs since they all point + * to the same branch_end. + */ pc = pc->branch_end; break; @@ -901,11 +990,11 @@ cleanup: size_t len; pprint(pc->nexti, pc->branch_if, NO_PPRINT_FLAGS); - ip = pc->branch_if; - pprint(ip->nexti, pc->branch_else, NO_PPRINT_FLAGS); - ip = pc->branch_else->nexti; + ip1 = pc->branch_if; + pprint(ip1->nexti, pc->branch_else, NO_PPRINT_FLAGS); + ip1 = pc->branch_else->nexti; - pc = ip->nexti; + pc = ip1->nexti; assert(pc->opcode == Op_cond_exp); pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS); @@ -930,6 +1019,13 @@ cleanup: indent(pc->exec_count); break; + case Op_comment: + print_comment(pc, 0); + break; + + case Op_list: + break; + default: cant_happen(); } @@ -939,6 +1035,25 @@ cleanup: } } +/* end_line --- end pretty print line with new line or on-line comment */ + +INSTRUCTION * +end_line(INSTRUCTION *ip) +{ + INSTRUCTION *ret = ip; + + if (ip->nexti->opcode == Op_comment + && ip->nexti->memory->comment_type == EOL_COMMENT) { + fprintf(prof_fp, "\t"); + print_comment(ip->nexti, -1); + ret = ip->nexti; + } + else + fprintf(prof_fp, "\n"); + + return ret; +} + /* pp_string_fp --- printy print a string to the fp */ /* @@ -970,7 +1085,7 @@ pp_string_fp(Func_print print_func, FILE *fp, const char *in_str, /* just_dump --- dump the profile and function stack and keep going */ -static RETSIGTYPE +static void just_dump(int signum) { extern INSTRUCTION *code_block; @@ -984,7 +1099,7 @@ just_dump(int signum) /* dump_and_exit --- dump the profile, the function stack, and exit */ -static RETSIGTYPE +static void dump_and_exit(int signum) { just_dump(signum); @@ -1012,6 +1127,31 @@ print_lib_list(FILE *prof_fp) fprintf(prof_fp, "\n"); } +/* print_comment --- print comment text with proper indentation */ + +static void +print_comment(INSTRUCTION* pc, long in) +{ + char *text; + size_t count; + bool after_newline = false; + + count = pc->memory->stlen; + text = pc->memory->stptr; + + if (in >= 0) + indent(in); /* is this correct? Where should comments go? */ + for (; count > 0; count--, text++) { + if (after_newline) { + indent(in); + after_newline = false; + } + putc(*text, prof_fp); + if (*text == '\n') + after_newline = true; + } +} + /* dump_prog --- dump the program */ /* @@ -1026,7 +1166,8 @@ dump_prog(INSTRUCTION *code) (void) time(& now); /* \n on purpose, with \n in ctime() output */ - fprintf(prof_fp, _("\t# gawk profile, created %s\n"), ctime(& now)); + if (do_profile) + fprintf(prof_fp, _("\t# gawk profile, created %s\n"), ctime(& now)); print_lib_list(prof_fp); pprint(code, NULL, NO_PPRINT_FLAGS); } @@ -1265,11 +1406,27 @@ parenthesize(int type, NODE *left, NODE *right) pp_parenthesize(right); } -/* pp_string --- pretty format a string or regex constant */ +/* pp_string --- pretty format a string or regular regex constant */ char * pp_string(const char *in_str, size_t len, int delim) { + return pp_string_or_strong_regex(in_str, len, delim, false); +} + +/* pp_strong_regex --- pretty format a hard regex constant */ + +static char * +pp_strong_regex(const char *in_str, size_t len, int delim) +{ + return pp_string_or_strong_regex(in_str, len, delim, true); +} + +/* pp_string_or_strong_regex --- pretty format a string, regex, or hard regex constant */ + +char * +pp_string_or_strong_regex(const char *in_str, size_t len, int delim, bool strong_regex) +{ static char str_escapes[] = "\a\b\f\n\r\t\v\\"; static char str_printables[] = "abfnrtv\\"; static char re_escapes[] = "\a\b\f\n\r\t\v"; @@ -1301,11 +1458,15 @@ pp_string(const char *in_str, size_t len, int delim) osiz *= 2; \ } ofre -= (l) - osiz = len + 3 + 2; /* initial size; 3 for delim + terminating null */ + /* initial size; 3 for delim + terminating null, 1 for @ */ + osiz = len + 3 + 1 + (strong_regex == true); emalloc(obuf, char *, osiz, "pp_string"); obufout = obuf; ofre = osiz - 1; + if (strong_regex) + *obufout++ = '@'; + *obufout++ = delim; for (; len > 0; len--, str++) { chksize(2); /* make space for 2 chars */ @@ -1313,10 +1474,9 @@ pp_string(const char *in_str, size_t len, int delim) *obufout++ = '\\'; *obufout++ = delim; } else if (*str == '\0') { - chksize(4); - *obufout++ = '\\'; *obufout++ = '0'; + chksize(2); /* need 2 more chars for this case */ *obufout++ = '0'; *obufout++ = '0'; } else if ((cp = strchr(escapes, *str)) != NULL) { @@ -1326,7 +1486,7 @@ pp_string(const char *in_str, size_t len, int delim) /* NB: Deliberate use of lower-case versions. */ } else if (isascii(*str) && isprint(*str)) { *obufout++ = *str; - ofre += 1; + ofre += 1; /* used 1 less than expected */ } else { size_t len; @@ -1566,7 +1726,7 @@ pp_group3(const char *s1, const char *s2, const char *s3) len1 = strlen(s1); len2 = strlen(s2); len3 = strlen(s3); - l = len1 + len2 + len3 + 2; + l = len1 + len2 + len3 + 1; emalloc(str, char *, l, "pp_group3"); s = str; if (len1 > 0) { @@ -1594,14 +1754,24 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED) static bool first = true; NODE *func; int pcount; + INSTRUCTION *fp; if (first) { first = false; - fprintf(prof_fp, _("\n\t# Functions, listed alphabetically\n")); + if (do_profile) + fprintf(prof_fp, _("\n\t# Functions, listed alphabetically\n")); } + fp = pc->nexti->nexti; func = pc->func_body; fprintf(prof_fp, "\n"); + + /* print any function comment */ + if (fp->opcode == Op_comment && fp->source_line == 0) { + print_comment(fp, -1); /* -1 ==> don't indent */ + fp = fp->nexti; + } + indent(pc->nexti->exec_count); fprintf(prof_fp, "%s %s(", op2str(Op_K_function), func->vname); pcount = func->param_cnt; @@ -1611,11 +1781,21 @@ pp_func(INSTRUCTION *pc, void *data ATTRIBUTE_UNUSED) if (j < pcount - 1) fprintf(prof_fp, ", "); } - fprintf(prof_fp, ")\n\t{\n"); + if (fp->opcode == Op_comment + && fp->memory->comment_type == EOL_COMMENT) { + fprintf(prof_fp, ")"); + fp = end_line(fp); + } else + fprintf(prof_fp, ")\n"); + if (do_profile) + indent(0); + fprintf(prof_fp, "{\n"); indent_in(); - pprint(pc->nexti->nexti, NULL, NO_PPRINT_FLAGS); /* function body */ + pprint(fp, NULL, NO_PPRINT_FLAGS); /* function body */ indent_out(); - fprintf(prof_fp, "\t}\n"); + if (do_profile) + indent(0); + fprintf(prof_fp, "}\n"); return 0; } @@ -75,10 +75,10 @@ make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal) * from that. */ if (buf == NULL) { - emalloc(buf, char *, len + 2, "make_regexp"); + emalloc(buf, char *, len + 1, "make_regexp"); buflen = len; } else if (len > buflen) { - erealloc(buf, char *, len + 2, "make_regexp"); + erealloc(buf, char *, len + 1, "make_regexp"); buflen = len; } dest = buf; @@ -351,10 +351,14 @@ re_update(NODE *t) /* regex was compiled with settings matching IGNORECASE */ if ((t->re_flags & CONSTANT) != 0) { /* it's a constant, so just return it as is */ - assert(t->type == Node_regex); + assert(t->type == Node_regex || t->type == Node_typedregex); return t->re_reg; } t1 = t->re_exp; + if (t1->type == Node_typedregex) { + assert((t1->re_flags & CONSTANT) != 0); + return t1->re_reg; + } if (t->re_text != NULL) { /* if contents haven't changed, just return it */ if (cmp_nodes(t->re_text, t1) == 0) @@ -429,6 +433,15 @@ avoid_dfa(NODE *re, char *str, size_t len) { char *end; + /* + * f = @/.../ + * if ("foo" ~ f) ... + * + * This creates a Node_dynregex with NULL re_reg. + */ + if (re->re_reg == NULL) + return false; + if (! re->re_reg->has_anchor) return false; @@ -853,10 +853,6 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) #ifndef _LIBC char *codeset_name; #endif -#if defined(GAWK) && defined(LIBC_IS_BORKED) - /* Needed for brain damaged systems */ - extern int gawk_mb_cur_max; -#endif memset (dfa, '\0', sizeof (re_dfa_t)); @@ -878,11 +874,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); dfa->state_hash_mask = table_size - 1; -#if defined(GAWK) && defined(LIBC_IS_BORKED) - dfa->mb_cur_max = gawk_mb_cur_max; -#else dfa->mb_cur_max = MB_CUR_MAX; -#endif #ifdef _LIBC if (dfa->mb_cur_max == 6 && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) @@ -907,10 +899,6 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) if (strcasecmp (codeset_name, "UTF-8") == 0 || strcasecmp (codeset_name, "UTF8") == 0) dfa->is_utf8 = 1; -#if defined(GAWK) && defined(LIBC_IS_BORKED) - if (gawk_mb_cur_max == 1) - dfa->is_utf8 = 0; -#endif /* defined(GAWK) && defined(LIBC_IS_BORKED) */ /* We check exhaustively in the loop below if this charset is a superset of ASCII. */ @@ -470,7 +470,7 @@ typedef struct #ifdef __USE_GNU /* Sets the current default syntax to SYNTAX, and return the old syntax. You can also simply assign to the `re_syntax_options' variable. */ -extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); +extern reg_syntax_t re_set_syntax (reg_syntax_t syntax); /* Compile the regular expression PATTERN, with length LENGTH and syntax given by the global `re_syntax_options', into the buffer @@ -480,14 +480,14 @@ extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); Note that the translate table must either have been initialised by `regcomp', with a malloc'ed value, or set to NULL before calling `regfree'. */ -extern const char *re_compile_pattern (const char *__pattern, size_t __length, - struct re_pattern_buffer *__buffer); +extern const char *re_compile_pattern (const char *pattern, size_t length, + struct re_pattern_buffer *buffer); /* Compile a fastmap for the compiled pattern in BUFFER; used to accelerate searches. Return 0 if successful and -2 if was an internal error. */ -extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); +extern int re_compile_fastmap (struct re_pattern_buffer *buffer); /* Search in the string STRING (with length LENGTH) for the pattern @@ -495,30 +495,30 @@ extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); characters. Return the starting position of the match, -1 for no match, or -2 for an internal error. Also return register information in REGS (if REGS and BUFFER->no_sub are nonzero). */ -extern int re_search (struct re_pattern_buffer *__buffer, const char *__cstring, - int __length, int __start, int __range, - struct re_registers *__regs); +extern int re_search (struct re_pattern_buffer *buffer, const char *c_string, + int length, int start, int range, + struct re_registers *regs); /* Like `re_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ -extern int re_search_2 (struct re_pattern_buffer *__buffer, - const char *__string1, int __length1, - const char *__string2, int __length2, int __start, - int __range, struct re_registers *__regs, int __stop); +extern int re_search_2 (struct re_pattern_buffer *buffer, + const char *string1, int length1, + const char *string2, int length2, int start, + int range, struct re_registers *regs, int stop); /* Like `re_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ -extern int re_match (struct re_pattern_buffer *__buffer, const char *__cstring, - int __length, int __start, struct re_registers *__regs); +extern int re_match (struct re_pattern_buffer *buffer, const char *c_string, + int length, int start, struct re_registers *regs); /* Relates to `re_match' as `re_search_2' relates to `re_search'. */ -extern int re_match_2 (struct re_pattern_buffer *__buffer, - const char *__string1, int __length1, - const char *__string2, int __length2, int __start, - struct re_registers *__regs, int __stop); +extern int re_match_2 (struct re_pattern_buffer *buffer, + const char *string1, int length1, + const char *string2, int length2, int start, + struct re_registers *regs, int stop); /* Set REGS to hold NUM_REGS registers, storing them in STARTS and @@ -533,10 +533,10 @@ extern int re_match_2 (struct re_pattern_buffer *__buffer, Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ -extern void re_set_registers (struct re_pattern_buffer *__buffer, - struct re_registers *__regs, - unsigned int __num_regs, - regoff_t *__starts, regoff_t *__ends); +extern void re_set_registers (struct re_pattern_buffer *buffer, + struct re_registers *regs, + unsigned int num_regs, + regoff_t *starts, regoff_t *ends); #endif /* Use GNU */ #if defined _REGEX_RE_COMP || (defined _LIBC && defined __USE_MISC) @@ -569,19 +569,19 @@ extern int re_exec (const char *); #endif /* POSIX compatibility. */ -extern int regcomp (regex_t *__restrict __preg, - const char *__restrict __pattern, - int __cflags); +extern int regcomp (regex_t *__restrict preg, + const char *__restrict pattern, + int cflags); -extern int regexec (const regex_t *__restrict __preg, - const char *__restrict __cstring, size_t __nmatch, - regmatch_t __pmatch[__restrict_arr], - int __eflags); +extern int regexec (const regex_t *__restrict preg, + const char *__restrict c_string, size_t nmatch, + regmatch_t pmatch[__restrict_arr], + int eflags); -extern size_t regerror (int __errcode, const regex_t *__restrict __preg, - char *__restrict __errbuf, size_t __errbuf_size); +extern size_t regerror (int errcode, const regex_t *__restrict preg, + char *__restrict errbuf, size_t errbuf_size); -extern void regfree (regex_t *__preg); +extern void regfree (regex_t *preg); #ifdef __cplusplus diff --git a/str_array.c b/str_array.c index 460e2f1d..f66b22cc 100644 --- a/str_array.c +++ b/str_array.c @@ -70,6 +70,25 @@ afunc_t str_array_func[] = { (afunc_t) 0, }; +static NODE **env_remove(NODE *symbol, NODE *subs); +static NODE **env_store(NODE *symbol, NODE *subs); +static NODE **env_clear(NODE *symbol, NODE *subs); + +/* special case for ENVIRON */ +afunc_t env_array_func[] = { + str_array_init, + (afunc_t) 0, + null_length, + str_lookup, + str_exists, + env_clear, + env_remove, + str_list, + str_copy, + str_dump, + env_store, +}; + static inline NODE **str_find(NODE *symbol, NODE *s1, size_t code1, unsigned long hash1); static void grow_table(NODE *symbol); @@ -149,7 +168,7 @@ str_lookup(NODE *symbol, NODE *subs) * flag on it since other variables could be using the same * reference-counted value. */ - if (subs->stfmt != -1 || (subs->flags & MAYBE_NUM) != 0) { + if (subs->stfmt != STFMT_UNUSED || (subs->flags & MAYBE_NUM) != 0) { NODE *tmp; /* @@ -751,3 +770,63 @@ scramble(unsigned long x) return x; } + +/* env_remove --- for ENVIRON, remove value from real environment */ + +static NODE ** +env_remove(NODE *symbol, NODE *subs) +{ + NODE **val = str_remove(symbol, subs); + + if (val != NULL) + (void) unsetenv(subs->stptr); + + return val; +} + +/* env_clear --- clear out the environment when ENVIRON is deleted */ + +static NODE ** +env_clear(NODE *symbol, NODE *subs) +{ + extern char **environ; + NODE **val = str_clear(symbol, subs); + + environ = NULL; /* ZAP! */ + + /* str_clear zaps the vtable, reset it */ + symbol->array_funcs = env_array_func; + + return val; +} + +/* env_store --- post assign function for ENVIRON, put new value into env */ + +static NODE ** +env_store(NODE *symbol, NODE *subs) +{ + NODE **val = str_exists(symbol, subs); + const char *newval; + + assert(val != NULL); + + newval = (*val)->stptr; + if (newval == NULL) + newval = ""; + + (void) setenv(subs->stptr, newval, 1); + + return val; +} + +/* init_env_array --- set up the pointers for ENVIRON. A bit hacky. */ + +void +init_env_array(NODE *env_node) +{ + /* If POSIX simply don't reset the vtable and things work as before */ + if (do_posix) + return; + + env_node->array_funcs = env_array_func; +} @@ -652,7 +652,7 @@ check_param_names(void) memset(& n, 0, sizeof n); n.type = Node_val; n.flags = STRING|STRCUR; - n.stfmt = -1; + n.stfmt = STFMT_UNUSED; /* * assoc_list() returns an array with two elements per awk array diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..fee5eeca --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,90 @@ +# +# test/CMakeLists.txt --- CMake input file for gawk +# +# Copyright (C) 2013 +# the Free Software Foundation, Inc. +# +# This file is part of GAWK, the GNU implementation of the +# AWK Programming Language. +# +# GAWK is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GAWK is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +# + +## process this file with CMake to produce Makefile + +if(WIN32) + set(SHELL_PREFIX "C:\\MinGW\\msys\\1.0\\bin\\sh") +endif() + +# Find the names of the groups of tests in Makefile.am. +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/Makefile.am ALL_GROUPS) +string(REGEX MATCHALL "[A-Z_]*_TESTS " ALL_GROUPS "${ALL_GROUPS}") +string(REGEX REPLACE "_TESTS " ";" ALL_GROUPS "${ALL_GROUPS}") +# For each group of test cases, search through Makefile.am and find the test cases. +foreach(testgroup ${ALL_GROUPS} ) + file(READ ${CMAKE_CURRENT_SOURCE_DIR}/Makefile.am ONE_GROUP) + string(REGEX MATCH "${testgroup}_TESTS = [a-z0-9_ \\\n\t]*" ONE_GROUP "${ONE_GROUP}") + string(REGEX REPLACE "${testgroup}_TESTS = " "" ONE_GROUP "${ONE_GROUP}") + string(REGEX REPLACE "[\\\n\t]" "" ONE_GROUP "${ONE_GROUP}") + string(REGEX REPLACE " " ";" ONE_GROUP "${ONE_GROUP}") + # Use each name of a test case to start a script that executes the test case. + foreach(testcase ${ONE_GROUP} ) + add_test("${testgroup}.${testcase}" ${SHELL_PREFIX} ${CMAKE_SOURCE_DIR}/cmake/basictest ${CMAKE_BINARY_DIR}/gawk${CMAKE_EXECUTABLE_SUFFIX} ${testcase}) + endforeach(testcase) +endforeach(testgroup) + +# Create an empty configuration file for customizing test execution. +set(CTestCustom ${CMAKE_BINARY_DIR}/CTestCustom.cmake) +file(WRITE ${CTestCustom} "# DO NOT EDIT, THIS FILE WILL BE OVERWRITTEN\n" ) +# Test case SHLIB.filefuncs needs a file named gawkapi.o in source directory. +file(APPEND ${CTestCustom} "file(COPY ${CMAKE_SOURCE_DIR}/README DESTINATION ${CMAKE_SOURCE_DIR}/gawkapi.o)\n") +# Exclude test cases from execution that make no sense on a certain platform. +file(APPEND ${CTestCustom} "set(CTEST_CUSTOM_TESTS_IGNORE\n") +if(WIN32) + file(APPEND ${CTestCustom} " BASIC.exitval2\n") + file(APPEND ${CTestCustom} " BASIC.hsprint\n") + file(APPEND ${CTestCustom} " BASIC.rstest4\n") + file(APPEND ${CTestCustom} " BASIC.rstest5\n") + file(APPEND ${CTestCustom} " UNIX.getlnhd\n") + file(APPEND ${CTestCustom} " UNIX.pid\n") + file(APPEND ${CTestCustom} " GAWK_EXT.beginfile1\n") + file(APPEND ${CTestCustom} " GAWK_EXT.beginfile2\n") + file(APPEND ${CTestCustom} " GAWK_EXT.clos1way\n") + file(APPEND ${CTestCustom} " GAWK_EXT.devfd\n") + file(APPEND ${CTestCustom} " GAWK_EXT.devfd1\n") + file(APPEND ${CTestCustom} " GAWK_EXT.devfd2\n") + file(APPEND ${CTestCustom} " GAWK_EXT.getlndir\n") + file(APPEND ${CTestCustom} " GAWK_EXT.posix\n") + file(APPEND ${CTestCustom} " GAWK_EXT.pty1\n") + file(APPEND ${CTestCustom} " INET.inetdayu\n") + file(APPEND ${CTestCustom} " INET.inetdayt\n") + file(APPEND ${CTestCustom} " INET.inetechu\n") + file(APPEND ${CTestCustom} " INET.inetecht\n") + file(APPEND ${CTestCustom} " MACHINE.double2\n") + file(APPEND ${CTestCustom} " LOCALE_CHARSET.fmttest\n") + file(APPEND ${CTestCustom} " LOCALE_CHARSET.lc_num1\n") + file(APPEND ${CTestCustom} " LOCALE_CHARSET.mbfw1\n") + file(APPEND ${CTestCustom} " SHLIB.filefuncs\n") + file(APPEND ${CTestCustom} " SHLIB.fnmatch\n") + file(APPEND ${CTestCustom} " SHLIB.fork\n") + file(APPEND ${CTestCustom} " SHLIB.fork2\n") + file(APPEND ${CTestCustom} " SHLIB.fts\n") + file(APPEND ${CTestCustom} " SHLIB.functab4\n") + file(APPEND ${CTestCustom} " SHLIB.readdir\n") + file(APPEND ${CTestCustom} " SHLIB.revtwoway\n") + file(APPEND ${CTestCustom} " SHLIB.rwarray\n") +endif() +file(APPEND ${CTestCustom} ")\n") + diff --git a/test/ChangeLog b/test/ChangeLog index f7c28922..8b4d70e8 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,9 +1,29 @@ +2016-07-03 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * Makefile.am (rebuild): New test. + * rebuild.awk, rebuild.in, rebuild.ok: New files. + 2016-07-01 Arnold D. Robbins <arnold@skeeve.com> * arrayind1.awk, arrayind1.ok: Comment out prints to stderr to avoid buffer flushing on obscure systems. * dumpvars.ok, symtab6.ok, symtab8.ok: Update after code changes. +2016-06-26 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * strnum2.ok: Fix results, since print for a strnum should not be + affected by OFMT or CONVFMT. + +2016-06-22 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * strnum2.awk, strnum2.ok: Improve test case to show both OFMT and + CONVFMT conversions. + +2016-06-20 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * Makefile.am (strnum2): New test. + * strnum2.awk, strnum2.ok: New files. + 2016-06-14 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (subback): New test. @@ -21,6 +41,18 @@ * mixed1.ok: Adjust to match what the code produces. Thanks to John E. Malmberg <wb8tyw@qsl.net> for the report. +2016-06-13 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * Makefile.am (forcenum, ignrcas3, intarray, lintexp, lintindex, + lintint, lintlength, lintset, mpfrstrtonum, mpgforcenum, printfchar, + strtonum1): New tests. + * forcenum.awk, forcenum.ok, ignrcas3.awk, ignrcas3.ok, intarray.awk, + intarray.ok, lintexp.awk, lintexp.ok, lintindex.awk, lintindex.ok, + lintint.awk, lintint.ok, lintlength.awk, lintlength.ok, lintset.awk, + lintset.ok, mpfrstrtonum.awk, mpfrstrtonum.ok, mpgforcenum.awk, + mpgforcenum.ok, printfchar.awk, printfchar.ok, strtonum1.awk, + strtonum1.ok: New files. + 2016-06-08 Arnold D. Robbins <arnold@skeeve.com> * symtab10.awk, symtab10.in, symtab10.ok: New files. @@ -37,6 +69,12 @@ * Makefile.am (fsnul1): New test. * fsnul1.awk, fsnul1.in, fsnul1.ok: New files. +2016-05-26 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (arrayind2): New test. + * arrayind2.awk, arrayind2.ok: New files. + Thanks to Andrew J. Schorr <aschorr@telemetry-investments.com>. + 2016-05-25 Arnold D. Robbins <arnold@skeeve.com> * arrayind1.awk: Flush writes to stderr. We hope this helps @@ -87,6 +125,11 @@ * clos1way2.ok, clos1way3.ok, clos1way4.ok: Updated after code changes. +2016-04-06 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (clos1way6): New test. + * clos1way6.awk, clos1way6.ok: New files. + 2016-04-04 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (clos1way2, clos1way3, clos1way4, clos1way5): @@ -97,10 +140,32 @@ * clos1way2.awk: Add call to fflush() to test it too. * clos1way2.ok: Updated after code change. +2016-03-27 Arnold D. Robbins <arnold@skeeve.com> + + * profile5.ok: Adjust after code changes. + +2016-03-21 Arnold D. Robbins <arnold@skeeve.com> + + * profile5.ok, profile10.awk, profile10.ok: Adjust after code changes. + +2016-03-19 Arnold D. Robbins <arnold@skeeve.com> + + * profile5.ok: Adjust after code changes. + * Makefile.am (profile10): New test. + * profile10.awk, profile10.ok: New files. + 2016-02-18 Arnold D. Robbins <arnold@skeeve.com> * profile2.ok, profile5.ok: Adjust after code changes. +2016-02-05 Arnold D. Robbins <arnold@skeeve.com> + + * badargs.ok: Update after adding Yet Another Command Line Option. + +2016-01-28 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (EXTRA_DIST): Add profile9.awk and profile9.ok. + 2016-01-14 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (aryprm9): New test. @@ -112,9 +177,16 @@ 2015-12-27 Arnold D. Robbins <arnold@skeeve.com> + These came in from gawk-4.1-stable: + * Makefile.am (profile8): New test. * profile8.awk, profile8.ok: New files. + These used to be profile8: + + * Makefile.am (profile9): Renamed. + * profile9.awk, profile9.ok: Renamed files. + 2015-11-24 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (watchpoint1): New test. @@ -164,10 +236,65 @@ * Makefile.am (mbstr2): New test. * mbstr2.awk, mbstr2.in, mbstr2.ok: New files. +2015-06-29 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (dbugeval2, typedregex3): New tests. + * dbugeval2.awk, dbugeval2.in, dbugeval2.ok: New files. + * typedregex3.awk, typedregex3.ok: New files. + Thanks to Hermann Peifer for the reports. + +2015-06-28 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (typedregex2): New test. + * typedregex2.awk, typedregex2.ok: New files. + Thanks to Hermann Peifer for the report. + +2015-06-26 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (dbugtypedre1): Renamed from dbugtypedre. + (dbugtypedre2): New test. + * dbugtypedre1.awk, dbugtypedre1.in, dbugtypedre1.ok: Renamed files. + * dbugtypedre2.awk, dbugtypedre2.in, dbugtypedre2.ok: New files. + + Unrelated: + + * id.ok: Update after code changes. + + Unrelated: + + * Makefile.am (getfile, dbugtypedre1, dbugtypedre2): Fixed to + work if building out of the source tree. + + Unrelated: + + * dbugtypedre1.ok, typedregex1.awk, typeof1.ok, typeof3.ok: + Update after code changes. + 2015-06-25 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (negtime): Fix out-of-tree test run. + Unrelated: + + * Makefile.am (typeof3, typeof4): New tests. + * typeof2.awk, typeof2.ok, typeof3.awk, typeof3.ok: New files. + + Unrelated: + + * Makefile.am (dbugtypedre): New tests. + * dbugtypedre.awk, dbugtypedre.in, dbugtypedre.ok: New files. + +2015-06-21 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (typeof2): New test. + * typeof2.awk, typeof2.ok: New files. + +2015-06-19 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (gsubind, typedregex1, typeof1): New tests. + * gsubind.awk, gsubind.ok, typedregex1.awk, typedregex1.ok, + typeof1.awk, typeof1.ok: New files. + 2015-06-17 Andrew J. Schorr <aschorr@telemetry-investments.com> * inplace1.ok, inplace2.ok, inplace3.ok: Update line number in error @@ -217,6 +344,11 @@ * regexpbrack2.awk, regexpbrack2.in, regexpbrack2.ok: New files. Thanks to Nelson Beebe. +2015-04-16 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (shadowbuiltin): New test. + * shadowbuiltin.awk, shadowbuiltin.ok: New files. + 2015-04-14 Arnold D. Robbins <arnold@skeeve.com> * indirectbuiltin.awk: Add another test (gensub 3 args). @@ -241,11 +373,22 @@ * Makefile.am (mpfrmemok1): Use -p- for portability and compatibility with pc/Makefile.tst. +2015-04-02 Arnold D. Robbins <arnold@skeeve.com> + + * id.ok, mpfrsqrt.awk: Update after rename of div() --> intdiv(). + 2015-03-31 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (indirectbuiltin): New test. * indirectbuiltin.awk, indirectbuiltin.ok: New files. +2015-03-27 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am: Remove defvar test and reference to files; test + code moved into extension/testext.c. + * defvar.awk, defvar.ok: Removed. + * testext.ok: Updated. + 2015-03-24 Arnold D. Robbins <arnold@skeeve.com> * id.ok: Update after fixes in code. @@ -271,11 +414,38 @@ * Makefile.am (fpat4): New test. * fpat4.awk, fpat4.ok: New files. +2015-03-08 Arnold D. Robbins <arnold@skeeve.com> + + * nonfatal3.awk, nonfatal3.ok: Adjust for portability. + Thanks to Hermann Peifer for the report. + 2015-03-06 Arnold D. Robbins <arnold@skeeve.com> * charasbytes.awk, ofs1.awk, range1.awk, sortglos.awk, sortglos.in: Remove execute permission. +2015-03-02 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * nonfatal1.awk: Do not print ERRNO, since the value appears to be + platform-dependent. Instead, print (ERRNO != ""). + * nonfatal1.ok: Update. + +2015-02-28 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * Makefile.am (EXTRA_DIST): Add nonfatal3.{awk,ok}. + (GAWK_EXT_TESTS): Add nonfatal3. + * nonfatal1.awk: Replace "ti10/357" with "local:host/25", since + "local:host" should be a universally bad hostname due to the + invalid ":" character. + * nonfatal1.ok: Update. + * nonfatal3.{awk,ok}: New test for connecting to a TCP port where + nobody is listening. + +2015-02-27 Arnold D. Robbins <arnold@skeeve.com> + + * nonfatal1.ok: Update after code changes. + * id.ok: Updated after code change. + 2015-02-26 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (EXTRA_DIST): Add profile0.in which got forgotten @@ -291,6 +461,16 @@ * Makefile.am (profile0): New test. * profile0.awk, profile0.in, profile0.ok: New files. +2015-02-08 Arnold D. Robbins <arnold@skeeve.com> + + * nonfatal1.awk, nonfatal2.awk: String is now "NONFATAL". + +2015-02-06 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (nonfatal1, nonfatal2): New tests. + * nonfatal1.awk, nonfatal1.ok: New files. + * nonfatal2.awk, nonfatal2.ok: New files. + 2015-02-01 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (paramasfunc1, paramasfunc2): Now need --posix. @@ -304,6 +484,16 @@ * paramasfunc2.awk, paramasfunc2.ok: New files. * exit.sh, indirectcall.awk: Update after code change. +2015-01-19 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (profile8): Actually add the test and the files. + Thanks to Hermann Peifer for the report. + +2015-01-16 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (profile8): New test. + * profile8.awk, profile8.ok: New files. + 2015-01-14 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (dumpvars): Grep out ENVIRON and PROCINFO since @@ -324,6 +514,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. @@ -335,6 +553,10 @@ and exit 1. Should help distros to notice when they have built gawk incorrectly. (Can you say "Fedora", boys and girls?) +2014-12-12 Arnold D. Robbins <arnold@skeeve.com> + + * profile5.ok: Updated after code changes. + 2014-11-26 Arnold D. Robbins <arnold@skeeve.com> * Gentests: Fix gensub call after adding warning. @@ -347,12 +569,17 @@ * Makefile.am (sortglos): New test. * sortglos.awk, sortglos.in, sortglos.ok: New files. + Thanks to Antonio Columbo. 2014-11-09 Arnold D. Robbins <arnold@skeeve.com> * 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. @@ -404,6 +631,16 @@ * filefuncs.awk: Change to build directory instead of "..". * Makefile.am (filefuncs): Pass in $(abs_top_builddir). +2014-09-13 Stephen Davies <sdavies@sdc.com.au> + + * Makefile.am (profile4, profile5): Changes processing to not delete + the first two lines. This is no longer needed. + * profile4.ok, profile5.ok: Changed to suit new rules and comments. + +2014-09-10 Arnold D. Robbins <arnold@skeeve.com> + + * profile2.ok, profile4.ok, profile5.ok: Update for new code. + 2014-09-05 Arnold D. Robbins <arnold@skeeve.com> * functab4.awk: Changed to use stat instead of chdir since @@ -450,6 +687,11 @@ * printhuge.awk, printhuge.ok: New files. Test from mail.green.fox@gmail.com. +2014-06-24 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (profile1, profile4, profile5): Adjust for change to + --pretty-print option. + 2014-06-19 Michael Forney <forney@google.com> * Makefile.am (poundbang): Fix relative path of AWKPROG. @@ -666,6 +908,12 @@ * Makefile.am (badassign1): New test. * badassign1.awk, badassign1.ok: New files. +2013-09-25 Arnold D. Robbins <arnold@skeeve.com> + + * Makfile.am (randtest): New test. + * randtest.sh, randtest.ok: New files. + * rand.ok: Updated to reflect new results based on code change. + 2013-09-13 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am: Fix quoting for generation of Maketests file so @@ -682,6 +930,10 @@ in locations with spaces in their names (think Windows or Mac OS X). * Gentests: Ditto for when creating Maketests file. +2013-07-30 Arnold D. Robbins <arnold@skeeve.com> + + * profile2.ok, profile5.ok: Update. + 2013-07-04 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (mbprintf4): New test. diff --git a/test/Makefile.am b/test/Makefile.am index 34cc954b..3a51b3ff 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -55,6 +55,8 @@ EXTRA_DIST = \ arrayind1.awk \ arrayind1.in \ arrayind1.ok \ + arrayind2.awk \ + arrayind2.ok \ arrayparm.awk \ arrayparm.ok \ arrayprm2.awk \ @@ -159,6 +161,8 @@ EXTRA_DIST = \ clos1way4.ok \ clos1way5.awk \ clos1way5.ok \ + clos1way6.awk \ + clos1way6.ok \ closebad.awk \ closebad.ok \ clsflnam.awk \ @@ -191,6 +195,15 @@ EXTRA_DIST = \ datanonl.ok \ dbugeval.in \ dbugeval.ok \ + dbugeval2.awk \ + dbugeval2.in \ + dbugeval2.ok \ + dbugtypedre1.awk \ + dbugtypedre1.in \ + dbugtypedre1.ok \ + dbugtypedre2.awk \ + dbugtypedre2.in \ + dbugtypedre2.ok \ defref.awk \ defref.ok \ delargv.awk \ @@ -227,6 +240,9 @@ EXTRA_DIST = \ dynlj.ok \ eofsplit.awk \ eofsplit.ok \ + errno.awk \ + errno.in \ + errno.ok \ exit.ok \ exit.sh \ exit2.awk \ @@ -284,6 +300,8 @@ EXTRA_DIST = \ fnparydl-mpfr.ok \ fnparydl.awk \ fnparydl.ok \ + forcenum.awk \ + forcenum.ok \ fordel.awk \ fordel.ok \ fork.awk \ @@ -363,6 +381,8 @@ EXTRA_DIST = \ gensub.ok \ gensub2.awk \ gensub2.ok \ + getfile.awk \ + getfile.ok \ getline.awk \ getline.in \ getline.ok \ @@ -396,6 +416,8 @@ EXTRA_DIST = \ gnureops.ok \ gsubasgn.awk \ gsubasgn.ok \ + gsubind.awk \ + gsubind.ok \ gsubtest.awk \ gsubtest.ok \ gsubtst2.awk \ @@ -443,6 +465,8 @@ EXTRA_DIST = \ igncfs.ok \ ignrcas2.awk \ ignrcas2.ok \ + ignrcas3.awk \ + ignrcas3.ok \ ignrcase.awk \ ignrcase.in \ ignrcase.ok \ @@ -485,6 +509,8 @@ EXTRA_DIST = \ inplace3.2.bak.ok \ inputred.awk \ inputred.ok \ + intarray.awk \ + intarray.ok \ intest.awk \ intest.ok \ intformat.awk \ @@ -506,9 +532,19 @@ EXTRA_DIST = \ leadnl.ok \ lint.awk \ lint.ok \ + lintexp.awk \ + lintexp.ok \ + lintindex.awk \ + lintindex.ok \ + lintint.awk \ + lintint.ok \ + lintlength.awk \ + lintlength.ok \ lintold.awk \ lintold.in \ lintold.ok \ + lintset.awk \ + lintset.ok \ lintwarn.awk \ lintwarn.ok \ litoct.awk \ @@ -588,6 +624,10 @@ EXTRA_DIST = \ mpfrsort.ok \ mpfrsqrt.awk \ mpfrsqrt.ok \ + mpfrstrtonum.awk \ + mpfrstrtonum.ok \ + mpgforcenum.awk \ + mpgforcenum.ok \ mtchi18n.awk \ mtchi18n.in \ mtchi18n.ok \ @@ -641,6 +681,12 @@ EXTRA_DIST = \ nondec.ok \ nondec2.awk \ nondec2.ok \ + nonfatal1.awk \ + nonfatal1.ok \ + nonfatal2.awk \ + nonfatal2.ok \ + nonfatal3.awk \ + nonfatal3.ok \ nonl.awk \ nonl.ok \ noparms.awk \ @@ -746,6 +792,8 @@ EXTRA_DIST = \ printfbad3.ok \ printfbad4.awk \ printfbad4.ok \ + printfchar.awk \ + printfchar.ok \ printfloat.awk \ printhuge.awk \ printhuge.ok \ @@ -772,6 +820,10 @@ EXTRA_DIST = \ profile7.ok \ profile8.awk \ profile8.ok \ + profile9.awk \ + profile9.ok \ + profile10.awk \ + profile10.ok \ prt1eval.awk \ prt1eval.ok \ prtoeval.awk \ @@ -781,6 +833,8 @@ EXTRA_DIST = \ rand-mpfr.ok \ rand.awk \ rand.ok \ + randtest.sh \ + randtest.ok \ range1.awk \ range1.in \ range1.ok \ @@ -800,6 +854,9 @@ EXTRA_DIST = \ rebuf.awk \ rebuf.in \ rebuf.ok \ + rebuild.awk \ + rebuild.in \ + rebuild.ok \ redfilnm.awk \ redfilnm.in \ redfilnm.ok \ @@ -900,6 +957,8 @@ EXTRA_DIST = \ sclifin.ok \ shadow.awk \ shadow.ok \ + shadowbuiltin.awk \ + shadowbuiltin.ok \ sigpipe1.awk \ sigpipe1.ok \ sort1.awk \ @@ -943,11 +1002,15 @@ EXTRA_DIST = \ strftlng.ok \ strnum1.awk \ strnum1.ok \ + strnum2.awk \ + strnum2.ok \ strtod.awk \ strtod.in \ strtod.ok \ strtonum.awk \ strtonum.ok \ + strtonum1.awk \ + strtonum1.ok \ subamp.awk \ subamp.in \ subamp.ok \ @@ -999,12 +1062,28 @@ EXTRA_DIST = \ testext.ok \ time.awk \ time.ok \ + timeout.awk \ + timeout.ok \ tradanch.awk \ tradanch.in \ tradanch.ok \ tweakfld.awk \ tweakfld.in \ tweakfld.ok \ + typedregex1.awk \ + typedregex1.ok \ + typedregex2.awk \ + typedregex2.ok \ + typedregex3.awk \ + typedregex3.ok \ + typeof1.awk \ + typeof1.ok \ + typeof2.awk \ + typeof2.ok \ + typeof3.awk \ + typeof3.ok \ + typeof4.awk \ + typeof4.ok \ uninit2.awk \ uninit2.ok \ uninit3.awk \ @@ -1058,7 +1137,7 @@ CLEANFILES = core core.* fmtspcl.ok # try to keep these sorted. each letter starts a new line BASIC_TESTS = \ - addcomma anchgsub argarray arrayind1 arrayparm arrayprm2 arrayprm3 \ + addcomma anchgsub argarray arrayind1 arrayind2 arrayparm arrayprm2 arrayprm3 \ arrayref arrymem1 arryref2 arryref3 arryref4 arryref5 arynasty \ arynocls aryprm1 aryprm2 aryprm3 aryprm4 aryprm5 aryprm6 aryprm7 \ aryprm8 aryprm9 arysubnm asgext awkpath \ @@ -1083,15 +1162,15 @@ BASIC_TESTS = \ octsub ofmt ofmta ofmtbig ofmtfidl ofmts ofs1 onlynl opasnidx opasnslf \ paramasfunc1 paramasfunc2 \ paramdup paramres paramtyp paramuninitglobal parse1 parsefld parseme \ - pcntplus posix2008sub prdupval prec printf0 printf1 prmarscl prmreuse \ + pcntplus posix2008sub prdupval prec printf0 printf1 printfchar prmarscl prmreuse \ prt1eval prtoeval \ - rand range1 readbuf rebrackloc rebt8b1 redfilnm \ + rand randtest range1 readbuf rebrackloc rebt8b1 rebuild redfilnm \ regeq regexpbrack regexpbrack2 \ regexprange regrange reindops \ reparse resplit rri1 rs rscompat rsnul1nl rsnulbig rsnulbig2 rstest1 rstest2 \ rstest3 rstest4 rstest5 rswhite \ scalar sclforin sclifin sigpipe1 sortempty sortglos splitargv splitarr splitdef \ - splitvar splitwht strcat1 strnum1 strtod subamp subback subi18n \ + splitvar splitwht strcat1 strnum1 strnum2 strtod subamp subback subi18n \ subsepnm subslash substr swaplns synerr1 synerr2 tradanch tweakfld \ uninit2 uninit3 uninit4 uninit5 uninitialized unterm uparrfs \ wideidx wideidx2 widesub widesub2 widesub3 widesub4 wjposer1 \ @@ -1104,26 +1183,31 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ backw badargs beginfile1 beginfile2 binmode1 charasbytes \ - colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 \ - crlf dbugeval delsub devfd devfd1 devfd2 dumpvars exit \ - fieldwdth fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \ + colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 clos1way6 \ + crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \ + devfd devfd1 devfd2 dumpvars errno exit \ + fieldwdth forcenum fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \ functab1 functab2 functab3 fwtest fwtest2 fwtest3 \ - genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops \ - icasefs icasers id igncdym igncfs ignrcas2 ignrcase \ + genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops gsubind \ + icasefs icasers id igncdym igncfs ignrcas2 ignrcas3 ignrcase \ incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \ - include include2 indirectbuiltin indirectcall indirectcall2 \ - lint lintold lintwarn \ + include include2 indirectbuiltin indirectcall indirectcall2 intarray \ + lint lintexp lintindex lintint lintlength lintold lintset lintwarn \ mixed1 manyfiles match1 match2 match3 mbstr1 mbstr2 \ muldimposix \ nastyparm negtime next nondec nondec2 \ + nonfatal1 nonfatal2 nonfatal3 \ patsplit posix printfbad1 printfbad2 printfbad3 printfbad4 printhuge procinfs \ - profile0 profile1 profile2 profile3 profile4 profile5 profile6 \ - profile7 profile8 pty1 \ + profile0 profile1 profile2 profile3 profile4 profile5 profile6 profile7 \ + profile8 profile9 profile10 pty1 \ rebuf regnul1 regnul2 regx8bit reginttrad reint reint2 rsgetline rsglstdin rsstart1 \ - rsstart2 rsstart3 rstest6 shadow sortfor sortu split_after_fpat \ + rsstart2 rsstart3 rstest6 shadow shadowbuiltin \ + sortfor sortu split_after_fpat \ splitarg4 strftime \ - strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \ + strtonum strtonum1 switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \ symtab7 symtab8 symtab9 symtab10 \ + typedregex1 typedregex2 typedregex3 typeof1 typeof2 typeof3 typeof4 \ + timeout \ watchpoint1 EXTRA_TESTS = inftest regtest @@ -1133,7 +1217,7 @@ INET_TESTS = inetdayu inetdayt inetechu inetecht MACHINE_TESTS = double1 double2 fmtspcl intformat MPFR_TESTS = mpfrnr mpfrnegzero mpfrmemok1 mpfrrem mpfrrnd mpfrieee \ - mpfrexprange mpfrsort mpfrsqrt mpfrbigint + mpfrexprange mpfrsort mpfrsqrt mpfrbigint mpfrstrtonum mpgforcenum LOCALE_CHARSET_TESTS = \ asort asorti backbigs1 backsmalls1 backsmalls2 \ @@ -1141,12 +1225,12 @@ LOCALE_CHARSET_TESTS = \ mbprintf1 mbprintf2 mbprintf3 mbprintf4 rebt8b2 rtlenmb sort1 sprintfc SHLIB_TESTS = \ - fnmatch filefuncs fork fork2 fts functab4 inplace1 inplace2 inplace3 \ + 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: NEED_LINT = \ - defref fmtspcl lintwarn noeffect nofmtch shadow \ + defref fmtspcl lintexp lintindex lintint lintlength lintwarn noeffect nofmtch shadow \ uninit2 uninit3 uninit4 uninit5 uninitialized # List of the tests which should be run with --lint-old option: @@ -1414,6 +1498,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 >_$@ @@ -1668,6 +1757,16 @@ nondec2:: @$(AWK) --non-decimal-data -v a=0x1 -f "$(srcdir)"/$@.awk >_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +intarray:: + @echo $@ + @$(AWK) --non-decimal-data -f "$(srcdir)"/$@.awk >_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +forcenum:: + @echo $@ + @$(AWK) --non-decimal-data -f "$(srcdir)"/$@.awk >_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + nofile:: @echo $@ @$(AWK) '{}' no/such/file >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1797,10 +1896,11 @@ profile0: profile1: @echo $@ - @$(AWK) --pretty-print=ap-$@.out -f "$(srcdir)"/xref.awk "$(srcdir)"/dtdgport.awk > _$@.out1 + @$(AWK) -f "$(srcdir)"/xref.awk "$(srcdir)"/dtdgport.awk > _$@.out1 + @$(AWK) --pretty-print=ap-$@.out -f "$(srcdir)"/xref.awk @$(AWK) -f ./ap-$@.out "$(srcdir)"/dtdgport.awk > _$@.out2 ; rm ap-$@.out @$(CMP) _$@.out1 _$@.out2 && rm _$@.out[12] || { echo EXIT CODE: $$? >>_$@ ; \ - cp "$(srcdir)"/dtdgport.awk > $@.ok ; } + cp "$(srcdir)"/dtdgport.awk $@.ok ; } profile2: @@ -1817,14 +1917,12 @@ profile3: profile4: @echo $@ - @GAWK_NO_PP_RUN=1 $(AWK) --profile=ap-$@.out -f "$(srcdir)"/$@.awk > /dev/null - @sed 1,2d < ap-$@.out > _$@; rm ap-$@.out + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ profile5: @echo $@ - @GAWK_NO_PP_RUN=1 $(AWK) --profile=ap-$@.out -f "$(srcdir)"/$@.awk > /dev/null - @sed 1,2d < ap-$@.out > _$@; rm ap-$@.out + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ profile6: @@ -1841,8 +1939,17 @@ profile7: profile8: @echo $@ - @$(AWK) --pretty=ap-$@.out -f "$(srcdir)"/$@.awk < /dev/null - @sed 1,2d < ap-$@.out > _$@; rm ap-$@.out + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +profile9: + @echo $@ + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +profile10: + @echo $@ + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ posix2008sub: @@ -1906,6 +2013,16 @@ mpfrsqrt: @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1 @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +mpfrstrtonum: + @echo $@ + @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +mpgforcenum: + @echo $@ + @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + mpfrrem: @echo $@ @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1 @@ -2015,6 +2132,11 @@ testext:: @$(AWK) -f ./testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ testext.awk +getfile: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -v TESTEXT_QUIET=1 -ltestext -f $@.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.; \ @@ -2089,6 +2211,12 @@ dfamb1: AWKPATH="$(srcdir)" $(AWK) -f $@.awk "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +randtest:: + @echo $@ + @GAWK="$(AWKPROG)" "$(srcdir)"/randtest.sh >_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + backbigs1: @echo $@ @[ -z "$$GAWKLOCALE" ] && GAWKLOCALE=en_US.UTF-8; \ @@ -2145,6 +2273,21 @@ negtime:: @TZ=GMT AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @AWKPATH="$(srcdir)" $(AWK) -f checknegtime.awk "$(srcdir)"/$@.ok _$@ && rm -f _$@ +dbugtypedre1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -D -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +dbugtypedre2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -D -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +dbugeval2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -D -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + muldimposix:: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ diff --git a/test/Makefile.in b/test/Makefile.in index 5baefb40..29064326 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -115,14 +115,14 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/arch.m4 \ $(top_srcdir)/m4/codeset.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ - $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lcmessage.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libsigsegv.m4 \ - $(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/mpfr.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/noreturn.m4 \ - $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/m4/readline.m4 $(top_srcdir)/m4/socket.m4 \ - $(top_srcdir)/m4/ulonglong.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libsigsegv.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/mpfr.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/noreturn.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/readline.m4 \ + $(top_srcdir)/m4/socket.m4 $(top_srcdir)/m4/ulonglong.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) @@ -312,6 +312,8 @@ EXTRA_DIST = \ arrayind1.awk \ arrayind1.in \ arrayind1.ok \ + arrayind2.awk \ + arrayind2.ok \ arrayparm.awk \ arrayparm.ok \ arrayprm2.awk \ @@ -416,6 +418,8 @@ EXTRA_DIST = \ clos1way4.ok \ clos1way5.awk \ clos1way5.ok \ + clos1way6.awk \ + clos1way6.ok \ closebad.awk \ closebad.ok \ clsflnam.awk \ @@ -448,6 +452,15 @@ EXTRA_DIST = \ datanonl.ok \ dbugeval.in \ dbugeval.ok \ + dbugeval2.awk \ + dbugeval2.in \ + dbugeval2.ok \ + dbugtypedre1.awk \ + dbugtypedre1.in \ + dbugtypedre1.ok \ + dbugtypedre2.awk \ + dbugtypedre2.in \ + dbugtypedre2.ok \ defref.awk \ defref.ok \ delargv.awk \ @@ -484,6 +497,9 @@ EXTRA_DIST = \ dynlj.ok \ eofsplit.awk \ eofsplit.ok \ + errno.awk \ + errno.in \ + errno.ok \ exit.ok \ exit.sh \ exit2.awk \ @@ -541,6 +557,8 @@ EXTRA_DIST = \ fnparydl-mpfr.ok \ fnparydl.awk \ fnparydl.ok \ + forcenum.awk \ + forcenum.ok \ fordel.awk \ fordel.ok \ fork.awk \ @@ -620,6 +638,8 @@ EXTRA_DIST = \ gensub.ok \ gensub2.awk \ gensub2.ok \ + getfile.awk \ + getfile.ok \ getline.awk \ getline.in \ getline.ok \ @@ -653,6 +673,8 @@ EXTRA_DIST = \ gnureops.ok \ gsubasgn.awk \ gsubasgn.ok \ + gsubind.awk \ + gsubind.ok \ gsubtest.awk \ gsubtest.ok \ gsubtst2.awk \ @@ -700,6 +722,8 @@ EXTRA_DIST = \ igncfs.ok \ ignrcas2.awk \ ignrcas2.ok \ + ignrcas3.awk \ + ignrcas3.ok \ ignrcase.awk \ ignrcase.in \ ignrcase.ok \ @@ -742,6 +766,8 @@ EXTRA_DIST = \ inplace3.2.bak.ok \ inputred.awk \ inputred.ok \ + intarray.awk \ + intarray.ok \ intest.awk \ intest.ok \ intformat.awk \ @@ -763,9 +789,19 @@ EXTRA_DIST = \ leadnl.ok \ lint.awk \ lint.ok \ + lintexp.awk \ + lintexp.ok \ + lintindex.awk \ + lintindex.ok \ + lintint.awk \ + lintint.ok \ + lintlength.awk \ + lintlength.ok \ lintold.awk \ lintold.in \ lintold.ok \ + lintset.awk \ + lintset.ok \ lintwarn.awk \ lintwarn.ok \ litoct.awk \ @@ -845,6 +881,10 @@ EXTRA_DIST = \ mpfrsort.ok \ mpfrsqrt.awk \ mpfrsqrt.ok \ + mpfrstrtonum.awk \ + mpfrstrtonum.ok \ + mpgforcenum.awk \ + mpgforcenum.ok \ mtchi18n.awk \ mtchi18n.in \ mtchi18n.ok \ @@ -898,6 +938,12 @@ EXTRA_DIST = \ nondec.ok \ nondec2.awk \ nondec2.ok \ + nonfatal1.awk \ + nonfatal1.ok \ + nonfatal2.awk \ + nonfatal2.ok \ + nonfatal3.awk \ + nonfatal3.ok \ nonl.awk \ nonl.ok \ noparms.awk \ @@ -1003,6 +1049,8 @@ EXTRA_DIST = \ printfbad3.ok \ printfbad4.awk \ printfbad4.ok \ + printfchar.awk \ + printfchar.ok \ printfloat.awk \ printhuge.awk \ printhuge.ok \ @@ -1029,6 +1077,10 @@ EXTRA_DIST = \ profile7.ok \ profile8.awk \ profile8.ok \ + profile9.awk \ + profile9.ok \ + profile10.awk \ + profile10.ok \ prt1eval.awk \ prt1eval.ok \ prtoeval.awk \ @@ -1038,6 +1090,8 @@ EXTRA_DIST = \ rand-mpfr.ok \ rand.awk \ rand.ok \ + randtest.sh \ + randtest.ok \ range1.awk \ range1.in \ range1.ok \ @@ -1057,6 +1111,9 @@ EXTRA_DIST = \ rebuf.awk \ rebuf.in \ rebuf.ok \ + rebuild.awk \ + rebuild.in \ + rebuild.ok \ redfilnm.awk \ redfilnm.in \ redfilnm.ok \ @@ -1157,6 +1214,8 @@ EXTRA_DIST = \ sclifin.ok \ shadow.awk \ shadow.ok \ + shadowbuiltin.awk \ + shadowbuiltin.ok \ sigpipe1.awk \ sigpipe1.ok \ sort1.awk \ @@ -1200,11 +1259,15 @@ EXTRA_DIST = \ strftlng.ok \ strnum1.awk \ strnum1.ok \ + strnum2.awk \ + strnum2.ok \ strtod.awk \ strtod.in \ strtod.ok \ strtonum.awk \ strtonum.ok \ + strtonum1.awk \ + strtonum1.ok \ subamp.awk \ subamp.in \ subamp.ok \ @@ -1256,12 +1319,28 @@ EXTRA_DIST = \ testext.ok \ time.awk \ time.ok \ + timeout.awk \ + timeout.ok \ tradanch.awk \ tradanch.in \ tradanch.ok \ tweakfld.awk \ tweakfld.in \ tweakfld.ok \ + typedregex1.awk \ + typedregex1.ok \ + typedregex2.awk \ + typedregex2.ok \ + typedregex3.awk \ + typedregex3.ok \ + typeof1.awk \ + typeof1.ok \ + typeof2.awk \ + typeof2.ok \ + typeof3.awk \ + typeof3.ok \ + typeof4.awk \ + typeof4.ok \ uninit2.awk \ uninit2.ok \ uninit3.awk \ @@ -1314,7 +1393,7 @@ CLEANFILES = core core.* fmtspcl.ok # try to keep these sorted. each letter starts a new line BASIC_TESTS = \ - addcomma anchgsub argarray arrayind1 arrayparm arrayprm2 arrayprm3 \ + addcomma anchgsub argarray arrayind1 arrayind2 arrayparm arrayprm2 arrayprm3 \ arrayref arrymem1 arryref2 arryref3 arryref4 arryref5 arynasty \ arynocls aryprm1 aryprm2 aryprm3 aryprm4 aryprm5 aryprm6 aryprm7 \ aryprm8 aryprm9 arysubnm asgext awkpath \ @@ -1339,15 +1418,15 @@ BASIC_TESTS = \ octsub ofmt ofmta ofmtbig ofmtfidl ofmts ofs1 onlynl opasnidx opasnslf \ paramasfunc1 paramasfunc2 \ paramdup paramres paramtyp paramuninitglobal parse1 parsefld parseme \ - pcntplus posix2008sub prdupval prec printf0 printf1 prmarscl prmreuse \ + pcntplus posix2008sub prdupval prec printf0 printf1 printfchar prmarscl prmreuse \ prt1eval prtoeval \ - rand range1 readbuf rebrackloc rebt8b1 redfilnm \ + rand randtest range1 readbuf rebrackloc rebt8b1 rebuild redfilnm \ regeq regexpbrack regexpbrack2 \ regexprange regrange reindops \ reparse resplit rri1 rs rscompat rsnul1nl rsnulbig rsnulbig2 rstest1 rstest2 \ rstest3 rstest4 rstest5 rswhite \ scalar sclforin sclifin sigpipe1 sortempty sortglos splitargv splitarr splitdef \ - splitvar splitwht strcat1 strnum1 strtod subamp subback subi18n \ + splitvar splitwht strcat1 strnum1 strnum2 strtod subamp subback subi18n \ subsepnm subslash substr swaplns synerr1 synerr2 tradanch tweakfld \ uninit2 uninit3 uninit4 uninit5 uninitialized unterm uparrfs \ wideidx wideidx2 widesub widesub2 widesub3 widesub4 wjposer1 \ @@ -1360,33 +1439,38 @@ UNIX_TESTS = \ GAWK_EXT_TESTS = \ aadelete1 aadelete2 aarray1 aasort aasorti argtest arraysort \ backw badargs beginfile1 beginfile2 binmode1 charasbytes \ - colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 \ - crlf dbugeval delsub devfd devfd1 devfd2 dumpvars exit \ - fieldwdth fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \ + colonwarn clos1way clos1way2 clos1way3 clos1way4 clos1way5 clos1way6 \ + crlf dbugeval dbugeval2 dbugtypedre1 dbugtypedre2 delsub \ + devfd devfd1 devfd2 dumpvars errno exit \ + fieldwdth forcenum fpat1 fpat2 fpat3 fpat4 fpat5 fpatnull fsfwfs funlen \ functab1 functab2 functab3 fwtest fwtest2 fwtest3 \ - genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops \ - icasefs icasers id igncdym igncfs ignrcas2 ignrcase \ + genpot gensub gensub2 getlndir gnuops2 gnuops3 gnureops gsubind \ + icasefs icasers id igncdym igncfs ignrcas2 ignrcas3 ignrcase \ incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \ - include include2 indirectbuiltin indirectcall indirectcall2 \ - lint lintold lintwarn \ + include include2 indirectbuiltin indirectcall indirectcall2 intarray \ + lint lintexp lintindex lintint lintlength lintold lintset lintwarn \ mixed1 manyfiles match1 match2 match3 mbstr1 mbstr2 \ muldimposix \ nastyparm negtime next nondec nondec2 \ + nonfatal1 nonfatal2 nonfatal3 \ patsplit posix printfbad1 printfbad2 printfbad3 printfbad4 printhuge procinfs \ - profile0 profile1 profile2 profile3 profile4 profile5 profile6 \ - profile7 profile8 pty1 \ + profile0 profile1 profile2 profile3 profile4 profile5 profile6 profile7 \ + profile8 profile9 profile10 pty1 \ rebuf regnul1 regnul2 regx8bit reginttrad reint reint2 rsgetline rsglstdin rsstart1 \ - rsstart2 rsstart3 rstest6 shadow sortfor sortu split_after_fpat \ + rsstart2 rsstart3 rstest6 shadow shadowbuiltin \ + sortfor sortu split_after_fpat \ splitarg4 strftime \ - strtonum switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \ + strtonum strtonum1 switch2 symtab1 symtab2 symtab3 symtab4 symtab5 symtab6 \ symtab7 symtab8 symtab9 symtab10 \ + typedregex1 typedregex2 typedregex3 typeof1 typeof2 typeof3 typeof4 \ + timeout \ watchpoint1 EXTRA_TESTS = inftest regtest INET_TESTS = inetdayu inetdayt inetechu inetecht MACHINE_TESTS = double1 double2 fmtspcl intformat MPFR_TESTS = mpfrnr mpfrnegzero mpfrmemok1 mpfrrem mpfrrnd mpfrieee \ - mpfrexprange mpfrsort mpfrsqrt mpfrbigint + mpfrexprange mpfrsort mpfrsqrt mpfrbigint mpfrstrtonum mpgforcenum LOCALE_CHARSET_TESTS = \ asort asorti backbigs1 backsmalls1 backsmalls2 \ @@ -1394,13 +1478,13 @@ LOCALE_CHARSET_TESTS = \ mbprintf1 mbprintf2 mbprintf3 mbprintf4 rebt8b2 rtlenmb sort1 sprintfc SHLIB_TESTS = \ - fnmatch filefuncs fork fork2 fts functab4 inplace1 inplace2 inplace3 \ + 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: NEED_LINT = \ - defref fmtspcl lintwarn noeffect nofmtch shadow \ + defref fmtspcl lintexp lintindex lintint lintlength lintwarn noeffect nofmtch shadow \ uninit2 uninit3 uninit4 uninit5 uninitialized @@ -1854,6 +1938,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 >_$@ @@ -2108,6 +2197,16 @@ nondec2:: @$(AWK) --non-decimal-data -v a=0x1 -f "$(srcdir)"/$@.awk >_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +intarray:: + @echo $@ + @$(AWK) --non-decimal-data -f "$(srcdir)"/$@.awk >_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +forcenum:: + @echo $@ + @$(AWK) --non-decimal-data -f "$(srcdir)"/$@.awk >_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + nofile:: @echo $@ @$(AWK) '{}' no/such/file >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -2237,10 +2336,11 @@ profile0: profile1: @echo $@ - @$(AWK) --pretty-print=ap-$@.out -f "$(srcdir)"/xref.awk "$(srcdir)"/dtdgport.awk > _$@.out1 + @$(AWK) -f "$(srcdir)"/xref.awk "$(srcdir)"/dtdgport.awk > _$@.out1 + @$(AWK) --pretty-print=ap-$@.out -f "$(srcdir)"/xref.awk @$(AWK) -f ./ap-$@.out "$(srcdir)"/dtdgport.awk > _$@.out2 ; rm ap-$@.out @$(CMP) _$@.out1 _$@.out2 && rm _$@.out[12] || { echo EXIT CODE: $$? >>_$@ ; \ - cp "$(srcdir)"/dtdgport.awk > $@.ok ; } + cp "$(srcdir)"/dtdgport.awk $@.ok ; } profile2: @echo $@ @@ -2256,14 +2356,12 @@ profile3: profile4: @echo $@ - @GAWK_NO_PP_RUN=1 $(AWK) --profile=ap-$@.out -f "$(srcdir)"/$@.awk > /dev/null - @sed 1,2d < ap-$@.out > _$@; rm ap-$@.out + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ profile5: @echo $@ - @GAWK_NO_PP_RUN=1 $(AWK) --profile=ap-$@.out -f "$(srcdir)"/$@.awk > /dev/null - @sed 1,2d < ap-$@.out > _$@; rm ap-$@.out + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ profile6: @@ -2280,8 +2378,17 @@ profile7: profile8: @echo $@ - @$(AWK) --pretty=ap-$@.out -f "$(srcdir)"/$@.awk < /dev/null - @sed 1,2d < ap-$@.out > _$@; rm ap-$@.out + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +profile9: + @echo $@ + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +profile10: + @echo $@ + @$(AWK) --pretty-print=_$@ -f "$(srcdir)"/$@.awk > /dev/null @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ posix2008sub: @@ -2345,6 +2452,16 @@ mpfrsqrt: @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1 @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +mpfrstrtonum: + @echo $@ + @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +mpgforcenum: + @echo $@ + @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + mpfrrem: @echo $@ @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1 @@ -2454,6 +2571,11 @@ testext:: @$(AWK) -f ./testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ testext.awk +getfile: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -v TESTEXT_QUIET=1 -ltestext -f $@.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.; \ @@ -2528,6 +2650,11 @@ dfamb1: AWKPATH="$(srcdir)" $(AWK) -f $@.awk "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +randtest:: + @echo $@ + @GAWK="$(AWKPROG)" "$(srcdir)"/randtest.sh >_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + backbigs1: @echo $@ @[ -z "$$GAWKLOCALE" ] && GAWKLOCALE=en_US.UTF-8; \ @@ -2584,6 +2711,21 @@ negtime:: @TZ=GMT AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @AWKPATH="$(srcdir)" $(AWK) -f checknegtime.awk "$(srcdir)"/$@.ok _$@ && rm -f _$@ +dbugtypedre1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -D -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +dbugtypedre2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -D -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +dbugeval2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -D -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + muldimposix:: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --posix >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -2628,6 +2770,11 @@ arrayind1: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +arrayind2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + arrayparm: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3308,6 +3455,11 @@ printf1: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +printfchar: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + prmarscl: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3355,6 +3507,11 @@ rebt8b1: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +rebuild: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + regeq: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3500,6 +3657,11 @@ strnum1: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +strnum2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + strtod: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3655,6 +3817,11 @@ clos1way5: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +clos1way6: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + crlf: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3770,6 +3937,11 @@ gnureops: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +gsubind: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + icasefs: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3795,6 +3967,11 @@ igncfs: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +ignrcas3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + ignrcase: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3825,11 +4002,36 @@ lint: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +lintexp: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +lintindex: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +lintint: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +lintlength: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + lintold: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint-old < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +lintset: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + lintwarn: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3860,6 +4062,21 @@ nondec: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +nonfatal1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +nonfatal2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +nonfatal3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + patsplit: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3920,6 +4137,11 @@ shadow: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +shadowbuiltin: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + sortfor: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3945,6 +4167,11 @@ strtonum: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +strtonum1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + switch2: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3980,6 +4207,46 @@ symtab7: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +typedregex1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typedregex2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typedregex3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typeof1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typeof2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typeof3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typeof4: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 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 57b5c5ad..525a44d1 100644 --- a/test/Maketests +++ b/test/Maketests @@ -15,6 +15,11 @@ arrayind1: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +arrayind2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + arrayparm: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -695,6 +700,11 @@ printf1: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +printfchar: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + prmarscl: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -742,6 +752,11 @@ rebt8b1: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +rebuild: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + regeq: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -887,6 +902,11 @@ strnum1: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +strnum2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + strtod: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1042,6 +1062,11 @@ clos1way5: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +clos1way6: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + crlf: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1157,6 +1182,11 @@ gnureops: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +gsubind: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + icasefs: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1182,6 +1212,11 @@ igncfs: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +ignrcas3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + ignrcase: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1212,11 +1247,36 @@ lint: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +lintexp: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +lintindex: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +lintint: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +lintlength: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + lintold: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint-old < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +lintset: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + lintwarn: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1247,6 +1307,21 @@ nondec: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +nonfatal1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +nonfatal2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +nonfatal3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + patsplit: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1307,6 +1382,11 @@ shadow: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk --lint >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +shadowbuiltin: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + sortfor: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1332,6 +1412,11 @@ strtonum: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +strtonum1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + switch2: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1367,6 +1452,46 @@ symtab7: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +typedregex1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typedregex2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typedregex3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typeof1: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typeof2: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typeof3: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +typeof4: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 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/arrayind2.awk b/test/arrayind2.awk new file mode 100644 index 00000000..200694eb --- /dev/null +++ b/test/arrayind2.awk @@ -0,0 +1,8 @@ +BEGIN { + pos[0] = 0 + posout[0] = 0 + split("00000779770060", f) # f[1] is a strnum + print typeof(f[1]) + pos[f[1]] = 1 + print typeof(f[1]) +} diff --git a/test/arrayind2.ok b/test/arrayind2.ok new file mode 100644 index 00000000..335b2005 --- /dev/null +++ b/test/arrayind2.ok @@ -0,0 +1,2 @@ +strnum +strnum diff --git a/test/badargs.ok b/test/badargs.ok index 1664ec1c..cd66dda0 100644 --- a/test/badargs.ok +++ b/test/badargs.ok @@ -26,6 +26,7 @@ Short options: GNU long options: (extensions) -p[file] --profile[=file] -P --posix -r --re-interval + -s --no-optimize -S --sandbox -t --lint-old -V --version diff --git a/test/clos1way6.awk b/test/clos1way6.awk new file mode 100644 index 00000000..19779d73 --- /dev/null +++ b/test/clos1way6.awk @@ -0,0 +1,7 @@ +BEGIN { + cmd = "cat - 1>&2; sleep 2" + PROCINFO[cmd, "NONFATAL"] = 1 + print "test1" |& cmd; close(cmd, "to") + fflush(cmd) + print "test2" |& cmd; print ERRNO +} diff --git a/test/clos1way6.ok b/test/clos1way6.ok new file mode 100644 index 00000000..5768617d --- /dev/null +++ b/test/clos1way6.ok @@ -0,0 +1,3 @@ +gawk: clos1way6.awk:5: warning: fflush: cannot flush: two-way pipe `cat - 1>&2; sleep 2' has closed write end +test1 +Bad file descriptor diff --git a/test/dbugeval2.awk b/test/dbugeval2.awk new file mode 100644 index 00000000..4997d1b4 --- /dev/null +++ b/test/dbugeval2.awk @@ -0,0 +1,4 @@ +BEGIN { + a = 2 + b = 3 +} diff --git a/test/dbugeval2.in b/test/dbugeval2.in new file mode 100644 index 00000000..165f7147 --- /dev/null +++ b/test/dbugeval2.in @@ -0,0 +1,3 @@ +b 3 +r +eval "print and(a, 3)" diff --git a/test/dbugeval2.ok b/test/dbugeval2.ok new file mode 100644 index 00000000..4d645269 --- /dev/null +++ b/test/dbugeval2.ok @@ -0,0 +1,7 @@ +Breakpoint 1 set at file `dbugeval2.awk', line 3 +Starting program: +Stopping in BEGIN ... +Breakpoint 1, main() at `dbugeval2.awk':3 +3 b = 3 +2 +EXIT CODE: 2 diff --git a/test/dbugtypedre1.awk b/test/dbugtypedre1.awk new file mode 100644 index 00000000..b8c0b6d7 --- /dev/null +++ b/test/dbugtypedre1.awk @@ -0,0 +1 @@ +@include "typeof1.awk" diff --git a/test/dbugtypedre1.in b/test/dbugtypedre1.in new file mode 100644 index 00000000..00158c65 --- /dev/null +++ b/test/dbugtypedre1.in @@ -0,0 +1,4 @@ +watch e +run +next +p e diff --git a/test/dbugtypedre1.ok b/test/dbugtypedre1.ok new file mode 100644 index 00000000..dffee0e8 --- /dev/null +++ b/test/dbugtypedre1.ok @@ -0,0 +1,17 @@ +Watchpoint 1: e +Starting program: +number +untyped +regexp +string +array number +Stopping in BEGIN ... +Watchpoint 1: e + Old value: untyped variable + New value: @/foo/ +main() at `typeof1.awk':7 +7 e = @/foo/ ; print typeof(e) +regexp +8 print typeof(@/bar/) +e = @/foo/ +EXIT CODE: 2 diff --git a/test/dbugtypedre2.awk b/test/dbugtypedre2.awk new file mode 100644 index 00000000..a78de32b --- /dev/null +++ b/test/dbugtypedre2.awk @@ -0,0 +1 @@ +BEGIN { x = 0; x = @/[a-z]/; x = "" } diff --git a/test/dbugtypedre2.in b/test/dbugtypedre2.in new file mode 100644 index 00000000..d01ce5a5 --- /dev/null +++ b/test/dbugtypedre2.in @@ -0,0 +1,4 @@ +w x + r + n + n diff --git a/test/dbugtypedre2.ok b/test/dbugtypedre2.ok new file mode 100644 index 00000000..9c04e1e7 --- /dev/null +++ b/test/dbugtypedre2.ok @@ -0,0 +1,15 @@ +Watchpoint 1: x +Starting program: +Stopping in BEGIN ... +Watchpoint 1: x + Old value: untyped variable + New value: 0 +main() at `dbugtypedre2.awk':1 +1 BEGIN { x = 0; x = @/[a-z]/; x = "" } +Watchpoint 1: x + Old value: 0 + New value: @/[a-z]/ +main() at `dbugtypedre2.awk':1 +1 BEGIN { x = 0; x = @/[a-z]/; x = "" } +Program exited normally with exit value: 0 +EXIT CODE: 2 diff --git a/test/dumpvars.ok b/test/dumpvars.ok index 85d1c859..7caecd35 100644 --- a/test/dumpvars.ok +++ b/test/dumpvars.ok @@ -9,7 +9,7 @@ FILENAME: "-" FNR: 3 FPAT: "[^[:space:]]+" FS: " " -FUNCTAB: array, 41 elements +FUNCTAB: array, 42 elements IGNORECASE: 0 LINT: 0 NF: 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/forcenum.awk b/test/forcenum.awk new file mode 100644 index 00000000..54c536c9 --- /dev/null +++ b/test/forcenum.awk @@ -0,0 +1,8 @@ +BEGIN { + # first, make some strnums + nf = split("|5apple|+NaN| 6|0x1az|011Q|027", f, "|") + for (i = 1; i <= nf; i++) { + x = f[i]+0 # trigger strnum conversion to number or string + printf "[%s] -> %g (type %s)\n", f[i], f[i], typeof(f[i]) + } +} diff --git a/test/forcenum.ok b/test/forcenum.ok new file mode 100644 index 00000000..c74eefc7 --- /dev/null +++ b/test/forcenum.ok @@ -0,0 +1,7 @@ +[] -> 0 (type string) +[5apple] -> 5 (type string) +[+NaN] -> nan (type number) +[ 6] -> 6 (type number) +[0x1az] -> 26 (type string) +[011Q] -> 9 (type string) +[027] -> 23 (type number) 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..1109a303 --- /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 (-) ERRNO () +get_file returned 1 +input_name - +end BEGIN +ENDFILE (-) ERRNO () +END +1 +goodbye +0 diff --git a/test/gsubind.awk b/test/gsubind.awk new file mode 100644 index 00000000..fce0d818 --- /dev/null +++ b/test/gsubind.awk @@ -0,0 +1,9 @@ +BEGIN { + f = "foo" + p = @/o/ + gsub(p, "q", f) + print f + fun = "gsub" + @fun(p, "q", f) + print f +} diff --git a/test/gsubind.ok b/test/gsubind.ok new file mode 100644 index 00000000..d25f018a --- /dev/null +++ b/test/gsubind.ok @@ -0,0 +1,3 @@ +fqq +gawk: gsubind.awk:7: fatal: gsub: can be called indirectly only with two arguments +EXIT CODE: 2 @@ -40,7 +40,6 @@ cos -> builtin dcgettext -> builtin dcngettext -> builtin exp -> builtin -extension -> builtin fflush -> builtin function1 -> user gensub -> builtin @@ -48,6 +47,7 @@ gsub -> builtin i -> untyped index -> builtin int -> builtin +intdiv -> builtin isarray -> builtin length -> builtin log -> builtin @@ -71,4 +71,5 @@ system -> builtin systime -> builtin tolower -> builtin toupper -> builtin +typeof -> builtin xor -> builtin diff --git a/test/ignrcas3.awk b/test/ignrcas3.awk new file mode 100644 index 00000000..e74eea64 --- /dev/null +++ b/test/ignrcas3.awk @@ -0,0 +1,7 @@ +BEGIN { + x = "0" + print x+0 # trigger NUMCUR + IGNORECASE = x # should enable ignorecase, since x is a non-null string + y = "aBc" + print (y ~ /abc/) +} diff --git a/test/ignrcas3.ok b/test/ignrcas3.ok new file mode 100644 index 00000000..0d66ea1a --- /dev/null +++ b/test/ignrcas3.ok @@ -0,0 +1,2 @@ +0 +1 diff --git a/test/intarray.awk b/test/intarray.awk new file mode 100644 index 00000000..2c30bd5f --- /dev/null +++ b/test/intarray.awk @@ -0,0 +1,10 @@ +BEGIN { + nf = split("5 |05|0x4|00| 5|-0x12| 011|-013", f, "|") + for (i = 1; i <= nf; i++) { + delete g + z = f[i]+0 # trigger numeric conversion + g[f[i]] + for (x in g) + printf "[%s]\n", x + } +} diff --git a/test/intarray.ok b/test/intarray.ok new file mode 100644 index 00000000..d4df7b8c --- /dev/null +++ b/test/intarray.ok @@ -0,0 +1,8 @@ +[5 ] +[05] +[0x4] +[00] +[ 5] +[-0x12] +[ 011] +[-013] diff --git a/test/lintexp.awk b/test/lintexp.awk new file mode 100644 index 00000000..082d7447 --- /dev/null +++ b/test/lintexp.awk @@ -0,0 +1,9 @@ +BEGIN { + split("0|0a", f, "|") + z = exp(f[1]) # no warning, since strnum converted to number + x = f[2]+0 # trigger NUMCUR + z = exp(f[2]) # should print a warning + x = "0" + y = x+0 # trigger NUMCUR + z = exp(x) # should print a warning, since x is still a string! +} diff --git a/test/lintexp.ok b/test/lintexp.ok new file mode 100644 index 00000000..33122f6d --- /dev/null +++ b/test/lintexp.ok @@ -0,0 +1,2 @@ +gawk: lintexp.awk:5: warning: exp: received non-numeric argument +gawk: lintexp.awk:8: warning: exp: received non-numeric argument diff --git a/test/lintindex.awk b/test/lintindex.awk new file mode 100644 index 00000000..8e6d7e56 --- /dev/null +++ b/test/lintindex.awk @@ -0,0 +1,10 @@ +BEGIN { + x = 537 + y = 3 + z = index(x, y) # should print lint warning + # now that STRCUR has been trigged on x and y, check that we still + # get the warning + z = index(x, y) # should print lint warning + if (z != 2) + print "oops" +} diff --git a/test/lintindex.ok b/test/lintindex.ok new file mode 100644 index 00000000..b89db6a5 --- /dev/null +++ b/test/lintindex.ok @@ -0,0 +1,4 @@ +gawk: lintindex.awk:4: warning: index: received non-string first argument +gawk: lintindex.awk:4: warning: index: received non-string second argument +gawk: lintindex.awk:7: warning: index: received non-string first argument +gawk: lintindex.awk:7: warning: index: received non-string second argument diff --git a/test/lintint.awk b/test/lintint.awk new file mode 100644 index 00000000..f4f687b0 --- /dev/null +++ b/test/lintint.awk @@ -0,0 +1,9 @@ +BEGIN { + split("0|0a", f, "|") + z = int(f[1]) # no warning, since strnum converted to number + x = f[2]+0 # trigger NUMCUR + z = int(f[2]) # should print a warning + x = "0" + y = x+0 # trigger NUMCUR + z = int(x) # should print a warning, since x is still a string! +} diff --git a/test/lintint.ok b/test/lintint.ok new file mode 100644 index 00000000..5bd5d589 --- /dev/null +++ b/test/lintint.ok @@ -0,0 +1,2 @@ +gawk: lintint.awk:5: warning: int: received non-numeric argument +gawk: lintint.awk:8: warning: int: received non-numeric argument diff --git a/test/lintlength.awk b/test/lintlength.awk new file mode 100644 index 00000000..ad217912 --- /dev/null +++ b/test/lintlength.awk @@ -0,0 +1,6 @@ +BEGIN { + x = 5 + z = length(x) # should issue a warning + y = (x "") # trigger STRCUR + z = length(x) # should still issue a warning +} diff --git a/test/lintlength.ok b/test/lintlength.ok new file mode 100644 index 00000000..cb369f7f --- /dev/null +++ b/test/lintlength.ok @@ -0,0 +1,2 @@ +gawk: lintlength.awk:3: warning: length: received non-string argument +gawk: lintlength.awk:5: warning: length: received non-string argument diff --git a/test/lintset.awk b/test/lintset.awk new file mode 100644 index 00000000..8d52eeb4 --- /dev/null +++ b/test/lintset.awk @@ -0,0 +1,5 @@ +BEGIN { + split("0a", f) # set f[0] to a strnum that is really a string + LINT = f[1] # lint should be enabled + x = exp("0") # should generate a warning +} diff --git a/test/lintset.ok b/test/lintset.ok new file mode 100644 index 00000000..7d67c614 --- /dev/null +++ b/test/lintset.ok @@ -0,0 +1 @@ +gawk: lintset.awk:4: warning: exp: received non-numeric argument diff --git a/test/mpfrsqrt.awk b/test/mpfrsqrt.awk index 23a15c92..3fb1f5f8 100644 --- a/test/mpfrsqrt.awk +++ b/test/mpfrsqrt.awk @@ -14,7 +14,7 @@ a=11111111111111111111111111111111111111111111111111111111111 print sqrt(a^2) #print sq_root(a^2) -# ADR: Added for gawk-4.1-stable which doesn't have built-in div() function +# ADR: Added for gawk-4.1-stable which doesn't have built-in intdiv() function if (PROCINFO["version"] < "4.1.60") print sq_root2(a^2) else @@ -27,9 +27,9 @@ function sq_root(x, temp,r,z) z=0 while (abs(z-temp)>1) { z=temp - div(x,temp,r) + intdiv(x,temp,r) temp=r["quotient"] + temp - div(temp,2,r) + intdiv(temp,2,r) temp=r["quotient"] } return temp diff --git a/test/mpfrstrtonum.awk b/test/mpfrstrtonum.awk new file mode 100644 index 00000000..79d6ad13 --- /dev/null +++ b/test/mpfrstrtonum.awk @@ -0,0 +1,5 @@ +BEGIN { + x = "011" + print x+0 # trigger NUMCUR + print strtonum(x) +} diff --git a/test/mpfrstrtonum.ok b/test/mpfrstrtonum.ok new file mode 100644 index 00000000..48a9ed43 --- /dev/null +++ b/test/mpfrstrtonum.ok @@ -0,0 +1,2 @@ +11 +9 diff --git a/test/mpgforcenum.awk b/test/mpgforcenum.awk new file mode 100644 index 00000000..b2d0b6f1 --- /dev/null +++ b/test/mpgforcenum.awk @@ -0,0 +1,5 @@ +BEGIN { + split("5apple", f) # make a strnum + x = f[1]+0 # force strnum conversion to number or string + print typeof(f[1]) # should be string +} diff --git a/test/mpgforcenum.ok b/test/mpgforcenum.ok new file mode 100644 index 00000000..ee8a39c3 --- /dev/null +++ b/test/mpgforcenum.ok @@ -0,0 +1 @@ +string diff --git a/test/nonfatal1.awk b/test/nonfatal1.awk new file mode 100644 index 00000000..a9228f3a --- /dev/null +++ b/test/nonfatal1.awk @@ -0,0 +1,6 @@ +BEGIN { + PROCINFO["NONFATAL"] + # note that ":" is not a valid hostname character + print |& "/inet/tcp/0/local:host/25" + print (ERRNO != "") +} diff --git a/test/nonfatal1.ok b/test/nonfatal1.ok new file mode 100644 index 00000000..51583f2c --- /dev/null +++ b/test/nonfatal1.ok @@ -0,0 +1,2 @@ +gawk: nonfatal1.awk:4: warning: remote host and port information (local:host, 25) invalid +1 diff --git a/test/nonfatal2.awk b/test/nonfatal2.awk new file mode 100644 index 00000000..fedbba43 --- /dev/null +++ b/test/nonfatal2.awk @@ -0,0 +1,5 @@ +BEGIN { + PROCINFO["NONFATAL"] = 1 + print > "/dev/no/such/file" + print ERRNO +} diff --git a/test/nonfatal2.ok b/test/nonfatal2.ok new file mode 100644 index 00000000..ddc88691 --- /dev/null +++ b/test/nonfatal2.ok @@ -0,0 +1 @@ +No such file or directory diff --git a/test/nonfatal3.awk b/test/nonfatal3.awk new file mode 100644 index 00000000..b2a4ec9e --- /dev/null +++ b/test/nonfatal3.awk @@ -0,0 +1,6 @@ +BEGIN { + PROCINFO["NONFATAL"] + # valid host but bogus port + print |& "/inet/tcp/0/localhost/0" + print ERRNO != "" +} diff --git a/test/nonfatal3.ok b/test/nonfatal3.ok new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/test/nonfatal3.ok @@ -0,0 +1 @@ +1 diff --git a/test/printfchar.awk b/test/printfchar.awk new file mode 100644 index 00000000..9e703c31 --- /dev/null +++ b/test/printfchar.awk @@ -0,0 +1,7 @@ +BEGIN { + x[65] + for (i in x) { + # i should be a string + printf "%c\n", i # should print 1st char of string + } +} diff --git a/test/printfchar.ok b/test/printfchar.ok new file mode 100644 index 00000000..1e8b3149 --- /dev/null +++ b/test/printfchar.ok @@ -0,0 +1 @@ +6 diff --git a/test/profile10.awk b/test/profile10.awk new file mode 100644 index 00000000..b78ae447 --- /dev/null +++ b/test/profile10.awk @@ -0,0 +1,42 @@ +BEGIN { # Comment 0 + if (1) { # Comment 1 + print "ABC" # Comment2 + } else { # Comment 3 + print "XYZ" # Comment 4 + } # Comment 5 + + while (c == d) { # Comment 6 + print "DEF" # Comment 7 + } # Comment 8 + + do { # Comment 9 + print "GHI" # Comment 10 + } while (e == f) # Comment 11 + + for (i in data) { # Comment 12 + print "JKL" # Comment 13 + } # Comment 14 + + for (z = 1; z <= 10; z++) { # Comment 15 + print "MNO" # Comment 16 + } # Comment 17 + + switch (q) { # Comment 18 + case "a": # Comment 19 + case "b": + # Comment 20 + break # Comment 21 + default: # Comment 22 + break # Comment 23 + } # Comment 24 + + if (1) { + print "foo" + } # Comment 25 + + if (2) { + print "bar" + } + # Comment 26 +} +# Comment 27 diff --git a/test/profile10.ok b/test/profile10.ok new file mode 100644 index 00000000..13f0b67b --- /dev/null +++ b/test/profile10.ok @@ -0,0 +1,40 @@ +BEGIN { # Comment 0 + if (1) { # Comment 1 + print "ABC" # Comment2 + } else { # Comment 3 + print "XYZ" # Comment 4 + } # Comment 5 + while (c == d) { # Comment 6 + print "DEF" # Comment 7 + } # Comment 8 + do { # Comment 9 + print "GHI" # Comment 10 + } while (e == f) # Comment 11 + for (i in data) { # Comment 12 + print "JKL" # Comment 13 + } # Comment 14 + for (z = 1; z <= 10; z++) { # Comment 15 + print "MNO" # Comment 16 + } # Comment 17 + switch (q) { + case "a": + # Comment 18 + case "b": + # Comment 19 + break # Comment 20 + # Comment 21 + default: + # Comment 22 + break # Comment 23 + } + # Comment 24 + if (1) { + print "foo" + } # Comment 25 + if (2) { + print "bar" + } + # Comment 26 +} + +# Comment 27 diff --git a/test/profile4.ok b/test/profile4.ok index dd845c1c..9d2b9430 100644 --- a/test/profile4.ok +++ b/test/profile4.ok @@ -1,11 +1,9 @@ - # BEGIN rule(s) - - BEGIN { - a = "foo" (c = "bar") - a = (b - c) "foo" - a = "foo" (b - c) - q = (d = "x") (e = "y") - a = (c = tolower("FOO")) in JUNK - x = y == 0 && z == 2 && q == 45 - } +BEGIN { + a = "foo" (c = "bar") + a = (b - c) "foo" + a = "foo" (b - c) + q = (d = "x") (e = "y") + a = (c = tolower("FOO")) in JUNK + x = y == 0 && z == 2 && q == 45 +} diff --git a/test/profile5.ok b/test/profile5.ok index 720683e2..0fb8589e 100644 --- a/test/profile5.ok +++ b/test/profile5.ok @@ -1,4596 +1,5705 @@ - # BEGIN rule(s) +BEGIN { + _addlib("_BASE") +} + +#___________________________________________________________________________________ +BEGIN { + BINMODE = "rw" + SUBSEP = "\000" + _NULARR[""] + delete _NULARR[""] + _INITBASE() +} + +BEGIN { + _addlib("_sYS") +} + +BEGIN { + _addlib("_rEG") +} + +BEGIN { + _addlib("_INSTRUC") +} + +#___________________________________________________________________________________ +BEGIN { + _delay_perfmsdelay = 11500 +} + +BEGIN { + _addlib("_ARR") +} + +#___________________________________________________________________________________ +BEGIN { +} + +BEGIN { ########################################################################### + _addlib("_EXTFN") +} + +#___________________________________________________________________________________ +BEGIN { + delete _XCHR + delete _ASC + delete _CHR + t = "" + for (i = 0; i < 256; i++) { + _ASC[a = _CHR[i] = sprintf("%c", i)] = i + _QASC[a] = sprintf("%.3o", i) + _XCHR[_CHR[i]] = sprintf("%c", (i < 128 ? i + 128 : i - 128)) + } + #_____________________________________________________________________________ + for (i = 0; i < 256; i++) { + _QSTRQ[_CHR[i]] = "\\" sprintf("%.3o", i) + } + #_______________________________________________________________________ + for (i = 0; i < 32; i++) { + _QSTR[_CHR[i]] = _QSTRQ[_CHR[i]] + } + for (; i < 128; i++) { + _QSTR[_CHR[i]] = _CHR[i] + } + for (; i < 256; i++) { + _QSTR[_CHR[i]] = _QSTRQ[_CHR[i]] + } + _QSTR["\\"] = "\\\\" #; _QSTR["\""]="\\\"" + #_____________________________________________________________________________ + _CHR["CR"] = "\r" + _CHR["EOL"] = "\r\n" + _CHR["EOF"] = "\032" + _QSTR[_CHR["EOL"]] = "\\015\\012" + #_______________________________________________________________________ + _CHR["MONTH"][_CHR["MONTH"]["Jan"] = "01"] = "Jan" + _CHR["MONTH"][_CHR["MONTH"]["Feb"] = "02"] = "Feb" + _CHR["MONTH"][_CHR["MONTH"]["Mar"] = "03"] = "Mar" + _CHR["MONTH"][_CHR["MONTH"]["Apr"] = "04"] = "Apr" + _CHR["MONTH"][_CHR["MONTH"]["May"] = "05"] = "May" + _CHR["MONTH"][_CHR["MONTH"]["Jun"] = "06"] = "Jun" + _CHR["MONTH"][_CHR["MONTH"]["Jul"] = "07"] = "Jul" + _CHR["MONTH"][_CHR["MONTH"]["Aug"] = "08"] = "Aug" + _CHR["MONTH"][_CHR["MONTH"]["Sep"] = "09"] = "Sep" + _CHR["MONTH"][_CHR["MONTH"]["Oct"] = "10"] = "Oct" + _CHR["MONTH"][_CHR["MONTH"]["Nov"] = "11"] = "Nov" + _CHR["MONTH"][_CHR["MONTH"]["Dec"] = "12"] = "Dec" + #_____________________________________________________________________________ + _TAB_STEP_DEFAULT = 8 + #_____________________________________________________________________________ + for (i = 0; i < 32; i++) { + _REXPSTR[_CHR[i]] = _QSTRQ[_CHR[i]] + } + for (; i < 256; i++) { + _REXPSTR[_CHR[i]] = _CHR[i] + } + _gensubfn("\\^$.()|{,}[-]?+*", ".", "_rexpstr_i0") +} + +BEGIN { + _addlib("_SYSIO") +} + +#___________________________________________________________________________________ +BEGIN { + _SYS_STDCON = "CON" + _CON_WIDTH = (match(_cmd("MODE " _SYS_STDCON " 2>NUL"), /Columns:[ \t]*([0-9]+)/, A) ? strtonum(A[1]) : 80) +} + +BEGIN { + _addlib("_FILEIO") +} + +#___________________________________________________________________________________ +BEGIN { + if (_SYS_STDOUT == "") { + _SYS_STDOUT = "/dev/stdout" + } + if (_SYS_STDERR == "") { + _SYS_STDERR = "/dev/stderr" + } + _CHR["SUBDIR"] = "\\" + if (_gawk_scriptlevel < 1) { + match(b = _cmd("echo %CD% 2>NUL"), /[^\x00-\x1F]*/) + ENVIRON["CD"] = _FILEIO_RD = _filerd(substr(b, RSTART, RLENGTH) _CHR["SUBDIR"]) + _FILEIO_R = _filer(_FILEIO_RD) + _FILEIO_D = _filed(_FILEIO_RD) + _setmpath(_filerd(_FILEIO_RD "_tmp" _CHR["SUBDIR"])) + } +} + +BEGIN { + _addlib("_tOBJ") +} + +#___________________________________________________________________________________ +BEGIN { + _tInBy = "\212._tInBy" + _tgenuid_init() + _UIDS[""] + delete _UIDS[""] + _UIDSDEL[""] + delete _UIDSDEL[""] + _tPREV[""] + _tPARENT[""] + _tNEXT[""] + _tFCHLD[""] + _tQCHLD[""] + _tLCHLD[""] + _tLINK[""] + _tCLASS[""] + _tSTR[""] + _tDLINK[""] + _[""] + delete _[""] + _ptr[""] + delete _ptr[""] + _TMP0[""] + delete _TMP0[""] + _TMP1[""] + delete _TMP1[""] +} + +BEGIN { + _addlib("_ERRLOG") +} + +#___________________________________________________________________________________ +BEGIN { + if (_gawk_scriptlevel < 1) { + _ERRLOG_TF = 1 + _ERRLOG_VF = 1 + _ERRLOG_IF = 1 + _ERRLOG_WF = 1 + _ERRLOG_EF = 1 + _ERRLOG_FF = 1 + _wrfile(_errlog_file = _getmpfile("OUTPUT.LOG"), "") + } +} + +BEGIN { + _addlib("_SHORTCUT") +} + +#___________________________________________________________________________________ +BEGIN { + _shortcut_init() +} + +BEGIN { ######################################################### + _addlib("_eXTFN") +} + +#___________________________________________________________________________________ +BEGIN { + _extfn_init() +} + +BEGIN { ############################################################ + _addlib("_sHARE") +} + +BEGIN { + _addlib("_FILEVER") +} + +BEGIN { + _addlib("_DS") ############################################################################### + _PRODUCT_NAME = "Deployment Solution Control" + _PRODUCT_VERSION = "1.0" + _PRODUCT_COPYRIGHT = "Copyright (C) 2013 by CosumoGEN" + _PRODUCT_FILENAME = "_main.ewk" +} + +# problem configuring uid by array charset: i can' understand what format of the array: possibly - remove array support +# after removal of array format detection: there is unfinished conflicts: it is possible to totally remove array uid-gen initialization + +#_____________________________________________________ +BEGIN { + _inituidefault() +} + +#_____________________________________________________ +BEGIN { + _initfilever() +} + +#_____________________________________________________ +BEGIN { + _initshare() +} + +#_________________________________________________________________ +BEGIN { + _inspass(_IMPORT, "_import_data") +} + +#_______________________________________________ +BEGIN { + _TEND[_ARRLEN] = 0 + _TYPEWORD = "_TYPE" +} + +#_______________________________________________ +BEGIN { + _ARRLEN = "\032LEN" + _ARRPTR = "\032PTR" + _ARRSTR = "" +} + +#_____________________________________________________ +BEGIN { + _getperf_fn = "_nop" +} - BEGIN { - _addlib("_BASE") - } +BEGIN { + _datablock_length = 262144 +} - BEGIN { - BINMODE = "rw" - SUBSEP = "\000" - _NULARR[""] - delete _NULARR[""] - _INITBASE() - } +#_____________________________________________________ +BEGIN { + _initrdreg() +} - BEGIN { - _addlib("_sYS") - } +#_____________________________________________________ +BEGIN { + _initregpath0() +} - BEGIN { - _addlib("_rEG") - } +#_____________________________________________________ +BEGIN { + _initsys() +} - BEGIN { - _addlib("_INSTRUC") - } +#_________________________________________________________________________________________ +########################################################################################## - BEGIN { - _delay_perfmsdelay = 11500 - } - BEGIN { - _addlib("_ARR") - } - BEGIN { - } - BEGIN { - _addlib("_EXTFN") - } - BEGIN { - delete _XCHR - delete _ASC - delete _CHR - t = "" - for (i = 0; i < 256; i++) { - _ASC[a = _CHR[i] = sprintf("%c", i)] = i - _QASC[a] = sprintf("%.3o", i) - _XCHR[_CHR[i]] = sprintf("%c", (i < 128 ? i + 128 : i - 128)) - } - for (i = 0; i < 256; i++) { - _QSTRQ[_CHR[i]] = "\\" sprintf("%.3o", i) - } - for (i = 0; i < 32; i++) { - _QSTR[_CHR[i]] = _QSTRQ[_CHR[i]] - } - for (; i < 128; i++) { - _QSTR[_CHR[i]] = _CHR[i] - } - for (; i < 256; i++) { - _QSTR[_CHR[i]] = _QSTRQ[_CHR[i]] - } - _QSTR["\\"] = "\\\\" - _CHR["CR"] = "\r" - _CHR["EOL"] = "\r\n" - _CHR["EOF"] = "\032" - _QSTR[_CHR["EOL"]] = "\\015\\012" - _CHR["MONTH"][_CHR["MONTH"]["Jan"] = "01"] = "Jan" - _CHR["MONTH"][_CHR["MONTH"]["Feb"] = "02"] = "Feb" - _CHR["MONTH"][_CHR["MONTH"]["Mar"] = "03"] = "Mar" - _CHR["MONTH"][_CHR["MONTH"]["Apr"] = "04"] = "Apr" - _CHR["MONTH"][_CHR["MONTH"]["May"] = "05"] = "May" - _CHR["MONTH"][_CHR["MONTH"]["Jun"] = "06"] = "Jun" - _CHR["MONTH"][_CHR["MONTH"]["Jul"] = "07"] = "Jul" - _CHR["MONTH"][_CHR["MONTH"]["Aug"] = "08"] = "Aug" - _CHR["MONTH"][_CHR["MONTH"]["Sep"] = "09"] = "Sep" - _CHR["MONTH"][_CHR["MONTH"]["Oct"] = "10"] = "Oct" - _CHR["MONTH"][_CHR["MONTH"]["Nov"] = "11"] = "Nov" - _CHR["MONTH"][_CHR["MONTH"]["Dec"] = "12"] = "Dec" - _TAB_STEP_DEFAULT = 8 - for (i = 0; i < 32; i++) { - _REXPSTR[_CHR[i]] = _QSTRQ[_CHR[i]] - } - for (; i < 256; i++) { - _REXPSTR[_CHR[i]] = _CHR[i] - } - _gensubfn("\\^$.()|{,}[-]?+*", ".", "_rexpstr_i0") - } - BEGIN { - _addlib("_SYSIO") - } - BEGIN { - _SYS_STDCON = "CON" - _CON_WIDTH = (match(_cmd("MODE " _SYS_STDCON " 2>NUL"), /Columns:[ \t]*([0-9]+)/, A) ? strtonum(A[1]) : 80) +#BootDevice BuildNumber BuildType Caption CodeSet CountryCode CreationClassName CSCreationClassName CSDVersion CSName CurrentTimeZone DataExecutionPrevention_32BitApplications DataExecutionPrevention_Available DataExecutionPrevention_Drivers DataExecutionPrevention_SupportPolicy Debug Description Distributed EncryptionLevel ForegroundApplicationBoost FreePhysicalMemory FreeSpaceInPagingFiles FreeVirtualMemory InstallDate LargeSystemCache LastBootUpTime LocalDateTime Locale Manufacturer MaxNumberOfProcesses MaxProcessMemorySize MUILanguages Name NumberOfLicensedUsers NumberOfProcesses NumberOfUsers OperatingSystemSKU Organization OSArchitecture OSLanguage OSProductSuite OSType OtherTypeDescription PAEEnabled PlusProductID PlusVersionNumber Primary ProductType RegisteredUser SerialNumber ServicePackMajorVersion ServicePackMinorVersion SizeStoredInPagingFiles Status SuiteMask SystemDevice SystemDirectory SystemDrive TotalSwapSpaceSize TotalVirtualMemorySize TotalVisibleMemorySize Version WindowsDirectory +#\Device\HarddiskVolume1 7601 Multiprocessor Free Microsoft Windows Server 2008 R2 Enterprise 1252 1 Win32_OperatingSystem Win32_ComputerSystem Service Pack 1 CPU 180 TRUE TRUE TRUE 3 FALSE FALSE 256 0 6925316 33518716 41134632 20110502192745.000000+180 20130426120425.497469+180 20130510134606.932000+180 0409 Microsoft Corporation -1 8589934464 {"en-US"} Microsoft Windows Server 2008 R2 Enterprise |C:\Windows|\Device\Harddisk0\Partition2 0 116 2 10 64-bit 1033 274 18 TRUE 3 Windows User 55041-507-2389175-84833 1 0 33554432 OK 274 \Device\HarddiskVolume2 C:\Windows\system32 C: 50311020 16758448 6.1.7601 C:\Windows +BEGIN { + a = ENVIRON["EGAWK_CMDLINE"] + gsub(/^[ \t]*/, "", a) + a = _lib_CMDLN(a) + if (a != "" && ! _LIBAPI["F"]["!"]) { + _out(_lib_HELP()) + _fatal("Bad comandline argument `" a "'") } - - BEGIN { - _addlib("_FILEIO") + gsub(/^[ \t]*/, "", a) + ENVIRON["EGAWK_CMDLINE"] = a + _lib_APPLY() + if (_basexit_fl) { + exit } + _INIT() + _START() + _END() +} - BEGIN { - if (_SYS_STDOUT == "") { - _SYS_STDOUT = "/dev/stdout" - } - if (_SYS_STDERR == "") { - _SYS_STDERR = "/dev/stderr" - } - _CHR["SUBDIR"] = "\\" - if (_gawk_scriptlevel < 1) { - match(b = _cmd("echo %CD% 2>NUL"), /[^\x00-\x1F]*/) - ENVIRON["CD"] = _FILEIO_RD = _filerd(substr(b, RSTART, RLENGTH) _CHR["SUBDIR"]) - _FILEIO_R = _filer(_FILEIO_RD) - _FILEIO_D = _filed(_FILEIO_RD) - _setmpath(_filerd(_FILEIO_RD "_tmp" _CHR["SUBDIR"])) - } - } - - BEGIN { - _addlib("_tOBJ") - } - - BEGIN { - _tInBy = "\212._tInBy" - _tgenuid_init() - _UIDS[""] - delete _UIDS[""] - _UIDSDEL[""] - delete _UIDSDEL[""] - _tPREV[""] - _tPARENT[""] - _tNEXT[""] - _tFCHLD[""] - _tQCHLD[""] - _tLCHLD[""] - _tLINK[""] - _tCLASS[""] - _tSTR[""] - _tDLINK[""] - _[""] - delete _[""] - _ptr[""] - delete _ptr[""] - _TMP0[""] - delete _TMP0[""] - _TMP1[""] - delete _TMP1[""] - } - - BEGIN { - _addlib("_ERRLOG") - } +#_____________________________________________________________________________ +END { + _EXIT() +} - BEGIN { - if (_gawk_scriptlevel < 1) { - _ERRLOG_TF = 1 - _ERRLOG_VF = 1 - _ERRLOG_IF = 1 - _ERRLOG_WF = 1 - _ERRLOG_EF = 1 - _ERRLOG_FF = 1 - _wrfile(_errlog_file = _getmpfile("OUTPUT.LOG"), "") +#_______________________________________________________________________ +######################################################################## +END { + if (_gawk_scriptlevel < 1) { + close(_errlog_file) + p = _Zimport(_rdfile(_errlog_file), _N()) + if ((t = _get_errout(p)) != "") { + _expout(t, "/dev/stderr") } } +} - BEGIN { - _addlib("_SHORTCUT") - } - - BEGIN { - _shortcut_init() - } - - BEGIN { - _addlib("_eXTFN") - } - - BEGIN { - _extfn_init() - } - - BEGIN { - _addlib("_sHARE") - } - - BEGIN { - _addlib("_FILEVER") - } - - BEGIN { - _addlib("_DS") - _PRODUCT_NAME = "Deployment Solution Control" - _PRODUCT_VERSION = "1.0" - _PRODUCT_COPYRIGHT = "Copyright (C) 2013 by CosumoGEN" - _PRODUCT_FILENAME = "_main.ewk" - } - - BEGIN { - _inituidefault() - } - - BEGIN { - _initfilever() - } - - BEGIN { - _initshare() - } - - BEGIN { - _inspass(_IMPORT, "_import_data") - } - - BEGIN { - _TEND[_ARRLEN] = 0 - _TYPEWORD = "_TYPE" - } - - BEGIN { - _ARRLEN = "\032LEN" - _ARRPTR = "\032PTR" - _ARRSTR = "" - } - - BEGIN { - _getperf_fn = "_nop" - } - - BEGIN { - _datablock_length = 262144 +########################################################################################## +# PUBLIC: +#_____________________________________________________________________________ +# _rFBRO(ptr) - Return ptr of first-bro. [TESTED] +# If !ptr then returns "". +#_____________________________________________________________________________ +# _rLBRO(ptr) - Return ptr of last-bro. [TESTED] +# If !ptr then returns "". +#_____________________________________________________________________________ +# _rQBRO(ptr) - Returns brothers total quantity. [TESTED] +# If !ptr then returns "". +END { + if (_gawk_scriptlevel < 1) { + if (! _fileio_notdeltmpflag) { + _FILEIO_TMPATHS[_FILEIO_TMPRD] + _Foreach(_FILEIO_TMPATHS, "_uninit_del") + } + } +} + +#___________________________________________________________________________________ +#################################################################################### + + + + + + + + + + + + + + + + +#___________________________________________________________________________________ +# fn _dirtree(array,pathmask) +# +# Return in `array' file tree from pathmask: +# array["file.filerdne"]="size date time" +# array["subdir.filerd"]["file.filerdne"]="size date time" +# array["subdir.filerd"]["file.filerd"][...] +# +# The array will be cleared before any action. Function return pathmask w/o ltabspc and rtabspc. +#___________________________________________________________________________________ + + + + + +# OK: change internal function's names to: w\o "_" +# OK: FLENGTH: should cover r-spcs +# OK: optimize REXP +# OK: add new symbols to dir/file names ( ! and + ) +# OK: create _getfilepath() +# OK: del - conflict with WROOTDIR (do not update it) +# OK: dir/del - support for filemask ( * and ? ) +# OK: how to define code injections: header\ender; and HANDLERS +# OK: units in header\ender? conline division... +# OK: _FILEPATH problem: it will not been defined at the moment when subscript0 starts - at the start TMPRD="_tmp" +# OK: del: if del("dir\\") - then all ok except it NOT deleted "dir\\" - _del function removed(renamed to __del) +# OK: tmpdirs: it delete only autotmp dir and only from script0 +# OK: MICROTEST: global testing of filepath (UNC! CORRECT RESULTS! ) +# question about cache: did new just now generated absolute filepath cached in FILECACHE? its seems like NO +# check _untmp: CONFLICT: if file or dir from autotmp dir will be untmp then it anyway will be deleted; but file or dir from other point never be deleted anyway - so what is the point of untmp????? +#ERRLOG: _setmpath: warning!!!!! + +#___________________________________________________________________________________ +#################################################################################### +# PUBLIC: +#___________________________________________________________________________________ +# +# fn _rdfile(_filepath) +# +# Read and return data from file specified in _filepath. +# If _filepath=="" then no action occured and return "". +# Function read and return data from file. No any changes in data occured. +# Function use _filerdne function internally. If some syntax error +# found in _filepath then function return "". +# If some error occured while reading data from file then fuction return "" +# and error-text is in ERRNO(and no close-file action will be occured!). +# If reading data completed successfully then function try to close +# file and if while closing file some error occured then function +# returns "" and error-text is in ERRNO. +# Otherwise function returns readed data. +#_____________________________________________________________________________ +# +# fn _wrfile(_filepath,_data) +# +# Write data into file specified in _filepath. +# If _filepath=="" then no action occured and return "". +# Function write _data to file. No any changes in data occured. +# Function use _filerdne function internally. If some syntax error +# found in _filepath then function return "". +# If some error occured while writing data to file then fuction return "" +# and error-text is in ERRNO(and no close-file action will be occured!). +# If writing data completed successfully then function try to close +# file and if while closing file some error occured then function +# returns "" and error-text is in ERRNO. +# Otherwise function returns _filepath(re-processed). +#___________________________________________________________________________________ +# +# fn _filepath(_filepath) +# +# Return re-processed root-dir-name-ext of _filepath. +# If _filepath=="" then no action occured and return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#_____________________________________________________________________________ +# +# fn _filerdne(_filepath) +# +# Return re-processed root-dir-filename of _filepath. +# If _filepath=="" then no action occured and return "". +# Function return result only if in _filepath present file-name(name +# and/or extension) - otherwise its return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#_____________________________________________________________________________ +# +# fn _filerdn(_filepath) +# +# Return re-processed root-dir-name of _filepath. +# If _filepath=="" then no action occured and return "". +# Function return result only if in _filepath present name field - +# - otherwise its return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#_____________________________________________________________________________ +# +# fn _filerd(_filepath) +# +# Return re-processed root-dir of _filepath. +# If _filepath=="" then no action occured and return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#_____________________________________________________________________________ +# +# fn _filer(_filepath) +# +# Return re-processed root of _filepath. +# If _filepath=="" then no action occured and return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#_____________________________________________________________________________ +# +# fn _filed(_filepath) +# +# Return re-processed dir of _filepath. +# If _filepath=="" then no action occured and return "". +# There is only one case when dir string can be =="" - when in +# _filepath specified unmounted drive(MS-format) and from- +# current-location address used(like Z:file.ext). In this +# case no rootdir-cache-record will be created. +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#_____________________________________________________________________________ +# fn _filene(_filepath) +# +# Return re-processed name-ext of _filepath. +# If _filepath=="" then no action occured and return "". +# Function return result only if in _filepath present file-name(name +# and/or extension) - otherwise its return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#_____________________________________________________________________________ +# +# fn _filen(_filepath) +# +# Return re-processed name of _filepath. +# If _filepath=="" then no action occured and return "". +# Function return result only if in _filepath present name field - +# - otherwise its return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#_____________________________________________________________________________ +# +# fn _file(_filepath) +# +# Return re-processed ext of _filepath. +# If _filepath=="" then no action occured and return "". +# Function return result only if in _filepath present ext field - +# - otherwise its return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +#___________________________________________________________________________________ +# +# fn _dir(_ARR,_filepathmask) +# +# Get file-/folder-list of root-folder of _filepathmask. +# If _filepathmask=="" then no action occured and return "". +# _filepathmask can contain symbols like `*' and `?' as like +# its used in `dir'-shell command. +# Function gets file-/folder-list of specified root-dir-_filepathmask +# and return this list in array _ARR - where each element: +# +# index - is the _filepath of file-or-folder name-ext +# value - contains 3 fields separated by " ": +# 1. =="D" if this is folder +# ==/[0-9]+/ if this is file - size of file in bytes +# 2. ==date-of-creation of file or folder +# 3. ==time-of-creation of file or folder +# +# Function returns quantity of items in ARR. +#___________________________________________________________________________________ +# +# fn _filexist(_filepath) +# +# Test if file or path or drive specified in _filepath is exist. +# If _filepath=="" then no action occured and return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +# Function returns _filepath if _filepath is exist. Otherwise +# function return 0. +#_____________________________________________________________________________ +# +# fn _filenotexist(_filepath) +# +# Test if file or path or drive specified in _filepath is not exist. +# If _filepath=="" then no action occured and return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +# Function returns 1 if _filepath is not exist. Otherwise function +# return 0. +#_____________________________________________________________________________ +# +# fn _newdir(_filepath) +# +# Create path specified in root-dir-_filepath. +# If _filepath=="" then no action occured and return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +# Function returns root-dir of _filepath. +#_______________________________________________________________________ +# +# fn _newdir(_filepath) +# +# Create path specified in root-dir-_filepath. If this folder +# already exist then it will be completely cleared. +# If _filepath=="" then no action occured and return "". +# If some syntax error found in _filepath then function return "" +# (and NO _filepath-cache-record will be created!). +# Function returns root-dir of _filepath. +#___________________________________________________________________________________ +# +# fn _getmpfile(_filepath,_currfilepath) +# +# Return .... +# +#_____________________________________________________________________________ +# +# fn _getmpdir(_filepath,_currfilepath) +# +# Return ... +# +#_____________________________________________________________________________ +# +# Temporary files folder. +# +# Temporary files folder location is defined by _FILEIO_TMPRD. +# If it wasn't been initialized before program run or not been initialized +# by ENVIRON["TMPDIR"] then it will defined as the: +# `current rootdir(stored in _FILEIO_RD)\programname.TMP' +# In this case if its already exist then it will completely cleared when _FILEIO +# library initialization processed. +# And at the program uninitialization processed it will completely +# cleared if _FILEIO_TMPCLRFLAG is true. +#___________________________________________________________________________________ +# +# var _FILEIO_RD (ENVIRON["CD"]) +# +# This var can be set before running program. It can contain path which +# will be used as default current dir while program run. +# If this var is set before program runs - then it will be refreshed by the +# _filerd it will be used as default current dir while program run. +# If this var is not set before program runs - then ENVIRON["CD"] can also +# set up default current dir while program run. If it set before program +# begin then it will be refreshed by the _filerd - and also writed into +# _FILEIO_RD. +# If both _FILEIO_RD and ENVIRON["CD"] are not set before program begins +# then real current root\dir will be writed into both _FILEIO_RD and +# ENVIRON["CD"] and it will be used as default current dir while program run. +# +#___________________________________________________________________________________ +# +# var _FILEIO_TMPRD (ENVIRON["TMPRD"]) +# +# This var can be set before running program. It can contain path which +# will be used as default temporary files root-folder while program run. +# If this var is set before program runs - then it will be refreshed by the +# _filerd - and also writed into ENVIRON["TMPRD"]. +# If this var is not set before program runs - then ENVIRON["TMPRD"] can also +# set up default temporary files root-folder while program run. If it set +# before program begin then it will be refreshed by the _filerd - and +# also writed into _FILEIO_TMPRD. +# If both _FILEIO_TMPRD and ENVIRON["TMPRD"] are not set before program begins +# then new folder into path specified by the _FILEIO_RD(after its handling) +# will be writed into both _FILEIO_TMPRD and ENVIRON["TMPRD"] and it +# will be used as default temporary files root-folder while program run. +#___________________________________________________________________________________ +# +# var _FILEPATH +# +# This var contain filepath of working script. It should be setting up externally. +# +# var _gawk_scriptlevel +#___________________________________________________________________________________ +#################################################################################### +END { + if (_constatstrln > 0) { + _constat() } +} - BEGIN { - _initrdreg() - } +#___________________________________________________________________________________ +#################################################################################### - BEGIN { - _initregpath0() - } - BEGIN { - _initsys() - } - - BEGIN { - a = ENVIRON["EGAWK_CMDLINE"] - gsub(/^[ \t]*/, "", a) - a = _lib_CMDLN(a) - if (a != "" && ! _LIBAPI["F"]["!"]) { - _out(_lib_HELP()) - _fatal("Bad comandline argument `" a "'") - } - gsub(/^[ \t]*/, "", a) - ENVIRON["EGAWK_CMDLINE"] = a - _lib_APPLY() - if (_basexit_fl) { - exit - } - _INIT() - _START() - _END() - } - # END rule(s) - END { - _EXIT() - } - END { - if (_gawk_scriptlevel < 1) { - close(_errlog_file) - p = _Zimport(_rdfile(_errlog_file), _N()) - if ((t = _get_errout(p)) != "") { - _expout(t, "/dev/stderr") - } - } - } - END { - if (_gawk_scriptlevel < 1) { - if (! _fileio_notdeltmpflag) { - _FILEIO_TMPATHS[_FILEIO_TMPRD] - _Foreach(_FILEIO_TMPATHS, "_uninit_del") - } - } - } - END { - if (_constatstrln > 0) { - _constat() - } - } +# make sure that stdout contain only expected characters +# make sure that stderr contain only expected characters +# redesign & reformat keys and its outputs +# try different key combinations +# add lib-specified to all libs - - # Functions, listed alphabetically - - function W(p, p0, p1) - { - if (isarray(p0)) { - delete p0[p] - if (isarray(p1)) { - for (i in p1) { - if (isarray(p1[i])) { - p0[p][i][""] - delete p0[p][i][""] - _N_i0(p0[p][i], p1[i]) - } else { - p0[p][i] = p1[i] - } - } - return p - } - return (p0[p] = p1) - } - delete _[p][p0] +#_______________________________________________________________________ +function W(p, p0, p1) +{ + ##################################################### + if (isarray(p0)) { + delete p0[p] if (isarray(p1)) { for (i in p1) { if (isarray(p1[i])) { - _[p][p0][i][""] - delete _[p][p0][i][""] - _N_i0(_[p][p0][i], p1[i]) + p0[p][i][""] + delete p0[p][i][""] + _N_i0(p0[p][i], p1[i]) } else { - _[p][p0][i] = p1[i] + p0[p][i] = p1[i] } } return p } - return (_[p][p0] = p1) + return (p0[p] = p1) } - - function _ARR(c, t, P) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_ARR 1.0") - case "_lib_BEGIN": - return - case "_lib_END": - return - } - } - - function _BASE(c, t, P, A) - { - switch (c) { - case "_lib_CMDLN": - if (match(t, /^((--([Vv])ersion)|(-([Vv])))[ \t]*/, A)) { - t = substr(t, RLENGTH + 1) - _cmdln_version = A[3] A[5] - } else if (match(t, /^((-?\?)|(--help))[ \t]*/)) { - t = substr(t, RLENGTH + 1) - _cmdln_help = 1 - } else if (match(t, /^--[ \t]*/)) { - return _endpass(substr(t, RLENGTH + 1)) - } - return t - case "_lib_APPLY": - if (_cmdln_help) { - match(_fbaccr(_LIBAPI, "_lib_HELP"), /^([^\x00]*)\x00([^\x01]*)\x01(.*)/, A) - _out(A[2] A[1] A[3]) - return _endpass(_basexit_fl = 1) - } - if (_cmdln_version) { - _out(_ln(_PRODUCT_NAME " v" _PRODUCT_VERSION) _ln(_PRODUCT_COPYRIGHT) _ln() ((_cmdln_version == "v" ? "" : _lib_NAMEVER()))) - return _endpass(_basexit_fl = 1) + delete _[p][p0] + if (isarray(p1)) { + for (i in p1) { + if (isarray(p1[i])) { + _[p][p0][i][""] + delete _[p][p0][i][""] + _N_i0(_[p][p0][i], p1[i]) + } else { + _[p][p0][i] = p1[i] } - return - case "_lib_HELP": - return ("\000" _ln(_PRODUCT_NAME " v" _PRODUCT_VERSION) _ln(_PRODUCT_COPYRIGHT) _ln() _ln(" Usage:") _ln() _ln(" " _PRODUCT_FILENAME " [/key1 /key2...] [-- cmdline]") _ln() _ln(" keys:") _ln() "\001" _ln(" -v -V --version - output product version and (if /V) all modules") _ln(" ? -? --help - output this help page") _ln(" -- - command line string edge")) - case "_lib_NAMEVER": - return _ln("_BASE 3.0") - case "_lib_BEGIN": - return - case "_lib_END": - return } + return p } + return (_[p][p0] = p1) +} - function _DS(c, t, P, a, A) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return (_ln() _ln(" Usage: " _PRODUCT_NAME " [/key1 /key2...] sourcefile [cmdline]") _ln()) - case "_lib_NAMEVER": - return - case "_lib_BEGIN": - return - case "_lib_END": - return +########################################################## +function _ARR(c, t, P) +{ + switch (c) { + case "_lib_CMDLN": + return t + #___________________________________________________________ + case "_lib_APPLY": + return + #___________________________________________________________ + case "_lib_HELP": + return + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_ARR 1.0") + #___________________________________________________________ + case "_lib_BEGIN": + return + #___________________________________________________________ + case "_lib_END": + return + } +} + +########################################################## +function _BASE(c, t, P, A) +{ + switch (c) { + case "_lib_CMDLN": + if (match(t, /^((--([Vv])ersion)|(-([Vv])))[ \t]*/, A)) { + t = substr(t, RLENGTH + 1) + _cmdln_version = A[3] A[5] + } else if (match(t, /^((-?\?)|(--help))[ \t]*/)) { + t = substr(t, RLENGTH + 1) + _cmdln_help = 1 + } else if (match(t, /^--[ \t]*/)) { + return _endpass(substr(t, RLENGTH + 1)) } + return t + #___________________________________________________________ + case "_lib_APPLY": + if (_cmdln_help) { + match(_fbaccr(_LIBAPI, "_lib_HELP"), /^([^\x00]*)\x00([^\x01]*)\x01(.*)/, A) + _out(A[2] A[1] A[3]) + return _endpass(_basexit_fl = 1) + } + if (_cmdln_version) { + _out(_ln(_PRODUCT_NAME " v" _PRODUCT_VERSION) _ln(_PRODUCT_COPYRIGHT) _ln() ((_cmdln_version == "v" ? "" : _lib_NAMEVER()))) + return _endpass(_basexit_fl = 1) + } + return + #___________________________________________________________ + case "_lib_HELP": + return ("\000" _ln(_PRODUCT_NAME " v" _PRODUCT_VERSION) _ln(_PRODUCT_COPYRIGHT) _ln() _ln(" Usage:") _ln() _ln(" " _PRODUCT_FILENAME " [/key1 /key2...] [-- cmdline]") _ln() _ln(" keys:") _ln() "\001" _ln(" -v -V --version - output product version and (if /V) all modules") _ln(" ? -? --help - output this help page") _ln(" -- - command line string edge")) + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_BASE 3.0") + #___________________________________________________________ + case "_lib_BEGIN": + return + #___________________________________________________________ + case "_lib_END": + return } +} - function _END() - { +#____________________________________________________________________________ +function _DS(c, t, P, a, A) +{ + ###################################################### + switch (c) { + case "_lib_CMDLN": + #___________________________________________________________ + return t + #_____________________________________________________ + case "_lib_APPLY": + return + #_____________________________________________________ + case "_lib_HELP": + return (_ln() _ln(" Usage: " _PRODUCT_NAME " [/key1 /key2...] sourcefile [cmdline]") _ln()) + #_____________________________________________________ + case "_lib_NAMEVER": + return + #_____________________________________________________ + case "_lib_BEGIN": + return + #_____________________________________________________ + case "_lib_END": + return } +} - function _ERRLOG(c, t, P, a, b, A) - { - switch (c) { - case "_lib_CMDLN": - if (match(t, /^[ \t]*-L:([TtVvIiWwEeFf]*)[ \t]*/, A)) { - t = substr(t, RLENGTH + 1) - _errlog_errflkey = _errlog_errflkey A[1] - } - return t - case "_lib_APPLY": - if (_errlog_errflkey) { - split(_errlog_errflkey, A, "") - for (a = 1; a in A; a++) { - if (A[a] == toupper(A[a])) { - b = 1 - } else { - b = "" - } - switch (toupper(A[a])) { - case "T": - _ERRLOG_TF = b - break - case "V": - _ERRLOG_VF = b - break - case "I": - _ERRLOG_IF = b - break - case "W": - _ERRLOG_WF = b - break - case "E": - _ERRLOG_EF = b - break - case "F": - _ERRLOG_FF = b - break - } +#______________________________________________________________________________________________ +function _END() +{ + ################################################################################# +} + +######################################################## +function _ERRLOG(c, t, P, a, b, A) +{ + switch (c) { + case "_lib_CMDLN": + if (match(t, /^[ \t]*-L:([TtVvIiWwEeFf]*)[ \t]*/, A)) { + t = substr(t, RLENGTH + 1) + _errlog_errflkey = _errlog_errflkey A[1] + } + return t + #_______________________________________________________________________ + case "_lib_APPLY": + if (_errlog_errflkey) { + split(_errlog_errflkey, A, "") + for (a = 1; a in A; a++) { + if (A[a] == toupper(A[a])) { + b = 1 + } else { + b = "" } - if (_ERRLOG_IF) { - _info("Log-message types inherited acc/deny: " "TRACE " ((_ERRLOG_TF ? "ON" : "OFF")) "/" "VERBOSE " ((_ERRLOG_VF ? "ON" : "OFF")) "/" "INFO " ((_ERRLOG_IF ? "ON" : "OFF")) "/" "WARNING " ((_ERRLOG_WF ? "ON" : "OFF")) "/" "ERROR " ((_ERRLOG_EF ? "ON" : "OFF")) "/" "FATAL " ((_ERRLOG_FF ? "ON" : "OFF"))) + switch (toupper(A[a])) { + case "T": + _ERRLOG_TF = b + break + case "V": + _ERRLOG_VF = b + break + case "I": + _ERRLOG_IF = b + break + case "W": + _ERRLOG_WF = b + break + case "E": + _ERRLOG_EF = b + break + case "F": + _ERRLOG_FF = b + break } } - return - case "_lib_HELP": - return (_ln(" -L:TtVvIiWwEeFf - enable(upcase: TVIWEF) or disable(lowcase: tviwef) allowable type of") _ln(" log messages. Trace/Verbose/Informational/Warning/Error/Fatal.") _ln()) - case "_lib_NAMEVER": - return _ln("_ERRLOG 1.0") - case "_lib_BEGIN": - P["_ERRLOG_TF"] = _ERRLOG_TF - P["_ERRLOG_VF"] = _ERRLOG_VF - P["_ERRLOG_IF"] = _ERRLOG_IF - P["_ERRLOG_WF"] = _ERRLOG_WF - P["_ERRLOG_EF"] = _ERRLOG_EF - P["_ERRLOG_FF"] = _ERRLOG_FF - P["_errlog_file"] = "/dev/stderr" - return + if (_ERRLOG_IF) { + _info("Log-message types inherited acc/deny: " "TRACE " ((_ERRLOG_TF ? "ON" : "OFF")) "/" "VERBOSE " ((_ERRLOG_VF ? "ON" : "OFF")) "/" "INFO " ((_ERRLOG_IF ? "ON" : "OFF")) "/" "WARNING " ((_ERRLOG_WF ? "ON" : "OFF")) "/" "ERROR " ((_ERRLOG_EF ? "ON" : "OFF")) "/" "FATAL " ((_ERRLOG_FF ? "ON" : "OFF"))) + } } + return + #_______________________________________________________________________ + case "_lib_HELP": + return (_ln(" -L:TtVvIiWwEeFf - enable(upcase: TVIWEF) or disable(lowcase: tviwef) allowable type of") _ln(" log messages. Trace/Verbose/Informational/Warning/Error/Fatal.") _ln()) + #_______________________________________________________________________ + case "_lib_NAMEVER": + return _ln("_ERRLOG 1.0") + #_______________________________________________________________________ + case "_lib_BEGIN": + P["_ERRLOG_TF"] = _ERRLOG_TF + P["_ERRLOG_VF"] = _ERRLOG_VF + P["_ERRLOG_IF"] = _ERRLOG_IF + P["_ERRLOG_WF"] = _ERRLOG_WF + P["_ERRLOG_EF"] = _ERRLOG_EF + P["_ERRLOG_FF"] = _ERRLOG_FF + P["_errlog_file"] = "/dev/stderr" + return } +} - function _EXIT() - { - } +#______________________________________________________________________________________________ +function _EXIT() +{ + ################################################################################ +} - function _EXTFN(c, t, P) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_EXTFN 1.0") - case "_lib_BEGIN": - return - case "_lib_END": - return - } +######################################################## +function _EXTFN(c, t, P) +{ + switch (c) { + case "_lib_CMDLN": + return t + #___________________________________________________________ + case "_lib_APPLY": + return + #___________________________________________________________ + case "_lib_HELP": + return + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_EXTFN 1.0") + #___________________________________________________________ + case "_lib_BEGIN": + return + #___________________________________________________________ + case "_lib_END": + return } - - function _FILEIO(c, t, P, A) - { - switch (c) { - case "_lib_CMDLN": - if (match(t, /^[ \t]*-[Tt]([\+-])[ \t]*/, A)) { - t = substr(t, RLENGTH + 1) - if (A[1] == "+") { - _fileio_notdeltmpflag = 1 - } else { - _fileio_notdeltmpflag = "" - } - } - return t - case "_lib_APPLY": - if (_fileio_notdeltmpflag) { - _info("Temporary objects deletion DISABLED (inherited)") - } - return - case "_lib_HELP": - return (_ln(" -[Tt][+-] - inherited: +enable\\-disable temporary files\\dirs deletion") _ln()) - case "_lib_NAMEVER": - return _ln("_FILEIO 2.1") - case "_lib_BEGIN": - P["ENVIRON"]["CD"] = ENVIRON["CD"] - P["_FILEIO_RD"] = _FILEIO_RD - P["_FILEIO_R"] = _FILEIO_R - P["_FILEIO_D"] = _FILEIO_D - if (! ("_FILEIO_TMPRD" in P)) { - P["_FILEIO_TMPRD"] = _getmpdir(_filen(P["SOURCE"]) "." ++_egawk_subcntr _CHR["SUBDIR"]) +} + +####################################################### +function _FILEIO(c, t, P, A) +{ + switch (c) { + case "_lib_CMDLN": + if (match(t, /^[ \t]*-[Tt]([\+-])[ \t]*/, A)) { + t = substr(t, RLENGTH + 1) + if (A[1] == "+") { + _fileio_notdeltmpflag = 1 + } else { + _fileio_notdeltmpflag = "" } - return - case "_lib_END": - return } - } - - function _FILEVER(c, t, P, a, A) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return - case "_lib_BEGIN": - return - case "_lib_END": - return + return t + #___________________________________________________________ + case "_lib_APPLY": + if (_fileio_notdeltmpflag) { + _info("Temporary objects deletion DISABLED (inherited)") } - } - - function _Foreach(A, f, p0, i) - { - for (i in A) { - @f(A, i, p0) + return + #___________________________________________________________ + case "_lib_HELP": + return (_ln(" -[Tt][+-] - inherited: +enable\\-disable temporary files\\dirs deletion") _ln()) + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_FILEIO 2.1") + #___________________________________________________________ + case "_lib_BEGIN": + P["ENVIRON"]["CD"] = ENVIRON["CD"] + P["_FILEIO_RD"] = _FILEIO_RD + P["_FILEIO_R"] = _FILEIO_R + P["_FILEIO_D"] = _FILEIO_D + if (! ("_FILEIO_TMPRD" in P)) { + P["_FILEIO_TMPRD"] = _getmpdir(_filen(P["SOURCE"]) "." ++_egawk_subcntr _CHR["SUBDIR"]) } + return + #___________________________________________________________ + case "_lib_END": + return } +} - function _INIT(f) - { +############################################################ +function _FILEVER(c, t, P, a, A) +{ + #_____________________________________________________________________________ + switch (c) { + case "_lib_CMDLN": + ################################################# + return t + #___________________________________________________________ + #_____________________________________________________ + case "_lib_APPLY": + return + #_____________________________________________________ + case "_lib_HELP": + return + #_____________________________________________________ + case "_lib_NAMEVER": + return + #_____________________________________________________ + case "_lib_BEGIN": + return + #_____________________________________________________ + case "_lib_END": + return } +} - function _INITBASE() - { - _egawk_utilpath = ENVIRON["EGAWK_PATH"] "BIN\\UTIL\\" +function _Foreach(A, f, p0, i) +{ + for (i in A) { + @f(A, i, p0) } +} - function _INSTRUC(c, t, P) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_INSTRUC 1.0") - case "_lib_BEGIN": - return - case "_lib_END": - return - } - } +function _INIT(f) +{ +} - function _N(F, v, p) - { - for (p in _UIDS) { - delete _UIDS[p] - return _nN_i0(p, F, v) - } - return _nN_i0(_tgenuid(), F, v) +#___________________________________________________________________________________ +function _INITBASE() +{ + ################################################################ + _egawk_utilpath = ENVIRON["EGAWK_PATH"] "BIN\\UTIL\\" +} + +###################################################### +function _INSTRUC(c, t, P) +{ + switch (c) { + case "_lib_CMDLN": + return t + #___________________________________________________________ + case "_lib_APPLY": + return + #___________________________________________________________ + case "_lib_HELP": + return + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_INSTRUC 1.0") + #___________________________________________________________ + case "_lib_BEGIN": + return + #___________________________________________________________ + case "_lib_END": + return } +} - function _SHORTCUT(c, t, P) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_shortcut 1.0") - case "_lib_BEGIN": - return - case "_lib_END": - return - } +#___________________________________________________________________________________ + + +#################################################################################### + + +#_____________________________________________________________________________ +function _N(F, v, p) +{ + ########################################################### + for (p in _UIDS) { + delete _UIDS[p] + return _nN_i0(p, F, v) } + return _nN_i0(_tgenuid(), F, v) +} - function _START(t, i, A) - { - _torexp_init() - test_uid() +##################################################### +function _SHORTCUT(c, t, P) +{ + switch (c) { + case "_lib_CMDLN": + return t + #___________________________________________________________ + case "_lib_APPLY": return - _conl(patsplit("a,b,c", A, /[^,]/, B)) - test_splitstr() + #___________________________________________________________ + case "_lib_HELP": return - A[""] - _CLASSPTR["ptr"] - ALTARR["ptra"] - _conl(_dumparr(SYMTAB)) - BB[1] = _NOP - zorr(1, 2, 3, 4, 5, 6) - zorr(BB, 1) - _rtn() - _rtn("") - _rtn(0) - _rtn("0") - _rtn(1) - _rtn("1") - _rtn(-1) - _rtn("-1") - _rtn("huj") - _rtn("ptr") - _rtn("ptra", ALTARR) - _rtn(ALTARR) - _rtn(ALTARR, ALTARR) + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_shortcut 1.0") + #___________________________________________________________ + case "_lib_BEGIN": return - _tstini() + #___________________________________________________________ + case "_lib_END": + return + } +} + +#______________________________________________________________________________________________ +function _START(t, i, A) +{ + ######################################################################### + _torexp_init() + test_uid() + return + _conl(patsplit("a,b,c", A, /[^,]/, B)) + test_splitstr() + return + A[""] + _CLASSPTR["ptr"] + ALTARR["ptra"] + _conl(_dumparr(SYMTAB)) + BB[1] = _NOP + zorr(1, 2, 3, 4, 5, 6) + zorr(BB, 1) + _rtn() + _rtn("") + _rtn(0) + _rtn("0") + _rtn(1) + _rtn("1") + _rtn(-1) + _rtn("-1") + _rtn("huj") + _rtn("ptr") + _rtn("ptra", ALTARR) + _rtn(ALTARR) + _rtn(ALTARR, ALTARR) + return + _tstini() + return + _splitpath_test() + # _split_regpath() + return + hh = "CPU" + _conl("go1!") + _conl(_var(_sharepath(hh, "gdfsgdsgsd sdgsdighjui teretiewrotrewut 345345345 rtjtireutireu huj"))) + _conl("go2!") + _conl(_var(_sharelist(AAA, hh), _dumparr(AAA))) + _conline() + A[1] = "h" + A[3] = "j" + t = "pizda" + if (match(t, /^pi(Z)da/, A)) { + _conl("match") + } else { + _conl("not match") + } + _conl(_dumparr(A)) + return + _pathSMA = "C:\\Program Files\\Altiris\\Altiris Agent\\" + DSPlugInPath = _pathSMA "Agents\\Deployment\\Agent\\" + DSAutoPath = _pathSMA + if (! _sysinfo(_SYS, _hostname)) { + _fatal("_sysinfo: unknown error") + } + _REG[""] + delete _REG[""] + _servoutput = _CHR["EOL"] _cmd("sc query state= all") + _dsbasepath = "\\\\CPU\\CPU\\DEV\\PROJECT\\_DS\\" + _rdreg(_REG, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris") + _wrfile("rego.txt", _dumparr(_REG)) + _conl("fF") + #_______________________________________________________________________ + c = _getreg_i1(DDD, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Altiris Agent\\Plugin Objects\\\204~.*\224Install path", _REG) + #_________________________________________________________________________________________ + pp = _n("NAME", "NS") + #pp=_n() + #___________________________________________________________________________________ + p = _defsolution(pp, "DS Plug-in", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Altiris Agent\\Plugin Objects\\Agents\\") + ClientConfiguration = _defdll(p, "Client Configuration", "ClientConfiguration") + ClientImagingPrep = _defdll(p, "Client Inaging Preparation", "ClientImagingPrep") + ClientImaging = _defdll(p, "Client Imaging", "ClientImaging") + ClientPCT = _defdll(p, "Client PCT", "ClientPCT") + ClientRebootTo = _defdll(p, "Client Reboot To", "ClientRebootTo") + DeploymentAgent = _defdll(p, "Deployment Agent", "Deployment Agent") + DeploymentSolutionBaseAgent = _defdll(p, "Deployment Solution Base Agent", "Deployment Solution Base Agent") + ClientBCDEdit = _defile(p, "Client BCD Edit", "ClientBCDEdit.dll") + ClientCopyFile = _defile(p, "Client Copy File", "ClientCopyFile.dll") + ClientPreImage = _defile(p, "Client Pre Image", "ClientPreImage.dll") + ClientRebootTo = _defile(p, "Client Reboot To", "ClientRebootTo.dll") + _defile(p, "ConfigService.exe", "ConfigService.exe", "") + _defile(p, "config.dll", "config.dll", "") + _defsrv(p, "DS Plug-in Service", "Altiris Deployment Solution - System Configuration") + _defreg(p, "Deployment Agent Path", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Deployment\\AgentInstallPath.STR") + _defile(p, "Altiris_DeploymentSolutionAgent_7_1_x86.msi", (_SYS["OSArchitecture"] == "64-bit" ? "C:\\Program Files\\Altiris\\Altiris Agent\\Agents\\SoftwareManagement\\Software Delivery\\{9D76E4CA-377A-472D-A82E-EDAD77E7E4ED}\\cache\\Altiris_DeploymentSolutionAgent_7_1_x64.msi" : "C:\\Program Files\\Altiris\\Altiris Agent\\Agents\\SoftwareManagement\\Software Delivery\\{4B747D25-612F-48FC-B6B5-9916D1BB755C}\\cache\\Altiris_DeploymentSolutionAgent_7_1_x86.msi"), "") + _defdir(p, "Deployment Folder", a = gensub(/[^\\]*$/, "", 1, _rdsafe(_REG, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Deployment\\AgentInstallPath.STR", "C:\\Program Files\\Altiris\\Altiris Agent\\Agents\\Deployment\\Agent\\"))) + #___________________________________________________________________________________ + p = _defsolution(pp, "DS Auto", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Altiris Agent\\Plugin Objects\\Agents\\") + _defdir(p, "C:\\Boot\\Altiris\\iso\\boot\\fonts\\", "C:\\Boot\\Altiris\\iso\\boot\\fonts\\") + _defdir(p, "C:\\Boot\\Altiris\\iso\\sources\\", "C:\\Boot\\Altiris\\iso\\sources\\") + _defile(p, "C:\\Boot\\Altiris\\iso\\autoinst.exe", "C:\\Boot\\Altiris\\iso\\autoinst.exe", "") + _defile(p, "C:\\Boot\\Altiris\\iso\\autoinst.ini", "C:\\Boot\\Altiris\\iso\\autoinst.ini", "") + _defile(p, "C:\\Boot\\Altiris\\iso\\autoutil.exe", "C:\\Boot\\Altiris\\iso\\autoutil.exe", "") + _defile(p, "C:\\Boot\\Altiris\\iso\\autoutil.ini", "C:\\Boot\\Altiris\\iso\\autoutil.ini", "") + _defile(p, "C:\\Boot\\Altiris\\iso\\bcdedit.exe", "C:\\Boot\\Altiris\\iso\\bcdedit.exe", "") + _defile(p, "C:\\Boot\\Altiris\\iso\\bootmgr", "C:\\Boot\\Altiris\\iso\\bootmgr", "") + _defile(p, "C:\\Boot\\Altiris\\iso\\bootsect.exe", "C:\\Boot\\Altiris\\iso\\bootsect.exe", "") + _defreg(p, "Deployment Automation reg.File", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\AutoUtil\\File.XSZ", "autoutil.exe") + _defreg(p, "Deployment Automation reg.Path", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\AutoUtil\\Path.XSZ", "%systemdrive%\\boot\\altiris\\iso") + #_________________________________________________________________________________________ + _check(pp) + #_________________________________________________________________________________________ + _conl(_report(pp)) + _wrfile("report.txt", _report(pp)) +} + +######################################################### +function _SYSIO(c, t, P) +{ + switch (c) { + case "_lib_CMDLN": + return t + #___________________________________________________________ + case "_lib_APPLY": return - _splitpath_test() + #___________________________________________________________ + case "_lib_HELP": return - hh = "CPU" - _conl("go1!") - _conl(_var(_sharepath(hh, "gdfsgdsgsd sdgsdighjui teretiewrotrewut 345345345 rtjtireutireu huj"))) - _conl("go2!") - _conl(_var(_sharelist(AAA, hh), _dumparr(AAA))) - _conline() - A[1] = "h" - A[3] = "j" - t = "pizda" - if (match(t, /^pi(Z)da/, A)) { - _conl("match") - } else { - _conl("not match") - } - _conl(_dumparr(A)) + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_SYSIO 1.0") + #___________________________________________________________ + case "_lib_BEGIN": + return + #___________________________________________________________ + case "_lib_END": return - _pathSMA = "C:\\Program Files\\Altiris\\Altiris Agent\\" - DSPlugInPath = _pathSMA "Agents\\Deployment\\Agent\\" - DSAutoPath = _pathSMA - if (! _sysinfo(_SYS, _hostname)) { - _fatal("_sysinfo: unknown error") - } - _REG[""] - delete _REG[""] - _servoutput = _CHR["EOL"] _cmd("sc query state= all") - _dsbasepath = "\\\\CPU\\CPU\\DEV\\PROJECT\\_DS\\" - _rdreg(_REG, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris") - _wrfile("rego.txt", _dumparr(_REG)) - _conl("fF") - c = _getreg_i1(DDD, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Altiris Agent\\Plugin Objects\\\204~.*\224Install path", _REG) - pp = _n("NAME", "NS") - p = _defsolution(pp, "DS Plug-in", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Altiris Agent\\Plugin Objects\\Agents\\") - ClientConfiguration = _defdll(p, "Client Configuration", "ClientConfiguration") - ClientImagingPrep = _defdll(p, "Client Inaging Preparation", "ClientImagingPrep") - ClientImaging = _defdll(p, "Client Imaging", "ClientImaging") - ClientPCT = _defdll(p, "Client PCT", "ClientPCT") - ClientRebootTo = _defdll(p, "Client Reboot To", "ClientRebootTo") - DeploymentAgent = _defdll(p, "Deployment Agent", "Deployment Agent") - DeploymentSolutionBaseAgent = _defdll(p, "Deployment Solution Base Agent", "Deployment Solution Base Agent") - ClientBCDEdit = _defile(p, "Client BCD Edit", "ClientBCDEdit.dll") - ClientCopyFile = _defile(p, "Client Copy File", "ClientCopyFile.dll") - ClientPreImage = _defile(p, "Client Pre Image", "ClientPreImage.dll") - ClientRebootTo = _defile(p, "Client Reboot To", "ClientRebootTo.dll") - _defile(p, "ConfigService.exe", "ConfigService.exe", "") - _defile(p, "config.dll", "config.dll", "") - _defsrv(p, "DS Plug-in Service", "Altiris Deployment Solution - System Configuration") - _defreg(p, "Deployment Agent Path", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Deployment\\AgentInstallPath.STR") - _defile(p, "Altiris_DeploymentSolutionAgent_7_1_x86.msi", (_SYS["OSArchitecture"] == "64-bit" ? "C:\\Program Files\\Altiris\\Altiris Agent\\Agents\\SoftwareManagement\\Software Delivery\\{9D76E4CA-377A-472D-A82E-EDAD77E7E4ED}\\cache\\Altiris_DeploymentSolutionAgent_7_1_x64.msi" : "C:\\Program Files\\Altiris\\Altiris Agent\\Agents\\SoftwareManagement\\Software Delivery\\{4B747D25-612F-48FC-B6B5-9916D1BB755C}\\cache\\Altiris_DeploymentSolutionAgent_7_1_x86.msi"), "") - _defdir(p, "Deployment Folder", a = gensub(/[^\\]*$/, "", 1, _rdsafe(_REG, "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Deployment\\AgentInstallPath.STR", "C:\\Program Files\\Altiris\\Altiris Agent\\Agents\\Deployment\\Agent\\"))) - p = _defsolution(pp, "DS Auto", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Altiris Agent\\Plugin Objects\\Agents\\") - _defdir(p, "C:\\Boot\\Altiris\\iso\\boot\\fonts\\", "C:\\Boot\\Altiris\\iso\\boot\\fonts\\") - _defdir(p, "C:\\Boot\\Altiris\\iso\\sources\\", "C:\\Boot\\Altiris\\iso\\sources\\") - _defile(p, "C:\\Boot\\Altiris\\iso\\autoinst.exe", "C:\\Boot\\Altiris\\iso\\autoinst.exe", "") - _defile(p, "C:\\Boot\\Altiris\\iso\\autoinst.ini", "C:\\Boot\\Altiris\\iso\\autoinst.ini", "") - _defile(p, "C:\\Boot\\Altiris\\iso\\autoutil.exe", "C:\\Boot\\Altiris\\iso\\autoutil.exe", "") - _defile(p, "C:\\Boot\\Altiris\\iso\\autoutil.ini", "C:\\Boot\\Altiris\\iso\\autoutil.ini", "") - _defile(p, "C:\\Boot\\Altiris\\iso\\bcdedit.exe", "C:\\Boot\\Altiris\\iso\\bcdedit.exe", "") - _defile(p, "C:\\Boot\\Altiris\\iso\\bootmgr", "C:\\Boot\\Altiris\\iso\\bootmgr", "") - _defile(p, "C:\\Boot\\Altiris\\iso\\bootsect.exe", "C:\\Boot\\Altiris\\iso\\bootsect.exe", "") - _defreg(p, "Deployment Automation reg.File", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\AutoUtil\\File.XSZ", "autoutil.exe") - _defreg(p, "Deployment Automation reg.Path", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\AutoUtil\\Path.XSZ", "%systemdrive%\\boot\\altiris\\iso") - _check(pp) - _conl(_report(pp)) - _wrfile("report.txt", _report(pp)) - } - - function _SYSIO(c, t, P) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_SYSIO 1.0") - case "_lib_BEGIN": - return - case "_lib_END": - return - } } +} - function _W(p, A, v) - { - if (isarray(v)) { - if (p) { - delete A[p] - A[p][""] - delete A[p][""] - _movarr(A[p], v) - } - return p - } +#_______________________________________________________________________ +######################################################################## +function _W(p, A, v) +{ + if (isarray(v)) { if (p) { delete A[p] - return (A[p] = v) + A[p][""] + delete A[p][""] + _movarr(A[p], v) } - return v + return p } - - function _Zexparr(S, s, t, i) - { - t = "" - if (isarray(S)) { - for (i in S) { - t = t ((isarray(S[i]) ? _Zexparr_i1(i) "\020" _Zexparr_i0(S[i]) "\021\021\020" : _Zexparr_i2(_Zexparr_i3(i) "\021" _Zexparr_i3(S[i])) "\020")) - } - } - if (s != "") { - gsub(/\x1B/, "\033;", s) - gsub(/\x10/, "\0330", s) - t = t "\021\021\020" s - } - gsub(/\x0A/, "\033:", t) - return t + if (p) { + delete A[p] + return (A[p] = v) } + return v +} - function _Zexparr_i0(S, t, i) - { +#_______________________________________________________________________ +function _Zexparr(S, s, t, i) +{ + ############################################## + t = "" + if (isarray(S)) { for (i in S) { t = t ((isarray(S[i]) ? _Zexparr_i1(i) "\020" _Zexparr_i0(S[i]) "\021\021\020" : _Zexparr_i2(_Zexparr_i3(i) "\021" _Zexparr_i3(S[i])) "\020")) } - return t } - - function _Zexparr_i1(t) - { - gsub(/\x1B/, "\033;", t) - gsub(/\x11/, "\0331", t) - gsub(/\x10/, "\0330", t) - return t - } - - function _Zexparr_i2(t) - { - gsub(/\x10/, "\0330", t) + if (s != "") { + gsub(/\x1B/, "\033;", s) + gsub(/\x10/, "\0330", s) + t = t "\021\021\020" s + } + gsub(/\x0A/, "\033:", t) + return t +} + +#_________________________________________________________________ +function _Zexparr_i0(S, t, i) +{ + for (i in S) { + t = t ((isarray(S[i]) ? _Zexparr_i1(i) "\020" _Zexparr_i0(S[i]) "\021\021\020" : _Zexparr_i2(_Zexparr_i3(i) "\021" _Zexparr_i3(S[i])) "\020")) + } + return t +} + +#_________________________________________________________________ +function _Zexparr_i1(t) +{ + gsub(/\x1B/, "\033;", t) + gsub(/\x11/, "\0331", t) + gsub(/\x10/, "\0330", t) + return t +} + +#_________________________________________________________________ +function _Zexparr_i2(t) +{ + gsub(/\x10/, "\0330", t) + return t +} + +#_________________________________________________________________ +function _Zexparr_i3(t) +{ + gsub(/\x1B/, "\033;", t) + gsub(/\x11/, "\0331", t) + return t +} + +#_______________________________________________________________________ +function _Zimparr(D, t, A, B) +{ + ############################################## + if (isarray(D)) { + split(t, A, /\x10/, B) + t = _Zimparr_i0(A, B, _Zimparr_i1(D, A, B, 1)) + gsub(/\x1B\x30/, "\020", t) + gsub(/\x1B\x3B/, "\033", t) return t } +} - function _Zexparr_i3(t) - { - gsub(/\x1B/, "\033;", t) - gsub(/\x11/, "\0331", t) - return t - } +#_________________________________________________________________ +function _Zimparr_i0(A, B, i) +{ + return ((i in A ? A[i] B[i] _Zimparr_i0(A, B, i + 1) : "")) +} - function _Zimparr(D, t, A, B) - { - if (isarray(D)) { - split(t, A, /\x10/, B) - t = _Zimparr_i0(A, B, _Zimparr_i1(D, A, B, 1)) - gsub(/\x1B\x30/, "\020", t) - gsub(/\x1B\x3B/, "\033", t) - return t +#_________________________________________________________________ +function _Zimparr_i1(D, A, B, i, t, a, n) +{ + while (i in B) { + if ((t = A[i++]) == "\021\021") { + return i } - } - - function _Zimparr_i0(A, B, i) - { - return ((i in A ? A[i] B[i] _Zimparr_i0(A, B, i + 1) : "")) - } - - function _Zimparr_i1(D, A, B, i, t, a, n) - { - while (i in B) { - if ((t = A[i++]) == "\021\021") { - return i + gsub(/\x1B\x30/, "\020", t) + if ((a = index(t, "\021")) > 0) { + if (isarray(D[n = _Zimparr_i2(substr(t, 1, a - 1))])) { + delete D[n] } - gsub(/\x1B\x30/, "\020", t) - if ((a = index(t, "\021")) > 0) { - if (isarray(D[n = _Zimparr_i2(substr(t, 1, a - 1))])) { - delete D[n] - } - D[n] = _Zimparr_i2(substr(t, a + 1)) - } else { - if (! isarray(D[t = _Zimparr_i2(t)])) { - delete D[t] - D[t][""] - delete D[t][""] - } - i = _Zimparr_i1(D[t], A, B, i) + D[n] = _Zimparr_i2(substr(t, a + 1)) + } else { + if (! isarray(D[t = _Zimparr_i2(t)])) { + delete D[t] + D[t][""] + delete D[t][""] + } + i = _Zimparr_i1(D[t], A, B, i) + } + } +} + +#_________________________________________________________________ +function _Zimparr_i2(t) +{ + gsub(/\x1B\x31/, "\021", t) + gsub(/\x1B\x3B/, "\033", t) + return t +} + +#_____________________________________________________________________________ +function _Zimport(t, p, A, c, i, n, B) +{ + ############################################## + if (p) { + c = split(t, B, /\x0A/) + for (i = 1; i <= c; i++) { + if ((t = B[i]) == "") { + continue } - } - } - - function _Zimparr_i2(t) - { - gsub(/\x1B\x31/, "\021", t) - gsub(/\x1B\x3B/, "\033", t) - return t - } - - function _Zimport(t, p, A, c, i, n, B) - { - if (p) { - c = split(t, B, /\x0A/) - for (i = 1; i <= c; i++) { - if ((t = B[i]) == "") { - continue - } - gsub(/\x1B\x3A/, "\n", t) - if (match(t, /^_ERRLOG: /)) { - _tLOG[n = _wLCHLD(p, _N())][""] - delete _tLOG[n][""] - _Zimparr(_tLOG[n], substr(t, 10)) - } else if ((t = _pass(_IMPORT, t, p, A)) != "") { - gsub(/\x1B\x3B/, "\033", t) - _wLCHLD(p, _N(_tSTR, t)) - } + gsub(/\x1B\x3A/, "\n", t) + if (match(t, /^_ERRLOG: /)) { + _tLOG[n = _wLCHLD(p, _N())][""] + delete _tLOG[n][""] + _Zimparr(_tLOG[n], substr(t, 10)) + } else if ((t = _pass(_IMPORT, t, p, A)) != "") { + gsub(/\x1B\x3B/, "\033", t) + _wLCHLD(p, _N(_tSTR, t)) } - return p - } else { - _expout(t) } - } - - function _acc(A, a, t) - { - if (t) { - if (_VLDMAXSTRING < length(t) + length(a)) { - if (a) { - if (_VLDMAXSTRING < length(t)) { - A[--A[_ARRPTR]] = a - A[--A[_ARRPTR]] = t - } else { - A[--A[_ARRPTR]] = a t - } + return p + } else { + _expout(t) + } +} + +function _acc(A, a, t) +{ + if (t) { + if (_VLDMAXSTRING < length(t) + length(a)) { + if (a) { + if (_VLDMAXSTRING < length(t)) { + A[--A[_ARRPTR]] = a + A[--A[_ARRPTR]] = t } else { - A[++A[_ARRLEN]] = t + A[--A[_ARRPTR]] = a t } - return "" + } else { + A[++A[_ARRLEN]] = t } - return (a t) + return "" } - return a + return (a t) } + return a +} - function _accmpu(A, a, n) - { - if (n) { - return (_mpufn0 = n) - } - if (_mpuacc) { - if (_VLDMAXSTRING < length(_mpuacc) + length(a)) { - if (a) { - if (_VLDMAXSTRING < length(_mpuacc)) { - A[--A[_ARRLEN]] = a - A[--A[_ARRLEN]] = _mpuacc - } else { - A[--A[_ARRLEN]] = a _mpuacc - } - } else { +function _accmpu(A, a, n) +{ + if (n) { + return (_mpufn0 = n) + } + if (_mpuacc) { + if (_VLDMAXSTRING < length(_mpuacc) + length(a)) { + if (a) { + if (_VLDMAXSTRING < length(_mpuacc)) { + A[--A[_ARRLEN]] = a A[--A[_ARRLEN]] = _mpuacc + } else { + A[--A[_ARRLEN]] = a _mpuacc } - _mpuacc = "" } else { - _mpuacc = a _mpuacc + A[--A[_ARRLEN]] = _mpuacc } + _mpuacc = "" } else { - _mpuacc = a + _mpuacc = a _mpuacc } + } else { + _mpuacc = a } +} - function _add(S, sf, D, df) - { - if (sf in S) { - if (isarray(S[sf])) { - if (df in D) { - if (isarray(D[df])) { - return _extarr(D[df], S[sf]) - } - delete D[df] - } - D[df][""] - delete D[df][""] - return _extarr(D[df], S[sf]) - } else { +#_______________________________________________________________________ +function _add(S, sf, D, df) +{ + ################################################ + if (sf in S) { + if (isarray(S[sf])) { + if (df in D) { if (isarray(D[df])) { - delete D[df] + return _extarr(D[df], S[sf]) } - D[df] = D[df] S[sf] + delete D[df] } + D[df][""] + delete D[df][""] + return _extarr(D[df], S[sf]) + } else { + if (isarray(D[df])) { + delete D[df] + } + D[df] = D[df] S[sf] } } +} - function _addarr(D, S) - { - if (isarray(S)) { - _addarr_i0(D, S) - } - } - - function _addarr_i0(D, S, i) - { - for (i in S) { - if (isarray(S[i])) { - delete D[i] - D[i][""] - delete D[i][""] - _addarr_i0(D[i], S[i]) - } else { - delete D[i] - D[i] = S[i] - } - } +#_________________________________________________________________ +function _addarr(D, S) +{ + ############################################# + if (isarray(S)) { + _addarr_i0(D, S) } +} - function _addarrmask(D, S, M) - { - for (_addarrmaski0 in M) { - if (_addarrmaski0 in S) { - if (isarray(S[_addarrmaski0])) { - if (! isarray(D[_addarrmaski0])) { - delete D[_addarrmaski0] - D[_addarrmaski0][""] - delete D[_addarrmaski0][""] - } - if (isarray(M[_addarrmaski0])) { - _addarrmask(D[_addarrmaski0], S[_addarrmaski0], M[_addarrmaski0]) - } else { - _extarr_i0(D[_addarrmaski0], S[_addarrmaski0]) - } +#_____________________________________________________ +function _addarr_i0(D, S, i) +{ + for (i in S) { + if (isarray(S[i])) { + delete D[i] + D[i][""] + delete D[i][""] + _addarr_i0(D[i], S[i]) + } else { + delete D[i] + D[i] = S[i] + } + } +} + +#_______________________________________________________________________ +function _addarrmask(D, S, M) +{ + ############################################# + for (_addarrmaski0 in M) { + if (_addarrmaski0 in S) { + if (isarray(S[_addarrmaski0])) { + if (! isarray(D[_addarrmaski0])) { + delete D[_addarrmaski0] + D[_addarrmaski0][""] + delete D[_addarrmaski0][""] + } + if (isarray(M[_addarrmaski0])) { + _addarrmask(D[_addarrmaski0], S[_addarrmaski0], M[_addarrmaski0]) } else { - if (isarray(D[_addarrmaski0])) { - delete D[_addarrmaski0] - } - D[_addarrmaski0] = S[_addarrmaski0] + _extarr_i0(D[_addarrmaski0], S[_addarrmaski0]) } } else { - delete D[_addarrmaski0] + if (isarray(D[_addarrmaski0])) { + delete D[_addarrmaski0] + } + D[_addarrmaski0] = S[_addarrmaski0] } + } else { + delete D[_addarrmaski0] } } +} - function _addf(A, f) - { - A["B"][""] = A["F"][A["B"][f] = A["B"][""]] = f - } +#___________________________________________________________________________________ +#################################################################################### - function _addfile(f, d, a, b) - { - if ((f = _wfilerdnehnd(f)) == "" || _filene(f) == "") { - ERRNO = "Filename error" - return - } - a = BINMODE - BINMODE = "rw" - b = ORS - ORS = "" - ERRNO = "" - print(d) >> f - if (ERRNO) { - return "" - } - close(f) - BINMODE = a - ORS = b - if (ERRNO) { - return "" - } - return d - } - function _addlib(f) - { - _addf(_LIBAPI, f) - } +#_______________________________________________________________________ +function _addf(A, f) +{ + ##################################################### + A["B"][""] = A["F"][A["B"][f] = A["B"][""]] = f +} - function _addlist(A, v) - { - A[++A[0]] = v +#___________________________________________________________ +function _addfile(f, d, a, b) +{ + ################################## + if ((f = _wfilerdnehnd(f)) == "" || _filene(f) == "") { + ERRNO = "Filename error" + return } - - function _bearray(A) - { - if (isarray(A) || A == 0 && A == "") { - return 1 - } + a = BINMODE + BINMODE = "rw" + b = ORS + ORS = "" + ERRNO = "" + print(d) >> f + if (ERRNO) { + return "" } - - function _bframe(A, t, p) - { - return _bframe_i0(A, t, p, A[""]) + close(f) + BINMODE = a + ORS = b + if (ERRNO) { + return "" } + return d +} - function _bframe_i0(A, t, p, f) - { - return ((f ? _bframe_i0(A, t, p, A[f]) (@f(t, p)) : "")) - } +#_____________________________________________________________________________ +function _addlib(f) +{ + ########################################################### + _addf(_LIBAPI, f) +} - function _cfguid(p, optr, pfx, sfx, hstrcnt, lstrchr) - { - delete _UIDOBL[p] - if (_isptr(optr)) { - if (optr == p) { - delete _UIDOBLV[p] - delete _UIDOBLV[_UIDOBLV[_UIDOBL[p] = p][""] = p][""] - } else if (optr in _UIDOBL) { - _UIDOBL[p] = _UIDOBL[optr] - } - } - _UIDPFX[p] = (_istr(pfx) ? pfx : "") - _UIDSFX[p] = (_istr(sfx) ? sfx : "") - if (_isptr(hstrcnt)) { - if (hstrcnt != p) { - _UIDCHR[p] = _UIDCHR[_UIDCNT[p] = _UIDCNT[hstrcnt]] - return p - } - hstrcnt = _NOP - } - _UIDCNTL[_UIDCNT[p] = p] = _cfguidchr(p, hstrcnt, lstrchr) - return p - } +#___________________________________________________________________________________ +#################################################################################### - function _cfguidchr(p, h, l, H, L) - { - if (_isptr(l)) { - if (l != p) { - return (_UIDCHR[p] = _UIDCHR[l]) - } - _UIDCHR[p] = p - l = _NOP - } - _UIDCHR[p] = p - _splitstr(H, h, _UIDCHRH[_classys]) - _splitstr(L, l, H) - delete _UIDCHRH[_UIDCHRH[p][""] = p][""] - delete _UIDCHRL[_UIDCHRL[p][""] = p][""] - _cfguidh(p, H, L) - return _cfguidl(p, L, L) - } - - function _cfguidh(p, H, L, hi, h, li) - { - for (hi = 1; hi in H; hi++) { - h = H[hi] - for (li = 1; li in L; li++) { - _UIDCHRH[p][h L[li]] - } - } - } - function _cfguidl(p, H, L, hi, h, hl, li) - { - for (hi = 1; hi in H; hi++) { - h = H[hi] - for (li = 1; li in L; li++) { - hl = _UIDCHRL[p][hl] = h L[li] - } - } - return hl - } +#_______________________________________________________________________ +function _addlist(A, v) +{ + ################################################## + A[++A[0]] = v +} - function _check(p) - { - _dll_check(p) - _file_check(p) - _serv_check(p) - _reg_check(p) +############################################ +function _bearray(A) +{ + #_______________________________________________________________________ + if (isarray(A) || A == 0 && A == "") { + return 1 #################################################### } +} - function _chrline(t, ts, w, s) - { - return ((t = " " _tabtospc(t, ts) ((t ? (t ~ /[ \t]$/ ? "" : " ") : ""))) _getchrln((s ? s : "_"), ((w ? w : _CON_WIDTH - 1)) - length(t)) _CHR["EOL"]) - } +#_________________________________________________________________ +function _bframe(A, t, p) +{ + ########################################### + return _bframe_i0(A, t, p, A[""]) +} - function _cmd(c, i, A) - { - _fio_cmda = RS - RS = ".{1,}" - _fio_cmdb = BINMODE - BINMODE = "rw" - ERRNO = RT = _NUL - c | getline RS - BINMODE = _fio_cmdb - RS = _fio_cmda - if (ERRNO || 0 > (_exitcode = close(c))) { - return (RT = _NOP) - } - return RT - } +#___________________________________________________________ +function _bframe_i0(A, t, p, f) +{ + return ((f ? _bframe_i0(A, t, p, A[f]) (@f(t, p)) : "")) +} - function _cmparr(A0, A1, R, a, i) - { - a = 0 - delete R - for (i in A0) { - if (! (i in A1)) { - a++ - R[i] = 0 - } else if (A0[i] != A1[i]) { - a++ - R[i] = 2 - } - } - for (i in A1) { - if (! (i in A0)) { - a++ - R[i] = 1 - } - } - return a - } +# add to _dumparr: checking that if element is undefined - function _con(t, ts, a, b, c, d, i, r, A, B) - { - d = RLENGTH - if ((c = split(r = t, A, /\x0D?\x0A/, B)) > 0) { - a = BINMODE - b = ORS - BINMODE = "rw" - ORS = "" - if (c > 1) { - if ((i = length(t = _tabtospc(A[1], ts, _conlastrln))) < _constatstrln) { - t = t _getchrln(" ", _constatstrln - i) - } - print(t B[1]) > _SYS_STDCON - for (i = 2; i < c; i++) { - print(_tabtospc(A[i], ts) B[i]) > _SYS_STDCON - } - print(_conlastr = _tabtospc(A[c], ts)) > _SYS_STDCON - fflush(_SYS_STDCON) - } else { - print(t = _tabtospc(t, ts, _conlastrln)) > _SYS_STDCON - fflush(_SYS_STDCON) - _conlastr = _conlastr t - } - if ((i = length(_conlastr)) >= _CON_WIDTH) { - _conlastr = substr(_conlastr, 1 + int(i / _CON_WIDTH) * _CON_WIDTH) - } - _conlastrln = length(_conlastr) - if (_constatstr) { - print((t = _constatgtstr(_constatstr, _CON_WIDTH - 1 - _conlastrln)) _CHR["CR"] _conlastr) > _SYS_STDCON - fflush(_SYS_STDCON) - _constatstrln = length(t) - } - BINMODE = a - ORS = b - RLENGTH = d - return r - } - RLENGTH = d - } - function _conin(t, a, b) - { - _constatpush() - _constat() - a = BINMODE - b = RS - BINMODE = "rw" - RS = "\n" - _con(t) - getline t < "CON" - close("CON") - _conlastrln = 0 - _conlastr = "" - gsub(/[\x0D\x0A]+/, "", t) - BINMODE = a - RS = b - _constatpop() - return t - } - function _conl(t, ts) - { - return _con(t ((t ~ /\x0A$/ ? "" : _CHR["EOL"])), ts) - } - function _conline(t, ts) - { - return _con(_chrline(t, ts)) - } - function _conlq(t, ts) - { - return _conl("`" t "'", ts) - } - function _constat(t, ts, ln, a) - { - if (_constatstrln > (ln = length(t = _constatgtstr(_constatstr = _tabtospc(t, ts), _CON_WIDTH - 1 - _conlastrln)))) { - t = t _getchrln(" ", _constatstrln - ln) - } - _constatstrln = ln - ln = ORS - a = BINMODE - BINMODE = "rw" - ORS = "" - print(t _CHR["CR"] _conlastr) > _SYS_STDCON - fflush(_SYS_STDCON) - ORS = ln - BINMODE = a - return _constatstr - } - function _constatgtstr(t, ln, a, b) - { - if (ln < 1) { - return "" - } - if ((a = length(t)) <= ln) { - return t - } - if (ln < 11) { - return substr(t, a - ln + 1) - } - if (ln < 19) { - return ("..." substr(t, a - ln + 4)) - } - return (substr(t, 1, b = int((ln - 3) / 2)) "..." substr(t, a - ln + b + 4)) - } - function _constatpop() - { - if (_CONSTATPUSH[0] > 0) { - return _constat(_CONSTATPUSH[_CONSTATPUSH[0]--]) - } - return _constat("") - } - function _constatpush(t, ts) - { - _CONSTATPUSH[++_CONSTATPUSH[0]] = _constatstr - if (t) { - _constat(t, ts) - } - return _constatstr - } - function _creport(p, t, f, z) - { - _[p]["REPORT"] = _[p]["REPORT"] _ln(t ((f == "" ? "" : ": " f))) - } - function _defdir(pp, n, f, v, p) - { - _[p = _wLCHLD(pp, _n("TYPE", "defdir"))]["NAME"] = n - _[p]["DIR"] = f - return p - } - function _defdll(pp, n, rn, p) - { - _[p = _wLCHLD(pp, _n("TYPE", "defdll"))]["NAME"] = n - _[p]["REGPATH"] = _[pp]["REGPATH"] rn - _[p]["ERRHOST"] = pp - return p - } - function _defescarr(D, r, S, i, c, t) - { - if (isarray(S)) { - for (i = 0; i < 256; i++) { - if ((c = _CHR[i]) ~ r) { - D[c] = "\\" S[c] - t = t c - } else if (D[c] == "") { - D[c] = c - } - } - } else { - for (i = 0; i < 256; i++) { - if ((c = _CHR[i]) ~ r) { - D[c] = S c - if (S != "") { - t = t c - } - } else if (D[c] == "") { - D[c] = c - } - } - } - return t - } - - function _defile(pp, n, f, v, p) - { - _[p = _wLCHLD(pp, _n("TYPE", "defile"))]["NAME"] = n - _[p]["FILE"] = f - if (! (v == 0 && v == "")) { - _[p]["RQVERSION"] = v - } - return p - } - function _defn(f, c, v) - { - FUNCTAB[c f] = v - } - function _defreg(pp, n, f, v, p) - { - _[p = _wLCHLD(pp, _n("TYPE", "defreg"))]["NAME"] = n - _[p]["REGPATH"] = f - if (! (v == 0 && v == "")) { - _[p]["VALUE"] = v - } - } - function _defsolution(pp, n, rn, p) - { - _[p = _wLCHLD(pp, _n("TYPE", "solution"))]["NAME"] = n - _[p]["REGPATH"] = rn - _[p]["ERRHOST"] = pp - return p - } - function _defsrv(pp, n, f, v, p) - { - _[p = _wLCHLD(pp, _n("TYPE", "defsrv"))]["NAME"] = n - _[p]["SERVNAME"] = f - return p - } - function _del(f, c, a, A) - { - if (match(f, /\\[ \t]*$/)) { - if ((c = toupper(_filerd(f))) && length(f) == FLENGTH) { - _cmd("rd " c " /S /Q 2>NUL") - _deletepfx(_WFILEROOTDIR, c) - _deletepfx(_FILEIO_RDTMP, c) - _deletepfx(_FILEIO_RDNETMP, c) - } else { - _conl("HUJ TEBE!") - return "" - } - } else { - a = _dir(A, f) - _cmd("del " f " /Q 2>NUL") - for (c in A) { - if (c ~ /\\$/) { - _cmd("rd " c " /S /Q 2>NUL") - _deletepfx(_WFILEROOTDIR, c) - _deletepfx(_FILEIO_RDTMP, c) - } - _deletepfx(_FILEIO_RDNETMP, c) - } +#_______________________________________________________________________ +function _cfguid(p, optr, pfx, sfx, hstrcnt, lstrchr) +{ + #################### 0 # + delete _UIDOBL[p] + if (_isptr(optr)) { + if (optr == p) { + delete _UIDOBLV[p] + delete _UIDOBLV[_UIDOBLV[_UIDOBL[p] = p][""] = p][""] + } else if (optr in _UIDOBL) { + _UIDOBL[p] = _UIDOBL[optr] } - return a } - - function _delay(t, a) - { - for (a = 1; a <= t; a++) { - _delayms() + _UIDPFX[p] = (_istr(pfx) ? pfx : "") + _UIDSFX[p] = (_istr(sfx) ? sfx : "") + if (_isptr(hstrcnt)) { + if (hstrcnt != p) { + _UIDCHR[p] = _UIDCHR[_UIDCNT[p] = _UIDCNT[hstrcnt]] + return p } + hstrcnt = _NOP } + _UIDCNTL[_UIDCNT[p] = p] = _cfguidchr(p, hstrcnt, lstrchr) + return p +} - function _delayms(a) - { - for (a = 1; a <= _delay_perfmsdelay; a++) { +#_____________________________________________________ +function _cfguidchr(p, h, l, H, L) +{ + if (_isptr(l)) { + if (l != p) { + return (_UIDCHR[p] = _UIDCHR[l]) } + _UIDCHR[p] = p + l = _NOP + } + _UIDCHR[p] = p + _splitstr(H, h, _UIDCHRH[_classys]) + _splitstr(L, l, H) + delete _UIDCHRH[_UIDCHRH[p][""] = p][""] + delete _UIDCHRL[_UIDCHRL[p][""] = p][""] + _cfguidh(p, H, L) + return _cfguidl(p, L, L) +} + +#_______________________________________________ +function _cfguidh(p, H, L, hi, h, li) +{ + for (hi = 1; hi in H; hi++) { + h = H[hi] + for (li = 1; li in L; li++) { + _UIDCHRH[p][h L[li]] + } + } +} + +function _cfguidl(p, H, L, hi, h, hl, li) +{ + for (hi = 1; hi in H; hi++) { + h = H[hi] + for (li = 1; li in L; li++) { + hl = _UIDCHRL[p][hl] = h L[li] + } + } + return hl +} + +#____________________________________________________________________________________________________ +function _check(p) +{ + #################################################################################### + _dll_check(p) + _file_check(p) + _serv_check(p) + _reg_check(p) +} + +#_______________________________________________________________________ +function _chrline(t, ts, w, s) +{ + ############################################# + return ((t = " " _tabtospc(t, ts) ((t ? (t ~ /[ \t]$/ ? "" : " ") : ""))) _getchrln((s ? s : "_"), ((w ? w : _CON_WIDTH - 1)) - length(t)) _CHR["EOL"]) +} + +#_____________________________________________________________________________ +function _cmd(c, i, A) +{ + ####################################################### + _fio_cmda = RS + RS = ".{1,}" + _fio_cmdb = BINMODE + BINMODE = "rw" + ERRNO = RT = _NUL + c | getline RS + BINMODE = _fio_cmdb + RS = _fio_cmda + if (ERRNO || 0 > (_exitcode = close(c))) { + return (RT = _NOP) } - - function _deletepfx(A, f, B, le, i) - { - le = length(f) - for (i in A) { - if (substr(toupper(i), 1, le) == f) { - B[i] = A[i] - delete A[i] + return RT +} + +#_______________________________________________________________________ +function _cmparr(A0, A1, R, a, i) +{ + ########################################## + a = 0 + delete R + for (i in A0) { + if (! (i in A1)) { + a++ + R[i] = 0 + } else if (A0[i] != A1[i]) { + a++ + R[i] = 2 + } + } + for (i in A1) { + if (! (i in A0)) { + a++ + R[i] = 1 + } + } + return a +} + +#_____________________________________________________________________________ +function _con(t, ts, a, b, c, d, i, r, A, B) +{ + ########################################## + d = RLENGTH + if ((c = split(r = t, A, /\x0D?\x0A/, B)) > 0) { + a = BINMODE + b = ORS + BINMODE = "rw" + ORS = "" + if (c > 1) { + if ((i = length(t = _tabtospc(A[1], ts, _conlastrln))) < _constatstrln) { + t = t _getchrln(" ", _constatstrln - i) + } + print(t B[1]) > _SYS_STDCON + for (i = 2; i < c; i++) { + print(_tabtospc(A[i], ts) B[i]) > _SYS_STDCON } + print(_conlastr = _tabtospc(A[c], ts)) > _SYS_STDCON + fflush(_SYS_STDCON) + } else { + print(t = _tabtospc(t, ts, _conlastrln)) > _SYS_STDCON + fflush(_SYS_STDCON) + _conlastr = _conlastr t + } + if ((i = length(_conlastr)) >= _CON_WIDTH) { + _conlastr = substr(_conlastr, 1 + int(i / _CON_WIDTH) * _CON_WIDTH) + } + _conlastrln = length(_conlastr) + if (_constatstr) { + print((t = _constatgtstr(_constatstr, _CON_WIDTH - 1 - _conlastrln)) _CHR["CR"] _conlastr) > _SYS_STDCON + fflush(_SYS_STDCON) + _constatstrln = length(t) } + BINMODE = a + ORS = b + RLENGTH = d + return r } - - function _delf(A, f) - { - A["B"][A["F"][A["B"][f]] = A["F"][f]] = A["B"][f] - delete A["F"][f] - delete A["B"][f] + RLENGTH = d +} + +#_______________________________________________________________________ +function _conin(t, a, b) +{ + ################################################# + _constatpush() + _constat() + a = BINMODE + b = RS + BINMODE = "rw" + RS = "\n" + _con(t) + getline t < "CON" + close("CON") + _conlastrln = 0 + _conlastr = "" + gsub(/[\x0D\x0A]+/, "", t) + BINMODE = a + RS = b + _constatpop() + return t +} + +#_______________________________________________________________________ +function _conl(t, ts) +{ + #################################################### + return _con(t ((t ~ /\x0A$/ ? "" : _CHR["EOL"])), ts) +} + +#_______________________________________________________________________ +function _conline(t, ts) +{ + ################################################# + return _con(_chrline(t, ts)) +} + +#___________________________________________________________________________________ +#################################################################################### +function _conlq(t, ts) +{ + return _conl("`" t "'", ts) +} + +#_______________________________________________________________________ +function _constat(t, ts, ln, a) +{ + ########################################### + if (_constatstrln > (ln = length(t = _constatgtstr(_constatstr = _tabtospc(t, ts), _CON_WIDTH - 1 - _conlastrln)))) { + t = t _getchrln(" ", _constatstrln - ln) + } + _constatstrln = ln + ln = ORS + a = BINMODE + BINMODE = "rw" + ORS = "" + print(t _CHR["CR"] _conlastr) > _SYS_STDCON + fflush(_SYS_STDCON) + ORS = ln + BINMODE = a + return _constatstr +} + +#_________________________________________________________________ +function _constatgtstr(t, ln, a, b) +{ + if (ln < 1) { + return "" } - - function _deluid(p) - { - if (p in _CLASSPTR) { - _deluida0 = _CLASSPTR[p] - if (_deluida0 in _UIDOBL) { - _UIDOBLV[_UIDOBL[_deluida0]][p] + if ((a = length(t)) <= ln) { + return t + } + if (ln < 11) { + return substr(t, a - ln + 1) + } + if (ln < 19) { + return ("..." substr(t, a - ln + 4)) + } + return (substr(t, 1, b = int((ln - 3) / 2)) "..." substr(t, a - ln + b + 4)) +} + +#_______________________________________________________________________ +function _constatpop() +{ + ################################################## + if (_CONSTATPUSH[0] > 0) { + return _constat(_CONSTATPUSH[_CONSTATPUSH[0]--]) + } + return _constat("") +} + +#_______________________________________________________________________ +function _constatpush(t, ts) +{ + ############################################# + _CONSTATPUSH[++_CONSTATPUSH[0]] = _constatstr + if (t) { + _constat(t, ts) + } + return _constatstr +} + +#___________________________________________________________________________________ +function _creport(p, t, f, z) +{ + _[p]["REPORT"] = _[p]["REPORT"] _ln(t ((f == "" ? "" : ": " f))) +} + +#_________________________________________________________________________________________ +function _defdir(pp, n, f, v, p) +{ + ############################################################# + _[p = _wLCHLD(pp, _n("TYPE", "defdir"))]["NAME"] = n + _[p]["DIR"] = f + return p +} + +#_________________________________________________________________________________________ +function _defdll(pp, n, rn, p) +{ + ############################################################## + _[p = _wLCHLD(pp, _n("TYPE", "defdll"))]["NAME"] = n + _[p]["REGPATH"] = _[pp]["REGPATH"] rn + _[p]["ERRHOST"] = pp + return p +} + +#___________________________________________________________ +function _defescarr(D, r, S, i, c, t) +{ + if (isarray(S)) { + for (i = 0; i < 256; i++) { + if ((c = _CHR[i]) ~ r) { + D[c] = "\\" S[c] + t = t c + } else if (D[c] == "") { + D[c] = c } } - delete _CLASSPTR[p] - return _deluida0 - } - - function _dir(A, rd, i, r, f, ds, pf, B, C) - { - delete A - gsub(/(^[ \t]*)|([ \t]*$)/, "", rd) - if (rd == "") { + } else { + for (i = 0; i < 256; i++) { + if ((c = _CHR[i]) ~ r) { + D[c] = S c + if (S != "") { + t = t c + } + } else if (D[c] == "") { + D[c] = c + } + } + } + return t +} + +#_________________________________________________________________________________________ +function _defile(pp, n, f, v, p) +{ + ############################################################# + _[p = _wLCHLD(pp, _n("TYPE", "defile"))]["NAME"] = n + _[p]["FILE"] = f + if (! (v == 0 && v == "")) { + _[p]["RQVERSION"] = v + } + return p +} + +#_______________________________________________________________________ +function _defn(f, c, v) +{ + ################################################### + FUNCTAB[c f] = v +} + +#_________________________________________________________________________________________ +function _defreg(pp, n, f, v, p) +{ + ############################################################# + _[p = _wLCHLD(pp, _n("TYPE", "defreg"))]["NAME"] = n + _[p]["REGPATH"] = f + if (! (v == 0 && v == "")) { + _[p]["VALUE"] = v + } +} + +#_______________________________________________________________________________________________ +function _defsolution(pp, n, rn, p) +{ + ############################################################### + _[p = _wLCHLD(pp, _n("TYPE", "solution"))]["NAME"] = n + _[p]["REGPATH"] = rn + _[p]["ERRHOST"] = pp + return p +} + +#_________________________________________________________________________________________ +function _defsrv(pp, n, f, v, p) +{ + ############################################################# + _[p = _wLCHLD(pp, _n("TYPE", "defsrv"))]["NAME"] = n + _[p]["SERVNAME"] = f + return p +} + +#_______________________________________________________________________ +function _del(f, c, a, A) +{ + ################################################# + if (match(f, /\\[ \t]*$/)) { + if ((c = toupper(_filerd(f))) && length(f) == FLENGTH) { + _cmd("rd " c " /S /Q 2>NUL") + _deletepfx(_WFILEROOTDIR, c) + _deletepfx(_FILEIO_RDTMP, c) + _deletepfx(_FILEIO_RDNETMP, c) + } else { + _conl("HUJ TEBE!") return "" } - i = split(_cmd("dir \"" rd "\" 2>NUL"), B, /\x0D?\x0A/) - 3 - pf = (match(B[4], /Directory of ([^\x00-\x1F]+)/, C) ? C[1] ((C[1] ~ /\\$/ ? "" : "\\")) : "") - for (r = 0; i > 5; i--) { - if (match(B[i], /^([^ \t]*)[ \t]+([^ \t]*)[ \t]+((<DIR>)|([0-9\,]+))[ \t]+([^\x00-\x1F]+)$/, C)) { - if (C[6] !~ /^\.\.?$/) { - if (C[4]) { - ds = "D " - } else { - ds = C[5] " " - gsub(/\,/, "", ds) - } - if ((f = _filepath(pf C[6] ((C[4] ? "\\" : "")))) != "") { - A[f] = ds C[1] " " C[2] - r++ - } - } + } else { + a = _dir(A, f) + _cmd("del " f " /Q 2>NUL") + for (c in A) { + if (c ~ /\\$/) { + _cmd("rd " c " /S /Q 2>NUL") + _deletepfx(_WFILEROOTDIR, c) + _deletepfx(_FILEIO_RDTMP, c) } + _deletepfx(_FILEIO_RDNETMP, c) } - return r } + return a +} - function _dirtree(A, f, B) - { - gsub(/(^[ \t]*)|([ \t]*$)/, "", f) - delete A - A[""] - delete A[""] - _dirtree_i0(B, 8, split(_cmd("dir \"" f "\" /-C /S 2>NUL"), B, /\x0D?\x0A/), A, f = _filerd(f)) - return f +#_______________________________________________________________________ +function _delay(t, a) +{ + ################################################### + for (a = 1; a <= t; a++) { + _delayms() } +} - function _dirtree_i0(B, i, c, A, f, lf, a, C) - { - delete A[f] - A[f][0] - delete A[f][0] - lf = length(f) - for (; i <= c; ) { - if (match(B[i], /^[ \t]*Directory of (.+)/, C)) { - if (substr(a = _filerd(C[1] "\\"), 1, lf) == f) { - i = _dirtree_i0(B, i + 4, c, A[f], a) +#_________________________________________________________________ +function _delayms(a) +{ + ############################################# + for (a = 1; a <= _delay_perfmsdelay; a++) { + } +} + +#_______________________________________________________________________ +function _deletepfx(A, f, B, le, i) +{ + ######################################## + le = length(f) + for (i in A) { + if (substr(toupper(i), 1, le) == f) { + B[i] = A[i] + delete A[i] + } + } +} + +#_________________________________________________________________ +function _delf(A, f) +{ + ############################################### + A["B"][A["F"][A["B"][f]] = A["F"][f]] = A["B"][f] + delete A["F"][f] + delete A["B"][f] +} + +#_______________________________________________________________________ +function _deluid(p) +{ + ################################################# 1 # + if (p in _CLASSPTR) { + _deluida0 = _CLASSPTR[p] + if (_deluida0 in _UIDOBL) { + _UIDOBLV[_UIDOBL[_deluida0]][p] + } + } + delete _CLASSPTR[p] + return _deluida0 +} + +#_______________________________________________________________________ +function _dir(A, rd, i, r, f, ds, pf, B, C) +{ + #################################### + delete A + gsub(/(^[ \t]*)|([ \t]*$)/, "", rd) + if (rd == "") { + return "" + } + i = split(_cmd("dir \"" rd "\" 2>NUL"), B, /\x0D?\x0A/) - 3 + pf = (match(B[4], /Directory of ([^\x00-\x1F]+)/, C) ? C[1] ((C[1] ~ /\\$/ ? "" : "\\")) : "") + for (r = 0; i > 5; i--) { + if (match(B[i], /^([^ \t]*)[ \t]+([^ \t]*)[ \t]+((<DIR>)|([0-9\,]+))[ \t]+([^\x00-\x1F]+)$/, C)) { + if (C[6] !~ /^\.\.?$/) { + if (C[4]) { + ds = "D " } else { - return i + ds = C[5] " " + gsub(/\,/, "", ds) + } + if ((f = _filepath(pf C[6] ((C[4] ? "\\" : "")))) != "") { + A[f] = ds C[1] " " C[2] + r++ } - } else if (match(B[i++], /^([^ \t\-]+)\-([^ \t\-]+)\-([^ \t]+)[ \t]+([^ \t]+)[ \t]+([0-9]+)[ \t]+(.+)$/, C)) { - A[f][f C[6]] = C[5] " " C[1] "/" _CHR["MONTH"][C[2]] "/" C[3] " " C[4] } } - return i } - - function _dll_check(pp) - { - _dllchktv = "" - _missfl = 1 - _tframe("_dll_check_i0", pp, _REG, pp) - if (1 || "AGENT" in _[pp]) { - if (_dllchktv != _[pp][".Product Version"]) { - _dllerr(_[pp]["AGENT"], "agent version (" _[pp][".Product Version"] ") do not match all lib versions: " _dllchktv "'") + return r +} + +#_________________________________________________________________ +function _dirtree(A, f, B) +{ + ######################################### + gsub(/(^[ \t]*)|([ \t]*$)/, "", f) + delete A + A[""] + delete A[""] + _dirtree_i0(B, 8, split(_cmd("dir \"" f "\" /-C /S 2>NUL"), B, /\x0D?\x0A/), A, f = _filerd(f)) + return f +} + +#___________________________________________________________ +function _dirtree_i0(B, i, c, A, f, lf, a, C) +{ + delete A[f] + A[f][0] + delete A[f][0] + lf = length(f) + for (; i <= c; ) { + if (match(B[i], /^[ \t]*Directory of (.+)/, C)) { + if (substr(a = _filerd(C[1] "\\"), 1, lf) == f) { + i = _dirtree_i0(B, i + 4, c, A[f], a) + } else { + return i } - } else if (! _missfl) { - _creport(pp, "agent not detected in registry") - } else { - _dllerr(pp, "agent not detected in registry but some registry entries exist:") - _tframe("_dll_check_i1", pp, pp) - } - } - - function _dll_check_i0(p, R, pp, p2, i, i2, r, f, v, rs, d, tv, tf) - { - if (_[p]["TYPE"] == "defdll") { - r = toupper(_[p]["REGPATH"]) - rs = 0 - tf = 0 - tv = "" - for (i in R) { - if (toupper(substr(i, 1, length(r))) == r) { - if ((_chka0 = substr(i, 1 + length(r), 1)) == "" || _chka0 == "\\") { + } else if (match(B[i++], /^([^ \t\-]+)\-([^ \t\-]+)\-([^ \t]+)[ \t]+([^ \t]+)[ \t]+([0-9]+)[ \t]+(.+)$/, C)) { + A[f][f C[6]] = C[5] " " C[1] "/" _CHR["MONTH"][C[2]] "/" C[3] " " C[4] + } + } + return i +} + +#_______________________________________________________________________ +function _dll_check(pp) +{ + _dllchktv = "" + _missfl = 1 + _tframe("_dll_check_i0", pp, _REG, pp) #also check that all dll have same version; also check that all dlls have success and then report that DS plug-in version n - installed + if (1 || "AGENT" in _[pp]) { + if (_dllchktv != _[pp][".Product Version"]) { + _dllerr(_[pp]["AGENT"], "agent version (" _[pp][".Product Version"] ") do not match all lib versions: " _dllchktv "'") + } + } else if (! _missfl) { + _creport(pp, "agent not detected in registry") + } else { + _dllerr(pp, "agent not detected in registry but some registry entries exist:") + _tframe("_dll_check_i1", pp, pp) + } +} + +#_______________________________________________ +function _dll_check_i0(p, R, pp, p2, i, i2, r, f, v, rs, d, tv, tf) +{ + if (_[p]["TYPE"] == "defdll") { + r = toupper(_[p]["REGPATH"]) + rs = 0 + tf = 0 + tv = "" + for (i in R) { + if (toupper(substr(i, 1, length(r))) == r) { + if ((_chka0 = substr(i, 1 + length(r), 1)) == "" || _chka0 == "\\") { + rs = 1 + _missfl = 1 + _[p]["." substr(gensub(/\....$/, "", 1, i), i2 = 2 + length(r), length(i) - i2 + 1)] = R[i] + if (chka0 != "") { rs = 1 - _missfl = 1 - _[p]["." substr(gensub(/\....$/, "", 1, i), i2 = 2 + length(r), length(i) - i2 + 1)] = R[i] - if (chka0 != "") { - rs = 1 - } } } } - if (rs) { - if ((i = ".Install Path") in _[p] && (i = ".Product Version") in _[p]) { - _[p]["STATUS"] = "PRESENT" - f = _[p][".Install Path"] - v = _[p][".Product Version"] - if (! (".Module" in _[p])) { - _[pp][".Product Version"] = v - _VAR["HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Deployment\\AgentInstallPath.STR"] = f - _[pp]["AGENT"] = p - _creport("OK: DLL DETECTED(" v "): " substr(_[p]["NAME"], 1, 112)) - } else { - if (_dllchktv == "") { - _dllchktv = v - } else if (v != _dllchktv) { - return _dllerr(p, "different versions detected: " _dllchktv "!=" v "'") - } - ERRNO = "" - if (_th1(_[p]["DATA"] = _rdfile(f), ERRNO)) { - delete _[p]["DATA"] - return _dllerr(p, "read lib: " ERRNO, f) - } - if (v != (_[p]["VERSION"] = _getfilever(f))) { - return _dllerr(p, "library file version mismatch: ==`" _[p]["VERSION"] "'; !=`" v "'", f) - } - _creport(p, "OK: LIBRARY DETECTED(" v "): " substr(f, 1, 100)) - } + } #{ rs=_missfl=1; _[p]["." gensub(/^([^\\]+\\)+(.*)\..../,"\\2","G",i)]=R[i] } } + if (rs) { + if ((i = ".Install Path") in _[p] && (i = ".Product Version") in _[p]) { + _[p]["STATUS"] = "PRESENT" + f = _[p][".Install Path"] + v = _[p][".Product Version"] + if (! (".Module" in _[p])) { + _[pp][".Product Version"] = v + _VAR["HKEY_LOCAL_MACHINE\\SOFTWARE\\Altiris\\Deployment\\AgentInstallPath.STR"] = f + _[pp]["AGENT"] = p + _creport("OK: DLL DETECTED(" v "): " substr(_[p]["NAME"], 1, 112)) } else { - tf = 1 - _dllerr(p, "registry corrupt: `" i "' not present") + if (_dllchktv == "") { + _dllchktv = v + } else if (v != _dllchktv) { + return _dllerr(p, "different versions detected: " _dllchktv "!=" v "'") + } + ERRNO = "" + if (_th1(_[p]["DATA"] = _rdfile(f), ERRNO)) { + delete _[p]["DATA"] + return _dllerr(p, "read lib: " ERRNO, f) + } + if (v != (_[p]["VERSION"] = _getfilever(f))) { + return _dllerr(p, "library file version mismatch: ==`" _[p]["VERSION"] "'; !=`" v "'", f) + } + _creport(p, "OK: LIBRARY DETECTED(" v "): " substr(f, 1, 100)) } } else { - _[p]["STATUS"] = "MISSED" + tf = 1 + _dllerr(p, "registry corrupt: `" i "' not present") } + } else { + _[p]["STATUS"] = "MISSED" } } +} - function _dll_check_i1(p, pp, p1, p2, p3, i) - { - if (_[p]["TYPE"] == "defdll") { - for (i in _[p]) { - if (i ~ /^\./) { - _dllerr(pp, " " _[p]["REGPATH"] "\\" substr(i, 2)) - } +#_______________________________________________ +function _dll_check_i1(p, pp, p1, p2, p3, i) +{ + if (_[p]["TYPE"] == "defdll") { + for (i in _[p]) { + if (i ~ /^\./) { + _dllerr(pp, " " _[p]["REGPATH"] "\\" substr(i, 2)) } } } +} - function _dllerr(p, t, f) - { - if (t !~ /\x00/) { - t = "ERROR: \000" t - } - _errfl = 1 - _[p]["ERROR"] = _[p]["ERROR"] _ln(t ((f == "" ? "" : ": " f))) +#___________________________________________________________________________________ +function _dllerr(p, t, f) +{ + if (t !~ /\x00/) { + t = "ERROR: \000" t } + _errfl = 1 + _[p]["ERROR"] = _[p]["ERROR"] _ln(t ((f == "" ? "" : ": " f))) +} - function _drawuid(p, cn, ch, o) - { - _conl("uid: " p) - _conl("\toblptr: " ((p in _UIDOBL ? _UIDOBL[p] "'" : "-"))) - if (p in _UIDOBL) { - if (! _isptr(o = _UIDOBL[p])) { - _conl(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> oblptr not pointer") - } - if (! isarray(_UIDOBLV[o])) { - _conl(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> no OBLV array at ptr") - } +function _drawuid(p, cn, ch, o) +{ + _conl("uid: " p) + _conl("\toblptr: " ((p in _UIDOBL ? _UIDOBL[p] "'" : "-"))) + if (p in _UIDOBL) { + if (! _isptr(o = _UIDOBL[p])) { + _conl(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> oblptr not pointer") } - _conl("\tprefix: " ((p in _UIDPFX ? _UIDPFX[p] "'" : "-"))) - _conl("\tsuffix: " ((p in _UIDSFX ? _UIDSFX[p] "'" : "-"))) - _conl("\tcounters: " (cn = (p in _UIDCNT ? _UIDCNT[p] "'" : "-"))) - if (cn != "-") { - _conl("\t\tcntrL: " _UIDCNTL[_UIDCNT[p]] "'") - _conl("\t\tcntrH: " _UIDCNTH[_UIDCNT[p]] "'") - } - _conl("\tcharset: " (ch = (p in _UIDCHR ? _UIDCHR[p] "'" : "-"))) - if (ch != "-") { - _conl("chrH: ") - _conl(_dumparr(_UIDCHRH[_UIDCHR[p]])) - _conl() - _conl("chrL: ") - _conl(_dumparr(_UIDCHRL[_UIDCHR[p]])) - _conl() - } - } - - function _dumparr(A, t, lv, a) - { - b = PROCINFO["sorted_in"] - PROCINFO["sorted_in"] = "_lengthsort" - if (isarray(A)) { - delete _DUMPARR - _dumparrc = _dumparrd = "" - _dumparr_i1(A, lv = ((lv == "" ? 16 : (lv == 0 || lv + 0 != 0 ? lv : (lv == "-*" ? -3 : (lv ~ /^\+?\*$/ ? 3 : 16))))) + 0, (lv < 0 ? -1 : 1), 0, _tabtospc(t)) - PROCINFO["sorted_in"] = a - return _retarrd(_DUMPARR, _dumparrd, _dumparrd = "") - } - } - - function _dumparr_i1(A, lv, ls, ln, t, t2, i, a, f) - { - t2 = _getchrln(" ", length(t)) - if (ln == lv) { - if (ls > 0) { - for (i in A) { - ++a - } - } else { - for (i in A) { - (isarray(A[i]) ? ++a : "") - } - } - if (length(_dumparrd = _dumparrd t ((a > 0 ? " ... (x" a ")" : "")) _CHR["EOL"]) > 262144) { - _DUMPARR[++_dumparrc] = _dumparrd - _dumparrd = "" - } - return + if (! isarray(_UIDOBLV[o])) { + _conl(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> no OBLV array at ptr") } - if (ls >= 0) { + } + _conl("\tprefix: " ((p in _UIDPFX ? _UIDPFX[p] "'" : "-"))) + _conl("\tsuffix: " ((p in _UIDSFX ? _UIDSFX[p] "'" : "-"))) + _conl("\tcounters: " (cn = (p in _UIDCNT ? _UIDCNT[p] "'" : "-"))) + if (cn != "-") { + _conl("\t\tcntrL: " _UIDCNTL[_UIDCNT[p]] "'") + _conl("\t\tcntrH: " _UIDCNTH[_UIDCNT[p]] "'") + } + _conl("\tcharset: " (ch = (p in _UIDCHR ? _UIDCHR[p] "'" : "-"))) + if (ch != "-") { + _conl("chrH: ") + _conl(_dumparr(_UIDCHRH[_UIDCHR[p]])) + _conl() + _conl("chrL: ") + _conl(_dumparr(_UIDCHRL[_UIDCHR[p]])) + _conl() + } +} + +#_______________________________________________________________________ +function _dumparr(A, t, lv, a) +{ + ############################################ + b = PROCINFO["sorted_in"] + PROCINFO["sorted_in"] = "_lengthsort" + if (isarray(A)) { + delete _DUMPARR + _dumparrc = _dumparrd = "" + _dumparr_i1(A, lv = ((lv == "" ? 16 : (lv == 0 || lv + 0 != 0 ? lv : (lv == "-*" ? -3 : (lv ~ /^\+?\*$/ ? 3 : 16))))) + 0, (lv < 0 ? -1 : 1), 0, _tabtospc(t)) + PROCINFO["sorted_in"] = a + return _retarrd(_DUMPARR, _dumparrd, _dumparrd = "") + } +} + +#___________________________________________________________ +function _dumparr_i1(A, lv, ls, ln, t, t2, i, a, f) +{ + t2 = _getchrln(" ", length(t)) + if (ln == lv) { + if (ls > 0) { for (i in A) { - if (! isarray(A[i])) { - if (length(_dumparrd = _dumparrd ((f ? t2 : t _nop(f = 1))) "[" i "]=" A[i] "'" _CHR["EOL"]) > 262144) { - _DUMPARR[++_dumparrc] = _dumparrd - _dumparrd = "" - } - } - } - } - for (i in A) { - if (isarray(A[i])) { - _dumparr_i1(A[i], lv, ls, ln + ls, _th0((f ? t2 : t), f = 1) "[" i "]") + ++a } - } - if (! f) { - if (length(_dumparrd = _dumparrd t _CHR["EOL"]) > 262144) { - _DUMPARR[++_dumparrc] = _dumparrd - _dumparrd = "" + } else { + for (i in A) { + (isarray(A[i]) ? ++a : "") } } - } - - function _dumpobj(p, f, t, s) - { - s = _dumpobj_i0(p, f, t = t "." p "{") - if (p = _rFCHLD(p)) { - return (s = s _dumpobjm(p, f, (s ? _getchrln(" ", length(t) - 1) : t " "))) + if (length(_dumparrd = _dumparrd t ((a > 0 ? " ... (x" a ")" : "")) _CHR["EOL"]) > 262144) { + _DUMPARR[++_dumparrc] = _dumparrd + _dumparrd = "" } - return s - } - - function _dumpobj_i0(p, f, t) - { - if (f == "") { - return _dumpobj_i2(p, t) - } - if (f == 0) { - return _dumpobj_i1(p, t " ") - } - return (_dumpobj_i1(p, t " ") _dumpobj_i2(p, _getchrln(" ", length(t)))) - } - - function _dumpobj_i1(p, t) - { - return _ln(t substr(((p in _tPREV ? "\253" _tPREV[p] : "")) " ", 1, 7) " " substr(((p in _tPARENT ? "\210" _tPARENT[p] : "")) " ", 1, 7) " " substr(((p in _tFCHLD ? _tFCHLD[p] : "")) "\205" ((p in _tQCHLD ? " (" _tQCHLD[p] ") " : "\205")) "\205" ((p in _tLCHLD ? _tLCHLD[p] : "")) " ", 1, 22) substr(((p in _tNEXT ? "\273" _tNEXT[p] : "")) " ", 1, 8)) - } - - function _dumpobj_i2(p, t) - { - return (_dumpobj_i3(_[p], t " ") _dumpobj_i3(_ptr[p], _getchrln(" ", length(t)) "`", "`")) + return } - - function _dumpobj_i3(A, t, p, e, s, i, t2) - { - if (isarray(A)) { - for (i in A) { - t2 = _getchrln(" ", length(t)) - for (i in A) { - if (isarray(A[i])) { - s = s _dumpobj_i3(A[i], t "[" _dumpobj_i4(i) "]", p, _ln()) - } else { - s = s _ln(t "[" _dumpobj_i4(i) "]=" p _dumpobj_i4(A[i]) "'") - } - t = t2 + if (ls >= 0) { + for (i in A) { + if (! isarray(A[i])) { + if (length(_dumparrd = _dumparrd ((f ? t2 : t _nop(f = 1))) "[" i "]=" A[i] "'" _CHR["EOL"]) > 262144) { + _DUMPARR[++_dumparrc] = _dumparrd + _dumparrd = "" } - return s } - return ((e == "" ? "" : t e)) } - if (A == 0 && A == "") { - return + } + for (i in A) { + if (isarray(A[i])) { + _dumparr_i1(A[i], lv, ls, ln + ls, _th0((f ? t2 : t), f = 1) "[" i "]") } - return _ln(t "=" _dumpobj_i4(p A) "'") } - - function _dumpobj_i4(t) - { - if (length(t) > 64) { - return (substr(t, 1, 28) " ... " substr(t, length(t) - 28)) + if (! f) { + if (length(_dumparrd = _dumparrd t _CHR["EOL"]) > 262144) { + _DUMPARR[++_dumparrc] = _dumparrd + _dumparrd = "" } - return t } +} - function _dumpobj_nc(p, f, t) - { - return _dumpobj_i0(p, f, t "." p "{ ") - } +#___________________________________________________________________________________ +#################################################################################### - function _dumpobjm(p, f, t, s, t2) - { - t2 = _getchrln(" ", length(t)) - do { - s = s _dumpobj(p, f, t) - t = t2 - } while (p = _rNEXT(p)) - return s - } - function _dumpobjm_nc(p, f, t, s, t2) - { - t2 = _getchrln(" ", length(t)) - do { - s = s _dumpobj_nc(p, f, t) - t = t2 - } while (p = _rNEXT(p)) - return s - } +#___________________________________________________________________________________ +# OTHER tFUNCTIONs ################################################################# - function _dumpuidgen(p, pd, pc, ps) - { - _conline("#" ++cntdm ": " p "'") - _conl() - if (p in _tuidel) { - _conl("DEL: " _var(pd = _tuidel[p])) - _conl(_dumparr(_tUIDEL[pd]) _ln()) - } - _conl("PFX: " _tUIDPFX[p] "'") - _conl("SFX: " _tUIDSFX[p] "'") - _conl("COUNT: " ((p in _tuidcnt ? (pc = _tuidcnt[p]) "'" : _th0("-", pc = -2)))) - _con("CHARS: ") - if (p in _tuidchr) { - _conl((ps = _tuidchr[p]) "'") - _conl("HCHR: " ((pc == -2 ? "-" : _tUIDCNTH[pc] "'"))) - _conl(_dumparr(_tUIDCHRH[ps]) _ln()) - _conl("LCHR: " ((pc == -2 ? "-" : _tUIDCNTL[pc] "'"))) - _conl(_dumparr(_tUIDCHRL[ps]) _ln()) - } else { - _conl("-") - } +#_____________________________________________________________________________ +function _dumpobj(p, f, t, s) +{ + ################################################### + s = _dumpobj_i0(p, f, t = t "." p "{") + if (p = _rFCHLD(p)) { + return (s = s _dumpobjm(p, f, (s ? _getchrln(" ", length(t) - 1) : t " "))) } + return s +} - function _dumpval(v, n) - { - _dumpstr = _dumpstr (v = _ln(((n == 0 && n == "" ? "RET" : n)) ": " ((v == 0 && v == "" ? "-" : v "'")))) - return v +#___________________________________________________________ +function _dumpobj_i0(p, f, t) +{ + if (f == "") { + return _dumpobj_i2(p, t) } - - function _eXTFN(c, t, P) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_extfn 1.0") - case "_lib_BEGIN": - return - case "_lib_END": - return - } - } - - function _endpass(t) - { - _endpass_v0 = t + if (f == 0) { + return _dumpobj_i1(p, t " ") } + return (_dumpobj_i1(p, t " ") _dumpobj_i2(p, _getchrln(" ", length(t)))) +} - function _err(t, a, b) - { - a = BINMODE - b = ORS - BINMODE = "rw" - ORS = "" - print(t) > _SYS_STDERR - fflush(_SYS_STDERR) - BINMODE = a - ORS = b - return t - } +#___________________________________________________________ +function _dumpobj_i1(p, t) +{ + return _ln(t substr(((p in _tPREV ? "\253" _tPREV[p] : "")) " ", 1, 7) " " substr(((p in _tPARENT ? "\210" _tPARENT[p] : "")) " ", 1, 7) " " substr(((p in _tFCHLD ? _tFCHLD[p] : "")) "\205" ((p in _tQCHLD ? " (" _tQCHLD[p] ") " : "\205")) "\205" ((p in _tLCHLD ? _tLCHLD[p] : "")) " ", 1, 22) substr(((p in _tNEXT ? "\273" _tNEXT[p] : "")) " ", 1, 8)) +} - function _errnl(t) - { - return _err(t ((t ~ /\x0A$/ ? "" : _CHR["EOL"]))) - } +#___________________________________________________________ +function _dumpobj_i2(p, t) +{ + return (_dumpobj_i3(_[p], t " ") _dumpobj_i3(_ptr[p], _getchrln(" ", length(t)) "`", "`")) +} - function _error(t, d, A) - { - if (_ERRLOG_EF) { - A["TYPE"] = "ERROR" - A["TEXT"] = t - _log(A, d) +#___________________________________________________________ +function _dumpobj_i3(A, t, p, e, s, i, t2) +{ + if (isarray(A)) { + for (i in A) { + t2 = _getchrln(" ", length(t)) + for (i in A) { + if (isarray(A[i])) { + s = s _dumpobj_i3(A[i], t "[" _dumpobj_i4(i) "]", p, _ln()) + } else { + s = s _ln(t "[" _dumpobj_i4(i) "]=" p _dumpobj_i4(A[i]) "'") + } + t = t2 + } + return s } + return ((e == "" ? "" : t e)) } - - function _exit(c) - { - exit c - } - - function _export_data(t, i, A) - { - A["DATA"] = t - A["ID"] = i - _expout("_DATA: " _Zexparr(A) "\n") + if (A == 0 && A == "") { + return } - - function _expout(t, d, a, b) - { - a = BINMODE - b = ORS - BINMODE = "rw" - ORS = "" - print(t) > ((d ? d : d = _errlog_file)) - fflush(d) - BINMODE = a - ORS = b + return _ln(t "=" _dumpobj_i4(p A) "'") +} + +#___________________________________________________________ +function _dumpobj_i4(t) +{ + if (length(t) > 64) { + return (substr(t, 1, 28) " ... " substr(t, length(t) - 28)) + } + return t +} + +#_________________________________________________________________ +function _dumpobj_nc(p, f, t) +{ + ####################################### + return _dumpobj_i0(p, f, t "." p "{ ") +} + +#_________________________________________________________________ +function _dumpobjm(p, f, t, s, t2) +{ + ################################### + t2 = _getchrln(" ", length(t)) + do { + s = s _dumpobj(p, f, t) + t = t2 + } while (p = _rNEXT(p)) + return s +} + +#_________________________________________________________________ +function _dumpobjm_nc(p, f, t, s, t2) +{ + ################################ + t2 = _getchrln(" ", length(t)) + do { + s = s _dumpobj_nc(p, f, t) + t = t2 + } while (p = _rNEXT(p)) + return s +} + +function _dumpuidgen(p, pd, pc, ps) +{ + _conline("#" ++cntdm ": " p "'") + _conl() + if (p in _tuidel) { + _conl("DEL: " _var(pd = _tuidel[p])) + _conl(_dumparr(_tUIDEL[pd]) _ln()) + } + _conl("PFX: " _tUIDPFX[p] "'") + _conl("SFX: " _tUIDSFX[p] "'") + _conl("COUNT: " ((p in _tuidcnt ? (pc = _tuidcnt[p]) "'" : _th0("-", pc = -2)))) + _con("CHARS: ") + if (p in _tuidchr) { + _conl((ps = _tuidchr[p]) "'") + _conl("HCHR: " ((pc == -2 ? "-" : _tUIDCNTH[pc] "'"))) + _conl(_dumparr(_tUIDCHRH[ps]) _ln()) + _conl("LCHR: " ((pc == -2 ? "-" : _tUIDCNTL[pc] "'"))) + _conl(_dumparr(_tUIDCHRL[ps]) _ln()) + } else { + _conl("-") + } +} + +#_____________________________________________________________________________ +function _dumpval(v, n) +{ + _dumpstr = _dumpstr (v = _ln(((n == 0 && n == "" ? "RET" : n)) ": " ((v == 0 && v == "" ? "-" : v "'")))) + return v +} + +######################################################## +function _eXTFN(c, t, P) +{ + switch (c) { + case "_lib_CMDLN": + return t + #___________________________________________________________ + case "_lib_APPLY": + return + #___________________________________________________________ + case "_lib_HELP": + return + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_extfn 1.0") + #___________________________________________________________ + case "_lib_BEGIN": + return + #___________________________________________________________ + case "_lib_END": + return } - - function _extfn_init() - { - _formatstrs_init() - _formatstrd_init() - _formatrexp_init() - _unformatstr_init() - _mac_init() +} + +#_________________________________________________________________ +function _endpass(t) +{ + _endpass_v0 = t +} + +#_______________________________________________________________________ +function _err(t, a, b) +{ + ################################################### + a = BINMODE + b = ORS + BINMODE = "rw" + ORS = "" + print(t) > _SYS_STDERR + fflush(_SYS_STDERR) + BINMODE = a + ORS = b + return t +} + +#_________________________________________________________________ +function _errnl(t) +{ + ################################################ + return _err(t ((t ~ /\x0A$/ ? "" : _CHR["EOL"]))) +} + +#_______________________________________________________________________ +function _error(t, d, A) +{ + ################################################# + if (_ERRLOG_EF) { + A["TYPE"] = "ERROR" + A["TEXT"] = t + _log(A, d) + } +} + +#_______________________________________________________________________ +function _exit(c) +{ + ####################################################### + exit c +} + +#_____________________________________________________________________________ +function _export_data(t, i, A) +{ + ################################################# + A["DATA"] = t + A["ID"] = i + _expout("_DATA: " _Zexparr(A) "\n") +} + +#___________________________________________________________________________________ +#################################################################################### + +#_____________________________________________________________________________ +function _expout(t, d, a, b) +{ + #################################################### + a = BINMODE + b = ORS + BINMODE = "rw" + ORS = "" + print(t) > ((d ? d : d = _errlog_file)) + fflush(d) + BINMODE = a + ORS = b +} + +#_________________________________________________________________________________________ +########################################################################################## +function _extfn_init() +{ + ############################################################## + _formatstrs_init() + _formatstrd_init() + _formatrexp_init() + _unformatstr_init() + _mac_init() +} + +function _faccl_i0(A, t, p, P, f, r) +{ + f = r = "" + if (isarray(A)) { + while (f = A[f]) { + r = (@f(t, p, P)) r + } + } + return r +} + +function _faccr_i0(A, t, p, P, f, r) +{ + f = r = "" + if (isarray(A)) { + while (f = A[f]) { + r = r @f(t, p, P) + } + } + return r +} + +#_______________________________________________________________________ +function _fatal(t, d, A) +{ + ################################################# + if (_ERRLOG_FF) { + A["TYPE"] = "FATAL" + A["TEXT"] = t + _log(A, d) + } + if (! d) { + exit + } +} + +function _fbaccl(A, t, p, P) +{ + return _faccl_i0(A["B"], t, p, P) +} + +function _fbaccr(A, t, p, P) +{ + return _faccr_i0(A["B"], t, p, P) +} + +function _ffaccl(A, t, p, P) +{ + return _faccl_i0(A["F"], t, p, P) +} + +function _ffaccr(A, t, p, P) +{ + return _faccr_i0(A["F"], t, p, P) +} + +################## +function _fframe(A, t, p) +{ + #_______________________________________________________________________ + return _fframe_i0(A, t, p, A[""]) ################################################# +} + +#___________________________________________________________ +function _fframe_i0(A, t, p, f) +{ + return ((f ? (@f(t, p)) _fframe_i0(A, t, p, A[f]) : "")) +} + +#_________________________________________________________________ +function _file(f) +{ + ################################################# + if ((f = _filerdnehnd(f)) == "") { + return "" } - - function _faccl_i0(A, t, p, P, f, r) - { - f = r = "" - if (isarray(A)) { - while (f = A[f]) { - r = (@f(t, p, P)) r - } + return ((f in _FILEXT ? _FILEXT[f] : "")) +} + +#_______________________________________________________________________ +function _file_check(p) +{ + if (1 || "AGENT" in _[p]) { + _tframe("_file_check_i0", p, p) + } +} + +#_______________________________________________ +function _file_check_i0(p, pp, p1, p2, f, v) +{ + if (_[p]["TYPE"] == "defile") { + f = _[p]["FILE"] + f = ((match(f, /^.:/) ? "" : _[_[pp]["AGENT"]][".Install Path"] "\\")) _[p]["FILE"] + if ("RQVERSION" in _[p]) { + v = _[p]["RQVERSION"] + } else { + v = _[pp][".Product Version"] } - return r - } - - function _faccr_i0(A, t, p, P, f, r) - { - f = r = "" - if (isarray(A)) { - while (f = A[f]) { - r = r @f(t, p, P) - } + ERRNO = "" + if (_th1(_[p]["DATA"] = _rdfile(f), ERRNO)) { + delete _[p]["DATA"] + return _dllerr(p, "read file: " ERRNO, f) } - return r - } - - function _fatal(t, d, A) - { - if (_ERRLOG_FF) { - A["TYPE"] = "FATAL" - A["TEXT"] = t - _log(A, d) + if (v != "" && v != (_[p]["VERSION"] = _getfilever(f))) { + return _dllerr(p, " file version mismatch: ==`" _[p]["VERSION"] "'; !=`" v "'", f) } - if (! d) { - exit + _creport(p, substr("OK: FILE DETECTED" ((v == "" ? "" : "(" v ")")) ": " f, 1, 122)) + } else if (_[p]["TYPE"] == "defdir") { + if (_filexist(f = _[p]["DIR"])) { + _creport(p, substr("OK: DIR DETECTED: " f, 1, 112)) + } else { + _dllerr(p, "directory " f " is not detected") } } +} - function _fbaccl(A, t, p, P) - { - return _faccl_i0(A["B"], t, p, P) - } - - function _fbaccr(A, t, p, P) - { - return _faccr_i0(A["B"], t, p, P) +#_________________________________________________________________ +function _filed(f, dd, d) +{ + ########################################## + if ((f = _filerdnehnd(f)) == "") { + return "" } - - function _ffaccl(A, t, p, P) - { - return _faccl_i0(A["F"], t, p, P) + if (f in _FILEDIRFL) { + return _FILEDIR[f] } - - function _ffaccr(A, t, p, P) - { - return _faccr_i0(A["F"], t, p, P) + if (f in _FILEROOT) { + if (d = filegetdrvdir(_FILEROOT[f])) { + _FILEDIRFL[f] + } + return (_FILEDIR[f] = d _FILEDIR[f]) } - - function _fframe(A, t, p) - { - return _fframe_i0(A, t, p, A[""]) + if ((dd = (dd ? dd : _FILEIO_RD), f) in _FILEDIR) { + return _FILEDIR[dd, f] } - - function _fframe_i0(A, t, p, f) - { - return ((f ? (@f(t, p)) _fframe_i0(A, t, p, A[f]) : "")) + if ((d = filedi(dd) _FILEDIR[f]) ~ /^\\/) { + return (_FILEDIR[dd, f] = d) } + return d +} - function _file(f) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - return ((f in _FILEXT ? _FILEXT[f] : "")) +#_________________________________________________________________ +function _filen(f) +{ + ################################################ + if ((f = _filerdnehnd(f)) == "") { + return "" } + return ((f in _FILENAM ? _FILENAM[f] : "")) +} - function _file_check(p) - { - if (1 || "AGENT" in _[p]) { - _tframe("_file_check_i0", p, p) - } +#_________________________________________________________________ +function _filene(f) +{ + ############################################### + if ((f = _filerdnehnd(f)) == "") { + return "" } + return (((f in _FILENAM ? _FILENAM[f] : "")) ((f in _FILEXT ? _FILEXT[f] : ""))) +} - function _file_check_i0(p, pp, p1, p2, f, v) - { - if (_[p]["TYPE"] == "defile") { - f = _[p]["FILE"] - f = ((match(f, /^.:/) ? "" : _[_[pp]["AGENT"]][".Install Path"] "\\")) _[p]["FILE"] - if ("RQVERSION" in _[p]) { - v = _[p]["RQVERSION"] - } else { - v = _[pp][".Product Version"] - } - ERRNO = "" - if (_th1(_[p]["DATA"] = _rdfile(f), ERRNO)) { - delete _[p]["DATA"] - return _dllerr(p, "read file: " ERRNO, f) - } - if (v != "" && v != (_[p]["VERSION"] = _getfilever(f))) { - return _dllerr(p, " file version mismatch: ==`" _[p]["VERSION"] "'; !=`" v "'", f) - } - _creport(p, substr("OK: FILE DETECTED" ((v == "" ? "" : "(" v ")")) ": " f, 1, 122)) - } else if (_[p]["TYPE"] == "defdir") { - if (_filexist(f = _[p]["DIR"])) { - _creport(p, substr("OK: DIR DETECTED: " f, 1, 112)) - } else { - _dllerr(p, "directory " f " is not detected") - } - } +#_________________________________________________________________ +function _filenotexist(f, a) +{ + ###################################### + if (f == "") { + return "" } - - function _filed(f, dd, d) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - if (f in _FILEDIRFL) { - return _FILEDIR[f] - } - if (f in _FILEROOT) { - if (d = filegetdrvdir(_FILEROOT[f])) { - _FILEDIRFL[f] - } - return (_FILEDIR[f] = d _FILEDIR[f]) - } - if ((dd = (dd ? dd : _FILEIO_RD), f) in _FILEDIR) { - return _FILEDIR[dd, f] - } - if ((d = filedi(dd) _FILEDIR[f]) ~ /^\\/) { - return (_FILEDIR[dd, f] = d) - } - return d + if ((a = _filepath(f)) == "") { + ERRNO = "Filepath error `" f "'" + return "" } - - function _filen(f) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - return ((f in _FILENAM ? _FILENAM[f] : "")) + _cmd("if exist \"" a "\" exit 1 2>NUL") + if (_exitcode == 1) { + return (ERRNO = _NOP) } + return a +} - function _filene(f) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - return (((f in _FILENAM ? _FILENAM[f] : "")) ((f in _FILEXT ? _FILEXT[f] : ""))) +#_______________________________________________________________________ +function _filepath(f, dd) +{ + ################################################ + if ((f = _filerdnehnd(f)) == "") { + return "" } + return (filegetrootdir(f, dd) ((f in _FILENAM ? _FILENAM[f] : "")) ((f in _FILEXT ? _FILEXT[f] : ""))) +} - function _filenotexist(f, a) - { - if (f == "") { - return "" - } - if ((a = _filepath(f)) == "") { - ERRNO = "Filepath error `" f "'" - return "" - } - _cmd("if exist \"" a "\" exit 1 2>NUL") - if (_exitcode == 1) { - return (ERRNO = _NOP) - } - return a +#_________________________________________________________________ +function _filer(f, dd) +{ + ############################################# + if ((f = _filerdnehnd(f)) == "") { + return "" } - - function _filepath(f, dd) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - return (filegetrootdir(f, dd) ((f in _FILENAM ? _FILENAM[f] : "")) ((f in _FILEXT ? _FILEXT[f] : ""))) + if (f in _FILEROOT) { + return _FILEROOT[f] } - - function _filer(f, dd) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - if (f in _FILEROOT) { - return _FILEROOT[f] - } - if ((dd = (dd ? dd : _FILEIO_RD), f) in _FILEROOT) { - return _FILEROOT[dd, f] - } - return (_FILEROOT[dd, f] = fileri(dd)) + if ((dd = (dd ? dd : _FILEIO_RD), f) in _FILEROOT) { + return _FILEROOT[dd, f] } + return (_FILEROOT[dd, f] = fileri(dd)) +} - function _filerd(f, dd) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - return filegetrootdir(f, dd) +#_________________________________________________________________ +function _filerd(f, dd) +{ + ############################################ + if ((f = _filerdnehnd(f)) == "") { + return "" } + return filegetrootdir(f, dd) +} - function _filerdn(f, dd) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - return ((f in _FILENAM ? filegetrootdir(f, dd) _FILENAM[f] : "")) +#_________________________________________________________________ +function _filerdn(f, dd) +{ + ########################################### + if ((f = _filerdnehnd(f)) == "") { + return "" } + return ((f in _FILENAM ? filegetrootdir(f, dd) _FILENAM[f] : "")) +} - function _filerdne(f, dd) - { - if ((f = _filerdnehnd(f)) == "") { - return "" - } - if (f in _FILENAM) { - return (filegetrootdir(f, dd) _FILENAM[f] ((f in _FILEXT ? _FILEXT[f] : ""))) - } - if (f in _FILEXT) { - return (filegetrootdir(f, dd) _FILEXT[f]) - } +#_________________________________________________________________ +function _filerdne(f, dd) +{ + ########################################## + if ((f = _filerdnehnd(f)) == "") { return "" } + if (f in _FILENAM) { + return (filegetrootdir(f, dd) _FILENAM[f] ((f in _FILEXT ? _FILEXT[f] : ""))) + } + if (f in _FILEXT) { + return (filegetrootdir(f, dd) _FILEXT[f]) + } + return "" +} - function _filerdnehnd(st, c, r, d, n, A) - { - if (st) { - if ((c = toupper(st)) in _FILECACHE) { - FLENGTH = length(st) - return _FILECACHE[c] - } - if (match(st, /^[ \t]*\\[ \t]*\\/)) { - if (match(substr(st, (FLENGTH = RLENGTH) + 1), /^[ \t]*([0-9A-Za-z\-]+)[ \t]*(\\[ \t]*([A-Za-z])[ \t]*\$[ \t]*)?(\\[ \t]*([0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+( +[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+)*[ \t]*\\)+[ \t]*)?(([0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+( +[0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+)*)[ \t]*)?/, A)) { - FLENGTH = FLENGTH + RLENGTH - d = ((A[3] ? "\\" A[3] "$" : "")) A[4] - gsub(/[ \t]*\\[ \t]*/, "\\", d) - if ((st = toupper((r = "\\\\" A[1]) d (n = A[8]))) in _FILECACHE) { - return (_FILECACHE[substr(c, 1, FLENGTH)] = _FILECACHE[st]) - } - _FILEDIR[c = _FILECACHE[substr(c, 1, FLENGTH)] = _FILECACHE[st] = ++_file_rootcntr] = d - _FILEDIRFL[c] - _FILEROOT[c] = r - } else { - FLENGTH = 0 - _filepath_err = "UNC" - return "" - } - } else { - match(st, /^(([ \t]*\.[ \t]*\\[ \t]*)|(([ \t]*([A-Za-z])[ \t]*(\:)[ \t]*)?([ \t]*(\\)[ \t]*)?))([ \t]*(([ \t]*[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+( +[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+)*[ \t]*\\)+)[ \t]*)?([ \t]*([0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+( +[0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+)*)[ \t]*)?/, A) - if (! (FLENGTH = RLENGTH)) { - return "" - } - d = A[8] A[10] +#___________________________________________________________ +function _filerdnehnd(st, c, r, d, n, A) +{ + if (st) { + if ((c = toupper(st)) in _FILECACHE) { + FLENGTH = length(st) + return _FILECACHE[c] + } + if (match(st, /^[ \t]*\\[ \t]*\\/)) { + if (match(substr(st, (FLENGTH = RLENGTH) + 1), /^[ \t]*([0-9A-Za-z\-]+)[ \t]*(\\[ \t]*([A-Za-z])[ \t]*\$[ \t]*)?(\\[ \t]*([0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+( +[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+)*[ \t]*\\)+[ \t]*)?(([0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+( +[0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+)*)[ \t]*)?/, A)) { + FLENGTH = FLENGTH + RLENGTH + d = ((A[3] ? "\\" A[3] "$" : "")) A[4] gsub(/[ \t]*\\[ \t]*/, "\\", d) - if ((st = toupper((r = A[5] A[6]) d (n = A[14]))) in _FILECACHE) { + if ((st = toupper((r = "\\\\" A[1]) d (n = A[8]))) in _FILECACHE) { return (_FILECACHE[substr(c, 1, FLENGTH)] = _FILECACHE[st]) } _FILEDIR[c = _FILECACHE[substr(c, 1, FLENGTH)] = _FILECACHE[st] = ++_file_rootcntr] = d - if (A[8]) { - _FILEDIRFL[c] - } - if (r) { - _FILEROOT[c] = r - } + _FILEDIRFL[c] + _FILEROOT[c] = r + } else { + FLENGTH = 0 + _filepath_err = "UNC" + return "" } - if (n) { - if (match(n, /\.[^\.]*$/)) { - _FILEXT[c] = substr(n, RSTART) - _FILENAM[c] = substr(n, 1, RSTART - 1) - } else { - _FILENAM[c] = n - } + } else { + match(st, /^(([ \t]*\.[ \t]*\\[ \t]*)|(([ \t]*([A-Za-z])[ \t]*(\:)[ \t]*)?([ \t]*(\\)[ \t]*)?))([ \t]*(([ \t]*[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+( +[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+)*[ \t]*\\)+)[ \t]*)?([ \t]*([0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+( +[0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+)*)[ \t]*)?/, A) + if (! (FLENGTH = RLENGTH)) { + return "" + } + d = A[8] A[10] + gsub(/[ \t]*\\[ \t]*/, "\\", d) + if ((st = toupper((r = A[5] A[6]) d (n = A[14]))) in _FILECACHE) { + return (_FILECACHE[substr(c, 1, FLENGTH)] = _FILECACHE[st]) + } + _FILEDIR[c = _FILECACHE[substr(c, 1, FLENGTH)] = _FILECACHE[st] = ++_file_rootcntr] = d + if (A[8]) { + _FILEDIRFL[c] + } + if (r) { + _FILEROOT[c] = r } - return c - } - return "" - } - - function _filexist(f, a) - { - if (f == "") { - return "" - } - if ((a = _filepath(f)) == "") { - ERRNO = "Filepath error `" f "'" - return "" - } - _cmd("if exist \"" a "\" exit 1 2>NUL") - if (_exitcode == 1) { - return a - } - ERRNO = "File not found `" f "'" - return _NOP - } - - function _fn(f, p0, p1, p2) - { - if (f in FUNCTAB) { - return @f(p0, p1, p2) - } - } - - function _foreach(A, f, r, p0, p1, p2, i, p) - { - if (isarray(A)) { - _TMP0[p = _n()]["."] = 1 - _foreach_i0(A, f, _TMP0[p], p0, p1, p2) - return _th0(_retarr(_TMP0[p]), _tdel(p)) - } - if (_isptr(A)) { - _TMP0[p = _n()][_ARRLEN] = 1 - _tframe4("_foreach_i1" ((r ? "~" r : "")), A, f, _TMP0[p], p0, p1) - return _th0(_retarr(_TMP0[p]), _tdel(p)) } - } - - function _foreach_i0(A, f, D, p0, p1, p2) - { - for (i in A) { - if (isarray(A[i])) { - _foreach_i0(A[i], f, D, p0, p1, p2) + if (n) { + if (match(n, /\.[^\.]*$/)) { + _FILEXT[c] = substr(n, RSTART) + _FILENAM[c] = substr(n, 1, RSTART - 1) } else { - _gen(D, @f(A[i], p0, p1, p2)) + _FILENAM[c] = n } } + return c } + return "" +} - function _foreach_i1(p, f, D, p0, p1, p2) - { - _gen(D, @f(p, p0, p1, p2)) - } - - function _formatrexp(t) - { - _formatstrq0 = split(t, _FORMATSTRA, /[\/\x00-\x1F\x80-\xFF]/, _FORMATSTRB) - _formatstrs0 = "" - for (t = 1; t < _formatstrq0; t++) { - _formatstrs0 = _formatstrs0 _FORMATSTRA[t] _FORMATREXPESC[_FORMATSTRB[t]] - } - return (_formatstrs0 _FORMATSTRA[t]) - } - - function _formatrexp_init() - { - _defescarr(_FORMATREXPESC, "[\\x00-\\x1F\\x80-\\xFF]", _QASC) - _defescarr(_FORMATREXPESC, "\\/", "\\") - _FORMATREXPESC["\t"] = "\\t" - } - - function _formatstrd(t) - { - _formatstrq0 = split(t, _FORMATSTRA, /["\x00-\x1F\x80-\xFF]/, _FORMATSTRB) - _formatstrs0 = "" - for (t = 1; t < _formatstrq0; t++) { - _formatstrs0 = _formatstrs0 _FORMATSTRA[t] _FORMATSTRDESC[_FORMATSTRB[t]] - } - return (_formatstrs0 _FORMATSTRA[t]) - } - - function _formatstrd_init() - { - _defescarr(_FORMATSTRDESC, "[\\x00-\\x1F\\x80-\\xFF]", _QASC) - _defescarr(_FORMATSTRDESC, "[\\\\\"]", "\\") - _FORMATSTRDESC["\t"] = "\\t" - } - - function _formatstrs(t) - { - _formatstrq0 = split(t, _FORMATSTRA, /['\x00-\x1F\x80-\xFF]/, _FORMATSTRB) - _formatstrs0 = "" - for (t = 1; t < _formatstrq0; t++) { - _formatstrs0 = _formatstrs0 _FORMATSTRA[t] _FORMATSTRSESC[_FORMATSTRB[t]] - } - return (_formatstrs0 _FORMATSTRA[t]) +#_______________________________________________________________________ +function _filexist(f, a) +{ + ################################################ + if (f == "") { + return "" } - - function _formatstrs_init() - { - _defescarr(_FORMATSTRSESC, "[\\x00-\\x1F\\x80-\\xFF]", _QASC) - _defescarr(_FORMATSTRSESC, "[\\\\']", "\\") - _FORMATSTRSESC["\t"] = "\\t" + if ((a = _filepath(f)) == "") { + ERRNO = "Filepath error `" f "'" + return "" } - - function _fpp(q, D, S) - { - _conl() - _conline(q) - _conl() - q = _patharr0(S, q) - _conl(_dumparr(S)) - _conl() - return q + _cmd("if exist \"" a "\" exit 1 2>NUL") + if (_exitcode == 1) { + return a } - - function _fthru(A, c, p, B) - { - return _fthru_i0(A, c, p, B, A[""]) + ERRNO = "File not found `" f "'" + return _NOP +} + +#_______________________________________________________________________ +function _fn(f, p0, p1, p2) +{ + ################################################ + if (f in FUNCTAB) { + return @f(p0, p1, p2) + } +} + +#_______________________________________________________________________ +function _foreach(A, f, r, p0, p1, p2, i, p) +{ + #################################### + if (isarray(A)) { + _TMP0[p = _n()]["."] = 1 + _foreach_i0(A, f, _TMP0[p], p0, p1, p2) + return _th0(_retarr(_TMP0[p]), _tdel(p)) + } + if (_isptr(A)) { + _TMP0[p = _n()][_ARRLEN] = 1 + _tframe4("_foreach_i1" ((r ? "~" r : "")), A, f, _TMP0[p], p0, p1) + return _th0(_retarr(_TMP0[p]), _tdel(p)) + } +} + +#_____________________________________________________ +function _foreach_i0(A, f, D, p0, p1, p2) +{ + for (i in A) { + if (isarray(A[i])) { + _foreach_i0(A[i], f, D, p0, p1, p2) + } else { + _gen(D, @f(A[i], p0, p1, p2)) + } + } +} + +#_____________________________________________________ +function _foreach_i1(p, f, D, p0, p1, p2) +{ + _gen(D, @f(p, p0, p1, p2)) +} + +#_____________________________________________________________________________ +function _formatrexp(t) +{ + _formatstrq0 = split(t, _FORMATSTRA, /[\/\x00-\x1F\x80-\xFF]/, _FORMATSTRB) + _formatstrs0 = "" + for (t = 1; t < _formatstrq0; t++) { + _formatstrs0 = _formatstrs0 _FORMATSTRA[t] _FORMATREXPESC[_FORMATSTRB[t]] + } + return (_formatstrs0 _FORMATSTRA[t]) +} + +#___________________________________________________________ +function _formatrexp_init() +{ + _defescarr(_FORMATREXPESC, "[\\x00-\\x1F\\x80-\\xFF]", _QASC) + _defescarr(_FORMATREXPESC, "\\/", "\\") + _FORMATREXPESC["\t"] = "\\t" +} + +#_____________________________________________________________________________ +function _formatstrd(t) +{ + _formatstrq0 = split(t, _FORMATSTRA, /["\x00-\x1F\x80-\xFF]/, _FORMATSTRB) + _formatstrs0 = "" + for (t = 1; t < _formatstrq0; t++) { + _formatstrs0 = _formatstrs0 _FORMATSTRA[t] _FORMATSTRDESC[_FORMATSTRB[t]] + } + return (_formatstrs0 _FORMATSTRA[t]) +} + +#___________________________________________________________ +function _formatstrd_init() +{ + _defescarr(_FORMATSTRDESC, "[\\x00-\\x1F\\x80-\\xFF]", _QASC) + _defescarr(_FORMATSTRDESC, "[\\\\\"]", "\\") + _FORMATSTRDESC["\t"] = "\\t" +} + +#__________________________________________________________________________________ +function _formatstrs(t) +{ + #################################################################################### + + + + + #___________________________________________________________________________________ + _formatstrq0 = split(t, _FORMATSTRA, /['\x00-\x1F\x80-\xFF]/, _FORMATSTRB) + _formatstrs0 = "" + for (t = 1; t < _formatstrq0; t++) { + _formatstrs0 = _formatstrs0 _FORMATSTRA[t] _FORMATSTRSESC[_FORMATSTRB[t]] + } + return (_formatstrs0 _FORMATSTRA[t]) +} + +#___________________________________________________________ +function _formatstrs_init() +{ + _defescarr(_FORMATSTRSESC, "[\\x00-\\x1F\\x80-\\xFF]", _QASC) + _defescarr(_FORMATSTRSESC, "[\\\\']", "\\") + _FORMATSTRSESC["\t"] = "\\t" +} + +function _fpp(q, D, S) +{ + _conl() + _conline(q) + _conl() + q = _patharr0(S, q) + #_arregpath(D,S) + #_conl(_dumparr(D)) + _conl(_dumparr(S)) + _conl() + return q +} + +#_______________________________________________________________________ +######################################################################## +function _fthru(A, c, p, B) +{ + return _fthru_i0(A, c, p, B, A[""]) +} + +#_________________________________________________________________ +function _fthru_i0(A, c, p, B, f) +{ + return ((f ? @f(c, _fthru_i0(A, c, p, B, A[f]), B) : "")) +} + +function _gen(D, t) +{ + if (length(D[D[_ARRLEN]] = D[D["."]] t) > _datablock_length) { + D[++D[_ARRLEN]] = "" + } +} + +#_____________________________________________________________________________ +function _gensubfn(t, r, f, p0, A) +{ + ############################################### + if (match(t, r, A)) { + return (substr(t, 1, RSTART - 1) (@f(_th0(substr(t, RSTART, RLENGTH), t = substr(t, RSTART + RLENGTH)), A, p0)) _gensubfn(t, r, f, p0)) + } + return t +} + +#_____________________________________________________________________________ +function _get_errout(p) +{ + ####################################################### + return _tframe("_get_errout_i0", p) +} + +#_______________________________________________________________________ +function _get_errout_i0(p, t, n, a) +{ + return ((p in _tLOG ? _get_errout_i1(p) _get_errout_i3(p) : "")) +} + +#_________________________________________________________________ +function _get_errout_i1(p, t, n, a) +{ + if (p in _tLOG) { + n = "" + if (_tLOG[p]["TYPE"]) { + n = _tLOG[p]["TYPE"] ": " _get_errout_i2(p) + if (match(_tLOG[p]["TEXT"], /\x1F/)) { + t = n + gsub(/[^\t]/, " ", t) + return (_ln(n substr(_tLOG[p]["TEXT"], 1, RSTART - 1)) _ln(t substr(_tLOG[p]["TEXT"], RSTART + 1))) + } + } + return _ln(n _tLOG[p]["TEXT"]) + } +} + +#_______________________________________________________________________ +function _get_errout_i2(p) +{ + return (("FILE" in _tLOG[p] ? _tLOG[p]["FILE"] (("LINE" in _tLOG[p] ? "(" _tLOG[p]["LINE"] ")" : "")) ": " : "")) +} + +#_______________________________________________________________________ +function _get_errout_i3(p, t, ts, cl, cp, cr, a, b) +{ + if ("LSTR" in _tLOG[p]) { + t = _tLOG[p]["FULLSTR"] + ts = _tLOG[p]["TS"] + cp = "^" + if ("CSTR" in _tLOG[p]) { + cr = _tLOG[p]["CSTR"] + cl = _tLOG[p]["CLSTR"] + if ("CPSTR" in _tLOG[p]) { + cp = _tLOG[p]["CPSTR"] + } + } + cr = substr(cr, length(cl) + length(cp) + 1) + return (_ln(_tabtospc(t, ts)) _ln(_getchrln(" ", a = length(_tabtospc(_tLOG[p]["LSTR"], ts))) _getchrln("-", b = length(_tabtospc(cl, ts, a))) _getchrln("^", b = length(_tabtospc(cp, ts, a = a + b))) _getchrln("-", length(_tabtospc(cr, ts, a + b))))) + } +} + +#_____________________________________________________________________________ +function _get_logout(p) +{ + ####################################################### + return _tframe("_get_logout_i0", p) +} + +#_______________________________________________________________________ +function _get_logout_i0(p, t, n, a) +{ + if (p in _tLOG) { + n = (("DATE" in _tLOG[p] ? _tLOG[p]["DATE"] " " : "")) (("TIME" in _tLOG[p] ? _tLOG[p]["TIME"] " " : "")) + if (_tLOG[p]["TYPE"]) { + n = n _tLOG[p]["TYPE"] ": " (("FILE" in _tLOG[p] ? _tLOG[p]["FILE"] (("LINE" in _tLOG[p] ? "(" _tLOG[p]["LINE"] ")" : "")) ": " : "")) + if (match(_tLOG[p]["TEXT"], /\x1F/)) { + t = n + gsub(/[^\t]/, " ", t) + return (_ln(n substr(_tLOG[p]["TEXT"], 1, RSTART - 1)) _ln(t substr(_tLOG[p]["TEXT"], RSTART + 1))) + } + } + return _ln(n _tLOG[p]["TEXT"]) + } +} + +#_______________________________________________________________________ +function _getchrln(s, w) +{ + ################################################# + if (s == "") { + return } - - function _fthru_i0(A, c, p, B, f) - { - return ((f ? @f(c, _fthru_i0(A, c, p, B, A[f]), B) : "")) + #if ( w!=w+0 || w<0 ) w=_CON_WIDTH + if (length(s) < w) { + if (s in _GETCHRLN) { + if (length(_getchrlnt0 = _GETCHRLN[s]) >= w) { + return substr(_getchrlnt0, 1, w) + } + } else { + _getchrlnt0 = s s + } + while (length(_getchrlnt0) < w) { + _getchrlnt0 = _getchrlnt0 _getchrlnt0 + } + _GETCHRLN[s] = _getchrlnt0 + return substr(_getchrlnt0, 1, w) + } else { + return substr(s, 1, w) + } +} + +#_______________________________________________________________________ +function _getdate() +{ + ##################################################### + return strftime("%F") +} + +#_____________________________________________________________________________ +function _getfilepath(t, f, al, b, A) +{ + ############################################ + ERRNO = "" + if (match(t, /^[ \t]*(("([^"]*)"[ \t]*)|([`']([^']*)'[ \t]*)|(([^ \t]+)[ \t]*))/, A)) { + al = RLENGTH + f = A[3] A[5] A[7] + _conl("_getfilepath(" f ") (" al ")") + if (b = _filepath(f)) { + if (length(f) <= FLENGTH) { + FLENGTH = al + return b + } + ERRNO = "Filepath `" f "' error" + } + } + FLENGTH = 0 +} + +function _getfilever(f) +{ + ############################################################# + split(_cmd(_fileverpath " \"" f "\""), _GETFILEVERA0, /[ \t]+/) + if (_GETFILEVERA0[5]) { + return _GETFILEVERA0[5] + } +} + +#_________________________________________________________________ +function _getime() +{ + ################################################ + return strftime("%H:%M:%S") +} + +#_________________________________________________________________ +function _getmpdir(f, dd) +{ + ########################################## + if (! dd || ! (dd = _filerd(dd))) { + dd = _FILEIO_TMPRD + } + if (f = (f ? _filerd(f, dd) : _filerd("_" ++_FILEIO_TMPCNTR "\\", dd))) { + _FILEIO_RDTMP[toupper(f)] + } + return f +} + +#_________________________________________________________________ +function _getmpfile(f, dd) +{ + ######################################### + if (! dd || ! (dd = _filerd(dd))) { + dd = _FILEIO_TMPRD + } + if (f = _filerdne((_filene(f) ? f : f "_" ++_FILEIO_TMPCNTR), dd)) { + _FILEIO_RDNETMP[toupper(f)] + } + return f +} + +#_______________________________________________________________________ +function _getperf(o, t, a) +{ + ############################################### + (o == "" ? ++_getperf_opcurr : _getperf_opcurr = o) + if ((a = _getsecond()) != _getperf_last) { + _getperf_opsec = (_getperf_opcurr - _getperf_opstart) / ((_getperf_last = a) - _getperf_start) + return @_getperf_fn(o, t, a) + } + return 1 +} + +#___________________________________________________________ +function _getperf_(o, t, a) +{ + if (a >= _getperf_end) { + return 0 } - - function _gen(D, t) - { - if (length(D[D[_ARRLEN]] = D[D["."]] t) > _datablock_length) { - D[++D[_ARRLEN]] = "" - } + if (_getperf_opsecp != _getperf_opsec) { + _constat(((_constatstr == _getperf_stat ? _getperf_statstr : _getperf_statstr = _constatstr)) t " [TIME=" (a - _getperf_start) " sec(" (_getperf_opsecp = _getperf_opsec) " ops/sec)]") + _getperf_stat = _constatstr + } + return 1 +} + +#___________________________________________________________ +function _getperf_noe(o, t, a) +{ + if (_getperf_opsecp != _getperf_opsec) { + _constat(((_constatstr == _getperf_stat ? _getperf_statstr : _getperf_statstr = _constatstr)) t " [TIME=" (a - _getperf_start) " sec(" (_getperf_opsecp = _getperf_opsec) " ops/sec)]") + _getperf_stat = _constatstr + } + return 1 +} + +#___________________________________________________________ +function _getperf_noenot(o, t, a) +{ + return 1 +} + +#___________________________________________________________ +function _getperf_not(o, t, a) +{ + if (a < _getperf_end) { + return 1 } - - function _gensubfn(t, r, f, p0, A) - { - if (match(t, r, A)) { - return (substr(t, 1, RSTART - 1) (@f(_th0(substr(t, RSTART, RLENGTH), t = substr(t, RSTART + RLENGTH)), A, p0)) _gensubfn(t, r, f, p0)) +} + +#_________________________________________________________________________________________ +########################################################################################## +function _getreg_i1(D, r, R, a, i, il, ir, rc, B) +{ + a = IGNORECASE + IGNORECASE = 1 + r = "^" _torexp(r) + rc = 0 + zs = "" + for (i in R) { + if (match(i, r, B)) { + il = B[_torexp_pfxcntr] + ir = gensub(/....$/, "", 1, substr(i, 1 + B[_torexp_pfxcntr, "length"])) + if (! gsub(/^\\/, "", ir) && match(il, /[^\\]+$/)) { + ir = substr(il, RSTART) ir + } + D[ir] = R[i] + rc++ + } + } + IGNORECASE = a + if (rc > 0) { + return rc + } +} + +#_________________________________________________________________ +function _getsecond() +{ + ############################################# + return systime() +} + +#___________________________________________________________ +function _getsecondsync(a, c, b, c2) +{ + ########################## + a = systime() + while (a == systime()) { + ++c + } + return (a + 1) +} + +#_______________________________________________________________________ +function _getuid(p) +{ + ################################################# 1 # + if (p in _UIDOBL) { + for (_tptr in _UIDOBLV[_getuida0 = _UIDOBL[p]]) { + delete _UIDOBLV[_getuida0][_tptr] + _CLASSPTR[_tptr] = p + return _tptr + } + } + _CLASSPTR[_tptr = _UIDPFX[p] _getuid_i0(_UIDCNT[p], _UIDCHRL[_tptr = _UIDCHR[p]], _UIDCHRH[_tptr]) _UIDSFX[p]] = p + return _tptr +} + +#_____________________________________________________ +function _getuid_i0(p, UL, UH) +{ + if ("" == (_tptr = UL[_UIDCNTL[p]])) { + for (_tptr in UH) { + delete UH[_tptr] + return ((_UIDCNTH[p] = _tptr) (_UIDCNTL[p] = UL[""])) + } + _fatal("out of UID") + } + return (_UIDCNTH[p] (_UIDCNTL[p] = _tptr)) +} + +function _handle8494(t) +{ + return gensub(/(.)/, ".\\1", "G", t) +} + +#_____________________________________________________________________________ +function _hexnum(n, l) +{ + ######################################################### + if (l + 0 < 1) { + l = 2 + } + return sprintf("%." ((l + 0 < 1 ? 2 : l)) "X", n) +} + +#_________________________________________________________________ +function _igetperf(t, s, o) +{ + ######################################### # t-test period in seconds(==0 ? no period; s(=true/false)-output/not output status; o-qnt of ops before test start + if (t == 0 && t == "" && s == 0 && s == "" && o == 0 && o == "") { + if (_getperf_fn !~ /not$/ && _constatstr == _getperf_stat) { + _constat(_getperf_statstr) } - return t - } - - function _get_errout(p) - { - return _tframe("_get_errout_i0", p) + _getperf_fn = "_nop" + return ("[TIME=" (_getperf_last - _getperf_start) " sec(" _getperf_opsec " ops/sec)]") + } + _conl("initiate _getperf") + _getperf_opstart = _getperf_opcurr = o + 0 + _getperf_opsec = _getperf_opsecp = _getperf_stat = _getperf_statstr = "" + _getperf_end = t + (_getperf_start = _getperf_last = _getsecondsync()) + _getperf_fn = ((t + 0 > 0 ? "_getperf_" : "_getperf_noe")) ((s ? "" : "not")) + return _getperf_start +} + +function _import_data(t, p, p2, a) +{ + if (match(t, /^_DATA: /)) { + _tDATA[a = _wLCHLD(p, _N())][""] + delete _tDATA[a][""] + _Zimparr(_tDATA[a], substr(t, 8)) + _conl("DATA: `" _tDATA[a]["ID"] "':`" _tDATA[a]["DATA"] "'") + return "" } - - function _get_errout_i0(p, t, n, a) - { - return ((p in _tLOG ? _get_errout_i1(p) _get_errout_i3(p) : "")) + return t +} + +#_______________________________________________________________________ +function _info(t, d, A) +{ + ################################################## + if (_ERRLOG_IF) { + A["TYPE"] = "INFO" + A["TEXT"] = t + _log(A, d) + } +} + +# test with the different path types +# _conl(_ln("SRC:") _dumparr(S)); _conl(); +function _ini(p, cs, dptr, pfx, sfx, hstr, lstr) +{ + return _inituid(p, cs, dptr, pfx, sfx, hstr, lstr, A) +} + +function _initfilever() +{ + _fileverpath = "\\\\CPU\\eGAWK\\LIB\\_filever\\_filever.exe" +} + +function _initrdreg() +{ + _RDREGTYPE["SZ"] = "STR" + _RDREGTYPE["DWORD"] = "W32" + _RDREGTYPE["QWORD"] = "W64" + _RDREGTYPE["BINARY"] = "BIN" + _RDREGTYPE["EXPAND_SZ"] = "XSZ" + _RDREGTYPE["MULTI_SZ"] = "MSZ" + _RDrdregfld = _rdregkey = 0 +} + +function _initregpath0() +{ + _REGPATH0REGDIR[""] = "HKEY_LOCAL_MACHINE" + _REGPATH0REGDIR["HKLM"] = "HKEY_LOCAL_MACHINE" + _REGPATH0REGDIR["HKEY_LOCAL_MACHINE"] = "HKEY_LOCAL_MACHINE" + _REGPATH0REGDIR["HKCR"] = "HKEY_CLASSES_ROOT" + _REGPATH0REGDIR["HKEY_CLASSES_ROOT"] = "HKEY_CLASSES_ROOT" + _REGPATH0REGDIR["HKCU"] = "HKEY_CURRENT_USER" + _REGPATH0REGDIR["HKEY_CURRENT_USER"] = "HKEY_CURRENT_USER" + _REGPATH0REGDIR["HKU"] = "HKEY_USERS" + _REGPATH0REGDIR["HKEY_USERS"] = "HKEY_USERS" + _REGPATH0REGDIR["HKCC"] = "HKEY_CURRENT_CONFIG" + _REGPATH0REGDIR["HKEY_CURRENT_CONFIG"] = "HKEY_CURRENT_CONFIG" + _REGPATH0REGDIR["HKPD"] = "HKEY_PERFORMANCE_DATA" + _REGPATH0REGDIR["HKEY_PERFORMANCE_DATA"] = "HKEY_PERFORMANCE_DATA" +} + +function _initshare() +{ + _sharextool = "\\\\CPU\\eGAWK\\LIB\\_share\\_share.exe" +} + +#_________________________________________ +function _initspecialuid() +{ + _NOINDEX = _getuid() + _LEN = _getuid() + _PTR = _getuid() + _NAME = _getuid() + _TYPE = _getuid() + _FORMAT = _getuid() +} + +function _initsys() +{ +} + +#_______________________________________________________________________ +function _inituid(p, cs, dptr, pfx, sfx, hstr, lstr, A) +{ + ################### 1 # + if (cs == 0 && cs == "") { + cs = p + p = _getuid() + } + _conl() + _conl() + _conl(cs) + if (match(cs, /^(([^:]*):)?(([^'\xB4]*\xB4.)*[^'\xB4]*)[']/, A)) { + pfx = A[3] + dptr = A[2] + } + if (match(cs = substr(cs, 1 + RLENGTH), /'(([^'\xB4]*\xB4.)*[^'\xB4]*)$/, A)) { + sfx = A[1] + cs = substr(cs, 1, RSTART - 1) + } + if (match(cs, /^(([`\^])(.*))/, A)) { + if (A[2] == "`") { + hstr = A[3] "~" + lstr = "" + } else { + lstr = A[3] "+" + hstr = "" + } + } else if (match(cs, /^(([^'\xB4\|]*\xB4.)*[^'\xB4\|]*)(\|(.*))?/, A)) { + hstr = A[1] + lstr = A[4] + } else { + ERRNO = "_inituid(): bad parameters" + return } - - function _get_errout_i1(p, t, n, a) - { - if (p in _tLOG) { - n = "" - if (_tLOG[p]["TYPE"]) { - n = _tLOG[p]["TYPE"] ": " _get_errout_i2(p) - if (match(_tLOG[p]["TEXT"], /\x1F/)) { - t = n - gsub(/[^\t]/, " ", t) - return (_ln(n substr(_tLOG[p]["TEXT"], 1, RSTART - 1)) _ln(t substr(_tLOG[p]["TEXT"], RSTART + 1))) + _conl(dptr ":" pfx "'" hstr "|" lstr "'" sfx) + return _cfguid(p, dptr, pfx, sfx, hstr, lstr) +} + +function _inituidefault(h, l, H, L) +{ + _classys = "" + delete _UIDOBLV[_UIDOBLV[_UIDOBL[_classys] = _classys][""] = _classys][""] + _UIDPFX[_classys] + _UIDSFX[_classys] + _UIDCNT[_classys] = _UIDCHR[_classys] = _CLASSPTR[_classys] = _classys + h = "AB" + l = h "01" + _splitstr(H, h) + _splitstr(L, l) + delete _UIDCHRH[_UIDCHRH[_classys][""] = _classys][""] + delete _UIDCHRL[_UIDCHRL[_classys][""] = _classys][""] + _UIDCNTH[_classys] + _cfguidh(_classys, H, L) + _UIDCNTL[_classys] = _cfguidl(_classys, L, L) + _CLASSFN[_classys]["del"] = "_tobjDEL" + _CLASSFN[_classys]["new"] = "_tobjNEW" + _drawuid(_classys) + _initspecialuid() +} + +#_______________________________________________________________________ +function _ins(S, sf, D, df) +{ + ################################################ + if (sf in S) { + if (isarray(S[sf])) { + if (df in D) { + if (isarray(D[df])) { + return _extarr(D[df], S[sf]) } + delete D[df] } - return _ln(n _tLOG[p]["TEXT"]) - } + D[df][""] + delete D[df][""] + return _extarr(D[df], S[sf]) + } else { + if (isarray(D[df])) { + delete D[df] + } + D[df] = S[sf] D[df] + } + } +} + +#_________________________________________________________________ +function _insf(A, f) +{ + ############################################### + A["F"][""] = A["B"][A["F"][f] = A["F"][""]] = f +} + +#_________________________________________________________________ +function _insframe(A, f) +{ + ########################################### + A[f] = A[""] + A[""] = f +} + +######################## +function _inspass(A, f) +{ + #_________________________________________________________________ + A[f] = A[""] + A[""] = f +} + +# there is problem with string's format: i can;t easilly merge 2 charsets: comma-divided and every-char-divided strings + +#_______________________________________________________________________ +function _isptr(p) +{ + ################################################## 1 # + if (isarray(p)) { + is = _NOP + it = "A" + return 0 } - - function _get_errout_i2(p) - { - return (("FILE" in _tLOG[p] ? _tLOG[p]["FILE"] (("LINE" in _tLOG[p] ? "(" _tLOG[p]["LINE"] ")" : "")) ": " : "")) + is = p + if (p == 0 && p == "") { + it = "-" + return 0 } - - function _get_errout_i3(p, t, ts, cl, cp, cr, a, b) - { - if ("LSTR" in _tLOG[p]) { - t = _tLOG[p]["FULLSTR"] - ts = _tLOG[p]["TS"] - cp = "^" - if ("CSTR" in _tLOG[p]) { - cr = _tLOG[p]["CSTR"] - cl = _tLOG[p]["CLSTR"] - if ("CPSTR" in _tLOG[p]) { - cp = _tLOG[p]["CPSTR"] - } - } - cr = substr(cr, length(cl) + length(cp) + 1) - return (_ln(_tabtospc(t, ts)) _ln(_getchrln(" ", a = length(_tabtospc(_tLOG[p]["LSTR"], ts))) _getchrln("-", b = length(_tabtospc(cl, ts, a))) _getchrln("^", b = length(_tabtospc(cp, ts, a = a + b))) _getchrln("-", length(_tabtospc(cr, ts, a + b))))) - } + if (p in _CLASSPTR) { + return (it = "P") } + it = "S" + return 0 +} - function _get_logout(p) - { - return _tframe("_get_logout_i0", p) +#_______________________________________________________________________ +function _istr(p) +{ + ################################################### 1 # + if (isarray(p)) { + is = _NOP + it = "A" + return 0 } - - function _get_logout_i0(p, t, n, a) - { - if (p in _tLOG) { - n = (("DATE" in _tLOG[p] ? _tLOG[p]["DATE"] " " : "")) (("TIME" in _tLOG[p] ? _tLOG[p]["TIME"] " " : "")) - if (_tLOG[p]["TYPE"]) { - n = n _tLOG[p]["TYPE"] ": " (("FILE" in _tLOG[p] ? _tLOG[p]["FILE"] (("LINE" in _tLOG[p] ? "(" _tLOG[p]["LINE"] ")" : "")) ": " : "")) - if (match(_tLOG[p]["TEXT"], /\x1F/)) { - t = n - gsub(/[^\t]/, " ", t) - return (_ln(n substr(_tLOG[p]["TEXT"], 1, RSTART - 1)) _ln(t substr(_tLOG[p]["TEXT"], RSTART + 1))) - } - } - return _ln(n _tLOG[p]["TEXT"]) + is = p + if (p == 0 && p == "") { + it = "-" + return 0 + } + return (it = (p == "" ? "s" : "S")) +} + +#_________________________________________________________________ +function _lengthsort(i1, v1, i2, v2) +{ + ############################## + return ((length(i1) < length(i2) ? -1 : (length(i1) > length(i2) ? 1 : (i1 < i2 ? -1 : 1)))) +} + +#_________________________________________________________________ +function _lib_APPLY() +{ + return _ffaccr(_LIBAPI, "_lib_APPLY") +} + +#_________________________________________________________________ +function _lib_BEGIN(A) +{ + return _ffaccr(_LIBAPI, "_lib_BEGIN", "", A) +} + +#_______________________________________________________________________ +function _lib_CMDLN(t) +{ + return _pass(_LIBAPI["F"], "_lib_CMDLN", t) +} + +#_________________________________________________________________ +function _lib_END(A) +{ + return _ffaccr(_LIBAPI, "_lib_END", "", A) +} + +#_________________________________________________________________ +function _lib_HELP() +{ + return _fbaccr(_LIBAPI, "_lib_HELP") +} + +#_________________________________________________________________ +function _lib_NAMEVER() +{ + return _fbaccr(_LIBAPI, "_lib_NAMEVER") +} + +#_____________________________________________________________________________ +function _ln(t) +{ + ############################################################### + return ((t ~ /\x0A$/ ? t : t _CHR["EOL"])) +} + +#_________________________________________________________________ +function _log(A, p, a, B) +{ + ########################################### + if (isarray(A)) { + A["TIME"] = _getime() + A["DATE"] = _getdate() + if (p) { + _tLOG[p = _wLCHLD(p, _N())][""] + delete _tLOG[p][""] + _movarr(_tLOG[p], A) + return p } + _expout("_ERRLOG: " _Zexparr(A) "\n") + } else { + B["TEXT"] = A + B["TYPE"] = "" + return _log(B, p) } +} - function _getchrln(s, w) - { - if (s == "") { - return +#_________________________________________________________________ +function _lspctab(t, ts, l, l1, l2, A) +{ + ################################ + while (match(t, /^(\t*)( *)((\t*)(.*))$/, A)) { + if (A[1, "length"] >= l) { + return substr(t, l + 1) } - if (length(s) < w) { - if (s in _GETCHRLN) { - if (length(_getchrlnt0 = _GETCHRLN[s]) >= w) { - return substr(_getchrlnt0, 1, w) - } - } else { - _getchrlnt0 = s s + if (A[2]) { + if ((l1 = int(A[2, "length"] / ts)) >= (l2 = l - A[1, "length"])) { + return (substr(A[2], l2 * ts + 1) A[3]) } - while (length(_getchrlnt0) < w) { - _getchrlnt0 = _getchrlnt0 _getchrlnt0 + if (! A[4]) { + return A[5] } - _GETCHRLN[s] = _getchrlnt0 - return substr(_getchrlnt0, 1, w) + t = A[1] _getchrln("\t", l1) A[3] } else { - return substr(s, 1, w) - } - } - - function _getdate() - { - return strftime("%F") - } - - function _getfilepath(t, f, al, b, A) - { - ERRNO = "" - if (match(t, /^[ \t]*(("([^"]*)"[ \t]*)|([`']([^']*)'[ \t]*)|(([^ \t]+)[ \t]*))/, A)) { - al = RLENGTH - f = A[3] A[5] A[7] - _conl("_getfilepath(" f ") (" al ")") - if (b = _filepath(f)) { - if (length(f) <= FLENGTH) { - FLENGTH = al - return b - } - ERRNO = "Filepath `" f "' error" - } - } - FLENGTH = 0 - } - - function _getfilever(f) - { - split(_cmd(_fileverpath " \"" f "\""), _GETFILEVERA0, /[ \t]+/) - if (_GETFILEVERA0[5]) { - return _GETFILEVERA0[5] + return t } } - - function _getime() - { - return strftime("%H:%M:%S") - } - - function _getmpdir(f, dd) - { - if (! dd || ! (dd = _filerd(dd))) { - dd = _FILEIO_TMPRD +} + +function _mac_init() +{ + _MACPFX["\204"] = "_macpfx84" + _MACPFX[""] = "_mpupfxsubret" + _MACPFX84SFX["\204"] = "_macpfx84" + _MACPFX84SFX["\224"] = "_macsfx94" + _MACPFX84SFX[""] = "_mpusfxsubret" + _VLDMAXSTRING = 1000000 +} + +function _macpfx84(F, D, C, p1, p2, p3) +{ + return _mpusub(_MACPFX84SFX, D, C, D[_mpuptr++], p1, p2, p3) +} + +function _macsfx94(F, D, C, p1, p2, p3) +{ + return _mpuretsub(D, _handle8494(_mpuacc)) +} + +#_______________________________________________________________________ +function _movarr(D, S) +{ + ################################################### + delete D + D[""] + delete D[""] + _addarr(D, S) +} + +function _mpu(t, F, p1, p2, p3, D, C) +{ + if (patsplit(t, C, /[\x84\x93\x94]/, D) > 0) { + _conline("CODE") + _conl() + _conl(_dumparr(C)) + _conline("DATA") + _conl() + _conl(_dumparr(D)) + _mpuptr = 0 + _mpucc0 = "" + _mpusub(F, D, C, D[_mpuptr++], p1, p2, p3) + return _mpuacc + } + return t +} + +# +# /rexpstr/ -> datastr +# (\x00\t\+)* -> 28 00 09 5B 2B 29 +# +# unesc all non-rexp characters: replace unesc of rexp-characters but do not remove it: \* -> \*, \x2A -> \*, \052 -> \*, \\ -> \# +function _mpudefaulthnd(F, D, C, p1, p2, p3) +{ + _mpuretsub(D, _mpucc0) +} + +function _mpupfxsubret(F, D, C, p1, p2, p3) +{ + return 1 +} + +function _mpuretsub(D, t) +{ + _mpuacc = D[_mpuptr++] + _accmpu(D, t) + return 1 +} + +function _mpusfxsubret(F, D, C, p1, p2, p3) +{ + return -1 +} + +function _mpusub(F, D, C, d, p1, p2, p3, q) +{ + q = D[_ARRLEN] + if (_VLDMAXSTRING < length(d)) { + D[--D[_ARRLEN]] = d + _mpuacc = "" + } else { + _mpuacc = d + } + d = _mpucc0 + _conl("_mpusub enter: in `" _mpuacc "' / _mpuptr=" _mpuptr "'") + do { + if ((_mpucc0 = C[_mpuptr]) in F) { + if (isarray(F[_mpucc0])) { + _mpufn0 = F[_mpucc0] + } + _conl("FN: `" _mpucc0 "' > CALL: `" _mpufn0 "' : _mpuacc=" _mpuacc "'") + } else { + _mpufn0 = "_mpudefaulthnd" + } + } while (! _accmpu(D, _mpuacc, @_mpufn0(F, D, C, p1, p2, p3))) + if (_mpufn0 == -1) { + _conl("WARNING: unclosed expression: `" d _mpuacc "'") + _mpuacc = d _mpuacc + } + _retarrm(D, q, "", (_mpufn0 == -1 ? _th0(d, _mpusubwrng("WARNING: unclosed expression", d _mpuacc)) : "")) + # collect: _mpuacc=_retarr(D) _mpuacc + _conl("mpusub exit: _mpuacc: `" _mpuacc "'") +} + +#_______________________________________________________________________ +function _n(F, v, p) +{ + ##################################################### + for (p in _UIDSDEL) { + delete _UIDSDEL[p] + delete _ptr[p] + delete _tPREV[p] + delete _tPARENT[p] + delete _tNEXT[p] + delete _tFCHLD[p] + delete _tQCHLD[p] + delete _tLCHLD[p] + delete _TMP0[p] + delete _TMP1[p] + delete _tLINK[p] + delete _tCLASS[p] + return _nN_i0(p, F, v) + } + for (p in _UIDS) { + delete _UIDS[p] + return _nN_i0(p, F, v) + } + return _nN_i0(_tgenuid(), F, v) +} + +#_____________________________________________________ +function _nN_i0(p, F, v) +{ + _[p][""] + delete _[p][""] + _ptr[p][""] + delete _ptr[p][""] + _TMP0[p][_ARRLEN] = _TMP1[p][_ARRLEN] = 0 + if (isarray(F)) { + delete F[p] + if (isarray(v)) { + F[p][""] + delete F[p][""] + _copyarr(F[p], v) + } else if (! (v == 0 && v == "")) { + F[p] = v } - if (f = (f ? _filerd(f, dd) : _filerd("_" ++_FILEIO_TMPCNTR "\\", dd))) { - _FILEIO_RDTMP[toupper(f)] + } else if (! (F == 0 && F == "")) { + if (isarray(v)) { + _[p][F][""] + delete _[p][F][""] + _copyarr(_[p][F], v) + } else if (v == 0 && v == "") { + _mpu(F, p) + } else { + _[p][F] = v } - return f } + return p +} - function _getmpfile(f, dd) - { - if (! dd || ! (dd = _filerd(dd))) { - dd = _FILEIO_TMPRD - } - if (f = _filerdne((_filene(f) ? f : f "_" ++_FILEIO_TMPCNTR), dd)) { - _FILEIO_RDNETMP[toupper(f)] - } - return f +#_________________________________________________________________ +function _newclrdir(f) +{ + ############################################ + if ((f = _filerd(f)) == "") { + return } - - function _getperf(o, t, a) - { - (o == "" ? ++_getperf_opcurr : _getperf_opcurr = o) - if ((a = _getsecond()) != _getperf_last) { - _getperf_opsec = (_getperf_opcurr - _getperf_opstart) / ((_getperf_last = a) - _getperf_start) - return @_getperf_fn(o, t, a) - } - return 1 + _cmd("rd " f " /S /Q 2>NUL") + _cmd("md " f " 2>NUL") + _WFILEROOTDIR[f] + return f +} + +#_______________________________________________________________________ +function _newdir(f) +{ + ##################################################### + if ((f = _filerd(f)) == "") { + return } - - function _getperf_(o, t, a) - { - if (a >= _getperf_end) { - return 0 - } - if (_getperf_opsecp != _getperf_opsec) { - _constat(((_constatstr == _getperf_stat ? _getperf_statstr : _getperf_statstr = _constatstr)) t " [TIME=" (a - _getperf_start) " sec(" (_getperf_opsecp = _getperf_opsec) " ops/sec)]") - _getperf_stat = _constatstr - } - return 1 + if (! (f in _WFILEROOTDIR)) { + _cmd("md " f " 2>NUL") + _WFILEROOTDIR[f] } - - function _getperf_noe(o, t, a) - { - if (_getperf_opsecp != _getperf_opsec) { - _constat(((_constatstr == _getperf_stat ? _getperf_statstr : _getperf_statstr = _constatstr)) t " [TIME=" (a - _getperf_start) " sec(" (_getperf_opsecp = _getperf_opsec) " ops/sec)]") - _getperf_stat = _constatstr + return f +} + +############################## +function _nop(p0, p1, p2, p3) +{ + #_______________________________________________________________________ +} + +#_____________________________________________________ +# _retarr(ARRAY,start,prefixtr,postfixtr) +# Return string collected from elements of ARRAY. +# The data elements in ARRAY have numeric indexes. By default it starts from element with index 1, but it is possible to locate elements starting from +# 0,-1,-.... The last data element in the ARRAY have the highest numeric index that is stored in ARRAY[_ARRLEN]. +# Optimized for very large data size. +# +# IN: ARRAY - source data array(is ARRAY is not array then return undefined) +# start - (optional) start index in ARRAY; if missed or have non-numeric value then start array index will be 1. +# prefixst - the string that will be inserted in the begin of generated return string +# postfix - the string that will be added at the end of generated return string +# MOD: - +# OUT: - +# RETURN: undefined - if ARRAY is not array; if ARRAY is empty; if start is higher than ARRAY last element index +# string - collected string: prefixtr-arraydata-postfixtr +#_________________________________________________________________ +function _nretarr(A, i, v, r, q) +{ + ##################################### + if ((i = (i == "" ? 1 : i + 0)) <= (q = A[_ARRLEN])) { + if (i <= (r = q - 16)) { + _ARRSTR = A[i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] + while (i < r) { + _ARRSTR = _ARRSTR A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] + } + _ARRSTR = _ARRSTR A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] v _retarr_i0(A, q, i) + return } - return 1 - } - - function _getperf_noenot(o, t, a) - { - return 1 + _ARRSTR = A[i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] v _retarr_i0(A, q, i) + return } - - function _getperf_not(o, t, a) - { - if (a < _getperf_end) { - return 1 + _ARRSTR = v + return +} + +#___________________________________________________________ +function _nretarrd(A, i, v, r, q) +{ + ############################## + if ((i = (i == "" ? 1 : i + 0)) <= (q = A[_ARRLEN])) { + if (i <= (r = q - 16)) { + _ARRSTR = A[i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] + while (i < r) { + _ARRSTR = _ARRSTR A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] + } + _ARRSTR = _ARRSTR A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] v _retarr_i0(A, q, i) + } else { + _ARRSTR = A[i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] v _retarr_i0(A, q, i) } + } else { + _ARRSTR = v } - - function _getreg_i1(D, r, R, a, i, il, ir, rc, B) - { - a = IGNORECASE + delete A + A[""] + delete A[""] +} + +#___________________________________________________________________________________ +#################################################################################### + +#___________________________________________________________________________________ +function _out(t, a, b) +{ + ############################################################### + a = BINMODE + b = ORS + BINMODE = "rw" + ORS = "" + print(t) > _SYS_STDOUT + fflush(_SYS_STDOUT) + BINMODE = a + ORS = b + return t +} + +#_________________________________________________________________ +function _outnl(t) +{ + ################################################ + return _out(t ((t ~ /\x0A$/ ? "" : _CHR["EOL"]))) +} + +function _p1(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s1, p1, p2, p3, p4, p5, p6, p7) +} + +function _p2(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s2, p1, p2, p3, p4, p5, p6, p7) +} + +function _p3(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s3, p1, p2, p3, p4, p5, p6, p7) +} + +function _p4(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s4, p1, p2, p3, p4, p5, p6, p7) +} + +function _p5(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s5, p1, p2, p3, p4, p5, p6, p7) +} + +function _p6(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s6, p1, p2, p3, p4, p5, p6, p7) +} + +function _p7(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s7, p1, p2, p3, p4, p5, p6, p7) +} + +function _p8(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s8, p1, p2, p3, p4, p5, p6, p7) +} + +#_______________________________________________________________________ +function _pass(A, f, t, p2, i, a) +{ + ########################################### + a = _endpass_v0 + _endpass_v0 = "" + i = 1 + while (t && i) { + i = "" + while ((i = A[i]) && t == (t = @i(f, t, p2))) { + } + } + if (i && _endpass_v0) { + A["!"] = 1 + t = _endpass_v0 + } else { + delete A["!"] + } + _endpass_v0 = a + return t +} + +# this is somnitelno: that / / . / / com 56 / / - is the DEV...; what is DEV ??? this already PROBLEM +#_____________________________________________________________________________ +function _patharr0(D, q, i, h, A, B) +{ + ############################################## + delete D + if (0 < (q = split(gensub(/\\/, "/", "G", gensub(/ *([:$\\\/]) */, "\\1", "G", gensub(/(^[ \t]+)|([ \t]+$)/, "", "G", q))), A, /\/+/, B))) { + if (2 > (h = length(B[1]))) { + D["type"] = "FILE" + A[1] = _patharr0_i0(A[1], D, "drive") + return _patharr0_i1(D, A, 1, q) + } + i = gensub(/ *([\.\?]) */, "\\1", "G", A[2]) IGNORECASE = 1 - r = "^" _torexp(r) - rc = 0 - zs = "" - for (i in R) { - if (match(i, r, B)) { - il = B[_torexp_pfxcntr] - ir = gensub(/....$/, "", 1, substr(i, 1 + B[_torexp_pfxcntr, "length"])) - if (! gsub(/^\\/, "", ir) && match(il, /[^\\]+$/)) { - ir = substr(il, RSTART) ir - } - D[ir] = R[i] - rc++ - } - } - IGNORECASE = a - if (rc > 0) { - return rc - } - } - - function _getsecond() - { - return systime() - } - - function _getsecondsync(a, c, b, c2) - { - a = systime() - while (a == systime()) { - ++c - } - return (a + 1) - } - - function _getuid(p) - { - if (p in _UIDOBL) { - for (_tptr in _UIDOBLV[_getuida0 = _UIDOBL[p]]) { - delete _UIDOBLV[_getuida0][_tptr] - _CLASSPTR[_tptr] = p - return _tptr + match(A[1], /^((https?)|(ftp)):$/) + IGNORECASE = 0 + if (RLENGTH > 0) { + D["type"] = toupper(substr(A[1], 1, RLENGTH - 1)) + _patharr0_i0(i, D, "site", "port") + } else if (A[1] == "") { + D["type"] = "UNC" + if (h > 2) { + D["host"] + A[2] = _patharr0_i0(A[2], D, "drive", "", "FILE") + return _patharr0_i1(D, A, 2, q) + } + if (i == "") { + return 1 } + D["host"] = i + A[3] = _patharr0_i0(A[3], D, "drive", "", "FILE") + } else { + D["type"] = "FILE" + A[1] = _patharr0_i0(A[1], D, "drive") + return _patharr0_i1(D, A, 1, q) } - _CLASSPTR[_tptr = _UIDPFX[p] _getuid_i0(_UIDCNT[p], _UIDCHRL[_tptr = _UIDCHR[p]], _UIDCHRH[_tptr]) _UIDSFX[p]] = p - return _tptr + return _patharr0_i1(D, A, 3, q) } +} - function _getuid_i0(p, UL, UH) - { - if ("" == (_tptr = UL[_UIDCNTL[p]])) { - for (_tptr in UH) { - delete UH[_tptr] - return ((_UIDCNTH[p] = _tptr) (_UIDCNTL[p] = UL[""])) - } - _fatal("out of UID") +#_____________________________________________________ +function _patharr0_i0(t, D, l, r, d, i) +{ + if (i = index(t, ":")) { + if (d) { + D["type"] = d } - return (_UIDCNTH[p] (_UIDCNTL[p] = _tptr)) - } - - function _handle8494(t) - { - return gensub(/(.)/, ".\\1", "G", t) - } - - function _hexnum(n, l) - { - if (l + 0 < 1) { - l = 2 + if (i > 1) { + D[l] = substr(t, 1, i - 1) } - return sprintf("%." ((l + 0 < 1 ? 2 : l)) "X", n) - } - - function _igetperf(t, s, o) - { - if (t == 0 && t == "" && s == 0 && s == "" && o == 0 && o == "") { - if (_getperf_fn !~ /not$/ && _constatstr == _getperf_stat) { - _constat(_getperf_statstr) - } - _getperf_fn = "_nop" - return ("[TIME=" (_getperf_last - _getperf_start) " sec(" _getperf_opsec " ops/sec)]") - } - _conl("initiate _getperf") - _getperf_opstart = _getperf_opcurr = o + 0 - _getperf_opsec = _getperf_opsecp = _getperf_stat = _getperf_statstr = "" - _getperf_end = t + (_getperf_start = _getperf_last = _getsecondsync()) - _getperf_fn = ((t + 0 > 0 ? "_getperf_" : "_getperf_noe")) ((s ? "" : "not")) - return _getperf_start - } - - function _import_data(t, p, p2, a) - { - if (match(t, /^_DATA: /)) { - _tDATA[a = _wLCHLD(p, _N())][""] - delete _tDATA[a][""] - _Zimparr(_tDATA[a], substr(t, 8)) - _conl("DATA: `" _tDATA[a]["ID"] "':`" _tDATA[a]["DATA"] "'") - return "" + if ((t = substr(t, i + 1)) && r) { + D[r] = t } return t - } - - function _info(t, d, A) - { - if (_ERRLOG_IF) { - A["TYPE"] = "INFO" - A["TEXT"] = t - _log(A, d) + } else if (t && r) { + D[l] = t + } + return t +} + +#_____________________________________________________ +function _patharr0_i1(D, A, i, q, t, c) +{ + if (D["type"] == "UNC") { + if (t = A[i++]) { + D[0] = (D["share"] = D[++c] = t) "/" + } else { + return 1 } } - - function _ini(p, cs, dptr, pfx, sfx, hstr, lstr) - { - return _inituid(p, cs, dptr, pfx, sfx, hstr, lstr, A) - } - - function _initfilever() - { - _fileverpath = "\\\\CPU\\eGAWK\\LIB\\_filever\\_filever.exe" - } - - function _initrdreg() - { - _RDREGTYPE["SZ"] = "STR" - _RDREGTYPE["DWORD"] = "W32" - _RDREGTYPE["QWORD"] = "W64" - _RDREGTYPE["BINARY"] = "BIN" - _RDREGTYPE["EXPAND_SZ"] = "XSZ" - _RDREGTYPE["MULTI_SZ"] = "MSZ" - _RDrdregfld = _rdregkey = 0 - } - - function _initregpath0() - { - _REGPATH0REGDIR[""] = "HKEY_LOCAL_MACHINE" - _REGPATH0REGDIR["HKLM"] = "HKEY_LOCAL_MACHINE" - _REGPATH0REGDIR["HKEY_LOCAL_MACHINE"] = "HKEY_LOCAL_MACHINE" - _REGPATH0REGDIR["HKCR"] = "HKEY_CLASSES_ROOT" - _REGPATH0REGDIR["HKEY_CLASSES_ROOT"] = "HKEY_CLASSES_ROOT" - _REGPATH0REGDIR["HKCU"] = "HKEY_CURRENT_USER" - _REGPATH0REGDIR["HKEY_CURRENT_USER"] = "HKEY_CURRENT_USER" - _REGPATH0REGDIR["HKU"] = "HKEY_USERS" - _REGPATH0REGDIR["HKEY_USERS"] = "HKEY_USERS" - _REGPATH0REGDIR["HKCC"] = "HKEY_CURRENT_CONFIG" - _REGPATH0REGDIR["HKEY_CURRENT_CONFIG"] = "HKEY_CURRENT_CONFIG" - _REGPATH0REGDIR["HKPD"] = "HKEY_PERFORMANCE_DATA" - _REGPATH0REGDIR["HKEY_PERFORMANCE_DATA"] = "HKEY_PERFORMANCE_DATA" - } - - function _initshare() - { - _sharextool = "\\\\CPU\\eGAWK\\LIB\\_share\\_share.exe" - } - - function _initspecialuid() - { - _NOINDEX = _getuid() - _LEN = _getuid() - _PTR = _getuid() - _NAME = _getuid() - _TYPE = _getuid() - _FORMAT = _getuid() + while (i < q) { + D[0] = D[0] (D[++c] = A[i++]) "/" } - - function _initsys() - { + if (i == q) { + if (match(t = A[i], /\.[^\.]*$/)) { + if (RSTART > 1) { + D["name"] = substr(t, 1, RSTART - 1) + } + D["ext"] = substr(t, RSTART, RLENGTH) + } else if (t != "") { + D["name"] = t + } } + return 1 +} - function _inituid(p, cs, dptr, pfx, sfx, hstr, lstr, A) - { - if (cs == 0 && cs == "") { - cs = p - p = _getuid() - } - _conl() - _conl() - _conl(cs) - if (match(cs, /^(([^:]*):)?(([^'\xB4]*\xB4.)*[^'\xB4]*)[']/, A)) { - pfx = A[3] - dptr = A[2] - } - if (match(cs = substr(cs, 1 + RLENGTH), /'(([^'\xB4]*\xB4.)*[^'\xB4]*)$/, A)) { - sfx = A[1] - cs = substr(cs, 1, RSTART - 1) - } - if (match(cs, /^(([`\^])(.*))/, A)) { - if (A[2] == "`") { - hstr = A[3] "~" - lstr = "" - } else { - lstr = A[3] "+" - hstr = "" +############################################################################# +function _pmap(m, s1, s2, s3, s4, s5, s6, s7, s8) +{ + if (match(m, /^([^\(]+)\(([^\)]*)\)$/, _QMAP)) { + _qparamf1 = _QMAP[1] + _QMAP[0] = "r" (_qparamc1 = split(_QMAP[2], _QMAP, "")) + _qparamf0 = "_p" _QMAP[_qparamc1--] + return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8) + } +} + +function _pr0(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1() +} + +function _pr1(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1(p1) +} + +function _pr2(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1(p1, p2) +} + +function _pr3(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1(p1, p2, p3) +} + +function _pr4(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1(p1, p2, p3, p4) +} + +function _pr5(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1(p1, p2, p3, p4, p5) +} + +function _pr6(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1(p1, p2, p3, p4, p5, p6) +} + +function _pr7(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1(p1, p2, p3, p4, p5, p6, p7) +} + +function _pr8(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) +{ + return @_qparamf1(p1, p2, p3, p4, p5, p6, p7, p8) +} + +#_________________________________________________________________ +function _printarr(A, t, lv, r, a) +{ + #################################### + a = PROCINFO["sorted_in"] + PROCINFO["sorted_in"] = "_lengthsort" + _printarrexp = (r ? r : "") + if (isarray(A)) { + delete _DUMPARR + _dumparrc = _dumparrd = "" + _printarr_i1(A, lv = ((lv == "" ? 16 : (lv == 0 || lv + 0 != 0 ? lv : (lv == "-*" ? -3 : (lv ~ /^\+?\*$/ ? 3 : 16))))) + 0, (lv < 0 ? -1 : 1), 0, _tabtospc(t)) + PROCINFO["sorted_in"] = a + return _retarrd(_DUMPARR, _dumparrd, _dumparrd = "") + } +} + +#___________________________________________________________ +function _printarr_i1(A, lv, ls, ln, t, t2, i, a, f) +{ + t2 = _getchrln(" ", length(t)) + if (ln == lv) { + if (ls > 0) { + for (i in A) { + ++a } - } else if (match(cs, /^(([^'\xB4\|]*\xB4.)*[^'\xB4\|]*)(\|(.*))?/, A)) { - hstr = A[1] - lstr = A[4] } else { - ERRNO = "_inituid(): bad parameters" - return + for (i in A) { + (isarray(A[i]) ? ++a : "") + } + } + if (length(_dumparrd = _dumparrd t ((a > 0 ? " ... (x" a ")" : "")) _CHR["EOL"]) > 262144) { + _conl(_dumparrd) + _dumparrd = "" } - _conl(dptr ":" pfx "'" hstr "|" lstr "'" sfx) - return _cfguid(p, dptr, pfx, sfx, hstr, lstr) - } - - function _inituidefault(h, l, H, L) - { - _classys = "" - delete _UIDOBLV[_UIDOBLV[_UIDOBL[_classys] = _classys][""] = _classys][""] - _UIDPFX[_classys] - _UIDSFX[_classys] - _UIDCNT[_classys] = _UIDCHR[_classys] = _CLASSPTR[_classys] = _classys - h = "AB" - l = h "01" - _splitstr(H, h) - _splitstr(L, l) - delete _UIDCHRH[_UIDCHRH[_classys][""] = _classys][""] - delete _UIDCHRL[_UIDCHRL[_classys][""] = _classys][""] - _UIDCNTH[_classys] - _cfguidh(_classys, H, L) - _UIDCNTL[_classys] = _cfguidl(_classys, L, L) - _CLASSFN[_classys]["del"] = "_tobjDEL" - _CLASSFN[_classys]["new"] = "_tobjNEW" - _drawuid(_classys) - _initspecialuid() - } - - function _ins(S, sf, D, df) - { - if (sf in S) { - if (isarray(S[sf])) { - if (df in D) { - if (isarray(D[df])) { - return _extarr(D[df], S[sf]) + return + } + if (ls >= 0) { + for (i in A) { + if (! _printarrexp || i ~ _printarrexp) { + if (! isarray(A[i])) { + if (length(_dumparrd = _dumparrd ((f ? t2 : t _nop(f = 1))) "[" i "]=" A[i] "'" _CHR["EOL"]) > 262144) { + _conl(_dumparrd) + _dumparrd = "" } - delete D[df] - } - D[df][""] - delete D[df][""] - return _extarr(D[df], S[sf]) - } else { - if (isarray(D[df])) { - delete D[df] } - D[df] = S[sf] D[df] } } } - - function _insf(A, f) - { - A["F"][""] = A["B"][A["F"][f] = A["F"][""]] = f - } - - function _insframe(A, f) - { - A[f] = A[""] - A[""] = f - } - - function _inspass(A, f) - { - A[f] = A[""] - A[""] = f - } - - function _isptr(p) - { - if (isarray(p)) { - is = _NOP - it = "A" - return 0 - } - is = p - if (p == 0 && p == "") { - it = "-" - return 0 - } - if (p in _CLASSPTR) { - return (it = "P") + for (i in A) { + if (isarray(A[i])) { + if (! _printarrexp || i ~ _printarrexp) { + _printarr_i1(A[i], lv, ls, ln + ls, _th0((f ? t2 : t), f = 1) "[" i "]") + } } - it = "S" - return 0 } - - function _istr(p) - { - if (isarray(p)) { - is = _NOP - it = "A" - return 0 - } - is = p - if (p == 0 && p == "") { - it = "-" - return 0 + if (! f) { + if (length(_dumparrd = _dumparrd t _CHR["EOL"]) > 262144) { + _conl(_dumparrd) + _dumparrd = "" } - return (it = (p == "" ? "s" : "S")) - } - - function _lengthsort(i1, v1, i2, v2) - { - return ((length(i1) < length(i2) ? -1 : (length(i1) > length(i2) ? 1 : (i1 < i2 ? -1 : 1)))) - } - - function _lib_APPLY() - { - return _ffaccr(_LIBAPI, "_lib_APPLY") - } - - function _lib_BEGIN(A) - { - return _ffaccr(_LIBAPI, "_lib_BEGIN", "", A) } +} - function _lib_CMDLN(t) - { - return _pass(_LIBAPI["F"], "_lib_CMDLN", t) +function _qparam(qm, p0, p1, p2, p3, p4, p5, p6, p7) +{ + if (qm == qm + 0 && qm > 0) { + _qparamim = substr(" ", 1, qm) + } else if (qm != "") { + _qparamim = qm + } else { + _qparamim = " " } + _qparamask = "" + return _qparam_i0(p0, p1, p2, p3, p4, p5, p6, p7) +} - function _lib_END(A) - { - return _ffaccr(_LIBAPI, "_lib_END", "", A) - } - - function _lib_HELP() - { - return _fbaccr(_LIBAPI, "_lib_HELP") - } - - function _lib_NAMEVER() - { - return _fbaccr(_LIBAPI, "_lib_NAMEVER") - } - - function _ln(t) - { - return ((t ~ /\x0A$/ ? t : t _CHR["EOL"])) - } - - function _log(A, p, a, B) - { - if (isarray(A)) { - A["TIME"] = _getime() - A["DATE"] = _getdate() - if (p) { - _tLOG[p = _wLCHLD(p, _N())][""] - delete _tLOG[p][""] - _movarr(_tLOG[p], A) - return p - } - _expout("_ERRLOG: " _Zexparr(A) "\n") +function _qparam_i0(p0, p1, p2, p3, p4, p5, p6, p7) +{ + _qparama0 = substr(_qparamim, 1, 1) + _qparamim = substr(_qparamim, 2) + switch (_qparama0) { + case "": + gsub(/ +$/, "", _qparamask) + return length(_qparamask) + default: + if (isarray(p0)) { + _qparama0 = "A" + } else if (p0 == "" && p0 == 0) { + _qparama0 = " " + } else if (_isptr(p0)) { + _qparama0 = "P" } else { - B["TEXT"] = A - B["TYPE"] = "" - return _log(B, p) - } + _qparama0 = "S" + } + case ".": + _qparamask = _qparamask _qparama0 + return _qparam_i0(p1, p2, p3, p4, p5, p6, p7) + } +} + +#_______________________________________________________________________ +function _qstr(t, c, A, B) +{ + ################################################ + c = "" + for (t = split(t, A, /[\x00-\x1F\\"]/, B); t >= 0; t--) { + c = _QSTR[B[t]] A[t + 1] c + } + return c +} + +#_________________________________________________________________ +function _qstrq(t) +{ + ################################################ + gsub(/\\/, "\\\\", t) + gsub(/"/, "\\\"", t) + return t +} + +################################################################ +function _rEG(c, t, P, a, A) +{ + #_____________________________________________________________________________ + switch (c) { + case "_lib_CMDLN": + ##################################################### + return t + #___________________________________________________________ + #_____________________________________________________ + case "_lib_APPLY": + return + #_____________________________________________________ + case "_lib_HELP": + return + #_____________________________________________________ + case "_lib_NAMEVER": + return _ln("_reg 0.001") + #_____________________________________________________ + case "_lib_BEGIN": + return + #_____________________________________________________ + case "_lib_END": + return } +} - function _lspctab(t, ts, l, l1, l2, A) - { - while (match(t, /^(\t*)( *)((\t*)(.*))$/, A)) { - if (A[1, "length"] >= l) { - return substr(t, l + 1) - } - if (A[2]) { - if ((l1 = int(A[2, "length"] / ts)) >= (l2 = l - A[1, "length"])) { - return (substr(A[2], l2 * ts + 1) A[3]) - } - if (! A[4]) { - return A[5] - } - t = A[1] _getchrln("\t", l1) A[3] - } else { - return t - } +#_______________________________________________________________________ +function _rFBRO(p) +{ + ###################################################### + if (p) { + if (p in _tPARENT) { + return _tFCHLD[_tPARENT[p]] } - } - - function _mac_init() - { - _MACPFX["\204"] = "_macpfx84" - _MACPFX[""] = "_mpupfxsubret" - _MACPFX84SFX["\204"] = "_macpfx84" - _MACPFX84SFX["\224"] = "_macsfx94" - _MACPFX84SFX[""] = "_mpusfxsubret" - _VLDMAXSTRING = 1000000 - } - - function _macpfx84(F, D, C, p1, p2, p3) - { - return _mpusub(_MACPFX84SFX, D, C, D[_mpuptr++], p1, p2, p3) - } - - function _macsfx94(F, D, C, p1, p2, p3) - { - return _mpuretsub(D, _handle8494(_mpuacc)) - } - - function _movarr(D, S) - { - delete D - D[""] - delete D[""] - _addarr(D, S) - } - - function _mpu(t, F, p1, p2, p3, D, C) - { - if (patsplit(t, C, /[\x84\x93\x94]/, D) > 0) { - _conline("CODE") - _conl() - _conl(_dumparr(C)) - _conline("DATA") - _conl() - _conl(_dumparr(D)) - _mpuptr = 0 - _mpucc0 = "" - _mpusub(F, D, C, D[_mpuptr++], p1, p2, p3) - return _mpuacc + while (p in _tPREV) { + p = _tPREV[p] } - return t - } - - function _mpudefaulthnd(F, D, C, p1, p2, p3) - { - _mpuretsub(D, _mpucc0) - } - - function _mpupfxsubret(F, D, C, p1, p2, p3) - { - return 1 - } - - function _mpuretsub(D, t) - { - _mpuacc = D[_mpuptr++] - _accmpu(D, t) - return 1 + return p } + return p +} - function _mpusfxsubret(F, D, C, p1, p2, p3) - { - return -1 +#_______________________________________________________________________ +function _rFCHLD(p) +{ + ##################################################### + if (p && p in _tFCHLD) { + return _tFCHLD[p] } + return "" +} - function _mpusub(F, D, C, d, p1, p2, p3, q) - { - q = D[_ARRLEN] - if (_VLDMAXSTRING < length(d)) { - D[--D[_ARRLEN]] = d - _mpuacc = "" - } else { - _mpuacc = d - } - d = _mpucc0 - _conl("_mpusub enter: in `" _mpuacc "' / _mpuptr=" _mpuptr "'") - do { - if ((_mpucc0 = C[_mpuptr]) in F) { - if (isarray(F[_mpucc0])) { - _mpufn0 = F[_mpucc0] - } - _conl("FN: `" _mpucc0 "' > CALL: `" _mpufn0 "' : _mpuacc=" _mpuacc "'") - } else { - _mpufn0 = "_mpudefaulthnd" - } - } while (! _accmpu(D, _mpuacc, @_mpufn0(F, D, C, p1, p2, p3))) - if (_mpufn0 == -1) { - _conl("WARNING: unclosed expression: `" d _mpuacc "'") - _mpuacc = d _mpuacc +######################## p="", !v +function _rLBRO(p) +{ + #_______________________________________________________________________ + if (p) { ###################################################### + if (p in _tPARENT) { + return _tLCHLD[_tPARENT[p]] } - _retarrm(D, q, "", (_mpufn0 == -1 ? _th0(d, _mpusubwrng("WARNING: unclosed expression", d _mpuacc)) : "")) - _conl("mpusub exit: _mpuacc: `" _mpuacc "'") - } - - function _n(F, v, p) - { - for (p in _UIDSDEL) { - delete _UIDSDEL[p] - delete _ptr[p] - delete _tPREV[p] - delete _tPARENT[p] - delete _tNEXT[p] - delete _tFCHLD[p] - delete _tQCHLD[p] - delete _tLCHLD[p] - delete _TMP0[p] - delete _TMP1[p] - delete _tLINK[p] - delete _tCLASS[p] - return _nN_i0(p, F, v) - } - for (p in _UIDS) { - delete _UIDS[p] - return _nN_i0(p, F, v) - } - return _nN_i0(_tgenuid(), F, v) - } - - function _nN_i0(p, F, v) - { - _[p][""] - delete _[p][""] - _ptr[p][""] - delete _ptr[p][""] - _TMP0[p][_ARRLEN] = _TMP1[p][_ARRLEN] = 0 - if (isarray(F)) { - delete F[p] - if (isarray(v)) { - F[p][""] - delete F[p][""] - _copyarr(F[p], v) - } else if (! (v == 0 && v == "")) { - F[p] = v - } - } else if (! (F == 0 && F == "")) { - if (isarray(v)) { - _[p][F][""] - delete _[p][F][""] - _copyarr(_[p][F], v) - } else if (v == 0 && v == "") { - _mpu(F, p) - } else { - _[p][F] = v - } + while (p in _tNEXT) { + p = _tNEXT[p] } return p } - - function _newclrdir(f) - { - if ((f = _filerd(f)) == "") { - return + return p +} + +######################## p="" +function _rLCHLD(p) +{ + #_______________________________________________________________________ + if (p && p in _tLCHLD) { ##################################################### + return _tLCHLD[p] + } + return "" +} + +#_______________________________________________________________________ +function _rLINK(p) +{ + ###################################################### + return ((p in _tLINK ? _tLINK[p] : "")) +} + +######################## p="" +function _rNEXT(p) +{ + #_______________________________________________________________________ + if (p && p in _tNEXT) { ###################################################### + return _tNEXT[p] + } + return "" +} + +######################## p="" +function _rPARENT(p) +{ + #_______________________________________________________________________ + if (p && p in _tPARENT) { #################################################### + return _tPARENT[p] + } + return "" +} + +######################## p="" +function _rPREV(p) +{ + #_______________________________________________________________________ + if (p && p in _tPREV) { ###################################################### + return _tPREV[p] + } + return "" +} + +######################## p="" +function _rQBRO(p, c, p1) +{ + #_______________________________________________________________________ + if (p) { ################################################ + if (p in _tPARENT) { + return _tQCHLD[_tPARENT[p]] } - _cmd("rd " f " /S /Q 2>NUL") - _cmd("md " f " 2>NUL") - _WFILEROOTDIR[f] - return f - } - - function _newdir(f) - { - if ((f = _filerd(f)) == "") { - return + c = 1 + p1 = p + while (p1 in _tPREV) { + c++ + p1 = _tPREV[p1] } - if (! (f in _WFILEROOTDIR)) { - _cmd("md " f " 2>NUL") - _WFILEROOTDIR[f] + while (p in _tNEXT) { + c++ + p = _tNEXT[p] } - return f + return c + } + return p +} + +######################## p="" +function _rQCHLD(p) +{ + #_______________________________________________________________________ + if (p && p in _tQCHLD) { ##################################################### + return _tQCHLD[p] + } + return "" +} + +#___________________________________________________________________________________ +# EMMULATED FUNCTIONAL FIELDS ###################################################### + +#_____________________________________________________________________________ +function _rSQFIRST(g, p, A) +{ + ##################################################### + if (isarray(A)) { + return _rSQFIRSTA(g, p, A) + } + _SQTOPTR[g] = p + _SQSTACK[g][0] = 0 + return _rsqgetptr(g, p) +} + +#_________________________________________________________________ +function _rSQFIRSTA(g, p, A) +{ + ######################################## + _SQTOPTR[g] = p + _SQSTACK[g][0] = 0 + if ((p = _rsqgetptr(g, p)) in A) { + return p } + return _rSQNEXTA(g, p, A) +} - function _nop(p0, p1, p2, p3) - { +#_______________________________________________________________________ +function _rSQNEXT(g, p, A) +{ + ################################################ + if (isarray(A)) { + return _rSQNEXTA(g, p, A) } + return _rsqnext_i0(g, p) +} - function _nretarr(A, i, v, r, q) - { - if ((i = (i == "" ? 1 : i + 0)) <= (q = A[_ARRLEN])) { - if (i <= (r = q - 16)) { - _ARRSTR = A[i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] - while (i < r) { - _ARRSTR = _ARRSTR A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] - } - _ARRSTR = _ARRSTR A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] v _retarr_i0(A, q, i) - return - } - _ARRSTR = A[i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] v _retarr_i0(A, q, i) - return +#_________________________________________________________________ +function _rSQNEXTA(g, p, A) +{ + ######################################### + if (p == _SQTOPTR[g]) { + if (_SQSTACK[g][0] > 0) { + _SQTOPTR[g] = _SQSTACK[g][_SQSTACK[g][0]--] + return _rSQNEXTA(g, _SQSTACK[g][_SQSTACK[g][0]--], A) } - _ARRSTR = v return } - - function _nretarrd(A, i, v, r, q) - { - if ((i = (i == "" ? 1 : i + 0)) <= (q = A[_ARRLEN])) { - if (i <= (r = q - 16)) { - _ARRSTR = A[i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] - while (i < r) { - _ARRSTR = _ARRSTR A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] - } - _ARRSTR = _ARRSTR A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] v _retarr_i0(A, q, i) - } else { - _ARRSTR = A[i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] v _retarr_i0(A, q, i) - } - } else { - _ARRSTR = v + while (p in _tNEXT) { + if ((p = _rsqgetptr(g, _tNEXT[p])) in A) { + return p } - delete A - A[""] - delete A[""] } + return ((p in _tPARENT ? _rSQNEXTA(g, _tPARENT[p], A) : "")) +} - function _out(t, a, b) - { - a = BINMODE - b = ORS - BINMODE = "rw" - ORS = "" - print(t) > _SYS_STDOUT - fflush(_SYS_STDOUT) - BINMODE = a - ORS = b - return t - } - - function _outnl(t) - { - return _out(t ((t ~ /\x0A$/ ? "" : _CHR["EOL"]))) - } - - function _p1(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s1, p1, p2, p3, p4, p5, p6, p7) - } - - function _p2(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s2, p1, p2, p3, p4, p5, p6, p7) - } - - function _p3(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s3, p1, p2, p3, p4, p5, p6, p7) - } - - function _p4(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s4, p1, p2, p3, p4, p5, p6, p7) - } +function _rconl(t) +{ + _rprt = _rprt _ln(t) +} - function _p5(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s5, p1, p2, p3, p4, p5, p6, p7) - } +function _rconline(t) +{ + _rprt = _rprt _ln((t = " " t " ") _getchrln("_", _CON_WIDTH - length(t) - 1)) +} - function _p6(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s6, p1, p2, p3, p4, p5, p6, p7) +#___________________________________________________________ +function _rd_shortcut(D, f) +{ + if ((_shrtcutf0 = _filepath(f)) && _shortcut_nerr(_shrtcuta0 = _cmd(_shortcut_fpath " /A:Q /F:\"" _shrtcutf0 "\" 2>&1"), _shrtcutf0)) { + ERRNO = "" + split(_shrtcuta0, _SHRTCUTA0, /\x0D?\x0A/) + for (_shrtcuta0 in _SHRTCUTA0) { + for (f in _SHORTCUTRSTRUC) { + if (match(_SHRTCUTA0[_shrtcuta0], "^" f)) { + D[_SHORTCUTRSTRUC[f]] = substr(_SHRTCUTA0[_shrtcuta0], 1 + RLENGTH) + } + } + } } + return ((ERRNO ? ERRNO = "read shortcut: " ERRNO : _NOP)) +} - function _p7(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s7, p1, p2, p3, p4, p5, p6, p7) +#_______________________________________________________________________ +function _rdfile(f, i, A) +{ + ################################################ + if ((f = _filerdne(f)) == "" || _filene(f) == "") { + ERRNO = "Filename error" + return } - - function _p8(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8, s8, p1, p2, p3, p4, p5, p6, p7) + _fio_cmda = RS + RS = ".{1,}" + _fio_cmdb = BINMODE + BINMODE = "rw" + ERRNO = RT = _NUL + getline RS < f + BINMODE = _fio_cmdb + RS = _fio_cmda + if (ERRNO == "") { + close(f) } - - function _pass(A, f, t, p2, i, a) - { - a = _endpass_v0 - _endpass_v0 = "" - i = 1 - while (t && i) { - i = "" - while ((i = A[i]) && t == (t = @i(f, t, p2))) { - } - } - if (i && _endpass_v0) { - A["!"] = 1 - t = _endpass_v0 - } else { - delete A["!"] - } - _endpass_v0 = a - return t + if (ERRNO == "") { + return RT } - - function _patharr0(D, q, i, h, A, B) - { - delete D - if (0 < (q = split(gensub(/\\/, "/", "G", gensub(/ *([:$\\\/]) */, "\\1", "G", gensub(/(^[ \t]+)|([ \t]+$)/, "", "G", q))), A, /\/+/, B))) { - if (2 > (h = length(B[1]))) { - D["type"] = "FILE" - A[1] = _patharr0_i0(A[1], D, "drive") - return _patharr0_i1(D, A, 1, q) - } - i = gensub(/ *([\.\?]) */, "\\1", "G", A[2]) - IGNORECASE = 1 - match(A[1], /^((https?)|(ftp)):$/) - IGNORECASE = 0 - if (RLENGTH > 0) { - D["type"] = toupper(substr(A[1], 1, RLENGTH - 1)) - _patharr0_i0(i, D, "site", "port") - } else if (A[1] == "") { - D["type"] = "UNC" - if (h > 2) { - D["host"] - A[2] = _patharr0_i0(A[2], D, "drive", "", "FILE") - return _patharr0_i1(D, A, 2, q) - } - if (i == "") { - return 1 + return (RT = _NOP) +} + +#################################################################################### +# PUBLIC: +#_____________________________________________________________________________ +# fn _th0,_th1,_th2,_th3 +# USAGE: +# _th0(p1,p2,p3,p4) +# +# Each of this functions can have up to 4 parameters. +# _th0(p1,p2,p3,p4) return 1st parameter (p1) +# _th1(p1,p2,p3,p4) return 2nd parameter (p2) +# _th2(p1,p2,p3,p4) return 3rd parameter (p3) +# _th3(p1,p2,p3,p4) return 4th parameter (p4) +#_____________________________________________________________________________ +# fn _nop(p1,p2,p3,p4,p5,p6,p7,p8) +# USAGE: +# _nop() +# +# Does not do any action. No result returned. Up to 8 parameters. +#_____________________________________________________________________________ +# fn _exit(c) +# USAGE: +# _exit(code) +# +# This function do the same as GAWK-operator `exit code'. +#_____________________________________________________________________________ +# fn _getdate() +# fn _getime() +# fn _getsecond() +# fn _getsecondsync() +function _rdreg(D, p) +{ + ################################################################ + _rdregp0 = "reg query \"" p "\" /S /reg:64 2>NUL" + _rdregfld = _rdregkey = 0 + _rdregq0 = split(gensub(/[\x0D?\x0A]{2,}/, _CHR["EOL"], "G", _cmd(_rdregp0)), _RDREGA0, /\x0D?\x0A/) + while (_rdregq0 > 0) { + _rdreg_i0(D) + } + return (_rdregfld + _rdregkey) +} + +#___________________________________________________________ +function _rdreg_i0(D, A) +{ + while (_rdregq0 > 0) { + if (match(_rdregp0 = _RDREGA0[_rdregq0--], / (.*) REG_((SZ)|(DWORD)|(QWORD)|(BINARY)|(EXPAND_SZ)|(MULTI_SZ)) (.*)$/, A)) { + if (! _rdreg_i0(D)) { + ++_rdregfld + D[_rdregp0 A[1] "." _RDREGTYPE[A[2]]] = A[9] + return + } else { + break + } + } else if (_rdregp0 ~ /^HK/) { + ++_rdregkey + return D[_rdregp0 = _rdregp0 "\\"] + } + } + return 1 +} + +#_____________________________________________________________________________________________________ +###################################################################################################### +function _rdsafe(A, i, d) +{ + if (i in A) { + return A[i] + } + return d +} + +#_______________________________________________________________________ +function _reg_check(p) +{ + _tframe("_reg_check_i0", p, p) +} + +#_______________________________________________ +function _reg_check_i0(p, pp, p1, p2) +{ + if (_[p]["TYPE"] == "defreg") { + if (_[p]["REGPATH"] in _REG) { + if ("VALUE" in _[p]) { + if (_[p]["VALUE"] == _REG[_[p]["REGPATH"]]) { + _creport(p, substr("OK: REGENTRY MATCH(==" _[p]["VALUE"] "): " _[p]["REGPATH"], 1, 126)) + } else { + _dllerr(p, substr("REGENTRY NOT MATCH(!=" _[p]["VALUE"] "): " _[p]["REGPATH"], 1, 126)) } - D["host"] = i - A[3] = _patharr0_i0(A[3], D, "drive", "", "FILE") + } else if (_VAR[_[p]["REGPATH"]] == _REG[_[p]["REGPATH"]]) { + _creport(p, substr("OK: REGPATH MATCH(==" _VAR[_[p]["REGPATH"]] "): " _[p]["REGPATH"], 1, 126)) } else { - D["type"] = "FILE" - A[1] = _patharr0_i0(A[1], D, "drive") - return _patharr0_i1(D, A, 1, q) + _dllerr(p, substr("REGPATH NOT MATCH(!=" _VAR[_[p]["REGPATH"]] "): " _[p]["REGPATH"], 1, 126)) } - return _patharr0_i1(D, A, 3, q) + } else { + _dllerr(p, substr("REGPATH NOT FOUND: " _[p]["REGPATH"], 1, 126)) } } +} - function _patharr0_i0(t, D, l, r, d, i) - { - if (i = index(t, ":")) { - if (d) { - D["type"] = d - } - if (i > 1) { - D[l] = substr(t, 1, i - 1) - } - if ((t = substr(t, i + 1)) && r) { - D[r] = t - } - return t - } else if (t && r) { - D[l] = t - } - return t - } +#_____________________________________________________ +function _registryinit() +{ + _registrytmpfile = _getmpfile() +} - function _patharr0_i1(D, A, i, q, t, c) - { - if (D["type"] == "UNC") { - if (t = A[i++]) { - D[0] = (D["share"] = D[++c] = t) "/" - } else { - return 1 - } +# _rdregfld : gvar - number of readed registry fields by _rdreg() +# _rdregkey : gvar - number of readed registry keys by _rdreg() +#_____________________________________________________________________________ +function _regpath0(D, i, s, q, S) +{ + ############################################ 0 # + if (i = _patharr0(S, i)) { + if ("name" in S) { + D["name"] = S["name"] } - while (i < q) { - D[0] = D[0] (D[++c] = A[i++]) "/" + if ("ext" in S) { + D["ext"] = S["ext"] } - if (i == q) { - if (match(t = A[i], /\.[^\.]*$/)) { - if (RSTART > 1) { - D["name"] = substr(t, 1, RSTART - 1) - } - D["ext"] = substr(t, RSTART, RLENGTH) - } else if (t != "") { - D["name"] = t - } + s = ((toupper(s = (i in S ? S[i] : "")) in _REGPATH0REGDIR ? D[++q] = _REGPATH0REGDIR[toupper(s)] : (D[++q] = _REGPATH0REGDIR[""]) "\\" (D[++q] = s))) "\\" + while (++i in S) { + s = s (D[++q] = S[i]) "\\" } - return 1 - } - - function _pmap(m, s1, s2, s3, s4, s5, s6, s7, s8) - { - if (match(m, /^([^\(]+)\(([^\)]*)\)$/, _QMAP)) { - _qparamf1 = _QMAP[1] - _QMAP[0] = "r" (_qparamc1 = split(_QMAP[2], _QMAP, "")) - _qparamf0 = "_p" _QMAP[_qparamc1--] - return @_qparamf0(s1, s2, s3, s4, s5, s6, s7, s8) - } - } - - function _pr0(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1() - } - - function _pr1(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1(p1) - } - - function _pr2(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1(p1, p2) - } - - function _pr3(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1(p1, p2, p3) - } - - function _pr4(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1(p1, p2, p3, p4) - } - - function _pr5(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1(p1, p2, p3, p4, p5) - } - - function _pr6(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1(p1, p2, p3, p4, p5, p6) - } - - function _pr7(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1(p1, p2, p3, p4, p5, p6, p7) - } - - function _pr8(s1, s2, s3, s4, s5, s6, s7, s8, p1, p2, p3, p4, p5, p6, p7, p8) - { - return @_qparamf1(p1, p2, p3, p4, p5, p6, p7, p8) - } - - function _printarr(A, t, lv, r, a) - { - a = PROCINFO["sorted_in"] - PROCINFO["sorted_in"] = "_lengthsort" - _printarrexp = (r ? r : "") - if (isarray(A)) { - delete _DUMPARR - _dumparrc = _dumparrd = "" - _printarr_i1(A, lv = ((lv == "" ? 16 : (lv == 0 || lv + 0 != 0 ? lv : (lv == "-*" ? -3 : (lv ~ /^\+?\*$/ ? 3 : 16))))) + 0, (lv < 0 ? -1 : 1), 0, _tabtospc(t)) - PROCINFO["sorted_in"] = a - return _retarrd(_DUMPARR, _dumparrd, _dumparrd = "") + if (s != "") { + D[0] = s } - } - - function _printarr_i1(A, lv, ls, ln, t, t2, i, a, f) - { - t2 = _getchrln(" ", length(t)) - if (ln == lv) { - if (ls > 0) { - for (i in A) { - ++a - } - } else { - for (i in A) { - (isarray(A[i]) ? ++a : "") - } + IGNORECASE = 1 + D["hostdir"] = "\\\\" (D["host"] = ("host" in S && ("" == (i = S["host"]) || "." == i || "?" == i || "localhost" == i) ? ENVIRON["COMPUTERNAME"] : i)) "\\" s + IGNORECASE = 0 + } +} + +#_________________________________________________________________________________________ +function _report(p) +{ + ####################################################################### + _report_t0 = _reportparnt = "" + _report_i0(p) + _tframe("_report_i0", p) + return _report_t0 +} + +function _report_i0(p, p0, p1, p2) +{ + if (p in _tPARENT) { + if (_reportparnt != (_reportparnt = _tPARENT[p])) { + _report_t0 = _report_t0 _ln() _ln((z = "_ " _[_tPARENT[p]]["NAME"] " ") _getchrln("_", _CON_WIDTH - length(z) - 2)) _ln(_getchrln("#", _CON_WIDTH - 2)) _ln() + } + } + if ("ERROR" in _[p]) { + _report_t0 = _report_t0 _reporterr(p, _[p]["ERROR"]) + } + if ("REPORT" in _[p]) { + _report_t0 = _report_t0 _ln(_[p]["REPORT"]) + } +} + +#___________________________________________________________________________________ +function _reporterr(p, t3, pp, t, t2) +{ + t = "" + pp = p + do { + ("NAME" in _[pp] ? t = _[pp]["NAME"] ": " t : "") + } while (pp = _rPARENT(pp)) + if (match(t3, /\x00/)) { + return (substr(t3, 1, RSTART - 1) t substr(t3, RSTART + 1)) + } + return (t t3) +} + +#___________________________________________________________________________________ +#################################################################################### + + + + +#_______________________________________________________________________ +# _CHR array +# +# _CHR[ASC-code decimal number]=="char" +# +# Contains 256 elements. The index is the decimal number from 0-255. +# The value is the single character with ASC-code equivalent to index number: +# +# _CHR[97] =="a" - character with ASC-code 97 is `a' +# +# This array is useful if you want to get character using it's ASC-code +#_________________________________________________________________ +# _ASC array +# +# _ASC[char]==number: ASC-code of char +# +# Contains 256 elements. The index is the any single character with ASC-code \x00-\xFF. +# The value is the number equivalent of character's ASC-code: +# +# _ASC["A"] ==65 - ASC-code of character `A' is 65 +# +# This array is useful if you want to get ASC-code of the character. +#_________________________________________________________________ +# _QASC array +# +# _QASC[char]=="string: octal ASC-code of char in 3-digit octal format" +# +# Contains 256 elements. The index is the any single charcter with ASC-code \x00-\xFF. +# The value is the octal number equivalent of character's ASC-code in fixed-length - 3-digit - string: +# +# _QASC["!"] =="041" - ASC-code of character `!' is 33(decimal) == 41(in octal) +# _QASC["\x0D"] =="015" +# +# This array is useful when some type of string escape conversion is performed. It allows quickly get +# replace string for the characters that can be specified only by character code in result string: +# +# "\x0D" -> "\\015" +#_______________________________________________________________________ + + + + + + + +#################################################################################### +# PUBLIC: +#_____________________________________________________________________________ +# fn _getchrln(ptt,len) +#_____________________________________________________________________________ +# fn _tabtospc(src,tabstep,xcoord) +#################################################################################### + +#_____________________________________________________________________________ +function _retarr(A, i, p, a, q) +{ + ################################################## + if (isarray(A)) { + i = (i == "" ? 0 : i + 0) + q = A[_ARRLEN] + 0 + if (i < q) { + return (p A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] _retarr_i0(A, q, i, a)) + } + } +} + +function _retarr_i0(A, q, i, a) +{ + if (i < q) { + return (A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] _retarr_i0(A, q, i, a)) + } + while (q < i) { + delete A[++q] + } + return a +} + +#_________________________________________________________________ +function _retarrd(A, v, i) +{ + ######################################### + if (1 in A) { + return (A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9] A[10] A[11] A[12] A[13] A[14] A[15] A[16] (((i = 17) in A ? _retarrd_i0(A, i) v : v))) + } + delete A + return v +} + +#_____________________________________________________ +function _retarrd_i0(A, i) +{ + if (i in A) { + return (A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] ((i in A ? _retarrd_i0(A, i) : ""))) + } + delete A +} + +#_______________________________________________________________________ +######################################################################## +#EXPERIMENTAL +function _rexpfn(R, t, p) +{ + _REXPFN[""] = "" + while (t) { + t = _rxpfn(R, t, p) + } + return _REXPFN[""] +} + +function _rexpfnend(t) +{ + _REXPFN[""] = t +} + +#_____________________________________________________________________________ +function _rexpstr(r, i, c, A) +{ + ################################################### + c = split(r, A, "") + r = "" + for (i = 1; i <= c; i++) { + r = r _REXPSTR[A[i]] + } + return r +} + +#_____________________________________________________________________________ +function _rexpstr_i0(t, A, p0) +{ + return (_REXPSTR[t] = "\\" t) +} + +#___________________________________________________________ +function _rmtsharerr(h, t) +{ + gsub(/[\x0D\x0A]+/, "", t) + if (t ~ /^The command failed: 53/) { + ERRNO = "host not found: \\\\" h + } else { + ERRNO = t ": \\\\" h + } +} + +function _rpp(q, D, S) +{ + _conl() + _conline(q) + _conl() + _regpath0(D, q) + #_conl(_dumparr(D)) + _conl(_ln("DEST:") _dumparr(D)) + _conl() + return q +} + +#_________________________________________________________________________________________ +function _rrdreg(DD, p, k, t, v, c, i, q, tT, A, B, C, D) +{ + ############################################# old; regedit + if (! _registrytmpfile) { + _registryinit() + } + _cmd("regedit /E \"" _registrytmpfile "\" \"" p "\" 2>&1") + q = patsplit(gensub(/[\x00\xFF\xFE]+/, "", "G", _rdfile(_registrytmpfile)), A, /\x0D?\x0A\[[^\]]+\]\x0D?\x0A/, B) + for (i = 1; i <= q; i++) { + p = gensub(/(^[ \t\x0D\x0A]*\[)|((\\)\\+)|(\][ \t\x0D\x0A]*$)/, "\\3", "G", A[i]) + DD[p "\\"] + delete C[split(B[i], C, /[\x0D\x0A]+/)] + for (c = 1; c in C; c++) { + tt = tt C[c] + if (gsub(/\\$/, "", tt)) { + continue } - if (length(_dumparrd = _dumparrd t ((a > 0 ? " ... (x" a ")" : "")) _CHR["EOL"]) > 262144) { - _conl(_dumparrd) - _dumparrd = "" + if (tt == "") { + continue } - return - } - if (ls >= 0) { - for (i in A) { - if (! _printarrexp || i ~ _printarrexp) { - if (! isarray(A[i])) { - if (length(_dumparrd = _dumparrd ((f ? t2 : t _nop(f = 1))) "[" i "]=" A[i] "'" _CHR["EOL"]) > 262144) { - _conl(_dumparrd) - _dumparrd = "" + if (match(_th0(tt, tt = ""), /((^"(([^\\"]|\\.)*)")|(@))=(("(([^\\"]|\\.)*)")|(dword:([[:xdigit:]]{8}))|(hex(\(([27b])\))?:(.*)))$/, D)) { + if (D[7]) { + t = "STR" + v = _unstr(D[8]) + } else if (D[10]) { + t = "W32" + v = D[11] + } else { + v = D[15] + if (D[13]) { + switch (D[14]) { + case "2": + t = "XSZ" + break + case "7": + t = "MSZ" + break + default: + t = "W64" } + } else { + t = "BIN" } } - } - } - for (i in A) { - if (isarray(A[i])) { - if (! _printarrexp || i ~ _printarrexp) { - _printarr_i1(A[i], lv, ls, ln + ls, _th0((f ? t2 : t), f = 1) "[" i "]") - } - } - } - if (! f) { - if (length(_dumparrd = _dumparrd t _CHR["EOL"]) > 262144) { - _conl(_dumparrd) - _dumparrd = "" - } - } - } - - function _qparam(qm, p0, p1, p2, p3, p4, p5, p6, p7) - { - if (qm == qm + 0 && qm > 0) { - _qparamim = substr(" ", 1, qm) - } else if (qm != "") { - _qparamim = qm - } else { - _qparamim = " " - } - _qparamask = "" - return _qparam_i0(p0, p1, p2, p3, p4, p5, p6, p7) - } - - function _qparam_i0(p0, p1, p2, p3, p4, p5, p6, p7) - { - _qparama0 = substr(_qparamim, 1, 1) - _qparamim = substr(_qparamim, 2) - switch (_qparama0) { - case "": - gsub(/ +$/, "", _qparamask) - return length(_qparamask) - default: - if (isarray(p0)) { - _qparama0 = "A" - } else if (p0 == "" && p0 == 0) { - _qparama0 = " " - } else if (_isptr(p0)) { - _qparama0 = "P" + DD[gensub(/(\\)\\+/, "\\1", "G", p "\\" _unstr(D[3] ((D[5] ? "(Default)" : ""))) "." t)] = v } else { - _qparama0 = "S" + _fatal("regedit: unknown output format(" c "): `" C[c] "'") } - case ".": - _qparamask = _qparamask _qparama0 - return _qparam_i0(p1, p2, p3, p4, p5, p6, p7) - } - } - - function _qstr(t, c, A, B) - { - c = "" - for (t = split(t, A, /[\x00-\x1F\\"]/, B); t >= 0; t--) { - c = _QSTR[B[t]] A[t + 1] c } - return c - } - - function _qstrq(t) - { - gsub(/\\/, "\\\\", t) - gsub(/"/, "\\\"", t) - return t } +} - function _rEG(c, t, P, a, A) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_reg 0.001") - case "_lib_BEGIN": - return - case "_lib_END": - return +#_________________________________________________________________ +function _rsqgetptr(g, p, A) +{ + if (p in _tLINK) { + _SQSTACK[g][++_SQSTACK[g][0]] = p + _SQSTACK[g][++_SQSTACK[g][0]] = _SQTOPTR[g] + while ((p = _tLINK[p]) in _tLINK) { + _con(".") } + _SQTOPTR[g] = p } - - function _rFBRO(p) - { - if (p) { - if (p in _tPARENT) { - return _tFCHLD[_tPARENT[p]] - } - while (p in _tPREV) { - p = _tPREV[p] - } - return p - } - return p + if (p in _tFCHLD) { + return _rsqgetptr(g, _tFCHLD[p]) } + return p +} - function _rFCHLD(p) - { - if (p && p in _tFCHLD) { - return _tFCHLD[p] +#___________________________________________________________ +function _rsqnext_i0(g, p) +{ + if (p == _SQTOPTR[g]) { + if (_SQSTACK[g][0] > 0) { + _SQTOPTR[g] = _SQSTACK[g][_SQSTACK[g][0]--] + return _rsqnext_i0(g, _SQSTACK[g][_SQSTACK[g][0]--]) } - return "" + return } - - function _rLBRO(p) - { - if (p) { - if (p in _tPARENT) { - return _tLCHLD[_tPARENT[p]] - } - while (p in _tNEXT) { - p = _tNEXT[p] + if (p in _tNEXT) { + return _rsqgetptr(g, _tNEXT[p]) + } + return _rsqnext_i0(g, _tPARENT[p]) +} + +function _rtn(v, A) +{ + _conl() + _conline(_val(v) " : " _val(A)) + _conl() + _rtn2(v, A) + _conl() +} + +function _rtn2(v, A, r, t) +{ + r = (isarray(A) ? _typa(v, A) : _typ(v)) + if ("`" > _t0 && _t0) { + _conl("ggggg") + } + t = ((r ? "TRUE" : "FALSE")) " / " ((r > 0 ? r ">0" : r "!>0")) " / " ((r + 0 > 0 ? r "+0>0" : r "+0!>0")) " / " ((r + 0 != r ? r "+0!=" r : r "+0==" r)) " / " ((r && "`" > r ? "'`'>" r " && " r : "!('`'>" r " && " r ")")) + _conl("`" r "' : " t) + return r +} + +function _rxpfn(R, t, p, i, f, A) +{ + for (i in R) { + if (match(t, i, A)) { + f = R[i] + if (t != (t = @f(A, substr(t, RLENGTH + 1), p))) { + return t } - return p } - return p - } - - function _rLCHLD(p) - { - if (p && p in _tLCHLD) { - return _tLCHLD[p] - } - return "" } + return _rexpfnend(t) +} - function _rLINK(p) - { - return ((p in _tLINK ? _tLINK[p] : "")) - } - - function _rNEXT(p) - { - if (p && p in _tNEXT) { - return _tNEXT[p] - } - return "" +############################################################## +function _sHARE(c, t, P, a, A) +{ + #_____________________________________________________________________________ + switch (c) { + case "_lib_CMDLN": + ################################################### + return t + #___________________________________________________________ + #_____________________________________________________ + case "_lib_APPLY": + return + #_____________________________________________________ + case "_lib_HELP": + return + #_____________________________________________________ + case "_lib_NAMEVER": + return _ln("_share 1.000") + #_____________________________________________________ + case "_lib_BEGIN": + return + #_____________________________________________________ + case "_lib_END": + return } +} - function _rPARENT(p) - { - if (p && p in _tPARENT) { - return _tPARENT[p] - } - return "" +################################################################ +function _sYS(c, t, P, a, A) +{ + #_____________________________________________________________________________ + switch (c) { + case "_lib_CMDLN": + ##################################################### + return t + #___________________________________________________________ + #_____________________________________________________ + case "_lib_APPLY": + return + #_____________________________________________________ + case "_lib_HELP": + return + #_____________________________________________________ + case "_lib_NAMEVER": + return + #_____________________________________________________ + case "_lib_BEGIN": + return + #_____________________________________________________ + case "_lib_END": + return } +} - function _rPREV(p) - { - if (p && p in _tPREV) { - return _tPREV[p] - } - return "" - } +#_______________________________________________________________________ +function _serv_check(p) +{ + _tframe("_serv_check_i0", p, p) +} - function _rQBRO(p, c, p1) - { - if (p) { - if (p in _tPARENT) { - return _tQCHLD[_tPARENT[p]] - } - c = 1 - p1 = p - while (p1 in _tPREV) { - c++ - p1 = _tPREV[p1] - } - while (p in _tNEXT) { - c++ - p = _tNEXT[p] +#_______________________________________________ +function _serv_check_i0(p, p0, p1, p2, p3, i, q, c) +{ + if (_[p]["TYPE"] == "defsrv") { + i = IGNORECASE + IGNORECASE = 1 + if (match(_servoutput, roi = "\\012DISPLAY_NAME: " _torexp(_[p]["SERVNAME"]))) { + _creport(p, "OK: SERVICE DETECTED: " substr(_[p]["SERVNAME"], 1, 112)) + } else { + _dllerr(p, "service " _[p]["SERVNAME"] " not detected") + } + } + IGNORECASE = i +} + +#_______________________________________________________________________ +function _setarrsort(f, a) +{ + ############################################## + a = PROCINFO["sorted_in"] + if (! f) { + delete PROCINFO["sorted_in"] + } else { + PROCINFO["sorted_in"] = f + } + return a +} + +#_______________________________________________________________________ +function _setmpath(p, a) +{ + ################################################ + ERRNO = "" + if (p && (a = _filerd(p))) { + if (_FILEIO_TMPRD) { + _FILEIO_TMPATHS[_FILEIO_TMPRD] + } + #if ( _filexist(a) ) _del(a) + #_cmd("rd " a " /S /Q 2>NUL"); _cmd("del " a " /Q 2>NUL") + return (_FILEIO_TMPRD = a) + } else { + return _warning("`" p "': cannot set temporary folder" ((ERRNO ? ": " ERRNO : ""))) + } +} + +#_________________________________________________________________________________________ +########################################################################################## +function _sharelist(D, h, q, c, l, A, B) +{ + ################################################# + delete D + c = _sharextool " \\\\" ((h == "" ? h = ENVIRON["COMPUTERNAME"] : h)) " 2>&1" + if (match(c = _cmd(c), /\x0AShare[^\x0A]*Remark/)) { + gsub(/(^[^-]*\x0D?\x0A-+\x0D?\x0A[ \t]*)|(\x0D?\x0AThe command completed successfully.*$)/, "", c) + l = RLENGTH - 7 + split(c, A, /([ \t]*\x0D?\x0A)+[ \t]*/) + for (c in A) { + if (match(A[c], /((([^ \t:]+[ \t]+)*[^ \t:]+)[ \t]+)([A-Za-z])[ \t]*:/, B) && ++q) { + D[B[2]] = (A[c] ~ /\.\.\.$/ ? _sharepath(h, B[2]) : gensub(/[ \t\\\/]*$/, "\\\\", 1, substr(A[c], 1 + B[1, "length"], l - B[1, "length"]))) } - return c - } - return p - } - - function _rQCHLD(p) - { - if (p && p in _tQCHLD) { - return _tQCHLD[p] - } - return "" - } - - function _rSQFIRST(g, p, A) - { - if (isarray(A)) { - return _rSQFIRSTA(g, p, A) - } - _SQTOPTR[g] = p - _SQSTACK[g][0] = 0 - return _rsqgetptr(g, p) - } - - function _rSQFIRSTA(g, p, A) - { - _SQTOPTR[g] = p - _SQSTACK[g][0] = 0 - if ((p = _rsqgetptr(g, p)) in A) { - return p } - return _rSQNEXTA(g, p, A) + return q } + return _rmtsharerr(h, c) +} - function _rSQNEXT(g, p, A) - { - if (isarray(A)) { - return _rSQNEXTA(g, p, A) - } - return _rsqnext_i0(g, p) +#_____________________________________________________________________________ +function _sharepath(h, s, A) +{ + ################################################### + s = _sharextool " \\\\" ((h == "" ? h = ENVIRON["COMPUTERNAME"] : h)) "\\\"" s "\" 2>&1" + if (match(s = _cmd(s), /\x0APath[ \t]+([^\x0D\x0A]+)/, _SHAREPATHA0)) { + return gensub(/[ \t\\\/]*$/, "\\\\", 1, _SHAREPATHA0[1]) } + return _rmtsharerr(h, s) +} - function _rSQNEXTA(g, p, A) - { - if (p == _SQTOPTR[g]) { - if (_SQSTACK[g][0] > 0) { - _SQTOPTR[g] = _SQSTACK[g][_SQSTACK[g][0]--] - return _rSQNEXTA(g, _SQSTACK[g][_SQSTACK[g][0]--], A) - } +function _shortcut(D, S) +{ + ############################################################# + if (isarray(D)) { + if (isarray(S)) { + _addarrmask(D, S, _SHORTCUTWSTRUC) + } else if (S == 0 && S == "") { # array,array2* - copy from array2 to array shorcut-specific elements + _addarrmask(D, _SHORTCUTDEFAULT, _SHORTCUTWSTRUC) + } else if (_isnotfileptr(S)) { # array* - define shortcut-specific elements in array by default values + _addarrmask(D, _[S], _SHORTCUTWSTRUC) + } else if (_rd_shortcut(D, S)) { + return # array,ptr* - copy from array _[ptr] to array shorcut-specific elements + } + } else if (D == 0 && D == "") { + return _NOP # array,filepath* - define in array shortcut-specific elements by reading its from shortcut file filepath(load shortcut) + # -* - no action(return -) + } else if (_isnotfileptr(D)) { + if (isarray(S)) { + _addarrmask(_[D], S, _SHORTCUTWSTRUC) + } else if (S == 0 && S == "") { # ptr,array* - copy from array to array _[ptr] shorcut-specific elements + _addarrmask(_[D], _SHORTCUTDEFAULT, _SHORTCUTWSTRUC) + } else if (_isnotfileptr(S)) { # ptr* - define shortcut-specifc elements in array _[ptr] by default values + _addarrmask(_[D], _[S], _SHORTCUTWSTRUC) + } else if (_rd_shortcut(_[D], S)) { + return # ptr,ptr2* - copy from array _[ptr2] to array _[ptr] shorcut-specific elements + } + } else { # ptr,filepath* - define in array _[ptr] shortcut-specific elements by reading its from shortcut file filepath(load shortcut) + if (isarray(S) && _wr_shortcut(D, S)) { + return # filepath,array* - [over]write shorcut file filepath; shortcut parameters will be defined by shortcut-specific elements in array(save shortcut) + } else if (S == 0 && S == "" && _wr_shortcut(D, _SHORTCUTDEFAULT)) { + return # filepath* - [over]write shorcut file filepath; shortcut parameters will be defined by default values + } else if (_isnotfileptr(S) && _wr_shortcut(D, _[S])) { + return # filepath,ptr* - [over]write shorcut file filepath; shortcut parameters will be defined by shortcut-specific elements in array _[ptr](save shortcut) + } else if (_rd_shortcut(_SHRTCUTA1, S) || _wr_shortcut(D, _SHRTCUTA1)) { return - } - while (p in _tNEXT) { - if ((p = _rsqgetptr(g, _tNEXT[p])) in A) { - return p + } } # filepath,filepath2* - [over]write shorcut file filepath; shortcut parameters will be defined from shortcut file filepath2(copy shortcut) + return 1 +} + +#________________________________________________ +function _shortcut_init(A, B, q) +{ + _SHORTCUTERR[2] = "file not found" + _SHORTCUTERR[3] = "no such filepath" + _SHORTCUTERR["The system cannot find the file specified."] = "no such filepath" + _SHORTCUTERR[5] = "file is folder" + _SHORTCUTERR["Access is denied."] = "file is folder" + _SHORTCUTERR[123] = "filepath syntax error" + _SHORTCUTERR["The filename, directory name, or volume label syntax is incorrect."] = "filepath syntax error" + q = "target\t\t\t/T:\t\t\t\tTargetPath=\t\t\t\t\ttarget?\t\t\t;\t\t\t_target\t\t\t\t\t\t\tTargetPathExpanded=\t\t\t\t\t\t\t;\t\t\tparameters\t\t\t/P:\t\t\t\tArguments=\t\t\t\t\tparaneters?\t\t\t;\t\t\t_parameters\t\t\t\t\t\t\tArgumentsExpanded=\t\t\t\t\t\t\t;\t\t\tstartdir\t\t\t/W:\t\t\t\tWorkingDirectory=\t\t\t\tstartdir?\t\t\t;\t\t\t_startdir\t\t\t\t\t\t\tWorkingDirectoryExpanded=\t\t\t\t\t\t;\t\t\trunstyle\t\t\t/R:\t\t\t\tRunStyle=\t\t\t\t\t1\t\t\t\t;\t\t\ticon,index\t\t\t/I:\t\t\t\tIconLocation=\t\t\t\ticon,index?\t\t\t;\t\t\txicon,index\t\t\t\t\t\t\tIconLocationExpanded=\t\t\t\t\t\t\t;\t\t\tshortcut key\t\t/H:\t\t\t\tHotKey=\t\t\t\t\t0\t\t\t\t;\t\t\tdescription\t\t\t/D:\t\t\t\tDescription=\t\t\t\t_env4: default shortcut\t" + split(q, _SHRTCUTA0, /[ \t]*;[ \t]*/) + for (q in _SHRTCUTA0) { + if (match(_SHRTCUTA0[q], /^([^\t]+)\t+([^\t]+)(\t+([^\t]+)(\t+([^\t]+))?)?/, B)) { + if (B[3] == "") { + _SHORTCUTRSTRUC[B[2]] = B[1] + } else if (B[5] == "") { + _SHORTCUTWSTRUC[_SHORTCUTRSTRUC[B[4]] = B[1]] = B[2] + delete _SHORTCUTDEFAULT[B[1]] + } else { + _SHORTCUTWSTRUC[_SHORTCUTRSTRUC[B[4]] = B[1]] = B[2] + _SHORTCUTDEFAULT[B[1]] = B[6] } + } else { + _fatal("_shortcut.init: _shortcut_struc: syntax error: `" _SHRTCUTA0[q] "'") } - return ((p in _tPARENT ? _rSQNEXTA(g, _tPARENT[p], A) : "")) } + _SHRTCUTA1[""] + delete _SHRTCUTA1[""] + _shortcut_fpath = "\\\\localhost\\eGAWK\\LIB\\_shortcut\\_shortcut.exe" +} - function _rconl(t) - { - _rprt = _rprt _ln(t) - } - - function _rconline(t) - { - _rprt = _rprt _ln((t = " " t " ") _getchrln("_", _CON_WIDTH - length(t) - 1)) +#_____________________________________________________ +function _shortcut_nerr(t, s, A) +{ + if (match(t, /\x0ASystem error (-?[0-9]+)[^\x0D\x0A]*[\x0D\x0A]+([^\x0D\x0A]+)/, A)) { + ERRNO = ((A[1] in _SHORTCUTERR ? _SHORTCUTERR[A[1]] : (A[2] in _SHORTCUTERR ? _SHORTCUTERR[A[2]] : tolower(gensub(/^(The )?(((.*)\.$)|(.*[^\.]$))/, "\\4\\5", "G", A[2])) "(" A[1] ")"))) ((s ? ": `" s "'" : "")) + } else { + return 1 } - - function _rd_shortcut(D, f) - { - if ((_shrtcutf0 = _filepath(f)) && _shortcut_nerr(_shrtcuta0 = _cmd(_shortcut_fpath " /A:Q /F:\"" _shrtcutf0 "\" 2>&1"), _shrtcutf0)) { - ERRNO = "" - split(_shrtcuta0, _SHRTCUTA0, /\x0D?\x0A/) - for (_shrtcuta0 in _SHRTCUTA0) { - for (f in _SHORTCUTRSTRUC) { - if (match(_SHRTCUTA0[_shrtcuta0], "^" f)) { - D[_SHORTCUTRSTRUC[f]] = substr(_SHRTCUTA0[_shrtcuta0], 1 + RLENGTH) - } - } +} + +function _split_regpath() +{ + _rpp(" / / / / ") + _rpp(" / / / / huj ") + _rpp(" / / / / huj / ") + _rpp(" / / / / huj / pizda.TSR ") + _rpp(" / / / / hklm ") + _rpp(" / / / / hklm / ") + _rpp(" / / / / hklm / huj ") + _rpp(" / / / / hklm / huj / ") + _rpp(" / / / / hklm / huj / \tpizda.TSR ") + _conl() + _conl("########################################################################################") + _conl() + _rpp(" / / / / hklm / software / altiris / fi le . ex t ") + _rpp(" / / . / / hkcr / software / altiris / fi le . ex t ") + _rpp(" / / ? / / hKcU / software / altiris / fi le . ex t ") + _rpp(" / / lOcAlHoSt / / hKu / software / altiris / fi le . ex t ") + _rpp(" / / ho st / / hKcc / software / altiris / fi le . ex t ") + _rpp(" / / ho st / / hKPd / software / altiris / fi le . ex t ") + _conl() + _conl("########################################################################################") + _conl() +} + +function _splitpath_test() +{ + _conl() + _conl("########################################################################################") + _conl() + _fpp(" ") + _fpp(" fi le . ex t ") + _fpp(" di r0 / / ") + _fpp(" di r0 / / fi le . ex t ") + _fpp(" / ") + _fpp(" / fi le . ex t ") + _fpp(" / di r0 / / ") + _fpp(" / di r0 / / fi le . ex t ") + _conl() + _conl("########################################################################################") + _conl() + _fpp(" c : ") + _fpp(" c : fi le . ex t ") + _fpp(" c : di r0 / / ") + _fpp(" c : di r0 / / fi le . ex t ") + _fpp(" c : / / ") + _fpp(" c : / / fi le . ex t ") + _fpp(" c : / / di r0 / / ") + _fpp(" c : / / di r0 / / fi le . ex t ") + _conl() + _conl("########################################################################################") + _conl() + _fpp(" / / ") + _fpp(" / / ho st . hs t ") + _fpp(" / / ho st / / ") + _fpp(" / / ho st / / fi le . ex t ") + _fpp(" / / ho st / / di r0 / / ") + _fpp(" / / ho st / / di r0 / / fi le . ex t ") + _conl() + _conl("########################################################################################") + _conl() + _fpp(" / / ho st / / c : ") + _fpp(" / / ho st / / c : fi le . ex t ") + _fpp(" / / ho st / / c : di r0 / / ") + _fpp(" / / ho st / / c : di r0 / / fi le . ex t ") + _fpp(" / / ho st / / c : / / ") + _fpp(" / / ho st / / c : / / fi le . ex t ") + _fpp(" / / ho st / / c : / / di r0 / / ") + _fpp(" / / ho st / / c : / / di r0 / / fi le . ex t ") + _conl() + _conl("########################################################################################") + _conl() + _fpp(" http : / / / ") + _fpp(" http : / / / si te . ex t ") + _fpp(" http : / / / si te / / ") + _fpp(" http : / / / si te / / fi le . ex t ") + _fpp(" http : / / / si te / / di r0 / / ") + _fpp(" http : / / / si te / / di r0 / / fi le . ex t ") + _conl() + _conl("########################################################################################") + _conl() + _fpp(" ftp : / / / : po rt ") + _fpp(" ftp : / / / si te . ex t : po rt ") + _fpp(" ftp : / / / si te : po rt / / ") + _fpp(" ftp : / / / si te : po rt / / fi le . ex t ") + _fpp(" ftp : / / / si te : po rt / / di r0 / / ") + _fpp(" ftp : / / / si te : po rt / / di r0 / / fi le . ex t ") + _conl() + _conl("## //. ######################################################################################") + _conl() + _fpp(" / / . ") + _fpp(" / / . / / ") + _fpp(" / / . / / com 56 ") + _fpp(" / / . / / com 56 / / ") + _fpp(" / / . / / c : ") + _fpp(" / / . / / c : / / ") + _fpp(" / / . / / c : com 56 ") + _fpp(" / / . / / c : com 56 / / ") + _fpp(" / / . / / c : / / com 56 ") + _fpp(" / / . / / c : / / com 56 / / ") + _conl() + _conl("## //? ######################################################################################") + _conl() + _fpp(" / / ? ") + _fpp(" / / ? / / ") + _fpp(" / / ? / / com 56 ") + _fpp(" / / ? / / com 56 / / ") + _fpp(" / / ? / / c : ") + _fpp(" / / ? / / c : / / ") + _fpp(" / / ? / / c : com 56 ") + _fpp(" / / ? / / c : com 56 / / ") + _fpp(" / / ? / / c : / / com 56 ") + _fpp(" / / ? / / c : / / com 56 / / ") + _conl() + _conl("########################################################################################") + _conl() + _fpp(" / / / ") + _fpp(" / / / . hs t ") + _fpp(" / / / / fi le . ex t ") + _fpp(" / / / / di r0 / / ") + _fpp(" / / / / di r0 / / di r1 / fi le . ex t ") + _fpp(" / / / / c : ") + _fpp(" / / / / c : fi le . ex t ") + _fpp(" / / / / c : di r0 / / ") + _fpp(" / / / / c : di r0 / / fi le . ex t ") + _fpp(" / / / / c : / / ") + _fpp(" / / / / c : / / fi le . ex t ") + _fpp(" / / / / c : / / di r0 / / ") + _fpp(" / / / / c : / / di r0 / / fi le . ex t ") + _conl() + _conl("########################################################################################") + _conl() + return +} + +#_______________________________________________________________________ +function _splitstr(A, t, r) +{ + ########################################### 1 # + if (_istr(t)) { + if (_splitstr_i0(A, t) > 0) { + return _splitstrp0 + } + if (_istr(r)) { + return _splitstr_i0(A, r) + } + } else { + if (it == "A") { + if (length(t) > 0) { + _movarr(A, t) + return (0 - length(A)) } } - return ((ERRNO ? ERRNO = "read shortcut: " ERRNO : _NOP)) + _istr(r) } - - function _rdfile(f, i, A) - { - if ((f = _filerdne(f)) == "" || _filene(f) == "") { - ERRNO = "Filename error" - return + if (it == "A") { + if (length(r) > 0) { + _movarr(A, r) + return (0 - length(A)) } - _fio_cmda = RS - RS = ".{1,}" - _fio_cmdb = BINMODE - BINMODE = "rw" - ERRNO = RT = _NUL - getline RS < f - BINMODE = _fio_cmdb - RS = _fio_cmda - if (ERRNO == "") { - close(f) - } - if (ERRNO == "") { - return RT - } - return (RT = _NOP) } +} - function _rdreg(D, p) - { - _rdregp0 = "reg query \"" p "\" /S /reg:64 2>NUL" - _rdregfld = _rdregkey = 0 - _rdregq0 = split(gensub(/[\x0D?\x0A]{2,}/, _CHR["EOL"], "G", _cmd(_rdregp0)), _RDREGA0, /\x0D?\x0A/) - while (_rdregq0 > 0) { - _rdreg_i0(D) - } - return (_rdregfld + _rdregkey) +#_____________________________________________________ +function _splitstr_i0(A, t, C) +{ + if (2 > (_splitstrq0 = patsplit(t, _SPLITSTRA0, /([^,\xB4]*\xB4.)*[^,\xB4]*/))) { + _splitstrq0 = split(gensub(/\xB4(.)/, "\\1", "G", t), _SPLITSTRA0, "") } - - function _rdreg_i0(D, A) - { - while (_rdregq0 > 0) { - if (match(_rdregp0 = _RDREGA0[_rdregq0--], / (.*) REG_((SZ)|(DWORD)|(QWORD)|(BINARY)|(EXPAND_SZ)|(MULTI_SZ)) (.*)$/, A)) { - if (! _rdreg_i0(D)) { - ++_rdregfld - D[_rdregp0 A[1] "." _RDREGTYPE[A[2]]] = A[9] - return - } else { - break - } - } else if (_rdregp0 ~ /^HK/) { - ++_rdregkey - return D[_rdregp0 = _rdregp0 "\\"] - } + delete A + _splitstri0 = _splitstrp0 = 0 + while (_splitstri0++ < _splitstrq0) { + if ((t = gensub(/\xB4(.)/, "\\1", "G", _SPLITSTRA0[_splitstri0])) in C || t == "") { + continue } - return 1 + C[A[++_splitstrp0] = t] } + return _splitstrp0 +} - function _rdsafe(A, i, d) - { - if (i in A) { - return A[i] - } - return d +#_______________________________________________ +function _strtorexp(t) +{ + gsub(/[\\\.\?\*\+\-\(\)\{\}\[\]\^\$\/\|]/, "\\\\&", t) + t = split(t, _TOREXP_STRA, /[\x00-\x1F]/, _TOREXP_STRB) + _torexp_strt0 = "" + for (_torexp_stri0 = 1; _torexp_stri0 < t; _torexp_stri0++) { + _torexp_strt0 = _torexp_strt0 _TOREXP_STRA[_torexp_stri0] "\\" _QASC[_TOREXP_STRB[_torexp_stri0]] } + return (_torexp_strt0 _TOREXP_STRA[_torexp_stri0]) +} - function _reg_check(p) - { - _tframe("_reg_check_i0", p, p) - } +function _subseqoff(r, B) +{ + patsplit(r, B, /\x84[^\x94]*\x94/) + return gensub(/\x84[^\x94]*\x94/, "\204", "G", r) +} - function _reg_check_i0(p, pp, p1, p2) - { - if (_[p]["TYPE"] == "defreg") { - if (_[p]["REGPATH"] in _REG) { - if ("VALUE" in _[p]) { - if (_[p]["VALUE"] == _REG[_[p]["REGPATH"]]) { - _creport(p, substr("OK: REGENTRY MATCH(==" _[p]["VALUE"] "): " _[p]["REGPATH"], 1, 126)) - } else { - _dllerr(p, substr("REGENTRY NOT MATCH(!=" _[p]["VALUE"] "): " _[p]["REGPATH"], 1, 126)) - } - } else if (_VAR[_[p]["REGPATH"]] == _REG[_[p]["REGPATH"]]) { - _creport(p, substr("OK: REGPATH MATCH(==" _VAR[_[p]["REGPATH"]] "): " _[p]["REGPATH"], 1, 126)) - } else { - _dllerr(p, substr("REGPATH NOT MATCH(!=" _VAR[_[p]["REGPATH"]] "): " _[p]["REGPATH"], 1, 126)) - } - } else { - _dllerr(p, substr("REGPATH NOT FOUND: " _[p]["REGPATH"], 1, 126)) - } - } +function _subseqon(B, r, F, f, s, e, q, i, A) +{ + q = split(r, A, /\x84/) + r = "" + f = F[""] + for (i = 1; i < q; i++) { + s = substr(e = B[i], 2, 1) + #_conl("curr r==`" r "': A[" i "]=`" A[i] "'") + #s=s in F ? _th0(F[s],_conl("handler `" F[s] "' for `" s "' ost=`" substr(e,3,length(e)-3) "'")) : _th0(F[""],_conl("default handler for `" s "'")) + s = (s in F ? F[s] : F[""]) + #_conl("`" f "'") + r = r (@f(A[i])) (@s(substr(e, 3, length(e) - 3))) } + return (r (@f(A[i]))) +} - function _registryinit() - { - _registrytmpfile = _getmpfile() - } +#_____________________________________________________________________________ +# _rdreg(ARRAY,reg_path) +# Import into ARRAY the content of the whole registree tree with the higher point specified by reg_path. +# ARRAY will be filled by the strings with following format: +# +# HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\GnuWin32\CoreUtils\5.3.0\pck\InstallPath.STR=C:\Program Files (x86)\GnuWin32 +# where: +# HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\GnuWin32\CoreUtils\5.3.0\pck <- REG KEY PATH +# InstallPath <- DATA FIELD +# STR <- TYPE +# C:\Program Files (x86)\GnuWin32 <- VALUE +# TYPE: +# STR - REG_SZ (String Value) +# W32 - REG_DWORD (DWORD (32-bit) Value) +# W64 - REG_QWORD (QWORD (64-bit) Value) +# BIN - REG_BINARY (Binary Value) +# XSZ - REG_EXPAND_SZ (Expandable String Value) +# MSZ - REG_MULTI_SZ (Multi-String Value) +#_________________________________________________________________________________________ - function _regpath0(D, i, s, q, S) - { - if (i = _patharr0(S, i)) { - if ("name" in S) { - D["name"] = S["name"] - } - if ("ext" in S) { - D["ext"] = S["ext"] - } - s = ((toupper(s = (i in S ? S[i] : "")) in _REGPATH0REGDIR ? D[++q] = _REGPATH0REGDIR[toupper(s)] : (D[++q] = _REGPATH0REGDIR[""]) "\\" (D[++q] = s))) "\\" - while (++i in S) { - s = s (D[++q] = S[i]) "\\" - } - if (s != "") { - D[0] = s - } - IGNORECASE = 1 - D["hostdir"] = "\\\\" (D["host"] = ("host" in S && ("" == (i = S["host"]) || "." == i || "?" == i || "localhost" == i) ? ENVIRON["COMPUTERNAME"] : i)) "\\" s - IGNORECASE = 0 - } - } - function _report(p) - { - _report_t0 = _reportparnt = "" - _report_i0(p) - _tframe("_report_i0", p) - return _report_t0 - } - function _report_i0(p, p0, p1, p2) - { - if (p in _tPARENT) { - if (_reportparnt != (_reportparnt = _tPARENT[p])) { - _report_t0 = _report_t0 _ln() _ln((z = "_ " _[_tPARENT[p]]["NAME"] " ") _getchrln("_", _CON_WIDTH - length(z) - 2)) _ln(_getchrln("#", _CON_WIDTH - 2)) _ln() - } - } - if ("ERROR" in _[p]) { - _report_t0 = _report_t0 _reporterr(p, _[p]["ERROR"]) - } - if ("REPORT" in _[p]) { - _report_t0 = _report_t0 _ln(_[p]["REPORT"]) - } - } - function _reporterr(p, t3, pp, t, t2) - { - t = "" - pp = p - do { - ("NAME" in _[pp] ? t = _[pp]["NAME"] ": " t : "") - } while (pp = _rPARENT(pp)) - if (match(t3, /\x00/)) { - return (substr(t3, 1, RSTART - 1) t substr(t3, RSTART + 1)) - } - return (t t3) - } +# HKCR HKEY_CLASSES_ROOT +# HKCU HKEY_CURRENT_USER +# HKLM HKEY_LOCAL_MACHINE +# HKU HKEY_USERS +# HKCC HKEY_CURRENT_CONFIG +# HKPD HKEY_PERFORMANCE_DATA - function _retarr(A, i, p, a, q) - { - if (isarray(A)) { - i = (i == "" ? 0 : i + 0) - q = A[_ARRLEN] + 0 - if (i < q) { - return (p A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] _retarr_i0(A, q, i, a)) - } - } - } - function _retarr_i0(A, q, i, a) - { - if (i < q) { - return (A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] A[++i] _retarr_i0(A, q, i, a)) - } - while (q < i) { - delete A[++q] - } - return a - } - function _retarrd(A, v, i) - { - if (1 in A) { - return (A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9] A[10] A[11] A[12] A[13] A[14] A[15] A[16] (((i = 17) in A ? _retarrd_i0(A, i) v : v))) - } - delete A - return v - } - function _retarrd_i0(A, i) - { - if (i in A) { - return (A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] A[i++] ((i in A ? _retarrd_i0(A, i) : ""))) - } - delete A - } - function _rexpfn(R, t, p) - { - _REXPFN[""] = "" - while (t) { - t = _rxpfn(R, t, p) - } - return _REXPFN[""] - } - function _rexpfnend(t) - { - _REXPFN[""] = t - } - function _rexpstr(r, i, c, A) - { - c = split(r, A, "") - r = "" - for (i = 1; i <= c; i++) { - r = r _REXPSTR[A[i]] - } - return r - } - function _rexpstr_i0(t, A, p0) - { - return (_REXPSTR[t] = "\\" t) - } - function _rmtsharerr(h, t) - { - gsub(/[\x0D\x0A]+/, "", t) - if (t ~ /^The command failed: 53/) { - ERRNO = "host not found: \\\\" h - } else { - ERRNO = t ": \\\\" h - } - } - function _rpp(q, D, S) - { - _conl() - _conline(q) - _conl() - _regpath0(D, q) - _conl(_ln("DEST:") _dumparr(D)) - _conl() - return q - } - function _rrdreg(DD, p, k, t, v, c, i, q, tT, A, B, C, D) - { - if (! _registrytmpfile) { - _registryinit() - } - _cmd("regedit /E \"" _registrytmpfile "\" \"" p "\" 2>&1") - q = patsplit(gensub(/[\x00\xFF\xFE]+/, "", "G", _rdfile(_registrytmpfile)), A, /\x0D?\x0A\[[^\]]+\]\x0D?\x0A/, B) - for (i = 1; i <= q; i++) { - p = gensub(/(^[ \t\x0D\x0A]*\[)|((\\)\\+)|(\][ \t\x0D\x0A]*$)/, "\\3", "G", A[i]) - DD[p "\\"] - delete C[split(B[i], C, /[\x0D\x0A]+/)] - for (c = 1; c in C; c++) { - tt = tt C[c] - if (gsub(/\\$/, "", tt)) { - continue - } - if (tt == "") { - continue - } - if (match(_th0(tt, tt = ""), /((^"(([^\\"]|\\.)*)")|(@))=(("(([^\\"]|\\.)*)")|(dword:([[:xdigit:]]{8}))|(hex(\(([27b])\))?:(.*)))$/, D)) { - if (D[7]) { - t = "STR" - v = _unstr(D[8]) - } else if (D[10]) { - t = "W32" - v = D[11] - } else { - v = D[15] - if (D[13]) { - switch (D[14]) { - case "2": - t = "XSZ" - break - case "7": - t = "MSZ" - break - default: - t = "W64" - } - } else { - t = "BIN" - } - } - DD[gensub(/(\\)\\+/, "\\1", "G", p "\\" _unstr(D[3] ((D[5] ? "(Default)" : ""))) "." t)] = v - } else { - _fatal("regedit: unknown output format(" c "): `" C[c] "'") - } - } - } - } - function _rsqgetptr(g, p, A) - { - if (p in _tLINK) { - _SQSTACK[g][++_SQSTACK[g][0]] = p - _SQSTACK[g][++_SQSTACK[g][0]] = _SQTOPTR[g] - while ((p = _tLINK[p]) in _tLINK) { - _con(".") - } - _SQTOPTR[g] = p - } - if (p in _tFCHLD) { - return _rsqgetptr(g, _tFCHLD[p]) - } - return p - } - function _rsqnext_i0(g, p) - { - if (p == _SQTOPTR[g]) { - if (_SQSTACK[g][0] > 0) { - _SQTOPTR[g] = _SQSTACK[g][_SQSTACK[g][0]--] - return _rsqnext_i0(g, _SQSTACK[g][_SQSTACK[g][0]--]) - } - return - } - if (p in _tNEXT) { - return _rsqgetptr(g, _tNEXT[p]) - } - return _rsqnext_i0(g, _tPARENT[p]) - } - - function _rtn(v, A) - { - _conl() - _conline(_val(v) " : " _val(A)) - _conl() - _rtn2(v, A) - _conl() - } - - function _rtn2(v, A, r, t) - { - r = (isarray(A) ? _typa(v, A) : _typ(v)) - if ("`" > _t0 && _t0) { - _conl("ggggg") - } - t = ((r ? "TRUE" : "FALSE")) " / " ((r > 0 ? r ">0" : r "!>0")) " / " ((r + 0 > 0 ? r "+0>0" : r "+0!>0")) " / " ((r + 0 != r ? r "+0!=" r : r "+0==" r)) " / " ((r && "`" > r ? "'`'>" r " && " r : "!('`'>" r " && " r ")")) - _conl("`" r "' : " t) - return r - } - function _rxpfn(R, t, p, i, f, A) - { - for (i in R) { - if (match(t, i, A)) { - f = R[i] - if (t != (t = @f(A, substr(t, RLENGTH + 1), p))) { - return t - } - } - } - return _rexpfnend(t) - } - - function _sHARE(c, t, P, a, A) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_share 1.000") - case "_lib_BEGIN": - return - case "_lib_END": - return - } - } - function _sYS(c, t, P, a, A) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return - case "_lib_BEGIN": - return - case "_lib_END": - return - } - } - function _serv_check(p) - { - _tframe("_serv_check_i0", p, p) - } - function _serv_check_i0(p, p0, p1, p2, p3, i, q, c) - { - if (_[p]["TYPE"] == "defsrv") { - i = IGNORECASE - IGNORECASE = 1 - if (match(_servoutput, roi = "\\012DISPLAY_NAME: " _torexp(_[p]["SERVNAME"]))) { - _creport(p, "OK: SERVICE DETECTED: " substr(_[p]["SERVNAME"], 1, 112)) - } else { - _dllerr(p, "service " _[p]["SERVNAME"] " not detected") - } - } - IGNORECASE = i - } - function _setarrsort(f, a) - { - a = PROCINFO["sorted_in"] - if (! f) { - delete PROCINFO["sorted_in"] - } else { - PROCINFO["sorted_in"] = f - } - return a - } - function _setmpath(p, a) - { - ERRNO = "" - if (p && (a = _filerd(p))) { - if (_FILEIO_TMPRD) { - _FILEIO_TMPATHS[_FILEIO_TMPRD] - } - return (_FILEIO_TMPRD = a) - } else { - return _warning("`" p "': cannot set temporary folder" ((ERRNO ? ": " ERRNO : ""))) - } - } - function _sharelist(D, h, q, c, l, A, B) - { - delete D - c = _sharextool " \\\\" ((h == "" ? h = ENVIRON["COMPUTERNAME"] : h)) " 2>&1" - if (match(c = _cmd(c), /\x0AShare[^\x0A]*Remark/)) { - gsub(/(^[^-]*\x0D?\x0A-+\x0D?\x0A[ \t]*)|(\x0D?\x0AThe command completed successfully.*$)/, "", c) - l = RLENGTH - 7 - split(c, A, /([ \t]*\x0D?\x0A)+[ \t]*/) - for (c in A) { - if (match(A[c], /((([^ \t:]+[ \t]+)*[^ \t:]+)[ \t]+)([A-Za-z])[ \t]*:/, B) && ++q) { - D[B[2]] = (A[c] ~ /\.\.\.$/ ? _sharepath(h, B[2]) : gensub(/[ \t\\\/]*$/, "\\\\", 1, substr(A[c], 1 + B[1, "length"], l - B[1, "length"]))) - } - } - return q - } - return _rmtsharerr(h, c) - } - function _sharepath(h, s, A) - { - s = _sharextool " \\\\" ((h == "" ? h = ENVIRON["COMPUTERNAME"] : h)) "\\\"" s "\" 2>&1" - if (match(s = _cmd(s), /\x0APath[ \t]+([^\x0D\x0A]+)/, _SHAREPATHA0)) { - return gensub(/[ \t\\\/]*$/, "\\\\", 1, _SHAREPATHA0[1]) - } - return _rmtsharerr(h, s) - } - function _shortcut(D, S) - { - if (isarray(D)) { - if (isarray(S)) { - _addarrmask(D, S, _SHORTCUTWSTRUC) - } else if (S == 0 && S == "") { - _addarrmask(D, _SHORTCUTDEFAULT, _SHORTCUTWSTRUC) - } else if (_isnotfileptr(S)) { - _addarrmask(D, _[S], _SHORTCUTWSTRUC) - } else if (_rd_shortcut(D, S)) { - return - } - } else if (D == 0 && D == "") { - return _NOP - } else if (_isnotfileptr(D)) { - if (isarray(S)) { - _addarrmask(_[D], S, _SHORTCUTWSTRUC) - } else if (S == 0 && S == "") { - _addarrmask(_[D], _SHORTCUTDEFAULT, _SHORTCUTWSTRUC) - } else if (_isnotfileptr(S)) { - _addarrmask(_[D], _[S], _SHORTCUTWSTRUC) - } else if (_rd_shortcut(_[D], S)) { - return - } - } else if (isarray(S) && _wr_shortcut(D, S)) { - return - } else if (S == 0 && S == "" && _wr_shortcut(D, _SHORTCUTDEFAULT)) { - return - } else if (_isnotfileptr(S) && _wr_shortcut(D, _[S])) { - return - } else if (_rd_shortcut(_SHRTCUTA1, S) || _wr_shortcut(D, _SHRTCUTA1)) { - return - } - return 1 - } - function _shortcut_init(A, B, q) - { - _SHORTCUTERR[2] = "file not found" - _SHORTCUTERR[3] = "no such filepath" - _SHORTCUTERR["The system cannot find the file specified."] = "no such filepath" - _SHORTCUTERR[5] = "file is folder" - _SHORTCUTERR["Access is denied."] = "file is folder" - _SHORTCUTERR[123] = "filepath syntax error" - _SHORTCUTERR["The filename, directory name, or volume label syntax is incorrect."] = "filepath syntax error" - q = "target\t\t\t/T:\t\t\t\tTargetPath=\t\t\t\t\ttarget?\t\t\t;\t\t\t_target\t\t\t\t\t\t\tTargetPathExpanded=\t\t\t\t\t\t\t;\t\t\tparameters\t\t\t/P:\t\t\t\tArguments=\t\t\t\t\tparaneters?\t\t\t;\t\t\t_parameters\t\t\t\t\t\t\tArgumentsExpanded=\t\t\t\t\t\t\t;\t\t\tstartdir\t\t\t/W:\t\t\t\tWorkingDirectory=\t\t\t\tstartdir?\t\t\t;\t\t\t_startdir\t\t\t\t\t\t\tWorkingDirectoryExpanded=\t\t\t\t\t\t;\t\t\trunstyle\t\t\t/R:\t\t\t\tRunStyle=\t\t\t\t\t1\t\t\t\t;\t\t\ticon,index\t\t\t/I:\t\t\t\tIconLocation=\t\t\t\ticon,index?\t\t\t;\t\t\txicon,index\t\t\t\t\t\t\tIconLocationExpanded=\t\t\t\t\t\t\t;\t\t\tshortcut key\t\t/H:\t\t\t\tHotKey=\t\t\t\t\t0\t\t\t\t;\t\t\tdescription\t\t\t/D:\t\t\t\tDescription=\t\t\t\t_env4: default shortcut\t" - split(q, _SHRTCUTA0, /[ \t]*;[ \t]*/) - for (q in _SHRTCUTA0) { - if (match(_SHRTCUTA0[q], /^([^\t]+)\t+([^\t]+)(\t+([^\t]+)(\t+([^\t]+))?)?/, B)) { - if (B[3] == "") { - _SHORTCUTRSTRUC[B[2]] = B[1] - } else if (B[5] == "") { - _SHORTCUTWSTRUC[_SHORTCUTRSTRUC[B[4]] = B[1]] = B[2] - delete _SHORTCUTDEFAULT[B[1]] - } else { - _SHORTCUTWSTRUC[_SHORTCUTRSTRUC[B[4]] = B[1]] = B[2] - _SHORTCUTDEFAULT[B[1]] = B[6] - } - } else { - _fatal("_shortcut.init: _shortcut_struc: syntax error: `" _SHRTCUTA0[q] "'") - } - } - _SHRTCUTA1[""] - delete _SHRTCUTA1[""] - _shortcut_fpath = "\\\\localhost\\eGAWK\\LIB\\_shortcut\\_shortcut.exe" - } - function _shortcut_nerr(t, s, A) - { - if (match(t, /\x0ASystem error (-?[0-9]+)[^\x0D\x0A]*[\x0D\x0A]+([^\x0D\x0A]+)/, A)) { - ERRNO = ((A[1] in _SHORTCUTERR ? _SHORTCUTERR[A[1]] : (A[2] in _SHORTCUTERR ? _SHORTCUTERR[A[2]] : tolower(gensub(/^(The )?(((.*)\.$)|(.*[^\.]$))/, "\\4\\5", "G", A[2])) "(" A[1] ")"))) ((s ? ": `" s "'" : "")) - } else { - return 1 - } - } - function _split_regpath() - { - _rpp(" / / / / ") - _rpp(" / / / / huj ") - _rpp(" / / / / huj / ") - _rpp(" / / / / huj / pizda.TSR ") - _rpp(" / / / / hklm ") - _rpp(" / / / / hklm / ") - _rpp(" / / / / hklm / huj ") - _rpp(" / / / / hklm / huj / ") - _rpp(" / / / / hklm / huj / \tpizda.TSR ") - _conl() - _conl("########################################################################################") - _conl() - _rpp(" / / / / hklm / software / altiris / fi le . ex t ") - _rpp(" / / . / / hkcr / software / altiris / fi le . ex t ") - _rpp(" / / ? / / hKcU / software / altiris / fi le . ex t ") - _rpp(" / / lOcAlHoSt / / hKu / software / altiris / fi le . ex t ") - _rpp(" / / ho st / / hKcc / software / altiris / fi le . ex t ") - _rpp(" / / ho st / / hKPd / software / altiris / fi le . ex t ") - _conl() - _conl("########################################################################################") - _conl() - } - function _splitpath_test() - { - _conl() - _conl("########################################################################################") - _conl() - _fpp(" ") - _fpp(" fi le . ex t ") - _fpp(" di r0 / / ") - _fpp(" di r0 / / fi le . ex t ") - _fpp(" / ") - _fpp(" / fi le . ex t ") - _fpp(" / di r0 / / ") - _fpp(" / di r0 / / fi le . ex t ") - _conl() - _conl("########################################################################################") - _conl() - _fpp(" c : ") - _fpp(" c : fi le . ex t ") - _fpp(" c : di r0 / / ") - _fpp(" c : di r0 / / fi le . ex t ") - _fpp(" c : / / ") - _fpp(" c : / / fi le . ex t ") - _fpp(" c : / / di r0 / / ") - _fpp(" c : / / di r0 / / fi le . ex t ") - _conl() - _conl("########################################################################################") - _conl() - _fpp(" / / ") - _fpp(" / / ho st . hs t ") - _fpp(" / / ho st / / ") - _fpp(" / / ho st / / fi le . ex t ") - _fpp(" / / ho st / / di r0 / / ") - _fpp(" / / ho st / / di r0 / / fi le . ex t ") - _conl() - _conl("########################################################################################") - _conl() - _fpp(" / / ho st / / c : ") - _fpp(" / / ho st / / c : fi le . ex t ") - _fpp(" / / ho st / / c : di r0 / / ") - _fpp(" / / ho st / / c : di r0 / / fi le . ex t ") - _fpp(" / / ho st / / c : / / ") - _fpp(" / / ho st / / c : / / fi le . ex t ") - _fpp(" / / ho st / / c : / / di r0 / / ") - _fpp(" / / ho st / / c : / / di r0 / / fi le . ex t ") - _conl() - _conl("########################################################################################") - _conl() - _fpp(" http : / / / ") - _fpp(" http : / / / si te . ex t ") - _fpp(" http : / / / si te / / ") - _fpp(" http : / / / si te / / fi le . ex t ") - _fpp(" http : / / / si te / / di r0 / / ") - _fpp(" http : / / / si te / / di r0 / / fi le . ex t ") - _conl() - _conl("########################################################################################") - _conl() - _fpp(" ftp : / / / : po rt ") - _fpp(" ftp : / / / si te . ex t : po rt ") - _fpp(" ftp : / / / si te : po rt / / ") - _fpp(" ftp : / / / si te : po rt / / fi le . ex t ") - _fpp(" ftp : / / / si te : po rt / / di r0 / / ") - _fpp(" ftp : / / / si te : po rt / / di r0 / / fi le . ex t ") - _conl() - _conl("## //. ######################################################################################") - _conl() - _fpp(" / / . ") - _fpp(" / / . / / ") - _fpp(" / / . / / com 56 ") - _fpp(" / / . / / com 56 / / ") - _fpp(" / / . / / c : ") - _fpp(" / / . / / c : / / ") - _fpp(" / / . / / c : com 56 ") - _fpp(" / / . / / c : com 56 / / ") - _fpp(" / / . / / c : / / com 56 ") - _fpp(" / / . / / c : / / com 56 / / ") - _conl() - _conl("## //? ######################################################################################") - _conl() - _fpp(" / / ? ") - _fpp(" / / ? / / ") - _fpp(" / / ? / / com 56 ") - _fpp(" / / ? / / com 56 / / ") - _fpp(" / / ? / / c : ") - _fpp(" / / ? / / c : / / ") - _fpp(" / / ? / / c : com 56 ") - _fpp(" / / ? / / c : com 56 / / ") - _fpp(" / / ? / / c : / / com 56 ") - _fpp(" / / ? / / c : / / com 56 / / ") - _conl() - _conl("########################################################################################") - _conl() - _fpp(" / / / ") - _fpp(" / / / . hs t ") - _fpp(" / / / / fi le . ex t ") - _fpp(" / / / / di r0 / / ") - _fpp(" / / / / di r0 / / di r1 / fi le . ex t ") - _fpp(" / / / / c : ") - _fpp(" / / / / c : fi le . ex t ") - _fpp(" / / / / c : di r0 / / ") - _fpp(" / / / / c : di r0 / / fi le . ex t ") - _fpp(" / / / / c : / / ") - _fpp(" / / / / c : / / fi le . ex t ") - _fpp(" / / / / c : / / di r0 / / ") - _fpp(" / / / / c : / / di r0 / / fi le . ex t ") - _conl() - _conl("########################################################################################") - _conl() - return - } - function _splitstr(A, t, r) - { - if (_istr(t)) { - if (_splitstr_i0(A, t) > 0) { - return _splitstrp0 - } - if (_istr(r)) { - return _splitstr_i0(A, r) - } - } else { - if (it == "A") { - if (length(t) > 0) { - _movarr(A, t) - return (0 - length(A)) - } - } - _istr(r) - } - if (it == "A") { - if (length(r) > 0) { - _movarr(A, r) - return (0 - length(A)) - } - } - } - function _splitstr_i0(A, t, C) - { - if (2 > (_splitstrq0 = patsplit(t, _SPLITSTRA0, /([^,\xB4]*\xB4.)*[^,\xB4]*/))) { - _splitstrq0 = split(gensub(/\xB4(.)/, "\\1", "G", t), _SPLITSTRA0, "") - } - delete A - _splitstri0 = _splitstrp0 = 0 - while (_splitstri0++ < _splitstrq0) { - if ((t = gensub(/\xB4(.)/, "\\1", "G", _SPLITSTRA0[_splitstri0])) in C || t == "") { - continue - } - C[A[++_splitstrp0] = t] - } - return _splitstrp0 - } - function _strtorexp(t) - { - gsub(/[\\\.\?\*\+\-\(\)\{\}\[\]\^\$\/\|]/, "\\\\&", t) - t = split(t, _TOREXP_STRA, /[\x00-\x1F]/, _TOREXP_STRB) - _torexp_strt0 = "" - for (_torexp_stri0 = 1; _torexp_stri0 < t; _torexp_stri0++) { - _torexp_strt0 = _torexp_strt0 _TOREXP_STRA[_torexp_stri0] "\\" _QASC[_TOREXP_STRB[_torexp_stri0]] - } - return (_torexp_strt0 _TOREXP_STRA[_torexp_stri0]) - } - function _subseqoff(r, B) - { - patsplit(r, B, /\x84[^\x94]*\x94/) - return gensub(/\x84[^\x94]*\x94/, "\204", "G", r) - } - function _subseqon(B, r, F, f, s, e, q, i, A) - { - q = split(r, A, /\x84/) - r = "" - f = F[""] - for (i = 1; i < q; i++) { - s = substr(e = B[i], 2, 1) - s = (s in F ? F[s] : F[""]) - r = r (@f(A[i])) (@s(substr(e, 3, length(e) - 3))) - } - return (r (@f(A[i]))) - } - function _sysinfo(D, h) - { - h = "wmic /NODE: \"" h "\" OS 2>NUL" - if (split(_cmd(h), _SYSINFOA0, /[\x0D\x0A]+/) == 3) { - _sysinfol0 = length(h = _SYSINFOA0[2]) + 1 - _sysinfoq0 = _sysinfoq1 = split(_SYSINFOA0[1], _SYSINFOA0, / +/, _SYSINFOB0) - while (--_sysinfoq0 > 0) { - D[_sysinfof0] = gensub(/^ +| +$/, "", "G", substr(h, _sysinfol0 = _sysinfol0 - (_sysinfol1 = length(_sysinfof0 = _SYSINFOA0[_sysinfoq0]) + length(_SYSINFOB0[_sysinfoq0])), _sysinfol1)) - } - return (_sysinfoq1 - 1) - } - } - function _tOBJ(c, t, P) - { - switch (c) { - case "_lib_CMDLN": - return t - case "_lib_APPLY": - return - case "_lib_HELP": - return - case "_lib_NAMEVER": - return _ln("_tOBJ 3.0") - case "_lib_BEGIN": - return - case "_lib_END": - return - case "_lib_CLEANUP": - return _tOBJ_CLEANUP() - } - } - function _tOBJ_CLEANUP(p) - { - for (p in UIDSDEL) { - delete _ptr[p] - delete _tPREV[p] - delete _tPARENT[p] - delete _tNEXT[p] - delete _tFCHLD[p] - delete _tQCHLD[p] - delete _tLCHLD[p] - delete _TMP0[p] - delete _TMP1[p] - delete _tLINK[p] - delete _tCLASS[p] - } - } - function _tabtospc(t, ts, xc, a, c, n, A, B) - { - if (! ts) { - ts = _TAB_STEP_DEFAULT - } - c = split("." t, A, /\t+/, B) - A[1] = substr(A[1], 2) - t = "" - for (n = 1; n <= c; n++) { - t = t A[n] _getchrln(" ", (xc = length(B[n]) * ts + int((a = xc + length(A[n])) / ts) * ts) - a) - } - return t - } - function _tapi(p, f, p0, p1, p2, p3, c) - { - c = p - do { - if (f in _[c]["API"]) { - f = _[c]["API"][f] - return @f(p, p0, p1, p2, p3) - } - c = _[c]["CLASS"] - } while ("CLASS" in _[c]) - } - function _tbframe(f, p, p0, p1) - { - delete _t_ENDF[++_t_ENDF[0]] - f = (p ? _tbframe_i0(f, p, p0, p1) : "") - --_t_ENDF[0] - return f - } - function _tbframe_i0(f, p, p0, p1, a) - { - while (p in _tLINK) { - p = _tLINK[p] - } - return ((p in _tLCHLD ? _tmbframe(f, _tLCHLD[p], p0, p1) : @f(p, p0, p1))) - } - function _tbframex(f, p, p0, p1) - { - delete _t_ENDF[++_t_ENDF[0]] - f = (p ? _tbframex_i0(f, p, p0, p1) : "") - --_t_ENDF[0] - return f - } - function _tbframex_i0(f, p, p0, p1) - { - while (p in _tLINK) { - p = _tLINK[p] - } - return ((p in _tLCHLD ? _tmbframex(f, _tLCHLD[p], p0, p1) : @f(p, p0, p1))) - } - function _tbpass(f, p, p0, p1) - { - delete _t_ENDF[++_t_ENDF[0]] - f = (p ? _tbpass_i0(f, p, p0, p1) : "") - --_t_ENDF[0] - return f - } - function _tbpass_i0(f, p, p0, p1, a) - { - while (p in _tLINK) { - p = _tLINK[p] - } - return ((p in _tLCHLD ? _tmbpass(f, _tLCHLD[p], p0, p1) : @f(p, p0, p1))) - } - function _tbpassx(f, p, p0, p1) - { - delete _t_ENDF[++_t_ENDF[0]] - f = (p ? _tbpassx_i0(f, p, p0, p1) : "") - --_t_ENDF[0] - return f - } - function _tbpassx_i0(f, p, p0, p1) - { - while (p in _tLINK) { - p = _tLINK[p] +#___________________________________________________________________________________ +#################################################################################### +function _sysinfo(D, h) +{ + ############################################################## + h = "wmic /NODE: \"" h "\" OS 2>NUL" + if (split(_cmd(h), _SYSINFOA0, /[\x0D\x0A]+/) == 3) { + _sysinfol0 = length(h = _SYSINFOA0[2]) + 1 + _sysinfoq0 = _sysinfoq1 = split(_SYSINFOA0[1], _SYSINFOA0, / +/, _SYSINFOB0) + while (--_sysinfoq0 > 0) { + D[_sysinfof0] = gensub(/^ +| +$/, "", "G", substr(h, _sysinfol0 = _sysinfol0 - (_sysinfol1 = length(_sysinfof0 = _SYSINFOA0[_sysinfoq0]) + length(_SYSINFOB0[_sysinfoq0])), _sysinfol1)) } - return ((p in _tLCHLD ? _tmbpassx(f, _tLCHLD[p], p0, p1) : @f(p, p0, p1))) + return (_sysinfoq1 - 1) } +} - function _tbrochld(p, f, pp) - { - if (p) { - if (p in _tFCHLD) { - f = _tFCHLD[p] - delete _tFCHLD[p] - delete _tLCHLD[p] - if (p in _tPARENT) { - pp = _tPARENT[p] - delete _tPARENT[p] - if (p in _tPREV) { - _tNEXT[_tPREV[f] = _tPREV[p]] = f - delete _tPREV[p] - } else { - _tFCHLD[pp] = f - } - for (; f in _tNEXT; f = _tNEXT[f]) { - _tPARENT[f] = pp - } - _tPARENT[f] = pp - if (p in _tNEXT) { - _tPREV[_tNEXT[f] = _tNEXT[p]] = f - delete _tNEXT[p] - } else { - _tLCHLD[pp] = f - } - _tQCHLD[pp] = _tQCHLD[pp] + _tQCHLD[p] - 1 - delete _tQCHLD[p] - return f - } else { - delete _tQCHLD[p] - if (p in _tPREV) { - _tNEXT[_tPREV[f] = _tPREV[p]] = f - delete _tPREV[p] - } - for (; f in _tNEXT; f = _tNEXT[f]) { - delete _tPARENT[f] - } - delete _tPARENT[f] - if (p in _tNEXT) { - _tPREV[_tNEXT[f] = _tNEXT[p]] = f - delete _tNEXT[p] - } - return f - } - } else if (p in _tPARENT) { +######################################################### +function _tOBJ(c, t, P) +{ + switch (c) { + case "_lib_CMDLN": + #___________________________________________________________ + return t + #___________________________________________________________ + case "_lib_APPLY": + return + #___________________________________________________________ + case "_lib_HELP": + return + #___________________________________________________________ + case "_lib_NAMEVER": + return _ln("_tOBJ 3.0") + #___________________________________________________________ + case "_lib_BEGIN": + return + #___________________________________________________________ + case "_lib_END": + return + #___________________________________________________________ + case "_lib_CLEANUP": + return _tOBJ_CLEANUP() + } +} + +#_______________________________________________________________________ +function _tOBJ_CLEANUP(p) +{ + ############################################## + for (p in UIDSDEL) { + delete _ptr[p] + delete _tPREV[p] + delete _tPARENT[p] + delete _tNEXT[p] + delete _tFCHLD[p] + delete _tQCHLD[p] + delete _tLCHLD[p] + delete _TMP0[p] + delete _TMP1[p] + delete _tLINK[p] + delete _tCLASS[p] + } +} + +#_______________________________________________________________________ +function _tabtospc(t, ts, xc, a, c, n, A, B) +{ + ################################## + if (! ts) { + ts = _TAB_STEP_DEFAULT + } + c = split("." t, A, /\t+/, B) + A[1] = substr(A[1], 2) + t = "" + for (n = 1; n <= c; n++) { + t = t A[n] _getchrln(" ", (xc = length(B[n]) * ts + int((a = xc + length(A[n])) / ts) * ts) - a) + } + return t +} + +#___________________________________________________________________________________ +#################################################################################### +function _tapi(p, f, p0, p1, p2, p3, c) +{ + c = p + do { + if (f in _[c]["API"]) { + f = _[c]["API"][f] + return @f(p, p0, p1, p2, p3) + } + c = _[c]["CLASS"] + } while ("CLASS" in _[c]) +} + +#_____________________________________________________________________________ +function _tbframe(f, p, p0, p1) +{ + ################################################## + delete _t_ENDF[++_t_ENDF[0]] + f = (p ? _tbframe_i0(f, p, p0, p1) : "") + --_t_ENDF[0] + return f +} + +#___________________________________________________________ +function _tbframe_i0(f, p, p0, p1, a) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tLCHLD ? _tmbframe(f, _tLCHLD[p], p0, p1) : @f(p, p0, p1))) +} + +#_______________________________________________________________________ +function _tbframex(f, p, p0, p1) +{ + ########################################### + delete _t_ENDF[++_t_ENDF[0]] + f = (p ? _tbframex_i0(f, p, p0, p1) : "") + --_t_ENDF[0] + return f +} + +#___________________________________________________________ +function _tbframex_i0(f, p, p0, p1) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tLCHLD ? _tmbframex(f, _tLCHLD[p], p0, p1) : @f(p, p0, p1))) +} + +#_____________________________________________________________________________ +function _tbpass(f, p, p0, p1) +{ + ################################################### + delete _t_ENDF[++_t_ENDF[0]] + f = (p ? _tbpass_i0(f, p, p0, p1) : "") + --_t_ENDF[0] + return f +} + +#___________________________________________________________ +function _tbpass_i0(f, p, p0, p1, a) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tLCHLD ? _tmbpass(f, _tLCHLD[p], p0, p1) : @f(p, p0, p1))) +} + +#_____________________________________________________________________________ +function _tbpassx(f, p, p0, p1) +{ + ################################################## + delete _t_ENDF[++_t_ENDF[0]] + f = (p ? _tbpassx_i0(f, p, p0, p1) : "") + --_t_ENDF[0] + return f +} + +#___________________________________________________________ +function _tbpassx_i0(f, p, p0, p1) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tLCHLD ? _tmbpassx(f, _tLCHLD[p], p0, p1) : @f(p, p0, p1))) +} + +#_____________________________________________________________________________ +function _tbrochld(p, f, pp) +{ + ################################################### # TEST!!! + if (p) { + if (p in _tFCHLD) { + f = _tFCHLD[p] + delete _tFCHLD[p] + delete _tLCHLD[p] + if (p in _tPARENT) { pp = _tPARENT[p] delete _tPARENT[p] if (p in _tPREV) { - if (p in _tNEXT) { - _tNEXT[_tPREV[f] = _tPREV[p]] = f = _tNEXT[p] - delete _tNEXT[p] - } else { - delete _tNEXT[_tLCHLD[pp] = _tPREV[p]] - } + _tNEXT[_tPREV[f] = _tPREV[p]] = f delete _tPREV[p] - _tQCHLD[pp]-- - } else if (p in _tNEXT) { - delete _tPREV[_tFCHLD[pp] = _tNEXT[p]] + } else { + _tFCHLD[pp] = f + } + for (; f in _tNEXT; f = _tNEXT[f]) { + _tPARENT[f] = pp + } + _tPARENT[f] = pp + if (p in _tNEXT) { + _tPREV[_tNEXT[f] = _tNEXT[p]] = f delete _tNEXT[p] - _tQCHLD[pp]-- } else { - delete _tFCHLD[pp] - delete _tLCHLD[pp] - delete _tQCHLD[pp] + _tLCHLD[pp] = f } - } else if (p in _tPREV) { + _tQCHLD[pp] = _tQCHLD[pp] + _tQCHLD[p] - 1 + delete _tQCHLD[p] + return f + } else { + delete _tQCHLD[p] + if (p in _tPREV) { + _tNEXT[_tPREV[f] = _tPREV[p]] = f + delete _tPREV[p] + } + for (; f in _tNEXT; f = _tNEXT[f]) { + delete _tPARENT[f] + } + delete _tPARENT[f] + if (p in _tNEXT) { + _tPREV[_tNEXT[f] = _tNEXT[p]] = f + delete _tNEXT[p] + } + return f + } + } else if (p in _tPARENT) { + pp = _tPARENT[p] + delete _tPARENT[p] + if (p in _tPREV) { if (p in _tNEXT) { _tNEXT[_tPREV[f] = _tPREV[p]] = f = _tNEXT[p] delete _tNEXT[p] } else { - delete _tNEXT[_tPREV[p]] + delete _tNEXT[_tLCHLD[pp] = _tPREV[p]] } delete _tPREV[p] + _tQCHLD[pp]-- } else if (p in _tNEXT) { - delete _tPREV[_tNEXT[p]] + delete _tPREV[_tFCHLD[pp] = _tNEXT[p]] delete _tNEXT[p] + _tQCHLD[pp]-- + } else { + delete _tFCHLD[pp] + delete _tLCHLD[pp] + delete _tQCHLD[pp] } - } - return p - } - - function _tbrunframe(f, p, p0, p1) - { - return _tbframe((f ? f : "_trunframe_i0"), p, p0, p1) - } - - function _tbrunframex(f, p, p0, p1) - { - return _tbframex((f ? f : "_trunframe_i0"), p, p0, p1) - } - - function _tbrunpass(f, p, p0, p1) - { - return _tbpass((f ? f : "_trunframe_i0"), p, p0, p1) - } - - function _tbrunpassx(f, p, p0, p1) - { - return _tbpassx((f ? f : "_trunframe_i0"), p, p0, p1) - } - - function _tdel(p, i) - { - if (p in _) { - _texclude(p) - for (i in _ptr[p]) { - if (isarray(_ptr[p][i])) { - _tdel_i1(_ptr[p][i]) - } else if (i = _ptr[p][i]) { - _tdel(i) - } - } - if (p in _tFCHLD) { - i = _tFCHLD[p] - do { - i = ((i in _tNEXT ? _tNEXT[i] : "")) _tdel_i0(i) - } while (i) + } else if (p in _tPREV) { + if (p in _tNEXT) { + _tNEXT[_tPREV[f] = _tPREV[p]] = f = _tNEXT[p] + delete _tNEXT[p] + } else { + delete _tNEXT[_tPREV[p]] } - delete _[p] - _UIDSDEL[p] + delete _tPREV[p] + } else if (p in _tNEXT) { + delete _tPREV[_tNEXT[p]] + delete _tNEXT[p] } } - - function _tdel_i0(p, i) - { + return p +} + +#_________________________________________________________________ +function _tbrunframe(f, p, p0, p1) +{ + ################################### + return _tbframe((f ? f : "_trunframe_i0"), p, p0, p1) +} + +#_________________________________________________________________ +function _tbrunframex(f, p, p0, p1) +{ + ################################## + return _tbframex((f ? f : "_trunframe_i0"), p, p0, p1) +} + +#_________________________________________________________________ +function _tbrunpass(f, p, p0, p1) +{ + #################################### + return _tbpass((f ? f : "_trunframe_i0"), p, p0, p1) +} + +#_________________________________________________________________ +function _tbrunpassx(f, p, p0, p1) +{ + ################################### + return _tbpassx((f ? f : "_trunframe_i0"), p, p0, p1) +} + +#_____________________________________________________________________________ +function _tdel(p, i) +{ + ########################################################## + if (p in _) { + _texclude(p) for (i in _ptr[p]) { if (isarray(_ptr[p][i])) { _tdel_i1(_ptr[p][i]) @@ -4607,1199 +5716,1434 @@ delete _[p] _UIDSDEL[p] } +} - function _tdel_i1(A, i) - { - for (i in A) { - if (isarray(A[i])) { - _tdel_i1(A[i]) - } else if (i = A[i]) { - _tdel(i) - } +#_____________________________________________________ +function _tdel_i0(p, i) +{ + for (i in _ptr[p]) { + if (isarray(_ptr[p][i])) { + _tdel_i1(_ptr[p][i]) + } else if (i = _ptr[p][i]) { + _tdel(i) } } - - function _tdelete(p, v) - { - if (p) { - _wLCHLD(_tDELPTR, p) - } - return v - } - - function _tdelitem(p) - { - if (p) { - if ("HOST" in _PTR[p] && "ITEMNAME" in _[p]) { - return _wLCHLD(_PTR[_PTR[p]["HOST"]]["ITEM"][_[p]["ITEMNAME"]], p) - } - _tdelete(p) - return p - } + if (p in _tFCHLD) { + i = _tFCHLD[p] + do { + i = ((i in _tNEXT ? _tNEXT[i] : "")) _tdel_i0(i) + } while (i) + } + delete _[p] + _UIDSDEL[p] +} + +#_____________________________________________________ +function _tdel_i1(A, i) +{ + for (i in A) { + if (isarray(A[i])) { + _tdel_i1(A[i]) + } else if (i = A[i]) { + _tdel(i) + } + } +} + +#_____________________________________________________________________________ +function _tdelete(p, v) +{ + ####################################################### # REMAKE EXCLUDE + if (p) { + _wLCHLD(_tDELPTR, p) + } + return v +} + +#_________________________________________________________________ +function _tdelitem(p) +{ + ############################################# + if (p) { + if ("HOST" in _PTR[p] && "ITEMNAME" in _[p]) { + return _wLCHLD(_PTR[_PTR[p]["HOST"]]["ITEM"][_[p]["ITEMNAME"]], p) + } + _tdelete(p) + return p } +} - function _tend(a, b) - { - if (b == "") { - return (_t_ENDF[_t_ENDF[0]] = a) - } else { - return (_t_ENDF[_t_ENDF[0] + a] = b) - } +#_______________________________________________________________________ +function _tend(a, b) +{ + ##################################################### + if (b == "") { + return (_t_ENDF[_t_ENDF[0]] = a) + } else { + return (_t_ENDF[_t_ENDF[0] + a] = b) } +} - function _texclude(p, v, pp) - { - if (p in _) { - if (p in _tPARENT) { - pp = _tPARENT[p] - delete _tPARENT[p] - if (p in _tPREV) { - if (p in _tNEXT) { - _tPREV[_tNEXT[v] = _tNEXT[p]] = v = _tPREV[p] - delete _tNEXT[p] - } else { - delete _tNEXT[_tLCHLD[pp] = _tPREV[p]] - } - delete _tPREV[p] - } else if (p in _tNEXT) { - delete _tPREV[_tFCHLD[pp] = _tNEXT[p]] - delete _tNEXT[p] - } else { - delete _tFCHLD[pp] - delete _tLCHLD[pp] - delete _tQCHLD[pp] - return p - } - --_tQCHLD[pp] - } else if (p in _tPREV) { +#_____________________________________________________________________________ +function _texclude(p, v, pp) +{ + ################################################### # TEST!!! + if (p in _) { + if (p in _tPARENT) { + pp = _tPARENT[p] + delete _tPARENT[p] + if (p in _tPREV) { if (p in _tNEXT) { _tPREV[_tNEXT[v] = _tNEXT[p]] = v = _tPREV[p] delete _tNEXT[p] } else { - delete _tNEXT[_tPREV[p]] + delete _tNEXT[_tLCHLD[pp] = _tPREV[p]] } delete _tPREV[p] } else if (p in _tNEXT) { - delete _tPREV[_tNEXT[p]] + delete _tPREV[_tFCHLD[pp] = _tNEXT[p]] delete _tNEXT[p] + } else { + delete _tFCHLD[pp] + delete _tLCHLD[pp] + delete _tQCHLD[pp] + return p } - return p - } - } - - function _tframe(fF, p, p0, p1, p2) - { - delete _t_ENDF[++_t_ENDF[0]] - p = (_isptr(p) ? (isarray(fF) ? _tframe_i1(fF, p, p0, p1, p2) : _tframe_i0(fF, p, p0, p1, p2)) : "") - --_t_ENDF[0] - return p - } - - function _tframe0(f, p, p0, p1, p2, p3, A) - { - if (_isptr(p)) { - if (isarray(f)) { - return _tframe0_i0(f, p) + --_tQCHLD[pp] + } else if (p in _tPREV) { + if (p in _tNEXT) { + _tPREV[_tNEXT[v] = _tNEXT[p]] = v = _tPREV[p] + delete _tNEXT[p] + } else { + delete _tNEXT[_tPREV[p]] } - _tframex_p0(A, f, 0) - return _th0(_tframe0_i0(A, p), --_TEND[_ARRLEN]) + delete _tPREV[p] + } else if (p in _tNEXT) { + delete _tPREV[_tNEXT[p]] + delete _tNEXT[p] } + return p } - - function _tframe0_i0(A, p, f) - { - if (p in _tLINK) { - _tframe_link = p - if ("`" in A) { - f = A["`"] - while (p in _tLINK) { - @f(p = _tLINK[p]) - } - } else { - while (p in _tLINK) { - p = _tLINK[p] - } +} + +# _tDLINK progressive development: concrete _tDLINK function\processing algo; all frame's families support +#_____________________________________________________________________________ +function _tframe(fF, p, p0, p1, p2) +{ + ############################################### + delete _t_ENDF[++_t_ENDF[0]] + p = (_isptr(p) ? (isarray(fF) ? _tframe_i1(fF, p, p0, p1, p2) : _tframe_i0(fF, p, p0, p1, p2)) : "") + --_t_ENDF[0] + return p +} + +#_____________________________________________________________________________ +function _tframe0(f, p, p0, p1, p2, p3, A) +{ + ######################################### + if (_isptr(p)) { + if (isarray(f)) { + return _tframe0_i0(f, p) + } + _tframex_p0(A, f, 0) + return _th0(_tframe0_i0(A, p), --_TEND[_ARRLEN]) + } +} + +#_______________________________________________ +function _tframe0_i0(A, p, f) +{ + if (p in _tLINK) { + _tframe_link = p + if ("`" in A) { + f = A["`"] + while (p in _tLINK) { + @f(p = _tLINK[p]) } } else { - _tframe_link = "" - } - if (p in _tFCHLD) { - return (_tframe0_i2(A, "^", p) _tframe0_i1(A, _tFCHLD[p])) - } - return _tframe0_i2(A, ".", p) - } - - function _tframe0_i1(A, p) - { - if (_TEND[_ARRLEN] in _TEND) { - return - } - if (p in _tNEXT) { - return (_tframe0_i0(A, p) _tframe0_i1(A, _tNEXT[p])) - } - return _tframe0_i0(A, p) - } - - function _tframe0_i2(A, m, p) - { - _tframe_dlink = p - while (p in _tDLINK) { - p = _tDLINK[p] - } - if (m in A) { - if (m "~" in A) { - if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { - return - } + while (p in _tLINK) { + p = _tLINK[p] } - m = A[m] - return @m(p) } + } else { + _tframe_link = "" } - - function _tframe1(f, p, p0, p1, p2, p3, A) - { - if (_isptr(p)) { - if (isarray(f)) { - return _tframe1_i0(f, p, p0) - } - _tframex_p0(A, f, 1) - return _th0(_tframe1_i0(A, p, p0), --_TEND[_ARRLEN]) - } + if (p in _tFCHLD) { + return (_tframe0_i2(A, "^", p) _tframe0_i1(A, _tFCHLD[p])) } + return _tframe0_i2(A, ".", p) +} - function _tframe1_i0(A, p, p0) - { - _tframe_link = p - while (p in _tLINK) { - p = _tLINK[p] - } - if (p in _tFCHLD) { - return (_tframe1_i2(A, "^", p, p0) _tframe1_i1(A, _tFCHLD[p], p0)) - } - return _tframe1_i2(A, ".", p, p0) +#_______________________________________________ +function _tframe0_i1(A, p) +{ + if (_TEND[_ARRLEN] in _TEND) { + return } - - function _tframe1_i1(A, p, p0) - { - if (_TEND[_ARRLEN] in _TEND) { - return - } - if (p in _tNEXT) { - return (_tframe1_i0(A, p, p0) _tframe1_i1(A, _tNEXT[p], p0)) - } - return _tframe1_i0(A, p, p0) + if (p in _tNEXT) { + return (_tframe0_i0(A, p) _tframe0_i1(A, _tNEXT[p])) } + return _tframe0_i0(A, p) +} - function _tframe1_i2(A, m, p, p0) - { - _tframe_dlink = p - while (p in _tDLINK) { - p = _tDLINK[p] - } - if (m in A) { - if (m "~" in A) { - if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { - return - } - } - m = A[m] - return @m(p, p0) - } +#_______________________________________________ +function _tframe0_i2(A, m, p) +{ + _tframe_dlink = p + while (p in _tDLINK) { + p = _tDLINK[p] } - - function _tframe2(f, p, p0, p1, p2, p3, A) - { - if (_isptr(p)) { - if (isarray(f)) { - return _tframe2_i0(f, p, p0, p1) + if (m in A) { + if (m "~" in A) { + if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { + return } - _tframex_p0(A, f, 2) - return _th0(_tframe2_i0(A, p, p0, p1), --_TEND[_ARRLEN]) } + m = A[m] + return @m(p) } +} - function _tframe2_i0(A, p, p0, p1) - { - _tframe_link = p - while (p in _tLINK) { - p = _tLINK[p] - } - if (p in _tFCHLD) { - return (_tframe2_i2(A, "^", p, p0, p1) _tframe2_i1(A, _tFCHLD[p], p0, p1)) +#_________________________________________________________________ +function _tframe1(f, p, p0, p1, p2, p3, A) +{ + ############################# + if (_isptr(p)) { + if (isarray(f)) { + return _tframe1_i0(f, p, p0) } - return _tframe2_i2(A, ".", p, p0, p1) + _tframex_p0(A, f, 1) + return _th0(_tframe1_i0(A, p, p0), --_TEND[_ARRLEN]) } +} - function _tframe2_i1(A, p, p0, p1) - { - if (_TEND[_ARRLEN] in _TEND) { - return - } - if (p in _tNEXT) { - return (_tframe2_i0(A, p, p0, p1) _tframe2_i1(A, _tNEXT[p], p0, p1)) - } - return _tframe2_i0(A, p, p0, p1) +#_______________________________________________ +function _tframe1_i0(A, p, p0) +{ + _tframe_link = p + while (p in _tLINK) { + p = _tLINK[p] } - - function _tframe2_i2(A, m, p, p0, p1) - { - _tframe_dlink = p - while (p in _tDLINK) { - p = _tDLINK[p] - } - if (m in A) { - if (m "~" in A) { - if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { - return - } - } - m = A[m] - return @m(p, p0, p1) - } + if (p in _tFCHLD) { + return (_tframe1_i2(A, "^", p, p0) _tframe1_i1(A, _tFCHLD[p], p0)) } + return _tframe1_i2(A, ".", p, p0) +} - function _tframe3(f, p, p0, p1, p2, p3, A) - { - if (_isptr(p)) { - if (isarray(f)) { - return _tframe3_i0(f, p, p0, p1, p2) - } - _tframex_p0(A, f, 3) - return _th0(_tframe3_i0(A, p, p0, p1, p2), --_TEND[_ARRLEN]) - } +#_______________________________________________ +function _tframe1_i1(A, p, p0) +{ + if (_TEND[_ARRLEN] in _TEND) { + return } - - function _tframe3_i0(A, p, p0, p1, p2) - { - _tframe_link = p - while (p in _tLINK) { - p = _tLINK[p] - } - if (p in _tFCHLD) { - return (_tframe3_i2(A, "^", p, p0, p1, p2) _tframe3_i1(A, _tFCHLD[p], p0, p1, p2)) - } - return _tframe3_i2(A, ".", p, p0, p1, p2) + if (p in _tNEXT) { + return (_tframe1_i0(A, p, p0) _tframe1_i1(A, _tNEXT[p], p0)) } + return _tframe1_i0(A, p, p0) +} - function _tframe3_i1(A, p, p0, p1, p2) - { - if (_TEND[_ARRLEN] in _TEND) { - return - } - if (p in _tNEXT) { - return (_tframe3_i0(A, p, p0, p1, p2) _tframe3_i1(A, _tNEXT[p], p0, p1, p2)) - } - return _tframe3_i0(A, p, p0, p1, p2) +#_______________________________________________ +function _tframe1_i2(A, m, p, p0) +{ + _tframe_dlink = p + while (p in _tDLINK) { + p = _tDLINK[p] } - - function _tframe3_i2(A, m, p, p0, p1, p2) - { - _tframe_dlink = p - while (p in _tDLINK) { - p = _tDLINK[p] - } - if (m in A) { - if (m "~" in A) { - if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { - return - } + if (m in A) { + if (m "~" in A) { + if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { + return } - m = A[m] - return @m(p, p0, p1, p2) } + m = A[m] + return @m(p, p0) } +} - function _tframe4(f, p, p0, p1, p2, p3, A) - { - if (_isptr(p)) { - if (isarray(f)) { - return _tframe4_i0(f, p, p0, p1, p2, p3) - } - _tframex_p0(A, f, 4) - return _th0(_tframe4_i0(A, p, p0, p1, p2, p3), --_TEND[_ARRLEN]) +#_________________________________________________________________ +function _tframe2(f, p, p0, p1, p2, p3, A) +{ + ############################# + if (_isptr(p)) { + if (isarray(f)) { + return _tframe2_i0(f, p, p0, p1) } + _tframex_p0(A, f, 2) + return _th0(_tframe2_i0(A, p, p0, p1), --_TEND[_ARRLEN]) } +} - function _tframe4_i0(A, p, p0, p1, p2, p3) - { - _tframe_link = p - while (p in _tLINK) { - p = _tLINK[p] - } - if (p in _tFCHLD) { - return (_tframe4_i2(A, "^", p, p0, p1, p2, p3) _tframe4_i1(A, _tFCHLD[p], p0, p1, p2, p3)) - } - return _tframe4_i2(A, ".", p, p0, p1, p2, p3) +#_______________________________________________ +function _tframe2_i0(A, p, p0, p1) +{ + _tframe_link = p + while (p in _tLINK) { + p = _tLINK[p] } - - function _tframe4_i1(A, p, p0, p1, p2, p3) - { - if (_TEND[_ARRLEN] in _TEND) { - return - } - if (p in _tNEXT) { - return (_tframe4_i0(A, p, p0, p1, p2, p3) _tframe4_i1(A, _tNEXT[p], p0, p1, p2, p3)) - } - return _tframe4_i0(A, p, p0, p1, p2, p3) + if (p in _tFCHLD) { + return (_tframe2_i2(A, "^", p, p0, p1) _tframe2_i1(A, _tFCHLD[p], p0, p1)) } + return _tframe2_i2(A, ".", p, p0, p1) +} - function _tframe4_i2(A, m, p, p0, p1, p2, p3) - { - _tframe_dlink = p - while (p in _tDLINK) { - p = _tDLINK[p] - } - if (m in A) { - if (m "~" in A) { - if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { - return - } - } - m = A[m] - return @m(p, p0, p1, p2, p3) - } +#_______________________________________________ +function _tframe2_i1(A, p, p0, p1) +{ + if (_TEND[_ARRLEN] in _TEND) { + return + } + if (p in _tNEXT) { + return (_tframe2_i0(A, p, p0, p1) _tframe2_i1(A, _tNEXT[p], p0, p1)) } + return _tframe2_i0(A, p, p0, p1) +} - function _tframe_i0(f, p, p0, p1, p2, a) - { - while (p in _tLINK) { - p = _tLINK[p] +#_______________________________________________ +function _tframe2_i2(A, m, p, p0, p1) +{ + _tframe_dlink = p + while (p in _tDLINK) { + p = _tDLINK[p] + } + if (m in A) { + if (m "~" in A) { + if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { + return + } } - return ((p in _tFCHLD ? _tmframe_i0(f, _tFCHLD[p], p0, p1, p2) : (p in _tDLINK ? @f(_tDLINK[p], p0, p1, p2) : @f(p, p0, p1, p2)))) + m = A[m] + return @m(p, p0, p1) } +} - function _tframe_i1(F, p, p0, p1, p2, a) - { - while (p in _tLINK) { - p = _tLINK[p] +#_________________________________________________________________ +function _tframe3(f, p, p0, p1, p2, p3, A) +{ + ############################# + if (_isptr(p)) { + if (isarray(f)) { + return _tframe3_i0(f, p, p0, p1, p2) } - return ((p in _tFCHLD ? (("." in F ? _th1(a = F["."], @a(p, p0, p1, p2)) : "")) _tmframe_i1(F, _tFCHLD[p], p0, p1, p2) : (">" in F ? _th1(a = F[">"], (p in _tDLINK ? @a(_tDLINK[p], p0, p1, p2) : @a(p, p0, p1, p2))) : ""))) + _tframex_p0(A, f, 3) + return _th0(_tframe3_i0(A, p, p0, p1, p2), --_TEND[_ARRLEN]) } +} - function _tframex(f, p, p0, p1) - { - delete _t_ENDF[++_t_ENDF[0]] - f = (p ? _tframex_i0(f, p, p0, p1) : "") - --_t_ENDF[0] - return f +#_______________________________________________ +function _tframe3_i0(A, p, p0, p1, p2) +{ + _tframe_link = p + while (p in _tLINK) { + p = _tLINK[p] } - - function _tframex_i0(f, p, p0, p1) - { - while (p in _tLINK) { - p = _tLINK[p] - } - return ((p in _tFCHLD ? _tmframex(f, _tFCHLD[p], p0, p1) : @f(p, p0, p1))) + if (p in _tFCHLD) { + return (_tframe3_i2(A, "^", p, p0, p1, p2) _tframe3_i1(A, _tFCHLD[p], p0, p1, p2)) } + return _tframe3_i2(A, ".", p, p0, p1, p2) +} - function _tframex_p0(A, f, q, i, B, C) - { - _tframe_qparam = q - delete _TEND[++_TEND[_ARRLEN]] - if (match(f, /\~(.*)$/, B)) { - A["^~"] = A[".~"] = B[1] - f = substr(f, 1, RSTART - 1) - } - A["."] = A["^"] = f +#_______________________________________________ +function _tframe3_i1(A, p, p0, p1, p2) +{ + if (_TEND[_ARRLEN] in _TEND) { return - q = split(f, B, /;/) - i = 0 - while (i < q) { - _tframex_p1(A, C[i]) - while (++i <= q) { - _tframex_p1(A, C[i], B[i]) - } - } } - - function _tframex_p1(A, v, i, r, B) - { - gsub(/[ \t]+/, "", v) - while (match(v, /^([^~]*)~\/(([^\/\\]*\\.)*[^\/\\]*)\//, B)) { - v = B[1] substr(v, RSTART + RLENGTH) - r = B[2] - } - if (i == "") { - if (v != "") { - A["."] = v - delete A["`"] - delete A["^"] - } - if (r != "") { - A[".~"] = A["`~"] = A["^~"] = r - } - } else if (match(v, /!/)) { - delete A[i] - } else { - A[i] = v - if (r != "") { - A[i "~"] = r - } - } + if (p in _tNEXT) { + return (_tframe3_i0(A, p, p0, p1, p2) _tframe3_i1(A, _tNEXT[p], p0, p1, p2)) } + return _tframe3_i0(A, p, p0, p1, p2) +} - function _tgenuid(c) - { - for (_uidcntr in _UIDARR1) { - delete _UIDARR1[_uidcntr] - for (c in _UIDARR0) { - _UIDS[_uidcntr c] - } - delete _UIDS[_uidcntr c] - return (_uidcntr c) - } - return _fatal("_tUID: Out of UID range") +#_______________________________________________ +function _tframe3_i2(A, m, p, p0, p1, p2) +{ + _tframe_dlink = p + while (p in _tDLINK) { + p = _tDLINK[p] } - - function _tgenuid_init(a, b, A) - { - _ptrlength = 4 - a = "\222\223\224\225\226\227\230\231\232" "\240\241\242\243\244\245\246\247" "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277" "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317" "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" - split(a, A, "") - for (a in A) { - for (b in A) { - _UIDARR0[A[a] A[b]] _UIDARR1[A[a] A[b]] + if (m in A) { + if (m "~" in A) { + if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { + return } } - _uidcntr = A[a] A[b] + m = A[m] + return @m(p, p0, p1, p2) } +} - function _tgetitem(p, n, a, b) - { - if (p) { - if (isarray(_PTR[p]["ITEM"]) && n in _PTR[p]["ITEM"]) { - a = _PTR[p]["ITEM"][n] - } else { - a = _PTR[p]["ITEM"][n] = _N() - } - if (! (b = _rFCHLD(a))) { - b = _wLCHLD(a, _N()) - _PTR[b]["HOST"] = p - _[b]["ITEMNAME"] = n - } - return b +#_________________________________________________________________ +function _tframe4(f, p, p0, p1, p2, p3, A) +{ + ############################# + if (_isptr(p)) { + if (isarray(f)) { + return _tframe4_i0(f, p, p0, p1, p2, p3) } + _tframex_p0(A, f, 4) + return _th0(_tframe4_i0(A, p, p0, p1, p2, p3), --_TEND[_ARRLEN]) } +} - function _tgetsp(p) - { - return _tSTACK[p][0] +#_______________________________________________ +function _tframe4_i0(A, p, p0, p1, p2, p3) +{ + _tframe_link = p + while (p in _tLINK) { + p = _tLINK[p] } - - function _th0(p, p1, p2, p3) - { - return p - } - - function _th1(p0, p, p2, p3) - { - return p + if (p in _tFCHLD) { + return (_tframe4_i2(A, "^", p, p0, p1, p2, p3) _tframe4_i1(A, _tFCHLD[p], p0, p1, p2, p3)) } + return _tframe4_i2(A, ".", p, p0, p1, p2, p3) +} - function _th10(p0, p1) - { - return (p1 p0) +#_______________________________________________ +function _tframe4_i1(A, p, p0, p1, p2, p3) +{ + if (_TEND[_ARRLEN] in _TEND) { + return } - - function _th2(p0, p1, r, p3) - { - return p + if (p in _tNEXT) { + return (_tframe4_i0(A, p, p0, p1, p2, p3) _tframe4_i1(A, _tNEXT[p], p0, p1, p2, p3)) } + return _tframe4_i0(A, p, p0, p1, p2, p3) +} - function _th3(p0, p1, p2, r) - { - return p +#_______________________________________________ +function _tframe4_i2(A, m, p, p0, p1, p2, p3) +{ + _tframe_dlink = p + while (p in _tDLINK) { + p = _tDLINK[p] } - - function _tifend(l) - { - return ((_t_ENDF[0] + l in _t_ENDF ? (_t_ENDF[_t_ENDF[0] + l] ? _t_ENDF[_t_ENDF[0] + l] : 1) : "")) - } - - function _tinit_i0(D, S, i) - { - for (i in S) { - if (isarray(S[i])) { - if (! isarray(D[i][""])) { - delete D[i] - D[i][""] - delete D[i][""] - } - _N_i0(D[i], S[i]) - } else { - if (isarray(D[i])) { - delete D[i] - } - D[i] = S[i] + if (m in A) { + if (m "~" in A) { + if (! (_TYPEWORD in _[p]) || A[m "~"] !~ _[p][_TYPEWORD]) { + return } } - } - - function _tlist(L, p, f) - { - _tlisti1 = _tlisti0 = L[_ARRLEN] + 0 - if (f == 0 && f == "") { - _tlist_i0(L, p) + m = A[m] + return @m(p, p0, p1, p2, p3) + } +} + +#___________________________________________________________ +function _tframe_i0(f, p, p0, p1, p2, a) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tFCHLD ? _tmframe_i0(f, _tFCHLD[p], p0, p1, p2) : (p in _tDLINK ? @f(_tDLINK[p], p0, p1, p2) : @f(p, p0, p1, p2)))) +} + +#___________________________________________________________ +function _tframe_i1(F, p, p0, p1, p2, a) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tFCHLD ? (("." in F ? _th1(a = F["."], @a(p, p0, p1, p2)) : "")) _tmframe_i1(F, _tFCHLD[p], p0, p1, p2) : (">" in F ? _th1(a = F[">"], (p in _tDLINK ? @a(_tDLINK[p], p0, p1, p2) : @a(p, p0, p1, p2))) : ""))) +} + +#_______________________________________________________________________ +function _tframex(f, p, p0, p1) +{ + ############################################ + delete _t_ENDF[++_t_ENDF[0]] + f = (p ? _tframex_i0(f, p, p0, p1) : "") + --_t_ENDF[0] + return f +} + +#___________________________________________________________ +function _tframex_i0(f, p, p0, p1) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tFCHLD ? _tmframex(f, _tFCHLD[p], p0, p1) : @f(p, p0, p1))) +} + +#_____________________________________________________ +function _tframex_p0(A, f, q, i, B, C) +{ + _tframe_qparam = q + delete _TEND[++_TEND[_ARRLEN]] + if (match(f, /\~(.*)$/, B)) { + A["^~"] = A[".~"] = B[1] + f = substr(f, 1, RSTART - 1) + } + A["."] = A["^"] = f + return + q = split(f, B, /;/) + i = 0 + while (i < q) { + _tframex_p1(A, C[i]) + while (++i <= q) { + _tframex_p1(A, C[i], B[i]) + } + } +} + +#_______________________________________________ +function _tframex_p1(A, v, i, r, B) +{ + gsub(/[ \t]+/, "", v) + while (match(v, /^([^~]*)~\/(([^\/\\]*\\.)*[^\/\\]*)\//, B)) { + v = B[1] substr(v, RSTART + RLENGTH) + r = B[2] + } + if (i == "") { + if (v != "") { + A["."] = v + delete A["`"] + delete A["^"] + } + if (r != "") { + A[".~"] = A["`~"] = A["^~"] = r + } + } else if (match(v, /!/)) { + delete A[i] + } else { + A[i] = v + if (r != "") { + A[i "~"] = r + } + } +} + +#_____________________________________________________ +# F v action +#----------------------------------------------------- +# - * no additional action +# A B delete A[p] and define A[p] as array; copy array B to array A[p] +# A - delete A[p] +# A "*" delete A[p]; A[p]="*" +# "*" B define _[p]["*"] as array; copy array B to array _[p]["*"] +# "*" - run _mpu program "*" for `p +# "*0" "*1" _[p]["*0"]="*1" +#___________________________________________________________ +function _tgenuid(c) +{ + for (_uidcntr in _UIDARR1) { + delete _UIDARR1[_uidcntr] + for (c in _UIDARR0) { + _UIDS[_uidcntr c] + } + delete _UIDS[_uidcntr c] + return (_uidcntr c) + } + return _fatal("_tUID: Out of UID range") +} + +#_____________________________________________________ +function _tgenuid_init(a, b, A) +{ + _ptrlength = 4 + a = "\222\223\224\225\226\227\230\231\232" "\240\241\242\243\244\245\246\247" "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277" "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317" "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" + split(a, A, "") + for (a in A) { + for (b in A) { + _UIDARR0[A[a] A[b]] _UIDARR1[A[a] A[b]] + } + } + _uidcntr = A[a] A[b] +} + +# if ( F in _TCLASS ) { _[p]["CLASS"]=_TCLASS[F]; _tapi(p); return p } +# # ??? _mpu(F,p) ??? +# return p } +# _[p][F]=v; return p } + +#_______________________________________________________________________ +function _tgetitem(p, n, a, b) +{ + ############################################ + if (p) { + if (isarray(_PTR[p]["ITEM"]) && n in _PTR[p]["ITEM"]) { + a = _PTR[p]["ITEM"][n] } else { - _tlistf0 = (f in _TAPI ? _TAPI[f] : f) - _tlist_i1(L, p) - } - return (_tlisti0 - _tlisti1) - } - - function _tlist_i0(L, p, q, i) - { - if (isarray(p)) { - q = p[_ARRLEN] - i = 0 - while (i++ < q) { - _tlist_i0(L, p[i]) - } - return - } - if (p in _) { - while (p in _tLINK) { - p = _tLINK[p] + a = _PTR[p]["ITEM"][n] = _N() + } + if (! (b = _rFCHLD(a))) { + b = _wLCHLD(a, _N()) + _PTR[b]["HOST"] = p + _[b]["ITEMNAME"] = n + } + return b + } +} + +#_________________________________________________________________ +function _tgetsp(p) +{ + ############################################### + return _tSTACK[p][0] +} + +#################################################################################### + +#_____________________________________________________________________________ +function _th0(p, p1, p2, p3) +{ + return p +} + +########################################## +function _th1(p0, p, p2, p3) +{ + #_________________________________________________________________ + return p +} + +############################## +function _th10(p0, p1) +{ + #_________________________________________________________________ + return (p1 p0) +} + +############################## +function _th2(p0, p1, r, p3) +{ + #_________________________________________________________________ + return p +} + +############################## +function _th3(p0, p1, p2, r) +{ + #_________________________________________________________________ + return p +} + +#_________________________________________________________________ +function _tifend(l) +{ + ############################################### + return ((_t_ENDF[0] + l in _t_ENDF ? (_t_ENDF[_t_ENDF[0] + l] ? _t_ENDF[_t_ENDF[0] + l] : 1) : "")) +} + +# test _tbrochld fn; develope tOBJ r\w func specification for brochld func + +#_________________________________________________________________ +function _tinit_i0(D, S, i) +{ + for (i in S) { + if (isarray(S[i])) { + if (! isarray(D[i][""])) { + delete D[i] + D[i][""] + delete D[i][""] } - L[++_tlisti0] = p - if (p in _tFCHLD) { - for (p = _tFCHLD[p]; p; p = (p in _tNEXT ? _tNEXT[p] : "")) { - _tlist_i0(L, p) - } + _N_i0(D[i], S[i]) + } else { + if (isarray(D[i])) { + delete D[i] } + D[i] = S[i] } } +} - function _tlist_i1(L, p) - { - if (isarray(p)) { - q = p[_ARRLEN] - i = 0 - while (i++ < q) { - _tlist_i1(L, p[i]) - } - return - } - if (p in _) { - while (p in _tLINK) { - p = _tLINK[p] - } - if (_tlistf0 in _[p]) { - L[++_tlisti0] = p - } - if (p in _tFCHLD) { - for (p = _tFCHLD[p]; p; p = (p in _tNEXT ? _tNEXT[p] : "")) { - _tlist_i1(L, p) - } - } - } - } +#_______________________________________________________________________ +######################################################################## - function _tmbframe(f, p, p0, p1, t) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - t = t _tbframe_i0(f, p, p0, p1, p = (p in _tPREV ? _tPREV[p] : "")) - } - return t - } - function _tmbframex(f, p, p0, p1, t) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - t = t _tbframex_i0(f, p, p0, p1) - p = (p in _tPREV ? _tPREV[p] : "") - } - return t - } - function _tmbpass(f, p, p0, p1) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - p0 = _tbpass_i0(f, p, p0, p1, p = (p in _tPREV ? _tPREV[p] : "")) - } - return p0 - } - function _tmbpassx(f, p, p0, p1) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - p0 = _tbpassx_i0(f, p, p0, p1) - p = (p in _tPREV ? _tPREV[p] : "") - } - return p0 - } - function _tmframe(f, p, p0, p1, p2) - { - delete _t_ENDF[++_t_ENDF[0]] - f = (p ? _tmframe_i0(f, p, p0, p1, p2) : "") - --_t_ENDF[0] - return f - } - function _tmframe_i0(f, p, p0, p1, p2, t) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - t = t _tframe_i0(f, p, p0, p1, p2, p = (p in _tNEXT ? _tNEXT[p] : "")) - } - return t - } - function _tmframe_i1(F, p, p0, p1, p2, t) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - t = t _tframe_i1(F, p, p0, p1, p2, p = (p in _tNEXT ? _tNEXT[p] : "")) - } - return t - } - function _tmframex(f, p, p0, p1, t) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - t = t _tframex_i0(f, p, p0, p1) - p = (p in _tNEXT ? _tNEXT[p] : "") - } - return t - } - function _tmpass(f, p, p0, p1) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - p0 = _tbpass_i0(f, p, p0, p1, p = (p in _tNEXT ? _tNEXT[p] : "")) - } - return p0 - } - function _tmpassx(f, p, p0, p1) - { - while (p && ! (_t_ENDF[0] in _t_ENDF)) { - p0 = _tbpassx_i0(f, p, p0, p1) - p = (p in _tNEXT ? _tNEXT[p] : "") - } - return p0 - } - function _torexp(r) - { - return _subseqon(_TOREXPB0, gensub(/(^[ \t]+)|(([ \t]*(\\)+)+[ \t]*)|([ \t]+$)/, "\\4", "G", _subseqoff(r, _TOREXPB0)), _TOREXPFN) - } - function _torexp_cmdstr(t) - { - return _strtorexp(gensub(/\^(.)/, "\\1", "G", t)) - } - function _torexp_fmask(t) - { - return gensub(/\\\*/, ".*", "G", gensub(/\\\?/, ".?", "G", _strtorexp(t))) - } - function _torexp_init() - { - _TOREXPFN[""] = "_strtorexp" - _TOREXPFN["~"] = "_torexp_rexp" - _TOREXPFN["="] = "_strtorexp" - _TOREXPFN[">"] = "_torexp_cmdstr" - _TOREXPFN["#"] = "_torexp_fmask" - _TOREXPFN["\""] = "_torexp_dqstr" - _TOREXPFN["'"] = "_torexp_sqstr" - } - function _torexp_rexp(t) - { - return t - } - function _tpass(f, p, p0, p1) - { - delete _t_ENDF[++_t_ENDF[0]] - f = (p ? _tpass_i0(f, p, p0, p1) : "") - --_t_ENDF[0] - return f - } - function _tpass_i0(f, p, p0, p1, a) - { - while (p in _tLINK) { - p = _tLINK[p] - } - return ((p in _tFCHLD ? _tmpass(f, _tFCHLD[p], p0, p1) : @f(p, p0, p1))) - } - function _tpassx(f, p, p0, p1) - { - delete _t_ENDF[++_t_ENDF[0]] - f = (p ? _tpassx_i0(f, p, p0, p1) : "") - --_t_ENDF[0] - return f - } - - function _tpassx_i0(f, p, p0, p1) - { - while (p in _tLINK) { - p = _tLINK[p] - } - return ((p in _tFCHLD ? _tmpassx(f, _tFCHLD[p], p0, p1) : @f(p, p0, p1))) - } - - function _tpop(p, aA, a) - { - if ((a = _tSTACK[p][0]) > 0) { - _tSTACK[p][0]-- - if (isarray(_tSTACK[p][a])) { - delete aA - _movarr(aA, _tSTACK[p][a]) - return - } - return _tSTACK[p][a] - } - _fatal("^" p ": Out of tSTACK") - } - - function _tpush(p, aA, a) - { - if (isarray(aA)) { - delete _tSTACK[p][a = ++_tSTACK[p][0]] - _tSTACK[p][a][""] - delete _tSTACK[p][a][""] - _movarr(_tSTACK[p][a], aA) - return - } - delete _tSTACK[p][a = ++_tSTACK[p][0]] - return (_tSTACK[p][a] = aA) - } - - function _tr(n, cs, H) - { - _rconline(n ": " cs) - _rconl() - if (match(cs, /^((([^\xB4:\[\|\]]*\xB4.)*[^\xB4:\[\|\]]*):)?((([^\xB4\[\|\]]*\xB4.)*[^\xB4\[\|\]]*)\[)?(([^\xB4\|\]]*\xB4.)*[^\xB4\|\]]*)?(\|(\.)?(([^\xB4\]]*\xB4.)*[^\xB4\]]*))?(\](.*))?$/, H)) { - _rconl("delptr: " _une(H[2]) "'") - _rconl("pfxstr: " _une(H[5]) "'") - _rconl("hichr: " _une(H[7]) "'") - _rconl("lochr: " _une((H[10] ? H[7] "' and " H[11] "'" : H[11] "'"))) - _rconl("sfxstr: " _une(H[14]) "'") - } else { - _rconl("NOT MATCH!") - } - _rconl() - } - - function _trace(t, d, A) - { - if (_ERRLOG_TF) { - A["TYPE"] = "TRACE" - A["TEXT"] = t - _log(A, d) - } - } - - function _trunframe(f, p, p0, p1, p2) - { - return _tframe((f ? f : "_trunframe_i0"), p, p0, p1, p2) - } - - function _trunframe_i0(p, p0, p1, p2, f) - { - if (p in _tFN) { - f = _tFN[p] - return @f(p, p0, p1, p2) - } - } - - function _trunframex(f, p, p0, p1) - { - return _tframex((f ? f : "_trunframe_i0"), p, p0, p1) - } - - function _trunpass(f, p, p0, p1) - { - return _tpass((f ? f : "_trunframe_i0"), p, p0, p1) - } - - function _trunpassx(f, p, p0, p1) - { - return _tpassx((f ? f : "_trunframe_i0"), p, p0, p1) - } - - function _tsetsp(p, v) - { - return (_tSTACK[p][0] = v) - } - - function _tstini() - { - _ini("uidel:pfx'hstr|lstr'sfx") - _ini("uidel:pfx'hstr|lstr'") - _ini("uidel:'hstr|lstr'sfx") - _ini("uidel:'hstr|lstr'") - _ini("uidel:pfx'hstr'sfx") - _ini("uidel:pfx'hstr'") - _ini("uidel:'hstr'sfx") - _ini("uidel:'hstr'") - _conl() - _conl("########################################################################################") - _conl() - _ini("pfx'hstr|lstr'sfx") - _ini("pfx'hstr|lstr'") - _ini("'hstr|lstr'sfx") - _ini("'hstr|lstr'") - _ini("pfx'hstr'sfx") - _ini("pfx'hstr'") - _ini("'hstr'sfx") - _ini("'hstr'") - _conl() - _conl("########################################################################################") - _conl() - _ini("uidel:pfx'`cntptr'sfx") - _ini("uidel:pfx'`cntptr'") - _ini("uidel:'`cntptr'sfx") - _ini("uidel:'`cntptr'") - _conl() - _conl("########################################################################################") - _conl() - _ini("pfx'`cntptr'sfx") - _ini("pfx'`cntptr'") - _ini("'`cntptr'sfx") - _ini("'`cntptr'") - _conl() - _conl("########################################################################################") - _conl() - _ini("uidel:pfx'^chrptr'sfx") - _ini("uidel:pfx'^chrptr'") - _ini("uidel:'^chrptr'sfx") - _ini("uidel:'^chrptr'") - _conl() - _conl("########################################################################################") - _conl() - _ini("pfx'^chrptr'sfx") - _ini("pfx'^chrptr'") - _ini("'^chrptr'sfx") - _ini("'^chrptr'") - _conl() - _conl("########################################################################################") - _conl() - } - function _tstv(p, A, r, f) - { - if (f == "") { - f = "tst_splitstr" - } - @f(_NOP, A, p) - @f(AA0, A, p) - @f(AB0, A, p) - @f(AC0, A, p) - @f("", A, p) - @f("a", A, p) - @f("\264a", A, p) - @f("\264", A, p) - @f("a\264\264\264,ba\264\264\264,", A, p) - @f("\264,", A, p) - @f(",", A, p) - @f("\264a,", A, p) - @f("ab,", A, p) - @f("ab,\264", A, p) - @f("\264a\264,,ba", A, p) - @f(",a,,b\264,c,,\264a,,\264,,,", A, p) - } - function _typ(p) - { - return (_t0 = (isarray(p) ? "#" : (p == 0 ? (p == "" ? 0 : (p in _CLASSPTR ? "`" : (p ? 3 : 4))) : (p in _CLASSPTR ? "`" : (p + 0 == p ? 5 : (p ? 3 : 2)))))) - } - function _typa(p, A) - { - return (_t0 = (isarray(p) ? "#" : (p == 0 ? (p == "" ? 0 : (p in A ? "`" : (p ? 3 : 4))) : (p in A ? "`" : (p + 0 == p ? 5 : (p ? 3 : 2)))))) - } - function _tzend(a, b) - { - if (b == 0 && b == "") { - return (_TEND[_TEND[_ARRLEN]] = a) - } else { - return (_TEND[_TEND[_ARRLEN] + a] = b) - } - } +#_______________________________________________________________________ +# _N(arr\str\mpuptr,val) \ _n(arr\str\mpuptr,val) +# This functions create new object and return ptr. +# _n() - creates object from list of deleted objects or if it's empty create new one, while _N() always create new one +# It is strongly recommended to use _N() for the objects that have some data outside of standart object arrays. Or - make routines +# that will clear outsided object data in case if object deleting. +# +# IN: arr\str\mpu,val - (both missed) just create obj and return ptr +# arr,val - create object and write arr[ptr]=val +# str,val - create object and write _[ptr][str]=val +# mpuptr - NOT ALLOWED (val missed) create object and run MPU-code specified by mpuptr with created object ptr as primary parameter +# MOD: - +# OUT: - +# RETURN: ptr - pointer to newly created object +#_________________________________________________________________ +# _tdel(ptr) +# This function exclude object from it's current structure and delete it. ptr can be later used by function: _n() for creating new object +# Also same story will occured with all chields and subchields of object specified by ptr. +# ??? What happened with linked py _ptr[ptr] objects ??? +# +# IN: ptr - pointer to object that will deleted +# MOD: - +# OUT: - +# RETURN: undefined +#_________________________________________________________________ +# _isptr(ptr) +# This function checks: is ptr is the object pointer that is currently exist? +# Unescaped remained data will be in data of src_dst_ptr. +# +# IN: ptr - string that will be tested +# MOD: - +# OUT: - +# RETURN: undefined - if ptr is not pointer to exist object +# ptr - if ptr is the pointer to exist object +#_________________________________________________________________ - function _uidcyc(p, i) - { - _dumpuidgen(p) - for (i = 1; i < 64 * 8 * 6 - 1; i++) { - _conl(i ":" _var(_getuid(p))) - } - _dumpuidgen(p) - } - function _une(t) - { - return gensub(/\xB4(.)/, "\\1", "G", t) - } - function _unformatrexp(t) - { - _formatstrq0 = split(t, _FORMATSTRA, /(\\[0-9]{1,3})|(\\x[[:xdigit:]]+)|(\\.)/, _FORMATSTRB) - _formatstrs0 = "" - for (t = 1; t < _formatstrq0; t++) { - _formatstrs0 = _formatstrs0 _FORMATSTRA[t] ((_FORMATSTRB[t] in _QESCHR ? _QESCREXP[_FORMATSTRB[t]] : _QESCREXP[toupper(substr(_FORMATSTRB[t], length(_FORMATSTRB[t]) - 1))])) - } - return (_formatstrs0 _FORMATSTRA[t]) - } - - function _unformatrexp_init(i, a) - { - _formatstrs0 = "\\^$.[]|()*+?{}-sSwW<>yB`'" - delete _FORMATSTRB - for (i = 0; i < 256; i++) { - _QESCREXP["\\" _CHR[i]] = (index(_formatstrs0, _CHR[i]) ? "\\" _CHR[i] : _CHR[i]) - } - for (i = 0; i < 256; i++) { - a = (index(_formatstrs0, _CHR[i]) ? "\\" : "") - _QESCREXP[sprintf("%.2X", i)] = a _CHR[i] - _QESCREXP["\\" sprintf("%.3o", i)] = a _CHR[i] - if (i < 8) { - _QESCREXP["\\" sprintf("%.1o", i)] = a _CHR[i] - } - if (i < 64) { - _QESCREXP["\\" sprintf("%.2o", i)] = a _CHR[i] - } - if (i < 16) { - _QESCREXP["\\x" sprintf("%.1X", i)] = _QESCREXP["\\x" sprintf("%.1x", i)] = a _CHR[i] - } - } - patsplit("a" 7 "b" 8 "f" 12 "n" 10 "r" 13 "t" 9 "v" 11, _FORMATSTRA, /[^0-9]/, _FORMATSTRB) - for (i in _FORMATSTRA) { - _QESCREXP["\\" _FORMATSTRA[i]] = _CHR[_FORMATSTRB[i] + 0] - } +#_________________________________________________________________ +# +# TO DESIGN: +# +# create basic objectapi interface support +# modify everywhere checking ptr not by `if ( ptr )...', but by `if ( ptr in _ )...' +# _TMP0, _TMP1 name change to something like _DATA name ??? +# think about redesigning routines for not depending if ptr is exist in tsysarrs: reason: performance\light code +function _tlist(L, p, f) +{ + _tlisti1 = _tlisti0 = L[_ARRLEN] + 0 + if (f == 0 && f == "") { + _tlist_i0(L, p) + } else { + _tlistf0 = (f in _TAPI ? _TAPI[f] : f) + _tlist_i1(L, p) } + return (_tlisti0 - _tlisti1) +} - function _unformatstr(t) - { - _formatstrq0 = split(t, _FORMATSTRA, /(\\[0-9]{1,3})|(\\x[[:xdigit:]]+)|(\\.)/, _FORMATSTRB) - _formatstrs0 = "" - for (t = 1; t < _formatstrq0; t++) { - _formatstrs0 = _formatstrs0 _FORMATSTRA[t] ((_FORMATSTRB[t] in _QESCHR ? _QESCHR[_FORMATSTRB[t]] : _QESCHR[toupper(substr(_FORMATSTRB[t], length(_FORMATSTRB[t]) - 1))])) +function _tlist_i0(L, p, q, i) +{ + if (isarray(p)) { + q = p[_ARRLEN] + i = 0 + while (i++ < q) { + _tlist_i0(L, p[i]) } - return (_formatstrs0 _FORMATSTRA[t]) + return } - - function _unformatstr_init(i) - { - for (i = 0; i < 256; i++) { - _QESCHR["\\" _CHR[i]] = _CHR[i] - } - for (i = 0; i < 256; i++) { - _QESCHR[sprintf("%.2X", i)] = _CHR[i] - _QESCHR["\\" sprintf("%.3o", i)] = _CHR[i] - if (i < 8) { - _QESCHR["\\" sprintf("%.1o", i)] = _CHR[i] - } - if (i < 64) { - _QESCHR["\\" sprintf("%.2o", i)] = _CHR[i] - } - if (i < 16) { - _QESCHR["\\x" sprintf("%.1X", i)] = _QESCHR["\\x" sprintf("%.1x", i)] = _CHR[i] - } - } - i = "a" 7 "b" 8 "f" 12 "n" 10 "r" 13 "t" 9 "v" 11 - patsplit(i, _FORMATSTRA, /[^0-9]/, _FORMATSTRB) - for (i in _FORMATSTRA) { - _QESCHR["\\" _FORMATSTRA[i]] = _CHR[_FORMATSTRB[i] + 0] + if (p in _) { + while (p in _tLINK) { + p = _tLINK[p] } - } - - function _uninit_del(A, i, p0) - { - _del(i) - } - - function _unstr(t) - { - return gensub(/\\(.)/, "\\1", "G", t) - } - - function _untmp(f, a) - { - if (f = filepath(f)) { - if (match(f, /\\$/)) { - _deletepfx(_FILEIO_RDTMP, a = toupper(f)) - _deletepfx(_FILEIO_RDNETMP, a) - } else { - delete _FILEIO_RDNETMP[toupper(f)] + L[++_tlisti0] = p + if (p in _tFCHLD) { + for (p = _tFCHLD[p]; p; p = (p in _tNEXT ? _tNEXT[p] : "")) { + _tlist_i0(L, p) } - return f } - return "" } +} - function _val(v, t) - { - if (isarray(v)) { - return (_dumparr(v) _ln(t)) - } - if (v == 0 && v == "") { - return (_ln("- (ERRNO=" ERRNO ")") _ln(t)) +function _tlist_i1(L, p) +{ + if (isarray(p)) { + q = p[_ARRLEN] + i = 0 + while (i++ < q) { + _tlist_i1(L, p[i]) } - return (_ln(v "'") _ln(t)) + return } - - function _val0(v) - { - if (isarray(v)) { - return _dumparr(v) - } - if (v == 0 && v == "") { - return "-" + if (p in _) { + while (p in _tLINK) { + p = _tLINK[p] } - return ("\"" v "\"") - } - - function _var(v, t) - { - if (isarray(v)) { - return (_dumparr(v) _ln(t)) + if (_tlistf0 in _[p]) { + L[++_tlisti0] = p } - if (v == 0 && v == "") { - return (_ln("- (ERRNO=" ERRNO ")") _ln(t)) + if (p in _tFCHLD) { + for (p = _tFCHLD[p]; p; p = (p in _tNEXT ? _tNEXT[p] : "")) { + _tlist_i1(L, p) + } + } + } +} + +#_________________________________________________________________ +function _tmbframe(f, p, p0, p1, t) +{ + ################################## + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + t = t _tbframe_i0(f, p, p0, p1, p = (p in _tPREV ? _tPREV[p] : "")) + } + return t +} + +#_________________________________________________________________ +function _tmbframex(f, p, p0, p1, t) +{ + ################################# + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + t = t _tbframex_i0(f, p, p0, p1) + p = (p in _tPREV ? _tPREV[p] : "") + } + return t +} + +#_________________________________________________________________ +function _tmbpass(f, p, p0, p1) +{ + ###################################### + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + p0 = _tbpass_i0(f, p, p0, p1, p = (p in _tPREV ? _tPREV[p] : "")) + } + return p0 +} + +#_________________________________________________________________ +function _tmbpassx(f, p, p0, p1) +{ + ##################################### + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + p0 = _tbpassx_i0(f, p, p0, p1) + p = (p in _tPREV ? _tPREV[p] : "") + } + return p0 +} + +#_________________________________________________________________ +function _tmframe(f, p, p0, p1, p2) +{ + ################################### + delete _t_ENDF[++_t_ENDF[0]] + f = (p ? _tmframe_i0(f, p, p0, p1, p2) : "") + --_t_ENDF[0] + return f +} + +#___________________________________________________________ +function _tmframe_i0(f, p, p0, p1, p2, t) +{ + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + t = t _tframe_i0(f, p, p0, p1, p2, p = (p in _tNEXT ? _tNEXT[p] : "")) + } + return t +} + +#___________________________________________________________ +function _tmframe_i1(F, p, p0, p1, p2, t) +{ + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + t = t _tframe_i1(F, p, p0, p1, p2, p = (p in _tNEXT ? _tNEXT[p] : "")) + } + return t +} + +#_________________________________________________________________ +function _tmframex(f, p, p0, p1, t) +{ + ################################## + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + t = t _tframex_i0(f, p, p0, p1) + p = (p in _tNEXT ? _tNEXT[p] : "") + } + return t +} + +#_________________________________________________________________ +function _tmpass(f, p, p0, p1) +{ + ####################################### + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + p0 = _tbpass_i0(f, p, p0, p1, p = (p in _tNEXT ? _tNEXT[p] : "")) + } + return p0 +} + +#_________________________________________________________________ +function _tmpassx(f, p, p0, p1) +{ + ###################################### + while (p && ! (_t_ENDF[0] in _t_ENDF)) { + p0 = _tbpassx_i0(f, p, p0, p1) + p = (p in _tNEXT ? _tNEXT[p] : "") + } + return p0 +} + +function _torexp(r) +{ + return _subseqon(_TOREXPB0, gensub(/(^[ \t]+)|(([ \t]*(\\)+)+[ \t]*)|([ \t]+$)/, "\\4", "G", _subseqoff(r, _TOREXPB0)), _TOREXPFN) +} + +function _torexp_cmdstr(t) +{ + return _strtorexp(gensub(/\^(.)/, "\\1", "G", t)) +} + +function _torexp_fmask(t) +{ + return gensub(/\\\*/, ".*", "G", gensub(/\\\?/, ".?", "G", _strtorexp(t))) +} + +#_______________________________________________ +function _torexp_init() +{ + _TOREXPFN[""] = "_strtorexp" + _TOREXPFN["~"] = "_torexp_rexp" + _TOREXPFN["="] = "_strtorexp" + _TOREXPFN[">"] = "_torexp_cmdstr" + _TOREXPFN["#"] = "_torexp_fmask" + _TOREXPFN["\""] = "_torexp_dqstr" + _TOREXPFN["'"] = "_torexp_sqstr" +} + +#_______________________________________________ +function _torexp_rexp(t) +{ + return t +} + +#_____________________________________________________________________________ +function _tpass(f, p, p0, p1) +{ + #################################################### + delete _t_ENDF[++_t_ENDF[0]] + f = (p ? _tpass_i0(f, p, p0, p1) : "") + --_t_ENDF[0] + return f +} + +#___________________________________________________________ +function _tpass_i0(f, p, p0, p1, a) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tFCHLD ? _tmpass(f, _tFCHLD[p], p0, p1) : @f(p, p0, p1))) +} + +#_____________________________________________________________________________ +function _tpassx(f, p, p0, p1) +{ + ################################################### + delete _t_ENDF[++_t_ENDF[0]] + f = (p ? _tpassx_i0(f, p, p0, p1) : "") + --_t_ENDF[0] + return f +} + +#___________________________________________________________ +function _tpassx_i0(f, p, p0, p1) +{ + while (p in _tLINK) { + p = _tLINK[p] + } + return ((p in _tFCHLD ? _tmpassx(f, _tFCHLD[p], p0, p1) : @f(p, p0, p1))) +} + +#_________________________________________________________________ +function _tpop(p, aA, a) +{ + ########################################### + if ((a = _tSTACK[p][0]) > 0) { + _tSTACK[p][0]-- + if (isarray(_tSTACK[p][a])) { + delete aA + _movarr(aA, _tSTACK[p][a]) + return } - return (_ln(v "'") _ln(t)) + return _tSTACK[p][a] } + _fatal("^" p ": Out of tSTACK") +} - function _verb(t, d, A) - { - if (_ERRLOG_VF) { - A["TYPE"] = "VERB" - A["TEXT"] = t - _log(A, d) - } +#_____________________________________________________________________________ +function _tpush(p, aA, a) +{ + ###################################################### + if (isarray(aA)) { + delete _tSTACK[p][a = ++_tSTACK[p][0]] + _tSTACK[p][a][""] + delete _tSTACK[p][a][""] + _movarr(_tSTACK[p][a], aA) + return } - - function _wFBRO(p, v, a) - { - if (p) { - if (v) { - for (a = p; a in _tPARENT; ) { - if ((a = _tPARENT[a]) == v) { - return v - } - } - if (p in _tPARENT) { - p = _tPARENT[p] - if (v in _tNEXT) { - if (v in _tPREV) { - _tPREV[_tNEXT[a] = _tNEXT[v]] = a = _tPREV[v] - delete _tPREV[v] - if (v in _tPARENT) { - if (p == (a = _tPARENT[v])) { - return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[p]] = v) - } - --_tQCHLD[a] - } - } else if (v in _tPARENT) { - if (p == (a = _tPARENT[v])) { - return v - } - delete _tPREV[_tFCHLD[a] = _tNEXT[v]] - --_tQCHLD[a] - } else { - delete _tPREV[_tNEXT[v]] - } - ++_tQCHLD[p] - return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[_tPARENT[v] = p]] = v) - } else { - if (v in _tPREV) { - if (v in _tPARENT) { - delete _tNEXT[_tLCHLD[a = _tPARENT[v]] = _tPREV[v]] - if (p == a) { - delete _tPREV[v] - return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[p]] = v) - } - --_tQCHLD[a] - } else { - delete _tNEXT[_tPREV[v]] - } - delete _tPREV[v] - } else if (v in _tPARENT) { - if (p == (a = _tPARENT[v])) { - return v - } - delete _tFCHLD[a] - delete _tLCHLD[a] - delete _tQCHLD[a] - } - ++_tQCHLD[p] - return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[_tPARENT[v] = p]] = v) - } - } else { - while (p in _tPREV) { - p = _tPREV[p] - } - if (v in _tPREV) { - if (v in _tPARENT) { - --_tQCHLD[a = _tPARENT[v]] - delete _tPARENT[v] - if (v in _tNEXT) { - _tNEXT[_tPREV[a] = _tPREV[v]] = a = _tNEXT[v] - } else { - delete _tNEXT[_tLCHLD[a] = _tPREV[v]] - } - } else if (v in _tNEXT) { - _tNEXT[_tPREV[a] = _tPREV[v]] = a = _tNEXT[v] - } else { - delete _tNEXT[_tPREV[v]] - } - delete _tPREV[v] - } else { - if (p == v) { - return v - } - if (v in _tPARENT) { - if (v in _tNEXT) { - delete _tPREV[_tFCHLD[a = _tPARENT[v]] = _tNEXT[v]] - --_tQCHLD[a] - } else { - delete _tLCHLD[a = _tPARENT[v]] - delete _tFCHLD[a] - delete _tQCHLD[a] - } - delete _tPARENT[v] - } else if (v in _tNEXT) { - delete _tPREV[_tNEXT[v]] - } - } - return (_tPREV[_tNEXT[v] = p] = v) - } - } else { - if (v == 0) { - return v - } - return v - } + delete _tSTACK[p][a = ++_tSTACK[p][0]] + return (_tSTACK[p][a] = aA) +} + +# prefix - +# prichr - aware character `{', `^',`]' +# sechr - aware character `.' as the first char of sechr, and character `}' +# suffix - aware character `]' +# cntptr - aware character `]' +function _tr(n, cs, H) +{ + #_tuidinitcs[p]=cs + #2 uidel, 5 pfx, 7 hichr,11(10) lochr,14 suffix + _rconline(n ": " cs) + _rconl() + if (match(cs, /^((([^\xB4:\[\|\]]*\xB4.)*[^\xB4:\[\|\]]*):)?((([^\xB4\[\|\]]*\xB4.)*[^\xB4\[\|\]]*)\[)?(([^\xB4\|\]]*\xB4.)*[^\xB4\|\]]*)?(\|(\.)?(([^\xB4\]]*\xB4.)*[^\xB4\]]*))?(\](.*))?$/, H)) { + _rconl("delptr: " _une(H[2]) "'") + _rconl("pfxstr: " _une(H[5]) "'") + _rconl("hichr: " _une(H[7]) "'") + _rconl("lochr: " _une((H[10] ? H[7] "' and " H[11] "'" : H[11] "'"))) + _rconl("sfxstr: " _une(H[14]) "'") + } else { + _rconl("NOT MATCH!") + } + _rconl() +} + +#_______________________________________________________________________ +function _trace(t, d, A) +{ + ################################################# + if (_ERRLOG_TF) { + A["TYPE"] = "TRACE" + A["TEXT"] = t + _log(A, d) + } +} + +#_________________________________________________________________ +function _trunframe(f, p, p0, p1, p2) +{ + ################################# + return _tframe((f ? f : "_trunframe_i0"), p, p0, p1, p2) +} + +#_________________________________________________________________ +function _trunframe_i0(p, p0, p1, p2, f) +{ + if (p in _tFN) { + f = _tFN[p] + return @f(p, p0, p1, p2) + } +} + +#_________________________________________________________________ +function _trunframex(f, p, p0, p1) +{ + ################################### + return _tframex((f ? f : "_trunframe_i0"), p, p0, p1) +} + +#_________________________________________________________________ +function _trunpass(f, p, p0, p1) +{ + ##################################### + return _tpass((f ? f : "_trunframe_i0"), p, p0, p1) +} + +#_________________________________________________________________ +function _trunpassx(f, p, p0, p1) +{ + #################################### + return _tpassx((f ? f : "_trunframe_i0"), p, p0, p1) +} + +#_________________________________________________________________ +function _tsetsp(p, v) +{ + ############################################# + return (_tSTACK[p][0] = v) +} + +# dptr - morg ptr; in case if object deleted then _CLASSPTR[ptr] will be deleted(object is death), but +# _tUIDEL[_CLASSPTR[ptr]] will be created that object can be resurrected from morg +# dptr can be any string containing any characters except `:'. It's not verified +# pfx,sfx - uid prefix str, and uid suffix str; this strings specifies string that can be inserted before/after +# uid generated by uid generator: +# +# class uid: pfx uidgen sfx +# +# Both can be any string(including ""), and can contains any character with B4-escaping feature. +# Note: that this strings cannot contains "'" character: it's should be escaped by B4-escaper. +# hstr,lstr - this values configure uid-generator itself. ther is a 3 combinations regarding its: +# +# hstr lstr function +# +# `ptr * - specify pointer to external uid-generator +# All uids and chars will be generated by external uid-generator +# * ^ptr - class will have it's own uid generator using external character set +# str str - class will have it's own uid generator with it's own character set +# character set inmplemented in hstr(high-charset) and in lstr(low-charset) in 2 ways: +# 1) "AB" "AB01" - this mean that high-charset contain chars: `A' and `B' +# low-charset contains chars: `A', `B', `0', `1' +# +# 2) "Az,By" "Ax,Bw,0v,1u" - this mean that high-charset contain chars: `Az' and `By' +# low-charset contains chars: `Ax', `Bw', `0v', `1u' +# Note: both: hstr and lstr cannot contain char `,' directly, but it's can uses +# B4-escaper to escape any char including `,' + + + +# !!!! in case of using `,' in hstr/lstr - the escaped `,' will leads to interpretate hstr and lstr as divided by `,' +# if parameters error then i should be more specific about what error in parameters detected +# document _inituid(): parameters; document cs: uid initialization string format +# test with escape char +# adv hstr and lstr splitting? +# chk if hstr len==0 ? +# return _tclass & report error? +# _tapi thru function + +# additional syntax checking ??? +# implement syntax and uid srv in docs +# add _dumpuid() ???? +# make performance measurement +# protection against badchar list +# additional feature to specify _getuid() to not resurrect uid; and informative that uid was ressurected or not +# build _defclass fn + +# _tuidinitcs ???? +# _tuidchrh[p] +# _tuidchrl[p] +# _tuidchr[p] +# _tuidcnt[p] +# _tUIDPFX[p] +# _tUIDSFX[p] +# _tUIDEL +# _tUIDCNTH +# _tUIDCNTL +# _tUIDCHRL +# _tUIDCHRH + +# create default class basic `new' and `del' functions +function _tstini() +{ + _ini("uidel:pfx'hstr|lstr'sfx") + _ini("uidel:pfx'hstr|lstr'") + _ini("uidel:'hstr|lstr'sfx") + _ini("uidel:'hstr|lstr'") + _ini("uidel:pfx'hstr'sfx") + _ini("uidel:pfx'hstr'") + _ini("uidel:'hstr'sfx") + _ini("uidel:'hstr'") + _conl() + _conl("########################################################################################") + _conl() + _ini("pfx'hstr|lstr'sfx") + _ini("pfx'hstr|lstr'") + _ini("'hstr|lstr'sfx") + _ini("'hstr|lstr'") + _ini("pfx'hstr'sfx") + _ini("pfx'hstr'") + _ini("'hstr'sfx") + _ini("'hstr'") + _conl() + _conl("########################################################################################") + _conl() + _ini("uidel:pfx'`cntptr'sfx") + _ini("uidel:pfx'`cntptr'") + _ini("uidel:'`cntptr'sfx") + _ini("uidel:'`cntptr'") + _conl() + _conl("########################################################################################") + _conl() + _ini("pfx'`cntptr'sfx") + _ini("pfx'`cntptr'") + _ini("'`cntptr'sfx") + _ini("'`cntptr'") + _conl() + _conl("########################################################################################") + _conl() + _ini("uidel:pfx'^chrptr'sfx") + _ini("uidel:pfx'^chrptr'") + _ini("uidel:'^chrptr'sfx") + _ini("uidel:'^chrptr'") + _conl() + _conl("########################################################################################") + _conl() + _ini("pfx'^chrptr'sfx") + _ini("pfx'^chrptr'") + _ini("'^chrptr'sfx") + _ini("'^chrptr'") + _conl() + _conl("########################################################################################") + _conl() +} + +function _tstv(p, A, r, f) +{ + if (f == "") { + f = "tst_splitstr" + } + @f(_NOP, A, p) + @f(AA0, A, p) + @f(AB0, A, p) + @f(AC0, A, p) + @f("", A, p) + @f("a", A, p) + @f("\264a", A, p) + @f("\264", A, p) + @f("a\264\264\264,ba\264\264\264,", A, p) + @f("\264,", A, p) + @f(",", A, p) + @f("\264a,", A, p) + @f("ab,", A, p) + @f("ab,\264", A, p) + @f("\264a\264,,ba", A, p) + @f(",a,,b\264,c,,\264a,,\264,,,", A, p) +} + +function _typ(p) +{ + return (_t0 = (isarray(p) ? "#" : (p == 0 ? (p == "" ? 0 : (p in _CLASSPTR ? "`" : (p ? 3 : 4))) : (p in _CLASSPTR ? "`" : (p + 0 == p ? 5 : (p ? 3 : 2)))))) +} + +function _typa(p, A) +{ + return (_t0 = (isarray(p) ? "#" : (p == 0 ? (p == "" ? 0 : (p in A ? "`" : (p ? 3 : 4))) : (p in A ? "`" : (p + 0 == p ? 5 : (p ? 3 : 2)))))) +} + +#_____________________________________________________ +# _tframe0(hndstr,ptr) +# +# +# IN: +# MOD: +# OUT: +# RETURN: +# +# handler string: +# Handler-string divides to words. Word splitter is char ";" +# +# Note that handler-string processed left to right. This mean that next word(more rightly) will overwrite fields implemented before(leftmost). +# Note that if word-string contains more than one rexp-field then only last rexp-field(most rightly) will be applied. +#_______________________________________________ +# TO DESIGN: +# +# 0-4: complete design of tlink handler call +# 1-4: add new tlink handler call +# 1-4: add new run fn (changed rexp to different for each type: see _tframe0) +# +# hndstr: +# may be add rexp for each type of handler and also total rexp for all ??? ADDED (test) +# may be add separator char ";" ??? ADDED (test) +#_______________________________________________________________________ +function _tzend(a, b) +{ + ##################################################### + if (b == 0 && b == "") { + return (_TEND[_TEND[_ARRLEN]] = a) + } else { + return (_TEND[_TEND[_ARRLEN] + a] = b) + } +} + +function _uidcyc(p, i) +{ + _dumpuidgen(p) + for (i = 1; i < 64 * 8 * 6 - 1; i++) { + _conl(i ":" _var(_getuid(p))) + } + _dumpuidgen(p) +} + +function _une(t) +{ + return gensub(/\xB4(.)/, "\\1", "G", t) +} + +#___________________________________________________________________________________ +function _unformatrexp(t) +{ + _formatstrq0 = split(t, _FORMATSTRA, /(\\[0-9]{1,3})|(\\x[[:xdigit:]]+)|(\\.)/, _FORMATSTRB) + _formatstrs0 = "" + for (t = 1; t < _formatstrq0; t++) { + _formatstrs0 = _formatstrs0 _FORMATSTRA[t] ((_FORMATSTRB[t] in _QESCHR ? _QESCREXP[_FORMATSTRB[t]] : _QESCREXP[toupper(substr(_FORMATSTRB[t], length(_FORMATSTRB[t]) - 1))])) + } + return (_formatstrs0 _FORMATSTRA[t]) +} + +#___________________________________________________________ +function _unformatrexp_init(i, a) +{ + _formatstrs0 = "\\^$.[]|()*+?{}-sSwW<>yB`'" + delete _FORMATSTRB + for (i = 0; i < 256; i++) { + _QESCREXP["\\" _CHR[i]] = (index(_formatstrs0, _CHR[i]) ? "\\" _CHR[i] : _CHR[i]) + } + for (i = 0; i < 256; i++) { + a = (index(_formatstrs0, _CHR[i]) ? "\\" : "") + _QESCREXP[sprintf("%.2X", i)] = a _CHR[i] + _QESCREXP["\\" sprintf("%.3o", i)] = a _CHR[i] + if (i < 8) { + _QESCREXP["\\" sprintf("%.1o", i)] = a _CHR[i] + } + if (i < 64) { + _QESCREXP["\\" sprintf("%.2o", i)] = a _CHR[i] + } + if (i < 16) { + _QESCREXP["\\x" sprintf("%.1X", i)] = _QESCREXP["\\x" sprintf("%.1x", i)] = a _CHR[i] + } + } + patsplit("a" 7 "b" 8 "f" 12 "n" 10 "r" 13 "t" 9 "v" 11, _FORMATSTRA, /[^0-9]/, _FORMATSTRB) + for (i in _FORMATSTRA) { + _QESCREXP["\\" _FORMATSTRA[i]] = _CHR[_FORMATSTRB[i] + 0] + } +} + +#___________________________________________________________________________________ +function _unformatstr(t) +{ + _formatstrq0 = split(t, _FORMATSTRA, /(\\[0-9]{1,3})|(\\x[[:xdigit:]]+)|(\\.)/, _FORMATSTRB) + _formatstrs0 = "" + for (t = 1; t < _formatstrq0; t++) { + _formatstrs0 = _formatstrs0 _FORMATSTRA[t] ((_FORMATSTRB[t] in _QESCHR ? _QESCHR[_FORMATSTRB[t]] : _QESCHR[toupper(substr(_FORMATSTRB[t], length(_FORMATSTRB[t]) - 1))])) + } + return (_formatstrs0 _FORMATSTRA[t]) +} + +#___________________________________________________________ +function _unformatstr_init(i) +{ + for (i = 0; i < 256; i++) { + _QESCHR["\\" _CHR[i]] = _CHR[i] + } + for (i = 0; i < 256; i++) { + _QESCHR[sprintf("%.2X", i)] = _CHR[i] + _QESCHR["\\" sprintf("%.3o", i)] = _CHR[i] + if (i < 8) { + _QESCHR["\\" sprintf("%.1o", i)] = _CHR[i] + } + if (i < 64) { + _QESCHR["\\" sprintf("%.2o", i)] = _CHR[i] + } + if (i < 16) { + _QESCHR["\\x" sprintf("%.1X", i)] = _QESCHR["\\x" sprintf("%.1x", i)] = _CHR[i] + } + } + i = "a" 7 "b" 8 "f" 12 "n" 10 "r" 13 "t" 9 "v" 11 + patsplit(i, _FORMATSTRA, /[^0-9]/, _FORMATSTRB) + for (i in _FORMATSTRA) { + _QESCHR["\\" _FORMATSTRA[i]] = _CHR[_FORMATSTRB[i] + 0] + } +} + +#_____________________________________________________________________________ +function _uninit_del(A, i, p0) +{ + _del(i) +} + +#################################################################################### +# PUBLIC: +#_____________________________________________________________________________ +# var _SYS_STDOUT - (by default = "/dev/stdout") standart output pipe filename +# var _SYS_STDERR - (by default = "/dev/stderr") standart error output pipe filename +# var _SYS_STDCON - (by default = "CON") standart console output device +#_____________________________________________________________________________ +# var _CHR["CR"] - return cursor to the position 0 without newline(normally ="\x0D") +# var _CHR["EOL"] - return cursor to the position 0 & newline (MS:="\x0D\x0A" / UX:="\x0D") +# var _CON_WIDTH - console width(columns number) +#_____________________________________________________________________________ +# fn _cmd(c) - execute shell command c and return output +# fn _err - output string w\o any addition into _SYS_STDERR device +# fn _errnl - output string with addition _CHR["EOL"] at the end of the string into _SYS_STDERR device +# fn _out - output string w\o any addition into _SYS_STDOUT device +# fn _outnl - output string with addition _CHR["EOL"] at the end of the string into _SYS_STDOUT device +#_____________________________________________________________________________ +# fn _con(text[,tabspace]) +# fn _conl(text[,tabspace]) +# fn _conline(text[,tabspace]) +# fn _constat(status[,tabspace]) +# fn _constatpush([status[,tabspace]]) +# fn _constatpop() +#_______________________________________________________________________ +# var _constatstr +#################################################################################### +function _unstr(t) +{ + return gensub(/\\(.)/, "\\1", "G", t) +} + +#_________________________________________________________________ +function _untmp(f, a) +{ + ############################################# + if (f = filepath(f)) { + if (match(f, /\\$/)) { + _deletepfx(_FILEIO_RDTMP, a = toupper(f)) + _deletepfx(_FILEIO_RDNETMP, a) } else { - if (p == 0) { - return v - } - if (v) { - return _texclude(v) - } - return v + delete _FILEIO_RDNETMP[toupper(f)] } + return f } - - function _wFCHLD(p, v, a) - { - if (p) { - if (v) { - if (p == v) { + return "" +} + +#_____________________________________________________________________________ +function _val(v, t) +{ + if (isarray(v)) { + return (_dumparr(v) _ln(t)) + } + if (v == 0 && v == "") { + return (_ln("- (ERRNO=" ERRNO ")") _ln(t)) + } + return (_ln(v "'") _ln(t)) +} + +#_____________________________________________________________________________ +function _val0(v) +{ + if (isarray(v)) { + return _dumparr(v) + } + if (v == 0 && v == "") { + return "-" + } + return ("\"" v "\"") +} + +#_____________________________________________________________________________ +function _var(v, t) +{ + if (isarray(v)) { + return (_dumparr(v) _ln(t)) + } + if (v == 0 && v == "") { + return (_ln("- (ERRNO=" ERRNO ")") _ln(t)) + } + return (_ln(v "'") _ln(t)) +} + +#_______________________________________________________________________ +function _verb(t, d, A) +{ + ################################################## + if (_ERRLOG_VF) { + A["TYPE"] = "VERB" + A["TEXT"] = t + _log(A, d) + } +} + +#_________________________________________________________________ +function _wFBRO(p, v, a) +{ + ########################################### + if (p) { + if (v) { + for (a = p; a in _tPARENT; ) { + if ((a = _tPARENT[a]) == v) { return v } - for (a = p; a in _tPARENT; ) { - if ((a = _tPARENT[a]) == v) { - return v - } - } + } ######################## v is parentesis of p + if (p in _tPARENT) { + p = _tPARENT[p] if (v in _tNEXT) { if (v in _tPREV) { _tPREV[_tNEXT[a] = _tNEXT[v]] = a = _tPREV[v] @@ -5819,11 +7163,8 @@ } else { delete _tPREV[_tNEXT[v]] } - if (p in _tFCHLD) { - ++_tQCHLD[p] - return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[_tPARENT[v] = p]] = v) - } - delete _tNEXT[v] + ++_tQCHLD[p] + return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[_tPARENT[v] = p]] = v) } else { if (v in _tPREV) { if (v in _tPARENT) { @@ -5845,159 +7186,166 @@ delete _tLCHLD[a] delete _tQCHLD[a] } - if (p in _tFCHLD) { - ++_tQCHLD[p] - return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[_tPARENT[v] = p]] = v) - } + ++_tQCHLD[p] + return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[_tPARENT[v] = p]] = v) } - _tQCHLD[p] = 1 - return (_tFCHLD[_tPARENT[v] = p] = _tLCHLD[p] = v) } else { - if (v == 0) { - if (p in _tFCHLD) { - v = _tFCHLD[p] - delete _tFCHLD[p] - delete _tLCHLD[p] - delete _tQCHLD[p] - do { - delete _tPARENT[v] - } while (v in _tNEXT && (v = _tNEXT[v])) + while (p in _tPREV) { + p = _tPREV[p] + } + if (v in _tPREV) { + if (v in _tPARENT) { + --_tQCHLD[a = _tPARENT[v]] + delete _tPARENT[v] + if (v in _tNEXT) { + _tNEXT[_tPREV[a] = _tPREV[v]] = a = _tNEXT[v] + } else { + delete _tNEXT[_tLCHLD[a] = _tPREV[v]] + } + } else if (v in _tNEXT) { + _tNEXT[_tPREV[a] = _tPREV[v]] = a = _tNEXT[v] + } else { + delete _tNEXT[_tPREV[v]] + } + delete _tPREV[v] + } else { + if (p == v) { + return v + } + if (v in _tPARENT) { + if (v in _tNEXT) { + delete _tPREV[_tFCHLD[a = _tPARENT[v]] = _tNEXT[v]] + --_tQCHLD[a] + } else { + delete _tLCHLD[a = _tPARENT[v]] + delete _tFCHLD[a] + delete _tQCHLD[a] + } + delete _tPARENT[v] + } else if (v in _tNEXT) { + delete _tPREV[_tNEXT[v]] } } - return v + return (_tPREV[_tNEXT[v] = p] = v) } } else { - if (p == 0) { + if (v == 0) { return v - } + } ######################## p=ptr, v=0 return v } + } else { ######################## p=ptr, v="" + if (p == 0) { + return v ######################## p=0 + } + if (v) { + return _texclude(v) ######################## p="", v=ptr - exclude v + } + return v } +} - function _wLBRO(p, v, a) - { - if (p) { - if (v) { - for (a = p; a in _tPARENT; ) { - if ((a = _tPARENT[a]) == v) { - return v - } +#_________________________________________________________________ +function _wFCHLD(p, v, a) +{ + ########################################## + if (p) { + if (v) { + if (p == v) { + return v + } ######################## p=v=ptr + for (a = p; a in _tPARENT; ) { + if ((a = _tPARENT[a]) == v) { + return v } - if (p in _tPARENT) { - p = _tPARENT[p] - if (v in _tPREV) { - if (v in _tNEXT) { - _tNEXT[_tPREV[a] = _tPREV[v]] = a = _tNEXT[v] - delete _tNEXT[v] - if (v in _tPARENT) { - if (p == (a = _tPARENT[v])) { - return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[p]] = v) - } - --_tQCHLD[a] - } - } else if (v in _tPARENT) { - if (p == (a = _tPARENT[v])) { - return v - } - delete _tNEXT[_tLCHLD[a] = _tPREV[v]] - --_tQCHLD[a] - } else { - delete _tNEXT[_tPREV[v]] - } - ++_tQCHLD[p] - return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[_tPARENT[v] = p]] = v) - } else { - if (v in _tNEXT) { - if (v in _tPARENT) { - delete _tPREV[_tFCHLD[a = _tPARENT[v]] = _tNEXT[v]] - if (p == a) { - delete _tNEXT[v] - return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[p]] = v) - } - --_tQCHLD[a] - } else { - delete _tPREV[_tNEXT[v]] - } - delete _tNEXT[v] - } else if (v in _tPARENT) { - if (p == (a = _tPARENT[v])) { - return v - } - delete _tLCHLD[a] - delete _tFCHLD[a] - delete _tQCHLD[a] + } ######################## v is parentesis of p + if (v in _tNEXT) { + if (v in _tPREV) { + _tPREV[_tNEXT[a] = _tNEXT[v]] = a = _tPREV[v] + delete _tPREV[v] + if (v in _tPARENT) { + if (p == (a = _tPARENT[v])) { + return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[p]] = v) } - ++_tQCHLD[p] - return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[_tPARENT[v] = p]] = v) + --_tQCHLD[a] } - } else { - while (p in _tNEXT) { - p = _tNEXT[p] + } else if (v in _tPARENT) { + if (p == (a = _tPARENT[v])) { + return v } - if (v in _tNEXT) { - if (v in _tPARENT) { - --_tQCHLD[a = _tPARENT[v]] - delete _tPARENT[v] - if (v in _tPREV) { - _tPREV[_tNEXT[a] = _tNEXT[v]] = a = _tPREV[v] - } else { - delete _tPREV[_tFCHLD[a] = _tNEXT[v]] - } - } else if (v in _tPREV) { - _tPREV[_tNEXT[a] = _tNEXT[v]] = a = _tPREV[v] - } else { - delete _tPREV[_tNEXT[v]] + delete _tPREV[_tFCHLD[a] = _tNEXT[v]] + --_tQCHLD[a] + } else { + delete _tPREV[_tNEXT[v]] + } + if (p in _tFCHLD) { + ++_tQCHLD[p] + return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[_tPARENT[v] = p]] = v) + } + delete _tNEXT[v] + } else { + if (v in _tPREV) { + if (v in _tPARENT) { + delete _tNEXT[_tLCHLD[a = _tPARENT[v]] = _tPREV[v]] + if (p == a) { + delete _tPREV[v] + return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[p]] = v) } - delete _tNEXT[v] + --_tQCHLD[a] } else { - if (p == v) { - return v - } - if (v in _tPARENT) { - if (v in _tPREV) { - delete _tNEXT[_tLCHLD[a = _tPARENT[v]] = _tPREV[v]] - --_tQCHLD[a] - } else { - delete _tFCHLD[a = _tPARENT[v]] - delete _tLCHLD[a] - delete _tQCHLD[a] - } - delete _tPARENT[v] - } else if (v in _tPREV) { - delete _tNEXT[_tPREV[v]] - } + delete _tNEXT[_tPREV[v]] } - return (_tNEXT[_tPREV[v] = p] = v) + delete _tPREV[v] + } else if (v in _tPARENT) { + if (p == (a = _tPARENT[v])) { + return v + } + delete _tFCHLD[a] + delete _tLCHLD[a] + delete _tQCHLD[a] } - } else { - if (v == 0) { - return v + if (p in _tFCHLD) { + ++_tQCHLD[p] + return (_tFCHLD[p] = _tPREV[_tNEXT[v] = _tFCHLD[_tPARENT[v] = p]] = v) } - return v } + _tQCHLD[p] = 1 + return (_tFCHLD[_tPARENT[v] = p] = _tLCHLD[p] = v) } else { - if (p == 0) { - return v - } - if (v) { - return _texclude(v) + if (v == 0) { + if (p in _tFCHLD) { ######################## p=ptr, v=0 > delete all chld + v = _tFCHLD[p] + delete _tFCHLD[p] + delete _tLCHLD[p] + delete _tQCHLD[p] + do { + delete _tPARENT[v] + } while (v in _tNEXT && (v = _tNEXT[v])) + } } return v } + } else { ######################## p=ptr, v="" > ignore action + if (p == 0) { + return v ######################## p=0 + } + return v } +} - function _wLCHLD(p, v, a) - { - if (p) { - if (v) { - if (p == v) { +#_________________________________________________________________ +function _wLBRO(p, v, a) +{ + ########################################### + if (p) { + if (v) { + for (a = p; a in _tPARENT; ) { + if ((a = _tPARENT[a]) == v) { return v } - for (a = p; a in _tPARENT; ) { - if ((a = _tPARENT[a]) == v) { - return v - } - } + } ######################## v is parentesis of p + if (p in _tPARENT) { + p = _tPARENT[p] if (v in _tPREV) { if (v in _tNEXT) { _tNEXT[_tPREV[a] = _tPREV[v]] = a = _tNEXT[v] @@ -6017,11 +7365,8 @@ } else { delete _tNEXT[_tPREV[v]] } - if (p in _tLCHLD) { - ++_tQCHLD[p] - return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[_tPARENT[v] = p]] = v) - } - delete _tPREV[v] + ++_tQCHLD[p] + return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[_tPARENT[v] = p]] = v) } else { if (v in _tNEXT) { if (v in _tPARENT) { @@ -6043,588 +7388,759 @@ delete _tFCHLD[a] delete _tQCHLD[a] } - if (p in _tLCHLD) { - ++_tQCHLD[p] - return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[_tPARENT[v] = p]] = v) - } + ++_tQCHLD[p] + return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[_tPARENT[v] = p]] = v) } - _tQCHLD[p] = 1 - return (_tLCHLD[_tPARENT[v] = p] = _tFCHLD[p] = v) } else { - if (v == 0) { - if (p in _tFCHLD) { - v = _tFCHLD[p] - delete _tFCHLD[p] - delete _tLCHLD[p] - delete _tQCHLD[p] - do { - delete _tPARENT[v] - } while (v in _tNEXT && (v = _tNEXT[v])) + while (p in _tNEXT) { + p = _tNEXT[p] + } + if (v in _tNEXT) { + if (v in _tPARENT) { + --_tQCHLD[a = _tPARENT[v]] + delete _tPARENT[v] + if (v in _tPREV) { + _tPREV[_tNEXT[a] = _tNEXT[v]] = a = _tPREV[v] + } else { + delete _tPREV[_tFCHLD[a] = _tNEXT[v]] + } + } else if (v in _tPREV) { + _tPREV[_tNEXT[a] = _tNEXT[v]] = a = _tPREV[v] + } else { + delete _tPREV[_tNEXT[v]] + } + delete _tNEXT[v] + } else { + if (p == v) { + return v + } + if (v in _tPARENT) { + if (v in _tPREV) { + delete _tNEXT[_tLCHLD[a = _tPARENT[v]] = _tPREV[v]] + --_tQCHLD[a] + } else { + delete _tFCHLD[a = _tPARENT[v]] + delete _tLCHLD[a] + delete _tQCHLD[a] + } + delete _tPARENT[v] + } else if (v in _tPREV) { + delete _tNEXT[_tPREV[v]] } } - return v + return (_tNEXT[_tPREV[v] = p] = v) } } else { - if (p == 0) { + if (v == 0) { return v - } + } ######################## p=ptr, v=0 return v } + } else { ######################## p=ptr, v="" + if (p == 0) { + return v ######################## p=0 + } + if (v) { + return _texclude(v) ######################## p="", v=ptr - exclude v + } + return v } +} - function _wLINK(p, v) - { - return (_tLINK[p] = v) - } - - function _wNEXT(p, v, a, b) - { - if (p) { - if (v) { - if (p == v) { +#_________________________________________________________________ +function _wLCHLD(p, v, a) +{ + ########################################## + if (p) { + if (v) { + if (p == v) { + return v + } ######################## p=v=ptr + for (a = p; a in _tPARENT; ) { + if ((a = _tPARENT[a]) == v) { return v } - for (a = p; a in _tPARENT; ) { - if ((a = _tPARENT[a]) == v) { - return v + } ######################## v is parentesis of p + if (v in _tPREV) { + if (v in _tNEXT) { + _tNEXT[_tPREV[a] = _tPREV[v]] = a = _tNEXT[v] + delete _tNEXT[v] + if (v in _tPARENT) { + if (p == (a = _tPARENT[v])) { + return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[p]] = v) + } + --_tQCHLD[a] } - } - if (v in _tPREV) { - if (p == (a = _tPREV[v])) { + } else if (v in _tPARENT) { + if (p == (a = _tPARENT[v])) { return v } - if (v in _tNEXT) { - _tPREV[_tNEXT[a] = _tNEXT[v]] = a - if (v in _tPARENT) { - --_tQCHLD[_tPARENT[v]] - } - } else { - delete _tNEXT[a] - if (v in _tPARENT) { - _tLCHLD[b = _tPARENT[v]] = a - --_tQCHLD[b] - } - } - } else if (v in _tNEXT) { + delete _tNEXT[_tLCHLD[a] = _tPREV[v]] + --_tQCHLD[a] + } else { + delete _tNEXT[_tPREV[v]] + } + if (p in _tLCHLD) { + ++_tQCHLD[p] + return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[_tPARENT[v] = p]] = v) + } + delete _tPREV[v] + } else { + if (v in _tNEXT) { if (v in _tPARENT) { delete _tPREV[_tFCHLD[a = _tPARENT[v]] = _tNEXT[v]] + if (p == a) { + delete _tNEXT[v] + return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[p]] = v) + } --_tQCHLD[a] } else { delete _tPREV[_tNEXT[v]] } + delete _tNEXT[v] } else if (v in _tPARENT) { - delete _tFCHLD[a = _tPARENT[v]] + if (p == (a = _tPARENT[v])) { + return v + } delete _tLCHLD[a] + delete _tFCHLD[a] delete _tQCHLD[a] } - if (p in _tNEXT) { - _tPREV[_tNEXT[v] = _tNEXT[p]] = v - if (p in _tPARENT) { - ++_tQCHLD[_tPARENT[v] = _tPARENT[p]] - } else { + if (p in _tLCHLD) { + ++_tQCHLD[p] + return (_tLCHLD[p] = _tNEXT[_tPREV[v] = _tLCHLD[_tPARENT[v] = p]] = v) + } + } + _tQCHLD[p] = 1 + return (_tLCHLD[_tPARENT[v] = p] = _tFCHLD[p] = v) + } else { + if (v == 0) { + if (p in _tFCHLD) { ######################## p=ptr, v=0 > delete all chld + v = _tFCHLD[p] + delete _tFCHLD[p] + delete _tLCHLD[p] + delete _tQCHLD[p] + do { delete _tPARENT[v] + } while (v in _tNEXT && (v = _tNEXT[v])) + } + } + return v + } + } else { ######################## p=ptr, v="" > ignore action + if (p == 0) { + return v ######################## p=0 + } + return v + } +} + +#_________________________________________________________________ +function _wLINK(p, v) +{ + ############################################## + return (_tLINK[p] = v) +} + +#_________________________________________________________________ +function _wNEXT(p, v, a, b) +{ + ######################################### + if (p) { + if (v) { + if (p == v) { + return v + } ######################## p=v=ptr + for (a = p; a in _tPARENT; ) { + if ((a = _tPARENT[a]) == v) { + return v + } + } ######################## v is parentesis of p + if (v in _tPREV) { + if (p == (a = _tPREV[v])) { + return v + } + if (v in _tNEXT) { + _tPREV[_tNEXT[a] = _tNEXT[v]] = a + if (v in _tPARENT) { + --_tQCHLD[_tPARENT[v]] } } else { - delete _tNEXT[v] - if (p in _tPARENT) { - ++_tQCHLD[_tPARENT[_tLCHLD[a] = v] = a = _tPARENT[p]] - } else { - delete _tPARENT[v] + delete _tNEXT[a] + if (v in _tPARENT) { + _tLCHLD[b = _tPARENT[v]] = a + --_tQCHLD[b] } } - return (_tNEXT[_tPREV[v] = p] = v) + } else if (v in _tNEXT) { + if (v in _tPARENT) { + delete _tPREV[_tFCHLD[a = _tPARENT[v]] = _tNEXT[v]] + --_tQCHLD[a] + } else { + delete _tPREV[_tNEXT[v]] + } + } else if (v in _tPARENT) { + delete _tFCHLD[a = _tPARENT[v]] + delete _tLCHLD[a] + delete _tQCHLD[a] + } + if (p in _tNEXT) { + _tPREV[_tNEXT[v] = _tNEXT[p]] = v + if (p in _tPARENT) { + ++_tQCHLD[_tPARENT[v] = _tPARENT[p]] + } else { + delete _tPARENT[v] + } } else { - if (v == 0) { - return v + delete _tNEXT[v] + if (p in _tPARENT) { + ++_tQCHLD[_tPARENT[_tLCHLD[a] = v] = a = _tPARENT[p]] + } else { + delete _tPARENT[v] } - return v } + return (_tNEXT[_tPREV[v] = p] = v) } else { - if (p == 0) { + if (v == 0) { return v - } - if (v) { - return _texclude(v) - } + } ######################## p=ptr, v=0 return v } - } - - function _wPARENT(p, v) - { + } else { ######################## p=ptr, v="" + if (p == 0) { + return v ######################## p=0 + } + if (v) { + return _texclude(v) ######################## p="", v=ptr - exclude v + } return v } - - function _wPREV(p, v, a, b) - { - if (p) { - if (v) { - if (p == v) { +} + +#_________________________________________________________________ +function _wPARENT(p, v) +{ + ############################################ + return v +} + +#_________________________________________________________________ +function _wPREV(p, v, a, b) +{ + ######################################### + if (p) { + if (v) { + if (p == v) { + return v + } ######################## p=v=ptr + for (a = p; a in _tPARENT; ) { + if ((a = _tPARENT[a]) == v) { return v } - for (a = p; a in _tPARENT; ) { - if ((a = _tPARENT[a]) == v) { - return v - } + } ######################## v is parentesis of p + if (v in _tNEXT) { + if (p == (a = _tNEXT[v])) { + return v } - if (v in _tNEXT) { - if (p == (a = _tNEXT[v])) { - return v - } - if (v in _tPREV) { - _tNEXT[_tPREV[a] = _tPREV[v]] = a - if (v in _tPARENT) { - --_tQCHLD[_tPARENT[v]] - } - } else { - delete _tPREV[a] - if (v in _tPARENT) { - _tFCHLD[b = _tPARENT[v]] = a - --_tQCHLD[b] - } + if (v in _tPREV) { + _tNEXT[_tPREV[a] = _tPREV[v]] = a + if (v in _tPARENT) { + --_tQCHLD[_tPARENT[v]] } - } else if (v in _tPREV) { + } else { + delete _tPREV[a] if (v in _tPARENT) { - delete _tNEXT[_tLCHLD[a = _tPARENT[v]] = _tPREV[v]] - --_tQCHLD[a] - } else { - delete _tNEXT[_tPREV[v]] + _tFCHLD[b = _tPARENT[v]] = a + --_tQCHLD[b] } - } else if (v in _tPARENT) { - delete _tLCHLD[a = _tPARENT[v]] - delete _tFCHLD[a] - delete _tQCHLD[a] } - if (p in _tPREV) { - _tNEXT[_tPREV[v] = _tPREV[p]] = v - if (p in _tPARENT) { - ++_tQCHLD[_tPARENT[v] = _tPARENT[p]] - } else { - delete _tPARENT[v] - } + } else if (v in _tPREV) { + if (v in _tPARENT) { + delete _tNEXT[_tLCHLD[a = _tPARENT[v]] = _tPREV[v]] + --_tQCHLD[a] } else { - delete _tPREV[v] - if (p in _tPARENT) { - ++_tQCHLD[_tPARENT[_tFCHLD[a] = v] = a = _tPARENT[p]] - } else { - delete _tPARENT[v] - } + delete _tNEXT[_tPREV[v]] + } + } else if (v in _tPARENT) { + delete _tLCHLD[a = _tPARENT[v]] + delete _tFCHLD[a] + delete _tQCHLD[a] + } + if (p in _tPREV) { + _tNEXT[_tPREV[v] = _tPREV[p]] = v + if (p in _tPARENT) { + ++_tQCHLD[_tPARENT[v] = _tPARENT[p]] + } else { + delete _tPARENT[v] } - return (_tPREV[_tNEXT[v] = p] = v) } else { - if (v == 0) { - return v + delete _tPREV[v] + if (p in _tPARENT) { + ++_tQCHLD[_tPARENT[_tFCHLD[a] = v] = a = _tPARENT[p]] + } else { + delete _tPARENT[v] } - return v } + return (_tPREV[_tNEXT[v] = p] = v) } else { - if (p == 0) { + if (v == 0) { return v - } - if (v) { - return _texclude(v) - } + } ######################## p=ptr, v=0 return v } - } - - function _wQBRO(p, v) - { + } else { ######################## p=ptr, v="" + if (p == 0) { + return v ######################## p=0 + } + if (v) { + return _texclude(v) ######################## p="", v=ptr - exclude v + } return v } - - function _wQCHLD(p, v) - { - if (p) { - if (v) { - } else { - if (v == 0) { - if (p in _tFCHLD) { - v = _tFCHLD[p] - delete _tFCHLD[p] - delete _tLCHLD[p] - delete _tQCHLD[p] - do { - delete _tPARENT[v] - } while (v in _tNEXT && (v = _tNEXT[v])) - } +} + +#_________________________________________________________________ +function _wQBRO(p, v) +{ + ############################################## + return v +} + +#_________________________________________________________________ +function _wQCHLD(p, v) +{ + ############################################# + if (p) { + if (v) { + } else { ######################## p=ptr, v=ptr + if (v == 0) { + if (p in _tFCHLD) { ######################## p=ptr, v=0 > delete all chld + v = _tFCHLD[p] + delete _tFCHLD[p] + delete _tLCHLD[p] + delete _tQCHLD[p] + do { + delete _tPARENT[v] + } while (v in _tNEXT && (v = _tNEXT[v])) } - return v - } - } else { - if (p == 0) { - return v } return v } + } else { ######################## p=ptr, v="" > ignore action + if (p == 0) { + return v + } ######################## p=0 + return v } +} - function _warning(t, d, A) - { - if (_ERRLOG_WF) { - A["TYPE"] = "WARNING" - A["TEXT"] = t - _log(A, d) - } +#_______________________________________________________________________ +function _warning(t, d, A) +{ + ############################################### + if (_ERRLOG_WF) { + A["TYPE"] = "WARNING" + A["TEXT"] = t + _log(A, d) } +} - function _wfilerdnehnd(f, t) - { - if ((f = _filerdne(f)) == "") { - return "" - } - if (! ((t = _filerd(f)) in _WFILEROOTDIR)) { - _cmd("md \"" t "\" 2>NUL") - _WFILEROOTDIR[t] - } - return f +#___________________________________________________________ +function _wfilerdnehnd(f, t) +{ + if ((f = _filerdne(f)) == "") { + return "" } - - function _wonl(t) - { - wonl = wonl _ln(t) + if (! ((t = _filerd(f)) in _WFILEROOTDIR)) { + _cmd("md \"" t "\" 2>NUL") + _WFILEROOTDIR[t] } + return f +} - function _wonline(t) - { - wonl = wonl _ln(substr(" _ " t " _____________________________________________________________________________________________________________________________________", 1, 126)) - } +function _wonl(t) +{ + wonl = wonl _ln(t) +} - function _wr_shortcut(f, S) - { - if (_shrtcutf0 = _filepath(f)) { - ERRNO = "" - _shrtcuta0 = _shortcut_fpath " /A:C /F:\"" _shrtcutf0 "\" 2>&1" - for (f in _SHORTCUTWSTRUC) { - if (f in S) { - _shrtcuta0 = _shrtcuta0 " " _SHORTCUTWSTRUC[f] "\"" (gensub(/(\\?)$/, "\\1\\1", 1, S[f])) "\"" - } - } - if (_shortcut_nerr(_cmd(_shrtcuta0), _shrtcutf0)) { - return - } - } - return ((ERRNO ? ERRNO = "write shortcut: " ERRNO : _NOP)) - } +function _wonline(t) +{ + wonl = wonl _ln(substr(" _ " t " _____________________________________________________________________________________________________________________________________", 1, 126)) +} - function _wrfile(f, d, a, b) - { - if ((f = _wfilerdnehnd(f)) == "" || _filene(f) == "") { - ERRNO = "Filename error" - return - } - a = BINMODE - BINMODE = "rw" - b = ORS - ORS = "" +#___________________________________________________________ +function _wr_shortcut(f, S) +{ + if (_shrtcutf0 = _filepath(f)) { ERRNO = "" - print(d) > f - if (ERRNO) { - return "" - } - close(f) - BINMODE = a - ORS = b - if (ERRNO) { - return "" + _shrtcuta0 = _shortcut_fpath " /A:C /F:\"" _shrtcutf0 "\" 2>&1" + for (f in _SHORTCUTWSTRUC) { + if (f in S) { + _shrtcuta0 = _shrtcuta0 " " _SHORTCUTWSTRUC[f] "\"" (gensub(/(\\?)$/, "\\1\\1", 1, S[f])) "\"" + } } - return f - } - - function _wrfile1(f, d, a, b) - { - if ((f = _wfilerdnehnd(f)) == "" || _filene(f) == "") { - ERRNO = "Filename error" + if (_shortcut_nerr(_cmd(_shrtcuta0), _shrtcutf0)) { return } - a = BINMODE - BINMODE = "rw" - b = ORS - ORS = "" - ERRNO = "" - print(d) > f - if (ERRNO) { - return "" - } - close(f) - BINMODE = a - ORS = b - if (ERRNO) { - return "" - } - return d } + return ((ERRNO ? ERRNO = "write shortcut: " ERRNO : _NOP)) +} - function _yexport(p) - { - return _tframe("_yexport_i0", p) +#_________________________________________________________________ +function _wrfile(f, d, a, b) +{ + ######################################### + if ((f = _wfilerdnehnd(f)) == "" || _filene(f) == "") { + ERRNO = "Filename error" + return } - - function _yexport_i0(p, p0, p1, p2) - { - if (p in _tLOG) { - return ("_ERRLOG: " _Zexparr(_tLOG[p]) "\n") - } - if (p in _tSTR) { - p = _tSTR[p] - gsub(/\x1B/, "\033;", p) - gsub(/\x0A/, "\033:", p) - return (p "\n") - } + a = BINMODE + BINMODE = "rw" + b = ORS + ORS = "" + ERRNO = "" + print(d) > f + if (ERRNO) { + return "" } - - function cmp_str_idx(i1, v1, i2, v2) - { - return ((i1 < i2 ? -1 : 1)) + close(f) + BINMODE = a + ORS = b + if (ERRNO) { + return "" } + return f +} - function filedi(f, d) - { - if ((f = filerdnehndi(f)) == "") { - return _FILEIO_D - } - if (f in _FILEDIRFL) { - return _FILEDIR[f] - } - if (f in _FILEROOT) { - if (d = filegetdrvdir(_FILEROOT[f])) { - _FILEDIRFL[f] - } - return (_FILEDIR[f] = d _FILEDIR[f]) - } - if ((_FILEIO_RD, f) in _FILEDIR) { - return _FILEDIR[_FILEIO_RD, f] - } - return (_FILEDIR[_FILEIO_RD, f] = _FILEIO_D _FILEDIR[f]) +#___________________________________________________________ +function _wrfile1(f, d, a, b) +{ + ################################## + if ((f = _wfilerdnehnd(f)) == "" || _filene(f) == "") { + ERRNO = "Filename error" + return } - - function filegetdrvdir(t, r) - { - if (t in _FILEDRV) { - return _FILEDRV[t] - } - if (match(r = _cmd("cd " t " 2>NUL"), /[^\x00-\x1F]+/)) { - r = gensub(/[ \t]*([\\\$\:])[ \t]*/, "\\1", "G", substr(r, RSTART, RLENGTH)) - gsub(/(^[ \t]*)|([ \t]*$)/, "", r) - if (match(r, /\:(.*)/)) { - return (_FILEDRV[tolower(t)] = _FILEDRV[toupper(t)] = substr(r, RSTART + 1) ((r ~ /\\$/ ? "" : "\\"))) - } - } + a = BINMODE + BINMODE = "rw" + b = ORS + ORS = "" + ERRNO = "" + print(d) > f + if (ERRNO) { return "" } - - function filegetrootdir(f, dd, d) - { - if (f in _FILEDIRFL) { - if (f in _FILEROOT) { - return (_FILEROOT[f] _FILEDIR[f]) - } - if ((dd = (dd ? dd : _FILEIO_RD), f) in _FILEROOT) { - return (_FILEROOT[dd, f] _FILEDIR[f]) - } - return ((_FILEROOT[dd, f] = fileri(dd)) _FILEDIR[f]) - } + close(f) + BINMODE = a + ORS = b + if (ERRNO) { + return "" + } + return d +} + +#_______________________________________________________________________ +function _yexport(p) +{ + ##################################################### + return _tframe("_yexport_i0", p) +} + +#_______________________________________________________________________ +function _yexport_i0(p, p0, p1, p2) +{ + if (p in _tLOG) { + return ("_ERRLOG: " _Zexparr(_tLOG[p]) "\n") + } + if (p in _tSTR) { + p = _tSTR[p] + gsub(/\x1B/, "\033;", p) + gsub(/\x0A/, "\033:", p) + return (p "\n") + } +} + +#_________________________________________________________________ +function cmp_str_idx(i1, v1, i2, v2) +{ + ############################## + return ((i1 < i2 ? -1 : 1)) +} + +#___________________________________________________________ +function filedi(f, d) +{ + if ((f = filerdnehndi(f)) == "") { + return _FILEIO_D + } + if (f in _FILEDIRFL) { + return _FILEDIR[f] + } + if (f in _FILEROOT) { + if (d = filegetdrvdir(_FILEROOT[f])) { + _FILEDIRFL[f] + } + return (_FILEDIR[f] = d _FILEDIR[f]) + } + if ((_FILEIO_RD, f) in _FILEDIR) { + return _FILEDIR[_FILEIO_RD, f] + } + return (_FILEDIR[_FILEIO_RD, f] = _FILEIO_D _FILEDIR[f]) +} + +#___________________________________________________________ +function filegetdrvdir(t, r) +{ + if (t in _FILEDRV) { + return _FILEDRV[t] + } + if (match(r = _cmd("cd " t " 2>NUL"), /[^\x00-\x1F]+/)) { + r = gensub(/[ \t]*([\\\$\:])[ \t]*/, "\\1", "G", substr(r, RSTART, RLENGTH)) + gsub(/(^[ \t]*)|([ \t]*$)/, "", r) + if (match(r, /\:(.*)/)) { + return (_FILEDRV[tolower(t)] = _FILEDRV[toupper(t)] = substr(r, RSTART + 1) ((r ~ /\\$/ ? "" : "\\"))) + } + } + return "" +} + +#___________________________________________________________ +function filegetrootdir(f, dd, d) +{ + if (f in _FILEDIRFL) { if (f in _FILEROOT) { - if (d = filegetdrvdir(_FILEROOT[f])) { - _FILEDIRFL[f] - return (_FILEROOT[f] (_FILEDIR[f] = d _FILEDIR[f])) - } else { - return (_FILEROOT[f] _FILEDIR[f]) - } + return (_FILEROOT[f] _FILEDIR[f]) } if ((dd = (dd ? dd : _FILEIO_RD), f) in _FILEROOT) { - if ((dd, f) in _FILEDIR) { - return (_FILEROOT[dd, f] _FILEDIR[dd, f]) - } - if ((d = filedi(dd) _FILEDIR[f]) ~ /^\\/) { - return (_FILEROOT[dd, f] (_FILEDIR[dd, f] = d)) - } - return (_FILEROOT[dd, f] d) + return (_FILEROOT[dd, f] _FILEDIR[f]) } + return ((_FILEROOT[dd, f] = fileri(dd)) _FILEDIR[f]) + } + if (f in _FILEROOT) { + if (d = filegetdrvdir(_FILEROOT[f])) { + _FILEDIRFL[f] + return (_FILEROOT[f] (_FILEDIR[f] = d _FILEDIR[f])) + } else { + return (_FILEROOT[f] _FILEDIR[f]) + } + } + if ((dd = (dd ? dd : _FILEIO_RD), f) in _FILEROOT) { if ((dd, f) in _FILEDIR) { - return ((_FILEROOT[dd, f] = fileri(dd)) _FILEDIR[dd, f]) + return (_FILEROOT[dd, f] _FILEDIR[dd, f]) } if ((d = filedi(dd) _FILEDIR[f]) ~ /^\\/) { - return ((_FILEROOT[dd, f] = fileri(dd)) (_FILEDIR[dd, f] = d)) + return (_FILEROOT[dd, f] (_FILEDIR[dd, f] = d)) } - return ((_FILEROOT[dd, f] = fileri(dd)) d) + return (_FILEROOT[dd, f] d) + } + if ((dd, f) in _FILEDIR) { + return ((_FILEROOT[dd, f] = fileri(dd)) _FILEDIR[dd, f]) } + if ((d = filedi(dd) _FILEDIR[f]) ~ /^\\/) { + return ((_FILEROOT[dd, f] = fileri(dd)) (_FILEDIR[dd, f] = d)) + } + return ((_FILEROOT[dd, f] = fileri(dd)) d) +} - function filerdnehndi(st, a, c, r, d, n, A) - { - if (st) { - if ((c = toupper(st)) in _FILECACHE) { - return _FILECACHE[c] - } - if (match(st, /^[ \t]*\\[ \t]*\\/)) { - if (match(substr(st, a = RLENGTH + 1), /^[ \t]*([0-9A-Za-z\-]+)[ \t]*(\\[ \t]*([A-Za-z])[ \t]*\$[ \t]*)?(\\[ \t]*([0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+( +[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+)*[ \t]*\\)*[ \t]*)?(([0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+( +[0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+)*)[ \t]*)?/, A)) { - a = a + RLENGTH - d = ((A[3] ? "\\" A[3] "$" : "")) "\\" A[5] - gsub(/[ \t]*\\[ \t]*/, "\\", d) - if ((st = toupper((r = "\\\\" A[1]) d (n = A[8]))) in _FILECACHE) { - return (_FILECACHE[substr(c, 1, a)] = _FILECACHE[st]) - } - _FILEDIR[c = _FILECACHE[substr(c, 1, a)] = _FILECACHE[st] = ++_file_rootcntr] = d - _FILEDIRFL[c] - _FILEROOT[c] = r - } else { - _filepath_err = "UNC" - return "" - } - } else { - match(st, /^(([ \t]*\.[ \t]*\\[ \t]*)|(([ \t]*([A-Za-z])[ \t]*(\:)[ \t]*)?([ \t]*(\\)[ \t]*)?))([ \t]*(([ \t]*[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+( +[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+)*[ \t]*\\)+)[ \t]*)?([ \t]*([0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+( +[0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+)*)[ \t]*)?/, A) - if (! RLENGTH) { - return "" - } - d = A[8] A[10] +#___________________________________________________________ +function filerdnehndi(st, a, c, r, d, n, A) +{ + if (st) { + if ((c = toupper(st)) in _FILECACHE) { + return _FILECACHE[c] + } + if (match(st, /^[ \t]*\\[ \t]*\\/)) { + if (match(substr(st, a = RLENGTH + 1), /^[ \t]*([0-9A-Za-z\-]+)[ \t]*(\\[ \t]*([A-Za-z])[ \t]*\$[ \t]*)?(\\[ \t]*([0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+( +[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+)*[ \t]*\\)*[ \t]*)?(([0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+( +[0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+)*)[ \t]*)?/, A)) { + a = a + RLENGTH + d = ((A[3] ? "\\" A[3] "$" : "")) "\\" A[5] gsub(/[ \t]*\\[ \t]*/, "\\", d) - if ((st = toupper((r = A[5] A[6]) d (n = A[14]))) in _FILECACHE) { - return (_FILECACHE[substr(c, 1, RLENGTH)] = _FILECACHE[st]) - } - _FILEDIR[c = _FILECACHE[substr(c, 1, RLENGTH)] = _FILECACHE[st] = ++_file_rootcntr] = d - if (A[8]) { - _FILEDIRFL[c] - } - if (r) { - _FILEROOT[c] = r + if ((st = toupper((r = "\\\\" A[1]) d (n = A[8]))) in _FILECACHE) { + return (_FILECACHE[substr(c, 1, a)] = _FILECACHE[st]) } + _FILEDIR[c = _FILECACHE[substr(c, 1, a)] = _FILECACHE[st] = ++_file_rootcntr] = d + _FILEDIRFL[c] + _FILEROOT[c] = r + } else { + _filepath_err = "UNC" + return "" } - if (n) { - if (match(n, /\.[^\.]*$/)) { - _FILEXT[c] = substr(n, RSTART) - _FILENAM[c] = substr(n, 1, RSTART - 1) - } else { - _FILENAM[c] = n - } + } else { + match(st, /^(([ \t]*\.[ \t]*\\[ \t]*)|(([ \t]*([A-Za-z])[ \t]*(\:)[ \t]*)?([ \t]*(\\)[ \t]*)?))([ \t]*(([ \t]*[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+( +[0-9A-Za-z_\!\+\-\[\]\(\)\{\}\~\.]+)*[ \t]*\\)+)[ \t]*)?([ \t]*([0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+( +[0-9A-Za-z_\!\+\.\~\-\[\]\{\}\(\)]+)*)[ \t]*)?/, A) + if (! RLENGTH) { + return "" + } + d = A[8] A[10] + gsub(/[ \t]*\\[ \t]*/, "\\", d) + if ((st = toupper((r = A[5] A[6]) d (n = A[14]))) in _FILECACHE) { + return (_FILECACHE[substr(c, 1, RLENGTH)] = _FILECACHE[st]) + } + _FILEDIR[c = _FILECACHE[substr(c, 1, RLENGTH)] = _FILECACHE[st] = ++_file_rootcntr] = d + if (A[8]) { + _FILEDIRFL[c] + } + if (r) { + _FILEROOT[c] = r } - return c - } - return "" - } - - function fileri(f) - { - if ((f = filerdnehndi(f)) == "") { - return _FILEIO_R - } - if (f in _FILEROOT) { - return _FILEROOT[f] - } - if ((_FILEIO_RD, f) in _FILEROOT) { - return _FILEROOT[_FILEIO_RD, f] } - return (_FILEROOT[_FILEIO_RD, f] = _FILEIO_R) - } - - function hujf(a, b, c) - { - _conl("hujf(" a "," b "," c ")") - } - - function ncmp_str_idx(i1, v1, i2, v2) - { - return ((i1 < i2 ? 1 : -1)) - } - - function test_cfg(p, z, AA0, a) - { - AA0[1] - _fclass = _cfguid(p = _getuid(_classys), _NOP, _NOP, _NOP, _NOP, _classys) - _conl() - _conline() - _conl() - _drawuid(p) - _fclass = _cfguid(p = _getuid(_classys), AA0, AA0, AA0, AA0, _classys) - _conl() - _conline() - _conl() - _drawuid(p) - a = _getuid(z = _fclass = _cfguid(p = _getuid(_classys), p, "<", ">", "ab", "cd")) - _conl("### " a "########") - _conline() - _conl() - _drawuid(p) - a = _getuid(_fclass = _cfguid(p = _getuid(_classys), z, 0, 0, _NOP, z)) - _conl("### " a "########") - _conline() - _conl() - _drawuid(p) - a = _getuid(_fclass = _cfguid(p = _getuid(_classys), z, "^", "$", z, _classys)) - _conl("### " a "########") - _conline() - _conl() - _drawuid(p) - _fclass = _cfguid(p = _getuid(_classys), "oblptr", "pfx", "sfx", "abcd") - _conl() - _conline() - _conl() - _drawuid(p) - _conl("```````````````````" z "'''''''''" ((_isptr(z) ? " ptr" : " not ptr"))) - _drawuid(z) - } - - function test_splitstr(A) - { - AA0[-1] = "huj" - AA0["A"] = "pizda" - AA0[1] = "zhopa" - delete AB0[AB0[""] = ""] - AC0[-1] = "HUJ" - AC0["A"] = "PIZDA" - AC0[1] = "ZHOPA" - _SPLITSTRB0["1"] - wonl = "" - _tstv(0, A, 0, "_tstv") - _conl(wonl) - _wrfile("wonl.out", wonl) - } - - function test_uid(p, i) - { - _fclass = _cfguid(p = _getuid(_classys), p, "pfx", "sfx", "abc") - _conl("_fclass uid: " _getuid(_fclass)) - _drawuid(_fclass) - _conl("_classys uid: " _getuid(_classys)) _drawuid(_classys) - for (i = 1; i < 81; i++) { - _conl(i ": " _getuid(_fclass)) - } - _drawuid(_fclass) - } - - function tst_splitstr(t, A, R, r) - { - delete A - A["not cleared"] - _wonl() - _wonline("_splitstr(" ((isarray(t) ? "ARR" ((length(t) > 0 ? "#" ((t[1] != "zhopa" ? "U" : "l")) : "")) : _val0(t))) ",A" ((isarray(R) ? ", ARR" ((length(R) > 0 ? "#" ((R[1] != "zhopa" ? "U" : "l")) : "")) : ", " _val0(R))) "):") - _wonl(_val0(r = _splitstr(t, A, R))) - _wonl("arrary A:") - _wonl(_dumparr(A)) - return r - } - - function tts(p, uidel, psfx, cnt, chr, p5, p6, p7, im) - { - im = " " - im = ".. .." - _conl("ret: " _qparam(im, p, uidel, psfx, cnt, chr, p5, p6, p7) "'") - _conl("mask: `" _qparamask "'") - } - - function zorr(A, i, r) - { - if (i in A) { - _conl("`" i "' in A") - } else { - _conl("`" i "' not in A") + if (n) { + if (match(n, /\.[^\.]*$/)) { + _FILEXT[c] = substr(n, RSTART) + _FILENAM[c] = substr(n, 1, RSTART - 1) + } else { + _FILENAM[c] = n + } } - r = A[i] == "" && A[i] == 0 - _conl("A[" i "] status is " r) - return - a = a + -a - _conl("``````````````" a "''''''''''''''''") - } - - function zzer() - { + return c } + return "" +} + +#_____________________________________________________ +function fileri(f) +{ + if ((f = filerdnehndi(f)) == "") { + return _FILEIO_R + } + if (f in _FILEROOT) { + return _FILEROOT[f] + } + if ((_FILEIO_RD, f) in _FILEROOT) { + return _FILEROOT[_FILEIO_RD, f] + } + return (_FILEROOT[_FILEIO_RD, f] = _FILEIO_R) +} + +function hujf(a, b, c) +{ + _conl("hujf(" a "," b "," c ")") +} + +#___________________________________________________________ +function ncmp_str_idx(i1, v1, i2, v2) +{ + ####################### + return ((i1 < i2 ? 1 : -1)) +} + +function test_cfg(p, z, AA0, a) +{ + AA0[1] + _fclass = _cfguid(p = _getuid(_classys), _NOP, _NOP, _NOP, _NOP, _classys) + _conl() + _conline() + _conl() + _drawuid(p) + _fclass = _cfguid(p = _getuid(_classys), AA0, AA0, AA0, AA0, _classys) + _conl() + _conline() + _conl() + _drawuid(p) + a = _getuid(z = _fclass = _cfguid(p = _getuid(_classys), p, "<", ">", "ab", "cd")) + _conl("### " a "########") + _conline() + _conl() + _drawuid(p) + a = _getuid(_fclass = _cfguid(p = _getuid(_classys), z, 0, 0, _NOP, z)) + _conl("### " a "########") + _conline() + _conl() + _drawuid(p) + a = _getuid(_fclass = _cfguid(p = _getuid(_classys), z, "^", "$", z, _classys)) + _conl("### " a "########") + _conline() + _conl() + _drawuid(p) + _fclass = _cfguid(p = _getuid(_classys), "oblptr", "pfx", "sfx", "abcd") + _conl() + _conline() + _conl() + _drawuid(p) + _conl("```````````````````" z "'''''''''" ((_isptr(z) ? " ptr" : " not ptr"))) + _drawuid(z) +} + +function test_splitstr(A) +{ + AA0[-1] = "huj" + AA0["A"] = "pizda" + AA0[1] = "zhopa" + delete AB0[AB0[""] = ""] + AC0[-1] = "HUJ" + AC0["A"] = "PIZDA" + AC0[1] = "ZHOPA" + _SPLITSTRB0["1"] + wonl = "" + _tstv(0, A, 0, "_tstv") + _conl(wonl) + _wrfile("wonl.out", wonl) +} + +function test_uid(p, i) +{ + #test_cfg() + #return + _fclass = _cfguid(p = _getuid(_classys), p, "pfx", "sfx", "abc") + #_fclass=_cfguid(p=_getuid(_classys),_NOP,_NOP,_NOP,"",_classys) + _conl("_fclass uid: " _getuid(_fclass)) + _drawuid(_fclass) + _conl("_classys uid: " _getuid(_classys)) _drawuid(_classys) + for (i = 1; i < 81; i++) { + _conl(i ": " _getuid(_fclass)) + } + _drawuid(_fclass) +} + +function tst_splitstr(t, A, R, r) +{ + delete A + A["not cleared"] + _wonl() + _wonline("_splitstr(" ((isarray(t) ? "ARR" ((length(t) > 0 ? "#" ((t[1] != "zhopa" ? "U" : "l")) : "")) : _val0(t))) ",A" ((isarray(R) ? ", ARR" ((length(R) > 0 ? "#" ((R[1] != "zhopa" ? "U" : "l")) : "")) : ", " _val0(R))) "):") + _wonl(_val0(r = _splitstr(t, A, R))) + _wonl("arrary A:") + _wonl(_dumparr(A)) + return r +} + +function tts(p, uidel, psfx, cnt, chr, p5, p6, p7, im) +{ + im = " " + im = ".. .." + _conl("ret: " _qparam(im, p, uidel, psfx, cnt, chr, p5, p6, p7) "'") + _conl("mask: `" _qparamask "'") +} + +# # - p is array +# ` - p is ptr detected in array _CLASSPTR(for _typ); or p is ptr detected in array A(for _typa) +# 0 - p is undefined + +# 2 - p is string=="" +# 3 - p is string!="" +# 4 - p is number 0 +# 5 - p is any number except 0(positive and negative) + +# str: _typ(p)+0 !_typ(p)+0 +# str/ptr _typ(p)>0 _typ(p)<1 +# str/arr "`">_typ(p0) && _t0 +# str/ptr/arr _typ(p) !_typ(p) +# ptr _typ(p)=="`" _typ(p)<"`" ? +# ptr/arr _typ(p)+0!=_t0 +# arr _typ(p)=="#" _typ(p)>"#" ? +function zorr(A, i, r) +{ + if (i in A) { + _conl("`" i "' in A") + } else { + _conl("`" i "' not in A") + } + r = A[i] == "" && A[i] == 0 + _conl("A[" i "] status is " r) + return + a = a + -a + _conl("``````````````" a "''''''''''''''''") +} + +#_____________________________________________________________________________ +function zzer() +{ + ################################################################ +} diff --git a/test/profile8.ok b/test/profile8.ok index 763c6fef..2b9c156f 100644 --- a/test/profile8.ok +++ b/test/profile8.ok @@ -1,23 +1,21 @@ - # Rule(s) - - { - if (0) { - } else { - } +{ + if (0) { + } else { } +} - { - while (0) { - } +{ + while (0) { } +} - { - do { - } while (0) - } +{ + do { + } while (0) +} - { - for (;;) { - } +{ + for (;;) { } +} diff --git a/test/profile9.awk b/test/profile9.awk new file mode 100644 index 00000000..16252cea --- /dev/null +++ b/test/profile9.awk @@ -0,0 +1,9 @@ +# Some +# header +# comments + +# Add up +{ sum += $1 } + +# Print sum +END { print sum } diff --git a/test/profile9.ok b/test/profile9.ok new file mode 100644 index 00000000..34f7a96b --- /dev/null +++ b/test/profile9.ok @@ -0,0 +1,14 @@ +# Some +# header +# comments + +# Add up +{ + sum += $1 +} + +# Print sum +END { + print sum +} + diff --git a/test/rand.ok b/test/rand.ok index 60432b95..1df4ba39 100644 --- a/test/rand.ok +++ b/test/rand.ok @@ -1 +1 @@ - 62 67 88 6 35 77 3 68 30 96 90 26 35 8 88 93 49 53 37 + 67 6 77 68 96 26 8 93 53 74 53 95 78 74 96 77 33 58 91 diff --git a/test/randtest.ok b/test/randtest.ok new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/randtest.ok diff --git a/test/randtest.sh b/test/randtest.sh new file mode 100755 index 00000000..b17fda73 --- /dev/null +++ b/test/randtest.sh @@ -0,0 +1,113 @@ +# THIS PURPOSELY DOES NOT HAVE A !# LINE !!!! +# +# Date: Mon, 9 Sep 2013 14:49:43 -0700 +# From: Bob Jewett <jewett@bill.scs.agilent.com> +# Message-Id: <201309092149.r89Lnh94010909@bill.scs.agilent.com> +# To: arnold@skeeve.com +# Subject: Re: [bug-gawk] Bug in random() in builtin.c +# +# Hi Arnold, +# +# Attached below is a script that tests gawk for this particular +# rand() problem. The pair-wise combinations show a strong +# autocorrelation for a delay of 31 pairs of rand() samples. +# +# The script prints out the measured autocorrelation for a record +# of NSAMPLES pairs. It also prints a fail message at the end if +# it fails. +# +# If you want to see the autocorrelation values, there is a print +# statement that if uncommented will save them to a file. +# +# Please let me know if the mailer screws up the transfer or +# if you have any questions about the test. +# +# Best regards, +# Bob +# +# -------------- test_pair_power_autocorrelation ----------------------- +# +#!/bin/ksh + +#GAWK=/bin/gawk + +# ADR: Get GAWK from the environment. +# Additional note: This wants ksh/bash for the use of $RANDOM below to +# seed the generator. However, shells that don't provide it won't be +# a problem since gawk will then seed the generator with the time of day, +# as srand() will be called without an argument. + +# large NSAMPLES and NRUNS will bring any correlation out of the noise better +NSAMPLES=1024; MAX_ALLOWED_SIGMA=5; NRUNS=50; + +$GAWK 'BEGIN{ + srand('$RANDOM'); + nsamples=('$NSAMPLES'); + max_allowed_sigma=('$MAX_ALLOWED_SIGMA'); + nruns=('$NRUNS'); + for(tau=0;tau<nsamples/2;tau++) corr[tau]=0; + + for(run=0;run<nruns;run++) { + sum=0; + + # Fill an array with a sequence of samples that are a + # function of pairs of rand() values. + + for(i=0;i<nsamples;i++) { + samp[i]=((rand()-0.5)*(rand()-0.5))^2; + sum=sum+samp[i]; + } + + # Subtract off the mean of the sequence: + + mean=sum/nsamples; + for(i=0;i<nsamples;i++) samp[i]=samp[i]-mean; + + # Calculate an autocorrelation function on the sequence. + # Because the values of rand() should be independent, there + # should be no peaks in the autocorrelation. + + for(tau=0;tau<nsamples/2;tau++) { + sum=0; + for(i=0;i<nsamples/2;i++) sum=sum+samp[i]*samp[i+tau]; + corr[tau]=corr[tau]+sum; + } + + } + # Normalize the autocorrelation to the tau=0 value. + + max_corr=corr[0]; + for(tau=0;tau<nsamples/2;tau++) corr[tau]=corr[tau]/max_corr; + + # OPTIONALLY Print out the autocorrelation values: + + # for(tau=0;tau<nsamples/2;tau++) print tau, corr[tau] > "pairpower_corr.data"; + + # Calculate the sigma for the non-zero tau values: + + power_sum=0; + + for(tau=1;tau<nsamples/2;tau++) power_sum=power_sum+(corr[tau])^2; + + sigma=sqrt(power_sum/(nsamples/2-1)); + + # See if any of the correlations exceed a reasonable number of sigma: + + passed=1; + for(tau=1;tau<nsamples/2;tau++) { + if ( abs(corr[tau])/sigma > max_allowed_sigma ) { + print "Tau=", tau ", Autocorr=", corr[tau]/sigma, "sigma"; + passed=0; + } + } + if(!passed) { + print "Test failed." + exit(1); + } + else exit (0); + } + +function abs(abs_input) { return(sqrt(abs_input^2)) ; } +' + +exit 0 diff --git a/test/rebuild.awk b/test/rebuild.awk new file mode 100644 index 00000000..7320f192 --- /dev/null +++ b/test/rebuild.awk @@ -0,0 +1,5 @@ +{ + $1 = "test" + print $0 + print typeof($2) +} diff --git a/test/rebuild.in b/test/rebuild.in new file mode 100644 index 00000000..b2901ea9 --- /dev/null +++ b/test/rebuild.in @@ -0,0 +1 @@ +a b diff --git a/test/rebuild.ok b/test/rebuild.ok new file mode 100644 index 00000000..29635279 --- /dev/null +++ b/test/rebuild.ok @@ -0,0 +1,2 @@ +test b +strnum diff --git a/test/shadowbuiltin.awk b/test/shadowbuiltin.awk new file mode 100644 index 00000000..3ae21725 --- /dev/null +++ b/test/shadowbuiltin.awk @@ -0,0 +1,10 @@ +function foo(gensub) +{ + print gensub + print lshift(1, 1) +} + +BEGIN { + x = 5 + foo(x) +} diff --git a/test/shadowbuiltin.ok b/test/shadowbuiltin.ok new file mode 100644 index 00000000..47586a86 --- /dev/null +++ b/test/shadowbuiltin.ok @@ -0,0 +1,2 @@ +5 +2 diff --git a/test/strnum2.awk b/test/strnum2.awk new file mode 100644 index 00000000..44931d5f --- /dev/null +++ b/test/strnum2.awk @@ -0,0 +1,18 @@ +BEGIN { + split(" 1.234 ", f, "|") # create a numeric string (strnum) value + OFMT = "%.1f" + CONVFMT = "%.2f" + + # Check whether a strnum is displayed the same way before and + # after force_number is called. Also, should numeric strings + # be formatted with OFMT and CONVFMT or show the original string value? + + print f[1] # OFMT + print (f[1] "") # CONVFMT + + # force conversion to NUMBER if it has not happened already + x = f[1]+0 + + print f[1] # OFMT + print (f[1] "") # CONVFMT +} diff --git a/test/strnum2.ok b/test/strnum2.ok new file mode 100644 index 00000000..63898bd4 --- /dev/null +++ b/test/strnum2.ok @@ -0,0 +1,4 @@ + 1.234 + 1.234 + 1.234 + 1.234 diff --git a/test/strtonum1.awk b/test/strtonum1.awk new file mode 100644 index 00000000..79d6ad13 --- /dev/null +++ b/test/strtonum1.awk @@ -0,0 +1,5 @@ +BEGIN { + x = "011" + print x+0 # trigger NUMCUR + print strtonum(x) +} diff --git a/test/strtonum1.ok b/test/strtonum1.ok new file mode 100644 index 00000000..48a9ed43 --- /dev/null +++ b/test/strtonum1.ok @@ -0,0 +1,2 @@ +11 +9 diff --git a/test/symtab6.ok b/test/symtab6.ok index 7de717a0..34c10636 100644 --- a/test/symtab6.ok +++ b/test/symtab6.ok @@ -9,7 +9,7 @@ FILENAME: "" FNR: 0 FPAT: "[^[:space:]]+" FS: " " -FUNCTAB: array, 41 elements +FUNCTAB: array, 42 elements IGNORECASE: 0 LINT: 0 NF: 0 diff --git a/test/symtab8.ok b/test/symtab8.ok index da29b585..0cf40fe9 100644 --- a/test/symtab8.ok +++ b/test/symtab8.ok @@ -9,7 +9,7 @@ FIELDWIDTHS: "" FNR: 1 FPAT: "[^[:space:]]+" FS: " " -FUNCTAB: array, 41 elements +FUNCTAB: array, 42 elements IGNORECASE: 0 LINT: 0 NF: 1 diff --git a/test/testext.ok b/test/testext.ok index a828ecb2..897a7336 100644 --- a/test/testext.ok +++ b/test/testext.ok @@ -23,6 +23,12 @@ var_test() returned 1, test_var = 42 test_errno() returned 1, ERRNO = No child processes +fubar = 9 +rumpus = -5 +uid matches 1 +api_major matches 1 +test_deferred returns 1 + length of test_array is 10, should be 10 test_array_size: incoming size is 10 test_array_size() returned 1, length is now 0 @@ -69,6 +75,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 diff --git a/test/typedregex1.awk b/test/typedregex1.awk new file mode 100644 index 00000000..f308a335 --- /dev/null +++ b/test/typedregex1.awk @@ -0,0 +1,296 @@ +# This file describes the semantics for hard regex constants +# As much as possible it's executable code so that it can be used +# (or split into) test cases for development and regression testing. + +function simple_tests( fbre, numresult, strresult) +{ + # usable as case value + switch ("foobaaar") { + case @/fo+ba+r/: + print "switch-case: ok" + break + default: + print "switch-case: fail" + break + } + + # usable with ~ and !~ + if ("foobaaar" ~ @/fo+ba+r/) + print "match ~: ok" + else + print "match ~: fail" + + if ("quasimoto" !~ @/fo+ba+r/) + print "match !~: ok" + else + print "match !~: fail" + + # assign to variable, use in match + fbre = @/fo+ba+r/ + if ("foobaaar" ~ fbre) + print "variable match ~: ok" + else + print "variable match ~: fail" + + if ("quasimoto" !~ fbre) + print "variable match !~: ok" + else + print "variable match !~: fail" + + # Use as numeric value, should be zero + numresult = fbre + 42 + if (numresult == 42) + print "variable as numeric value: ok" + else + print "variable as numeric value: fail" + + # Use as string value, should be string value of regexp text + strresult = "<" fbre ">" + if (strresult == "<fo+ba+r>") + print "variable as string value: ok" + else + print "variable as string value: fail", strresult + + # typeof should work + if (typeof(@/fo+ba+r/) == "regexp") + print "typeof constant: ok" + else + print "typeof constant: fail" + + if (typeof(fbre) == "regexp") + print "typeof variable: ok" + else + print "typeof variable: fail" + + # conversion to number, works. should it be fatal? + fbre++ + if (fbre == 1) + print "conversion to number: ok" + else + print "conversion to number: fail" + + if (typeof(fbre) == "number") + print "typeof variable after conversion: ok" + else + print "typeof variable after conversion: fail" +} + +function match_tests( fbre, fun) +{ + if (match("foobaaar", @/fo+ba+r/)) + print "match(constant): ok" + else + print "match(constant): fail" + + fbre = @/fo+ba+r/ + if (match("foobaaar", fbre)) + print "match(variable): ok" + else + print "match(variable): fail" + + fun = "match" + if (@fun("foobaaar", @/fo+ba+r/)) + print "match(constant) indirect: ok" + else + print "match(constant) indirect: fail" + + if (@fun("foobaaar", fbre)) + print "match(variable) indirect: ok" + else + print "match(variable) indirect: fail" +} + +function sub_tests( fbre, count, target, fun) +{ + target = "abc foobaar def foobar ghi" + count = sub(@/fo+ba+r/, "XX", target) + if (count == 1 && target == "abc XX def foobar ghi") + print "sub(constant): ok" + else + print "sub(constant): fail" + + fbre = @/fo+ba+r/ + target = "abc foobaar def foobar ghi" + count = sub(fbre, "XX", target) + if (count == 1 && target == "abc XX def foobar ghi") + print "sub(variable): ok" + else + print "sub(variable): fail" + + fun = "sub" + $0 = "abc foobaar def foobar ghi" + count = @fun(@/fo+ba+r/, "XX") + if (count == 1 && $0 == "abc XX def foobar ghi") + print "sub(constant) indirect: ok" + else + print "sub(constant) indirect: fail" + + $0 = "abc foobaar def foobar ghi" + count = @fun(fbre, "XX") + if (count == 1 && $0 == "abc XX def foobar ghi") + print "sub(variable) indirect: ok" + else + print "sub(variable) indirect: fail" +} + +function gsub_tests( fbre, count, target, fun) +{ + target = "abc foobaar def foobar ghi" + count = gsub(@/fo+ba+r/, "XX", target) + if (count == 2 && target == "abc XX def XX ghi") + print "gsub(constant): ok" + else + print "gsub(constant): fail" + + fbre = @/fo+ba+r/ + target = "abc foobaar def foobar ghi" + count = gsub(fbre, "XX", target) + if (count == 2 && target == "abc XX def XX ghi") + print "gsub(variable): ok" + else + print "gsub(variable): fail" + + fun = "gsub" + $0 = "abc foobaar def foobar ghi" + count = @fun(@/fo+ba+r/, "XX") + if (count == 2 && $0 == "abc XX def XX ghi") + print "gsub(constant) indirect: ok" + else + print "gsub(constant) indirect: fail" + + $0 = "abc foobaar def foobar ghi" + count = @fun(fbre, "XX") + if (count == 2 && $0 == "abc XX def XX ghi") + print "gsub(variable) indirect: ok" + else + print "gsub(variable) indirect: fail" +} + +function gensub_tests( fbre, result, target, fun) +{ + target = "abc foobaar def foobar ghi" + result = gensub(@/fo+ba+r/, "XX", "g", target) + if (result == "abc XX def XX ghi") + print "gensub(constant): ok" + else + print "gensub(constant): fail" + + fbre = @/fo+ba+r/ + target = "abc foobaar def foobar ghi" + result = gensub(fbre, "XX", "g", target) + if (result == "abc XX def XX ghi") + print "gensub(variable): ok" + else + print "gensub(variable): fail" + + fun = "gensub" + $0 = "abc foobaar def foobar ghi" + result = @fun(@/fo+ba+r/, "XX", "g") + if (result == "abc XX def XX ghi") + print "gensub(constant) indirect: ok" + else + print "gensub(constant) indirect: fail" + + $0 = "abc foobaar def foobar ghi" + result = @fun(fbre, "XX", "g") + if (result == "abc XX def XX ghi") + print "gensub(variable) indirect: ok" + else + print "gensub(variable) indirect: fail" + + result = @fun(@/fo+ba+r/, "XX", "g", target) + if (result == "abc XX def XX ghi") + print "gensub(constant) indirect 2: ok" + else + print "gensub(constant) indirect 2: fail" + + result = @fun(fbre, "XX", "g", target) + if (result == "abc XX def XX ghi") + print "gensub(variable) indirect 2: ok" + else + print "gensub(variable) indirect 2: fail" +} + +function split_tests( fbre, data, seps, fun, b1) +{ + delete data + delete seps + b1 = split("a:b:c:d", data, @/:/, seps) + if (b1 == 4 && data[1] == "a" && seps[1] == ":") + print "split(constant): ok" + else + print "split(constant): fail" + + delete data + delete seps + fbre = @/:/ + b1 = split("a:b:c:d", data, fbre, seps) + if (b1 == 4 && data[1] == "a" && seps[1] == ":") + print "split(variable): ok" + else + print "split(variable): fail" + + fun = "split" + delete data + delete seps + b1 = @fun("a:b:c:d", data, @/:/, seps) + if (b1 == 4 && data[1] == "a" && seps[1] == ":") + print "split(constant) indirect: ok" + else + print "split(constant) indirect: fail" + + delete data + delete seps + b1 = @fun("a:b:c:d", data, fbre, seps) + if (b1 == 4 && data[1] == "a" && seps[1] == ":") + print "split(variable) indirect: ok" + else + print "split(variable) indirect: fail" +} + +function patsplit_tests( fbre, data, seps, fun, b1) +{ + delete data + delete seps + b1 = patsplit("a:b:c:d", data, @/[a-z]+/, seps) + if (b1 == 4 && data[1] == "a" && seps[1] == ":") + print "patsplit(constant): ok" + else + print "patsplit(constant): fail" + + delete data + delete seps + fbre = @/[a-z]+/ + b1 = patsplit("a:b:c:d", data, fbre, seps) + if (b1 == 4 && data[1] == "a" && seps[1] == ":") + print "patsplit(variable): ok" + else + print "patsplit(variable): fail" + + fun = "patsplit" + delete data + delete seps + b1 = @fun("a:b:c:d", data, @/[a-z]+/, seps) + if (b1 == 4 && data[1] == "a" && seps[1] == ":") + print "patsplit(constant) indirect: ok" + else + print "patsplit(constant) indirect: fail" + + delete data + delete seps + b1 = @fun("a:b:c:d", data, fbre, seps) + if (b1 == 4 && data[1] == "a" && seps[1] == ":") + print "patsplit(variable) indirect: ok" + else + print "patsplit(variable) indirect: fail" +} + +BEGIN { + simple_tests() + match_tests() + sub_tests() + gsub_tests() + gensub_tests() + split_tests() + patsplit_tests() +} diff --git a/test/typedregex1.ok b/test/typedregex1.ok new file mode 100644 index 00000000..03ef7cfa --- /dev/null +++ b/test/typedregex1.ok @@ -0,0 +1,37 @@ +switch-case: ok +match ~: ok +match !~: ok +variable match ~: ok +variable match !~: ok +variable as numeric value: ok +variable as string value: ok +typeof constant: ok +typeof variable: ok +conversion to number: ok +typeof variable after conversion: ok +match(constant): ok +match(variable): ok +match(constant) indirect: ok +match(variable) indirect: ok +sub(constant): ok +sub(variable): ok +sub(constant) indirect: ok +sub(variable) indirect: ok +gsub(constant): ok +gsub(variable): ok +gsub(constant) indirect: ok +gsub(variable) indirect: ok +gensub(constant): ok +gensub(variable): ok +gensub(constant) indirect: ok +gensub(variable) indirect: ok +gensub(constant) indirect 2: ok +gensub(variable) indirect 2: ok +split(constant): ok +split(variable): ok +split(constant) indirect: ok +split(variable) indirect: ok +patsplit(constant): ok +patsplit(variable): ok +patsplit(constant) indirect: ok +patsplit(variable) indirect: ok diff --git a/test/typedregex2.awk b/test/typedregex2.awk new file mode 100644 index 00000000..e17df4be --- /dev/null +++ b/test/typedregex2.awk @@ -0,0 +1,11 @@ +BEGIN { + x = @/xxx/ + y = @/yyy/ + print typeof(x), typeof(y) + print x, y + + x++ + y = y "" + print typeof(x), typeof(y) + print x, y +} diff --git a/test/typedregex2.ok b/test/typedregex2.ok new file mode 100644 index 00000000..832ef551 --- /dev/null +++ b/test/typedregex2.ok @@ -0,0 +1,4 @@ +regexp regexp +xxx yyy +number string +1 yyy diff --git a/test/typedregex3.awk b/test/typedregex3.awk new file mode 100644 index 00000000..ee6bcb69 --- /dev/null +++ b/test/typedregex3.awk @@ -0,0 +1,11 @@ +BEGIN { + a[1] = @/abc/ + b[1][2][3] = @/xyz/ + print typeof(a[1]), typeof(b[1][2][3]) + print a[1], b[1][2][3] + + a[1]++ + b[1][2][3] "" + print typeof(a[1]), typeof(b[1][2][3]) + print a[1], b[1][2][3] +} diff --git a/test/typedregex3.ok b/test/typedregex3.ok new file mode 100644 index 00000000..9f8b881a --- /dev/null +++ b/test/typedregex3.ok @@ -0,0 +1,4 @@ +regexp regexp +abc xyz +number regexp +1 xyz diff --git a/test/typeof1.awk b/test/typeof1.awk new file mode 100644 index 00000000..c301030e --- /dev/null +++ b/test/typeof1.awk @@ -0,0 +1,9 @@ +BEGIN { + a = 5 ; print typeof(a) + print typeof(b) + print typeof(@/foo/) + c = "foo" ; print typeof(c) + d[1] = 1 ; print typeof(d), typeof(d[1]) + e = @/foo/ ; print typeof(e) + print typeof(@/bar/) +} diff --git a/test/typeof1.ok b/test/typeof1.ok new file mode 100644 index 00000000..132cc24e --- /dev/null +++ b/test/typeof1.ok @@ -0,0 +1,7 @@ +number +untyped +regexp +string +array number +regexp +regexp diff --git a/test/typeof2.awk b/test/typeof2.awk new file mode 100644 index 00000000..25da02e4 --- /dev/null +++ b/test/typeof2.awk @@ -0,0 +1,20 @@ +BEGIN { + print typeof(x) + x[1] = 3 + print typeof(x) +} + +function test1() { +} + +function test2(p) { + p[1] = 1 +} + +BEGIN { + print typeof(a) + test1(a) + print typeof(a) + test2(a) + print typeof(a) +} diff --git a/test/typeof2.ok b/test/typeof2.ok new file mode 100644 index 00000000..cc032a83 --- /dev/null +++ b/test/typeof2.ok @@ -0,0 +1,6 @@ +untyped +array +untyped +gawk: typeof2.awk:16: warning: function `test1' called with more arguments than declared +untyped +array diff --git a/test/typeof3.awk b/test/typeof3.awk new file mode 100644 index 00000000..d148f373 --- /dev/null +++ b/test/typeof3.awk @@ -0,0 +1,19 @@ +BEGIN { + x = @/xx/ + print typeof(x) + print x +} + +# this set may not really be needed for the test +BEGIN { + x = 4 + print typeof(@/xxx/) + print typeof(3) + print x +} + +BEGIN { + print typeof(x) + print typeof(a[1]) + a[1][2] # fatals on this +} diff --git a/test/typeof3.ok b/test/typeof3.ok new file mode 100644 index 00000000..a6cd6c4a --- /dev/null +++ b/test/typeof3.ok @@ -0,0 +1,9 @@ +regexp +xx +regexp +number +4 +number +unassigned +gawk: typeof3.awk:18: fatal: attempt to use scalar `a["1"]' as an array +EXIT CODE: 2 diff --git a/test/typeof4.awk b/test/typeof4.awk new file mode 100644 index 00000000..62c2905c --- /dev/null +++ b/test/typeof4.awk @@ -0,0 +1,13 @@ +BEGIN{ a["x"]["y"]["z"]="scalar" ; walk_array(a, "a")} +function walk_array(arr, name, i, r) +{ + for (i in arr) { + r = typeof(arr[i]) +# printf("typeof(%s[%s]) = %s\n", name, i, r) > "/dev/stderr" + if (r == "array") { + walk_array(arr[i], name "[" i "]") + } else { + printf "%s[%s] = %s\n", name, i, arr[i] + } + } +} diff --git a/test/typeof4.ok b/test/typeof4.ok new file mode 100644 index 00000000..fca0263d --- /dev/null +++ b/test/typeof4.ok @@ -0,0 +1 @@ +a[x][y][z] = scalar diff --git a/vms/ChangeLog b/vms/ChangeLog index 3a018787..510f61cd 100644 --- a/vms/ChangeLog +++ b/vms/ChangeLog @@ -88,6 +88,11 @@ * remove_old_gawk.com: Look for old gawk images that may have been installed in the wrong directory. +2015-07-02 John E. Malmberg <wb8tyw@qsl.net> + + * build_gawk_pcsi_desc.com: Update to support new VMS + producer of VSI. + 2015-05-19 Arnold D. Robbins <arnold@skeeve.com> * 4.1.3: Release tar ball made. |