aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt108
-rw-r--r--ChangeLog1236
-rw-r--r--Checklist4
-rw-r--r--Makefile.am5
-rw-r--r--Makefile.in35
-rw-r--r--NEWS80
-rw-r--r--README_d/ChangeLog4
-rw-r--r--README_d/README.cmake95
-rw-r--r--TODO165
-rw-r--r--aclocal.m41
-rw-r--r--array.c70
-rw-r--r--awk.h162
-rw-r--r--awkgram.c2558
-rw-r--r--awkgram.y788
-rw-r--r--awklib/Makefile.am9
-rw-r--r--awklib/Makefile.in119
-rw-r--r--awklib/eg/lib/intdiv.awk20
-rw-r--r--awklib/eg/prog/pi.awk18
-rw-r--r--builtin.c628
-rw-r--r--cint_array.c50
-rw-r--r--cmake/Toolchain_clang.cmake19
-rw-r--r--cmake/Toolchain_generic.cmake21
-rw-r--r--cmake/Toolchain_mingw32.cmake23
-rw-r--r--cmake/Toolchain_s390.cmake20
-rw-r--r--cmake/auk.icobin0 -> 5190 bytes
-rwxr-xr-xcmake/basictest553
-rwxr-xr-xcmake/configure58
-rw-r--r--cmake/configure.cmake300
-rwxr-xr-xcmake/docmaker100
-rw-r--r--cmake/package.cmake54
-rw-r--r--cmd.h14
-rw-r--r--command.c68
-rw-r--r--command.y90
-rw-r--r--configh.in15
-rwxr-xr-xconfigure968
-rw-r--r--configure.ac65
-rw-r--r--custom.h14
-rw-r--r--debug.c309
-rw-r--r--dfa.c1033
-rw-r--r--dfa.h42
-rw-r--r--doc/CMakeLists.txt95
-rw-r--r--doc/ChangeLog250
-rw-r--r--doc/Makefile.am14
-rw-r--r--doc/Makefile.in30
-rw-r--r--doc/awkcard.in24
-rw-r--r--doc/gawk.1138
-rw-r--r--doc/gawk.info2280
-rw-r--r--doc/gawk.texi1050
-rw-r--r--doc/gawktexi.in951
-rw-r--r--doc/wordlist6
-rw-r--r--eval.c155
-rw-r--r--ext.c178
-rw-r--r--extension/CMakeLists.txt84
-rw-r--r--extension/ChangeLog194
-rw-r--r--extension/configure.ac4
-rw-r--r--extension/filefuncs.c14
-rw-r--r--extension/fnmatch.c8
-rw-r--r--extension/fork.c8
-rw-r--r--extension/inplace.c10
-rw-r--r--extension/ordchr.c8
-rw-r--r--extension/readdir.c8
-rw-r--r--extension/readfile.c12
-rw-r--r--extension/revoutput.c8
-rw-r--r--extension/revtwoway.c8
-rw-r--r--extension/rwarray.c16
-rw-r--r--extension/rwarray0.c16
-rw-r--r--extension/stack.c10
-rw-r--r--extension/testext.c213
-rw-r--r--extras/ChangeLog3
-rw-r--r--extras/Makefile.am29
-rw-r--r--extras/Makefile.in528
-rw-r--r--extras/gawk.csh11
-rw-r--r--extras/gawk.sh31
-rw-r--r--field.c139
-rw-r--r--floatcomp.c10
-rw-r--r--floatmagic.h12
-rw-r--r--gawkapi.c156
-rw-r--r--gawkapi.h77
-rw-r--r--gawkmisc.c10
-rw-r--r--hardregex.txt24
-rw-r--r--helpers/ChangeLog16
-rw-r--r--helpers/testdfa.c53
-rw-r--r--helpers/testnet.c8
-rw-r--r--int_array.c112
-rw-r--r--interpret.h143
-rw-r--r--io.c441
-rw-r--r--localeinfo.c113
-rw-r--r--localeinfo.h54
-rw-r--r--m4/ChangeLog12
-rw-r--r--m4/arch.m437
-rw-r--r--m4/isc-posix.m424
-rw-r--r--main.c99
-rw-r--r--mbsupport.h10
-rw-r--r--missing_d/ChangeLog10
-rw-r--r--missing_d/getaddrinfo.c16
-rw-r--r--missing_d/getaddrinfo.h2
-rw-r--r--missing_d/snprintf.c10
-rw-r--r--mpfr.c246
-rw-r--r--msg.c10
-rw-r--r--node.c178
-rw-r--r--nonposix.h10
-rw-r--r--old-extension/ChangeLog13
-rw-r--r--old-extension/bindarr.c14
-rw-r--r--old-extension/fileop.c12
-rw-r--r--old-extension/sparr.c14
-rw-r--r--old-extension/spec_array.c22
-rw-r--r--pc/ChangeLog8
-rw-r--r--pc/config.h22
-rw-r--r--pc/popen.c2
-rw-r--r--po/CMakeLists.txt133
-rw-r--r--posix/ChangeLog4
-rw-r--r--posix/gawkmisc.c6
-rw-r--r--profile.c451
-rw-r--r--protos.h14
-rw-r--r--random.h10
-rw-r--r--re.c84
-rw-r--r--regcomp.c14
-rw-r--r--regex.h62
-rw-r--r--replace.c12
-rw-r--r--str_array.c115
-rw-r--r--symbol.c40
-rw-r--r--test/CMakeLists.txt90
-rw-r--r--test/ChangeLog314
-rw-r--r--test/Makefile.am221
-rw-r--r--test/Makefile.in370
-rw-r--r--test/Maketests135
-rw-r--r--test/anchor.awk33
-rw-r--r--test/anchor.in3
-rw-r--r--test/anchor.ok6
-rwxr-xr-xtest/arrayind1.awk1
-rw-r--r--test/arrayind2.awk8
-rw-r--r--test/arrayind2.ok2
-rw-r--r--test/arrdbg.awk17
-rw-r--r--test/badargs.ok1
-rw-r--r--test/clos1way6.awk7
-rw-r--r--test/clos1way6.ok3
-rw-r--r--test/dbugeval2.awk4
-rw-r--r--test/dbugeval2.in3
-rw-r--r--test/dbugeval2.ok7
-rw-r--r--test/dbugtypedre1.awk1
-rw-r--r--test/dbugtypedre1.in4
-rw-r--r--test/dbugtypedre1.ok17
-rw-r--r--test/dbugtypedre2.awk1
-rw-r--r--test/dbugtypedre2.in4
-rw-r--r--test/dbugtypedre2.ok15
-rw-r--r--test/dumpvars.ok2
-rw-r--r--test/errno.awk10
-rw-r--r--test/errno.in3
-rw-r--r--test/errno.ok3
-rw-r--r--test/forcenum.awk8
-rw-r--r--test/forcenum.ok7
-rw-r--r--test/getfile.awk35
-rw-r--r--test/getfile.ok17
-rw-r--r--test/gsubind.awk10
-rw-r--r--test/gsubind.ok1
-rw-r--r--test/id.ok3
-rw-r--r--test/ignrcas4.awk7
-rw-r--r--test/ignrcas4.ok2
-rw-r--r--test/intarray.awk19
-rw-r--r--test/intarray.ok0
-rw-r--r--test/lintexp.awk9
-rw-r--r--test/lintexp.ok2
-rw-r--r--test/lintindex.awk10
-rw-r--r--test/lintindex.ok4
-rw-r--r--test/lintint.awk9
-rw-r--r--test/lintint.ok2
-rw-r--r--test/lintlength.awk6
-rw-r--r--test/lintlength.ok2
-rw-r--r--test/lintset.awk5
-rw-r--r--test/lintset.ok1
-rw-r--r--test/mpfrmemok1.ok2
-rw-r--r--test/mpfrsqrt.awk6
-rw-r--r--test/mpfrstrtonum.awk5
-rw-r--r--test/mpfrstrtonum.ok2
-rw-r--r--test/mpgforcenum.awk5
-rw-r--r--test/mpgforcenum.ok1
-rw-r--r--test/nonfatal1.awk6
-rw-r--r--test/nonfatal1.ok2
-rw-r--r--test/nonfatal2.awk5
-rw-r--r--test/nonfatal2.ok1
-rw-r--r--test/nonfatal3.awk6
-rw-r--r--test/nonfatal3.ok1
-rw-r--r--test/printfchar.awk7
-rw-r--r--test/printfchar.ok1
-rw-r--r--test/profile10.awk42
-rw-r--r--test/profile10.ok40
-rw-r--r--test/profile4.ok18
-rw-r--r--test/profile5.ok13026
-rw-r--r--test/profile8.ok30
-rw-r--r--test/profile9.awk9
-rw-r--r--test/profile9.ok14
-rw-r--r--test/rand.ok2
-rw-r--r--test/randtest.ok0
-rwxr-xr-xtest/randtest.sh113
-rw-r--r--test/rebuild.awk5
-rw-r--r--test/rebuild.in1
-rw-r--r--test/rebuild.ok2
-rw-r--r--test/shadowbuiltin.awk10
-rw-r--r--test/shadowbuiltin.ok2
-rw-r--r--test/status-close.awk14
-rw-r--r--test/status-close.ok6
-rw-r--r--test/strnum2.awk18
-rw-r--r--test/strnum2.ok4
-rw-r--r--test/strtonum1.awk5
-rw-r--r--test/strtonum1.ok2
-rw-r--r--test/symtab6.ok2
-rw-r--r--test/symtab8.ok2
-rw-r--r--test/testext.ok12
-rw-r--r--test/timeout.awk26
-rw-r--r--test/timeout.ok12
-rw-r--r--test/typedregex1.awk296
-rw-r--r--test/typedregex1.ok37
-rw-r--r--test/typedregex2.awk11
-rw-r--r--test/typedregex2.ok4
-rw-r--r--test/typedregex3.awk11
-rw-r--r--test/typedregex3.ok4
-rw-r--r--test/typeof1.awk9
-rw-r--r--test/typeof1.ok4
-rw-r--r--test/typeof2.awk20
-rw-r--r--test/typeof2.ok6
-rw-r--r--test/typeof3.awk19
-rw-r--r--test/typeof3.ok6
-rw-r--r--test/typeof4.awk13
-rw-r--r--test/typeof4.ok1
-rw-r--r--verify.h279
-rw-r--r--vms/ChangeLog13
-rw-r--r--vms/vms_gawk.c2
227 files changed, 23381 insertions, 11664 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)
diff --git a/ChangeLog b/ChangeLog
index 7d3b0f0e..986b8561 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,11 +5,17 @@
* nonposix.h (w32_maybe_set_errno) [__MINGW32__]: Add prototype.
+2016-11-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ * eval.c (flags2str): Add NO_EXT_SET and NUMCONSTSTR.
+
2016-10-31 Arnold D. Robbins <arnold@skeeve.com>
Fix valgrind issues.
* io.c (init_awkpath): Need to allocate max_path+3 pointers.
+ * awkgram.y (make_profile_number): Need to add STRCUR flag and
+ set n->stfmt to STFMT_UNUSED. See the comment in the code.
2016-10-26 Arnold D. Robbins <arnold@skeeve.com>
@@ -21,12 +27,77 @@
null elements represent the current directory. Sheesh.
Bug reported by "Jun T." <takimoto-j@kba.biglobe.ne.jp>.
+ Disallow negative arguments to the bitwise functions.
+
+ * NEWS: Document this.
+ * builtin.c (do_lshift, do_rshift, do_and, do_or, do_xor, do_compl):
+ Make negative arguments a fatal error.
+ * mpfr.c (do_mpfr_compl, get_intval): Ditto.
+
+2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * General: Remove trailing whitespace from all relevant files.
+ * mpfr.c: Replace Unicode sequences with ASCII.
+ * cint_array.c: Ditto.
+
+2016-10-16 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awkgram.y: Typo fix in call to add_sign_to_num.
+
+2016-10-16 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awk.h (enum opcodeval): Add Op_unary_plus.
+ * awkgram.y (add_sign_to_num): New routine to put in a sign on
+ profiling constants. Call it as necessary.
+ In unary plus production, use new opcode, or set up a
+ constant as for unary minus.
+ (negate_num): Call add_sign_to_num instead of doing it directly.
+ * eval.c (optypetab): Add entry for Op_unary_plus.
+ * interpret.h (r_interpret): Add case for Op_unary_plus.
+ * profile.c (pprint, prec_level, is_scalar): Ditto.
+
+2016-10-13 Arnold D. Robbins <arnold@skeeve.com>
+
+ * dfa.c: Sync with GNULIB.
+
+2016-10-12 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awkgram.y (make_profile_number): Allocate an extra byte for the
+ string, so there's room for a minus if necessary. Store '\0'
+ in the right place.
+ (negate_num): Use memmove to shift the string up and then
+ insert a minus, instead of doing a fresh alloc + copy + free.
+
+2016-10-11 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awk.h (NUMCONSTSTR): New flag value.
+ * awkgram.y (make_profile_number): New function. Use it
+ wherever we make a number. This calls make_number and then, if
+ pretty printing, save the original string value and sets NUMCONSTSTR.
+ (negate_num): If NUNCONSTSTR set, update the saved string value.
+ * profile.c (pp_number): Assert NUMCONSSTR set, use that value.
+ Remove previous code.
+
2016-09-24 Eli Zaretskii <eliz@gnu.org>
* debug.c (restart) [__MINGW32__]: Cast 2nd argument of execvp to
avoid compiler warnings about prototype mismatch. Reported by
Marc de Bourget <marcdebourget@gmail.com>.
+2016-09-09 Norihiro Tanaka <noritnk@kcn.ne.jp>
+
+ * awk.h (struct Regexp): Remove member has_anchor. All uses removed.
+ * re.c (make_regexp, research): Use dfa matcher for regex with anchor.
+
+2016-09-09 Arnold D. Robbins <arnold@skeeve.com>
+
+ * dfa.c: Sync with grep.
+
+2016-09-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ * dfa.c, dfa.h: Sync with grep.
+ * re.c (make_regexp): Adjust to DFA API changes.
+
2016-09-08 Arnold D. Robbins <arnold@skeeve.com>
* command.y: Update license text to version 3. Oops.
@@ -37,6 +108,65 @@
GPLv3+ and with correct FSF address. Thanks to
David Kaspar <dkaspar@redhat.com> for pointing out the need.
+2016-09-02 Arnold D. Robbins <arnold@skeeve.com>
+
+ * dfa.c: Sync with grep.
+
+2016-09-01 Arnold D. Robbins <arnold@skeeve.com>
+
+ Merge grep's now thread-safe dfa. Wheee.
+
+ * dfa.h, dfa.c: Sync with grep.
+ * localeinfo.h, localeinfo.c, verify.h: New files.
+ * Makefile.am (base_sources): Adjust.
+ * awk.h (using_utf8): Declare new function.
+ * node.c (str2wstr): Use using_utf8 instead of now-gone dfa function.
+ * re.c: Include "localeinfo.h".
+ (localeinfo): New static variable.
+ (make_regexp): Adjust call to dfa_syntax.
+ (resetup): Call init_localeinfo on localeinfo. Remove call to
+ now-gone function dfa_init.
+ (using_utf8): New function.
+
+2016-08-29 Arnold D. Robbins <arnold@skeeve.com>
+
+ * configure.ac (fwrite_unlocked): Check for it.
+ * awk.h (fwrite): Define to fwrite_unlocked if we have it.
+ * NEWS: Make note of speed improvement.
+
+2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
+
+ POSIX now says use strcmp for == and !=. Thanks to Chet Ramey
+ for pointing me at the change. Make it so:
+
+ * awk.h (cmp_nodes): New 3rd param indicating strcmp, not strcoll.
+ * debug.c (cmp_val): Update call to cmp_nodes.
+ * eval.c (cmp_nodes): New 3rd param indicating strcmp, not strcoll.
+ Adjust code and all callers.
+ (scalar_cmp_t): New enum type. Used in ...
+ (cmp_scalars): ... in order to call cmp_nodes correctly.
+ * interpret.h: Use the enum type in calls to cmp_scalars.
+ * re.c (re_update): Adjust call to cmp_nodes.
+
+2016-08-25 Norihiro Tanaka <noritnk@kcn.ne.jp>
+
+ * awk.h (struct Regexp): Remove dfa. Now dfareg instead of it. All
+ referers changed.
+ * re.c (research): Arrange caller of dfaexec and research.
+ * (avoid_dfa): Removed. All callers changed.
+ * awk.h (avoid_dfa): Removed.
+
+ Other changes by Arnold Robbins:
+
+ * awk.h (struct Regexp): Change various boolean members to bool.
+ (RE_NO_FLAGS): New #define.
+ * interpret.h: Use RE_NO_FLAGS instead of zero.
+ * re.c (research): Prettify the logic a little bit.
+
+2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
+
+ * dfa.c: Sync with grep.
+
2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
* 4.1.4: Release tar ball made.
@@ -59,6 +189,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
@@ -85,6 +221,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.
@@ -118,6 +276,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
@@ -162,6 +331,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
@@ -182,6 +366,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.
@@ -192,6 +456,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.
@@ -202,10 +482,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>
@@ -242,6 +622,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
@@ -290,6 +680,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.
@@ -302,12 +699,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
@@ -383,6 +788,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
@@ -400,12 +814,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
@@ -437,6 +893,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.
@@ -485,6 +946,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
@@ -546,6 +1044,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
@@ -558,6 +1062,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
@@ -595,6 +1104,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
@@ -721,6 +1236,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.
@@ -734,6 +1341,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.
@@ -758,6 +1375,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
@@ -768,6 +1396,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.
@@ -792,6 +1428,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.
@@ -824,6 +1465,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.
@@ -837,6 +1493,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
@@ -850,6 +1514,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).
@@ -871,6 +1552,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
@@ -912,6 +1602,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.
@@ -928,6 +1639,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.
@@ -942,6 +1659,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.
@@ -953,6 +1674,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.
@@ -967,6 +1706,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.
@@ -974,6 +1733,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.
@@ -997,6 +1770,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,
@@ -1059,6 +1860,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.
@@ -1076,6 +1882,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.
@@ -1094,6 +1916,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.
@@ -1198,6 +2138,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.
@@ -1220,6 +2190,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.
@@ -1281,12 +2261,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
@@ -1359,6 +2362,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 ...
@@ -1420,6 +2462,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.
@@ -1444,6 +2507,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
@@ -1515,6 +2585,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
@@ -1537,6 +2613,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.
@@ -1551,6 +2642,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:
@@ -1671,6 +2769,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
@@ -2037,6 +3142,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
@@ -2054,6 +3164,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.
@@ -2073,6 +3188,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
@@ -2154,6 +3276,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.
@@ -2162,6 +3290,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.
@@ -2170,6 +3308,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 ...
@@ -2180,6 +3336,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
@@ -2190,6 +3385,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/Checklist b/Checklist
index b33fac65..f180522d 100644
--- a/Checklist
+++ b/Checklist
@@ -1,4 +1,4 @@
-Fri Aug 12 11:39:43 IDT 2016
+Wed Nov 2 05:40:56 IST 2016
============================
A checklist for making releases
@@ -30,6 +30,7 @@ doc/gawk.1 is up to date
doc/awkcard.in is up to date
Run prepinfo on the manual.
Spell check the manual.
+Update the wordlist for spell checking.
test/Makefile.am: order and prettify lists of tests
API Version numbers have been modified correctly in gawkapi.h.
@@ -39,6 +40,7 @@ Testing on
make maintainer-clean
make release
+ compile with tcc
compile with pcc
compile with clang
diff --git a/Makefile.am b/Makefile.am
index 8660c111..9acae0bc 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
@@ -109,6 +109,8 @@ base_sources = \
gettext.h \
int_array.c \
interpret.h \
+ localeinfo.c \
+ localeinfo.h \
io.c \
mbsupport.h \
main.c \
@@ -126,6 +128,7 @@ base_sources = \
replace.c \
str_array.c \
symbol.c \
+ verify.h \
version.c \
xalloc.h
diff --git a/Makefile.in b/Makefile.in
index afb9bdc7..f103a420 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 \
@@ -143,10 +143,11 @@ am__objects_1 = array.$(OBJEXT) awkgram.$(OBJEXT) builtin.$(OBJEXT) \
dfa.$(OBJEXT) eval.$(OBJEXT) ext.$(OBJEXT) field.$(OBJEXT) \
floatcomp.$(OBJEXT) gawkapi.$(OBJEXT) gawkmisc.$(OBJEXT) \
getopt.$(OBJEXT) getopt1.$(OBJEXT) int_array.$(OBJEXT) \
- io.$(OBJEXT) main.$(OBJEXT) mpfr.$(OBJEXT) msg.$(OBJEXT) \
- node.$(OBJEXT) profile.$(OBJEXT) random.$(OBJEXT) re.$(OBJEXT) \
- regex.$(OBJEXT) replace.$(OBJEXT) str_array.$(OBJEXT) \
- symbol.$(OBJEXT) version.$(OBJEXT)
+ localeinfo.$(OBJEXT) io.$(OBJEXT) main.$(OBJEXT) \
+ mpfr.$(OBJEXT) msg.$(OBJEXT) node.$(OBJEXT) profile.$(OBJEXT) \
+ random.$(OBJEXT) re.$(OBJEXT) regex.$(OBJEXT) \
+ replace.$(OBJEXT) str_array.$(OBJEXT) symbol.$(OBJEXT) \
+ version.$(OBJEXT)
am_gawk_OBJECTS = $(am__objects_1)
gawk_OBJECTS = $(am_gawk_OBJECTS)
gawk_LDADD = $(LDADD)
@@ -262,9 +263,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 +488,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
@@ -518,6 +519,8 @@ base_sources = \
gettext.h \
int_array.c \
interpret.h \
+ localeinfo.c \
+ localeinfo.h \
io.c \
mbsupport.h \
main.c \
@@ -535,6 +538,7 @@ base_sources = \
replace.c \
str_array.c \
symbol.c \
+ verify.h \
version.c \
xalloc.h
@@ -681,6 +685,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int_array.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localeinfo.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpfr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg.Po@am__quote@
diff --git a/NEWS b/NEWS
index c149dfd7..a06db845 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,86 @@
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.
+
+20. Gawk now uses fwrite_unlocked if it's available. The yields a 7% - 18%
+ improvement in raw output speed (gawk '{ print }' on a large file).
+
+21. Pretty printing now uses the original text of constant numeric values for
+ pretty printing and profiling.
+
+22. Passing negative operands to any of the bitwise functions now
+ produces a fatal error.
+
Changes from 4.1.3 to 4.1.4
---------------------------
diff --git a/README_d/ChangeLog b/README_d/ChangeLog
index da3ced84..496195f9 100644
--- a/README_d/ChangeLog
+++ b/README_d/ChangeLog
@@ -31,6 +31,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.
+
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..bafb82c8
--- /dev/null
+++ b/TODO
@@ -0,0 +1,165 @@
+Fri Jun 19 12:44:56 IDT 2015
+============================
+
+There were too many files tracking different thoughts and ideas for
+things to do, or consider doing. This file merges them into one. As
+tasks are completed, they should be removed.
+
+This file should exist only in the master branch or branches based off
+of it for development, but not in the stable branch. This may require some
+careful work with Git.
+
+TODO
+====
+
+Minor Cleanups and Code Improvements
+------------------------------------
+
+ API:
+ ??? #if !defined(GAWK) && !defined(GAWK_OMIT_CONVENIENCE_MACROS)
+
+ ?? Add debugger commands to reference card
+
+ Look at function order within files.
+
+ Consider removing use of and/or need for the protos.h file.
+
+ Recheck if gnulib regex can be dropped in
+
+ Fully synchronize whitespace tests (for \s, \S in Unicode
+ environment) with those of GNU grep.
+
+ See if something like b = a "" can be optimized to not do
+ a concatenation, but instead just set STRCUR on a.
+
+Minor New Features
+------------------
+
+ Enable command line source text in the debugger.
+
+ Enhance extension/fork.c waitpid to allow the caller to specify
+ the options. And add an optional array argument to wait and
+ waitpid in which to return exit status information.
+
+ Consider relaxing the strictness of --posix.
+
+ ? Add an optional base to strtonum, allowing 2-36.
+
+ ? Optional third argument for index indicating where to start the
+ search.
+
+Major New Features
+------------------
+
+ Think about how to generalize indirect access. Manuel Collado
+ suggests things like
+
+ foo = 5
+ @"foo" += 4
+
+ Also needed:
+
+ Indirect through array elements, not just scalar variables
+
+ Add ability to do decimal arithmetic.
+
+ Rework management of array index storage. (Partially DONE.)
+
+ Consider using an atom table for all string array indices.
+
+ DBM storage of awk arrays. Try to allow multiple dbm packages.
+
+ ?? A RECLEN variable for fixed-length record input. PROCINFO["RS"]
+ would be "RS" or "RECLEN" depending upon what's in use.
+ *** Could this be done as an extension?
+
+ ?? Use a new or improved dfa and/or regex library.
+
+ Rewrite in C++.
+
+Things To Think About That May Never Happen
+-------------------------------------------
+
+ Consider making shadowed variables a warning and not
+ a fatal warning when --lint=fatal.
+
+ Similar for extra parameters in a function call.
+
+ Look at code coverage tools, like S2E: https://s2e.epfl.ch/
+
+ Try running with diehard. See http://www.diehard-software.org,
+ https://github.com/emeryberger/DieHard
+
+ Implement namespaces. Arnold suggested the following in an email:
+ - Extend the definition of an 'identifier' to include "." as a valid
+ character although an identifier can't start with it.
+ - Extension libraries install functions and global variables with names
+ that have a "." in them: XML.parse(), XML.name, whatever.
+ - Awk code can read/write such variables and call such functions,
+ but they cannot define such functions
+ function XML.foo() { .. } # error
+ or create a variable with such a name if it doesn't exist. This would
+ be a run-time error, not a parse-time error.
+ - This last rule may be too restrictive.
+ I don't want to get into fancy rules a la perl and file-scope visibility
+ etc, I'd like to keep things simple. But how we design this is going
+ to be very important.
+
+ Include a sample rpm spec file in a new packaging subdirectory.
+ (Really needed?)
+
+ Patch lexer for @include and @load to make quotes optional.
+ (Really needed?)
+
+ Add a lint check if the return value of a function is used but
+ the function did not supply a value.
+
+ Consider making gawk output +nan for NaN values so that it
+ will accept its own output as input.
+ NOTE: Investigated this. GLIBC formats NaN as '-nan'
+ and -NaN as 'nan'. Dealing with this is not simple.
+
+ Enhance FIELDWIDTHS with some way to indicate "the rest of the record".
+ E.g., a length of 0 or -1 or something. Maybe "n"?
+
+ Review the bash source script for working with shared libraries in
+ order to nuke the use of libtool. [ Partially started in the
+ dead-branches/nolibtool branch. ]
+
+Things That We Decided We Will Never Do
+=======================================
+
+ Consider moving var_value info into Node_var itself to reduce
+ memory usage. This would break all uses of get_lhs in the
+ code. It's too sweeping a change.
+
+ Add macros for working with flags instead of using & and |
+ directly.
+
+ FIX regular field splitting to use FPAT algorithm.
+ Note: Looked at this. Not sure it's with the trouble:
+ If it ain't broke...
+
+ Scope IDs for IPv6 addresses
+
+ Gnulib
+
+ Make FIELDWIDTHS be an array?
+
+ "Do an optimization pass over parse tree?"
+ This isn't relevant now that we are using a byte code engine.
+
+ "Consider integrating Fred Fish's DBUG library into gawk."
+ I did this once as an experiment. But I don't see a lot of value
+ to this at this stage of the development. Stepping through things
+ in a debugger is generally enough. Also, I would have to try to
+ track down the latest version of this.
+
+ "Make awk '/foo/' files... run at egrep speeds" (How?)
+ This has been on the list since the early days (gawk 1.x or early
+ 2.x). But I am not sure how to really do this, nor have I done
+ timings, nor does there seem to be any real demand for this.
+
+ Change from dlopen to using the libltdl library (i.e. lt_dlopen).
+ This may support more platforms. If we move off of libtool
+ then this is the wrong direction.
diff --git a/aclocal.m4 b/aclocal.m4
index c150e9a8..2e07e0a8 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -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])
diff --git a/array.c b/array.c
index 8c9cc72e..85377081 100644
--- a/array.c
+++ b/array.c
@@ -2,23 +2,23 @@
* array.c - routines for awk arrays.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2014, 2016,
* 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
@@ -102,7 +102,7 @@ make_array()
/* vname, flags, and parent_array not set here */
return array;
-}
+}
/* null_array --- force symbol to be an empty typeless array */
@@ -150,7 +150,7 @@ null_lookup(NODE *symbol, NODE *subs)
return symbol->alookup(symbol, subs);
}
-/* null_length --- default function for array length interface */
+/* null_length --- default function for array length interface */
NODE **
null_length(NODE *symbol, NODE *subs ATTRIBUTE_UNUSED)
@@ -198,7 +198,7 @@ assoc_copy(NODE *symbol, NODE *newsymb)
void
assoc_dump(NODE *symbol, NODE *ndump)
{
- if (symbol->adump)
+ if (symbol->adump)
(void) symbol->adump(symbol, ndump);
}
@@ -229,7 +229,7 @@ make_aname(const NODE *symbol)
max_alen = alen + SLEN;
emalloc(aname, char *, (max_alen + 1) * sizeof(char *), "make_aname");
} else if (alen > max_alen) {
- max_alen = alen + SLEN;
+ max_alen = alen + SLEN;
erealloc(aname, char *, (max_alen + 1) * sizeof(char *), "make_aname");
}
memcpy(aname, symbol->vname, alen + 1);
@@ -258,11 +258,11 @@ array_vname(const NODE *symbol)
const NODE *save_symbol = symbol;
const char *from = _("from %s");
const char *aname;
-
+
if (symbol->type != Node_array_ref
|| symbol->orig_array->type != Node_var_array
) {
- if (symbol->type != Node_var_array || symbol->parent_array == NULL)
+ if (symbol->type != Node_var_array || symbol->parent_array == NULL)
return symbol->vname;
return make_aname(symbol);
}
@@ -373,7 +373,7 @@ force_array(NODE *symbol, bool canfatal)
/* set_SUBSEP --- update SUBSEP related variables when SUBSEP assigned to */
-
+
void
set_SUBSEP()
{
@@ -396,7 +396,7 @@ concat_exp(int nargs, bool do_subsep)
size_t subseplen = 0;
int i;
extern NODE **args_array;
-
+
if (nargs == 1)
return POP_STRING();
@@ -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);
@@ -498,13 +498,13 @@ adjust_fcall_stack(NODE *symbol, int nsubs)
* But excludes cases like (nsubs = 0):
*
* function f(c, d) { delete c; ..}
- * BEGIN { a[0][0] = 1; f(a[0], a[0]); ...}
+ * BEGIN { a[0][0] = 1; f(a[0], a[0]); ...}
*/
null_array(r);
r->parent_array = NULL;
continue;
- }
+ }
/* Case 2 */
for (n = n->parent_array; n != NULL; n = n->parent_array) {
@@ -648,7 +648,7 @@ do_delete_loop(NODE *symbol, NODE **lhs)
efree(list);
/* blast the array in one shot */
- adjust_fcall_stack(symbol, 0);
+ adjust_fcall_stack(symbol, 0);
assoc_clear(symbol);
}
@@ -703,8 +703,15 @@ 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>"
+ fprintf(output_fp, "stfmt=%d, ", n->stfmt);
+ /*
+ * 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);
}
@@ -1047,7 +1054,7 @@ sort_up_index_number(const void *p1, const void *p2)
ret = cmp_numbers(t1, t2);
if (ret != 0)
- return ret;
+ return ret;
/* break a tie with the index string itself */
t1 = force_string((NODE *) t1);
@@ -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);
@@ -1243,7 +1241,7 @@ sort_user_func(const void *p1, const void *p2)
}
-/* assoc_list -- construct, and optionally sort, a list of array elements */
+/* assoc_list -- construct, and optionally sort, a list of array elements */
NODE **
assoc_list(NODE *symbol, const char *sort_str, sort_context_t sort_ctxt)
@@ -1282,7 +1280,7 @@ assoc_list(NODE *symbol, const char *sort_str, sort_context_t sort_ctxt)
extern int currule;
int save_rule = 0;
assoc_kind_t assoc_kind = ANONE;
-
+
elem_size = 1;
for (qi = 0, j = sizeof(sort_funcs)/sizeof(sort_funcs[0]); qi < j; qi++) {
@@ -1306,7 +1304,7 @@ assoc_list(NODE *symbol, const char *sort_str, sort_context_t sort_ctxt)
} else { /* unrecognized */
NODE *f;
- const char *sp;
+ const char *sp;
for (sp = sort_str; *sp != '\0' && ! isspace((unsigned char) *sp); sp++)
continue;
@@ -1330,7 +1328,7 @@ assoc_list(NODE *symbol, const char *sort_str, sort_context_t sort_ctxt)
code->func_body = f;
code->func_name = NULL; /* not needed, func_body already assigned */
(code + 1)->expr_count = 4; /* function takes 4 arguments */
- code->nexti = bcalloc(Op_stop, 1, 0);
+ code->nexti = bcalloc(Op_stop, 1, 0);
/*
* make non-redirected getline, exit, `next' and `nextfile' fatal in
@@ -1357,7 +1355,7 @@ assoc_list(NODE *symbol, const char *sort_str, sort_context_t sort_ctxt)
if (cmp_func == sort_user_func) {
code = POP_CODE();
- currule = save_rule; /* restore current rule */
+ currule = save_rule; /* restore current rule */
bcfree(code->nexti); /* Op_stop */
bcfree(code); /* Op_func_call */
}
diff --git a/awk.h b/awk.h
index ff622898..4cc3b487 100644
--- a/awk.h
+++ b/awk.h
@@ -1,23 +1,23 @@
/*
- * awk.h -- Definitions for gawk.
+ * awk.h -- Definitions for gawk.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2016 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
@@ -178,6 +178,10 @@ extern void *memset_ulong(void *dest, int val, unsigned long l);
#define memset memset_ulong
#endif
+#ifdef HAVE_FWRITE_UNLOCKED
+#define fwrite fwrite_unlocked
+#endif /* HAVE_FWRITE_UNLOCKED */
+
#if defined(__EMX__) || defined(__MINGW32__)
#include "nonposix.h"
#endif /* defined(__EMX__) || defined(__MINGW32__) */
@@ -206,11 +210,9 @@ typedef struct Regexp {
struct re_pattern_buffer pat;
struct re_registers regs;
struct dfa *dfareg;
- short dfa;
- short has_anchor; /* speed up of avoid_dfa kludge, temporary */
- short non_empty; /* for use in fpat_parse_field */
- short has_meta; /* re has meta chars so (probably) isn't simple string */
- short maybe_long; /* re has meta chars that can match long text */
+ bool non_empty; /* for use in fpat_parse_field */
+ bool has_meta; /* re has meta chars so (probably) isn't simple string */
+ bool maybe_long; /* re has meta chars that can match long text */
} Regexp;
#define RESTART(rp,s) (rp)->regs.start[0]
#define REEND(rp,s) (rp)->regs.end[0]
@@ -219,6 +221,7 @@ typedef struct Regexp {
#define NUMSUBPATS(rp,s) (rp)->regs.num_regs
/* regexp matching flags: */
+#define RE_NO_FLAGS 0 /* empty flags */
#define RE_NEED_START 1 /* need to know start/end of match */
#define RE_NO_BOL 2 /* not allowed to match ^ in regexp */
@@ -272,7 +275,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 +394,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 +413,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
@@ -453,6 +459,7 @@ typedef struct exp_node {
# define HALFHAT 0x10000 /* half-capacity Hashed Array Tree;
* See cint_array.c */
# define XARRAY 0x20000
+# define NUMCONSTSTR 0x40000 /* have string value for numeric constant */
} NODE;
#define vname sub.nodep.name
@@ -480,6 +487,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 +508,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
@@ -522,7 +546,7 @@ typedef struct exp_node {
#define array_size sub.nodep.cnt
#define array_capacity sub.nodep.reserved
#define xarray sub.nodep.rn
-#define parent_array sub.nodep.x.extra
+#define parent_array sub.nodep.x.extra
#define ainit array_funcs[0]
#define ainit_ind 0
@@ -556,6 +580,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,
@@ -597,6 +626,7 @@ typedef enum opcodeval {
Op_postincrement,
Op_postdecrement,
Op_unary_minus,
+ Op_unary_plus,
Op_field_spec,
/* unary relationals */
@@ -633,7 +663,7 @@ typedef enum opcodeval {
Op_nomatch,
Op_rule,
-
+
/* keywords */
Op_K_case,
Op_K_default,
@@ -654,7 +684,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 +692,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 +720,7 @@ typedef enum opcodeval {
Op_func,
+ Op_comment, /* for pretty printing */
Op_exec_count,
Op_breakpoint,
Op_lint,
@@ -697,13 +728,13 @@ typedef enum opcodeval {
Op_stop,
/* parsing (yylex and yyparse), should never appear in valid compiled code */
- Op_token,
+ Op_token,
Op_symbol,
Op_list,
/* program structures -- for use in the profiler/pretty printer */
Op_K_do,
- Op_K_for,
+ Op_K_for,
Op_K_arrayfor,
Op_K_while,
Op_K_switch,
@@ -772,7 +803,7 @@ typedef struct exp_instruction {
/* Op_K_exit */
#define target_end d.di
-#define target_atexit x.xi
+#define target_atexit x.xi
/* Op_newfile, Op_K_getline, Op_nextfile */
#define target_endfile x.xi
@@ -861,7 +892,7 @@ typedef struct exp_instruction {
#define field_assign x.aptr
/* Op_field_assign, Op_var_assign */
-#define assign_ctxt d.dl
+#define assign_ctxt d.dl
/* Op_concat */
#define concat_flag d.dl
@@ -894,7 +925,7 @@ typedef struct exp_instruction {
/* Op_line_range */
#define condpair_left d.di
-#define condpair_right x.xi
+#define condpair_right x.xi
/* Op_store_var */
#define initval x.xn
@@ -984,7 +1015,7 @@ typedef struct srcfile {
int fd;
int maxlen; /* size of the longest line */
- void (*fini_func)(); /* dynamic extension of type SRC_EXTLIB */
+ void (*fini_func)(); /* dynamic extension of type SRC_EXTLIB */
char *lexptr;
char *lexend;
@@ -1022,7 +1053,7 @@ enum block_id {
BLOCK_NODE,
BLOCK_BUCKET,
BLOCK_MAX /* count */
-};
+};
typedef int (*Func_pre_exec)(INSTRUCTION **);
typedef void (*Func_post_exec)(INSTRUCTION *);
@@ -1036,7 +1067,7 @@ typedef void (*Func_post_exec)(INSTRUCTION *);
#ifndef LONG_MIN
#define LONG_MIN ((long)(-LONG_MAX - 1L))
#endif
-#define UNLIMITED LONG_MAX
+#define UNLIMITED LONG_MAX
/* -------------------------- External variables -------------------------- */
/* gawk builtin variables */
@@ -1181,7 +1212,7 @@ extern STACK_ITEM *stack_top;
#define POP_ADDRESS() (decr_sp()->lptr)
#define PEEK(n) ((stack_ptr - (n))->rptr)
#define TOP() (stack_ptr->rptr) /* same as PEEK(0) */
-#define TOP_ADDRESS() (stack_ptr->lptr)
+#define TOP_ADDRESS() (stack_ptr->lptr)
#define PUSH(r) (void) (incr_sp()->rptr = (r))
#define PUSH_ADDRESS(l) (void) (incr_sp()->lptr = (l))
#define REPLACE(r) (void) (stack_ptr->rptr = (r))
@@ -1203,6 +1234,7 @@ extern void r_unref(NODE *tmp);
static inline void
DEREF(NODE *r)
{
+ assert(r->valref > 0);
if (--r->valref == 0)
r_unref(r);
}
@@ -1306,7 +1338,7 @@ if (--val) \
typedef enum { SORTED_IN = 1, ASORT, ASORTI } sort_context_t;
typedef enum {
ANONE = 0x00, /* "unused" value */
- AINDEX = 0x001, /* list of indices */
+ AINDEX = 0x001, /* list of indices */
AVALUE = 0x002, /* list of values */
AINUM = 0x004, /* numeric index */
AISTR = 0x008, /* string index */
@@ -1339,6 +1371,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,17 +1434,20 @@ 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);
extern void init_interpret(void);
-extern int cmp_nodes(NODE *t1, NODE *t2);
+extern int cmp_nodes(NODE *t1, NODE *t2, bool use_strcmp);
extern int cmp_awknums(const NODE *t1, const NODE *t2);
extern void set_IGNORECASE(void);
extern void set_OFS(void);
@@ -1443,10 +1479,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 +1542,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 +1560,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 +1569,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 +1586,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);
@@ -1614,9 +1655,9 @@ extern void reg_error(const char *s);
extern Regexp *re_update(NODE *t);
extern void resyntax(int syntax);
extern void resetup(void);
-extern int avoid_dfa(NODE *re, char *str, size_t len);
extern int reisstring(const char *text, size_t len, Regexp *re, const char *buf);
extern int get_numbase(const char *str, bool use_locale);
+extern bool using_utf8(void);
/* symbol.c */
extern void load_symbols();
@@ -1720,7 +1761,7 @@ POP_SCALAR()
if (t->type == Node_var_array)
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t));
-
+
return t;
}
@@ -1733,7 +1774,7 @@ TOP_SCALAR()
if (t->type == Node_var_array)
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t));
-
+
return t;
}
@@ -1751,7 +1792,7 @@ in_array(NODE *a, NODE *s)
NODE **ret;
ret = a->aexists(a, s);
-
+
return ret ? *ret : NULL;
}
@@ -1777,7 +1818,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 +1848,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 *
diff --git a/awkgram.c b/awkgram.c
index dbfc5e6e..78839fe9 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -80,7 +80,7 @@ static void lintwarn_ln(int line, const char *m, ...) ATTRIBUTE_PRINTF_2;
static void warning_ln(int line, const char *m, ...) ATTRIBUTE_PRINTF_2;
static char *get_src_buf(void);
static int yylex(void);
-int yyparse(void);
+int yyparse(void);
static INSTRUCTION *snode(INSTRUCTION *subn, INSTRUCTION *op);
static char **check_params(char *fname, int pcount, INSTRUCTION *list);
static int install_function(char *fname, INSTRUCTION *fi, INSTRUCTION *plist);
@@ -97,6 +97,7 @@ static int include_source(INSTRUCTION *file);
static int load_library(INSTRUCTION *file);
static void next_sourcefile(void);
static char *tokexpand(void);
+static NODE *make_profile_number(double d, const char *str, size_t len);
#define instruction(t) bcalloc(t, 1, 0)
@@ -123,10 +124,18 @@ 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 void add_sign_to_num(NODE *n, char sign);
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;
@@ -146,7 +155,7 @@ static char *lexptr; /* pointer to next char during parsing */
static char *lexend; /* end of buffer */
static char *lexptr_begin; /* keep track of where we were for error msgs */
static char *lexeme; /* beginning of lexeme for debugging */
-static bool lexeof; /* seen EOF for current source? */
+static bool lexeof; /* seen EOF for current source? */
static char *thisline = NULL;
static int in_braces = 0; /* count braces for firstline, lastline in an 'action' */
static int lastline = 0;
@@ -181,17 +190,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 216 "awkgram.c" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
@@ -345,7 +366,7 @@ int yyparse (void);
/* Copy the second part of user declarations. */
-#line 349 "awkgram.c" /* yacc.c:358 */
+#line 370 "awkgram.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -587,16 +608,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 +668,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, 215, 215, 217, 222, 223, 227, 239, 244, 255,
+ 262, 268, 277, 285, 287, 292, 300, 302, 308, 316,
+ 326, 356, 370, 384, 392, 403, 415, 417, 419, 425,
+ 433, 434, 438, 438, 484, 483, 517, 519, 524, 534,
+ 581, 586, 587, 591, 593, 595, 602, 692, 734, 776,
+ 889, 896, 903, 914, 924, 934, 944, 956, 973, 972,
+ 997, 1009, 1009, 1108, 1108, 1142, 1173, 1182, 1183, 1189,
+ 1190, 1197, 1202, 1214, 1228, 1230, 1238, 1245, 1247, 1258,
+ 1260, 1269, 1270, 1278, 1283, 1283, 1294, 1298, 1306, 1307,
+ 1310, 1312, 1317, 1318, 1327, 1328, 1333, 1338, 1347, 1349,
+ 1351, 1358, 1359, 1365, 1366, 1371, 1373, 1378, 1380, 1388,
+ 1393, 1402, 1403, 1408, 1410, 1415, 1417, 1425, 1430, 1438,
+ 1443, 1450, 1452, 1454, 1471, 1481, 1488, 1490, 1495, 1497,
+ 1499, 1507, 1509, 1514, 1516, 1521, 1523, 1525, 1581, 1583,
+ 1585, 1587, 1589, 1591, 1593, 1595, 1609, 1614, 1619, 1644,
+ 1650, 1652, 1654, 1656, 1658, 1660, 1665, 1669, 1701, 1703,
+ 1709, 1715, 1728, 1729, 1730, 1735, 1740, 1744, 1748, 1763,
+ 1784, 1789, 1826, 1855, 1856, 1862, 1863, 1868, 1870, 1877,
+ 1894, 1911, 1913, 1920, 1925, 1933, 1943, 1955, 1964, 1968,
+ 1972, 1976, 1980, 1984, 1987, 1989, 1993, 1997, 2001
};
#endif
@@ -687,13 +709,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 +741,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 +797,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 +863,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 +1106,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 +1146,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 +1171,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 +1864,24 @@ yyreduce:
switch (yyn)
{
case 3:
-#line 197 "awkgram.y" /* yacc.c:1646 */
+#line 218 "awkgram.y" /* yacc.c:1646 */
{
rule = 0;
yyerrok;
}
-#line 1847 "awkgram.c" /* yacc.c:1646 */
+#line 1873 "awkgram.c" /* yacc.c:1646 */
break;
case 5:
-#line 203 "awkgram.y" /* yacc.c:1646 */
+#line 224 "awkgram.y" /* yacc.c:1646 */
{
next_sourcefile();
}
-#line 1855 "awkgram.c" /* yacc.c:1646 */
+#line 1881 "awkgram.c" /* yacc.c:1646 */
break;
case 6:
-#line 207 "awkgram.y" /* yacc.c:1646 */
+#line 228 "awkgram.y" /* yacc.c:1646 */
{
rule = 0;
/*
@@ -1864,19 +1890,20 @@ yyreduce:
*/
/* yyerrok; */
}
-#line 1868 "awkgram.c" /* yacc.c:1646 */
+#line 1894 "awkgram.c" /* yacc.c:1646 */
break;
case 7:
-#line 219 "awkgram.y" /* yacc.c:1646 */
+#line 240 "awkgram.y" /* yacc.c:1646 */
{
(void) append_rule((yyvsp[-1]), (yyvsp[0]));
+ first_rule = false;
}
-#line 1876 "awkgram.c" /* yacc.c:1646 */
+#line 1903 "awkgram.c" /* yacc.c:1646 */
break;
case 8:
-#line 223 "awkgram.y" /* yacc.c:1646 */
+#line 245 "awkgram.y" /* yacc.c:1646 */
{
if (rule != Rule) {
msg(_("%s blocks must have an action part"), ruletab[rule]);
@@ -1887,41 +1914,42 @@ yyreduce:
} else /* pattern rule with non-empty pattern */
(void) append_rule((yyvsp[-1]), NULL);
}
-#line 1891 "awkgram.c" /* yacc.c:1646 */
+#line 1918 "awkgram.c" /* yacc.c:1646 */
break;
case 9:
-#line 234 "awkgram.y" /* yacc.c:1646 */
+#line 256 "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 1929 "awkgram.c" /* yacc.c:1646 */
break;
case 10:
-#line 240 "awkgram.y" /* yacc.c:1646 */
+#line 263 "awkgram.y" /* yacc.c:1646 */
{
want_source = false;
at_seen = false;
yyerrok;
}
-#line 1911 "awkgram.c" /* yacc.c:1646 */
+#line 1939 "awkgram.c" /* yacc.c:1646 */
break;
case 11:
-#line 246 "awkgram.y" /* yacc.c:1646 */
+#line 269 "awkgram.y" /* yacc.c:1646 */
{
want_source = false;
at_seen = false;
yyerrok;
}
-#line 1921 "awkgram.c" /* yacc.c:1646 */
+#line 1949 "awkgram.c" /* yacc.c:1646 */
break;
case 12:
-#line 255 "awkgram.y" /* yacc.c:1646 */
+#line 278 "awkgram.y" /* yacc.c:1646 */
{
if (include_source((yyvsp[0])) < 0)
YYABORT;
@@ -1929,23 +1957,23 @@ yyreduce:
bcfree((yyvsp[0]));
(yyval) = NULL;
}
-#line 1933 "awkgram.c" /* yacc.c:1646 */
+#line 1961 "awkgram.c" /* yacc.c:1646 */
break;
case 13:
-#line 263 "awkgram.y" /* yacc.c:1646 */
+#line 286 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 1939 "awkgram.c" /* yacc.c:1646 */
+#line 1967 "awkgram.c" /* yacc.c:1646 */
break;
case 14:
-#line 265 "awkgram.y" /* yacc.c:1646 */
+#line 288 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 1945 "awkgram.c" /* yacc.c:1646 */
+#line 1973 "awkgram.c" /* yacc.c:1646 */
break;
case 15:
-#line 270 "awkgram.y" /* yacc.c:1646 */
+#line 293 "awkgram.y" /* yacc.c:1646 */
{
if (load_library((yyvsp[0])) < 0)
YYABORT;
@@ -1953,35 +1981,49 @@ yyreduce:
bcfree((yyvsp[0]));
(yyval) = NULL;
}
-#line 1957 "awkgram.c" /* yacc.c:1646 */
+#line 1985 "awkgram.c" /* yacc.c:1646 */
break;
case 16:
-#line 278 "awkgram.y" /* yacc.c:1646 */
+#line 301 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 1963 "awkgram.c" /* yacc.c:1646 */
+#line 1991 "awkgram.c" /* yacc.c:1646 */
break;
case 17:
-#line 280 "awkgram.y" /* yacc.c:1646 */
+#line 303 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 1969 "awkgram.c" /* yacc.c:1646 */
+#line 1997 "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 308 "awkgram.y" /* yacc.c:1646 */
+ {
+ rule = Rule;
+ if (comment != NULL) {
+ (yyval) = list_create(comment);
+ comment = NULL;
+ } else
+ (yyval) = NULL;
+ }
+#line 2010 "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 317 "awkgram.y" /* yacc.c:1646 */
+ {
+ rule = Rule;
+ if (comment != NULL) {
+ (yyval) = list_prepend((yyvsp[0]), comment);
+ comment = NULL;
+ } else
+ (yyval) = (yyvsp[0]);
+ }
+#line 2023 "awkgram.c" /* yacc.c:1646 */
break;
case 20:
-#line 289 "awkgram.y" /* yacc.c:1646 */
+#line 327 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *tp;
@@ -2004,127 +2046,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 2057 "awkgram.c" /* yacc.c:1646 */
break;
case 21:
-#line 315 "awkgram.y" /* yacc.c:1646 */
+#line 357 "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 2075 "awkgram.c" /* yacc.c:1646 */
break;
case 22:
-#line 326 "awkgram.y" /* yacc.c:1646 */
+#line 371 "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 2093 "awkgram.c" /* yacc.c:1646 */
break;
case 23:
-#line 337 "awkgram.y" /* yacc.c:1646 */
+#line 385 "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 2105 "awkgram.c" /* yacc.c:1646 */
break;
case 24:
-#line 343 "awkgram.y" /* yacc.c:1646 */
+#line 393 "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 2117 "awkgram.c" /* yacc.c:1646 */
break;
case 25:
-#line 352 "awkgram.y" /* yacc.c:1646 */
+#line 404 "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 2130 "awkgram.c" /* yacc.c:1646 */
break;
case 26:
-#line 362 "awkgram.y" /* yacc.c:1646 */
+#line 416 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2078 "awkgram.c" /* yacc.c:1646 */
+#line 2136 "awkgram.c" /* yacc.c:1646 */
break;
case 27:
-#line 364 "awkgram.y" /* yacc.c:1646 */
+#line 418 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2084 "awkgram.c" /* yacc.c:1646 */
+#line 2142 "awkgram.c" /* yacc.c:1646 */
break;
case 28:
-#line 366 "awkgram.y" /* yacc.c:1646 */
+#line 420 "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 2152 "awkgram.c" /* yacc.c:1646 */
break;
case 29:
-#line 372 "awkgram.y" /* yacc.c:1646 */
+#line 426 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = (yyvsp[0]);
at_seen = false;
}
-#line 2103 "awkgram.c" /* yacc.c:1646 */
+#line 2161 "awkgram.c" /* yacc.c:1646 */
break;
case 32:
-#line 385 "awkgram.y" /* yacc.c:1646 */
+#line 438 "awkgram.y" /* yacc.c:1646 */
+ { want_param_names = FUNC_HEADER; }
+#line 2167 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 33:
+#line 439 "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 2209 "awkgram.c" /* yacc.c:1646 */
break;
- case 33:
-#line 403 "awkgram.y" /* yacc.c:1646 */
+ case 34:
+#line 484 "awkgram.y" /* yacc.c:1646 */
{ want_regexp = true; }
-#line 2124 "awkgram.c" /* yacc.c:1646 */
+#line 2215 "awkgram.c" /* yacc.c:1646 */
break;
- case 34:
-#line 405 "awkgram.y" /* yacc.c:1646 */
+ case 35:
+#line 486 "awkgram.y" /* yacc.c:1646 */
{
NODE *n, *exp;
char *re;
@@ -2153,69 +2244,112 @@ yyreduce:
(yyval)->opcode = Op_match_rec;
(yyval)->memory = n;
}
-#line 2157 "awkgram.c" /* yacc.c:1646 */
+#line 2248 "awkgram.c" /* yacc.c:1646 */
break;
- case 35:
-#line 437 "awkgram.y" /* yacc.c:1646 */
+ case 36:
+#line 518 "awkgram.y" /* yacc.c:1646 */
{ bcfree((yyvsp[0])); }
-#line 2163 "awkgram.c" /* yacc.c:1646 */
+#line 2254 "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 524 "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 2269 "awkgram.c" /* yacc.c:1646 */
break;
- case 38:
-#line 445 "awkgram.y" /* yacc.c:1646 */
+ case 39:
+#line 535 "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 2320 "awkgram.c" /* yacc.c:1646 */
break;
- case 39:
-#line 458 "awkgram.y" /* yacc.c:1646 */
+ case 40:
+#line 582 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2192 "awkgram.c" /* yacc.c:1646 */
+#line 2326 "awkgram.c" /* yacc.c:1646 */
break;
- case 42:
-#line 468 "awkgram.y" /* yacc.c:1646 */
+ case 43:
+#line 592 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2198 "awkgram.c" /* yacc.c:1646 */
+#line 2332 "awkgram.c" /* yacc.c:1646 */
break;
- case 43:
-#line 470 "awkgram.y" /* yacc.c:1646 */
+ case 44:
+#line 594 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 2204 "awkgram.c" /* yacc.c:1646 */
+#line 2338 "awkgram.c" /* yacc.c:1646 */
break;
- case 44:
-#line 472 "awkgram.y" /* yacc.c:1646 */
+ case 45:
+#line 596 "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 2349 "awkgram.c" /* yacc.c:1646 */
break;
- case 45:
-#line 479 "awkgram.y" /* yacc.c:1646 */
+ case 46:
+#line 603 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *dflt, *curr = NULL, *cexp, *cstmt;
INSTRUCTION *ip, *nextc, *tbreak;
@@ -2224,7 +2358,7 @@ yyreduce:
int case_count = 0;
int i;
- tbreak = instruction(Op_no_op);
+ tbreak = instruction(Op_no_op);
cstmt = list_create(tbreak);
cexp = list_create(instruction(Op_pop));
dflt = instruction(Op_jmp);
@@ -2236,7 +2370,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;
@@ -2251,7 +2385,7 @@ yyreduce:
error_ln(curr->source_line,
_("duplicate case values in switch body: %s"), caseval);
}
-
+
if (case_values == NULL)
emalloc(case_values, const char **, sizeof(char *) * maxcount, "statement");
else if (case_count >= maxcount) {
@@ -2302,22 +2436,22 @@ yyreduce:
(void) list_merge(ip, cexp);
(yyval) = list_merge(ip, cstmt);
- break_allowed--;
+ break_allowed--;
fix_break_continue(ip, tbreak, NULL);
}
-#line 2309 "awkgram.c" /* yacc.c:1646 */
+#line 2443 "awkgram.c" /* yacc.c:1646 */
break;
- case 46:
-#line 569 "awkgram.y" /* yacc.c:1646 */
- {
+ case 47:
+#line 693 "awkgram.y" /* yacc.c:1646 */
+ {
/*
* -----------------
* tc:
* cond
* -----------------
* [Op_jmp_false tb ]
- * -----------------
+ * -----------------
* body
* -----------------
* [Op_jmp tc ]
@@ -2351,18 +2485,18 @@ yyreduce:
continue_allowed--;
fix_break_continue(ip, tbreak, tcont);
}
-#line 2355 "awkgram.c" /* yacc.c:1646 */
+#line 2489 "awkgram.c" /* yacc.c:1646 */
break;
- case 47:
-#line 611 "awkgram.y" /* yacc.c:1646 */
+ case 48:
+#line 735 "awkgram.y" /* yacc.c:1646 */
{
/*
* -----------------
* z:
* body
* -----------------
- * tc:
+ * tc:
* cond
* -----------------
* [Op_jmp_true | z ]
@@ -2397,11 +2531,11 @@ yyreduce:
} /* else
$1 and $4 are NULLs */
}
-#line 2401 "awkgram.c" /* yacc.c:1646 */
+#line 2535 "awkgram.c" /* yacc.c:1646 */
break;
- case 48:
-#line 653 "awkgram.y" /* yacc.c:1646 */
+ case 49:
+#line 777 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *ip;
char *var_name = (yyvsp[-5])->lextok;
@@ -2413,7 +2547,7 @@ yyreduce:
&& ((yyvsp[0])->nexti->memory->type != Node_var || !((yyvsp[0])->nexti->memory->var_update))
&& strcmp((yyvsp[0])->nexti->memory->vname, var_name) == 0
) {
-
+
/* Efficiency hack. Recognize the special case of
*
* for (iggy in foo)
@@ -2425,10 +2559,10 @@ yyreduce:
*
* Check that the body is a `delete a[i]' statement,
* and that both the loop var and array names match.
- */
+ */
NODE *arr = NULL;
- ip = (yyvsp[0])->nexti->nexti;
+ ip = (yyvsp[0])->nexti->nexti;
if ((yyvsp[-3])->nexti->opcode == Op_push && (yyvsp[-3])->lasti == (yyvsp[-3])->nexti)
arr = (yyvsp[-3])->nexti->memory;
if (arr != NULL
@@ -2454,7 +2588,7 @@ yyreduce:
/* [ Op_push_array a ]
* [ Op_arrayfor_init | ib ]
- * ic:[ Op_arrayfor_incr | ib ]
+ * ic:[ Op_arrayfor_incr | ib ]
* [ Op_var_assign if any ]
*
* body
@@ -2483,7 +2617,7 @@ regular_loop:
} /* else
$1 is NULL */
- /* add update_FOO instruction if necessary */
+ /* add update_FOO instruction if necessary */
if ((yyvsp[-4])->array_var->type == Node_var && (yyvsp[-4])->array_var->var_update) {
(void) list_append(ip, instruction(Op_var_update));
ip->lasti->update_var = (yyvsp[-4])->array_var->var_update;
@@ -2499,7 +2633,7 @@ regular_loop:
if (do_pretty_print) {
(void) list_append(ip, instruction(Op_exec_count));
((yyvsp[-7]) + 1)->forloop_cond = (yyvsp[-4]);
- ((yyvsp[-7]) + 1)->forloop_body = ip->lasti;
+ ((yyvsp[-7]) + 1)->forloop_body = ip->lasti;
}
if ((yyvsp[0]) != NULL)
@@ -2509,75 +2643,78 @@ regular_loop:
ip->lasti->target_jmp = (yyvsp[-4]);
(yyval) = list_append(ip, tbreak);
fix_break_continue(ip, tbreak, tcont);
- }
+ }
break_allowed--;
continue_allowed--;
}
-#line 2518 "awkgram.c" /* yacc.c:1646 */
+#line 2652 "awkgram.c" /* yacc.c:1646 */
break;
- case 49:
-#line 766 "awkgram.y" /* yacc.c:1646 */
+ case 50:
+#line 890 "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 2663 "awkgram.c" /* yacc.c:1646 */
break;
- case 50:
-#line 773 "awkgram.y" /* yacc.c:1646 */
+ case 51:
+#line 897 "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 2674 "awkgram.c" /* yacc.c:1646 */
break;
- case 51:
-#line 780 "awkgram.y" /* yacc.c:1646 */
+ case 52:
+#line 904 "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 2686 "awkgram.c" /* yacc.c:1646 */
break;
- case 52:
-#line 790 "awkgram.y" /* yacc.c:1646 */
- {
+ case 53:
+#line 915 "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 2700 "awkgram.c" /* yacc.c:1646 */
break;
- case 53:
-#line 799 "awkgram.y" /* yacc.c:1646 */
+ case 54:
+#line 925 "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 2714 "awkgram.c" /* yacc.c:1646 */
break;
- case 54:
-#line 808 "awkgram.y" /* yacc.c:1646 */
+ case 55:
+#line 935 "awkgram.y" /* yacc.c:1646 */
{
/* if inside function (rule = 0), resolve context at run-time */
if (rule && rule != Rule)
@@ -2585,12 +2722,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 2728 "awkgram.c" /* yacc.c:1646 */
break;
- case 55:
-#line 817 "awkgram.y" /* yacc.c:1646 */
+ case 56:
+#line 945 "awkgram.y" /* yacc.c:1646 */
{
/* if inside function (rule = 0), resolve context at run-time */
if (rule == BEGIN || rule == END || rule == ENDFILE)
@@ -2600,15 +2738,16 @@ 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 2744 "awkgram.c" /* yacc.c:1646 */
break;
- case 56:
-#line 828 "awkgram.y" /* yacc.c:1646 */
+ case 57:
+#line 957 "awkgram.y" /* yacc.c:1646 */
{
/* Initialize the two possible jump targets, the actual target
- * is resolved at run-time.
+ * is resolved at run-time.
*/
(yyvsp[-2])->target_end = ip_end; /* first instruction in end_block */
(yyvsp[-2])->target_atexit = ip_atexit; /* cleanup and go home */
@@ -2619,21 +2758,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 2764 "awkgram.c" /* yacc.c:1646 */
break;
- case 57:
-#line 843 "awkgram.y" /* yacc.c:1646 */
+ case 58:
+#line 973 "awkgram.y" /* yacc.c:1646 */
{
if (! in_function)
yyerror(_("`return' used outside function context"));
}
-#line 2633 "awkgram.c" /* yacc.c:1646 */
+#line 2773 "awkgram.c" /* yacc.c:1646 */
break;
- case 58:
-#line 846 "awkgram.y" /* yacc.c:1646 */
+ case 59:
+#line 976 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[-1]) == NULL) {
(yyval) = list_create((yyvsp[-3]));
@@ -2653,18 +2793,19 @@ regular_loop:
(yyval) = list_append((yyvsp[-1]), (yyvsp[-3]));
}
+ (yyval) = add_pending_comment((yyval));
}
-#line 2658 "awkgram.c" /* yacc.c:1646 */
+#line 2799 "awkgram.c" /* yacc.c:1646 */
break;
- case 60:
-#line 878 "awkgram.y" /* yacc.c:1646 */
+ case 61:
+#line 1009 "awkgram.y" /* yacc.c:1646 */
{ in_print = true; in_parens = 0; }
-#line 2664 "awkgram.c" /* yacc.c:1646 */
+#line 2805 "awkgram.c" /* yacc.c:1646 */
break;
- case 61:
-#line 879 "awkgram.y" /* yacc.c:1646 */
+ case 62:
+#line 1010 "awkgram.y" /* yacc.c:1646 */
{
/*
* Optimization: plain `print' has no expression list, so $3 is null.
@@ -2732,7 +2873,7 @@ regular_loop:
* [$1 | NULL | redir_type | expr_count]
*
*/
-regular_print:
+regular_print:
if ((yyvsp[0]) == NULL) { /* no redirection */
if ((yyvsp[-1]) == NULL) { /* printf without arg */
(yyvsp[-3])->expr_count = 0;
@@ -2760,18 +2901,19 @@ regular_print:
}
}
}
+ (yyval) = add_pending_comment((yyval));
}
-#line 2765 "awkgram.c" /* yacc.c:1646 */
+#line 2907 "awkgram.c" /* yacc.c:1646 */
break;
- case 62:
-#line 976 "awkgram.y" /* yacc.c:1646 */
+ case 63:
+#line 1108 "awkgram.y" /* yacc.c:1646 */
{ sub_counter = 0; }
-#line 2771 "awkgram.c" /* yacc.c:1646 */
+#line 2913 "awkgram.c" /* yacc.c:1646 */
break;
- case 63:
-#line 977 "awkgram.y" /* yacc.c:1646 */
+ case 64:
+#line 1109 "awkgram.y" /* yacc.c:1646 */
{
char *arr = (yyvsp[-2])->lextok;
@@ -2803,12 +2945,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 2951 "awkgram.c" /* yacc.c:1646 */
break;
- case 64:
-#line 1014 "awkgram.y" /* yacc.c:1646 */
+ case 65:
+#line 1147 "awkgram.y" /* yacc.c:1646 */
{
static bool warned = false;
char *arr = (yyvsp[-1])->lextok;
@@ -2833,57 +2976,61 @@ 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 2982 "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 1174 "awkgram.y" /* yacc.c:1646 */
+ {
+ (yyval) = optimize_assignment((yyvsp[0]));
+ (yyval) = add_pending_comment((yyval));
+ }
+#line 2991 "awkgram.c" /* yacc.c:1646 */
break;
- case 66:
-#line 1045 "awkgram.y" /* yacc.c:1646 */
+ case 67:
+#line 1182 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2850 "awkgram.c" /* yacc.c:1646 */
+#line 2997 "awkgram.c" /* yacc.c:1646 */
break;
- case 67:
-#line 1047 "awkgram.y" /* yacc.c:1646 */
+ case 68:
+#line 1184 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2856 "awkgram.c" /* yacc.c:1646 */
+#line 3003 "awkgram.c" /* yacc.c:1646 */
break;
- case 68:
-#line 1052 "awkgram.y" /* yacc.c:1646 */
+ case 69:
+#line 1189 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2862 "awkgram.c" /* yacc.c:1646 */
+#line 3009 "awkgram.c" /* yacc.c:1646 */
break;
- case 69:
-#line 1054 "awkgram.y" /* yacc.c:1646 */
+ case 70:
+#line 1191 "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 3020 "awkgram.c" /* yacc.c:1646 */
break;
- case 70:
-#line 1061 "awkgram.y" /* yacc.c:1646 */
+ case 71:
+#line 1198 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 2879 "awkgram.c" /* yacc.c:1646 */
+#line 3026 "awkgram.c" /* yacc.c:1646 */
break;
- case 71:
-#line 1066 "awkgram.y" /* yacc.c:1646 */
+ case 72:
+#line 1203 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *casestmt = (yyvsp[0]);
if ((yyvsp[0]) == NULL)
- casestmt = list_create(instruction(Op_no_op));
+ casestmt = list_create(instruction(Op_no_op));
if (do_pretty_print)
(void) list_prepend(casestmt, instruction(Op_exec_count));
(yyvsp[-4])->case_exp = (yyvsp[-3]);
@@ -2891,11 +3038,11 @@ regular_print:
bcfree((yyvsp[-2]));
(yyval) = (yyvsp[-4]);
}
-#line 2895 "awkgram.c" /* yacc.c:1646 */
+#line 3042 "awkgram.c" /* yacc.c:1646 */
break;
- case 72:
-#line 1078 "awkgram.y" /* yacc.c:1646 */
+ case 73:
+#line 1215 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *casestmt = (yyvsp[0]);
if ((yyvsp[0]) == NULL)
@@ -2906,89 +3053,94 @@ regular_print:
(yyvsp[-3])->case_stmt = casestmt;
(yyval) = (yyvsp[-3]);
}
-#line 2910 "awkgram.c" /* yacc.c:1646 */
+#line 3057 "awkgram.c" /* yacc.c:1646 */
break;
- case 73:
-#line 1092 "awkgram.y" /* yacc.c:1646 */
+ case 74:
+#line 1229 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2916 "awkgram.c" /* yacc.c:1646 */
+#line 3063 "awkgram.c" /* yacc.c:1646 */
break;
- case 74:
-#line 1094 "awkgram.y" /* yacc.c:1646 */
- {
+ case 75:
+#line 1231 "awkgram.y" /* yacc.c:1646 */
+ {
NODE *n = (yyvsp[0])->memory;
(void) force_number(n);
negate_num(n);
bcfree((yyvsp[-1]));
(yyval) = (yyvsp[0]);
}
-#line 2928 "awkgram.c" /* yacc.c:1646 */
+#line 3075 "awkgram.c" /* yacc.c:1646 */
break;
- case 75:
-#line 1102 "awkgram.y" /* yacc.c:1646 */
+ case 76:
+#line 1239 "awkgram.y" /* yacc.c:1646 */
{
+ NODE *n = (yyvsp[0])->lasti->memory;
bcfree((yyvsp[-1]));
+ add_sign_to_num(n, '+');
(yyval) = (yyvsp[0]);
}
-#line 2937 "awkgram.c" /* yacc.c:1646 */
+#line 3086 "awkgram.c" /* yacc.c:1646 */
break;
- case 76:
-#line 1107 "awkgram.y" /* yacc.c:1646 */
+ case 77:
+#line 1246 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2943 "awkgram.c" /* yacc.c:1646 */
+#line 3092 "awkgram.c" /* yacc.c:1646 */
break;
- case 77:
-#line 1109 "awkgram.y" /* yacc.c:1646 */
+ case 78:
+#line 1248 "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 3104 "awkgram.c" /* yacc.c:1646 */
break;
- case 78:
-#line 1117 "awkgram.y" /* yacc.c:1646 */
+ case 79:
+#line 1259 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2958 "awkgram.c" /* yacc.c:1646 */
+#line 3110 "awkgram.c" /* yacc.c:1646 */
break;
- case 79:
-#line 1119 "awkgram.y" /* yacc.c:1646 */
+ case 80:
+#line 1261 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 2964 "awkgram.c" /* yacc.c:1646 */
+#line 3116 "awkgram.c" /* yacc.c:1646 */
break;
- case 81:
-#line 1129 "awkgram.y" /* yacc.c:1646 */
+ case 82:
+#line 1271 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = (yyvsp[-1]);
}
-#line 2972 "awkgram.c" /* yacc.c:1646 */
+#line 3124 "awkgram.c" /* yacc.c:1646 */
break;
- case 82:
-#line 1136 "awkgram.y" /* yacc.c:1646 */
+ case 83:
+#line 1278 "awkgram.y" /* yacc.c:1646 */
{
in_print = false;
in_parens = 0;
(yyval) = NULL;
}
-#line 2982 "awkgram.c" /* yacc.c:1646 */
+#line 3134 "awkgram.c" /* yacc.c:1646 */
break;
- case 83:
-#line 1141 "awkgram.y" /* yacc.c:1646 */
+ case 84:
+#line 1283 "awkgram.y" /* yacc.c:1646 */
{ in_print = false; in_parens = 0; }
-#line 2988 "awkgram.c" /* yacc.c:1646 */
+#line 3140 "awkgram.c" /* yacc.c:1646 */
break;
- case 84:
-#line 1142 "awkgram.y" /* yacc.c:1646 */
+ case 85:
+#line 1284 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[-2])->redir_type == redirect_twoway
&& (yyvsp[0])->lasti->opcode == Op_K_getline_redir
@@ -2996,63 +3148,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 3152 "awkgram.c" /* yacc.c:1646 */
break;
- case 85:
-#line 1153 "awkgram.y" /* yacc.c:1646 */
+ case 86:
+#line 1295 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = mk_condition((yyvsp[-3]), (yyvsp[-5]), (yyvsp[0]), NULL, NULL);
}
-#line 3008 "awkgram.c" /* yacc.c:1646 */
+#line 3160 "awkgram.c" /* yacc.c:1646 */
break;
- case 86:
-#line 1158 "awkgram.y" /* yacc.c:1646 */
+ case 87:
+#line 1300 "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 3168 "awkgram.c" /* yacc.c:1646 */
break;
- case 91:
-#line 1175 "awkgram.y" /* yacc.c:1646 */
+ case 92:
+#line 1317 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3022 "awkgram.c" /* yacc.c:1646 */
+#line 3174 "awkgram.c" /* yacc.c:1646 */
break;
- case 92:
-#line 1177 "awkgram.y" /* yacc.c:1646 */
+ case 93:
+#line 1319 "awkgram.y" /* yacc.c:1646 */
{
bcfree((yyvsp[-1]));
(yyval) = (yyvsp[0]);
}
-#line 3031 "awkgram.c" /* yacc.c:1646 */
+#line 3183 "awkgram.c" /* yacc.c:1646 */
break;
- case 93:
-#line 1185 "awkgram.y" /* yacc.c:1646 */
+ case 94:
+#line 1327 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3037 "awkgram.c" /* yacc.c:1646 */
+#line 3189 "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 1329 "awkgram.y" /* yacc.c:1646 */
+ { (yyval) = (yyvsp[0]); }
+#line 3195 "awkgram.c" /* yacc.c:1646 */
break;
- case 95:
-#line 1192 "awkgram.y" /* yacc.c:1646 */
+ case 96:
+#line 1334 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->param_count = 0;
(yyval) = list_create((yyvsp[0]));
}
-#line 3052 "awkgram.c" /* yacc.c:1646 */
+#line 3204 "awkgram.c" /* yacc.c:1646 */
break;
- case 96:
-#line 1197 "awkgram.y" /* yacc.c:1646 */
+ case 97:
+#line 1339 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[-2]) != NULL && (yyvsp[0]) != NULL) {
(yyvsp[0])->param_count = (yyvsp[-2])->lasti->param_count + 1;
@@ -3061,74 +3213,74 @@ regular_print:
} else
(yyval) = NULL;
}
-#line 3065 "awkgram.c" /* yacc.c:1646 */
+#line 3217 "awkgram.c" /* yacc.c:1646 */
break;
- case 97:
-#line 1206 "awkgram.y" /* yacc.c:1646 */
+ case 98:
+#line 1348 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3071 "awkgram.c" /* yacc.c:1646 */
+#line 3223 "awkgram.c" /* yacc.c:1646 */
break;
- case 98:
-#line 1208 "awkgram.y" /* yacc.c:1646 */
+ case 99:
+#line 1350 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 3077 "awkgram.c" /* yacc.c:1646 */
+#line 3229 "awkgram.c" /* yacc.c:1646 */
break;
- case 99:
-#line 1210 "awkgram.y" /* yacc.c:1646 */
+ case 100:
+#line 1352 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-2]); }
-#line 3083 "awkgram.c" /* yacc.c:1646 */
+#line 3235 "awkgram.c" /* yacc.c:1646 */
break;
- case 100:
-#line 1216 "awkgram.y" /* yacc.c:1646 */
+ case 101:
+#line 1358 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3089 "awkgram.c" /* yacc.c:1646 */
+#line 3241 "awkgram.c" /* yacc.c:1646 */
break;
- case 101:
-#line 1218 "awkgram.y" /* yacc.c:1646 */
+ case 102:
+#line 1360 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3095 "awkgram.c" /* yacc.c:1646 */
+#line 3247 "awkgram.c" /* yacc.c:1646 */
break;
- case 102:
-#line 1223 "awkgram.y" /* yacc.c:1646 */
+ case 103:
+#line 1365 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3101 "awkgram.c" /* yacc.c:1646 */
+#line 3253 "awkgram.c" /* yacc.c:1646 */
break;
- case 103:
-#line 1225 "awkgram.y" /* yacc.c:1646 */
+ case 104:
+#line 1367 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3107 "awkgram.c" /* yacc.c:1646 */
+#line 3259 "awkgram.c" /* yacc.c:1646 */
break;
- case 104:
-#line 1230 "awkgram.y" /* yacc.c:1646 */
+ case 105:
+#line 1372 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_expression_list(NULL, (yyvsp[0])); }
-#line 3113 "awkgram.c" /* yacc.c:1646 */
+#line 3265 "awkgram.c" /* yacc.c:1646 */
break;
- case 105:
-#line 1232 "awkgram.y" /* yacc.c:1646 */
+ case 106:
+#line 1374 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
yyerrok;
}
-#line 3122 "awkgram.c" /* yacc.c:1646 */
+#line 3274 "awkgram.c" /* yacc.c:1646 */
break;
- case 106:
-#line 1237 "awkgram.y" /* yacc.c:1646 */
+ case 107:
+#line 1379 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3128 "awkgram.c" /* yacc.c:1646 */
+#line 3280 "awkgram.c" /* yacc.c:1646 */
break;
- case 107:
-#line 1239 "awkgram.y" /* yacc.c:1646 */
+ case 108:
+#line 1381 "awkgram.y" /* yacc.c:1646 */
{
/*
* Returning the expression list instead of NULL lets
@@ -3136,58 +3288,128 @@ regular_print:
*/
(yyval) = (yyvsp[-1]);
}
-#line 3140 "awkgram.c" /* yacc.c:1646 */
+#line 3292 "awkgram.c" /* yacc.c:1646 */
break;
- case 108:
-#line 1247 "awkgram.y" /* yacc.c:1646 */
+ case 109:
+#line 1389 "awkgram.y" /* yacc.c:1646 */
{
/* Ditto */
(yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
}
-#line 3149 "awkgram.c" /* yacc.c:1646 */
+#line 3301 "awkgram.c" /* yacc.c:1646 */
break;
- case 109:
-#line 1252 "awkgram.y" /* yacc.c:1646 */
+ case 110:
+#line 1394 "awkgram.y" /* yacc.c:1646 */
{
/* Ditto */
(yyval) = (yyvsp[-2]);
}
-#line 3158 "awkgram.c" /* yacc.c:1646 */
+#line 3310 "awkgram.c" /* yacc.c:1646 */
break;
- case 110:
-#line 1261 "awkgram.y" /* yacc.c:1646 */
+ case 111:
+#line 1402 "awkgram.y" /* yacc.c:1646 */
+ { (yyval) = NULL; }
+#line 3316 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 112:
+#line 1404 "awkgram.y" /* yacc.c:1646 */
+ { (yyval) = (yyvsp[0]); }
+#line 3322 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 113:
+#line 1409 "awkgram.y" /* yacc.c:1646 */
+ { (yyval) = mk_expression_list(NULL, (yyvsp[0])); }
+#line 3328 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 114:
+#line 1411 "awkgram.y" /* yacc.c:1646 */
+ {
+ (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
+ yyerrok;
+ }
+#line 3337 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 115:
+#line 1416 "awkgram.y" /* yacc.c:1646 */
+ { (yyval) = NULL; }
+#line 3343 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 116:
+#line 1418 "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 3355 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 117:
+#line 1426 "awkgram.y" /* yacc.c:1646 */
+ {
+ /* Ditto */
+ (yyval) = mk_expression_list((yyvsp[-2]), (yyvsp[0]));
+ }
+#line 3364 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 118:
+#line 1431 "awkgram.y" /* yacc.c:1646 */
+ {
+ /* Ditto */
+ (yyval) = (yyvsp[-2]);
+ }
+#line 3373 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 119:
+#line 1438 "awkgram.y" /* yacc.c:1646 */
+ { (yyval) = (yyvsp[0]); }
+#line 3379 "awkgram.c" /* yacc.c:1646 */
+ break;
+
+ case 120:
+#line 1444 "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 3390 "awkgram.c" /* yacc.c:1646 */
break;
- case 111:
-#line 1268 "awkgram.y" /* yacc.c:1646 */
+ case 121:
+#line 1451 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3175 "awkgram.c" /* yacc.c:1646 */
+#line 3396 "awkgram.c" /* yacc.c:1646 */
break;
- case 112:
-#line 1270 "awkgram.y" /* yacc.c:1646 */
+ case 122:
+#line 1453 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_boolean((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3181 "awkgram.c" /* yacc.c:1646 */
+#line 3402 "awkgram.c" /* yacc.c:1646 */
break;
- case 113:
-#line 1272 "awkgram.y" /* yacc.c:1646 */
+ case 123:
+#line 1455 "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 +3419,11 @@ regular_print:
(yyval) = list_append(list_merge((yyvsp[-2]), (yyvsp[0])), (yyvsp[-1]));
}
}
-#line 3201 "awkgram.c" /* yacc.c:1646 */
+#line 3423 "awkgram.c" /* yacc.c:1646 */
break;
- case 114:
-#line 1288 "awkgram.y" /* yacc.c:1646 */
+ case 124:
+#line 1472 "awkgram.y" /* yacc.c:1646 */
{
if (do_lint_old)
warning_ln((yyvsp[-1])->source_line,
@@ -3211,91 +3433,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 3437 "awkgram.c" /* yacc.c:1646 */
break;
- case 115:
-#line 1298 "awkgram.y" /* yacc.c:1646 */
+ case 125:
+#line 1482 "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 3448 "awkgram.c" /* yacc.c:1646 */
break;
- case 116:
-#line 1305 "awkgram.y" /* yacc.c:1646 */
+ case 126:
+#line 1489 "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 3454 "awkgram.c" /* yacc.c:1646 */
break;
- case 117:
-#line 1307 "awkgram.y" /* yacc.c:1646 */
+ case 127:
+#line 1491 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3238 "awkgram.c" /* yacc.c:1646 */
+#line 3460 "awkgram.c" /* yacc.c:1646 */
break;
- case 118:
-#line 1312 "awkgram.y" /* yacc.c:1646 */
+ case 128:
+#line 1496 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3244 "awkgram.c" /* yacc.c:1646 */
+#line 3466 "awkgram.c" /* yacc.c:1646 */
break;
- case 119:
-#line 1314 "awkgram.y" /* yacc.c:1646 */
+ case 129:
+#line 1498 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3250 "awkgram.c" /* yacc.c:1646 */
+#line 3472 "awkgram.c" /* yacc.c:1646 */
break;
- case 120:
-#line 1316 "awkgram.y" /* yacc.c:1646 */
- {
+ case 130:
+#line 1500 "awkgram.y" /* yacc.c:1646 */
+ {
(yyvsp[0])->opcode = Op_assign_quotient;
(yyval) = (yyvsp[0]);
}
-#line 3259 "awkgram.c" /* yacc.c:1646 */
+#line 3481 "awkgram.c" /* yacc.c:1646 */
break;
- case 121:
-#line 1324 "awkgram.y" /* yacc.c:1646 */
+ case 131:
+#line 1508 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3265 "awkgram.c" /* yacc.c:1646 */
+#line 3487 "awkgram.c" /* yacc.c:1646 */
break;
- case 122:
-#line 1326 "awkgram.y" /* yacc.c:1646 */
+ case 132:
+#line 1510 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3271 "awkgram.c" /* yacc.c:1646 */
+#line 3493 "awkgram.c" /* yacc.c:1646 */
break;
- case 123:
-#line 1331 "awkgram.y" /* yacc.c:1646 */
+ case 133:
+#line 1515 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3277 "awkgram.c" /* yacc.c:1646 */
+#line 3499 "awkgram.c" /* yacc.c:1646 */
break;
- case 124:
-#line 1333 "awkgram.y" /* yacc.c:1646 */
+ case 134:
+#line 1517 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3283 "awkgram.c" /* yacc.c:1646 */
+#line 3505 "awkgram.c" /* yacc.c:1646 */
break;
- case 125:
-#line 1338 "awkgram.y" /* yacc.c:1646 */
+ case 135:
+#line 1522 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3289 "awkgram.c" /* yacc.c:1646 */
+#line 3511 "awkgram.c" /* yacc.c:1646 */
break;
- case 126:
-#line 1340 "awkgram.y" /* yacc.c:1646 */
+ case 136:
+#line 1524 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3295 "awkgram.c" /* yacc.c:1646 */
+#line 3517 "awkgram.c" /* yacc.c:1646 */
break;
- case 127:
-#line 1342 "awkgram.y" /* yacc.c:1646 */
+ case 137:
+#line 1526 "awkgram.y" /* yacc.c:1646 */
{
int count = 2;
bool is_simple_var = false;
@@ -3321,10 +3543,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 +3562,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 +3570,47 @@ regular_print:
max_args = count;
}
}
-#line 3346 "awkgram.c" /* yacc.c:1646 */
+#line 3574 "awkgram.c" /* yacc.c:1646 */
break;
- case 129:
-#line 1394 "awkgram.y" /* yacc.c:1646 */
+ case 139:
+#line 1584 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3352 "awkgram.c" /* yacc.c:1646 */
+#line 3580 "awkgram.c" /* yacc.c:1646 */
break;
- case 130:
-#line 1396 "awkgram.y" /* yacc.c:1646 */
+ case 140:
+#line 1586 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3358 "awkgram.c" /* yacc.c:1646 */
+#line 3586 "awkgram.c" /* yacc.c:1646 */
break;
- case 131:
-#line 1398 "awkgram.y" /* yacc.c:1646 */
+ case 141:
+#line 1588 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3364 "awkgram.c" /* yacc.c:1646 */
+#line 3592 "awkgram.c" /* yacc.c:1646 */
break;
- case 132:
-#line 1400 "awkgram.y" /* yacc.c:1646 */
+ case 142:
+#line 1590 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3370 "awkgram.c" /* yacc.c:1646 */
+#line 3598 "awkgram.c" /* yacc.c:1646 */
break;
- case 133:
-#line 1402 "awkgram.y" /* yacc.c:1646 */
+ case 143:
+#line 1592 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3376 "awkgram.c" /* yacc.c:1646 */
+#line 3604 "awkgram.c" /* yacc.c:1646 */
break;
- case 134:
-#line 1404 "awkgram.y" /* yacc.c:1646 */
+ case 144:
+#line 1594 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3382 "awkgram.c" /* yacc.c:1646 */
+#line 3610 "awkgram.c" /* yacc.c:1646 */
break;
- case 135:
-#line 1406 "awkgram.y" /* yacc.c:1646 */
+ case 145:
+#line 1596 "awkgram.y" /* yacc.c:1646 */
{
/*
* In BEGINFILE/ENDFILE, allow `getline [var] < file'
@@ -3396,29 +3624,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 3628 "awkgram.c" /* yacc.c:1646 */
break;
- case 136:
-#line 1420 "awkgram.y" /* yacc.c:1646 */
+ case 146:
+#line 1610 "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 3637 "awkgram.c" /* yacc.c:1646 */
break;
- case 137:
-#line 1425 "awkgram.y" /* yacc.c:1646 */
+ case 147:
+#line 1615 "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 3646 "awkgram.c" /* yacc.c:1646 */
break;
- case 138:
-#line 1430 "awkgram.y" /* yacc.c:1646 */
+ case 148:
+#line 1620 "awkgram.y" /* yacc.c:1646 */
{
if (do_lint_old) {
warning_ln((yyvsp[-1])->source_line,
@@ -3438,69 +3666,69 @@ regular_print:
(yyval) = list_append(list_merge(t, (yyvsp[0])), (yyvsp[-1]));
}
}
-#line 3442 "awkgram.c" /* yacc.c:1646 */
+#line 3670 "awkgram.c" /* yacc.c:1646 */
break;
- case 139:
-#line 1455 "awkgram.y" /* yacc.c:1646 */
+ case 149:
+#line 1645 "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 3679 "awkgram.c" /* yacc.c:1646 */
break;
- case 140:
-#line 1461 "awkgram.y" /* yacc.c:1646 */
+ case 150:
+#line 1651 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3457 "awkgram.c" /* yacc.c:1646 */
+#line 3685 "awkgram.c" /* yacc.c:1646 */
break;
- case 141:
-#line 1463 "awkgram.y" /* yacc.c:1646 */
+ case 151:
+#line 1653 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3463 "awkgram.c" /* yacc.c:1646 */
+#line 3691 "awkgram.c" /* yacc.c:1646 */
break;
- case 142:
-#line 1465 "awkgram.y" /* yacc.c:1646 */
+ case 152:
+#line 1655 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3469 "awkgram.c" /* yacc.c:1646 */
+#line 3697 "awkgram.c" /* yacc.c:1646 */
break;
- case 143:
-#line 1467 "awkgram.y" /* yacc.c:1646 */
+ case 153:
+#line 1657 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3475 "awkgram.c" /* yacc.c:1646 */
+#line 3703 "awkgram.c" /* yacc.c:1646 */
break;
- case 144:
-#line 1469 "awkgram.y" /* yacc.c:1646 */
+ case 154:
+#line 1659 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3481 "awkgram.c" /* yacc.c:1646 */
+#line 3709 "awkgram.c" /* yacc.c:1646 */
break;
- case 145:
-#line 1471 "awkgram.y" /* yacc.c:1646 */
+ case 155:
+#line 1661 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = mk_binary((yyvsp[-2]), (yyvsp[0]), (yyvsp[-1])); }
-#line 3487 "awkgram.c" /* yacc.c:1646 */
+#line 3715 "awkgram.c" /* yacc.c:1646 */
break;
- case 146:
-#line 1476 "awkgram.y" /* yacc.c:1646 */
+ case 156:
+#line 1666 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_create((yyvsp[0]));
}
-#line 3495 "awkgram.c" /* yacc.c:1646 */
+#line 3723 "awkgram.c" /* yacc.c:1646 */
break;
- case 147:
-#line 1480 "awkgram.y" /* yacc.c:1646 */
+ case 157:
+#line 1670 "awkgram.y" /* yacc.c:1646 */
{
if ((yyvsp[0])->opcode == Op_match_rec) {
(yyvsp[0])->opcode = Op_nomatch;
(yyvsp[-1])->opcode = Op_push_i;
- (yyvsp[-1])->memory = make_number(0.0);
+ (yyvsp[-1])->memory = make_profile_number(0.0, "0", 1);
(yyval) = list_append(list_append(list_create((yyvsp[-1])),
instruction(Op_field_spec)), (yyvsp[0]));
} else {
@@ -3509,7 +3737,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 +3755,37 @@ regular_print:
}
}
}
-#line 3531 "awkgram.c" /* yacc.c:1646 */
+#line 3759 "awkgram.c" /* yacc.c:1646 */
break;
- case 148:
-#line 1512 "awkgram.y" /* yacc.c:1646 */
+ case 158:
+#line 1702 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 3537 "awkgram.c" /* yacc.c:1646 */
+#line 3765 "awkgram.c" /* yacc.c:1646 */
break;
- case 149:
-#line 1514 "awkgram.y" /* yacc.c:1646 */
+ case 159:
+#line 1704 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = snode((yyvsp[-1]), (yyvsp[-3]));
if ((yyval) == NULL)
YYABORT;
}
-#line 3547 "awkgram.c" /* yacc.c:1646 */
+#line 3775 "awkgram.c" /* yacc.c:1646 */
break;
- case 150:
-#line 1520 "awkgram.y" /* yacc.c:1646 */
+ case 160:
+#line 1710 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = snode((yyvsp[-1]), (yyvsp[-3]));
if ((yyval) == NULL)
YYABORT;
}
-#line 3557 "awkgram.c" /* yacc.c:1646 */
+#line 3785 "awkgram.c" /* yacc.c:1646 */
break;
- case 151:
-#line 1526 "awkgram.y" /* yacc.c:1646 */
+ case 161:
+#line 1716 "awkgram.y" /* yacc.c:1646 */
{
static bool warned = false;
@@ -3570,52 +3798,52 @@ regular_print:
if ((yyval) == NULL)
YYABORT;
}
-#line 3574 "awkgram.c" /* yacc.c:1646 */
+#line 3802 "awkgram.c" /* yacc.c:1646 */
break;
- case 154:
-#line 1541 "awkgram.y" /* yacc.c:1646 */
+ case 164:
+#line 1731 "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 3811 "awkgram.c" /* yacc.c:1646 */
break;
- case 155:
-#line 1546 "awkgram.y" /* yacc.c:1646 */
+ case 165:
+#line 1736 "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 3820 "awkgram.c" /* yacc.c:1646 */
break;
- case 156:
-#line 1551 "awkgram.y" /* yacc.c:1646 */
+ case 166:
+#line 1741 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_create((yyvsp[0]));
}
-#line 3600 "awkgram.c" /* yacc.c:1646 */
+#line 3828 "awkgram.c" /* yacc.c:1646 */
break;
- case 157:
-#line 1555 "awkgram.y" /* yacc.c:1646 */
+ case 167:
+#line 1745 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_create((yyvsp[0]));
}
-#line 3608 "awkgram.c" /* yacc.c:1646 */
+#line 3836 "awkgram.c" /* yacc.c:1646 */
break;
- case 158:
-#line 1559 "awkgram.y" /* yacc.c:1646 */
+ case 168:
+#line 1749 "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);
- negate_num(n);
+ negate_num(n);
(yyval) = (yyvsp[0]);
bcfree((yyvsp[-1]));
} else {
@@ -3623,34 +3851,42 @@ regular_print:
(yyval) = list_append((yyvsp[0]), (yyvsp[-1]));
}
}
-#line 3627 "awkgram.c" /* yacc.c:1646 */
+#line 3855 "awkgram.c" /* yacc.c:1646 */
break;
- case 159:
-#line 1574 "awkgram.y" /* yacc.c:1646 */
+ case 169:
+#line 1764 "awkgram.y" /* yacc.c:1646 */
{
- /*
- * was: $$ = $2
- * POSIX semantics: force a conversion to numeric type
- */
- (yyvsp[-1])->opcode = Op_plus_i;
- (yyvsp[-1])->memory = make_number(0.0);
- (yyval) = list_append((yyvsp[0]), (yyvsp[-1]));
+ if ((yyvsp[0])->lasti->opcode == Op_push_i
+ && ((yyvsp[0])->lasti->memory->flags & STRING) == 0
+ && ((yyvsp[0])->lasti->memory->flags & NUMCONSTSTR) != 0) {
+ NODE *n = (yyvsp[0])->lasti->memory;
+ add_sign_to_num(n, '+');
+ (yyval) = (yyvsp[0]);
+ bcfree((yyvsp[-1]));
+ } else {
+ /*
+ * was: $$ = $2
+ * POSIX semantics: force a conversion to numeric type
+ */
+ (yyvsp[-1])->opcode = Op_unary_plus;
+ (yyval) = list_append((yyvsp[0]), (yyvsp[-1]));
+ }
}
-#line 3641 "awkgram.c" /* yacc.c:1646 */
+#line 3877 "awkgram.c" /* yacc.c:1646 */
break;
- case 160:
-#line 1587 "awkgram.y" /* yacc.c:1646 */
+ case 170:
+#line 1785 "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 3886 "awkgram.c" /* yacc.c:1646 */
break;
- case 161:
-#line 1592 "awkgram.y" /* yacc.c:1646 */
+ case 171:
+#line 1790 "awkgram.y" /* yacc.c:1646 */
{
/* indirect function call */
INSTRUCTION *f, *t;
@@ -3665,7 +3901,7 @@ regular_print:
warned = true;
lintwarn("%s", msg);
}
-
+
f = (yyvsp[0])->lasti;
f->opcode = Op_indirect_func_call;
name = estrdup(f->func_name, strlen(f->func_name));
@@ -3684,18 +3920,18 @@ regular_print:
(yyval) = list_prepend((yyvsp[0]), t);
at_seen = false;
}
-#line 3688 "awkgram.c" /* yacc.c:1646 */
+#line 3924 "awkgram.c" /* yacc.c:1646 */
break;
- case 162:
-#line 1629 "awkgram.y" /* yacc.c:1646 */
+ case 172:
+#line 1827 "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);
@@ -3709,55 +3945,55 @@ regular_print:
(yyval) = list_create((yyvsp[-3]));
} else {
INSTRUCTION *t = (yyvsp[-1]);
- ((yyvsp[-3]) + 1)->expr_count = count_expressions(&t, true);
+ ((yyvsp[-3]) + 1)->expr_count = count_expressions(&t, true);
(yyval) = list_append(t, (yyvsp[-3]));
}
}
-#line 3717 "awkgram.c" /* yacc.c:1646 */
+#line 3953 "awkgram.c" /* yacc.c:1646 */
break;
- case 163:
-#line 1657 "awkgram.y" /* yacc.c:1646 */
+ case 173:
+#line 1855 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3723 "awkgram.c" /* yacc.c:1646 */
+#line 3959 "awkgram.c" /* yacc.c:1646 */
break;
- case 164:
-#line 1659 "awkgram.y" /* yacc.c:1646 */
+ case 174:
+#line 1857 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3729 "awkgram.c" /* yacc.c:1646 */
+#line 3965 "awkgram.c" /* yacc.c:1646 */
break;
- case 165:
-#line 1664 "awkgram.y" /* yacc.c:1646 */
+ case 175:
+#line 1862 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3735 "awkgram.c" /* yacc.c:1646 */
+#line 3971 "awkgram.c" /* yacc.c:1646 */
break;
- case 166:
-#line 1666 "awkgram.y" /* yacc.c:1646 */
+ case 176:
+#line 1864 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 3741 "awkgram.c" /* yacc.c:1646 */
+#line 3977 "awkgram.c" /* yacc.c:1646 */
break;
- case 167:
-#line 1671 "awkgram.y" /* yacc.c:1646 */
+ case 177:
+#line 1869 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3747 "awkgram.c" /* yacc.c:1646 */
+#line 3983 "awkgram.c" /* yacc.c:1646 */
break;
- case 168:
-#line 1673 "awkgram.y" /* yacc.c:1646 */
+ case 178:
+#line 1871 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_merge((yyvsp[-1]), (yyvsp[0]));
}
-#line 3755 "awkgram.c" /* yacc.c:1646 */
+#line 3991 "awkgram.c" /* yacc.c:1646 */
break;
- case 169:
-#line 1680 "awkgram.y" /* yacc.c:1646 */
+ case 179:
+#line 1878 "awkgram.y" /* yacc.c:1646 */
{
- INSTRUCTION *ip = (yyvsp[0])->lasti;
+ INSTRUCTION *ip = (yyvsp[0])->lasti;
int count = ip->sub_count; /* # of SUBSEP-seperated expressions */
if (count > 1) {
/* change Op_subscript or Op_sub_array to Op_concat */
@@ -3769,11 +4005,11 @@ regular_print:
sub_counter++; /* count # of dimensions */
(yyval) = (yyvsp[0]);
}
-#line 3773 "awkgram.c" /* yacc.c:1646 */
+#line 4009 "awkgram.c" /* yacc.c:1646 */
break;
- case 170:
-#line 1697 "awkgram.y" /* yacc.c:1646 */
+ case 180:
+#line 1895 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *t = (yyvsp[-1]);
if ((yyvsp[-1]) == NULL) {
@@ -3782,36 +4018,36 @@ regular_print:
/* install Null string as subscript. */
t = list_create(instruction(Op_push_i));
t->nexti->memory = dupnode(Nnull_string);
- (yyvsp[0])->sub_count = 1;
+ (yyvsp[0])->sub_count = 1;
} else
(yyvsp[0])->sub_count = count_expressions(&t, false);
(yyval) = list_append(t, (yyvsp[0]));
}
-#line 3791 "awkgram.c" /* yacc.c:1646 */
+#line 4027 "awkgram.c" /* yacc.c:1646 */
break;
- case 171:
-#line 1714 "awkgram.y" /* yacc.c:1646 */
+ case 181:
+#line 1912 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); }
-#line 3797 "awkgram.c" /* yacc.c:1646 */
+#line 4033 "awkgram.c" /* yacc.c:1646 */
break;
- case 172:
-#line 1716 "awkgram.y" /* yacc.c:1646 */
+ case 182:
+#line 1914 "awkgram.y" /* yacc.c:1646 */
{
(yyval) = list_merge((yyvsp[-1]), (yyvsp[0]));
}
-#line 3805 "awkgram.c" /* yacc.c:1646 */
+#line 4041 "awkgram.c" /* yacc.c:1646 */
break;
- case 173:
-#line 1723 "awkgram.y" /* yacc.c:1646 */
+ case 183:
+#line 1921 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[-1]); }
-#line 3811 "awkgram.c" /* yacc.c:1646 */
+#line 4047 "awkgram.c" /* yacc.c:1646 */
break;
- case 174:
-#line 1728 "awkgram.y" /* yacc.c:1646 */
+ case 184:
+#line 1926 "awkgram.y" /* yacc.c:1646 */
{
char *var_name = (yyvsp[0])->lextok;
@@ -3819,22 +4055,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 4059 "awkgram.c" /* yacc.c:1646 */
break;
- case 175:
-#line 1736 "awkgram.y" /* yacc.c:1646 */
+ case 185:
+#line 1934 "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 4070 "awkgram.c" /* yacc.c:1646 */
break;
- case 176:
-#line 1746 "awkgram.y" /* yacc.c:1646 */
+ case 186:
+#line 1944 "awkgram.y" /* yacc.c:1646 */
{
INSTRUCTION *ip = (yyvsp[0])->nexti;
if (ip->opcode == Op_push
@@ -3846,73 +4082,73 @@ regular_print:
} else
(yyval) = (yyvsp[0]);
}
-#line 3850 "awkgram.c" /* yacc.c:1646 */
+#line 4086 "awkgram.c" /* yacc.c:1646 */
break;
- case 177:
-#line 1758 "awkgram.y" /* yacc.c:1646 */
+ case 187:
+#line 1956 "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 4096 "awkgram.c" /* yacc.c:1646 */
break;
- case 178:
-#line 1767 "awkgram.y" /* yacc.c:1646 */
+ case 188:
+#line 1965 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->opcode = Op_postincrement;
}
-#line 3868 "awkgram.c" /* yacc.c:1646 */
+#line 4104 "awkgram.c" /* yacc.c:1646 */
break;
- case 179:
-#line 1771 "awkgram.y" /* yacc.c:1646 */
+ case 189:
+#line 1969 "awkgram.y" /* yacc.c:1646 */
{
(yyvsp[0])->opcode = Op_postdecrement;
}
-#line 3876 "awkgram.c" /* yacc.c:1646 */
+#line 4112 "awkgram.c" /* yacc.c:1646 */
break;
- case 180:
-#line 1774 "awkgram.y" /* yacc.c:1646 */
+ case 190:
+#line 1972 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = NULL; }
-#line 3882 "awkgram.c" /* yacc.c:1646 */
+#line 4118 "awkgram.c" /* yacc.c:1646 */
break;
- case 182:
-#line 1782 "awkgram.y" /* yacc.c:1646 */
+ case 192:
+#line 1980 "awkgram.y" /* yacc.c:1646 */
{ yyerrok; }
-#line 3888 "awkgram.c" /* yacc.c:1646 */
+#line 4124 "awkgram.c" /* yacc.c:1646 */
break;
- case 183:
-#line 1786 "awkgram.y" /* yacc.c:1646 */
+ case 193:
+#line 1984 "awkgram.y" /* yacc.c:1646 */
{ yyerrok; }
-#line 3894 "awkgram.c" /* yacc.c:1646 */
+#line 4130 "awkgram.c" /* yacc.c:1646 */
break;
- case 186:
-#line 1795 "awkgram.y" /* yacc.c:1646 */
+ case 196:
+#line 1993 "awkgram.y" /* yacc.c:1646 */
{ yyerrok; }
-#line 3900 "awkgram.c" /* yacc.c:1646 */
+#line 4136 "awkgram.c" /* yacc.c:1646 */
break;
- case 187:
-#line 1799 "awkgram.y" /* yacc.c:1646 */
+ case 197:
+#line 1997 "awkgram.y" /* yacc.c:1646 */
{ (yyval) = (yyvsp[0]); yyerrok; }
-#line 3906 "awkgram.c" /* yacc.c:1646 */
+#line 4142 "awkgram.c" /* yacc.c:1646 */
break;
- case 188:
-#line 1803 "awkgram.y" /* yacc.c:1646 */
+ case 198:
+#line 2001 "awkgram.y" /* yacc.c:1646 */
{ yyerrok; }
-#line 3912 "awkgram.c" /* yacc.c:1646 */
+#line 4148 "awkgram.c" /* yacc.c:1646 */
break;
-#line 3916 "awkgram.c" /* yacc.c:1646 */
+#line 4152 "awkgram.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -4140,7 +4376,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 1805 "awkgram.y" /* yacc.c:1906 */
+#line 2003 "awkgram.y" /* yacc.c:1906 */
struct token {
@@ -4157,7 +4393,7 @@ struct token {
# define BREAK 0x0800 /* break allowed inside */
# define CONTINUE 0x1000 /* continue allowed inside */
# define DEBUG_USE 0x2000 /* for use by developers */
-
+
NODE *(*ptr)(int); /* function that implements this keyword */
NODE *(*ptr2)(int); /* alternate arbitrary-precision function */
};
@@ -4217,9 +4453,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 +4465,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 +4499,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)},
};
@@ -4290,7 +4525,7 @@ getfname(NODE *(*fptr)(int))
j = sizeof(tokentab) / sizeof(tokentab[0]);
/* linear search, no other way to do it */
- for (i = 0; i < j; i++)
+ for (i = 0; i < j; i++)
if (tokentab[i].ptr == fptr || tokentab[i].ptr2 == fptr)
return tokentab[i].operator;
@@ -4306,6 +4541,8 @@ negate_num(NODE *n)
int tval = 0;
#endif
+ add_sign_to_num(n, '-');
+
if (! is_mpg_number(n)) {
n->numbr = -n->numbr;
return;
@@ -4338,6 +4575,21 @@ negate_num(NODE *n)
#endif
}
+/* add_sign_to_num --- make a constant unary plus or minus for profiling */
+
+static void
+add_sign_to_num(NODE *n, char sign)
+{
+ if ((n->flags & NUMCONSTSTR) != 0) {
+ char *s;
+
+ s = n->stptr;
+ memmove(& s[1], & s[0], n->stlen + 1);
+ s[0] = sign;
+ n->stlen++;
+ }
+}
+
/* print_included_from --- print `Included from ..' file names and locations */
static void
@@ -4346,7 +4598,7 @@ print_included_from()
int saveline, line;
SRCFILE *s;
- /* suppress current file name, line # from `.. included from ..' msgs */
+ /* suppress current file name, line # from `.. included from ..' msgs */
saveline = sourceline;
sourceline = 0;
@@ -4440,7 +4692,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 +4722,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;
@@ -4556,7 +4799,7 @@ mk_program()
if (prog_block == NULL) {
if (end_block->nexti == end_block->lasti
- && beginfile_block->nexti == beginfile_block->lasti
+ && beginfile_block->nexti == beginfile_block->lasti
&& endfile_block->nexti == endfile_block->lasti
) {
/* no pattern-action and (real) end, beginfile or endfile blocks */
@@ -4571,6 +4814,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));
@@ -4593,7 +4841,7 @@ mk_program()
(void) list_prepend(prog_block, ip_rec);
(void) list_append(prog_block, instruction(Op_jmp));
prog_block->lasti->target_jmp = ip_rec;
-
+
list_append(beginfile_block, instruction(Op_after_beginfile));
cp = list_merge(beginfile_block, prog_block);
@@ -4603,6 +4851,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,13 +4864,17 @@ 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
#undef end_block
#undef prog_block
#undef beginfile_block
-#undef endfile_block
+#undef endfile_block
}
/* parse_program --- read in the program and convert into a list of instructions */
@@ -4636,7 +4894,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;
@@ -4767,7 +5025,7 @@ add_srcfile(enum srctype stype, char *src, SRCFILE *thisfile, bool *already_incl
*already_included = true;
return NULL;
} else {
- /* duplicates are allowed for -f */
+ /* duplicates are allowed for -f */
if (s->stype == SRC_INC)
fatal(_("can't include `%s' and use it as a program file"), src);
/* no need to scan for further matches, since
@@ -4818,11 +5076,11 @@ include_source(INSTRUCTION *file)
sourcefile->srclines = sourceline;
sourcefile->lexptr = lexptr;
sourcefile->lexend = lexend;
- sourcefile->lexptr_begin = lexptr_begin;
+ sourcefile->lexptr_begin = lexptr_begin;
sourcefile->lexeme = lexeme;
sourcefile->lasttok = lasttok;
- /* included file becomes the current source */
+ /* included file becomes the current source */
sourcefile = s;
lexptr = NULL;
sourceline = 0;
@@ -5107,7 +5365,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);
@@ -5129,7 +5387,7 @@ tokexpand()
{
static int toksize;
int tokoffset;
-
+
if (tokstart != NULL) {
tokoffset = tok - tokstart;
toksize *= 2;
@@ -5197,8 +5455,8 @@ again:
int idx, work_ring_idx = cur_ring_idx;
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 +5513,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 +5644,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 +5673,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) {
@@ -5342,7 +5722,7 @@ yylex(void)
lasttok = 0;
return SUBSCRIPT;
}
-
+
if (lasttok == LEX_EOF) /* error earlier in current source, must give up !! */
return 0;
@@ -5366,6 +5746,7 @@ yylex(void)
lexeme = lexptr;
thisline = NULL;
+
if (want_regexp) {
int in_brack = 0; /* count brackets, [[:alnum:]] allowed */
int b_index = -1;
@@ -5376,7 +5757,7 @@ yylex(void)
*
* [..[..] []] [^]] [.../...]
* [...\[...] [...\]...] [...\/...]
- *
+ *
* (Remember that all of the above are inside /.../)
*
* The code for \ handles \[, \] and \/.
@@ -5405,7 +5786,7 @@ yylex(void)
break;
case ']':
if (in_brack > 0
- && (cur_index == b_index + 1
+ && (cur_index == b_index + 1
|| (cur_index == b_index + 2 && tok[-1] == '^')))
; /* do nothing */
else {
@@ -5452,7 +5833,9 @@ end_regexp:
peek);
}
}
- return lasttok = REGEXP;
+ lasttok = REGEXP;
+
+ return lasttok;
case '\n':
pushback();
yyerror(_("unterminated regexp"));
@@ -5488,9 +5871,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 +5899,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 +5916,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();
}
@@ -5553,7 +5954,7 @@ retry:
in_parens--;
return lasttok = c;
- case '(':
+ case '(':
in_parens++;
return lasttok = c;
case '$':
@@ -5656,7 +6057,7 @@ retry:
did_warn_op = true;
warning(_("operator `^' is not supported in old awk"));
}
- yylval = GET_INSTRUCTION(Op_exp);
+ yylval = GET_INSTRUCTION(Op_exp);
return lasttok = '^';
}
@@ -5737,7 +6138,7 @@ retry:
lastline = sourceline;
return lasttok = c;
}
- did_newline++;
+ did_newline = true;
--lexptr; /* pick up } next time */
return lasttok = NEWLINE;
@@ -5779,7 +6180,7 @@ retry:
yylval->lextok = estrdup(tokstart, tok - tokstart);
return lasttok = FILENAME;
}
-
+
yylval->opcode = Op_push_i;
yylval->memory = make_str_node(tokstart,
tok - tokstart, esc_seen ? SCAN : 0);
@@ -5945,14 +6346,19 @@ retry:
IEEE_FMT(r->mpg_numbr, tval);
}
yylval->memory = r;
+ if (do_pretty_print) {
+ yylval->memory->stptr = estrdup(tokstart, strlen(tokstart)-1);
+ yylval->memory->stlen = strlen(tokstart)-1;
+ yylval->memory->flags |= NUMCONSTSTR;
+ }
return lasttok = YNUMBER;
}
#endif
if (base != 10)
- d = nondec2awknum(tokstart, strlen(tokstart));
+ d = nondec2awknum(tokstart, strlen(tokstart), NULL);
else
d = atof(tokstart);
- yylval->memory = make_number(d);
+ yylval->memory = make_profile_number(d, tokstart, strlen(tokstart) - 1);
if (d <= INT32_MAX && d >= INT32_MIN && d == (int32_t) d)
yylval->memory->flags |= NUMINT;
return lasttok = YNUMBER;
@@ -6035,6 +6441,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"),
@@ -6079,7 +6512,7 @@ retry:
case LEX_BEGIN:
case LEX_END:
case LEX_BEGINFILE:
- case LEX_ENDFILE:
+ case LEX_ENDFILE:
yylval = bcalloc(tokentab[mid].value, 3, sourceline);
break;
@@ -6128,7 +6561,7 @@ out:
tokkey = estrdup(tokstart, tok - tokstart);
if (*lexptr == '(') {
yylval = bcalloc(Op_token, 2, sourceline);
- yylval->lextok = tokkey;
+ yylval->lextok = tokkey;
return lasttok = FUNC_CALL;
} else {
static bool goto_warned = false;
@@ -6204,7 +6637,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
nexp++;
}
assert(nexp > 0);
- }
+ }
/* check against how many args. are allowed for this builtin */
args_allowed = tokentab[idx].flags & ARGS;
@@ -6235,7 +6668,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
INSTRUCTION *expr;
expr = list_create(instruction(Op_push_i));
- expr->nexti->memory = make_number(0.0);
+ expr->nexti->memory = make_profile_number(0.0, "0", 1);
(void) mk_expression_list(subn,
list_append(expr, instruction(Op_field_spec)));
}
@@ -6275,7 +6708,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
subn->lasti->assign_ctxt = Op_sub_builtin;
}
- return subn;
+ return subn;
} else {
/* gensub */
@@ -6283,7 +6716,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
r->sub_flags |= GENSUB;
if (nexp == 3) {
ip = instruction(Op_push_i);
- ip->memory = make_number(0.0);
+ ip->memory = make_profile_number(0.0, "0", 1);
(void) mk_expression_list(subn,
list_append(list_create(ip), instruction(Op_field_spec)));
}
@@ -6294,7 +6727,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
@@ -6304,25 +6737,34 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
/* special case processing for a few builtins */
if (r->builtin == do_length) {
- if (nexp == 0) {
+ if (nexp == 0) {
/* no args. Use $0 */
INSTRUCTION *list;
- r->expr_count = 1;
+ r->expr_count = 1;
list = list_create(r);
(void) list_prepend(list, instruction(Op_field_spec));
(void) list_prepend(list, instruction(Op_push_i));
- list->nexti->memory = make_number(0.0);
- return list;
+ list->nexti->memory = make_profile_number(0.0, "0", 1);
+ return list;
} else {
arg = subn->nexti;
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 +6841,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 +6853,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 +6962,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 +7050,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
*/
@@ -6649,7 +7087,7 @@ mk_function(INSTRUCTION *fi, INSTRUCTION *def)
return fi;
}
-/*
+/*
* install_function:
* install function name in the symbol table.
* Extra work, build up and install a list of the parameter names.
@@ -6673,7 +7111,7 @@ install_function(char *fname, INSTRUCTION *fi, INSTRUCTION *plist)
fi->func_body = f;
f->param_cnt = pcount;
f->code_ptr = fi;
- f->fparms = NULL;
+ f->fparms = NULL;
if (pcount > 0) {
char **pnames;
pnames = check_params(fname, pcount, plist); /* frees plist */
@@ -6730,7 +7168,7 @@ check_params(char *fname, int pcount, INSTRUCTION *list)
}
bcfree(list);
- return pnames;
+ return pnames;
}
@@ -6738,7 +7176,7 @@ check_params(char *fname, int pcount, INSTRUCTION *list)
undef HASHSIZE
#endif
#define HASHSIZE 1021
-
+
static struct fdesc {
char *name;
short used;
@@ -6800,7 +7238,7 @@ check_funcs()
if (! in_main_context())
goto free_mem;
-
+
for (i = 0; i < HASHSIZE; i++) {
for (fp = ftable[i]; fp != NULL; fp = fp->next) {
#ifdef REALLYMEAN
@@ -6894,6 +7332,7 @@ make_regnode(int type, NODE *exp)
}
n->re_exp = exp;
n->re_flags = CONSTANT;
+ n->valref = 1;
}
return n;
}
@@ -6909,6 +7348,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);
@@ -7103,6 +7544,8 @@ mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION *op)
}
op->opcode = Op_push_i;
+ // We don't need to call make_profile_number() here since
+ // optimizing is disabled when doing pretty printing.
op->memory = make_number(res);
unref(n1);
unref(n2);
@@ -7135,7 +7578,7 @@ mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION *op)
break;
default:
goto regular;
- }
+ }
op->memory = ip2->memory;
bcfree(ip2);
@@ -7151,7 +7594,7 @@ regular:
}
/* mk_boolean --- instructions for boolean and, or */
-
+
static INSTRUCTION *
mk_boolean(INSTRUCTION *left, INSTRUCTION *right, INSTRUCTION *op)
{
@@ -7179,7 +7622,7 @@ mk_boolean(INSTRUCTION *left, INSTRUCTION *right, INSTRUCTION *op)
right->lasti->target_stmt = left->lasti;
} else { /* optimization for x || y || z || ... */
INSTRUCTION *ip;
-
+
op->opcode = final_opc;
(void) list_append(right, op);
op->target_stmt = tp;
@@ -7216,7 +7659,7 @@ mk_condition(INSTRUCTION *cond, INSTRUCTION *ifp, INSTRUCTION *true_branch,
*
* ----------------
* [Op_jmp y]
- * ----------------
+ * ----------------
* f:
* false_branch
* ----------------
@@ -7324,7 +7767,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 +7813,6 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
action),
tp);
}
-
}
list_append(rule_list, rp + 1);
@@ -7375,7 +7821,7 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
rule_block[rule] = ip;
else
(void) list_merge(rule_block[rule], ip);
-
+
return rule_block[rule];
}
@@ -7397,7 +7843,7 @@ mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, INSTRUCTION *op)
break;
case Op_push:
case Op_push_array:
- tp->opcode = Op_push_lhs;
+ tp->opcode = Op_push_lhs;
break;
case Op_field_assign:
yyerror(_("cannot assign a value to the result of a field post-increment expression"));
@@ -7452,7 +7898,7 @@ optimize_assignment(INSTRUCTION *exp)
* Replaces Op_push_array + Op_subscript_lhs + Op_assign + Op_pop
* with single instruction Op_store_sub.
* Limitation: 1 dimension and sub is simple var/value.
- *
+ *
* 2) Simple variable assignment var = x:
* Replaces Op_push_lhs + Op_assign + Op_pop with Op_store_var.
*
@@ -7476,7 +7922,7 @@ optimize_assignment(INSTRUCTION *exp)
i1 = exp->lasti;
if ( i1->opcode != Op_assign
- && i1->opcode != Op_field_assign)
+ && i1->opcode != Op_field_assign)
return list_append(exp, instruction(Op_pop));
for (i2 = exp->nexti; i2 != i1; i2 = i2->nexti) {
@@ -7551,7 +7997,7 @@ optimize_assignment(INSTRUCTION *exp)
* so use expr_count instead.
*/
i3->nexti = NULL;
- i2->opcode = Op_no_op;
+ i2->opcode = Op_no_op;
bcfree(i1); /* Op_assign */
exp->lasti = i3; /* update Op_list */
return exp;
@@ -7574,7 +8020,7 @@ optimize_assignment(INSTRUCTION *exp)
&& (i3->memory->flags & INTLSTR) == 0
&& i3->nexti == i2
) {
- /* constant initializer */
+ /* constant initializer */
i2->initval = i3->memory;
bcfree(i3);
exp->nexti = i2;
@@ -7610,7 +8056,7 @@ mk_getline(INSTRUCTION *op, INSTRUCTION *var, INSTRUCTION *redir, int redirtype)
* [ file (simp_exp)]
* [ [ var ] ]
* [ Op_K_getline_redir|NULL|redir_type|into_var]
- * [ [var_assign] ]
+ * [ [var_assign] ]
*
*/
@@ -7619,7 +8065,7 @@ mk_getline(INSTRUCTION *op, INSTRUCTION *var, INSTRUCTION *redir, int redirtype)
bcfree(op);
op = bcalloc(Op_K_getline, 2, sline);
(op + 1)->target_endfile = ip_endfile;
- (op + 1)->target_beginfile = ip_beginfile;
+ (op + 1)->target_beginfile = ip_beginfile;
}
if (var != NULL) {
@@ -7677,11 +8123,11 @@ mk_for_loop(INSTRUCTION *forp, INSTRUCTION *init, INSTRUCTION *cond,
* ------------------------
* body (may be NULL)
* ------------------------
- * tc:
+ * tc:
* incr (may be NULL)
- * [ Op_jmp x ]
+ * [ Op_jmp x ]
* ------------------------
- * tb:[ Op_no_op ]
+ * tb:[ Op_no_op ]
*/
INSTRUCTION *ip, *tbreak, *tcont;
@@ -7793,7 +8239,7 @@ mk_expression_list(INSTRUCTION *list, INSTRUCTION *s1)
/* we can't just combine all bytecodes, since we need to
* process individual expressions for a few builtins in snode() (-:
*/
-
+
/* -- list of lists */
/* [Op_list| ... ]------
* |
@@ -7849,7 +8295,7 @@ count_expressions(INSTRUCTION **list, bool isarg)
(void) list_merge(r, expr);
expr = t2->nexti;
}
-
+
assert(count > 0);
if (! isarg && count > max_args)
max_args = count;
@@ -7936,6 +8382,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
@@ -8095,7 +8561,7 @@ install_builtins(void)
* The scene of the murder was grisly to look upon. When the inspector
* arrived, the sergeant turned to him and said, "Another programmer stabbed
* in the back. He never knew what happened."
- *
+ *
* The inspector replied, "Looks like the MO of isalpha, and his even meaner
* big brother, isalnum. The Locale brothers." The sergeant merely
* shuddered in horror.
@@ -8141,3 +8607,25 @@ is_identchar(int c)
{
return (is_alnum(c) || c == '_');
}
+
+/* make_profile_number --- make a number that can be printed when profiling */
+
+static NODE *
+make_profile_number(double d, const char *str, size_t len)
+{
+ NODE *n = make_number(d);
+ if (do_pretty_print) {
+ // extra byte in case need to add minus sign in negate_num
+ n->stptr = estrdup(str, len + 1);
+ n->stptr[len] = '\0';
+ n->stlen = len;
+ // Set STRCUR and n->stfmt for use when profiling
+ // (i.e., actually running the program) so that
+ // force_string() on this item will work ok.
+ // Thanks and a tip of the hatlo to valgrind.
+ n->flags |= (NUMCONSTSTR|STRCUR);
+ n->stfmt = STFMT_UNUSED;
+ }
+
+ return n;
+}
diff --git a/awkgram.y b/awkgram.y
index 4eab3d6f..4ed1e78b 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -2,7 +2,7 @@
* awkgram.y --- yacc/bison parser
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2016 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
@@ -40,7 +40,7 @@ static void lintwarn_ln(int line, const char *m, ...) ATTRIBUTE_PRINTF_2;
static void warning_ln(int line, const char *m, ...) ATTRIBUTE_PRINTF_2;
static char *get_src_buf(void);
static int yylex(void);
-int yyparse(void);
+int yyparse(void);
static INSTRUCTION *snode(INSTRUCTION *subn, INSTRUCTION *op);
static char **check_params(char *fname, int pcount, INSTRUCTION *list);
static int install_function(char *fname, INSTRUCTION *fi, INSTRUCTION *plist);
@@ -57,6 +57,7 @@ static int include_source(INSTRUCTION *file);
static int load_library(INSTRUCTION *file);
static void next_sourcefile(void);
static char *tokexpand(void);
+static NODE *make_profile_number(double d, const char *str, size_t len);
#define instruction(t) bcalloc(t, 1, 0)
@@ -83,10 +84,18 @@ 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 void add_sign_to_num(NODE *n, char sign);
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;
@@ -106,7 +115,7 @@ static char *lexptr; /* pointer to next char during parsing */
static char *lexend; /* end of buffer */
static char *lexptr_begin; /* keep track of where we were for error msgs */
static char *lexeme; /* beginning of lexeme for debugging */
-static bool lexeof; /* seen EOF for current source? */
+static bool lexeof; /* seen EOF for current source? */
static char *thisline = NULL;
static int in_braces = 0; /* count braces for firstline, lastline in an 'action' */
static int lastline = 0;
@@ -141,11 +150,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);
@@ -160,7 +181,7 @@ extern double fmod(double x, double y);
%token LEX_BEGIN LEX_END LEX_IF LEX_ELSE LEX_RETURN LEX_DELETE
%token LEX_SWITCH LEX_CASE LEX_DEFAULT LEX_WHILE LEX_DO LEX_FOR LEX_BREAK LEX_CONTINUE
%token LEX_PRINT LEX_PRINTF LEX_NEXT LEX_EXIT LEX_FUNCTION
-%token LEX_BEGINFILE LEX_ENDFILE
+%token LEX_BEGINFILE LEX_ENDFILE
%token LEX_GETLINE LEX_NEXTFILE
%token LEX_IN
%token LEX_AND LEX_OR INCREMENT DECREMENT
@@ -218,6 +239,7 @@ rule
: pattern action
{
(void) append_rule($1, $2);
+ first_rule = false;
}
| pattern statement_term
{
@@ -234,6 +256,7 @@ rule
{
in_function = NULL;
(void) mk_function($1, $2);
+ want_param_names = DONT_CHECK;
yyerrok;
}
| '@' LEX_INCLUDE source statement_term
@@ -282,9 +305,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 +346,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 +402,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;
}
;
@@ -379,18 +433,45 @@ lex_builtin
: LEX_BUILTIN
| LEX_LENGTH
;
-
+
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 +521,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; }
@@ -484,7 +608,7 @@ statement
int case_count = 0;
int i;
- tbreak = instruction(Op_no_op);
+ tbreak = instruction(Op_no_op);
cstmt = list_create(tbreak);
cexp = list_create(instruction(Op_pop));
dflt = instruction(Op_jmp);
@@ -496,7 +620,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;
@@ -511,7 +635,7 @@ statement
error_ln(curr->source_line,
_("duplicate case values in switch body: %s"), caseval);
}
-
+
if (case_values == NULL)
emalloc(case_values, const char **, sizeof(char *) * maxcount, "statement");
else if (case_count >= maxcount) {
@@ -562,18 +686,18 @@ statement
(void) list_merge(ip, cexp);
$$ = list_merge(ip, cstmt);
- break_allowed--;
+ break_allowed--;
fix_break_continue(ip, tbreak, NULL);
}
| LEX_WHILE '(' exp r_paren opt_nls statement
- {
+ {
/*
* -----------------
* tc:
* cond
* -----------------
* [Op_jmp_false tb ]
- * -----------------
+ * -----------------
* body
* -----------------
* [Op_jmp tc ]
@@ -614,7 +738,7 @@ statement
* z:
* body
* -----------------
- * tc:
+ * tc:
* cond
* -----------------
* [Op_jmp_true | z ]
@@ -661,7 +785,7 @@ statement
&& ($8->nexti->memory->type != Node_var || !($8->nexti->memory->var_update))
&& strcmp($8->nexti->memory->vname, var_name) == 0
) {
-
+
/* Efficiency hack. Recognize the special case of
*
* for (iggy in foo)
@@ -673,10 +797,10 @@ statement
*
* Check that the body is a `delete a[i]' statement,
* and that both the loop var and array names match.
- */
+ */
NODE *arr = NULL;
- ip = $8->nexti->nexti;
+ ip = $8->nexti->nexti;
if ($5->nexti->opcode == Op_push && $5->lasti == $5->nexti)
arr = $5->nexti->memory;
if (arr != NULL
@@ -702,7 +826,7 @@ statement
/* [ Op_push_array a ]
* [ Op_arrayfor_init | ib ]
- * ic:[ Op_arrayfor_incr | ib ]
+ * ic:[ Op_arrayfor_incr | ib ]
* [ Op_var_assign if any ]
*
* body
@@ -731,7 +855,7 @@ regular_loop:
} /* else
$1 is NULL */
- /* add update_FOO instruction if necessary */
+ /* add update_FOO instruction if necessary */
if ($4->array_var->type == Node_var && $4->array_var->var_update) {
(void) list_append(ip, instruction(Op_var_update));
ip->lasti->update_var = $4->array_var->var_update;
@@ -747,7 +871,7 @@ regular_loop:
if (do_pretty_print) {
(void) list_append(ip, instruction(Op_exec_count));
($1 + 1)->forloop_cond = $4;
- ($1 + 1)->forloop_body = ip->lasti;
+ ($1 + 1)->forloop_body = ip->lasti;
}
if ($8 != NULL)
@@ -757,7 +881,7 @@ regular_loop:
ip->lasti->target_jmp = $4;
$$ = list_append(ip, tbreak);
fix_break_continue(ip, tbreak, tcont);
- }
+ }
break_allowed--;
continue_allowed--;
@@ -782,17 +906,19 @@ regular_loop:
$$ = list_prepend($1, instruction(Op_exec_count));
else
$$ = $1;
+ $$ = add_pending_comment($$);
}
;
non_compound_stmt
: LEX_BREAK statement_term
- {
+ {
if (! break_allowed)
error_ln($1->source_line,
_("`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 +928,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 +939,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,11 +951,12 @@ 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
{
/* Initialize the two possible jump targets, the actual target
- * is resolved at run-time.
+ * is resolved at run-time.
*/
$1->target_end = ip_end; /* first instruction in end_block */
$1->target_atexit = ip_atexit; /* cleanup and go home */
@@ -838,6 +967,7 @@ non_compound_stmt
$$->nexti->memory = dupnode(Nnull_string);
} else
$$ = list_append($2, $1);
+ $$ = add_pending_comment($$);
}
| LEX_RETURN
{
@@ -862,6 +992,7 @@ non_compound_stmt
$$ = list_append($3, $1);
}
+ $$ = add_pending_comment($$);
}
| simple_stmt statement_term
;
@@ -943,7 +1074,7 @@ simple_stmt
* [$1 | NULL | redir_type | expr_count]
*
*/
-regular_print:
+regular_print:
if ($4 == NULL) { /* no redirection */
if ($3 == NULL) { /* printf without arg */
$1->expr_count = 0;
@@ -971,6 +1102,7 @@ regular_print:
}
}
}
+ $$ = add_pending_comment($$);
}
| LEX_DELETE NAME { sub_counter = 0; } delete_subscript_list
@@ -1005,7 +1137,8 @@ regular_print:
$1->expr_count = sub_counter;
$$ = list_append(list_append($4, $2), $1);
}
- }
+ $$ = add_pending_comment($$);
+ }
| LEX_DELETE '(' NAME ')'
/*
* this is for tawk compatibility. maybe the warnings
@@ -1035,9 +1168,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
@@ -1066,7 +1203,7 @@ case_statement
{
INSTRUCTION *casestmt = $5;
if ($5 == NULL)
- casestmt = list_create(instruction(Op_no_op));
+ casestmt = list_create(instruction(Op_no_op));
if (do_pretty_print)
(void) list_prepend(casestmt, instruction(Op_exec_count));
$1->case_exp = $2;
@@ -1091,7 +1228,7 @@ case_value
: YNUMBER
{ $$ = $1; }
| '-' YNUMBER %prec UNARY
- {
+ {
NODE *n = $2->memory;
(void) force_number(n);
negate_num(n);
@@ -1100,14 +1237,19 @@ case_value
}
| '+' YNUMBER %prec UNARY
{
+ NODE *n = $2->lasti->memory;
bcfree($1);
+ add_sign_to_num(n, '+');
$$ = $2;
}
- | YSTRING
+ | YSTRING
{ $$ = $1; }
- | regexp
+ | 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 +1326,7 @@ opt_param_list
: /* empty */
{ $$ = NULL; }
| param_list
- { $$ = $1 ; }
+ { $$ = $1; }
;
param_list
@@ -1255,6 +1397,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 +1458,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 */
@@ -1313,7 +1497,7 @@ assign_operator
| ASSIGNOP
{ $$ = $1; }
| SLASH_BEFORE_EQUAL ASSIGN /* `/=' */
- {
+ {
$2->opcode = Op_assign_quotient;
$$ = $2;
}
@@ -1364,10 +1548,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 +1567,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;
@@ -1481,7 +1671,7 @@ non_post_simp_exp
if ($2->opcode == Op_match_rec) {
$2->opcode = Op_nomatch;
$1->opcode = Op_push_i;
- $1->memory = make_number(0.0);
+ $1->memory = make_profile_number(0.0, "0", 1);
$$ = list_append(list_append(list_create($1),
instruction(Op_field_spec)), $2);
} else {
@@ -1490,7 +1680,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 +1700,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,11 +1748,11 @@ 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);
- negate_num(n);
+ negate_num(n);
$$ = $2;
bcfree($1);
} else {
@@ -1572,13 +1762,21 @@ non_post_simp_exp
}
| '+' simp_exp %prec UNARY
{
- /*
- * was: $$ = $2
- * POSIX semantics: force a conversion to numeric type
- */
- $1->opcode = Op_plus_i;
- $1->memory = make_number(0.0);
- $$ = list_append($2, $1);
+ if ($2->lasti->opcode == Op_push_i
+ && ($2->lasti->memory->flags & STRING) == 0
+ && ($2->lasti->memory->flags & NUMCONSTSTR) != 0) {
+ NODE *n = $2->lasti->memory;
+ add_sign_to_num(n, '+');
+ $$ = $2;
+ bcfree($1);
+ } else {
+ /*
+ * was: $$ = $2
+ * POSIX semantics: force a conversion to numeric type
+ */
+ $1->opcode = Op_unary_plus;
+ $$ = list_append($2, $1);
+ }
}
;
@@ -1603,7 +1801,7 @@ func_call
warned = true;
lintwarn("%s", msg);
}
-
+
f = $2->lasti;
f->opcode = Op_indirect_func_call;
name = estrdup(f->func_name, strlen(f->func_name));
@@ -1625,14 +1823,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);
@@ -1646,7 +1844,7 @@ direct_func_call
$$ = list_create($1);
} else {
INSTRUCTION *t = $3;
- ($1 + 1)->expr_count = count_expressions(&t, true);
+ ($1 + 1)->expr_count = count_expressions(&t, true);
$$ = list_append(t, $1);
}
}
@@ -1678,7 +1876,7 @@ delete_subscript
delete_exp_list
: bracketed_exp_list
{
- INSTRUCTION *ip = $1->lasti;
+ INSTRUCTION *ip = $1->lasti;
int count = ip->sub_count; /* # of SUBSEP-seperated expressions */
if (count > 1) {
/* change Op_subscript or Op_sub_array to Op_concat */
@@ -1702,7 +1900,7 @@ bracketed_exp_list
/* install Null string as subscript. */
t = list_create(instruction(Op_push_i));
t->nexti->memory = dupnode(Nnull_string);
- $3->sub_count = 1;
+ $3->sub_count = 1;
} else
$3->sub_count = count_expressions(&t, false);
$$ = list_append(t, $3);
@@ -1818,7 +2016,7 @@ struct token {
# define BREAK 0x0800 /* break allowed inside */
# define CONTINUE 0x1000 /* continue allowed inside */
# define DEBUG_USE 0x2000 /* for use by developers */
-
+
NODE *(*ptr)(int); /* function that implements this keyword */
NODE *(*ptr2)(int); /* alternate arbitrary-precision function */
};
@@ -1878,9 +2076,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 +2088,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 +2122,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)},
};
@@ -1951,7 +2148,7 @@ getfname(NODE *(*fptr)(int))
j = sizeof(tokentab) / sizeof(tokentab[0]);
/* linear search, no other way to do it */
- for (i = 0; i < j; i++)
+ for (i = 0; i < j; i++)
if (tokentab[i].ptr == fptr || tokentab[i].ptr2 == fptr)
return tokentab[i].operator;
@@ -1967,6 +2164,8 @@ negate_num(NODE *n)
int tval = 0;
#endif
+ add_sign_to_num(n, '-');
+
if (! is_mpg_number(n)) {
n->numbr = -n->numbr;
return;
@@ -1999,6 +2198,21 @@ negate_num(NODE *n)
#endif
}
+/* add_sign_to_num --- make a constant unary plus or minus for profiling */
+
+static void
+add_sign_to_num(NODE *n, char sign)
+{
+ if ((n->flags & NUMCONSTSTR) != 0) {
+ char *s;
+
+ s = n->stptr;
+ memmove(& s[1], & s[0], n->stlen + 1);
+ s[0] = sign;
+ n->stlen++;
+ }
+}
+
/* print_included_from --- print `Included from ..' file names and locations */
static void
@@ -2007,7 +2221,7 @@ print_included_from()
int saveline, line;
SRCFILE *s;
- /* suppress current file name, line # from `.. included from ..' msgs */
+ /* suppress current file name, line # from `.. included from ..' msgs */
saveline = sourceline;
sourceline = 0;
@@ -2101,7 +2315,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 +2345,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;
@@ -2217,7 +2422,7 @@ mk_program()
if (prog_block == NULL) {
if (end_block->nexti == end_block->lasti
- && beginfile_block->nexti == beginfile_block->lasti
+ && beginfile_block->nexti == beginfile_block->lasti
&& endfile_block->nexti == endfile_block->lasti
) {
/* no pattern-action and (real) end, beginfile or endfile blocks */
@@ -2232,6 +2437,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));
@@ -2254,7 +2464,7 @@ mk_program()
(void) list_prepend(prog_block, ip_rec);
(void) list_append(prog_block, instruction(Op_jmp));
prog_block->lasti->target_jmp = ip_rec;
-
+
list_append(beginfile_block, instruction(Op_after_beginfile));
cp = list_merge(beginfile_block, prog_block);
@@ -2264,6 +2474,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,13 +2487,17 @@ 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
#undef end_block
#undef prog_block
#undef beginfile_block
-#undef endfile_block
+#undef endfile_block
}
/* parse_program --- read in the program and convert into a list of instructions */
@@ -2297,7 +2517,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;
@@ -2428,7 +2648,7 @@ add_srcfile(enum srctype stype, char *src, SRCFILE *thisfile, bool *already_incl
*already_included = true;
return NULL;
} else {
- /* duplicates are allowed for -f */
+ /* duplicates are allowed for -f */
if (s->stype == SRC_INC)
fatal(_("can't include `%s' and use it as a program file"), src);
/* no need to scan for further matches, since
@@ -2479,11 +2699,11 @@ include_source(INSTRUCTION *file)
sourcefile->srclines = sourceline;
sourcefile->lexptr = lexptr;
sourcefile->lexend = lexend;
- sourcefile->lexptr_begin = lexptr_begin;
+ sourcefile->lexptr_begin = lexptr_begin;
sourcefile->lexeme = lexeme;
sourcefile->lasttok = lasttok;
- /* included file becomes the current source */
+ /* included file becomes the current source */
sourcefile = s;
lexptr = NULL;
sourceline = 0;
@@ -2768,7 +2988,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);
@@ -2790,7 +3010,7 @@ tokexpand()
{
static int toksize;
int tokoffset;
-
+
if (tokstart != NULL) {
tokoffset = tok - tokstart;
toksize *= 2;
@@ -2858,8 +3078,8 @@ again:
int idx, work_ring_idx = cur_ring_idx;
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 +3136,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 +3267,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 +3296,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) {
@@ -3003,7 +3345,7 @@ yylex(void)
lasttok = 0;
return SUBSCRIPT;
}
-
+
if (lasttok == LEX_EOF) /* error earlier in current source, must give up !! */
return 0;
@@ -3027,6 +3369,7 @@ yylex(void)
lexeme = lexptr;
thisline = NULL;
+
if (want_regexp) {
int in_brack = 0; /* count brackets, [[:alnum:]] allowed */
int b_index = -1;
@@ -3037,7 +3380,7 @@ yylex(void)
*
* [..[..] []] [^]] [.../...]
* [...\[...] [...\]...] [...\/...]
- *
+ *
* (Remember that all of the above are inside /.../)
*
* The code for \ handles \[, \] and \/.
@@ -3066,7 +3409,7 @@ yylex(void)
break;
case ']':
if (in_brack > 0
- && (cur_index == b_index + 1
+ && (cur_index == b_index + 1
|| (cur_index == b_index + 2 && tok[-1] == '^')))
; /* do nothing */
else {
@@ -3113,7 +3456,9 @@ end_regexp:
peek);
}
}
- return lasttok = REGEXP;
+ lasttok = REGEXP;
+
+ return lasttok;
case '\n':
pushback();
yyerror(_("unterminated regexp"));
@@ -3149,9 +3494,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 +3522,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 +3539,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();
}
@@ -3214,7 +3577,7 @@ retry:
in_parens--;
return lasttok = c;
- case '(':
+ case '(':
in_parens++;
return lasttok = c;
case '$':
@@ -3317,7 +3680,7 @@ retry:
did_warn_op = true;
warning(_("operator `^' is not supported in old awk"));
}
- yylval = GET_INSTRUCTION(Op_exp);
+ yylval = GET_INSTRUCTION(Op_exp);
return lasttok = '^';
}
@@ -3398,7 +3761,7 @@ retry:
lastline = sourceline;
return lasttok = c;
}
- did_newline++;
+ did_newline = true;
--lexptr; /* pick up } next time */
return lasttok = NEWLINE;
@@ -3440,7 +3803,7 @@ retry:
yylval->lextok = estrdup(tokstart, tok - tokstart);
return lasttok = FILENAME;
}
-
+
yylval->opcode = Op_push_i;
yylval->memory = make_str_node(tokstart,
tok - tokstart, esc_seen ? SCAN : 0);
@@ -3606,14 +3969,19 @@ retry:
IEEE_FMT(r->mpg_numbr, tval);
}
yylval->memory = r;
+ if (do_pretty_print) {
+ yylval->memory->stptr = estrdup(tokstart, strlen(tokstart)-1);
+ yylval->memory->stlen = strlen(tokstart)-1;
+ yylval->memory->flags |= NUMCONSTSTR;
+ }
return lasttok = YNUMBER;
}
#endif
if (base != 10)
- d = nondec2awknum(tokstart, strlen(tokstart));
+ d = nondec2awknum(tokstart, strlen(tokstart), NULL);
else
d = atof(tokstart);
- yylval->memory = make_number(d);
+ yylval->memory = make_profile_number(d, tokstart, strlen(tokstart) - 1);
if (d <= INT32_MAX && d >= INT32_MIN && d == (int32_t) d)
yylval->memory->flags |= NUMINT;
return lasttok = YNUMBER;
@@ -3696,6 +4064,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"),
@@ -3740,7 +4135,7 @@ retry:
case LEX_BEGIN:
case LEX_END:
case LEX_BEGINFILE:
- case LEX_ENDFILE:
+ case LEX_ENDFILE:
yylval = bcalloc(tokentab[mid].value, 3, sourceline);
break;
@@ -3789,7 +4184,7 @@ out:
tokkey = estrdup(tokstart, tok - tokstart);
if (*lexptr == '(') {
yylval = bcalloc(Op_token, 2, sourceline);
- yylval->lextok = tokkey;
+ yylval->lextok = tokkey;
return lasttok = FUNC_CALL;
} else {
static bool goto_warned = false;
@@ -3865,7 +4260,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
nexp++;
}
assert(nexp > 0);
- }
+ }
/* check against how many args. are allowed for this builtin */
args_allowed = tokentab[idx].flags & ARGS;
@@ -3896,7 +4291,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
INSTRUCTION *expr;
expr = list_create(instruction(Op_push_i));
- expr->nexti->memory = make_number(0.0);
+ expr->nexti->memory = make_profile_number(0.0, "0", 1);
(void) mk_expression_list(subn,
list_append(expr, instruction(Op_field_spec)));
}
@@ -3936,7 +4331,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
subn->lasti->assign_ctxt = Op_sub_builtin;
}
- return subn;
+ return subn;
} else {
/* gensub */
@@ -3944,7 +4339,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
r->sub_flags |= GENSUB;
if (nexp == 3) {
ip = instruction(Op_push_i);
- ip->memory = make_number(0.0);
+ ip->memory = make_profile_number(0.0, "0", 1);
(void) mk_expression_list(subn,
list_append(list_create(ip), instruction(Op_field_spec)));
}
@@ -3955,7 +4350,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
@@ -3965,25 +4360,34 @@ snode(INSTRUCTION *subn, INSTRUCTION *r)
/* special case processing for a few builtins */
if (r->builtin == do_length) {
- if (nexp == 0) {
+ if (nexp == 0) {
/* no args. Use $0 */
INSTRUCTION *list;
- r->expr_count = 1;
+ r->expr_count = 1;
list = list_create(r);
(void) list_prepend(list, instruction(Op_field_spec));
(void) list_prepend(list, instruction(Op_push_i));
- list->nexti->memory = make_number(0.0);
- return list;
+ list->nexti->memory = make_profile_number(0.0, "0", 1);
+ return list;
} else {
arg = subn->nexti;
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 +4464,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 +4476,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 +4585,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 +4673,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
*/
@@ -4310,7 +4710,7 @@ mk_function(INSTRUCTION *fi, INSTRUCTION *def)
return fi;
}
-/*
+/*
* install_function:
* install function name in the symbol table.
* Extra work, build up and install a list of the parameter names.
@@ -4334,7 +4734,7 @@ install_function(char *fname, INSTRUCTION *fi, INSTRUCTION *plist)
fi->func_body = f;
f->param_cnt = pcount;
f->code_ptr = fi;
- f->fparms = NULL;
+ f->fparms = NULL;
if (pcount > 0) {
char **pnames;
pnames = check_params(fname, pcount, plist); /* frees plist */
@@ -4391,7 +4791,7 @@ check_params(char *fname, int pcount, INSTRUCTION *list)
}
bcfree(list);
- return pnames;
+ return pnames;
}
@@ -4399,7 +4799,7 @@ check_params(char *fname, int pcount, INSTRUCTION *list)
undef HASHSIZE
#endif
#define HASHSIZE 1021
-
+
static struct fdesc {
char *name;
short used;
@@ -4461,7 +4861,7 @@ check_funcs()
if (! in_main_context())
goto free_mem;
-
+
for (i = 0; i < HASHSIZE; i++) {
for (fp = ftable[i]; fp != NULL; fp = fp->next) {
#ifdef REALLYMEAN
@@ -4555,6 +4955,7 @@ make_regnode(int type, NODE *exp)
}
n->re_exp = exp;
n->re_flags = CONSTANT;
+ n->valref = 1;
}
return n;
}
@@ -4570,6 +4971,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);
@@ -4764,6 +5167,8 @@ mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION *op)
}
op->opcode = Op_push_i;
+ // We don't need to call make_profile_number() here since
+ // optimizing is disabled when doing pretty printing.
op->memory = make_number(res);
unref(n1);
unref(n2);
@@ -4796,7 +5201,7 @@ mk_binary(INSTRUCTION *s1, INSTRUCTION *s2, INSTRUCTION *op)
break;
default:
goto regular;
- }
+ }
op->memory = ip2->memory;
bcfree(ip2);
@@ -4812,7 +5217,7 @@ regular:
}
/* mk_boolean --- instructions for boolean and, or */
-
+
static INSTRUCTION *
mk_boolean(INSTRUCTION *left, INSTRUCTION *right, INSTRUCTION *op)
{
@@ -4840,7 +5245,7 @@ mk_boolean(INSTRUCTION *left, INSTRUCTION *right, INSTRUCTION *op)
right->lasti->target_stmt = left->lasti;
} else { /* optimization for x || y || z || ... */
INSTRUCTION *ip;
-
+
op->opcode = final_opc;
(void) list_append(right, op);
op->target_stmt = tp;
@@ -4877,7 +5282,7 @@ mk_condition(INSTRUCTION *cond, INSTRUCTION *ifp, INSTRUCTION *true_branch,
*
* ----------------
* [Op_jmp y]
- * ----------------
+ * ----------------
* f:
* false_branch
* ----------------
@@ -4985,7 +5390,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 +5436,6 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
action),
tp);
}
-
}
list_append(rule_list, rp + 1);
@@ -5036,7 +5444,7 @@ append_rule(INSTRUCTION *pattern, INSTRUCTION *action)
rule_block[rule] = ip;
else
(void) list_merge(rule_block[rule], ip);
-
+
return rule_block[rule];
}
@@ -5058,7 +5466,7 @@ mk_assignment(INSTRUCTION *lhs, INSTRUCTION *rhs, INSTRUCTION *op)
break;
case Op_push:
case Op_push_array:
- tp->opcode = Op_push_lhs;
+ tp->opcode = Op_push_lhs;
break;
case Op_field_assign:
yyerror(_("cannot assign a value to the result of a field post-increment expression"));
@@ -5113,7 +5521,7 @@ optimize_assignment(INSTRUCTION *exp)
* Replaces Op_push_array + Op_subscript_lhs + Op_assign + Op_pop
* with single instruction Op_store_sub.
* Limitation: 1 dimension and sub is simple var/value.
- *
+ *
* 2) Simple variable assignment var = x:
* Replaces Op_push_lhs + Op_assign + Op_pop with Op_store_var.
*
@@ -5137,7 +5545,7 @@ optimize_assignment(INSTRUCTION *exp)
i1 = exp->lasti;
if ( i1->opcode != Op_assign
- && i1->opcode != Op_field_assign)
+ && i1->opcode != Op_field_assign)
return list_append(exp, instruction(Op_pop));
for (i2 = exp->nexti; i2 != i1; i2 = i2->nexti) {
@@ -5212,7 +5620,7 @@ optimize_assignment(INSTRUCTION *exp)
* so use expr_count instead.
*/
i3->nexti = NULL;
- i2->opcode = Op_no_op;
+ i2->opcode = Op_no_op;
bcfree(i1); /* Op_assign */
exp->lasti = i3; /* update Op_list */
return exp;
@@ -5235,7 +5643,7 @@ optimize_assignment(INSTRUCTION *exp)
&& (i3->memory->flags & INTLSTR) == 0
&& i3->nexti == i2
) {
- /* constant initializer */
+ /* constant initializer */
i2->initval = i3->memory;
bcfree(i3);
exp->nexti = i2;
@@ -5271,7 +5679,7 @@ mk_getline(INSTRUCTION *op, INSTRUCTION *var, INSTRUCTION *redir, int redirtype)
* [ file (simp_exp)]
* [ [ var ] ]
* [ Op_K_getline_redir|NULL|redir_type|into_var]
- * [ [var_assign] ]
+ * [ [var_assign] ]
*
*/
@@ -5280,7 +5688,7 @@ mk_getline(INSTRUCTION *op, INSTRUCTION *var, INSTRUCTION *redir, int redirtype)
bcfree(op);
op = bcalloc(Op_K_getline, 2, sline);
(op + 1)->target_endfile = ip_endfile;
- (op + 1)->target_beginfile = ip_beginfile;
+ (op + 1)->target_beginfile = ip_beginfile;
}
if (var != NULL) {
@@ -5338,11 +5746,11 @@ mk_for_loop(INSTRUCTION *forp, INSTRUCTION *init, INSTRUCTION *cond,
* ------------------------
* body (may be NULL)
* ------------------------
- * tc:
+ * tc:
* incr (may be NULL)
- * [ Op_jmp x ]
+ * [ Op_jmp x ]
* ------------------------
- * tb:[ Op_no_op ]
+ * tb:[ Op_no_op ]
*/
INSTRUCTION *ip, *tbreak, *tcont;
@@ -5454,7 +5862,7 @@ mk_expression_list(INSTRUCTION *list, INSTRUCTION *s1)
/* we can't just combine all bytecodes, since we need to
* process individual expressions for a few builtins in snode() (-:
*/
-
+
/* -- list of lists */
/* [Op_list| ... ]------
* |
@@ -5510,7 +5918,7 @@ count_expressions(INSTRUCTION **list, bool isarg)
(void) list_merge(r, expr);
expr = t2->nexti;
}
-
+
assert(count > 0);
if (! isarg && count > max_args)
max_args = count;
@@ -5597,6 +6005,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
@@ -5756,7 +6184,7 @@ install_builtins(void)
* The scene of the murder was grisly to look upon. When the inspector
* arrived, the sergeant turned to him and said, "Another programmer stabbed
* in the back. He never knew what happened."
- *
+ *
* The inspector replied, "Looks like the MO of isalpha, and his even meaner
* big brother, isalnum. The Locale brothers." The sergeant merely
* shuddered in horror.
@@ -5802,3 +6230,25 @@ is_identchar(int c)
{
return (is_alnum(c) || c == '_');
}
+
+/* make_profile_number --- make a number that can be printed when profiling */
+
+static NODE *
+make_profile_number(double d, const char *str, size_t len)
+{
+ NODE *n = make_number(d);
+ if (do_pretty_print) {
+ // extra byte in case need to add minus sign in negate_num
+ n->stptr = estrdup(str, len + 1);
+ n->stptr[len] = '\0';
+ n->stlen = len;
+ // Set STRCUR and n->stfmt for use when profiling
+ // (i.e., actually running the program) so that
+ // force_string() on this item will work ok.
+ // Thanks and a tip of the hatlo to valgrind.
+ n->flags |= (NUMCONSTSTR|STRCUR);
+ n->stfmt = STFMT_UNUSED;
+ }
+
+ return n;
+}
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
+}
diff --git a/builtin.c b/builtin.c
index 18c01f6e..c3e55596 100644
--- a/builtin.c
+++ b/builtin.c
@@ -2,22 +2,22 @@
* builtin.c - Builtin functions and various utility procedures.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2016 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
@@ -133,10 +133,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 */
@@ -148,7 +152,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);
@@ -193,9 +197,9 @@ do_fflush(int nargs)
/*
* November, 2012.
- * It turns out that circa 2002, when BWK
+ * It turns out that circa 2002, when BWK
* added fflush() and fflush("") to his awk, he made both of
- * them flush everything.
+ * them flush everything.
*
* Now, with our inside agent getting ready to try to get fflush()
* standardized in POSIX, we are going to make our awk consistent
@@ -354,9 +358,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"));
}
@@ -386,7 +390,7 @@ do_index(int nargs)
* If we don't have valid wide character strings, use
* the real bytes.
*/
- do_single_byte = ((s1->wstlen == 0 && s1->stlen > 0)
+ do_single_byte = ((s1->wstlen == 0 && s1->stlen > 0)
|| (s2->wstlen == 0 && s2->stlen > 0));
}
@@ -469,7 +473,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);
@@ -484,6 +488,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) {
@@ -515,7 +525,7 @@ do_length(int nargs)
/*
* Support for deferred loading of array elements requires that
- * we use the array length interface even though it isn't
+ * we use the array length interface even though it isn't
* necessary for the built-in array types.
*
* 1/2015: The deferred arrays are gone, but this is probably
@@ -528,7 +538,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);
@@ -557,7 +567,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)
@@ -716,7 +726,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;
@@ -956,7 +966,7 @@ check_pos:
case ' ': /* print ' ' or '-' */
/* 'space' flag is ignored */
/* if '+' already present */
- if (signchar != false)
+ if (signchar != false)
goto check_pos;
/* FALL THROUGH */
case '+': /* print '+' or '-' */
@@ -982,18 +992,18 @@ check_pos:
alt = true;
goto check_pos;
case '\'':
-#if defined(HAVE_LOCALE_H)
+#if defined(HAVE_LOCALE_H)
quote_flag = true;
goto check_pos;
#else
- goto retry;
+ goto retry;
#endif
case 'l':
if (big_flag)
break;
else {
static bool warned = false;
-
+
if (do_lint && ! warned) {
lintwarn(_("`l' is meaningless in awk formats; ignored"));
warned = true;
@@ -1010,7 +1020,7 @@ check_pos:
break;
else {
static bool warned = false;
-
+
if (do_lint && ! warned) {
lintwarn(_("`L' is meaningless in awk formats; ignored"));
warned = true;
@@ -1027,7 +1037,7 @@ check_pos:
break;
else {
static bool warned = false;
-
+
if (do_lint && ! warned) {
lintwarn(_("`h' is meaningless in awk formats; ignored"));
warned = true;
@@ -1043,8 +1053,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) {
@@ -1214,7 +1223,7 @@ out0:
jj = 0; /* keep using current val in loc.grouping[ii] */
else if (loc.grouping[ii+1] == CHAR_MAX)
quote_flag = false;
- else {
+ else {
ii++;
jj = 0;
}
@@ -1329,7 +1338,7 @@ mpf1:
zero_flag = (! lj
&& ((zero_flag && ! have_prec)
|| (fw == 0 && have_prec)));
-
+
(void) mpfr_get_z(mpzval, mf, MPFR_RNDZ); /* convert to GMP integer */
fmt_type = have_prec ? MP_INT_WITH_PREC : MP_INT_WITHOUT_PREC;
zi = mpzval;
@@ -1394,11 +1403,11 @@ mpf1:
PREPEND(ts[k]);
}
}
- if (loc.grouping[ii+1] == 0)
+ if (loc.grouping[ii+1] == 0)
jj = 0; /* keep using current val in loc.grouping[ii] */
- else if (loc.grouping[ii+1] == CHAR_MAX)
+ else if (loc.grouping[ii+1] == CHAR_MAX)
quote_flag = false;
- else {
+ else {
ii++;
jj = 0;
}
@@ -1578,7 +1587,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:
@@ -1649,7 +1658,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) {
@@ -1660,7 +1669,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();
}
@@ -1673,14 +1682,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
@@ -1713,7 +1730,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);
@@ -1854,7 +1871,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);
@@ -1903,7 +1920,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;
@@ -1917,16 +1934,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);
@@ -1952,9 +1966,9 @@ 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);
format = t1->stptr;
formatlen = t1->stlen;
@@ -2028,7 +2042,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);
@@ -2086,7 +2100,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;
@@ -2114,22 +2128,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)
@@ -2150,7 +2154,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;
@@ -2162,14 +2166,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
@@ -2183,8 +2195,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) {
@@ -2215,21 +2229,25 @@ do_print(int nargs, int redirtype)
/* do_print_rec --- special case printing of $0, for speed */
-void
+void
do_print_rec(int nargs, int redirtype)
{
FILE *fp = NULL;
NODE *f0;
struct redirect *rp = NULL;
- int errflg; /* not used, sigh */
+ int errflg = 0;
NODE *redir_exp = NULL;
assert(nargs == 0);
if (redirtype != 0) {
redir_exp = TOP();
- rp = redirect(redir_exp, redirtype, & errflg);
+ rp = redirect(redir_exp, redirtype, & errflg, true);
if (rp != NULL) {
if ((rp->flag & RED_TWOWAY) != 0 && rp->output.fp == NULL) {
+ if (is_non_fatal_redirect(redir_exp->stptr)) {
+ update_ERRNO_int(EBADF);
+ return;
+ }
(void) close_rp(rp, CLOSE_ALL);
fatal(_("print: attempt to write to closed write end of two-way pipe"));
}
@@ -2240,6 +2258,11 @@ do_print_rec(int nargs, int redirtype)
} else
fp = output_fp;
+ if (errflg) {
+ update_ERRNO_int(errflg);
+ return;
+ }
+
if (fp == NULL)
return;
@@ -2333,7 +2356,7 @@ do_tolower(int nargs)
NODE *t1, *t2;
t1 = POP_SCALAR();
- if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
+ if (do_lint && (fixtype(t1)->flags & STRING) == 0)
lintwarn(_("tolower: received non-string argument"));
t1 = force_string(t1);
t2 = make_string(t1->stptr, t1->stlen);
@@ -2364,7 +2387,7 @@ do_toupper(int nargs)
NODE *t1, *t2;
t1 = POP_SCALAR();
- if (do_lint && (t1->flags & (STRING|STRCUR)) == 0)
+ if (do_lint && (fixtype(t1)->flags & STRING) == 0)
lintwarn(_("toupper: received non-string argument"));
t1 = force_string(t1);
t2 = make_string(t1->stptr, t1->stlen);
@@ -2397,9 +2420,9 @@ do_atan2(int nargs)
POP_TWO_SCALARS(t1, t2);
if (do_lint) {
- if ((t1->flags & (NUMCUR|NUMBER)) == 0)
+ if ((fixtype(t1)->flags & NUMBER) == 0)
lintwarn(_("atan2: received non-numeric first argument"));
- if ((t2->flags & (NUMCUR|NUMBER)) == 0)
+ if ((fixtype(t2)->flags & NUMBER) == 0)
lintwarn(_("atan2: received non-numeric second argument"));
}
d1 = force_number(t1)->numbr;
@@ -2418,7 +2441,7 @@ do_sin(int nargs)
double d;
tmp = POP_SCALAR();
- if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+ if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
lintwarn(_("sin: received non-numeric argument"));
d = sin((double) force_number(tmp)->numbr);
DEREF(tmp);
@@ -2434,7 +2457,7 @@ do_cos(int nargs)
double d;
tmp = POP_SCALAR();
- if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0)
+ if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0)
lintwarn(_("cos: received non-numeric argument"));
d = cos((double) force_number(tmp)->numbr);
DEREF(tmp);
@@ -2453,6 +2476,8 @@ static char *const state = (char *const) istate;
NODE *
do_rand(int nargs ATTRIBUTE_UNUSED)
{
+ double tmprand;
+#define RAND_DIVISOR ((double)GAWK_RANDOM_MAX+1.0)
if (firstrand) {
(void) initstate((unsigned) 1, state, SIZEOF_STATE);
/* don't need to srandom(1), initstate() does it for us. */
@@ -2464,7 +2489,66 @@ do_rand(int nargs ATTRIBUTE_UNUSED)
*
* 0 <= n < 1
*/
- return make_number((AWKNUM) (random() % GAWK_RANDOM_MAX) / GAWK_RANDOM_MAX);
+ /*
+ * Date: Wed, 28 Aug 2013 17:52:46 -0700
+ * From: Bob Jewett <jewett@bill.scs.agilent.com>
+ *
+ * Call random() twice to fill in more bits in the value
+ * of the double. Also, there is a bug in random() such
+ * that when the values of successive values are combined
+ * like (rand1*rand2)^2, (rand3*rand4)^2, ... the
+ * resulting time series is not white noise. The
+ * following also seems to fix that bug.
+ *
+ * The add/subtract 0.5 keeps small bits from filling
+ * below 2^-53 in the double, not that anyone should be
+ * looking down there.
+ *
+ * Date: Wed, 25 Sep 2013 10:45:38 -0600 (MDT)
+ * From: "Nelson H. F. Beebe" <beebe@math.utah.edu>
+ * (4) The code is typical of many published fragments for converting
+ * from integer to floating-point, and I discuss the serious pitfalls
+ * in my book, because it leads to platform-dependent behavior at the
+ * end points of the interval [0,1]
+ *
+ * (5) the documentation in the gawk info node says
+ *
+ * `rand()'
+ * Return a random number. The values of `rand()' are uniformly
+ * distributed between zero and one. The value could be zero but is
+ * never one.(1)
+ *
+ * The division by RAND_DIVISOR may not guarantee that 1.0 is never
+ * returned: the programmer forgot the platform-dependent issue of
+ * rounding.
+ *
+ * For points 4 and 5, the safe way is a loop:
+ *
+ * double
+ * rand(void) // return value in [0.0, 1.0)
+ * {
+ * value = internal_rand();
+ *
+ * while (value == 1.0)
+ * value = internal_rand();
+ *
+ * return (value);
+ * }
+ */
+
+ do {
+ long d1, d2;
+ /*
+ * Do the calls in predictable order to avoid
+ * compiler differences in order of evaluation.
+ */
+ d1 = random();
+ d2 = random();
+ tmprand = 0.5 + ( (d1/RAND_DIVISOR + d2) / RAND_DIVISOR );
+ tmprand -= 0.5;
+ } while (tmprand == 1.0);
+
+ return make_number((AWKNUM) tmprand);
}
/* do_srand --- seed the random number generator */
@@ -2487,7 +2571,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);
@@ -2525,7 +2609,7 @@ do_match(int nargs)
tre = POP();
rp = re_update(tre);
t1 = POP_STRING();
-
+
rstart = research(rp, t1->stptr, 0, t1->stlen, RE_NEED_START);
if (rstart >= 0) { /* match succeded */
size_t *wc_indices = NULL;
@@ -2538,7 +2622,7 @@ do_match(int nargs)
}
rstart++; /* now it's 1-based indexing */
-
+
/* Build the array only if the caller wants the optional subpatterns */
if (dest != NULL) {
subsepstr = SUBSEP_node->var_value->stptr;
@@ -2554,7 +2638,7 @@ do_match(int nargs)
size_t subpat_len;
NODE **lhs;
NODE *sub;
-
+
start = t1->stptr + s;
subpat_start = s;
subpat_len = len = SUBPATEND(rp, t1->stptr, ii) - s;
@@ -2562,7 +2646,7 @@ do_match(int nargs)
subpat_start = wc_indices[s];
subpat_len = wc_indices[s + len - 1] - subpat_start + 1;
}
-
+
it = make_string(start, len);
it->flags |= MAYBE_NUM; /* user input */
@@ -2577,8 +2661,8 @@ 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");
} else if (amt > oldamt) {
@@ -2588,9 +2672,9 @@ do_match(int nargs)
memcpy(buf, buff, ilen);
memcpy(buf + ilen, subsepstr, subseplen);
memcpy(buf + ilen + subseplen, "start", 6);
-
+
slen = ilen + subseplen + 5;
-
+
it = make_number((AWKNUM) subpat_start + 1);
sub = make_string(buf, slen);
lhs = assoc_lookup(dest, sub);
@@ -2599,13 +2683,13 @@ do_match(int nargs)
if (dest->astore != NULL)
(*dest->astore)(dest, sub);
unref(sub);
-
+
memcpy(buf, buff, ilen);
memcpy(buf + ilen, subsepstr, subseplen);
memcpy(buf + ilen + subseplen, "length", 7);
-
+
slen = ilen + subseplen + 6;
-
+
it = make_number((AWKNUM) subpat_len);
sub = make_string(buf, slen);
lhs = assoc_lookup(dest, sub);
@@ -2640,9 +2724,9 @@ do_match(int nargs)
* Gsub can be tricksy; particularly when handling the case of null strings.
* The following awk code was useful in debugging problems. It is too bad
* that it does not readily translate directly into the C code, below.
- *
+ *
* #! /usr/local/bin/mawk -f
- *
+ *
* BEGIN {
* true = 1; false = 0
* print "--->", mygsub("abc", "b+", "FOO")
@@ -2652,7 +2736,7 @@ do_match(int nargs)
* print "--->", mygsub("abc", "c+", "X")
* print "--->", mygsub("abc", "x*$", "X")
* }
- *
+ *
* function mygsub(str, regex, replace, origstr, newstr, eosflag, nonzeroflag)
* {
* origstr = str;
@@ -2690,7 +2774,7 @@ do_match(int nargs)
* }
* if (length(str) > 0)
* newstr = newstr str # rest of string
- *
+ *
* return newstr
* }
*/
@@ -2702,7 +2786,7 @@ do_match(int nargs)
*
* The relevant text is to be found on lines 6394-6407 (pages 166, 167) of the
* 2001 standard:
- *
+ *
* sub(ere, repl[, in ])
* Substitute the string repl in place of the first instance of the
* extended regular expression ERE in string in and return the number of
@@ -2751,56 +2835,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);
@@ -2812,30 +2888,30 @@ set_how_many:
/* original string */
if ((flags & LITERAL) != 0)
- t = POP_STRING();
+ target = POP_STRING();
else {
lhs = POP_ADDRESS();
- t = force_string(*lhs);
+ target = force_string(*lhs);
}
}
global = (how_many == -1);
- s = POP_STRING(); /* replacement text */
+ rep_node = POP_STRING(); /* replacement text */
decr_sp(); /* regexp, already updated above */
/* do the search early to avoid work on non-match */
- if (research(rp, t->stptr, 0, t->stlen, RE_NEED_START) == -1 ||
- RESTART(rp, t->stptr) > t->stlen)
+ if (research(rp, target->stptr, 0, target->stlen, RE_NEED_START) == -1 ||
+ RESTART(rp, target->stptr) > target->stlen)
goto done;
- t->flags |= STRING;
+ target->flags |= STRING;
- text = t->stptr;
- textlen = t->stlen;
+ text = target->stptr;
+ textlen = target->stlen;
- repl = s->stptr;
- replend = repl + s->stlen;
+ repl = rep_node->stptr;
+ replend = repl + rep_node->stlen;
repllen = replend - repl;
ampersands = 0;
@@ -2853,6 +2929,7 @@ set_how_many:
index_multibyte_buffer(repl, mb_indices, repllen);
}
+ /* compute length of replacement string, number of ampersands */
for (scan = repl; scan < replend; scan++) {
if ((gawk_mb_cur_max == 1 || (repllen > 0 && mb_indices[scan - repl] == 1))
&& (*scan == '&')) {
@@ -2899,24 +2976,32 @@ set_how_many:
lastmatchnonzero = false;
- /* guesstimate how much room to allocate; +2 forces > 0 */
- buflen = textlen + (ampersands + 1) * repllen + 2;
- emalloc(buf, char *, buflen + 2, "do_sub");
+ /* guesstimate how much room to allocate; +1 forces > 0 */
+ buflen = textlen + (ampersands + 1) * repllen + 1;
+ emalloc(buf, char *, buflen + 1, "do_sub");
buf[buflen] = '\0';
- buf[buflen + 1] = '\0';
bp = buf;
for (current = 1;; current++) {
matches++;
- matchstart = t->stptr + RESTART(rp, t->stptr);
- matchend = t->stptr + REEND(rp, t->stptr);
+ matchstart = target->stptr + RESTART(rp, target->stptr);
+ matchend = target->stptr + REEND(rp, target->stptr);
/*
* create the result, copying in parts of the original
- * string
+ * string. note that length of replacement string can
+ * vary since ampersand is actual text of regexp match.
*/
- len = matchstart - text + repllen
- + ampersands * (matchend - matchstart);
+
+ /*
+ * add 1 to len to handle "empty" case where
+ * matchend == matchstart and we force a match on a single
+ * char. Use 'matchend - text' instead of 'matchstart - text'
+ * because we may not actually make any substitution depending
+ * on the 'global' and 'how_many' values.
+ */
+ len = matchend - text + repllen
+ + ampersands * (matchend - matchstart) + 1;
sofar = bp - buf;
while (buflen < (sofar + len + 1)) {
buflen *= 2;
@@ -2963,13 +3048,13 @@ set_how_many:
if (flags & GENSUB) { /* gensub, behave sanely */
if (isdigit((unsigned char) scan[1])) {
int dig = scan[1] - '0';
- if (dig < NUMSUBPATS(rp, t->stptr) && SUBPATSTART(rp, tp->stptr, dig) != -1) {
+ if (dig < NUMSUBPATS(rp, target->stptr) && SUBPATSTART(rp, tp->stptr, dig) != -1) {
char *start, *end;
-
- start = t->stptr
- + SUBPATSTART(rp, t->stptr, dig);
- end = t->stptr
- + SUBPATEND(rp, t->stptr, dig);
+
+ start = target->stptr
+ + SUBPATSTART(rp, target->stptr, dig);
+ end = target->stptr
+ + SUBPATEND(rp, target->stptr, dig);
for (cp = start; cp < end; cp++)
*bp++ = *cp;
@@ -3025,19 +3110,29 @@ set_how_many:
textlen = text + textlen - matchend;
text = matchend;
+#if 0
+ if (bp - buf > sofar + len)
+ fprintf(stderr, "debug: len = %zu, but used %ld\n", len, (long)((bp - buf) - (long)sofar));
+#endif
+
if ((current >= how_many && ! global)
|| ((long) textlen <= 0 && matchstart == matchend)
- || research(rp, t->stptr, text - t->stptr, textlen, RE_NEED_START) == -1)
+ || research(rp, target->stptr, text - target->stptr, textlen, RE_NEED_START) == -1)
break;
}
sofar = bp - buf;
- if (buflen - sofar - textlen - 1) {
- buflen = sofar + textlen + 2;
+ if (buflen < (sofar + textlen + 1)) {
+ buflen = sofar + textlen + 1;
erealloc(buf, char *, buflen, "do_sub");
bp = buf + sofar;
}
- for (scan = matchend; scan < text + textlen; scan++)
+ /*
+ * Note that text == matchend, since that assignment is made before
+ * exiting the 'for' loop above. Thus we copy in the rest of the
+ * original string.
+ */
+ for (scan = text; scan < text + textlen; scan++)
*bp++ = *scan;
*bp = '\0';
textlen = bp - buf;
@@ -3046,31 +3141,31 @@ set_how_many:
efree(mb_indices);
done:
- DEREF(s);
+ DEREF(rep_node);
if ((matches == 0 || (flags & LITERAL) != 0) && buf != NULL) {
- efree(buf);
+ efree(buf);
buf = NULL;
}
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 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);
+ *lhs = make_str_node(buf, textlen, ALREADY_MALLOCED);
}
return make_number((AWKNUM) matches);
@@ -3238,16 +3333,18 @@ 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;
shift = force_number(s2)->numbr;
+ if (val < 0 || shift < 0)
+ fatal(_("lshift(%f, %f): negative values are not allowed"), val, shift);
+
if (do_lint) {
- if (val < 0 || shift < 0)
- lintwarn(_("lshift(%f, %f): negative values will give strange results"), val, shift);
if (double_to_int(val) != val || double_to_int(shift) != shift)
lintwarn(_("lshift(%f, %f): fractional values will be truncated"), val, shift);
if (shift >= sizeof(uintmax_t) * CHAR_BIT)
@@ -3275,16 +3372,18 @@ 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;
shift = force_number(s2)->numbr;
+ if (val < 0 || shift < 0)
+ fatal(_("rshift(%f, %f): negative values are not allowed"), val, shift);
+
if (do_lint) {
- if (val < 0 || shift < 0)
- lintwarn(_("rshift(%f, %f): negative values will give strange results"), val, shift);
if (double_to_int(val) != val || double_to_int(shift) != shift)
lintwarn(_("rshift(%f, %f): fractional values will be truncated"), val, shift);
if (shift >= sizeof(uintmax_t) * CHAR_BIT)
@@ -3317,12 +3416,12 @@ 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;
- if (do_lint && val < 0)
- lintwarn(_("and: argument %d negative value %g will give strange results"), i, val);
+ if (val < 0)
+ fatal(_("and: argument %d negative value %g is not allowed"), i, val);
uval = (uintmax_t) val;
res &= uval;
@@ -3349,12 +3448,12 @@ 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;
- if (do_lint && val < 0)
- lintwarn(_("or: argument %d negative value %g will give strange results"), i, val);
+ if (val < 0)
+ fatal(_("or: argument %d negative value %g is not allowed"), i, val);
uval = (uintmax_t) val;
res |= uval;
@@ -3381,12 +3480,12 @@ 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;
- if (do_lint && val < 0)
- lintwarn(_("xor: argument %d negative value %g will give strange results"), i, val);
+ if (val < 0)
+ fatal(_("xor: argument %d negative value %g is not allowed"), i, val);
uval = (uintmax_t) val;
if (i == 1)
@@ -3410,17 +3509,16 @@ 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);
- if (do_lint) {
- if (d < 0)
- lintwarn(_("compl(%f): negative value will give strange results"), d);
- if (double_to_int(d) != d)
- lintwarn(_("compl(%f): fractional value will be truncated"), d);
- }
+ if (d < 0)
+ fatal(_("compl(%f): negative value is not allowed"), d);
+
+ if (do_lint && double_to_int(d) != d)
+ lintwarn(_("compl(%f): fractional value will be truncated"), d);
uval = (uintmax_t) d;
uval = ~ uval;
@@ -3435,11 +3533,11 @@ do_strtonum(int nargs)
NODE *tmp;
AWKNUM d;
- tmp = POP_SCALAR();
- if ((tmp->flags & (NUMBER|NUMCUR)) != 0)
- d = (AWKNUM) force_number(tmp)->numbr;
+ tmp = fixtype(POP_SCALAR());
+ if ((tmp->flags & NUMBER) != 0)
+ d = (AWKNUM) tmp->numbr;
else if (get_numbase(tmp->stptr, use_lc_numeric) != 10)
- d = nondec2awknum(tmp->stptr, tmp->stlen);
+ d = nondec2awknum(tmp->stptr, tmp->stlen, NULL);
else
d = (AWKNUM) force_number(tmp)->numbr;
@@ -3456,7 +3554,7 @@ do_strtonum(int nargs)
*/
AWKNUM
-nondec2awknum(char *str, size_t len)
+nondec2awknum(char *str, size_t len, char **endptr)
{
AWKNUM retval = 0.0;
char save;
@@ -3468,8 +3566,11 @@ nondec2awknum(char *str, size_t len)
* User called strtonum("0x") or some such,
* so just quit early.
*/
- if (len <= 2)
+ if (len <= 2) {
+ if (endptr)
+ *endptr = start;
return (AWKNUM) 0.0;
+ }
for (str += 2, len -= 2; len > 0; len--, str++) {
switch (*str) {
@@ -3502,14 +3603,21 @@ nondec2awknum(char *str, size_t len)
val = *str - 'A' + 10;
break;
default:
+ if (endptr)
+ *endptr = str;
goto done;
}
retval = (retval * 16) + val;
}
+ if (endptr)
+ *endptr = str;
} else if (*str == '0') {
for (; len > 0; len--) {
- if (! isdigit((unsigned char) *str))
+ if (! isdigit((unsigned char) *str)) {
+ if (endptr)
+ *endptr = str;
goto done;
+ }
else if (*str == '8' || *str == '9') {
str = start;
goto decimal;
@@ -3517,11 +3625,13 @@ nondec2awknum(char *str, size_t len)
retval = (retval * 8) + (*str - '0');
str++;
}
+ if (endptr)
+ *endptr = str;
} else {
decimal:
save = str[len];
str[len] = '\0';
- retval = strtod(str, NULL);
+ retval = strtod(str, endptr);
str[len] = save;
}
done:
@@ -3757,6 +3867,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 */
@@ -3813,3 +4042,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/cint_array.c b/cint_array.c
index 7a92cb0d..092ce88a 100644
--- a/cint_array.c
+++ b/cint_array.c
@@ -2,23 +2,23 @@
* cint_array.c - routines for arrays of (mostly) consecutive positive integer indices.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2013, 2016,
* 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
@@ -37,7 +37,7 @@ extern NODE **is_integer(NODE *symbol, NODE *subs);
* THRESHOLD --- Maximum capacity waste; THRESHOLD >= 2^(NHAT + 1).
*/
-static int NHAT = 10;
+static int NHAT = 10;
static long THRESHOLD;
/*
@@ -102,7 +102,7 @@ static void leaf_info(NODE *array, NODE *ndump, const char *aname);
static void leaf_print(NODE *array, size_t bi, int indent_level);
#endif
-/* powers of 2 table upto 2^30 */
+/* powers of 2 table upto 2^30 */
static const long power_two_table[] = {
1, 2, 4, 8, 16, 32, 64,
128, 256, 512, 1024, 2048, 4096,
@@ -118,7 +118,7 @@ static const long power_two_table[] = {
/*
* To store 2^n integers, allocate top-level array of size n, elements
* of which are 1-Dimensional (leaf-array) of geometrically increasing
- * size (power of 2).
+ * size (power of 2).
*
* [0] --> [ 0 ]
* [1] --> [ 1 ]
@@ -128,7 +128,7 @@ static const long power_two_table[] = {
* |k| --> [ 2^(k - 1)| ... | 2^k - 1 ]
* ...
*
- * For a given integer n (> 0), the leaf-array is at 1 + floor(log2(n)).
+ * For a given integer n (> 0), the leaf-array is at 1 + floor(log2(n)).
*
* The idea for the geometrically increasing array sizes is from:
* Fast Functional Lists, Hash-Lists, Deques and Variable Length Arrays.
@@ -394,7 +394,7 @@ cint_copy(NODE *symbol, NODE *newsymb)
for (i = NHAT; i < INT32_BIT; i++) {
if (old[i] == NULL)
continue;
- new[i] = make_node(Node_array_tree);
+ new[i] = make_node(Node_array_tree);
tree_copy(newsymb, old[i], new[i]);
}
@@ -494,7 +494,7 @@ cint_dump(NODE *symbol, NODE *ndump)
xsize = xn->table_size;
}
cint_size = symbol->table_size - xsize;
-
+
if ((symbol->flags & XARRAY) == 0)
fprintf(output_fp, "%s `%s'\n",
(symbol->parent_array == NULL) ? "array" : "sub-array",
@@ -525,7 +525,7 @@ cint_dump(NODE *symbol, NODE *ndump)
/* Node_array_tree + HAT */
kb += (sizeof(NODE) + tree_kilobytes(tn)) / 1024.0;
}
- kb += (INT32_BIT * sizeof(NODE *)) / 1024.0; /* symbol->nodes */
+ kb += (INT32_BIT * sizeof(NODE *)) / 1024.0; /* symbol->nodes */
kb += (symbol->array_capacity * sizeof(NODE *)) / 1024.0; /* value nodes in Node_array_leaf(s) */
if (xn != NULL) {
if (xn->array_funcs == int_array_func)
@@ -600,12 +600,12 @@ cint_hash(long k)
* By Sean Eron Anderson
* seander@cs.stanford.edu
* Individually, the code snippets here are in the public domain
- * (unless otherwise noted) — feel free to use them however you please.
- * The aggregate collection and descriptions are © 1997-2005
+ * (unless otherwise noted) --- feel free to use them however you please.
+ * The aggregate collection and descriptions are (C) 1997-2005
* Sean Eron Anderson. The code and descriptions are distributed in the
* hope that they will be useful, but WITHOUT ANY WARRANTY and without
* even the implied warranty of merchantability or fitness for a particular
- * purpose.
+ * purpose.
*
*/
@@ -678,15 +678,15 @@ cint_print(NODE *symbol)
/*
* A half HAT is defined here as a HAT with a top-level array of size n^2/2
* and holds the first n^2/2 elements.
- *
+ *
* 1. 2^8 elements can be stored in a full HAT of size 2^4.
- * 2. 2^9 elements can be stored in a half HAT of size 2^5.
+ * 2. 2^9 elements can be stored in a half HAT of size 2^5.
* 3. When the number of elements is some power of 2, it
* can be stored in a full or a half HAT.
* 4. When the number of elements is some power of 2, it
* can be stored in a HAT (full or half) with HATs as leaf elements
* (full or half), and so on (e.g. 2^8 elements in a HAT of size 2^4 (top-level
- * array dimension) with each leaf array being a HAT of size 2^2).
+ * array dimension) with each leaf array being a HAT of size 2^2).
*
* IMPLEMENTATION DETAILS:
* 1. A HAT of 2^12 elements needs 2^6 house-keeping NODEs
@@ -737,7 +737,7 @@ tree_lookup(NODE *symbol, NODE *tree, long k, int m, long base)
*/
n = (m + 1) / 2;
-
+
if (tree->table_size == 0) {
size_t actual_size;
NODE **table;
@@ -920,7 +920,7 @@ tree_list(NODE *tree, NODE **list, assoc_kind_t assoc_kind)
static void
tree_copy(NODE *newsymb, NODE *tree, NODE *newtree)
-{
+{
NODE **old, **new;
size_t j, hsize;
@@ -1061,13 +1061,13 @@ leaf_lookup(NODE *symbol, NODE *array, long k, long size, long base)
}
-/* leaf_exists --- check if the array contains an integer subscript */
+/* leaf_exists --- check if the array contains an integer subscript */
static inline NODE **
leaf_exists(NODE *array, long k)
{
NODE **lhs;
- lhs = array->nodes + (k - array->array_base);
+ lhs = array->nodes + (k - array->array_base);
return (*lhs != NULL) ? lhs : NULL;
}
@@ -1086,7 +1086,7 @@ leaf_clear(NODE *array)
continue;
if (r->type == Node_var_array) {
assoc_clear(r); /* recursively clear all sub-arrays */
- efree(r->vname);
+ efree(r->vname);
freenode(r);
} else
unref(r);
@@ -1104,7 +1104,7 @@ leaf_remove(NODE *symbol, NODE *array, long k)
{
NODE **lhs;
- lhs = array->nodes + (k - array->array_base);
+ lhs = array->nodes + (k - array->array_base);
if (*lhs == NULL)
return false;
*lhs = NULL;
@@ -1171,7 +1171,7 @@ leaf_list(NODE *array, NODE **list, assoc_kind_t assoc_kind)
/* index */
num = array->array_base + ci;
if ((assoc_kind & AISTR) != 0) {
- sprintf(buf, "%ld", num);
+ sprintf(buf, "%ld", num);
subs = make_string(buf, strlen(buf));
subs->numbr = num;
subs->flags |= (NUMCUR|NUMINT);
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
new file mode 100644
index 00000000..795ef1d9
--- /dev/null
+++ b/cmake/auk.ico
Binary files differ
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)
diff --git a/cmd.h b/cmd.h
index 11844157..4313a6fd 100644
--- a/cmd.h
+++ b/cmd.h
@@ -2,22 +2,22 @@
* cmd.h - definitions for command parser
*/
-/*
+/*
* Copyright (C) 2004, 2010, 2011, 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
@@ -106,7 +106,7 @@ enum argtype {
D_range
};
-/* non-number arguments to commands */
+/* non-number arguments to commands */
enum nametypeval {
A_NONE = 0,
@@ -135,7 +135,7 @@ typedef struct cmd_argument {
NODE *nodeval;
} value;
-#define a_int value.lval /* type = D_int or D_range */
+#define a_int value.lval /* type = D_int or D_range */
#define a_argument value.lval /* type = D_argument */
#define a_string value.sval /* type = D_string, D_array, D_subscript or D_variable */
#define a_node value.nodeval /* type = D_node, D_field or D_func */
diff --git a/command.c b/command.c
index 95f28f31..a0469bb8 100644
--- a/command.c
+++ b/command.c
@@ -89,7 +89,7 @@ static bool want_nodeval = false;
static int cmd_idx = -1; /* index of current command in cmd table */
static int repeat_idx = -1; /* index of last repeatable command in command table */
-static CMDARG *arg_list = NULL; /* list of arguments */
+static CMDARG *arg_list = NULL; /* list of arguments */
static long errcount = 0;
static char *lexptr_begin = NULL;
static bool in_commands = false;
@@ -97,7 +97,7 @@ static int num_dim;
static bool in_eval = false;
static const char start_EVAL[] = "function @eval(){";
-static const char end_EVAL[] = "}";
+static const char end_EVAL[] = "}";
static CMDARG *append_statement(CMDARG *stmt_list, char *stmt);
static NODE *concat_args(CMDARG *a, int count);
@@ -1553,7 +1553,7 @@ yyreduce:
bool terminate = false;
CMDARG *args;
int ctype = 0;
-
+
ctype = cmdtab[cmd_idx].type;
/* a blank line repeats previous command
@@ -1794,7 +1794,7 @@ yyreduce:
if (type) {
in_commands = true;
if (input_from_tty) {
- dbg_prompt = commands_prompt;
+ dbg_prompt = commands_prompt;
fprintf(out_fp, _("Type commands for when %s %d is hit, one per line.\n"),
(type == D_break) ? "breakpoint" : "watchpoint", num);
fprintf(out_fp, _("End with the command \"end\"\n"));
@@ -1811,7 +1811,7 @@ yyreduce:
yyerror(_("`end' valid only in command `commands' or `eval'"));
else {
if (input_from_tty)
- dbg_prompt = dgawk_prompt;
+ dbg_prompt = dgawk_prompt;
in_commands = false;
}
}
@@ -2108,7 +2108,7 @@ yyreduce:
CMDARG *a;
NODE *subs;
int count = 0;
-
+
for (a = (yyvsp[-1]); a != NULL; a = a->next)
count++;
subs = concat_args((yyvsp[-1]), count);
@@ -2165,7 +2165,7 @@ yyreduce:
case 145:
#line 678 "command.y" /* yacc.c:1646 */
- {
+ {
NODE *n = (yyvsp[0])->a_node;
if ((n->flags & NUMBER) == 0)
yyerror(_("non-numeric value found, numeric expected"));
@@ -2176,7 +2176,7 @@ yyreduce:
case 146:
#line 685 "command.y" /* yacc.c:1646 */
- {
+ {
NODE *n = (yyvsp[0])->a_node;
if ((n->flags & NUMBER) == 0)
yyerror(_("non-numeric value found, numeric expected"));
@@ -2498,12 +2498,12 @@ yyreturn:
-/* append_statement --- append 'stmt' to the list of eval awk statements */
+/* append_statement --- append 'stmt' to the list of eval awk statements */
static CMDARG *
-append_statement(CMDARG *stmt_list, char *stmt)
+append_statement(CMDARG *stmt_list, char *stmt)
{
- CMDARG *a, *arg;
+ CMDARG *a, *arg;
char *s;
int len, slen, ssize;
@@ -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 */
@@ -2535,14 +2535,14 @@ append_statement(CMDARG *stmt_list, char *stmt)
s[slen] = '\0';
return arg;
}
-
+
len = strlen(stmt) + 1; /* 1 for newline */
s = stmt_list->a_string;
slen = strlen(s);
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
@@ -2699,7 +2699,7 @@ get_command_name(int ctype)
return cmdtab[i].name;
}
return NULL;
-}
+}
/* mk_cmdarg --- make an argument for command */
@@ -2714,7 +2714,7 @@ mk_cmdarg(enum argtype type)
}
/* append_cmdarg --- append ARG to the list of arguments for the current command */
-
+
static void
append_cmdarg(CMDARG *arg)
{
@@ -2785,7 +2785,7 @@ yylex(void)
static char *lexend;
int c;
char *tokstart;
- size_t toklen;
+ size_t toklen;
yylval = (CMDARG *) NULL;
@@ -2799,7 +2799,7 @@ yylex(void)
again:
lexptr_begin = read_a_line(dbg_prompt);
if (lexptr_begin == NULL) { /* EOF or error */
- if (get_eof_status() == EXIT_FATAL)
+ if (get_eof_status() == EXIT_FATAL)
exit(EXIT_FATAL);
if (get_eof_status() == EXIT_FAILURE) {
static int seen_eof = 0;
@@ -2831,7 +2831,7 @@ again:
&& input_from_tty
)
history_expand_line(&lexptr_begin);
-
+
lexptr = lexptr_begin;
lexend = lexptr + strlen(lexptr);
if (*lexptr == '\0' /* blank line */
@@ -2850,14 +2850,14 @@ again:
}
repeat_idx = -1;
}
-
+
c = *lexptr;
while (c == ' ' || c == '\t')
c = *++lexptr;
if (! input_from_tty && c == '#')
- return '\n';
+ return '\n';
tokstart = lexptr;
if (lexptr >= lexend)
@@ -2914,7 +2914,7 @@ again:
}
c = *lexptr;
-
+
if (cmdtab[cmd_idx].type == D_option) {
if (c == '=')
return *lexptr++;
@@ -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) != '"') {
@@ -3016,8 +3016,8 @@ err:
r = mpg_integer();
mpfr_get_z(r->mpg_i, tmp->mpg_numbr, MPFR_RNDZ);
unref(tmp);
- }
- } else
+ }
+ } else
#endif
r = make_number(strtod(tokstart, & lexptr));
@@ -3126,7 +3126,7 @@ concat_args(CMDARG *arg, int count)
n = force_string(arg->a_node);
return dupnode(n);
}
-
+
emalloc(tmp, NODE **, count * sizeof(NODE *), "concat_args");
subseplen = SUBSEP_node->var_value->stlen;
subsep = SUBSEP_node->var_value->stptr;
@@ -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;
@@ -3161,7 +3161,7 @@ concat_args(CMDARG *arg, int count)
}
/* find_command --- find the index in 'cmdtab' using exact,
- * abbreviation or unique partial match
+ * abbreviation or unique partial match
*/
static int
@@ -3253,10 +3253,10 @@ do_help(CMDARG *arg, int cmd)
#ifdef HAVE_LIBREADLINE
-/* next_word --- find the next word in a line to complete
+/* next_word --- find the next word in a line to complete
* (word seperation characters are space and tab).
*/
-
+
static char *
next_word(char *p, int len, char **endp)
{
@@ -3338,10 +3338,10 @@ command_completion(const char *text, int start, int end)
if (this_cmd == D_print || this_cmd == D_printf)
return rl_completion_matches(text, variable_generator);
return NULL;
-}
+}
/* command_generator --- generator function for command completion */
-
+
static char *
command_generator(const char *text, int state)
{
@@ -3414,7 +3414,7 @@ argument_generator(const char *text, int state)
if (strncmp(name, text, textlen) == 0)
return estrdup(name, strlen(name));
}
- }
+ }
return NULL;
}
diff --git a/command.y b/command.y
index d0507034..4597dba1 100644
--- a/command.y
+++ b/command.y
@@ -2,23 +2,23 @@
* command.y - yacc/bison parser for debugger commands.
*/
-/*
+/*
* Copyright (C) 2004, 2010, 2011, 2014, 2016
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
@@ -42,7 +42,7 @@ static bool want_nodeval = false;
static int cmd_idx = -1; /* index of current command in cmd table */
static int repeat_idx = -1; /* index of last repeatable command in command table */
-static CMDARG *arg_list = NULL; /* list of arguments */
+static CMDARG *arg_list = NULL; /* list of arguments */
static long errcount = 0;
static char *lexptr_begin = NULL;
static bool in_commands = false;
@@ -50,7 +50,7 @@ static int num_dim;
static bool in_eval = false;
static const char start_EVAL[] = "function @eval(){";
-static const char end_EVAL[] = "}";
+static const char end_EVAL[] = "}";
static CMDARG *append_statement(CMDARG *stmt_list, char *stmt);
static NODE *concat_args(CMDARG *a, int count);
@@ -132,7 +132,7 @@ line
bool terminate = false;
CMDARG *args;
int ctype = 0;
-
+
ctype = cmdtab[cmd_idx].type;
/* a blank line repeats previous command
@@ -308,7 +308,7 @@ command
| D_LIST list_args
| D_UNTIL location
| D_CLEAR location
- | break_cmd break_args
+ | break_cmd break_args
| D_SET { want_nodeval = true; } variable '=' node
| D_OPTION option_args
| D_RETURN { want_nodeval = true; } opt_node
@@ -345,7 +345,7 @@ command
if (type) {
in_commands = true;
if (input_from_tty) {
- dbg_prompt = commands_prompt;
+ dbg_prompt = commands_prompt;
fprintf(out_fp, _("Type commands for when %s %d is hit, one per line.\n"),
(type == D_break) ? "breakpoint" : "watchpoint", num);
fprintf(out_fp, _("End with the command \"end\"\n"));
@@ -358,7 +358,7 @@ command
yyerror(_("`end' valid only in command `commands' or `eval'"));
else {
if (input_from_tty)
- dbg_prompt = dgawk_prompt;
+ dbg_prompt = dgawk_prompt;
in_commands = false;
}
}
@@ -493,9 +493,9 @@ location
break_args
: /* empty */
- { $$ = NULL; }
+ { $$ = NULL; }
| plus_integer { want_nodeval = true; } condition_exp
- | func_name
+ | func_name
| D_STRING ':' plus_integer { want_nodeval = true; } condition_exp
| D_STRING ':' func_name
;
@@ -631,7 +631,7 @@ subscript
CMDARG *a;
NODE *subs;
int count = 0;
-
+
for (a = $2; a != NULL; a = a->next)
count++;
subs = concat_args($2, count);
@@ -641,7 +641,7 @@ subscript
$2->a_node = subs;
$$ = $2;
}
- | '[' exp_list error
+ | '[' exp_list error
;
subscript_list
@@ -675,14 +675,14 @@ node
: D_NODE
{ $$ = $1; }
| '+' D_NODE
- {
+ {
NODE *n = $2->a_node;
if ((n->flags & NUMBER) == 0)
yyerror(_("non-numeric value found, numeric expected"));
$$ = $2;
}
| '-' D_NODE
- {
+ {
NODE *n = $2->a_node;
if ((n->flags & NUMBER) == 0)
yyerror(_("non-numeric value found, numeric expected"));
@@ -705,7 +705,7 @@ opt_integer
| integer
{ $$ = $1; }
;
-
+
plus_integer
: D_INT
{
@@ -720,7 +720,7 @@ plus_integer
$$ = $2;
}
;
-
+
integer
: D_INT
{ $$ = $1; }
@@ -748,12 +748,12 @@ nls
%%
-/* append_statement --- append 'stmt' to the list of eval awk statements */
+/* append_statement --- append 'stmt' to the list of eval awk statements */
static CMDARG *
-append_statement(CMDARG *stmt_list, char *stmt)
+append_statement(CMDARG *stmt_list, char *stmt)
{
- CMDARG *a, *arg;
+ CMDARG *a, *arg;
char *s;
int len, slen, ssize;
@@ -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 */
@@ -785,14 +785,14 @@ append_statement(CMDARG *stmt_list, char *stmt)
s[slen] = '\0';
return arg;
}
-
+
len = strlen(stmt) + 1; /* 1 for newline */
s = stmt_list->a_string;
slen = strlen(s);
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
@@ -949,7 +949,7 @@ get_command_name(int ctype)
return cmdtab[i].name;
}
return NULL;
-}
+}
/* mk_cmdarg --- make an argument for command */
@@ -964,7 +964,7 @@ mk_cmdarg(enum argtype type)
}
/* append_cmdarg --- append ARG to the list of arguments for the current command */
-
+
static void
append_cmdarg(CMDARG *arg)
{
@@ -1035,7 +1035,7 @@ yylex(void)
static char *lexend;
int c;
char *tokstart;
- size_t toklen;
+ size_t toklen;
yylval = (CMDARG *) NULL;
@@ -1049,7 +1049,7 @@ yylex(void)
again:
lexptr_begin = read_a_line(dbg_prompt);
if (lexptr_begin == NULL) { /* EOF or error */
- if (get_eof_status() == EXIT_FATAL)
+ if (get_eof_status() == EXIT_FATAL)
exit(EXIT_FATAL);
if (get_eof_status() == EXIT_FAILURE) {
static int seen_eof = 0;
@@ -1081,7 +1081,7 @@ again:
&& input_from_tty
)
history_expand_line(&lexptr_begin);
-
+
lexptr = lexptr_begin;
lexend = lexptr + strlen(lexptr);
if (*lexptr == '\0' /* blank line */
@@ -1100,14 +1100,14 @@ again:
}
repeat_idx = -1;
}
-
+
c = *lexptr;
while (c == ' ' || c == '\t')
c = *++lexptr;
if (! input_from_tty && c == '#')
- return '\n';
+ return '\n';
tokstart = lexptr;
if (lexptr >= lexend)
@@ -1164,7 +1164,7 @@ again:
}
c = *lexptr;
-
+
if (cmdtab[cmd_idx].type == D_option) {
if (c == '=')
return *lexptr++;
@@ -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) != '"') {
@@ -1266,8 +1266,8 @@ err:
r = mpg_integer();
mpfr_get_z(r->mpg_i, tmp->mpg_numbr, MPFR_RNDZ);
unref(tmp);
- }
- } else
+ }
+ } else
#endif
r = make_number(strtod(tokstart, & lexptr));
@@ -1376,7 +1376,7 @@ concat_args(CMDARG *arg, int count)
n = force_string(arg->a_node);
return dupnode(n);
}
-
+
emalloc(tmp, NODE **, count * sizeof(NODE *), "concat_args");
subseplen = SUBSEP_node->var_value->stlen;
subsep = SUBSEP_node->var_value->stptr;
@@ -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;
@@ -1411,7 +1411,7 @@ concat_args(CMDARG *arg, int count)
}
/* find_command --- find the index in 'cmdtab' using exact,
- * abbreviation or unique partial match
+ * abbreviation or unique partial match
*/
static int
@@ -1503,10 +1503,10 @@ do_help(CMDARG *arg, int cmd)
#ifdef HAVE_LIBREADLINE
-/* next_word --- find the next word in a line to complete
+/* next_word --- find the next word in a line to complete
* (word seperation characters are space and tab).
*/
-
+
static char *
next_word(char *p, int len, char **endp)
{
@@ -1588,10 +1588,10 @@ command_completion(const char *text, int start, int end)
if (this_cmd == D_print || this_cmd == D_printf)
return rl_completion_matches(text, variable_generator);
return NULL;
-}
+}
/* command_generator --- generator function for command completion */
-
+
static char *
command_generator(const char *text, int state)
{
@@ -1664,7 +1664,7 @@ argument_generator(const char *text, int state)
if (strncmp(name, text, textlen) == 0)
return estrdup(name, strlen(name));
}
- }
+ }
return NULL;
}
diff --git a/configh.in b/configh.in
index d3624c2b..41f63d4f 100644
--- a/configh.in
+++ b/configh.in
@@ -48,6 +48,9 @@
/* Define to 1 if you have the `fmod' function. */
#undef HAVE_FMOD
+/* Define to 1 if you have the `fwrite_unlocked' function. */
+#undef HAVE_FWRITE_UNLOCKED
+
/* have getaddrinfo */
#undef HAVE_GETADDRINFO
@@ -168,6 +171,9 @@
/* Define to 1 if you have the `setsid' function. */
#undef HAVE_SETSID
+/* Define to 1 if you have the `sigprocmask' function. */
+#undef HAVE_SIGPROCMASK
+
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
@@ -302,6 +308,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 +341,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 +368,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
diff --git a/configure b/configure
index 074ae48f..1fd6e4e8 100755
--- a/configure
+++ b/configure
@@ -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.4.
+# 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.4'
-PACKAGE_STRING='GNU Awk 4.1.4'
+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.4 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.4:";;
+ 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.4
+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.4, 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.4'
+ 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 :
@@ -10438,11 +9811,13 @@ esac
# Need the check for mkstemp and tmpfile for missing_d/snprintf.c.
for ac_func in __etoa_l atexit btowc fmod getgrent getgroups grantpt \
+ fwrite_unlocked \
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 +10872,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 +11013,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 +11418,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.4, 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 +11486,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.4
+GNU Awk config.status 4.1.60
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -12257,6 +11628,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 6f31e812..518a7398 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.4, 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
@@ -284,11 +264,13 @@ esac
# Need the check for mkstemp and tmpfile for missing_d/snprintf.c.
AC_CHECK_FUNCS(__etoa_l atexit btowc fmod getgrent getgroups grantpt \
+ fwrite_unlocked \
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 +402,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
diff --git a/custom.h b/custom.h
index 5660a66f..90fd1f63 100644
--- a/custom.h
+++ b/custom.h
@@ -10,23 +10,23 @@
* the information, to arnold@skeeve.com.
*/
-/*
+/*
* Copyright (C) 1995-2004, 2008, 2009, 2011, 2016
* 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
@@ -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)
diff --git a/debug.c b/debug.c
index 6d40cac5..6e3082d7 100644
--- a/debug.c
+++ b/debug.c
@@ -1,23 +1,23 @@
/*
- * debug.c - gawk debugger
+ * debug.c - gawk debugger
*/
-/*
+/*
* Copyright (C) 2004, 2010-2013, 2016 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
@@ -77,7 +77,7 @@ struct commands_item {
CMDARG *arg;
};
-/* breakpoint structure */
+/* breakpoint structure */
typedef struct break_point {
struct break_point *next;
struct break_point *prev;
@@ -99,7 +99,7 @@ typedef struct break_point {
#define BP_TEMP 4
#define BP_IGNORE 8
-} BREAKPOINT;
+} BREAKPOINT;
static BREAKPOINT breakpoints = { &breakpoints, &breakpoints, 0 };
@@ -126,12 +126,12 @@ struct list_item {
NODE *symbol; /* variable or function param */
NODE **subs; /* subscripts */
- int num_subs; /* subscript(dimension) count */
+ int num_subs; /* subscript(dimension) count */
char *sname; /* symbol or param name */
long fcall_count;
- struct commands_item commands;
+ struct commands_item commands;
int silent;
struct condition cndn;
@@ -149,8 +149,8 @@ struct list_item {
#define PARAM 1
#define SUBSCRIPT 2
#define FIELD_NUM 4
-#define OLD_IS_ARRAY 8 /* old item is array */
-#define CUR_IS_ARRAY 16 /* current item is array */
+#define OLD_IS_ARRAY 8 /* old item is array */
+#define CUR_IS_ARRAY 16 /* current item is array */
};
#define IS_PARAM(d) (((d)->flags & PARAM) != 0)
@@ -175,7 +175,7 @@ static struct {
INSTRUCTION *pc; /* 'until' and 'return' commands */
int repeat_count; /* 'step', 'next', 'stepi', 'nexti' commands */
bool print_frame; /* print frame info, 'finish' and 'until' */
- bool print_ret; /* print returned value, 'finish' */
+ bool print_ret; /* print returned value, 'finish' */
int break_point; /* non-zero (breakpoint number) if stopped at break point */
int watch_point; /* non-zero (watchpoint number) if stopped at watch point */
@@ -183,7 +183,7 @@ static struct {
* awk interpreter and return control
* to debugger command interpreter.
*/
-
+
enum argtype command; /* command type */
} stop;
@@ -216,7 +216,7 @@ struct dbg_option {
int *num_val;
char **str_val;
void (*assign)(const char *);
- const char *help_txt;
+ const char *help_txt;
};
#define DEFAULT_HISTFILE "./.gawk_history"
@@ -273,7 +273,7 @@ jmp_buf pager_quit_tag;
bool pager_quit_tag_valid = false;
static int screen_width = INT_MAX; /* no of columns */
static int screen_height = INT_MAX; /* no of rows */
-static int pager_lines_printed = 0; /* no of lines printed so far */
+static int pager_lines_printed = 0; /* no of lines printed so far */
static void restart(bool run) ATTRIBUTE_NORETURN;
static void close_all(void);
@@ -574,7 +574,7 @@ print_lines(char *src, int start_line, int nlines)
for (i = start_line; i < start_line + nlines; i++) {
int supposed_len, len;
char *p;
-
+
sprintf(linebuf, "%-8d", i);
/* mark the line about to be executed with =>; nlines > 1
@@ -582,7 +582,7 @@ print_lines(char *src, int start_line, int nlines)
*/
if (nlines > 1) {
BREAKPOINT *b;
- bool has_bpt = false;
+ bool has_bpt = false;
for (b = breakpoints.prev; b != &breakpoints; b = b->prev) {
if (src == b->src && i == b->bpi->source_line) {
has_bpt = true;
@@ -595,7 +595,7 @@ print_lines(char *src, int start_line, int nlines)
else
sprintf(linebuf, "%-4d =>", i);
} else if (has_bpt)
- sprintf(linebuf, "%-4d:b ", i);
+ sprintf(linebuf, "%-4d:b ", i);
}
p = linebuf + strlen(linebuf);
@@ -647,7 +647,7 @@ do_list(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
long count = list_size;
INSTRUCTION *rp;
char *src = cur_srcfile->src;
-
+
line_first = last_printed_line + 1; /* default or no arg */
if (arg == NULL) /* list or list + */
goto list;
@@ -679,10 +679,10 @@ range:
count = arg->a_int - line_first + 1;
break;
- case D_string:
+ case D_string:
src = arg->a_string;
if (arg->next != NULL) {
- arg = arg->next;
+ arg = arg->next;
if (arg->type == D_int) /* list file:n */
goto line;
else if (arg->type == D_range) /* list file:m-n */
@@ -713,7 +713,7 @@ list:
if (line_last != -1) {
last_printed_line = line_last;
last_print_count = line_last - line_first + 1;
- }
+ }
return false;
}
@@ -780,7 +780,7 @@ do_info(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
continue;
start++;
*end = '\0';
- gprintf(out_fp, "%s", start); /* FIXME: translate ? */
+ gprintf(out_fp, "%s", start); /* FIXME: translate ? */
*end = '}';
}
}
@@ -900,7 +900,7 @@ do_info(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
sub = d->subs[i];
gprintf(out_fp, "[\"%s\"]", sub->stptr);
}
- gprintf(out_fp, "\n");
+ gprintf(out_fp, "\n");
} else if (IS_FIELD(d))
gprintf(out_fp, "%d:\t$%ld\n", d->number, get_number_si(symbol));
else
@@ -920,7 +920,7 @@ do_info(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
continue;
start++;
*end = '\0';
- gprintf(out_fp, "%s", start); /* FIXME: translate ? */
+ gprintf(out_fp, "%s", start); /* FIXME: translate ? */
*end = '}';
}
}
@@ -998,7 +998,7 @@ find_param(const char *name, long num, char **pname)
func = f->func_node;
pcount = func->param_cnt;
for (i = 0; i < pcount; i++) {
- fparam = func->fparms[i].param;
+ fparam = func->fparms[i].param;
if (strcmp(name, fparam) == 0) {
r = f->stack[i];
if (r->type == Node_array_ref)
@@ -1123,7 +1123,7 @@ print_subscript(NODE *arr, char *arr_name, CMDARG *a, int count)
else {
/* print # of elements in array */
fprintf(out_fp, "%s = ", r->vname);
- print_symbol(r, false);
+ print_symbol(r, false);
}
} else {
fprintf(out_fp, "%s[\"%s\"] = ", arr_name, subs->stptr);
@@ -1163,7 +1163,7 @@ do_print_var(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
if ((r = find_array(name)) != NULL) {
int count = a->a_count;
for (; count > 0; count--) {
- NODE *value, *subs;
+ NODE *value, *subs;
a = a->next;
subs = a->a_node;
value = in_array(r, subs);
@@ -1195,9 +1195,9 @@ do_print_var(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
/* notably D_node, subscript for invalid array name; skip */
break;
}
- }
+ }
return false;
-}
+}
/* do_set_var --- set command */
@@ -1358,7 +1358,7 @@ delete_item(struct list_item *d)
free_context(d->cndn.ctxt, false);
if (d->cndn.expr != NULL)
efree(d->cndn.expr);
-
+
d->next->prev = d->prev;
d->prev->next = d->next;
efree(d);
@@ -1533,7 +1533,7 @@ display(struct list_item *d)
symbol = r;
if (i == count - 1) /* it's a sub-array */
goto print_sym; /* print # of elements in sub-array */
- } else {
+ } else {
if (i != count - 1)
return; /* FIXME msg and delete item ? */
fprintf(out_fp, "%d: %s[\"%s\"] = ", d->number,
@@ -1574,15 +1574,15 @@ do_display(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
}
/* do_undisplay --- undisplay command */
-
+
int
do_undisplay(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
{
do_delete_item(&display_list, arg);
- return false;
+ return false;
}
-/* condition_triggered --- test if a condition expression is true */
+/* condition_triggered --- test if a condition expression is true */
static int
condition_triggered(struct condition *cndn)
@@ -1631,21 +1631,21 @@ find_subscript(struct list_item *item, NODE **ptr)
}
/* cmp_val --- compare values of watched item, returns true if different; */
-
+
static int
-cmp_val(struct list_item *w, NODE *old, NODE *new)
+cmp_val(struct list_item *w, NODE *old, NODE *new)
{
/*
* case old new result
* ------------------------------
- * 1: NULL ARRAY true
+ * 1: NULL ARRAY true
* 2: NULL SCALAR true
* 3: NULL NULL false
* 4: SCALAR SCALAR cmp_node
* 5: SCALAR ARRAY true
* 6: SCALAR NULL true
* 7: ARRAY SCALAR true
- * 8: ARRAY ARRAY compare size
+ * 8: ARRAY ARRAY compare size
* 9: ARRAY NULL true
*/
@@ -1670,7 +1670,7 @@ cmp_val(struct list_item *w, NODE *old, NODE *new)
if (new->type == Node_var_array) /* 5 */
return true;
- return cmp_nodes(old, new); /* 4 */
+ return cmp_nodes(old, new, true); /* 4 */
}
/* watchpoint_triggered --- check if we should stop at this watchpoint;
@@ -1834,7 +1834,7 @@ do_watch(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
}
/* do_unwatch --- unwatch command */
-
+
int
do_unwatch(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
{
@@ -1881,9 +1881,9 @@ print_function(INSTRUCTION *pc, void *x)
{
NODE *func;
int i, pcount;
- struct pf_data *data = (struct pf_data *) x;
+ struct pf_data *data = (struct pf_data *) x;
int defn = data->defn;
- Func_print print_func = data->print_func;
+ Func_print print_func = data->print_func;
FILE *fp = data->fp;
func = pc->func_body;
@@ -1892,7 +1892,7 @@ print_function(INSTRUCTION *pc, void *x)
print_func(fp, "%s(", func->vname);
for (i = 0; i < pcount; i++) {
print_func(fp, "%s", func->fparms[i].param);
- if (i < pcount - 1)
+ if (i < pcount - 1)
print_func(fp, ", ");
}
print_func(fp, ")");
@@ -1936,7 +1936,7 @@ print_numbered_frame(long num)
} else {
fprintf(out_fp, _("#%ld\tin "), num);
print_frame(f->func_node, f->vname,
- ((INSTRUCTION *) find_frame(num - 1)->reti)->source_line);
+ ((INSTRUCTION *) find_frame(num - 1)->reti)->source_line);
}
fprintf(out_fp, "\n");
}
@@ -1965,7 +1965,7 @@ do_backtrace(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
if (cur < 0)
cur = 0;
}
- }
+ }
for (; cur <= last; cur++) {
print_numbered_frame(cur);
@@ -1973,12 +1973,12 @@ do_backtrace(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
if (cur <= fcall_count)
fprintf(out_fp, _("More stack frames follow ...\n"));
return false;
-}
+}
/* print_cur_frame_and_sourceline --- print current frame, and
* current source line.
*/
-
+
static void
print_cur_frame_and_sourceline()
{
@@ -2092,7 +2092,7 @@ find_rule(char *src, long lineno)
/* mk_breakpoint --- create a breakpoint instruction and the corresponding
* breakpoint structure.
*/
-
+
static INSTRUCTION *
mk_breakpoint(char *src, int srcline)
{
@@ -2113,7 +2113,7 @@ mk_breakpoint(char *src, int srcline)
b->src = src;
bp->break_pt = b;
b->bpi = bp;
-
+
/* prepend to list */
b->next = breakpoints.next;
b->prev = &breakpoints;
@@ -2136,7 +2136,7 @@ delete_breakpoint(BREAKPOINT *b)
* deleteing the instruction is not that simple,
* since could have reference to it somewhere else (e.g. cur_pc).
*/
-
+
pc->opcode = Op_no_op;
pc->source_line = 0;
pc->break_pt = NULL;
@@ -2147,7 +2147,7 @@ delete_breakpoint(BREAKPOINT *b)
delete_commands_item(c->next);
}
- free_context(b->cndn.ctxt, false);
+ free_context(b->cndn.ctxt, false);
if (b->cndn.expr != NULL)
efree(b->cndn.expr);
@@ -2165,7 +2165,7 @@ find_breakpoint(long num)
BREAKPOINT *b;
if (num <= 0)
- return NULL;
+ return NULL;
for (b = breakpoints.next; b != &breakpoints; b = b->next) {
if (b->number == num)
@@ -2175,7 +2175,7 @@ find_breakpoint(long num)
}
/* add_breakpoint --- add a breakpoint instruction between PREVP and IP */
-
+
static BREAKPOINT *
add_breakpoint(INSTRUCTION *prevp, INSTRUCTION *ip, char *src, bool silent)
{
@@ -2255,7 +2255,7 @@ set_breakpoint_at(INSTRUCTION *rp, int lineno, bool silent)
* a monotonically increasing sequence. Check if the line # is between
* the first and last statements of the case block before continuing
* the search.
- */
+ */
for (i2 = ip->stmt_start, i1 = i2->nexti; i2 != ip->stmt_end;
i2 = i1, i1 = i1->nexti) {
if (i1->source_line >= lineno)
@@ -2293,7 +2293,7 @@ set_breakpoint_next(INSTRUCTION *rp, INSTRUCTION *ip)
}
return NULL;
}
-
+
/* set_breakpoint --- set a breakpoint */
static int
@@ -2309,7 +2309,7 @@ set_breakpoint(CMDARG *arg, bool temporary)
if (arg == NULL) {
/*
* (From GDB Documentation):
-*
+*
* When called without any arguments, break sets a breakpoint at the next instruction
* to be executed in the selected stack frame (see section Examining the Stack).
* In any selected frame but the innermost, this makes your program stop as soon
@@ -2322,7 +2322,7 @@ set_breakpoint(CMDARG *arg, bool temporary)
* one instruction has been executed. If it did not do this,
* you would be unable to proceed past a breakpoint without first disabling the
* breakpoint. This rule applies whether or not the breakpoint already existed
-* when your program stopped.
+* when your program stopped.
*/
CHECK_PROG_RUNNING();
if (cur_frame == 0) {
@@ -2427,7 +2427,7 @@ breakpoint_triggered(BREAKPOINT *b)
if ((b->flags & BP_ENABLE_ONCE) != 0) {
b->flags &= ~BP_ENABLE_ONCE;
b->flags &= ~BP_ENABLE;
- }
+ }
return b->number;
}
@@ -2437,7 +2437,7 @@ int
do_breakpoint(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
{
return set_breakpoint(arg, false);
-}
+}
/* do_tmp_breakpoint --- tbreak command */
@@ -2611,7 +2611,7 @@ do_delete_breakpoint(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
delete_all = prompt_yes_no(
_("Delete all breakpoints? (y or n) "),
_("y")[0], true, out_fp);
-
+
if (delete_all) {
while (breakpoints.next != &breakpoints)
delete_breakpoint(breakpoints.next);
@@ -2736,7 +2736,7 @@ initialize_readline()
/* our completion function. */
rl_attempted_completion_function = command_completion;
- read_a_line = readline;
+ read_a_line = readline;
}
#else
#define initialize_readline() /* nothing */
@@ -2769,9 +2769,9 @@ debug_prog(INSTRUCTION *pc)
if (! read_a_line)
read_a_line = g_readline;
- push_cmd_src(input_fd, input_from_tty, read_a_line, 0, 0, EXIT_FATAL);
+ push_cmd_src(input_fd, input_from_tty, read_a_line, 0, 0, EXIT_FATAL);
- setbuf(out_fp, (char *) NULL);
+ setbuf(out_fp, (char *) NULL);
for (cur_srcfile = srcfiles->prev; cur_srcfile != srcfiles;
cur_srcfile = cur_srcfile->prev) {
if (cur_srcfile->stype == SRC_FILE
@@ -2800,7 +2800,7 @@ debug_prog(INSTRUCTION *pc)
unserialize(HISTORY);
unserialize(OPTION);
unsetenv("DGAWK_RESTART");
- fprintf(out_fp, "Restarting ...\n");
+ fprintf(out_fp, "Restarting ...\n");
if (strcasecmp(run, "true") == 0)
(void) do_run(NULL, 0);
@@ -2867,7 +2867,7 @@ check_breakpoint(INSTRUCTION **pi)
pc = *pi;
if (stop.command == D_return)
- return false;
+ return false;
if (pc->opcode == Op_breakpoint) {
int bnum;
*pi = pc->nexti; /* skip past the breakpoint instruction;
@@ -3239,7 +3239,7 @@ check_return(INSTRUCTION **pi)
func = find_frame(cur_frame)->func_node;
assert(func != NULL);
- *pi = (func->code_ptr + 1)->lasti;
+ *pi = (func->code_ptr + 1)->lasti;
/* assert((*pi)->opcode == Op_K_return); */
}
@@ -3306,7 +3306,7 @@ do_until(CMDARG *arg, int cmd)
int lineno;
INSTRUCTION *rp, *ip;
NODE *func;
-
+
CHECK_PROG_RUNNING();
stop.pc = NULL;
stop.sourceline = 0;
@@ -3413,7 +3413,7 @@ print_watch_item(struct list_item *w)
sub = w->subs[i];
fprintf(out_fp, "[\"%s\"]", sub->stptr);
}
- fprintf(out_fp, "\n");
+ fprintf(out_fp, "\n");
} else if (IS_FIELD(w))
fprintf(out_fp, "$%ld\n", get_number_si(symbol));
else
@@ -3478,12 +3478,12 @@ next_command()
print_watch_item(w);
}
- /* frame info */
+ /* frame info */
if (stop.print_frame) {
print_frame(frame_ptr->func_node, source, sourceline);
fprintf(out_fp, "\n");
stop.print_frame = false;
- }
+ }
(void) print_lines(source, sourceline, 1);
@@ -3495,12 +3495,12 @@ no_output:
/* update last_printed_line, so that output of 'list' is
* centered around current sourceline
*/
-
+
last_printed_line = sourceline - list_size / 2;
if (last_printed_line < 0)
last_printed_line = 0;
- /* update current source file */
+ /* update current source file */
s = source_find(source);
if (cur_srcfile != s) {
if (cur_srcfile->fd != INVALID_HANDLE) {
@@ -3526,7 +3526,7 @@ no_output:
read_command(); /* zzparse */
}
-/* debug_post_execute --- post_hook in the interpreter */
+/* debug_post_execute --- post_hook in the interpreter */
static void
debug_post_execute(INSTRUCTION *pc)
@@ -3545,14 +3545,14 @@ debug_post_execute(INSTRUCTION *pc)
stop.command = D_illegal;
stop.check_func = NULL;
fprintf(out_fp, _("'finish' not meaningful with non-local jump '%s'\n"),
- op2str(pc->opcode));
+ op2str(pc->opcode));
} else if (stop.command == D_until) {
/* cancel until command */
stop.print_frame = false;
stop.command = D_illegal;
stop.check_func = NULL;
fprintf(out_fp, _("'until' not meaningful with non-local jump '%s'\n"),
- op2str(pc->opcode));
+ op2str(pc->opcode));
}
break;
@@ -3579,7 +3579,7 @@ debug_post_execute(INSTRUCTION *pc)
}
}
-/* debug_pre_execute --- pre_hook, called by the interpreter before execution;
+/* debug_pre_execute --- pre_hook, called by the interpreter before execution;
* checks if execution needs to be suspended and control
* transferred to the debugger.
*/
@@ -3609,7 +3609,7 @@ debug_pre_execute(INSTRUCTION **pi)
* yield surprising results. Ditto for Op_push_lhs for special variables
* (upto Op_var_assign, the set_FOO routine).
*/
-
+
switch (cur_pc->opcode) {
case Op_field_spec_lhs:
cant_stop = true;
@@ -3617,7 +3617,7 @@ debug_pre_execute(INSTRUCTION **pi)
case Op_field_assign:
cant_stop = false;
- return true; /* may stop at next instruction */
+ return true; /* may stop at next instruction */
case Op_push_lhs:
m = cur_pc->memory;
@@ -3647,7 +3647,7 @@ debug_pre_execute(INSTRUCTION **pi)
break; /* processed later in check_breakpoint() */
default:
- if (cur_pc->source_line <= 0)
+ if (cur_pc->source_line <= 0)
return true;
break;
}
@@ -3685,7 +3685,7 @@ debug_pre_execute(INSTRUCTION **pi)
/* print_memory --- print a scalar value */
-static void
+static void
print_memory(NODE *m, NODE *func, Func_print print_func, FILE *fp)
{
switch (m->type) {
@@ -3703,17 +3703,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));
@@ -3725,7 +3714,7 @@ print_memory(NODE *m, NODE *func, Func_print print_func, FILE *fp)
case Node_dynregex:
break;
-
+
case Node_param_list:
assert(func != NULL);
print_func(fp, "%s", func->fparms[m->param_cnt].param);
@@ -3790,7 +3779,7 @@ print_instruction(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump)
func = find_frame(0)->func_node;
}
-
+
switch (pc->opcode) {
case Op_K_if:
print_func(fp, "[branch_if = %p] [branch_else = %p] [branch_else->lasti = %p]\n",
@@ -3954,7 +3943,7 @@ print_instruction(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump)
genflags2str(pc->sub_flags, values));
}
break;
-
+
case Op_builtin:
print_func(fp, "%s [arg_count = %ld]\n", getfname(pc->builtin),
pc->expr_count);
@@ -3987,7 +3976,7 @@ print_instruction(INSTRUCTION *pc, Func_print print_func, FILE *fp, int in_dump)
break;
case Op_concat:
- /* NB: concat_flag CSVAR only used in grammar, don't display it */
+ /* NB: concat_flag CSVAR only used in grammar, don't display it */
print_func(fp, "[expr_count = %ld] [concat_flag = %s]\n",
pc->expr_count,
(pc->concat_flag & CSUBSEP) != 0 ? "CSUBSEP" : "0");
@@ -4028,10 +4017,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:
@@ -4064,7 +4061,7 @@ do_trace_instruction(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
else
do_trace = false;
return false;
-}
+}
/* print_code --- print a list of instructions */
@@ -4148,7 +4145,7 @@ do_save(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
*/
if (strlen(line) > 1
- && strncmp(line, "sa", 2) == 0)
+ && strncmp(line, "sa", 2) == 0)
continue;
fprintf(fp, "%s\n", line);
@@ -4164,9 +4161,9 @@ do_save(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
int
do_option(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
{
- const struct dbg_option *opt;
+ const struct dbg_option *opt;
char *name, *value;
-
+
if (arg == NULL) { /* display all available options and corresponding values */
for (opt = option_list; opt->name; opt++) {
if (opt->str_val != NULL)
@@ -4201,7 +4198,7 @@ do_option(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
#ifdef HAVE_LIBREADLINE
-/* initialize_pager --- initialize our idea of the terminal size */
+/* initialize_pager --- initialize our idea of the terminal size */
void
initialize_pager(FILE *fp)
@@ -4237,9 +4234,9 @@ prompt_continue(FILE *fp)
if (quit_pager)
longjmp(pager_quit_tag, 1);
pager_lines_printed = 0;
-}
+}
-/* gprintf --- like fprintf but allows paging */
+/* gprintf --- like fprintf but allows paging */
int
gprintf(FILE *fp, const char *format, ...)
@@ -4254,13 +4251,13 @@ 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
-
+
while (true) {
va_start(args, format);
nchar = vsnprintf(buf + bl, buflen - bl, format, args);
@@ -4274,14 +4271,14 @@ gprintf(FILE *fp, const char *format, ...)
break;
}
- /* enlarge buffer, and try again */
+ /* enlarge buffer, and try again */
buflen *= 2;
- erealloc(buf, char *, (buflen + 2) * sizeof(char), "gprintf");
+ erealloc(buf, char *, buflen * sizeof(char), "gprintf");
}
bl = 0;
for (p = buf; (q = strchr(p, '\n')) != NULL; p = q + 1) {
- int sz = (int) (q - p);
+ int sz = (int) (q - p);
while (sz > 0) {
int cnt;
@@ -4301,7 +4298,7 @@ gprintf(FILE *fp, const char *format, ...)
sz -= screen_width;
assert(sz > 0);
p += cnt;
- }
+ }
}
fprintf(fp, "\n");
@@ -4316,7 +4313,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",
@@ -4326,7 +4323,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",
@@ -4405,7 +4402,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;
@@ -4414,7 +4411,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
@@ -4457,7 +4454,7 @@ enlarge_buffer:
else
nchar = snprintf(buf + bl, buflen - bl, "%d%c%d%c%s%c",
wd->number, FSEP, D_variable, FSEP, wd->sname, FSEP);
- cnum = wd->number;
+ cnum = wd->number;
commands = &wd->commands;
cndn = &wd->cndn;
break;
@@ -4515,7 +4512,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");
@@ -4548,8 +4545,8 @@ enlarge_buffer:
buf[bl++] = FSEP; /* field */
buf[bl++] = RSEP; /* record */
buf[bl] = '\0';
-
- /* condition expression */
+
+ /* condition expression */
if (cndn->expr) {
bl--; /* undo RSEP from above */
nchar = strlen(cndn->expr);
@@ -4577,7 +4574,7 @@ enlarge_buffer:
break;
default:
break;
- }
+ }
}
if (bl > 0) /* non-empty list */
@@ -4600,7 +4597,7 @@ unserialize_commands(char *str, int str_len)
/* unserialize_list_item --- create a list_item structure from unserialized data */
-
+
static struct list_item *
unserialize_list_item(struct list_item *list, char **pstr, int *pstr_len, int field_cnt)
{
@@ -4650,7 +4647,7 @@ unserialize_list_item(struct list_item *list, char **pstr, int *pstr_len, int fi
l->subs = subs;
}
l->number = num; /* keep same item number across executions */
-
+
if (list == &watch_list) {
initialize_watch_item(l);
/* unserialize watchpoint `commands' */
@@ -4667,11 +4664,11 @@ unserialize_list_item(struct list_item *list, char **pstr, int *pstr_len, int fi
} else
list->number = num;
- return l;
+ return l;
}
/* unserialize_breakpoint --- create a breakpoint structure from unserialized data */
-
+
static BREAKPOINT *
unserialize_breakpoint(char **pstr, int *pstr_len, int field_cnt)
{
@@ -4706,7 +4703,7 @@ unserialize_breakpoint(char **pstr, int *pstr_len, int field_cnt)
if (field_cnt > 6) /* unserialize breakpoint `commands' */
unserialize_commands(pstr[6], pstr_len[6]);
- if (field_cnt > 7) { /* condition expression */
+ if (field_cnt > 7) { /* condition expression */
char *expr;
expr = estrdup(pstr[7], pstr_len[7]);
if (parse_condition(D_break, b->number, expr) != 0)
@@ -4774,7 +4771,7 @@ unserialize(int type)
#ifdef GAWKDEBUG
fatal("Increase MAX_FIELD and recompile.\n");
#else
- return;
+ return;
#endif
}
@@ -4864,7 +4861,7 @@ has_break_or_watch_point(int *pnum, bool any)
/* N.B: breakpoints and watchpoints get numbers from a single
* counter/sequencer watch_list.number.
- */
+ */
for (b = breakpoints.next; b != &breakpoints; b = b->next) {
if (b->number == *pnum)
@@ -4899,7 +4896,7 @@ do_commands(CMDARG *arg, int cmd)
static struct list_item *w;
static struct commands_item *commands;
struct commands_item *c;
-
+
if (cmd == D_commands) {
int num = -1, type;
if (arg == NULL)
@@ -4947,7 +4944,7 @@ do_commands(CMDARG *arg, int cmd)
c->next = NULL;
c->cmd = cmd;
- /* N.B.: first arg is the command string, see command.y */
+ /* N.B.: first arg is the command string, see command.y */
c->cmd_string = arg->a_string;
c->arg = arg->next; /* actual arguments to the command */
efree(arg);
@@ -5044,7 +5041,7 @@ do_print_f(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
d_error(_("attempt to use array `%s[\"%s\"]' in a scalar context"),
name, subs->stptr);
goto done;
- } else
+ } else
tmp[i] = value;
} else {
if (value == NULL) {
@@ -5062,7 +5059,7 @@ do_print_f(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
}
}
}
- break;
+ break;
case D_node:
tmp[i] = a->a_node;
break;
@@ -5118,7 +5115,7 @@ static int
open_readfd(const char *file)
{
int fd;
-
+
fd = open(file, O_RDONLY);
if (fd <= INVALID_HANDLE)
return INVALID_HANDLE;
@@ -5150,14 +5147,14 @@ find_option(char *name)
void
option_help()
{
- const struct dbg_option *opt;
+ const struct dbg_option *opt;
for (opt = option_list; opt->name; opt++)
fprintf(out_fp, "\t%-15.15s - %s\n", opt->name, _(opt->help_txt));
}
#ifdef HAVE_LIBREADLINE
-
+
/* option_generator --- generator function for option name completion */
char *
@@ -5219,7 +5216,7 @@ set_gawk_output(const char *file)
output_is_tty = os_isatty(fileno(stderr));
return;
}
-
+
if (strncmp(cp, "fd/", 3) == 0) {
cp += 3;
fd = (int) strtoul(cp, NULL, 10);
@@ -5237,7 +5234,7 @@ set_gawk_output(const char *file)
if (fd > INVALID_HANDLE && fp == NULL) {
fp = fdopen(fd, "w");
if (fp == NULL)
- close(fd);
+ close(fd);
}
} else {
@@ -5268,7 +5265,7 @@ set_prompt(const char *value)
dbg_prompt = dgawk_prompt;
}
-/* set_option_flag --- convert option string to flag value */
+/* set_option_flag --- convert option string to flag value */
static int
set_option_flag(const char *value)
@@ -5352,7 +5349,7 @@ read_commands_string(const char *prompt ATTRIBUTE_UNUSED)
return NULL;
p = (char *) commands_string;
- end = (char *) commands_string + commands_string_len;
+ end = (char *) commands_string + commands_string_len;
for (; p < end; p++) {
if (*p == line_sep) {
line = estrdup(commands_string, p - commands_string);
@@ -5374,7 +5371,7 @@ static void
save_options(const char *file)
{
FILE *fp;
- const struct dbg_option *opt;
+ const struct dbg_option *opt;
fp = fopen(file, "w");
if (fp == NULL)
@@ -5413,7 +5410,7 @@ close_all()
close_extensions();
- set_gawk_output(NULL); /* closes output_fp if not stdout */
+ set_gawk_output(NULL); /* closes output_fp if not stdout */
}
/* pre_execute_code --- pre_hook for execute_code, called by pre_execute */
@@ -5463,7 +5460,7 @@ execute_code(volatile INSTRUCTION *code)
/* We use one global stack for all contexts.
* Save # of items in stack; in case of
* a fatal error, pop stack until it has that many items.
- */
+ */
save_stack_size = (stack_ptr - stack_bottom) + 1;
do_flags = false;
@@ -5499,13 +5496,13 @@ do_eval(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
int ret;
int save_flags = do_flags;
SRCFILE *the_source;
-
+
if (prog_running) {
this_frame = find_frame(0);
this_func = this_frame->func_node;
}
- install_params(this_func); /* expose current function parameters to eval */
+ install_params(this_func); /* expose current function parameters to eval */
ctxt = new_context();
ctxt->install_func = append_symbol; /* keep track of newly installed globals */
push_context(ctxt);
@@ -5530,9 +5527,9 @@ do_eval(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
eval->func_name = NULL; /* not needed, func_body already assigned */
(eval + 1)->expr_count = 0;
eval->nexti = bcalloc(Op_stop, 1, 0);
-
+
} else {
- /* execute as a part of the current function */
+ /* execute as a part of the current function */
int i;
INSTRUCTION *t;
@@ -5545,7 +5542,7 @@ do_eval(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
/* add or append eval locals to the current frame stack */
ecount = f->param_cnt; /* eval local count */
pcount = this_func->param_cnt;
-
+
if (ecount > 0) {
if (pcount == 0)
emalloc(this_frame->stack, NODE **, ecount * sizeof(NODE *), "do_eval");
@@ -5585,7 +5582,7 @@ do_eval(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
/* else
fatal error */
- if (this_func != NULL && ecount > 0) {
+ if (this_func != NULL && ecount > 0) {
int i;
/* undo frame manipulation from above */
@@ -5640,7 +5637,7 @@ GDB Documentation:
immediately for syntactic correctness, and to determine whether symbols
in it have referents in the context of your breakpoint. If expression
uses symbols not referenced in the context of the breakpoint, GDB prints
-an error message:
+an error message:
No symbol "foo" in current context.
*/
@@ -5676,7 +5673,7 @@ parse_condition(int type, int num, char *expr)
cndn = &b->cndn;
rp = find_rule(b->src, b->bpi->source_line);
if (rp != NULL && rp->opcode == Op_func)
- this_func = rp->func_body;
+ this_func = rp->func_body;
} else if (type == D_watch && (w = find_item(&watch_list, num)) != NULL) {
cndn = &w->cndn;
this_func = find_frame(cur_frame)->func_node;
@@ -5696,7 +5693,7 @@ parse_condition(int type, int num, char *expr)
do_flags = false;
ret = parse_program(&code);
do_flags = save_flags;
- remove_params(this_func);
+ remove_params(this_func);
pop_context();
if (ret != 0 || invalid_symbol) {
@@ -5705,7 +5702,7 @@ parse_condition(int type, int num, char *expr)
}
/* condition expression is parsed as awk pattern without
- * any action. The code is then modified to end up with
+ * any action. The code is then modified to end up with
* a `1.0' on stack when the expression is true, `0.0' otherwise.
*/
@@ -5720,7 +5717,7 @@ parse_condition(int type, int num, char *expr)
it->nexti = bcalloc(Op_jmp, 1, 0);
it->nexti->target_jmp = stop;
it->nexti->nexti = rule->lasti;
-
+
it = rule->lasti; /* Op_no_op, target for Op_jmp_false */
assert(it->opcode == Op_no_op);
it->opcode = Op_push_i;
@@ -5798,13 +5795,13 @@ push_cmd_src(
/* eof_status = EXIT_FATAL - exit with status EXIT_FATAL on EOF or error.
* = EXIT_FAILURE - exit status EXIT_FAILURE on error.
- * = EXIT_SUCCESS - don't exit on EOF or error.
+ * = EXIT_SUCCESS - don't exit on EOF or error.
*/
cs->eof_status = eofstatus;
cs->str = NULL;
cs->next = cmd_src;
cmd_src = cs;
-
+
input_fd = fd;
input_from_tty = istty;
read_a_line = readfunc;
diff --git a/dfa.c b/dfa.c
index 4d1e1ab0..62bb6435 100644
--- a/dfa.c
+++ b/dfa.c
@@ -59,7 +59,6 @@
#define _(str) gettext (str)
#include <wchar.h>
-#include <wctype.h>
#include "xalloc.h"
@@ -69,6 +68,8 @@
#include "dfa.h"
+#include "localeinfo.h"
+
#ifdef GAWK
static int
is_blank (int c)
@@ -77,14 +78,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
@@ -337,9 +330,6 @@ typedef struct
size_t hash; /* Hash of the positions of this state. */
position_set elems; /* Positions this state could match. */
unsigned char context; /* Context from previous state. */
- bool curr_dependent; /* True if the follows of any positions with
- ANYCHAR depends on the next character's
- context. */
unsigned short constraint; /* Constraint for this state to accept. */
token first_end; /* Token value of the first END in elems. */
position_set mbps; /* Positions which can match multibyte
@@ -372,6 +362,10 @@ struct regex_syntax
/* Flag for case-folding letters into sets. */
bool case_fold;
+ /* True if ^ and $ match only the start and end of data, and do not match
+ end-of-line within data. */
+ bool anchor;
+
/* End-of-line byte in data. */
unsigned char eolbyte;
@@ -395,8 +389,8 @@ struct regex_syntax
meaning of the @#%!@#%^!@ syntax bits. */
struct lexer_state
{
- char const *lexptr; /* Pointer to next input character. */
- size_t lexleft; /* Number of characters remaining. */
+ char const *ptr; /* Pointer to next input character. */
+ size_t left; /* Number of characters remaining. */
token lasttok; /* Previous token returned; initially END. */
size_t parens; /* Count of outstanding left parens. */
int minrep, maxrep; /* Repeat counts for {m,n}. */
@@ -435,12 +429,13 @@ struct dfa
charclass *charclasses; /* Array of character sets for CSET tokens. */
size_t cindex; /* Index for adding new charclasses. */
size_t calloc; /* Number of charclasses allocated. */
+ size_t canychar; /* Index of anychar class, or (size_t) -1. */
/* Scanner state */
- struct lexer_state lexstate;
+ struct lexer_state lex;
/* Parser state */
- struct parser_state parsestate;
+ struct parser_state parse;
/* Fields filled by the parser. */
token *tokens; /* Postfix parse array. */
@@ -453,14 +448,9 @@ struct dfa
size_t nregexps; /* Count of parallel regexps being built
with dfaparse. */
bool fast; /* The DFA is fast. */
- bool multibyte; /* MB_CUR_MAX > 1. */
token utf8_anychar_classes[5]; /* To lower ANYCHAR in UTF-8 locales. */
mbstate_t mbs; /* Multibyte conversion state. */
- /* dfaexec implementation. */
- char *(*dfaexec) (struct dfa *, char const *, char *,
- bool, size_t *, bool *);
-
/* The following are valid only if MB_CUR_MAX > 1. */
/* The value of multibyte_prop[i] is defined by following rule.
@@ -546,6 +536,21 @@ struct dfa
state_num **mb_trans; /* Transition tables for states with ANYCHAR. */
state_num mb_trcount; /* Number of transition tables for states with
ANYCHAR that have actually been built. */
+
+ /* Information derived from the locale. This is at the end so that
+ a quick memset need not clear it specially. */
+
+ /* dfaexec implementation. */
+ char *(*dfaexec) (struct dfa *, char const *, char *,
+ bool, size_t *, bool *);
+
+ /* The locale is simple, like the C locale. These locales can be
+ processed more efficiently, e.g., the relationship between lower-
+ and upper-case letters is 1-1. */
+ bool simple_locale;
+
+ /* Other cached information derived from the locale. */
+ struct localeinfo localeinfo;
};
/* Some macros for user access to dfa internals. */
@@ -559,13 +564,8 @@ struct dfa
static void regexp (struct dfa *dfa);
-/* A table indexed by byte values that contains the corresponding wide
- character (if any) for that byte. WEOF means the byte is not a
- valid single-byte character. */
-static wint_t mbrtowc_cache[NOTCHAR];
-
/* Store into *PWC the result of converting the leading bytes of the
- multibyte buffer S of length N bytes, using the mbrtowc_cache in *D
+ multibyte buffer S of length N bytes, using D->localeinfo.sbctowc
and updating the conversion state in *D. On conversion error,
convert just a single byte, to WEOF. Return the number of bytes
converted.
@@ -574,7 +574,7 @@ static wint_t mbrtowc_cache[NOTCHAR];
* PWC points to wint_t, not to wchar_t.
* The last arg is a dfa *D instead of merely a multibyte conversion
- state D->mbs. D also contains an mbrtowc_cache for speed.
+ state D->mbs.
* N must be at least 1.
* S[N - 1] must be a sentinel byte.
* Shift encodings are not supported.
@@ -585,7 +585,7 @@ static size_t
mbs_to_wchar (wint_t *pwc, char const *s, size_t n, struct dfa *d)
{
unsigned char uc = s[0];
- wint_t wc = mbrtowc_cache[uc];
+ wint_t wc = d->localeinfo.sbctowc[uc];
if (wc == WEOF)
{
@@ -762,7 +762,7 @@ maybe_realloc (void *ptr, size_t nitems, size_t *nalloc, size_t itemsize)
/* In DFA D, find the index of charclass S, or allocate a new one. */
static size_t
-dfa_charclass_index (struct dfa *d, charclass const s)
+charclass_index (struct dfa *d, charclass const s)
{
size_t i;
@@ -777,78 +777,21 @@ dfa_charclass_index (struct dfa *d, charclass const s)
}
static bool
-unibyte_word_constituent (unsigned char c)
+unibyte_word_constituent (struct dfa const *dfa, unsigned char c)
{
- return mbrtowc_cache[c] != WEOF && (isalnum (c) || (c) == '_');
+ return dfa->localeinfo.sbctowc[c] != WEOF && (isalnum (c) || (c) == '_');
}
static int
char_context (struct dfa const *dfa, unsigned char c)
{
- if (c == dfa->syntax.eolbyte)
+ if (c == dfa->syntax.eolbyte && !dfa->syntax.anchor)
return CTX_NEWLINE;
- if (unibyte_word_constituent (c))
+ if (unibyte_word_constituent (dfa, c))
return CTX_LETTER;
return CTX_NONE;
}
-/* UTF-8 encoding allows some optimizations that we can't otherwise
- assume in a multibyte encoding. */
-static bool using_utf8;
-
-bool
-dfa_using_utf8 (void)
-{
- return using_utf8;
-}
-
-static void
-init_mbrtowc_cache (void)
-{
- int i;
- for (i = CHAR_MIN; i <= CHAR_MAX; ++i)
- {
- char c = i;
- unsigned char uc = i;
- mbstate_t s = { 0 };
- wchar_t wc;
- mbrtowc_cache[uc] = mbrtowc (&wc, &c, 1, &s) <= 1 ? wc : WEOF;
- }
-}
-
-/* Entry point to set syntax options. */
-void
-dfasyntax (struct dfa *dfa, reg_syntax_t bits, bool fold, unsigned char eol)
-{
- int i;
- dfa->syntax.syntax_bits_set = true;
- dfa->syntax.syntax_bits = bits;
- dfa->syntax.case_fold = fold;
- dfa->syntax.eolbyte = eol;
-
- for (i = CHAR_MIN; i <= CHAR_MAX; ++i)
- {
- unsigned char uc = i;
-
- /* Use mbrtowc_cache to calculate sbit. */
- dfa->syntax.sbit[uc] = char_context (dfa, uc);
- switch (dfa->syntax.sbit[uc])
- {
- case CTX_LETTER:
- setbit (uc, dfa->syntax.letters);
- break;
- case CTX_NEWLINE:
- setbit (uc, dfa->syntax.newline);
- break;
- }
-
- /* POSIX requires that the five bytes in "\n\r./" (including the
- terminating NUL) cannot occur inside a multibyte character. */
- dfa->syntax.never_trail[uc] = (using_utf8 ? (uc & 0xc0) != 0x80
- : strchr ("\n\r./", uc) != NULL);
- }
-}
-
/* Set a bit in the charclass for the given wchar_t. Do nothing if WC
is represented by a multi-byte sequence. Even for MB_CUR_MAX == 1,
this may happen when folding case in weird Turkish locales where
@@ -877,30 +820,10 @@ setbit_case_fold_c (int b, charclass c)
setbit (i, c);
}
-static void check_utf8 (void)
-{
- wchar_t wc;
- mbstate_t mbs = { 0 };
- using_utf8 = mbrtowc (&wc, "\xc4\x80", 2, &mbs) == 2 && wc == 0x100;
-}
-
-static bool unibyte_c;
-
-static void check_unibyte_c (void)
-{
- char const *locale = setlocale (LC_ALL, NULL);
- unibyte_c = (!locale
- || STREQ (locale, "C")
- || STREQ (locale, "POSIX"));
-}
-
-/* The current locale is known to be a unibyte locale
- without multicharacter collating sequences and where range
- comparisons simply use the native encoding. These locales can be
- processed more efficiently. */
+/* Return true if the locale compatible with the C locale. */
static bool
-using_simple_locale (struct dfa const *dfa)
+using_simple_locale (bool multibyte)
{
/* The native character set is known to be compatible with
the C locale. The following test isn't perfect, but it's good
@@ -918,7 +841,15 @@ using_simple_locale (struct dfa const *dfa)
&& '}' == 125 && '~' == 126)
};
- return (!native_c_charset || dfa->multibyte) ? false : unibyte_c;
+ if (native_c_charset && !multibyte)
+ return true;
+ else
+ {
+ /* Treat C and POSIX locales as being compatible. Also, treat
+ errors as compatible, as these are invariably from stubs. */
+ char const *loc = setlocale (LC_ALL, NULL);
+ return !loc || STREQ (loc, "C") || STREQ (loc, "POSIX");
+ }
}
/* Fetch the next lexical input character. Set C (of type int) to the
@@ -930,23 +861,23 @@ using_simple_locale (struct dfa const *dfa)
otherwise. */
# define FETCH_WC(dfa, c, wc, eoferr) \
do { \
- if (! dfa->lexstate.lexleft) \
+ if (! (dfa)->lex.left) \
{ \
if ((eoferr) != 0) \
dfaerror (eoferr); \
else \
- return dfa->lexstate.lasttok = END; \
+ return (dfa)->lex.lasttok = END; \
} \
else \
{ \
wint_t _wc; \
- size_t nbytes = mbs_to_wchar (&_wc, dfa->lexstate.lexptr, \
- dfa->lexstate.lexleft, dfa); \
- dfa->lexstate.cur_mb_len = nbytes; \
+ size_t nbytes = mbs_to_wchar (&_wc, (dfa)->lex.ptr, \
+ (dfa)->lex.left, dfa); \
+ (dfa)->lex.cur_mb_len = nbytes; \
(wc) = _wc; \
- (c) = nbytes == 1 ? to_uchar (*dfa->lexstate.lexptr) : EOF; \
- dfa->lexstate.lexptr += nbytes; \
- dfa->lexstate.lexleft -= nbytes; \
+ (c) = nbytes == 1 ? to_uchar ((dfa)->lex.ptr[0]) : EOF; \
+ (dfa)->lex.ptr += nbytes; \
+ (dfa)->lex.left -= nbytes; \
} \
} while (false)
@@ -954,53 +885,6 @@ using_simple_locale (struct dfa const *dfa)
# define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
-/* The set of wchar_t values C such that there's a useful locale
- somewhere where C != towupper (C) && C != towlower (towupper (C)).
- For example, 0x00B5 (U+00B5 MICRO SIGN) is in this table, because
- towupper (0x00B5) == 0x039C (U+039C GREEK CAPITAL LETTER MU), and
- towlower (0x039C) == 0x03BC (U+03BC GREEK SMALL LETTER MU). */
-static short const lonesome_lower[] =
- {
- 0x00B5, 0x0131, 0x017F, 0x01C5, 0x01C8, 0x01CB, 0x01F2, 0x0345,
- 0x03C2, 0x03D0, 0x03D1, 0x03D5, 0x03D6, 0x03F0, 0x03F1,
-
- /* U+03F2 GREEK LUNATE SIGMA SYMBOL lacks a specific uppercase
- counterpart in locales predating Unicode 4.0.0 (April 2003). */
- 0x03F2,
-
- 0x03F5, 0x1E9B, 0x1FBE,
- };
-
-/* Maximum number of characters that can be the case-folded
- counterparts of a single character, not counting the character
- itself. This is 1 for towupper, 1 for towlower, and 1 for each
- entry in LONESOME_LOWER. */
-enum
-{ CASE_FOLDED_BUFSIZE = 2 + sizeof lonesome_lower / sizeof *lonesome_lower };
-
-/* Find the characters equal to C after case-folding, other than C
- itself, and store them into FOLDED. Return the number of characters
- stored. */
-static unsigned int
-case_folded_counterparts (wchar_t c, wchar_t folded[CASE_FOLDED_BUFSIZE])
-{
- unsigned int i;
- unsigned int n = 0;
- wint_t uc = towupper (c);
- wint_t lc = towlower (uc);
- if (uc != c)
- folded[n++] = uc;
- if (lc != uc && lc != c && towupper (lc) == uc)
- folded[n++] = lc;
- for (i = 0; i < sizeof lonesome_lower / sizeof *lonesome_lower; i++)
- {
- wint_t li = lonesome_lower[i];
- if (li != lc && li != uc && li != c && towupper (li) == uc)
- folded[n++] = li;
- }
- return n;
-}
-
typedef int predicate (int);
/* The following list maps the names of the Posix named character classes
@@ -1069,7 +953,7 @@ parse_bracket_exp (struct dfa *dfa)
size_t chars_al;
chars_al = 0;
- if (dfa->multibyte)
+ if (dfa->localeinfo.multibyte)
{
dfa->mbcsets = maybe_realloc (dfa->mbcsets, dfa->nmbcsets,
&dfa->mbcsets_alloc,
@@ -1092,7 +976,7 @@ parse_bracket_exp (struct dfa *dfa)
{
FETCH_WC (dfa, c, wc, _("unbalanced ["));
invert = true;
- known_bracket_exp = using_simple_locale (dfa);
+ known_bracket_exp = dfa->simple_locale;
}
else
invert = false;
@@ -1120,8 +1004,8 @@ parse_bracket_exp (struct dfa *dfa)
for (;;)
{
FETCH_WC (dfa, c, wc, _("unbalanced ["));
- if ((c == c1 && *dfa->lexstate.lexptr == ']')
- || dfa->lexstate.lexleft == 0)
+ if (dfa->lex.left == 0
+ || (c == c1 && dfa->lex.ptr[0] == ']'))
break;
if (len < MAX_BRACKET_STRING_LEN)
str[len++] = c;
@@ -1141,13 +1025,13 @@ parse_bracket_exp (struct dfa *dfa)
{
char const *class
= (dfa->syntax.case_fold && (STREQ (str, "upper")
- || STREQ (str, "lower")) ?
- "alpha" : str);
+ || STREQ (str, "lower"))
+ ? "alpha" : str);
const struct dfa_ctype *pred = find_pred (class);
if (!pred)
dfaerror (_("invalid character class"));
- if (dfa->multibyte && !pred->single_byte_only)
+ if (dfa->localeinfo.multibyte && !pred->single_byte_only)
known_bracket_exp = false;
else
for (c2 = 0; c2 < NOTCHAR; ++c2)
@@ -1182,7 +1066,7 @@ parse_bracket_exp (struct dfa *dfa)
/* A bracket expression like [a-[.aa.]] matches an unknown set.
Treat it like [-a[.aa.]] while parsing it, and
remember that the set is unknown. */
- if (c2 == '[' && *dfa->lexstate.lexptr == '.')
+ if (c2 == '[' && dfa->lex.ptr[0] == '.')
{
known_bracket_exp = false;
c2 = ']';
@@ -1192,8 +1076,8 @@ parse_bracket_exp (struct dfa *dfa)
{
/* In the case [x-], the - is an ordinary hyphen,
which is left in c1, the lookahead character. */
- dfa->lexstate.lexptr -= dfa->lexstate.cur_mb_len;
- dfa->lexstate.lexleft += dfa->lexstate.cur_mb_len;
+ dfa->lex.ptr -= dfa->lex.cur_mb_len;
+ dfa->lex.left += dfa->lex.cur_mb_len;
}
else
{
@@ -1207,9 +1091,9 @@ parse_bracket_exp (struct dfa *dfa)
/* Treat [x-y] as a range if x != y. */
if (wc != wc2 || wc == WEOF)
{
- if (dfa->multibyte)
+ if (dfa->localeinfo.multibyte)
known_bracket_exp = false;
- else if (using_simple_locale (dfa))
+ else if (dfa->simple_locale)
{
int ci;
for (ci = c; ci <= c2; ci++)
@@ -1236,7 +1120,7 @@ parse_bracket_exp (struct dfa *dfa)
colon_warning_state |= (c == ':') ? 2 : 4;
- if (!dfa->multibyte)
+ if (!dfa->localeinfo.multibyte)
{
if (dfa->syntax.case_fold)
setbit_case_fold_c (c, ccl);
@@ -1273,37 +1157,45 @@ parse_bracket_exp (struct dfa *dfa)
if (! known_bracket_exp)
return BACKREF;
- if (dfa->multibyte)
+ if (dfa->localeinfo.multibyte)
{
work_mbc->invert = invert;
- work_mbc->cset = emptyset (ccl) ? -1 : dfa_charclass_index (dfa, ccl);
+ work_mbc->cset = emptyset (ccl) ? -1 : charclass_index (dfa, ccl);
return MBCSET;
}
if (invert)
{
- assert (!dfa->multibyte);
+ assert (!dfa->localeinfo.multibyte);
notset (ccl);
if (dfa->syntax.syntax_bits & RE_HAT_LISTS_NOT_NEWLINE)
clrbit ('\n', ccl);
}
- return CSET + dfa_charclass_index (dfa, ccl);
+ return CSET + charclass_index (dfa, ccl);
}
-#define PUSH_LEX_STATE(s) \
- do \
- { \
- char const *lexptr_saved = dfa->lexstate.lexptr; \
- size_t lexleft_saved = dfa->lexstate.lexleft; \
- dfa->lexstate.lexptr = (s); \
- dfa->lexstate.lexleft = strlen (dfa->lexstate.lexptr)
+struct lexptr
+{
+ char const *ptr;
+ size_t left;
+};
-#define POP_LEX_STATE() \
- dfa->lexstate.lexptr = lexptr_saved; \
- dfa->lexstate.lexleft = lexleft_saved; \
- } \
- while (false)
+static void
+push_lex_state (struct dfa *dfa, struct lexptr *ls, char const *s)
+{
+ ls->ptr = dfa->lex.ptr;
+ ls->left = dfa->lex.left;
+ dfa->lex.ptr = s;
+ dfa->lex.left = strlen (s);
+}
+
+static void
+pop_lex_state (struct dfa *dfa, struct lexptr const *ls)
+{
+ dfa->lex.ptr = ls->ptr;
+ dfa->lex.left = ls->left;
+}
static token
lex (struct dfa *dfa)
@@ -1321,14 +1213,14 @@ lex (struct dfa *dfa)
"if (backslash) ...". */
for (i = 0; i < 2; ++i)
{
- FETCH_WC (dfa, c, dfa->lexstate.wctok, NULL);
+ FETCH_WC (dfa, c, dfa->lex.wctok, NULL);
switch (c)
{
case '\\':
if (backslash)
goto normal_char;
- if (dfa->lexstate.lexleft == 0)
+ if (dfa->lex.left == 0)
dfaerror (_("unfinished \\ escape"));
backslash = true;
break;
@@ -1337,28 +1229,29 @@ lex (struct dfa *dfa)
if (backslash)
goto normal_char;
if (dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_ANCHORS
- || dfa->lexstate.lasttok == END || dfa->lexstate.lasttok == LPAREN
- || dfa->lexstate.lasttok == OR)
- return dfa->lexstate.lasttok = BEGLINE;
+ || dfa->lex.lasttok == END || dfa->lex.lasttok == LPAREN
+ || dfa->lex.lasttok == OR)
+ return dfa->lex.lasttok = BEGLINE;
goto normal_char;
case '$':
if (backslash)
goto normal_char;
if (dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_ANCHORS
- || dfa->lexstate.lexleft == 0
- || (dfa->syntax.syntax_bits & RE_NO_BK_PARENS
- ? dfa->lexstate.lexleft > 0 && *dfa->lexstate.lexptr == ')'
- : dfa->lexstate.lexleft > 1 && dfa->lexstate.lexptr[0] == '\\'
- && dfa->lexstate.lexptr[1] == ')')
- || (dfa->syntax.syntax_bits & RE_NO_BK_VBAR
- ? dfa->lexstate.lexleft > 0 && *dfa->lexstate.lexptr == '|'
- : dfa->lexstate.lexleft > 1 && dfa->lexstate.lexptr[0] == '\\'
- && dfa->lexstate.lexptr[1] == '|')
+ || dfa->lex.left == 0
+ || ((dfa->lex.left
+ > !(dfa->syntax.syntax_bits & RE_NO_BK_PARENS))
+ && (dfa->lex.ptr[!(dfa->syntax.syntax_bits & RE_NO_BK_PARENS)
+ & (dfa->lex.ptr[0] == '\\')]
+ == ')'))
+ || ((dfa->lex.left
+ > !(dfa->syntax.syntax_bits & RE_NO_BK_VBAR))
+ && (dfa->lex.ptr[!(dfa->syntax.syntax_bits & RE_NO_BK_VBAR)
+ & (dfa->lex.ptr[0] == '\\')]
+ == '|'))
|| ((dfa->syntax.syntax_bits & RE_NEWLINE_ALT)
- && dfa->lexstate.lexleft > 0
- && *dfa->lexstate.lexptr == '\n'))
- return dfa->lexstate.lasttok = ENDLINE;
+ && dfa->lex.left > 0 && dfa->lex.ptr[0] == '\n'))
+ return dfa->lex.lasttok = ENDLINE;
goto normal_char;
case '1':
@@ -1372,8 +1265,8 @@ lex (struct dfa *dfa)
case '9':
if (backslash && !(dfa->syntax.syntax_bits & RE_NO_BK_REFS))
{
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok = BACKREF;
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok = BACKREF;
}
goto normal_char;
@@ -1381,7 +1274,7 @@ lex (struct dfa *dfa)
if (backslash && !(dfa->syntax.syntax_bits & RE_NO_GNU_OPS))
{
/* FIXME: should be beginning of string */
- return dfa->lexstate.lasttok = BEGLINE;
+ return dfa->lex.lasttok = BEGLINE;
}
goto normal_char;
@@ -1389,28 +1282,28 @@ lex (struct dfa *dfa)
if (backslash && !(dfa->syntax.syntax_bits & RE_NO_GNU_OPS))
{
/* FIXME: should be end of string */
- return dfa->lexstate.lasttok = ENDLINE;
+ return dfa->lex.lasttok = ENDLINE;
}
goto normal_char;
case '<':
if (backslash && !(dfa->syntax.syntax_bits & RE_NO_GNU_OPS))
- return dfa->lexstate.lasttok = BEGWORD;
+ return dfa->lex.lasttok = BEGWORD;
goto normal_char;
case '>':
if (backslash && !(dfa->syntax.syntax_bits & RE_NO_GNU_OPS))
- return dfa->lexstate.lasttok = ENDWORD;
+ return dfa->lex.lasttok = ENDWORD;
goto normal_char;
case 'b':
if (backslash && !(dfa->syntax.syntax_bits & RE_NO_GNU_OPS))
- return dfa->lexstate.lasttok = LIMWORD;
+ return dfa->lex.lasttok = LIMWORD;
goto normal_char;
case 'B':
if (backslash && !(dfa->syntax.syntax_bits & RE_NO_GNU_OPS))
- return dfa->lexstate.lasttok = NOTLIMWORD;
+ return dfa->lex.lasttok = NOTLIMWORD;
goto normal_char;
case '?':
@@ -1419,17 +1312,17 @@ lex (struct dfa *dfa)
if (backslash != ((dfa->syntax.syntax_bits & RE_BK_PLUS_QM) != 0))
goto normal_char;
if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS)
- && dfa->lexstate.laststart)
+ && dfa->lex.laststart)
goto normal_char;
- return dfa->lexstate.lasttok = QMARK;
+ return dfa->lex.lasttok = QMARK;
case '*':
if (backslash)
goto normal_char;
if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS)
- && dfa->lexstate.laststart)
+ && dfa->lex.laststart)
goto normal_char;
- return dfa->lexstate.lasttok = STAR;
+ return dfa->lex.lasttok = STAR;
case '+':
if (dfa->syntax.syntax_bits & RE_LIMITED_OPS)
@@ -1437,9 +1330,9 @@ lex (struct dfa *dfa)
if (backslash != ((dfa->syntax.syntax_bits & RE_BK_PLUS_QM) != 0))
goto normal_char;
if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS)
- && dfa->lexstate.laststart)
+ && dfa->lex.laststart)
goto normal_char;
- return dfa->lexstate.lasttok = PLUS;
+ return dfa->lex.lasttok = PLUS;
case '{':
if (!(dfa->syntax.syntax_bits & RE_INTERVALS))
@@ -1447,7 +1340,7 @@ lex (struct dfa *dfa)
if (backslash != ((dfa->syntax.syntax_bits & RE_NO_BK_BRACES) == 0))
goto normal_char;
if (!(dfa->syntax.syntax_bits & RE_CONTEXT_INDEP_OPS)
- && dfa->lexstate.laststart)
+ && dfa->lex.laststart)
goto normal_char;
/* Cases:
@@ -1457,111 +1350,107 @@ lex (struct dfa *dfa)
{,} - 0 to infinity (same as '*')
{M,N} - M through N */
{
- char const *p = dfa->lexstate.lexptr;
- char const *lim = p + dfa->lexstate.lexleft;
- dfa->lexstate.minrep = dfa->lexstate.maxrep = -1;
+ char const *p = dfa->lex.ptr;
+ char const *lim = p + dfa->lex.left;
+ dfa->lex.minrep = dfa->lex.maxrep = -1;
for (; p != lim && ISASCIIDIGIT (*p); p++)
- {
- if (dfa->lexstate.minrep < 0)
- dfa->lexstate.minrep = *p - '0';
- else
- dfa->lexstate.minrep = MIN (RE_DUP_MAX + 1,
- (dfa->lexstate.minrep
- * 10 + *p - '0'));
- }
+ dfa->lex.minrep = (dfa->lex.minrep < 0
+ ? *p - '0'
+ : MIN (RE_DUP_MAX + 1,
+ dfa->lex.minrep * 10 + *p - '0'));
if (p != lim)
{
if (*p != ',')
- dfa->lexstate.maxrep = dfa->lexstate.minrep;
+ dfa->lex.maxrep = dfa->lex.minrep;
else
{
- if (dfa->lexstate.minrep < 0)
- dfa->lexstate.minrep = 0;
+ if (dfa->lex.minrep < 0)
+ dfa->lex.minrep = 0;
while (++p != lim && ISASCIIDIGIT (*p))
- {
- if (dfa->lexstate.maxrep < 0)
- dfa->lexstate.maxrep = *p - '0';
- else
- dfa->lexstate.maxrep = MIN (RE_DUP_MAX + 1,
- (dfa->lexstate.maxrep
- * 10 + *p - '0'));
- }
+ dfa->lex.maxrep
+ = (dfa->lex.maxrep < 0
+ ? *p - '0'
+ : MIN (RE_DUP_MAX + 1,
+ dfa->lex.maxrep * 10 + *p - '0'));
}
}
if (! ((! backslash || (p != lim && *p++ == '\\'))
&& p != lim && *p++ == '}'
- && 0 <= dfa->lexstate.minrep
- && (dfa->lexstate.maxrep < 0
- || dfa->lexstate.minrep <= dfa->lexstate.maxrep)))
+ && 0 <= dfa->lex.minrep
+ && (dfa->lex.maxrep < 0
+ || dfa->lex.minrep <= dfa->lex.maxrep)))
{
if (dfa->syntax.syntax_bits & RE_INVALID_INTERVAL_ORD)
goto normal_char;
dfaerror (_("invalid content of \\{\\}"));
}
- if (RE_DUP_MAX < dfa->lexstate.maxrep)
+ if (RE_DUP_MAX < dfa->lex.maxrep)
dfaerror (_("regular expression too big"));
- dfa->lexstate.lexptr = p;
- dfa->lexstate.lexleft = lim - p;
+ dfa->lex.ptr = p;
+ dfa->lex.left = lim - p;
}
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok = REPMN;
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok = REPMN;
case '|':
if (dfa->syntax.syntax_bits & RE_LIMITED_OPS)
goto normal_char;
if (backslash != ((dfa->syntax.syntax_bits & RE_NO_BK_VBAR) == 0))
goto normal_char;
- dfa->lexstate.laststart = true;
- return dfa->lexstate.lasttok = OR;
+ dfa->lex.laststart = true;
+ return dfa->lex.lasttok = OR;
case '\n':
if (dfa->syntax.syntax_bits & RE_LIMITED_OPS
|| backslash || !(dfa->syntax.syntax_bits & RE_NEWLINE_ALT))
goto normal_char;
- dfa->lexstate.laststart = true;
- return dfa->lexstate.lasttok = OR;
+ dfa->lex.laststart = true;
+ return dfa->lex.lasttok = OR;
case '(':
if (backslash != ((dfa->syntax.syntax_bits & RE_NO_BK_PARENS) == 0))
goto normal_char;
- ++dfa->lexstate.parens;
- dfa->lexstate.laststart = true;
- return dfa->lexstate.lasttok = LPAREN;
+ dfa->lex.parens++;
+ dfa->lex.laststart = true;
+ return dfa->lex.lasttok = LPAREN;
case ')':
if (backslash != ((dfa->syntax.syntax_bits & RE_NO_BK_PARENS) == 0))
goto normal_char;
- if (dfa->lexstate.parens == 0
+ if (dfa->lex.parens == 0
&& dfa->syntax.syntax_bits & RE_UNMATCHED_RIGHT_PAREN_ORD)
goto normal_char;
- --dfa->lexstate.parens;
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok = RPAREN;
+ dfa->lex.parens--;
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok = RPAREN;
case '.':
if (backslash)
goto normal_char;
- if (dfa->multibyte)
+ if (dfa->canychar == (size_t) -1)
{
- /* In multibyte environment period must match with a single
- character not a byte. So we use ANYCHAR. */
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok = ANYCHAR;
+ zeroset (ccl);
+ notset (ccl);
+ if (!(dfa->syntax.syntax_bits & RE_DOT_NEWLINE))
+ clrbit ('\n', ccl);
+ if (dfa->syntax.syntax_bits & RE_DOT_NOT_NULL)
+ clrbit ('\0', ccl);
+ if (dfa->localeinfo.multibyte)
+ for (c2 = 0; c2 < NOTCHAR; c2++)
+ if (dfa->localeinfo.sbctowc[c2] == WEOF)
+ clrbit (c2, ccl);
+ dfa->canychar = charclass_index (dfa, ccl);
}
- zeroset (ccl);
- notset (ccl);
- if (!(dfa->syntax.syntax_bits & RE_DOT_NEWLINE))
- clrbit ('\n', ccl);
- if (dfa->syntax.syntax_bits & RE_DOT_NOT_NULL)
- clrbit ('\0', ccl);
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok = CSET + dfa_charclass_index (dfa, ccl);
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok = (dfa->localeinfo.multibyte
+ ? ANYCHAR
+ : CSET + dfa->canychar);
case 's':
case 'S':
if (!backslash || (dfa->syntax.syntax_bits & RE_NO_GNU_OPS))
goto normal_char;
- if (!dfa->multibyte)
+ if (!dfa->localeinfo.multibyte)
{
zeroset (ccl);
for (c2 = 0; c2 < NOTCHAR; ++c2)
@@ -1569,9 +1458,8 @@ lex (struct dfa *dfa)
setbit (c2, ccl);
if (c == 'S')
notset (ccl);
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok = CSET + dfa_charclass_index (dfa,
- ccl);
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok = CSET + charclass_index (dfa, ccl);
}
/* FIXME: see if optimizing this, as is done with ANYCHAR and
@@ -1580,31 +1468,31 @@ lex (struct dfa *dfa)
/* \s and \S are documented to be equivalent to [[:space:]] and
[^[:space:]] respectively, so tell the lexer to process those
strings, each minus its "already processed" '['. */
- PUSH_LEX_STATE (c == 's' ? "[:space:]]" : "^[:space:]]");
-
- dfa->lexstate.lasttok = parse_bracket_exp (dfa);
-
- POP_LEX_STATE ();
+ {
+ struct lexptr ls;
+ push_lex_state (dfa, &ls, &"^[:space:]]"[c == 's']);
+ dfa->lex.lasttok = parse_bracket_exp (dfa);
+ pop_lex_state (dfa, &ls);
+ }
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok;
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok;
case 'w':
case 'W':
if (!backslash || (dfa->syntax.syntax_bits & RE_NO_GNU_OPS))
goto normal_char;
- if (!dfa->multibyte)
+ if (!dfa->localeinfo.multibyte)
{
zeroset (ccl);
for (c2 = 0; c2 < NOTCHAR; ++c2)
- if (unibyte_word_constituent (c2))
+ if (dfa->syntax.sbit[c2] == CTX_LETTER)
setbit (c2, ccl);
if (c == 'W')
notset (ccl);
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok = CSET + dfa_charclass_index (dfa,
- ccl);
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok = CSET + charclass_index (dfa, ccl);
}
/* FIXME: see if optimizing this, as is done with ANYCHAR and
@@ -1613,38 +1501,38 @@ lex (struct dfa *dfa)
/* \w and \W are documented to be equivalent to [_[:alnum:]] and
[^_[:alnum:]] respectively, so tell the lexer to process those
strings, each minus its "already processed" '['. */
- PUSH_LEX_STATE (c == 'w' ? "_[:alnum:]]" : "^_[:alnum:]]");
-
- dfa->lexstate.lasttok = parse_bracket_exp (dfa);
-
- POP_LEX_STATE ();
+ {
+ struct lexptr ls;
+ push_lex_state (dfa, &ls, &"^_[:alnum:]]"[c == 'w']);
+ dfa->lex.lasttok = parse_bracket_exp (dfa);
+ pop_lex_state (dfa, &ls);
+ }
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok;
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok;
case '[':
if (backslash)
goto normal_char;
- dfa->lexstate.laststart = false;
- return dfa->lexstate.lasttok = parse_bracket_exp (dfa);
+ dfa->lex.laststart = false;
+ return dfa->lex.lasttok = parse_bracket_exp (dfa);
default:
normal_char:
- dfa->lexstate.laststart = false;
+ dfa->lex.laststart = false;
/* For multibyte character sets, folding is done in atom. Always
return WCHAR. */
- if (dfa->multibyte)
- return dfa->lexstate.lasttok = WCHAR;
+ if (dfa->localeinfo.multibyte)
+ return dfa->lex.lasttok = WCHAR;
if (dfa->syntax.case_fold && isalpha (c))
{
zeroset (ccl);
setbit_case_fold_c (c, ccl);
- return dfa->lexstate.lasttok = CSET + dfa_charclass_index (dfa,
- ccl);
+ return dfa->lex.lasttok = CSET + charclass_index (dfa, ccl);
}
- return dfa->lexstate.lasttok = c;
+ return dfa->lex.lasttok = c;
}
}
@@ -1661,11 +1549,11 @@ addtok_mb (struct dfa *dfa, token t, int mbprop)
{
dfa->tokens = x2nrealloc (dfa->tokens, &dfa->talloc,
sizeof *dfa->tokens);
- if (dfa->multibyte)
+ if (dfa->localeinfo.multibyte)
dfa->multibyte_prop = xnrealloc (dfa->multibyte_prop, dfa->talloc,
sizeof *dfa->multibyte_prop);
}
- if (dfa->multibyte)
+ if (dfa->localeinfo.multibyte)
dfa->multibyte_prop[dfa->tindex] = mbprop;
dfa->tokens[dfa->tindex++] = t;
@@ -1678,21 +1566,21 @@ addtok_mb (struct dfa *dfa, token t, int mbprop)
case CAT:
case OR:
- --dfa->parsestate.depth;
+ dfa->parse.depth--;
break;
case BACKREF:
dfa->fast = false;
/* fallthrough */
default:
- ++dfa->nleaves;
+ dfa->nleaves++;
/* fallthrough */
case EMPTY:
- ++dfa->parsestate.depth;
+ dfa->parse.depth++;
break;
}
- if (dfa->parsestate.depth > dfa->depth)
- dfa->depth = dfa->parsestate.depth;
+ if (dfa->parse.depth > dfa->depth)
+ dfa->depth = dfa->parse.depth;
}
static void addtok_wc (struct dfa *dfa, wint_t wc);
@@ -1702,7 +1590,7 @@ static void addtok_wc (struct dfa *dfa, wint_t wc);
static void
addtok (struct dfa *dfa, token t)
{
- if (dfa->multibyte && t == MBCSET)
+ if (dfa->localeinfo.multibyte && t == MBCSET)
{
bool need_or = false;
struct mb_char_classes *work_mbc = &dfa->mbcsets[dfa->nmbcsets - 1];
@@ -1749,19 +1637,19 @@ addtok_wc (struct dfa *dfa, wint_t wc)
size_t stored_bytes = wcrtomb ((char *) buf, wc, &s);
if (stored_bytes != (size_t) -1)
- dfa->lexstate.cur_mb_len = stored_bytes;
+ dfa->lex.cur_mb_len = stored_bytes;
else
{
/* This is merely stop-gap. buf[0] is undefined, yet skipping
the addtok_mb call altogether can corrupt the heap. */
- dfa->lexstate.cur_mb_len = 1;
+ dfa->lex.cur_mb_len = 1;
buf[0] = 0;
}
- addtok_mb (dfa, buf[0], dfa->lexstate.cur_mb_len == 1 ? 3 : 1);
- for (i = 1; i < dfa->lexstate.cur_mb_len; i++)
+ addtok_mb (dfa, buf[0], dfa->lex.cur_mb_len == 1 ? 3 : 1);
+ for (i = 1; i < dfa->lex.cur_mb_len; i++)
{
- addtok_mb (dfa, buf[i], i == dfa->lexstate.cur_mb_len - 1 ? 2 : 0);
+ addtok_mb (dfa, buf[i], i == dfa->lex.cur_mb_len - 1 ? 2 : 0);
addtok (dfa, CAT);
}
}
@@ -1801,7 +1689,7 @@ add_utf8_anychar (struct dfa *dfa)
if (dfa->syntax.syntax_bits & RE_DOT_NOT_NULL)
clrbit ('\0', c);
}
- dfa->utf8_anychar_classes[i] = CSET + dfa_charclass_index (dfa, c);
+ dfa->utf8_anychar_classes[i] = CSET + charclass_index (dfa, c);
}
/* A valid UTF-8 character is
@@ -1862,18 +1750,18 @@ add_utf8_anychar (struct dfa *dfa)
static void
atom (struct dfa *dfa)
{
- if (dfa->parsestate.tok == WCHAR)
+ if (dfa->parse.tok == WCHAR)
{
- if (dfa->lexstate.wctok == WEOF)
+ if (dfa->lex.wctok == WEOF)
addtok (dfa, BACKREF);
else
{
- addtok_wc (dfa, dfa->lexstate.wctok);
+ addtok_wc (dfa, dfa->lex.wctok);
if (dfa->syntax.case_fold)
{
wchar_t folded[CASE_FOLDED_BUFSIZE];
- unsigned int i, n = case_folded_counterparts (dfa->lexstate.wctok,
+ unsigned int i, n = case_folded_counterparts (dfa->lex.wctok,
folded);
for (i = 0; i < n; i++)
{
@@ -1883,9 +1771,9 @@ atom (struct dfa *dfa)
}
}
- dfa->parsestate.tok = lex (dfa);
+ dfa->parse.tok = lex (dfa);
}
- else if (dfa->parsestate.tok == ANYCHAR && using_utf8)
+ else if (dfa->parse.tok == ANYCHAR && dfa->localeinfo.using_utf8)
{
/* For UTF-8 expand the period to a series of CSETs that define a valid
UTF-8 character. This avoids using the slow multibyte path. I'm
@@ -1895,26 +1783,25 @@ atom (struct dfa *dfa)
UTF-8: it is the most used, and the structure of the encoding
makes the correctness more obvious. */
add_utf8_anychar (dfa);
- dfa->parsestate.tok = lex (dfa);
+ dfa->parse.tok = lex (dfa);
}
- else if ((dfa->parsestate.tok >= 0 && dfa->parsestate.tok < NOTCHAR)
- || dfa->parsestate.tok >= CSET || dfa->parsestate.tok == BACKREF
- || dfa->parsestate.tok == BEGLINE || dfa->parsestate.tok == ENDLINE
- || dfa->parsestate.tok == BEGWORD || dfa->parsestate.tok == ANYCHAR
- || dfa->parsestate.tok == MBCSET || dfa->parsestate.tok == ENDWORD
- || dfa->parsestate.tok == LIMWORD
- || dfa->parsestate.tok == NOTLIMWORD)
+ else if ((0 <= dfa->parse.tok && dfa->parse.tok < NOTCHAR)
+ || dfa->parse.tok >= CSET || dfa->parse.tok == BACKREF
+ || dfa->parse.tok == BEGLINE || dfa->parse.tok == ENDLINE
+ || dfa->parse.tok == BEGWORD || dfa->parse.tok == ANYCHAR
+ || dfa->parse.tok == MBCSET || dfa->parse.tok == ENDWORD
+ || dfa->parse.tok == LIMWORD || dfa->parse.tok == NOTLIMWORD)
{
- addtok (dfa, dfa->parsestate.tok);
- dfa->parsestate.tok = lex (dfa);
+ addtok (dfa, dfa->parse.tok);
+ dfa->parse.tok = lex (dfa);
}
- else if (dfa->parsestate.tok == LPAREN)
+ else if (dfa->parse.tok == LPAREN)
{
- dfa->parsestate.tok = lex (dfa);
+ dfa->parse.tok = lex (dfa);
regexp (dfa);
- if (dfa->parsestate.tok != RPAREN)
+ if (dfa->parse.tok != RPAREN)
dfaerror (_("unbalanced ("));
- dfa->parsestate.tok = lex (dfa);
+ dfa->parse.tok = lex (dfa);
}
else
addtok (dfa, EMPTY);
@@ -1947,7 +1834,7 @@ copytoks (struct dfa *dfa, size_t tindex, size_t ntokens)
{
size_t i;
- if (dfa->multibyte)
+ if (dfa->localeinfo.multibyte)
for (i = 0; i < ntokens; ++i)
addtok_mb (dfa, dfa->tokens[tindex + i], dfa->multibyte_prop[tindex + i]);
else
@@ -1962,40 +1849,39 @@ closure (struct dfa *dfa)
size_t tindex, ntokens;
atom (dfa);
- while (dfa->parsestate.tok == QMARK || dfa->parsestate.tok == STAR
- || dfa->parsestate.tok == PLUS || dfa->parsestate.tok == REPMN)
- if (dfa->parsestate.tok == REPMN
- && (dfa->lexstate.minrep || dfa->lexstate.maxrep))
+ while (dfa->parse.tok == QMARK || dfa->parse.tok == STAR
+ || dfa->parse.tok == PLUS || dfa->parse.tok == REPMN)
+ if (dfa->parse.tok == REPMN && (dfa->lex.minrep || dfa->lex.maxrep))
{
ntokens = nsubtoks (dfa, dfa->tindex);
tindex = dfa->tindex - ntokens;
- if (dfa->lexstate.maxrep < 0)
+ if (dfa->lex.maxrep < 0)
addtok (dfa, PLUS);
- if (dfa->lexstate.minrep == 0)
+ if (dfa->lex.minrep == 0)
addtok (dfa, QMARK);
- for (i = 1; i < dfa->lexstate.minrep; ++i)
+ for (i = 1; i < dfa->lex.minrep; i++)
{
copytoks (dfa, tindex, ntokens);
addtok (dfa, CAT);
}
- for (; i < dfa->lexstate.maxrep; ++i)
+ for (; i < dfa->lex.maxrep; i++)
{
copytoks (dfa, tindex, ntokens);
addtok (dfa, QMARK);
addtok (dfa, CAT);
}
- dfa->parsestate.tok = lex (dfa);
+ dfa->parse.tok = lex (dfa);
}
- else if (dfa->parsestate.tok == REPMN)
+ else if (dfa->parse.tok == REPMN)
{
dfa->tindex -= nsubtoks (dfa, dfa->tindex);
- dfa->parsestate.tok = lex (dfa);
+ dfa->parse.tok = lex (dfa);
closure (dfa);
}
else
{
- addtok (dfa, dfa->parsestate.tok);
- dfa->parsestate.tok = lex (dfa);
+ addtok (dfa, dfa->parse.tok);
+ dfa->parse.tok = lex (dfa);
}
}
@@ -2003,8 +1889,8 @@ static void
branch (struct dfa* dfa)
{
closure (dfa);
- while (dfa->parsestate.tok != RPAREN && dfa->parsestate.tok != OR
- && dfa->parsestate.tok >= 0)
+ while (dfa->parse.tok != RPAREN && dfa->parse.tok != OR
+ && dfa->parse.tok >= 0)
{
closure (dfa);
addtok (dfa, CAT);
@@ -2015,9 +1901,9 @@ static void
regexp (struct dfa *dfa)
{
branch (dfa);
- while (dfa->parsestate.tok == OR)
+ while (dfa->parse.tok == OR)
{
- dfa->parsestate.tok = lex (dfa);
+ dfa->parse.tok = lex (dfa);
branch (dfa);
addtok (dfa, OR);
}
@@ -2029,26 +1915,26 @@ regexp (struct dfa *dfa)
static void
dfaparse (char const *s, size_t len, struct dfa *d)
{
- d->lexstate.lexptr = s;
- d->lexstate.lexleft = len;
- d->lexstate.lasttok = END;
- d->lexstate.laststart = true;
- d->lexstate.parens = 0;
- if (d->multibyte)
+ d->lex.ptr = s;
+ d->lex.left = len;
+ d->lex.lasttok = END;
+ d->lex.laststart = true;
+ d->lex.parens = 0;
+ if (d->localeinfo.multibyte)
{
- d->lexstate.cur_mb_len = 0;
+ d->lex.cur_mb_len = 0;
memset (&d->mbs, 0, sizeof d->mbs);
}
if (!d->syntax.syntax_bits_set)
dfaerror (_("no syntax specified"));
- d->parsestate.tok = lex (d);
- d->parsestate.depth = d->depth;
+ d->parse.tok = lex (d);
+ d->parse.depth = d->depth;
regexp (d);
- if (d->parsestate.tok != END)
+ if (d->parse.tok != END)
dfaerror (_("unbalanced )"));
addtok (d, END - d->nregexps);
@@ -2169,7 +2055,6 @@ state_index (struct dfa *d, position_set const *s, int context)
size_t hash = 0;
int constraint = 0;
state_num i, j;
- bool curr_dependent = false;
token first_end = 0;
for (i = 0; i < s->nelem; ++i)
@@ -2223,17 +2108,6 @@ state_index (struct dfa *d, position_set const *s, int context)
}
else if (d->tokens[s->elems[j].index] == BACKREF)
constraint = NO_CONSTRAINT;
- if (d->multibyte && d->tokens[s->elems[j].index] == ANYCHAR)
- {
- int acceptable
- = ((SUCCEEDS_IN_CONTEXT (c, context, CTX_NEWLINE)
- ? CTX_NEWLINE : 0)
- | (SUCCEEDS_IN_CONTEXT (c, context, CTX_LETTER)
- ? CTX_LETTER : 0)
- | (SUCCEEDS_IN_CONTEXT (c, context, CTX_NONE)
- ? CTX_NONE : 0));
- curr_dependent |= acceptable && (context & ~acceptable);
- }
}
@@ -2244,7 +2118,6 @@ state_index (struct dfa *d, position_set const *s, int context)
alloc_position_set (&d->states[i].elems, s->nelem);
copy (s, &d->states[i].elems);
d->states[i].context = context;
- d->states[i].curr_dependent = curr_dependent;
d->states[i].constraint = constraint;
d->states[i].first_end = first_end;
d->states[i].mbps.nelem = 0;
@@ -2331,11 +2204,10 @@ charclass_context (struct dfa const *dfa, charclass c)
int context = 0;
unsigned int j;
- if (tstbit (dfa->syntax.eolbyte, c))
- context |= CTX_NEWLINE;
-
for (j = 0; j < CHARCLASS_WORDS; ++j)
{
+ if (c[j] & dfa->syntax.newline[j])
+ context |= CTX_NEWLINE;
if (c[j] & dfa->syntax.letters[j])
context |= CTX_LETTER;
if (c[j] & ~(dfa->syntax.letters[j] | dfa->syntax.newline[j]))
@@ -2700,25 +2572,22 @@ dfastate (state_num s, struct dfa *d, state_num trans[])
setbit (d->tokens[pos.index], matches);
else if (d->tokens[pos.index] >= CSET)
copyset (d->charclasses[d->tokens[pos.index] - CSET], matches);
- else if (d->multibyte && d->tokens[pos.index] == ANYCHAR)
+ else if (d->tokens[pos.index] == ANYCHAR)
{
- /* ANYCHAR must match a single character, so put it to
- D->states[s].mbps which contains the positions which can
- match with a single character not a byte. If all
- positions with ANYCHAR do not depend on the context of
- the next character, put its follows instead to
+ copyset (d->charclasses[d->canychar], matches);
+
+ /* ANYCHAR must match with a single character, so we must put
+ it to D->states[s].mbps which contains the positions which
+ can match with a single character not a byte. If all
+ positions which has ANYCHAR does not depend on context of
+ next character, we put the follows instead of it to
D->states[s].mbps to optimize. */
- if (d->states[s].curr_dependent)
- {
- if (d->states[s].mbps.nelem == 0)
- alloc_position_set (&d->states[s].mbps, 1);
- insert (pos, &d->states[s].mbps);
- }
- else if (SUCCEEDS_IN_CONTEXT (pos.constraint,
- d->states[s].context, CTX_ANY))
+ if (SUCCEEDS_IN_CONTEXT (pos.constraint, d->states[s].context,
+ CTX_NONE))
{
if (d->states[s].mbps.nelem == 0)
- alloc_position_set (&d->states[s].mbps, 1);
+ alloc_position_set (&d->states[s].mbps,
+ d->follows[pos.index].nelem);
for (j = 0; j < d->follows[pos.index].nelem; j++)
insert (d->follows[pos.index].elems[j], &d->states[s].mbps);
}
@@ -2832,22 +2701,27 @@ dfastate (state_num s, struct dfa *d, state_num trans[])
is to fail miserably. */
if (d->searchflag)
{
- /* Find the state(s) corresponding to the positions of state 0. */
- copy (&d->states[0].elems, &follows);
- separate_contexts = state_separate_contexts (&follows);
- state = state_index (d, &follows, separate_contexts ^ CTX_ANY);
- if (separate_contexts & CTX_NEWLINE)
- state_newline = state_index (d, &follows, CTX_NEWLINE);
- else
- state_newline = state;
- if (separate_contexts & CTX_LETTER)
- state_letter = state_index (d, &follows, CTX_LETTER);
- else
- state_letter = state;
+ int c;
+
+ state_newline = 0;
+ state_letter = d->min_trcount - 1;
+ state = d->initstate_notbol;
- for (i = 0; i < NOTCHAR; ++i)
- trans[i] = unibyte_word_constituent (i) ? state_letter : state;
- trans[d->syntax.eolbyte] = state_newline;
+ for (c = 0; c < NOTCHAR; ++c)
+ {
+ switch (d->syntax.sbit[c])
+ {
+ case CTX_NEWLINE:
+ trans[c] = state_newline;
+ break;
+ case CTX_LETTER:
+ trans[c] = state_letter;
+ break;
+ default:
+ trans[c] = state;
+ break;
+ }
+ }
}
else
for (i = 0; i < NOTCHAR; ++i)
@@ -2863,7 +2737,7 @@ dfastate (state_num s, struct dfa *d, state_num trans[])
for (k = 0; k < d->follows[grps[i].elems[j]].nelem; ++k)
insert (d->follows[grps[i].elems[j]].elems[k], &follows);
- if (d->multibyte)
+ if (d->localeinfo.multibyte)
{
/* If a token in follows.elems is not 1st byte of a multibyte
character, or the states of follows must accept the bytes
@@ -2896,7 +2770,7 @@ dfastate (state_num s, struct dfa *d, state_num trans[])
/* If we are building a searching matcher, throw in the positions
of state 0 as well. */
- if (d->searchflag && (!d->multibyte || !next_isnt_1st_byte))
+ if (d->searchflag && (!d->localeinfo.multibyte || !next_isnt_1st_byte))
{
merge (&d->states[0].elems, &follows, &tmp);
copy (&tmp, &follows);
@@ -2950,12 +2824,18 @@ dfastate (state_num s, struct dfa *d, state_num trans[])
{
int c = j * CHARCLASS_WORD_BITS + k;
- if (c == d->syntax.eolbyte)
- trans[c] = state_newline;
- else if (unibyte_word_constituent (c))
- trans[c] = state_letter;
- else if (c < NOTCHAR)
- trans[c] = state;
+ switch (d->syntax.sbit[c])
+ {
+ case CTX_NEWLINE:
+ trans[c] = state_newline;
+ break;
+ case CTX_LETTER:
+ trans[c] = state_letter;
+ break;
+ default:
+ trans[c] = state;
+ break;
+ }
}
}
@@ -2993,7 +2873,7 @@ realloc_trans_if_necessary (struct dfa *d, state_num new_state)
d->fails = xnrealloc (d->fails, newalloc, sizeof *d->fails);
d->success = xnrealloc (d->success, newalloc, sizeof *d->success);
d->newlines = xnrealloc (d->newlines, newalloc, sizeof *d->newlines);
- if (d->multibyte)
+ if (d->localeinfo.multibyte)
{
realtrans = d->mb_trans ? d->mb_trans - 1 : NULL;
realtrans = xnrealloc (realtrans, newalloc1, sizeof *realtrans);
@@ -3005,7 +2885,7 @@ realloc_trans_if_necessary (struct dfa *d, state_num new_state)
{
d->trans[oldalloc] = NULL;
d->fails[oldalloc] = NULL;
- if (d->multibyte)
+ if (d->localeinfo.multibyte)
d->mb_trans[oldalloc] = NULL;
}
}
@@ -3039,7 +2919,7 @@ build_state (state_num s, struct dfa *d)
}
d->trcount = d->min_trcount;
- if (d->multibyte)
+ if (d->localeinfo.multibyte)
{
for (i = d->min_trcount; i < d->tralloc; i++)
{
@@ -3096,16 +2976,6 @@ transit_state_singlebyte (struct dfa *d, state_num s, unsigned char const **pp)
{
state_num *t;
- if (**pp == d->syntax.eolbyte)
- {
- /* S is always an initial state in transit_state, so the
- transition table for the state must have been built already. */
- assert (d->trans[s] || d->fails[s]);
-
- ++*pp;
- return d->newlines[s];
- }
-
if (d->trans[s])
t = d->trans[s];
else if (d->fails[s])
@@ -3132,15 +3002,12 @@ static state_num
transit_state (struct dfa *d, state_num s, unsigned char const **pp,
unsigned char const *end)
{
- state_num s1;
+ state_num s1, s2;
wint_t wc;
int separate_contexts;
- state_num state, state_newline, mb_index;
- size_t i, j;
+ size_t i;
int mbclen = mbs_to_wchar (&wc, (char const *) *pp, end - *pp, d);
- int context = wc == d->syntax.eolbyte ? CTX_NEWLINE : CTX_NONE;
- bool context_newline = context == CTX_NEWLINE;
/* This state has some operators which can match a multibyte character. */
d->mb_follows.nelem = 0;
@@ -3152,31 +3019,9 @@ transit_state (struct dfa *d, state_num s, unsigned char const **pp,
s = transit_state_singlebyte (d, s, pp);
*pp += mbclen - i;
- if (d->states[s1].curr_dependent)
+ if (wc == WEOF)
{
- if (s < 0)
- d->mb_follows.nelem = 0;
- else
- copy (&d->states[s].elems, &d->mb_follows);
-
- for (i = 0; i < d->states[s1].mbps.nelem; i++)
- {
- if (!SUCCEEDS_IN_CONTEXT (d->states[s1].mbps.elems[i].constraint,
- d->states[s1].context, context))
- continue;
- for (j = 0; j < d->follows[d->states[s1].mbps.elems[i].index].nelem;
- j++)
- insert (d->follows[d->states[s1].mbps.elems[i].index].elems[j],
- &d->mb_follows);
- }
-
- separate_contexts = state_separate_contexts (&d->mb_follows);
- if (context_newline && separate_contexts & CTX_NEWLINE)
- s = state_index (d, &d->mb_follows, CTX_NEWLINE);
- else
- s = state_index (d, &d->mb_follows, separate_contexts ^ CTX_ANY);
- realloc_trans_if_necessary (d, s);
-
+ /* It is an invalid character, so ANYCHAR is not accepted. */
return s;
}
@@ -3187,11 +3032,11 @@ transit_state (struct dfa *d, state_num s, unsigned char const **pp,
{
if (MAX_TRCOUNT <= d->mb_trcount)
{
- state_num s2;
- for (s2 = -1; s2 < d->tralloc; s2++)
+ state_num s3;
+ for (s3 = -1; s3 < d->tralloc; s3++)
{
- free (d->mb_trans[s2]);
- d->mb_trans[s2] = NULL;
+ free (d->mb_trans[s3]);
+ d->mb_trans[s3] = NULL;
}
for (i = 0; i < d->sindex; i++)
@@ -3201,22 +3046,16 @@ transit_state (struct dfa *d, state_num s, unsigned char const **pp,
d->states[s1].mb_trindex = d->mb_trcount++;
}
- mb_index = d->states[s1].mb_trindex * 2;
-
if (! d->mb_trans[s])
{
enum { TRANSPTR_SIZE = sizeof *d->mb_trans[s] };
- enum { TRANSALLOC_SIZE = 2 * MAX_TRCOUNT * TRANSPTR_SIZE };
+ enum { TRANSALLOC_SIZE = MAX_TRCOUNT * TRANSPTR_SIZE };
d->mb_trans[s] = xmalloc (TRANSALLOC_SIZE);
- for (i = 0; i < 2 * MAX_TRCOUNT; i++)
+ for (i = 0; i < MAX_TRCOUNT; i++)
d->mb_trans[s][i] = -1;
}
- else
- {
- state = d->mb_trans[s][mb_index + context_newline];
- if (0 <= state)
- return state;
- }
+ else if (d->mb_trans[s][d->states[s1].mb_trindex] >= 0)
+ return d->mb_trans[s][d->states[s1].mb_trindex];
if (s < 0)
copy (&d->states[s1].mbps, &d->mb_follows);
@@ -3224,17 +3063,12 @@ transit_state (struct dfa *d, state_num s, unsigned char const **pp,
merge (&d->states[s1].mbps, &d->states[s].elems, &d->mb_follows);
separate_contexts = state_separate_contexts (&d->mb_follows);
- state = state_index (d, &d->mb_follows, separate_contexts ^ CTX_ANY);
- if (separate_contexts & CTX_NEWLINE)
- state_newline = state_index (d, &d->mb_follows, CTX_NEWLINE);
- else
- state_newline = state;
- realloc_trans_if_necessary (d, state_newline);
+ s2 = state_index (d, &d->mb_follows, separate_contexts ^ CTX_ANY);
+ realloc_trans_if_necessary (d, s2);
- d->mb_trans[s][mb_index] = state;
- d->mb_trans[s][mb_index + 1] = state_newline;
+ d->mb_trans[s][d->states[s1].mb_trindex] = s2;
- return context_newline ? state_newline : state;
+ return s2;
}
/* The initial state may encounter a byte which is not a single byte character
@@ -3254,16 +3088,14 @@ transit_state (struct dfa *d, state_num s, unsigned char const **pp,
Both P and MBP must be no larger than END. */
static unsigned char const *
skip_remains_mb (struct dfa *d, unsigned char const *p,
- unsigned char const *mbp, char const *end, wint_t *wcp)
+ unsigned char const *mbp, char const *end)
{
- wint_t wc = WEOF;
+ wint_t wc;
if (d->syntax.never_trail[*p])
return p;
while (mbp < p)
mbp += mbs_to_wchar (&wc, (char const *) mbp,
end - (char const *) mbp, d);
- if (wcp != NULL)
- *wcp = wc;
return mbp;
}
@@ -3299,6 +3131,39 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
unsigned char saved_end;
size_t nlcount = 0;
+ if (MAX_TRCOUNT <= d->sindex)
+ {
+ for (s = d->min_trcount; s < d->sindex; s++)
+ {
+ free (d->states[s].elems.elems);
+ free (d->states[s].mbps.elems);
+ }
+ d->sindex = d->min_trcount;
+
+ if (d->trans)
+ {
+ for (s = 0; s < d->tralloc; s++)
+ {
+ free (d->trans[s]);
+ free (d->fails[s]);
+ d->trans[s] = d->fails[s] = NULL;
+ }
+ d->trcount = 0;
+ }
+
+ if (d->localeinfo.multibyte && d->mb_trans)
+ {
+ for (s = -1; s < d->tralloc; s++)
+ {
+ free (d->mb_trans[s]);
+ d->mb_trans[s] = NULL;
+ }
+ for (s = 0; s < d->min_trcount; s++)
+ d->states[s].mb_trindex = -1;
+ d->mb_trcount = 0;
+ }
+ }
+
if (!d->tralloc)
{
realloc_trans_if_necessary (d, 1);
@@ -3320,51 +3185,25 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
for (;;)
{
- if (multibyte)
+ while ((t = trans[s]) != NULL)
{
- while ((t = trans[s]) != NULL)
+ if (s < d->min_trcount)
{
- s1 = s;
-
- if (s < d->min_trcount)
+ if (!multibyte || d->states[s].mbps.nelem == 0)
{
- if (d->min_trcount == 1)
- {
- if (d->states[s].mbps.nelem == 0)
- {
- do
- {
- while (t[*p] == 0)
- p++;
- p = mbp = skip_remains_mb (d, p, mbp, end, NULL);
- }
- while (t[*p] == 0);
- }
- else
- p = mbp = skip_remains_mb (d, p, mbp, end, NULL);
- }
- else
- {
- wint_t wc;
- mbp = skip_remains_mb (d, p, mbp, end, &wc);
-
- /* If d->min_trcount is greater than 1, maybe
- transit to another initial state after skip. */
- if (p < mbp)
- {
- /* It's CTX_LETTER or CTX_NONE. CTX_NEWLINE
- cannot happen, as we assume that a newline
- is always a single byte character. */
- s1 = s = d->initstate_notbol;
- p = mbp;
- }
- }
+ while (t[*p] == s)
+ p++;
}
+ if (multibyte)
+ p = mbp = skip_remains_mb (d, p, mbp, end);
+ }
+
+ if (multibyte)
+ {
+ s1 = s;
- if (d->states[s].mbps.nelem == 0 || (*p == eol && !allow_nl)
- || (*p == '\n' && !(d->syntax.syntax_bits & RE_DOT_NEWLINE))
- || (*p == '\0' && (d->syntax.syntax_bits & RE_DOT_NOT_NULL))
- || (char *) p >= end)
+ if (d->states[s].mbps.nelem == 0
+ || d->localeinfo.sbctowc[*p] != WEOF || (char *) p >= end)
{
/* If an input character does not match ANYCHAR, do it
like a single-byte character. */
@@ -3373,28 +3212,11 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
else
{
s = transit_state (d, s, &p, (unsigned char *) end);
- if (s >= 0 && p[-1] == eol)
- nlcount++;
mbp = p;
trans = d->trans;
}
}
- }
- else
- {
- if (s == 0)
- {
- t = trans[s];
- if (t)
- {
- while (t[*p] == 0)
- p++;
- s1 = 0;
- s = t[*p++];
- }
- }
-
- while ((t = trans[s]) != NULL)
+ else
{
s1 = t[*p++];
t = trans[s1];
@@ -3405,6 +3227,11 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
s1 = tmp; /* swap */
break;
}
+ if (s < d->min_trcount)
+ {
+ while (t[*p] == s1)
+ p++;
+ }
s = t[*p++];
}
}
@@ -3422,19 +3249,25 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
nlcount++;
mbp = p;
- s = allow_nl ? d->newlines[s1] : 0;
+ s = (allow_nl ? d->newlines[s1]
+ : d->syntax.sbit[eol] == CTX_NEWLINE ? 0
+ : d->syntax.sbit[eol] == CTX_LETTER ? d->min_trcount - 1
+ : d->initstate_notbol);
}
else if (d->fails[s])
{
- if (d->success[s] & d->syntax.sbit[*p])
+ if ((d->success[s] & d->syntax.sbit[*p])
+ || ((char *) p == end
+ && ACCEPTS_IN_CONTEXT (d->states[s].context, CTX_NEWLINE, s,
+ *d)))
goto done;
+ if (multibyte && s < d->min_trcount)
+ p = mbp = skip_remains_mb (d, p, mbp, end);
+
s1 = s;
if (!multibyte || d->states[s].mbps.nelem == 0
- || (*p == eol && !allow_nl)
- || (*p == '\n' && !(d->syntax.syntax_bits & RE_DOT_NEWLINE))
- || (*p == '\0' && (d->syntax.syntax_bits & RE_DOT_NOT_NULL))
- || (char *) p >= end)
+ || d->localeinfo.sbctowc[*p] != WEOF || (char *) p >= end)
{
/* If a input character does not match ANYCHAR, do it
like a single-byte character. */
@@ -3443,8 +3276,6 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
else
{
s = transit_state (d, s, &p, (unsigned char *) end);
- if (s >= 0 && p[-1] == eol)
- nlcount++;
mbp = p;
trans = d->trans;
}
@@ -3490,7 +3321,7 @@ dfaexec_noop (struct dfa *d, char const *begin, char *end,
return (char *) begin;
}
-/* Like dfaexec_main (D, BEGIN, END, ALLOW_NL, COUNT, D->multibyte),
+/* Like dfaexec_main (D, BEGIN, END, ALLOW_NL, COUNT, D->localeinfo.multibyte),
but faster and set *BACKREF if the DFA code does not support this
regexp usage. */
@@ -3548,7 +3379,7 @@ dfa_supported (struct dfa const *d)
case ENDWORD:
case LIMWORD:
case NOTLIMWORD:
- if (!d->multibyte)
+ if (!d->localeinfo.multibyte)
continue;
/* fallthrough */
@@ -3566,7 +3397,7 @@ dfaoptimize (struct dfa *d)
size_t i;
bool have_backref = false;
- if (!using_utf8)
+ if (!d->localeinfo.using_utf8)
return;
for (i = 0; i < d->tindex; ++i)
@@ -3596,7 +3427,7 @@ dfaoptimize (struct dfa *d)
}
free_mbdata (d);
- d->multibyte = false;
+ d->localeinfo.multibyte = false;
d->dfaexec = dfaexec_sb;
d->fast = true;
}
@@ -3611,7 +3442,7 @@ dfassbuild (struct dfa *d)
struct dfa *sup = dfaalloc ();
*sup = *d;
- sup->multibyte = false;
+ sup->localeinfo.multibyte = false;
sup->dfaexec = dfaexec_sb;
sup->multibyte_prop = NULL;
sup->mbcsets = NULL;
@@ -3644,7 +3475,7 @@ dfassbuild (struct dfa *d)
case BACKREF:
zeroset (ccl);
notset (ccl);
- sup->tokens[j++] = CSET + dfa_charclass_index (sup, ccl);
+ sup->tokens[j++] = CSET + charclass_index (sup, ccl);
sup->tokens[j++] = STAR;
if (d->tokens[i + 1] == QMARK || d->tokens[i + 1] == STAR
|| d->tokens[i + 1] == PLUS)
@@ -3655,13 +3486,14 @@ dfassbuild (struct dfa *d)
case ENDWORD:
case LIMWORD:
case NOTLIMWORD:
- if (d->multibyte)
+ if (d->localeinfo.multibyte)
{
/* These constraints aren't supported in a multibyte locale.
Ignore them in the superset DFA. */
sup->tokens[j++] = EMPTY;
break;
}
+ /* fallthrough */
default:
sup->tokens[j++] = d->tokens[i];
if ((0 <= d->tokens[i] && d->tokens[i] < NOTCHAR)
@@ -3672,7 +3504,7 @@ dfassbuild (struct dfa *d)
}
sup->tindex = j;
- if (have_nchar && (have_achar || d->multibyte))
+ if (have_nchar && (have_achar || d->localeinfo.multibyte))
d->superset = sup;
else
{
@@ -3714,7 +3546,7 @@ dfafree (struct dfa *d)
free (d->charclasses);
free (d->tokens);
- if (d->multibyte)
+ if (d->localeinfo.multibyte)
free_mbdata (d);
for (i = 0; i < d->sindex; ++i)
@@ -4238,20 +4070,51 @@ dfamustfree (struct dfamust *dm)
struct dfa *
dfaalloc (void)
{
- struct dfa *d = xcalloc (1, sizeof (struct dfa));
- d->multibyte = MB_CUR_MAX > 1;
- d->dfaexec = d->multibyte ? dfaexec_mb : dfaexec_sb;
- d->fast = !d->multibyte;
- d->lexstate.cur_mb_len = 1;
- return d;
+ return xmalloc (sizeof (struct dfa));
}
+/* Initialize DFA. */
void
-dfa_init (void)
+dfasyntax (struct dfa *dfa, struct localeinfo const *linfo,
+ reg_syntax_t bits, int dfaopts)
{
- check_utf8 ();
- check_unibyte_c ();
- init_mbrtowc_cache ();
+ int i;
+ memset (dfa, 0, offsetof (struct dfa, dfaexec));
+ dfa->dfaexec = linfo->multibyte ? dfaexec_mb : dfaexec_sb;
+ dfa->simple_locale = using_simple_locale (linfo->multibyte);
+ dfa->localeinfo = *linfo;
+
+ dfa->fast = !dfa->localeinfo.multibyte;
+
+ dfa->canychar = -1;
+ dfa->lex.cur_mb_len = 1;
+ dfa->syntax.syntax_bits_set = true;
+ dfa->syntax.case_fold = (dfaopts & DFA_CASE_FOLD) != 0;
+ dfa->syntax.anchor = (dfaopts & DFA_ANCHOR) != 0;
+ dfa->syntax.eolbyte = dfaopts & DFA_EOL_NUL ? '\0' : '\n';
+ dfa->syntax.syntax_bits = bits;
+
+ for (i = CHAR_MIN; i <= CHAR_MAX; ++i)
+ {
+ unsigned char uc = i;
+
+ dfa->syntax.sbit[uc] = char_context (dfa, uc);
+ switch (dfa->syntax.sbit[uc])
+ {
+ case CTX_LETTER:
+ setbit (uc, dfa->syntax.letters);
+ break;
+ case CTX_NEWLINE:
+ setbit (uc, dfa->syntax.newline);
+ break;
+ }
+
+ /* POSIX requires that the five bytes in "\n\r./" (including the
+ terminating NUL) cannot occur inside a multibyte character. */
+ dfa->syntax.never_trail[uc] = (dfa->localeinfo.using_utf8
+ ? (uc & 0xc0) != 0x80
+ : strchr ("\n\r./", uc) != NULL);
+ }
}
/* vim:set shiftwidth=2: */
diff --git a/dfa.h b/dfa.h
index 02f56f44..8608b108 100644
--- a/dfa.h
+++ b/dfa.h
@@ -26,7 +26,13 @@
#endif /* HAVE_STDBOOL_H */
#include <stddef.h>
-#define _GL_ATTRIBUTE_MALLOC
+#if 3 <= __GNUC__
+# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+#else
+# define _GL_ATTRIBUTE_MALLOC
+#endif
+
+struct localeinfo; /* See localeinfo.h. */
/* Element of a list of strings, at least one of which is known to
appear in any R.E. matching the DFA. */
@@ -48,17 +54,36 @@ struct dfa;
calling dfafree() on it. */
extern struct dfa *dfaalloc (void) _GL_ATTRIBUTE_MALLOC;
+/* DFA options that can be ORed together, for dfasyntax's 4th arg. */
+enum
+ {
+ /* ^ and $ match only the start and end of data, and do not match
+ end-of-line within data. This is always false for grep, but
+ possibly true for other apps. */
+ DFA_ANCHOR = 1 << 0,
+
+ /* Ignore case while matching. */
+ DFA_CASE_FOLD = 1 << 1,
+
+ /* '\0' in data is end-of-line, instead of the traditional '\n'. */
+ DFA_EOL_NUL = 1 << 2
+ };
+
+/* Initialize or reinitialize a DFA. This must be called before
+ any of the routines below. The arguments are:
+ 1. The DFA to operate on.
+ 2. Information about the current locale.
+ 3. Syntax bits described in regex.h.
+ 4. Additional DFA options described above. */
+extern void dfasyntax (struct dfa *, struct localeinfo const *,
+ reg_syntax_t, int);
+
/* Build and return the struct dfamust from the given struct dfa. */
extern struct dfamust *dfamust (struct dfa const *);
/* Free the storage held by the components of a struct dfamust. */
extern void dfamustfree (struct dfamust *);
-/* dfasyntax() takes four arguments; the first is the dfa to operate on, the
- second sets the syntax bits described earlier in this file, the third sets
- the case-folding flag, and the fourth specifies the line terminator. */
-extern void dfasyntax (struct dfa *, reg_syntax_t, bool, unsigned char);
-
/* Compile the given string of the given length into the given struct dfa.
Final argument is a flag specifying whether to build a searching or an
exact matcher. */
@@ -103,8 +128,3 @@ extern void dfawarn (const char *);
takes a single argument, a NUL-terminated string describing the error.
The user must supply a dfaerror. */
extern _Noreturn void dfaerror (const char *);
-
-extern bool dfa_using_utf8 (void) _GL_ATTRIBUTE_PURE;
-
-/* This must be called before calling any of the above dfa*() functions. */
-extern void dfa_init (void);
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 2aaad031..a5d8cc47 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,15 @@
+2016-11-04 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in: Fix a spelling error.
+ * wordlist: Update.
+
+2016-10-25 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in: Document that negative arguments are not allowed
+ for bitwise functions. Add a sidebar explaining it a bit and
+ also showing the difference with and without -M.
+ * gawk.1: Document that negative arguments are not allowed.
+
2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in: Remove references to MS-DOS and OS/2,
@@ -19,11 +31,18 @@
2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
+ * gawktexi.in (POSIX String Comparison): Update for new
+ spec where == and != use strcmp, rest use strcoll. Thanks to
+ Chet Ramey for pointing me at the new rules.
+
+2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
+
* 4.1.4: Release tar ball made.
2016-08-24 Arnold D. Robbins <arnold@skeeve.com>
* wordlist: Add more words.
+ * gawktexi.in: Fix more typos.
2016-08-23 Arnold D. Robbins <arnold@skeeve.com>
@@ -33,6 +52,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.
@@ -41,6 +66,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.
@@ -54,6 +85,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
@@ -62,6 +103,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
@@ -78,6 +128,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
@@ -88,6 +144,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
@@ -120,6 +181,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>
@@ -129,6 +192,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
@@ -161,17 +232,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.
@@ -185,6 +278,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>
@@ -197,6 +295,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.
@@ -228,11 +330,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.
@@ -258,6 +375,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.
@@ -282,15 +406,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.
@@ -312,6 +454,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>
@@ -319,10 +466,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>
@@ -336,6 +490,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.
@@ -392,6 +552,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>
@@ -400,6 +561,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>
@@ -429,7 +591,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>
@@ -451,12 +613,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.
@@ -488,6 +678,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.
@@ -501,6 +696,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.
@@ -514,6 +714,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>
@@ -555,10 +756,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.
@@ -654,6 +870,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.
@@ -687,6 +907,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.
@@ -701,6 +925,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
@@ -711,6 +947,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.
@@ -1007,7 +1248,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>
@@ -1081,6 +1322,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
diff --git a/doc/gawk.1 b/doc/gawk.1
index 2caa87ad..22b41f34 100644
--- a/doc/gawk.1
+++ b/doc/gawk.1
@@ -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
@@ -3102,6 +3181,11 @@ values to
.B uintmax_t
integers, doing the operation, and then converting the
result back to floating point.
+.PP
+.BR NOTE :
+Passing negative operands to any of these functions causes
+a fatal error.
+.PP
The functions are:
.TP "\w'\fBrshift(\fIval\fB, \fIcount\fB)\fR'u+2n"
\fBand(\fIv1\fB, \fIv2 \fR[, ...]\fB)\fR
@@ -3134,13 +3218,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 +4085,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 dade486a..fca83585 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
@@ -2623,30 +2628,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 compatibility. 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
@@ -2660,9 +2668,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::).
@@ -2683,6 +2688,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',
@@ -2931,6 +2941,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.
@@ -2970,6 +2983,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.
@@ -2996,7 +3012,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
@@ -3046,13 +3063,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.
@@ -3317,6 +3327,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.

@@ -3443,15 +3454,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
@@ -4028,7 +4042,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
================================
@@ -4102,10 +4116,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
@@ -4176,6 +4209,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.
@@ -4437,7 +4471,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'.
@@ -4489,11 +4523,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
@@ -5439,6 +5468,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 attempted. *Note Retrying
+Input:: for further information about this feature.
+
In the following examples, COMMAND stands for a string value that
represents a shell command.
@@ -5874,7 +5908,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
=================================
@@ -5953,7 +5987,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
@@ -5967,9 +6002,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 Directories on the Command Line
+4.11 Retrying Reads After Certain Input Errors
+==============================================
+
+This minor node describes a feature that is specific to 'gawk'.
+
+ When 'gawk' encounters an error while reading input, 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.12 Directories on the Command Line
====================================
According to the POSIX standard, files named on the 'awk' command line
@@ -5992,7 +6054,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
@@ -6064,7 +6126,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
@@ -6114,6 +6176,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.
@@ -7021,7 +7084,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
=========================================
@@ -7166,11 +7229,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
@@ -7184,14 +7259,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
@@ -7213,10 +7347,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:
@@ -8474,18 +8613,18 @@ Constant Regexps::, where this is discussed in more detail.

File: gawk.info, Node: POSIX String Comparison, Prev: Comparison Operators, Up: Typing and Comparison
-6.3.2.3 String Comparison with POSIX Rules
-..........................................
+6.3.2.3 String Comparison Based on Locale Collating Order
+.........................................................
-The POSIX standard says that string comparison is performed based on the
-locale's "collating order". This is the order in which characters sort,
-as defined by the locale (for more discussion, *note Locales::). This
-order is usually very different from the results obtained when doing
-straight character-by-character comparison.(1)
+The POSIX standard used to say that all string comparisons are performed
+based on the locale's "collating order". This is the order in which
+characters sort, as defined by the locale (for more discussion, *note
+Locales::). This order is usually very different from the results
+obtained when doing straight byte-by-byte comparison.(1)
Because this behavior differs considerably from existing practice,
-'gawk' only implements it when in POSIX mode (*note Options::). Here is
-an example to illustrate the difference, in an 'en_US.UTF-8' locale:
+'gawk' only implemented it when in POSIX mode (*note Options::). Here
+is an example to illustrate the difference, in an 'en_US.UTF-8' locale:
$ gawk 'BEGIN { printf("ABC < abc = %s\n",
> ("ABC" < "abc" ? "TRUE" : "FALSE")) }'
@@ -8494,11 +8633,28 @@ an example to illustrate the difference, in an 'en_US.UTF-8' locale:
> ("ABC" < "abc" ? "TRUE" : "FALSE")) }'
-| ABC < abc = FALSE
+ Fortunately, as of August 2016, comparison based on locale collating
+order is no longer required for the '==' and '!=' operators.(2)
+However, comparison based on locales is still required for '<', '<=',
+'>', and '>='. POSIX thus recommends as follows:
+
+ Since the '==' operator checks whether strings are identical, not
+ whether they collate equally, applications needing to check whether
+ strings collate equally can use:
+
+ a <= b && a >= b
+
+ As of version 4.2, 'gawk' continues to use locale collating order for
+'<', '<=', '>', and '>=' only in POSIX mode.
+
---------- Footnotes ----------
(1) Technically, string comparison is supposed to behave the same way
as if the strings were compared with the C 'strcoll()' function.
+ (2) See the Austin Group website
+(http://austingroupbugs.net/view.php?id=1070).
+

File: gawk.info, Node: Boolean Ops, Next: Conditional Exp, Prev: Typing and Comparison, Up: Truth Values and Conditions
@@ -10136,7 +10292,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.
@@ -10233,10 +10389,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
@@ -10300,10 +10452,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
@@ -10326,6 +10492,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
@@ -10374,6 +10545,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.
@@ -10472,6 +10647,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
@@ -11886,6 +12069,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,
@@ -13273,13 +13471,10 @@ are enclosed in square brackets ([ ]):
Return the bitwise XOR of the arguments. There must be at least
two.
- For all of these functions, first the double-precision floating-point
-value is converted to the widest C unsigned integer type, then the
-bitwise operation is performed. If the result cannot be represented
-exactly as a C 'double', leading nonzero bits are removed one by one
-until it can be represented exactly. The result is then converted back
-into a C 'double'. (If you don't understand this paragraph, don't worry
-about it.)
+ CAUTION: Beginning with 'gawk' 4.1 4.2, negative operands are not
+ allowed for any of these functions. A negative operand produces a
+ fatal error. See the sidebar "Beware The Smoke and Mirrors!" for
+ more information as to why.
Here is a user-defined function (*note User-defined::) that
illustrates the use of these functions:
@@ -13341,26 +13536,113 @@ decimal and octal values for the same numbers (*note
Nondecimal-numbers::), and then demonstrates the results of the
'compl()', 'lshift()', and 'rshift()' functions.
+ Beware The Smoke and Mirrors!
+
+ It other languages, bitwise operations are performed on integer
+values, not floating-point values. As a general statement, such
+operations work best when performed on unsigned integers.
+
+ 'gawk' attempts to treat the arguments to the bitwise functions as
+unsigned integers. For this reason, negative arguments produce a fatal
+error.
+
+ In normal operation, for all of these functions, first the
+double-precision floating-point value is converted to the widest C
+unsigned integer type, then the bitwise operation is performed. If the
+result cannot be represented exactly as a C 'double', leading nonzero
+bits are removed one by one until it can be represented exactly. The
+result is then converted back into a C 'double'.(2)
+
+ However, when using arbitrary precision arithmetic with the '-M'
+option (*note Arbitrary Precision Arithmetic::), the results may differ.
+This is particularly noticeable with the 'compl()' function:
+
+ $ gawk 'BEGIN { print compl(42) }'
+ -| 9007199254740949
+ $ gawk -M 'BEGIN { print compl(42) }'
+ -| -43
+
+ What's going on becomes clear when printing the results in
+hexadecimal:
+
+ $ gawk 'BEGIN { printf "%#x\n", compl(42) }'
+ -| 0x1fffffffffffd5
+ $ gawk -M 'BEGIN { printf "%#x\n", compl(42) }'
+ -| 0xffffffffffffffd5
+
+ When using the '-M' option, under the hood, 'gawk' uses GNU MP
+arbitrary precision integers which have at least 64 bits of precision.
+When not using '-M', 'gawk' stores integral values in regular
+double-precision floating point, which only maintain 53 bits of
+precision. Furthermore, the GNU MP library treats (or least seems to
+treat) the leading bit as a sign bit; thus the result with '-M' in this
+case is a negative number.
+
+ In short, using 'gawk' for any but the simplest kind of bitwise
+operations is probably a bad idea; caveat emptor!
+
---------- Footnotes ----------
(1) This example shows that zeros come in on the left side. For
'gawk', this is always true, but in some languages, it's possible to
have the left side fill with ones.
+ (2) If you don't understand this paragraph, the upshot is that 'gawk'
+can only store a particular range of integer values; numbers outside
+that range are reduced to fit within the range.
+

File: gawk.info, Node: Type Functions, Next: I18N Functions, Prev: Bitwise Functions, Up: Built-in
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
@@ -13374,6 +13656,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
@@ -19689,9 +19978,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
@@ -19979,8 +20274,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/
@@ -20039,8 +20333,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
@@ -20081,8 +20403,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
@@ -21777,6 +22098,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 discussing. 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
@@ -21805,6 +22182,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
@@ -22538,6 +22918,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
@@ -22900,6 +23336,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.
@@ -22955,6 +23392,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
@@ -23312,7 +23751,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:
@@ -23339,11 +23778,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:
@@ -23796,6 +24241,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.
@@ -24160,7 +24608,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
--------------------------
@@ -24644,9 +25092,78 @@ array:
environment variable.)

-File: gawk.info, Node: Extension API Variables, Next: Extension API Boilerplate, Prev: Array Manipulation, Up: Extension API Description
+File: gawk.info, Node: Redirection API, Next: Extension API Variables, Prev: Array Manipulation, Up: Extension API Description
+
+16.4.12 Accessing and Manipulating Redirections
+-----------------------------------------------
+
+The following function allows extensions to access and manipulate
+redirections.
+
+'awk_bool_t get_file(const char *name,'
+' size_t name_len,'
+' const char *filetype,'
+' int fd,'
+' const awk_input_buf_t **ibufp,'
+' const awk_output_buf_t **obufp);'
+ Look up a file in 'gawk''s internal redirection table. If 'name'
+ is 'NULL' or 'name_len' is zero, return data for the currently open
+ input file corresponding to 'FILENAME'. (This does not access the
+ 'filetype' argument, so that may be undefined). If the file is not
+ already open, attempt to open it. The 'filetype' argument must be
+ zero-terminated and should be one of:
+
+ '">"'
+ A file opened for output.
+
+ '">>"'
+ A file opened for append.
+
+ '"<"'
+ A file opened for input.
+
+ '"|>"'
+ A pipe opened for output.
+
+ '"|<"'
+ A pipe opened for input.
+
+ '"|&"'
+ A two-way coprocess.
+
+ On error, return a 'false' value. Otherwise, return 'true', and
+ return additional information about the redirection in the 'ibufp'
+ and 'obufp' pointers. For input redirections, the '*ibufp' value
+ should be non-'NULL', and '*obufp' should be 'NULL'. For output
+ redirections, the '*obufp' value should be non-'NULL', and '*ibufp'
+ should be 'NULL'. For two-way coprocesses, both values should be
+ non-'NULL'.
+
+ In the usual case, the extension is interested in '(*ibufp)->fd'
+ and/or 'fileno((*obufp)->fp)'. If the file is not already open,
+ and the 'fd' argument is non-negative, 'gawk' will use that file
+ descriptor instead of opening the file in the usual way. If 'fd'
+ is non-negative, but the file exists already, 'gawk' ignores 'fd'
+ and returns the existing file. It is the caller's responsibility
+ to notice that neither the 'fd' in the returned 'awk_input_buf_t'
+ nor the 'fd' in the returned 'awk_output_buf_t' matches the
+ requested value.
-16.4.12 API Variables
+ Note that supplying a file descriptor is currently _not_ supported
+ for pipes. However, supplying a file descriptor should work for
+ input, output, append, and two-way (coprocess) sockets. If
+ 'filetype' is two-way, 'gawk' assumes that it is a socket! Note
+ that in the two-way case, the input and output file descriptors may
+ differ. To check for success, you must check whether either
+ matches.
+
+ It is anticipated that this API function will be used to implement
+I/O multiplexing and a socket library.
+
+
+File: gawk.info, Node: Extension API Variables, Next: Extension API Boilerplate, Prev: Redirection API, Up: Extension API Description
+
+16.4.13 API Variables
---------------------
The API provides two sets of variables. The first provides information
@@ -24663,7 +25180,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
@@ -24715,7 +25232,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
@@ -24750,7 +25267,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
@@ -26078,15 +26595,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
@@ -26164,7 +26683,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
@@ -26499,6 +27018,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
@@ -26548,6 +27070,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
@@ -26558,16 +27083,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:
@@ -26601,6 +27126,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
@@ -26992,6 +27522,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
@@ -27106,7 +27664,7 @@ ranges, such that outside the '"C"' and '"POSIX"' locales, the meaning
of range expressions was _undefined_.(3)
By using this lovely technical term, the standard gives license to
-implementors to implement ranges in whatever way they choose. The
+implementers to implement ranges in whatever way they choose. The
'gawk' maintainer chose to apply the pre-POSIX meaning both with the
default regexp matching and when '--traditional' or '--posix' are used.
In all cases 'gawk' remains POSIX-compliant.
@@ -27510,7 +28068,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
@@ -27552,17 +28112,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.
@@ -27593,11 +28158,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
--------------------------------------------
@@ -27652,9 +28218,42 @@ will be asked for your password, and you will have to have been set up
previously as a user who is allowed to run the 'sudo' command.

-File: gawk.info, Node: Additional Configuration Options, Next: Configuration Philosophy, Prev: Quick Installation, Up: Unix Installation
+File: gawk.info, Node: Shell Startup Files, Next: Additional Configuration Options, Prev: Quick Installation, Up: Unix Installation
+
+B.2.2 Shell Startup Files
+-------------------------
+
+The distribution contains shell startup files 'gawk.sh' and 'gawk.csh'
+containing functions to aid in manipulating the 'AWKPATH' and
+'AWKLIBPATH' environment variables. On a Fedora system, these files
+should be installed in '/etc/profile.d'; on other platforms, the
+appropriate location may be different.
+
+'gawkpath_default'
+ Reset the 'AWKPATH' environment variable to its default value.
-B.2.2 Additional Configuration Options
+'gawkpath_prepend'
+ Add the argument to the front of the 'AWKPATH' environment
+ variable.
+
+'gawkpath_append'
+ Add the argument to the end of the 'AWKPATH' environment variable.
+
+'gawklibpath_default'
+ Reset the 'AWKLIBPATH' environment variable to its default value.
+
+'gawklibpath_prepend'
+ Add the argument to the front of the 'AWKLIBPATH' environment
+ variable.
+
+'gawklibpath_append'
+ Add the argument to the end of the 'AWKLIBPATH' environment
+ variable.
+
+
+File: gawk.info, Node: Additional Configuration Options, Next: Configuration Philosophy, Prev: Shell Startup Files, Up: Unix Installation
+
+B.2.3 Additional Configuration Options
--------------------------------------
There are several additional options you may use on the 'configure'
@@ -27698,7 +28297,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
@@ -31585,20 +32184,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)
@@ -31608,7 +32208,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)
@@ -31618,31 +32218,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)
@@ -31715,16 +32316,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.
@@ -31941,7 +32542,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)
@@ -32012,16 +32613,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.
@@ -32091,7 +32692,7 @@ Index
* BINMODE variable: User-modified. (line 15)
* BINMODE variable <1>: PC Using. (line 16)
* bit-manipulation functions: Bitwise Functions. (line 6)
-* bits2str() user-defined function: Bitwise Functions. (line 72)
+* bits2str() user-defined function: Bitwise Functions. (line 69)
* bitwise AND: Bitwise Functions. (line 40)
* bitwise complement: Bitwise Functions. (line 44)
* bitwise OR: Bitwise Functions. (line 50)
@@ -32140,7 +32741,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.
@@ -32330,9 +32931,9 @@ Index
(line 31)
* converting, dates to timestamps: Time Functions. (line 76)
* converting, numbers to strings: Strings And Numbers. (line 6)
-* converting, numbers to strings <1>: Bitwise Functions. (line 111)
+* converting, numbers to strings <1>: Bitwise Functions. (line 108)
* converting, strings to numbers: Strings And Numbers. (line 6)
-* converting, strings to numbers <1>: Bitwise Functions. (line 111)
+* converting, strings to numbers <1>: Bitwise Functions. (line 108)
* CONVFMT variable: Strings And Numbers. (line 29)
* CONVFMT variable <1>: User-modified. (line 30)
* CONVFMT variable, and array subscripts: Numeric Array Subscripts.
@@ -32347,7 +32948,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)
@@ -32377,12 +32978,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)
@@ -32577,12 +33178,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)
@@ -32605,7 +33206,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)
@@ -32613,9 +33214,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.
@@ -32623,7 +33226,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.
@@ -32659,12 +33262,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)
@@ -32719,14 +33322,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)
@@ -32767,7 +33370,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)
@@ -32786,7 +33389,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)
@@ -32842,7 +33445,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)
@@ -32870,7 +33472,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)
@@ -32938,8 +33540,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.
@@ -32991,7 +33593,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)
@@ -33042,8 +33644,8 @@ Index
* G., Daniel Richard: Acknowledgments. (line 60)
* G., Daniel Richard <1>: Maintainers. (line 14)
* 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)
@@ -33064,10 +33666,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)
@@ -33079,7 +33681,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)
@@ -33107,9 +33709,9 @@ Index
* gawk, newlines in: Statements/Lines. (line 12)
* gawk, octal numbers and: Nondecimal-numbers. (line 41)
* 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.
@@ -33119,21 +33721,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)
@@ -33187,7 +33795,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)
@@ -33215,7 +33823,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)
@@ -33237,7 +33845,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)
@@ -33319,7 +33927,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.
@@ -33375,7 +33985,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.
@@ -33448,7 +34058,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)
@@ -33469,9 +34079,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)
@@ -33508,12 +34118,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)
@@ -33525,8 +34135,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)
@@ -33546,10 +34156,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)
@@ -33576,7 +34184,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)
@@ -33585,8 +34193,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)
@@ -33599,7 +34207,7 @@ Index
* null strings, converting numbers to strings: Strings And Numbers.
(line 21)
* null strings, matching: String Functions. (line 537)
-* number as string of bits: Bitwise Functions. (line 111)
+* number as string of bits: Bitwise Functions. (line 108)
* number of array elements: String Functions. (line 200)
* number sign (#), #! (executable scripts): Executable Scripts.
(line 6)
@@ -33610,7 +34218,7 @@ Index
* numbers, Cliff random: Cliff Random Function.
(line 6)
* numbers, converting: Strings And Numbers. (line 6)
-* numbers, converting <1>: Bitwise Functions. (line 111)
+* numbers, converting <1>: Bitwise Functions. (line 108)
* numbers, converting, to strings: User-modified. (line 30)
* numbers, converting, to strings <1>: User-modified. (line 104)
* numbers, hexadecimal: Nondecimal-numbers. (line 6)
@@ -33706,7 +34314,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)
@@ -33750,14 +34358,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.
@@ -33775,7 +34383,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)
@@ -33796,7 +34404,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.
@@ -33808,9 +34416,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)
@@ -33825,12 +34431,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)
@@ -33877,14 +34483,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.
@@ -33892,8 +34498,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)
@@ -33929,7 +34535,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)
@@ -33938,12 +34544,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)
@@ -34030,6 +34636,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)
@@ -34053,7 +34660,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)
@@ -34079,11 +34686,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)
@@ -34094,14 +34701,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)
@@ -34120,7 +34727,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 9)
* semicolon (;), separating statements in actions: Statements/Lines.
(line 90)
@@ -34132,7 +34739,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)
@@ -34184,14 +34790,15 @@ 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, Beware The Smoke and Mirrors!: Bitwise Functions. (line 126)
* 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.
@@ -34213,19 +34820,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)
@@ -34275,10 +34882,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)
@@ -34315,7 +34922,7 @@ Index
* string-translation functions: I18N Functions. (line 6)
* strings splitting, example: String Functions. (line 334)
* strings, converting: Strings And Numbers. (line 6)
-* strings, converting <1>: Bitwise Functions. (line 111)
+* strings, converting <1>: Bitwise Functions. (line 108)
* strings, converting letter case: String Functions. (line 523)
* strings, converting, numbers to: User-modified. (line 30)
* strings, converting, numbers to <1>: User-modified. (line 104)
@@ -34350,9 +34957,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)
@@ -34366,7 +34973,7 @@ Index
* tee.awk program: Tee Program. (line 26)
* temporary breakpoint: Breakpoint Control. (line 90)
* terminating records: awk split records. (line 124)
-* testbits.awk program: Bitwise Functions. (line 72)
+* testbits.awk program: Bitwise Functions. (line 69)
* testext extension: Extension Sample API Tests.
(line 6)
* Texinfo: Conventions. (line 6)
@@ -34422,7 +35029,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)
@@ -34456,6 +35063,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.
@@ -34478,7 +35087,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.
@@ -34497,10 +35106,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)
@@ -34531,10 +35141,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)
@@ -34571,7 +35181,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)
@@ -34601,563 +35211,571 @@ Index

Tag Table:
Node: Top1200
-Node: Foreword342162
-Node: Foreword446604
-Node: Preface48136
-Ref: Preface-Footnote-150995
-Ref: Preface-Footnote-251102
-Ref: Preface-Footnote-351336
-Node: History51478
-Node: Names53830
-Ref: Names-Footnote-154924
-Node: This Manual55071
-Ref: This Manual-Footnote-161556
-Node: Conventions61656
-Node: Manual History64010
-Ref: Manual History-Footnote-167005
-Ref: Manual History-Footnote-267046
-Node: How To Contribute67120
-Node: Acknowledgments68249
-Node: Getting Started73135
-Node: Running gawk75574
-Node: One-shot76764
-Node: Read Terminal78027
-Node: Long80020
-Node: Executable Scripts81533
-Ref: Executable Scripts-Footnote-184328
-Node: Comments84431
-Node: Quoting86915
-Node: DOS Quoting92432
-Node: Sample Data Files93107
-Node: Very Simple95702
-Node: Two Rules100604
-Node: More Complex102489
-Node: Statements/Lines105355
-Ref: Statements/Lines-Footnote-1109814
-Node: Other Features110079
-Node: When111015
-Ref: When-Footnote-1112769
-Node: Intro Summary112834
-Node: Invoking Gawk113718
-Node: Command Line115232
-Node: Options116030
-Ref: Options-Footnote-1131937
-Ref: Options-Footnote-2132167
-Node: Other Arguments132192
-Node: Naming Standard Input135139
-Node: Environment Variables136232
-Node: AWKPATH Variable136790
-Ref: AWKPATH Variable-Footnote-1140091
-Ref: AWKPATH Variable-Footnote-2140125
-Node: AWKLIBPATH Variable140386
-Node: Other Environment Variables141530
-Node: Exit Status145478
-Node: Include Files146155
-Node: Loading Shared Libraries149750
-Node: Obsolete151178
-Node: Undocumented151870
-Node: Invoking Summary152167
-Node: Regexp153827
-Node: Regexp Usage155281
-Node: Escape Sequences157318
-Node: Regexp Operators163332
-Ref: Regexp Operators-Footnote-1170748
-Ref: Regexp Operators-Footnote-2170895
-Node: Bracket Expressions170993
-Ref: table-char-classes173469
-Node: Leftmost Longest176606
-Node: Computed Regexps177909
-Node: GNU Regexp Operators181336
-Node: Case-sensitivity185015
-Ref: Case-sensitivity-Footnote-1187902
-Ref: Case-sensitivity-Footnote-2188137
-Node: Regexp Summary188245
-Node: Reading Files189711
-Node: Records191805
-Node: awk split records192538
-Node: gawk split records197469
-Ref: gawk split records-Footnote-1202009
-Node: Fields202046
-Ref: Fields-Footnote-1204826
-Node: Nonconstant Fields204912
-Ref: Nonconstant Fields-Footnote-1207148
-Node: Changing Fields207352
-Node: Field Separators213280
-Node: Default Field Splitting215978
-Node: Regexp Field Splitting217096
-Node: Single Character Fields220449
-Node: Command Line Field Separator221509
-Node: Full Line Fields224727
-Ref: Full Line Fields-Footnote-1226249
-Ref: Full Line Fields-Footnote-2226295
-Node: Field Splitting Summary226396
-Node: Constant Size228470
-Node: Splitting By Content233048
-Ref: Splitting By Content-Footnote-1237019
-Node: Multiple Line237182
-Ref: Multiple Line-Footnote-1243064
-Node: Getline243243
-Node: Plain Getline245447
-Node: Getline/Variable248086
-Node: Getline/File249235
-Node: Getline/Variable/File250621
-Ref: Getline/Variable/File-Footnote-1252224
-Node: Getline/Pipe252312
-Node: Getline/Variable/Pipe255017
-Node: Getline/Coprocess256150
-Node: Getline/Variable/Coprocess257415
-Node: Getline Notes258155
-Node: Getline Summary260950
-Ref: table-getline-variants261372
-Node: Read Timeout262120
-Ref: Read Timeout-Footnote-1265961
-Node: Command-line directories266019
-Node: Input Summary266923
-Node: Input Exercises270095
-Node: Printing270823
-Node: Print272599
-Node: Print Examples274056
-Node: Output Separators276836
-Node: OFMT278853
-Node: Printf280209
-Node: Basic Printf280994
-Node: Control Letters282568
-Node: Format Modifiers286556
-Node: Printf Examples292571
-Node: Redirection295057
-Node: Special FD301898
-Ref: Special FD-Footnote-1305066
-Node: Special Files305140
-Node: Other Inherited Files305757
-Node: Special Network306758
-Node: Special Caveats307618
-Node: Close Files And Pipes308567
-Ref: Close Files And Pipes-Footnote-1315760
-Ref: Close Files And Pipes-Footnote-2315908
-Node: Output Summary316059
-Node: Output Exercises317057
-Node: Expressions317736
-Node: Values318924
-Node: Constants319602
-Node: Scalar Constants320293
-Ref: Scalar Constants-Footnote-1321157
-Node: Nondecimal-numbers321407
-Node: Regexp Constants324420
-Node: Using Constant Regexps324946
-Node: Variables328109
-Node: Using Variables328766
-Node: Assignment Options330676
-Node: Conversion332549
-Node: Strings And Numbers333073
-Ref: Strings And Numbers-Footnote-1336136
-Node: Locale influences conversions336245
-Ref: table-locale-affects339003
-Node: All Operators339621
-Node: Arithmetic Ops340250
-Node: Concatenation342756
-Ref: Concatenation-Footnote-1345603
-Node: Assignment Ops345710
-Ref: table-assign-ops350701
-Node: Increment Ops352014
-Node: Truth Values and Conditions355474
-Node: Truth Values356548
-Node: Typing and Comparison357596
-Node: Variable Typing358416
-Node: Comparison Operators362040
-Ref: table-relational-ops362459
-Node: POSIX String Comparison365954
-Ref: POSIX String Comparison-Footnote-1367028
-Node: Boolean Ops367167
-Ref: Boolean Ops-Footnote-1371649
-Node: Conditional Exp371741
-Node: Function Calls373477
-Node: Precedence377354
-Node: Locales381013
-Node: Expressions Summary382645
-Node: Patterns and Actions385218
-Node: Pattern Overview386338
-Node: Regexp Patterns388015
-Node: Expression Patterns388557
-Node: Ranges392338
-Node: BEGIN/END395446
-Node: Using BEGIN/END396207
-Ref: Using BEGIN/END-Footnote-1398943
-Node: I/O And BEGIN/END399049
-Node: BEGINFILE/ENDFILE401363
-Node: Empty404270
-Node: Using Shell Variables404587
-Node: Action Overview406861
-Node: Statements409186
-Node: If Statement411034
-Node: While Statement412529
-Node: Do Statement414557
-Node: For Statement415705
-Node: Switch Statement418863
-Node: Break Statement421249
-Node: Continue Statement423341
-Node: Next Statement425168
-Node: Nextfile Statement427551
-Node: Exit Statement430203
-Node: Built-in Variables432606
-Node: User-modified433739
-Ref: User-modified-Footnote-1441364
-Node: Auto-set441426
-Ref: Auto-set-Footnote-1454782
-Ref: Auto-set-Footnote-2454988
-Node: ARGC and ARGV455044
-Node: Pattern Action Summary459257
-Node: Arrays461687
-Node: Array Basics463016
-Node: Array Intro463860
-Ref: figure-array-elements465835
-Ref: Array Intro-Footnote-1468539
-Node: Reference to Elements468667
-Node: Assigning Elements471131
-Node: Array Example471622
-Node: Scanning an Array473381
-Node: Controlling Scanning476403
-Ref: Controlling Scanning-Footnote-1481802
-Node: Numeric Array Subscripts482118
-Node: Uninitialized Subscripts484302
-Node: Delete485921
-Ref: Delete-Footnote-1488673
-Node: Multidimensional488730
-Node: Multiscanning491825
-Node: Arrays of Arrays493416
-Node: Arrays Summary498183
-Node: Functions500276
-Node: Built-in501314
-Node: Calling Built-in502395
-Node: Numeric Functions504391
-Ref: Numeric Functions-Footnote-1508419
-Ref: Numeric Functions-Footnote-2508776
-Ref: Numeric Functions-Footnote-3508824
-Node: String Functions509096
-Ref: String Functions-Footnote-1532600
-Ref: String Functions-Footnote-2532728
-Ref: String Functions-Footnote-3532976
-Node: Gory Details533063
-Ref: table-sub-escapes534854
-Ref: table-sub-proposed536373
-Ref: table-posix-sub537736
-Ref: table-gensub-escapes539277
-Ref: Gory Details-Footnote-1540100
-Node: I/O Functions540254
-Ref: table-system-return-values546836
-Ref: I/O Functions-Footnote-1548816
-Ref: I/O Functions-Footnote-2548964
-Node: Time Functions549084
-Ref: Time Functions-Footnote-1559606
-Ref: Time Functions-Footnote-2559674
-Ref: Time Functions-Footnote-3559832
-Ref: Time Functions-Footnote-4559943
-Ref: Time Functions-Footnote-5560055
-Ref: Time Functions-Footnote-6560282
-Node: Bitwise Functions560548
-Ref: table-bitwise-ops561142
-Ref: Bitwise Functions-Footnote-1565480
-Node: Type Functions565653
-Node: I18N Functions566809
-Node: User-defined568460
-Node: Definition Syntax569265
-Ref: Definition Syntax-Footnote-1574952
-Node: Function Example575023
-Ref: Function Example-Footnote-1577945
-Node: Function Caveats577967
-Node: Calling A Function578485
-Node: Variable Scope579443
-Node: Pass By Value/Reference582437
-Node: Return Statement585936
-Node: Dynamic Typing588915
-Node: Indirect Calls589845
-Ref: Indirect Calls-Footnote-1600096
-Node: Functions Summary600224
-Node: Library Functions602929
-Ref: Library Functions-Footnote-1606536
-Ref: Library Functions-Footnote-2606679
-Node: Library Names606850
-Ref: Library Names-Footnote-1610310
-Ref: Library Names-Footnote-2610533
-Node: General Functions610619
-Node: Strtonum Function611722
-Node: Assert Function614744
-Node: Round Function618070
-Node: Cliff Random Function619611
-Node: Ordinal Functions620627
-Ref: Ordinal Functions-Footnote-1623690
-Ref: Ordinal Functions-Footnote-2623942
-Node: Join Function624152
-Ref: Join Function-Footnote-1625922
-Node: Getlocaltime Function626122
-Node: Readfile Function629864
-Node: Shell Quoting631836
-Node: Data File Management633237
-Node: Filetrans Function633869
-Node: Rewind Function637965
-Node: File Checking639871
-Ref: File Checking-Footnote-1641205
-Node: Empty Files641406
-Node: Ignoring Assigns643385
-Node: Getopt Function644935
-Ref: Getopt Function-Footnote-1656404
-Node: Passwd Functions656604
-Ref: Passwd Functions-Footnote-1665443
-Node: Group Functions665531
-Ref: Group Functions-Footnote-1673429
-Node: Walking Arrays673636
-Node: Library Functions Summary676644
-Node: Library Exercises678050
-Node: Sample Programs678515
-Node: Running Examples679285
-Node: Clones680013
-Node: Cut Program681237
-Node: Egrep Program691166
-Ref: Egrep Program-Footnote-1698678
-Node: Id Program698788
-Node: Split Program702468
-Ref: Split Program-Footnote-1705927
-Node: Tee Program706056
-Node: Uniq Program708846
-Node: Wc Program716272
-Ref: Wc Program-Footnote-1720527
-Node: Miscellaneous Programs720621
-Node: Dupword Program721834
-Node: Alarm Program723864
-Node: Translate Program728719
-Ref: Translate Program-Footnote-1733284
-Node: Labels Program733554
-Ref: Labels Program-Footnote-1736905
-Node: Word Sorting736989
-Node: History Sorting741061
-Node: Extract Program742896
-Node: Simple Sed750425
-Node: Igawk Program753499
-Ref: Igawk Program-Footnote-1767830
-Ref: Igawk Program-Footnote-2768032
-Ref: Igawk Program-Footnote-3768154
-Node: Anagram Program768269
-Node: Signature Program771331
-Node: Programs Summary772578
-Node: Programs Exercises773792
-Ref: Programs Exercises-Footnote-1777921
-Node: Advanced Features778012
-Node: Nondecimal Data780002
-Node: Array Sorting781593
-Node: Controlling Array Traversal782293
-Ref: Controlling Array Traversal-Footnote-1790660
-Node: Array Sorting Functions790778
-Ref: Array Sorting Functions-Footnote-1795869
-Node: Two-way I/O796065
-Ref: Two-way I/O-Footnote-1802359
-Ref: Two-way I/O-Footnote-2802546
-Node: TCP/IP Networking802628
-Node: Profiling805746
-Node: Advanced Features Summary813285
-Node: Internationalization815221
-Node: I18N and L10N816701
-Node: Explaining gettext817388
-Ref: Explaining gettext-Footnote-1823280
-Ref: Explaining gettext-Footnote-2823465
-Node: Programmer i18n823630
-Ref: Programmer i18n-Footnote-1828485
-Node: Translator i18n828534
-Node: String Extraction829328
-Ref: String Extraction-Footnote-1830460
-Node: Printf Ordering830546
-Ref: Printf Ordering-Footnote-1833332
-Node: I18N Portability833396
-Ref: I18N Portability-Footnote-1835852
-Node: I18N Example835915
-Ref: I18N Example-Footnote-1838721
-Node: Gawk I18N838794
-Node: I18N Summary839439
-Node: Debugger840780
-Node: Debugging841802
-Node: Debugging Concepts842243
-Node: Debugging Terms844052
-Node: Awk Debugging846627
-Node: Sample Debugging Session847533
-Node: Debugger Invocation848067
-Node: Finding The Bug849453
-Node: List of Debugger Commands855931
-Node: Breakpoint Control857264
-Node: Debugger Execution Control860958
-Node: Viewing And Changing Data864320
-Node: Execution Stack867694
-Node: Debugger Info869331
-Node: Miscellaneous Debugger Commands873402
-Node: Readline Support878490
-Node: Limitations879386
-Node: Debugging Summary881495
-Node: Arbitrary Precision Arithmetic882668
-Node: Computer Arithmetic884084
-Ref: table-numeric-ranges887675
-Ref: Computer Arithmetic-Footnote-1888397
-Node: Math Definitions888454
-Ref: table-ieee-formats891768
-Ref: Math Definitions-Footnote-1892371
-Node: MPFR features892476
-Node: FP Math Caution894193
-Ref: FP Math Caution-Footnote-1895265
-Node: Inexactness of computations895634
-Node: Inexact representation896594
-Node: Comparing FP Values897954
-Node: Errors accumulate899036
-Node: Getting Accuracy900469
-Node: Try To Round903179
-Node: Setting precision904078
-Ref: table-predefined-precision-strings904775
-Node: Setting the rounding mode906605
-Ref: table-gawk-rounding-modes906979
-Ref: Setting the rounding mode-Footnote-1910387
-Node: Arbitrary Precision Integers910566
-Ref: Arbitrary Precision Integers-Footnote-1913550
-Node: POSIX Floating Point Problems913699
-Ref: POSIX Floating Point Problems-Footnote-1917581
-Node: Floating point summary917619
-Node: Dynamic Extensions919809
-Node: Extension Intro921362
-Node: Plugin License922628
-Node: Extension Mechanism Outline923425
-Ref: figure-load-extension923864
-Ref: figure-register-new-function925429
-Ref: figure-call-new-function926521
-Node: Extension API Description928583
-Node: Extension API Functions Introduction930031
-Node: General Data Types934843
-Ref: General Data Types-Footnote-1940798
-Node: Memory Allocation Functions941097
-Ref: Memory Allocation Functions-Footnote-1943942
-Node: Constructor Functions944041
-Node: Registration Functions945786
-Node: Extension Functions946471
-Node: Exit Callback Functions948770
-Node: Extension Version String950020
-Node: Input Parsers950683
-Node: Output Wrappers960565
-Node: Two-way processors965077
-Node: Printing Messages967342
-Ref: Printing Messages-Footnote-1968416
-Node: Updating ERRNO968569
-Node: Requesting Values969308
-Ref: table-value-types-returned970045
-Node: Accessing Parameters970928
-Node: Symbol Table Access972163
-Node: Symbol table by name972675
-Node: Symbol table by cookie974696
-Ref: Symbol table by cookie-Footnote-1978848
-Node: Cached values978912
-Ref: Cached values-Footnote-1982419
-Node: Array Manipulation982510
-Ref: Array Manipulation-Footnote-1983609
-Node: Array Data Types983646
-Ref: Array Data Types-Footnote-1986304
-Node: Array Functions986396
-Node: Flattening Arrays990254
-Node: Creating Arrays997162
-Node: Extension API Variables1001931
-Node: Extension Versioning1002567
-Ref: gawk-api-version1003004
-Node: Extension API Informational Variables1004760
-Node: Extension API Boilerplate1005824
-Node: Finding Extensions1009638
-Node: Extension Example1010197
-Node: Internal File Description1010995
-Node: Internal File Ops1015075
-Ref: Internal File Ops-Footnote-11026837
-Node: Using Internal File Ops1026977
-Ref: Using Internal File Ops-Footnote-11029360
-Node: Extension Samples1029634
-Node: Extension Sample File Functions1031163
-Node: Extension Sample Fnmatch1038812
-Node: Extension Sample Fork1040299
-Node: Extension Sample Inplace1041517
-Node: Extension Sample Ord1044727
-Node: Extension Sample Readdir1045563
-Ref: table-readdir-file-types1046452
-Node: Extension Sample Revout1047257
-Node: Extension Sample Rev2way1047846
-Node: Extension Sample Read write array1048586
-Node: Extension Sample Readfile1050528
-Node: Extension Sample Time1051623
-Node: Extension Sample API Tests1052971
-Node: gawkextlib1053463
-Node: Extension summary1055887
-Node: Extension Exercises1059579
-Node: Language History1061077
-Node: V7/SVR3.11062733
-Node: SVR41064885
-Node: POSIX1066319
-Node: BTL1067698
-Node: POSIX/GNU1068427
-Node: Feature History1073948
-Node: Common Extensions1087277
-Node: Ranges and Locales1088560
-Ref: Ranges and Locales-Footnote-11093176
-Ref: Ranges and Locales-Footnote-21093203
-Ref: Ranges and Locales-Footnote-31093438
-Node: Contributors1093659
-Node: History summary1099219
-Node: Installation1100599
-Node: Gawk Distribution1101543
-Node: Getting1102027
-Node: Extracting1102988
-Node: Distribution contents1104626
-Node: Unix Installation1110368
-Node: Quick Installation1110984
-Node: Additional Configuration Options1113411
-Node: Configuration Philosophy1115215
-Node: Non-Unix Installation1117584
-Node: PC Installation1118044
-Node: PC Binary Installation1118882
-Node: PC Compiling1119317
-Node: PC Using1120434
-Node: Cygwin1123479
-Node: MSYS1124249
-Node: VMS Installation1124750
-Node: VMS Compilation1125541
-Ref: VMS Compilation-Footnote-11126770
-Node: VMS Dynamic Extensions1126828
-Node: VMS Installation Details1128513
-Node: VMS Running1130766
-Node: VMS GNV1135045
-Node: VMS Old Gawk1135780
-Node: Bugs1136251
-Node: Bug address1136914
-Node: Usenet1139311
-Node: Maintainers1140086
-Node: Other Versions1141462
-Node: Installation summary1148046
-Node: Notes1149081
-Node: Compatibility Mode1149946
-Node: Additions1150728
-Node: Accessing The Source1151653
-Node: Adding Code1153088
-Node: New Ports1159307
-Node: Derived Files1163795
-Ref: Derived Files-Footnote-11169280
-Ref: Derived Files-Footnote-21169315
-Ref: Derived Files-Footnote-31169913
-Node: Future Extensions1170027
-Node: Implementation Limitations1170685
-Node: Extension Design1171868
-Node: Old Extension Problems1173022
-Ref: Old Extension Problems-Footnote-11174540
-Node: Extension New Mechanism Goals1174597
-Ref: Extension New Mechanism Goals-Footnote-11177961
-Node: Extension Other Design Decisions1178150
-Node: Extension Future Growth1180263
-Node: Old Extension Mechanism1181099
-Node: Notes summary1182862
-Node: Basic Concepts1184044
-Node: Basic High Level1184725
-Ref: figure-general-flow1185007
-Ref: figure-process-flow1185692
-Ref: Basic High Level-Footnote-11188993
-Node: Basic Data Typing1189178
-Node: Glossary1192506
-Node: Copying1224453
-Node: GNU Free Documentation License1261992
-Node: Index1287110
+Node: Foreword342530
+Node: Foreword446972
+Node: Preface48504
+Ref: Preface-Footnote-151363
+Ref: Preface-Footnote-251470
+Ref: Preface-Footnote-351704
+Node: History51846
+Node: Names54198
+Ref: Names-Footnote-155292
+Node: This Manual55439
+Ref: This Manual-Footnote-161924
+Node: Conventions62024
+Node: Manual History64378
+Ref: Manual History-Footnote-167373
+Ref: Manual History-Footnote-267414
+Node: How To Contribute67488
+Node: Acknowledgments68617
+Node: Getting Started73503
+Node: Running gawk75942
+Node: One-shot77132
+Node: Read Terminal78395
+Node: Long80388
+Node: Executable Scripts81901
+Ref: Executable Scripts-Footnote-184696
+Node: Comments84799
+Node: Quoting87283
+Node: DOS Quoting92800
+Node: Sample Data Files93475
+Node: Very Simple96070
+Node: Two Rules100972
+Node: More Complex102857
+Node: Statements/Lines105723
+Ref: Statements/Lines-Footnote-1110182
+Node: Other Features110447
+Node: When111383
+Ref: When-Footnote-1113137
+Node: Intro Summary113202
+Node: Invoking Gawk114086
+Node: Command Line115600
+Node: Options116398
+Ref: Options-Footnote-1132497
+Ref: Options-Footnote-2132727
+Node: Other Arguments132752
+Node: Naming Standard Input135699
+Node: Environment Variables136792
+Node: AWKPATH Variable137350
+Ref: AWKPATH Variable-Footnote-1140761
+Ref: AWKPATH Variable-Footnote-2140795
+Node: AWKLIBPATH Variable141056
+Node: Other Environment Variables142313
+Node: Exit Status146134
+Node: Include Files146811
+Node: Loading Shared Libraries150406
+Node: Obsolete151834
+Node: Undocumented152526
+Node: Invoking Summary152823
+Node: Regexp154483
+Node: Regexp Usage156002
+Node: Escape Sequences158039
+Node: Regexp Operators164271
+Ref: Regexp Operators-Footnote-1171687
+Ref: Regexp Operators-Footnote-2171834
+Node: Bracket Expressions171932
+Ref: table-char-classes174408
+Node: Leftmost Longest177545
+Node: Computed Regexps178848
+Node: GNU Regexp Operators182275
+Node: Case-sensitivity185954
+Ref: Case-sensitivity-Footnote-1188850
+Ref: Case-sensitivity-Footnote-2189085
+Node: Strong Regexp Constants189193
+Node: Regexp Summary189982
+Node: Reading Files191457
+Node: Records193620
+Node: awk split records194353
+Node: gawk split records199284
+Ref: gawk split records-Footnote-1203824
+Node: Fields203861
+Node: Nonconstant Fields206602
+Ref: Nonconstant Fields-Footnote-1208838
+Node: Changing Fields209042
+Node: Field Separators214970
+Node: Default Field Splitting217668
+Node: Regexp Field Splitting218786
+Node: Single Character Fields222139
+Node: Command Line Field Separator223199
+Node: Full Line Fields226417
+Ref: Full Line Fields-Footnote-1227939
+Ref: Full Line Fields-Footnote-2227985
+Node: Field Splitting Summary228086
+Node: Constant Size230160
+Node: Splitting By Content234738
+Ref: Splitting By Content-Footnote-1238709
+Node: Multiple Line238872
+Ref: Multiple Line-Footnote-1244754
+Node: Getline244933
+Node: Plain Getline247400
+Node: Getline/Variable250039
+Node: Getline/File251188
+Node: Getline/Variable/File252574
+Ref: Getline/Variable/File-Footnote-1254177
+Node: Getline/Pipe254265
+Node: Getline/Variable/Pipe256970
+Node: Getline/Coprocess258103
+Node: Getline/Variable/Coprocess259368
+Node: Getline Notes260108
+Node: Getline Summary262903
+Ref: table-getline-variants263325
+Node: Read Timeout264073
+Ref: Read Timeout-Footnote-1267979
+Node: Retrying Input268037
+Node: Command-line directories269236
+Node: Input Summary270142
+Node: Input Exercises273314
+Node: Printing274042
+Node: Print275876
+Node: Print Examples277333
+Node: Output Separators280113
+Node: OFMT282130
+Node: Printf283486
+Node: Basic Printf284271
+Node: Control Letters285845
+Node: Format Modifiers289833
+Node: Printf Examples295848
+Node: Redirection298334
+Node: Special FD305175
+Ref: Special FD-Footnote-1308343
+Node: Special Files308417
+Node: Other Inherited Files309034
+Node: Special Network310035
+Node: Special Caveats310895
+Node: Close Files And Pipes311844
+Ref: table-close-pipe-return-values318751
+Ref: Close Files And Pipes-Footnote-1319534
+Ref: Close Files And Pipes-Footnote-2319682
+Node: Nonfatal319834
+Node: Output Summary322159
+Node: Output Exercises323381
+Node: Expressions324060
+Node: Values325248
+Node: Constants325926
+Node: Scalar Constants326617
+Ref: Scalar Constants-Footnote-1327481
+Node: Nondecimal-numbers327731
+Node: Regexp Constants330744
+Node: Using Constant Regexps331270
+Node: Variables334433
+Node: Using Variables335090
+Node: Assignment Options337000
+Node: Conversion338873
+Node: Strings And Numbers339397
+Ref: Strings And Numbers-Footnote-1342460
+Node: Locale influences conversions342569
+Ref: table-locale-affects345327
+Node: All Operators345945
+Node: Arithmetic Ops346574
+Node: Concatenation349080
+Ref: Concatenation-Footnote-1351927
+Node: Assignment Ops352034
+Ref: table-assign-ops357025
+Node: Increment Ops358338
+Node: Truth Values and Conditions361798
+Node: Truth Values362872
+Node: Typing and Comparison363920
+Node: Variable Typing364740
+Node: Comparison Operators368364
+Ref: table-relational-ops368783
+Node: POSIX String Comparison372278
+Ref: POSIX String Comparison-Footnote-1373973
+Ref: POSIX String Comparison-Footnote-2374112
+Node: Boolean Ops374196
+Ref: Boolean Ops-Footnote-1378678
+Node: Conditional Exp378770
+Node: Function Calls380506
+Node: Precedence384383
+Node: Locales388042
+Node: Expressions Summary389674
+Node: Patterns and Actions392247
+Node: Pattern Overview393367
+Node: Regexp Patterns395044
+Node: Expression Patterns395586
+Node: Ranges399367
+Node: BEGIN/END402475
+Node: Using BEGIN/END403236
+Ref: Using BEGIN/END-Footnote-1405972
+Node: I/O And BEGIN/END406078
+Node: BEGINFILE/ENDFILE408392
+Node: Empty411299
+Node: Using Shell Variables411616
+Node: Action Overview413890
+Node: Statements416215
+Node: If Statement418063
+Node: While Statement419558
+Node: Do Statement421586
+Node: For Statement422734
+Node: Switch Statement425892
+Node: Break Statement428278
+Node: Continue Statement430370
+Node: Next Statement432197
+Node: Nextfile Statement434580
+Node: Exit Statement437232
+Node: Built-in Variables439635
+Node: User-modified440768
+Node: Auto-set448354
+Ref: Auto-set-Footnote-1463007
+Ref: Auto-set-Footnote-2463213
+Node: ARGC and ARGV463269
+Node: Pattern Action Summary467482
+Node: Arrays469912
+Node: Array Basics471241
+Node: Array Intro472085
+Ref: figure-array-elements474060
+Ref: Array Intro-Footnote-1476764
+Node: Reference to Elements476892
+Node: Assigning Elements479356
+Node: Array Example479847
+Node: Scanning an Array481606
+Node: Controlling Scanning484628
+Ref: Controlling Scanning-Footnote-1490027
+Node: Numeric Array Subscripts490343
+Node: Uninitialized Subscripts492527
+Node: Delete494146
+Ref: Delete-Footnote-1496898
+Node: Multidimensional496955
+Node: Multiscanning500050
+Node: Arrays of Arrays501641
+Node: Arrays Summary506408
+Node: Functions508501
+Node: Built-in509539
+Node: Calling Built-in510620
+Node: Numeric Functions512616
+Ref: Numeric Functions-Footnote-1517449
+Ref: Numeric Functions-Footnote-2517806
+Ref: Numeric Functions-Footnote-3517854
+Node: String Functions518126
+Ref: String Functions-Footnote-1541630
+Ref: String Functions-Footnote-2541758
+Ref: String Functions-Footnote-3542006
+Node: Gory Details542093
+Ref: table-sub-escapes543884
+Ref: table-sub-proposed545403
+Ref: table-posix-sub546766
+Ref: table-gensub-escapes548307
+Ref: Gory Details-Footnote-1549130
+Node: I/O Functions549284
+Ref: table-system-return-values555866
+Ref: I/O Functions-Footnote-1557846
+Ref: I/O Functions-Footnote-2557994
+Node: Time Functions558114
+Ref: Time Functions-Footnote-1568636
+Ref: Time Functions-Footnote-2568704
+Ref: Time Functions-Footnote-3568862
+Ref: Time Functions-Footnote-4568973
+Ref: Time Functions-Footnote-5569085
+Ref: Time Functions-Footnote-6569312
+Node: Bitwise Functions569578
+Ref: table-bitwise-ops570172
+Ref: Bitwise Functions-Footnote-1576218
+Ref: Bitwise Functions-Footnote-2576391
+Node: Type Functions576582
+Node: I18N Functions579114
+Node: User-defined580765
+Node: Definition Syntax581570
+Ref: Definition Syntax-Footnote-1587257
+Node: Function Example587328
+Ref: Function Example-Footnote-1590250
+Node: Function Caveats590272
+Node: Calling A Function590790
+Node: Variable Scope591748
+Node: Pass By Value/Reference594742
+Node: Return Statement598241
+Node: Dynamic Typing601220
+Node: Indirect Calls602150
+Ref: Indirect Calls-Footnote-1612401
+Node: Functions Summary612529
+Node: Library Functions615234
+Ref: Library Functions-Footnote-1618841
+Ref: Library Functions-Footnote-2618984
+Node: Library Names619155
+Ref: Library Names-Footnote-1622615
+Ref: Library Names-Footnote-2622838
+Node: General Functions622924
+Node: Strtonum Function624027
+Node: Assert Function627049
+Node: Round Function630375
+Node: Cliff Random Function631916
+Node: Ordinal Functions632932
+Ref: Ordinal Functions-Footnote-1635995
+Ref: Ordinal Functions-Footnote-2636247
+Node: Join Function636457
+Ref: Join Function-Footnote-1638227
+Node: Getlocaltime Function638427
+Node: Readfile Function642169
+Node: Shell Quoting644141
+Node: Data File Management645542
+Node: Filetrans Function646174
+Node: Rewind Function650270
+Node: File Checking652176
+Ref: File Checking-Footnote-1653510
+Node: Empty Files653711
+Node: Ignoring Assigns655690
+Node: Getopt Function657240
+Ref: Getopt Function-Footnote-1668709
+Node: Passwd Functions668909
+Ref: Passwd Functions-Footnote-1677748
+Node: Group Functions677836
+Ref: Group Functions-Footnote-1685734
+Node: Walking Arrays685941
+Node: Library Functions Summary688949
+Node: Library Exercises690355
+Node: Sample Programs690820
+Node: Running Examples691590
+Node: Clones692318
+Node: Cut Program693542
+Node: Egrep Program703471
+Ref: Egrep Program-Footnote-1710983
+Node: Id Program711093
+Node: Split Program714773
+Ref: Split Program-Footnote-1718232
+Node: Tee Program718361
+Node: Uniq Program721151
+Node: Wc Program728577
+Ref: Wc Program-Footnote-1732832
+Node: Miscellaneous Programs732926
+Node: Dupword Program734139
+Node: Alarm Program736169
+Node: Translate Program741024
+Ref: Translate Program-Footnote-1745589
+Node: Labels Program745859
+Ref: Labels Program-Footnote-1749210
+Node: Word Sorting749294
+Node: History Sorting753366
+Node: Extract Program755201
+Node: Simple Sed762730
+Node: Igawk Program765804
+Ref: Igawk Program-Footnote-1780135
+Ref: Igawk Program-Footnote-2780337
+Ref: Igawk Program-Footnote-3780459
+Node: Anagram Program780574
+Node: Signature Program783636
+Node: Programs Summary784883
+Node: Programs Exercises786097
+Ref: Programs Exercises-Footnote-1790226
+Node: Advanced Features790317
+Node: Nondecimal Data792307
+Node: Array Sorting793898
+Node: Controlling Array Traversal794598
+Ref: Controlling Array Traversal-Footnote-1802965
+Node: Array Sorting Functions803083
+Ref: Array Sorting Functions-Footnote-1808174
+Node: Two-way I/O808370
+Ref: Two-way I/O-Footnote-1814920
+Ref: Two-way I/O-Footnote-2815107
+Node: TCP/IP Networking815189
+Node: Profiling818307
+Ref: Profiling-Footnote-1826800
+Node: Advanced Features Summary827123
+Node: Internationalization828967
+Node: I18N and L10N830447
+Node: Explaining gettext831134
+Ref: Explaining gettext-Footnote-1837026
+Ref: Explaining gettext-Footnote-2837211
+Node: Programmer i18n837376
+Ref: Programmer i18n-Footnote-1842231
+Node: Translator i18n842280
+Node: String Extraction843074
+Ref: String Extraction-Footnote-1844206
+Node: Printf Ordering844292
+Ref: Printf Ordering-Footnote-1847078
+Node: I18N Portability847142
+Ref: I18N Portability-Footnote-1849598
+Node: I18N Example849661
+Ref: I18N Example-Footnote-1852467
+Node: Gawk I18N852540
+Node: I18N Summary853185
+Node: Debugger854526
+Node: Debugging855548
+Node: Debugging Concepts855989
+Node: Debugging Terms857798
+Node: Awk Debugging860373
+Node: Sample Debugging Session861279
+Node: Debugger Invocation861813
+Node: Finding The Bug863199
+Node: List of Debugger Commands869677
+Node: Breakpoint Control871010
+Node: Debugger Execution Control874704
+Node: Viewing And Changing Data878066
+Node: Execution Stack881440
+Node: Debugger Info883077
+Node: Miscellaneous Debugger Commands887148
+Node: Readline Support892236
+Node: Limitations893132
+Ref: Limitations-Footnote-1897363
+Node: Debugging Summary897414
+Node: Arbitrary Precision Arithmetic898693
+Node: Computer Arithmetic900109
+Ref: table-numeric-ranges903700
+Ref: Computer Arithmetic-Footnote-1904422
+Node: Math Definitions904479
+Ref: table-ieee-formats907793
+Ref: Math Definitions-Footnote-1908396
+Node: MPFR features908501
+Node: FP Math Caution910218
+Ref: FP Math Caution-Footnote-1911290
+Node: Inexactness of computations911659
+Node: Inexact representation912619
+Node: Comparing FP Values913979
+Node: Errors accumulate915061
+Node: Getting Accuracy916494
+Node: Try To Round919204
+Node: Setting precision920103
+Ref: table-predefined-precision-strings920800
+Node: Setting the rounding mode922630
+Ref: table-gawk-rounding-modes923004
+Ref: Setting the rounding mode-Footnote-1926412
+Node: Arbitrary Precision Integers926591
+Ref: Arbitrary Precision Integers-Footnote-1931508
+Node: POSIX Floating Point Problems931657
+Ref: POSIX Floating Point Problems-Footnote-1935539
+Node: Floating point summary935577
+Node: Dynamic Extensions937767
+Node: Extension Intro939320
+Node: Plugin License940586
+Node: Extension Mechanism Outline941383
+Ref: figure-load-extension941822
+Ref: figure-register-new-function943387
+Ref: figure-call-new-function944479
+Node: Extension API Description946541
+Node: Extension API Functions Introduction948073
+Node: General Data Types952932
+Ref: General Data Types-Footnote-1958887
+Node: Memory Allocation Functions959186
+Ref: Memory Allocation Functions-Footnote-1962031
+Node: Constructor Functions962130
+Node: Registration Functions963875
+Node: Extension Functions964560
+Node: Exit Callback Functions967183
+Node: Extension Version String968433
+Node: Input Parsers969096
+Node: Output Wrappers978978
+Node: Two-way processors983490
+Node: Printing Messages985755
+Ref: Printing Messages-Footnote-1986926
+Node: Updating ERRNO987079
+Node: Requesting Values987818
+Ref: table-value-types-returned988555
+Node: Accessing Parameters989438
+Node: Symbol Table Access990673
+Node: Symbol table by name991185
+Node: Symbol table by cookie993206
+Ref: Symbol table by cookie-Footnote-1997358
+Node: Cached values997422
+Ref: Cached values-Footnote-11000929
+Node: Array Manipulation1001020
+Ref: Array Manipulation-Footnote-11002111
+Node: Array Data Types1002148
+Ref: Array Data Types-Footnote-11004806
+Node: Array Functions1004898
+Node: Flattening Arrays1008756
+Node: Creating Arrays1015664
+Node: Redirection API1020433
+Node: Extension API Variables1023264
+Node: Extension Versioning1023897
+Ref: gawk-api-version1024334
+Node: Extension API Informational Variables1026090
+Node: Extension API Boilerplate1027154
+Node: Finding Extensions1030968
+Node: Extension Example1031527
+Node: Internal File Description1032325
+Node: Internal File Ops1036405
+Ref: Internal File Ops-Footnote-11048167
+Node: Using Internal File Ops1048307
+Ref: Using Internal File Ops-Footnote-11050690
+Node: Extension Samples1050964
+Node: Extension Sample File Functions1052493
+Node: Extension Sample Fnmatch1060142
+Node: Extension Sample Fork1061629
+Node: Extension Sample Inplace1062847
+Node: Extension Sample Ord1066057
+Node: Extension Sample Readdir1066893
+Ref: table-readdir-file-types1067782
+Node: Extension Sample Revout1068587
+Node: Extension Sample Rev2way1069176
+Node: Extension Sample Read write array1069916
+Node: Extension Sample Readfile1071858
+Node: Extension Sample Time1072953
+Node: Extension Sample API Tests1074301
+Node: gawkextlib1074793
+Node: Extension summary1077240
+Node: Extension Exercises1080942
+Node: Language History1082440
+Node: V7/SVR3.11084096
+Node: SVR41086248
+Node: POSIX1087682
+Node: BTL1089061
+Node: POSIX/GNU1089790
+Node: Feature History1095652
+Node: Common Extensions1110022
+Node: Ranges and Locales1111305
+Ref: Ranges and Locales-Footnote-11115921
+Ref: Ranges and Locales-Footnote-21115948
+Ref: Ranges and Locales-Footnote-31116183
+Node: Contributors1116404
+Node: History summary1121964
+Node: Installation1123344
+Node: Gawk Distribution1124288
+Node: Getting1124772
+Node: Extracting1125733
+Node: Distribution contents1127371
+Node: Unix Installation1133456
+Node: Quick Installation1134138
+Node: Shell Startup Files1136552
+Node: Additional Configuration Options1137630
+Node: Configuration Philosophy1139435
+Node: Non-Unix Installation1141804
+Node: PC Installation1142264
+Node: PC Binary Installation1143102
+Node: PC Compiling1143537
+Node: PC Using1144654
+Node: Cygwin1147699
+Node: MSYS1148469
+Node: VMS Installation1148970
+Node: VMS Compilation1149761
+Ref: VMS Compilation-Footnote-11150990
+Node: VMS Dynamic Extensions1151048
+Node: VMS Installation Details1152733
+Node: VMS Running1154986
+Node: VMS GNV1159265
+Node: VMS Old Gawk1160000
+Node: Bugs1160471
+Node: Bug address1161134
+Node: Usenet1163531
+Node: Maintainers1164306
+Node: Other Versions1165682
+Node: Installation summary1172266
+Node: Notes1173301
+Node: Compatibility Mode1174166
+Node: Additions1174948
+Node: Accessing The Source1175873
+Node: Adding Code1177308
+Node: New Ports1183527
+Node: Derived Files1188015
+Ref: Derived Files-Footnote-11193500
+Ref: Derived Files-Footnote-21193535
+Ref: Derived Files-Footnote-31194133
+Node: Future Extensions1194247
+Node: Implementation Limitations1194905
+Node: Extension Design1196088
+Node: Old Extension Problems1197242
+Ref: Old Extension Problems-Footnote-11198760
+Node: Extension New Mechanism Goals1198817
+Ref: Extension New Mechanism Goals-Footnote-11202181
+Node: Extension Other Design Decisions1202370
+Node: Extension Future Growth1204483
+Node: Old Extension Mechanism1205319
+Node: Notes summary1207082
+Node: Basic Concepts1208264
+Node: Basic High Level1208945
+Ref: figure-general-flow1209227
+Ref: figure-process-flow1209912
+Ref: Basic High Level-Footnote-11213213
+Node: Basic Data Typing1213398
+Node: Glossary1216726
+Node: Copying1248673
+Node: GNU Free Documentation License1286212
+Node: Index1311330

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index e1b8fbbb..9015d5f4 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
@@ -4044,6 +4049,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
@@ -4052,18 +4058,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 compatibility. 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}]
@@ -4072,6 +4082,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.
@@ -4101,11 +4112,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}).
@@ -4143,6 +4149,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
@@ -4456,6 +4469,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.
@@ -4487,6 +4503,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.
@@ -4514,6 +4533,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
@@ -4568,14 +4589,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.
@@ -4873,6 +4886,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
@@ -4965,6 +5004,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
@@ -5155,17 +5195,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
@@ -6221,6 +6265,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
@@ -6311,6 +6374,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.
@@ -6685,16 +6749,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}.
@@ -7139,7 +7199,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
@@ -8102,6 +8161,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 attempted. @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.
@@ -8756,7 +8822,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
@@ -8766,6 +8833,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
@@ -8927,6 +9024,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
@@ -10353,17 +10451,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,
@@ -10410,17 +10517,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,
@@ -10432,6 +10548,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
@@ -10461,6 +10641,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
@@ -12380,19 +12566,19 @@ One special place where @code{/foo/} is @emph{not} an abbreviation for
where this is discussed in more detail.
@node POSIX String Comparison
-@subsubsection String Comparison with POSIX Rules
+@subsubsection String Comparison Based on Locale Collating Order
-The POSIX standard says that string comparison is performed based
-on the locale's @dfn{collating order}. This is the order in which
-characters sort, as defined by the locale (for more discussion,
-@pxref{Locales}). This order is usually very different
-from the results obtained when doing straight character-by-character
-comparison.@footnote{Technically, string comparison is supposed
-to behave the same way as if the strings were compared with the C
-@code{strcoll()} function.}
+The POSIX standard used to say that all string comparisons are
+performed based on the locale's @dfn{collating order}. This
+is the order in which characters sort, as defined by the locale
+(for more discussion, @pxref{Locales}). This order is usually very
+different from the results obtained when doing straight byte-by-byte
+comparison.@footnote{Technically, string comparison is supposed to behave
+the same way as if the strings were compared with the C @code{strcoll()}
+function.}
Because this behavior differs considerably from existing practice,
-@command{gawk} only implements it when in POSIX mode (@pxref{Options}).
+@command{gawk} only implemented it when in POSIX mode (@pxref{Options}).
Here is an example to illustrate the difference, in an @code{en_US.UTF-8}
locale:
@@ -12405,6 +12591,26 @@ $ @kbd{gawk --posix 'BEGIN @{ printf("ABC < abc = %s\n",}
@print{} ABC < abc = FALSE
@end example
+Fortunately, as of August 2016, comparison based on locale
+collating order is no longer required for the @code{==} and @code{!=}
+operators.@footnote{See @uref{http://austingroupbugs.net/view.php?id=1070,
+the Austin Group website}.} However, comparison based on locales is still
+required for @code{<}, @code{<=}, @code{>}, and @code{>=}. POSIX thus
+recommends as follows:
+
+@quotation
+Since the @code{==} operator checks whether strings are identical,
+not whether they collate equally, applications needing to check whether
+strings collate equally can use:
+
+@example
+a <= b && a >= b
+@end example
+@end quotation
+
+As of @value{PVERSION} 4.2, @command{gawk} continues to use locale
+collating order for @code{<}, @code{<=}, @code{>}, and @code{>=} only
+in POSIX mode.
@node Boolean Ops
@subsection Boolean Expressions
@@ -14564,12 +14770,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:
@@ -14793,10 +14998,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
@@ -14830,6 +15049,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}
@@ -14898,6 +15122,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.
@@ -15021,6 +15249,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.
@@ -16961,6 +17197,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
@@ -19126,12 +19379,12 @@ Return the value of @var{val}, shifted right by @var{count} bits.
Return the bitwise XOR of the arguments. There must be at least two.
@end table
-For all of these functions, first the double-precision floating-point value is
-converted to the widest C unsigned integer type, then the bitwise operation is
-performed. If the result cannot be represented exactly as a C @code{double},
-leading nonzero bits are removed one by one until it can be represented
-exactly. The result is then converted back into a C @code{double}. (If
-you don't understand this paragraph, don't worry about it.)
+@quotation CAUTION
+Beginning with @command{gawk} @value{VERSION} 4.2, negative
+operands are not allowed for any of these functions. A negative
+operand produces a fatal error. See the sidebar
+``Beware The Smoke and Mirrors!'' for more information as to why.
+@end quotation
Here is a user-defined function (@pxref{User-defined})
that illustrates the use of these functions:
@@ -19236,19 +19489,192 @@ decimal and octal values for the same numbers
and then demonstrates the
results of the @code{compl()}, @code{lshift()}, and @code{rshift()} functions.
+@cindex sidebar, Beware The Smoke and Mirrors!
+@ifdocbook
+@docbook
+<sidebar><title>Beware The Smoke and Mirrors!</title>
+@end docbook
+
+
+It other languages, bitwise operations are performed on integer values,
+not floating-point values. As a general statement, such operations work
+best when performed on unsigned integers.
+
+@command{gawk} attempts to treat the arguments to the bitwise functions
+as unsigned integers. For this reason, negative arguments produce a
+fatal error.
+
+In normal operation, for all of these functions, first the
+double-precision floating-point value is converted to the widest C
+unsigned integer type, then the bitwise operation is performed. If the
+result cannot be represented exactly as a C @code{double}, leading
+nonzero bits are removed one by one until it can be represented exactly.
+The result is then converted back into a C @code{double}.@footnote{If you don't
+understand this paragraph, the upshot is that @command{gawk} can only
+store a particular range of integer values; numbers outside that range
+are reduced to fit within the range.}
+
+However, when using arbitrary precision arithmetic with the @option{-M}
+option (@pxref{Arbitrary Precision Arithmetic}), the results may differ.
+This is particularly noticeable with the @code{compl()} function:
+
+@example
+$ @kbd{gawk 'BEGIN @{ print compl(42) @}'}
+@print{} 9007199254740949
+$ @kbd{gawk -M 'BEGIN @{ print compl(42) @}'}
+@print{} -43
+@end example
+
+What's going on becomes clear when printing the results
+in hexadecimal:
+
+@example
+$ @kbd{gawk 'BEGIN @{ printf "%#x\n", compl(42) @}'}
+@print{} 0x1fffffffffffd5
+$ @kbd{gawk -M 'BEGIN @{ printf "%#x\n", compl(42) @}'}
+@print{} 0xffffffffffffffd5
+@end example
+
+When using the @option{-M} option, under the hood, @command{gawk} uses
+GNU MP arbitrary precision integers which have at least 64 bits of precision.
+When not using @option{-M}, @command{gawk} stores integral values in
+regular double-precision floating point, which only maintain 53 bits of
+precision. Furthermore, the GNU MP library treats (or least seems to treat)
+the leading bit as a sign bit; thus the result with @option{-M} in this case is
+a negative number.
+
+In short, using @command{gawk} for any but the simplest kind of bitwise
+operations is probably a bad idea; caveat emptor!
+
+
+@docbook
+</sidebar>
+@end docbook
+@end ifdocbook
+
+@ifnotdocbook
+@cartouche
+@center @b{Beware The Smoke and Mirrors!}
+
+
+
+It other languages, bitwise operations are performed on integer values,
+not floating-point values. As a general statement, such operations work
+best when performed on unsigned integers.
+
+@command{gawk} attempts to treat the arguments to the bitwise functions
+as unsigned integers. For this reason, negative arguments produce a
+fatal error.
+
+In normal operation, for all of these functions, first the
+double-precision floating-point value is converted to the widest C
+unsigned integer type, then the bitwise operation is performed. If the
+result cannot be represented exactly as a C @code{double}, leading
+nonzero bits are removed one by one until it can be represented exactly.
+The result is then converted back into a C @code{double}.@footnote{If you don't
+understand this paragraph, the upshot is that @command{gawk} can only
+store a particular range of integer values; numbers outside that range
+are reduced to fit within the range.}
+
+However, when using arbitrary precision arithmetic with the @option{-M}
+option (@pxref{Arbitrary Precision Arithmetic}), the results may differ.
+This is particularly noticeable with the @code{compl()} function:
+
+@example
+$ @kbd{gawk 'BEGIN @{ print compl(42) @}'}
+@print{} 9007199254740949
+$ @kbd{gawk -M 'BEGIN @{ print compl(42) @}'}
+@print{} -43
+@end example
+
+What's going on becomes clear when printing the results
+in hexadecimal:
+
+@example
+$ @kbd{gawk 'BEGIN @{ printf "%#x\n", compl(42) @}'}
+@print{} 0x1fffffffffffd5
+$ @kbd{gawk -M 'BEGIN @{ printf "%#x\n", compl(42) @}'}
+@print{} 0xffffffffffffffd5
+@end example
+
+When using the @option{-M} option, under the hood, @command{gawk} uses
+GNU MP arbitrary precision integers which have at least 64 bits of precision.
+When not using @option{-M}, @command{gawk} stores integral values in
+regular double-precision floating point, which only maintain 53 bits of
+precision. Furthermore, the GNU MP library treats (or least seems to treat)
+the leading bit as a sign bit; thus the result with @option{-M} in this case is
+a negative number.
+
+In short, using @command{gawk} for any but the simplest kind of bitwise
+operations is probably a bad idea; caveat emptor!
+
+@end cartouche
+@end ifnotdocbook
+
@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
@@ -19266,6 +19692,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
@@ -27526,9 +27959,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
@@ -27912,8 +28352,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
@@ -28007,10 +28446,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
@@ -28051,8 +28515,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
@@ -30242,6 +30705,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 discussing. 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!
@@ -30278,6 +30800,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
@@ -31095,6 +31621,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
@@ -31494,6 +32136,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
@@ -31569,6 +32212,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:
@@ -31957,7 +32604,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
@@ -31989,11 +32636,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
@@ -32496,6 +33149,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.
@@ -33539,6 +34195,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
@@ -35106,18 +35831,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}
@@ -35217,7 +35945,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
@@ -35746,6 +36474,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
@@ -35833,6 +36565,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
@@ -35871,6 +36608,7 @@ The
@option{-p},
@option{-P},
@option{-r},
+@option{-s},
@option{-S},
@option{-t},
and
@@ -35895,6 +36633,7 @@ and the
@option{--load},
@option{--non-decimal-data},
@option{--optimize},
+@option{--no-optimize},
@option{--posix},
@option{--pretty-print},
@option{--profile},
@@ -35965,6 +36704,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
@@ -36591,6 +37340,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
@@ -36720,7 +37515,7 @@ and
@uref{http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap09.html#tag_21_09_03_05, its rationale}.}
By using this lovely technical term, the standard gives license
-to implementors to implement ranges in whatever way they choose.
+to implementers to implement ranges in whatever way they choose.
The @command{gawk} maintainer chose to apply the pre-POSIX meaning
both with the default regexp matching and when @option{--traditional} or
@option{--posix} are used.
@@ -37257,6 +38052,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
@@ -37301,8 +38098,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
@@ -37313,6 +38108,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.
@@ -37341,6 +38142,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
@@ -37421,6 +38223,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 207c85bb..3e33d75d 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
@@ -3955,6 +3960,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
@@ -3963,18 +3969,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 compatibility. 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}]
@@ -3983,6 +3993,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.
@@ -4012,11 +4023,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}).
@@ -4054,6 +4060,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
@@ -4367,6 +4380,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.
@@ -4398,6 +4414,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.
@@ -4425,6 +4444,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
@@ -4479,14 +4500,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.
@@ -4784,6 +4797,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
@@ -4876,6 +4915,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
@@ -5066,17 +5106,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
@@ -6005,6 +6049,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
@@ -6095,6 +6158,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.
@@ -6412,16 +6476,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}.
@@ -6835,7 +6895,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
@@ -7702,6 +7761,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 attempted. @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.
@@ -8356,7 +8422,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
@@ -8366,6 +8433,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
@@ -8527,6 +8624,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
@@ -9907,17 +10005,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,
@@ -9928,6 +10035,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
@@ -9957,6 +10128,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
@@ -11708,19 +11885,19 @@ One special place where @code{/foo/} is @emph{not} an abbreviation for
where this is discussed in more detail.
@node POSIX String Comparison
-@subsubsection String Comparison with POSIX Rules
+@subsubsection String Comparison Based on Locale Collating Order
-The POSIX standard says that string comparison is performed based
-on the locale's @dfn{collating order}. This is the order in which
-characters sort, as defined by the locale (for more discussion,
-@pxref{Locales}). This order is usually very different
-from the results obtained when doing straight character-by-character
-comparison.@footnote{Technically, string comparison is supposed
-to behave the same way as if the strings were compared with the C
-@code{strcoll()} function.}
+The POSIX standard used to say that all string comparisons are
+performed based on the locale's @dfn{collating order}. This
+is the order in which characters sort, as defined by the locale
+(for more discussion, @pxref{Locales}). This order is usually very
+different from the results obtained when doing straight byte-by-byte
+comparison.@footnote{Technically, string comparison is supposed to behave
+the same way as if the strings were compared with the C @code{strcoll()}
+function.}
Because this behavior differs considerably from existing practice,
-@command{gawk} only implements it when in POSIX mode (@pxref{Options}).
+@command{gawk} only implemented it when in POSIX mode (@pxref{Options}).
Here is an example to illustrate the difference, in an @code{en_US.UTF-8}
locale:
@@ -11733,6 +11910,26 @@ $ @kbd{gawk --posix 'BEGIN @{ printf("ABC < abc = %s\n",}
@print{} ABC < abc = FALSE
@end example
+Fortunately, as of August 2016, comparison based on locale
+collating order is no longer required for the @code{==} and @code{!=}
+operators.@footnote{See @uref{http://austingroupbugs.net/view.php?id=1070,
+the Austin Group website}.} However, comparison based on locales is still
+required for @code{<}, @code{<=}, @code{>}, and @code{>=}. POSIX thus
+recommends as follows:
+
+@quotation
+Since the @code{==} operator checks whether strings are identical,
+not whether they collate equally, applications needing to check whether
+strings collate equally can use:
+
+@example
+a <= b && a >= b
+@end example
+@end quotation
+
+As of @value{PVERSION} 4.2, @command{gawk} continues to use locale
+collating order for @code{<}, @code{<=}, @code{>}, and @code{>=} only
+in POSIX mode.
@node Boolean Ops
@subsection Boolean Expressions
@@ -13892,12 +14089,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:
@@ -14121,10 +14317,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
@@ -14158,6 +14368,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}
@@ -14226,6 +14441,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.
@@ -14349,6 +14568,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.
@@ -16243,6 +16470,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
@@ -18247,12 +18491,12 @@ Return the value of @var{val}, shifted right by @var{count} bits.
Return the bitwise XOR of the arguments. There must be at least two.
@end table
-For all of these functions, first the double-precision floating-point value is
-converted to the widest C unsigned integer type, then the bitwise operation is
-performed. If the result cannot be represented exactly as a C @code{double},
-leading nonzero bits are removed one by one until it can be represented
-exactly. The result is then converted back into a C @code{double}. (If
-you don't understand this paragraph, don't worry about it.)
+@quotation CAUTION
+Beginning with @command{gawk} @value{VERSION} 4.2, negative
+operands are not allowed for any of these functions. A negative
+operand produces a fatal error. See the sidebar
+``Beware The Smoke and Mirrors!'' for more information as to why.
+@end quotation
Here is a user-defined function (@pxref{User-defined})
that illustrates the use of these functions:
@@ -18357,19 +18601,124 @@ decimal and octal values for the same numbers
and then demonstrates the
results of the @code{compl()}, @code{lshift()}, and @code{rshift()} functions.
+@sidebar Beware The Smoke and Mirrors!
+
+It other languages, bitwise operations are performed on integer values,
+not floating-point values. As a general statement, such operations work
+best when performed on unsigned integers.
+
+@command{gawk} attempts to treat the arguments to the bitwise functions
+as unsigned integers. For this reason, negative arguments produce a
+fatal error.
+
+In normal operation, for all of these functions, first the
+double-precision floating-point value is converted to the widest C
+unsigned integer type, then the bitwise operation is performed. If the
+result cannot be represented exactly as a C @code{double}, leading
+nonzero bits are removed one by one until it can be represented exactly.
+The result is then converted back into a C @code{double}.@footnote{If you don't
+understand this paragraph, the upshot is that @command{gawk} can only
+store a particular range of integer values; numbers outside that range
+are reduced to fit within the range.}
+
+However, when using arbitrary precision arithmetic with the @option{-M}
+option (@pxref{Arbitrary Precision Arithmetic}), the results may differ.
+This is particularly noticeable with the @code{compl()} function:
+
+@example
+$ @kbd{gawk 'BEGIN @{ print compl(42) @}'}
+@print{} 9007199254740949
+$ @kbd{gawk -M 'BEGIN @{ print compl(42) @}'}
+@print{} -43
+@end example
+
+What's going on becomes clear when printing the results
+in hexadecimal:
+
+@example
+$ @kbd{gawk 'BEGIN @{ printf "%#x\n", compl(42) @}'}
+@print{} 0x1fffffffffffd5
+$ @kbd{gawk -M 'BEGIN @{ printf "%#x\n", compl(42) @}'}
+@print{} 0xffffffffffffffd5
+@end example
+
+When using the @option{-M} option, under the hood, @command{gawk} uses
+GNU MP arbitrary precision integers which have at least 64 bits of precision.
+When not using @option{-M}, @command{gawk} stores integral values in
+regular double-precision floating point, which only maintain 53 bits of
+precision. Furthermore, the GNU MP library treats (or least seems to treat)
+the leading bit as a sign bit; thus the result with @option{-M} in this case is
+a negative number.
+
+In short, using @command{gawk} for any but the simplest kind of bitwise
+operations is probably a bad idea; caveat emptor!
+
+@end sidebar
+
@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
@@ -18387,6 +18736,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
@@ -26617,9 +26973,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
@@ -27003,8 +27366,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
@@ -27098,10 +27460,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
@@ -27142,8 +27529,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
@@ -29333,6 +29719,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 discussing. 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!
@@ -29369,6 +29814,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
@@ -30186,6 +30635,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
@@ -30585,6 +31150,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
@@ -30660,6 +31226,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:
@@ -31048,7 +31618,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
@@ -31080,11 +31650,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
@@ -31587,6 +32163,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.
@@ -32630,6 +33209,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
@@ -34197,18 +34845,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}
@@ -34308,7 +34959,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
@@ -34837,6 +35488,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
@@ -34924,6 +35579,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
@@ -34962,6 +35622,7 @@ The
@option{-p},
@option{-P},
@option{-r},
+@option{-s},
@option{-S},
@option{-t},
and
@@ -34986,6 +35647,7 @@ and the
@option{--load},
@option{--non-decimal-data},
@option{--optimize},
+@option{--no-optimize},
@option{--posix},
@option{--pretty-print},
@option{--profile},
@@ -35056,6 +35718,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
@@ -35682,6 +36354,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
@@ -35811,7 +36529,7 @@ and
@uref{http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap09.html#tag_21_09_03_05, its rationale}.}
By using this lovely technical term, the standard gives license
-to implementors to implement ranges in whatever way they choose.
+to implementers to implement ranges in whatever way they choose.
The @command{gawk} maintainer chose to apply the pre-POSIX meaning
both with the default regexp matching and when @option{--traditional} or
@option{--posix} are used.
@@ -36348,6 +37066,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
@@ -36392,8 +37112,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
@@ -36404,6 +37122,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.
@@ -36432,6 +37156,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
@@ -36512,6 +37237,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/wordlist b/doc/wordlist
index 7bbed134..759afc87 100644
--- a/doc/wordlist
+++ b/doc/wordlist
@@ -554,6 +554,7 @@ Yawitz
Za
Zaphod
Zaretskii
+Zaretskii's
Zcrtdll
Zeichen
Zeichenkette
@@ -879,6 +880,7 @@ dir
dircategory
direntry
distributable
+div
djgpp
dl
dlload
@@ -957,6 +959,7 @@ expr
ext
extenders
extern
+ezwinports
fPIC
fabi
fabius
@@ -968,6 +971,7 @@ fdata
fe
ferror
fffffffffff
+fffffffffffd
fflush
fi
fieldlist
@@ -1361,6 +1365,7 @@ netlib
newdata
newdir
newgawk
+newgroup
newsxfer
nexgo
nextfile
@@ -1901,6 +1906,7 @@ xdeadBEEF
xdigit
xfcc
xfcd
+xffffffffffffffd
xgawk
xgettext
xnrkb
diff --git a/eval.c b/eval.c
index 36dab2fb..284bf2eb 100644
--- a/eval.c
+++ b/eval.c
@@ -1,23 +1,23 @@
/*
- * eval.c - gawk bytecode interpreter
+ * eval.c - gawk bytecode interpreter
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2016 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
@@ -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);
@@ -54,7 +53,7 @@ static NODE *node_Boolean[2];
#ifdef C
#undef C
#endif
-#define C(c) ((char)c)
+#define C(c) ((char)c)
/*
* This table is used by the regexp routines to do case independent
* matching. Basically, every ascii character maps to itself, except
@@ -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",
@@ -289,6 +287,7 @@ static struct optypetab {
{ "Op_postincrement", "++" },
{ "Op_postdecrement", "--" },
{ "Op_unary_minus", "-" },
+ { "Op_unary_plus", "+" },
{ "Op_field_spec", "$" },
{ "Op_not", "! " },
{ "Op_assign", " = " },
@@ -315,7 +314,7 @@ static struct optypetab {
{ "Op_match", " ~ " },
{ "Op_match_rec", NULL },
{ "Op_nomatch", " !~ " },
- { "Op_rule", NULL },
+ { "Op_rule", NULL },
{ "Op_K_case", "case" },
{ "Op_K_default", "default" },
{ "Op_K_break", "break" },
@@ -334,12 +333,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 +363,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 },
@@ -444,10 +444,12 @@ flags2str(int flagval)
{ WSTRCUR, "WSTRCUR" },
{ MPFN, "MPFN" },
{ MPZN, "MPZN" },
+ { NO_EXT_SET, "NO_EXT_SET" },
{ NULL_FIELD, "NULL_FIELD" },
{ ARRAYMAXED, "ARRAYMAXED" },
{ HALFHAT, "HALFHAT" },
{ XARRAY, "XARRAY" },
+ { NUMCONSTSTR, "NUMCONSTSTR" },
{ 0, NULL },
};
@@ -575,7 +577,7 @@ posix_compare(NODE *s1, NODE *s2)
/* cmp_nodes --- compare two nodes, returning negative, 0, positive */
int
-cmp_nodes(NODE *t1, NODE *t2)
+cmp_nodes(NODE *t1, NODE *t2, bool use_strcmp)
{
int ret = 0;
size_t len1, len2;
@@ -584,14 +586,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);
@@ -604,7 +600,7 @@ cmp_nodes(NODE *t1, NODE *t2)
if (len1 == 0 || len2 == 0)
return ldiff;
- if (do_posix)
+ if (do_posix && ! use_strcmp)
return posix_compare(t1, t2);
l = (ldiff <= 0 ? len1 : len2);
@@ -646,7 +642,7 @@ push_frame(NODE *f)
}
if (fcall_count > 1)
- memmove(fcall_list + 2, fcall_list + 1, (fcall_count - 1) * sizeof(NODE *));
+ memmove(fcall_list + 2, fcall_list + 1, (fcall_count - 1) * sizeof(NODE *));
fcall_list[1] = f;
}
@@ -657,7 +653,7 @@ static void
pop_frame()
{
if (fcall_count > 1)
- memmove(fcall_list + 1, fcall_list + 2, (fcall_count - 1) * sizeof(NODE *));
+ memmove(fcall_list + 1, fcall_list + 2, (fcall_count - 1) * sizeof(NODE *));
fcall_count--;
assert(fcall_count >= 0);
if (do_debug)
@@ -700,7 +696,6 @@ void
set_IGNORECASE()
{
static bool warned = false;
- NODE *n = IGNORECASE_node->var_value;
if ((do_lint || do_traditional) && ! warned) {
warned = true;
@@ -709,19 +704,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 +716,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 +725,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 +812,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;
@@ -904,7 +887,7 @@ fmt_index(NODE *n)
emalloc(fmt_list, NODE **, fmt_num*sizeof(*fmt_list), "fmt_index");
n = force_string(n);
while (ix < fmt_hiwater) {
- if (cmp_nodes(fmt_list[ix], n) == 0)
+ if (cmp_nodes(fmt_list[ix], n, true) == 0)
return ix;
ix++;
}
@@ -949,36 +932,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 +992,7 @@ update_ERRNO_int(int errcode)
{
char *cp;
+ update_PROCINFO_num("errno", errcode);
if (errcode) {
cp = strerror(errcode);
cp = gettext(cp);
@@ -1031,6 +1007,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 +1017,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);
}
@@ -1099,7 +1077,7 @@ STACK_ITEM *stack_bottom;
STACK_ITEM *stack_top;
static unsigned long STACK_SIZE = 256; /* initial size of stack */
int max_args = 0; /* maximum # of arguments to printf, print, sprintf,
- * or # of array subscripts, or adjacent strings
+ * or # of array subscripts, or adjacent strings
* to be concatenated.
*/
NODE **args_array = NULL;
@@ -1171,7 +1149,7 @@ r_get_lhs(NODE *n, bool reference)
/* r_get_field --- get the address of a field node */
-
+
NODE **
r_get_field(NODE *n, Func_ptr *assign, bool reference)
{
@@ -1181,7 +1159,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"));
@@ -1243,7 +1221,7 @@ calc_exp(AWKNUM x1, AWKNUM x2)
}
-/* setup_frame --- setup new frame for function call */
+/* setup_frame --- setup new frame for function call */
static INSTRUCTION *
setup_frame(INSTRUCTION *pc)
@@ -1285,7 +1263,7 @@ setup_frame(INSTRUCTION *pc)
}
- /* check for extra args */
+ /* check for extra args */
if (arg_count > pcount) {
warning(
_("function `%s' called with more arguments than declared"),
@@ -1379,7 +1357,7 @@ setup_frame(INSTRUCTION *pc)
/* setup new frame */
getnode(frame_ptr);
- frame_ptr->type = Node_frame;
+ frame_ptr->type = Node_frame;
frame_ptr->stack = sp;
frame_ptr->prev_frame_size = (stack_ptr - stack_bottom); /* size of the previous stack frame */
frame_ptr->func_node = f;
@@ -1497,7 +1475,7 @@ unwind_stack(long n)
if (in_main_context() && ! exiting)
fatal(_("unwind_stack: unexpected type `%s'"),
nodetype2str(r->type));
- /* else
+ /* else
* Node_var_array,
* Node_param_list,
* Node_var (e.g: trying to use scalar for array)
@@ -1511,7 +1489,7 @@ unwind_stack(long n)
break;
}
return cp;
-}
+}
/* pop_fcall --- pop off the innermost frame */
@@ -1530,21 +1508,18 @@ 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);
}
+typedef enum {
+ SCALAR_EQ_NEQ,
+ SCALAR_RELATIONAL
+} scalar_cmp_t;
+
/* cmp_scalars -- compare two nodes on the stack */
static inline int
-cmp_scalars()
+cmp_scalars(scalar_cmp_t comparison_type)
{
NODE *t1, *t2;
int di;
@@ -1555,14 +1530,14 @@ cmp_scalars()
DEREF(t2);
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t1));
}
- di = cmp_nodes(t1, t2);
+ di = cmp_nodes(t1, t2, comparison_type == SCALAR_EQ_NEQ);
DEREF(t1);
DEREF(t2);
return di;
}
/* op_assign --- assignment operators excluding = */
-
+
static void
op_assign(OPCODE op)
{
@@ -1664,9 +1639,9 @@ POP_CODE()
typedef struct exec_state {
struct exec_state *next;
- INSTRUCTION *cptr; /* either getline (Op_K_getline) or the
+ INSTRUCTION *cptr; /* either getline (Op_K_getline) or the
* implicit "open-file, read-record" loop (Op_newfile).
- */
+ */
int rule; /* rule for the INSTRUCTION */
@@ -1732,7 +1707,7 @@ register_exec_hook(Func_pre_exec preh, Func_post_exec posth)
/*
* multiple post-exec hooks aren't supported. post-exec hook is mainly
* for use by the debugger.
- */
+ */
if (! preh || (post_execute && posth))
return false;
@@ -1760,7 +1735,7 @@ register_exec_hook(Func_pre_exec preh, Func_post_exec posth)
}
-/* interpreter routine when not debugging */
+/* interpreter routine when not debugging */
#include "interpret.h"
/* interpreter routine with exec hook(s). Used when debugging and/or with MPFR. */
@@ -1808,6 +1783,6 @@ init_interpret()
if (num_exec_hook > 0)
interpret = h_interpret;
else
- interpret = r_interpret;
+ interpret = r_interpret;
}
diff --git a/ext.c b/ext.c
index 45f1e6de..10a42210 100644
--- a/ext.c
+++ b/ext.c
@@ -9,20 +9,20 @@
/*
* Copyright (C) 1995 - 2001, 2003-2014, 2016,
* 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
@@ -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')
@@ -212,15 +120,15 @@ make_builtin(const awk_ext_func_t *funcinfo)
/* user-defined function */
fatal(_("make_builtin: can't redefine function `%s'"), name);
} else if (f->type == Node_ext_func) {
- /* multiple extension() calls etc. */
+ /* multiple extension() calls etc. */
if (do_lint)
lintwarn(_("make_builtin: function `%s' already defined"), name);
return awk_false;
} else
- /* variable name etc. */
+ /* variable name etc. */
fatal(_("make_builtin: function name `%s' previously defined"), name);
} else if (check_special(name) >= 0)
- fatal(_("make_builtin: can't use gawk built-in `%s' as function name"), name);
+ fatal(_("make_builtin: can't use gawk built-in `%s' as function name"), name);
if (count < 0)
fatal(_("make_builtin: negative argument count for function `%s'"),
@@ -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);
@@ -315,7 +167,7 @@ get_argument(int i)
if (t->type == Node_array_ref) {
if (t->orig_array->type == Node_var) {
- /* already a scalar, can no longer use it as array */
+ /* already a scalar, can no longer use it as array */
t->type = Node_var;
t->var_value = Nnull_string;
return t;
@@ -339,10 +191,10 @@ get_actual_argument(NODE *t, int i, bool want_array)
{
char *fname;
INSTRUCTION *pc;
-
+
pc = TOP()->code_ptr; /* Op_ext_builtin instruction */
fname = (pc + 1)->func_name;
-
+
if (t->type == Node_var_new) {
if (want_array)
return force_array(t, false);
@@ -387,7 +239,7 @@ close_extensions()
if (srcfiles == NULL)
return;
- for (s = srcfiles->next; s != srcfiles; s = s->next)
+ for (s = srcfiles->next; s != srcfiles; s = s->next)
if (s->stype == SRC_EXTLIB && s->fini_func)
(*s->fini_func)();
}
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 f8d1517e..52d4ddb5 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,7 @@
+2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * General: Remove trailing whitespace from all relevant files.
+
2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
* 4.1.4: Release tar ball made.
@@ -11,6 +15,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.
@@ -81,11 +90,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.
@@ -122,11 +139,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
@@ -298,6 +390,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 d0eed3cc..b5b27d03 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.4, bug-gawk@gnu.org, gawk-extensions)
+AC_INIT([GNU Awk Bundled Extensions],[4.1.4],[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..a074de53 100644
--- a/extension/filefuncs.c
+++ b/extension/filefuncs.c
@@ -12,20 +12,20 @@
/*
* Copyright (C) 2001, 2004, 2005, 2010-2016
* 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
@@ -484,7 +484,7 @@ do_stat(int nargs, awk_value_t *result)
warning(ext_id, _("stat: bad parameters"));
return make_number(-1, result);
}
-
+
if (nargs == 3) {
statfunc = stat;
}
@@ -561,7 +561,7 @@ do_statvfs(int nargs, awk_value_t *result)
#endif
array_set_numeric(array, "flag", vfsbuf.f_flag); /* mount flags */
array_set_numeric(array, "namemax", vfsbuf.f_namemax); /* maximum filename length */
-
+
return make_number(ret, result);
}
@@ -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/fnmatch.c b/extension/fnmatch.c
index a85bcc78..f5fb02c6 100644
--- a/extension/fnmatch.c
+++ b/extension/fnmatch.c
@@ -8,20 +8,20 @@
/*
* Copyright (C) 2012, 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
diff --git a/extension/fork.c b/extension/fork.c
index 0ca0a0e0..82593b7f 100644
--- a/extension/fork.c
+++ b/extension/fork.c
@@ -7,20 +7,20 @@
/*
* Copyright (C) 2001, 2004, 2011, 2012, 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
diff --git a/extension/inplace.c b/extension/inplace.c
index c7eb5564..26c37922 100644
--- a/extension/inplace.c
+++ b/extension/inplace.c
@@ -4,20 +4,20 @@
/*
* Copyright (C) 2013-2015 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
@@ -132,7 +132,7 @@ do_inplace_begin(int nargs, awk_value_t *result)
if (nargs != 2)
fatal(ext_id, _("inplace_begin: expects 2 arguments but called with %d"), nargs);
-
+
if (! get_argument(0, AWK_STRING, &filename))
fatal(ext_id, _("inplace_begin: cannot retrieve 1st argument as a string filename"));
diff --git a/extension/ordchr.c b/extension/ordchr.c
index 8ec9de3f..4f9cd616 100644
--- a/extension/ordchr.c
+++ b/extension/ordchr.c
@@ -10,20 +10,20 @@
/*
* Copyright (C) 2001, 2004, 2011, 2012, 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
diff --git a/extension/readdir.c b/extension/readdir.c
index 4578b864..6106a44b 100644
--- a/extension/readdir.c
+++ b/extension/readdir.c
@@ -11,20 +11,20 @@
/*
* Copyright (C) 2012-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
diff --git a/extension/readfile.c b/extension/readfile.c
index d4b4aef9..fbe25748 100644
--- a/extension/readfile.c
+++ b/extension/readfile.c
@@ -14,20 +14,20 @@
/*
* Copyright (C) 2002, 2003, 2004, 2011, 2012, 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
@@ -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/revoutput.c b/extension/revoutput.c
index 69257167..84d0aaa5 100644
--- a/extension/revoutput.c
+++ b/extension/revoutput.c
@@ -8,20 +8,20 @@
/*
* Copyright (C) 2012, 2013, 2015 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
diff --git a/extension/revtwoway.c b/extension/revtwoway.c
index dfe58a1e..82fabb2b 100644
--- a/extension/revtwoway.c
+++ b/extension/revtwoway.c
@@ -8,20 +8,20 @@
/*
* Copyright (C) 2012-2014, 2016 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
diff --git a/extension/rwarray.c b/extension/rwarray.c
index 155cc47c..15e121af 100644
--- a/extension/rwarray.c
+++ b/extension/rwarray.c
@@ -8,20 +8,20 @@
/*
* Copyright (C) 2009-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
@@ -80,7 +80,7 @@ static awk_bool_t read_value(FILE *fp, awk_value_t *value);
* Minor version 4 bytes - network order
* Element count 4 bytes - network order
* Elements
- *
+ *
* For each element:
* Length of index val: 4 bytes - network order
* Index val as characters (N bytes)
@@ -436,7 +436,7 @@ read_value(FILE *fp, awk_value_t *value)
awk_array_t array = create_array();
if (! read_array(fp, array))
- return awk_false;
+ return awk_false;
/* hook into value */
value->val_type = AWK_ARRAY;
@@ -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..00289cad 100644
--- a/extension/rwarray0.c
+++ b/extension/rwarray0.c
@@ -8,20 +8,20 @@
/*
* Copyright (C) 2009, 2010, 2011, 2012, 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
@@ -76,7 +76,7 @@ static awk_bool_t read_value(int fd, awk_value_t *value);
* Minor version 4 bytes - network order
* Element count 4 bytes - network order
* Elements
- *
+ *
* For each element:
* Length of index val: 4 bytes - network order
* Index val as characters (N bytes)
@@ -431,7 +431,7 @@ read_value(int fd, awk_value_t *value)
awk_array_t array = create_array();
if (read_array(fd, array) != 0)
- return awk_false;
+ return awk_false;
/* hook into value */
value->val_type = AWK_ARRAY;
@@ -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/stack.c b/extension/stack.c
index 6150442c..637378e2 100644
--- a/extension/stack.c
+++ b/extension/stack.c
@@ -2,22 +2,22 @@
* stack.c -- Implementation for stack functions for use by extensions.
*/
-/*
+/*
* Copyright (C) 2012, 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
diff --git a/extension/testext.c b/extension/testext.c
index 4a1e7032..9216d64a 100644
--- a/extension/testext.c
+++ b/extension/testext.c
@@ -5,20 +5,20 @@
/*
* Copyright (C) 2012, 2013, 2014, 2015
* 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
@@ -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:$*"
+}
diff --git a/field.c b/field.c
index 5f5b2b65..4f24d5f3 100644
--- a/field.c
+++ b/field.c
@@ -2,22 +2,22 @@
* field.c - routines for dealing with fields and record parsing
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2016 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
@@ -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;
@@ -278,7 +276,7 @@ set_record(const char *buf, int cnt)
memcpy(databuf, buf, cnt);
/*
- * Add terminating '\0' so that C library routines
+ * Add terminating '\0' so that C library routines
* will know when to stop.
*/
databuf[cnt] = '\0';
@@ -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;
@@ -341,7 +339,7 @@ set_NF()
assert(NF != -1);
(void) force_number(NF_node->var_value);
- nf = get_number_si(NF_node->var_value);
+ nf = get_number_si(NF_node->var_value);
if (nf < 0)
fatal(_("NF set to negative value"));
NF = nf;
@@ -409,7 +407,7 @@ re_parse_field(long up_to, /* parse only up to this field number */
sep = scan;
while (scan < end && (*scan == ' ' || *scan == '\t' || *scan == '\n'))
scan++;
- if (sep_arr != NULL && sep < scan)
+ if (sep_arr != NULL && sep < scan)
set_element(nf, sep, (long)(scan - sep), sep_arr);
}
@@ -441,8 +439,8 @@ re_parse_field(long up_to, /* parse only up to this field number */
}
(*set)(++nf, field,
(long)(scan + RESTART(rp, scan) - field), n);
- if (sep_arr != NULL)
- set_element(nf, scan + RESTART(rp, scan),
+ if (sep_arr != NULL)
+ set_element(nf, scan + RESTART(rp, scan),
(long) (REEND(rp, scan) - RESTART(rp, scan)), sep_arr);
scan += REEND(rp, scan);
field = scan;
@@ -506,7 +504,7 @@ def_parse_field(long up_to, /* parse only up to this field number */
sep = scan;
for (; nf < up_to; scan++) {
/*
- * special case: fs is single space, strip leading whitespace
+ * special case: fs is single space, strip leading whitespace
*/
while (scan < end && (*scan == ' ' || *scan == '\t' || *scan == '\n'))
scan++;
@@ -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()
@@ -857,11 +786,11 @@ get_field(long requested, Func_ptr *assign)
/*
* Keep things uniform. Also, mere intention of assigning something
* to $n should not make $0 invalid. Makes sense to invalidate $0
- * after the actual assignment is performed. Not a real issue in
+ * after the actual assignment is performed. Not a real issue in
* the interpreter otherwise, but causes problem in the
* debugger when watching or printing fields.
*/
-
+
if (assign != NULL)
*assign = invalidate_field0; /* $0 needs reconstruction */
#endif
@@ -977,12 +906,12 @@ do_split(int nargs)
if (sep_arr != NULL) {
if (sep_arr == arr)
- fatal(_("split: cannot use the same array for second and fourth args"));
+ fatal(_("split: cannot use the same array for second and fourth args"));
/* This checks need to be done before clearing any of the arrays */
for (tmp = sep_arr->parent_array; tmp != NULL; tmp = tmp->parent_array)
if (tmp == arr)
- fatal(_("split: cannot use a subarray of second arg for fourth arg"));
+ fatal(_("split: cannot use a subarray of second arg for fourth arg"));
for (tmp = arr->parent_array; tmp != NULL; tmp = tmp->parent_array)
if (tmp == sep_arr)
fatal(_("split: cannot use a subarray of fourth arg for second arg"));
@@ -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 {
@@ -1071,7 +997,7 @@ do_patsplit(int nargs)
if (sep_arr != NULL) {
if (sep_arr == arr)
- fatal(_("patsplit: cannot use the same array for second and fourth args"));
+ fatal(_("patsplit: cannot use the same array for second and fourth args"));
/* These checks need to be done before clearing any of the arrays */
for (tmp = sep_arr->parent_array; tmp != NULL; tmp = tmp->parent_array)
@@ -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");
}
@@ -1165,7 +1091,7 @@ set_FIELDWIDTHS()
|| (*end != '\0' && ! is_blank(*end))
|| !(0 < tmp && tmp <= INT_MAX)
) {
- fatal_error = true;
+ fatal_error = true;
break;
}
FIELDWIDTHS[i] = tmp;
@@ -1236,7 +1162,7 @@ set_FS()
* FS_regexp will be NULL with a non-null FS_re_yes_case.
* refree() handles null argument; no need for `if (FS_regexp != NULL)' below.
* Please do not remerge.
- */
+ */
refree(FS_re_yes_case);
refree(FS_re_no_case);
FS_re_yes_case = FS_re_no_case = FS_regexp = NULL;
@@ -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] == ' ')
@@ -1482,19 +1405,19 @@ incr_scan(char **scanp, size_t len, mbstate_t *mbs)
* BEGIN {
* false = 0
* true = 1
- *
+ *
* fpat[1] = "([^,]*)|(\"[^\"]+\")"
* fpat[2] = fpat[1]
* fpat[3] = fpat[1]
* fpat[4] = "aa+"
* fpat[5] = fpat[4]
- *
+ *
* data[1] = "Robbins,,Arnold,"
* data[2] = "Smith,,\"1234 A Pretty Place, NE\",Sometown,NY,12345-6789,USA"
* data[3] = "Robbins,Arnold,\"1234 A Pretty Place, NE\",Sometown,NY,12345-6789,USA"
* data[4] = "bbbaaacccdddaaaaaqqqq"
* data[5] = "bbbaaacccdddaaaaaqqqqa" # should get trailing qqqa
- *
+ *
* for (i = 1; i in data; i++) {
* printf("Splitting: <%s>\n", data[i])
* n = mypatsplit(data[i], fields, fpat[i], seps)
@@ -1505,7 +1428,7 @@ incr_scan(char **scanp, size_t len, mbstate_t *mbs)
* printf("seps[%s] = <%s>\n", j, seps[j])
* }
* }
- *
+ *
* function mypatsplit(string, array, pattern, seps,
* eosflag, non_empty, nf) # locals
* {
@@ -1513,7 +1436,7 @@ incr_scan(char **scanp, size_t len, mbstate_t *mbs)
* delete seps
* if (length(string) == 0)
* return 0
- *
+ *
* eosflag = non_empty = false
* nf = 0
* while (match(string, pattern)) {
@@ -1564,7 +1487,7 @@ incr_scan(char **scanp, size_t len, mbstate_t *mbs)
* }
* if (length(string) > 0)
* seps[nf] = string
- *
+ *
* return length(array)
* }
*/
@@ -1637,7 +1560,7 @@ fpat_parse_field(long up_to, /* parse only up to this field number */
* last match was non-empty, and at the
* current character we get a zero length match,
* which we don't want, so skip over it
- */
+ */
non_empty = false;
if (sep_arr != NULL) {
need_to_set_sep = false;
diff --git a/floatcomp.c b/floatcomp.c
index 9ba169a4..7317fa75 100644
--- a/floatcomp.c
+++ b/floatcomp.c
@@ -2,23 +2,23 @@
* floatcomp.c - Isolate floating point details.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2011, 2016
* 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
diff --git a/floatmagic.h b/floatmagic.h
index c6aabd92..cb22b611 100644
--- a/floatmagic.h
+++ b/floatmagic.h
@@ -1,23 +1,23 @@
/*
- * floatmagic.h -- Definitions of isnan and isinf for gawk.
+ * floatmagic.h -- Definitions of isnan and isinf for gawk.
*/
-/*
+/*
* Copyright (C) 2009 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
diff --git a/gawkapi.c b/gawkapi.c
index 1ef2f79e..ba881a3c 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -2,22 +2,22 @@
* gawkapi.c -- Implement the functions defined for gawkapi.h
*/
-/*
+/*
* Copyright (C) 2012-2016 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
@@ -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);
/*
@@ -71,7 +76,7 @@ api_get_argument(awk_ext_id_t id, size_t count,
goto scalar;
}
}
-
+
/* at this point, we have real type */
if (arg->type == Node_var_array || arg->type == Node_array_ref) {
if (wanted != AWK_ARRAY && wanted != AWK_UNDEFINED)
@@ -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;
@@ -485,7 +502,7 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted)
* - No access to special variables (NF, etc.)
* - One special exception: PROCINFO.
* - Use sym_update() to change a value, including from UNDEFINED
- * to scalar or array.
+ * to scalar or array.
*/
/*
* Lookup a variable, fills in value. No messing with the value
@@ -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,12 +806,15 @@ 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;
}
/*
- * remove_element --- remove an array element
+ * remove_element --- remove an array element
* common code used by multiple functions
*/
@@ -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 */
diff --git a/gawkapi.h b/gawkapi.h
index 039ec5fa..7482af51 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -2,22 +2,22 @@
* gawkapi.h -- Definitions for use by extension functions calling into gawk.
*/
-/*
+/*
* Copyright (C) 2012-2016 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
@@ -53,7 +53,7 @@
* This API purposely restricts itself to ISO C 90 features. In particular, no
* bool, no // comments, no use of the restrict keyword, or anything else,
* in order to provide maximal portability.
- *
+ *
* Exception: the "inline" keyword is used below in the "constructor"
* functions. If your compiler doesn't support it, you should either
* -Dinline='' on your command line, or use the autotools and include a
@@ -136,7 +136,7 @@ typedef struct awk_input {
* parser is responsible for managing its own memory buffer.
* Similarly, gawk will make its own copy of RT, so the parser
* is also responsible for managing this memory.
- *
+ *
* It is guaranteed that errcode is a valid pointer, so there is
* no need to test for a NULL value. Gawk sets *errcode to 0,
* so there is no need to set it unless an error occurs.
@@ -165,7 +165,7 @@ typedef struct awk_input {
/* put last, for alignment. bleah */
struct stat sbuf; /* stat buf */
-
+
} awk_input_buf_t;
typedef struct awk_input_parser {
@@ -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.
@@ -521,7 +531,7 @@ typedef struct gawk_api {
* - Read-only access to special variables (NF, etc.)
* - One special exception: PROCINFO.
* - Use sym_update() to change a value, including from UNDEFINED
- * to scalar or array.
+ * to scalar or array.
*/
/*
* Lookup a variable, fill in value. No messing with the value
@@ -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/gawkmisc.c b/gawkmisc.c
index 0172a810..f1658921 100644
--- a/gawkmisc.c
+++ b/gawkmisc.c
@@ -2,23 +2,23 @@
* gawkmisc.c --- miscellanious gawk routines that are OS specific.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2004, 2010, 2011
* 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
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 d27fc555..d29071e3 100644
--- a/helpers/ChangeLog
+++ b/helpers/ChangeLog
@@ -1,3 +1,11 @@
+2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * General: Remove trailing whitespace from all relevant files.
+
+2016-09-08 Paul Eggert <eggert@cs.ucla.edu>
+
+ * testdfa.c: Adjust to DFA API changes.
+
2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
* 4.1.4: Release tar ball made.
@@ -37,6 +45,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..72b97907 100644
--- a/helpers/testdfa.c
+++ b/helpers/testdfa.c
@@ -2,22 +2,22 @@
* testdfa.c --- abstracted from gawk.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-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
@@ -44,6 +44,7 @@
#define _Noreturn
#define _GL_ATTRIBUTE_PURE
#include "dfa.h"
+#include "localeinfo.h"
const char *regexflags2str(int flags);
char *databuf(int fd);
@@ -71,7 +72,8 @@ void usage(const char *myname)
int main(int argc, char **argv)
{
- int c, ret, try_backref;
+ int c, ret;
+ bool try_backref;
struct re_pattern_buffer pat;
struct re_registers regs;
struct dfa *dfareg;
@@ -84,6 +86,7 @@ int main(int argc, char **argv)
char save;
size_t count = 0;
char *place;
+ struct localeinfo localeinfo;
if (argc < 2)
usage(argv[0]);
@@ -158,7 +161,6 @@ int main(int argc, char **argv)
dfa_syn = syn;
if (ignorecase)
dfa_syn |= RE_ICASE;
- dfasyntax(dfa_syn, ignorecase, '\n');
re_set_syntax(syn);
if ((rerr = re_compile_pattern(pattern, len, & pat)) != NULL) {
@@ -171,6 +173,10 @@ int main(int argc, char **argv)
pat.newline_anchor = false; /* don't get \n in middle of string */
dfareg = dfaalloc();
+ init_localeinfo(&localeinfo);
+ dfasyntax(dfareg, &localeinfo, dfa_syn,
+ ignorecase ? DFA_CASE_FOLD : 0);
+
printf("Calling dfacomp(%s, %d, %p, true)\n",
pattern, (int) len, dfareg);
@@ -372,10 +378,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;
@@ -389,23 +395,14 @@ setup_pattern(const char *pattern, size_t *len)
/*
* Build a copy of the string (in buf) with the
* escaped characters translated, and generate the regex
- * from that.
+ * 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) {
@@ -502,16 +499,16 @@ setup_pattern(const char *pattern, size_t *len)
*
* Parse a C escape sequence. STRING_PTR points to a variable containing a
* pointer to the string to parse. That pointer is updated past the
- * characters we use. The value of the escape sequence is returned.
+ * characters we use. The value of the escape sequence is returned.
*
* A negative value means the sequence \ newline was seen, which is supposed to
- * be equivalent to nothing at all.
+ * be equivalent to nothing at all.
*
* If \ is followed by a null character, we return a negative value and leave
- * the string pointer pointing at the null character.
+ * the string pointer pointing at the null character.
*
* If \ is followed by 000, we return 0 and leave the string pointer after the
- * zeros. A value of 0 does not mean end of string.
+ * zeros. A value of 0 does not mean end of string.
*
* POSIX doesn't allow \x.
*/
@@ -600,7 +597,7 @@ parse_escape(const char **string_ptr)
#ifdef C
#undef C
#endif
-#define C(c) ((char)c)
+#define C(c) ((char)c)
/*
* This table is used by the regexp routines to do case independent
* matching. Basically, every ascii character maps to itself, except
diff --git a/helpers/testnet.c b/helpers/testnet.c
index feda38b4..cbe2d97e 100644
--- a/helpers/testnet.c
+++ b/helpers/testnet.c
@@ -220,9 +220,9 @@ devopen(const char *name, const char *mode)
localpname = cp;
while (*cp != '/' && *cp != '\0')
cp++;
- /*
+ /*
* Require a port, let them explicitly put 0 if
- * they don't care.
+ * they don't care.
*/
if (*cp != '/' || cp == localpname) {
fprintf(stderr, _("special file name `%s' is incomplete"), name);
@@ -241,7 +241,7 @@ devopen(const char *name, const char *mode)
cp++;
hostname = cp;
while (*cp != '/' && *cp != '\0')
- cp++;
+ cp++;
if (*cp != '/' || cp == hostname) {
*localpnamelastcharp = '/';
fprintf(stderr, _("must supply a remote hostname to `/inet'"));
@@ -278,7 +278,7 @@ devopen(const char *name, const char *mode)
char *cp, *end;
unsigned long count = 0;
char *ms2;
-
+
first_time = false;
if ((cp = getenv("GAWK_SOCK_RETRIES")) != NULL) {
count = strtoul(cp, & end, 10);
diff --git a/int_array.c b/int_array.c
index 6cffec86..2ab68eeb 100644
--- a/int_array.c
+++ b/int_array.c
@@ -2,23 +2,23 @@
* int_array.c - routines for arrays of integer indices.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2013, 2016,
* 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
@@ -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;
-
- if (len == 0 || (! isdigit((unsigned char) *cp) && *cp != '-'))
- return NULL;
- if (len > 1 &&
- ((*cp == '0') /* "00", "011" .. */
- || (*cp == '-' && *(cp + 1) == '0') /* "-0", "-011" .. */
- )
- )
- return NULL;
- if (len == 1 && *cp != '-') { /* single digit */
- subs->numbr = (long) (*cp - '0');
- if ((subs->flags & MAYBE_NUM) != 0) {
- subs->flags &= ~MAYBE_NUM;
- subs->flags |= NUMBER;
- }
- subs->flags |= (NUMCUR|NUMINT);
- return & success_node;
- }
+ /* must be a STRING */
+ char *cp = subs->stptr, *cpend, *ptr;
+ char save;
+ size_t len = subs->stlen;
- cpend = cp + len;
- save = *cpend;
- *cpend = '\0';
+ if (len == 0 || (! isdigit((unsigned char) *cp) && *cp != '-'))
+ return NULL;
- errno = 0;
- l = strtol(cp, & ptr, 10);
- *cpend = save;
- if (errno != 0 || ptr != cpend)
- return NULL;
- subs->numbr = l;
+ if (len > 1 &&
+ ((*cp == '0') /* "00", "011" .. */
+ || (*cp == '-' && *(cp + 1) == '0') /* "-0", "-011" .. */
+ )
+ )
+ return NULL;
+ if (len == 1 && *cp != '-') { /* single digit */
+ subs->numbr = (long) (*cp - '0');
if ((subs->flags & MAYBE_NUM) != 0) {
- subs->flags &= ~MAYBE_NUM;
+ subs->flags &= ~(MAYBE_NUM|STRING);
subs->flags |= NUMBER;
}
- subs->flags |= NUMCUR;
- if (l <= INT32_MAX && l >= INT32_MIN) {
- subs->flags |= NUMINT;
- return & success_node;
- }
+ subs->flags |= (NUMCUR|NUMINT);
+ return & success_node;
}
+
+ cpend = cp + len;
+ save = *cpend;
+ *cpend = '\0';
+
+ errno = 0;
+ l = strtol(cp, & ptr, 10);
+ *cpend = save;
+ if (errno != 0 || ptr != cpend)
+ return NULL;
+
+ subs->numbr = l;
+ if ((subs->flags & MAYBE_NUM) != 0) {
+ subs->flags &= ~(MAYBE_NUM|STRING);
+ subs->flags |= NUMBER;
+ }
+ subs->flags |= NUMCUR;
+ if (l <= INT32_MAX && l >= INT32_MIN) {
+ subs->flags |= NUMINT;
+ return & success_node;
+ }
+
return NULL;
#endif /* CHECK_INTEGER_USING_FORCE_NUMBER */
}
@@ -238,7 +240,7 @@ int_lookup(NODE *symbol, NODE *subs)
if (! is_integer(symbol, subs)) {
- xn = symbol->xarray;
+ xn = symbol->xarray;
if (xn == NULL) {
xn = symbol->xarray = make_array();
xn->vname = symbol->vname; /* shallow copy */
@@ -256,9 +258,9 @@ int_lookup(NODE *symbol, NODE *subs)
hash1 = int_hash(k, symbol->array_size);
if ((lhs = int_find(symbol, k, hash1)) != NULL)
return lhs;
-
+
/* It's not there, install it */
-
+
symbol->table_size++;
/* first see if we would need to grow the array, before installing */
@@ -272,7 +274,7 @@ int_lookup(NODE *symbol, NODE *subs)
/* have to recompute hash value for new size */
hash1 = int_hash(k, symbol->array_size);
}
-
+
return int_insert(symbol, k, hash1);
}
@@ -326,7 +328,7 @@ int_clear(NODE *symbol, NODE *subs ATTRIBUTE_UNUSED)
r = b->aivalue[j];
if (r->type == Node_var_array) {
assoc_clear(r); /* recursively clear all sub-arrays */
- efree(r->vname);
+ efree(r->vname);
freenode(r);
} else
unref(r);
@@ -452,7 +454,7 @@ int_copy(NODE *symbol, NODE *newsymb)
/* find the current hash size */
cursize = symbol->array_size;
-
+
/* allocate new table */
emalloc(new, BUCKET **, cursize * sizeof(BUCKET *), "int_copy");
memset(new, '\0', cursize * sizeof(BUCKET *));
@@ -491,7 +493,7 @@ int_copy(NODE *symbol, NODE *newsymb)
newchain->ainext = NULL;
pnew = & newchain->ainext;
}
- }
+ }
if (symbol->xarray != NULL) {
NODE *xn, *n;
@@ -537,7 +539,7 @@ int_list(NODE *symbol, NODE *t)
if ((assoc_kind & (AINDEX|AVALUE)) == (AINDEX|AVALUE))
elem_size = 2;
list_size = elem_size * num_elems;
-
+
if (symbol->xarray != NULL) {
xn = symbol->xarray;
list = xn->alist(xn, t);
@@ -557,7 +559,7 @@ int_list(NODE *symbol, NODE *t)
/* index */
num = b->ainum[j];
if ((assoc_kind & AISTR) != 0) {
- sprintf(buf, "%ld", num);
+ sprintf(buf, "%ld", num);
subs = make_string(buf, strlen(buf));
subs->numbr = num;
subs->flags |= (NUMCUR|NUMINT);
@@ -602,7 +604,7 @@ int_kilobytes(NODE *symbol)
for (b = symbol->buckets[i]; b != NULL; b = b->ainext)
bucket_cnt++;
}
- kb = (((AWKNUM) bucket_cnt) * sizeof (BUCKET) +
+ kb = (((AWKNUM) bucket_cnt) * sizeof (BUCKET) +
((AWKNUM) symbol->array_size) * sizeof (BUCKET *)) / 1024.0;
if (symbol->xarray != NULL)
@@ -736,7 +738,7 @@ int_hash(uint32_t k, uint32_t hsize)
*/
/* This is the final mixing function used by Paul Hsieh in SuperFastHash. */
-
+
k ^= k << 3;
k += k >> 5;
k ^= k << 4;
@@ -778,7 +780,7 @@ int_insert(NODE *symbol, long k, uint32_t hash1)
b = symbol->buckets[hash1];
- /* Only the first bucket in the chain can be partially full, but is never empty. */
+ /* Only the first bucket in the chain can be partially full, but is never empty. */
if (b == NULL || (i = b->aicount) == 2) {
getbucket(b);
@@ -818,7 +820,7 @@ grow_int_table(NODE *symbol)
static const unsigned long sizes[] = {
13, 127, 1021, 8191, 16381, 32749, 65497,
131101, 262147, 524309, 1048583, 2097169,
- 4194319, 8388617, 16777259, 33554467,
+ 4194319, 8388617, 16777259, 33554467,
67108879, 134217757, 268435459, 536870923,
1073741827
};
diff --git a/interpret.h b/interpret.h
index e9abdffb..bba3cbb5 100644
--- a/interpret.h
+++ b/interpret.h
@@ -2,22 +2,22 @@
* interpret.h --- run a list of instructions.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2015 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
@@ -99,7 +99,7 @@ top:
/* avoid false source indications */
source = NULL;
sourceline = 0;
- (void) nextfile(& curfile, true); /* close input data file */
+ (void) nextfile(& curfile, true); /* close input data file */
/*
* This used to be:
*
@@ -144,6 +144,7 @@ top:
case Op_push:
case Op_push_arg:
+ case Op_push_arg_untyped:
{
NODE *save_symbol;
bool isparam = false;
@@ -160,7 +161,7 @@ top:
m = m->orig_array;
}
}
-
+
switch (m->type) {
case Node_var:
if (do_lint && var_uninitialized(m))
@@ -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"),
@@ -198,7 +203,7 @@ uninitialized_scalar:
cant_happen();
}
}
- break;
+ break;
case Op_push_param: /* function argument */
m = pc->memory;
@@ -236,7 +241,7 @@ uninitialized_scalar:
/* for FUNCTAB, get the name as the element value */
if (t1 == func_table) {
static bool warned = false;
-
+
if (do_lint && ! warned) {
warned = true;
lintwarn(_("FUNCTAB is a gawk extension"));
@@ -254,7 +259,7 @@ uninitialized_scalar:
/* for SYMTAB, step through to the actual variable */
if (t1 == symbol_table) {
static bool warned = false;
-
+
if (do_lint && ! warned) {
warned = true;
lintwarn(_("SYMTAB is a gawk extension"));
@@ -299,7 +304,7 @@ uninitialized_scalar:
t1 = POP_ARRAY();
if (do_lint && in_array(t1, t2) == NULL) {
t2 = force_string(t2);
- if (pc->do_reference)
+ if (pc->do_reference)
lintwarn(_("reference to uninitialized element `%s[\"%.*s\"]'"),
array_vname(t1), (int) t2->stlen, t2->stptr);
if (t2->stlen == 0)
@@ -403,7 +408,7 @@ uninitialized_scalar:
case Op_jmp_true:
r = POP_SCALAR();
di = eval_condition(r);
- DEREF(r);
+ DEREF(r);
if (di)
JUMPTO(pc->target_jmp);
break;
@@ -439,37 +444,37 @@ uninitialized_scalar:
break;
case Op_equal:
- r = node_Boolean[cmp_scalars() == 0];
+ r = node_Boolean[cmp_scalars(SCALAR_EQ_NEQ) == 0];
UPREF(r);
REPLACE(r);
break;
case Op_notequal:
- r = node_Boolean[cmp_scalars() != 0];
+ r = node_Boolean[cmp_scalars(SCALAR_EQ_NEQ) != 0];
UPREF(r);
REPLACE(r);
break;
case Op_less:
- r = node_Boolean[cmp_scalars() < 0];
+ r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) < 0];
UPREF(r);
REPLACE(r);
break;
case Op_greater:
- r = node_Boolean[cmp_scalars() > 0];
+ r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) > 0];
UPREF(r);
REPLACE(r);
break;
case Op_leq:
- r = node_Boolean[cmp_scalars() <= 0];
+ r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) <= 0];
UPREF(r);
REPLACE(r);
break;
case Op_geq:
- r = node_Boolean[cmp_scalars() >= 0];
+ r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) >= 0];
UPREF(r);
REPLACE(r);
break;
@@ -494,7 +499,7 @@ plus:
case Op_minus:
t2 = POP_NUMBER();
x2 = t2->numbr;
- DEREF(t2);
+ DEREF(t2);
minus:
t1 = TOP_NUMBER();
r = make_number(t1->numbr - x2);
@@ -544,7 +549,7 @@ quotient:
r = make_number(t1->numbr / x2);
DEREF(t1);
REPLACE(r);
- break;
+ break;
case Op_mod_i:
x2 = force_number(pc->memory)->numbr;
@@ -611,6 +616,11 @@ mod:
REPLACE(r);
break;
+ case Op_unary_plus:
+ // Force argument to be numeric
+ t1 = TOP_NUMBER();
+ break;
+
case Op_store_sub:
/*
* array[sub] assignment optimization,
@@ -663,7 +673,7 @@ mod:
* simple variable assignment optimization,
* see awkgram.y (optimize_assignment)
*/
-
+
lhs = get_lhs(pc->memory, false);
unref(*lhs);
r = pc->initval; /* constant initializer */
@@ -709,7 +719,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 +729,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';
@@ -727,14 +737,15 @@ mod:
} else
free_wstr(*lhs);
} else {
- size_t nlen = t1->stlen + t2->stlen;
+ 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);
+ t1 = *lhs = make_str_node(p, nlen, ALREADY_MALLOCED);
}
DEREF(t2);
break;
@@ -749,7 +760,7 @@ mod:
break;
case Op_subscript_assign:
- /* conditionally execute post-assignment routine for an array element */
+ /* conditionally execute post-assignment routine for an array element */
if (set_idx != NULL) {
di = true;
@@ -826,12 +837,11 @@ mod:
t2 = TOP_SCALAR(); /* switch expression */
t2 = force_string(t2);
rp = re_update(m);
- di = (research(rp, t2->stptr, 0, t2->stlen,
- avoid_dfa(m, t2->stptr, t2->stlen)) >= 0);
+ di = (research(rp, t2->stptr, 0, t2->stlen, RE_NO_FLAGS) >= 0);
} else {
t1 = POP_SCALAR(); /* case value */
t2 = TOP_SCALAR(); /* switch expression */
- di = (cmp_nodes(t2, t1) == 0);
+ di = (cmp_nodes(t2, t1, true) == 0);
DEREF(t1);
}
@@ -942,16 +952,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();
@@ -988,26 +994,13 @@ arrayfor:
}
PUSH(m);
break;
-
+
case Op_match_rec:
m = pc->memory;
t1 = *get_field(0, (Func_ptr *) 0);
match_re:
rp = re_update(m);
- /*
- * Any place where research() is called with a last parameter of
- * zero, we need to use the avoid_dfa test. This appears here and
- * in the code for Op_K_case.
- *
- * A new or improved dfa that distinguishes beginning/end of
- * string from beginning/end of line will allow us to get rid of
- * this hack.
- *
- * The avoid_dfa() function is in re.c; it is not very smart.
- */
-
- di = research(rp, t1->stptr, 0, t1->stlen,
- avoid_dfa(m, t1->stptr, t1->stlen));
+ di = research(rp, t1->stptr, 0, t1->stlen, RE_NO_FLAGS);
di = (di == -1) ^ (op != Op_nomatch);
if (op != Op_match_rec) {
decr_sp();
@@ -1062,7 +1055,7 @@ match_re:
} else if (f->type == Node_builtin_func) {
int arg_count = (pc + 1)->expr_count;
builtin_func_t the_func = lookup_builtin(t1->stptr);
-
+
assert(the_func != NULL);
/* call it */
@@ -1078,8 +1071,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,20 +1082,17 @@ 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];
npc[1].func_name = fname; /* name of the builtin */
npc[1].expr_count = bc->expr_count; /* defined max # of arguments */
- ni = npc;
+ ni = npc;
JUMPTO(ni);
} else
fatal(_("function called indirectly through `%s' does not exist"),
- pc->func_name);
+ pc->func_name);
}
pc->func_body = f; /* save for next call */
@@ -1119,12 +1108,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,15 +1121,12 @@ 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 */
(pc + 1)->expr_count = bc->expr_count; /* defined max # of arguments */
- ni = pc;
+ ni = pc;
JUMPTO(ni);
}
@@ -1152,7 +1138,7 @@ match_re:
m = POP_SCALAR(); /* return value */
ni = pop_fcall();
-
+
/* put the return value back on stack */
PUSH(m);
@@ -1177,7 +1163,7 @@ match_re:
/* Save execution state so that we can return to it
* from Op_after_beginfile or Op_after_endfile.
- */
+ */
push_exec_state(pc, currule, source, stack_ptr);
@@ -1235,8 +1221,8 @@ match_re:
execute beginfile block */
}
break;
-
- case Op_get_record:
+
+ case Op_get_record:
{
int errcode = 0;
@@ -1294,13 +1280,13 @@ match_re:
JUMPTO(ni);
} else {
/* do run ENDFILE block(s) first. */
-
+
/* Execution state to return to in Op_after_endfile. */
push_exec_state(ni, currule, source, stack_ptr);
JUMPTO(pc->target_endfile);
- }
- } /* else
+ }
+ } /* else
Start over with the first rule. */
/* empty the run-time stack to avoid memory leak */
@@ -1391,7 +1377,7 @@ match_re:
/* not already triggered and left expression is true */
decr_sp();
ip->triggered = true;
- JUMPTO(ip->target_jmp); /* evaluate right expression */
+ JUMPTO(ip->target_jmp); /* evaluate right expression */
}
result = ip->triggered || di;
@@ -1417,6 +1403,7 @@ match_re:
case Op_K_if:
case Op_K_else:
case Op_cond_exp:
+ case Op_comment:
break;
default:
diff --git a/io.c b/io.c
index 2dbc07a6..6f9ffbf6 100644
--- a/io.c
+++ b/io.c
@@ -2,23 +2,23 @@
* io.c --- routines for dealing with input and output and records
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2016,
* 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
@@ -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;
@@ -356,7 +357,7 @@ init_io()
* PROCINFO entries for timeout are dynamic;
* We can't be any more specific than this.
*/
- if (PROCINFO_node != NULL)
+ if (PROCINFO_node != NULL)
read_can_timeout = true;
}
@@ -416,7 +417,7 @@ after_beginfile(IOBUF **curfile)
bool valid;
fname = iop->public.name;
- errcode = iop->errcode;
+ errcode = iop->errcode;
valid = iop->valid;
errno = 0;
update_ERRNO_int(errcode);
@@ -465,12 +466,12 @@ nextfile(IOBUF **curfile, bool skipping)
(void) iop_close(iop);
*curfile = NULL;
return 1; /* run endfile block */
- } else
+ } else
return 0;
}
argc = get_number_si(ARGC_node->var_value);
-
+
for (; i < argc; i++) {
tmp = make_number((AWKNUM) i);
(void) force_string(tmp);
@@ -596,10 +597,11 @@ inrec(IOBUF *iop, int *errcode)
cnt = EOF;
else if ((iop->flag & IOP_CLOSED) != 0)
cnt = EOF;
- else
+ 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))
@@ -1002,7 +1022,7 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
#ifdef VMS
/* Alpha/VMS V7.1+ C RTL is returning these instead
of EMFILE (haven't tried other post-V6.2 systems) */
- else if ((errno == EIO || errno == EVMSERR) &&
+ else if ((errno == EIO || errno == EVMSERR) &&
(vaxc$errno == SS$_EXQUOTA ||
vaxc$errno == SS$_EXBYTLM ||
vaxc$errno == RMS$_ACC ||
@@ -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
@@ -1105,7 +1168,7 @@ close_one()
}
if (rp == NULL)
/* surely this is the only reason ??? */
- fatal(_("too many pipes or input files open"));
+ fatal(_("too many pipes or input files open"));
}
/* do_close --- completely close an open file or pipe */
@@ -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,18 +1743,11 @@ 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;
char *ms2;
-
+
first_time = false;
if ((cp = getenv("GAWK_SOCK_RETRIES")) != NULL) {
count = strtoul(cp, & end, 10);
@@ -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)
@@ -1798,7 +1886,7 @@ two_way_open(const char *str, struct redirect *rp)
char c;
int master, dup_master;
int slave;
- int save_errno;
+ int save_errno;
pid_t pid;
struct stat statb;
struct termios st;
@@ -2053,7 +2141,7 @@ use_pipes:
#if defined(__EMX__) || defined(__MINGW32__)
save_stdin = dup(0); /* duplicate stdin */
save_stdout = dup(1); /* duplicate stdout */
-
+
if (save_stdout == -1 || save_stdin == -1) {
/* if an error occurs close all open file handles */
save_errno = errno;
@@ -2066,7 +2154,7 @@ use_pipes:
errno = save_errno;
return false;
}
-
+
/* connect pipes to stdin and stdout */
close(1); /* close stdout */
if (dup(ctop[1]) != 1) { /* connect pipe input to stdout */
@@ -2086,7 +2174,7 @@ use_pipes:
/* none of these handles must be inherited by the child process */
(void) close(ptoc[0]); /* close pipe output, child will use stdin instead */
(void) close(ctop[1]); /* close pipe input, child will use stdout instead */
-
+
os_close_on_exec(ptoc[1], str, "pipe", "from"); /* pipe input: output of the parent process */
os_close_on_exec(ctop[0], str, "pipe", "from"); /* pipe output: input of the parent process */
os_close_on_exec(save_stdin, str, "pipe", "from"); /* saved stdin of the parent process */
@@ -2100,7 +2188,7 @@ use_pipes:
qcmd = quote_cmd(str), NULL);
efree(qcmd);
#endif
-
+
/* restore stdin and stdout */
close(1);
if (dup(save_stdout) != 1) {
@@ -2109,7 +2197,7 @@ use_pipes:
fatal(_("restoring stdout in parent process failed\n"));
}
close(save_stdout);
-
+
close(0);
if (dup(save_stdin) != 0) {
close(save_stdin);
@@ -2135,7 +2223,7 @@ use_pipes:
errno = save_errno;
return false;
}
-
+
if (pid == 0) { /* child */
if (close(1) == -1)
fatal(_("close of stdout in child failed (%s)"),
@@ -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;
}
@@ -2313,10 +2444,10 @@ gawk_popen(const char *cmd, struct redirect *rp)
fatal(_("moving pipe to stdout in child failed (dup: %s)"),
strerror(errno));
}
-
+
/* none of these handles must be inherited by the child process */
close(p[1]); /* close pipe input */
-
+
os_close_on_exec(p[0], cmd, "pipe", "from"); /* pipe output: input of the parent process */
os_close_on_exec(save_stdout, cmd, "pipe", "from"); /* saved stdout of the parent process */
@@ -2327,7 +2458,7 @@ gawk_popen(const char *cmd, struct redirect *rp)
qcmd = quote_cmd(cmd), NULL);
efree(qcmd);
#endif
-
+
/* restore stdout */
close(1);
if (dup(save_stdout) != 1) {
@@ -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)
@@ -2574,8 +2709,8 @@ do_getline(int into_variable, IOBUF *iop)
typedef struct {
const char *envname;
char **dfltp; /* pointer to address of default path */
- char **awkpath; /* array containing library search paths */
- int max_pathlen; /* length of the longest item in awkpath */
+ char **awkpath; /* array containing library search paths */
+ int max_pathlen; /* length of the longest item in awkpath */
} path_info;
static path_info pi_awkpath = {
@@ -2659,7 +2794,7 @@ init_awkpath(path_info *pi)
pi->awkpath[i] = NULL;
}
-/* do_find_source --- search $AWKPATH for file, return NULL if not found */
+/* do_find_source --- search $AWKPATH for file, return NULL if not found */
static char *
do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi)
@@ -2683,7 +2818,7 @@ do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi)
if (pi->awkpath == NULL)
init_awkpath(pi);
- emalloc(path, char *, pi->max_pathlen + strlen(src) + 1, "do_find_source");
+ emalloc(path, char *, pi->max_pathlen + strlen(src) + 1, "do_find_source");
for (i = 0; pi->awkpath[i] != NULL; i++) {
if (strcmp(pi->awkpath[i], "./") == 0 || strcmp(pi->awkpath[i], ".") == 0)
*path = '\0';
@@ -2700,7 +2835,7 @@ do_find_source(const char *src, struct stat *stb, int *errcode, path_info *pi)
return NULL;
}
-/* find_source --- find source file with default file extension handling */
+/* find_source --- find source file with default file extension handling */
char *
find_source(const char *src, struct stat *stb, int *errcode, int is_extlib)
@@ -3085,7 +3220,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;
@@ -3117,10 +3252,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)
@@ -3128,7 +3263,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)
@@ -3168,51 +3303,51 @@ rs1scan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state)
* Subject: Re: multibyte locales: any way to find if a character isn't multibyte?
* Date: Mon, 23 Jun 2003 12:20:16 +0200
* Cc: isamu@yamato.ibm.com
- *
+ *
* Hi,
- *
+ *
* > Is there any way to make the following query to the current locale?
* >
* > Given an 8-bit value, can this value ever appear as part of
* > a multibyte character?
- *
+ *
* There is no simple answer here. The easiest solution I see is to
* get the current locale's codeset (via locale_charset() which is a
* wrapper around nl_langinfo(CODESET)), and then perform a case-by-case
* treatment of the known multibyte encodings, from GB2312 to EUC-JISX0213;
* for the unibyte encodings, a single btowc() call will tell you.
- *
+ *
* > This is particularly critical for me for ASCII newline ('\n'). If I
* > can be guaranteed that it never shows up as part of a multibyte character,
* > I can speed up gawk considerably in mulitbyte locales.
- *
+ *
* This is much simpler to answer!
* In all ASCII based multibyte encodings used for locales today (this
* excludes EBCDIC based doublebyte encodings from IBM, and also excludes
* ISO-2022-JP which is used for email exchange but not as a locale encoding)
* ALL bytes in the range 0x00..0x2F occur only as a single character, not
* as part of a multibyte character.
- *
+ *
* So it's safe to assume, but deserves a comment in the source.
- *
+ *
* Bruno
***************************************************************
* From: Bruno Haible <bruno@clisp.org>
* To: Aharon Robbins <arnold@skeeve.com>
* Subject: Re: multibyte locales: any way to find if a character isn't multibyte?
* Date: Mon, 23 Jun 2003 14:27:49 +0200
- *
+ *
* On Monday 23 June 2003 14:11, you wrote:
- *
+ *
* > if (rs != '\n' && MB_CUR_MAX > 1) {
- *
+ *
* If you assume ASCII, you can even write
- *
+ *
* if (rs >= 0x30 && MB_CUR_MAX > 1) {
- *
+ *
* (this catches also the space character) but if portability to EBCDIC
* systems is desired, your code is fine as is.
- *
+ *
* Bruno
*/
/* Thus, the check for \n here; big speedup ! */
@@ -3460,10 +3595,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
@@ -3507,8 +3677,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;
@@ -3582,6 +3754,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) {
@@ -3694,7 +3868,7 @@ set_RS()
* in case of fatal error in make_regexp.
*/
refree(RS_re_yes_case); /* NULL argument is ok */
- refree(RS_re_no_case);
+ refree(RS_re_no_case);
RS_re_yes_case = RS_re_no_case = RS_regexp = NULL;
if (RS->stlen == 0) {
@@ -3733,17 +3907,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;
}
@@ -3823,9 +3993,9 @@ inetfile(const char *str, struct inet_socket_info *isi)
isi->localport.offset = cp-str;
while (*cp != '/' && *cp != '\0')
cp++;
- /*
+ /*
* Require a port, let them explicitly put 0 if
- * they don't care.
+ * they don't care.
*/
if (*cp != '/' || ((isi->localport.len = (cp-str)-isi->localport.offset) == 0))
return false;
@@ -3834,7 +4004,7 @@ inetfile(const char *str, struct inet_socket_info *isi)
cp++;
isi->remotehost.offset = cp-str;
while (*cp != '/' && *cp != '\0')
- cp++;
+ cp++;
if (*cp != '/' || ((isi->remotehost.len = (cp-str)-isi->remotehost.offset) == 0))
return false;
@@ -3850,7 +4020,7 @@ inetfile(const char *str, struct inet_socket_info *isi)
*/
isi->remoteport.offset = cp-str;
while (*cp != '/' && *cp != '\0')
- cp++;
+ cp++;
if (*cp != '\0' || ((isi->remoteport.len = (cp-str)-isi->remoteport.offset) == 0))
return false;
@@ -3866,22 +4036,31 @@ inetfile(const char *str, struct inet_socket_info *isi)
/*
* in_PROCINFO --- return value for a PROCINFO element with
* SUBSEP seperated indices.
- */
+ */
static NODE *
in_PROCINFO(const char *pidx1, const char *pidx2, NODE **full_idx)
{
char *str;
size_t str_len;
- NODE *r, *sub = NULL;
+ 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);
@@ -3895,8 +4074,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/localeinfo.c b/localeinfo.c
new file mode 100644
index 00000000..ca96afc7
--- /dev/null
+++ b/localeinfo.c
@@ -0,0 +1,113 @@
+/* locale information
+
+ Copyright 2016 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include <localeinfo.h>
+
+#include <verify.h>
+
+#include <limits.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wctype.h>
+
+/* The sbclen implementation relies on this. */
+verify (MB_LEN_MAX <= SCHAR_MAX);
+
+/* Return true if the locale uses UTF-8. */
+
+static bool
+is_using_utf8 (void)
+{
+ wchar_t wc;
+ mbstate_t mbs = {0};
+ return mbrtowc (&wc, "\xc4\x80", 2, &mbs) == 2 && wc == 0x100;
+}
+
+/* Initialize *LOCALEINFO from the current locale. */
+
+void
+init_localeinfo (struct localeinfo *localeinfo)
+{
+ int i;
+
+ localeinfo->multibyte = MB_CUR_MAX > 1;
+ localeinfo->using_utf8 = is_using_utf8 ();
+
+ for (i = CHAR_MIN; i <= CHAR_MAX; i++)
+ {
+ char c = i;
+ unsigned char uc = i;
+ mbstate_t s = {0};
+ wchar_t wc;
+ size_t len = mbrtowc (&wc, &c, 1, &s);
+ localeinfo->sbclen[uc] = len <= 1 ? 1 : - (int) - len;
+ localeinfo->sbctowc[uc] = len <= 1 ? wc : WEOF;
+ }
+}
+
+/* The set of wchar_t values C such that there's a useful locale
+ somewhere where C != towupper (C) && C != towlower (towupper (C)).
+ For example, 0x00B5 (U+00B5 MICRO SIGN) is in this table, because
+ towupper (0x00B5) == 0x039C (U+039C GREEK CAPITAL LETTER MU), and
+ towlower (0x039C) == 0x03BC (U+03BC GREEK SMALL LETTER MU). */
+static short const lonesome_lower[] =
+ {
+ 0x00B5, 0x0131, 0x017F, 0x01C5, 0x01C8, 0x01CB, 0x01F2, 0x0345,
+ 0x03C2, 0x03D0, 0x03D1, 0x03D5, 0x03D6, 0x03F0, 0x03F1,
+
+ /* U+03F2 GREEK LUNATE SIGMA SYMBOL lacks a specific uppercase
+ counterpart in locales predating Unicode 4.0.0 (April 2003). */
+ 0x03F2,
+
+ 0x03F5, 0x1E9B, 0x1FBE,
+ };
+
+/* Verify that the worst case fits. This is 1 for towupper, 1 for
+ towlower, and 1 for each entry in LONESOME_LOWER. */
+verify (1 + 1 + sizeof lonesome_lower / sizeof *lonesome_lower
+ <= CASE_FOLDED_BUFSIZE);
+
+/* Find the characters equal to C after case-folding, other than C
+ itself, and store them into FOLDED. Return the number of characters
+ stored. */
+
+int
+case_folded_counterparts (wchar_t c, wchar_t folded[CASE_FOLDED_BUFSIZE])
+{
+ int i;
+ int n = 0;
+ wint_t uc = towupper (c);
+ wint_t lc = towlower (uc);
+ if (uc != c)
+ folded[n++] = uc;
+ if (lc != uc && lc != c && towupper (lc) == uc)
+ folded[n++] = lc;
+ for (i = 0; i < sizeof lonesome_lower / sizeof *lonesome_lower; i++)
+ {
+ wint_t li = lonesome_lower[i];
+ if (li != lc && li != uc && li != c && towupper (li) == uc)
+ folded[n++] = li;
+ }
+ return n;
+}
diff --git a/localeinfo.h b/localeinfo.h
new file mode 100644
index 00000000..cf2f9a69
--- /dev/null
+++ b/localeinfo.h
@@ -0,0 +1,54 @@
+/* locale information
+
+ Copyright 2016 Free Software Foundation, Inc.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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. */
+
+/* Written by Paul Eggert. */
+
+#include <limits.h>
+#include <stdbool.h>
+#include <wchar.h>
+
+struct localeinfo
+{
+ /* MB_CUR_MAX > 1. */
+ bool multibyte;
+
+ /* The locale uses UTF-8. */
+ bool using_utf8;
+
+ /* An array indexed by byte values B that contains 1 if B is a
+ single-byte character, -1 if B is an encoding error, and -2 if B
+ is the leading byte of a multibyte character that contains more
+ than one byte. */
+ signed char sbclen[UCHAR_MAX + 1];
+
+ /* An array indexed by byte values B that contains the corresponding
+ wide character (if any) for B if sbclen[B] == 1. WEOF means the
+ byte is not a valid single-byte character, i.e., sbclen[B] == -1
+ or -2. */
+ wint_t sbctowc[UCHAR_MAX + 1];
+};
+
+extern void init_localeinfo (struct localeinfo *);
+
+/* Maximum number of characters that can be the case-folded
+ counterparts of a single character, not counting the character
+ itself. This is a generous upper bound. */
+enum { CASE_FOLDED_BUFSIZE = 32 };
+
+extern int case_folded_counterparts (wchar_t, wchar_t[CASE_FOLDED_BUFSIZE]);
diff --git a/m4/ChangeLog b/m4/ChangeLog
index e801ddc9..d3a23cc3 100644
--- a/m4/ChangeLog
+++ b/m4/ChangeLog
@@ -12,6 +12,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
@@ -51,6 +59,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.
diff --git a/m4/arch.m4 b/m4/arch.m4
index 441602cd..70cee013 100644
--- a/m4/arch.m4
+++ b/m4/arch.m4
@@ -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"])
- ]
-)
diff --git a/main.c b/main.c
index be210036..7da650bd 100644
--- a/main.c
+++ b/main.c
@@ -1,23 +1,23 @@
/*
- * main.c -- Code generator and main program for gawk.
+ * main.c -- Code generator and main program for gawk.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2016 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
@@ -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();
@@ -368,7 +357,7 @@ main(int argc, char **argv)
init_debug();
#ifdef HAVE_MPFR
- /* Set up MPFR defaults, and register pre-exec hook to process arithmetic opcodes */
+ /* Set up MPFR defaults, and register pre-exec hook to process arithmetic opcodes */
if (do_mpfr)
init_mpfr(DEFAULT_PREC, DEFAULT_ROUNDMODE);
#endif
@@ -469,7 +458,7 @@ main(int argc, char **argv)
/* Read in the program */
if (parse_program(& code_block) != 0)
exit(EXIT_FAILURE);
-
+
if (do_intl)
exit(EXIT_SUCCESS);
@@ -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);
@@ -532,7 +520,7 @@ main(int argc, char **argv)
if (do_tidy_mem)
release_all_vars();
-
+
/* keep valgrind happier */
if (extra_stack)
efree(extra_stack);
@@ -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);
@@ -674,7 +663,7 @@ GNU General Public License for more details.\n\
static const char blurb_part3[] =
N_("You should have received a copy of the GNU General Public License\n\
along with this program. If not, see http://www.gnu.org/licenses/.\n");
-
+
/* multiple blurbs are needed for some brain dead compilers. */
printf(_(blurb_part1), UPDATE_YEAR); /* Last update year */
fputs(_(blurb_part2), stdout);
@@ -785,7 +774,7 @@ static const struct varinit varinit[] = {
{&FPAT_node, "FPAT", "[^[:space:]]+", 0, NULL, set_FPAT, false, NON_STANDARD },
{&IGNORECASE_node, "IGNORECASE", NULL, 0, NULL, set_IGNORECASE, false, NON_STANDARD },
{&LINT_node, "LINT", NULL, 0, NULL, set_LINT, false, NON_STANDARD },
-{&PREC_node, "PREC", NULL, DEFAULT_PREC, NULL, set_PREC, false, NON_STANDARD},
+{&PREC_node, "PREC", NULL, DEFAULT_PREC, NULL, set_PREC, false, NON_STANDARD},
{&NF_node, "NF", NULL, -1, update_NF, set_NF, false, 0 },
{&NR_node, "NR", NULL, 0, update_NR, set_NR, true, 0 },
{&OFMT_node, "OFMT", "%.6g", 0, NULL, set_OFMT, true, 0 },
@@ -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;
}
@@ -1132,7 +1153,7 @@ arg_assign(char *arg, bool initing)
if (! initing) {
var = lookup(arg);
if (var != NULL && var->type == Node_func)
- fatal(_("cannot use function `%s' as variable name"), arg);
+ fatal(_("cannot use function `%s' as variable name"), arg);
}
/*
@@ -1183,7 +1204,7 @@ arg_assign(char *arg, bool initing)
/* catchsig --- catch signals */
-static RETSIGTYPE
+static void
catchsig(int sig)
{
if (sig == SIGFPE) {
@@ -1254,7 +1275,7 @@ version()
#ifdef HAVE_MPFR
printf(" (GNU MPFR %s, GNU MP %s)", mpfr_get_version(), gmp_version);
#endif
- printf("\n");
+ printf("\n");
print_ext_versions();
/*
@@ -1337,7 +1358,7 @@ estrdup(const char *str, size_t len)
s[len] = '\0';
return s;
}
-
+
#if defined(HAVE_LOCALE_H)
/* init_locale --- initialize locale info. */
@@ -1407,7 +1428,7 @@ long
getenv_long(const char *name)
{
const char *val;
- long newval;
+ long newval;
if ((val = getenv(name)) != NULL && isdigit((unsigned char) *val)) {
for (newval = 0; *val && isdigit((unsigned char) *val); val++)
newval = (newval * 10) + *val - '0';
@@ -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;
@@ -1433,7 +1454,7 @@ parse_args(int argc, char **argv)
/* we do error messages ourselves on invalid options */
opterr = false;
- /* copy argv before getopt gets to it; used to restart the debugger */
+ /* copy argv before getopt gets to it; used to restart the debugger */
save_argv(argc, argv);
/* option processing. ready, set, go! */
@@ -1583,7 +1604,11 @@ parse_args(int argc, char **argv)
case 'r':
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/mbsupport.h b/mbsupport.h
index 37dd219d..e7b40423 100644
--- a/mbsupport.h
+++ b/mbsupport.h
@@ -2,23 +2,23 @@
* mbsupport.h --- Localize determination of whether we have multibyte stuff.
*/
-/*
+/*
* Copyright (C) 2004, 2005, 2011, 2012, 2015, 2016
* 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
diff --git a/missing_d/ChangeLog b/missing_d/ChangeLog
index 19d57042..83f5b93e 100644
--- a/missing_d/ChangeLog
+++ b/missing_d/ChangeLog
@@ -1,3 +1,7 @@
+2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * General: Remove trailing whitespace from all relevant files.
+
2016-09-07 Arnold D. Robbins <arnold@skeeve.com>
* setenv.c: Update license text in setenv.c. Thanks
@@ -16,6 +20,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);
diff --git a/missing_d/snprintf.c b/missing_d/snprintf.c
index 6cee2bed..9d692d5a 100644
--- a/missing_d/snprintf.c
+++ b/missing_d/snprintf.c
@@ -2,22 +2,22 @@
* snprintf.c - Implement snprintf and vsnprintf on platforms that need them.
*/
-/*
+/*
* Copyright (C) 2006, 2007 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
diff --git a/mpfr.c b/mpfr.c
index db2eb697..cdcc9bb2 100644
--- a/mpfr.c
+++ b/mpfr.c
@@ -2,22 +2,22 @@
* mpfr.c - routines for arbitrary-precision number support in gawk.
*/
-/*
+/*
* Copyright (C) 2012, 2013, 2015 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
@@ -118,7 +118,7 @@ mpg_node(unsigned int tp)
mpz_init(r->mpg_i);
r->flags = MPZN;
}
-
+
r->valref = 1;
r->flags |= MALLOC|NUMBER|NUMCUR;
r->stptr = NULL;
@@ -151,7 +151,7 @@ mpg_make_number(double x)
return r;
}
-/* mpg_strtoui --- assign arbitrary-precision integral value from a string */
+/* mpg_strtoui --- assign arbitrary-precision integral value from a string */
int
mpg_strtoui(mpz_ptr zi, char *str, size_t len, char **end, int base)
@@ -264,7 +264,7 @@ mpg_zero(NODE *n)
n->flags &= ~MPFN;
}
if (! is_mpg_integer(n)) {
- mpz_init(n->mpg_i); /* this also sets its value to 0 */
+ mpz_init(n->mpg_i); /* this also sets its value to 0 */
n->flags |= MPZN;
} else
mpz_set_si(n->mpg_i, 0);
@@ -329,13 +329,13 @@ 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)
return true;
errno = 0;
- return false;
+ return false;
}
/* mpg_force_number --- force a value to be a multiple-precision number */
@@ -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);
@@ -387,7 +384,7 @@ mpg_format_val(const char *format, int index, NODE *s)
efree(s->stptr);
s->stptr = r->stptr;
freenode(r); /* Do not unref(r)! We want to keep s->stptr == r->stpr. */
-
+
s->flags |= STRCUR;
free_wstr(s);
return s;
@@ -430,8 +427,8 @@ mpg_cmp(const NODE *t1, const NODE *t2)
/*
- * mpg_update_var --- update NR or FNR.
- * NR_node->var_value(mpz_t) = MNR(mpz_t) * LONG_MAX + NR(long)
+ * mpg_update_var --- update NR or FNR.
+ * NR_node->var_value(mpz_t) = MNR(mpz_t) * LONG_MAX + NR(long)
*/
NODE *
@@ -485,7 +482,7 @@ mpg_set_var(NODE *n)
if (is_mpg_integer(val))
r = val->mpg_i;
else {
- /* convert float to integer */
+ /* convert float to integer */
mpfr_get_z(mpzval, val->mpg_numbr, MPFR_RNDZ);
r = mpzval;
}
@@ -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 */
@@ -553,7 +548,7 @@ set_PREC()
if (prec <= 0) {
force_number(val);
- prec = get_number_si(val);
+ prec = get_number_si(val);
if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) {
force_string(val);
warning(_("PREC value `%.*s' is invalid"), (int) val->stlen, val->stptr);
@@ -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);
@@ -688,7 +683,7 @@ do_mpfr_atan2(int nargs)
p1 = MP_FLOAT(t1);
p2 = MP_FLOAT(t2);
res = mpg_float();
- /* See MPFR documentation for handling of special values like +inf as an argument */
+ /* See MPFR documentation for handling of special values like +inf as an argument */
tval = mpfr_atan2(res->mpg_numbr, p1, p2, ROUND_MODE);
IEEE_FMT(res->mpg_numbr, tval);
@@ -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);
@@ -818,28 +813,26 @@ do_mpfr_compl(int nargs)
/* [+-]inf or NaN */
return tmp;
}
- if (do_lint) {
- if (mpfr_sgn(p) < 0)
- lintwarn("%s",
- mpg_fmt(_("compl(%Rg): negative value will give strange results"), p)
+ if (mpfr_sgn(p) < 0)
+ fatal("%s",
+ mpg_fmt(_("compl(%Rg): negative value is not allowed"), p)
);
+ if (do_lint) {
if (! mpfr_integer_p(p))
lintwarn("%s",
mpg_fmt(_("comp(%Rg): fractional value will be truncated"), p)
);
}
-
+
mpfr_get_z(mpzval, p, MPFR_RNDZ); /* float to integer conversion */
zptr = mpzval;
} else {
- /* (tmp->flags & MPZN) != 0 */
+ /* (tmp->flags & MPZN) != 0 */
zptr = tmp->mpg_i;
- if (do_lint) {
- if (mpz_sgn(zptr) < 0)
- lintwarn("%s",
- mpg_fmt(_("cmpl(%Zd): negative values will give strange results"), zptr)
+ if (mpz_sgn(zptr) < 0)
+ fatal("%s",
+ mpg_fmt(_("compl(%Zd): negative values is not allowed"), zptr)
);
- }
}
r = mpg_integer();
@@ -855,7 +848,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);
@@ -875,13 +868,13 @@ get_intval(NODE *t1, int argnum, const char *op)
return pz; /* should be freed */
}
- if (do_lint) {
- if (mpfr_sgn(left) < 0)
- lintwarn("%s",
- mpg_fmt(_("%s: argument #%d negative value %Rg will give strange results"),
+ if (mpfr_sgn(left) < 0)
+ fatal("%s",
+ mpg_fmt(_("%s: argument #%d negative value %Rg is not allowed"),
op, argnum, left)
);
+ if (do_lint) {
if (! mpfr_integer_p(left))
lintwarn("%s",
mpg_fmt(_("%s: argument #%d fractional value %Rg will be truncated"),
@@ -893,16 +886,15 @@ get_intval(NODE *t1, int argnum, const char *op)
mpz_init(pz);
mpfr_get_z(pz, left, MPFR_RNDZ); /* float to integer conversion */
return pz; /* should be freed */
- }
- /* (t1->flags & MPZN) != 0 */
+ }
+ /* (t1->flags & MPZN) != 0 */
pz = t1->mpg_i;
- if (do_lint) {
- if (mpz_sgn(pz) < 0)
- lintwarn("%s",
- mpg_fmt(_("%s: argument #%d negative value %Zd will give strange results"),
+ if (mpz_sgn(pz) < 0)
+ fatal("%s",
+ mpg_fmt(_("%s: argument #%d negative value %Zd is not allowed"),
op, argnum, pz)
);
- }
+
return pz; /* must not be freed */
}
@@ -927,7 +919,7 @@ do_mpfr_lshift(int nargs)
NODE *t1, *t2, *res;
unsigned long shift;
mpz_ptr pz1, pz2;
-
+
t2 = POP_SCALAR();
t1 = POP_SCALAR();
@@ -959,7 +951,7 @@ do_mpfr_rshift(int nargs)
NODE *t1, *t2, *res;
unsigned long shift;
mpz_ptr pz1, pz2;
-
+
t2 = POP_SCALAR();
t1 = POP_SCALAR();
@@ -969,7 +961,7 @@ do_mpfr_rshift(int nargs)
/* N.B: See do_mpfp_lshift. */
shift = mpz_get_ui(pz2); /* GMP integer => unsigned long conversion */
res = mpg_integer();
- mpz_fdiv_q_2exp(res->mpg_i, pz1, shift); /* res = pz1 / 2^shift, round towards −inf */
+ mpz_fdiv_q_2exp(res->mpg_i, pz1, shift); /* res = pz1 / 2^shift, round towards -inf */
free_intval(t1, pz1);
free_intval(t2, pz2);
@@ -1080,25 +1072,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 +1165,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 +1179,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
@@ -1204,13 +1282,13 @@ mpg_tofloat(mpfr_ptr mf, mpz_ptr mz)
/*
* When implicitely converting a GMP integer operand to a MPFR float, use
* a precision sufficiently large to hold the converted value exactly.
- *
+ *
* $ ./gawk -M 'BEGIN { print 13 % 2 }'
* 1
* If the user-specified precision is used to convert the integer 13 to a
* float, one will get:
* $ ./gawk -M 'BEGIN { PREC=2; print 13 % 2.0 }'
- * 0
+ * 0
*/
prec = mpz_sizeinbase(mz, 2); /* most significant 1 bit position starting at 1 */
@@ -1224,7 +1302,7 @@ mpg_tofloat(mpfr_ptr mf, mpz_ptr mz)
else
prec = PRECISION_MIN;
/*
- * Always set the precision to avoid hysteresis, since do_mpfr_func
+ * Always set the precision to avoid hysteresis, since do_mpfr_func
* may copy our precision.
*/
if (prec != mpfr_get_prec(mf))
@@ -1235,7 +1313,7 @@ mpg_tofloat(mpfr_ptr mf, mpz_ptr mz)
}
-/* mpg_add --- add arbitrary-precision numbers */
+/* mpg_add --- add arbitrary-precision numbers */
static NODE *
mpg_add(NODE *t1, NODE *t2)
@@ -1318,7 +1396,7 @@ mpg_mul(NODE *t1, NODE *t2)
}
-/* mpg_pow --- exponentiation involving arbitrary-precision numbers */
+/* mpg_pow --- exponentiation involving arbitrary-precision numbers */
static NODE *
mpg_pow(NODE *t1, NODE *t2)
@@ -1417,11 +1495,11 @@ mpg_mod(NODE *t1, NODE *t2)
}
return r;
}
-
+
/*
* mpg_interpret --- pre-exec hook in the interpreter. Handles
* arithmetic operations with MPFR/GMP numbers.
- */
+ */
static int
mpg_interpret(INSTRUCTION **cp)
@@ -1502,7 +1580,7 @@ quotient:
if (op == Op_quotient)
DEREF(t2);
REPLACE(r);
- break;
+ break;
case Op_mod_i:
t2 = force_number(pc->memory);
diff --git a/msg.c b/msg.c
index 16fef73a..ffca3355 100644
--- a/msg.c
+++ b/msg.c
@@ -2,23 +2,23 @@
* msg.c - routines for error messages.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2001, 2003, 2010-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 2, 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
diff --git a/node.c b/node.c
index b63017aa..fa73c1a4 100644
--- a/node.c
+++ b/node.c
@@ -2,23 +2,23 @@
* node.c -- routines for node management
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2001, 2003-2015,
* 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
@@ -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,15 +152,28 @@ 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;
}
/*
* The following lookup table is used as an optimization in force_string;
- * (more complicated) variations on this theme didn't seem to pay off, but
+ * (more complicated) variations on this theme didn't seem to pay off, but
* systematic testing might be in order at some point.
*/
static const char *values[] = {
@@ -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,18 +312,18 @@ 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;
}
}
-
+
return r;
}
@@ -386,18 +383,18 @@ 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';
-
+
if ((flags & SCAN) != 0) { /* scan for escape sequences */
const char *pf;
char *ptm;
@@ -481,16 +478,16 @@ r_unref(NODE *tmp)
*
* Parse a C escape sequence. STRING_PTR points to a variable containing a
* pointer to the string to parse. That pointer is updated past the
- * characters we use. The value of the escape sequence is returned.
+ * characters we use. The value of the escape sequence is returned.
*
* A negative value means the sequence \ newline was seen, which is supposed to
- * be equivalent to nothing at all.
+ * be equivalent to nothing at all.
*
* If \ is followed by a null character, we return a negative value and leave
- * the string pointer pointing at the null character.
+ * the string pointer pointing at the null character.
*
* If \ is followed by 000, we return 0 and leave the string pointer after the
- * zeros. A value of 0 does not mean end of string.
+ * zeros. A value of 0 does not mean end of string.
*
* POSIX doesn't allow \x.
*/
@@ -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;
/*
@@ -756,7 +752,7 @@ str2wstr(NODE *n, size_t **ptr)
* stopping early. This is particularly important
* for match() where we need to build the indices.
*/
- if (dfa_using_utf8()) {
+ if (using_utf8()) {
count = 1;
wc = 0xFFFD; /* unicode replacement character */
goto set_wc;
@@ -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) {
@@ -981,7 +981,7 @@ void init_btowc_cache()
#define BLOCKCHUNK 100
BLOCK nextfree[BLOCK_MAX] = {
- { 0, NULL}, /* invalid */
+ { 0, NULL}, /* invalid */
{ sizeof(NODE), NULL },
{ sizeof(BUCKET), NULL },
};
diff --git a/nonposix.h b/nonposix.h
index b3497891..cbc4f499 100644
--- a/nonposix.h
+++ b/nonposix.h
@@ -2,22 +2,22 @@
* nonposix.h --- definitions needed on non-POSIX systems.
*/
-/*
+/*
* Copyright (C) 2012, 2013, 2016 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
diff --git a/old-extension/ChangeLog b/old-extension/ChangeLog
index 34da558f..bd848f9a 100644
--- a/old-extension/ChangeLog
+++ b/old-extension/ChangeLog
@@ -1,3 +1,16 @@
+2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * General: Remove trailing whitespace from all relevant files.
+
+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..1a0104db 100644
--- a/old-extension/bindarr.c
+++ b/old-extension/bindarr.c
@@ -3,22 +3,22 @@
* to array and array elements.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2011 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
@@ -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();
@@ -286,7 +286,7 @@ do_unbind_array(int nargs)
*symbol = *xn;
freenode(xn);
- return make_number(0);
+ return make_number(0);
}
diff --git a/old-extension/fileop.c b/old-extension/fileop.c
index 86f62576..97a51c81 100644
--- a/old-extension/fileop.c
+++ b/old-extension/fileop.c
@@ -5,20 +5,20 @@
/*
* Copyright (C) 2012 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
@@ -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);
@@ -379,7 +379,7 @@ dlload(NODE *tree, void *dl)
}
-/* dlunload --- routine called when exiting */
+/* dlunload --- routine called when exiting */
void
dlunload()
diff --git a/old-extension/sparr.c b/old-extension/sparr.c
index a3d06e66..1e8642dd 100644
--- a/old-extension/sparr.c
+++ b/old-extension/sparr.c
@@ -5,20 +5,20 @@
/*
* Copyright (C) 2012 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
@@ -75,7 +75,7 @@ static void
store_SYS(NODE *symbol, NODE *subs, NODE *val, void *data)
{
sdata_t *sd = (sdata_t *) data;
-
+
if (subs != NULL && val != NULL && val->type == Node_val) {
force_string(subs);
if (strcmp(subs->stptr, "readline") == 0) {
@@ -98,7 +98,7 @@ load_READLINE(NODE *symbol, void *data)
int i;
bool long_line = false;
- if (! sd->load_file) /* non-existent SYS["readline"] or already loaded */
+ if (! sd->load_file) /* non-existent SYS["readline"] or already loaded */
return;
file = sd->filename;
@@ -145,7 +145,7 @@ load_READLINE(NODE *symbol, void *data)
}
fclose(fp);
sd->load_file = false; /* don't load this file again */
-}
+}
/* dlload --- load this library */
diff --git a/old-extension/spec_array.c b/old-extension/spec_array.c
index 34d15fc5..f933aa35 100644
--- a/old-extension/spec_array.c
+++ b/old-extension/spec_array.c
@@ -4,20 +4,20 @@
/*
* Copyright (C) 2012, 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
@@ -52,7 +52,7 @@ typedef struct spec_array {
* void load_func(NODE *array, void *data)
*
* Use register_deferred_array(array, load_func, void *data) to
- * bind an array to the load routine.
+ * bind an array to the load routine.
*/
static NODE **deferred_array_init(NODE *, NODE *);
@@ -72,7 +72,7 @@ static afunc_t deferred_array_func[] = {
deferred_array_exists,
deferred_array_clear,
deferred_array_remove,
- deferred_array_list,
+ deferred_array_list,
deferred_array_copy,
null_afunc, /* dump */
(afunc_t) 0, /* store */
@@ -86,7 +86,7 @@ deferred_array_init(NODE *symbol, NODE *subs)
{
if (symbol != NULL) {
array_t *av = (array_t *) symbol->xarray;
- symbol->xarray = NULL; /* this is to avoid an assertion failure in null_array */
+ symbol->xarray = NULL; /* this is to avoid an assertion failure in null_array */
null_array(symbol); /* typeless empty array */
if (symbol->parent_array == NULL) {
/* main array */
@@ -141,7 +141,7 @@ static NODE **
deferred_array_remove(NODE *symbol, NODE *subs)
{
array_t *av = (array_t *) symbol->xarray;
-
+
(void) SUPER(aremove)(symbol, subs);
if (av) {
symbol->xarray = NULL;
@@ -157,7 +157,7 @@ static NODE **
deferred_array_clear(NODE *symbol, NODE *subs)
{
array_t *av = (array_t *) symbol->xarray;
-
+
(void) SUPER(aclear)(symbol, subs);
if (av) {
symbol->xarray = NULL;
@@ -181,7 +181,7 @@ deferred_array_clear(NODE *symbol, NODE *subs)
* The store routine must take an additional argument for the
* value. The value can be NULL if the specific element is
* removed from the array. The subscript (and the value) is NULL
- * when the entire array is deleted.
+ * when the entire array is deleted.
*
* void store_func(NODE *array, NODE *subs, NODE *value, void *data)
*
@@ -207,7 +207,7 @@ static afunc_t dyn_array_func[] = {
dyn_array_exists,
dyn_array_clear,
dyn_array_remove,
- dyn_array_list,
+ dyn_array_list,
dyn_array_copy,
null_afunc, /* dump */
dyn_array_store,
diff --git a/pc/ChangeLog b/pc/ChangeLog
index 1ff3bb1f..49ce73fa 100644
--- a/pc/ChangeLog
+++ b/pc/ChangeLog
@@ -3,6 +3,10 @@
* gawkmisc.pc (w32_maybe_set_errno) [__MINGW32__]: New function,
to correct errno when it is not set to a useful value.
+2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * General: Remove trailing whitespace from all relevant files.
+
2016-09-24 Eli Zaretskii <eliz@gnu.org>
Fix compilation warnings on MinGW with the latest runtime.
@@ -97,6 +101,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 d584973a..11323793 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.4"
+#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.4"
+#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.4"
+#define VERSION "4.1.60"
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
diff --git a/pc/popen.c b/pc/popen.c
index 73770d98..425d32b9 100644
--- a/pc/popen.c
+++ b/pc/popen.c
@@ -104,7 +104,7 @@ scriptify(const char *command)
free(cmd);
cmd = NULL;
}
- if (fp) fclose(fp);
+ if (fp) fclose(fp);
return(cmd);
}
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})
diff --git a/posix/ChangeLog b/posix/ChangeLog
index c5ce0340..cd1a2f68 100644
--- a/posix/ChangeLog
+++ b/posix/ChangeLog
@@ -1,3 +1,7 @@
+2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * General: Remove trailing whitespace from all relevant files.
+
2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
* 4.1.4: Release tar ball made.
diff --git a/posix/gawkmisc.c b/posix/gawkmisc.c
index d422bd0f..40950826 100644
--- a/posix/gawkmisc.c
+++ b/posix/gawkmisc.c
@@ -1,5 +1,5 @@
/* gawkmisc.c --- miscellaneous gawk routines that are OS specific.
-
+
Copyright (C) 1986, 1988, 1989, 1991 - 1998, 2001 - 2004, 2011
the Free Software Foundation, Inc.
@@ -40,7 +40,7 @@ char *
gawk_name(const char *filespec)
{
char *p;
-
+
/* "path/name" -> "name" */
p = strrchr(filespec, '/');
return (p == NULL ? (char *) filespec : p + 1);
@@ -272,7 +272,7 @@ os_isatty(int fd)
{
return isatty(fd);
}
-
+
/* files_are_same --- return true if files are identical */
int
diff --git a/profile.c b/profile.c
index 39c4f03d..80f68607 100644
--- a/profile.c
+++ b/profile.c
@@ -2,22 +2,22 @@
* profile.c - gawk bytecode pretty-printer with counts
*/
-/*
+/*
* Copyright (C) 1999-2016 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
@@ -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:
@@ -300,7 +347,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, int flags)
cant_happen();
}
- switch (pc->opcode) {
+ switch (pc->opcode) {
case Op_store_var:
t2 = pp_pop(); /* l.h.s. */
t1 = pp_pop(); /* r.h.s. */
@@ -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:
@@ -343,7 +390,7 @@ cleanup:
efree(tmp);
pp_free(t1);
pp_push(pc->opcode, str, CAN_FREE);
- break;
+ break;
case Op_and:
case Op_or:
@@ -416,10 +463,13 @@ cleanup:
case Op_field_spec:
case Op_field_spec_lhs:
case Op_unary_minus:
+ case Op_unary_plus:
case Op_not:
t1 = pp_pop();
if (is_binary(t1->type)
- || (((OPCODE) t1->type) == pc->opcode && pc->opcode == Op_unary_minus))
+ || (((OPCODE) t1->type) == pc->opcode
+ && (pc->opcode == Op_unary_minus
+ || pc->opcode == Op_unary_plus)))
pp_parenthesize(t1);
/* optypes table (eval.c) includes space after ! */
@@ -452,8 +502,8 @@ cleanup:
pp_free(t2);
pp_free(t1);
if ((flags & IN_FOR_HEADER) == 0)
- fprintf(prof_fp, "\n");
- break;
+ pc = end_line(pc);
+ break;
case Op_concat:
str = pp_concat(pc->expr_count);
@@ -470,10 +520,10 @@ cleanup:
sub = pp_list(pc->expr_count, NULL, pc->expr_count > 1 ? "][" : ", ");
fprintf(prof_fp, "%s %s[%s]", op2str(Op_K_delete), array, sub);
efree(sub);
- } else
+ } 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;
@@ -482,7 +532,7 @@ cleanup:
/* Efficency hack not in effect because of exec_count instruction */
cant_happen();
break;
-
+
case Op_in_array:
{
char *array, *sub;
@@ -511,7 +561,7 @@ cleanup:
case Op_field_assign:
case Op_subscript_assign:
case Op_arrayfor_init:
- case Op_arrayfor_incr:
+ case Op_arrayfor_incr:
case Op_arrayfor_final:
case Op_newfile:
case Op_get_record:
@@ -572,7 +622,7 @@ cleanup:
else {
tmp = pp_list(pc->expr_count, " ", ", ");
tmp[strlen(tmp) - 1] = '\0'; /* remove trailing space */
- }
+ }
if (pc->redir_type != 0) {
t1 = pp_pop();
@@ -585,13 +635,13 @@ cleanup:
fprintf(prof_fp, "%s%s", op2str(pc->opcode), tmp);
efree(tmp);
if ((flags & IN_FOR_HEADER) == 0)
- fprintf(prof_fp, "\n");
+ pc = end_line(pc);
break;
case Op_push_re:
if (pc->memory->type != Node_regex)
break;
- /* else
+ /* else
fall through */
case Op_match_rec:
{
@@ -666,7 +716,7 @@ cleanup:
if (pc->opcode == Op_indirect_func_call)
pre = "@";
else
- pre = "";
+ pre = "";
pcount = (pc + 1)->expr_count;
if (pcount > 0) {
tmp = pp_list(pcount, "()", ", ");
@@ -686,7 +736,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 +745,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 +756,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);
- fprintf(prof_fp, "%s (", op2str(pc->opcode));
+ 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 +835,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 +853,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 +896,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 +915,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 +959,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,13 +984,13 @@ 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);
+ pprint(pc->nexti, pc->branch_end, NO_PPRINT_FLAGS);
f = pp_pop();
t = pp_pop();
@@ -923,13 +1006,20 @@ cleanup:
pp_push(Op_cond_exp, str, CAN_FREE);
pc = pc->branch_end;
}
- break;
+ break;
case Op_exec_count:
if (flags == NO_PPRINT_FLAGS)
indent(pc->exec_count);
break;
+ case Op_comment:
+ print_comment(pc, 0);
+ break;
+
+ case Op_list:
+ break;
+
default:
cant_happen();
}
@@ -939,6 +1029,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 +1079,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 +1093,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 +1121,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 +1160,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);
}
@@ -1066,6 +1201,7 @@ prec_level(int type)
return 13;
case Op_unary_minus:
+ case Op_unary_plus:
case Op_not:
return 12;
@@ -1152,6 +1288,7 @@ is_scalar(int type)
case Op_postincrement:
case Op_postdecrement:
case Op_unary_minus:
+ case Op_unary_plus:
case Op_not:
return true;
@@ -1265,11 +1402,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 +1447,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 +1460,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 +1472,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;
@@ -1350,45 +1496,12 @@ pp_string(const char *in_str, size_t len, int delim)
char *
pp_number(NODE *n)
{
-#define PP_PRECISION 6
char *str;
-#ifdef HAVE_MPFR
- size_t count;
-
- if (is_mpg_float(n)) {
- count = mpfr_get_prec(n->mpg_numbr) / 3; /* ~ 3.22 binary digits per decimal digit */
- emalloc(str, char *, count, "pp_number");
- /*
- * 3/2015: Format string used to be "%0.*R*g". That padded
- * with leading zeros. But it doesn't do that for regular
- * numbers in the non-MPFR case.
- */
- mpfr_sprintf(str, "%.*R*g", PP_PRECISION, ROUND_MODE, n->mpg_numbr);
- } else if (is_mpg_integer(n)) {
- count = mpz_sizeinbase(n->mpg_i, 10) + 2; /* +1 for sign, +1 for NUL at end */
- emalloc(str, char *, count, "pp_number");
- mpfr_sprintf(str, "%Zd", n->mpg_i);
- } else
-#endif
- {
- /* Use format_val() to get integral values printed as integers */
- NODE *s;
-
- getnode(s);
- *s = *n;
- s->flags &= ~STRCUR;
-
- s = r_format_val("%.6g", 0, s);
-
- s->stptr[s->stlen] = '\0';
- str = s->stptr;
-
- freenode(s);
- }
-
+ assert((n->flags & NUMCONSTSTR) != 0);
+ emalloc(str, char *, n->stlen + 1, "pp_number");
+ strcpy(str, n->stptr);
return str;
-#undef PP_PRECISION
}
/* pp_node --- pretty format a node */
@@ -1441,7 +1554,7 @@ pp_list(int nargs, const char *paren, const char *delim)
emalloc(str, char *, len + 1, "pp_list");
s = str;
if (paren != NULL)
- *s++ = paren[0];
+ *s++ = paren[0];
if (nargs > 0) {
r = pp_args[nargs];
memcpy(s, r->pp_str, r->pp_len);
@@ -1461,7 +1574,7 @@ pp_list(int nargs, const char *paren, const char *delim)
if (paren != NULL)
*s++ = paren[1];
*s = '\0';
- return str;
+ return str;
}
/* is_unary_minus --- return true if string starts with unary minus */
@@ -1536,7 +1649,7 @@ pp_concat(int nargs)
*s++ = ' ';
}
}
-
+
pl_l = prec_level(pp_args[nargs-1]->type);
pl_r = prec_level(pp_args[nargs]->type);
r = pp_args[nargs];
@@ -1552,7 +1665,7 @@ pp_concat(int nargs)
pp_free(r);
*s = '\0';
- return str;
+ return str;
}
/* pp_group3 --- string together up to 3 strings */
@@ -1566,7 +1679,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 +1707,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 +1734,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;
}
diff --git a/protos.h b/protos.h
index 7bef8b84..5693a43b 100644
--- a/protos.h
+++ b/protos.h
@@ -2,22 +2,22 @@
* protos.h -- function prototypes for when the headers don't have them.
*/
-/*
+/*
* Copyright (C) 1991 - 2002, 2011 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
@@ -64,7 +64,7 @@ extern size_t strftime(char *, size_t, const char *, const struct tm *);
extern time_t time(time_t *);
extern FILE *fdopen(int, const char *);
-extern int fprintf(FILE *, const char *, ...);
+extern int fprintf(FILE *, const char *, ...);
#if ! defined(__GNU_LIBRARY__)
extern size_t fwrite(const aptr_t, size_t, size_t, FILE *);
#endif
@@ -124,7 +124,7 @@ extern unsigned long int strtoul(const char *, char **endptr, int base);
#ifndef HAVE_TZSET
extern void tzset();
#endif
-
+
#ifndef HAVE_MKTIME
extern time_t mktime(struct tm *tp);
#endif
diff --git a/random.h b/random.h
index d4c6ef16..84b31414 100644
--- a/random.h
+++ b/random.h
@@ -2,22 +2,22 @@
* random.h - redefine name of random lib routines to avoid conflicts
*/
-/*
+/*
* Copyright (C) 1996, 2001, 2004, 2005, 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
diff --git a/re.c b/re.c
index 878c884e..fd3ef9ef 100644
--- a/re.c
+++ b/re.c
@@ -2,22 +2,22 @@
* re.c - compile regular expressions.
*/
-/*
+/*
* Copyright (C) 1991-2016 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
@@ -25,10 +25,14 @@
#include "awk.h"
+#include "localeinfo.h"
+
static reg_syntax_t syn;
static void check_bracket_exp(char *s, size_t len);
const char *regexflags2str(int flags);
+static struct localeinfo localeinfo;
+
/* make_regexp --- generate compiled regular expressions */
Regexp *
@@ -45,7 +49,6 @@ make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal)
int c, c2;
static bool first = true;
static bool no_dfa = false;
- bool has_anchor = false;
reg_syntax_t dfa_syn;
int i;
@@ -72,13 +75,13 @@ make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal)
/*
* Build a copy of the string (in buf) with the
* escaped characters translated, and generate the regex
- * from that.
+ * 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;
@@ -156,9 +159,6 @@ make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal)
} /* switch */
} else {
c = *src;
- if (c == '^' || c == '$')
- has_anchor = true;
-
*dest++ = *src++; /* not '\\' */
}
if (gawk_mb_cur_max > 1 && is_multibyte)
@@ -170,7 +170,6 @@ make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal)
emalloc(rp, Regexp *, sizeof(*rp), "make_regexp");
memset((char *) rp, 0, sizeof(*rp));
- rp->dfareg = NULL;
rp->pat.allocated = 0; /* regex will allocate the buffer */
emalloc(rp->pat.fastmap, char *, 256, "make_regexp");
@@ -223,13 +222,12 @@ make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal)
/* gack. this must be done *after* re_compile_pattern */
rp->pat.newline_anchor = false; /* don't get \n in middle of string */
if (dfa && ! no_dfa) {
- rp->dfa = true;
rp->dfareg = dfaalloc();
- dfasyntax(rp->dfareg, dfa_syn, ignorecase, '\n');
+ dfasyntax(rp->dfareg, & localeinfo, dfa_syn,
+ (ignorecase ? DFA_CASE_FOLD : 0) | DFA_ANCHOR);
dfacomp(buf, len, rp->dfareg, true);
} else
- rp->dfa = false;
- rp->has_anchor = has_anchor;
+ rp->dfareg = NULL;
/* Additional flags that help with RS as regexp. */
for (i = 0; i < len; i++) {
@@ -245,7 +243,7 @@ make_regexp(const char *s, size_t len, bool ignorecase, bool dfa, bool canfatal)
break;
}
}
-
+
return rp;
}
@@ -278,26 +276,24 @@ research(Regexp *rp, char *str, int start,
* starts in the middle of a string, so don't bother trying it
* in that case.
*/
- if (rp->dfa && ! no_bol && start == 0) {
- char save;
- size_t count = 0;
+ if (rp->dfareg != NULL && ! no_bol && start == 0) {
struct dfa *superset = dfasuperset(rp->dfareg);
- /*
- * dfa likes to stick a '\n' right after the matched
- * text. So we just save and restore the character.
- */
- save = str[start+len];
if (superset)
ret = dfaexec(superset, str+start, str+start+len,
true, NULL, NULL);
- if (ret)
+
+ if (ret && (! need_start
+ || (! superset && dfaisfast(rp->dfareg))))
ret = dfaexec(rp->dfareg, str+start, str+start+len,
- true, &count, &try_backref);
- str[start+len] = save;
+ true, NULL, &try_backref);
}
if (ret) {
- if (need_start || rp->dfa == false || try_backref) {
+ if ( rp->dfareg == NULL
+ || start != 0
+ || no_bol
+ || need_start
+ || try_backref) {
/*
* Passing NULL as last arg speeds up search for cases
* where we don't need the start/end info.
@@ -319,14 +315,14 @@ void
refree(Regexp *rp)
{
if (rp == NULL)
- return;
+ return;
rp->pat.translate = NULL;
regfree(& rp->pat);
if (rp->regs.start)
free(rp->regs.start);
if (rp->regs.end)
free(rp->regs.end);
- if (rp->dfa) {
+ if (rp->dfareg != NULL) {
dfafree(rp->dfareg);
free(rp->dfareg);
}
@@ -359,7 +355,7 @@ re_update(NODE *t)
t1 = t->re_exp;
if (t->re_text != NULL) {
/* if contents haven't changed, just return it */
- if (cmp_nodes(t->re_text, t1) == 0)
+ if (cmp_nodes(t->re_text, t1, true) == 0)
return t->re_reg;
/* things changed, fall through to recompile */
unref(t->re_text);
@@ -398,6 +394,9 @@ re_update(NODE *t)
void
resetup()
{
+ // init localeinfo for dfa
+ init_localeinfo(& localeinfo);
+
/*
* Syntax bits: _that_ is yet another mind trip. Recreational drugs
* are helpful for recovering from the experience.
@@ -421,25 +420,14 @@ resetup()
syn |= RE_INTERVALS | RE_INVALID_INTERVAL_ORD | RE_NO_BK_BRACES;
(void) re_set_syntax(syn);
-
- dfa_init();
}
-/* avoid_dfa --- return true if we should not use the DFA matcher */
+/* using_utf8 --- are we using utf8 */
-int
-avoid_dfa(NODE *re, char *str, size_t len)
+bool
+using_utf8(void)
{
- char *end;
-
- if (! re->re_reg->has_anchor)
- return false;
-
- for (end = str + len; str < end; str++)
- if (*str == '\n')
- return true;
-
- return false;
+ return localeinfo.using_utf8;
}
/* reisstring --- return true if the RE match is a simple string match */
diff --git a/regcomp.c b/regcomp.c
index 11c94fc1..5ac53701 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -216,7 +216,7 @@ static const size_t __re_error_msgid_idx[] =
#ifndef HAVE_BTOWC
-wchar_t
+wchar_t
btowc (int c)
{
wchar_t wtmp[2];
@@ -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. */
diff --git a/regex.h b/regex.h
index 872c4b6e..143b3afa 100644
--- a/regex.h
+++ b/regex.h
@@ -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/replace.c b/replace.c
index 6d345f52..db7f0893 100644
--- a/replace.c
+++ b/replace.c
@@ -2,22 +2,22 @@
* replace.c -- Get replacement versions of functions.
*/
-/*
+/*
* Copyright (C) 1989, 1991-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
@@ -84,7 +84,7 @@
#ifndef HAVE_TZSET
#include "missing_d/tzset.c"
#endif /* HAVE_TZSET */
-
+
#ifndef HAVE_MKTIME
/* mktime.c defines main() if DEBUG is set */
#undef DEBUG
diff --git a/str_array.c b/str_array.c
index 460e2f1d..65e0b741 100644
--- a/str_array.c
+++ b/str_array.c
@@ -2,23 +2,23 @@
* str_array.c - routines for associative arrays of string indices.
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2013, 2016,
* 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
@@ -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);
@@ -107,7 +126,7 @@ str_array_init(NODE *symbol ATTRIBUTE_UNUSED, NODE *subs ATTRIBUTE_UNUSED)
* isn't there. Returns a pointer ala get_lhs to where its value is stored.
*
* SYMBOL is the address of the node (or other pointer) being dereferenced.
- * SUBS is a number or string used as the subscript.
+ * SUBS is a number or string used as the subscript.
*/
static NODE **
@@ -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;
/*
@@ -175,7 +194,7 @@ str_lookup(NODE *symbol, NODE *subs)
}
subs = tmp;
} else {
- /* string value already "frozen" */
+ /* string value already "frozen" */
subs = dupnode(subs);
}
@@ -226,7 +245,7 @@ str_clear(NODE *symbol, NODE *subs ATTRIBUTE_UNUSED)
r = b->ahvalue;
if (r->type == Node_var_array) {
assoc_clear(r); /* recursively clear all sub-arrays */
- efree(r->vname);
+ efree(r->vname);
freenode(r);
} else
unref(r);
@@ -303,7 +322,7 @@ str_copy(NODE *symbol, NODE *newsymb)
BUCKET **old, **new, **pnew;
BUCKET *chain, *newchain;
unsigned long cursize, i;
-
+
assert(symbol->table_size > 0);
/* find the current hash size */
@@ -349,7 +368,7 @@ str_copy(NODE *symbol, NODE *newsymb)
newchain->ahnext = NULL;
pnew = & newchain->ahnext;
}
- }
+ }
newsymb->table_size = symbol->table_size;
newsymb->buckets = new;
@@ -383,9 +402,9 @@ str_list(NODE *symbol, NODE *t)
if ((assoc_kind & (AINDEX|AVALUE|ADELETE)) == (AINDEX|ADELETE))
num_elems = 1;
list_size = elem_size * num_elems;
-
+
emalloc(list, NODE **, list_size * sizeof(NODE *), "str_list");
-
+
/* populate it */
for (i = 0; i < symbol->array_size; i++) {
@@ -409,7 +428,7 @@ str_list(NODE *symbol, NODE *t)
}
if (k >= list_size)
return list;
- }
+ }
}
return list;
}
@@ -426,7 +445,7 @@ str_kilobytes(NODE *symbol)
bucket_cnt = symbol->table_size;
/* This does not include extra memory for indices with stfmt != -1 */
- kb = (((AWKNUM) bucket_cnt) * sizeof (BUCKET) +
+ kb = (((AWKNUM) bucket_cnt) * sizeof (BUCKET) +
((AWKNUM) symbol->array_size) * sizeof (BUCKET *)) / 1024.0;
return kb;
}
@@ -514,7 +533,7 @@ str_dump(NODE *symbol, NODE *ndump)
return NULL;
#undef HCNT
-}
+}
/* awk_hash --- calculate the hash function of the string in subs */
@@ -627,11 +646,11 @@ grow_table(NODE *symbol)
* very large (> 8K), we just double more or less, instead of
* just jumping from 8K to 64K.
*/
-
+
static const unsigned long sizes[] = {
13, 127, 1021, 8191, 16381, 32749, 65497,
131101, 262147, 524309, 1048583, 2097169,
- 4194319, 8388617, 16777259, 33554467,
+ 4194319, 8388617, 16777259, 33554467,
67108879, 134217757, 268435459, 536870923,
1073741827
};
@@ -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;
+}
diff --git a/symbol.c b/symbol.c
index fe7e3753..e1504300 100644
--- a/symbol.c
+++ b/symbol.c
@@ -2,22 +2,22 @@
* symbol.c - routines for symbol table management and code allocation
*/
-/*
+/*
* Copyright (C) 1986, 1988, 1989, 1991-2015 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
@@ -71,7 +71,7 @@ init_symbol_table()
/*
* install_symbol:
* Install a global name in the symbol table, even if it is already there.
- * Caller must check against redefinition if that is desired.
+ * Caller must check against redefinition if that is desired.
*/
NODE *
@@ -129,7 +129,7 @@ make_params(char **pnames, int pcount)
{
NODE *p, *parms;
int i;
-
+
if (pcount <= 0 || pnames == NULL)
return NULL;
@@ -242,12 +242,12 @@ destroy_symbol(NODE *r)
NODE *n;
int i;
int pcount = r->param_cnt;
-
- /* function parameters of type Node_param_list */
+
+ /* function parameters of type Node_param_list */
for (i = 0; i < pcount; i++) {
n = r->fparms + i;
efree(n->param);
- }
+ }
efree(r->fparms);
}
break;
@@ -260,7 +260,7 @@ destroy_symbol(NODE *r)
assoc_clear(r);
break;
- case Node_var:
+ case Node_var:
unref(r->var_value);
break;
@@ -369,7 +369,7 @@ comp_symbol(const void *v1, const void *v2)
typedef enum { FUNCTION = 1, VARIABLE } SYMBOL_TYPE;
/* get_symbols --- return a list of optionally sorted symbols */
-
+
static NODE **
get_symbols(SYMBOL_TYPE what, bool sort)
{
@@ -448,7 +448,7 @@ function_list(bool sort)
return get_symbols(FUNCTION, sort);
}
-/* print_vars --- print names and values of global variables */
+/* print_vars --- print names and values of global variables */
void
print_vars(NODE **table, int (*print_func)(FILE *, const char *, ...), FILE *fp)
@@ -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
@@ -708,7 +708,7 @@ bcfree(INSTRUCTION *cp)
cp->opcode = 0;
cp->nexti = pool_list->freei;
pool_list->freei = cp;
-}
+}
/* bcalloc --- allocate a new instruction */
@@ -804,7 +804,7 @@ push_context(AWK_CONTEXT *ctxt)
ctxt_level++;
}
-/* pop_context --- switch to previous execution context. */
+/* pop_context --- switch to previous execution context. */
void
pop_context()
@@ -831,7 +831,7 @@ in_main_context()
return (ctxt_level == 1);
}
-/* free_context --- free context structure and related data. */
+/* free_context --- free context structure and related data. */
void
free_context(AWK_CONTEXT *ctxt, bool keep_globals)
@@ -864,7 +864,7 @@ free_context(AWK_CONTEXT *ctxt, bool keep_globals)
efree(ctxt);
}
-/* free_bc_internal --- free internal memory of an instruction. */
+/* free_bc_internal --- free internal memory of an instruction. */
static void
free_bc_internal(INSTRUCTION *cp)
@@ -888,7 +888,7 @@ free_bc_internal(INSTRUCTION *cp)
if (m->re_text != NULL)
unref(m->re_text);
freenode(m);
- break;
+ break;
case Op_token:
/* token lost during error recovery in yyparse */
if (cp->lextok != NULL)
@@ -906,7 +906,7 @@ free_bc_internal(INSTRUCTION *cp)
case Op_illegal:
cant_happen();
default:
- break;
+ break;
}
}
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 280a80ae..dfba45a0 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,7 +1,45 @@
+2016-11-04 Fabio Berton <fabio.berton@ossystems.com.br>
+
+ * arrayind1.awk: Remove "#!/usr/local/bin/awk -f" as none of the
+ other awk scripts in the test suite have a hashbang.
+
+2016-10-07 Arnold D. Robbins <arnold@skeeve.com>
+
+ * mpfrmemok1.ok: Update after code change.
+
+2016-09-09 Norihiro Tanaka <noritnk@kcn.ne.jp>
+
+ * Makefile.am (anchor): New test.
+ * anchor.awk, anchor.in, anchor.ok: New files.
+
2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
* 4.1.4: Release tar ball made.
+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
@@ -20,17 +58,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.
@@ -48,6 +130,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.
@@ -64,6 +158,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
@@ -114,6 +214,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):
@@ -124,10 +229,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.
@@ -139,9 +266,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.
@@ -191,10 +325,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
@@ -244,6 +433,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).
@@ -268,11 +462,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.
@@ -298,11 +503,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
@@ -318,6 +550,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.
@@ -331,6 +573,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
@@ -351,6 +603,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.
@@ -362,6 +642,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.
@@ -374,12 +658,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.
@@ -431,6 +720,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
@@ -477,6 +776,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.
@@ -693,6 +997,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
@@ -709,6 +1019,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..9dbedb35 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -47,6 +47,9 @@ EXTRA_DIST = \
anchgsub.awk \
anchgsub.in \
anchgsub.ok \
+ anchor.awk \
+ anchor.in \
+ anchor.ok \
argarray.awk \
argarray.in \
argarray.ok \
@@ -55,6 +58,8 @@ EXTRA_DIST = \
arrayind1.awk \
arrayind1.in \
arrayind1.ok \
+ arrayind2.awk \
+ arrayind2.ok \
arrayparm.awk \
arrayparm.ok \
arrayprm2.awk \
@@ -65,6 +70,7 @@ EXTRA_DIST = \
arrayref.ok \
arraysort.awk \
arraysort.ok \
+ arrdbg.awk \
arrymem1.awk \
arrymem1.ok \
arryref2.awk \
@@ -159,6 +165,8 @@ EXTRA_DIST = \
clos1way4.ok \
clos1way5.awk \
clos1way5.ok \
+ clos1way6.awk \
+ clos1way6.ok \
closebad.awk \
closebad.ok \
clsflnam.awk \
@@ -191,6 +199,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 +244,9 @@ EXTRA_DIST = \
dynlj.ok \
eofsplit.awk \
eofsplit.ok \
+ errno.awk \
+ errno.in \
+ errno.ok \
exit.ok \
exit.sh \
exit2.awk \
@@ -284,6 +304,8 @@ EXTRA_DIST = \
fnparydl-mpfr.ok \
fnparydl.awk \
fnparydl.ok \
+ forcenum.awk \
+ forcenum.ok \
fordel.awk \
fordel.ok \
fork.awk \
@@ -363,6 +385,8 @@ EXTRA_DIST = \
gensub.ok \
gensub2.awk \
gensub2.ok \
+ getfile.awk \
+ getfile.ok \
getline.awk \
getline.in \
getline.ok \
@@ -396,6 +420,8 @@ EXTRA_DIST = \
gnureops.ok \
gsubasgn.awk \
gsubasgn.ok \
+ gsubind.awk \
+ gsubind.ok \
gsubtest.awk \
gsubtest.ok \
gsubtst2.awk \
@@ -445,6 +471,8 @@ EXTRA_DIST = \
ignrcas2.ok \
ignrcas3.awk \
ignrcas3.ok \
+ ignrcas4.awk \
+ ignrcas4.ok \
ignrcase.awk \
ignrcase.in \
ignrcase.ok \
@@ -487,6 +515,8 @@ EXTRA_DIST = \
inplace3.2.bak.ok \
inputred.awk \
inputred.ok \
+ intarray.awk \
+ intarray.ok \
intest.awk \
intest.ok \
intformat.awk \
@@ -508,9 +538,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 +630,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 +687,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 +800,8 @@ EXTRA_DIST = \
printfbad3.ok \
printfbad4.awk \
printfbad4.ok \
+ printfchar.awk \
+ printfchar.ok \
printfloat.awk \
printhuge.awk \
printhuge.ok \
@@ -776,6 +828,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 +841,8 @@ EXTRA_DIST = \
rand-mpfr.ok \
rand.awk \
rand.ok \
+ randtest.sh \
+ randtest.ok \
range1.awk \
range1.in \
range1.ok \
@@ -804,6 +862,9 @@ EXTRA_DIST = \
rebuf.awk \
rebuf.in \
rebuf.ok \
+ rebuild.awk \
+ rebuild.in \
+ rebuild.ok \
redfilnm.awk \
redfilnm.in \
redfilnm.ok \
@@ -904,6 +965,8 @@ EXTRA_DIST = \
sclifin.ok \
shadow.awk \
shadow.ok \
+ shadowbuiltin.awk \
+ shadowbuiltin.ok \
sigpipe1.awk \
sigpipe1.ok \
sort1.awk \
@@ -943,6 +1006,8 @@ EXTRA_DIST = \
sprintfc.awk \
sprintfc.in \
sprintfc.ok \
+ status-close.awk \
+ status-close.ok \
strcat1.awk \
strcat1.ok \
strftime.awk \
@@ -950,11 +1015,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 +1075,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 +1150,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 anchor 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 +1176,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 +1194,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 +1237,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 +1245,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 +1297,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 +1339,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 +1524,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 +1783,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 +1922,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 +1943,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 +1965,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 +2039,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 +2158,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 +2237,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 +2299,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 +2350,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..f1ffc0db 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)
@@ -304,6 +304,9 @@ EXTRA_DIST = \
anchgsub.awk \
anchgsub.in \
anchgsub.ok \
+ anchor.awk \
+ anchor.in \
+ anchor.ok \
argarray.awk \
argarray.in \
argarray.ok \
@@ -312,6 +315,8 @@ EXTRA_DIST = \
arrayind1.awk \
arrayind1.in \
arrayind1.ok \
+ arrayind2.awk \
+ arrayind2.ok \
arrayparm.awk \
arrayparm.ok \
arrayprm2.awk \
@@ -322,6 +327,7 @@ EXTRA_DIST = \
arrayref.ok \
arraysort.awk \
arraysort.ok \
+ arrdbg.awk \
arrymem1.awk \
arrymem1.ok \
arryref2.awk \
@@ -416,6 +422,8 @@ EXTRA_DIST = \
clos1way4.ok \
clos1way5.awk \
clos1way5.ok \
+ clos1way6.awk \
+ clos1way6.ok \
closebad.awk \
closebad.ok \
clsflnam.awk \
@@ -448,6 +456,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 +501,9 @@ EXTRA_DIST = \
dynlj.ok \
eofsplit.awk \
eofsplit.ok \
+ errno.awk \
+ errno.in \
+ errno.ok \
exit.ok \
exit.sh \
exit2.awk \
@@ -541,6 +561,8 @@ EXTRA_DIST = \
fnparydl-mpfr.ok \
fnparydl.awk \
fnparydl.ok \
+ forcenum.awk \
+ forcenum.ok \
fordel.awk \
fordel.ok \
fork.awk \
@@ -620,6 +642,8 @@ EXTRA_DIST = \
gensub.ok \
gensub2.awk \
gensub2.ok \
+ getfile.awk \
+ getfile.ok \
getline.awk \
getline.in \
getline.ok \
@@ -653,6 +677,8 @@ EXTRA_DIST = \
gnureops.ok \
gsubasgn.awk \
gsubasgn.ok \
+ gsubind.awk \
+ gsubind.ok \
gsubtest.awk \
gsubtest.ok \
gsubtst2.awk \
@@ -702,6 +728,8 @@ EXTRA_DIST = \
ignrcas2.ok \
ignrcas3.awk \
ignrcas3.ok \
+ ignrcas4.awk \
+ ignrcas4.ok \
ignrcase.awk \
ignrcase.in \
ignrcase.ok \
@@ -744,6 +772,8 @@ EXTRA_DIST = \
inplace3.2.bak.ok \
inputred.awk \
inputred.ok \
+ intarray.awk \
+ intarray.ok \
intest.awk \
intest.ok \
intformat.awk \
@@ -765,9 +795,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 +887,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 +944,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 +1057,8 @@ EXTRA_DIST = \
printfbad3.ok \
printfbad4.awk \
printfbad4.ok \
+ printfchar.awk \
+ printfchar.ok \
printfloat.awk \
printhuge.awk \
printhuge.ok \
@@ -1033,6 +1085,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 +1098,8 @@ EXTRA_DIST = \
rand-mpfr.ok \
rand.awk \
rand.ok \
+ randtest.sh \
+ randtest.ok \
range1.awk \
range1.in \
range1.ok \
@@ -1061,6 +1119,9 @@ EXTRA_DIST = \
rebuf.awk \
rebuf.in \
rebuf.ok \
+ rebuild.awk \
+ rebuild.in \
+ rebuild.ok \
redfilnm.awk \
redfilnm.in \
redfilnm.ok \
@@ -1161,6 +1222,8 @@ EXTRA_DIST = \
sclifin.ok \
shadow.awk \
shadow.ok \
+ shadowbuiltin.awk \
+ shadowbuiltin.ok \
sigpipe1.awk \
sigpipe1.ok \
sort1.awk \
@@ -1200,6 +1263,8 @@ EXTRA_DIST = \
sprintfc.awk \
sprintfc.in \
sprintfc.ok \
+ status-close.awk \
+ status-close.ok \
strcat1.awk \
strcat1.ok \
strftime.awk \
@@ -1207,11 +1272,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 +1332,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 +1406,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 anchor 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 +1432,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 +1450,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 +1497,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 +1738,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 +1780,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 +1963,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 +2222,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 +2361,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 +2381,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 +2403,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 +2477,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 +2596,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 +2675,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 +2736,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 +2786,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:
@@ -2639,11 +2803,21 @@ anchgsub:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+anchor:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
arrayind1:
@echo $@
@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 +3503,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 +3555,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 +3695,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 +3710,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 +3815,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 +3885,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 +4005,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 +4035,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 +4070,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 +4130,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 +4205,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 +4240,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 +4280,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 +4410,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..a13ed244 100644
--- a/test/Maketests
+++ b/test/Maketests
@@ -10,11 +10,21 @@ anchgsub:
@AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+anchor:
+ @echo $@
+ @AWKPATH="$(srcdir)" $(AWK) -f $@.awk < "$(srcdir)"/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
arrayind1:
@echo $@
@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 +710,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 +762,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 +902,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 +917,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 +1022,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 +1092,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 +1212,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 +1242,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 +1277,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 +1337,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 +1412,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 +1447,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 +1487,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/anchor.awk b/test/anchor.awk
new file mode 100644
index 00000000..56f47569
--- /dev/null
+++ b/test/anchor.awk
@@ -0,0 +1,33 @@
+BEGIN { RS = "" }
+
+{
+ if (/^A/)
+ print "ok"
+ else
+ print "not ok"
+
+ if (/B$/)
+ print "not ok"
+ else
+ print "ok"
+
+ if (/^C/)
+ print "not ok"
+ else
+ print "ok"
+
+ if (/D$/)
+ print "not ok"
+ else
+ print "ok"
+
+ if (/^E/)
+ print "not ok"
+ else
+ print "ok"
+
+ if (/F$/)
+ print "ok"
+ else
+ print "not ok"
+}
diff --git a/test/anchor.in b/test/anchor.in
new file mode 100644
index 00000000..a97e9859
--- /dev/null
+++ b/test/anchor.in
@@ -0,0 +1,3 @@
+A line1 B
+C line2 D
+E line3 F
diff --git a/test/anchor.ok b/test/anchor.ok
new file mode 100644
index 00000000..7780b88b
--- /dev/null
+++ b/test/anchor.ok
@@ -0,0 +1,6 @@
+ok
+ok
+ok
+ok
+ok
+ok
diff --git a/test/arrayind1.awk b/test/arrayind1.awk
index 5d4a6f3d..59e8b4ea 100755
--- a/test/arrayind1.awk
+++ b/test/arrayind1.awk
@@ -1,4 +1,3 @@
-#!/usr/local/bin/awk -f
# this script renums pedigrees with metafounders
# so that they are added *before*regular animals
# mf are ascertained because they are not in the 1st column
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
diff --git a/test/id.ok b/test/id.ok
index ab9f6392..7454a4fc 100644
--- a/test/id.ok
+++ b/test/id.ok
@@ -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/mpfrmemok1.ok b/test/mpfrmemok1.ok
index 2389a2d5..6bbd0309 100644
--- a/test/mpfrmemok1.ok
+++ b/test/mpfrmemok1.ok
@@ -2,6 +2,6 @@
# BEGIN rule(s)
BEGIN {
- 1 v = 340282366920938463463374607431768211456
+ 1 v = 0x0100000000000000000000000000000000
}
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/verify.h b/verify.h
new file mode 100644
index 00000000..5c8381d2
--- /dev/null
+++ b/verify.h
@@ -0,0 +1,279 @@
+/* Compile-time assert-like macros.
+
+ Copyright (C) 2005-2006, 2009-2016 Free Software Foundation, Inc.
+
+ This program 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.
+
+ This program 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
+
+#ifndef _GL_VERIFY_H
+#define _GL_VERIFY_H
+
+
+/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11.
+ This is supported by GCC 4.6.0 and later, in C mode, and its use
+ here generates easier-to-read diagnostics when verify (R) fails.
+
+ Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11.
+ This will likely be supported by future GCC versions, in C++ mode.
+
+ Use this only with GCC. If we were willing to slow 'configure'
+ down we could also use it with other compilers, but since this
+ affects only the quality of diagnostics, why bother? */
+#if (4 < __GNUC__ + (6 <= __GNUC_MINOR__) \
+ && (201112L <= __STDC_VERSION__ || !defined __STRICT_ANSI__) \
+ && !defined __cplusplus)
+# define _GL_HAVE__STATIC_ASSERT 1
+#endif
+/* The condition (99 < __GNUC__) is temporary, until we know about the
+ first G++ release that supports static_assert. */
+#if (99 < __GNUC__) && defined __cplusplus
+# define _GL_HAVE_STATIC_ASSERT 1
+#endif
+
+/* FreeBSD 9.1 <sys/cdefs.h>, included by <stddef.h> and lots of other
+ system headers, defines a conflicting _Static_assert that is no
+ better than ours; override it. */
+#ifndef _GL_HAVE_STATIC_ASSERT
+# include <stddef.h>
+# undef _Static_assert
+#endif
+
+/* Each of these macros verifies that its argument R is nonzero. To
+ be portable, R should be an integer constant expression. Unlike
+ assert (R), there is no run-time overhead.
+
+ If _Static_assert works, verify (R) uses it directly. Similarly,
+ _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct
+ that is an operand of sizeof.
+
+ The code below uses several ideas for C++ compilers, and for C
+ compilers that do not support _Static_assert:
+
+ * The first step is ((R) ? 1 : -1). Given an expression R, of
+ integral or boolean or floating-point type, this yields an
+ expression of integral type, whose value is later verified to be
+ constant and nonnegative.
+
+ * Next this expression W is wrapped in a type
+ struct _gl_verify_type {
+ unsigned int _gl_verify_error_if_negative: W;
+ }.
+ If W is negative, this yields a compile-time error. No compiler can
+ deal with a bit-field of negative size.
+
+ One might think that an array size check would have the same
+ effect, that is, that the type struct { unsigned int dummy[W]; }
+ would work as well. However, inside a function, some compilers
+ (such as C++ compilers and GNU C) allow local parameters and
+ variables inside array size expressions. With these compilers,
+ an array size check would not properly diagnose this misuse of
+ the verify macro:
+
+ void function (int n) { verify (n < 0); }
+
+ * For the verify macro, the struct _gl_verify_type will need to
+ somehow be embedded into a declaration. To be portable, this
+ declaration must declare an object, a constant, a function, or a
+ typedef name. If the declared entity uses the type directly,
+ such as in
+
+ struct dummy {...};
+ typedef struct {...} dummy;
+ extern struct {...} *dummy;
+ extern void dummy (struct {...} *);
+ extern struct {...} *dummy (void);
+
+ two uses of the verify macro would yield colliding declarations
+ if the entity names are not disambiguated. A workaround is to
+ attach the current line number to the entity name:
+
+ #define _GL_CONCAT0(x, y) x##y
+ #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y)
+ extern struct {...} * _GL_CONCAT (dummy, __LINE__);
+
+ But this has the problem that two invocations of verify from
+ within the same macro would collide, since the __LINE__ value
+ would be the same for both invocations. (The GCC __COUNTER__
+ macro solves this problem, but is not portable.)
+
+ A solution is to use the sizeof operator. It yields a number,
+ getting rid of the identity of the type. Declarations like
+
+ extern int dummy [sizeof (struct {...})];
+ extern void dummy (int [sizeof (struct {...})]);
+ extern int (*dummy (void)) [sizeof (struct {...})];
+
+ can be repeated.
+
+ * Should the implementation use a named struct or an unnamed struct?
+ Which of the following alternatives can be used?
+
+ extern int dummy [sizeof (struct {...})];
+ extern int dummy [sizeof (struct _gl_verify_type {...})];
+ extern void dummy (int [sizeof (struct {...})]);
+ extern void dummy (int [sizeof (struct _gl_verify_type {...})]);
+ extern int (*dummy (void)) [sizeof (struct {...})];
+ extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})];
+
+ In the second and sixth case, the struct type is exported to the
+ outer scope; two such declarations therefore collide. GCC warns
+ about the first, third, and fourth cases. So the only remaining
+ possibility is the fifth case:
+
+ extern int (*dummy (void)) [sizeof (struct {...})];
+
+ * GCC warns about duplicate declarations of the dummy function if
+ -Wredundant-decls is used. GCC 4.3 and later have a builtin
+ __COUNTER__ macro that can let us generate unique identifiers for
+ each dummy function, to suppress this warning.
+
+ * This implementation exploits the fact that older versions of GCC,
+ which do not support _Static_assert, also do not warn about the
+ last declaration mentioned above.
+
+ * GCC warns if -Wnested-externs is enabled and verify() is used
+ within a function body; but inside a function, you can always
+ arrange to use verify_expr() instead.
+
+ * In C++, any struct definition inside sizeof is invalid.
+ Use a template type to work around the problem. */
+
+/* Concatenate two preprocessor tokens. */
+#define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y)
+#define _GL_CONCAT0(x, y) x##y
+
+/* _GL_COUNTER is an integer, preferably one that changes each time we
+ use it. Use __COUNTER__ if it works, falling back on __LINE__
+ otherwise. __LINE__ isn't perfect, but it's better than a
+ constant. */
+#if defined __COUNTER__ && __COUNTER__ != __COUNTER__
+# define _GL_COUNTER __COUNTER__
+#else
+# define _GL_COUNTER __LINE__
+#endif
+
+/* Generate a symbol with the given prefix, making it unique if
+ possible. */
+#define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER)
+
+/* Verify requirement R at compile-time, as an integer constant expression
+ that returns 1. If R is false, fail at compile-time, preferably
+ with a diagnostic that includes the string-literal DIAGNOSTIC. */
+
+#define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \
+ (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC)))
+
+#ifdef __cplusplus
+# if !GNULIB_defined_struct__gl_verify_type
+template <int w>
+ struct _gl_verify_type {
+ unsigned int _gl_verify_error_if_negative: w;
+ };
+# define GNULIB_defined_struct__gl_verify_type 1
+# endif
+# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
+ _gl_verify_type<(R) ? 1 : -1>
+#elif defined _GL_HAVE__STATIC_ASSERT
+# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
+ struct { \
+ _Static_assert (R, DIAGNOSTIC); \
+ int _gl_dummy; \
+ }
+#else
+# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
+ struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; }
+#endif
+
+/* Verify requirement R at compile-time, as a declaration without a
+ trailing ';'. If R is false, fail at compile-time, preferably
+ with a diagnostic that includes the string-literal DIAGNOSTIC.
+
+ Unfortunately, unlike C11, this implementation must appear as an
+ ordinary declaration, and cannot appear inside struct { ... }. */
+
+#ifdef _GL_HAVE__STATIC_ASSERT
+# define _GL_VERIFY _Static_assert
+#else
+# define _GL_VERIFY(R, DIAGNOSTIC) \
+ extern int (*_GL_GENSYM (_gl_verify_function) (void)) \
+ [_GL_VERIFY_TRUE (R, DIAGNOSTIC)]
+#endif
+
+/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */
+#ifdef _GL_STATIC_ASSERT_H
+# if !defined _GL_HAVE__STATIC_ASSERT && !defined _Static_assert
+# define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC)
+# endif
+# if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert
+# define static_assert _Static_assert /* C11 requires this #define. */
+# endif
+#endif
+
+/* @assert.h omit start@ */
+
+/* Each of these macros verifies that its argument R is nonzero. To
+ be portable, R should be an integer constant expression. Unlike
+ assert (R), there is no run-time overhead.
+
+ There are two macros, since no single macro can be used in all
+ contexts in C. verify_true (R) is for scalar contexts, including
+ integer constant expression contexts. verify (R) is for declaration
+ contexts, e.g., the top level. */
+
+/* Verify requirement R at compile-time, as an integer constant expression.
+ Return 1. This is equivalent to verify_expr (R, 1).
+
+ verify_true is obsolescent; please use verify_expr instead. */
+
+#define verify_true(R) _GL_VERIFY_TRUE (R, "verify_true (" #R ")")
+
+/* Verify requirement R at compile-time. Return the value of the
+ expression E. */
+
+#define verify_expr(R, E) \
+ (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E))
+
+/* Verify requirement R at compile-time, as a declaration without a
+ trailing ';'. */
+
+#define verify(R) _GL_VERIFY (R, "verify (" #R ")")
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/* Assume that R always holds. This lets the compiler optimize
+ accordingly. R should not have side-effects; it may or may not be
+ evaluated. Behavior is undefined if R is false. */
+
+#if (__has_builtin (__builtin_unreachable) \
+ || 4 < __GNUC__ + (5 <= __GNUC_MINOR__))
+# define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
+#elif 1200 <= _MSC_VER
+# define assume(R) __assume (R)
+#elif ((defined GCC_LINT || defined lint) \
+ && (__has_builtin (__builtin_trap) \
+ || 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__))))
+ /* Doing it this way helps various packages when configured with
+ --enable-gcc-warnings, which compiles with -Dlint. It's nicer
+ when 'assume' silences warnings even with older GCCs. */
+# define assume(R) ((R) ? (void) 0 : __builtin_trap ())
+#else
+# define assume(R) ((void) (0 && (R)))
+#endif
+
+/* @assert.h omit end@ */
+
+#endif
diff --git a/vms/ChangeLog b/vms/ChangeLog
index 56890275..dd021669 100644
--- a/vms/ChangeLog
+++ b/vms/ChangeLog
@@ -1,7 +1,11 @@
2016-10-24 John E. Malmberg <wb8tyw@qsl.net>
- * backup_gawk_src.com: Do not backup entire git repository.
- * pcsi_product_gawk.com: Create a ZIP archive of PCSI kit.
+ * backup_gawk_src.com: Do not backup entire git repository.
+ * pcsi_product_gawk.com: Create a ZIP archive of PCSI kit.
+
+2016-10-23 Arnold D. Robbins <arnold@skeeve.com>
+
+ * General: Remove trailing whitespace from all relevant files.
2016-08-25 Arnold D. Robbins <arnold@skeeve.com>
@@ -102,6 +106,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.
diff --git a/vms/vms_gawk.c b/vms/vms_gawk.c
index 4080e1db..0caab21f 100644
--- a/vms/vms_gawk.c
+++ b/vms/vms_gawk.c
@@ -16,7 +16,7 @@
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. */
-
+
/*
* vms_gawk.c - routines to parse the command line as a native DCL command