diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | extension/ChangeLog | 12 | ||||
-rw-r--r-- | extension/filefuncs.c | 14 | ||||
-rw-r--r-- | extension/fork.c | 4 | ||||
-rw-r--r-- | extension/ordchr.c | 4 | ||||
-rw-r--r-- | extension/readfile.c | 2 | ||||
-rw-r--r-- | extension/time.c | 5 | ||||
-rw-r--r-- | gawkapi.c | 153 | ||||
-rw-r--r-- | gawkapi.h | 68 | ||||
-rw-r--r-- | test/ChangeLog | 4 | ||||
-rw-r--r-- | test/Makefile.am | 2 | ||||
-rw-r--r-- | test/Makefile.in | 2 |
12 files changed, 184 insertions, 101 deletions
@@ -1,3 +1,18 @@ +2012-06-12 Arnold D. Robbins <arnold@skeeve.com> + + * gawkapi.h (awk_value_t): Restore union. + (get_curfunc_param): Renamed to get_argument. Return type changed + to awk_bool_t. Semantics better thought out and documented. + (awk_atexit, get_array_element): Return type now void. + (sym_lookup): Return type now void. Argument order rationalized. + + * gawkapi.c (node_to_awk_value): Return type is now awk_bool_t. + Semantics now match table in gawkawpi.h. + (api_awk_atexit): Return type now void. + (api_sym_lookup): Return type is now awk_bool_t. Change parameter + order. + (api_get_array_element): Return type is now awk_bool_t. + 2012-06-10 Andrew J. Schorr <aschorr@telemetry-investments.com> * TODO.xgawk: Addition of time extension moved to "done" section. diff --git a/extension/ChangeLog b/extension/ChangeLog index 5e513f8e..6c4ea84a 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -1,3 +1,15 @@ +2012-06-12 Arnold D. Robbins <arnold@skeeve.com> + + * filefuncs.c (do_chdir): Replace get_curfunc_param with get_argument. + (format_mode): Use unsigned masks. + (do_stat): Replace get_curfunc_param with get_argument. + * fork.c (do_fork): Rearrange arg order in call to sym_lookup + (do_waitpid): Replace get_curfunc_param with get_argument. + * ordchr.c (do_ord, do_chr): Replace get_curfunc_param with get_argument. + * readfile.c (do_readfile): Replace get_curfunc_param with get_argument. + * time.c (do_sleep): Replace get_curfunc_param with get_argument. + Replace set_ERRNO with update_ERRNO_str for no way to sleep case. + 2012-06-10 Andrew J. Schorr <aschorr@telemetry-investments.com> * Makefile.am: Add time extension. diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 4d382005..12f3acb6 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -57,7 +57,7 @@ do_chdir(int nargs, awk_value_t *result) if (do_lint && nargs != 1) lintwarn(ext_id, "chdir: called with incorrect number of arguments, expecting 1"); - if (get_curfunc_param(0, AWK_STRING, & newdir) != NULL) { + if (get_argument(0, AWK_STRING, & newdir)) { ret = chdir(newdir.str_value.str); if (ret < 0) update_ERRNO_int(errno); @@ -73,7 +73,7 @@ format_mode(unsigned long fmode) { static char outbuf[12]; static struct ftype_map { - int mask; + unsigned int mask; int charval; } ftype_map[] = { { S_IFREG, '-' }, /* redundant */ @@ -94,7 +94,7 @@ format_mode(unsigned long fmode) #endif /* S_IFDOOR */ }; static struct mode_map { - int mask; + unsigned int mask; int rep; } map[] = { { S_IRUSR, 'r' }, { S_IWUSR, 'w' }, { S_IXUSR, 'x' }, @@ -102,7 +102,7 @@ format_mode(unsigned long fmode) { S_IROTH, 'r' }, { S_IWOTH, 'w' }, { S_IXOTH, 'x' }, }; static struct setuid_map { - int mask; + unsigned int mask; int index; int small_rep; int big_rep; @@ -243,7 +243,7 @@ do_stat(int nargs, awk_value_t *result) const char *type = "unknown"; awk_value_t tmp; static struct ftype_map { - int mask; + unsigned int mask; const char *type; } ftype_map[] = { { S_IFREG, "file" }, @@ -270,8 +270,8 @@ do_stat(int nargs, awk_value_t *result) } /* file is first arg, array to hold results is second */ - if ( get_curfunc_param(0, AWK_STRING, & file_param) == NULL - || get_curfunc_param(1, AWK_ARRAY, & array_param) == NULL) { + if ( ! get_argument(0, AWK_STRING, & file_param) + || ! get_argument(1, AWK_ARRAY, & array_param)) { warning(ext_id, "stat: bad parameters"); return make_number(-1, result); } diff --git a/extension/fork.c b/extension/fork.c index 1d4ad82c..0c2e31d0 100644 --- a/extension/fork.c +++ b/extension/fork.c @@ -78,7 +78,7 @@ do_fork(int nargs, awk_value_t *result) /* update PROCINFO in the child, if the array exists */ awk_value_t procinfo; - if (sym_lookup("PROCINFO", & procinfo, AWK_ARRAY) != NULL) { + if (sym_lookup("PROCINFO", AWK_ARRAY, & procinfo)) { if (procinfo.val_type != AWK_ARRAY) { if (do_lint) lintwarn(ext_id, "fork: PROCINFO is not an array!"); @@ -105,7 +105,7 @@ do_waitpid(int nargs, awk_value_t *result) if (do_lint && nargs > 1) lintwarn(ext_id, "waitpid: called with too many arguments"); - if (get_curfunc_param(0, AWK_NUMBER, &pid) != NULL) { + if (get_argument(0, AWK_NUMBER, &pid)) { options = WNOHANG|WUNTRACED; ret = waitpid(pid.num_value, NULL, options); if (ret < 0) diff --git a/extension/ordchr.c b/extension/ordchr.c index c5d2bb45..dc02479a 100644 --- a/extension/ordchr.c +++ b/extension/ordchr.c @@ -56,7 +56,7 @@ do_ord(int nargs, awk_value_t *result) if (do_lint && nargs > 1) lintwarn(ext_id, "ord: called with too many arguments"); - if (get_curfunc_param(0, AWK_STRING, & str) != NULL) { + if (get_argument(0, AWK_STRING, & str)) { ret = str.str_value.str[0]; } else if (do_lint) lintwarn(ext_id, "ord: called with no arguments"); @@ -80,7 +80,7 @@ do_chr(int nargs, awk_value_t *result) if (do_lint && nargs > 1) lintwarn(ext_id, "chr: called with too many arguments"); - if (get_curfunc_param(0, AWK_NUMBER, &num) != NULL) { + if (get_argument(0, AWK_NUMBER, & num)) { val = num.num_value; ret = val; /* convert to int */ ret &= 0xff; diff --git a/extension/readfile.c b/extension/readfile.c index ca513912..166bb8fb 100644 --- a/extension/readfile.c +++ b/extension/readfile.c @@ -66,7 +66,7 @@ do_readfile(int nargs, awk_value_t *result) if (do_lint && nargs > 1) lintwarn(ext_id, "readfile: called with too many arguments"); - if (get_curfunc_param(0, AWK_STRING, &filename) != NULL) { + if (get_argument(0, AWK_STRING, &filename)) { ret = stat(filename.str_value.str, & sbuf); if (ret < 0) { update_ERRNO_int(errno); diff --git a/extension/time.c b/extension/time.c index 4f590c88..09e71d0e 100644 --- a/extension/time.c +++ b/extension/time.c @@ -116,8 +116,7 @@ do_sleep(int nargs, awk_value_t *result) if (do_lint && nargs > 1) lintwarn(ext_id, "sleep: called with too many arguments"); - - if (get_curfunc_param(0, AWK_NUMBER, &num) == NULL) { + if (get_argument(0, AWK_NUMBER, &num) == NULL) { update_ERRNO_string("sleep: missing required numeric argument", 1); return make_number(-1, result); } @@ -151,7 +150,7 @@ do_sleep(int nargs, awk_value_t *result) #else /* no way to sleep on this platform */ rc = -1; - set_ERRNO("sleep: not supported on this platform"); + update_ERRNO_str("sleep: not supported on this platform", 0); #endif return make_number(rc, result); @@ -25,24 +25,32 @@ #include "awk.h" -static awk_value_t *node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted); +static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted); /* * Get the count'th paramater, zero-based. - * Returns NULL if count is out of range, or if actual paramater - * does not match what is specified in wanted. + * Returns false if count is out of range, or if actual paramater + * does not match what is specified in wanted. In the latter + * case, fills in result->val_type with the actual type. */ -static awk_value_t * -api_get_curfunc_param(awk_ext_id_t id, size_t count, +static awk_bool_t +api_get_argument(awk_ext_id_t id, size_t count, awk_valtype_t wanted, awk_value_t *result) { NODE *arg; + if (result == NULL) + return false; + arg = (wanted == AWK_ARRAY ? get_array_argument(count, false) : get_scalar_argument(count, false) ); - if (arg == NULL) - return NULL; + + if (arg == NULL) { + memset(result, 0, sizeof(*result)); + result->val_type = AWK_UNDEFINED; + return false; + } return node_to_awk_value(arg, result, wanted); } @@ -142,7 +150,8 @@ api_unset_ERRNO(awk_ext_id_t id) } -/* Add a function to the interpreter, returns true upon success */ +/* api_add_ext_func --- add a function to the interpreter, returns true upon success */ + static awk_bool_t api_add_ext_func(awk_ext_id_t id, const awk_ext_func_t *func, @@ -177,7 +186,7 @@ run_ext_exit_handlers(int exitval) /* api_awk_atexit --- add an exit call back, returns true upon success */ -static awk_bool_t +static void api_awk_atexit(awk_ext_id_t id, void (*funcp)(void *data, int exit_status), void *arg0) @@ -194,73 +203,87 @@ api_awk_atexit(awk_ext_id_t id, /* add to linked list, LIFO order */ p->next = list_head; list_head = p; - return true; /* for now */ } /* node_to_awk_value --- convert a node into a value for an extension */ -static awk_value_t * +static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) { - /* clear out the result */ - memset(val, 0, sizeof(*val)); + awk_bool_t ret = false; - switch (wanted) { - case AWK_NUMBER: - case AWK_STRING: - /* handle it below */ - break; - - case AWK_UNDEFINED: - /* ignore the actual value. weird but could happen */ + switch (node->type) { + case Node_var_new: /* undefined variable */ val->val_type = AWK_UNDEFINED; - return val; - - case AWK_ARRAY: - if (node->type == Node_var_array) { - val->val_type = AWK_ARRAY; - val->array_cookie = node; - - return val; + if (wanted == AWK_UNDEFINED) { + ret = true; } - return NULL; - - default: - fatal(_("node_to_awk_value: invalid value for `wanted' (%d)"), wanted); break; - } - /* get here only for string or number */ - - switch (node->type) { case Node_var: node = node->var_value; /* FALL THROUGH */ case Node_val: - /* make sure both values are valid */ - (void) force_number(node); - (void) force_string(node); - - if (wanted == AWK_NUMBER) { + /* a scalar value */ + switch (wanted) { + case AWK_NUMBER: val->val_type = AWK_NUMBER; - val->num_value = get_number_d(node); - val->str_value.str = node->stptr; - val->str_value.len = node->stlen; - } else if (wanted == AWK_STRING) { + + (void) force_number(node); + if (node->flags & NUMCUR) { + val->num_value = get_number_d(node); + ret = true; + } + break; + + case AWK_STRING: val->val_type = AWK_STRING; - val->str_value.str = node->stptr; - val->str_value.len = node->stlen; - val->num_value = get_number_d(node); + + (void) force_string(node); + if (node->flags & STRCUR) { + val->str_value.str = node->stptr; + val->str_value.len = node->stlen; + ret = true; + } + break; + + case AWK_UNDEFINED: + /* return true and actual type for request of undefined */ + if (node->flags & NUMBER) { + val->val_type = AWK_NUMBER; + val->num_value = get_number_d(node); + ret = true; + } else if (node->flags & STRING) { + val->val_type = AWK_STRING; + val->str_value.str = node->stptr; + val->str_value.len = node->stlen; + ret = true; + } else + val->val_type = AWK_UNDEFINED; + break; + + case AWK_ARRAY: + break; } - return val; + break; - case Node_var_new: case Node_var_array: + val->val_type = AWK_ARRAY; + if (wanted == AWK_ARRAY || wanted == AWK_UNDEFINED) { + val->array_cookie = node; + ret = true; + } else { + ret = false; + } + break; + default: + val->val_type = AWK_UNDEFINED; + ret = false; break; } - return NULL; + return ret; } /* @@ -271,22 +294,26 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) * to scalar or array. */ /* - * Lookup a variable, return its value. No messing with the value - * returned. Return value is NULL if the variable doesn't exist. - * Built-in variables (except PROCINFO) may not be changed by an extension. + * Lookup a variable, fills in value. No messing with the value + * returned. Returns false if the variable doesn't exist + * or the wrong type was requested. + * In the latter case, fills in vaule->val_type with the real type. + * Built-in variables (except PROCINFO) may not be accessed by an extension. */ -static awk_value_t * +static awk_bool_t api_sym_lookup(awk_ext_id_t id, - const char *name, awk_value_t *result, - awk_valtype_t wanted) + const char *name, + awk_valtype_t wanted, + awk_value_t *result) { NODE *node; if ( name == NULL || *name == '\0' + || result == NULL || is_off_limits_var(name) /* most built-in vars not allowed */ || (node = lookup(name)) == NULL) - return NULL; + return false; return node_to_awk_value(node, result, wanted); } @@ -334,12 +361,12 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) * Return the value of an element - read only! * Use set_array_element to change it. */ -static awk_value_t * +static awk_bool_t api_get_array_element(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t *const index, - awk_value_t *result, awk_valtype_t wanted) + awk_valtype_t wanted, awk_value_t *result) { - return NULL; /* for now */ + return true; /* for now */ } /* @@ -438,7 +465,7 @@ gawk_api_t api_impl = { GAWK_API_MINOR_VERSION, { 0 }, /* do_flags */ - api_get_curfunc_param, + api_get_argument, api_fatal, api_warning, @@ -116,15 +116,18 @@ typedef void *awk_array_t; /* * An awk value. The val_type tag indicates what - * is contained. For scalars, gawk fills in both kinds - * of values and val_type indicates the assigned type. - * For arrays, the scalar types will be set to zero. + * is in the union. */ typedef struct { awk_valtype_t val_type; - awk_string_t str_value; - double num_value; - awk_array_t array_cookie; + union { + awk_string_t s; + double d; + awk_array_t a; + } u; +#define str_value u.s +#define num_value u.d +#define array_cookie u.a } awk_value_t; /* @@ -195,10 +198,27 @@ typedef struct gawk_api { /* * Get the count'th paramater, zero-based. - * Returns NULL if count is out of range, or if actual paramater - * does not match what is specified in wanted. + * Returns false if count is out of range, or if actual paramater + * does not match what is specified in wanted. In that case, + * result->val_type will hold the actual type of what was passed. + + Table entry is type returned: + + +-----------------------------------------+ + | Type Requested: | + +----------+----------+-------+-----------+ + | String | Number | Array | Undefined | + +---------+-----------+----------+----------+-------+-----------+ + | Type | String | String | false | false | String | + | of +-----------+----------+----------+-------+-----------+ + | Actual | Number | false | Number | false | Number | + | Value: +-----------+----------+----------+-------+-----------+ + | | Array | false | false | Array | Array | + | +-----------+----------+----------+-------+-----------+ + | | Undefined | false | false | false | Undefined | + +---------+-----------+----------+----------+-------+-----------+ */ - awk_value_t *(*get_curfunc_param)(awk_ext_id_t id, size_t count, + awk_bool_t (*get_argument)(awk_ext_id_t id, size_t count, awk_valtype_t wanted, awk_value_t *result); @@ -221,7 +241,7 @@ typedef struct gawk_api { const char *namespace); /* Add an exit call back, returns true upon success */ - awk_bool_t (*awk_atexit)(awk_ext_id_t id, + void (*awk_atexit)(awk_ext_id_t id, void (*funcp)(void *data, int exit_status), void *arg0); @@ -233,20 +253,23 @@ typedef struct gawk_api { * to scalar or array. */ /* - * Lookup a variable, return its value. No messing with the value - * returned. Return value is NULL if the variable doesn't exist. - * - * Returns a pointer to a static variable. Correct usage is thus: + * Lookup a variable, fills in value. No messing with the value + * returned. Returns false if the variable doesn't exist + * or the wrong type was requested. + * In the latter case, fills in vaule->val_type with the real type. + * Built-in variables (except PROCINFO) may not be accessed by an extension. * * awk_value_t val; - * if (api->sym_lookup(id, name, &val, wanted) == NULL) + * if (! api->sym_lookup(id, name, wanted, & val)) * error_code(); * else { * // safe to use val * } */ - awk_value_t *(*sym_lookup)(awk_ext_id_t id, const char *name, awk_value_t *result, - awk_valtype_t wanted); + awk_bool_t (*sym_lookup)(awk_ext_id_t id, + const char *name, + awk_valtype_t wanted, + awk_value_t *result); /* * Update a value. Adds it to the symbol table if not there. @@ -260,10 +283,13 @@ typedef struct gawk_api { /* * Return the value of an element - read only! * Use set_array_element() to change it. + * Behavior for value and return is same as for get_argument + * and sym_lookup. */ - awk_value_t *(*get_array_element)(awk_ext_id_t id, + awk_bool_t (*get_array_element)(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t *const index, - awk_value_t *result, awk_valtype_t wanted); + awk_valtype_t wanted, + awk_value_t *result); /* * Change (or create) element in existing array with @@ -321,8 +347,8 @@ typedef struct gawk_api { #define do_debug (api->do_flags[gawk_do_debug]) #define do_mpfr (api->do_flags[gawk_do_mpfr]) -#define get_curfunc_param(count, wanted, result) \ - (api->get_curfunc_param(ext_id, count, wanted, result)) +#define get_argument(count, wanted, result) \ + (api->get_argument(ext_id, count, wanted, result)) #define fatal api->api_fatal #define warning api->api_warning diff --git a/test/ChangeLog b/test/ChangeLog index 72a7c9ff..ac8737d6 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,7 @@ +2012-06-12 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (clean): Add fork.tmp.* to the list. + 2012-06-10 Andrew J. Schorr <aschorr@telemetry-investments.com> * Makefile.am (EXTRA_DIST): Add new files time.awk and time.ok. diff --git a/test/Makefile.am b/test/Makefile.am index 6c65ae3c..6b052f1d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1588,7 +1588,7 @@ $(srcdir)/Maketests: $(srcdir)/Makefile.am $(srcdir)/Gentests $(AWK) -f $(srcdir)/Gentests "$(srcdir)/Makefile.am" $$files > $(srcdir)/Maketests clean: - rm -fr _* core core.* fmtspcl.ok junk out1 out2 out3 strftime.ok test1 test2 seq *~ readfile.ok + rm -fr _* core core.* fmtspcl.ok junk out1 out2 out3 strftime.ok test1 test2 seq *~ readfile.ok fork.tmp.* # An attempt to print something that can be grepped for in build logs pass-fail: diff --git a/test/Makefile.in b/test/Makefile.in index 2ec90244..05f9db13 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -3195,7 +3195,7 @@ $(srcdir)/Maketests: $(srcdir)/Makefile.am $(srcdir)/Gentests $(AWK) -f $(srcdir)/Gentests "$(srcdir)/Makefile.am" $$files > $(srcdir)/Maketests clean: - rm -fr _* core core.* fmtspcl.ok junk out1 out2 out3 strftime.ok test1 test2 seq *~ readfile.ok + rm -fr _* core core.* fmtspcl.ok junk out1 out2 out3 strftime.ok test1 test2 seq *~ readfile.ok fork.tmp.* # An attempt to print something that can be grepped for in build logs pass-fail: |