aboutsummaryrefslogtreecommitdiffstats
path: root/gawkapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'gawkapi.c')
-rw-r--r--gawkapi.c113
1 files changed, 82 insertions, 31 deletions
diff --git a/gawkapi.c b/gawkapi.c
index 3f9159d9..f57f4f58 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -75,7 +75,8 @@ awk_value_to_node(const awk_value_t *retval)
} else if (retval->val_type == AWK_NUMBER) {
ext_ret_val = make_number(retval->num_value);
} else {
- ext_ret_val = make_string(retval->str_value.str, retval->str_value.len);
+ ext_ret_val = make_string(retval->str_value.str,
+ retval->str_value.len);
}
return ext_ret_val;
@@ -366,36 +367,46 @@ static awk_bool_t
api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value)
{
NODE *node;
+ NODE *array_node;
+
+ if ( name == NULL
+ || *name == '\0'
+ || is_off_limits_var(name) /* most built-in vars not allowed */
+ || value == NULL)
+ return false;
switch (value->val_type) {
case AWK_NUMBER:
case AWK_STRING:
case AWK_UNDEFINED:
- break;
-
case AWK_ARRAY:
- return false;
+ break;
default:
/* fatal(_("api_sym_update: invalid value for type of new value (%d)"), value->val_type); */
return false;
}
- if ( name == NULL
- || *name == '\0'
- || is_off_limits_var(name) /* most built-in vars not allowed */
- || value == NULL)
- return false;
-
node = lookup(name);
if (node == NULL) {
/* new value to be installed */
- node = install_symbol((char *) name, Node_var);
+ if (value->val_type == AWK_ARRAY) {
+ array_node = awk_value_to_node(value);
+ node = install_symbol(estrdup((char *) name, strlen(name)),
+ Node_var_array);
+ array_node->vname = node->vname;
+ *node = *array_node;
+ freenode(array_node);
+ } else {
+ /* regular variable */
+ node = install_symbol(estrdup((char *) name, strlen(name)),
+ Node_var);
+ unref(node->var_value);
+ node->var_value = awk_value_to_node(value);
+ }
}
- unref(node->var_value);
-
- node->var_value = awk_value_to_node(value);
+ /* FIXME: Handle case where it exists already */
return true;
}
@@ -407,25 +418,30 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value)
*/
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_valtype_t wanted, awk_value_t *result)
+ awk_array_t a_cookie,
+ const awk_value_t *const index,
+ awk_value_t *result)
{
- NODE *array;
+ NODE *array = (NODE *) a_cookie;
NODE *subscript;
+ NODE **aptr;
/* don't check for index len zero, null str is ok as index */
- if ( a_cookie == NULL
+ if ( array == NULL
+ || array->type != Node_var_array
|| result == NULL
|| index == NULL
|| index->val_type != AWK_STRING
|| index->str_value.str == NULL)
return false;
- array = (NODE *) a_cookie;
subscript = awk_value_to_node(index);
- /* FIXME: write rest of code */
+ aptr = assoc_lookup(array, subscript);
+ unref(subscript);
+ if (aptr == NULL)
+ return false;
- return true; /* for now */
+ return node_to_awk_value(*aptr, result, AWK_UNDEFINED);
}
/*
@@ -441,7 +457,8 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
NODE **aptr;
/* don't check for index len zero, null str is ok as index */
- if ( a_cookie == NULL
+ if ( array == NULL
+ || array->type != Node_var_array
|| element == NULL
|| element->index.str == NULL)
return false;
@@ -451,6 +468,7 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
unref(tmp);
unref(*aptr);
*aptr = awk_value_to_node(& element->value);
+
return true;
}
@@ -462,7 +480,33 @@ static awk_bool_t
api_del_array_element(awk_ext_id_t id,
awk_array_t a_cookie, const awk_value_t* const index)
{
- return true; /* for now */
+ NODE *array, *sub, *val;
+
+ array = (NODE *) a_cookie;
+ if ( array == NULL
+ || array->type != Node_var_array
+ || index == NULL
+ || index->val_type != AWK_STRING)
+ return false;
+
+ sub = awk_value_to_node(index);
+ val = in_array(array, sub);
+
+ if (val == NULL)
+ return false;
+
+ if (val->type == Node_var_array) {
+ assoc_clear(val);
+ /* cleared a sub-array, free Node_var_array */
+ efree(val->vname);
+ freenode(val);
+ } else
+ unref(val);
+
+ (void) assoc_remove(array, sub);
+ unref(sub);
+
+ return true;
}
/*
@@ -486,7 +530,13 @@ api_get_element_count(awk_ext_id_t id,
static awk_array_t
api_create_array(awk_ext_id_t id)
{
- return NULL; /* for now */
+ NODE *n;
+
+ getnode(n);
+ memset(n, 0, sizeof(NODE));
+ init_array(n);
+
+ return (awk_array_t) n;
}
/* Clear out an array */
@@ -564,12 +614,13 @@ gawk_api_t api_impl = {
void
init_ext_api()
{
- api_impl.do_flags[0] = do_lint;
- api_impl.do_flags[1] = do_traditional;
- api_impl.do_flags[2] = do_profile;
- api_impl.do_flags[3] = do_sandbox;
- api_impl.do_flags[4] = do_debug;
- api_impl.do_flags[5] = do_mpfr;
+ /* force values to 1 / 0 */
+ api_impl.do_flags[0] = (do_lint ? 1 : 0);
+ api_impl.do_flags[1] = (do_traditional ? 1 : 0);
+ api_impl.do_flags[2] = (do_profile ? 1 : 0);
+ api_impl.do_flags[3] = (do_sandbox ? 1 : 0);
+ api_impl.do_flags[4] = (do_debug ? 1 : 0);
+ api_impl.do_flags[5] = (do_mpfr ? 1 : 0);
}
/* update_ext_api --- update the variables in the API that can change */
@@ -577,5 +628,5 @@ init_ext_api()
void
update_ext_api()
{
- api_impl.do_flags[0] = do_lint;
+ api_impl.do_flags[0] = (do_lint ? 1 : 0);
}