diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2016-12-06 22:06:26 +0200 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2016-12-06 22:06:26 +0200 |
commit | f2b6d100d8958a9c811c950f113a0ce38a25d484 (patch) | |
tree | 53c03280dab7f88134bbcdad1279f13cf12b0cf6 | |
parent | 0dd8054d05d8286f2f7cbcf85456c6953a9b6146 (diff) | |
download | egawk-f2b6d100d8958a9c811c950f113a0ce38a25d484.tar.gz egawk-f2b6d100d8958a9c811c950f113a0ce38a25d484.tar.bz2 egawk-f2b6d100d8958a9c811c950f113a0ce38a25d484.zip |
Add min_required and max_expected arg counts to API.
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | awk.h | 7 | ||||
-rw-r--r-- | ext.c | 3 | ||||
-rw-r--r-- | extension/ChangeLog | 17 | ||||
-rw-r--r-- | extension/filefuncs.c | 25 | ||||
-rw-r--r-- | extension/fnmatch.c | 9 | ||||
-rw-r--r-- | extension/fork.c | 18 | ||||
-rw-r--r-- | extension/inplace.c | 4 | ||||
-rw-r--r-- | extension/ordchr.c | 26 | ||||
-rw-r--r-- | extension/readfile.c | 7 | ||||
-rw-r--r-- | extension/rwarray.c | 10 | ||||
-rw-r--r-- | extension/rwarray0.c | 10 | ||||
-rw-r--r-- | extension/testext.c | 28 | ||||
-rw-r--r-- | extension/time.c | 10 | ||||
-rw-r--r-- | gawkapi.h | 17 | ||||
-rw-r--r-- | interpret.h | 16 |
16 files changed, 108 insertions, 113 deletions
@@ -1,3 +1,17 @@ +2016-12-06 Arnold D. Robbins <arnold@skeeve.com> + + Add minimum required and maximum expected number of arguments + to the API. + + * awk.h (INSTRUCTION): Add new members min_required and max_expected. + * ext.c (make_builtin): Store values from extension function struct + into the INSTRUCTION. + * gawkapi.h (awk_ext_func): Add min_required args. Make both it and + max_expected_args into unsigned short to match type in INSTRUCTION. + * interpret.h (Op_ext_builtin): Store min_required and max_expected + in instructions. Add checking code and lint checks. + (Op_ext_func): Copy min_required and max_expected from function info. + 2016-11-30 Arnold D. Robbins <arnold@skeeve.com> * dfa.c: Sync with fixes in GNULIB. @@ -778,6 +778,10 @@ typedef struct exp_instruction { void (*aptr)(void); struct exp_instruction *xi; struct break_point *bpt; + struct { + uint16_t mr; // minimum required + uint16_t me; // maximum expected + } fa; // function args } x; short source_line; @@ -793,6 +797,9 @@ typedef struct exp_instruction { #define expr_count x.xl +#define min_required x.fa.mr +#define max_expected x.fa.me + #define target_continue d.di #define target_jmp d.di #define target_break x.xi @@ -136,7 +136,8 @@ make_builtin(const awk_ext_func_t *funcinfo) b = bcalloc(Op_symbol, 1, 0); b->extfunc = funcinfo->function; - b->expr_count = count; + b->min_required = funcinfo->min_required_args; + b->max_expected = funcinfo->max_expected_args; /* NB: extension sub must return something */ diff --git a/extension/ChangeLog b/extension/ChangeLog index 52d4ddb5..845391f9 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -1,3 +1,20 @@ +2016-12-06 Arnold D. Robbins <arnold@skeeve.com> + + Add minimum required and maximum expected number of arguments + to the API. + + * filefuncs.c: Update with max expected value. Remove lint + checks since that's now done by gawk. + * fnmatch.c: Ditto. + * fork.c: Ditto. + * inplace.c: Ditto. + * ordchr.c: Ditto. + * readfile.c: Ditto. + * rwarray.c: Ditto. + * rwarray0.c: Ditto. + * testext.c: Ditto. + * time.c: Ditto. + 2016-10-23 Arnold D. Robbins <arnold@skeeve.com> * General: Remove trailing whitespace from all relevant files. diff --git a/extension/filefuncs.c b/extension/filefuncs.c index a074de53..02b40534 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -160,9 +160,6 @@ do_chdir(int nargs, awk_value_t *result) assert(result != NULL); - if (do_lint && nargs != 1) - lintwarn(ext_id, _("chdir: called with incorrect number of arguments, expecting 1")); - if (get_argument(0, AWK_STRING, & newdir)) { ret = chdir(newdir.str_value.str); if (ret < 0) @@ -472,12 +469,6 @@ do_stat(int nargs, awk_value_t *result) assert(result != NULL); - if (nargs != 2 && nargs != 3) { - if (do_lint) - lintwarn(ext_id, _("stat: called with wrong number of arguments")); - return make_number(-1, result); - } - /* file is first arg, array to hold results is second */ if ( ! get_argument(0, AWK_STRING, & file_param) || ! get_argument(1, AWK_ARRAY, & array_param)) { @@ -522,12 +513,6 @@ do_statvfs(int nargs, awk_value_t *result) assert(result != NULL); - if (nargs != 2) { - if (do_lint) - lintwarn(ext_id, _("statvfs: called with wrong number of arguments")); - return make_number(-1, result); - } - /* file is first arg, array to hold results is second */ if ( ! get_argument(0, AWK_STRING, & file_param) || ! get_argument(1, AWK_ARRAY, & array_param)) { @@ -845,7 +830,7 @@ do_fts(int nargs, awk_value_t *result) assert(result != NULL); fts_errors = 0; /* ensure a fresh start */ - if (do_lint && nargs != 3) + if (nargs > 3) lintwarn(ext_id, _("fts: called with incorrect number of arguments, expecting 3")); if (! get_argument(0, AWK_ARRAY, & pathlist)) { @@ -928,13 +913,13 @@ out: #endif /* ! __MINGW32__ */ static awk_ext_func_t func_table[] = { - { "chdir", do_chdir, 1 }, - { "stat", do_stat, 3 }, + { "chdir", do_chdir, 1, 1 }, + { "stat", do_stat, 2, 3 }, #ifndef __MINGW32__ - { "fts", do_fts, 3 }, + { "fts", do_fts, 3, 3 }, #endif #if defined(HAVE_SYS_STATVFS_H) && defined(HAVE_STATVFS) - { "statvfs", do_statvfs, 2 }, + { "statvfs", do_statvfs, 2, 2 }, #endif }; diff --git a/extension/fnmatch.c b/extension/fnmatch.c index f5fb02c6..caf64a7b 100644 --- a/extension/fnmatch.c +++ b/extension/fnmatch.c @@ -107,13 +107,8 @@ do_fnmatch(int nargs, awk_value_t *result) int int_flags, retval; make_number(-1.0, result); /* default return */ -#ifdef HAVE_FNMATCH - if (nargs < 3) { - warning(ext_id, _("fnmatch: called with less than three arguments")); - goto out; - } else if (do_lint && nargs > 3) - lintwarn(ext_id, _("fnmatch: called with more than three arguments")); +#ifdef HAVE_FNMATCH if (! get_argument(0, AWK_STRING, & pattern)) { warning(ext_id, _("fnmatch: could not get first argument")); goto out; @@ -199,7 +194,7 @@ init_fnmatch(void) } static awk_ext_func_t func_table[] = { - { "fnmatch", do_fnmatch, 3 }, + { "fnmatch", do_fnmatch, 3, 3 }, }; /* define the dl_load function using the boilerplate macro */ diff --git a/extension/fork.c b/extension/fork.c index 82593b7f..064a2a8c 100644 --- a/extension/fork.c +++ b/extension/fork.c @@ -77,9 +77,6 @@ do_fork(int nargs, awk_value_t *result) assert(result != NULL); - if (do_lint && nargs > 0) - lintwarn(ext_id, _("fork: called with too many arguments")); - ret = fork(); if (ret < 0) @@ -114,16 +111,12 @@ do_waitpid(int nargs, awk_value_t *result) assert(result != NULL); - if (do_lint && nargs > 1) - lintwarn(ext_id, _("waitpid: called with too many arguments")); - if (get_argument(0, AWK_NUMBER, &pid)) { options = WNOHANG|WUNTRACED; ret = waitpid(pid.num_value, NULL, options); if (ret < 0) update_ERRNO_int(errno); - } else if (do_lint) - lintwarn(ext_id, _("wait: called with no arguments")); + } /* Set the return value */ return make_number(ret, result); @@ -139,9 +132,6 @@ do_wait(int nargs, awk_value_t *result) assert(result != NULL); - if (do_lint && nargs > 0) - lintwarn(ext_id, _("wait: called with too many arguments")); - ret = wait(NULL); if (ret < 0) update_ERRNO_int(errno); @@ -151,9 +141,9 @@ do_wait(int nargs, awk_value_t *result) } static awk_ext_func_t func_table[] = { - { "fork", do_fork, 0 }, - { "waitpid", do_waitpid, 1 }, - { "wait", do_wait, 0 }, + { "fork", do_fork, 0, 0 }, + { "waitpid", do_waitpid, 1, 1 }, + { "wait", do_wait, 0, 0 }, }; /* define the dl_load function using the boilerplate macro */ diff --git a/extension/inplace.c b/extension/inplace.c index 26c37922..19ee5605 100644 --- a/extension/inplace.c +++ b/extension/inplace.c @@ -262,8 +262,8 @@ do_inplace_end(int nargs, awk_value_t *result) } static awk_ext_func_t func_table[] = { - { "inplace_begin", do_inplace_begin, 2 }, - { "inplace_end", do_inplace_end, 2 }, + { "inplace_begin", do_inplace_begin, 2, 2 }, + { "inplace_end", do_inplace_end, 2, 2 }, }; static awk_bool_t init_inplace(void) diff --git a/extension/ordchr.c b/extension/ordchr.c index 4f9cd616..3722ced8 100644 --- a/extension/ordchr.c +++ b/extension/ordchr.c @@ -65,17 +65,10 @@ do_ord(int nargs, awk_value_t *result) assert(result != NULL); - if (do_lint && nargs > 1) - lintwarn(ext_id, _("ord: called with too many arguments")); - if (get_argument(0, AWK_STRING, & str)) { ret = str.str_value.str[0]; - } else if (do_lint) { - if (nargs == 0) - lintwarn(ext_id, _("ord: called with no arguments")); - else - lintwarn(ext_id, _("ord: called with inappropriate argument(s)")); - } + } else if (do_lint) + lintwarn(ext_id, _("ord: called with inappropriate argument(s)")); /* Set the return value */ return make_number(ret, result); @@ -95,29 +88,22 @@ do_chr(int nargs, awk_value_t *result) assert(result != NULL); - if (do_lint && nargs > 1) - lintwarn(ext_id, _("chr: called with too many arguments")); - if (get_argument(0, AWK_NUMBER, & num)) { val = num.num_value; ret = val; /* convert to int */ ret &= 0xff; str[0] = ret; str[1] = '\0'; - } else if (do_lint) { - if (nargs == 0) - lintwarn(ext_id, _("chr: called with no arguments")); - else - lintwarn(ext_id, _("chr: called with inappropriate argument(s)")); - } + } else if (do_lint) + lintwarn(ext_id, _("chr: called with inappropriate argument(s)")); /* Set the return value */ return make_const_string(str, 1, result); } static awk_ext_func_t func_table[] = { - { "ord", do_ord, 1 }, - { "chr", do_chr, 1 }, + { "ord", do_ord, 1, 1 }, + { "chr", do_chr, 1, 1 }, }; /* define the dl_load function using the boilerplate macro */ diff --git a/extension/readfile.c b/extension/readfile.c index fbe25748..cc9a4c14 100644 --- a/extension/readfile.c +++ b/extension/readfile.c @@ -109,9 +109,6 @@ do_readfile(int nargs, awk_value_t *result) assert(result != NULL); make_null_string(result); /* default return value */ - if (do_lint && nargs > 1) - lintwarn(ext_id, _("readfile: called with too many arguments")); - unset_ERRNO(); if (get_argument(0, AWK_STRING, &filename)) { @@ -134,7 +131,7 @@ do_readfile(int nargs, awk_value_t *result) make_malloced_string(text, sbuf.st_size, result); goto done; } else if (do_lint) - lintwarn(ext_id, _("readfile: called with no arguments")); + lintwarn(ext_id, _("readfile: called with wrong kind of argument")); done: /* Set the return value */ @@ -241,7 +238,7 @@ init_readfile() } static awk_ext_func_t func_table[] = { - { "readfile", do_readfile, 1 }, + { "readfile", do_readfile, 1, 1 }, }; /* define the dl_load function using the boilerplate macro */ diff --git a/extension/rwarray.c b/extension/rwarray.c index 15e121af..8c3200ea 100644 --- a/extension/rwarray.c +++ b/extension/rwarray.c @@ -109,9 +109,6 @@ do_writea(int nargs, awk_value_t *result) assert(result != NULL); make_number(0.0, result); - if (do_lint && nargs > 2) - lintwarn(ext_id, _("writea: called with too many arguments")); - if (nargs < 2) goto out; @@ -265,9 +262,6 @@ do_reada(int nargs, awk_value_t *result) assert(result != NULL); make_number(0.0, result); - if (do_lint && nargs > 2) - lintwarn(ext_id, _("reada: called with too many arguments")); - if (nargs < 2) goto out; @@ -470,8 +464,8 @@ read_value(FILE *fp, awk_value_t *value) } static awk_ext_func_t func_table[] = { - { "writea", do_writea, 2 }, - { "reada", do_reada, 2 }, + { "writea", do_writea, 2, 2 }, + { "reada", do_reada, 2, 2 }, }; diff --git a/extension/rwarray0.c b/extension/rwarray0.c index 00289cad..35e0a702 100644 --- a/extension/rwarray0.c +++ b/extension/rwarray0.c @@ -105,9 +105,6 @@ do_writea(int nargs, awk_value_t *result) assert(result != NULL); make_number(0.0, result); - if (do_lint && nargs > 2) - lintwarn(ext_id, _("writea: called with too many arguments")); - if (nargs < 2) goto out; @@ -261,9 +258,6 @@ do_reada(int nargs, awk_value_t *result) assert(result != NULL); make_number(0.0, result); - if (do_lint && nargs > 2) - lintwarn(ext_id, _("reada: called with too many arguments")); - if (nargs < 2) goto out; @@ -465,8 +459,8 @@ read_value(int fd, awk_value_t *value) } static awk_ext_func_t func_table[] = { - { "writea", do_writea, 2 }, - { "reada", do_reada, 2 }, + { "writea", do_writea, 2, 2 }, + { "reada", do_reada, 2, 2 }, }; diff --git a/extension/testext.c b/extension/testext.c index 9216d64a..227714e1 100644 --- a/extension/testext.c +++ b/extension/testext.c @@ -1024,20 +1024,20 @@ static void at_exit2(void *data, int exit_status) } static awk_ext_func_t func_table[] = { - { "dump_array_and_delete", dump_array_and_delete, 2 }, - { "try_modify_environ", try_modify_environ, 0 }, - { "var_test", var_test, 1 }, - { "test_deferred", test_deferred, 0 }, - { "test_errno", test_errno, 0 }, - { "test_array_size", test_array_size, 1 }, - { "test_array_elem", test_array_elem, 2 }, - { "test_array_param", test_array_param, 1 }, - { "print_do_lint", print_do_lint, 0 }, - { "test_scalar", test_scalar, 1 }, - { "test_scalar_reserved", test_scalar_reserved, 0 }, - { "test_indirect_vars", test_indirect_vars, 0 }, - { "test_get_file", test_get_file, 2 }, - { "get_file", do_get_file, 4 }, + { "dump_array_and_delete", dump_array_and_delete, 2, 2 }, + { "try_modify_environ", try_modify_environ, 0, 0 }, + { "var_test", var_test, 1, 1 }, + { "test_deferred", test_deferred, 0, 0 }, + { "test_errno", test_errno, 0, 0 }, + { "test_array_size", test_array_size, 1, 1 }, + { "test_array_elem", test_array_elem, 2, 2 }, + { "test_array_param", test_array_param, 1, 1 }, + { "print_do_lint", print_do_lint, 0, 0 }, + { "test_scalar", test_scalar, 1, 1 }, + { "test_scalar_reserved", test_scalar_reserved, 0, 0 }, + { "test_indirect_vars", test_indirect_vars, 0, 0 }, + { "test_get_file", test_get_file, 2, 2 }, + { "get_file", do_get_file, 4, 4 }, }; /* init_testext --- additional initialization function */ diff --git a/extension/time.c b/extension/time.c index e6b2b39f..67002752 100644 --- a/extension/time.c +++ b/extension/time.c @@ -109,9 +109,6 @@ do_gettimeofday(int nargs, awk_value_t *result) assert(result != NULL); - if (do_lint && nargs > 0) - lintwarn(ext_id, _("gettimeofday: ignoring arguments")); - #if defined(HAVE_GETTIMEOFDAY) { struct timeval tv; @@ -161,9 +158,6 @@ do_sleep(int nargs, awk_value_t *result) assert(result != NULL); - if (do_lint && nargs > 1) - lintwarn(ext_id, _("sleep: called with too many arguments")); - if (! get_argument(0, AWK_NUMBER, &num)) { update_ERRNO_string(_("sleep: missing required numeric argument")); return make_number(-1, result); @@ -212,8 +206,8 @@ do_sleep(int nargs, awk_value_t *result) } static awk_ext_func_t func_table[] = { - { "gettimeofday", do_gettimeofday, 0 }, - { "sleep", do_sleep, 1 }, + { "gettimeofday", do_gettimeofday, 0, 0 }, + { "sleep", do_sleep, 1, 1 }, }; /* define the dl_load function using the boilerplate macro */ @@ -376,15 +376,22 @@ typedef struct awk_flat_array { * Each extension function may decide what to do if the number of * arguments isn't what it expected. Following awk functions, it * is likely OK to ignore extra arguments. - - * Note that the 'max_expected_args' value should be used by the - * extension function itself only to trigger a lint warning if more - * arguments are passed to the function. + * + * 'min_required_args' indicates how many arguments MUST be passed. + * The API will throw a fatal error if not enough are passed. + * + * 'max_expected_args' is more benign; if more than that are passed, + * the API prints a lint message (IFF lint is enabled, of course). + * + * In any case, the extension function itself need not compare the + * actual number of arguments passed to those two values if it does + * not want to. */ typedef struct awk_ext_func { const char *name; awk_value_t *(*function)(int num_actual_args, awk_value_t *result); - size_t max_expected_args; + unsigned short min_required_args; + unsigned short max_expected_args; } awk_ext_func_t; typedef void *awk_ext_id_t; /* opaque type for extension id */ diff --git a/interpret.h b/interpret.h index da8e0604..2cefc14c 100644 --- a/interpret.h +++ b/interpret.h @@ -956,8 +956,21 @@ arrayfor: case Op_ext_builtin: { int arg_count = pc->expr_count; + int min_req = pc[1].min_required; + int max_expect = pc[1].max_expected; awk_value_t result; + if (min_req == 0 && max_expect == 0 && arg_count > min_req) + fatal(_("%s: cannot be called with arguments"), pc[1].func_name); + + if (min_req > 0 && arg_count < min_req) + fatal(_("%s: expects at least %d arguments, called with %d arguments"), + pc[1].func_name, min_req, arg_count); + + if (do_lint && arg_count > max_expect) + lintwarn(_("%s: called with %d arguments, only expecting %d"), + pc[1].func_name, arg_count, max_expect); + PUSH_CODE(pc); r = awk_value_to_node(pc->extfunc(arg_count, & result)); (void) POP_CODE(); @@ -1093,7 +1106,8 @@ match_re: npc[0].expr_count = arg_count; /* actual argument count */ npc[1] = pc[1]; npc[1].func_name = fname; /* name of the builtin */ - npc[1].expr_count = bc->expr_count; /* defined max # of arguments */ + npc[1].min_required = bc->min_required; + npc[1].max_expected = bc->max_expected; ni = npc; JUMPTO(ni); } else |