aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2012-07-11 21:26:37 +0300
committerArnold D. Robbins <arnold@skeeve.com>2012-07-11 21:26:37 +0300
commit6d1724214a95330b63a6a557f89fb9b40b4a521f (patch)
tree829b2da90fcfdd4193beaa187c3325a861706a3b
parente33b672ff4ab1b7469355a79eaf4c4740f412e45 (diff)
downloadegawk-6d1724214a95330b63a6a557f89fb9b40b4a521f.tar.gz
egawk-6d1724214a95330b63a6a557f89fb9b40b4a521f.tar.bz2
egawk-6d1724214a95330b63a6a557f89fb9b40b4a521f.zip
API clean up and require strings to be malloced.
-rw-r--r--ChangeLog27
-rw-r--r--extension/ChangeLog11
-rw-r--r--extension/filefuncs.c10
-rw-r--r--extension/fork.c2
-rw-r--r--extension/ordchr.c2
-rw-r--r--extension/readfile.c4
-rw-r--r--extension/rwarray.c4
-rw-r--r--extension/testext.c28
-rw-r--r--gawkapi.c128
-rw-r--r--gawkapi.h179
10 files changed, 284 insertions, 111 deletions
diff --git a/ChangeLog b/ChangeLog
index 759daaa8..2429bd8b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2012-07-11 Arnold D. Robbins <arnold@skeeve.com>
+
+ Lots of API work.
+
+ * gawkapi.h: Function pointer members renamed api_XXXX and
+ macros adjusted. More documentation.
+ (awk_valtype_t): New AWK_SCALAR enum for scalar cookies.
+ (awk_scalar_t): New type.
+ (awk_value_t): New member scalar_cookie.
+ (api_sym_update_scalar): New API function.
+ (erealloc): New macro.
+ (make_const_string): New macro, renamed from dup_string.
+ (make_malloced_string): New macro, renamed from make_string.
+ (make_null_string): New inline function.
+
+ * gawkapi.c (awk_value_to_node): Assume that string values came
+ from malloc.
+ (node_to_awk_value): Handle AWK_SCALAR.
+ (api_sym_update): Ditto.
+ (api_sym_update_scalar): New routine.
+ (api_get_array_element): Return false if the element doesn't exist.
+ Always unref the subscript.
+ (remove_element): New helper routine.
+ (api_del_array_element): Use it.
+ (api_release_flattened_array): Ditto.
+ (api_impl): Add the new routine.
+
2012-07-11 Andrew J. Schorr <aschorr@telemetry-investments.com>
* gawkapi.c (api_sym_update): Allow val_type to be AWK_UNDEFINED
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 7e61fc54..be315619 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,14 @@
+2012-07-11 Arnold D. Robbins <arnold@skeeve.com>
+
+ * filefuncs.c (array_set, do_stat): Use make_const_string.
+ * fork.c (array_set_numeric): Ditto.
+ * ordchr.c (do_chr): Ditto.
+ * readfile.c (do_readfile): Use make_null_string, make_malloced_string.
+ * rwarray.c (read_elem): Ditto.
+ * testext.c (valrep2str): Add case for AWK_SCALAR.
+ (test_array_elem): Duplicate strings coming from gawk before passing
+ them back in.
+
2012-07-09 Arnold D. Robbins <arnold@skeeve.com>
* filefuncs.c (do_readfile): Return "" and set ERRNO on error
diff --git a/extension/filefuncs.c b/extension/filefuncs.c
index 32a3cee6..74af8b1b 100644
--- a/extension/filefuncs.c
+++ b/extension/filefuncs.c
@@ -214,7 +214,7 @@ array_set(awk_array_t array, const char *sub, awk_value_t *value)
awk_value_t index;
set_array_element(array,
- make_string(sub, strlen(sub), & index),
+ make_const_string(sub, strlen(sub), & index),
value);
}
@@ -292,7 +292,7 @@ do_stat(int nargs, awk_value_t *result)
}
/* fill in the array */
- array_set(array, "name", make_string(name, file_param.str_value.len, &tmp));
+ array_set(array, "name", make_const_string(name, file_param.str_value.len, &tmp));
array_set_numeric(array, "dev", sbuf.st_dev);
array_set_numeric(array, "ino", sbuf.st_ino);
array_set_numeric(array, "mode", sbuf.st_mode);
@@ -317,7 +317,7 @@ do_stat(int nargs, awk_value_t *result)
#endif /* HAVE_ST_BLKSIZE */
pmode = format_mode(sbuf.st_mode);
- array_set(array, "pmode", make_string(pmode, strlen(pmode), & tmp));
+ array_set(array, "pmode", make_const_string(pmode, strlen(pmode), & tmp));
/* for symbolic links, add a linkval field */
if (S_ISLNK(sbuf.st_mode)) {
@@ -326,7 +326,7 @@ do_stat(int nargs, awk_value_t *result)
if ((buf = read_symlink(name, sbuf.st_size,
& linksize)) != NULL)
- array_set(array, "linkval", make_string(buf, linksize, & tmp));
+ array_set(array, "linkval", make_malloced_string(buf, linksize, & tmp));
else
warning(ext_id, "stat: unable to read symbolic link `%s'", name);
}
@@ -340,7 +340,7 @@ do_stat(int nargs, awk_value_t *result)
}
}
- array_set(array, "type", make_string(type, strlen(type), &tmp));
+ array_set(array, "type", make_const_string(type, strlen(type), &tmp));
ret = 1; /* success */
diff --git a/extension/fork.c b/extension/fork.c
index efad17eb..84232663 100644
--- a/extension/fork.c
+++ b/extension/fork.c
@@ -53,7 +53,7 @@ array_set_numeric(awk_array_t array, const char *sub, double num)
awk_value_t index, value;
set_array_element(array,
- make_string(sub, strlen(sub), & index),
+ make_const_string(sub, strlen(sub), & index),
make_number(num, & value));
}
diff --git a/extension/ordchr.c b/extension/ordchr.c
index 8d7eac8f..3ab0f872 100644
--- a/extension/ordchr.c
+++ b/extension/ordchr.c
@@ -103,7 +103,7 @@ do_chr(int nargs, awk_value_t *result)
}
/* Set the return value */
- return dup_string(str, 1, result);
+ return make_const_string(str, 1, result);
}
static awk_ext_func_t func_table[] = {
diff --git a/extension/readfile.c b/extension/readfile.c
index 56bdcbc3..1b6772fe 100644
--- a/extension/readfile.c
+++ b/extension/readfile.c
@@ -65,7 +65,7 @@ do_readfile(int nargs, awk_value_t *result)
int fd;
assert(result != NULL);
- make_string("", 0, result); /* default return value */
+ make_null_string(result); /* default return value */
if (do_lint && nargs > 1)
lintwarn(ext_id, "readfile: called with too many arguments");
@@ -98,7 +98,7 @@ do_readfile(int nargs, awk_value_t *result)
}
close(fd);
- make_string(text, sbuf.st_size, result);
+ make_malloced_string(text, sbuf.st_size, result);
goto done;
} else if (do_lint)
lintwarn(ext_id, "readfile: called with no arguments");
diff --git a/extension/rwarray.c b/extension/rwarray.c
index a63fa3d2..64c501dd 100644
--- a/extension/rwarray.c
+++ b/extension/rwarray.c
@@ -394,9 +394,9 @@ read_elem(int fd, awk_element_t *element)
if (read(fd, buffer, index_len) != (ssize_t) index_len) {
return 0;
}
- make_string(buffer, index_len, & element->index);
+ make_const_string(buffer, index_len, & element->index);
} else {
- make_string("", 0, & element->index);
+ make_null_string(& element->index);
}
if (! read_value(fd, & element->value))
diff --git a/extension/testext.c b/extension/testext.c
index e54055cc..8dac1c2b 100644
--- a/extension/testext.c
+++ b/extension/testext.c
@@ -59,6 +59,9 @@ valrep2str(const awk_value_t *value)
case AWK_ARRAY:
strcpy(buf, "<array>");
break;
+ case AWK_SCALAR:
+ strcpy(buf, "<scalar>");
+ break;
case AWK_STRING:
if (value->str_value.len < size)
size = value->str_value.len;
@@ -334,7 +337,7 @@ BEGIN {
static awk_value_t *
test_array_elem(int nargs, awk_value_t *result)
{
- awk_value_t array, index, value;
+ awk_value_t array, index, index2, value;
make_number(0.0, result); /* default return until full success */
@@ -354,7 +357,8 @@ test_array_elem(int nargs, awk_value_t *result)
printf("test_array_elem: get_argument 1 (index) failed\n");
goto out;
}
- if (! get_array_element(array.array_cookie, & index, AWK_UNDEFINED, & value)) {
+ (void) make_const_string(index.str_value.str, index.str_value.len, & index2);
+ if (! get_array_element(array.array_cookie, & index2, AWK_UNDEFINED, & value)) {
printf("test_array_elem: get_array_element failed\n");
goto out;
}
@@ -365,28 +369,29 @@ test_array_elem(int nargs, awk_value_t *result)
/* change the element - "3" */
(void) make_number(42.0, & value);
- if (! set_array_element(array.array_cookie, & index, & value)) {
+ (void) make_const_string(index.str_value.str, index.str_value.len, & index2);
+ if (! set_array_element(array.array_cookie, & index2, & value)) {
printf("test_array_elem: set_array_element failed\n");
goto out;
}
/* delete another element - "5" */
- (void) make_string("5", 1, & index);
+ (void) make_const_string("5", 1, & index);
if (! del_array_element(array.array_cookie, & index)) {
printf("test_array_elem: del_array_element failed\n");
goto out;
}
/* add a new element - "7" */
- (void) make_string("7", 1, & index);
- (void) make_string("seven", 5, & value);
+ (void) make_const_string("7", 1, & index);
+ (void) make_const_string("seven", 5, & value);
if (! set_array_element(array.array_cookie, & index, & value)) {
printf("test_array_elem: set_array_element failed\n");
goto out;
}
/* add a subarray */
- (void) make_string("subarray", 8, & index);
+ (void) make_const_string("subarray", 8, & index);
fill_in_array(& value);
if (! set_array_element(array.array_cookie, & index, & value)) {
printf("test_array_elem: set_array_element (subarray) failed\n");
@@ -488,14 +493,14 @@ fill_in_array(awk_value_t *new_array)
a_cookie = create_array();
- (void) make_string("hello", 5, & index);
- (void) make_string("world", 5, & value);
+ (void) make_const_string("hello", 5, & index);
+ (void) make_const_string("world", 5, & value);
if (! set_array_element(a_cookie, & index, & value)) {
printf("fill_in_array:%d: set_array_element failed\n", __LINE__);
return;
}
- (void) make_string("answer", 6, & index);
+ (void) make_const_string("answer", 6, & index);
(void) make_number(42.0, & value);
if (! set_array_element(a_cookie, & index, & value)) {
printf("fill_in_array:%d: set_array_element failed\n", __LINE__);
@@ -620,7 +625,8 @@ BEGIN {
if (! sym_update("answer_num", make_number(42, & value)))
printf("testext: sym_update(\"answer_num\") failed!\n");
- if (! sym_update("message_string", dup_string(message, strlen(message), & value)))
+ if (! sym_update("message_string",
+ make_const_string(message, strlen(message), & value)))
printf("testext: sym_update(\"answer_num\") failed!\n");
create_new_array();
diff --git a/gawkapi.c b/gawkapi.c
index 3fa3e3ba..c5f8953d 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -140,8 +140,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_str_node(retval->str_value.str,
+ retval->str_value.len, ALREADY_MALLOCED);
}
return ext_ret_val;
@@ -317,6 +317,14 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted)
break;
case Node_var:
+ /* a scalar value */
+ if (wanted == AWK_SCALAR) {
+ val->val_type = AWK_SCALAR;
+ val->scalar_cookie = (void *) node;
+ ret = true;
+ break;
+ }
+
node = node->var_value;
/* FALL THROUGH */
case Node_val:
@@ -343,6 +351,16 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted)
}
break;
+ case AWK_SCALAR:
+ if (node->flags & NUMBER) {
+ val->val_type = AWK_NUMBER;
+ } else if (node->flags & STRING) {
+ val->val_type = AWK_STRING;
+ } else
+ val->val_type = AWK_UNDEFINED;
+ ret = false;
+ break;
+
case AWK_UNDEFINED:
/* return true and actual type for request of undefined */
if (node->flags & NUMBER) {
@@ -466,6 +484,9 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value)
/* if we get here, then it exists already */
switch (value->val_type) {
+ case AWK_SCALAR:
+ return false;
+
case AWK_STRING:
case AWK_NUMBER:
case AWK_UNDEFINED:
@@ -484,6 +505,33 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value)
return true;
}
+/* api_sym_update_scalar --- update a scalar cookie */
+
+static awk_bool_t
+api_sym_update_scalar(awk_ext_id_t id,
+ awk_scalar_t cookie,
+ awk_value_t *value)
+{
+ NODE *node = (NODE *) cookie;
+ NODE *new_value;
+
+ if (value == NULL
+ || node == NULL
+ || node->type != Node_var)
+ return false;
+
+ new_value = awk_value_to_node(value);
+ if (new_value->type != Node_val) {
+ unref(new_value);
+ return false;
+ }
+
+ unref(node->var_value);
+ node->var_value = new_value;
+
+ return true;
+}
+
/* Array management */
/*
* Return the value of an element - read only!
@@ -510,10 +558,21 @@ api_get_array_element(awk_ext_id_t id,
return false;
subscript = awk_value_to_node(index);
+
+ /* if it doesn't exist, return false */
+ if (in_array(array, subscript) == NULL) {
+ unref(subscript);
+ return false;
+ }
+
aptr = assoc_lookup(array, subscript);
- unref(subscript);
- if (aptr == NULL)
+
+ if (aptr == NULL) { /* can't happen */
+ unref(subscript);
return false;
+ }
+
+ unref(subscript);
return node_to_awk_value(*aptr, result, wanted);
}
@@ -556,6 +615,32 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie,
}
/*
+ * remove_element --- remove an array element
+ * common code used by multiple functions
+ */
+
+static void
+remove_element(NODE *array, NODE *subscript)
+{
+ NODE *val;
+
+ val = in_array(array, subscript);
+
+ if (val == NULL)
+ return;
+
+ 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, subscript);
+}
+
+/*
* Remove the element with the given index.
* Returns success if removed or if element did not exist.
*/
@@ -563,7 +648,7 @@ static awk_bool_t
api_del_array_element(awk_ext_id_t id,
awk_array_t a_cookie, const awk_value_t* const index)
{
- NODE *array, *sub, *val;
+ NODE *array, *sub;
array = (NODE *) a_cookie;
if ( array == NULL
@@ -573,20 +658,7 @@ api_del_array_element(awk_ext_id_t id,
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);
+ remove_element(array, sub);
unref(sub);
return true;
@@ -698,7 +770,7 @@ api_release_flattened_array(awk_ext_id_t id,
{
NODE *array = a_cookie;
NODE **list;
- size_t i;
+ size_t i, j, k;
if ( array == NULL
|| array->type != Node_var_array
@@ -710,17 +782,12 @@ api_release_flattened_array(awk_ext_id_t id,
list = (NODE **) data->opaque2;
- /* Delete items flagged for delete. */
- for (i = 0; i < data->count; i++) {
- if ((data->elements[i].flags & AWK_ELEMENT_DELETE) != 0) {
- /* let the other guy do the work */
- (void) api_del_array_element(id, a_cookie,
- & data->elements[i].index);
- }
- }
-
/* free index nodes */
- for (i = 0; i < 2 * array->table_size; i += 2) {
+ for (i = j = 0, k = 2 * array->table_size; i < k; i += 2, j++) {
+ /* Delete items flagged for delete. */
+ if ((data->elements[j].flags & AWK_ELEMENT_DELETE) != 0) {
+ remove_element(array, list[i]);
+ }
unref(list[i]);
}
@@ -754,6 +821,7 @@ gawk_api_t api_impl = {
api_sym_lookup,
api_sym_update,
+ api_sym_update_scalar,
api_get_array_element,
api_set_array_element,
diff --git a/gawkapi.h b/gawkapi.h
index 5be5ea08..2bef258e 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -42,6 +42,26 @@
* functions. If your compiler doesn't support it, you should either
* -Dinline='' on your command line, or use the autotools and include a
* config.h in your extensions.
+ *
+ * Additional important information:
+ *
+ * 1. ALL string values in awk_value_t objects need to come from malloc().
+ * Gawk will handle releasing the storage if necessary. This is slightly
+ * awkward, in that you can't take an awk_value_t that you got from gawk
+ * and reuse it directly, even for something that is conceptually pass
+ * by value.
+ *
+ * 2. The correct way to create new arrays is to work "bottom up".
+ *
+ * new_array = create_array();
+ * // fill in new array with lots of subscripts and values
+ * val.val_type = AWK_ARRAY;
+ * val.array_cookie = new_array;
+ * sym_update("array", &val); // install array in the symbol table
+ *
+ * After doing so, do NOT make further use of the new_array variable;
+ * instead use sym_lookup to get the array_cookie if you need to do further
+ * manipulation of the array.
*/
/* Allow use in C++ code. */
@@ -73,7 +93,8 @@ typedef enum {
AWK_UNDEFINED,
AWK_NUMBER,
AWK_STRING,
- AWK_ARRAY
+ AWK_ARRAY,
+ AWK_SCALAR, /* opaque access to a variable */
} awk_valtype_t;
/*
@@ -88,6 +109,9 @@ typedef struct {
/* Arrays are represented as an opaque type. */
typedef void *awk_array_t;
+/* Scalars can be represented as an opaque type. */
+typedef void *awk_scalar_t;
+
/*
* An awk value. The val_type tag indicates what
* is in the union.
@@ -98,10 +122,12 @@ typedef struct {
awk_string_t s;
double d;
awk_array_t a;
+ awk_array_t scl;
} u;
#define str_value u.s
#define num_value u.d
#define array_cookie u.a
+#define scalar_cookie u.scl
} awk_value_t;
/*
@@ -200,23 +226,23 @@ typedef struct gawk_api {
Table entry is type returned:
- +-----------------------------------------+
- | Type Requested: |
- +----------+----------+-------+-----------+
- | String | Number | Array | Undefined |
- +---------+-----------+----------+----------+-------+-----------+
- | Type | String | String | Number if| false | String |
- | | | | it can be| | |
- | | | |converted,| | |
- | | | | else | | |
- | | | | false | | |
- | of +-----------+----------+----------+-------+-----------+
- | Actual | Number | String | Number | false | Number |
- | Value: +-----------+----------+----------+-------+-----------+
- | | Array | false | false | Array | Array |
- | +-----------+----------+----------+-------+-----------+
- | | Undefined | false | false | false | Undefined |
- +---------+-----------+----------+----------+-------+-----------+
+ +---------------------------------------------------+
+ | Type Requested: |
+ +----------+----------+-------+---------+-----------+
+ | String | Number | Array | Scalar | Undefined |
+ +---------+-----------+----------+----------+-------+---------+-----------+
+ | Type | String | String | Number if| false | Scalar | String |
+ | | | | it can be| | | |
+ | | | |converted,| | | |
+ | | | | else | | | |
+ | | | | false | | | |
+ | of +-----------+----------+----------+-------+---------+-----------+
+ | Actual | Number | String | Number | false | Scalar | Number |
+ | Value: +-----------+----------+----------+-------+---------+-----------+
+ | | Array | false | false | Array | false | Array |
+ | +-----------+----------+----------+-------+---------+-----------+
+ | | Undefined | false | false | false | false | Undefined |
+ +---------+-----------+----------+----------+-------+---------+-----------+
*/
/*
@@ -225,7 +251,7 @@ typedef struct gawk_api {
* does not match what is specified in wanted. In that case,
* result->val_type is as described above.
*/
- awk_bool_t (*get_argument)(awk_ext_id_t id, size_t count,
+ awk_bool_t (*api_get_argument)(awk_ext_id_t id, size_t count,
awk_valtype_t wanted,
awk_value_t *result);
@@ -235,7 +261,7 @@ typedef struct gawk_api {
* if count is too big, or if the argument's type is
* not undefined.
*/
- awk_bool_t (*set_argument)(awk_ext_id_t id,
+ awk_bool_t (*api_set_argument)(awk_ext_id_t id,
size_t count,
awk_array_t array);
@@ -245,20 +271,20 @@ typedef struct gawk_api {
void (*api_lintwarn)(awk_ext_id_t id, const char *format, ...);
/* Register an open hook; for opening files read-only */
- void (*register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF_PUBLIC *));
+ void (*api_register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF_PUBLIC *));
/* Functions to update ERRNO */
- void (*update_ERRNO_int)(awk_ext_id_t id, int errno_val);
- void (*update_ERRNO_string)(awk_ext_id_t id, const char *string,
+ void (*api_update_ERRNO_int)(awk_ext_id_t id, int errno_val);
+ void (*api_update_ERRNO_string)(awk_ext_id_t id, const char *string,
awk_bool_t translate);
- void (*unset_ERRNO)(awk_ext_id_t id);
+ void (*api_unset_ERRNO)(awk_ext_id_t id);
/* Add a function to the interpreter, returns true upon success */
- awk_bool_t (*add_ext_func)(awk_ext_id_t id, const awk_ext_func_t *func,
+ awk_bool_t (*api_add_ext_func)(awk_ext_id_t id, const awk_ext_func_t *func,
const char *namespace);
/* Add an exit call back, returns true upon success */
- void (*awk_atexit)(awk_ext_id_t id,
+ void (*api_awk_atexit)(awk_ext_id_t id,
void (*funcp)(void *data, int exit_status),
void *arg0);
@@ -285,7 +311,7 @@ typedef struct gawk_api {
* // safe to use val
* }
*/
- awk_bool_t (*sym_lookup)(awk_ext_id_t id,
+ awk_bool_t (*api_sym_lookup)(awk_ext_id_t id,
const char *name,
awk_valtype_t wanted,
awk_value_t *result);
@@ -296,16 +322,32 @@ typedef struct gawk_api {
* 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);
+ awk_bool_t (*api_sym_update)(awk_ext_id_t id, const char *name, awk_value_t *value);
+
+ /*
+ * Work with a scalar cookie.
+ * Flow is
+ * sym_lookup with wanted == AWK_SCALAR
+ * if returns false
+ * sym_update with real initial value
+ * sym_lookup again with AWK_SCALAR
+ * else
+ * use the scalar cookie
+ *
+ * Return will be false if the new value is not one of
+ * AWK_STRING or AWK_NUMBER.
+ */
+ awk_bool_t (*api_sym_update_scalar)(awk_ext_id_t id,
+ awk_scalar_t cookie, awk_value_t *value);
/* Array management */
/*
* 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
+ * Behavior for value and return is same as for api_get_argument
* and sym_lookup.
*/
- awk_bool_t (*get_array_element)(awk_ext_id_t id,
+ 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,
@@ -315,7 +357,7 @@ typedef struct gawk_api {
* Change (or create) element in existing array with
* element->index and element->value.
*/
- awk_bool_t (*set_array_element)(awk_ext_id_t id, awk_array_t a_cookie,
+ awk_bool_t (*api_set_array_element)(awk_ext_id_t id, awk_array_t a_cookie,
const awk_value_t *const index,
const awk_value_t *const value);
@@ -323,24 +365,24 @@ typedef struct gawk_api {
* Remove the element with the given index.
* Returns success if removed or if element did not exist.
*/
- awk_bool_t (*del_array_element)(awk_ext_id_t id,
+ awk_bool_t (*api_del_array_element)(awk_ext_id_t id,
awk_array_t a_cookie, const awk_value_t* const index);
/*
* Retrieve total number of elements in array.
* Returns false if some kind of error.
*/
- awk_bool_t (*get_element_count)(awk_ext_id_t id,
+ awk_bool_t (*api_get_element_count)(awk_ext_id_t id,
awk_array_t a_cookie, size_t *count);
/* Create a new array cookie to which elements may be added */
- awk_array_t (*create_array)(awk_ext_id_t id);
+ awk_array_t (*api_create_array)(awk_ext_id_t id);
/* Clear out an array */
- awk_bool_t (*clear_array)(awk_ext_id_t id, awk_array_t a_cookie);
+ awk_bool_t (*api_clear_array)(awk_ext_id_t id, awk_array_t a_cookie);
/* Flatten out an array so that it can be looped over easily. */
- awk_bool_t (*flatten_array)(awk_ext_id_t id,
+ awk_bool_t (*api_flatten_array)(awk_ext_id_t id,
awk_array_t a_cookie,
awk_flat_array_t **data);
@@ -349,7 +391,7 @@ typedef struct gawk_api {
* Count must match what gawk thinks the size is.
* Otherwise it's a fatal error.
*/
- awk_bool_t (*release_flattened_array)(awk_ext_id_t id,
+ awk_bool_t (*api_release_flattened_array)(awk_ext_id_t id,
awk_array_t a_cookie,
awk_flat_array_t *data);
} gawk_api_t;
@@ -367,52 +409,54 @@ typedef struct gawk_api {
#define do_mpfr (api->do_flags[gawk_do_mpfr])
#define get_argument(count, wanted, result) \
- (api->get_argument(ext_id, count, wanted, result))
+ (api->api_get_argument(ext_id, count, wanted, result))
#define set_argument(count, new_array) \
- (api->set_argument(ext_id, count, new_array))
+ (api->api_set_argument(ext_id, count, new_array))
#define fatal api->api_fatal
#define warning api->api_warning
#define lintwarn api->api_lintwarn
-#define register_open_hook(func) (api->register_open_hook(ext_id, func))
+#define register_open_hook(func) (api->api_register_open_hook(ext_id, func))
-#define update_ERRNO_int(e) (api->update_ERRNO_int(ext_id, e))
+#define update_ERRNO_int(e) (api->api_update_ERRNO_int(ext_id, e))
#define update_ERRNO_string(str, translate) \
- (api->update_ERRNO_string(ext_id, str, translate))
-#define unset_ERRNO() (api->unset_ERRNO(ext_id))
+ (api->api_update_ERRNO_string(ext_id, str, translate))
+#define unset_ERRNO() (api->api_unset_ERRNO(ext_id))
-#define add_ext_func(func, ns) (api->add_ext_func(ext_id, func, ns))
-#define awk_atexit(funcp, arg0) (api->awk_atexit(ext_id, funcp, arg0))
+#define add_ext_func(func, ns) (api->api_add_ext_func(ext_id, func, ns))
+#define awk_atexit(funcp, arg0) (api->api_awk_atexit(ext_id, funcp, arg0))
-#define sym_lookup(name, wanted, result) (api->sym_lookup(ext_id, name, wanted, result))
+#define sym_lookup(name, wanted, result) (api->api_sym_lookup(ext_id, name, wanted, result))
#define sym_update(name, value) \
- (api->sym_update(ext_id, name, value))
+ (api->api_sym_update(ext_id, name, value))
+#define sym_update_scalar(scalar_cookie, value) \
+ (api->api_sym_update_scalar)(ext_id, scalar_cookie, value)
#define get_array_element(array, index, wanted, result) \
- (api->get_array_element(ext_id, array, index, wanted, result))
+ (api->api_get_array_element(ext_id, array, index, wanted, result))
#define set_array_element(array, index, value) \
- (api->set_array_element(ext_id, array, index, value))
+ (api->api_set_array_element(ext_id, array, index, value))
#define set_array_element_by_elem(array, elem) \
- (set_array_element(array, & (elem)->index, & (elem)->value))
+ (api->api_set_array_element(ext_id, array, & (elem)->index, & (elem)->value))
#define del_array_element(array, index) \
- (api->del_array_element(ext_id, array, index))
+ (api->api_del_array_element(ext_id, array, index))
#define get_element_count(array, count_p) \
- (api->get_element_count(ext_id, array, count_p))
+ (api->api_get_element_count(ext_id, array, count_p))
-#define create_array() (api->create_array(ext_id))
+#define create_array() (api->api_create_array(ext_id))
-#define clear_array(array) (api->clear_array(ext_id, array))
+#define clear_array(array) (api->api_clear_array(ext_id, array))
#define flatten_array(array, data) \
- (api->flatten_array(ext_id, array, data))
+ (api->api_flatten_array(ext_id, array, data))
#define release_flattened_array(array, data) \
- (api->release_flattened_array(ext_id, array, data))
+ (api->api_release_flattened_array(ext_id, array, data))
#define emalloc(pointer, type, size, message) \
do { \
@@ -420,6 +464,12 @@ typedef struct gawk_api {
fatal(ext_id, "malloc of %d bytes failed\n", size); \
} while(0)
+#define erealloc(pointer, type, size, message) \
+ do { \
+ if ((pointer = (type) realloc(pointer, size)) == 0) \
+ fatal(ext_id, "realloc of %d bytes failed\n", size); \
+ } while(0)
+
/* Constructor functions */
/* r_make_string --- make a string value in result from the passed-in string */
@@ -440,7 +490,7 @@ r_make_string(const gawk_api_t *api, /* needed for emalloc */
result->str_value.len = length;
if (duplicate) {
- emalloc(cp, char *, length + 2, "make_string");
+ emalloc(cp, char *, length + 2, "r_make_string");
memcpy(cp, string, length);
cp[length] = '\0';
result->str_value.str = cp;
@@ -451,8 +501,19 @@ r_make_string(const gawk_api_t *api, /* needed for emalloc */
return result;
}
-#define make_string(str, len, result) r_make_string(api, ext_id, str, len, 0, result)
-#define dup_string(str, len, result) r_make_string(api, ext_id, str, len, 1, result)
+#define make_const_string(str, len, result) r_make_string(api, ext_id, str, len, 1, result)
+#define make_malloced_string(str, len, result) r_make_string(api, ext_id, str, len, 0, result)
+
+/* make_null_string --- make a null string value */
+
+static inline awk_value_t *
+make_null_string(awk_value_t *result)
+{
+ memset(result, 0, sizeof(*result));
+ result->val_type = AWK_UNDEFINED;
+
+ return result;
+}
/* make_number --- make a number value in result */