diff options
189 files changed, 20632 insertions, 9895 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) @@ -16,6 +16,12 @@ * dfa.c: Sync with grep. +2016-08-15 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * int_array.c (is_integer): Fix merge of stable changes to remove + obsolete string formatting check that has been superseded by + the new standard_integer_string check. + 2016-08-14 Arnold D. Robbins <arnold@skeeve.com> * re.c (make_regexp): Only call dfasyntax if actually using @@ -42,6 +48,28 @@ force_number to parse the string, but this is disabled due to possible negative performance impact. +2016-08-03 Arnold D. Robbins <arnold@skeeve.com> + + Remove typed regexes until they can be done properly. + + * NEWS: Updated. + * awk.h (enum nodevals): Remove Node_typedregex. + (force_string, force_number): Remove check for Node_typedregex. + * awkgram.y (TYPED_REGEXP): Remove token. + (grammar): Remove productions related to typed regexps. + (yylex): Don't find a typed regex or return it. + (valinfo): Remove code for Node_typedregex. + * builtin.c (do_length, do_print, call_sub, call_match, + call_split_func, do_typeof): Remove code for Node_typedregex. + * debug.c (watchpoint_triggered, print_memory): Remove code + for Node_typedregex. + * eval.c (nodetypes, setup_frame): Remove code for Node_typedregex. + * interpret.h (r_interpret): Remove code for Node_typedregex. + * profile.c (pprint): Remove code for Node_typedregex. + (pp_strong_regex): Removed. + (pp_string_or_strong_regex): Remove code for Node_typedregex. + * re.c (re_update): Remove code for Node_typedregex. + 2016-08-01 Arnold D. Robbins <arnold@skeeve.com> * README, NEWS: Mark DJGPP port as unsupported. @@ -75,6 +103,17 @@ should not be mapped to upper case. Fixes inconsistencies between dfa and regex in some single bytes locales; notably el_GR.iso88597. +2016-07-23 Arnold D. Robbins <arnold@skeeve.com> + + Make result of close on a pipe match result of system. + Thanks to Mike Brennan for the encouragement. + + * awk.h (sanitize_exit_status): Declare routine. + * builtin.c (sanitize_exit_status): New routine. + (do_system): Use it. + * io.c (close_rp): Use it on pclose result. + (gawk_pclose): Use it. + 2016-07-23 Andrew J. Schorr <aschorr@telemetry-investments.com> * builtin.c (do_print): Improve logic for formatting @@ -119,6 +158,21 @@ * dfa.c: Sync with GNU grep. + Unrelated: + + * builtin.c (do_print): Coding style change. + +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 @@ -139,6 +193,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. @@ -149,6 +283,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. @@ -159,10 +309,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> @@ -199,6 +449,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 @@ -247,6 +507,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. @@ -259,12 +526,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 @@ -340,6 +615,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 @@ -357,12 +641,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 @@ -394,6 +720,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. @@ -442,6 +773,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 @@ -503,6 +871,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 @@ -515,6 +889,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 @@ -552,6 +931,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 @@ -678,6 +1063,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. @@ -691,6 +1168,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. @@ -715,6 +1202,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 @@ -725,6 +1223,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. @@ -749,6 +1255,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. @@ -781,6 +1292,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. @@ -794,6 +1320,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 @@ -807,6 +1341,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). @@ -828,6 +1379,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 @@ -869,6 +1429,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. @@ -885,6 +1466,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. @@ -899,6 +1486,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. @@ -910,6 +1501,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. @@ -924,6 +1533,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. @@ -931,6 +1560,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. @@ -954,6 +1597,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, @@ -1016,6 +1687,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. @@ -1033,6 +1709,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. @@ -1051,6 +1743,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. @@ -1155,6 +1965,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. @@ -1177,6 +2017,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. @@ -1238,12 +2088,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 @@ -1316,6 +2189,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 ... @@ -1377,6 +2289,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. @@ -1401,6 +2334,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 @@ -1472,6 +2412,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 @@ -1494,6 +2440,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. @@ -1508,6 +2469,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: @@ -1628,6 +2596,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 @@ -1994,6 +2969,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 @@ -2011,6 +2991,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. @@ -2030,6 +3015,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 @@ -2111,6 +3103,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. @@ -2119,6 +3117,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. @@ -2127,6 +3135,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 ... @@ -2137,6 +3163,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 @@ -2147,6 +3212,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 8660c111..dce65018 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 afb9bdc7..036361cb 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,77 @@ 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. The new typeof() function can be used to indicate if a variable or + array element is an array, string or number. The isarray() + function is deprecated in favor of typeof(). + +16. As promised when 4.1 was released, the old extension mechanism, + using the `extension' function, is now gone. + +17. Support for GNU/Linux on Alpha systems has been removed. + +18. 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. + +19. 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,167 @@ +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 +------------------------------------ + + Use fwrite_unlocked if available. Brings about 7% speedup for output. + + 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); @@ -272,7 +272,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 +391,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 +410,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 @@ -480,6 +483,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 @@ -494,6 +504,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 @@ -556,6 +576,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, @@ -654,7 +679,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 */ @@ -663,6 +687,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, @@ -690,6 +715,7 @@ typedef enum opcodeval { Op_func, + Op_comment, /* for pretty printing */ Op_exec_count, Op_breakpoint, Op_lint, @@ -1203,6 +1229,7 @@ extern void r_unref(NODE *tmp); static inline void DEREF(NODE *r) { + assert(r->valref > 0); if (--r->valref == 0) r_unref(r); } @@ -1339,6 +1366,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); @@ -1401,12 +1429,15 @@ 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); +extern int sanitize_exit_status(int status); /* eval.c */ extern void PUSH_CODE(INSTRUCTION *cp); extern INSTRUCTION *POP_CODE(void); @@ -1443,10 +1474,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); @@ -1508,7 +1537,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); @@ -1523,6 +1555,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); @@ -1530,6 +1564,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); @@ -1546,6 +1581,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); @@ -1777,7 +1813,7 @@ static inline NODE * force_string(NODE *s) { 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); @@ -1807,6 +1843,51 @@ force_number(NODE *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); + 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 @@ -345,7 +364,7 @@ int yyparse (void); /* Copy the second part of user declarations. */ -#line 349 "awkgram.c" /* yacc.c:358 */ +#line 368 "awkgram.c" /* yacc.c:358 */ #ifdef short # undef short @@ -587,16 +606,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 1155 +#define YYLAST 1147 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 75 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 65 +#define YYNNTS 69 /* YYNRULES -- Number of rules. */ -#define YYNRULES 188 +#define YYNRULES 198 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 335 +#define YYNSTATES 345 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ @@ -647,25 +666,26 @@ static const yytype_uint8 yytranslate[] = /* 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, 517, 522, 532, + 579, 584, 585, 589, 591, 593, 600, 690, 732, 774, + 887, 894, 901, 912, 922, 932, 942, 954, 971, 970, + 995, 1007, 1007, 1106, 1106, 1140, 1171, 1180, 1181, 1187, + 1188, 1195, 1200, 1212, 1226, 1228, 1236, 1241, 1243, 1254, + 1256, 1265, 1266, 1274, 1279, 1279, 1290, 1294, 1302, 1303, + 1306, 1308, 1313, 1314, 1323, 1324, 1329, 1334, 1343, 1345, + 1347, 1354, 1355, 1361, 1362, 1367, 1369, 1374, 1376, 1384, + 1389, 1398, 1399, 1404, 1406, 1411, 1413, 1421, 1426, 1434, + 1439, 1446, 1448, 1450, 1467, 1477, 1484, 1486, 1491, 1493, + 1495, 1503, 1505, 1510, 1512, 1517, 1519, 1521, 1577, 1579, + 1581, 1583, 1585, 1587, 1589, 1591, 1605, 1610, 1615, 1640, + 1646, 1648, 1650, 1652, 1654, 1656, 1661, 1665, 1697, 1699, + 1705, 1711, 1724, 1725, 1726, 1731, 1736, 1740, 1744, 1759, + 1772, 1777, 1814, 1843, 1844, 1850, 1851, 1856, 1858, 1865, + 1882, 1899, 1901, 1908, 1913, 1921, 1931, 1943, 1952, 1956, + 1960, 1964, 1968, 1972, 1975, 1977, 1981, 1985, 1989 }; #endif @@ -687,13 +707,14 @@ static const char *const yytname[] = "'>'", "'+'", "'-'", "'*'", "'/'", "'%'", "'!'", "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", + "lex_builtin", "function_prologue", "$@1", "regexp", "$@2", "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", "$@5", "if_statement", "nls", "opt_nls", "input_redir", + "output_redir", "$@6", "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", + "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", @@ -718,54 +739,55 @@ static const yytype_uint16 yytoknum[] = }; # endif -#define YYPACT_NINF -273 +#define YYPACT_NINF -280 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-273))) + (!!((Yystate) == (-280))) -#define YYTABLE_NINF -104 +#define YYTABLE_NINF -113 #define yytable_value_is_error(Yytable_value) \ - (!!((Yytable_value) == (-104))) + (!!((Yytable_value) == (-113))) /* 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 + -280, 341, -280, -280, -30, -14, -280, -280, -280, -280, + 235, -280, -280, 56, 56, 56, 64, 69, -280, -280, + -280, 1011, 1011, -280, 1011, 1057, 786, 206, -280, -22, + -3, -280, -280, 31, 723, 984, 336, 408, -280, -280, + -280, -280, 169, 754, 786, -280, 5, -280, -280, -280, + -280, -280, 88, 87, -280, 103, -280, -280, -280, 754, + 754, 158, 98, 4, 98, 98, 1011, 77, -280, -280, + 61, 313, 45, 127, -280, 120, -280, -280, -280, 31, + -280, 120, -280, 168, -280, -280, 1011, 182, 1011, 1011, + 1011, 120, -280, -280, -280, 1011, 149, 336, 1011, 1011, + 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011, + -280, -280, -280, -280, 175, 1011, -280, 122, 129, -280, + 1026, 15, 1026, -280, -280, -280, -280, 1011, -280, 122, + 122, 313, -280, -280, -280, 1011, 120, -280, 152, 832, + -280, -280, 17, -19, -280, 44, -19, 31, -280, 561, + -280, -280, 151, -280, 311, 231, 1090, 1011, 190, 56, + -26, -26, 98, 98, 98, 98, -26, -26, 98, 98, + 98, 98, -280, 1026, -280, 1011, 859, -280, 40, 336, + -280, -280, 1026, -280, 182, -280, 1026, -280, -280, -280, + -280, -280, 124, -280, 26, 135, 144, 120, 150, -19, + -19, -280, -280, -19, 1011, -19, 120, -280, -280, -19, + -280, -280, 1026, -280, 142, 120, 1011, 1026, -280, -280, + -280, -280, -280, -280, 122, 138, -280, 1011, 1011, -280, + 215, 1011, 1011, 675, 905, -280, -280, -280, -19, 1026, + -280, -280, -280, 607, 561, 120, -280, -280, 1026, 120, + -280, 154, 313, -19, -14, 155, 313, 313, 196, 9, + -280, 142, -280, 786, 219, -280, 16, -280, -280, -280, + -280, -280, 120, -280, -280, 8, -280, -280, -280, 120, + 120, 165, 182, 120, 61, -280, -280, 675, -280, -280, + -3, 675, 1011, 122, 708, 152, 1011, 216, -280, -280, + 313, 120, 256, 120, 984, 120, 3, 120, 675, 120, + 938, 675, -280, 366, 194, -280, 176, -280, -280, 938, + 122, -280, -280, -280, 243, 246, -280, 194, -280, 120, + -280, 122, 120, -280, -280, 120, -280, 120, 675, -280, + 413, 675, -280, 487, -280 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -773,64 +795,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, 184, 166, 167, 21, 22, + 0, 23, 24, 173, 0, 0, 0, 161, 5, 88, + 37, 0, 0, 36, 0, 0, 0, 0, 3, 0, + 0, 156, 34, 4, 19, 127, 135, 136, 138, 162, + 170, 186, 163, 0, 0, 181, 0, 185, 27, 26, + 30, 31, 0, 0, 28, 92, 174, 164, 165, 0, + 0, 0, 169, 163, 168, 157, 0, 190, 163, 107, + 0, 105, 0, 0, 171, 90, 196, 7, 8, 41, + 38, 90, 9, 0, 89, 131, 0, 0, 0, 0, + 0, 90, 132, 134, 133, 0, 0, 137, 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 + 129, 128, 146, 147, 0, 0, 115, 0, 0, 113, + 119, 0, 105, 183, 182, 29, 32, 0, 145, 0, + 0, 0, 188, 189, 187, 108, 90, 193, 0, 0, + 158, 14, 0, 0, 17, 0, 0, 91, 191, 0, + 42, 35, 123, 124, 121, 122, 0, 0, 125, 173, + 143, 144, 140, 141, 142, 139, 154, 155, 151, 152, + 153, 150, 130, 120, 172, 116, 0, 180, 0, 93, + 159, 160, 109, 198, 0, 110, 106, 13, 10, 16, + 11, 40, 0, 58, 0, 0, 0, 90, 0, 0, + 0, 79, 80, 0, 101, 0, 90, 39, 52, 0, + 61, 45, 66, 38, 194, 90, 0, 20, 149, 117, + 118, 114, 98, 96, 0, 0, 148, 0, 101, 63, + 0, 0, 0, 0, 67, 53, 54, 55, 0, 102, + 56, 192, 60, 0, 0, 90, 195, 43, 126, 90, + 99, 0, 0, 0, 175, 0, 0, 0, 0, 184, + 68, 0, 57, 0, 83, 81, 0, 44, 25, 33, + 100, 97, 90, 59, 64, 0, 177, 179, 65, 90, + 90, 0, 0, 90, 0, 84, 62, 0, 176, 178, + 0, 0, 0, 0, 0, 82, 0, 86, 69, 47, + 0, 90, 0, 90, 85, 90, 0, 90, 0, 90, + 67, 0, 71, 0, 0, 70, 0, 48, 49, 67, + 0, 87, 74, 77, 0, 0, 78, 0, 197, 90, + 46, 0, 90, 76, 75, 90, 38, 90, 0, 38, + 0, 0, 51, 0, 50 }; /* 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 + -280, -280, -280, -280, -280, -280, 228, -280, -280, -280, + -280, -54, -280, -280, -212, -33, -176, -280, -280, -227, + -280, -280, -279, -280, -280, -280, -280, -280, -280, -280, + -280, 52, 28, -280, -280, -280, 32, -280, -39, 93, + -280, 2, -1, -280, -280, -280, -29, 42, -280, 241, + -280, 11, 109, -280, -280, -6, -40, -280, -280, -72, + -2, -280, -27, -236, -56, -280, -20, -51, -108 }; /* 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, 143, 146, 29, 77, 53, 54, 30, + 178, 31, 83, 32, 149, 78, 207, 208, 228, 209, + 243, 254, 261, 306, 315, 327, 210, 264, 286, 296, + 211, 147, 148, 128, 224, 225, 238, 265, 70, 117, + 118, 119, 212, 115, 94, 95, 35, 36, 37, 38, + 39, 40, 55, 274, 275, 276, 45, 46, 47, 41, + 42, 134, 213, 214, 140, 245, 215, 329, 139 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -838,242 +861,240 @@ 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, - 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, - 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, + 34, 244, 80, 80, 312, 121, 124, 260, 267, 81, + 176, 56, 57, 58, 138, 153, 135, 135, 187, 63, + 63, 123, 63, 68, 288, 71, -104, 313, 314, 19, + 229, 320, 19, 63, 100, 101, 102, 43, 74, 103, + 331, 222, 120, 122, 223, 189, 141, 112, 113, 282, + 75, 142, 76, 33, 19, 76, 44, 258, 120, 120, + 5, 174, 135, 62, 64, 131, 65, -104, -12, 75, + 136, 136, 74, 180, 181, 44, -90, 97, 44, 44, + 330, 79, 84, 260, -104, 152, 177, 154, 155, 156, + -104, -12, 260, 230, 158, -15, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, -94, 150, + 188, 297, 226, 190, 173, 299, 136, 251, -15, 157, + 132, 133, 25, 81, 340, 63, 81, 343, 144, 137, + 175, 59, 318, 145, 182, 321, 60, 125, 186, 250, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 171, 129, 130, 126, 270, 217, 56, 271, 127, + 85, 4, 342, 103, 183, 344, 235, 236, 249, 179, + 237, 19, 240, 151, 120, 120, 242, 219, 221, 81, + 81, 110, 111, 81, 136, 81, 5, 159, 172, 81, + 137, 227, 184, 136, 246, 79, 272, -112, 79, -113, + 279, 280, 231, 239, 266, 262, -95, 92, 93, 4, + 293, 232, 112, 113, 277, 248, 76, 234, 81, 255, + 273, 114, 281, 278, 284, 233, 252, 239, 295, 285, + 256, 257, 292, 81, 241, 277, 305, 301, 48, 49, + 85, 283, 122, 247, 307, 86, -113, -113, 328, 206, + 333, 79, 79, 334, 72, 79, 73, 79, 82, 326, + 253, 79, 71, 298, 332, 85, 67, 304, 218, 289, + 86, 87, 88, 268, 303, 337, 335, 269, 0, 0, + 50, 51, 309, 0, 0, 0, 0, 92, 93, 0, + 79, 300, 0, 302, 63, 0, 87, 88, 89, 0, + 287, 0, 63, 0, 52, 79, 0, 290, 291, 90, + 0, 294, 92, 93, 0, 0, 0, 0, 0, 0, + 85, 0, 85, 0, 0, 86, 0, 86, 0, 308, + 76, 310, 0, 311, 316, 317, 0, 319, 0, 0, + 0, 2, 3, 0, 4, 5, 97, 0, 6, 7, + 0, 87, 0, 87, 88, 89, 0, 336, 8, 9, + 338, 0, 0, 339, 0, 341, 90, 92, 93, 92, + 93, 0, 0, 322, 323, 0, 10, 11, 12, 13, + 0, 137, 0, 0, 14, 15, 16, 17, 18, 0, + 0, 0, 19, 20, 98, 99, 100, 101, 102, 21, + 22, 103, 23, 0, 24, 0, 0, 25, 26, 0, + 27, 0, 0, -18, 191, -18, 4, 5, 20, 0, + 6, 7, 0, 0, 324, 325, 0, 23, 0, 0, + 0, 0, 192, 0, 193, 194, 195, -73, -73, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 0, + 0, 13, 205, 0, 0, 0, 14, 15, 16, 17, + 0, 0, 0, 0, -73, 20, 104, 105, 106, 107, + 108, 21, 22, 109, 23, 0, 24, 0, 0, 25, + 26, 0, 61, 0, 0, 75, -73, 76, 191, 0, + 4, 5, 0, 0, 6, 7, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 192, 0, 193, 194, + 195, -72, -72, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 0, 0, 0, 13, 205, 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, 191, 0, 4, 5, 0, 0, 6, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 192, 0, 193, 194, 195, 0, 0, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 0, 0, 0, 13, + 205, 0, 0, 0, 14, 15, 16, 17, 69, 0, + 4, 5, 0, 20, 6, 7, 0, -103, 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, - 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, + 61, 0, 0, 75, 206, 76, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 14, 15, 16, 17, 0, 0, 0, 0, -103, 20, + 0, 0, 0, 0, 0, 21, 22, 0, 23, 0, + 24, 0, 0, 25, 263, -103, 61, 0, 4, 5, + 0, -103, 6, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 192, 0, 193, 194, 195, 0, + 0, 196, 197, 198, 199, 200, 201, 202, 203, 204, + 0, 4, 5, 13, 205, 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, 116, 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, -111, 61, 13, 0, 0, 0, 0, 14, + 15, 16, 17, 185, 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, 4, 5, 0, 0, 6, 7, 0, 0, + 220, 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, + 0, 0, 0, 0, 20, 0, 0, 0, 0, 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, 61, 14, 15, 16, 17, 0, 0, 4, 259, + 0, 20, 6, 7, 0, 0, 0, 21, 22, 0, + 23, 0, 24, 0, 0, 25, 26, 194, 61, 0, + 0, 0, 0, 0, 0, 0, 201, 202, 0, 0, + 0, 4, 5, 13, 0, 6, 7, 0, 14, 15, + 16, 17, 0, 0, 0, 0, 0, 20, 0, 0, + 194, 0, 0, 21, 22, 0, 23, 0, 24, 201, + 202, 25, 26, 0, 61, 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, 216, 0, 92, 93 }; 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, - 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, + 1, 213, 29, 30, 1, 44, 46, 234, 244, 29, + 118, 13, 14, 15, 70, 87, 1, 1, 1, 21, + 22, 16, 24, 25, 16, 26, 10, 24, 25, 51, + 4, 310, 51, 35, 60, 61, 62, 67, 27, 65, + 319, 1, 43, 44, 4, 1, 1, 43, 44, 40, + 72, 6, 74, 1, 51, 74, 70, 233, 59, 60, + 4, 117, 1, 21, 22, 66, 24, 51, 51, 72, + 55, 55, 61, 129, 130, 70, 73, 35, 70, 70, + 316, 29, 51, 310, 68, 86, 71, 88, 89, 90, + 74, 74, 319, 67, 95, 51, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 68, 81, + 143, 287, 184, 146, 115, 291, 55, 225, 74, 91, + 43, 44, 66, 143, 336, 127, 146, 339, 1, 68, + 1, 67, 308, 6, 135, 311, 67, 49, 139, 1, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 59, 60, 67, 1, 157, 159, 4, 56, + 9, 3, 338, 65, 136, 341, 199, 200, 224, 127, + 203, 51, 205, 5, 175, 176, 209, 175, 176, 199, + 200, 12, 13, 203, 55, 205, 4, 38, 13, 209, + 68, 67, 40, 55, 214, 143, 252, 68, 146, 9, + 256, 257, 67, 204, 243, 238, 68, 56, 57, 3, + 282, 67, 43, 44, 254, 216, 74, 67, 238, 4, + 253, 52, 26, 68, 263, 197, 227, 228, 284, 10, + 231, 232, 67, 253, 206, 275, 20, 293, 3, 4, + 9, 261, 243, 215, 300, 14, 56, 57, 54, 73, + 7, 199, 200, 7, 48, 203, 50, 205, 30, 313, + 228, 209, 263, 290, 320, 9, 25, 296, 159, 275, + 14, 40, 41, 245, 294, 331, 327, 249, -1, -1, + 45, 46, 302, -1, -1, -1, -1, 56, 57, -1, + 238, 292, -1, 294, 296, -1, 40, 41, 42, -1, + 272, -1, 304, -1, 69, 253, -1, 279, 280, 53, + -1, 283, 56, 57, -1, -1, -1, -1, -1, -1, + 9, -1, 9, -1, -1, 14, -1, 14, -1, 301, + 74, 303, -1, 305, 306, 307, -1, 309, -1, -1, + -1, 0, 1, -1, 3, 4, 304, -1, 7, 8, + -1, 40, -1, 40, 41, 42, -1, 329, 17, 18, + 332, -1, -1, 335, -1, 337, 53, 56, 57, 56, + 57, -1, -1, 7, 8, -1, 35, 36, 37, 38, + -1, 68, -1, -1, 43, 44, 45, 46, 47, -1, + -1, -1, 51, 52, 58, 59, 60, 61, 62, 58, + 59, 65, 61, -1, 63, -1, -1, 66, 67, -1, + 69, -1, -1, 72, 1, 74, 3, 4, 52, -1, + 7, 8, -1, -1, 58, 59, -1, 61, -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, 58, 59, 60, 61, + 62, 58, 59, 65, 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, -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, + 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, 3, 4, -1, -1, 7, 8, -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, + -1, -1, -1, -1, 52, -1, -1, -1, -1, -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 + -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, 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, 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 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -1083,37 +1104,38 @@ 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, + 84, 86, 88, 106, 117, 121, 122, 123, 124, 125, + 126, 134, 135, 67, 70, 131, 132, 133, 3, 4, + 45, 46, 69, 82, 83, 127, 135, 135, 135, 67, + 67, 69, 122, 135, 122, 122, 67, 124, 135, 1, + 113, 117, 48, 50, 126, 72, 74, 81, 90, 106, + 137, 141, 81, 87, 51, 9, 14, 40, 41, 42, + 53, 55, 56, 57, 119, 120, 11, 122, 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 + 12, 13, 43, 44, 52, 118, 1, 114, 115, 116, + 117, 113, 117, 16, 131, 49, 67, 56, 108, 114, + 114, 117, 43, 44, 136, 1, 55, 68, 139, 143, + 139, 1, 6, 78, 1, 6, 79, 106, 107, 89, + 107, 5, 117, 134, 117, 117, 117, 107, 117, 38, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 13, 117, 139, 1, 143, 71, 85, 122, + 139, 139, 117, 107, 40, 1, 117, 1, 90, 1, + 90, 1, 19, 21, 22, 23, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 39, 73, 91, 92, 94, + 101, 105, 117, 137, 138, 141, 54, 117, 127, 116, + 1, 116, 1, 4, 109, 110, 134, 67, 93, 4, + 67, 67, 67, 107, 67, 90, 90, 90, 111, 117, + 90, 107, 90, 95, 89, 140, 141, 107, 117, 139, + 1, 143, 117, 111, 96, 4, 117, 117, 91, 4, + 94, 97, 90, 67, 102, 112, 113, 138, 107, 107, + 1, 4, 139, 90, 128, 129, 130, 131, 68, 139, + 139, 26, 40, 141, 113, 10, 103, 107, 16, 130, + 107, 107, 67, 134, 107, 139, 104, 91, 137, 91, + 117, 139, 117, 141, 121, 20, 98, 139, 107, 141, + 107, 107, 1, 24, 25, 99, 107, 107, 91, 107, + 97, 91, 7, 8, 58, 59, 86, 100, 54, 142, + 138, 97, 139, 7, 7, 142, 107, 139, 107, 107, + 89, 107, 91, 89, 91 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ @@ -1122,22 +1144,23 @@ 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 + 83, 83, 85, 84, 87, 86, 88, 88, 89, 89, + 89, 90, 90, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 92, 92, 92, 92, 92, 93, 92, + 92, 95, 94, 96, 94, 94, 94, 97, 97, 98, + 98, 98, 99, 99, 100, 100, 100, 100, 100, 101, + 101, 102, 102, 103, 104, 103, 105, 105, 106, 106, + 107, 107, 108, 108, 109, 109, 110, 110, 110, 110, + 110, 111, 111, 112, 112, 113, 113, 113, 113, 113, + 113, 114, 114, 115, 115, 115, 115, 115, 115, 116, + 117, 117, 117, 117, 117, 117, 117, 117, 118, 118, + 118, 119, 119, 120, 120, 121, 121, 121, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, + 123, 123, 123, 123, 123, 123, 124, 124, 124, 124, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 125, 125, 126, 127, 127, 128, 128, 129, 129, 130, + 131, 132, 132, 133, 134, 134, 135, 135, 136, 136, + 136, 137, 138, 139, 140, 140, 141, 142, 143 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -1146,14 +1169,15 @@ 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, + 1, 1, 0, 7, 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, 0, 1, 1, 3, 1, 2, 3, 3, 1, 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, @@ -1838,24 +1862,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 1871 "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 1879 "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 +1888,20 @@ yyreduce: */ /* yyerrok; */ } -#line 1868 "awkgram.c" /* yacc.c:1646 */ +#line 1892 "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 1901 "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 +1912,42 @@ yyreduce: } else /* pattern rule with non-empty pattern */ (void) append_rule((yyvsp[-1]), NULL); } -#line 1891 "awkgram.c" /* yacc.c:1646 */ +#line 1916 "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 1927 "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 1937 "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 1947 "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 +1955,23 @@ yyreduce: bcfree((yyvsp[0])); (yyval) = NULL; } -#line 1933 "awkgram.c" /* yacc.c:1646 */ +#line 1959 "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 1965 "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 1971 "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 +1979,49 @@ yyreduce: bcfree((yyvsp[0])); (yyval) = NULL; } -#line 1957 "awkgram.c" /* yacc.c:1646 */ +#line 1983 "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 1989 "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 1995 "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 2008 "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 2021 "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 +2044,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 2055 "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 2073 "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 2091 "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 2103 "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 2115 "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 2128 "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 2134 "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 2140 "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 2150 "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 2159 "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 2165 "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 2207 "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 2213 "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 +2242,112 @@ yyreduce: (yyval)->opcode = Op_match_rec; (yyval)->memory = n; } -#line 2157 "awkgram.c" /* yacc.c:1646 */ +#line 2246 "awkgram.c" /* yacc.c:1646 */ break; - case 35: -#line 437 "awkgram.y" /* yacc.c:1646 */ + case 36: +#line 516 "awkgram.y" /* yacc.c:1646 */ { bcfree((yyvsp[0])); } -#line 2163 "awkgram.c" /* yacc.c:1646 */ +#line 2252 "awkgram.c" /* yacc.c:1646 */ break; - case 37: -#line 443 "awkgram.y" /* yacc.c:1646 */ - { (yyval) = NULL; } -#line 2169 "awkgram.c" /* yacc.c:1646 */ + case 38: +#line 522 "awkgram.y" /* yacc.c:1646 */ + { + 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 2267 "awkgram.c" /* yacc.c:1646 */ break; - case 38: -#line 445 "awkgram.y" /* yacc.c:1646 */ + case 39: +#line 533 "awkgram.y" /* yacc.c:1646 */ { - if ((yyvsp[0]) == NULL) - (yyval) = (yyvsp[-1]); - else { + 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 2318 "awkgram.c" /* yacc.c:1646 */ break; - case 39: -#line 458 "awkgram.y" /* yacc.c:1646 */ + case 40: +#line 580 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2192 "awkgram.c" /* yacc.c:1646 */ +#line 2324 "awkgram.c" /* yacc.c:1646 */ break; - case 42: -#line 468 "awkgram.y" /* yacc.c:1646 */ + case 43: +#line 590 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2198 "awkgram.c" /* yacc.c:1646 */ +#line 2330 "awkgram.c" /* yacc.c:1646 */ break; - case 43: -#line 470 "awkgram.y" /* yacc.c:1646 */ + case 44: +#line 592 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 2204 "awkgram.c" /* yacc.c:1646 */ +#line 2336 "awkgram.c" /* yacc.c:1646 */ break; - case 44: -#line 472 "awkgram.y" /* yacc.c:1646 */ + case 45: +#line 594 "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 2347 "awkgram.c" /* yacc.c:1646 */ break; - case 45: -#line 479 "awkgram.y" /* yacc.c:1646 */ + case 46: +#line 601 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *dflt, *curr = NULL, *cexp, *cstmt; INSTRUCTION *ip, *nextc, *tbreak; @@ -2236,7 +2368,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 +2437,11 @@ yyreduce: break_allowed--; fix_break_continue(ip, tbreak, NULL); } -#line 2309 "awkgram.c" /* yacc.c:1646 */ +#line 2441 "awkgram.c" /* yacc.c:1646 */ break; - case 46: -#line 569 "awkgram.y" /* yacc.c:1646 */ + case 47: +#line 691 "awkgram.y" /* yacc.c:1646 */ { /* * ----------------- @@ -2351,11 +2483,11 @@ yyreduce: continue_allowed--; fix_break_continue(ip, tbreak, tcont); } -#line 2355 "awkgram.c" /* yacc.c:1646 */ +#line 2487 "awkgram.c" /* yacc.c:1646 */ break; - case 47: -#line 611 "awkgram.y" /* yacc.c:1646 */ + case 48: +#line 733 "awkgram.y" /* yacc.c:1646 */ { /* * ----------------- @@ -2397,11 +2529,11 @@ yyreduce: } /* else $1 and $4 are NULLs */ } -#line 2401 "awkgram.c" /* yacc.c:1646 */ +#line 2533 "awkgram.c" /* yacc.c:1646 */ break; - case 48: -#line 653 "awkgram.y" /* yacc.c:1646 */ + case 49: +#line 775 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip; char *var_name = (yyvsp[-5])->lextok; @@ -2514,70 +2646,73 @@ regular_loop: break_allowed--; continue_allowed--; } -#line 2518 "awkgram.c" /* yacc.c:1646 */ +#line 2650 "awkgram.c" /* yacc.c:1646 */ break; - case 49: -#line 766 "awkgram.y" /* yacc.c:1646 */ + case 50: +#line 888 "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 2661 "awkgram.c" /* yacc.c:1646 */ break; - case 50: -#line 773 "awkgram.y" /* yacc.c:1646 */ + case 51: +#line 895 "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 2672 "awkgram.c" /* yacc.c:1646 */ break; - case 51: -#line 780 "awkgram.y" /* yacc.c:1646 */ + case 52: +#line 902 "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 2684 "awkgram.c" /* yacc.c:1646 */ break; - case 52: -#line 790 "awkgram.y" /* yacc.c:1646 */ + case 53: +#line 913 "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 2698 "awkgram.c" /* yacc.c:1646 */ break; - case 53: -#line 799 "awkgram.y" /* yacc.c:1646 */ + case 54: +#line 923 "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 2712 "awkgram.c" /* yacc.c:1646 */ break; - case 54: -#line 808 "awkgram.y" /* yacc.c:1646 */ + case 55: +#line 933 "awkgram.y" /* yacc.c:1646 */ { /* if inside function (rule = 0), resolve context at run-time */ if (rule && rule != Rule) @@ -2585,12 +2720,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 2726 "awkgram.c" /* yacc.c:1646 */ break; - case 55: -#line 817 "awkgram.y" /* yacc.c:1646 */ + case 56: +#line 943 "awkgram.y" /* yacc.c:1646 */ { /* if inside function (rule = 0), resolve context at run-time */ if (rule == BEGIN || rule == END || rule == ENDFILE) @@ -2600,12 +2736,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 2742 "awkgram.c" /* yacc.c:1646 */ break; - case 56: -#line 828 "awkgram.y" /* yacc.c:1646 */ + case 57: +#line 955 "awkgram.y" /* yacc.c:1646 */ { /* Initialize the two possible jump targets, the actual target * is resolved at run-time. @@ -2619,21 +2756,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 2762 "awkgram.c" /* yacc.c:1646 */ break; - case 57: -#line 843 "awkgram.y" /* yacc.c:1646 */ + case 58: +#line 971 "awkgram.y" /* yacc.c:1646 */ { if (! in_function) yyerror(_("`return' used outside function context")); } -#line 2633 "awkgram.c" /* yacc.c:1646 */ +#line 2771 "awkgram.c" /* yacc.c:1646 */ break; - case 58: -#line 846 "awkgram.y" /* yacc.c:1646 */ + case 59: +#line 974 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-1]) == NULL) { (yyval) = list_create((yyvsp[-3])); @@ -2653,18 +2791,19 @@ regular_loop: (yyval) = list_append((yyvsp[-1]), (yyvsp[-3])); } + (yyval) = add_pending_comment((yyval)); } -#line 2658 "awkgram.c" /* yacc.c:1646 */ +#line 2797 "awkgram.c" /* yacc.c:1646 */ break; - case 60: -#line 878 "awkgram.y" /* yacc.c:1646 */ + case 61: +#line 1007 "awkgram.y" /* yacc.c:1646 */ { in_print = true; in_parens = 0; } -#line 2664 "awkgram.c" /* yacc.c:1646 */ +#line 2803 "awkgram.c" /* yacc.c:1646 */ break; - case 61: -#line 879 "awkgram.y" /* yacc.c:1646 */ + case 62: +#line 1008 "awkgram.y" /* yacc.c:1646 */ { /* * Optimization: plain `print' has no expression list, so $3 is null. @@ -2760,18 +2899,19 @@ regular_print: } } } + (yyval) = add_pending_comment((yyval)); } -#line 2765 "awkgram.c" /* yacc.c:1646 */ +#line 2905 "awkgram.c" /* yacc.c:1646 */ break; - case 62: -#line 976 "awkgram.y" /* yacc.c:1646 */ + case 63: +#line 1106 "awkgram.y" /* yacc.c:1646 */ { sub_counter = 0; } -#line 2771 "awkgram.c" /* yacc.c:1646 */ +#line 2911 "awkgram.c" /* yacc.c:1646 */ break; - case 63: -#line 977 "awkgram.y" /* yacc.c:1646 */ + case 64: +#line 1107 "awkgram.y" /* yacc.c:1646 */ { char *arr = (yyvsp[-2])->lextok; @@ -2803,12 +2943,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 2949 "awkgram.c" /* yacc.c:1646 */ break; - case 64: -#line 1014 "awkgram.y" /* yacc.c:1646 */ + case 65: +#line 1145 "awkgram.y" /* yacc.c:1646 */ { static bool warned = false; char *arr = (yyvsp[-1])->lextok; @@ -2833,53 +2974,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 2980 "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 66: +#line 1172 "awkgram.y" /* yacc.c:1646 */ + { + (yyval) = optimize_assignment((yyvsp[0])); + (yyval) = add_pending_comment((yyval)); + } +#line 2989 "awkgram.c" /* yacc.c:1646 */ break; - case 66: -#line 1045 "awkgram.y" /* yacc.c:1646 */ + case 67: +#line 1180 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2850 "awkgram.c" /* yacc.c:1646 */ +#line 2995 "awkgram.c" /* yacc.c:1646 */ break; - case 67: -#line 1047 "awkgram.y" /* yacc.c:1646 */ + case 68: +#line 1182 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2856 "awkgram.c" /* yacc.c:1646 */ +#line 3001 "awkgram.c" /* yacc.c:1646 */ break; - case 68: -#line 1052 "awkgram.y" /* yacc.c:1646 */ + case 69: +#line 1187 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2862 "awkgram.c" /* yacc.c:1646 */ +#line 3007 "awkgram.c" /* yacc.c:1646 */ break; - case 69: -#line 1054 "awkgram.y" /* yacc.c:1646 */ + case 70: +#line 1189 "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 3018 "awkgram.c" /* yacc.c:1646 */ break; - case 70: -#line 1061 "awkgram.y" /* yacc.c:1646 */ + case 71: +#line 1196 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 2879 "awkgram.c" /* yacc.c:1646 */ +#line 3024 "awkgram.c" /* yacc.c:1646 */ break; - case 71: -#line 1066 "awkgram.y" /* yacc.c:1646 */ + case 72: +#line 1201 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *casestmt = (yyvsp[0]); if ((yyvsp[0]) == NULL) @@ -2891,11 +3036,11 @@ regular_print: bcfree((yyvsp[-2])); (yyval) = (yyvsp[-4]); } -#line 2895 "awkgram.c" /* yacc.c:1646 */ +#line 3040 "awkgram.c" /* yacc.c:1646 */ break; - case 72: -#line 1078 "awkgram.y" /* yacc.c:1646 */ + case 73: +#line 1213 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *casestmt = (yyvsp[0]); if ((yyvsp[0]) == NULL) @@ -2906,17 +3051,17 @@ regular_print: (yyvsp[-3])->case_stmt = casestmt; (yyval) = (yyvsp[-3]); } -#line 2910 "awkgram.c" /* yacc.c:1646 */ +#line 3055 "awkgram.c" /* yacc.c:1646 */ break; - case 73: -#line 1092 "awkgram.y" /* yacc.c:1646 */ + case 74: +#line 1227 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2916 "awkgram.c" /* yacc.c:1646 */ +#line 3061 "awkgram.c" /* yacc.c:1646 */ break; - case 74: -#line 1094 "awkgram.y" /* yacc.c:1646 */ + case 75: +#line 1229 "awkgram.y" /* yacc.c:1646 */ { NODE *n = (yyvsp[0])->memory; (void) force_number(n); @@ -2924,71 +3069,74 @@ regular_print: bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 2928 "awkgram.c" /* yacc.c:1646 */ +#line 3073 "awkgram.c" /* yacc.c:1646 */ break; - case 75: -#line 1102 "awkgram.y" /* yacc.c:1646 */ + case 76: +#line 1237 "awkgram.y" /* yacc.c:1646 */ { bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 2937 "awkgram.c" /* yacc.c:1646 */ +#line 3082 "awkgram.c" /* yacc.c:1646 */ break; - case 76: -#line 1107 "awkgram.y" /* yacc.c:1646 */ + case 77: +#line 1242 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2943 "awkgram.c" /* yacc.c:1646 */ +#line 3088 "awkgram.c" /* yacc.c:1646 */ break; - case 77: -#line 1109 "awkgram.y" /* yacc.c:1646 */ + case 78: +#line 1244 "awkgram.y" /* yacc.c:1646 */ { - (yyvsp[0])->opcode = Op_push_re; + if ((yyvsp[0])->memory->type == Node_regex) + (yyvsp[0])->opcode = Op_push_re; + else + (yyvsp[0])->opcode = Op_push; (yyval) = (yyvsp[0]); } -#line 2952 "awkgram.c" /* yacc.c:1646 */ +#line 3100 "awkgram.c" /* yacc.c:1646 */ break; - case 78: -#line 1117 "awkgram.y" /* yacc.c:1646 */ + case 79: +#line 1255 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2958 "awkgram.c" /* yacc.c:1646 */ +#line 3106 "awkgram.c" /* yacc.c:1646 */ break; - case 79: -#line 1119 "awkgram.y" /* yacc.c:1646 */ + case 80: +#line 1257 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 2964 "awkgram.c" /* yacc.c:1646 */ +#line 3112 "awkgram.c" /* yacc.c:1646 */ break; - case 81: -#line 1129 "awkgram.y" /* yacc.c:1646 */ + case 82: +#line 1267 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 2972 "awkgram.c" /* yacc.c:1646 */ +#line 3120 "awkgram.c" /* yacc.c:1646 */ break; - case 82: -#line 1136 "awkgram.y" /* yacc.c:1646 */ + case 83: +#line 1274 "awkgram.y" /* yacc.c:1646 */ { in_print = false; in_parens = 0; (yyval) = NULL; } -#line 2982 "awkgram.c" /* yacc.c:1646 */ +#line 3130 "awkgram.c" /* yacc.c:1646 */ break; - case 83: -#line 1141 "awkgram.y" /* yacc.c:1646 */ + case 84: +#line 1279 "awkgram.y" /* yacc.c:1646 */ { in_print = false; in_parens = 0; } -#line 2988 "awkgram.c" /* yacc.c:1646 */ +#line 3136 "awkgram.c" /* yacc.c:1646 */ break; - case 84: -#line 1142 "awkgram.y" /* yacc.c:1646 */ + case 85: +#line 1280 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-2])->redir_type == redirect_twoway && (yyvsp[0])->lasti->opcode == Op_K_getline_redir @@ -2996,63 +3144,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 3148 "awkgram.c" /* yacc.c:1646 */ break; - case 85: -#line 1153 "awkgram.y" /* yacc.c:1646 */ + case 86: +#line 1291 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_condition((yyvsp[-3]), (yyvsp[-5]), (yyvsp[0]), NULL, NULL); } -#line 3008 "awkgram.c" /* yacc.c:1646 */ +#line 3156 "awkgram.c" /* yacc.c:1646 */ break; - case 86: -#line 1158 "awkgram.y" /* yacc.c:1646 */ + case 87: +#line 1296 "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 3164 "awkgram.c" /* yacc.c:1646 */ break; - case 91: -#line 1175 "awkgram.y" /* yacc.c:1646 */ + case 92: +#line 1313 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3022 "awkgram.c" /* yacc.c:1646 */ +#line 3170 "awkgram.c" /* yacc.c:1646 */ break; - case 92: -#line 1177 "awkgram.y" /* yacc.c:1646 */ + case 93: +#line 1315 "awkgram.y" /* yacc.c:1646 */ { bcfree((yyvsp[-1])); (yyval) = (yyvsp[0]); } -#line 3031 "awkgram.c" /* yacc.c:1646 */ +#line 3179 "awkgram.c" /* yacc.c:1646 */ break; - case 93: -#line 1185 "awkgram.y" /* yacc.c:1646 */ + case 94: +#line 1323 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3037 "awkgram.c" /* yacc.c:1646 */ +#line 3185 "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 95: +#line 1325 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = (yyvsp[0]); } +#line 3191 "awkgram.c" /* yacc.c:1646 */ break; - case 95: -#line 1192 "awkgram.y" /* yacc.c:1646 */ + case 96: +#line 1330 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->param_count = 0; (yyval) = list_create((yyvsp[0])); } -#line 3052 "awkgram.c" /* yacc.c:1646 */ +#line 3200 "awkgram.c" /* yacc.c:1646 */ break; - case 96: -#line 1197 "awkgram.y" /* yacc.c:1646 */ + case 97: +#line 1335 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[-2]) != NULL && (yyvsp[0]) != NULL) { (yyvsp[0])->param_count = (yyvsp[-2])->lasti->param_count + 1; @@ -3061,74 +3209,74 @@ regular_print: } else (yyval) = NULL; } -#line 3065 "awkgram.c" /* yacc.c:1646 */ +#line 3213 "awkgram.c" /* yacc.c:1646 */ break; - case 97: -#line 1206 "awkgram.y" /* yacc.c:1646 */ + case 98: +#line 1344 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3071 "awkgram.c" /* yacc.c:1646 */ +#line 3219 "awkgram.c" /* yacc.c:1646 */ break; - case 98: -#line 1208 "awkgram.y" /* yacc.c:1646 */ + case 99: +#line 1346 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3077 "awkgram.c" /* yacc.c:1646 */ +#line 3225 "awkgram.c" /* yacc.c:1646 */ break; - case 99: -#line 1210 "awkgram.y" /* yacc.c:1646 */ + case 100: +#line 1348 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-2]); } -#line 3083 "awkgram.c" /* yacc.c:1646 */ +#line 3231 "awkgram.c" /* yacc.c:1646 */ break; - case 100: -#line 1216 "awkgram.y" /* yacc.c:1646 */ + case 101: +#line 1354 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3089 "awkgram.c" /* yacc.c:1646 */ +#line 3237 "awkgram.c" /* yacc.c:1646 */ break; - case 101: -#line 1218 "awkgram.y" /* yacc.c:1646 */ + case 102: +#line 1356 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3095 "awkgram.c" /* yacc.c:1646 */ +#line 3243 "awkgram.c" /* yacc.c:1646 */ break; - case 102: -#line 1223 "awkgram.y" /* yacc.c:1646 */ + case 103: +#line 1361 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3101 "awkgram.c" /* yacc.c:1646 */ +#line 3249 "awkgram.c" /* yacc.c:1646 */ break; - case 103: -#line 1225 "awkgram.y" /* yacc.c:1646 */ + case 104: +#line 1363 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3107 "awkgram.c" /* yacc.c:1646 */ +#line 3255 "awkgram.c" /* yacc.c:1646 */ break; - case 104: -#line 1230 "awkgram.y" /* yacc.c:1646 */ + case 105: +#line 1368 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_expression_list(NULL, (yyvsp[0])); } -#line 3113 "awkgram.c" /* yacc.c:1646 */ +#line 3261 "awkgram.c" /* yacc.c:1646 */ break; - case 105: -#line 1232 "awkgram.y" /* yacc.c:1646 */ + case 106: +#line 1370 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); yyerrok; } -#line 3122 "awkgram.c" /* yacc.c:1646 */ +#line 3270 "awkgram.c" /* yacc.c:1646 */ break; - case 106: -#line 1237 "awkgram.y" /* yacc.c:1646 */ + case 107: +#line 1375 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3128 "awkgram.c" /* yacc.c:1646 */ +#line 3276 "awkgram.c" /* yacc.c:1646 */ break; - case 107: -#line 1239 "awkgram.y" /* yacc.c:1646 */ + case 108: +#line 1377 "awkgram.y" /* yacc.c:1646 */ { /* * Returning the expression list instead of NULL lets @@ -3136,58 +3284,128 @@ regular_print: */ (yyval) = (yyvsp[-1]); } -#line 3140 "awkgram.c" /* yacc.c:1646 */ +#line 3288 "awkgram.c" /* yacc.c:1646 */ break; - case 108: -#line 1247 "awkgram.y" /* yacc.c:1646 */ + case 109: +#line 1385 "awkgram.y" /* yacc.c:1646 */ { /* Ditto */ (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); } -#line 3149 "awkgram.c" /* yacc.c:1646 */ +#line 3297 "awkgram.c" /* yacc.c:1646 */ break; - case 109: -#line 1252 "awkgram.y" /* yacc.c:1646 */ + case 110: +#line 1390 "awkgram.y" /* yacc.c:1646 */ { /* Ditto */ (yyval) = (yyvsp[-2]); } -#line 3158 "awkgram.c" /* yacc.c:1646 */ +#line 3306 "awkgram.c" /* yacc.c:1646 */ break; - case 110: -#line 1261 "awkgram.y" /* yacc.c:1646 */ + case 111: +#line 1398 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = NULL; } +#line 3312 "awkgram.c" /* yacc.c:1646 */ + break; + + case 112: +#line 1400 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = (yyvsp[0]); } +#line 3318 "awkgram.c" /* yacc.c:1646 */ + break; + + case 113: +#line 1405 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = mk_expression_list(NULL, (yyvsp[0])); } +#line 3324 "awkgram.c" /* yacc.c:1646 */ + break; + + case 114: +#line 1407 "awkgram.y" /* yacc.c:1646 */ + { + (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); + yyerrok; + } +#line 3333 "awkgram.c" /* yacc.c:1646 */ + break; + + case 115: +#line 1412 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = NULL; } +#line 3339 "awkgram.c" /* yacc.c:1646 */ + break; + + case 116: +#line 1414 "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 3351 "awkgram.c" /* yacc.c:1646 */ + break; + + case 117: +#line 1422 "awkgram.y" /* yacc.c:1646 */ + { + /* Ditto */ + (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0])); + } +#line 3360 "awkgram.c" /* yacc.c:1646 */ + break; + + case 118: +#line 1427 "awkgram.y" /* yacc.c:1646 */ + { + /* Ditto */ + (yyval) = (yyvsp[-2]); + } +#line 3369 "awkgram.c" /* yacc.c:1646 */ + break; + + case 119: +#line 1434 "awkgram.y" /* yacc.c:1646 */ + { (yyval) = (yyvsp[0]); } +#line 3375 "awkgram.c" /* yacc.c:1646 */ + break; + + case 120: +#line 1440 "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 3386 "awkgram.c" /* yacc.c:1646 */ break; - case 111: -#line 1268 "awkgram.y" /* yacc.c:1646 */ + case 121: +#line 1447 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3175 "awkgram.c" /* yacc.c:1646 */ +#line 3392 "awkgram.c" /* yacc.c:1646 */ break; - case 112: -#line 1270 "awkgram.y" /* yacc.c:1646 */ + case 122: +#line 1449 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3181 "awkgram.c" /* yacc.c:1646 */ +#line 3398 "awkgram.c" /* yacc.c:1646 */ break; - case 113: -#line 1272 "awkgram.y" /* yacc.c:1646 */ + case 123: +#line 1451 "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 +3415,11 @@ regular_print: (yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), (yyvsp[-1])); } } -#line 3201 "awkgram.c" /* yacc.c:1646 */ +#line 3419 "awkgram.c" /* yacc.c:1646 */ break; - case 114: -#line 1288 "awkgram.y" /* yacc.c:1646 */ + case 124: +#line 1468 "awkgram.y" /* yacc.c:1646 */ { if (do_lint_old) warning_ln((yyvsp[-1])->source_line, @@ -3211,91 +3429,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 3433 "awkgram.c" /* yacc.c:1646 */ break; - case 115: -#line 1298 "awkgram.y" /* yacc.c:1646 */ + case 125: +#line 1478 "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 3444 "awkgram.c" /* yacc.c:1646 */ break; - case 116: -#line 1305 "awkgram.y" /* yacc.c:1646 */ + case 126: +#line 1485 "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 3450 "awkgram.c" /* yacc.c:1646 */ break; - case 117: -#line 1307 "awkgram.y" /* yacc.c:1646 */ + case 127: +#line 1487 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3238 "awkgram.c" /* yacc.c:1646 */ +#line 3456 "awkgram.c" /* yacc.c:1646 */ break; - case 118: -#line 1312 "awkgram.y" /* yacc.c:1646 */ + case 128: +#line 1492 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3244 "awkgram.c" /* yacc.c:1646 */ +#line 3462 "awkgram.c" /* yacc.c:1646 */ break; - case 119: -#line 1314 "awkgram.y" /* yacc.c:1646 */ + case 129: +#line 1494 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3250 "awkgram.c" /* yacc.c:1646 */ +#line 3468 "awkgram.c" /* yacc.c:1646 */ break; - case 120: -#line 1316 "awkgram.y" /* yacc.c:1646 */ + case 130: +#line 1496 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_assign_quotient; (yyval) = (yyvsp[0]); } -#line 3259 "awkgram.c" /* yacc.c:1646 */ +#line 3477 "awkgram.c" /* yacc.c:1646 */ break; - case 121: -#line 1324 "awkgram.y" /* yacc.c:1646 */ + case 131: +#line 1504 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3265 "awkgram.c" /* yacc.c:1646 */ +#line 3483 "awkgram.c" /* yacc.c:1646 */ break; - case 122: -#line 1326 "awkgram.y" /* yacc.c:1646 */ + case 132: +#line 1506 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3271 "awkgram.c" /* yacc.c:1646 */ +#line 3489 "awkgram.c" /* yacc.c:1646 */ break; - case 123: -#line 1331 "awkgram.y" /* yacc.c:1646 */ + case 133: +#line 1511 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3277 "awkgram.c" /* yacc.c:1646 */ +#line 3495 "awkgram.c" /* yacc.c:1646 */ break; - case 124: -#line 1333 "awkgram.y" /* yacc.c:1646 */ + case 134: +#line 1513 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3283 "awkgram.c" /* yacc.c:1646 */ +#line 3501 "awkgram.c" /* yacc.c:1646 */ break; - case 125: -#line 1338 "awkgram.y" /* yacc.c:1646 */ + case 135: +#line 1518 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3289 "awkgram.c" /* yacc.c:1646 */ +#line 3507 "awkgram.c" /* yacc.c:1646 */ break; - case 126: -#line 1340 "awkgram.y" /* yacc.c:1646 */ + case 136: +#line 1520 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3295 "awkgram.c" /* yacc.c:1646 */ +#line 3513 "awkgram.c" /* yacc.c:1646 */ break; - case 127: -#line 1342 "awkgram.y" /* yacc.c:1646 */ + case 137: +#line 1522 "awkgram.y" /* yacc.c:1646 */ { int count = 2; bool is_simple_var = false; @@ -3321,10 +3539,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 +3558,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 +3566,47 @@ regular_print: max_args = count; } } -#line 3346 "awkgram.c" /* yacc.c:1646 */ +#line 3570 "awkgram.c" /* yacc.c:1646 */ break; - case 129: -#line 1394 "awkgram.y" /* yacc.c:1646 */ + case 139: +#line 1580 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3352 "awkgram.c" /* yacc.c:1646 */ +#line 3576 "awkgram.c" /* yacc.c:1646 */ break; - case 130: -#line 1396 "awkgram.y" /* yacc.c:1646 */ + case 140: +#line 1582 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3358 "awkgram.c" /* yacc.c:1646 */ +#line 3582 "awkgram.c" /* yacc.c:1646 */ break; - case 131: -#line 1398 "awkgram.y" /* yacc.c:1646 */ + case 141: +#line 1584 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3364 "awkgram.c" /* yacc.c:1646 */ +#line 3588 "awkgram.c" /* yacc.c:1646 */ break; - case 132: -#line 1400 "awkgram.y" /* yacc.c:1646 */ + case 142: +#line 1586 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3370 "awkgram.c" /* yacc.c:1646 */ +#line 3594 "awkgram.c" /* yacc.c:1646 */ break; - case 133: -#line 1402 "awkgram.y" /* yacc.c:1646 */ + case 143: +#line 1588 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3376 "awkgram.c" /* yacc.c:1646 */ +#line 3600 "awkgram.c" /* yacc.c:1646 */ break; - case 134: -#line 1404 "awkgram.y" /* yacc.c:1646 */ + case 144: +#line 1590 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3382 "awkgram.c" /* yacc.c:1646 */ +#line 3606 "awkgram.c" /* yacc.c:1646 */ break; - case 135: -#line 1406 "awkgram.y" /* yacc.c:1646 */ + case 145: +#line 1592 "awkgram.y" /* yacc.c:1646 */ { /* * In BEGINFILE/ENDFILE, allow `getline [var] < file' @@ -3396,29 +3620,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 3624 "awkgram.c" /* yacc.c:1646 */ break; - case 136: -#line 1420 "awkgram.y" /* yacc.c:1646 */ + case 146: +#line 1606 "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 3633 "awkgram.c" /* yacc.c:1646 */ break; - case 137: -#line 1425 "awkgram.y" /* yacc.c:1646 */ + case 147: +#line 1611 "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 3642 "awkgram.c" /* yacc.c:1646 */ break; - case 138: -#line 1430 "awkgram.y" /* yacc.c:1646 */ + case 148: +#line 1616 "awkgram.y" /* yacc.c:1646 */ { if (do_lint_old) { warning_ln((yyvsp[-1])->source_line, @@ -3438,64 +3662,64 @@ regular_print: (yyval) = list_append(list_merge(t, (yyvsp[0])), (yyvsp[-1])); } } -#line 3442 "awkgram.c" /* yacc.c:1646 */ +#line 3666 "awkgram.c" /* yacc.c:1646 */ break; - case 139: -#line 1455 "awkgram.y" /* yacc.c:1646 */ + case 149: +#line 1641 "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 3675 "awkgram.c" /* yacc.c:1646 */ break; - case 140: -#line 1461 "awkgram.y" /* yacc.c:1646 */ + case 150: +#line 1647 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3457 "awkgram.c" /* yacc.c:1646 */ +#line 3681 "awkgram.c" /* yacc.c:1646 */ break; - case 141: -#line 1463 "awkgram.y" /* yacc.c:1646 */ + case 151: +#line 1649 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3463 "awkgram.c" /* yacc.c:1646 */ +#line 3687 "awkgram.c" /* yacc.c:1646 */ break; - case 142: -#line 1465 "awkgram.y" /* yacc.c:1646 */ + case 152: +#line 1651 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3469 "awkgram.c" /* yacc.c:1646 */ +#line 3693 "awkgram.c" /* yacc.c:1646 */ break; - case 143: -#line 1467 "awkgram.y" /* yacc.c:1646 */ + case 153: +#line 1653 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3475 "awkgram.c" /* yacc.c:1646 */ +#line 3699 "awkgram.c" /* yacc.c:1646 */ break; - case 144: -#line 1469 "awkgram.y" /* yacc.c:1646 */ + case 154: +#line 1655 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3481 "awkgram.c" /* yacc.c:1646 */ +#line 3705 "awkgram.c" /* yacc.c:1646 */ break; - case 145: -#line 1471 "awkgram.y" /* yacc.c:1646 */ + case 155: +#line 1657 "awkgram.y" /* yacc.c:1646 */ { (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); } -#line 3487 "awkgram.c" /* yacc.c:1646 */ +#line 3711 "awkgram.c" /* yacc.c:1646 */ break; - case 146: -#line 1476 "awkgram.y" /* yacc.c:1646 */ + case 156: +#line 1662 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3495 "awkgram.c" /* yacc.c:1646 */ +#line 3719 "awkgram.c" /* yacc.c:1646 */ break; - case 147: -#line 1480 "awkgram.y" /* yacc.c:1646 */ + case 157: +#line 1666 "awkgram.y" /* yacc.c:1646 */ { if ((yyvsp[0])->opcode == Op_match_rec) { (yyvsp[0])->opcode = Op_nomatch; @@ -3509,7 +3733,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 +3751,37 @@ regular_print: } } } -#line 3531 "awkgram.c" /* yacc.c:1646 */ +#line 3755 "awkgram.c" /* yacc.c:1646 */ break; - case 148: -#line 1512 "awkgram.y" /* yacc.c:1646 */ + case 158: +#line 1698 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3537 "awkgram.c" /* yacc.c:1646 */ +#line 3761 "awkgram.c" /* yacc.c:1646 */ break; - case 149: -#line 1514 "awkgram.y" /* yacc.c:1646 */ + case 159: +#line 1700 "awkgram.y" /* yacc.c:1646 */ { (yyval) = snode((yyvsp[-1]), (yyvsp[-3])); if ((yyval) == NULL) YYABORT; } -#line 3547 "awkgram.c" /* yacc.c:1646 */ +#line 3771 "awkgram.c" /* yacc.c:1646 */ break; - case 150: -#line 1520 "awkgram.y" /* yacc.c:1646 */ + case 160: +#line 1706 "awkgram.y" /* yacc.c:1646 */ { (yyval) = snode((yyvsp[-1]), (yyvsp[-3])); if ((yyval) == NULL) YYABORT; } -#line 3557 "awkgram.c" /* yacc.c:1646 */ +#line 3781 "awkgram.c" /* yacc.c:1646 */ break; - case 151: -#line 1526 "awkgram.y" /* yacc.c:1646 */ + case 161: +#line 1712 "awkgram.y" /* yacc.c:1646 */ { static bool warned = false; @@ -3570,48 +3794,48 @@ regular_print: if ((yyval) == NULL) YYABORT; } -#line 3574 "awkgram.c" /* yacc.c:1646 */ +#line 3798 "awkgram.c" /* yacc.c:1646 */ break; - case 154: -#line 1541 "awkgram.y" /* yacc.c:1646 */ + case 164: +#line 1727 "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 3807 "awkgram.c" /* yacc.c:1646 */ break; - case 155: -#line 1546 "awkgram.y" /* yacc.c:1646 */ + case 165: +#line 1732 "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 3816 "awkgram.c" /* yacc.c:1646 */ break; - case 156: -#line 1551 "awkgram.y" /* yacc.c:1646 */ + case 166: +#line 1737 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3600 "awkgram.c" /* yacc.c:1646 */ +#line 3824 "awkgram.c" /* yacc.c:1646 */ break; - case 157: -#line 1555 "awkgram.y" /* yacc.c:1646 */ + case 167: +#line 1741 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_create((yyvsp[0])); } -#line 3608 "awkgram.c" /* yacc.c:1646 */ +#line 3832 "awkgram.c" /* yacc.c:1646 */ break; - case 158: -#line 1559 "awkgram.y" /* yacc.c:1646 */ + case 168: +#line 1745 "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 +3847,11 @@ regular_print: (yyval) = list_append((yyvsp[0]), (yyvsp[-1])); } } -#line 3627 "awkgram.c" /* yacc.c:1646 */ +#line 3851 "awkgram.c" /* yacc.c:1646 */ break; - case 159: -#line 1574 "awkgram.y" /* yacc.c:1646 */ + case 169: +#line 1760 "awkgram.y" /* yacc.c:1646 */ { /* * was: $$ = $2 @@ -3637,20 +3861,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 3865 "awkgram.c" /* yacc.c:1646 */ break; - case 160: -#line 1587 "awkgram.y" /* yacc.c:1646 */ + case 170: +#line 1773 "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 3874 "awkgram.c" /* yacc.c:1646 */ break; - case 161: -#line 1592 "awkgram.y" /* yacc.c:1646 */ + case 171: +#line 1778 "awkgram.y" /* yacc.c:1646 */ { /* indirect function call */ INSTRUCTION *f, *t; @@ -3684,18 +3908,18 @@ regular_print: (yyval) = list_prepend((yyvsp[0]), t); at_seen = false; } -#line 3688 "awkgram.c" /* yacc.c:1646 */ +#line 3912 "awkgram.c" /* yacc.c:1646 */ break; - case 162: -#line 1629 "awkgram.y" /* yacc.c:1646 */ + case 172: +#line 1815 "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 +3937,49 @@ regular_print: (yyval) = list_append(t, (yyvsp[-3])); } } -#line 3717 "awkgram.c" /* yacc.c:1646 */ +#line 3941 "awkgram.c" /* yacc.c:1646 */ break; - case 163: -#line 1657 "awkgram.y" /* yacc.c:1646 */ + case 173: +#line 1843 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3723 "awkgram.c" /* yacc.c:1646 */ +#line 3947 "awkgram.c" /* yacc.c:1646 */ break; - case 164: -#line 1659 "awkgram.y" /* yacc.c:1646 */ + case 174: +#line 1845 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3729 "awkgram.c" /* yacc.c:1646 */ +#line 3953 "awkgram.c" /* yacc.c:1646 */ break; - case 165: -#line 1664 "awkgram.y" /* yacc.c:1646 */ + case 175: +#line 1850 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3735 "awkgram.c" /* yacc.c:1646 */ +#line 3959 "awkgram.c" /* yacc.c:1646 */ break; - case 166: -#line 1666 "awkgram.y" /* yacc.c:1646 */ + case 176: +#line 1852 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3741 "awkgram.c" /* yacc.c:1646 */ +#line 3965 "awkgram.c" /* yacc.c:1646 */ break; - case 167: -#line 1671 "awkgram.y" /* yacc.c:1646 */ + case 177: +#line 1857 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3747 "awkgram.c" /* yacc.c:1646 */ +#line 3971 "awkgram.c" /* yacc.c:1646 */ break; - case 168: -#line 1673 "awkgram.y" /* yacc.c:1646 */ + case 178: +#line 1859 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_merge((yyvsp[-1]), (yyvsp[0])); } -#line 3755 "awkgram.c" /* yacc.c:1646 */ +#line 3979 "awkgram.c" /* yacc.c:1646 */ break; - case 169: -#line 1680 "awkgram.y" /* yacc.c:1646 */ + case 179: +#line 1866 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip = (yyvsp[0])->lasti; int count = ip->sub_count; /* # of SUBSEP-seperated expressions */ @@ -3769,11 +3993,11 @@ regular_print: sub_counter++; /* count # of dimensions */ (yyval) = (yyvsp[0]); } -#line 3773 "awkgram.c" /* yacc.c:1646 */ +#line 3997 "awkgram.c" /* yacc.c:1646 */ break; - case 170: -#line 1697 "awkgram.y" /* yacc.c:1646 */ + case 180: +#line 1883 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *t = (yyvsp[-1]); if ((yyvsp[-1]) == NULL) { @@ -3787,31 +4011,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 4015 "awkgram.c" /* yacc.c:1646 */ break; - case 171: -#line 1714 "awkgram.y" /* yacc.c:1646 */ + case 181: +#line 1900 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); } -#line 3797 "awkgram.c" /* yacc.c:1646 */ +#line 4021 "awkgram.c" /* yacc.c:1646 */ break; - case 172: -#line 1716 "awkgram.y" /* yacc.c:1646 */ + case 182: +#line 1902 "awkgram.y" /* yacc.c:1646 */ { (yyval) = list_merge((yyvsp[-1]), (yyvsp[0])); } -#line 3805 "awkgram.c" /* yacc.c:1646 */ +#line 4029 "awkgram.c" /* yacc.c:1646 */ break; - case 173: -#line 1723 "awkgram.y" /* yacc.c:1646 */ + case 183: +#line 1909 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[-1]); } -#line 3811 "awkgram.c" /* yacc.c:1646 */ +#line 4035 "awkgram.c" /* yacc.c:1646 */ break; - case 174: -#line 1728 "awkgram.y" /* yacc.c:1646 */ + case 184: +#line 1914 "awkgram.y" /* yacc.c:1646 */ { char *var_name = (yyvsp[0])->lextok; @@ -3819,22 +4043,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 4047 "awkgram.c" /* yacc.c:1646 */ break; - case 175: -#line 1736 "awkgram.y" /* yacc.c:1646 */ + case 185: +#line 1922 "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 4058 "awkgram.c" /* yacc.c:1646 */ break; - case 176: -#line 1746 "awkgram.y" /* yacc.c:1646 */ + case 186: +#line 1932 "awkgram.y" /* yacc.c:1646 */ { INSTRUCTION *ip = (yyvsp[0])->nexti; if (ip->opcode == Op_push @@ -3846,73 +4070,73 @@ regular_print: } else (yyval) = (yyvsp[0]); } -#line 3850 "awkgram.c" /* yacc.c:1646 */ +#line 4074 "awkgram.c" /* yacc.c:1646 */ break; - case 177: -#line 1758 "awkgram.y" /* yacc.c:1646 */ + case 187: +#line 1944 "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 4084 "awkgram.c" /* yacc.c:1646 */ break; - case 178: -#line 1767 "awkgram.y" /* yacc.c:1646 */ + case 188: +#line 1953 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postincrement; } -#line 3868 "awkgram.c" /* yacc.c:1646 */ +#line 4092 "awkgram.c" /* yacc.c:1646 */ break; - case 179: -#line 1771 "awkgram.y" /* yacc.c:1646 */ + case 189: +#line 1957 "awkgram.y" /* yacc.c:1646 */ { (yyvsp[0])->opcode = Op_postdecrement; } -#line 3876 "awkgram.c" /* yacc.c:1646 */ +#line 4100 "awkgram.c" /* yacc.c:1646 */ break; - case 180: -#line 1774 "awkgram.y" /* yacc.c:1646 */ + case 190: +#line 1960 "awkgram.y" /* yacc.c:1646 */ { (yyval) = NULL; } -#line 3882 "awkgram.c" /* yacc.c:1646 */ +#line 4106 "awkgram.c" /* yacc.c:1646 */ break; - case 182: -#line 1782 "awkgram.y" /* yacc.c:1646 */ + case 192: +#line 1968 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3888 "awkgram.c" /* yacc.c:1646 */ +#line 4112 "awkgram.c" /* yacc.c:1646 */ break; - case 183: -#line 1786 "awkgram.y" /* yacc.c:1646 */ + case 193: +#line 1972 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3894 "awkgram.c" /* yacc.c:1646 */ +#line 4118 "awkgram.c" /* yacc.c:1646 */ break; - case 186: -#line 1795 "awkgram.y" /* yacc.c:1646 */ + case 196: +#line 1981 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3900 "awkgram.c" /* yacc.c:1646 */ +#line 4124 "awkgram.c" /* yacc.c:1646 */ break; - case 187: -#line 1799 "awkgram.y" /* yacc.c:1646 */ + case 197: +#line 1985 "awkgram.y" /* yacc.c:1646 */ { (yyval) = (yyvsp[0]); yyerrok; } -#line 3906 "awkgram.c" /* yacc.c:1646 */ +#line 4130 "awkgram.c" /* yacc.c:1646 */ break; - case 188: -#line 1803 "awkgram.y" /* yacc.c:1646 */ + case 198: +#line 1989 "awkgram.y" /* yacc.c:1646 */ { yyerrok; } -#line 3912 "awkgram.c" /* yacc.c:1646 */ +#line 4136 "awkgram.c" /* yacc.c:1646 */ break; -#line 3916 "awkgram.c" /* yacc.c:1646 */ +#line 4140 "awkgram.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -4140,7 +4364,7 @@ yyreturn: #endif return yyresult; } -#line 1805 "awkgram.y" /* yacc.c:1906 */ +#line 1991 "awkgram.y" /* yacc.c:1906 */ struct token { @@ -4217,9 +4441,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 +4453,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 +4487,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 +4663,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 +4693,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 +4785,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 +4822,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 +4835,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 +4865,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 +5336,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 +5427,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 +5484,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 +5615,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 +5644,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) { @@ -5366,6 +5717,7 @@ yylex(void) lexeme = lexptr; thisline = NULL; + if (want_regexp) { int in_brack = 0; /* count brackets, [[:alnum:]] allowed */ int b_index = -1; @@ -5452,7 +5804,9 @@ end_regexp: peek); } } - return lasttok = REGEXP; + lasttok = REGEXP; + + return lasttok; case '\n': pushback(); yyerror(_("unterminated regexp")); @@ -5488,9 +5842,23 @@ 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; @@ -5502,7 +5870,7 @@ retry: 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 +5887,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 +6109,7 @@ retry: lastline = sourceline; return lasttok = c; } - did_newline++; + did_newline = true; --lexptr; /* pick up } next time */ return lasttok = NEWLINE; @@ -5949,7 +6321,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 +6407,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 +6693,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 +6718,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 +6807,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 +6819,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; @@ -6520,18 +6928,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 +7016,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 */ @@ -6894,6 +7298,7 @@ make_regnode(int type, NODE *exp) } n->re_exp = exp; n->re_flags = CONSTANT; + n->valref = 1; } return n; } @@ -6909,6 +7314,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 +7731,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 +7777,6 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action) action), tp); } - } list_append(rule_list, rp + 1); @@ -7936,6 +8346,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); @@ -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; } ; @@ -440,19 +519,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 +618,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 +904,7 @@ regular_loop: $$ = list_prepend($1, instruction(Op_exec_count)); else $$ = $1; + $$ = add_pending_comment($$); } ; @@ -793,6 +916,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 +926,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 +937,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 +949,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 +965,7 @@ non_compound_stmt $$->nexti->memory = dupnode(Nnull_string); } else $$ = list_append($2, $1); + $$ = add_pending_comment($$); } | LEX_RETURN { @@ -862,6 +990,7 @@ non_compound_stmt $$ = list_append($3, $1); } + $$ = add_pending_comment($$); } | simple_stmt statement_term ; @@ -971,6 +1100,7 @@ regular_print: } } } + $$ = add_pending_comment($$); } | LEX_DELETE NAME { sub_counter = 0; } delete_subscript_list @@ -1005,6 +1135,7 @@ regular_print: $1->expr_count = sub_counter; $$ = list_append(list_append($4, $2), $1); } + $$ = add_pending_comment($$); } | LEX_DELETE '(' NAME ')' /* @@ -1035,9 +1166,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,7 +1242,10 @@ case_value { $$ = $1; } | regexp { - $1->opcode = Op_push_re; + if ($1->memory->type == Node_regex) + $1->opcode = Op_push_re; + else + $1->opcode = Op_push; $$ = $1; } ; @@ -1184,7 +1322,7 @@ opt_param_list : /* empty */ { $$ = NULL; } | param_list - { $$ = $1 ; } + { $$ = $1; } ; param_list @@ -1255,6 +1393,47 @@ 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; } + ; + /* Expressions, not including the comma operator. */ exp : variable assign_operator exp %prec ASSIGNOP @@ -1275,6 +1454,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 +1544,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 +1563,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 +1676,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 +1696,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 +1744,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 +1811,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 +2064,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 +2076,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 +2110,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 +2286,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 +2316,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 +2408,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 +2445,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 +2458,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 +2488,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 +2959,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 +3050,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 +3107,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 +3238,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 +3267,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) { @@ -3027,6 +3340,7 @@ yylex(void) lexeme = lexptr; thisline = NULL; + if (want_regexp) { int in_brack = 0; /* count brackets, [[:alnum:]] allowed */ int b_index = -1; @@ -3113,7 +3427,9 @@ end_regexp: peek); } } - return lasttok = REGEXP; + lasttok = REGEXP; + + return lasttok; case '\n': pushback(); yyerror(_("unterminated regexp")); @@ -3149,9 +3465,23 @@ 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; @@ -3163,7 +3493,7 @@ retry: 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 +3510,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 +3732,7 @@ retry: lastline = sourceline; return lasttok = c; } - did_newline++; + did_newline = true; --lexptr; /* pick up } next time */ return lasttok = NEWLINE; @@ -3610,7 +3944,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 +4030,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 +4316,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 +4341,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 +4430,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 +4442,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; @@ -4181,18 +4551,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 +4639,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 */ @@ -4555,6 +4921,7 @@ make_regnode(int type, NODE *exp) } n->re_exp = exp; n->re_flags = CONSTANT; + n->valref = 1; } return n; } @@ -4570,6 +4937,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 +5354,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 +5400,6 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action) action), tp); } - } list_append(rule_list, rp + 1); @@ -5597,6 +5969,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) { @@ -524,7 +534,7 @@ do_length(int nargs) assert(tmp->type == Node_val); - 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; @@ -2110,22 +2124,12 @@ do_system(int nargs) ; /* leave it alone, full 16 bits */ else if (do_traditional) #ifdef __MINGW32__ - ret = (((unsigned)status) & ~0xC0000000); + ret = (((unsigned)status) & ~0xC0000000); #else ret = (status / 256.0); #endif - else if (WIFEXITED(status)) - ret = WEXITSTATUS(status); /* normal exit */ - else if (WIFSIGNALED(status)) { - bool coredumped = false; -#ifdef WCOREDUMP - coredumped = WCOREDUMP(status); -#endif - /* use 256 since exit values are 8 bits */ - ret = WTERMSIG(status) + - (coredumped ? 512 : 256); - } else - ret = 0; /* shouldn't get here */ + else + ret = sanitize_exit_status(status); } if ((BINMODE & BINMODE_INPUT) != 0) @@ -2146,7 +2150,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 +2162,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,8 +2191,10 @@ do_print(int nargs, int redirtype) fatal(_("attempt to use array `%s' in a scalar context"), array_vname(tmp)); } - if ((tmp->flags & STRCUR) == 0 || (tmp->stfmt != -1 && tmp->stfmt != OFMTidx)) - args_array[i] = format_val(OFMT, OFMTidx, tmp); + if ( (tmp->flags & STRCUR) == 0 + || ( tmp->stfmt != STFMT_UNUSED + && tmp->stfmt != OFMTidx)) + args_array[i] = format_val(OFMT, OFMTidx, tmp); } if (redir_exp != NULL) { @@ -2217,15 +2231,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")); } @@ -2236,6 +2254,11 @@ do_print_rec(int nargs, int redirtype) } else fp = output_fp; + if (errflg) { + update_ERRNO_int(errflg); + return; + } + if (fp == NULL) return; @@ -2329,7 +2352,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); @@ -2360,7 +2383,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); @@ -2393,9 +2416,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; @@ -2414,7 +2437,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); @@ -2430,7 +2453,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); @@ -2449,6 +2472,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. */ @@ -2460,7 +2485,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 */ @@ -2483,7 +2567,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); @@ -2573,7 +2657,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"); @@ -2747,56 +2831,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 */ - - 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; + target = POP_STRING(); /* original string */ - 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); @@ -2808,30 +2884,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; @@ -2849,6 +2925,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 == '&')) { @@ -2895,24 +2972,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; @@ -2959,13 +3044,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; @@ -3021,19 +3106,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; @@ -3042,7 +3137,7 @@ set_how_many: efree(mb_indices); done: - DEREF(s); + DEREF(rep_node); if ((matches == 0 || (flags & LITERAL) != 0) && buf != NULL) { efree(buf); @@ -3052,18 +3147,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); @@ -3234,9 +3329,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; @@ -3271,9 +3366,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; @@ -3313,7 +3408,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; @@ -3345,7 +3440,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; @@ -3377,7 +3472,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; @@ -3406,7 +3501,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); @@ -3431,11 +3526,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; @@ -3452,7 +3547,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; @@ -3464,8 +3559,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) { @@ -3498,14 +3596,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; @@ -3513,11 +3618,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: @@ -3753,6 +3860,125 @@ 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_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 */ @@ -3809,3 +4035,24 @@ mbc_char_count(const char *ptr, size_t numbytes) return sum; } + +/* sanitize_exit_status --- convert a 16 bit Unix exit status into something reasonable */ + +int sanitize_exit_status(int status) +{ + int ret = 0; + + if (WIFEXITED(status)) + ret = WEXITSTATUS(status); /* normal exit */ + else if (WIFSIGNALED(status)) { + bool coredumped = false; +#ifdef WCOREDUMP + coredumped = WCOREDUMP(status); +#endif + /* use 256 since exit values are 8 bits */ + ret = WTERMSIG(status) + (coredumped ? 512 : 256); + } else + ret = 0; /* shouldn't get here */ + + return ret; +} 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.3j. +# 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.3j' -PACKAGE_STRING='GNU Awk 4.1.3j' +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.3j 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.3j:";; + 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.3j +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.3j, 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.3j' + 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.3j, 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.3j +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 3e415c1d..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.3j, 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) @@ -3699,17 +3699,6 @@ 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)); @@ -4024,10 +4013,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 +4247,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 +4269,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 +4309,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 +4319,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 +4398,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 +4407,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 +4508,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 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 c910247d..b60457e9 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -10,6 +10,12 @@ * gawktexi.in: Fix typos, adjust update date. * awkcard.in: Update copyright years. +2016-08-03 Arnold D. Robbins <arnold@skeeve.com> + + Remove typed regexes until they can be done properly. + + * gawk.1, gawktexi.in: Updated. + 2016-08-01 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Mark DJGPP port as unsupported. @@ -18,6 +24,12 @@ * gawktexi.in: Fix a typo. Thanks to Marco Curreli for reporting. +2016-07-23 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Document return value of close on a pipe now like + that of system: exit status, status + 256 for signal, or + status + 512 for signal with core dump. + 2016-07-18 Arnold D. Robbins <arnold@skeeve.com> * gawktexi.in: Fix a typo. Thanks to Antonio Colombo for reporting. @@ -31,6 +43,16 @@ * gawktexi.in (Auto-set): Add example use of multiply function. +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 @@ -39,6 +61,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 @@ -55,6 +86,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 @@ -65,6 +102,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 @@ -97,6 +139,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> @@ -106,6 +150,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 @@ -138,17 +190,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. @@ -162,6 +236,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> @@ -174,6 +253,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. @@ -205,11 +288,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. @@ -235,6 +333,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. @@ -259,15 +364,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. @@ -289,6 +412,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> @@ -296,10 +424,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> @@ -313,6 +448,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. @@ -369,6 +510,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> @@ -377,6 +519,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> @@ -406,7 +549,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> @@ -428,12 +571,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. @@ -465,6 +636,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. @@ -478,6 +654,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. @@ -491,6 +672,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> @@ -532,10 +714,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. @@ -631,6 +828,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. @@ -664,6 +865,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. @@ -678,6 +883,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 @@ -688,6 +905,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. @@ -984,7 +1206,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> @@ -1058,6 +1280,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 bda97de7..a2015629 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 \ @@ -51,7 +51,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 @@ -77,9 +77,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 @@ -93,12 +93,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 96103d72..9c7bbc2e 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 \ @@ -378,7 +378,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/" @@ -882,9 +882,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 @@ -898,12 +898,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 34648bef..16e4b19d 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,27 @@ 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"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 +4080,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 6dcbfc3e..a708ef66 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 @@ -3048,13 +3065,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. @@ -3319,6 +3329,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. @@ -3445,15 +3456,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 @@ -4030,7 +4044,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 ================================ @@ -4104,10 +4118,29 @@ 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/ + + +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 @@ -4178,6 +4211,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. @@ -4439,7 +4473,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'. @@ -4491,11 +4525,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 @@ -5441,6 +5470,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. @@ -5876,7 +5910,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 ================================= @@ -5955,7 +5989,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 @@ -5969,9 +6004,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 @@ -5994,7 +6056,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 @@ -6066,7 +6128,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 @@ -6116,6 +6178,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. @@ -7023,7 +7086,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 ========================================= @@ -7168,11 +7231,23 @@ there is a system problem closing the file or process. In these cases, 'gawk' sets the predefined variable 'ERRNO' to a string describing the problem. - In 'gawk', when closing a pipe or coprocess (input or output), the -return value is the exit status of the command.(2) Otherwise, it is the -return value from the system's 'close()' or 'fclose()' C functions when -closing input or output files, respectively. This value is zero if the -close succeeds, or -1 if it fails. + In 'gawk', starting with version 4.2, when closing a pipe or +coprocess (input or output), the return value is the exit status of the +command, as described in *note Table 5.1: +table-close-pipe-return-values.(2) Otherwise, it is the return value +from the system's 'close()' or 'fclose()' C functions when closing input +or output files, respectively. This value is zero if the close +succeeds, or -1 if it fails. + +Situation Return value from 'close()' +-------------------------------------------------------------------------- +Normal exit of command Command's exit status +Death by signal of command 256 + number of murderous signal +Death by signal of command 512 + number of murderous signal +with core dump +Some kind of error -1 + +Table 5.1: Return values from 'close()' of a pipe The POSIX standard is very vague; it says that 'close()' returns zero on success and a nonzero value otherwise. In general, different @@ -7186,14 +7261,73 @@ Options::), 'gawk' just returns zero when closing a pipe. is called a "zombie," and cleaning up after it is referred to as "reaping." - (2) This is a full 16-bit value as returned by the 'wait()' system -call. See the system manual pages for information on how to decode this -value. + (2) Prior to version 4.2, the return value from closing a pipe or +co-process was the full 16-bit exit value as defined by the 'wait()' +system call. + + +File: gawk.info, Node: Nonfatal, Next: Output Summary, Prev: Close Files And Pipes, Up: Printing + +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: Close Files And Pipes, Up: Printing +File: gawk.info, Node: Output Summary, Next: Output Exercises, Prev: Nonfatal, Up: Printing -5.10 Summary +5.11 Summary ============ * The 'print' statement prints comma-separated expressions. Each @@ -7215,10 +7349,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: @@ -10138,7 +10277,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. @@ -10235,10 +10374,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 @@ -10302,10 +10437,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 @@ -10328,6 +10477,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 @@ -10376,6 +10530,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. @@ -10474,6 +10632,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 @@ -11888,6 +12054,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, @@ -13355,14 +13536,52 @@ 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. + + '"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 @@ -13376,6 +13595,13 @@ 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. + + '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 @@ -19691,9 +19917,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 @@ -19981,8 +20213,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/ @@ -20041,8 +20272,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 @@ -20083,8 +20342,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 @@ -21779,6 +22037,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 @@ -21807,6 +22121,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 @@ -22540,6 +22857,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 @@ -22902,6 +23275,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. @@ -22957,6 +23331,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 @@ -23314,7 +23690,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: @@ -23341,11 +23717,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: @@ -23798,6 +24180,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. @@ -24162,7 +24547,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 -------------------------- @@ -24646,9 +25031,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: -16.4.12 API Variables + '">"' + 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. + + 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 @@ -24665,7 +25119,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 @@ -24717,7 +25171,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 @@ -24752,7 +25206,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 @@ -26080,15 +26534,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 @@ -26166,7 +26622,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 @@ -26501,6 +26957,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 @@ -26550,6 +27009,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 @@ -26560,16 +27022,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: @@ -26603,6 +27065,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 @@ -26994,6 +27461,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 @@ -27512,7 +28007,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 @@ -27554,17 +28051,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. @@ -27595,11 +28097,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 -------------------------------------------- @@ -27654,9 +28157,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. + +'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.2 Additional Configuration Options +B.2.3 Additional Configuration Options -------------------------------------- There are several additional options you may use on the 'configure' @@ -27700,7 +28236,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 @@ -31694,20 +32230,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) @@ -31717,7 +32254,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) @@ -31727,31 +32264,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) @@ -31824,16 +32362,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. @@ -32050,7 +32588,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) @@ -32121,16 +32659,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. @@ -32249,7 +32787,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. @@ -32457,7 +32995,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) @@ -32487,12 +33025,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 326) +* dark corner, FILENAME variable <1>: Auto-set. (line 108) +* dark corner, FNR/NR variables: Auto-set. (line 357) * dark corner, format-control characters: Control Letters. (line 18) * dark corner, format-control characters <1>: Control Letters. (line 93) @@ -32687,12 +33225,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) @@ -32715,7 +33253,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) @@ -32723,9 +33261,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. @@ -32733,7 +33273,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. @@ -32769,12 +33309,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) @@ -32828,14 +33368,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) @@ -32876,7 +33416,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) @@ -32895,7 +33435,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) @@ -32951,7 +33491,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) @@ -32979,7 +33518,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) @@ -33047,8 +33586,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 326) +* FNR variable <1>: Auto-set. (line 118) +* FNR variable, changing: Auto-set. (line 357) * for statement: For Statement. (line 6) * for statement, looping over arrays: Scanning an Array. (line 20) * fork() extension function: Extension Sample Fork. @@ -33100,7 +33639,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) @@ -33151,8 +33690,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) @@ -33173,10 +33712,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) @@ -33188,7 +33727,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) @@ -33218,9 +33757,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. @@ -33230,21 +33769,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) @@ -33298,7 +33843,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) @@ -33326,7 +33871,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) @@ -33348,7 +33893,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) @@ -33430,7 +33975,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. @@ -33486,7 +34033,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. @@ -33559,7 +34106,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) @@ -33580,9 +34127,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) @@ -33619,12 +34166,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) @@ -33636,8 +34183,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) @@ -33657,10 +34204,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) @@ -33687,7 +34232,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) @@ -33696,8 +34241,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 326) +* NR variable <1>: Auto-set. (line 143) +* NR variable, changing: Auto-set. (line 357) * null strings: awk split records. (line 114) * null strings <1>: Regexp Field Splitting. (line 43) @@ -33817,7 +34362,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) @@ -33861,14 +34406,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. @@ -33886,7 +34431,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) @@ -33907,7 +34452,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. @@ -33919,9 +34464,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) @@ -33936,12 +34479,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) @@ -33988,14 +34531,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. @@ -34003,8 +34546,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) @@ -34040,7 +34583,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) @@ -34049,12 +34592,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) @@ -34141,6 +34684,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) @@ -34164,7 +34708,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) @@ -34190,11 +34734,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) @@ -34205,14 +34749,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) @@ -34231,7 +34775,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) @@ -34243,7 +34787,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) @@ -34295,14 +34838,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 324) +* sidebar, Changing NR and FNR: Auto-set. (line 355) * 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. @@ -34324,19 +34867,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) @@ -34386,10 +34929,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) @@ -34461,9 +35004,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) @@ -34533,7 +35076,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) @@ -34567,6 +35110,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. @@ -34589,7 +35134,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. @@ -34609,10 +35154,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) @@ -34643,10 +35189,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) @@ -34683,7 +35229,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) @@ -34713,563 +35259,569 @@ 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 Status145517 -Node: Include Files146194 -Node: Loading Shared Libraries149789 -Node: Obsolete151217 -Node: Undocumented151909 -Node: Invoking Summary152206 -Node: Regexp153866 -Node: Regexp Usage155320 -Node: Escape Sequences157357 -Node: Regexp Operators163371 -Ref: Regexp Operators-Footnote-1170787 -Ref: Regexp Operators-Footnote-2170934 -Node: Bracket Expressions171032 -Ref: table-char-classes173508 -Node: Leftmost Longest176645 -Node: Computed Regexps177948 -Node: GNU Regexp Operators181375 -Node: Case-sensitivity185054 -Ref: Case-sensitivity-Footnote-1187941 -Ref: Case-sensitivity-Footnote-2188176 -Node: Regexp Summary188284 -Node: Reading Files189750 -Node: Records191844 -Node: awk split records192577 -Node: gawk split records197508 -Ref: gawk split records-Footnote-1202048 -Node: Fields202085 -Ref: Fields-Footnote-1204865 -Node: Nonconstant Fields204951 -Ref: Nonconstant Fields-Footnote-1207187 -Node: Changing Fields207391 -Node: Field Separators213319 -Node: Default Field Splitting216017 -Node: Regexp Field Splitting217135 -Node: Single Character Fields220488 -Node: Command Line Field Separator221548 -Node: Full Line Fields224766 -Ref: Full Line Fields-Footnote-1226288 -Ref: Full Line Fields-Footnote-2226334 -Node: Field Splitting Summary226435 -Node: Constant Size228509 -Node: Splitting By Content233087 -Ref: Splitting By Content-Footnote-1237058 -Node: Multiple Line237221 -Ref: Multiple Line-Footnote-1243103 -Node: Getline243282 -Node: Plain Getline245486 -Node: Getline/Variable248125 -Node: Getline/File249274 -Node: Getline/Variable/File250660 -Ref: Getline/Variable/File-Footnote-1252263 -Node: Getline/Pipe252351 -Node: Getline/Variable/Pipe255056 -Node: Getline/Coprocess256189 -Node: Getline/Variable/Coprocess257454 -Node: Getline Notes258194 -Node: Getline Summary260989 -Ref: table-getline-variants261411 -Node: Read Timeout262159 -Ref: Read Timeout-Footnote-1266000 -Node: Command-line directories266058 -Node: Input Summary266962 -Node: Input Exercises270134 -Node: Printing270862 -Node: Print272638 -Node: Print Examples274095 -Node: Output Separators276875 -Node: OFMT278892 -Node: Printf280248 -Node: Basic Printf281033 -Node: Control Letters282607 -Node: Format Modifiers286595 -Node: Printf Examples292610 -Node: Redirection295096 -Node: Special FD301937 -Ref: Special FD-Footnote-1305105 -Node: Special Files305179 -Node: Other Inherited Files305796 -Node: Special Network306797 -Node: Special Caveats307657 -Node: Close Files And Pipes308606 -Ref: Close Files And Pipes-Footnote-1315799 -Ref: Close Files And Pipes-Footnote-2315947 -Node: Output Summary316098 -Node: Output Exercises317096 -Node: Expressions317775 -Node: Values318963 -Node: Constants319641 -Node: Scalar Constants320332 -Ref: Scalar Constants-Footnote-1321196 -Node: Nondecimal-numbers321446 -Node: Regexp Constants324459 -Node: Using Constant Regexps324985 -Node: Variables328148 -Node: Using Variables328805 -Node: Assignment Options330715 -Node: Conversion332588 -Node: Strings And Numbers333112 -Ref: Strings And Numbers-Footnote-1336175 -Node: Locale influences conversions336284 -Ref: table-locale-affects339042 -Node: All Operators339660 -Node: Arithmetic Ops340289 -Node: Concatenation342795 -Ref: Concatenation-Footnote-1345642 -Node: Assignment Ops345749 -Ref: table-assign-ops350740 -Node: Increment Ops352053 -Node: Truth Values and Conditions355513 -Node: Truth Values356587 -Node: Typing and Comparison357635 -Node: Variable Typing358455 -Node: Comparison Operators362079 -Ref: table-relational-ops362498 -Node: POSIX String Comparison365993 -Ref: POSIX String Comparison-Footnote-1367067 -Node: Boolean Ops367206 -Ref: Boolean Ops-Footnote-1371688 -Node: Conditional Exp371780 -Node: Function Calls373516 -Node: Precedence377393 -Node: Locales381052 -Node: Expressions Summary382684 -Node: Patterns and Actions385257 -Node: Pattern Overview386377 -Node: Regexp Patterns388054 -Node: Expression Patterns388596 -Node: Ranges392377 -Node: BEGIN/END395485 -Node: Using BEGIN/END396246 -Ref: Using BEGIN/END-Footnote-1398982 -Node: I/O And BEGIN/END399088 -Node: BEGINFILE/ENDFILE401402 -Node: Empty404309 -Node: Using Shell Variables404626 -Node: Action Overview406900 -Node: Statements409225 -Node: If Statement411073 -Node: While Statement412568 -Node: Do Statement414596 -Node: For Statement415744 -Node: Switch Statement418902 -Node: Break Statement421288 -Node: Continue Statement423380 -Node: Next Statement425207 -Node: Nextfile Statement427590 -Node: Exit Statement430242 -Node: Built-in Variables432645 -Node: User-modified433778 -Ref: User-modified-Footnote-1441403 -Node: Auto-set441465 -Ref: Auto-set-Footnote-1454821 -Ref: Auto-set-Footnote-2455027 -Node: ARGC and ARGV455083 -Node: Pattern Action Summary459296 -Node: Arrays461726 -Node: Array Basics463055 -Node: Array Intro463899 -Ref: figure-array-elements465874 -Ref: Array Intro-Footnote-1468578 -Node: Reference to Elements468706 -Node: Assigning Elements471170 -Node: Array Example471661 -Node: Scanning an Array473420 -Node: Controlling Scanning476442 -Ref: Controlling Scanning-Footnote-1481841 -Node: Numeric Array Subscripts482157 -Node: Uninitialized Subscripts484341 -Node: Delete485960 -Ref: Delete-Footnote-1488712 -Node: Multidimensional488769 -Node: Multiscanning491864 -Node: Arrays of Arrays493455 -Node: Arrays Summary498222 -Node: Functions500315 -Node: Built-in501353 -Node: Calling Built-in502434 -Node: Numeric Functions504430 -Ref: Numeric Functions-Footnote-1508458 -Ref: Numeric Functions-Footnote-2508815 -Ref: Numeric Functions-Footnote-3508863 -Node: String Functions509135 -Ref: String Functions-Footnote-1532639 -Ref: String Functions-Footnote-2532767 -Ref: String Functions-Footnote-3533015 -Node: Gory Details533102 -Ref: table-sub-escapes534893 -Ref: table-sub-proposed536412 -Ref: table-posix-sub537775 -Ref: table-gensub-escapes539316 -Ref: Gory Details-Footnote-1540139 -Node: I/O Functions540293 -Ref: table-system-return-values546875 -Ref: I/O Functions-Footnote-1548855 -Ref: I/O Functions-Footnote-2549003 -Node: Time Functions549123 -Ref: Time Functions-Footnote-1559628 -Ref: Time Functions-Footnote-2559696 -Ref: Time Functions-Footnote-3559854 -Ref: Time Functions-Footnote-4559965 -Ref: Time Functions-Footnote-5560077 -Ref: Time Functions-Footnote-6560304 -Node: Bitwise Functions560570 -Ref: table-bitwise-ops561164 -Ref: Bitwise Functions-Footnote-1565502 -Node: Type Functions565675 -Node: I18N Functions566831 -Node: User-defined568482 -Node: Definition Syntax569287 -Ref: Definition Syntax-Footnote-1574974 -Node: Function Example575045 -Ref: Function Example-Footnote-1577967 -Node: Function Caveats577989 -Node: Calling A Function578507 -Node: Variable Scope579465 -Node: Pass By Value/Reference582459 -Node: Return Statement585958 -Node: Dynamic Typing588937 -Node: Indirect Calls589867 -Ref: Indirect Calls-Footnote-1600118 -Node: Functions Summary600246 -Node: Library Functions602951 -Ref: Library Functions-Footnote-1606558 -Ref: Library Functions-Footnote-2606701 -Node: Library Names606872 -Ref: Library Names-Footnote-1610332 -Ref: Library Names-Footnote-2610555 -Node: General Functions610641 -Node: Strtonum Function611744 -Node: Assert Function614766 -Node: Round Function618092 -Node: Cliff Random Function619633 -Node: Ordinal Functions620649 -Ref: Ordinal Functions-Footnote-1623712 -Ref: Ordinal Functions-Footnote-2623964 -Node: Join Function624174 -Ref: Join Function-Footnote-1625944 -Node: Getlocaltime Function626144 -Node: Readfile Function629886 -Node: Shell Quoting631858 -Node: Data File Management633259 -Node: Filetrans Function633891 -Node: Rewind Function637987 -Node: File Checking639893 -Ref: File Checking-Footnote-1641227 -Node: Empty Files641428 -Node: Ignoring Assigns643407 -Node: Getopt Function644957 -Ref: Getopt Function-Footnote-1656426 -Node: Passwd Functions656626 -Ref: Passwd Functions-Footnote-1665465 -Node: Group Functions665553 -Ref: Group Functions-Footnote-1673450 -Node: Walking Arrays673657 -Node: Library Functions Summary676665 -Node: Library Exercises678071 -Node: Sample Programs678536 -Node: Running Examples679306 -Node: Clones680034 -Node: Cut Program681258 -Node: Egrep Program691187 -Ref: Egrep Program-Footnote-1698699 -Node: Id Program698809 -Node: Split Program702489 -Ref: Split Program-Footnote-1705948 -Node: Tee Program706077 -Node: Uniq Program708867 -Node: Wc Program716293 -Ref: Wc Program-Footnote-1720548 -Node: Miscellaneous Programs720642 -Node: Dupword Program721855 -Node: Alarm Program723885 -Node: Translate Program728740 -Ref: Translate Program-Footnote-1733305 -Node: Labels Program733575 -Ref: Labels Program-Footnote-1736926 -Node: Word Sorting737010 -Node: History Sorting741082 -Node: Extract Program742917 -Node: Simple Sed750446 -Node: Igawk Program753520 -Ref: Igawk Program-Footnote-1767851 -Ref: Igawk Program-Footnote-2768053 -Ref: Igawk Program-Footnote-3768175 -Node: Anagram Program768290 -Node: Signature Program771352 -Node: Programs Summary772599 -Node: Programs Exercises773813 -Ref: Programs Exercises-Footnote-1777942 -Node: Advanced Features778033 -Node: Nondecimal Data780023 -Node: Array Sorting781614 -Node: Controlling Array Traversal782314 -Ref: Controlling Array Traversal-Footnote-1790681 -Node: Array Sorting Functions790799 -Ref: Array Sorting Functions-Footnote-1795890 -Node: Two-way I/O796086 -Ref: Two-way I/O-Footnote-1802380 -Ref: Two-way I/O-Footnote-2802567 -Node: TCP/IP Networking802649 -Node: Profiling805767 -Node: Advanced Features Summary813306 -Node: Internationalization815242 -Node: I18N and L10N816722 -Node: Explaining gettext817409 -Ref: Explaining gettext-Footnote-1823301 -Ref: Explaining gettext-Footnote-2823486 -Node: Programmer i18n823651 -Ref: Programmer i18n-Footnote-1828506 -Node: Translator i18n828555 -Node: String Extraction829349 -Ref: String Extraction-Footnote-1830481 -Node: Printf Ordering830567 -Ref: Printf Ordering-Footnote-1833353 -Node: I18N Portability833417 -Ref: I18N Portability-Footnote-1835873 -Node: I18N Example835936 -Ref: I18N Example-Footnote-1838742 -Node: Gawk I18N838815 -Node: I18N Summary839460 -Node: Debugger840801 -Node: Debugging841823 -Node: Debugging Concepts842264 -Node: Debugging Terms844073 -Node: Awk Debugging846648 -Node: Sample Debugging Session847554 -Node: Debugger Invocation848088 -Node: Finding The Bug849474 -Node: List of Debugger Commands855952 -Node: Breakpoint Control857285 -Node: Debugger Execution Control860979 -Node: Viewing And Changing Data864341 -Node: Execution Stack867715 -Node: Debugger Info869352 -Node: Miscellaneous Debugger Commands873423 -Node: Readline Support878511 -Node: Limitations879407 -Node: Debugging Summary881516 -Node: Arbitrary Precision Arithmetic882689 -Node: Computer Arithmetic884105 -Ref: table-numeric-ranges887696 -Ref: Computer Arithmetic-Footnote-1888418 -Node: Math Definitions888475 -Ref: table-ieee-formats891789 -Ref: Math Definitions-Footnote-1892392 -Node: MPFR features892497 -Node: FP Math Caution894214 -Ref: FP Math Caution-Footnote-1895286 -Node: Inexactness of computations895655 -Node: Inexact representation896615 -Node: Comparing FP Values897975 -Node: Errors accumulate899057 -Node: Getting Accuracy900490 -Node: Try To Round903200 -Node: Setting precision904099 -Ref: table-predefined-precision-strings904796 -Node: Setting the rounding mode906626 -Ref: table-gawk-rounding-modes907000 -Ref: Setting the rounding mode-Footnote-1910408 -Node: Arbitrary Precision Integers910587 -Ref: Arbitrary Precision Integers-Footnote-1913571 -Node: POSIX Floating Point Problems913720 -Ref: POSIX Floating Point Problems-Footnote-1917602 -Node: Floating point summary917640 -Node: Dynamic Extensions919830 -Node: Extension Intro921383 -Node: Plugin License922649 -Node: Extension Mechanism Outline923446 -Ref: figure-load-extension923885 -Ref: figure-register-new-function925450 -Ref: figure-call-new-function926542 -Node: Extension API Description928604 -Node: Extension API Functions Introduction930052 -Node: General Data Types934864 -Ref: General Data Types-Footnote-1940819 -Node: Memory Allocation Functions941118 -Ref: Memory Allocation Functions-Footnote-1943963 -Node: Constructor Functions944062 -Node: Registration Functions945807 -Node: Extension Functions946492 -Node: Exit Callback Functions948791 -Node: Extension Version String950041 -Node: Input Parsers950704 -Node: Output Wrappers960586 -Node: Two-way processors965098 -Node: Printing Messages967363 -Ref: Printing Messages-Footnote-1968437 -Node: Updating ERRNO968590 -Node: Requesting Values969329 -Ref: table-value-types-returned970066 -Node: Accessing Parameters970949 -Node: Symbol Table Access972184 -Node: Symbol table by name972696 -Node: Symbol table by cookie974717 -Ref: Symbol table by cookie-Footnote-1978869 -Node: Cached values978933 -Ref: Cached values-Footnote-1982440 -Node: Array Manipulation982531 -Ref: Array Manipulation-Footnote-1983630 -Node: Array Data Types983667 -Ref: Array Data Types-Footnote-1986325 -Node: Array Functions986417 -Node: Flattening Arrays990275 -Node: Creating Arrays997183 -Node: Extension API Variables1001952 -Node: Extension Versioning1002588 -Ref: gawk-api-version1003025 -Node: Extension API Informational Variables1004781 -Node: Extension API Boilerplate1005845 -Node: Finding Extensions1009659 -Node: Extension Example1010218 -Node: Internal File Description1011016 -Node: Internal File Ops1015096 -Ref: Internal File Ops-Footnote-11026858 -Node: Using Internal File Ops1026998 -Ref: Using Internal File Ops-Footnote-11029381 -Node: Extension Samples1029655 -Node: Extension Sample File Functions1031184 -Node: Extension Sample Fnmatch1038833 -Node: Extension Sample Fork1040320 -Node: Extension Sample Inplace1041538 -Node: Extension Sample Ord1044748 -Node: Extension Sample Readdir1045584 -Ref: table-readdir-file-types1046473 -Node: Extension Sample Revout1047278 -Node: Extension Sample Rev2way1047867 -Node: Extension Sample Read write array1048607 -Node: Extension Sample Readfile1050549 -Node: Extension Sample Time1051644 -Node: Extension Sample API Tests1052992 -Node: gawkextlib1053484 -Node: Extension summary1055908 -Node: Extension Exercises1059600 -Node: Language History1061098 -Node: V7/SVR3.11062754 -Node: SVR41064906 -Node: POSIX1066340 -Node: BTL1067719 -Node: POSIX/GNU1068448 -Node: Feature History1073969 -Node: Common Extensions1087298 -Node: Ranges and Locales1088581 -Ref: Ranges and Locales-Footnote-11093197 -Ref: Ranges and Locales-Footnote-21093224 -Ref: Ranges and Locales-Footnote-31093459 -Node: Contributors1093680 -Node: History summary1099240 -Node: Installation1100620 -Node: Gawk Distribution1101564 -Node: Getting1102048 -Node: Extracting1103009 -Node: Distribution contents1104647 -Node: Unix Installation1110398 -Node: Quick Installation1111014 -Node: Additional Configuration Options1113441 -Node: Configuration Philosophy1115245 -Node: Non-Unix Installation1117614 -Node: PC Installation1118072 -Node: PC Binary Installation1119392 -Node: PC Compiling1121244 -Ref: PC Compiling-Footnote-11124038 -Node: PC Testing1124147 -Node: PC Using1125327 -Ref: PC Using-Footnote-11129480 -Node: Cygwin1129553 -Node: MSYS1130323 -Node: VMS Installation1130824 -Node: VMS Compilation1131615 -Ref: VMS Compilation-Footnote-11132844 -Node: VMS Dynamic Extensions1132902 -Node: VMS Installation Details1134587 -Node: VMS Running1136840 -Node: VMS GNV1141119 -Node: VMS Old Gawk1141854 -Node: Bugs1142325 -Node: Other Versions1146640 -Node: Installation summary1153224 -Node: Notes1154275 -Node: Compatibility Mode1155140 -Node: Additions1155922 -Node: Accessing The Source1156847 -Node: Adding Code1158282 -Node: New Ports1164501 -Node: Derived Files1168989 -Ref: Derived Files-Footnote-11174474 -Ref: Derived Files-Footnote-21174509 -Ref: Derived Files-Footnote-31175107 -Node: Future Extensions1175221 -Node: Implementation Limitations1175879 -Node: Extension Design1177062 -Node: Old Extension Problems1178216 -Ref: Old Extension Problems-Footnote-11179734 -Node: Extension New Mechanism Goals1179791 -Ref: Extension New Mechanism Goals-Footnote-11183155 -Node: Extension Other Design Decisions1183344 -Node: Extension Future Growth1185457 -Node: Old Extension Mechanism1186293 -Node: Notes summary1188056 -Node: Basic Concepts1189238 -Node: Basic High Level1189919 -Ref: figure-general-flow1190201 -Ref: figure-process-flow1190886 -Ref: Basic High Level-Footnote-11194187 -Node: Basic Data Typing1194372 -Node: Glossary1197700 -Node: Copying1229647 -Node: GNU Free Documentation License1267186 -Node: Index1292304 +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 Status146172 +Node: Include Files146849 +Node: Loading Shared Libraries150444 +Node: Obsolete151872 +Node: Undocumented152564 +Node: Invoking Summary152861 +Node: Regexp154521 +Node: Regexp Usage156040 +Node: Escape Sequences158077 +Node: Regexp Operators164309 +Ref: Regexp Operators-Footnote-1171725 +Ref: Regexp Operators-Footnote-2171872 +Node: Bracket Expressions171970 +Ref: table-char-classes174446 +Node: Leftmost Longest177583 +Node: Computed Regexps178886 +Node: GNU Regexp Operators182313 +Node: Case-sensitivity185992 +Ref: Case-sensitivity-Footnote-1188888 +Ref: Case-sensitivity-Footnote-2189123 +Node: Strong Regexp Constants189231 +Node: Regexp Summary190020 +Node: Reading Files191495 +Node: Records193658 +Node: awk split records194391 +Node: gawk split records199322 +Ref: gawk split records-Footnote-1203862 +Node: Fields203899 +Node: Nonconstant Fields206640 +Ref: Nonconstant Fields-Footnote-1208876 +Node: Changing Fields209080 +Node: Field Separators215008 +Node: Default Field Splitting217706 +Node: Regexp Field Splitting218824 +Node: Single Character Fields222177 +Node: Command Line Field Separator223237 +Node: Full Line Fields226455 +Ref: Full Line Fields-Footnote-1227977 +Ref: Full Line Fields-Footnote-2228023 +Node: Field Splitting Summary228124 +Node: Constant Size230198 +Node: Splitting By Content234776 +Ref: Splitting By Content-Footnote-1238747 +Node: Multiple Line238910 +Ref: Multiple Line-Footnote-1244792 +Node: Getline244971 +Node: Plain Getline247437 +Node: Getline/Variable250076 +Node: Getline/File251225 +Node: Getline/Variable/File252611 +Ref: Getline/Variable/File-Footnote-1254214 +Node: Getline/Pipe254302 +Node: Getline/Variable/Pipe257007 +Node: Getline/Coprocess258140 +Node: Getline/Variable/Coprocess259405 +Node: Getline Notes260145 +Node: Getline Summary262940 +Ref: table-getline-variants263362 +Node: Read Timeout264110 +Ref: Read Timeout-Footnote-1268016 +Node: Retrying Input268074 +Node: Command-line directories269273 +Node: Input Summary270179 +Node: Input Exercises273351 +Node: Printing274079 +Node: Print275913 +Node: Print Examples277370 +Node: Output Separators280150 +Node: OFMT282167 +Node: Printf283523 +Node: Basic Printf284308 +Node: Control Letters285882 +Node: Format Modifiers289870 +Node: Printf Examples295885 +Node: Redirection298371 +Node: Special FD305212 +Ref: Special FD-Footnote-1308380 +Node: Special Files308454 +Node: Other Inherited Files309071 +Node: Special Network310072 +Node: Special Caveats310932 +Node: Close Files And Pipes311881 +Ref: table-close-pipe-return-values318788 +Ref: Close Files And Pipes-Footnote-1319571 +Ref: Close Files And Pipes-Footnote-2319719 +Node: Nonfatal319871 +Node: Output Summary322196 +Node: Output Exercises323418 +Node: Expressions324097 +Node: Values325285 +Node: Constants325963 +Node: Scalar Constants326654 +Ref: Scalar Constants-Footnote-1327518 +Node: Nondecimal-numbers327768 +Node: Regexp Constants330781 +Node: Using Constant Regexps331307 +Node: Variables334470 +Node: Using Variables335127 +Node: Assignment Options337037 +Node: Conversion338910 +Node: Strings And Numbers339434 +Ref: Strings And Numbers-Footnote-1342497 +Node: Locale influences conversions342606 +Ref: table-locale-affects345364 +Node: All Operators345982 +Node: Arithmetic Ops346611 +Node: Concatenation349117 +Ref: Concatenation-Footnote-1351964 +Node: Assignment Ops352071 +Ref: table-assign-ops357062 +Node: Increment Ops358375 +Node: Truth Values and Conditions361835 +Node: Truth Values362909 +Node: Typing and Comparison363957 +Node: Variable Typing364777 +Node: Comparison Operators368401 +Ref: table-relational-ops368820 +Node: POSIX String Comparison372315 +Ref: POSIX String Comparison-Footnote-1373389 +Node: Boolean Ops373528 +Ref: Boolean Ops-Footnote-1378010 +Node: Conditional Exp378102 +Node: Function Calls379838 +Node: Precedence383715 +Node: Locales387374 +Node: Expressions Summary389006 +Node: Patterns and Actions391579 +Node: Pattern Overview392699 +Node: Regexp Patterns394376 +Node: Expression Patterns394918 +Node: Ranges398699 +Node: BEGIN/END401807 +Node: Using BEGIN/END402568 +Ref: Using BEGIN/END-Footnote-1405304 +Node: I/O And BEGIN/END405410 +Node: BEGINFILE/ENDFILE407724 +Node: Empty410631 +Node: Using Shell Variables410948 +Node: Action Overview413222 +Node: Statements415547 +Node: If Statement417395 +Node: While Statement418890 +Node: Do Statement420918 +Node: For Statement422066 +Node: Switch Statement425224 +Node: Break Statement427610 +Node: Continue Statement429702 +Node: Next Statement431529 +Node: Nextfile Statement433912 +Node: Exit Statement436564 +Node: Built-in Variables438967 +Node: User-modified440100 +Node: Auto-set447686 +Ref: Auto-set-Footnote-1462339 +Ref: Auto-set-Footnote-2462545 +Node: ARGC and ARGV462601 +Node: Pattern Action Summary466814 +Node: Arrays469244 +Node: Array Basics470573 +Node: Array Intro471417 +Ref: figure-array-elements473392 +Ref: Array Intro-Footnote-1476096 +Node: Reference to Elements476224 +Node: Assigning Elements478688 +Node: Array Example479179 +Node: Scanning an Array480938 +Node: Controlling Scanning483960 +Ref: Controlling Scanning-Footnote-1489359 +Node: Numeric Array Subscripts489675 +Node: Uninitialized Subscripts491859 +Node: Delete493478 +Ref: Delete-Footnote-1496230 +Node: Multidimensional496287 +Node: Multiscanning499382 +Node: Arrays of Arrays500973 +Node: Arrays Summary505740 +Node: Functions507833 +Node: Built-in508871 +Node: Calling Built-in509952 +Node: Numeric Functions511948 +Ref: Numeric Functions-Footnote-1516781 +Ref: Numeric Functions-Footnote-2517138 +Ref: Numeric Functions-Footnote-3517186 +Node: String Functions517458 +Ref: String Functions-Footnote-1540962 +Ref: String Functions-Footnote-2541090 +Ref: String Functions-Footnote-3541338 +Node: Gory Details541425 +Ref: table-sub-escapes543216 +Ref: table-sub-proposed544735 +Ref: table-posix-sub546098 +Ref: table-gensub-escapes547639 +Ref: Gory Details-Footnote-1548462 +Node: I/O Functions548616 +Ref: table-system-return-values555198 +Ref: I/O Functions-Footnote-1557178 +Ref: I/O Functions-Footnote-2557326 +Node: Time Functions557446 +Ref: Time Functions-Footnote-1567951 +Ref: Time Functions-Footnote-2568019 +Ref: Time Functions-Footnote-3568177 +Ref: Time Functions-Footnote-4568288 +Ref: Time Functions-Footnote-5568400 +Ref: Time Functions-Footnote-6568627 +Node: Bitwise Functions568893 +Ref: table-bitwise-ops569487 +Ref: Bitwise Functions-Footnote-1573825 +Node: Type Functions573998 +Node: I18N Functions576530 +Node: User-defined578181 +Node: Definition Syntax578986 +Ref: Definition Syntax-Footnote-1584673 +Node: Function Example584744 +Ref: Function Example-Footnote-1587666 +Node: Function Caveats587688 +Node: Calling A Function588206 +Node: Variable Scope589164 +Node: Pass By Value/Reference592158 +Node: Return Statement595657 +Node: Dynamic Typing598636 +Node: Indirect Calls599566 +Ref: Indirect Calls-Footnote-1609817 +Node: Functions Summary609945 +Node: Library Functions612650 +Ref: Library Functions-Footnote-1616257 +Ref: Library Functions-Footnote-2616400 +Node: Library Names616571 +Ref: Library Names-Footnote-1620031 +Ref: Library Names-Footnote-2620254 +Node: General Functions620340 +Node: Strtonum Function621443 +Node: Assert Function624465 +Node: Round Function627791 +Node: Cliff Random Function629332 +Node: Ordinal Functions630348 +Ref: Ordinal Functions-Footnote-1633411 +Ref: Ordinal Functions-Footnote-2633663 +Node: Join Function633873 +Ref: Join Function-Footnote-1635643 +Node: Getlocaltime Function635843 +Node: Readfile Function639585 +Node: Shell Quoting641557 +Node: Data File Management642958 +Node: Filetrans Function643590 +Node: Rewind Function647686 +Node: File Checking649592 +Ref: File Checking-Footnote-1650926 +Node: Empty Files651127 +Node: Ignoring Assigns653106 +Node: Getopt Function654656 +Ref: Getopt Function-Footnote-1666125 +Node: Passwd Functions666325 +Ref: Passwd Functions-Footnote-1675164 +Node: Group Functions675252 +Ref: Group Functions-Footnote-1683149 +Node: Walking Arrays683356 +Node: Library Functions Summary686364 +Node: Library Exercises687770 +Node: Sample Programs688235 +Node: Running Examples689005 +Node: Clones689733 +Node: Cut Program690957 +Node: Egrep Program700886 +Ref: Egrep Program-Footnote-1708398 +Node: Id Program708508 +Node: Split Program712188 +Ref: Split Program-Footnote-1715647 +Node: Tee Program715776 +Node: Uniq Program718566 +Node: Wc Program725992 +Ref: Wc Program-Footnote-1730247 +Node: Miscellaneous Programs730341 +Node: Dupword Program731554 +Node: Alarm Program733584 +Node: Translate Program738439 +Ref: Translate Program-Footnote-1743004 +Node: Labels Program743274 +Ref: Labels Program-Footnote-1746625 +Node: Word Sorting746709 +Node: History Sorting750781 +Node: Extract Program752616 +Node: Simple Sed760145 +Node: Igawk Program763219 +Ref: Igawk Program-Footnote-1777550 +Ref: Igawk Program-Footnote-2777752 +Ref: Igawk Program-Footnote-3777874 +Node: Anagram Program777989 +Node: Signature Program781051 +Node: Programs Summary782298 +Node: Programs Exercises783512 +Ref: Programs Exercises-Footnote-1787641 +Node: Advanced Features787732 +Node: Nondecimal Data789722 +Node: Array Sorting791313 +Node: Controlling Array Traversal792013 +Ref: Controlling Array Traversal-Footnote-1800380 +Node: Array Sorting Functions800498 +Ref: Array Sorting Functions-Footnote-1805589 +Node: Two-way I/O805785 +Ref: Two-way I/O-Footnote-1812335 +Ref: Two-way I/O-Footnote-2812522 +Node: TCP/IP Networking812604 +Node: Profiling815722 +Ref: Profiling-Footnote-1824215 +Node: Advanced Features Summary824538 +Node: Internationalization826382 +Node: I18N and L10N827862 +Node: Explaining gettext828549 +Ref: Explaining gettext-Footnote-1834441 +Ref: Explaining gettext-Footnote-2834626 +Node: Programmer i18n834791 +Ref: Programmer i18n-Footnote-1839646 +Node: Translator i18n839695 +Node: String Extraction840489 +Ref: String Extraction-Footnote-1841621 +Node: Printf Ordering841707 +Ref: Printf Ordering-Footnote-1844493 +Node: I18N Portability844557 +Ref: I18N Portability-Footnote-1847013 +Node: I18N Example847076 +Ref: I18N Example-Footnote-1849882 +Node: Gawk I18N849955 +Node: I18N Summary850600 +Node: Debugger851941 +Node: Debugging852963 +Node: Debugging Concepts853404 +Node: Debugging Terms855213 +Node: Awk Debugging857788 +Node: Sample Debugging Session858694 +Node: Debugger Invocation859228 +Node: Finding The Bug860614 +Node: List of Debugger Commands867092 +Node: Breakpoint Control868425 +Node: Debugger Execution Control872119 +Node: Viewing And Changing Data875481 +Node: Execution Stack878855 +Node: Debugger Info880492 +Node: Miscellaneous Debugger Commands884563 +Node: Readline Support889651 +Node: Limitations890547 +Ref: Limitations-Footnote-1894778 +Node: Debugging Summary894829 +Node: Arbitrary Precision Arithmetic896108 +Node: Computer Arithmetic897524 +Ref: table-numeric-ranges901115 +Ref: Computer Arithmetic-Footnote-1901837 +Node: Math Definitions901894 +Ref: table-ieee-formats905208 +Ref: Math Definitions-Footnote-1905811 +Node: MPFR features905916 +Node: FP Math Caution907633 +Ref: FP Math Caution-Footnote-1908705 +Node: Inexactness of computations909074 +Node: Inexact representation910034 +Node: Comparing FP Values911394 +Node: Errors accumulate912476 +Node: Getting Accuracy913909 +Node: Try To Round916619 +Node: Setting precision917518 +Ref: table-predefined-precision-strings918215 +Node: Setting the rounding mode920045 +Ref: table-gawk-rounding-modes920419 +Ref: Setting the rounding mode-Footnote-1923827 +Node: Arbitrary Precision Integers924006 +Ref: Arbitrary Precision Integers-Footnote-1928923 +Node: POSIX Floating Point Problems929072 +Ref: POSIX Floating Point Problems-Footnote-1932954 +Node: Floating point summary932992 +Node: Dynamic Extensions935182 +Node: Extension Intro936735 +Node: Plugin License938001 +Node: Extension Mechanism Outline938798 +Ref: figure-load-extension939237 +Ref: figure-register-new-function940802 +Ref: figure-call-new-function941894 +Node: Extension API Description943956 +Node: Extension API Functions Introduction945488 +Node: General Data Types950347 +Ref: General Data Types-Footnote-1956302 +Node: Memory Allocation Functions956601 +Ref: Memory Allocation Functions-Footnote-1959446 +Node: Constructor Functions959545 +Node: Registration Functions961290 +Node: Extension Functions961975 +Node: Exit Callback Functions964598 +Node: Extension Version String965848 +Node: Input Parsers966511 +Node: Output Wrappers976393 +Node: Two-way processors980905 +Node: Printing Messages983170 +Ref: Printing Messages-Footnote-1984341 +Node: Updating ERRNO984494 +Node: Requesting Values985233 +Ref: table-value-types-returned985970 +Node: Accessing Parameters986853 +Node: Symbol Table Access988088 +Node: Symbol table by name988600 +Node: Symbol table by cookie990621 +Ref: Symbol table by cookie-Footnote-1994773 +Node: Cached values994837 +Ref: Cached values-Footnote-1998344 +Node: Array Manipulation998435 +Ref: Array Manipulation-Footnote-1999526 +Node: Array Data Types999563 +Ref: Array Data Types-Footnote-11002221 +Node: Array Functions1002313 +Node: Flattening Arrays1006171 +Node: Creating Arrays1013079 +Node: Redirection API1017848 +Node: Extension API Variables1020679 +Node: Extension Versioning1021312 +Ref: gawk-api-version1021749 +Node: Extension API Informational Variables1023505 +Node: Extension API Boilerplate1024569 +Node: Finding Extensions1028383 +Node: Extension Example1028942 +Node: Internal File Description1029740 +Node: Internal File Ops1033820 +Ref: Internal File Ops-Footnote-11045582 +Node: Using Internal File Ops1045722 +Ref: Using Internal File Ops-Footnote-11048105 +Node: Extension Samples1048379 +Node: Extension Sample File Functions1049908 +Node: Extension Sample Fnmatch1057557 +Node: Extension Sample Fork1059044 +Node: Extension Sample Inplace1060262 +Node: Extension Sample Ord1063472 +Node: Extension Sample Readdir1064308 +Ref: table-readdir-file-types1065197 +Node: Extension Sample Revout1066002 +Node: Extension Sample Rev2way1066591 +Node: Extension Sample Read write array1067331 +Node: Extension Sample Readfile1069273 +Node: Extension Sample Time1070368 +Node: Extension Sample API Tests1071716 +Node: gawkextlib1072208 +Node: Extension summary1074655 +Node: Extension Exercises1078357 +Node: Language History1079855 +Node: V7/SVR3.11081511 +Node: SVR41083663 +Node: POSIX1085097 +Node: BTL1086476 +Node: POSIX/GNU1087205 +Node: Feature History1093067 +Node: Common Extensions1107437 +Node: Ranges and Locales1108720 +Ref: Ranges and Locales-Footnote-11113336 +Ref: Ranges and Locales-Footnote-21113363 +Ref: Ranges and Locales-Footnote-31113598 +Node: Contributors1113819 +Node: History summary1119379 +Node: Installation1120759 +Node: Gawk Distribution1121703 +Node: Getting1122187 +Node: Extracting1123148 +Node: Distribution contents1124786 +Node: Unix Installation1130880 +Node: Quick Installation1131562 +Node: Shell Startup Files1133976 +Node: Additional Configuration Options1135054 +Node: Configuration Philosophy1136859 +Node: Non-Unix Installation1139228 +Node: PC Installation1139686 +Node: PC Binary Installation1141006 +Node: PC Compiling1142858 +Ref: PC Compiling-Footnote-11145652 +Node: PC Testing1145761 +Node: PC Using1146941 +Ref: PC Using-Footnote-11151094 +Node: Cygwin1151167 +Node: MSYS1151937 +Node: VMS Installation1152438 +Node: VMS Compilation1153229 +Ref: VMS Compilation-Footnote-11154458 +Node: VMS Dynamic Extensions1154516 +Node: VMS Installation Details1156201 +Node: VMS Running1158454 +Node: VMS GNV1162733 +Node: VMS Old Gawk1163468 +Node: Bugs1163939 +Node: Other Versions1168254 +Node: Installation summary1174838 +Node: Notes1175889 +Node: Compatibility Mode1176754 +Node: Additions1177536 +Node: Accessing The Source1178461 +Node: Adding Code1179896 +Node: New Ports1186115 +Node: Derived Files1190603 +Ref: Derived Files-Footnote-11196088 +Ref: Derived Files-Footnote-21196123 +Ref: Derived Files-Footnote-31196721 +Node: Future Extensions1196835 +Node: Implementation Limitations1197493 +Node: Extension Design1198676 +Node: Old Extension Problems1199830 +Ref: Old Extension Problems-Footnote-11201348 +Node: Extension New Mechanism Goals1201405 +Ref: Extension New Mechanism Goals-Footnote-11204769 +Node: Extension Other Design Decisions1204958 +Node: Extension Future Growth1207071 +Node: Old Extension Mechanism1207907 +Node: Notes summary1209670 +Node: Basic Concepts1210852 +Node: Basic High Level1211533 +Ref: figure-general-flow1211815 +Ref: figure-process-flow1212500 +Ref: Basic High Level-Footnote-11215801 +Node: Basic Data Typing1215986 +Node: Glossary1219314 +Node: Copying1251261 +Node: GNU Free Documentation License1288800 +Node: Index1313918 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index acf57e50..2dfd067b 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 @@ -4579,14 +4600,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. @@ -4884,6 +4897,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 @@ -4976,6 +5015,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 @@ -5166,17 +5206,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 @@ -6232,6 +6276,25 @@ 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 + @node Regexp Summary @section Summary @@ -6322,6 +6385,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. @@ -6696,16 +6760,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}. @@ -7150,7 +7210,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 @@ -8113,6 +8172,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. @@ -8767,7 +8833,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 @@ -8777,6 +8844,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 @@ -8938,6 +9035,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 @@ -10364,17 +10462,26 @@ a system problem closing the file or process. In these cases, @command{gawk} sets the predefined variable @code{ERRNO} to a string describing the problem. -In @command{gawk}, -when closing a pipe or coprocess (input or output), -the return value is the exit status of the command.@footnote{ -This is a full 16-bit value as returned by the @code{wait()} -system call. See the system manual pages for information on -how to decode this value.} -Otherwise, it is the return value from the system's @code{close()} or -@code{fclose()} C functions when closing input or output -files, respectively. -This value is zero if the close succeeds, or @minus{}1 if -it fails. +In @command{gawk}, starting with version 4.2, when closing a pipe or +coprocess (input or output), the return value is the exit status of the +command, as described in @ref{table-close-pipe-return-values}.@footnote{Prior +to version 4.2, the return value from closing a pipe or co-process +was the full 16-bit exit value as defined by the @code{wait()} system +call.} Otherwise, it is the return value from the system's @code{close()} +or @code{fclose()} C functions when closing input or output files, +respectively. This value is zero if the close succeeds, or @minus{}1 +if it fails. + +@float Table,table-close-pipe-return-values +@caption{Return values from @code{close()} of a pipe} +@multitable @columnfractions .40 .60 +@headitem Situation @tab Return value from @code{close()} +@item Normal exit of command @tab Command's exit status +@item Death by signal of command @tab 256 + number of murderous signal +@item Death by signal of command with core dump @tab 512 + number of murderous signal +@item Some kind of error @tab @minus{}1 +@end multitable +@end float The POSIX standard is very vague; it says that @code{close()} returns zero on success and a nonzero value otherwise. In general, @@ -10421,17 +10528,26 @@ a system problem closing the file or process. In these cases, @command{gawk} sets the predefined variable @code{ERRNO} to a string describing the problem. -In @command{gawk}, -when closing a pipe or coprocess (input or output), -the return value is the exit status of the command.@footnote{ -This is a full 16-bit value as returned by the @code{wait()} -system call. See the system manual pages for information on -how to decode this value.} -Otherwise, it is the return value from the system's @code{close()} or -@code{fclose()} C functions when closing input or output -files, respectively. -This value is zero if the close succeeds, or @minus{}1 if -it fails. +In @command{gawk}, starting with version 4.2, when closing a pipe or +coprocess (input or output), the return value is the exit status of the +command, as described in @ref{table-close-pipe-return-values}.@footnote{Prior +to version 4.2, the return value from closing a pipe or co-process +was the full 16-bit exit value as defined by the @code{wait()} system +call.} Otherwise, it is the return value from the system's @code{close()} +or @code{fclose()} C functions when closing input or output files, +respectively. This value is zero if the close succeeds, or @minus{}1 +if it fails. + +@float Table,table-close-pipe-return-values +@caption{Return values from @code{close()} of a pipe} +@multitable @columnfractions .40 .60 +@headitem Situation @tab Return value from @code{close()} +@item Normal exit of command @tab Command's exit status +@item Death by signal of command @tab 256 + number of murderous signal +@item Death by signal of command with core dump @tab 512 + number of murderous signal +@item Some kind of error @tab @minus{}1 +@end multitable +@end float The POSIX standard is very vague; it says that @code{close()} returns zero on success and a nonzero value otherwise. In general, @@ -10443,6 +10559,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 @@ -10472,6 +10652,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 @@ -14575,12 +14761,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: @@ -14804,10 +14989,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 @@ -14841,6 +15040,11 @@ value to be meaningful when an I/O operation returns a failure value, such as @code{getline} returning @minus{}1. You are, of course, free to clear it yourself before doing an I/O operation. +If the value of @code{ERRNO} corresponds to a system error in the C +@code{errno} variable, then @code{PROCINFO["errno"]} will be set to the value +of @code{errno}. For non-system errors, @code{PROCINFO["errno"]} will +be zero. + @cindex @code{FILENAME} variable @cindex dark corner, @code{FILENAME} variable @item @code{FILENAME} @@ -14909,6 +15113,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. @@ -15032,6 +15240,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. @@ -16972,6 +17188,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 @@ -19250,16 +19483,67 @@ 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 "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 @@ -19277,6 +19561,13 @@ 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. + +@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 @@ -27538,9 +27829,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 @@ -27924,8 +28222,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 @@ -28019,10 +28316,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 @@ -28063,8 +28385,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 @@ -30254,6 +30575,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! @@ -30290,6 +30670,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 @@ -31107,6 +31491,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 @@ -31506,6 +32006,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 @@ -31581,6 +32082,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: @@ -31969,7 +32474,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 @@ -32001,11 +32506,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 @@ -32508,6 +33019,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. @@ -33551,6 +34065,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 @@ -35118,18 +35701,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} @@ -35229,7 +35815,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 @@ -35758,6 +36344,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 @@ -35845,6 +36435,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 @@ -35883,6 +36478,7 @@ The @option{-p}, @option{-P}, @option{-r}, +@option{-s}, @option{-S}, @option{-t}, and @@ -35907,6 +36503,7 @@ and the @option{--load}, @option{--non-decimal-data}, @option{--optimize}, +@option{--no-optimize}, @option{--posix}, @option{--pretty-print}, @option{--profile}, @@ -35977,6 +36574,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 @@ -36603,6 +37210,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 @@ -37269,6 +37922,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 @@ -37313,8 +37968,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 @@ -37325,6 +37978,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. @@ -37356,6 +38015,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 @@ -37436,6 +38096,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 2c94c301..513bb80d 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 @@ -4490,14 +4511,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. @@ -4795,6 +4808,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 @@ -4887,6 +4926,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 @@ -5077,17 +5117,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 @@ -6016,6 +6060,25 @@ 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 + @node Regexp Summary @section Summary @@ -6106,6 +6169,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. @@ -6423,16 +6487,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}. @@ -6846,7 +6906,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 @@ -7713,6 +7772,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. @@ -8367,7 +8433,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 @@ -8377,6 +8444,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 @@ -8538,6 +8635,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 @@ -9918,17 +10016,26 @@ a system problem closing the file or process. In these cases, @command{gawk} sets the predefined variable @code{ERRNO} to a string describing the problem. -In @command{gawk}, -when closing a pipe or coprocess (input or output), -the return value is the exit status of the command.@footnote{ -This is a full 16-bit value as returned by the @code{wait()} -system call. See the system manual pages for information on -how to decode this value.} -Otherwise, it is the return value from the system's @code{close()} or -@code{fclose()} C functions when closing input or output -files, respectively. -This value is zero if the close succeeds, or @minus{}1 if -it fails. +In @command{gawk}, starting with version 4.2, when closing a pipe or +coprocess (input or output), the return value is the exit status of the +command, as described in @ref{table-close-pipe-return-values}.@footnote{Prior +to version 4.2, the return value from closing a pipe or co-process +was the full 16-bit exit value as defined by the @code{wait()} system +call.} Otherwise, it is the return value from the system's @code{close()} +or @code{fclose()} C functions when closing input or output files, +respectively. This value is zero if the close succeeds, or @minus{}1 +if it fails. + +@float Table,table-close-pipe-return-values +@caption{Return values from @code{close()} of a pipe} +@multitable @columnfractions .40 .60 +@headitem Situation @tab Return value from @code{close()} +@item Normal exit of command @tab Command's exit status +@item Death by signal of command @tab 256 + number of murderous signal +@item Death by signal of command with core dump @tab 512 + number of murderous signal +@item Some kind of error @tab @minus{}1 +@end multitable +@end float The POSIX standard is very vague; it says that @code{close()} returns zero on success and a nonzero value otherwise. In general, @@ -9939,6 +10046,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 @@ -9968,6 +10139,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 @@ -13903,12 +14080,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: @@ -14132,10 +14308,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 @@ -14169,6 +14359,11 @@ value to be meaningful when an I/O operation returns a failure value, such as @code{getline} returning @minus{}1. You are, of course, free to clear it yourself before doing an I/O operation. +If the value of @code{ERRNO} corresponds to a system error in the C +@code{errno} variable, then @code{PROCINFO["errno"]} will be set to the value +of @code{errno}. For non-system errors, @code{PROCINFO["errno"]} will +be zero. + @cindex @code{FILENAME} variable @cindex dark corner, @code{FILENAME} variable @item @code{FILENAME} @@ -14237,6 +14432,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. @@ -14360,6 +14559,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. @@ -16254,6 +16461,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 @@ -18371,16 +18595,67 @@ 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 "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 @@ -18398,6 +18673,13 @@ 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. + +@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 @@ -26629,9 +26911,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 @@ -27015,8 +27304,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 @@ -27110,10 +27398,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 @@ -27154,8 +27467,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 @@ -29345,6 +29657,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! @@ -29381,6 +29752,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 @@ -30198,6 +30573,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 @@ -30597,6 +31088,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 @@ -30672,6 +31164,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: @@ -31060,7 +31556,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 @@ -31092,11 +31588,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 @@ -31599,6 +32101,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. @@ -32642,6 +33147,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 @@ -34209,18 +34783,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} @@ -34320,7 +34897,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 @@ -34849,6 +35426,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 @@ -34936,6 +35517,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 @@ -34974,6 +35560,7 @@ The @option{-p}, @option{-P}, @option{-r}, +@option{-s}, @option{-S}, @option{-t}, and @@ -34998,6 +35585,7 @@ and the @option{--load}, @option{--non-decimal-data}, @option{--optimize}, +@option{--no-optimize}, @option{--posix}, @option{--pretty-print}, @option{--profile}, @@ -35068,6 +35656,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 @@ -35694,6 +36292,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 @@ -36360,6 +37004,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 @@ -36404,8 +37050,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 @@ -36416,6 +37060,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. @@ -36447,6 +37097,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 @@ -36527,6 +37178,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); @@ -243,7 +242,6 @@ static const char *const nodetypes[] = { "Node_param_list", "Node_func", "Node_ext_func", - "Node_old_ext_func", "Node_builtin_func", "Node_array_ref", "Node_array_tree", @@ -334,12 +332,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 }, @@ -364,6 +362,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 }, @@ -584,14 +583,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); @@ -700,7 +693,6 @@ void set_IGNORECASE() { static bool warned = false; - NODE *n = IGNORECASE_node->var_value; if ((do_lint || do_traditional) && ! warned) { warned = true; @@ -709,19 +701,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 */ } @@ -732,7 +713,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; @@ -741,7 +722,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) @@ -829,9 +809,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; @@ -949,36 +929,28 @@ set_LINT() { #ifndef NO_LINT int old_lint = do_lint; - NODE *n = LINT_node->var_value; + NODE *n = fixtype(LINT_node->var_value); /* start with clean defaults */ lintfunc = r_warning; do_flags &= ~(DO_LINT_ALL|DO_LINT_INVALID); - 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) { - if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0) - do_flags |= DO_LINT_INVALID; - else { - do_flags |= DO_LINT_ALL; - if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0) - lintfunc = r_fatal; - } - } - } else { - (void) force_number(n); - if (! iszero(n)) + if ((n->flags & STRING) != 0) { + const char *lintval; + size_t lintlen; + + lintval = n->stptr; + lintlen = n->stlen; + if (lintlen > 0) { + if (lintlen == 7 && strncmp(lintval, "invalid", 7) == 0) + do_flags |= DO_LINT_INVALID; + else { do_flags |= DO_LINT_ALL; + if (lintlen == 5 && strncmp(lintval, "fatal", 5) == 0) + lintfunc = r_fatal; + } } - } else if ((n->flags & (NUMCUR|NUMBER)) != 0) { - (void) force_number(n); + } else { if (! iszero(n)) do_flags |= DO_LINT_ALL; } @@ -1017,6 +989,7 @@ update_ERRNO_int(int errcode) { char *cp; + update_PROCINFO_num("errno", errcode); if (errcode) { cp = strerror(errcode); cp = gettext(cp); @@ -1031,6 +1004,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)); } @@ -1040,6 +1014,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); } @@ -1181,7 +1156,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")); @@ -1530,15 +1505,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 6cffec86..c244169f 100644 --- a/int_array.c +++ b/int_array.c @@ -167,49 +167,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; + /* must be a STRING */ + 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; - } - - 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; #endif /* CHECK_INTEGER_USING_FORCE_NUMBER */ } diff --git a/interpret.h b/interpret.h index e9abdffb..6b832c16 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"), @@ -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(); @@ -1078,8 +1080,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 +1091,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 +1117,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 +1130,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 +1412,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 @@ -1164,7 +1227,8 @@ do_close(int nargs) * POSIX says close() returns 0 on success, non-zero otherwise. * For POSIX, at this point we just return 0. Otherwise we * return the exit status of the process or of pclose(), depending. - * This whole business is a mess. + * Down in the call tree of close_redir(), we rationalize the + * value like we do for system(). */ if (do_posix) { unref(tmp); @@ -1206,13 +1270,14 @@ close_rp(struct redirect *rp, two_way_close_type how) #endif /* HAVE_SOCKETS */ (void) iop_close(rp->iop); } else + /* status already sanitized */ status = gawk_pclose(rp); rp->iop = NULL; } } else if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE)) { /* write to pipe */ - status = pclose(rp->output.fp); + status = sanitize_exit_status(pclose(rp->output.fp)); if ((BINMODE & BINMODE_INPUT) != 0) os_setbinmode(fileno(stdin), O_BINARY); @@ -1442,7 +1507,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 +1526,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 +1548,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 +1716,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 +1728,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 +1743,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 +1768,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 +1825,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 +2305,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 +2357,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 +2390,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; } @@ -2390,7 +2521,7 @@ gawk_pclose(struct redirect *rp) /* process previously found, return stored status */ if (rp->pid == -1) return rp->status; - rp->status = wait_any(rp->pid); + rp->status = sanitize_exit_status(wait_any(rp->pid)); rp->pid = -1; return rp->status; } @@ -2479,7 +2610,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 +2620,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 +2636,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 +2686,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 +2750,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 +3205,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 +3237,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 +3248,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 +3580,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 +3662,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 +3739,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 +3892,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 +4031,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 +4059,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 */ @@ -194,6 +194,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) @@ -307,22 +308,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(); @@ -511,9 +500,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); @@ -609,6 +597,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); @@ -911,9 +900,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 * @@ -1013,6 +1033,7 @@ load_procinfo() groupset = NULL; } #endif + load_procinfo_argv(); return PROCINFO_node; } @@ -1183,7 +1204,7 @@ arg_assign(char *arg, bool initing) /* catchsig --- catch signals */ -static RETSIGTYPE +static void catchsig(int sig) { if (sig == SIGFPE) { @@ -1424,7 +1445,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; @@ -1584,6 +1605,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; @@ -1658,6 +1683,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); @@ -329,7 +329,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) @@ -343,20 +343,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; } @@ -375,7 +372,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); @@ -523,11 +520,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 */ @@ -677,9 +672,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); @@ -710,7 +705,7 @@ do_mpfr_func(const char *name, mpfr_prec_t argprec; 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); @@ -777,7 +772,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); @@ -807,7 +802,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); @@ -855,7 +850,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); @@ -1080,25 +1075,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); @@ -1176,7 +1168,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)) @@ -1190,6 +1182,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 20e703bd..139ef1bb 100644 --- a/pc/ChangeLog +++ b/pc/ChangeLog @@ -69,6 +69,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 d30be4de..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.3j" +#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.3j" +#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.3j" +#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,19 @@ #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 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 +48,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 +125,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 +200,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 +326,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 +373,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 +499,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 +520,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,7 +632,7 @@ 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: @@ -686,7 +733,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 +742,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 +753,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 +832,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 +850,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 +893,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 +912,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 +956,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 +981,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 +1010,13 @@ cleanup: indent(pc->exec_count); break; + case Op_comment: + print_comment(pc, 0); + break; + + case Op_list: + break; + default: cant_happen(); } @@ -939,6 +1026,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 +1076,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 +1090,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 +1118,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 +1157,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 +1397,20 @@ 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_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,7 +1442,8 @@ 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; @@ -1313,10 +1455,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 +1467,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 +1707,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 +1735,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 +1762,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; @@ -432,6 +432,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 bf16b002..28b15fa3 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,27 @@ +2016-08-16 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * Makefile.am (arrdbg): New test using adump. + (ARRAYDEBUG_TESTS): New test group requiring ARRAYDEBUG compilation. + (check): Add arraydebug-tests. + (arraydebug-tests): Check $(ARRAYDEBUG_TESTS) when compiled with + ARRAYDEBUG. + * arrdbg.awk: New test using adump to check array type. + +2016-08-14 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * intarray.awk, intarray.ok: Updated. + +2016-08-03 Arnold D. Robbins <arnold@skeeve.com> + + Remove typed regexes until they can be done correctly. + + * typeof1.awk, typeof1.ok: Adjusted. + * typeof3.awk, typeof3.ok: Adjusted. + * gsubind.awk, gsubind.ok: Adjusted. + * Makefile.am (TYPED_RE_TESTS): New macro to hold typed regexp tests. + (dbugtypedre1, dbugtypedre2, typedregex1, typedregex2, + typedregex3): Moved into it. + 2016-08-01 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (ignrcas3): Adjust to check that the el_GR.xxx locale @@ -16,17 +40,61 @@ * ignrcas3.awk, ignrcas3.ok: New files. Based on test code from Norihiro Tanaka <noritnk@kcn.ne.jp>. + * Makefile.am (ignrcas4): New test. + * ignrcas4.awk, ignrcas4.ok: Andrew Schorr's files, renamed. + +2016-07-23 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (status-close): New test. + * status-close.awk, status-close.ok: New files. + 2015-06-17 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (ofmtstrnum): New test. * ofmtstrnum.awk, ofmtstrnum.ok: New files. +2016-07-20 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (EXTRA_DIST): Remove clos1way6.ok2. + (close1way6): Removed test, it will be autogenerated back into + the right place. + * clos1way6.awk: Use gensub on ERRNO to force the right text. + Thanks to Andrew Schorr for the suggestion. + * clos1way6.ok2: Removed. + +2016-07-19 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (clos1way6): Add additional file to check result + against for 32 bit Solaris. Thanks to Dagobert Michelsen for + the report. + * clos1way6.ok2: New file. + +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. @@ -44,6 +112,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. @@ -60,6 +140,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 @@ -110,6 +196,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): @@ -120,10 +211,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. @@ -135,9 +248,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. @@ -187,10 +307,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 @@ -240,6 +415,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). @@ -264,11 +444,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. @@ -294,11 +485,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 @@ -314,6 +532,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. @@ -327,6 +555,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 @@ -347,6 +585,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. @@ -358,6 +624,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. @@ -370,12 +640,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. @@ -427,6 +702,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 @@ -473,6 +758,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. @@ -689,6 +979,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 @@ -705,6 +1001,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 e27dcf65..a0b4f525 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 \ @@ -65,6 +67,7 @@ EXTRA_DIST = \ arrayref.ok \ arraysort.awk \ arraysort.ok \ + arrdbg.awk \ arrymem1.awk \ arrymem1.ok \ arryref2.awk \ @@ -159,6 +162,8 @@ EXTRA_DIST = \ clos1way4.ok \ clos1way5.awk \ clos1way5.ok \ + clos1way6.awk \ + clos1way6.ok \ closebad.awk \ closebad.ok \ clsflnam.awk \ @@ -191,6 +196,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 +241,9 @@ EXTRA_DIST = \ dynlj.ok \ eofsplit.awk \ eofsplit.ok \ + errno.awk \ + errno.in \ + errno.ok \ exit.ok \ exit.sh \ exit2.awk \ @@ -284,6 +301,8 @@ EXTRA_DIST = \ fnparydl-mpfr.ok \ fnparydl.awk \ fnparydl.ok \ + forcenum.awk \ + forcenum.ok \ fordel.awk \ fordel.ok \ fork.awk \ @@ -363,6 +382,8 @@ EXTRA_DIST = \ gensub.ok \ gensub2.awk \ gensub2.ok \ + getfile.awk \ + getfile.ok \ getline.awk \ getline.in \ getline.ok \ @@ -396,6 +417,8 @@ EXTRA_DIST = \ gnureops.ok \ gsubasgn.awk \ gsubasgn.ok \ + gsubind.awk \ + gsubind.ok \ gsubtest.awk \ gsubtest.ok \ gsubtst2.awk \ @@ -445,6 +468,8 @@ EXTRA_DIST = \ ignrcas2.ok \ ignrcas3.awk \ ignrcas3.ok \ + ignrcas4.awk \ + ignrcas4.ok \ ignrcase.awk \ ignrcase.in \ ignrcase.ok \ @@ -487,6 +512,8 @@ EXTRA_DIST = \ inplace3.2.bak.ok \ inputred.awk \ inputred.ok \ + intarray.awk \ + intarray.ok \ intest.awk \ intest.ok \ intformat.awk \ @@ -508,9 +535,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 \ @@ -590,6 +627,10 @@ EXTRA_DIST = \ mpfrsort.ok \ mpfrsqrt.awk \ mpfrsqrt.ok \ + mpfrstrtonum.awk \ + mpfrstrtonum.ok \ + mpgforcenum.awk \ + mpgforcenum.ok \ mtchi18n.awk \ mtchi18n.in \ mtchi18n.ok \ @@ -643,6 +684,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 \ @@ -750,6 +797,8 @@ EXTRA_DIST = \ printfbad3.ok \ printfbad4.awk \ printfbad4.ok \ + printfchar.awk \ + printfchar.ok \ printfloat.awk \ printhuge.awk \ printhuge.ok \ @@ -776,6 +825,10 @@ EXTRA_DIST = \ profile7.ok \ profile8.awk \ profile8.ok \ + profile9.awk \ + profile9.ok \ + profile10.awk \ + profile10.ok \ prt1eval.awk \ prt1eval.ok \ prtoeval.awk \ @@ -785,6 +838,8 @@ EXTRA_DIST = \ rand-mpfr.ok \ rand.awk \ rand.ok \ + randtest.sh \ + randtest.ok \ range1.awk \ range1.in \ range1.ok \ @@ -804,6 +859,9 @@ EXTRA_DIST = \ rebuf.awk \ rebuf.in \ rebuf.ok \ + rebuild.awk \ + rebuild.in \ + rebuild.ok \ redfilnm.awk \ redfilnm.in \ redfilnm.ok \ @@ -904,6 +962,8 @@ EXTRA_DIST = \ sclifin.ok \ shadow.awk \ shadow.ok \ + shadowbuiltin.awk \ + shadowbuiltin.ok \ sigpipe1.awk \ sigpipe1.ok \ sort1.awk \ @@ -943,6 +1003,8 @@ EXTRA_DIST = \ sprintfc.awk \ sprintfc.in \ sprintfc.ok \ + status-close.awk \ + status-close.ok \ strcat1.awk \ strcat1.ok \ strftime.awk \ @@ -950,11 +1012,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 \ @@ -1006,12 +1072,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 \ @@ -1065,7 +1147,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 \ @@ -1091,15 +1173,15 @@ BASIC_TESTS = \ 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 status-close 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 \ @@ -1109,31 +1191,42 @@ UNIX_TESTS = \ fflush getlnhd localenl pid pipeio1 pipeio2 poundbang \ rtlen rtlen01 space strftlng +TYPED_RE_TESTS = \ + dbugtypedre1 dbugtypedre2 \ + typedregex1 typedregex2 typedregex3 + 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 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 ignrcas4 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 sortfor2 sortu split_after_fpat \ + rsstart2 rsstart3 rstest6 shadow shadowbuiltin \ + sortfor sortfor2 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 \ + typeof1 typeof2 typeof3 typeof4 \ + timeout \ watchpoint1 +ARRAYDEBUG_TESTS = arrdbg + EXTRA_TESTS = inftest regtest ignrcas3 INET_TESTS = inetdayu inetdayt inetechu inetecht @@ -1141,7 +1234,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 \ @@ -1149,12 +1242,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: @@ -1201,7 +1294,7 @@ check: msg \ printlang \ basic-msg-start basic basic-msg-end \ unix-msg-start unix-tests unix-msg-end \ - extend-msg-start gawk-extensions extend-msg-end \ + extend-msg-start gawk-extensions arraydebug-tests extend-msg-end \ machine-msg-start machine-tests machine-msg-end \ charset-tests-all \ shlib-msg-start shlib-tests shlib-msg-end \ @@ -1243,6 +1336,12 @@ mpfr-tests: else $(MAKE) $(MPFR_TESTS) ; \ fi +arraydebug-tests: + @if echo $(CFLAGS) | grep ARRAYDEBUG > /dev/null ; then \ + $(MAKE) $(ARRAYDEBUG_TESTS) ; \ + else echo gawk is not compiled to support the array debug tests ; \ + fi + shlib-tests: @if $(AWK) --version | $(AWK) ' /API/ { exit 1 }' ; then \ echo shlib tests not supported on this system ; \ @@ -1422,6 +1521,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 >_$@ @@ -1676,6 +1780,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: $$? >>_$@ @@ -1805,10 +1919,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: @@ -1825,14 +1940,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: @@ -1849,8 +1962,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: @@ -1914,6 +2036,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 @@ -2023,6 +2155,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.; \ @@ -2097,6 +2234,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; \ @@ -2153,6 +2296,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: $$? >>_$@ @@ -2189,6 +2347,12 @@ ignrcas3:: $(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ ; \ fi +arrdbg: + @echo $@ + @$(AWK) -v "okfile=$(srcdir)/$@.ok" -f "$(srcdir)"/$@.awk | grep array_f >_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok +# @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok || exit 0 + # Targets generated for other tests: include Maketests diff --git a/test/Makefile.in b/test/Makefile.in index 0a5595ba..5731487f 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 \ @@ -322,6 +324,7 @@ EXTRA_DIST = \ arrayref.ok \ arraysort.awk \ arraysort.ok \ + arrdbg.awk \ arrymem1.awk \ arrymem1.ok \ arryref2.awk \ @@ -416,6 +419,8 @@ EXTRA_DIST = \ clos1way4.ok \ clos1way5.awk \ clos1way5.ok \ + clos1way6.awk \ + clos1way6.ok \ closebad.awk \ closebad.ok \ clsflnam.awk \ @@ -448,6 +453,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 +498,9 @@ EXTRA_DIST = \ dynlj.ok \ eofsplit.awk \ eofsplit.ok \ + errno.awk \ + errno.in \ + errno.ok \ exit.ok \ exit.sh \ exit2.awk \ @@ -541,6 +558,8 @@ EXTRA_DIST = \ fnparydl-mpfr.ok \ fnparydl.awk \ fnparydl.ok \ + forcenum.awk \ + forcenum.ok \ fordel.awk \ fordel.ok \ fork.awk \ @@ -620,6 +639,8 @@ EXTRA_DIST = \ gensub.ok \ gensub2.awk \ gensub2.ok \ + getfile.awk \ + getfile.ok \ getline.awk \ getline.in \ getline.ok \ @@ -653,6 +674,8 @@ EXTRA_DIST = \ gnureops.ok \ gsubasgn.awk \ gsubasgn.ok \ + gsubind.awk \ + gsubind.ok \ gsubtest.awk \ gsubtest.ok \ gsubtst2.awk \ @@ -702,6 +725,8 @@ EXTRA_DIST = \ ignrcas2.ok \ ignrcas3.awk \ ignrcas3.ok \ + ignrcas4.awk \ + ignrcas4.ok \ ignrcase.awk \ ignrcase.in \ ignrcase.ok \ @@ -744,6 +769,8 @@ EXTRA_DIST = \ inplace3.2.bak.ok \ inputred.awk \ inputred.ok \ + intarray.awk \ + intarray.ok \ intest.awk \ intest.ok \ intformat.awk \ @@ -765,9 +792,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 \ @@ -847,6 +884,10 @@ EXTRA_DIST = \ mpfrsort.ok \ mpfrsqrt.awk \ mpfrsqrt.ok \ + mpfrstrtonum.awk \ + mpfrstrtonum.ok \ + mpgforcenum.awk \ + mpgforcenum.ok \ mtchi18n.awk \ mtchi18n.in \ mtchi18n.ok \ @@ -900,6 +941,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 \ @@ -1007,6 +1054,8 @@ EXTRA_DIST = \ printfbad3.ok \ printfbad4.awk \ printfbad4.ok \ + printfchar.awk \ + printfchar.ok \ printfloat.awk \ printhuge.awk \ printhuge.ok \ @@ -1033,6 +1082,10 @@ EXTRA_DIST = \ profile7.ok \ profile8.awk \ profile8.ok \ + profile9.awk \ + profile9.ok \ + profile10.awk \ + profile10.ok \ prt1eval.awk \ prt1eval.ok \ prtoeval.awk \ @@ -1042,6 +1095,8 @@ EXTRA_DIST = \ rand-mpfr.ok \ rand.awk \ rand.ok \ + randtest.sh \ + randtest.ok \ range1.awk \ range1.in \ range1.ok \ @@ -1061,6 +1116,9 @@ EXTRA_DIST = \ rebuf.awk \ rebuf.in \ rebuf.ok \ + rebuild.awk \ + rebuild.in \ + rebuild.ok \ redfilnm.awk \ redfilnm.in \ redfilnm.ok \ @@ -1161,6 +1219,8 @@ EXTRA_DIST = \ sclifin.ok \ shadow.awk \ shadow.ok \ + shadowbuiltin.awk \ + shadowbuiltin.ok \ sigpipe1.awk \ sigpipe1.ok \ sort1.awk \ @@ -1200,6 +1260,8 @@ EXTRA_DIST = \ sprintfc.awk \ sprintfc.in \ sprintfc.ok \ + status-close.awk \ + status-close.ok \ strcat1.awk \ strcat1.ok \ strftime.awk \ @@ -1207,11 +1269,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 \ @@ -1263,12 +1329,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 \ @@ -1321,7 +1403,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 \ @@ -1347,15 +1429,15 @@ BASIC_TESTS = \ 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 status-close 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 \ @@ -1365,36 +1447,46 @@ UNIX_TESTS = \ fflush getlnhd localenl pid pipeio1 pipeio2 poundbang \ rtlen rtlen01 space strftlng +TYPED_RE_TESTS = \ + dbugtypedre1 dbugtypedre2 \ + typedregex1 typedregex2 typedregex3 + 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 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 ignrcas4 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 sortfor2 sortu split_after_fpat \ + rsstart2 rsstart3 rstest6 shadow shadowbuiltin \ + sortfor sortfor2 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 \ + typeof1 typeof2 typeof3 typeof4 \ + timeout \ watchpoint1 +ARRAYDEBUG_TESTS = arrdbg EXTRA_TESTS = inftest regtest ignrcas3 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 \ @@ -1402,13 +1494,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 @@ -1643,7 +1735,7 @@ check: msg \ printlang \ basic-msg-start basic basic-msg-end \ unix-msg-start unix-tests unix-msg-end \ - extend-msg-start gawk-extensions extend-msg-end \ + extend-msg-start gawk-extensions arraydebug-tests extend-msg-end \ machine-msg-start machine-tests machine-msg-end \ charset-tests-all \ shlib-msg-start shlib-tests shlib-msg-end \ @@ -1685,6 +1777,12 @@ mpfr-tests: else $(MAKE) $(MPFR_TESTS) ; \ fi +arraydebug-tests: + @if echo $(CFLAGS) | grep ARRAYDEBUG > /dev/null ; then \ + $(MAKE) $(ARRAYDEBUG_TESTS) ; \ + else echo gawk is not compiled to support the array debug tests ; \ + fi + shlib-tests: @if $(AWK) --version | $(AWK) ' /API/ { exit 1 }' ; then \ echo shlib tests not supported on this system ; \ @@ -1862,6 +1960,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 >_$@ @@ -2116,6 +2219,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: $$? >>_$@ @@ -2245,10 +2358,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 $@ @@ -2264,14 +2378,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: @@ -2288,8 +2400,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: @@ -2353,6 +2474,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 @@ -2462,6 +2593,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.; \ @@ -2536,6 +2672,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; \ @@ -2592,6 +2733,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: $$? >>_$@ @@ -2627,6 +2783,11 @@ ignrcas3:: AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ ; \ $(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ ; \ fi + +arrdbg: + @echo $@ + @$(AWK) -v "okfile=$(srcdir)/$@.ok" -f "$(srcdir)"/$@.awk | grep array_f >_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok Gt-dummy: # file Maketests, generated from Makefile.am by the Gentests program addcomma: @@ -2644,6 +2805,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: $$? >>_$@ @@ -3329,6 +3495,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: $$? >>_$@ @@ -3376,6 +3547,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: $$? >>_$@ @@ -3511,6 +3687,11 @@ splitwht: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +status-close: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + strcat1: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3521,6 +3702,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: $$? >>_$@ @@ -3621,6 +3807,21 @@ getlnhd: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 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 _$@ + aadelete1: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -3676,6 +3877,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: $$? >>_$@ @@ -3791,6 +3997,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: $$? >>_$@ @@ -3816,6 +4027,11 @@ igncfs: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +ignrcas4: + @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: $$? >>_$@ @@ -3846,11 +4062,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: $$? >>_$@ @@ -3881,6 +4122,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: $$? >>_$@ @@ -3941,6 +4197,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: $$? >>_$@ @@ -3971,6 +4232,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: $$? >>_$@ @@ -4006,6 +4272,31 @@ symtab7: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 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: $$? >>_$@ @@ -4111,6 +4402,7 @@ time: @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ # end of file Maketests +# @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ "$(srcdir)"/$@.ok || exit 0 # Targets generated for other tests: diff --git a/test/Maketests b/test/Maketests index c48b76df..b28a32ab 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: $$? >>_$@ @@ -700,6 +705,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: $$? >>_$@ @@ -747,6 +757,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: $$? >>_$@ @@ -882,6 +897,11 @@ splitwht: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +status-close: + @echo $@ + @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + strcat1: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -892,6 +912,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: $$? >>_$@ @@ -992,6 +1017,21 @@ getlnhd: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 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 _$@ + aadelete1: @echo $@ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @@ -1047,6 +1087,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: $$? >>_$@ @@ -1162,6 +1207,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: $$? >>_$@ @@ -1187,6 +1237,11 @@ igncfs: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +ignrcas4: + @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: $$? >>_$@ @@ -1217,11 +1272,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: $$? >>_$@ @@ -1252,6 +1332,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: $$? >>_$@ @@ -1312,6 +1407,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: $$? >>_$@ @@ -1342,6 +1442,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: $$? >>_$@ @@ -1377,6 +1482,31 @@ symtab7: @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 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/arrdbg.awk b/test/arrdbg.awk new file mode 100644 index 00000000..951acb41 --- /dev/null +++ b/test/arrdbg.awk @@ -0,0 +1,17 @@ +function check(x, exptype, f) { + f[x] + printf "array_f subscript [%s]\n", x + printf "array_f subscript [%s]\n", x > okfile + adump(f, -1) + printf " array_func: %s_array_func\n", exptype > okfile +} + +BEGIN { + check(3.0, "cint") + check(-3, "int") + check("3.0", "str") + split(" 3", f, "|") # create a maybe_num value + check(f[1], "str") + check("0", "cint") + check("-1", "int") +} 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..f10c0193 --- /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 gensub(/number/, "descriptor", 1, 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..fec6cbc6 --- /dev/null +++ b/test/gsubind.awk @@ -0,0 +1,10 @@ +BEGIN { + f = "foo" +# p = @/o/ +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..ca6662e5 --- /dev/null +++ b/test/gsubind.ok @@ -0,0 +1 @@ +fqq @@ -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/ignrcas4.awk b/test/ignrcas4.awk new file mode 100644 index 00000000..e74eea64 --- /dev/null +++ b/test/ignrcas4.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/ignrcas4.ok b/test/ignrcas4.ok new file mode 100644 index 00000000..0d66ea1a --- /dev/null +++ b/test/ignrcas4.ok @@ -0,0 +1,2 @@ +0 +1 diff --git a/test/intarray.awk b/test/intarray.awk new file mode 100644 index 00000000..8785ea9e --- /dev/null +++ b/test/intarray.awk @@ -0,0 +1,19 @@ +BEGIN { + nf = split("5 |05|0x4|00| 5|-0x12| 011|-013|1.0|5.1e1|-5|-05|+2", f, "|") + for (i = 1; i <= nf; i++) { + delete g + g[f[i]] + for (x in g) { + if (x"" != f[i]"") + printf "Error in string test: [%s] != [%s]\n", x, f[i] + } + + delete g + z = f[i]+0 # trigger numeric conversion + g[f[i]] + for (x in g) { + if (x"" != f[i]"") + printf "Error in strnum test: [%s] != [%s]\n", x, f[i] + } + } +} diff --git a/test/intarray.ok b/test/intarray.ok new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/intarray.ok 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/status-close.awk b/test/status-close.awk new file mode 100644 index 00000000..345bea49 --- /dev/null +++ b/test/status-close.awk @@ -0,0 +1,14 @@ +BEGIN { + cat = "cat ; exit 3" + print system("echo xxx | (cat ; exit 4)") + + print "YYY" | cat + + print close(cat) + + echo = "echo boo ; exit 5" + echo | getline boo + print "got", boo + + print close(echo) +} diff --git a/test/status-close.ok b/test/status-close.ok new file mode 100644 index 00000000..ad3c0ce1 --- /dev/null +++ b/test/status-close.ok @@ -0,0 +1,6 @@ +xxx +4 +YYY +3 +got boo +5 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..9db64484 --- /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..c172da5e --- /dev/null +++ b/test/typeof1.ok @@ -0,0 +1,4 @@ +number +untyped +string +array number 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..e31bf602 --- /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..9a897048 --- /dev/null +++ b/test/typeof3.ok @@ -0,0 +1,6 @@ +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 d9d7a4a7..73b30a9a 100644 --- a/vms/ChangeLog +++ b/vms/ChangeLog @@ -93,6 +93,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. |