diff options
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | awk.h | 2 | ||||
-rw-r--r-- | builtin.c | 99 | ||||
-rw-r--r-- | doc/ChangeLog | 9 | ||||
-rw-r--r-- | doc/gawk.info | 666 | ||||
-rw-r--r-- | doc/gawk.texi | 28 | ||||
-rw-r--r-- | doc/gawktexi.in | 28 | ||||
-rw-r--r-- | field.c | 4 | ||||
-rw-r--r-- | interpret.h | 17 | ||||
-rw-r--r-- | mpfr.c | 20 | ||||
-rw-r--r-- | pc/ChangeLog | 4 | ||||
-rw-r--r-- | pc/Makefile.tst | 8 | ||||
-rw-r--r-- | test/ChangeLog | 5 | ||||
-rw-r--r-- | test/Makefile.am | 10 | ||||
-rw-r--r-- | test/Makefile.in | 10 | ||||
-rw-r--r-- | test/indirectbuiltin2.awk | 29 | ||||
-rw-r--r-- | test/indirectbuiltin2.ok | 6 |
17 files changed, 640 insertions, 337 deletions
@@ -1,3 +1,35 @@ +2022-02-07 Arnold D. Robbins <arnold@skeeve.com> + + Continue fixing indirect calls of builtins. + + * awk.h (check_exact_args, check_args_min_max): Add declarations. + * builtin.c (check_exact_args, check_args_min_max): New functions. + (do_exp, do_fflush, do_index, do_int, do_isarray, do_length, do_log, + do_sqrt, do_strftime, do_systime, do_mktime, do_system, do_tolower, + do_toupper, do_atan2, do_sin, do_cos, do_rand, do_srand, do_match, + do_sub, do_lshift, do_rshift, do_compl, do_strtonum, do_dcgettext, + do_dcngettext, do_bindtextdomain, do_intdiv, do_typeof): Call + the argument checking functions. + (call_sub, call_match): Manually check argument count. + * field.c (do_split, do_patsplit): Call the argument checking + functions. + * interpret.h (r_interpret): For indirect call of extension functions, + pop the function name off the stack when done. + * mpfr.c (do_atan2, do_mpfr_func, do_mpfr_int, do_mpfr_compl, + do_mpfr_lshift, do_mpfr_rshift, do_mpfr_strtonum, do_mpfr_rand, + do_mpfr_srand, do_mpfr_intdiv): Call the argument checking functions. + +2022-02-04 Arnold D. Robbins <arnold@skeeve.com> + + Start fixing issues with indirect calls of builtins. + Thanks to Denis Shirokov <cosmogen@gmail.com> for the initial report. + Much more remains to be done. + + * builtin.c (do_length): Check number of arguments, fatal if not one. + If passed Node_var_new, turn it into the null string. + * interpret.h (r_interpret): For Op_indirect_call, pop the function + name off the stack. + 2022-01-05 Arnold D. Robbins <arnold@skeeve.com> * awkgram.y (change_namespace): New function. Extracted from @@ -1520,6 +1520,8 @@ extern int strncasecmpmbs(const unsigned char *, extern int sanitize_exit_status(int status); extern void check_symtab_functab(NODE *dest, const char *fname, const char *msg); extern NODE *do_mkbool(int nargs); +extern void check_exact_args(int nargs, const char *fname, int count); +extern void check_args_min_max(int nargs, const char *fname, int min, int max); /* debug.c */ extern void init_debug(void); extern int debug_prog(INSTRUCTION *pc); @@ -90,6 +90,22 @@ fatal(_("attempt to use array `%s' in a scalar context"), array_vname(s1)); \ }} while (false) +/* check argument counts --- for use when called indirectly */ + +void +check_exact_args(int nargs, const char *fname, int count) +{ + if (nargs != count) + fatal(_("%s: called with %d arguments"), fname, nargs); +} + +void +check_args_min_max(int nargs, const char *fname, int min, int max) +{ + if (nargs < min || nargs > max) + fatal(_("%s: called with %d arguments"), fname, nargs); +} + /* * Since we supply the version of random(), we know what * value to use here. @@ -173,6 +189,8 @@ do_exp(int nargs) NODE *tmp; double d, res; + check_exact_args(nargs, "exp", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), "exp"); @@ -235,6 +253,8 @@ do_fflush(int nargs) * Now, both calls flush everything. */ + check_args_min_max(nargs, "fflush", 0, 1); + /* fflush() */ if (nargs == 0) { status = flush_io(); // ERRNO updated @@ -381,6 +401,8 @@ do_index(int nargs) bool do_single_byte = false; mbstate_t mbs1, mbs2; + check_exact_args(nargs, "index", 2); + if (gawk_mb_cur_max > 1) { memset(& mbs1, 0, sizeof(mbstate_t)); memset(& mbs2, 0, sizeof(mbstate_t)); @@ -503,6 +525,8 @@ do_int(int nargs) NODE *tmp; double d; + check_exact_args(nargs, "int", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), "int"); @@ -520,6 +544,8 @@ do_isarray(int nargs) NODE *tmp; int ret = 1; + check_exact_args(nargs, "isarray", 1); + tmp = POP(); if (tmp->type != Node_var_array) { ret = 0; @@ -538,6 +564,8 @@ do_length(int nargs) NODE *tmp; size_t len; + check_exact_args(nargs, "length", 1); + tmp = POP(); if (tmp->type == Node_var_array) { static bool warned = false; @@ -561,6 +589,10 @@ do_length(int nargs) size = assoc_length(tmp); return make_number(size); + } else if (tmp->type == Node_var_new) { + // this can happen from an indirect call + DEREF(tmp); + tmp = dupnode(Nnull_string); } assert(tmp->type == Node_val); @@ -593,6 +625,8 @@ do_log(int nargs) NODE *tmp; double d, arg; + check_exact_args(nargs, "log", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), "log"); @@ -1796,6 +1830,8 @@ do_sqrt(int nargs) NODE *tmp; double arg; + check_exact_args(nargs, "sqrt", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), "sqrt"); @@ -1818,6 +1854,8 @@ do_substr(int nargs) double d_index = 0, d_length = 0; size_t src_len; + check_args_min_max(nargs, "substr", 2, 3); + if (nargs == 3) { t1 = POP_NUMBER(); d_length = get_number_d(t1); @@ -1982,6 +2020,8 @@ do_strftime(int nargs) (void) time(& fclock); /* current time of day */ do_gmt = false; + check_args_min_max(nargs, "strftime", 0, 3); + if (PROCINFO_node != NULL) { sub = make_string("strftime", 8); val = in_array(PROCINFO_node, sub); @@ -2098,6 +2138,8 @@ do_systime(int nargs ATTRIBUTE_UNUSED) { time_t lclock; + check_exact_args(nargs, "systime", 0); + (void) time(& lclock); return make_number((AWKNUM) lclock); } @@ -2116,6 +2158,8 @@ do_mktime(int nargs) char save; bool do_gmt; + check_args_min_max(nargs, "mktime", 1, 2); + if (nargs == 2) { t2 = POP_SCALAR(); do_gmt = boolval(t2); @@ -2179,6 +2223,8 @@ do_system(int nargs) char save; int status; + check_exact_args(nargs, "system", 1); + if (do_sandbox) fatal(_("'system' function not allowed in sandbox mode")); @@ -2435,6 +2481,8 @@ do_tolower(int nargs) { NODE *t1, *t2; + check_exact_args(nargs, "tolower", 1); + t1 = POP_SCALAR(); if (do_lint && (fixtype(t1)->flags & STRING) == 0) lintwarn(_("%s: received non-string argument"), "tolower"); @@ -2466,6 +2514,8 @@ do_toupper(int nargs) { NODE *t1, *t2; + check_exact_args(nargs, "toupper", 1); + t1 = POP_SCALAR(); if (do_lint && (fixtype(t1)->flags & STRING) == 0) lintwarn(_("%s: received non-string argument"), "toupper"); @@ -2498,6 +2548,8 @@ do_atan2(int nargs) NODE *t1, *t2; double d1, d2; + check_exact_args(nargs, "atan2", 2); + POP_TWO_SCALARS(t1, t2); if (do_lint) { if ((fixtype(t1)->flags & NUMBER) == 0) @@ -2520,6 +2572,8 @@ do_sin(int nargs) NODE *tmp; double d; + check_exact_args(nargs, "sin", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), "sin"); @@ -2536,6 +2590,8 @@ do_cos(int nargs) NODE *tmp; double d; + check_exact_args(nargs, "cos", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), "cos"); @@ -2557,6 +2613,9 @@ NODE * do_rand(int nargs ATTRIBUTE_UNUSED) { double tmprand; + + check_exact_args(nargs, "rand", 0); + #define RAND_DIVISOR ((double)GAWK_RANDOM_MAX+1.0) if (firstrand) { (void) initstate((unsigned) 1, state, SIZEOF_STATE); @@ -2647,6 +2706,8 @@ do_srand(int nargs) (void) setstate(state); } + check_args_min_max(nargs, "srand", 0, 1); + if (nargs == 0) srandom((unsigned int) (save_seed = (long) time((time_t *) 0))); else { @@ -2679,6 +2740,8 @@ do_match(int nargs) char *subsepstr; size_t subseplen; + check_args_min_max(nargs, "match", 2, 3); + dest = NULL; if (nargs == 3) { /* 3rd optional arg for the subpatterns */ dest = POP_PARAM(); @@ -2907,6 +2970,8 @@ do_sub(int nargs, unsigned int flags) double d; NODE *glob_flag; + check_exact_args(nargs, "gensub", 4); + tmp = PEEK(3); rp = re_update(tmp); @@ -2935,6 +3000,12 @@ do_sub(int nargs, unsigned int flags) } DEREF(glob_flag); } else { + if ((flags & GSUB) != 0) { + check_exact_args(nargs, "gsub", 3); + } else { + check_exact_args(nargs, "sub", 3); + } + /* take care of regexp early, in case re_update is fatal */ tmp = PEEK(2); @@ -3301,6 +3372,9 @@ call_sub(const char *name, int nargs) PUSH_ADDRESS(lhs); } else { /* gensub */ + if (nargs < 3 || nargs > 4) + fatal(_("indirect call to gensub requires three to four arguments")); + if (nargs == 4) rhs = POP(); else @@ -3360,6 +3434,9 @@ call_match(int nargs) NODE *regex, *text, *array; NODE *result; + if (nargs < 2 || nargs > 3) + fatal(_("indirect call to match requires two or three arguments")); + regex = text = array = NULL; if (nargs == 3) array = POP(); @@ -3401,8 +3478,8 @@ call_split_func(const char *name, int nargs) NODE *result; regex = seps = NULL; - if (nargs < 2) - fatal(_("indirect call to %s requires at least two arguments"), + if (nargs < 2 || nargs > 4) + fatal(_("indirect call to %s requires two to four arguments"), name); if (nargs == 4) @@ -3466,6 +3543,8 @@ do_lshift(int nargs) uintmax_t uval, ushift, res; AWKNUM val, shift; + check_exact_args(nargs, "lshift", 2); + POP_TWO_SCALARS(s1, s2); if (do_lint) { if ((fixtype(s1)->flags & NUMBER) == 0) @@ -3505,6 +3584,8 @@ do_rshift(int nargs) uintmax_t uval, ushift, res; AWKNUM val, shift; + check_exact_args(nargs, "rshift", 2); + POP_TWO_SCALARS(s1, s2); if (do_lint) { if ((fixtype(s1)->flags & NUMBER) == 0) @@ -3637,6 +3718,8 @@ do_compl(int nargs) double d; uintmax_t uval; + check_exact_args(nargs, "compl", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), "compl"); @@ -3662,6 +3745,8 @@ do_strtonum(int nargs) NODE *tmp; AWKNUM d; + check_exact_args(nargs, "strtonum", 1); + tmp = fixtype(POP_SCALAR()); if ((tmp->flags & NUMBER) != 0) d = (AWKNUM) tmp->numbr; @@ -3863,6 +3948,8 @@ do_dcgettext(int nargs) char *domain; char save1 = '\0', save2 = '\0'; + check_args_min_max(nargs, "dcgettext", 1, 3); + if (nargs == 3) { /* third argument */ tmp = POP_STRING(); lc_cat = localecategory_from_argument(tmp); @@ -3924,6 +4011,8 @@ do_dcngettext(int nargs) char save = '\0', save1 = '\0', save2 = '\0'; bool saved_end = false; + check_args_min_max(nargs, "dcngettext", 3, 5); + if (nargs == 5) { /* fifth argument */ tmp = POP_STRING(); lc_cat = localecategory_from_argument(tmp); @@ -4005,6 +4094,8 @@ do_bindtextdomain(int nargs) const char *directory, *domain; const char *the_result; + check_args_min_max(nargs, "bindtextdomain", 1, 2); + t1 = t2 = NULL; /* set defaults */ directory = NULL; @@ -4058,6 +4149,8 @@ do_intdiv(int nargs) NODE *numerator, *denominator, *result; double num, denom, quotient, remainder; + check_exact_args(nargs, "intdiv", 3); + result = POP_PARAM(); if (result->type != Node_var_array) fatal(_("intdiv: third argument is not an array")); @@ -4115,6 +4208,8 @@ do_typeof(int nargs) bool deref = true; NODE *dbg; + check_args_min_max(nargs, "typeof", 1, 2); + if (nargs == 2) { /* 2nd optional arg for debugging */ dbg = POP_PARAM(); if (dbg->type != Node_var_array) diff --git a/doc/ChangeLog b/doc/ChangeLog index db08ab90..b44c5a8d 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,6 +1,13 @@ +2022-02-07 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Indirect Calls): Expand discussion of calling + built-in functions directly. + (POSIX Floating Point Problems): Add a note that the sign of + NaN values can vary. + 2022-01-05 Arnold D. Robbins <arnold@skeeve.com> - * gawktexi.ini (Indirect Calls): Use `the_function' everywhere. + * gawktexi.in (Indirect Calls): Use `the_function' everywhere. Thanks to John Naman, <gawker@703n.com> for the report. 2021-12-10 Arnold D. Robbins <arnold@skeeve.com> diff --git a/doc/gawk.info b/doc/gawk.info index 97cb96ca..f4afd8e3 100644 --- a/doc/gawk.info +++ b/doc/gawk.info @@ -15577,14 +15577,27 @@ Dynamic Extensions::). There are some limitations when calling built-in functions indirectly, as follows. * You cannot pass a regular expression constant to a built-in - function through an indirect function call.(1) This applies to the + function through an indirect function call. This applies to the 'sub()', 'gsub()', 'gensub()', 'match()', 'split()' and - 'patsplit()' functions. + 'patsplit()' functions. However, you can pass a strongly typed + regexp constant (*note Strong Regexp Constants::). * If calling 'sub()' or 'gsub()', you may only pass two arguments, since those functions are unusual in that they update their third argument. This means that '$0' will be updated. + * You cannot indirectly call built-in functions that can take '$0' as + a default parameter; you must supply an argument instead. For + example, you must pass an argument to 'length()' if calling it + indirectly. + + * Calling a built-in function indirectly with the wrong number of + arguments for that function causes a fatal error. For example, + calling 'length()' with two arguments. These errors are found at + runtime instead of when 'gawk' parses your program, since 'gawk' + doesn't know until runtime if you have passed the correct number of + arguments or not. + 'gawk' does its best to make indirect function calls efficient. For example, in the following case: @@ -15593,11 +15606,6 @@ example, in the following case: 'gawk' looks up the actual function to call only once. - ---------- Footnotes ---------- - - (1) This may change in a future version; recheck the documentation -that comes with your version of 'gawk' to see if it has. - File: gawk.info, Node: Functions Summary, Prev: Indirect Calls, Up: Functions @@ -25278,6 +25286,13 @@ described: '+inf', '-inf', '+nan', or '-nan'. Similarly, in POSIX mode, 'gawk' prints the result of the system's C 'printf()' function using the '%g' format string for the value, whatever that may be. + NOTE: The sign used for NaN values can vary! The result depends + upon both the underlying system architecture and the underlying + library used to format NaN values. In particular, it's possible to + get different results for the same function call depending upon + whether or not 'gawk' is running in MPFR mode ('-M') or not. + Caveat Emptor! + ---------- Footnotes ---------- (1) You asked for it, you got it. @@ -39042,325 +39057,324 @@ Ref: Function Caveats-Footnote-1637557 Node: Return Statement637677 Node: Dynamic Typing640656 Node: Indirect Calls641586 -Ref: Indirect Calls-Footnote-1651853 -Node: Functions Summary651981 -Node: Library Functions654686 -Ref: Library Functions-Footnote-1658293 -Ref: Library Functions-Footnote-2658436 -Node: Library Names658607 -Ref: Library Names-Footnote-1662274 -Ref: Library Names-Footnote-2662497 -Node: General Functions662583 -Node: Strtonum Function663765 -Node: Assert Function666787 -Node: Round Function670113 -Node: Cliff Random Function671653 -Node: Ordinal Functions672669 -Ref: Ordinal Functions-Footnote-1675732 -Ref: Ordinal Functions-Footnote-2675984 -Node: Join Function676194 -Ref: Join Function-Footnote-1677964 -Node: Getlocaltime Function678164 -Node: Readfile Function681906 -Node: Shell Quoting683883 -Node: Isnumeric Function685311 -Node: Data File Management686699 -Node: Filetrans Function687331 -Node: Rewind Function691427 -Node: File Checking693336 -Ref: File Checking-Footnote-1694670 -Node: Empty Files694871 -Node: Ignoring Assigns696850 -Node: Getopt Function698400 -Ref: Getopt Function-Footnote-1713697 -Node: Passwd Functions713897 -Ref: Passwd Functions-Footnote-1722736 -Node: Group Functions722824 -Ref: Group Functions-Footnote-1730722 -Node: Walking Arrays730929 -Node: Library Functions Summary733937 -Node: Library Exercises735343 -Node: Sample Programs735808 -Node: Running Examples736578 -Node: Clones737306 -Node: Cut Program738530 -Node: Egrep Program748670 -Node: Id Program757671 -Node: Split Program767606 -Ref: Split Program-Footnote-1777499 -Node: Tee Program777672 -Node: Uniq Program780462 -Node: Wc Program788050 -Node: Bytes vs. Characters788437 -Node: Using extensions789985 -Node: wc program790739 -Node: Miscellaneous Programs795604 -Node: Dupword Program796817 -Node: Alarm Program798847 -Node: Translate Program803702 -Ref: Translate Program-Footnote-1808267 -Node: Labels Program808537 -Ref: Labels Program-Footnote-1811888 -Node: Word Sorting811972 -Node: History Sorting816044 -Node: Extract Program818269 -Node: Simple Sed826282 -Node: Igawk Program829356 -Ref: Igawk Program-Footnote-1843687 -Ref: Igawk Program-Footnote-2843889 -Ref: Igawk Program-Footnote-3844011 -Node: Anagram Program844126 -Node: Signature Program847188 -Node: Programs Summary848435 -Node: Programs Exercises849649 -Ref: Programs Exercises-Footnote-1853779 -Node: Advanced Features853865 -Node: Nondecimal Data855996 -Node: Boolean Typed Values857594 -Node: Array Sorting859475 -Node: Controlling Array Traversal860180 -Ref: Controlling Array Traversal-Footnote-1868548 -Node: Array Sorting Functions868666 -Ref: Array Sorting Functions-Footnote-1874040 -Node: Two-way I/O874236 -Ref: Two-way I/O-Footnote-1881962 -Ref: Two-way I/O-Footnote-2882149 -Node: TCP/IP Networking882231 -Node: Profiling885307 -Node: Extension Philosophy894616 -Node: Advanced Features Summary896095 -Node: Internationalization898110 -Node: I18N and L10N899784 -Node: Explaining gettext900471 -Ref: Explaining gettext-Footnote-1906363 -Ref: Explaining gettext-Footnote-2906548 -Node: Programmer i18n906713 -Ref: Programmer i18n-Footnote-1911662 -Node: Translator i18n911711 -Node: String Extraction912505 -Ref: String Extraction-Footnote-1913637 -Node: Printf Ordering913723 -Ref: Printf Ordering-Footnote-1916509 -Node: I18N Portability916573 -Ref: I18N Portability-Footnote-1919029 -Node: I18N Example919092 -Ref: I18N Example-Footnote-1922367 -Ref: I18N Example-Footnote-2922440 -Node: Gawk I18N922549 -Node: I18N Summary923171 -Node: Debugger924512 -Node: Debugging925512 -Node: Debugging Concepts925953 -Node: Debugging Terms927762 -Node: Awk Debugging930337 -Ref: Awk Debugging-Footnote-1931282 -Node: Sample Debugging Session931414 -Node: Debugger Invocation931948 -Node: Finding The Bug933334 -Node: List of Debugger Commands939808 -Node: Breakpoint Control941141 -Node: Debugger Execution Control944835 -Node: Viewing And Changing Data948197 -Node: Execution Stack951738 -Node: Debugger Info953375 -Node: Miscellaneous Debugger Commands957446 -Node: Readline Support962508 -Node: Limitations963404 -Node: Debugging Summary965958 -Node: Namespaces967237 -Node: Global Namespace968348 -Node: Qualified Names969746 -Node: Default Namespace970745 -Node: Changing The Namespace971486 -Node: Naming Rules973100 -Node: Internal Name Management974948 -Node: Namespace Example975990 -Node: Namespace And Features978552 -Node: Namespace Summary979987 -Node: Arbitrary Precision Arithmetic981464 -Node: Computer Arithmetic982951 -Ref: table-numeric-ranges986717 -Ref: table-floating-point-ranges987211 -Ref: Computer Arithmetic-Footnote-1987870 -Node: Math Definitions987927 -Ref: table-ieee-formats990903 -Node: MPFR features991471 -Node: FP Math Caution993189 -Ref: FP Math Caution-Footnote-1994261 -Node: Inexactness of computations994630 -Node: Inexact representation995661 -Node: Comparing FP Values997021 -Node: Errors accumulate998262 -Node: Strange values999718 -Ref: Strange values-Footnote-11002306 -Node: Getting Accuracy1002411 -Node: Try To Round1005121 -Node: Setting precision1006020 -Ref: table-predefined-precision-strings1006717 -Node: Setting the rounding mode1008548 -Ref: table-gawk-rounding-modes1008922 -Ref: Setting the rounding mode-Footnote-11012854 -Node: Arbitrary Precision Integers1013033 -Ref: Arbitrary Precision Integers-Footnote-11016208 -Node: Checking for MPFR1016357 -Node: POSIX Floating Point Problems1017831 -Ref: POSIX Floating Point Problems-Footnote-11022116 -Node: Floating point summary1022154 -Node: Dynamic Extensions1024344 -Node: Extension Intro1025897 -Node: Plugin License1027163 -Node: Extension Mechanism Outline1027960 -Ref: figure-load-extension1028399 -Ref: figure-register-new-function1029965 -Ref: figure-call-new-function1031058 -Node: Extension API Description1033121 -Node: Extension API Functions Introduction1034834 -Ref: table-api-std-headers1036670 -Node: General Data Types1040920 -Ref: General Data Types-Footnote-11049626 -Node: Memory Allocation Functions1049925 -Ref: Memory Allocation Functions-Footnote-11054426 -Node: Constructor Functions1054525 -Node: API Ownership of MPFR and GMP Values1058178 -Node: Registration Functions1059491 -Node: Extension Functions1060191 -Node: Exit Callback Functions1065513 -Node: Extension Version String1066763 -Node: Input Parsers1067426 -Node: Output Wrappers1080147 -Node: Two-way processors1084659 -Node: Printing Messages1086924 -Ref: Printing Messages-Footnote-11088095 -Node: Updating ERRNO1088248 -Node: Requesting Values1088987 -Ref: table-value-types-returned1089724 -Node: Accessing Parameters1090833 -Node: Symbol Table Access1092070 -Node: Symbol table by name1092582 -Ref: Symbol table by name-Footnote-11095607 -Node: Symbol table by cookie1095735 -Ref: Symbol table by cookie-Footnote-11099920 -Node: Cached values1099984 -Ref: Cached values-Footnote-11103520 -Node: Array Manipulation1103673 -Ref: Array Manipulation-Footnote-11104764 -Node: Array Data Types1104801 -Ref: Array Data Types-Footnote-11107459 -Node: Array Functions1107551 -Node: Flattening Arrays1112049 -Node: Creating Arrays1119025 -Node: Redirection API1123792 -Node: Extension API Variables1126625 -Node: Extension Versioning1127336 -Ref: gawk-api-version1127765 -Node: Extension GMP/MPFR Versioning1129497 -Node: Extension API Informational Variables1131125 -Node: Extension API Boilerplate1132198 -Node: Changes from API V11136172 -Node: Finding Extensions1137744 -Node: Extension Example1138303 -Node: Internal File Description1139101 -Node: Internal File Ops1143181 -Ref: Internal File Ops-Footnote-11154531 -Node: Using Internal File Ops1154671 -Ref: Using Internal File Ops-Footnote-11157054 -Node: Extension Samples1157328 -Node: Extension Sample File Functions1158857 -Node: Extension Sample Fnmatch1166506 -Node: Extension Sample Fork1167993 -Node: Extension Sample Inplace1169211 -Node: Extension Sample Ord1172837 -Node: Extension Sample Readdir1173673 -Ref: table-readdir-file-types1174562 -Node: Extension Sample Revout1175630 -Node: Extension Sample Rev2way1176219 -Node: Extension Sample Read write array1176959 -Node: Extension Sample Readfile1180125 -Node: Extension Sample Time1181220 -Node: Extension Sample API Tests1182972 -Node: gawkextlib1183464 -Node: Extension summary1186382 -Node: Extension Exercises1190084 -Node: Language History1191326 -Node: V7/SVR3.11192982 -Node: SVR41195134 -Node: POSIX1196568 -Node: BTL1197949 -Node: POSIX/GNU1198678 -Node: Feature History1204456 -Node: Common Extensions1221631 -Node: Ranges and Locales1222914 -Ref: Ranges and Locales-Footnote-11227530 -Ref: Ranges and Locales-Footnote-21227557 -Ref: Ranges and Locales-Footnote-31227792 -Node: Contributors1228015 -Node: History summary1234012 -Node: Installation1235392 -Node: Gawk Distribution1236336 -Node: Getting1236820 -Node: Extracting1237783 -Node: Distribution contents1239421 -Node: Unix Installation1246482 -Node: Quick Installation1247286 -Node: Compiling with MPFR1249706 -Node: Shell Startup Files1250396 -Node: Additional Configuration Options1251485 -Node: Configuration Philosophy1253800 -Node: Compiling from Git1256196 -Node: Building the Documentation1256751 -Node: Non-Unix Installation1258135 -Node: PC Installation1258595 -Node: PC Binary Installation1259433 -Node: PC Compiling1260306 -Node: PC Using1261423 -Node: Cygwin1264976 -Node: MSYS1266200 -Node: VMS Installation1266802 -Node: VMS Compilation1267521 -Ref: VMS Compilation-Footnote-11268750 -Node: VMS Dynamic Extensions1268808 -Node: VMS Installation Details1270493 -Node: VMS Running1272755 -Node: VMS GNV1277034 -Node: Bugs1277748 -Node: Bug definition1278660 -Node: Bug address1281596 -Node: Usenet1284984 -Node: Performance bugs1286173 -Node: Asking for help1289094 -Node: Maintainers1291061 -Node: Other Versions1292255 -Node: Installation summary1300419 -Node: Notes1301783 -Node: Compatibility Mode1302577 -Node: Additions1303359 -Node: Accessing The Source1304284 -Node: Adding Code1305721 -Node: New Ports1311913 -Node: Derived Files1316288 -Ref: Derived Files-Footnote-11321948 -Ref: Derived Files-Footnote-21321983 -Ref: Derived Files-Footnote-31322581 -Node: Future Extensions1322695 -Node: Implementation Limitations1323353 -Node: Extension Design1324563 -Node: Old Extension Problems1325707 -Ref: Old Extension Problems-Footnote-11327225 -Node: Extension New Mechanism Goals1327282 -Ref: Extension New Mechanism Goals-Footnote-11330646 -Node: Extension Other Design Decisions1330835 -Node: Extension Future Growth1332948 -Node: Notes summary1333554 -Node: Basic Concepts1334712 -Node: Basic High Level1335393 -Ref: figure-general-flow1335675 -Ref: figure-process-flow1336361 -Ref: Basic High Level-Footnote-11339663 -Node: Basic Data Typing1339848 -Node: Glossary1343176 -Node: Copying1375063 -Node: GNU Free Documentation License1412606 -Node: Index1437726 +Node: Functions Summary652513 +Node: Library Functions655218 +Ref: Library Functions-Footnote-1658825 +Ref: Library Functions-Footnote-2658968 +Node: Library Names659139 +Ref: Library Names-Footnote-1662806 +Ref: Library Names-Footnote-2663029 +Node: General Functions663115 +Node: Strtonum Function664297 +Node: Assert Function667319 +Node: Round Function670645 +Node: Cliff Random Function672185 +Node: Ordinal Functions673201 +Ref: Ordinal Functions-Footnote-1676264 +Ref: Ordinal Functions-Footnote-2676516 +Node: Join Function676726 +Ref: Join Function-Footnote-1678496 +Node: Getlocaltime Function678696 +Node: Readfile Function682438 +Node: Shell Quoting684415 +Node: Isnumeric Function685843 +Node: Data File Management687231 +Node: Filetrans Function687863 +Node: Rewind Function691959 +Node: File Checking693868 +Ref: File Checking-Footnote-1695202 +Node: Empty Files695403 +Node: Ignoring Assigns697382 +Node: Getopt Function698932 +Ref: Getopt Function-Footnote-1714229 +Node: Passwd Functions714429 +Ref: Passwd Functions-Footnote-1723268 +Node: Group Functions723356 +Ref: Group Functions-Footnote-1731254 +Node: Walking Arrays731461 +Node: Library Functions Summary734469 +Node: Library Exercises735875 +Node: Sample Programs736340 +Node: Running Examples737110 +Node: Clones737838 +Node: Cut Program739062 +Node: Egrep Program749202 +Node: Id Program758203 +Node: Split Program768138 +Ref: Split Program-Footnote-1778031 +Node: Tee Program778204 +Node: Uniq Program780994 +Node: Wc Program788582 +Node: Bytes vs. Characters788969 +Node: Using extensions790517 +Node: wc program791271 +Node: Miscellaneous Programs796136 +Node: Dupword Program797349 +Node: Alarm Program799379 +Node: Translate Program804234 +Ref: Translate Program-Footnote-1808799 +Node: Labels Program809069 +Ref: Labels Program-Footnote-1812420 +Node: Word Sorting812504 +Node: History Sorting816576 +Node: Extract Program818801 +Node: Simple Sed826814 +Node: Igawk Program829888 +Ref: Igawk Program-Footnote-1844219 +Ref: Igawk Program-Footnote-2844421 +Ref: Igawk Program-Footnote-3844543 +Node: Anagram Program844658 +Node: Signature Program847720 +Node: Programs Summary848967 +Node: Programs Exercises850181 +Ref: Programs Exercises-Footnote-1854311 +Node: Advanced Features854397 +Node: Nondecimal Data856528 +Node: Boolean Typed Values858126 +Node: Array Sorting860007 +Node: Controlling Array Traversal860712 +Ref: Controlling Array Traversal-Footnote-1869080 +Node: Array Sorting Functions869198 +Ref: Array Sorting Functions-Footnote-1874572 +Node: Two-way I/O874768 +Ref: Two-way I/O-Footnote-1882494 +Ref: Two-way I/O-Footnote-2882681 +Node: TCP/IP Networking882763 +Node: Profiling885839 +Node: Extension Philosophy895148 +Node: Advanced Features Summary896627 +Node: Internationalization898642 +Node: I18N and L10N900316 +Node: Explaining gettext901003 +Ref: Explaining gettext-Footnote-1906895 +Ref: Explaining gettext-Footnote-2907080 +Node: Programmer i18n907245 +Ref: Programmer i18n-Footnote-1912194 +Node: Translator i18n912243 +Node: String Extraction913037 +Ref: String Extraction-Footnote-1914169 +Node: Printf Ordering914255 +Ref: Printf Ordering-Footnote-1917041 +Node: I18N Portability917105 +Ref: I18N Portability-Footnote-1919561 +Node: I18N Example919624 +Ref: I18N Example-Footnote-1922899 +Ref: I18N Example-Footnote-2922972 +Node: Gawk I18N923081 +Node: I18N Summary923703 +Node: Debugger925044 +Node: Debugging926044 +Node: Debugging Concepts926485 +Node: Debugging Terms928294 +Node: Awk Debugging930869 +Ref: Awk Debugging-Footnote-1931814 +Node: Sample Debugging Session931946 +Node: Debugger Invocation932480 +Node: Finding The Bug933866 +Node: List of Debugger Commands940340 +Node: Breakpoint Control941673 +Node: Debugger Execution Control945367 +Node: Viewing And Changing Data948729 +Node: Execution Stack952270 +Node: Debugger Info953907 +Node: Miscellaneous Debugger Commands957978 +Node: Readline Support963040 +Node: Limitations963936 +Node: Debugging Summary966490 +Node: Namespaces967769 +Node: Global Namespace968880 +Node: Qualified Names970278 +Node: Default Namespace971277 +Node: Changing The Namespace972018 +Node: Naming Rules973632 +Node: Internal Name Management975480 +Node: Namespace Example976522 +Node: Namespace And Features979084 +Node: Namespace Summary980519 +Node: Arbitrary Precision Arithmetic981996 +Node: Computer Arithmetic983483 +Ref: table-numeric-ranges987249 +Ref: table-floating-point-ranges987743 +Ref: Computer Arithmetic-Footnote-1988402 +Node: Math Definitions988459 +Ref: table-ieee-formats991435 +Node: MPFR features992003 +Node: FP Math Caution993721 +Ref: FP Math Caution-Footnote-1994793 +Node: Inexactness of computations995162 +Node: Inexact representation996193 +Node: Comparing FP Values997553 +Node: Errors accumulate998794 +Node: Strange values1000250 +Ref: Strange values-Footnote-11002838 +Node: Getting Accuracy1002943 +Node: Try To Round1005653 +Node: Setting precision1006552 +Ref: table-predefined-precision-strings1007249 +Node: Setting the rounding mode1009080 +Ref: table-gawk-rounding-modes1009454 +Ref: Setting the rounding mode-Footnote-11013386 +Node: Arbitrary Precision Integers1013565 +Ref: Arbitrary Precision Integers-Footnote-11016740 +Node: Checking for MPFR1016889 +Node: POSIX Floating Point Problems1018363 +Ref: POSIX Floating Point Problems-Footnote-11023016 +Node: Floating point summary1023054 +Node: Dynamic Extensions1025244 +Node: Extension Intro1026797 +Node: Plugin License1028063 +Node: Extension Mechanism Outline1028860 +Ref: figure-load-extension1029299 +Ref: figure-register-new-function1030865 +Ref: figure-call-new-function1031958 +Node: Extension API Description1034021 +Node: Extension API Functions Introduction1035734 +Ref: table-api-std-headers1037570 +Node: General Data Types1041820 +Ref: General Data Types-Footnote-11050526 +Node: Memory Allocation Functions1050825 +Ref: Memory Allocation Functions-Footnote-11055326 +Node: Constructor Functions1055425 +Node: API Ownership of MPFR and GMP Values1059078 +Node: Registration Functions1060391 +Node: Extension Functions1061091 +Node: Exit Callback Functions1066413 +Node: Extension Version String1067663 +Node: Input Parsers1068326 +Node: Output Wrappers1081047 +Node: Two-way processors1085559 +Node: Printing Messages1087824 +Ref: Printing Messages-Footnote-11088995 +Node: Updating ERRNO1089148 +Node: Requesting Values1089887 +Ref: table-value-types-returned1090624 +Node: Accessing Parameters1091733 +Node: Symbol Table Access1092970 +Node: Symbol table by name1093482 +Ref: Symbol table by name-Footnote-11096507 +Node: Symbol table by cookie1096635 +Ref: Symbol table by cookie-Footnote-11100820 +Node: Cached values1100884 +Ref: Cached values-Footnote-11104420 +Node: Array Manipulation1104573 +Ref: Array Manipulation-Footnote-11105664 +Node: Array Data Types1105701 +Ref: Array Data Types-Footnote-11108359 +Node: Array Functions1108451 +Node: Flattening Arrays1112949 +Node: Creating Arrays1119925 +Node: Redirection API1124692 +Node: Extension API Variables1127525 +Node: Extension Versioning1128236 +Ref: gawk-api-version1128665 +Node: Extension GMP/MPFR Versioning1130397 +Node: Extension API Informational Variables1132025 +Node: Extension API Boilerplate1133098 +Node: Changes from API V11137072 +Node: Finding Extensions1138644 +Node: Extension Example1139203 +Node: Internal File Description1140001 +Node: Internal File Ops1144081 +Ref: Internal File Ops-Footnote-11155431 +Node: Using Internal File Ops1155571 +Ref: Using Internal File Ops-Footnote-11157954 +Node: Extension Samples1158228 +Node: Extension Sample File Functions1159757 +Node: Extension Sample Fnmatch1167406 +Node: Extension Sample Fork1168893 +Node: Extension Sample Inplace1170111 +Node: Extension Sample Ord1173737 +Node: Extension Sample Readdir1174573 +Ref: table-readdir-file-types1175462 +Node: Extension Sample Revout1176530 +Node: Extension Sample Rev2way1177119 +Node: Extension Sample Read write array1177859 +Node: Extension Sample Readfile1181025 +Node: Extension Sample Time1182120 +Node: Extension Sample API Tests1183872 +Node: gawkextlib1184364 +Node: Extension summary1187282 +Node: Extension Exercises1190984 +Node: Language History1192226 +Node: V7/SVR3.11193882 +Node: SVR41196034 +Node: POSIX1197468 +Node: BTL1198849 +Node: POSIX/GNU1199578 +Node: Feature History1205356 +Node: Common Extensions1222531 +Node: Ranges and Locales1223814 +Ref: Ranges and Locales-Footnote-11228430 +Ref: Ranges and Locales-Footnote-21228457 +Ref: Ranges and Locales-Footnote-31228692 +Node: Contributors1228915 +Node: History summary1234912 +Node: Installation1236292 +Node: Gawk Distribution1237236 +Node: Getting1237720 +Node: Extracting1238683 +Node: Distribution contents1240321 +Node: Unix Installation1247382 +Node: Quick Installation1248186 +Node: Compiling with MPFR1250606 +Node: Shell Startup Files1251296 +Node: Additional Configuration Options1252385 +Node: Configuration Philosophy1254700 +Node: Compiling from Git1257096 +Node: Building the Documentation1257651 +Node: Non-Unix Installation1259035 +Node: PC Installation1259495 +Node: PC Binary Installation1260333 +Node: PC Compiling1261206 +Node: PC Using1262323 +Node: Cygwin1265876 +Node: MSYS1267100 +Node: VMS Installation1267702 +Node: VMS Compilation1268421 +Ref: VMS Compilation-Footnote-11269650 +Node: VMS Dynamic Extensions1269708 +Node: VMS Installation Details1271393 +Node: VMS Running1273655 +Node: VMS GNV1277934 +Node: Bugs1278648 +Node: Bug definition1279560 +Node: Bug address1282496 +Node: Usenet1285884 +Node: Performance bugs1287073 +Node: Asking for help1289994 +Node: Maintainers1291961 +Node: Other Versions1293155 +Node: Installation summary1301319 +Node: Notes1302683 +Node: Compatibility Mode1303477 +Node: Additions1304259 +Node: Accessing The Source1305184 +Node: Adding Code1306621 +Node: New Ports1312813 +Node: Derived Files1317188 +Ref: Derived Files-Footnote-11322848 +Ref: Derived Files-Footnote-21322883 +Ref: Derived Files-Footnote-31323481 +Node: Future Extensions1323595 +Node: Implementation Limitations1324253 +Node: Extension Design1325463 +Node: Old Extension Problems1326607 +Ref: Old Extension Problems-Footnote-11328125 +Node: Extension New Mechanism Goals1328182 +Ref: Extension New Mechanism Goals-Footnote-11331546 +Node: Extension Other Design Decisions1331735 +Node: Extension Future Growth1333848 +Node: Notes summary1334454 +Node: Basic Concepts1335612 +Node: Basic High Level1336293 +Ref: figure-general-flow1336575 +Ref: figure-process-flow1337261 +Ref: Basic High Level-Footnote-11340563 +Node: Basic Data Typing1340748 +Node: Glossary1344076 +Node: Copying1375963 +Node: GNU Free Documentation License1413506 +Node: Index1438626 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index 7fb6a570..dbacdb2f 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -22281,16 +22281,28 @@ built-in functions indirectly, as follows. @itemize @value{BULLET} @item You cannot pass a regular expression constant to a built-in function -through an indirect function call.@footnote{This may change in a future -version; recheck the documentation that comes with your version of -@command{gawk} to see if it has.} This applies to the @code{sub()}, +through an indirect function call. This applies to the @code{sub()}, @code{gsub()}, @code{gensub()}, @code{match()}, @code{split()} and -@code{patsplit()} functions. +@code{patsplit()} functions. However, you can pass a strongly typed +regexp constant (@pxref{Strong Regexp Constants}). @item If calling @code{sub()} or @code{gsub()}, you may only pass two arguments, since those functions are unusual in that they update their third argument. This means that @code{$0} will be updated. + +@item +You cannot indirectly call built-in functions that can take @code{$0} as +a default parameter; you must supply an argument instead. For example, +you must pass an argument to @code{length()} if calling it indirectly. + +@item +Calling a built-in function indirectly with the wrong number of arguments +for that function causes a fatal error. For example, calling +@code{length()} with two arguments. These errors are found at runtime +instead of when @command{gawk} parses your program, since @command{gawk} +doesn't know until runtime if you have passed the correct number of +arguments or not. @end itemize @command{gawk} does its best to make indirect function calls efficient. @@ -35284,6 +35296,14 @@ Similarly, in POSIX mode, @command{gawk} prints the result of the system's C @code{printf()} function using the @code{%g} format string for the value, whatever that may be. +@quotation NOTE +The sign used for NaN values can vary! The result depends upon both +the underlying system architecture and the underlying library used to +format NaN values. In particular, it's possible to get different results +for the same function call depending upon whether or not @command{gawk} +is running in MPFR mode (@option{-M}) or not. Caveat Emptor! +@end quotation + @node Floating point summary @section Summary diff --git a/doc/gawktexi.in b/doc/gawktexi.in index f8c164e9..36850146 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -21193,16 +21193,28 @@ built-in functions indirectly, as follows. @itemize @value{BULLET} @item You cannot pass a regular expression constant to a built-in function -through an indirect function call.@footnote{This may change in a future -version; recheck the documentation that comes with your version of -@command{gawk} to see if it has.} This applies to the @code{sub()}, +through an indirect function call. This applies to the @code{sub()}, @code{gsub()}, @code{gensub()}, @code{match()}, @code{split()} and -@code{patsplit()} functions. +@code{patsplit()} functions. However, you can pass a strongly typed +regexp constant (@pxref{Strong Regexp Constants}). @item If calling @code{sub()} or @code{gsub()}, you may only pass two arguments, since those functions are unusual in that they update their third argument. This means that @code{$0} will be updated. + +@item +You cannot indirectly call built-in functions that can take @code{$0} as +a default parameter; you must supply an argument instead. For example, +you must pass an argument to @code{length()} if calling it indirectly. + +@item +Calling a built-in function indirectly with the wrong number of arguments +for that function causes a fatal error. For example, calling +@code{length()} with two arguments. These errors are found at runtime +instead of when @command{gawk} parses your program, since @command{gawk} +doesn't know until runtime if you have passed the correct number of +arguments or not. @end itemize @command{gawk} does its best to make indirect function calls efficient. @@ -34127,6 +34139,14 @@ Similarly, in POSIX mode, @command{gawk} prints the result of the system's C @code{printf()} function using the @code{%g} format string for the value, whatever that may be. +@quotation NOTE +The sign used for NaN values can vary! The result depends upon both +the underlying system architecture and the underlying library used to +format NaN values. In particular, it's possible to get different results +for the same function call depending upon whether or not @command{gawk} +is running in MPFR mode (@option{-M}) or not. Caveat Emptor! +@end quotation + @node Floating point summary @section Summary @@ -979,6 +979,8 @@ do_split(int nargs) Regexp *, Setfunc, NODE *, NODE *, bool); Regexp *rp = NULL; + check_args_min_max(nargs, "split", 3, 4); + if (nargs == 4) { static bool warned = false; @@ -1081,6 +1083,8 @@ do_patsplit(int nargs) char *s; Regexp *rp = NULL; + check_args_min_max(nargs, "patsplit", 3, 4); + if (nargs == 4) { sep_arr = POP_PARAM(); if (sep_arr->type != Node_var_array) diff --git a/interpret.h b/interpret.h index df70bd09..3d9ba572 100644 --- a/interpret.h +++ b/interpret.h @@ -67,6 +67,7 @@ r_interpret(INSTRUCTION *code) Regexp *rp; NODE *set_array = NULL; /* array with a post-assignment routine */ NODE *set_idx = NULL; /* the index of the array element */ + bool in_indirect_call = false; /* array subscript */ @@ -1059,6 +1060,14 @@ arrayfor: DEREF(t1); } free_api_string_copies(); + + if (in_indirect_call) { + // pop function name off the stack + NODE *fname = POP(); + DEREF(fname); + in_indirect_call = false; + } + PUSH(r); } break; @@ -1132,6 +1141,7 @@ match_re: NODE *f = NULL; int arg_count; char save; + NODE *function_name; arg_count = (pc + 1)->expr_count; t1 = PEEK(arg_count); /* indirect var */ @@ -1174,6 +1184,12 @@ match_re: r = the_func(arg_count); str_restore(t1, save); + // Normally, setup_frame() handles getting rid of the + // function name. Since we have called the builtin directly, + // we have to manually do this here. + function_name = POP(); + DEREF(function_name); + PUSH(r); break; } else if (f->type != Node_func) { @@ -1195,6 +1211,7 @@ match_re: npc[1] = pc[1]; npc[1].func_name = fname; /* name of the builtin */ npc[1].c_function = bc->c_function; + in_indirect_call = true; ni = npc; JUMPTO(ni); } else @@ -767,6 +767,8 @@ do_mpfr_atan2(int nargs) mpfr_ptr p1, p2; int tval; + check_exact_args(nargs, "atan2", 2); + t2 = POP_SCALAR(); t1 = POP_SCALAR(); @@ -803,6 +805,8 @@ do_mpfr_func(const char *name, int tval; mpfr_prec_t argprec; + check_exact_args(nargs, name, 1); + t1 = POP_SCALAR(); if (do_lint && (fixtype(t1)->flags & NUMBER) == 0) lintwarn(_("%s: received non-numeric argument"), name); @@ -874,6 +878,8 @@ do_mpfr_int(int nargs) { NODE *tmp, *r; + check_exact_args(nargs, "int", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("int: received non-numeric argument")); @@ -904,6 +910,8 @@ do_mpfr_compl(int nargs) NODE *tmp, *r; mpz_ptr zptr; + check_exact_args(nargs, "compl", 1); + tmp = POP_SCALAR(); if (do_lint && (fixtype(tmp)->flags & NUMBER) == 0) lintwarn(_("compl: received non-numeric argument")); @@ -1023,6 +1031,8 @@ do_mpfr_lshift(int nargs) unsigned long shift; mpz_ptr pz1, pz2; + check_exact_args(nargs, "lshift", 2); + t2 = POP_SCALAR(); t1 = POP_SCALAR(); @@ -1055,6 +1065,8 @@ do_mpfr_rshift(int nargs) unsigned long shift; mpz_ptr pz1, pz2; + check_exact_args(nargs, "rshift", 2); + t2 = POP_SCALAR(); t1 = POP_SCALAR(); @@ -1175,6 +1187,8 @@ do_mpfr_strtonum(int nargs) { NODE *tmp, *r; + check_exact_args(nargs, "strtonum", 1); + tmp = fixtype(POP_SCALAR()); if ((tmp->flags & NUMBER) == 0) { r = mpg_integer(); /* will be changed to MPFR float if necessary in force_mpnum() */ @@ -1212,6 +1226,8 @@ do_mpfr_rand(int nargs ATTRIBUTE_UNUSED) NODE *res; int tval; + check_exact_args(nargs, "rand", 0); + if (firstrand) { #if 0 /* Choose the default algorithm */ @@ -1262,6 +1278,8 @@ do_mpfr_srand(int nargs) firstrand = false; } + check_args_min_max(nargs, "srand", 0, 1); + res = mpg_integer(); mpz_set(res->mpg_i, seed); /* previous seed */ @@ -1303,6 +1321,8 @@ do_mpfr_intdiv(int nargs) NODE *quotient, *remainder; NODE *sub, **lhs; + check_exact_args(nargs, "intdiv", 3); + result = POP_PARAM(); if (result->type != Node_var_array) fatal(_("intdiv: third argument is not an array")); diff --git a/pc/ChangeLog b/pc/ChangeLog index 7b6bc9f7..cbca6b52 100644 --- a/pc/ChangeLog +++ b/pc/ChangeLog @@ -1,3 +1,7 @@ +2022-02-09 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.tst: Regenerated. + 2022-01-05 Arnold D. Robbins <arnold@skeeve.com> * Makefile.tst: Regenerated. diff --git a/pc/Makefile.tst b/pc/Makefile.tst index 5caf38cc..775ad2c1 100644 --- a/pc/Makefile.tst +++ b/pc/Makefile.tst @@ -197,6 +197,7 @@ GAWK_EXT_TESTS = \ icasefs icasers id igncdym igncfs ignrcas2 ignrcas4 ignrcase \ incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \ include include2 indirectbuiltin indirectcall indirectcall2 \ + indirectbuiltin2 \ inf-nan-torture intarray iolint isarrayunset lint lintexp \ lintindex lintint lintlength lintold lintplus lintset lintwarn \ manyfiles match1 match2 match3 mbstr1 mbstr2 mixed1 mktime \ @@ -1245,6 +1246,13 @@ argcasfile: @echo $@ @-$(AWK) -f "$(srcdir)"/$@.awk ARGC=1 ' /no/such/file' < "$(srcdir)/$@.in" >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +indirectbuiltin2: + @echo $@ + @-for test in 0 1 2 3 4 5 ; do \ + $(AWK) -v test=$$test -f "$(srcdir)"/$@.awk ; \ + done > _$@ 2>&1 || exit 0 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ Gt-dummy: # file Maketests, generated from Makefile.am by the Gentests program addcomma: diff --git a/test/ChangeLog b/test/ChangeLog index 47289312..6cd59729 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,8 @@ +2022-02-09 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (EXTRA_DIST): indirectbuiltin2, new test. + * indirectbuiltin2.awk, indirectbuiltin2.ok: New files. + 2022-01-05 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (EXTRA_DIST): nsidentifier, new test. diff --git a/test/Makefile.am b/test/Makefile.am index 16606b09..ca4920fe 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -569,6 +569,8 @@ EXTRA_DIST = \ include.ok \ indirectbuiltin.awk \ indirectbuiltin.ok \ + indirectbuiltin2.awk \ + indirectbuiltin2.ok \ indirectcall2.awk \ indirectcall2.ok \ indirectcall.awk \ @@ -1455,6 +1457,7 @@ GAWK_EXT_TESTS = \ icasefs icasers id igncdym igncfs ignrcas2 ignrcas4 ignrcase \ incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \ include include2 indirectbuiltin indirectcall indirectcall2 \ + indirectbuiltin2 \ inf-nan-torture intarray iolint isarrayunset lint lintexp \ lintindex lintint lintlength lintold lintplus lintset lintwarn \ manyfiles match1 match2 match3 mbstr1 mbstr2 mixed1 mktime \ @@ -2504,6 +2507,13 @@ argcasfile: @-$(AWK) -f "$(srcdir)"/$@.awk ARGC=1 ' /no/such/file' < "$(srcdir)/$@.in" >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ +indirectbuiltin2: + @echo $@ + @-for test in 0 1 2 3 4 5 ; do \ + $(AWK) -v test=$$test -f "$(srcdir)"/$@.awk ; \ + done > _$@ 2>&1 || exit 0 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + # Targets generated for other tests: include Maketests diff --git a/test/Makefile.in b/test/Makefile.in index cb4551e2..380a7d90 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -835,6 +835,8 @@ EXTRA_DIST = \ include.ok \ indirectbuiltin.awk \ indirectbuiltin.ok \ + indirectbuiltin2.awk \ + indirectbuiltin2.ok \ indirectcall2.awk \ indirectcall2.ok \ indirectcall.awk \ @@ -1721,6 +1723,7 @@ GAWK_EXT_TESTS = \ icasefs icasers id igncdym igncfs ignrcas2 ignrcas4 ignrcase \ incdupe incdupe2 incdupe3 incdupe4 incdupe5 incdupe6 incdupe7 \ include include2 indirectbuiltin indirectcall indirectcall2 \ + indirectbuiltin2 \ inf-nan-torture intarray iolint isarrayunset lint lintexp \ lintindex lintint lintlength lintold lintplus lintset lintwarn \ manyfiles match1 match2 match3 mbstr1 mbstr2 mixed1 mktime \ @@ -2952,6 +2955,13 @@ argcasfile: @echo $@ @-$(AWK) -f "$(srcdir)"/$@.awk ARGC=1 ' /no/such/file' < "$(srcdir)/$@.in" >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ + +indirectbuiltin2: + @echo $@ + @-for test in 0 1 2 3 4 5 ; do \ + $(AWK) -v test=$$test -f "$(srcdir)"/$@.awk ; \ + done > _$@ 2>&1 || exit 0 + @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@ Gt-dummy: # file Maketests, generated from Makefile.am by the Gentests program addcomma: diff --git a/test/indirectbuiltin2.awk b/test/indirectbuiltin2.awk new file mode 100644 index 00000000..6409f91a --- /dev/null +++ b/test/indirectbuiltin2.awk @@ -0,0 +1,29 @@ +@load "ordchr" + +BEGIN { + o = "ord" # check stack for indirect call of ext function + l = "length" # check bad args for function of 1 argument + m = "match" # check bad args for function of 3-4 argument + s = "systime" # check bad args for function of 0 arguments + + switch (test) { + case 0: + print "indirect, " @o("A") + break + case 1: + print @l() + break + case 2: + print @l("a", "b") + break + case 3: + print @m(@/foo/) + break + case 4: + print @m(@/foo/, "bar", a, b) + break + case 5: + print @s("xxx") + break + } +} diff --git a/test/indirectbuiltin2.ok b/test/indirectbuiltin2.ok new file mode 100644 index 00000000..dfb2005e --- /dev/null +++ b/test/indirectbuiltin2.ok @@ -0,0 +1,6 @@ +indirect, 65 +gawk: ./indirectbuiltin2.awk:14: fatal: length: called with 0 arguments +gawk: ./indirectbuiltin2.awk:17: fatal: length: called with 2 arguments +gawk: ./indirectbuiltin2.awk:20: fatal: indirect call to match requires two or three arguments +gawk: ./indirectbuiltin2.awk:23: fatal: indirect call to match requires two or three arguments +gawk: ./indirectbuiltin2.awk:26: fatal: systime: called with 1 arguments |