aboutsummaryrefslogtreecommitdiffstats
path: root/gawkapi.h
diff options
context:
space:
mode:
Diffstat (limited to 'gawkapi.h')
-rw-r--r--gawkapi.h179
1 files changed, 120 insertions, 59 deletions
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 */