diff options
-rw-r--r-- | ChangeLog | 64 | ||||
-rw-r--r-- | awk.h | 15 | ||||
-rw-r--r-- | awkgram.c | 6 | ||||
-rw-r--r-- | awkgram.y | 6 | ||||
-rw-r--r-- | awklib/eg/lib/intdiv.awk | 7 | ||||
-rw-r--r-- | builtin.c | 2 | ||||
-rw-r--r-- | configh.in | 3 | ||||
-rwxr-xr-x | configure | 18 | ||||
-rw-r--r-- | configure.ac | 11 | ||||
-rw-r--r-- | doc/ChangeLog | 7 | ||||
-rw-r--r-- | doc/awkcard.in | 6 | ||||
-rw-r--r-- | doc/gawk.1 | 2 | ||||
-rw-r--r-- | doc/gawk.info | 773 | ||||
-rw-r--r-- | doc/gawk.texi | 32 | ||||
-rw-r--r-- | doc/gawktexi.in | 32 | ||||
-rw-r--r-- | extension/ChangeLog | 35 | ||||
-rw-r--r-- | extension/Makefile.am | 8 | ||||
-rw-r--r-- | extension/Makefile.in | 47 | ||||
-rw-r--r-- | extension/aclocal.m4 | 1 | ||||
-rw-r--r-- | extension/configh.in | 6 | ||||
-rwxr-xr-x | extension/configure | 88 | ||||
-rw-r--r-- | extension/configure.ac | 13 | ||||
-rw-r--r-- | extension/intdiv.c | 215 | ||||
-rw-r--r-- | gawkapi.c | 117 | ||||
-rw-r--r-- | gawkapi.h | 97 | ||||
-rw-r--r-- | mpfr.c | 22 | ||||
-rw-r--r-- | node.c | 14 | ||||
-rw-r--r-- | test/ChangeLog | 5 | ||||
-rw-r--r-- | test/dumpvars.ok | 2 | ||||
-rw-r--r-- | test/id.ok | 1 | ||||
-rw-r--r-- | test/mpfrsqrt.awk | 2 | ||||
-rw-r--r-- | test/symtab6.ok | 2 | ||||
-rw-r--r-- | test/symtab8.ok | 2 |
33 files changed, 1148 insertions, 513 deletions
@@ -62,6 +62,10 @@ * gawkapi.h, gawkapi.c: Typo fixes in comments. +2017-06-26 Arnold D. Robbins <arnold@skeeve.com> + + * configure.ac: Turn a tab into a space in AC_DEFINE(SUPPLY_INTDIV). + 2017-06-25 Andrew J. Schorr <aschorr@telemetry-investments.com> * gawkmisc.c (xmalloc): Remove function now in support/xalloc.h. @@ -200,11 +204,27 @@ 2017-04-16 Arnold D. Robbins <arnold@skeeve.com> + Rename intdiv it intdiv0 and require enabling at configure time. + + * awkgram.y (tokentab): Bracket intdiv0 in #ifdef SUPPLY_INTDIV. + (snode): Similar. + * builtin.c (do_intdiv): Bracket in #ifdef SUPPLY_INTDIV. + * mpfr.c (do_mpfr_intdiv): Bracket in #ifdef SUPPLY_INTDIV. + * configure.ac: Add --enable-builtin-intdiv0 option. If enabled, + also revise doc/gawktexi.in. + +2017-04-16 Arnold D. Robbins <arnold@skeeve.com> + * builtin.c (do_intdiv): Use DEREF on the arguments. Thanks to Andrew Schorr for finding the problem. * mpfr.c (do_mpfr_intdiv): Return -1 if numerator or denominator are not valid numbers. Unref various bits first. +2017-04-13 Arnold D. Robbins <arnold@skeeve.com> + + * awk.h (make_number_node): Simplify. + * mpfr.c (mpg_node): Change parameter name to `flags'. + 2017-04-12 Arnold D. Robbins <arnold@skeeve.com> * mpfr.c (mpg_format_val): Set STRCUR flag when we're done. @@ -213,6 +233,9 @@ * builtin.c (do_dcgettext): Move declaration of reslen to outside the ifdefs. Thanks to Hermann Peifer for the report. + * gawkapi.c (awk_value_to_node): Initialize ext_ret_val to NULL + to avoid compiler warnings. + 2017-04-12 Manuel Collado <m-collado@users.sourceforge.net> Fix the FPAT bug reported by Ed Morton in the gawk-bug mailing list. @@ -691,6 +714,47 @@ not updating the node correctly by setting STRING and STRCUR flags and setting stfmt. +2017-01-06 Andrew J. Schorr <aschorr@telemetry-investments.com> + + Enhance API to support extended-precision arithmetic. + * awk.h (enum block_id): Add new values BLOCK_MPFR and BLOCK_MPZ. + (make_number_node): New inline function to reduce code duplication + for creating numeric nodes. + * gawkapi.h (gawk_api_major_version): Bump to 3. + (awk_number_t): New typedef to represent numbers with varying internal + representations. + (awk_value_t): For numbers, replace double with awk_number_t. + (num_value): Redefine. + (num_type, num_ptr): New defines for awk_number_t union members. + (gawk_api_t): Add constants for version checking: gmp_major_version, + gmp_minor_version, mpfr_major_version, and mpfr_minor_version. + Add functions api_get_mpfr and api_get_mpz to allocate memory for + extended-precision numbers to hand to gawk. + (get_mpfr_ptr, get_mpz_ptr): Helper macros to wrap api_get_mpfr and + api_get_mpz. + (make_number): Modify to populate awk_number_t correctly. + (make_number_mpz, make_number_mpfr): New helper functions to create + extended-precision numeric nodes. + (check_mpfr_version): New macro to check GMP/MPFR version compatibility + in extensions that want to support extended-precision math. + * gawkapi.c (getmpfr, freempfr, getmpz, freempz): New macros to + allocate and free memory blocks for extended-precision math. + (awk_value_to_node): For AWK_NUMBER values, support three different + kinds of internal numbers: double, mpz_t, and mpfr_t. + (assign_number): New helper function to convert a numeric node to + an awk_value_t. + (node_to_awk_value): Use assign_number to pass numbers properly. + (api_get_mpfr): Implement new api_get_mpfr hook. + (api_get_mpfz): Implement new api_get_mpz hook. + (api_impl): Add GMP & MPFR versions, api_get_mpfr, and api_get_mpz. + * node.c (r_make_number): Use new make_number_node inline function + to reduce code duplication. + (nextfree): Add block allocators for mpfr_t and mpz_t. + (more_blocks): Add an assert to protect against cases where the block + size is too small to hold our structure. + * mpfr.c (mpg_node): Use new make_number_node inline function + to reduce code duplication. + 2017-01-04 Arnold Robbins <arnold@skeeve.com> * config.guess, config.sub, compile, depcomp: Sync from latest @@ -1066,6 +1066,8 @@ struct block_header { enum block_id { BLOCK_NODE = 0, BLOCK_BUCKET, + BLOCK_MPFR, + BLOCK_MPZ, BLOCK_MAX /* count */ }; @@ -1989,6 +1991,19 @@ erealloc_real(void *ptr, size_t count, const char *where, const char *var, const return ret; } +/* make_number_node --- make node with the given flags */ + +static inline NODE * +make_number_node(unsigned int flags) +{ + NODE *r; + getnode(r); + memset(r, 0, sizeof(*r)); + r->type = Node_val; + r->valref = 1; + r->flags = (flags|MALLOC|NUMBER|NUMCUR); + return r; +} /* * str_terminate_f, str_terminate, str_restore: function and macros to @@ -4552,7 +4552,9 @@ 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)}, +#ifdef SUPPLY_INTDIV +{"intdiv0", Op_builtin, LEX_BUILTIN, GAWKX|A(3), do_intdiv, MPF(intdiv)}, +#endif {"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}, @@ -6867,6 +6869,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) arg = subn->nexti; if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push) arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */ +#ifdef SUPPLY_INTDIV } else if (r->builtin == do_intdiv #ifdef HAVE_MPFR || r->builtin == MPF(intdiv) @@ -6876,6 +6879,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) ip = arg->lasti; if (ip->opcode == Op_push) ip->opcode = Op_push_array; +#endif /* SUPPLY_INTDIV */ } else if (r->builtin == do_match) { static bool warned = false; @@ -2132,7 +2132,9 @@ 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)}, +#ifdef SUPPLY_INTDIV +{"intdiv0", Op_builtin, LEX_BUILTIN, GAWKX|A(3), do_intdiv, MPF(intdiv)}, +#endif {"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}, @@ -4447,6 +4449,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) arg = subn->nexti; if (arg->nexti == arg->lasti && arg->nexti->opcode == Op_push) arg->nexti->opcode = Op_push_arg_untyped; /* argument may be untyped */ +#ifdef SUPPLY_INTDIV } else if (r->builtin == do_intdiv #ifdef HAVE_MPFR || r->builtin == MPF(intdiv) @@ -4456,6 +4459,7 @@ snode(INSTRUCTION *subn, INSTRUCTION *r) ip = arg->lasti; if (ip->opcode == Op_push) ip->opcode = Op_push_array; +#endif /* SUPPLY_INTDIV */ } else if (r->builtin == do_match) { static bool warned = false; diff --git a/awklib/eg/lib/intdiv.awk b/awklib/eg/lib/intdiv.awk index dbc553b0..9de5978e 100644 --- a/awklib/eg/lib/intdiv.awk +++ b/awklib/eg/lib/intdiv.awk @@ -1,4 +1,4 @@ -# intdiv --- do integer division +# intdiv0 --- do integer division # # Arnold Robbins, arnold@skeeve.com, Public Domain @@ -6,8 +6,11 @@ # # Name changed from div() to intdiv() # April, 2015 +# +# Changed to intdiv0() +# April, 2016 -function intdiv(numerator, denominator, result) +function intdiv0(numerator, denominator, result) { split("", result) @@ -3971,6 +3971,7 @@ do_bindtextdomain(int nargs) return make_string(the_result, strlen(the_result)); } +#ifdef SUPPLY_INTDIV /* do_intdiv --- do integer division, return quotient and remainder in dest array */ /* @@ -4039,6 +4040,7 @@ do_intdiv(int nargs) return make_number((AWKNUM) 0.0); } +#endif /* SUPPLY_INTDIV */ /* do_typeof --- return a string with the type of the arg */ @@ -377,6 +377,9 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS +/* enable built-in intdiv0 function */ +#undef SUPPLY_INTDIV + /* some systems define this type here */ #undef TIME_T_IN_SYS_TYPES_H @@ -766,6 +766,7 @@ enable_silent_rules with_whiny_user_strftime enable_lint enable_severe_portability_problems +enable_builtin_intdiv0 enable_mpfr enable_dependency_tracking enable_largefile @@ -1413,6 +1414,8 @@ Optional Features: --disable-lint do not compile in gawk lint checking --enable-severe-portability-problems allow really nasty portability problems + --enable-builtin-intdiv0 + enable built-in intdiv0 function --disable-mpfr do not check for MPFR --enable-dependency-tracking do not reject slow dependency extractors @@ -3245,6 +3248,21 @@ $as_echo "#define I_DONT_KNOW_WHAT_IM_DOING 1" >>confdefs.h fi +# Check whether --enable-builtin-intdiv0 was given. +if test "${enable_builtin_intdiv0+set}" = set; then : + enableval=$enable_builtin_intdiv0; if test "$enableval" = yes + then + +$as_echo "#define SUPPLY_INTDIV 1" >>confdefs.h + + sed '/^@set PATCHLEVEL/a\ +@set INTDIV' < "$srcdir"/doc/gawktexi.in > foo + cp foo "$srcdir"/doc/gawktexi.in + rm foo + fi + +fi + SKIP_MPFR=no # Check whether --enable-mpfr was given. diff --git a/configure.ac b/configure.ac index 011532f4..785f5c5b 100644 --- a/configure.ac +++ b/configure.ac @@ -67,6 +67,17 @@ AC_ARG_ENABLE([severe-portability-problems], AC_DEFINE(I_DONT_KNOW_WHAT_IM_DOING, 1, [enable severe portability problems]) fi ) +AC_ARG_ENABLE([builtin-intdiv0], + [AS_HELP_STRING([--enable-builtin-intdiv0],[enable built-in intdiv0 function])], + if test "$enableval" = yes + then + AC_DEFINE(SUPPLY_INTDIV, 1, [enable built-in intdiv0 function]) + sed '/^@set PATCHLEVEL/a\ +@set INTDIV' < "$srcdir"/doc/gawktexi.in > foo + cp foo "$srcdir"/doc/gawktexi.in + rm foo + fi +) SKIP_MPFR=no AC_ARG_ENABLE([mpfr], diff --git a/doc/ChangeLog b/doc/ChangeLog index 0ebbb091..26729b9d 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -64,6 +64,13 @@ 2017-04-16 Arnold D. Robbins <arnold@skeeve.com> + * awkcard.in: Comment out description of intdiv(). + * gawk.1: Ditto. + * gawktexi.in: References to intdiv changed to intdiv0 and + bracketed inside @ifset INTDIV. Not set by default. + +2017-04-16 Arnold D. Robbins <arnold@skeeve.com> + * gawktexi.in: Improve documentation of the intdiv() function. 2017-04-12 Arnold D. Robbins <arnold@skeeve.com> diff --git a/doc/awkcard.in b/doc/awkcard.in index 86aeee2e..165fca43 100644 --- a/doc/awkcard.in +++ b/doc/awkcard.in @@ -1617,9 +1617,9 @@ l lw(1.9i). \*(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} +.\" \*(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. @@ -2711,6 +2711,7 @@ The exponential function. .TP .BI int( expr ) Truncate to integer. +.ig .TP .BI intdiv( num ", " denom ", " result ) Truncate @@ -2728,6 +2729,7 @@ This is a .I gawk extension, primarily of value when working with arbitrarily large integers. +.. .TP .BI log( expr ) The natural logarithm function. diff --git a/doc/gawk.info b/doc/gawk.info index 41b10fda..6a339595 100644 --- a/doc/gawk.info +++ b/doc/gawk.info @@ -12400,24 +12400,6 @@ 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 'div()' - function. 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. Attempting division by zero - causes a fatal error. The function returns zero upon success, and - -1 upon error. - - 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, @@ -23223,59 +23205,7 @@ the following: 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>. +(unless the denominator evenly divides into the numerator). ---------- Footnotes ---------- @@ -27594,9 +27524,6 @@ 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 @@ -28061,8 +27988,6 @@ POSIX 'awk', in the order they were added to 'gawk'. * 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::. @@ -34474,8 +34399,6 @@ Index * instruction tracing, in debugger: Debugger Info. (line 90) * int: Numeric Functions. (line 24) * 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. @@ -34625,9 +34548,9 @@ Index * localization: I18N and L10N. (line 6) * localization, See internationalization, localization: I18N and L10N. (line 6) -* log: Numeric Functions. (line 47) +* log: Numeric Functions. (line 29) * log files, timestamps in: Time Functions. (line 6) -* logarithm: Numeric Functions. (line 47) +* logarithm: Numeric Functions. (line 29) * logical false/true: Truth Values. (line 6) * logical operators, See Boolean expressions: Boolean Ops. (line 6) * login information: Passwd Functions. (line 16) @@ -35091,12 +35014,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 52) +* rand: Numeric Functions. (line 34) * random numbers, Cliff: Cliff Random Function. (line 6) * random numbers, rand()/srand() functions: Numeric Functions. - (line 52) -* random numbers, seed of: Numeric Functions. (line 82) + (line 34) +* random numbers, seed of: Numeric Functions. (line 64) * range expressions (regexps): Bracket Expressions. (line 6) * range patterns: Ranges. (line 6) * range patterns, line continuation and: Ranges. (line 64) @@ -35274,7 +35197,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 82) +* seeding random number generator: Numeric Functions. (line 64) * semicolon (;), AWKPATH variable and: PC Using. (line 9) * semicolon (;), separating statements in actions: Statements/Lines. (line 90) @@ -35378,8 +35301,8 @@ Index * SIGUSR1 signal, for dynamic profiling: Profiling. (line 186) * silent debugger command: Debugger Execution Control. (line 10) -* sin: Numeric Functions. (line 93) -* sine: Numeric Functions. (line 93) +* sin: Numeric Functions. (line 75) +* sine: Numeric Functions. (line 75) * single quote ('): One-shot. (line 15) * single quote (') in gawk command lines: Long. (line 35) * single quote ('), in shell commands: Quoting. (line 48) @@ -35429,10 +35352,10 @@ Index * sprintf() function, OFMT variable and: User-modified. (line 116) * sprintf() function, print/printf statements and: Round Function. (line 6) -* sqrt: Numeric Functions. (line 96) +* sqrt: Numeric Functions. (line 78) * square brackets ([]), regexp operator: Regexp Operators. (line 56) -* square root: Numeric Functions. (line 96) -* srand: Numeric Functions. (line 100) +* square root: Numeric Functions. (line 78) +* srand: Numeric Functions. (line 82) * stack frame: Debugging Terms. (line 10) * Stallman, Richard: Manual History. (line 6) * Stallman, Richard <1>: Acknowledgments. (line 18) @@ -35997,341 +35920,341 @@ Node: Functions521911 Node: Built-in522949 Node: Calling Built-in524030 Node: Numeric Functions526026 -Ref: Numeric Functions-Footnote-1530971 -Ref: Numeric Functions-Footnote-2531328 -Ref: Numeric Functions-Footnote-3531376 -Node: String Functions531648 -Ref: String Functions-Footnote-1555306 -Ref: String Functions-Footnote-2555434 -Ref: String Functions-Footnote-3555682 -Node: Gory Details555769 -Ref: table-sub-escapes557560 -Ref: table-sub-proposed559079 -Ref: table-posix-sub560442 -Ref: table-gensub-escapes561983 -Ref: Gory Details-Footnote-1562806 -Node: I/O Functions562960 -Ref: table-system-return-values569542 -Ref: I/O Functions-Footnote-1571522 -Ref: I/O Functions-Footnote-2571670 -Node: Time Functions571790 -Ref: Time Functions-Footnote-1582457 -Ref: Time Functions-Footnote-2582525 -Ref: Time Functions-Footnote-3582683 -Ref: Time Functions-Footnote-4582794 -Ref: Time Functions-Footnote-5582906 -Ref: Time Functions-Footnote-6583133 -Node: Bitwise Functions583399 -Ref: table-bitwise-ops583993 -Ref: Bitwise Functions-Footnote-1590026 -Ref: Bitwise Functions-Footnote-2590199 -Node: Type Functions590390 -Node: I18N Functions593307 -Node: User-defined594958 -Node: Definition Syntax595763 -Ref: Definition Syntax-Footnote-1601450 -Node: Function Example601521 -Ref: Function Example-Footnote-1604443 -Node: Function Caveats604465 -Node: Calling A Function604983 -Node: Variable Scope605941 -Node: Pass By Value/Reference608935 -Node: Return Statement612434 -Node: Dynamic Typing615413 -Node: Indirect Calls616343 -Ref: Indirect Calls-Footnote-1626594 -Node: Functions Summary626722 -Node: Library Functions629427 -Ref: Library Functions-Footnote-1633034 -Ref: Library Functions-Footnote-2633177 -Node: Library Names633348 -Ref: Library Names-Footnote-1636808 -Ref: Library Names-Footnote-2637031 -Node: General Functions637117 -Node: Strtonum Function638220 -Node: Assert Function641242 -Node: Round Function644568 -Node: Cliff Random Function646109 -Node: Ordinal Functions647125 -Ref: Ordinal Functions-Footnote-1650188 -Ref: Ordinal Functions-Footnote-2650440 -Node: Join Function650650 -Ref: Join Function-Footnote-1652420 -Node: Getlocaltime Function652620 -Node: Readfile Function656362 -Node: Shell Quoting658334 -Node: Data File Management659735 -Node: Filetrans Function660367 -Node: Rewind Function664463 -Node: File Checking666373 -Ref: File Checking-Footnote-1667707 -Node: Empty Files667908 -Node: Ignoring Assigns669887 -Node: Getopt Function671437 -Ref: Getopt Function-Footnote-1682906 -Node: Passwd Functions683106 -Ref: Passwd Functions-Footnote-1691945 -Node: Group Functions692033 -Ref: Group Functions-Footnote-1699931 -Node: Walking Arrays700138 -Node: Library Functions Summary703146 -Node: Library Exercises704552 -Node: Sample Programs705017 -Node: Running Examples705787 -Node: Clones706515 -Node: Cut Program707739 -Node: Egrep Program717668 -Ref: Egrep Program-Footnote-1725180 -Node: Id Program725290 -Node: Split Program728970 -Ref: Split Program-Footnote-1732429 -Node: Tee Program732558 -Node: Uniq Program735348 -Node: Wc Program742774 -Ref: Wc Program-Footnote-1747029 -Node: Miscellaneous Programs747123 -Node: Dupword Program748336 -Node: Alarm Program750366 -Node: Translate Program755221 -Ref: Translate Program-Footnote-1759786 -Node: Labels Program760056 -Ref: Labels Program-Footnote-1763407 -Node: Word Sorting763491 -Node: History Sorting767563 -Node: Extract Program769398 -Node: Simple Sed776927 -Node: Igawk Program780001 -Ref: Igawk Program-Footnote-1794332 -Ref: Igawk Program-Footnote-2794534 -Ref: Igawk Program-Footnote-3794656 -Node: Anagram Program794771 -Node: Signature Program797833 -Node: Programs Summary799080 -Node: Programs Exercises800294 -Ref: Programs Exercises-Footnote-1804423 -Node: Advanced Features804514 -Node: Nondecimal Data806504 -Node: Array Sorting808095 -Node: Controlling Array Traversal808795 -Ref: Controlling Array Traversal-Footnote-1817162 -Node: Array Sorting Functions817280 -Ref: Array Sorting Functions-Footnote-1822371 -Node: Two-way I/O822567 -Ref: Two-way I/O-Footnote-1829118 -Ref: Two-way I/O-Footnote-2829305 -Node: TCP/IP Networking829387 -Node: Profiling832505 -Ref: Profiling-Footnote-1841177 -Node: Advanced Features Summary841500 -Node: Internationalization843344 -Node: I18N and L10N844824 -Node: Explaining gettext845511 -Ref: Explaining gettext-Footnote-1851403 -Ref: Explaining gettext-Footnote-2851588 -Node: Programmer i18n851753 -Ref: Programmer i18n-Footnote-1856702 -Node: Translator i18n856751 -Node: String Extraction857545 -Ref: String Extraction-Footnote-1858677 -Node: Printf Ordering858763 -Ref: Printf Ordering-Footnote-1861549 -Node: I18N Portability861613 -Ref: I18N Portability-Footnote-1864069 -Node: I18N Example864132 -Ref: I18N Example-Footnote-1866938 -Node: Gawk I18N867011 -Node: I18N Summary867656 -Node: Debugger868997 -Node: Debugging870019 -Node: Debugging Concepts870460 -Node: Debugging Terms872269 -Node: Awk Debugging874844 -Node: Sample Debugging Session875750 -Node: Debugger Invocation876284 -Node: Finding The Bug877670 -Node: List of Debugger Commands884148 -Node: Breakpoint Control885481 -Node: Debugger Execution Control889175 -Node: Viewing And Changing Data892537 -Node: Execution Stack895911 -Node: Debugger Info897548 -Node: Miscellaneous Debugger Commands901619 -Node: Readline Support906707 -Node: Limitations907603 -Node: Debugging Summary909712 -Node: Arbitrary Precision Arithmetic910991 -Node: Computer Arithmetic912476 -Ref: table-numeric-ranges916067 -Ref: Computer Arithmetic-Footnote-1916789 -Node: Math Definitions916846 -Ref: table-ieee-formats920160 -Ref: Math Definitions-Footnote-1920763 -Node: MPFR features920868 -Node: FP Math Caution922585 -Ref: FP Math Caution-Footnote-1923657 -Node: Inexactness of computations924026 -Node: Inexact representation924986 -Node: Comparing FP Values926346 -Node: Errors accumulate927428 -Node: Getting Accuracy928861 -Node: Try To Round931571 -Node: Setting precision932470 -Ref: table-predefined-precision-strings933167 -Node: Setting the rounding mode934997 -Ref: table-gawk-rounding-modes935371 -Ref: Setting the rounding mode-Footnote-1938779 -Node: Arbitrary Precision Integers938958 -Ref: Arbitrary Precision Integers-Footnote-1943863 -Node: Checking for MPFR944012 -Node: POSIX Floating Point Problems945309 -Ref: POSIX Floating Point Problems-Footnote-1949180 -Node: Floating point summary949218 -Node: Dynamic Extensions951408 -Node: Extension Intro952961 -Node: Plugin License954227 -Node: Extension Mechanism Outline955024 -Ref: figure-load-extension955463 -Ref: figure-register-new-function957028 -Ref: figure-call-new-function958120 -Node: Extension API Description960182 -Node: Extension API Functions Introduction961824 -Node: General Data Types967158 -Ref: General Data Types-Footnote-1974363 -Node: Memory Allocation Functions974662 -Ref: Memory Allocation Functions-Footnote-1977814 -Node: Constructor Functions977913 -Node: Registration Functions980912 -Node: Extension Functions981597 -Node: Exit Callback Functions986810 -Node: Extension Version String988060 -Node: Input Parsers988723 -Node: Output Wrappers1001430 -Node: Two-way processors1005942 -Node: Printing Messages1008207 -Ref: Printing Messages-Footnote-11009378 -Node: Updating ERRNO1009531 -Node: Requesting Values1010270 -Ref: table-value-types-returned1011007 -Node: Accessing Parameters1011943 -Node: Symbol Table Access1013178 -Node: Symbol table by name1013690 -Node: Symbol table by cookie1015479 -Ref: Symbol table by cookie-Footnote-11019664 -Node: Cached values1019728 -Ref: Cached values-Footnote-11023264 -Node: Array Manipulation1023355 -Ref: Array Manipulation-Footnote-11024446 -Node: Array Data Types1024483 -Ref: Array Data Types-Footnote-11027141 -Node: Array Functions1027233 -Node: Flattening Arrays1031632 -Node: Creating Arrays1038573 -Node: Redirection API1043342 -Node: Extension API Variables1046184 -Node: Extension Versioning1046817 -Ref: gawk-api-version1047254 -Node: Extension API Informational Variables1048982 -Node: Extension API Boilerplate1050046 -Node: Changes from API V11053908 -Node: Finding Extensions1054568 -Node: Extension Example1055127 -Node: Internal File Description1055925 -Node: Internal File Ops1060005 -Ref: Internal File Ops-Footnote-11071405 -Node: Using Internal File Ops1071545 -Ref: Using Internal File Ops-Footnote-11073928 -Node: Extension Samples1074202 -Node: Extension Sample File Functions1075731 -Node: Extension Sample Fnmatch1083380 -Node: Extension Sample Fork1084867 -Node: Extension Sample Inplace1086085 -Node: Extension Sample Ord1089302 -Node: Extension Sample Readdir1090138 -Ref: table-readdir-file-types1091027 -Node: Extension Sample Revout1091832 -Node: Extension Sample Rev2way1092421 -Node: Extension Sample Read write array1093161 -Node: Extension Sample Readfile1095103 -Node: Extension Sample Time1096198 -Node: Extension Sample API Tests1097546 -Node: gawkextlib1098038 -Node: Extension summary1100485 -Node: Extension Exercises1104187 -Node: Language History1105685 -Node: V7/SVR3.11107341 -Node: SVR41109493 -Node: POSIX1110927 -Node: BTL1112306 -Node: POSIX/GNU1113035 -Node: Feature History1118927 -Node: Common Extensions1133351 -Node: Ranges and Locales1134634 -Ref: Ranges and Locales-Footnote-11139250 -Ref: Ranges and Locales-Footnote-21139277 -Ref: Ranges and Locales-Footnote-31139512 -Node: Contributors1139733 -Node: History summary1145293 -Node: Installation1146673 -Node: Gawk Distribution1147617 -Node: Getting1148101 -Node: Extracting1149062 -Node: Distribution contents1150700 -Node: Unix Installation1157042 -Node: Quick Installation1157724 -Node: Shell Startup Files1160138 -Node: Additional Configuration Options1161227 -Node: Configuration Philosophy1163216 -Node: Non-Unix Installation1165585 -Node: PC Installation1166045 -Node: PC Binary Installation1166883 -Node: PC Compiling1167318 -Node: PC Using1168435 -Node: Cygwin1171480 -Node: MSYS1172250 -Node: VMS Installation1172751 -Node: VMS Compilation1173542 -Ref: VMS Compilation-Footnote-11174771 -Node: VMS Dynamic Extensions1174829 -Node: VMS Installation Details1176514 -Node: VMS Running1178767 -Node: VMS GNV1183046 -Node: VMS Old Gawk1183781 -Node: Bugs1184252 -Node: Bug address1184915 -Node: Usenet1187312 -Node: Maintainers1188089 -Node: Other Versions1189465 -Node: Installation summary1196049 -Node: Notes1197084 -Node: Compatibility Mode1197949 -Node: Additions1198731 -Node: Accessing The Source1199656 -Node: Adding Code1201091 -Node: New Ports1207309 -Node: Derived Files1211797 -Ref: Derived Files-Footnote-11217282 -Ref: Derived Files-Footnote-21217317 -Ref: Derived Files-Footnote-31217915 -Node: Future Extensions1218029 -Node: Implementation Limitations1218687 -Node: Extension Design1219870 -Node: Old Extension Problems1221024 -Ref: Old Extension Problems-Footnote-11222542 -Node: Extension New Mechanism Goals1222599 -Ref: Extension New Mechanism Goals-Footnote-11225963 -Node: Extension Other Design Decisions1226152 -Node: Extension Future Growth1228265 -Node: Old Extension Mechanism1229101 -Node: Notes summary1230864 -Node: Basic Concepts1232046 -Node: Basic High Level1232727 -Ref: figure-general-flow1233009 -Ref: figure-process-flow1233694 -Ref: Basic High Level-Footnote-11236995 -Node: Basic Data Typing1237180 -Node: Glossary1240508 -Node: Copying1272455 -Node: GNU Free Documentation License1309994 -Node: Index1335112 +Ref: Numeric Functions-Footnote-1530054 +Ref: Numeric Functions-Footnote-2530411 +Ref: Numeric Functions-Footnote-3530459 +Node: String Functions530731 +Ref: String Functions-Footnote-1554389 +Ref: String Functions-Footnote-2554517 +Ref: String Functions-Footnote-3554765 +Node: Gory Details554852 +Ref: table-sub-escapes556643 +Ref: table-sub-proposed558162 +Ref: table-posix-sub559525 +Ref: table-gensub-escapes561066 +Ref: Gory Details-Footnote-1561889 +Node: I/O Functions562043 +Ref: table-system-return-values568625 +Ref: I/O Functions-Footnote-1570605 +Ref: I/O Functions-Footnote-2570753 +Node: Time Functions570873 +Ref: Time Functions-Footnote-1581540 +Ref: Time Functions-Footnote-2581608 +Ref: Time Functions-Footnote-3581766 +Ref: Time Functions-Footnote-4581877 +Ref: Time Functions-Footnote-5581989 +Ref: Time Functions-Footnote-6582216 +Node: Bitwise Functions582482 +Ref: table-bitwise-ops583076 +Ref: Bitwise Functions-Footnote-1589109 +Ref: Bitwise Functions-Footnote-2589282 +Node: Type Functions589473 +Node: I18N Functions592390 +Node: User-defined594041 +Node: Definition Syntax594846 +Ref: Definition Syntax-Footnote-1600533 +Node: Function Example600604 +Ref: Function Example-Footnote-1603526 +Node: Function Caveats603548 +Node: Calling A Function604066 +Node: Variable Scope605024 +Node: Pass By Value/Reference608018 +Node: Return Statement611517 +Node: Dynamic Typing614496 +Node: Indirect Calls615426 +Ref: Indirect Calls-Footnote-1625677 +Node: Functions Summary625805 +Node: Library Functions628510 +Ref: Library Functions-Footnote-1632117 +Ref: Library Functions-Footnote-2632260 +Node: Library Names632431 +Ref: Library Names-Footnote-1635891 +Ref: Library Names-Footnote-2636114 +Node: General Functions636200 +Node: Strtonum Function637303 +Node: Assert Function640325 +Node: Round Function643651 +Node: Cliff Random Function645192 +Node: Ordinal Functions646208 +Ref: Ordinal Functions-Footnote-1649271 +Ref: Ordinal Functions-Footnote-2649523 +Node: Join Function649733 +Ref: Join Function-Footnote-1651503 +Node: Getlocaltime Function651703 +Node: Readfile Function655445 +Node: Shell Quoting657417 +Node: Data File Management658818 +Node: Filetrans Function659450 +Node: Rewind Function663546 +Node: File Checking665456 +Ref: File Checking-Footnote-1666790 +Node: Empty Files666991 +Node: Ignoring Assigns668970 +Node: Getopt Function670520 +Ref: Getopt Function-Footnote-1681989 +Node: Passwd Functions682189 +Ref: Passwd Functions-Footnote-1691028 +Node: Group Functions691116 +Ref: Group Functions-Footnote-1699014 +Node: Walking Arrays699221 +Node: Library Functions Summary702229 +Node: Library Exercises703635 +Node: Sample Programs704100 +Node: Running Examples704870 +Node: Clones705598 +Node: Cut Program706822 +Node: Egrep Program716751 +Ref: Egrep Program-Footnote-1724263 +Node: Id Program724373 +Node: Split Program728053 +Ref: Split Program-Footnote-1731512 +Node: Tee Program731641 +Node: Uniq Program734431 +Node: Wc Program741857 +Ref: Wc Program-Footnote-1746112 +Node: Miscellaneous Programs746206 +Node: Dupword Program747419 +Node: Alarm Program749449 +Node: Translate Program754304 +Ref: Translate Program-Footnote-1758869 +Node: Labels Program759139 +Ref: Labels Program-Footnote-1762490 +Node: Word Sorting762574 +Node: History Sorting766646 +Node: Extract Program768481 +Node: Simple Sed776010 +Node: Igawk Program779084 +Ref: Igawk Program-Footnote-1793415 +Ref: Igawk Program-Footnote-2793617 +Ref: Igawk Program-Footnote-3793739 +Node: Anagram Program793854 +Node: Signature Program796916 +Node: Programs Summary798163 +Node: Programs Exercises799377 +Ref: Programs Exercises-Footnote-1803506 +Node: Advanced Features803597 +Node: Nondecimal Data805587 +Node: Array Sorting807178 +Node: Controlling Array Traversal807878 +Ref: Controlling Array Traversal-Footnote-1816245 +Node: Array Sorting Functions816363 +Ref: Array Sorting Functions-Footnote-1821454 +Node: Two-way I/O821650 +Ref: Two-way I/O-Footnote-1828201 +Ref: Two-way I/O-Footnote-2828388 +Node: TCP/IP Networking828470 +Node: Profiling831588 +Ref: Profiling-Footnote-1840260 +Node: Advanced Features Summary840583 +Node: Internationalization842427 +Node: I18N and L10N843907 +Node: Explaining gettext844594 +Ref: Explaining gettext-Footnote-1850486 +Ref: Explaining gettext-Footnote-2850671 +Node: Programmer i18n850836 +Ref: Programmer i18n-Footnote-1855785 +Node: Translator i18n855834 +Node: String Extraction856628 +Ref: String Extraction-Footnote-1857760 +Node: Printf Ordering857846 +Ref: Printf Ordering-Footnote-1860632 +Node: I18N Portability860696 +Ref: I18N Portability-Footnote-1863152 +Node: I18N Example863215 +Ref: I18N Example-Footnote-1866021 +Node: Gawk I18N866094 +Node: I18N Summary866739 +Node: Debugger868080 +Node: Debugging869102 +Node: Debugging Concepts869543 +Node: Debugging Terms871352 +Node: Awk Debugging873927 +Node: Sample Debugging Session874833 +Node: Debugger Invocation875367 +Node: Finding The Bug876753 +Node: List of Debugger Commands883231 +Node: Breakpoint Control884564 +Node: Debugger Execution Control888258 +Node: Viewing And Changing Data891620 +Node: Execution Stack894994 +Node: Debugger Info896631 +Node: Miscellaneous Debugger Commands900702 +Node: Readline Support905790 +Node: Limitations906686 +Node: Debugging Summary908795 +Node: Arbitrary Precision Arithmetic910074 +Node: Computer Arithmetic911559 +Ref: table-numeric-ranges915150 +Ref: Computer Arithmetic-Footnote-1915872 +Node: Math Definitions915929 +Ref: table-ieee-formats919243 +Ref: Math Definitions-Footnote-1919846 +Node: MPFR features919951 +Node: FP Math Caution921668 +Ref: FP Math Caution-Footnote-1922740 +Node: Inexactness of computations923109 +Node: Inexact representation924069 +Node: Comparing FP Values925429 +Node: Errors accumulate926511 +Node: Getting Accuracy927944 +Node: Try To Round930654 +Node: Setting precision931553 +Ref: table-predefined-precision-strings932250 +Node: Setting the rounding mode934080 +Ref: table-gawk-rounding-modes934454 +Ref: Setting the rounding mode-Footnote-1937862 +Node: Arbitrary Precision Integers938041 +Ref: Arbitrary Precision Integers-Footnote-1941216 +Node: Checking for MPFR941365 +Node: POSIX Floating Point Problems942662 +Ref: POSIX Floating Point Problems-Footnote-1946533 +Node: Floating point summary946571 +Node: Dynamic Extensions948761 +Node: Extension Intro950314 +Node: Plugin License951580 +Node: Extension Mechanism Outline952377 +Ref: figure-load-extension952816 +Ref: figure-register-new-function954381 +Ref: figure-call-new-function955473 +Node: Extension API Description957535 +Node: Extension API Functions Introduction959177 +Node: General Data Types964511 +Ref: General Data Types-Footnote-1971716 +Node: Memory Allocation Functions972015 +Ref: Memory Allocation Functions-Footnote-1975167 +Node: Constructor Functions975266 +Node: Registration Functions978265 +Node: Extension Functions978950 +Node: Exit Callback Functions984163 +Node: Extension Version String985413 +Node: Input Parsers986076 +Node: Output Wrappers998783 +Node: Two-way processors1003295 +Node: Printing Messages1005560 +Ref: Printing Messages-Footnote-11006731 +Node: Updating ERRNO1006884 +Node: Requesting Values1007623 +Ref: table-value-types-returned1008360 +Node: Accessing Parameters1009296 +Node: Symbol Table Access1010531 +Node: Symbol table by name1011043 +Node: Symbol table by cookie1012832 +Ref: Symbol table by cookie-Footnote-11017017 +Node: Cached values1017081 +Ref: Cached values-Footnote-11020617 +Node: Array Manipulation1020708 +Ref: Array Manipulation-Footnote-11021799 +Node: Array Data Types1021836 +Ref: Array Data Types-Footnote-11024494 +Node: Array Functions1024586 +Node: Flattening Arrays1028985 +Node: Creating Arrays1035926 +Node: Redirection API1040695 +Node: Extension API Variables1043537 +Node: Extension Versioning1044170 +Ref: gawk-api-version1044607 +Node: Extension API Informational Variables1046335 +Node: Extension API Boilerplate1047399 +Node: Changes from API V11051261 +Node: Finding Extensions1051921 +Node: Extension Example1052480 +Node: Internal File Description1053278 +Node: Internal File Ops1057358 +Ref: Internal File Ops-Footnote-11068758 +Node: Using Internal File Ops1068898 +Ref: Using Internal File Ops-Footnote-11071281 +Node: Extension Samples1071555 +Node: Extension Sample File Functions1073084 +Node: Extension Sample Fnmatch1080733 +Node: Extension Sample Fork1082220 +Node: Extension Sample Inplace1083438 +Node: Extension Sample Ord1086655 +Node: Extension Sample Readdir1087491 +Ref: table-readdir-file-types1088380 +Node: Extension Sample Revout1089185 +Node: Extension Sample Rev2way1089774 +Node: Extension Sample Read write array1090514 +Node: Extension Sample Readfile1092456 +Node: Extension Sample Time1093551 +Node: Extension Sample API Tests1094899 +Node: gawkextlib1095391 +Node: Extension summary1097838 +Node: Extension Exercises1101540 +Node: Language History1103038 +Node: V7/SVR3.11104694 +Node: SVR41106846 +Node: POSIX1108280 +Node: BTL1109659 +Node: POSIX/GNU1110388 +Node: Feature History1116166 +Node: Common Extensions1130531 +Node: Ranges and Locales1131814 +Ref: Ranges and Locales-Footnote-11136430 +Ref: Ranges and Locales-Footnote-21136457 +Ref: Ranges and Locales-Footnote-31136692 +Node: Contributors1136913 +Node: History summary1142473 +Node: Installation1143853 +Node: Gawk Distribution1144797 +Node: Getting1145281 +Node: Extracting1146242 +Node: Distribution contents1147880 +Node: Unix Installation1154222 +Node: Quick Installation1154904 +Node: Shell Startup Files1157318 +Node: Additional Configuration Options1158407 +Node: Configuration Philosophy1160396 +Node: Non-Unix Installation1162765 +Node: PC Installation1163225 +Node: PC Binary Installation1164063 +Node: PC Compiling1164498 +Node: PC Using1165615 +Node: Cygwin1168660 +Node: MSYS1169430 +Node: VMS Installation1169931 +Node: VMS Compilation1170722 +Ref: VMS Compilation-Footnote-11171951 +Node: VMS Dynamic Extensions1172009 +Node: VMS Installation Details1173694 +Node: VMS Running1175947 +Node: VMS GNV1180226 +Node: VMS Old Gawk1180961 +Node: Bugs1181432 +Node: Bug address1182095 +Node: Usenet1184492 +Node: Maintainers1185269 +Node: Other Versions1186645 +Node: Installation summary1193229 +Node: Notes1194264 +Node: Compatibility Mode1195129 +Node: Additions1195911 +Node: Accessing The Source1196836 +Node: Adding Code1198271 +Node: New Ports1204489 +Node: Derived Files1208977 +Ref: Derived Files-Footnote-11214462 +Ref: Derived Files-Footnote-21214497 +Ref: Derived Files-Footnote-31215095 +Node: Future Extensions1215209 +Node: Implementation Limitations1215867 +Node: Extension Design1217050 +Node: Old Extension Problems1218204 +Ref: Old Extension Problems-Footnote-11219722 +Node: Extension New Mechanism Goals1219779 +Ref: Extension New Mechanism Goals-Footnote-11223143 +Node: Extension Other Design Decisions1223332 +Node: Extension Future Growth1225445 +Node: Old Extension Mechanism1226281 +Node: Notes summary1228044 +Node: Basic Concepts1229226 +Node: Basic High Level1229907 +Ref: figure-general-flow1230189 +Ref: figure-process-flow1230874 +Ref: Basic High Level-Footnote-11234175 +Node: Basic Data Typing1234360 +Node: Glossary1237688 +Node: Copying1269635 +Node: GNU Free Documentation License1307174 +Node: Index1332292 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index 66312691..ae389448 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -17566,9 +17566,10 @@ 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 +@ifset INTDIV +@item @code{intdiv0(@var{numerator}, @var{denominator}, @var{result})} +@cindexawkfunc{intdiv0} +@cindex intdiv0 Perform integer division, similar to the standard C @code{div()} function. First, truncate @code{numerator} and @code{denominator} towards zero, creating integer values. Clear the @code{result} @@ -17586,6 +17587,7 @@ Precision Integers}). This function is a @code{gawk} extension. It is not available in compatibility mode (@pxref{Options}). +@end ifset @item @code{log(@var{x})} @cindexawkfunc{log} @@ -32023,16 +32025,18 @@ gawk -M 'BEGIN @{ n = 13; print n % 2 @}' 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 +divides into the numerator). +@ifset INTDIV +In order to do integer division or remainder with arbitrary precision integers, use the built-in -@code{intdiv()} function (@pxref{Numeric Functions}). +@code{intdiv0()} function (@pxref{Numeric Functions}). -You can simulate the @code{intdiv()} function in standard @command{awk} +You can simulate the @code{intdiv0()} function in standard @command{awk} using this user-defined function: @example @c file eg/lib/intdiv.awk -# intdiv --- do integer division +# intdiv0 --- do integer division @c endfile @ignore @@ -32043,12 +32047,15 @@ using this user-defined function: # # Name changed from div() to intdiv() # April, 2015 +# +# Changed to intdiv0() +# April, 2016 @c endfile @end ignore @c file eg/lib/intdiv.awk -function intdiv(numerator, denominator, result) +function intdiv0(numerator, denominator, result) @{ split("", result) @@ -32135,6 +32142,7 @@ 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 +@end ifset @node Checking for MPFR @section How To Check If MPFR Is Available @@ -37275,10 +37283,12 @@ The @code{bindtextdomain()}, @code{dcgettext()}, and @code{dcngettext()} functions for internationalization (@pxref{Programmer i18n}) +@ifset INTDIV @item -The @code{intdiv()} function for doing integer +The @code{intdiv0()} function for doing integer division and remainder (@pxref{Numeric Functions}) +@end ifset @end itemize @item @@ -38074,9 +38084,11 @@ The @command{igawk} program and its manual page are no longer installed when @command{gawk} is built. @xref{Igawk Program}. +@ifset INTDIV @item -The @code{intdiv()} function. +The @code{intdiv0()} function. @xref{Numeric Functions}. +@end ifset @item The maximum number of hexadecimal digits in @samp{\x} escapes diff --git a/doc/gawktexi.in b/doc/gawktexi.in index f7d396bf..76e91b31 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -16839,9 +16839,10 @@ 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 +@ifset INTDIV +@item @code{intdiv0(@var{numerator}, @var{denominator}, @var{result})} +@cindexawkfunc{intdiv0} +@cindex intdiv0 Perform integer division, similar to the standard C @code{div()} function. First, truncate @code{numerator} and @code{denominator} towards zero, creating integer values. Clear the @code{result} @@ -16859,6 +16860,7 @@ Precision Integers}). This function is a @code{gawk} extension. It is not available in compatibility mode (@pxref{Options}). +@end ifset @item @code{log(@var{x})} @cindexawkfunc{log} @@ -31037,16 +31039,18 @@ gawk -M 'BEGIN @{ n = 13; print n % 2 @}' 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 +divides into the numerator). +@ifset INTDIV +In order to do integer division or remainder with arbitrary precision integers, use the built-in -@code{intdiv()} function (@pxref{Numeric Functions}). +@code{intdiv0()} function (@pxref{Numeric Functions}). -You can simulate the @code{intdiv()} function in standard @command{awk} +You can simulate the @code{intdiv0()} function in standard @command{awk} using this user-defined function: @example @c file eg/lib/intdiv.awk -# intdiv --- do integer division +# intdiv0 --- do integer division @c endfile @ignore @@ -31057,12 +31061,15 @@ using this user-defined function: # # Name changed from div() to intdiv() # April, 2015 +# +# Changed to intdiv0() +# April, 2016 @c endfile @end ignore @c file eg/lib/intdiv.awk -function intdiv(numerator, denominator, result) +function intdiv0(numerator, denominator, result) @{ split("", result) @@ -31149,6 +31156,7 @@ 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 +@end ifset @node Checking for MPFR @section How To Check If MPFR Is Available @@ -36289,10 +36297,12 @@ The @code{bindtextdomain()}, @code{dcgettext()}, and @code{dcngettext()} functions for internationalization (@pxref{Programmer i18n}) +@ifset INTDIV @item -The @code{intdiv()} function for doing integer +The @code{intdiv0()} function for doing integer division and remainder (@pxref{Numeric Functions}) +@end ifset @end itemize @item @@ -37088,9 +37098,11 @@ The @command{igawk} program and its manual page are no longer installed when @command{gawk} is built. @xref{Igawk Program}. +@ifset INTDIV @item -The @code{intdiv()} function. +The @code{intdiv0()} function. @xref{Numeric Functions}. +@end ifset @item The maximum number of hexadecimal digits in @samp{\x} escapes diff --git a/extension/ChangeLog b/extension/ChangeLog index 8e6daab6..b7643571 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -2,6 +2,11 @@ * Makefile.am: Update copyright year. +2017-06-27 Arnold D. Robbins <arnold@skeeve.com> + + * Makfile.am (intdiv_la_LIBADD): Add LIBMPFR for Cygwin. + Thanks to Eli Zaretskii for the tip that this is necessary. + 2017-06-22 Andrew J. Schorr <aschorr@telemetry-investments.com> * rwarray.c (read_value): Use malloc instead of calloc, since @@ -22,6 +27,26 @@ * gawkfts.c (fts_open): Replace malloc+memset with calloc. * rwarray0.c (read_value): Ditto. +2017-04-16 Arnold D. Robbins <arnold@skeeve.com> + + * intdiv.c (func_table): Function is now named intdiv. + +2017-04-14 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * intdiv.c (do_intdiv): On division by zero, return -1 and issue a + warning instead of throwing a fatal error. + +2017-04-13 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * intdiv.c (do_intdiv): On a division by zero fatal error, there's + no need to clear the numerator and denominator and add a fake return. + +2017-04-13 Arnold D. Robbins <arnold@skeeve.com> + + * configure.ac: Alphabetize function list in AC_CHECK_FUNCS. + * intdiv.c: Add descriptive comments to some functions. + (do_intdiv): Make division by zero fatal in MPFR case. + 2017-04-03 Arnold D. Robbins <arnold@skeeve.com> * inplace.c (inplace_end): Correct the function name in the @@ -88,6 +113,16 @@ system headers assume that if this is defined, it must have a numeric value. +2017-01-06 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * intdiv.c: New extension to demonstrate how to implement intdiv + using the new extended-precision math API. + * Makefile.am (pkgextension_LTLIBRARIES): Add intdiv.la. + (intdiv_la_SOURCES, intdiv_la_LDFLAGS, intdiv_la_LIBADD): Add support + for new intdiv library. + * configure.ac (AC_CHECK_FUNCS): Check for fmod needed by intdiv. + (GNUPG_CHECK_MPFR): Add check for MPFR support. + 2016-12-22 Arnold D. Robbins <arnold@skeeve.com> * testext.c (valrep2str): Update for new API types. diff --git a/extension/Makefile.am b/extension/Makefile.am index 92787923..147da40a 100644 --- a/extension/Makefile.am +++ b/extension/Makefile.am @@ -39,6 +39,7 @@ pkgextension_LTLIBRARIES = \ fnmatch.la \ fork.la \ inplace.la \ + intdiv.la \ ordchr.la \ readdir.la \ readfile.la \ @@ -52,7 +53,7 @@ noinst_LTLIBRARIES = \ testext.la MY_MODULE_FLAGS = -module -avoid-version -no-undefined -# on Cygwin, gettext requires that we link with -lintl +# On Cygwin, gettext requires that we link with -lintl MY_LIBS = $(LTLIBINTL) filefuncs_la_SOURCES = filefuncs.c stack.h stack.c gawkfts.h \ @@ -72,6 +73,11 @@ inplace_la_SOURCES = inplace.c inplace_la_LDFLAGS = $(MY_MODULE_FLAGS) inplace_la_LIBADD = $(MY_LIBS) +# On Cygwin, intdiv has to be linked with the MPFR and GMP libraries +intdiv_la_SOURCES = intdiv.c +intdiv_la_LDFLAGS = $(MY_MODULE_FLAGS) +intdiv_la_LIBADD = $(MY_LIBS) $(LIBMPFR) + ordchr_la_SOURCES = ordchr.c ordchr_la_LDFLAGS = $(MY_MODULE_FLAGS) ordchr_la_LIBADD = $(MY_LIBS) diff --git a/extension/Makefile.in b/extension/Makefile.in index f6e5abd1..917618cb 100644 --- a/extension/Makefile.in +++ b/extension/Makefile.in @@ -114,10 +114,10 @@ host_triplet = @host@ subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../m4/arch.m4 \ - $(top_srcdir)/m4/dirfd.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/../m4/mpfr.m4 $(top_srcdir)/m4/dirfd.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ @@ -187,6 +187,12 @@ inplace_la_OBJECTS = $(am_inplace_la_OBJECTS) inplace_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(inplace_la_LDFLAGS) $(LDFLAGS) -o $@ +intdiv_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_intdiv_la_OBJECTS = intdiv.lo +intdiv_la_OBJECTS = $(am_intdiv_la_OBJECTS) +intdiv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(intdiv_la_LDFLAGS) $(LDFLAGS) -o $@ ordchr_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_ordchr_la_OBJECTS = ordchr.lo ordchr_la_OBJECTS = $(am_ordchr_la_OBJECTS) @@ -277,17 +283,17 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \ - $(fork_la_SOURCES) $(inplace_la_SOURCES) $(ordchr_la_SOURCES) \ - $(readdir_la_SOURCES) $(readdir_test_la_SOURCES) \ - $(readfile_la_SOURCES) $(revoutput_la_SOURCES) \ - $(revtwoway_la_SOURCES) $(rwarray_la_SOURCES) \ - $(testext_la_SOURCES) $(time_la_SOURCES) + $(fork_la_SOURCES) $(inplace_la_SOURCES) $(intdiv_la_SOURCES) \ + $(ordchr_la_SOURCES) $(readdir_la_SOURCES) \ + $(readdir_test_la_SOURCES) $(readfile_la_SOURCES) \ + $(revoutput_la_SOURCES) $(revtwoway_la_SOURCES) \ + $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES) DIST_SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \ - $(fork_la_SOURCES) $(inplace_la_SOURCES) $(ordchr_la_SOURCES) \ - $(readdir_la_SOURCES) $(readdir_test_la_SOURCES) \ - $(readfile_la_SOURCES) $(revoutput_la_SOURCES) \ - $(revtwoway_la_SOURCES) $(rwarray_la_SOURCES) \ - $(testext_la_SOURCES) $(time_la_SOURCES) + $(fork_la_SOURCES) $(inplace_la_SOURCES) $(intdiv_la_SOURCES) \ + $(ordchr_la_SOURCES) $(readdir_la_SOURCES) \ + $(readdir_test_la_SOURCES) $(readfile_la_SOURCES) \ + $(revoutput_la_SOURCES) $(revtwoway_la_SOURCES) \ + $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ @@ -422,6 +428,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBMPFR = @LIBMPFR@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ @@ -520,6 +527,7 @@ pkgextension_LTLIBRARIES = \ fnmatch.la \ fork.la \ inplace.la \ + intdiv.la \ ordchr.la \ readdir.la \ readfile.la \ @@ -533,7 +541,7 @@ noinst_LTLIBRARIES = \ testext.la MY_MODULE_FLAGS = -module -avoid-version -no-undefined -# on Cygwin, gettext requires that we link with -lintl +# On Cygwin, gettext requires that we link with -lintl MY_LIBS = $(LTLIBINTL) filefuncs_la_SOURCES = filefuncs.c stack.h stack.c gawkfts.h \ gawkfts.c gawkdirfd.h @@ -549,6 +557,11 @@ fork_la_LIBADD = $(MY_LIBS) inplace_la_SOURCES = inplace.c inplace_la_LDFLAGS = $(MY_MODULE_FLAGS) inplace_la_LIBADD = $(MY_LIBS) + +# On Cygwin, intdiv has to be linked with the MPFR and GMP libraries +intdiv_la_SOURCES = intdiv.c +intdiv_la_LDFLAGS = $(MY_MODULE_FLAGS) +intdiv_la_LIBADD = $(MY_LIBS) $(LIBMPFR) ordchr_la_SOURCES = ordchr.c ordchr_la_LDFLAGS = $(MY_MODULE_FLAGS) ordchr_la_LIBADD = $(MY_LIBS) @@ -713,6 +726,9 @@ fork.la: $(fork_la_OBJECTS) $(fork_la_DEPENDENCIES) $(EXTRA_fork_la_DEPENDENCIES inplace.la: $(inplace_la_OBJECTS) $(inplace_la_DEPENDENCIES) $(EXTRA_inplace_la_DEPENDENCIES) $(AM_V_CCLD)$(inplace_la_LINK) -rpath $(pkgextensiondir) $(inplace_la_OBJECTS) $(inplace_la_LIBADD) $(LIBS) +intdiv.la: $(intdiv_la_OBJECTS) $(intdiv_la_DEPENDENCIES) $(EXTRA_intdiv_la_DEPENDENCIES) + $(AM_V_CCLD)$(intdiv_la_LINK) -rpath $(pkgextensiondir) $(intdiv_la_OBJECTS) $(intdiv_la_LIBADD) $(LIBS) + ordchr.la: $(ordchr_la_OBJECTS) $(ordchr_la_DEPENDENCIES) $(EXTRA_ordchr_la_DEPENDENCIES) $(AM_V_CCLD)$(ordchr_la_LINK) -rpath $(pkgextensiondir) $(ordchr_la_OBJECTS) $(ordchr_la_LIBADD) $(LIBS) @@ -751,6 +767,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fork.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gawkfts.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inplace.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intdiv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ordchr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdir_test.Plo@am__quote@ diff --git a/extension/aclocal.m4 b/extension/aclocal.m4 index 5665d48e..1e7a343c 100644 --- a/extension/aclocal.m4 +++ b/extension/aclocal.m4 @@ -1211,6 +1211,7 @@ AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([../m4/arch.m4]) +m4_include([../m4/mpfr.m4]) m4_include([m4/dirfd.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) diff --git a/extension/configh.in b/extension/configh.in index d3a226a5..9d3d9919 100644 --- a/extension/configh.in +++ b/extension/configh.in @@ -27,6 +27,9 @@ /* Define to 1 if you have the `fdopendir' function. */ #undef HAVE_FDOPENDIR +/* Define to 1 if you have the `fmod' function. */ +#undef HAVE_FMOD + /* Define to 1 if you have the `fnmatch' function. */ #undef HAVE_FNMATCH @@ -51,6 +54,9 @@ /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have fully functional mpfr and gmp libraries. */ +#undef HAVE_MPFR + /* Define to 1 if you have the `nanosleep' function. */ #undef HAVE_NANOSLEEP diff --git a/extension/configure b/extension/configure index 40601550..7ae66543 100755 --- a/extension/configure +++ b/extension/configure @@ -635,6 +635,7 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS +LIBMPFR pkgextensiondir LT_SYS_LIBRARY_PATH OTOOL64 @@ -763,6 +764,7 @@ with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock +with_mpfr ' ac_precious_vars='build_alias host_alias @@ -1416,6 +1418,7 @@ Optional Packages: --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). + --with-mpfr=DIR look for the mpfr and gmp libraries in DIR Some influential environment variables: CC C compiler command @@ -12859,8 +12862,89 @@ $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi -for ac_func in fdopendir fnmatch gettimeofday \ - getdtablesize nanosleep select statvfs GetSystemTimeAsFileTime +case `uname -m` in +*'Power Macintosh'*) + : ;; +*) + + +# Check whether --with-mpfr was given. +if test "${with_mpfr+set}" = set; then : + withval=$with_mpfr; _do_mpfr=$withval +else + _do_mpfr=yes +fi + + + if test "$_do_mpfr" != "no" ; then + if test -d "$withval" ; then + CPPFLAGS="${CPPFLAGS} -I$withval/include" + LDFLAGS="${LDFLAGS} -L$withval/lib" + fi + + _mpfr_save_libs=$LIBS + _combo="-lmpfr -lgmp" + LIBS="$LIBS $_combo" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mpfr via \"$_combo\" is present and usable" >&5 +$as_echo_n "checking whether mpfr via \"$_combo\" is present and usable... " >&6; } + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +#include <stdio.h> +#include <mpfr.h> +#include <gmp.h> + +int +main () +{ + +mpfr_t p; +mpz_t z; +mpfr_init(p); +mpz_init(z); +mpfr_printf("%Rf%Zd", p, z); +mpfr_clear(p); +mpz_clear(z); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + _found_mpfr=yes +else + _found_mpfr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_found_mpfr" >&5 +$as_echo "$_found_mpfr" >&6; } + + LIBS=$_mpfr_save_libs + + if test $_found_mpfr = yes ; then + +$as_echo "#define HAVE_MPFR 1" >>confdefs.h + + LIBMPFR=$_combo + + break + fi + + unset _mpfr_save_libs + unset _combo + unset _found_mpfr + fi + + ;; +esac + +for ac_func in fdopendir fmod fnmatch getdtablesize \ + gettimeofday nanosleep select statvfs GetSystemTimeAsFileTime do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/extension/configure.ac b/extension/configure.ac index b5b27d03..bde6e3d3 100644 --- a/extension/configure.ac +++ b/extension/configure.ac @@ -69,8 +69,17 @@ AC_HEADER_DIRENT AC_HEADER_MAJOR AC_HEADER_TIME -AC_CHECK_FUNCS(fdopendir fnmatch gettimeofday \ - getdtablesize nanosleep select statvfs GetSystemTimeAsFileTime) +dnl check for mpfr support +case `uname -m` in +*'Power Macintosh'*) + : ;; +*) + GNUPG_CHECK_MPFR + ;; +esac + +AC_CHECK_FUNCS(fdopendir fmod fnmatch getdtablesize \ + gettimeofday nanosleep select statvfs GetSystemTimeAsFileTime) GAWK_FUNC_DIRFD GAWK_PREREQ_DIRFD diff --git a/extension/intdiv.c b/extension/intdiv.c new file mode 100644 index 00000000..77b4290b --- /dev/null +++ b/extension/intdiv.c @@ -0,0 +1,215 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <math.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#include "gawkapi.h" + +#ifdef HAVE_MPFR +#include <gmp.h> +#include <mpfr.h> +#endif + +#include "gettext.h" +#define _(msgid) gettext(msgid) +#define N_(msgid) msgid + +static const gawk_api_t *api; /* for convenience macros to work */ +static awk_ext_id_t *ext_id; +static const char *ext_version = "intdiv extension: version 1.0"; + +int plugin_is_GPL_compatible; + +/* double_to_int --- get the integer part of a double */ + +static double +double_to_int(double d) +{ + if (d >= 0) + d = floor(d); + else + d = ceil(d); + return d; +} + +/* array_set_number --- set an array element to a numeric value */ + +static void +array_set_number(awk_array_t array, const char *sub, size_t sublen, double num) +{ + awk_value_t index, tmp; + + set_array_element(array, make_const_string(sub, sublen, & index), make_number(num, & tmp)); +} + +#ifdef HAVE_MPFR + +/* mpz_conv --- convert an awk_value_t to an MPZ value */ + +static mpz_ptr +mpz_conv(const awk_value_t *arg, mpz_ptr tmp) +{ + switch (arg->num_type) { + case AWK_NUMBER_TYPE_MPZ: + return arg->num_ptr; + case AWK_NUMBER_TYPE_MPFR: + if (! mpfr_number_p(arg->num_ptr)) + return NULL; + mpz_init(tmp); + mpfr_get_z(tmp, arg->num_ptr, MPFR_RNDZ); + return tmp; + case AWK_NUMBER_TYPE_DOUBLE: /* can this happen? */ + mpz_init(tmp); + mpz_set_d(tmp, double_to_int(arg->num_value)); + return tmp; + default: /* should never happen */ + fatal(ext_id, _("intdiv: invalid numeric type `%d'"), arg->num_type); + return NULL; + } +} + +/* array_set_mpz --- set an array element to an MPZ value */ + +static void +array_set_mpz(awk_array_t array, const char *sub, size_t sublen, mpz_ptr num) +{ + awk_value_t index, tmp; + + set_array_element(array, make_const_string(sub, sublen, & index), make_number_mpz(num, & tmp)); +} + +#endif + +/* 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) + */ + +static awk_value_t * +do_intdiv(int nargs, awk_value_t *result, struct awk_ext_func *unused) +{ + awk_value_t nv, dv, array_param; + awk_array_t array; + + if (! get_argument(0, AWK_NUMBER, & nv)) { + warning(ext_id, _("intdiv: first argument must be numeric")); + return make_number(-1, result); + } + if (! get_argument(1, AWK_NUMBER, & dv)) { + warning(ext_id, _("intdiv: second argument must be numeric")); + return make_number(-1, result); + } + if (! get_argument(2, AWK_ARRAY, & array_param)) { + warning(ext_id, _("intdiv: third argument must be an array")); + return make_number(-1, result); + } + array = array_param.array_cookie; + clear_array(array); + +#ifdef HAVE_MPFR + if (nv.num_type == AWK_NUMBER_TYPE_DOUBLE && dv.num_type == AWK_NUMBER_TYPE_DOUBLE) { +#endif + /* regular precision */ + double num, denom, quotient, remainder; + + num = double_to_int(nv.num_value); + denom = double_to_int(dv.num_value); + + if (denom == 0.0) { + warning(ext_id, _("intdiv: division by zero attempted")); + return make_number(-1, result); + } + + quotient = double_to_int(num / denom); +#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); + + array_set_number(array, "quotient", 8, quotient); + array_set_number(array, "remainder", 9, remainder); +#ifdef HAVE_MPFR + } else { + /* extended precision */ + mpz_ptr numer, denom; + mpz_t numer_tmp, denom_tmp; + mpz_ptr quotient, remainder; + + /* convert numerator and denominator to integer */ + if (!(numer = mpz_conv(&nv, numer_tmp))) { + warning(ext_id, _("intdiv: numerator is not finite")); + return make_number(-1, result); + } + if (!(denom = mpz_conv(&dv, denom_tmp))) { + warning(ext_id, _("intdiv: denominator is not finite")); + if (numer == numer_tmp) + mpz_clear(numer); + return make_number(-1, result); + } + if (mpz_sgn(denom) == 0) { + warning(ext_id, _("intdiv: division by zero attempted")); + if (numer == numer_tmp) + mpz_clear(numer); + if (denom == denom_tmp) + mpz_clear(denom); + return make_number(-1, result); + } + + /* ask gawk to allocate return values for us */ + quotient = get_mpz_ptr(); + remainder = get_mpz_ptr(); + + /* do the division */ + mpz_tdiv_qr(quotient, remainder, numer, denom); + + array_set_mpz(array, "quotient", 8, quotient); + array_set_mpz(array, "remainder", 9, remainder); + + /* release temporary variables */ + if (numer == numer_tmp) + mpz_clear(numer); + if (denom == denom_tmp) + mpz_clear(denom); + } +#endif + + return make_number(0, result); +} + +static awk_ext_func_t func_table[] = { + { "intdiv", do_intdiv, 3, 3, awk_false, NULL }, +}; + +/* init_intdiv --- initialization routine */ + +static awk_bool_t +init_intdiv(void) +{ +#ifdef HAVE_MPFR + check_mpfr_version(intdiv) +#endif + return awk_true; +} + +static awk_bool_t (*init_func)(void) = init_intdiv; + +/* define the dl_load function using the boilerplate macro */ + +dl_load_func(func_table, intdiv, "") @@ -25,6 +25,14 @@ #include "awk.h" +#ifdef HAVE_MPFR +#define getmpfr(n) getblock(n, BLOCK_MPFR, mpfr_ptr) +#define freempfr(n) freeblock(n, BLOCK_MPFR) + +#define getmpz(n) getblock(n, BLOCK_MPZ, mpz_ptr) +#define freempz(n) freeblock(n, BLOCK_MPZ) +#endif + /* Declare some globals used by api_get_file: */ extern IOBUF *curfile; extern INSTRUCTION *main_beginfile; @@ -145,7 +153,7 @@ api_set_argument(awk_ext_id_t id, NODE * awk_value_to_node(const awk_value_t *retval) { - NODE *ext_ret_val; + NODE *ext_ret_val = NULL; NODE *v; if (retval == NULL) @@ -159,7 +167,36 @@ awk_value_to_node(const awk_value_t *retval) ext_ret_val = dupnode(Nnull_string); break; case AWK_NUMBER: - ext_ret_val = make_number(retval->num_value); + switch (retval->num_type) { + case AWK_NUMBER_TYPE_DOUBLE: + ext_ret_val = make_number(retval->num_value); + break; + case AWK_NUMBER_TYPE_MPFR: +#ifdef HAVE_MPFR + if (! do_mpfr) + fatal(_("awk_value_to_node: not in MPFR mode")); + ext_ret_val = make_number_node(MPFN); + memcpy(&ext_ret_val->mpg_numbr, retval->num_ptr, sizeof(ext_ret_val->mpg_numbr)); + freempfr(retval->num_ptr); +#else + fatal(_("awk_value_to_node: MPFR not supported")); +#endif + break; + case AWK_NUMBER_TYPE_MPZ: +#ifdef HAVE_MPFR + if (! do_mpfr) + fatal(_("awk_value_to_node: not in MPFR mode")); + ext_ret_val = make_number_node(MPZN); + memcpy(&ext_ret_val->mpg_i, retval->num_ptr, sizeof(ext_ret_val->mpg_i)); + freempz(retval->num_ptr); +#else + fatal(_("awk_value_to_node: MPFR not supported")); +#endif + break; + default: + fatal(_("awk_value_to_node: invalid number type `%d'"), retval->num_type); + break; + } break; case AWK_STRING: ext_ret_val = make_str_node(retval->str_value.str, @@ -450,6 +487,34 @@ assign_string(NODE *node, awk_value_t *val, awk_valtype_t val_type) val->str_value.len = node->stlen; } +/* assign_number -- return a number node */ + +static inline void +assign_number(NODE *node, awk_value_t *val) +{ + val->val_type = AWK_NUMBER; + switch (node->flags & (MPFN|MPZN)) { + case 0: + val->num_value = node->numbr; + val->num_type = AWK_NUMBER_TYPE_DOUBLE; + val->num_ptr = NULL; + break; + case MPFN: + val->num_value = mpfr_get_d(node->mpg_numbr, ROUND_MODE); + val->num_type = AWK_NUMBER_TYPE_MPFR; + val->num_ptr = &node->mpg_numbr; + break; + case MPZN: + val->num_value = mpz_get_d(node->mpg_i); + val->num_type = AWK_NUMBER_TYPE_MPZ; + val->num_ptr = &node->mpg_i; + break; + default: + fatal(_("node_to_awk_value: detected invalid numeric flags combination `%s'; please file a bug report."), flags2str(node->flags)); + break; + } +} + /* assign_regex --- return a regex node */ static inline void @@ -502,9 +567,8 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) if (node->flags & REGEX) val->val_type = AWK_REGEX; else { - val->val_type = AWK_NUMBER; (void) force_number(node); - val->num_value = get_number_d(node); + assign_number(node, val); ret = awk_true; } break; @@ -606,8 +670,7 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) ret = awk_true; break; case NUMBER: - val->val_type = AWK_NUMBER; - val->num_value = get_number_d(node); + assign_number(node, val); ret = awk_true; break; case NUMBER|USER_INPUT: @@ -1219,6 +1282,36 @@ api_release_value(awk_ext_id_t id, awk_value_cookie_t value) return awk_true; } +/* api_get_mpfr --- allocate an mpfr_ptr */ + +static void * +api_get_mpfr(awk_ext_id_t id) +{ +#ifdef HAVE_MPFR + mpfr_ptr p; + getmpfr(p); + mpfr_init(p); + return p; +#else + fatal(_("api_get_mpfr: MPFR not supported")); +#endif +} + +/* api_get_mpz --- allocate an mpz_ptr */ + +static void * +api_get_mpz(awk_ext_id_t id) +{ +#ifdef HAVE_MPFR + mpz_ptr p; + getmpz(p); + mpz_init(p); + return p; +#else + fatal(_("api_get_mpfr: MPFR not supported")); +#endif +} + /* api_get_file --- return a handle to an existing or newly opened file */ static awk_bool_t @@ -1346,6 +1439,16 @@ gawk_api_t api_impl = { /* data */ GAWK_API_MAJOR_VERSION, /* major and minor versions */ GAWK_API_MINOR_VERSION, + +#ifdef HAVE_MPFR + __GNU_MP_VERSION, + __GNU_MP_VERSION_MINOR, + MPFR_VERSION_MAJOR, + MPFR_VERSION_MINOR, +#else + 0, 0, 0, 0, +#endif + { 0 }, /* do_flags */ /* registration functions */ @@ -1398,6 +1501,8 @@ gawk_api_t api_impl = { calloc, realloc, free, + api_get_mpfr, + api_get_mpz, /* Find/open a file */ api_get_file, @@ -296,7 +296,7 @@ typedef struct awk_two_way_processor { awk_const struct awk_two_way_processor *awk_const next; /* for use by gawk */ } awk_two_way_processor_t; -#define gawk_api_major_version 2 +#define gawk_api_major_version 3 #define gawk_api_minor_version 0 /* Current version of the API. */ @@ -323,6 +323,16 @@ typedef struct awk_string { size_t len; /* length thereof, in chars */ } awk_string_t; +typedef struct awk_number { + double d; /* always populated in data received from gawk */ + enum AWK_NUMBER_TYPE { + AWK_NUMBER_TYPE_DOUBLE, + AWK_NUMBER_TYPE_MPFR, + AWK_NUMBER_TYPE_MPZ + } type; + void *ptr; /* either NULL or mpfr_ptr or mpz_ptr */ +} awk_number_t; + /* Arrays are represented as an opaque type. */ typedef void *awk_array_t; @@ -358,7 +368,7 @@ typedef struct awk_value { awk_valtype_t val_type; union { awk_string_t s; - double d; + awk_number_t n; awk_array_t a; awk_scalar_t scl; awk_value_cookie_t vc; @@ -366,7 +376,9 @@ typedef struct awk_value { #define str_value u.s #define strnum_value str_value #define regex_value str_value -#define num_value u.d +#define num_value u.n.d +#define num_type u.n.type +#define num_ptr u.n.ptr #define array_cookie u.a #define scalar_cookie u.scl #define value_cookie u.vc @@ -452,6 +464,12 @@ typedef struct gawk_api { awk_const int major_version; awk_const int minor_version; + /* GMP/MPFR versions, if extended-precision is available */ + awk_const int gmp_major_version; + awk_const int gmp_minor_version; + awk_const int mpfr_major_version; + awk_const int mpfr_minor_version; + /* * These can change on the fly as things happen within gawk. * Currently only do_lint is prone to change, but we reserve @@ -749,6 +767,20 @@ typedef struct gawk_api { void *(*api_realloc)(void *ptr, size_t size); void (*api_free)(void *ptr); + /* + * A function that returns mpfr data should call this function + * to allocate and initialize an mpfr_ptr for use in an + * awk_value_t structure that will be handed to gawk. + */ + void *(*api_get_mpfr)(awk_ext_id_t id); + + /* + * A function that returns mpz data should call this function + * to allocate and initialize an mpz_ptr for use in an + * awk_value_t structure that will be handed to gawk. + */ + void *(*api_get_mpz)(awk_ext_id_t id); + /* * 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 @@ -794,7 +826,6 @@ typedef struct gawk_api { */ const awk_input_buf_t **ibufp, const awk_output_buf_t **obufp); - } gawk_api_t; #ifndef GAWK /* these are not for the gawk code itself! */ @@ -884,6 +915,9 @@ typedef struct gawk_api { #define get_file(name, namelen, filetype, fd, ibuf, obuf) \ (api->api_get_file(ext_id, name, namelen, filetype, fd, ibuf, obuf)) +#define get_mpfr_ptr() (api->api_get_mpfr(ext_id)) +#define get_mpz_ptr() (api->api_get_mpz(ext_id)) + #define register_ext_version(version) \ (api->api_register_ext_version(ext_id, version)) @@ -980,11 +1014,39 @@ make_null_string(awk_value_t *result) static inline awk_value_t * make_number(double num, awk_value_t *result) { - memset(result, 0, sizeof(*result)); - result->val_type = AWK_NUMBER; result->num_value = num; + result->num_type = AWK_NUMBER_TYPE_DOUBLE; + return result; +} + +/* + * make_number_mpz --- make an mpz number value in result. + * The mpz_ptr must be from a call to get_mpz_ptr. Gawk will now + * take ownership of this memory. + */ +static inline awk_value_t * +make_number_mpz(void *mpz_ptr, awk_value_t *result) +{ + result->val_type = AWK_NUMBER; + result->num_type = AWK_NUMBER_TYPE_MPZ; + result->num_ptr = mpz_ptr; + return result; +} + +/* + * make_number_mpfr --- make an mpfr number value in result. + * The mpfr_ptr must be from a call to get_mpfr_ptr. Gawk will now + * take ownership of this memory. + */ + +static inline awk_value_t * +make_number_mpfr(void *mpfr_ptr, awk_value_t *result) +{ + result->val_type = AWK_NUMBER; + result->num_type = AWK_NUMBER_TYPE_MPFR; + result->num_ptr = mpfr_ptr; return result; } @@ -1077,6 +1139,29 @@ int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) \ return (errors == 0); \ } +/* + * If you are using extended-precision calculations in your library, please + * call this macro from your init_func. + */ +#define check_mpfr_version(extension) { \ + if (api->gmp_major_version != __GNU_MP_VERSION \ + || api->gmp_minor_version < __GNU_MP_VERSION_MINOR) { \ + fprintf(stderr, #extension ": GMP version mismatch with gawk!\n"); \ + fprintf(stderr, "\tmy version (%d, %d), gawk version (%d, %d)\n", \ + __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, \ + api->gmp_major_version, api->gmp_minor_version); \ + exit(1); \ + } \ + if (api->mpfr_major_version != MPFR_VERSION_MAJOR \ + || api->mpfr_minor_version < MPFR_VERSION_MINOR) { \ + fprintf(stderr, #extension ": MPFR version mismatch with gawk!\n"); \ + fprintf(stderr, "\tmy version (%d, %d), gawk version (%d, %d)\n", \ + MPFR_VERSION_MAJOR, MPFR_VERSION_MINOR, \ + api->mpfr_major_version, api->mpfr_minor_version); \ + exit(1); \ + } \ +} + #endif /* GAWK */ #ifdef __cplusplus @@ -103,28 +103,16 @@ cleanup_mpfr(void) /* mpg_node --- allocate a node to store MPFR float or GMP integer */ NODE * -mpg_node(unsigned int tp) +mpg_node(unsigned int flags) { - NODE *r; - getnode(r); - r->type = Node_val; + NODE *r = make_number_node(flags); - if (tp == MPFN) { + if (flags == MPFN) /* Initialize, set precision to the default precision, and value to NaN */ mpfr_init(r->mpg_numbr); - r->flags = MPFN; - } else { + else /* Initialize and set value to 0 */ mpz_init(r->mpg_i); - r->flags = MPZN; - } - - r->valref = 1; - r->flags |= MALLOC|NUMBER|NUMCUR; - r->stptr = NULL; - r->stlen = 0; - r->wstptr = NULL; - r->wstlen = 0; return r; } @@ -1181,6 +1169,7 @@ do_mpfr_srand(int nargs) return res; } +#ifdef SUPPLY_INTDIV /* do_mpfr_intdiv --- do integer division, return quotient and remainder in dest array */ /* @@ -1274,6 +1263,7 @@ do_mpfr_intdiv(int nargs) return make_number((AWKNUM) 0.0); } +#endif /* SUPPLY_INTDIV */ /* * mpg_tofloat --- convert an arbitrary-precision integer operand to @@ -333,16 +333,8 @@ r_dupnode(NODE *n) static NODE * r_make_number(double x) { - NODE *r; - getnode(r); - r->type = Node_val; + NODE *r = make_number_node(0); r->numbr = x; - r->flags = MALLOC|NUMBER|NUMCUR; - r->valref = 1; - r->stptr = NULL; - r->stlen = 0; - r->wstptr = NULL; - r->wstlen = 0; return r; } @@ -1005,6 +997,10 @@ void init_btowc_cache() struct block_header nextfree[BLOCK_MAX] = { { NULL, sizeof(NODE) }, { NULL, sizeof(BUCKET) }, +#ifdef HAVE_MPFR + { NULL, sizeof(mpfr_t) }, + { NULL, sizeof(mpz_t) }, +#endif }; diff --git a/test/ChangeLog b/test/ChangeLog index 0452ebab..90051a9b 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -53,6 +53,11 @@ * Makefile.am (charset-msg-start): Document that having el_GR.iso88597 is helpful. +2017-04-16 Arnold D. Robbins <arnold@skeeve.com> + + * mpfrsqrt.awk: Add `@load intdiv'. + * dumpvars.ok, id.ok, symtab6.ok, symtab8.ok: Updated. + 2017-04-12 Manuel Collado <m-collado@users.sourceforge.net> * Makefile.am (fpat6): New test. diff --git a/test/dumpvars.ok b/test/dumpvars.ok index 7caecd35..85d1c859 100644 --- a/test/dumpvars.ok +++ b/test/dumpvars.ok @@ -9,7 +9,7 @@ FILENAME: "-" FNR: 3 FPAT: "[^[:space:]]+" FS: " " -FUNCTAB: array, 42 elements +FUNCTAB: array, 41 elements IGNORECASE: 0 LINT: 0 NF: 1 @@ -47,7 +47,6 @@ gsub -> builtin i -> untyped index -> builtin int -> builtin -intdiv -> builtin isarray -> builtin length -> builtin log -> builtin diff --git a/test/mpfrsqrt.awk b/test/mpfrsqrt.awk index 3fb1f5f8..8cc416bb 100644 --- a/test/mpfrsqrt.awk +++ b/test/mpfrsqrt.awk @@ -9,6 +9,8 @@ # # Running this program (sqrt-bug.awk): # -------------------------------------------------------------------- + +@load "intdiv" BEGIN { a=11111111111111111111111111111111111111111111111111111111111 print sqrt(a^2) diff --git a/test/symtab6.ok b/test/symtab6.ok index 34c10636..7de717a0 100644 --- a/test/symtab6.ok +++ b/test/symtab6.ok @@ -9,7 +9,7 @@ FILENAME: "" FNR: 0 FPAT: "[^[:space:]]+" FS: " " -FUNCTAB: array, 42 elements +FUNCTAB: array, 41 elements IGNORECASE: 0 LINT: 0 NF: 0 diff --git a/test/symtab8.ok b/test/symtab8.ok index 0cf40fe9..da29b585 100644 --- a/test/symtab8.ok +++ b/test/symtab8.ok @@ -9,7 +9,7 @@ FIELDWIDTHS: "" FNR: 1 FPAT: "[^[:space:]]+" FS: " " -FUNCTAB: array, 42 elements +FUNCTAB: array, 41 elements IGNORECASE: 0 LINT: 0 NF: 1 |