aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2012-06-12 22:10:31 +0300
committerArnold D. Robbins <arnold@skeeve.com>2012-06-12 22:10:31 +0300
commit820b6a2ccb7859e15ade36af6ac1d0d08c1da4b1 (patch)
treee820c47953f997e8d267854fd921417d61d8ec3a
parentb4a2d75b7d9fd23069a55dc91a42f7fddd0c7570 (diff)
downloadegawk-820b6a2ccb7859e15ade36af6ac1d0d08c1da4b1.tar.gz
egawk-820b6a2ccb7859e15ade36af6ac1d0d08c1da4b1.tar.bz2
egawk-820b6a2ccb7859e15ade36af6ac1d0d08c1da4b1.zip
Further cleanups and improvements in API.
-rw-r--r--ChangeLog15
-rw-r--r--extension/ChangeLog12
-rw-r--r--extension/filefuncs.c14
-rw-r--r--extension/fork.c4
-rw-r--r--extension/ordchr.c4
-rw-r--r--extension/readfile.c2
-rw-r--r--extension/time.c5
-rw-r--r--gawkapi.c153
-rw-r--r--gawkapi.h68
-rw-r--r--test/ChangeLog4
-rw-r--r--test/Makefile.am2
-rw-r--r--test/Makefile.in2
12 files changed, 184 insertions, 101 deletions
diff --git a/ChangeLog b/ChangeLog
index fb7b6ae2..d6bad9ea 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);
diff --git a/gawkapi.c b/gawkapi.c
index 95bcbf15..885d514f 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -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,
diff --git a/gawkapi.h b/gawkapi.h
index 09a1ce79..7e6a66fc 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -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: