aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--gawkapi.c112
-rw-r--r--gawkapi.h4
-rw-r--r--main.c2
4 files changed, 93 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index b73e398f..46a9e337 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2012-05-30 Arnold D. Robbins <arnold@skeeve.com>
+
+ * main.c (is_off_limits_var): Minor coding style edit.
+ * gawkapi.c (awk_value_to_node): More cleanup.
+ (node_to_awk_value): Use `wanted' for decision making.
+ (api_sym_update): Start implementation. Needs more work.
+ General: More cleanup, comments.
+ * gawkapi.h (api_sym_update): Add additional comments.
+
2012-05-29 Arnold D. Robbins <arnold@skeeve.com>
* gawkapi.c (node_to_awk_value): Add third parameter indicating type
diff --git a/gawkapi.c b/gawkapi.c
index 03db6b80..3b915fc2 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -59,8 +59,7 @@ awk_value_to_node(const awk_value_t *retval)
ext_ret_val = NULL;
if (retval->val_type == AWK_ARRAY) {
- getnode(ext_ret_val);
- *ext_ret_val = *((NODE *) retval->array_cookie);
+ ext_ret_val = (NODE *) retval->array_cookie;
} else if (retval->val_type == AWK_UNDEFINED) {
ext_ret_val = dupnode(Nnull_string);
} else if (retval->val_type == AWK_NUMBER) {
@@ -68,6 +67,7 @@ awk_value_to_node(const awk_value_t *retval)
} else {
ext_ret_val = make_string(retval->str_value.str, retval->str_value.len);
}
+
return ext_ret_val;
}
@@ -175,7 +175,8 @@ run_ext_exit_handlers(int exitval)
list_head = NULL;
}
-/* Add an exit call back, returns true upon success */
+/* api_awk_atexit --- add an exit call back, returns true upon success */
+
static awk_bool_t
api_awk_atexit(awk_ext_id_t id,
void (*funcp)(void *data, int exit_status),
@@ -196,61 +197,80 @@ api_awk_atexit(awk_ext_id_t id,
return true; /* for now */
}
-/*
- * Symbol table access:
- * - No access to special variables (NF, etc.)
- * - One special exception: PROCINFO.
- * - Use sym_update() to change a value, including from UNDEFINED
- * to scalar or array.
- */
+/* node_to_awk_value --- convert a node into a value for an extension */
+
static awk_value_t *
node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted)
{
+ /* clear out the result */
memset(val, 0, sizeof(*val));
- if (node->type != Node_var_array) {
- /* make sure both values are valid */
- (void) force_number(node);
- (void) force_string(node);
+ switch (wanted) {
+ case AWK_NUMBER:
+ case AWK_STRING:
+ /* handle it below */
+ break;
+
+ case AWK_UNDEFINED:
+ /* ignore the actual value. weird but could happen */
+ 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;
+ }
+ 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:
- if (node->flags & NUMBER) {
+ /* make sure both values are valid */
+ (void) force_number(node);
+ (void) force_string(node);
+
+ if (wanted == 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 (node->flags & STRING) {
+ } else if (wanted == 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);
- } else {
- return NULL;
}
- break;
+ return val;
case Node_var_new:
- val->val_type = AWK_UNDEFINED;
- break;
-
case Node_var_array:
- val->val_type = AWK_ARRAY;
- val->array_cookie = node;
- break;
-
default:
- return NULL;
+ break;
}
- return val;
+ return NULL;
}
/*
+ * Symbol table access:
+ * - No access to special variables (NF, etc.)
+ * - One special exception: PROCINFO.
+ * - Use sym_update() to change a value, including from UNDEFINED
+ * 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.
@@ -271,13 +291,41 @@ api_sym_lookup(awk_ext_id_t id,
return node_to_awk_value(node, result, wanted);
}
-/*
- * Update a value. Adds it to the symbol table if not there.
- * Changing types is not allowed.
- */
+/* api_sym_update --- update a value, see gawkapi.h for semantics */
+
static awk_bool_t
api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value)
{
+ NODE *node;
+
+ if ( name == NULL
+ || *name == '\0'
+ || value == NULL
+ || is_off_limits_var(name)) /* most built-in vars not allowed */
+ return false;
+
+ node = lookup(name);
+
+ if (node == NULL) {
+ /* new value to be installed */
+ } else {
+ /* existing value to be updated */
+ }
+
+ switch (value->val_type) {
+ case AWK_NUMBER:
+ case AWK_STRING:
+ case AWK_UNDEFINED:
+ break;
+
+ case AWK_ARRAY:
+ return false;
+
+ default:
+ fatal(_("api_sym_update: invalid value for type of new value (%d)"), value->val_type);
+ return false;
+ }
+
return true; /* for now */
}
diff --git a/gawkapi.h b/gawkapi.h
index 5fd2ebe1..87d2d2f0 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -245,7 +245,9 @@ typedef struct gawk_api {
/*
* Update a value. Adds it to the symbol table if not there.
- * Changing types is not allowed.
+ * Changing types (scalar <--> array) is not allowed.
+ * In fact, using this to update an array is not allowed, either.
+ * Such an attempt returns false.
*/
awk_bool_t (*sym_update)(awk_ext_id_t id, const char *name, awk_value_t *value);
diff --git a/main.c b/main.c
index e2f70d77..91da77d7 100644
--- a/main.c
+++ b/main.c
@@ -1203,7 +1203,7 @@ is_off_limits_var(const char *var)
for (vp = varinit; vp->name != NULL; vp++) {
if (strcmp(vp->name, var) == 0)
- return !(vp->flags & NOT_OFF_LIMITS);
+ return ((vp->flags & NOT_OFF_LIMITS) == 0);
}
return false;