From 60a3183d9a228569eee98b19c67600e103ae1eac Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 15 May 2012 22:28:11 +0300 Subject: Start fleshing out new extension API. --- gawkapi.c | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 gawkapi.c (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c new file mode 100644 index 00000000..059d49e5 --- /dev/null +++ b/gawkapi.c @@ -0,0 +1,339 @@ +/* + * gawkapi.c -- Implement the functions defined for gawkapi.h + */ + +/* + * Copyright (C) 2012, the Free Software Foundation, Inc. + * + * This file is part of GAWK, the GNU implementation of the + * AWK Programming Language. + * + * GAWK is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GAWK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "awk.h" + +/* + * 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. + */ +static awk_value_t * +api_get_curfunc_param(awk_ext_id_t id, size_t count, + awk_param_type_t wanted) +{ + return NULL; /* for now */ +} + +/* Set the return value. Gawk takes ownership of string memory */ +static void +api_set_return_value(awk_ext_id_t id, const awk_value_t *retval) +{ +} + +/* Functions to print messages */ +/* FIXME: Code duplicate from msg.c. Fix this. */ +static void +api_fatal(awk_ext_id_t id, const char *format, ...) +{ + va_list args; + va_start(args, format); + err(_("fatal: "), format, args); + va_end(args); +#ifdef GAWKDEBUG + abort(); +#endif + gawk_exit(EXIT_FATAL); +} + +static void +api_warning(awk_ext_id_t id, const char *format, ...) +{ + va_list args; + va_start(args, format); + err(_("warning: "), format, args); + va_end(args); +} + +static void +api_lintwarn(awk_ext_id_t id, const char *format, ...) +{ + va_list args; + va_start(args, format); + if (lintwarn == r_fatal) { + err(_("fatal: "), format, args); + va_end(args); +#ifdef GAWKDEBUG + abort(); +#endif + gawk_exit(EXIT_FATAL); + } else { + err(_("warning: "), format, args); + va_end(args); + } +} + +/* Register an open hook; for opening files read-only */ +static awk_bool_t +api_register_open_hook(awk_ext_id_t id, void* (*open_func)(IOBUF *)) +{ + return true; /* for now */ +} + +/* Functions to update ERRNO */ +static void +api_update_ERRNO_int(awk_ext_id_t id, int errno_val) +{ + update_ERRNO_int(errno_val); +} + +static void +api_update_ERRNO_string(awk_ext_id_t id, const char *string, + awk_bool_t translate) +{ + update_ERRNO_string(string, translate); +} + +static void +api_unset_ERRNO(awk_ext_id_t id) +{ + unset_ERRNO(); +} + + +/* 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) +{ + return true; /* for now */ +} + +/* Stuff for exit handler - do it as linked list */ + +struct ext_exit_handler { + struct ext_exit_handler *next; + void (*funcp)(void *data, int exit_status); + void *arg0; +}; +static struct ext_exit_handler *list_head = NULL; + +/* run_ext_exit_handlers --- run the extension exit handlers, LIFO order */ + +void +run_ext_exit_handlers(int exitval) +{ + struct ext_exit_handler *p, *next; + + for (p = list_head; p != NULL; p = next) { + next = p->next; + p->funcp(p->arg0, exitval); + free(p); + } + list_head = NULL; +} + +/* 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), + void *arg0) +{ + struct ext_exit_handler *p; + + /* allocate memory */ + emalloc(p, struct ext_exit_handler *, sizeof(struct ext_exit_handler), "api_awk_atexit"); + + /* fill it in */ + p->funcp = funcp; + p->arg0 = arg0; + + /* add to linked list, LIFO order */ + p->next = list_head; + list_head = p; + 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. + */ +/* + * Lookup a variable, return its value. No messing with the value + * returned. Return value is NULL if the variable doesn't exist. + */ +static const awk_value_t *const +api_sym_lookup(awk_ext_id_t id, const char *name) +{ + return NULL; /* for now */ +} + +/* + * Update a value. Adds it to the symbol table if not there. + * Changing types is not allowed. + */ +static awk_bool_t +api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) +{ + return true; /* for now */ +} + +/* Array management */ +/* + * Return the value of an element - read only! + * Use set_array_element to change it. + */ +static const awk_value_t *const +api_get_array_element(awk_ext_id_t id, + awk_array_t a_cookie, const awk_value_t *const index) +{ + return NULL; /* for now */ +} + +/* + * Change (or create) element in existing array with + * element->index and element->value. + */ +static awk_bool_t +api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, + awk_element_t *element) +{ + return true; /* for now */ +} + +/* + * Remove the element with the given index. + * Returns success if removed or if element did not exist. + */ +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 */ +} + +/* + * Retrieve total number of elements in array. + * Returns false if some kind of error. + */ +static awk_bool_t +api_get_element_count(awk_ext_id_t id, + awk_array_t a_cookie, size_t *count) +{ + return true; /* for now */ +} + +/* Create a new array cookie to which elements may be added */ +static awk_array_t +api_create_array(awk_ext_id_t id) +{ + return NULL; /* for now */ +} + +/* Clear out an array */ +static awk_bool_t +api_clear_array(awk_ext_id_t id, awk_array_t a_cookie) +{ + return true; /* for now */ +} + +/* Flatten out an array so that it can be looped over easily. */ +static awk_bool_t +api_flatten_array(awk_ext_id_t id, + awk_array_t a_cookie, + size_t *count, + awk_element_t **data) +{ + return true; /* for now */ +} + +/* + * When done, release the memory, delete any marked elements + * Count must match what gawk thinks the size is. + */ +static awk_bool_t +api_release_flattened_array(awk_ext_id_t id, + awk_array_t a_cookie, + size_t count, + awk_element_t *data) +{ + return true; /* for now */ +} + +/* Constructor functions */ +static awk_value_t * +api_make_string(awk_ext_id_t id, + const char *string, size_t length) +{ + static awk_value_t result; + + result.val_type = AWK_STRING; + result.str_value.str = (char *) string; + result.str_value.len = length; + + return & result; +} + +static awk_value_t * +api_make_number(awk_ext_id_t id, double num) +{ + static awk_value_t result; + + result.val_type = AWK_NUMBER; + result.num_value = num; + + return & result; +} + +static gawk_api_t api_impl = { + GAWK_API_MAJOR_VERSION, /* major and minor versions */ + GAWK_API_MINOR_VERSION, + { 0 }, /* do_flags */ + + api_get_curfunc_param, + api_set_return_value, + + api_fatal, + api_warning, + api_lintwarn, + + api_register_open_hook, + + api_update_ERRNO_int, + api_update_ERRNO_string, + api_unset_ERRNO, + + api_add_ext_func, + + api_awk_atexit, + + api_sym_lookup, + api_sym_update, + + api_get_array_element, + api_set_array_element, + api_del_array_element, + api_get_element_count, + api_create_array, + api_clear_array, + api_flatten_array, + api_release_flattened_array, + + /* Constructor functions */ + api_make_string, + api_make_number, +}; -- cgit v1.2.3 From 85458962f4ca247b4c263a5588150960ee6f3e42 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 16 May 2012 22:22:57 +0300 Subject: More work on extension API. --- gawkapi.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 059d49e5..d4d6503a 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -115,7 +115,9 @@ api_unset_ERRNO(awk_ext_id_t id) /* 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) +api_add_ext_func(awk_ext_id_t id, + const awk_ext_func_t *func, + const char *namespace) { return true; /* for now */ } @@ -277,14 +279,27 @@ api_release_flattened_array(awk_ext_id_t id, /* Constructor functions */ static awk_value_t * api_make_string(awk_ext_id_t id, - const char *string, size_t length) + const char *string, + size_t length, + awk_bool_t duplicate) { static awk_value_t result; + char *cp = NULL; result.val_type = AWK_STRING; - result.str_value.str = (char *) string; result.str_value.len = length; + if (duplicate) { + emalloc(cp, char *, length + 1, "api_make_string"); + memcpy(cp, string, length); + cp[length] = '\0'; + + result.str_value.str = cp; + } else { + result.str_value.str = (char *) string; + } + + return & result; } -- cgit v1.2.3 From 0f2e51f9b18a1c4e203e0bd0ac3c68db9faa9b6d Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 16 May 2012 22:55:58 +0300 Subject: More progress on extension API. --- gawkapi.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index d4d6503a..2eb071c6 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -86,10 +86,11 @@ api_lintwarn(awk_ext_id_t id, const char *format, ...) } /* Register an open hook; for opening files read-only */ -static awk_bool_t + +static void api_register_open_hook(awk_ext_id_t id, void* (*open_func)(IOBUF *)) { - return true; /* for now */ + register_open_hook(open_func); } /* Functions to update ERRNO */ @@ -174,6 +175,37 @@ api_awk_atexit(awk_ext_id_t id, * - Use sym_update() to change a value, including from UNDEFINED * to scalar or array. */ +static const awk_value_t *const +node_to_awk_value(NODE *node) +{ + static awk_value_t val; + + memset(& val, 0, sizeof(val)); + switch (node->type) { + case Node_var_new: + val.val_type = AWK_UNDEFINED; + break; + case Node_var: + if ((node->var_value->flags & NUMBER) != 0) { + val.val_type = AWK_NUMBER; + val.num_value = get_number_d(node->var_value); + } else { + val.val_type = AWK_STRING; + val.str_value.str = node->var_value->stptr; + val.str_value.len = node->var_value->stlen; + } + break; + case Node_var_array: + val.val_type = AWK_ARRAY; + val.array_cookie = node; + break; + default: + return NULL; + } + + return & val; +} + /* * Lookup a variable, return its value. No messing with the value * returned. Return value is NULL if the variable doesn't exist. @@ -181,7 +213,12 @@ api_awk_atexit(awk_ext_id_t id, static const awk_value_t *const api_sym_lookup(awk_ext_id_t id, const char *name) { - return NULL; /* for now */ + NODE *node; + + if (name == NULL || (node = lookup(name)) == NULL) + return NULL; + + return node_to_awk_value(node); } /* @@ -236,7 +273,13 @@ static awk_bool_t api_get_element_count(awk_ext_id_t id, awk_array_t a_cookie, size_t *count) { - return true; /* for now */ + NODE *node = (NODE *) a_cookie; + + if (node == NULL || node->type != Node_var_array) + return false; + + *count = node->array_size; + return true; } /* Create a new array cookie to which elements may be added */ @@ -250,7 +293,13 @@ api_create_array(awk_ext_id_t id) static awk_bool_t api_clear_array(awk_ext_id_t id, awk_array_t a_cookie) { - return true; /* for now */ + NODE *node = (NODE *) a_cookie; + + if (node == NULL || node->type != Node_var_array) + return false; + + assoc_clear(node); + return true; } /* Flatten out an array so that it can be looped over easily. */ -- cgit v1.2.3 From 860fe8fd4734fb3e9cc5568595ce1ac719d71112 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 18 May 2012 14:24:51 +0300 Subject: Further ext API progress. --- gawkapi.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 2eb071c6..2a9ad927 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -25,6 +25,19 @@ #include "awk.h" +static const awk_value_t *const node_to_awk_value(NODE *node); + +/* + * This value is passed back to gawk when an extension function returns. + * Having it static is not wonderful, but on the other hand gawk is not + * multithreaded and calls to extension functions are not multithreaded. + * + * Hmm. They should not be recursive either, but since C code cannot call + * back into awk code, there should not be a problem. But we should + * document how this works. + */ +static NODE *ext_ret_val; + /* * Get the count'th paramater, zero-based. * Returns NULL if count is out of range, or if actual paramater @@ -34,13 +47,51 @@ static awk_value_t * api_get_curfunc_param(awk_ext_id_t id, size_t count, awk_param_type_t wanted) { - return NULL; /* for now */ + NODE *arg; + + arg = (wanted == AWK_PARAM_ARRAY + ? get_array_argument(count, false) + : get_scalar_argument(count, false) ); + if (arg == NULL) + return NULL; + + if (arg->type != Node_var_array) { + if (wanted == AWK_PARAM_NUMBER) { + (void) force_number(arg); + } else { + (void) force_string(arg); + } + } + + return (awk_value_t *) node_to_awk_value(arg); } /* Set the return value. Gawk takes ownership of string memory */ static void api_set_return_value(awk_ext_id_t id, const awk_value_t *retval) { + if (retval == NULL) + fatal(_("api_set_return_value: received null retval")); + + ext_ret_val = NULL; + getnode(ext_ret_val); + if (retval->val_type == AWK_ARRAY) { + *ext_ret_val = *((NODE *) retval->array_cookie); + } else if (retval->val_type == AWK_UNDEFINED) { + /* free node */ + ext_ret_val = Nnull_string; + } else if (retval->val_type == AWK_NUMBER) { + ext_ret_val->type = Node_val; + ext_ret_val->flags |= NUMBER|NUMCUR; + /* FIXME: How to do this? + ext_ret_val->numbr = retval->num_value; + */ + } else { + ext_ret_val->type = Node_val; + ext_ret_val->flags |= STRING|STRCUR; + ext_ret_val->stptr = retval->str_value.str; + ext_ret_val->stlen = retval->str_value.len; + } } /* Functions to print messages */ -- cgit v1.2.3 From cd9fdf221c0504639a38e773c3d56a32ae80e2cc Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 20 May 2012 22:26:46 +0300 Subject: More extension work. --- gawkapi.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 2a9ad927..e1d2a511 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -452,3 +452,16 @@ static gawk_api_t api_impl = { api_make_string, api_make_number, }; + +/* init_ext_api --- init the extension API */ + +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; +} -- cgit v1.2.3 From 577c3fc31a2718461fba2e599d162de96fe838fa Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 24 May 2012 15:34:17 -0400 Subject: First working version of new API mechanism (probably has memory leaks). --- gawkapi.c | 148 +++++++++++++++++++++++--------------------------------------- 1 file changed, 55 insertions(+), 93 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index e1d2a511..dbaa730e 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -25,18 +25,7 @@ #include "awk.h" -static const awk_value_t *const node_to_awk_value(NODE *node); - -/* - * This value is passed back to gawk when an extension function returns. - * Having it static is not wonderful, but on the other hand gawk is not - * multithreaded and calls to extension functions are not multithreaded. - * - * Hmm. They should not be recursive either, but since C code cannot call - * back into awk code, there should not be a problem. But we should - * document how this works. - */ -static NODE *ext_ret_val; +static awk_value_t *node_to_awk_value(NODE *node, awk_value_t *result); /* * Get the count'th paramater, zero-based. @@ -45,31 +34,33 @@ static NODE *ext_ret_val; */ static awk_value_t * api_get_curfunc_param(awk_ext_id_t id, size_t count, - awk_param_type_t wanted) + awk_valtype_t wanted, awk_value_t *result) { NODE *arg; - arg = (wanted == AWK_PARAM_ARRAY + arg = (wanted == AWK_ARRAY ? get_array_argument(count, false) : get_scalar_argument(count, false) ); if (arg == NULL) return NULL; if (arg->type != Node_var_array) { - if (wanted == AWK_PARAM_NUMBER) { + if (wanted == AWK_NUMBER) { (void) force_number(arg); } else { (void) force_string(arg); } } - return (awk_value_t *) node_to_awk_value(arg); + return node_to_awk_value(arg, result); } /* Set the return value. Gawk takes ownership of string memory */ -static void -api_set_return_value(awk_ext_id_t id, const awk_value_t *retval) +NODE * +awk_value_to_node(const awk_value_t *retval) { + NODE *ext_ret_val; + if (retval == NULL) fatal(_("api_set_return_value: received null retval")); @@ -79,19 +70,13 @@ api_set_return_value(awk_ext_id_t id, const awk_value_t *retval) *ext_ret_val = *((NODE *) retval->array_cookie); } else if (retval->val_type == AWK_UNDEFINED) { /* free node */ - ext_ret_val = Nnull_string; + ext_ret_val = dupnode(Nnull_string); } else if (retval->val_type == AWK_NUMBER) { - ext_ret_val->type = Node_val; - ext_ret_val->flags |= NUMBER|NUMCUR; - /* FIXME: How to do this? - ext_ret_val->numbr = retval->num_value; - */ + ext_ret_val = make_number(retval->num_value); } else { - ext_ret_val->type = Node_val; - ext_ret_val->flags |= STRING|STRCUR; - ext_ret_val->stptr = retval->str_value.str; - ext_ret_val->stlen = retval->str_value.len; + ext_ret_val = make_string(retval->str_value.str, retval->str_value.len); } + return ext_ret_val; } /* Functions to print messages */ @@ -171,7 +156,7 @@ api_add_ext_func(awk_ext_id_t id, const awk_ext_func_t *func, const char *namespace) { - return true; /* for now */ + return make_builtin(func); } /* Stuff for exit handler - do it as linked list */ @@ -226,50 +211,60 @@ api_awk_atexit(awk_ext_id_t id, * - Use sym_update() to change a value, including from UNDEFINED * to scalar or array. */ -static const awk_value_t *const -node_to_awk_value(NODE *node) +static awk_value_t * +node_to_awk_value(NODE *node, awk_value_t *val) { - static awk_value_t val; - - memset(& val, 0, sizeof(val)); + memset(val, 0, sizeof(*val)); switch (node->type) { + case Node_val: + if (node->flags & NUMBER) { + val->val_type = AWK_NUMBER; + val->num_value = get_number_d(node); + } else if (node->flags & STRING) { + val->val_type = AWK_STRING; + val->str_value.str = node->stptr; + val->str_value.len = node->stlen; + } else { + return NULL; + } + case Node_var_new: - val.val_type = AWK_UNDEFINED; + val->val_type = AWK_UNDEFINED; break; case Node_var: if ((node->var_value->flags & NUMBER) != 0) { - val.val_type = AWK_NUMBER; - val.num_value = get_number_d(node->var_value); + val->val_type = AWK_NUMBER; + val->num_value = get_number_d(node->var_value); } else { - val.val_type = AWK_STRING; - val.str_value.str = node->var_value->stptr; - val.str_value.len = node->var_value->stlen; + val->val_type = AWK_STRING; + val->str_value.str = node->var_value->stptr; + val->str_value.len = node->var_value->stlen; } break; case Node_var_array: - val.val_type = AWK_ARRAY; - val.array_cookie = node; + val->val_type = AWK_ARRAY; + val->array_cookie = node; break; default: return NULL; } - return & val; + return val; } /* * Lookup a variable, return its value. No messing with the value * returned. Return value is NULL if the variable doesn't exist. */ -static const awk_value_t *const -api_sym_lookup(awk_ext_id_t id, const char *name) +static awk_value_t * +api_sym_lookup(awk_ext_id_t id, const char *name, awk_value_t *result) { NODE *node; if (name == NULL || (node = lookup(name)) == NULL) return NULL; - return node_to_awk_value(node); + return node_to_awk_value(node, result); } /* @@ -287,9 +282,10 @@ 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 const awk_value_t *const +static awk_value_t * api_get_array_element(awk_ext_id_t id, - awk_array_t a_cookie, const awk_value_t *const index) + awk_array_t a_cookie, const awk_value_t *const index, + awk_value_t *result) { return NULL; /* for now */ } @@ -302,7 +298,16 @@ static awk_bool_t api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, awk_element_t *element) { - return true; /* for now */ + NODE *array = (NODE *)a_cookie; + NODE *tmp; + NODE **aptr; + + tmp = make_string(element->index.str, element->index.len); + aptr = assoc_lookup(array, tmp); + unref(tmp); + unref(*aptr); + *aptr = awk_value_to_node(& element->value); + return true; } /* @@ -376,51 +381,12 @@ api_release_flattened_array(awk_ext_id_t id, return true; /* for now */ } -/* Constructor functions */ -static awk_value_t * -api_make_string(awk_ext_id_t id, - const char *string, - size_t length, - awk_bool_t duplicate) -{ - static awk_value_t result; - char *cp = NULL; - - result.val_type = AWK_STRING; - result.str_value.len = length; - - if (duplicate) { - emalloc(cp, char *, length + 1, "api_make_string"); - memcpy(cp, string, length); - cp[length] = '\0'; - - result.str_value.str = cp; - } else { - result.str_value.str = (char *) string; - } - - - return & result; -} - -static awk_value_t * -api_make_number(awk_ext_id_t id, double num) -{ - static awk_value_t result; - - result.val_type = AWK_NUMBER; - result.num_value = num; - - return & result; -} - -static gawk_api_t api_impl = { +gawk_api_t api_impl = { GAWK_API_MAJOR_VERSION, /* major and minor versions */ GAWK_API_MINOR_VERSION, { 0 }, /* do_flags */ api_get_curfunc_param, - api_set_return_value, api_fatal, api_warning, @@ -447,10 +413,6 @@ static gawk_api_t api_impl = { api_clear_array, api_flatten_array, api_release_flattened_array, - - /* Constructor functions */ - api_make_string, - api_make_number, }; /* init_ext_api --- init the extension API */ -- cgit v1.2.3 From eec7101174a3b2807fb282272f75cc13d4b953c3 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 25 May 2012 15:18:43 +0300 Subject: Additional changes / some cleanups. --- gawkapi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index dbaa730e..a25a8905 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -255,13 +255,17 @@ node_to_awk_value(NODE *node, awk_value_t *val) /* * 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. */ static awk_value_t * api_sym_lookup(awk_ext_id_t id, const char *name, awk_value_t *result) { NODE *node; - if (name == NULL || (node = lookup(name)) == NULL) + if ( name == NULL + || *name == '\0' + || is_off_limits_var(name) /* most built-in vars not allowed */ + || (node = lookup(name)) == NULL) return NULL; return node_to_awk_value(node, result); -- cgit v1.2.3 From 04dc190623f0d99d80387b33ca747b8cbad37724 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 29 May 2012 23:33:27 +0300 Subject: Further API work. --- gawkapi.c | 56 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index a25a8905..03db6b80 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -25,7 +25,7 @@ #include "awk.h" -static awk_value_t *node_to_awk_value(NODE *node, awk_value_t *result); +static awk_value_t *node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted); /* * Get the count'th paramater, zero-based. @@ -44,32 +44,24 @@ api_get_curfunc_param(awk_ext_id_t id, size_t count, if (arg == NULL) return NULL; - if (arg->type != Node_var_array) { - if (wanted == AWK_NUMBER) { - (void) force_number(arg); - } else { - (void) force_string(arg); - } - } - - return node_to_awk_value(arg, result); + return node_to_awk_value(arg, result, wanted); } -/* Set the return value. Gawk takes ownership of string memory */ +/* awk_value_to_node --- convert a value into a NODE */ + NODE * awk_value_to_node(const awk_value_t *retval) { NODE *ext_ret_val; if (retval == NULL) - fatal(_("api_set_return_value: received null retval")); + fatal(_("awk_value_to_node: received null retval")); ext_ret_val = NULL; - getnode(ext_ret_val); if (retval->val_type == AWK_ARRAY) { + getnode(ext_ret_val); *ext_ret_val = *((NODE *) retval->array_cookie); } else if (retval->val_type == AWK_UNDEFINED) { - /* free node */ ext_ret_val = dupnode(Nnull_string); } else if (retval->val_type == AWK_NUMBER) { ext_ret_val = make_number(retval->num_value); @@ -212,39 +204,45 @@ api_awk_atexit(awk_ext_id_t id, * to scalar or array. */ static awk_value_t * -node_to_awk_value(NODE *node, awk_value_t *val) +node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) { 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 (node->type) { + case Node_var: + node = node->var_value; + /* FALL THROUGH */ case Node_val: if (node->flags & 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) { 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; case Node_var_new: val->val_type = AWK_UNDEFINED; break; - case Node_var: - if ((node->var_value->flags & NUMBER) != 0) { - val->val_type = AWK_NUMBER; - val->num_value = get_number_d(node->var_value); - } else { - val->val_type = AWK_STRING; - val->str_value.str = node->var_value->stptr; - val->str_value.len = node->var_value->stlen; - } - break; + case Node_var_array: val->val_type = AWK_ARRAY; val->array_cookie = node; break; + default: return NULL; } @@ -258,7 +256,9 @@ node_to_awk_value(NODE *node, awk_value_t *val) * Built-in variables (except PROCINFO) may not be changed by an extension. */ static awk_value_t * -api_sym_lookup(awk_ext_id_t id, const char *name, awk_value_t *result) +api_sym_lookup(awk_ext_id_t id, + const char *name, awk_value_t *result, + awk_valtype_t wanted) { NODE *node; @@ -268,7 +268,7 @@ api_sym_lookup(awk_ext_id_t id, const char *name, awk_value_t *result) || (node = lookup(name)) == NULL) return NULL; - return node_to_awk_value(node, result); + return node_to_awk_value(node, result, wanted); } /* @@ -289,7 +289,7 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) static awk_value_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_value_t *result, awk_valtype_t wanted) { return NULL; /* for now */ } -- cgit v1.2.3 From e6ddb0631c88b591792e3486f857ca26875de310 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 30 May 2012 21:47:18 +0300 Subject: Continue refining extension API and implementation. --- gawkapi.c | 112 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 32 deletions(-) (limited to 'gawkapi.c') 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,60 +197,79 @@ 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. @@ -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 */ } -- cgit v1.2.3 From dab3a678b3f65ae4cde21ca4b1d4fd24e8a71918 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 6 Jun 2012 20:08:02 +0300 Subject: Changes to LINT reflect to extn API. Add API tests. --- gawkapi.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 3b915fc2..7a79f782 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -479,3 +479,11 @@ init_ext_api() api_impl.do_flags[4] = do_debug; api_impl.do_flags[5] = do_mpfr; } + +/* update_ext_api --- update the variables in the API that can change */ + +void +update_ext_api() +{ + api_impl.do_flags[0] = do_lint; +} -- cgit v1.2.3 From 7891af5ec56ff4ed99435433c135079a9e24e037 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 10 Jun 2012 21:03:48 -0400 Subject: Add time extension providing gettimeofday and sleep. --- gawkapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 7a79f782..95bcbf15 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -132,7 +132,7 @@ static void api_update_ERRNO_string(awk_ext_id_t id, const char *string, awk_bool_t translate) { - update_ERRNO_string(string, translate); + update_ERRNO_string(string, (translate ? TRANSLATE : DONT_TRANSLATE)); } static void -- cgit v1.2.3 From 820b6a2ccb7859e15ade36af6ac1d0d08c1da4b1 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 12 Jun 2012 22:10:31 +0300 Subject: Further cleanups and improvements in API. --- gawkapi.c | 153 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 90 insertions(+), 63 deletions(-) (limited to 'gawkapi.c') 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, -- cgit v1.2.3 From 8ce87087172ee5be4ee72a1513daad3821185bf7 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 12 Jun 2012 23:11:37 +0300 Subject: More API implementations and testext improvements. --- gawkapi.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 22 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 885d514f..3f9159d9 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -42,6 +42,8 @@ api_get_argument(awk_ext_id_t id, size_t count, if (result == NULL) return false; + (void) id; + arg = (wanted == AWK_ARRAY ? get_array_argument(count, false) : get_scalar_argument(count, false) ); @@ -81,10 +83,16 @@ awk_value_to_node(const awk_value_t *retval) /* Functions to print messages */ /* FIXME: Code duplicate from msg.c. Fix this. */ + +/* api_fatal --- print a fatal message and exit */ + static void api_fatal(awk_ext_id_t id, const char *format, ...) { va_list args; + + (void) id; + va_start(args, format); err(_("fatal: "), format, args); va_end(args); @@ -94,19 +102,29 @@ api_fatal(awk_ext_id_t id, const char *format, ...) gawk_exit(EXIT_FATAL); } +/* api_warning --- print a warning message and exit */ + static void api_warning(awk_ext_id_t id, const char *format, ...) { va_list args; + + (void) id; + va_start(args, format); err(_("warning: "), format, args); va_end(args); } +/* api_lintwarn --- print a lint warning message and exit if appropriate */ + static void api_lintwarn(awk_ext_id_t id, const char *format, ...) { va_list args; + + (void) id; + va_start(args, format); if (lintwarn == r_fatal) { err(_("fatal: "), format, args); @@ -121,31 +139,47 @@ api_lintwarn(awk_ext_id_t id, const char *format, ...) } } -/* Register an open hook; for opening files read-only */ +/* api_register_open_hook --- register an open hook; for opening files read-only */ static void api_register_open_hook(awk_ext_id_t id, void* (*open_func)(IOBUF *)) { + (void) id; + register_open_hook(open_func); } /* Functions to update ERRNO */ + +/* api_update_ERRNO_int --- update ERRNO with an integer value */ + static void api_update_ERRNO_int(awk_ext_id_t id, int errno_val) { + (void) id; + update_ERRNO_int(errno_val); } +/* api_update_ERRNO_string --- update ERRNO with a string value */ + static void -api_update_ERRNO_string(awk_ext_id_t id, const char *string, - awk_bool_t translate) +api_update_ERRNO_string(awk_ext_id_t id, + const char *string, + awk_bool_t translate) { + (void) id; + update_ERRNO_string(string, (translate ? TRANSLATE : DONT_TRANSLATE)); } +/* api_unset_ERRNO --- unset ERRNO */ + static void api_unset_ERRNO(awk_ext_id_t id) { + (void) id; + unset_ERRNO(); } @@ -157,6 +191,9 @@ api_add_ext_func(awk_ext_id_t id, const awk_ext_func_t *func, const char *namespace) { + (void) id; + (void) namespace; + return make_builtin(func); } @@ -193,6 +230,8 @@ api_awk_atexit(awk_ext_id_t id, { struct ext_exit_handler *p; + (void) id; + /* allocate memory */ emalloc(p, struct ext_exit_handler *, sizeof(struct ext_exit_handler), "api_awk_atexit"); @@ -300,6 +339,9 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) * 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. */ + +/* api_sym_lookup --- look up a symbol */ + static awk_bool_t api_sym_lookup(awk_ext_id_t id, const char *name, @@ -318,27 +360,13 @@ api_sym_lookup(awk_ext_id_t id, return node_to_awk_value(node, result, wanted); } -/* api_sym_update --- update a value, see gawkapi.h for semantics */ +/* api_sym_update --- update a symbol's 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: @@ -349,11 +377,27 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) return false; default: - fatal(_("api_sym_update: invalid value for type of new value (%d)"), value->val_type); + /* fatal(_("api_sym_update: invalid value for type of new value (%d)"), value->val_type); */ return false; } - return true; /* for now */ + 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); + } + unref(node->var_value); + + node->var_value = awk_value_to_node(value); + + return true; } /* Array management */ @@ -366,6 +410,21 @@ 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) { + NODE *array; + NODE *subscript; + + /* don't check for index len zero, null str is ok as index */ + if ( a_cookie == NULL + || 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 */ + return true; /* for now */ } @@ -381,6 +440,12 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, NODE *tmp; NODE **aptr; + /* don't check for index len zero, null str is ok as index */ + if ( a_cookie == NULL + || element == NULL + || element->index.str == NULL) + return false; + tmp = make_string(element->index.str, element->index.len); aptr = assoc_lookup(array, tmp); unref(tmp); @@ -410,10 +475,10 @@ api_get_element_count(awk_ext_id_t id, { NODE *node = (NODE *) a_cookie; - if (node == NULL || node->type != Node_var_array) + if (count == NULL || node == NULL || node->type != Node_var_array) return false; - *count = node->array_size; + *count = node->table_size; return true; } -- cgit v1.2.3 From 5e79fa8735ec2984fee9054cccd51d86fa939621 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 17 Jun 2012 20:47:50 +0300 Subject: Still more API and testext.c work. --- gawkapi.c | 113 +++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 31 deletions(-) (limited to 'gawkapi.c') 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); } -- cgit v1.2.3 From 6311c35dd8984a8516802b3cc111c1f411e098fd Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 18 Jun 2012 21:13:34 +0300 Subject: More API implementation progress. --- gawkapi.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index f57f4f58..b616fbfc 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -405,8 +405,25 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) unref(node->var_value); node->var_value = awk_value_to_node(value); } + return true; + } + + /* if we get here, then it exists already */ + switch (value->val_type) { + case AWK_STRING: + case AWK_NUMBER: + if (node->type == Node_var || node->type == Node_var_new) { + unref(node->var_value); + node->var_value = awk_value_to_node(value); + } else { + return false; + } + break; + + case AWK_ARRAY: + case AWK_UNDEFINED: + return false; /* not allowed */ } - /* FIXME: Handle case where it exists already */ return true; } @@ -420,6 +437,7 @@ 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) { NODE *array = (NODE *) a_cookie; @@ -441,7 +459,7 @@ api_get_array_element(awk_ext_id_t id, if (aptr == NULL) return false; - return node_to_awk_value(*aptr, result, AWK_UNDEFINED); + return node_to_awk_value(*aptr, result, wanted); } /* -- cgit v1.2.3 From 1e3ac8a49caeeb991d8163042a576a66db51c74b Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 18 Jun 2012 23:00:58 +0300 Subject: Get most of array flattening done. --- gawkapi.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 8 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index b616fbfc..b1fba48a 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -478,10 +478,11 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, if ( array == NULL || array->type != Node_var_array || element == NULL - || element->index.str == NULL) + || element->index.str_value.str == NULL) return false; - tmp = make_string(element->index.str, element->index.len); + tmp = make_string(element->index.str_value.str, + element->index.str_value.len); aptr = assoc_lookup(array, tmp); unref(tmp); unref(*aptr); @@ -570,14 +571,56 @@ api_clear_array(awk_ext_id_t id, awk_array_t a_cookie) return true; } -/* Flatten out an array so that it can be looped over easily. */ +/* api_flatten_array --- flatten out an array so that it can be looped over easily. */ + static awk_bool_t api_flatten_array(awk_ext_id_t id, awk_array_t a_cookie, - size_t *count, - awk_element_t **data) + awk_flat_array_t **data) { - return true; /* for now */ + NODE **list; + size_t i, j; + NODE *array = (NODE *) a_cookie; + size_t alloc_size; + + if ( array == NULL + || array->type != Node_var_array + || array->table_size == 0 + || data == NULL) + return false; + + alloc_size = sizeof(awk_flat_array_t) + + (array->table_size - 1) * sizeof(awk_element_t); + + emalloc(*data, awk_flat_array_t *, alloc_size, + "api_flatten_array"); + memset(*data, 0, alloc_size); + + list = assoc_list(array, "@unsorted", ASORTI); + + (*data)->opaque1 = array; + (*data)->opaque2 = list; + (*data)->count = array->table_size; + + for (i = j = 0; i < 2 * array->table_size; i += 2, j++) { + NODE *index, *value; + + index = force_string(list[i]); + value = list[i + 1]; /* number or string or subarray */ + + /* convert index and value to ext types */ + if (! node_to_awk_value(index, + & (*data)->elements[j].index, AWK_UNDEFINED)) { + fatal(_("api_flatten_array: could not convert index %d\n"), + (int) i); + } + if (! node_to_awk_value(value, + & (*data)->elements[j].value, AWK_UNDEFINED)) { + fatal(_("api_flatten_array: could not convert value %d\n"), + (int) i); + } + } + return true; } /* @@ -587,9 +630,30 @@ api_flatten_array(awk_ext_id_t id, static awk_bool_t api_release_flattened_array(awk_ext_id_t id, awk_array_t a_cookie, - size_t count, - awk_element_t *data) + awk_flat_array_t *data) { + NODE *array = a_cookie; + NODE **list; + size_t i; + + if ( array == NULL + || array->type != Node_var_array + || data == NULL + || array != (NODE *) data->opaque1 + || data->count != array->table_size + || data->opaque2 == NULL) + return false; + + list = (NODE **) data->opaque2; + + /* FIXME: Delete items flagged for delete. */ + + /* free index nodes */ + for (i = 0; i < 2 * array->table_size; i += 2) + unref(list[i]); + + efree(list); + return true; /* for now */ } -- cgit v1.2.3 From 3a40be8a79f9d4e4bb205cca4eb15b1ee811f60c Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 19 Jun 2012 20:42:51 +0300 Subject: Fix code duplication in gawkapi.c from msg.c. --- gawkapi.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index b1fba48a..92403dce 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -83,7 +83,6 @@ awk_value_to_node(const awk_value_t *retval) } /* Functions to print messages */ -/* FIXME: Code duplicate from msg.c. Fix this. */ /* api_fatal --- print a fatal message and exit */ @@ -95,12 +94,8 @@ api_fatal(awk_ext_id_t id, const char *format, ...) (void) id; va_start(args, format); - err(_("fatal: "), format, args); + err(true, _("fatal: "), format, args); va_end(args); -#ifdef GAWKDEBUG - abort(); -#endif - gawk_exit(EXIT_FATAL); } /* api_warning --- print a warning message and exit */ @@ -113,7 +108,7 @@ api_warning(awk_ext_id_t id, const char *format, ...) (void) id; va_start(args, format); - err(_("warning: "), format, args); + err(false, _("warning: "), format, args); va_end(args); } @@ -128,14 +123,10 @@ api_lintwarn(awk_ext_id_t id, const char *format, ...) va_start(args, format); if (lintwarn == r_fatal) { - err(_("fatal: "), format, args); + err(true, _("fatal: "), format, args); va_end(args); -#ifdef GAWKDEBUG - abort(); -#endif - gawk_exit(EXIT_FATAL); } else { - err(_("warning: "), format, args); + err(false, _("warning: "), format, args); va_end(args); } } -- cgit v1.2.3 From fd3c1195711270a001d860770098b8c0d9118c10 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 19 Jun 2012 20:54:19 +0300 Subject: Delete marked elements from flattened array. --- gawkapi.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 92403dce..5eb16881 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -637,15 +637,24 @@ api_release_flattened_array(awk_ext_id_t id, list = (NODE **) data->opaque2; - /* FIXME: Delete items flagged for delete. */ + /* 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 = 0; i < 2 * array->table_size; i += 2) { unref(list[i]); + } efree(list); + efree(data); - return true; /* for now */ + return true; } gawk_api_t api_impl = { -- cgit v1.2.3 From d66f3c9922e36bb2e760e0ac36364c1a5aa11442 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 20 Jun 2012 21:41:15 +0300 Subject: API: Add set_parameter function and test. --- gawkapi.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 7 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 5eb16881..ad7e68fd 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -44,17 +44,83 @@ api_get_argument(awk_ext_id_t id, size_t count, (void) id; - arg = (wanted == AWK_ARRAY - ? get_array_argument(count, false) - : get_scalar_argument(count, false) ); - - if (arg == NULL) { - memset(result, 0, sizeof(*result)); - result->val_type = AWK_UNDEFINED; + /* set up default result */ + memset(result, 0, sizeof(*result)); + result->val_type = AWK_UNDEFINED; + + /* + * Song and dance here. get_array_argument() and get_scalar_argument() + * will force a change in type of a parameter that is Node_var_new. + * + * Start by looking at the unadulterated argument as it was passed. + */ + arg = get_argument(count); + if (arg == NULL) return false; + + /* if type is undefined */ + if (arg->type == Node_var_new) { + if (wanted == AWK_UNDEFINED) + return true; + else if (wanted == AWK_ARRAY) { + goto array; + } else { + goto scalar; + } } + + /* at this point, we have real type */ + if (arg->type == Node_var_array || arg->type == Node_array_ref) { + if (wanted != AWK_ARRAY && wanted != AWK_UNDEFINED) + return false; + goto array; + } else + goto scalar; + +array: + /* get the array here */ + arg = get_array_argument(count, false); + if (arg == NULL) + return false; return node_to_awk_value(arg, result, wanted); + +scalar: + /* at this point we have a real type that is not an array */ + arg = get_scalar_argument(count, false); + if (arg == NULL) + return false; + + return node_to_awk_value(arg, result, wanted); +} + +static awk_bool_t +api_set_argument(awk_ext_id_t id, + size_t count, + awk_array_t new_array) +{ + NODE *arg; + NODE *array = (NODE *) new_array; + awk_valtype_t valtype; + + (void) id; + + if (array == NULL || array->type != Node_var_array) + return false; + + if ( (arg = get_argument(count)) == NULL + || arg->type != Node_var_new) + return false; + + arg = get_array_argument(count, false); + if (arg == NULL) + return false; + + array->vname = arg->vname; + *arg = *array; + freenode(array); + + return true; } /* awk_value_to_node --- convert a value into a NODE */ @@ -663,6 +729,7 @@ gawk_api_t api_impl = { { 0 }, /* do_flags */ api_get_argument, + api_set_argument, api_fatal, api_warning, -- cgit v1.2.3 From 898eb2ad1d514887993994e60fe860ac3ee1bba8 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 21 Jun 2012 22:20:38 +0300 Subject: Further API code and test code. --- gawkapi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index ad7e68fd..139d77b8 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -101,7 +101,6 @@ api_set_argument(awk_ext_id_t id, { NODE *arg; NODE *array = (NODE *) new_array; - awk_valtype_t valtype; (void) id; @@ -544,6 +543,8 @@ 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); + if ((*aptr)->type == Node_var_array) + (*aptr)->parent_array = array; return true; } -- cgit v1.2.3 From 37cd3566b9b74c43d5f11f1cba8dec147a25e474 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 24 Jun 2012 21:07:22 +0300 Subject: Get rwarray extension working with new API. --- gawkapi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 139d77b8..f87c7759 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -528,6 +528,7 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, { NODE *array = (NODE *)a_cookie; NODE *tmp; + NODE *elem; NODE **aptr; /* don't check for index len zero, null str is ok as index */ @@ -542,9 +543,13 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, aptr = assoc_lookup(array, tmp); unref(tmp); unref(*aptr); - *aptr = awk_value_to_node(& element->value); - if ((*aptr)->type == Node_var_array) - (*aptr)->parent_array = array; + elem = *aptr = awk_value_to_node(& element->value); + if (elem->type == Node_var_array) { + elem->parent_array = array; + elem->vname = estrdup(element->index.str_value.str, + element->index.str_value.len); + make_aname(elem); + } return true; } -- cgit v1.2.3 From 6139211362667682c3022a72321e0cd8945b6592 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 24 Jun 2012 18:43:49 -0400 Subject: Hide private parts of IOBUF from extensions. --- gawkapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index f87c7759..0a00be69 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -199,7 +199,7 @@ api_lintwarn(awk_ext_id_t id, const char *format, ...) /* api_register_open_hook --- register an open hook; for opening files read-only */ static void -api_register_open_hook(awk_ext_id_t id, void* (*open_func)(IOBUF *)) +api_register_open_hook(awk_ext_id_t id, void* (*open_func)(IOBUF_PUBLIC *)) { (void) id; -- cgit v1.2.3 From 7d37bcd5a8066718b15de8c03725708819389931 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 9 Jul 2012 21:17:10 +0300 Subject: API: Update set_array_element(). Adjust extensions. --- gawkapi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 0a00be69..ad82f6fa 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -524,7 +524,8 @@ api_get_array_element(awk_ext_id_t id, */ static awk_bool_t api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, - awk_element_t *element) + const awk_value_t *const index, + const awk_value_t *const value) { NODE *array = (NODE *)a_cookie; NODE *tmp; @@ -534,20 +535,20 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, /* don't check for index len zero, null str is ok as index */ if ( array == NULL || array->type != Node_var_array - || element == NULL - || element->index.str_value.str == NULL) + || index == NULL + || value == NULL + || index->str_value.str == NULL) return false; - tmp = make_string(element->index.str_value.str, - element->index.str_value.len); + tmp = make_string(index->str_value.str, index->str_value.len); aptr = assoc_lookup(array, tmp); unref(tmp); unref(*aptr); - elem = *aptr = awk_value_to_node(& element->value); + elem = *aptr = awk_value_to_node(value); if (elem->type == Node_var_array) { elem->parent_array = array; - elem->vname = estrdup(element->index.str_value.str, - element->index.str_value.len); + elem->vname = estrdup(index->str_value.str, + index->str_value.len); make_aname(elem); } -- cgit v1.2.3 From e33b672ff4ab1b7469355a79eaf4c4740f412e45 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Wed, 11 Jul 2012 09:34:46 -0400 Subject: Patch API sym_update to accept AWK_UNDEFINED for "". --- gawkapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index ad82f6fa..3fa3e3ba 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -468,6 +468,7 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) switch (value->val_type) { case AWK_STRING: case AWK_NUMBER: + case AWK_UNDEFINED: if (node->type == Node_var || node->type == Node_var_new) { unref(node->var_value); node->var_value = awk_value_to_node(value); @@ -477,7 +478,6 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) break; case AWK_ARRAY: - case AWK_UNDEFINED: return false; /* not allowed */ } -- cgit v1.2.3 From 6d1724214a95330b63a6a557f89fb9b40b4a521f Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 11 Jul 2012 21:26:37 +0300 Subject: API clean up and require strings to be malloced. --- gawkapi.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 98 insertions(+), 30 deletions(-) (limited to 'gawkapi.c') 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); } @@ -555,6 +614,32 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, return true; } +/* + * 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, -- cgit v1.2.3 From 64fecd1d7a14c23fbbd6938e237c66a31fabb04f Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Wed, 11 Jul 2012 15:22:39 -0400 Subject: API array functions now accept any scalar value for an array subscript. --- gawkapi.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index c5f8953d..9e4f731b 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -132,16 +132,23 @@ awk_value_to_node(const awk_value_t *retval) if (retval == NULL) fatal(_("awk_value_to_node: received null retval")); - ext_ret_val = NULL; - if (retval->val_type == AWK_ARRAY) { + switch (retval->val_type) { + case AWK_ARRAY: ext_ret_val = (NODE *) retval->array_cookie; - } else if (retval->val_type == AWK_UNDEFINED) { + break; + case AWK_UNDEFINED: ext_ret_val = dupnode(Nnull_string); - } else if (retval->val_type == AWK_NUMBER) { + break; + case AWK_NUMBER: ext_ret_val = make_number(retval->num_value); - } else { + break; + case AWK_STRING: ext_ret_val = make_str_node(retval->str_value.str, retval->str_value.len, ALREADY_MALLOCED); + break; + default: /* AWK_SCALAR or any invalid type */ + ext_ret_val = NULL; + break; } return ext_ret_val; @@ -532,6 +539,24 @@ api_sym_update_scalar(awk_ext_id_t id, return true; } +/* + * Test if a type is allowed for an array subscript. A string or numeric + * value is fine, and undefined is equivalent to "", so those are OK. + * We reject AWK_ARRAY and AWK_SCALAR. + */ +static inline int +valid_subscript_type(awk_valtype_t valtype) +{ + switch (valtype) { + case AWK_UNDEFINED: + case AWK_NUMBER: + case AWK_STRING: + return true; + default: + return false; + } +} + /* Array management */ /* * Return the value of an element - read only! @@ -553,8 +578,7 @@ api_get_array_element(awk_ext_id_t id, || array->type != Node_var_array || result == NULL || index == NULL - || index->val_type != AWK_STRING - || index->str_value.str == NULL) + || ! valid_subscript_type(index->val_type)) return false; subscript = awk_value_to_node(index); @@ -596,10 +620,10 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, || array->type != Node_var_array || index == NULL || value == NULL - || index->str_value.str == NULL) + || ! valid_subscript_type(index->val_type)) return false; - tmp = make_string(index->str_value.str, index->str_value.len); + tmp = awk_value_to_node(index); aptr = assoc_lookup(array, tmp); unref(tmp); unref(*aptr); @@ -654,7 +678,7 @@ api_del_array_element(awk_ext_id_t id, if ( array == NULL || array->type != Node_var_array || index == NULL - || index->val_type != AWK_STRING) + || ! valid_subscript_type(index->val_type)) return false; sub = awk_value_to_node(index); -- cgit v1.2.3 From dda2495337929a86cc40017d8f1cd72a46876618 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 12 Jul 2012 09:24:55 -0400 Subject: Add sym_lookup_scalar to API for fast scalar_cookie value retrieval. --- gawkapi.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 9e4f731b..b6d83acb 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -442,6 +442,24 @@ api_sym_lookup(awk_ext_id_t id, return node_to_awk_value(node, result, wanted); } +/* api_sym_lookup_scalar --- retrieve the current value of a scalar */ + +static awk_bool_t +api_sym_lookup_scalar(awk_ext_id_t id, + awk_scalar_t cookie, + awk_valtype_t wanted, + awk_value_t *result) +{ + NODE *node = (NODE *) cookie; + + if (node == NULL + || result == NULL + || node->type != Node_var) + return false; + + return node_to_awk_value(node, result, wanted); +} + /* api_sym_update --- update a symbol's value, see gawkapi.h for semantics */ static awk_bool_t @@ -844,6 +862,7 @@ gawk_api_t api_impl = { api_awk_atexit, api_sym_lookup, + api_sym_lookup_scalar, api_sym_update, api_sym_update_scalar, -- cgit v1.2.3 From 28daef44c3c08f16002c678319a30b816f6972fd Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 12 Jul 2012 22:45:25 +0300 Subject: Allow creation of constants from extensions. --- gawkapi.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index b6d83acb..e8d50e8c 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -26,6 +26,7 @@ #include "awk.h" static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted); +static void set_constant(); /* * Get the count'th paramater, zero-based. @@ -460,10 +461,13 @@ api_sym_lookup_scalar(awk_ext_id_t id, return node_to_awk_value(node, result, wanted); } -/* api_sym_update --- update a symbol's value, see gawkapi.h for semantics */ +/* api_sym_update_real --- update a symbol's 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) +sym_update_real(awk_ext_id_t id, + const char *name, + awk_value_t *value, + bool is_const) { NODE *node; NODE *array_node; @@ -503,6 +507,8 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) Node_var); unref(node->var_value); node->var_value = awk_value_to_node(value); + if (is_const) + node->var_assign = set_constant; } return true; } @@ -518,6 +524,9 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) if (node->type == Node_var || node->type == Node_var_new) { unref(node->var_value); node->var_value = awk_value_to_node(value); + /* let the extension change its own variable */ + if (is_const) + node->var_assign = set_constant; } else { return false; } @@ -530,6 +539,26 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) return true; } +/* api_sym_update --- update a symbol, non-constant */ + +static awk_bool_t +api_sym_update(awk_ext_id_t id, + const char *name, + awk_value_t *value) +{ + return sym_update_real(id, name, value, false); +} + +/* api_sym_update --- update a symbol, constant */ + +static awk_bool_t +api_sym_constant(awk_ext_id_t id, + const char *name, + awk_value_t *value) +{ + return sym_update_real(id, name, value, true); +} + /* api_sym_update_scalar --- update a scalar cookie */ static awk_bool_t @@ -864,6 +893,7 @@ gawk_api_t api_impl = { api_sym_lookup, api_sym_lookup_scalar, api_sym_update, + api_sym_constant, api_sym_update_scalar, api_get_array_element, @@ -897,3 +927,11 @@ update_ext_api() { api_impl.do_flags[0] = (do_lint ? 1 : 0); } + +/* set_constant --- prevent awk code from changing a constant */ + +static void +set_constant() +{ + fatal(_("cannot assign to defined constant")); +} -- cgit v1.2.3 From 7e99da1009403952ec84ade1cad199b59927f735 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 16 Jul 2012 21:16:22 +0300 Subject: Minor performance improvement in sym_update_scalar. --- gawkapi.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index e8d50e8c..6c03dd0b 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -129,6 +129,7 @@ NODE * awk_value_to_node(const awk_value_t *retval) { NODE *ext_ret_val; + NODE *v; if (retval == NULL) fatal(_("awk_value_to_node: received null retval")); @@ -147,7 +148,14 @@ awk_value_to_node(const awk_value_t *retval) ext_ret_val = make_str_node(retval->str_value.str, retval->str_value.len, ALREADY_MALLOCED); break; - default: /* AWK_SCALAR or any invalid type */ + case AWK_SCALAR: + v = (NODE *) retval->scalar_cookie; + if (v->type != Node_var) + ext_ret_val = NULL; + else + ext_ret_val = dupnode(v->var_value); + break; + default: /* any invalid type */ ext_ret_val = NULL; break; } @@ -568,20 +576,52 @@ api_sym_update_scalar(awk_ext_id_t id, { NODE *node = (NODE *) cookie; NODE *new_value; + bool hard_way = false; 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); + switch (value->val_type) { + case AWK_NUMBER: + case AWK_UNDEFINED: + case AWK_SCALAR: + hard_way = true; + /* fall through */ + case AWK_STRING: + break; + default: return false; + break; + } + + hard_way = (hard_way || node->var_value->valref > 1); + + if (hard_way) { + /* do it the harder way */ + + unref(node->var_value); + node->var_value = awk_value_to_node(value); + + return true; + } + + /* convert value to string, optimized */ + new_value = node->var_value; + free_wstr(new_value); + new_value->flags &= ~(NUMBER|NUMCUR); + new_value->stfmt = -1; + + if ((new_value->flags & STRING) != 0) { + if ((new_value->flags & MALLOC) != 0) { + efree(new_value->stptr); + } } - unref(node->var_value); - node->var_value = new_value; + new_value->stptr = value->str_value.str; + new_value->stlen = value->str_value.len; + new_value->flags |= (STRING|STRCUR|MALLOC); return true; } -- cgit v1.2.3 From 0907dd281b71fb440c83fc53e6b4c7312f1c1f47 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 17 Jul 2012 23:13:14 +0300 Subject: Add AWK_VALUE_COOKIE. And performance speedup. --- gawkapi.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 6c03dd0b..22d218d8 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -155,6 +155,9 @@ awk_value_to_node(const awk_value_t *retval) else ext_ret_val = dupnode(v->var_value); break; + case AWK_VALUE_COOKIE: + ext_ret_val = dupnode((NODE *)(retval->value_cookie)); + break; default: /* any invalid type */ ext_ret_val = NULL; break; @@ -585,8 +588,24 @@ api_sym_update_scalar(awk_ext_id_t id, switch (value->val_type) { case AWK_NUMBER: + if (node->var_value->valref == 1 && ! do_mpfr) { + NODE *r = node->var_value; + + r->numbr = value->num_value; + if (r->flags & STRCUR) { + efree(r->stptr); + r->stptr = NULL; + r->stlen = 0; + } + free_wstr(r); + r->flags = NUMBER|NUMCUR; + return true; + } + /* otherwise, fall through */ + case AWK_UNDEFINED: case AWK_SCALAR: + case AWK_VALUE_COOKIE: hard_way = true; /* fall through */ case AWK_STRING: @@ -638,6 +657,7 @@ valid_subscript_type(awk_valtype_t valtype) case AWK_UNDEFINED: case AWK_NUMBER: case AWK_STRING: + case AWK_VALUE_COOKIE: return true; default: return false; @@ -908,6 +928,20 @@ api_release_flattened_array(awk_ext_id_t id, return true; } +static awk_bool_t +api_create_value(awk_ext_id_t id, awk_value_t *value, + awk_value_cookie_t *result) +{ + return (*result = awk_value_to_node(value)) != NULL; +} + +static awk_bool_t +api_release_value(awk_ext_id_t id, awk_value_cookie_t value) +{ + unref((NODE *) value); + return true; +} + gawk_api_t api_impl = { GAWK_API_MAJOR_VERSION, /* major and minor versions */ GAWK_API_MINOR_VERSION, @@ -944,6 +978,9 @@ gawk_api_t api_impl = { api_clear_array, api_flatten_array, api_release_flattened_array, + + api_create_value, + api_release_value, }; /* init_ext_api --- init the extension API */ -- cgit v1.2.3 From 2abd3979c829934905f5a84dd2f5836b1d8eec37 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 17 Jul 2012 23:44:30 +0300 Subject: More API work. --- gawkapi.c | 73 ++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 31 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 22d218d8..c750f064 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -396,6 +396,7 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) break; case AWK_ARRAY: + case AWK_VALUE_COOKIE: break; } break; @@ -544,6 +545,7 @@ sym_update_real(awk_ext_id_t id, break; case AWK_ARRAY: + case AWK_VALUE_COOKIE: return false; /* not allowed */ } @@ -579,7 +581,6 @@ api_sym_update_scalar(awk_ext_id_t id, { NODE *node = (NODE *) cookie; NODE *new_value; - bool hard_way = false; if (value == NULL || node == NULL @@ -598,7 +599,7 @@ api_sym_update_scalar(awk_ext_id_t id, r->stlen = 0; } free_wstr(r); - r->flags = NUMBER|NUMCUR; + r->flags = MALLOC|NUMBER|NUMCUR; return true; } /* otherwise, fall through */ @@ -606,41 +607,37 @@ api_sym_update_scalar(awk_ext_id_t id, case AWK_UNDEFINED: case AWK_SCALAR: case AWK_VALUE_COOKIE: - hard_way = true; - /* fall through */ + break; case AWK_STRING: + /* convert value to string, optimized */ + if (node->var_value->valref == 1) { + new_value = node->var_value; + free_wstr(new_value); + new_value->flags &= ~(NUMBER|NUMCUR); + new_value->stfmt = -1; + + if ((new_value->flags & STRING) != 0) { + if ((new_value->flags & MALLOC) != 0) { + efree(new_value->stptr); + } + } + + new_value->stptr = value->str_value.str; + new_value->stlen = value->str_value.len; + new_value->flags |= (STRING|STRCUR|MALLOC); + + return true; + } break; - default: + case AWK_ARRAY: return false; break; } - hard_way = (hard_way || node->var_value->valref > 1); - - if (hard_way) { - /* do it the harder way */ - - unref(node->var_value); - node->var_value = awk_value_to_node(value); - - return true; - } - - /* convert value to string, optimized */ - new_value = node->var_value; - free_wstr(new_value); - new_value->flags &= ~(NUMBER|NUMCUR); - new_value->stfmt = -1; - - if ((new_value->flags & STRING) != 0) { - if ((new_value->flags & MALLOC) != 0) { - efree(new_value->stptr); - } - } + /* do it the harder way */ - new_value->stptr = value->str_value.str; - new_value->stlen = value->str_value.len; - new_value->flags |= (STRING|STRCUR|MALLOC); + unref(node->var_value); + node->var_value = awk_value_to_node(value); return true; } @@ -659,9 +656,11 @@ valid_subscript_type(awk_valtype_t valtype) case AWK_STRING: case AWK_VALUE_COOKIE: return true; - default: + case AWK_SCALAR: + case AWK_ARRAY: return false; } + return false; } /* Array management */ @@ -932,6 +931,18 @@ static awk_bool_t api_create_value(awk_ext_id_t id, awk_value_t *value, awk_value_cookie_t *result) { + switch (value->val_type) { + case AWK_NUMBER: + case AWK_STRING: + case AWK_UNDEFINED: + break; + case AWK_ARRAY: + case AWK_SCALAR: + case AWK_VALUE_COOKIE: + /* reject anything other than a simple scalar */ + return false; + } + return (*result = awk_value_to_node(value)) != NULL; } -- cgit v1.2.3 From ffbf8454171c0ef037db425f436c735da3691d9f Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Tue, 17 Jul 2012 17:23:42 -0400 Subject: Clean up support for AWK_SCALAR and AWK_VALUE_COOKIE. --- gawkapi.c | 55 +++++++++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 36 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index c750f064..50ebc457 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -495,6 +495,8 @@ sym_update_real(awk_ext_id_t id, case AWK_STRING: case AWK_UNDEFINED: case AWK_ARRAY: + case AWK_SCALAR: + case AWK_VALUE_COOKIE: break; default: @@ -517,7 +519,6 @@ sym_update_real(awk_ext_id_t id, /* regular variable */ node = install_symbol(estrdup((char *) name, strlen(name)), Node_var); - unref(node->var_value); node->var_value = awk_value_to_node(value); if (is_const) node->var_assign = set_constant; @@ -525,31 +526,18 @@ sym_update_real(awk_ext_id_t id, return true; } - /* 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: - if (node->type == Node_var || node->type == Node_var_new) { - unref(node->var_value); - node->var_value = awk_value_to_node(value); - /* let the extension change its own variable */ - if (is_const) - node->var_assign = set_constant; - } else { - return false; - } - break; - - case AWK_ARRAY: - case AWK_VALUE_COOKIE: - return false; /* not allowed */ + /* If we get here, then it exists already. Any valid type is + * OK except for AWK_ARRAY. */ + if ((value->val_type != AWK_ARRAY) && + (node->type == Node_var || node->type == Node_var_new)) { + unref(node->var_value); + node->var_value = awk_value_to_node(value); + /* let the extension change its own variable */ + if (is_const) + node->var_assign = set_constant; + return true; } - - return true; + return false; } /* api_sym_update --- update a symbol, non-constant */ @@ -629,7 +617,7 @@ api_sym_update_scalar(awk_ext_id_t id, return true; } break; - case AWK_ARRAY: + default: /* reject AWK_ARRAY or an invalid type */ return false; break; } @@ -643,9 +631,8 @@ api_sym_update_scalar(awk_ext_id_t id, } /* - * Test if a type is allowed for an array subscript. A string or numeric - * value is fine, and undefined is equivalent to "", so those are OK. - * We reject AWK_ARRAY and AWK_SCALAR. + * Test if a type is allowed for an array subscript. + * Any scalar value is fine, so only AWK_ARRAY (or an invalid type) is illegal. */ static inline int valid_subscript_type(awk_valtype_t valtype) @@ -654,13 +641,12 @@ valid_subscript_type(awk_valtype_t valtype) case AWK_UNDEFINED: case AWK_NUMBER: case AWK_STRING: + case AWK_SCALAR: case AWK_VALUE_COOKIE: return true; - case AWK_SCALAR: - case AWK_ARRAY: + default: /* AWK_ARRAY or an invalid type */ return false; } - return false; } /* Array management */ @@ -934,11 +920,8 @@ api_create_value(awk_ext_id_t id, awk_value_t *value, switch (value->val_type) { case AWK_NUMBER: case AWK_STRING: - case AWK_UNDEFINED: break; - case AWK_ARRAY: - case AWK_SCALAR: - case AWK_VALUE_COOKIE: + default: /* reject anything other than a simple scalar */ return false; } -- cgit v1.2.3 From 50831fa7f402480d83d5e3647d09acdad7cd0eeb Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 20 Jul 2012 12:00:31 +0300 Subject: Update doc in header. Redo update_scalar. --- gawkapi.c | 60 +++++++++++++++++++++++++++--------------------------------- 1 file changed, 27 insertions(+), 33 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index c750f064..8dd900ec 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -589,57 +589,51 @@ api_sym_update_scalar(awk_ext_id_t id, switch (value->val_type) { case AWK_NUMBER: - if (node->var_value->valref == 1 && ! do_mpfr) { + case AWK_STRING: + /* try for optimization */ + if (node->var_value->valref == 1) { NODE *r = node->var_value; - r->numbr = value->num_value; + if (value->val_type == AWK_NUMBER && do_mpfr) + break; /* break switch, do it the hard way */ + + /* release the old string value if any */ if (r->flags & STRCUR) { - efree(r->stptr); + if (r->flags & MALLOC) + efree(r->stptr); r->stptr = NULL; r->stlen = 0; } free_wstr(r); - r->flags = MALLOC|NUMBER|NUMCUR; + + if (value->val_type == AWK_NUMBER) { + r->flags = MALLOC|NUMBER|NUMCUR; + r->numbr = value->num_value; + } else { + r->flags &= ~(NUMBER|NUMCUR); + r->flags |= (STRING|STRCUR|MALLOC); + r->stfmt = -1; + r->stptr = value->str_value.str; + r->stlen = value->str_value.len; + } + return true; } - /* otherwise, fall through */ - + /* else + fall through */ case AWK_UNDEFINED: case AWK_SCALAR: case AWK_VALUE_COOKIE: - break; - case AWK_STRING: - /* convert value to string, optimized */ - if (node->var_value->valref == 1) { - new_value = node->var_value; - free_wstr(new_value); - new_value->flags &= ~(NUMBER|NUMCUR); - new_value->stfmt = -1; - - if ((new_value->flags & STRING) != 0) { - if ((new_value->flags & MALLOC) != 0) { - efree(new_value->stptr); - } - } + unref(node->var_value); + node->var_value = awk_value_to_node(value); - new_value->stptr = value->str_value.str; - new_value->stlen = value->str_value.len; - new_value->flags |= (STRING|STRCUR|MALLOC); + return true; - return true; - } - break; case AWK_ARRAY: - return false; break; } - /* do it the harder way */ - - unref(node->var_value); - node->var_value = awk_value_to_node(value); - - return true; + return false; } /* -- cgit v1.2.3 From 3d2d6b46bf3325c0273b35a202184ab09d38e0cd Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 25 Jul 2012 22:34:19 +0300 Subject: Start refactoring iop handling. Add readdir extension. --- gawkapi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 9e1c1095..09c9f399 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -215,14 +215,14 @@ api_lintwarn(awk_ext_id_t id, const char *format, ...) } } -/* api_register_open_hook --- register an open hook; for opening files read-only */ +/* api_register_input_parser --- register an input_parser; for opening files read-only */ static void -api_register_open_hook(awk_ext_id_t id, void* (*open_func)(IOBUF_PUBLIC *)) +api_register_input_parser(awk_ext_id_t id, awk_input_parser_t *input_parser) { (void) id; - register_open_hook(open_func); + register_input_parser(input_parser); } /* Functions to update ERRNO */ @@ -942,7 +942,7 @@ gawk_api_t api_impl = { api_warning, api_lintwarn, - api_register_open_hook, + api_register_input_parser, api_update_ERRNO_int, api_update_ERRNO_string, -- cgit v1.2.3 From 40eefdd931066129d0bb2f6144a0ec7741c6cc2b Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 25 Jul 2012 22:56:37 +0300 Subject: Remove translation of errno strings from API. --- gawkapi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 09c9f399..b72a62a6 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -241,12 +241,11 @@ api_update_ERRNO_int(awk_ext_id_t id, int errno_val) static void api_update_ERRNO_string(awk_ext_id_t id, - const char *string, - awk_bool_t translate) + const char *string) { (void) id; - update_ERRNO_string(string, (translate ? TRANSLATE : DONT_TRANSLATE)); + update_ERRNO_string(string); } /* api_unset_ERRNO --- unset ERRNO */ -- cgit v1.2.3 From 1a69f3ec43ba9748ad63443f88b2e26b014c11d2 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 26 Jul 2012 11:08:02 -0400 Subject: Fix api_sym_update_scalar. --- gawkapi.c | 78 ++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 31 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index b72a62a6..a1241dfc 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -574,53 +574,69 @@ api_sym_update_scalar(awk_ext_id_t id, || node->type != Node_var) return false; + /* + * Optimization: if valref is 1, and the new value is a string or + * a number, we can avoid calling unref and then making a new node + * by simply installing the new value. First, we follow the same + * recipe used by node.c:r_unref to wipe the current values, and then + * we copy the logic from r_make_number or r_make_str_node to install + * the new value. + */ switch (value->val_type) { case AWK_NUMBER: + if (node->var_value->valref == 1 && ! do_mpfr) { + NODE *r = node->var_value; + + /* r_unref: */ + if ((r->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) + efree(r->stptr); + free_wstr(r); + + /* r_make_number: */ + r->numbr = value->num_value; + r->flags = MALLOC|NUMBER|NUMCUR; + r->stptr = NULL; + r->stlen = 0; + return true; + } + break; case AWK_STRING: - /* try for optimization */ if (node->var_value->valref == 1) { NODE *r = node->var_value; - if (value->val_type == AWK_NUMBER && do_mpfr) - break; /* break switch, do it the hard way */ - - /* release the old string value if any */ - if (r->flags & STRCUR) { - if (r->flags & MALLOC) - efree(r->stptr); - r->stptr = NULL; - r->stlen = 0; - } + /* r_unref: */ + if ((r->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) + efree(r->stptr); +#ifdef HAVE_MPFR + if (is_mpg_float(r)) + mpfr_clear(r->mpg_numbr); + else if (is_mpg_integer(r)) + mpz_clear(r->mpg_i); +#endif free_wstr(r); - if (value->val_type == AWK_NUMBER) { - r->flags = MALLOC|NUMBER|NUMCUR; - r->numbr = value->num_value; - } else { - r->flags &= ~(NUMBER|NUMCUR); - r->flags |= (STRING|STRCUR|MALLOC); - r->stfmt = -1; - r->stptr = value->str_value.str; - r->stlen = value->str_value.len; - } - + /* r_make_str_node(ALREADY_MALLOCED): */ + r->numbr = 0; + r->flags = (MALLOC|STRING|STRCUR); + r->stfmt = -1; + r->stptr = value->str_value.str; + r->stlen = value->str_value.len; return true; } - /* else - fall through */ + break; case AWK_UNDEFINED: case AWK_SCALAR: case AWK_VALUE_COOKIE: - unref(node->var_value); - node->var_value = awk_value_to_node(value); - - return true; - - case AWK_ARRAY: break; + + default: /* AWK_ARRAY or invalid type */ + return false; } - return false; + /* do it the hard (slow) way */ + unref(node->var_value); + node->var_value = awk_value_to_node(value); + return true; } /* -- cgit v1.2.3 From 652a11e5fbe9862a2b8e961b32b9748b3c2c418b Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 26 Jul 2012 22:27:54 +0300 Subject: Add set_RT to API and to readdir extension. --- gawkapi.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index a1241dfc..12cd8afc 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -222,9 +222,41 @@ api_register_input_parser(awk_ext_id_t id, awk_input_parser_t *input_parser) { (void) id; + if (input_parser == NULL) + return; + register_input_parser(input_parser); } +/* api_set_RT --- set RT's value */ + +static void +api_set_RT(awk_ext_id_t id, awk_value_t *value) +{ + NODE *n; + + (void) id; + + if (value == NULL) + return; + + switch (value->val_type) { + case AWK_UNDEFINED: + set_RT_to_null(); + break; + case AWK_ARRAY: + case AWK_VALUE_COOKIE: + break; + case AWK_STRING: + case AWK_NUMBER: + case AWK_SCALAR: + n = awk_value_to_node(value); + force_string(n); + set_RT(n->stptr, n->stlen); + unref(n); + } +} + /* Functions to update ERRNO */ /* api_update_ERRNO_int --- update ERRNO with an integer value */ @@ -567,7 +599,6 @@ api_sym_update_scalar(awk_ext_id_t id, awk_value_t *value) { NODE *node = (NODE *) cookie; - NODE *new_value; if (value == NULL || node == NULL @@ -958,6 +989,7 @@ gawk_api_t api_impl = { api_lintwarn, api_register_input_parser, + api_set_RT, api_update_ERRNO_int, api_update_ERRNO_string, -- cgit v1.2.3 From 0544971abd3bf6eda1531e62b4a19e221a68a6e5 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 26 Jul 2012 23:11:15 +0300 Subject: Minor bug fix in api_set_RT. --- gawkapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 12cd8afc..a2128fe3 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -253,7 +253,7 @@ api_set_RT(awk_ext_id_t id, awk_value_t *value) n = awk_value_to_node(value); force_string(n); set_RT(n->stptr, n->stlen); - unref(n); + freenode(n); } } -- cgit v1.2.3 From 207fc1458c7f168822e454a89f23428c64163427 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 27 Jul 2012 15:25:05 +0300 Subject: Fix bug in API set_RT, bug in readdir.c. --- gawkapi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index a2128fe3..39e85e5d 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -252,8 +252,7 @@ api_set_RT(awk_ext_id_t id, awk_value_t *value) case AWK_SCALAR: n = awk_value_to_node(value); force_string(n); - set_RT(n->stptr, n->stlen); - freenode(n); + set_RT(n); /* set_RT takes ownership of n */ } } -- cgit v1.2.3 From 0eaab9127d090da073a53695583837fcbd2be9d3 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 29 Jul 2012 17:13:13 +0300 Subject: Update input_parser interface for RT. --- gawkapi.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 39e85e5d..721d69dc 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -228,34 +228,6 @@ api_register_input_parser(awk_ext_id_t id, awk_input_parser_t *input_parser) register_input_parser(input_parser); } -/* api_set_RT --- set RT's value */ - -static void -api_set_RT(awk_ext_id_t id, awk_value_t *value) -{ - NODE *n; - - (void) id; - - if (value == NULL) - return; - - switch (value->val_type) { - case AWK_UNDEFINED: - set_RT_to_null(); - break; - case AWK_ARRAY: - case AWK_VALUE_COOKIE: - break; - case AWK_STRING: - case AWK_NUMBER: - case AWK_SCALAR: - n = awk_value_to_node(value); - force_string(n); - set_RT(n); /* set_RT takes ownership of n */ - } -} - /* Functions to update ERRNO */ /* api_update_ERRNO_int --- update ERRNO with an integer value */ @@ -988,7 +960,6 @@ gawk_api_t api_impl = { api_lintwarn, api_register_input_parser, - api_set_RT, api_update_ERRNO_int, api_update_ERRNO_string, -- cgit v1.2.3 From 88e81c931345aa485e55c6d6c7f3ad61dc200fed Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 8 Aug 2012 22:37:55 +0300 Subject: Add fts() extension, support, doc, and test. --- gawkapi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 721d69dc..c34b52bb 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -517,6 +517,7 @@ sym_update_real(awk_ext_id_t id, array_node->vname = node->vname; *node = *array_node; freenode(array_node); + value->array_cookie = node; /* pass new cookie back to extension */ } else { /* regular variable */ node = install_symbol(estrdup((char *) name, strlen(name)), -- cgit v1.2.3 From 8970970f3f3bc3d757fe491e90e608366fb7e604 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 24 Aug 2012 13:25:52 +0300 Subject: Add output and two-way processors to API. Update Mac config stuff. --- gawkapi.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index c34b52bb..8fd20472 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -228,6 +228,33 @@ api_register_input_parser(awk_ext_id_t id, awk_input_parser_t *input_parser) register_input_parser(input_parser); } +/* api_register_output_wrapper --- egister an output wrapper, for writing files / two-way pipes */ + +static void api_register_output_wrapper(awk_ext_id_t id, + awk_output_wrapper_t *output_wrapper) +{ + (void) id; + + if (output_wrapper == NULL) + return; + + register_output_wrapper(output_wrapper); +} + +/* api_register_two_way_processor --- register a processor for two way I/O */ + +static void +api_register_two_way_processor(awk_ext_id_t id, + awk_two_way_processor_t *two_way_processor) +{ + (void) id; + + if (two_way_processor == NULL) + return; + + register_two_way_processor(two_way_processor); +} + /* Functions to update ERRNO */ /* api_update_ERRNO_int --- update ERRNO with an integer value */ @@ -526,20 +553,25 @@ sym_update_real(awk_ext_id_t id, if (is_const) node->var_assign = set_constant; } + return true; } - /* If we get here, then it exists already. Any valid type is - * OK except for AWK_ARRAY. */ - if ((value->val_type != AWK_ARRAY) && - (node->type == Node_var || node->type == Node_var_new)) { + /* + * If we get here, then it exists already. Any valid type is + * OK except for AWK_ARRAY. + */ + if ( value->val_type != AWK_ARRAY + && (node->type == Node_var || node->type == Node_var_new)) { unref(node->var_value); node->var_value = awk_value_to_node(value); /* let the extension change its own variable */ if (is_const) node->var_assign = set_constant; + return true; } + return false; } @@ -961,6 +993,8 @@ gawk_api_t api_impl = { api_lintwarn, api_register_input_parser, + api_register_output_wrapper, + api_register_two_way_processor, api_update_ERRNO_int, api_update_ERRNO_string, -- cgit v1.2.3 From 759f2234c9bfa689151277fd2215bc0927cfc9c3 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 24 Aug 2012 13:40:22 +0300 Subject: Add facility to get vesion info from extensions. --- gawkapi.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 8fd20472..fe6eefc2 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -980,6 +980,33 @@ api_release_value(awk_ext_id_t id, awk_value_cookie_t value) return true; } +/* + * Register a version string for this extension with gawk. + */ + +static struct version_info { + const char *version; + struct version_info *next; +}; + +static struct version_info *vi_head; + +/* api_register_ext_version --- add an extension version string to the list */ + +static void +api_register_ext_version(awk_ext_id_t id, const char *version) +{ + + struct version_info *info; + + (void) id; + + emalloc(info, struct version_info *, sizeof(struct version_info), "register_ext_version"); + info->version = version; + info->next = vi_head; + vi_head = info; +} + gawk_api_t api_impl = { GAWK_API_MAJOR_VERSION, /* major and minor versions */ GAWK_API_MINOR_VERSION, @@ -1021,6 +1048,8 @@ gawk_api_t api_impl = { api_create_value, api_release_value, + + api_register_ext_version, }; /* init_ext_api --- init the extension API */ @@ -1052,3 +1081,14 @@ set_constant() { fatal(_("cannot assign to defined constant")); } + +/* print_ext_versions --- print the list */ + +extern void +print_ext_versions(void) +{ + struct version_info *p; + + for (p = vi_head; p != NULL; p = p->next) + printf("%s\n", p->version); +} -- cgit v1.2.3 From 9b8770d74f2e1cfd719fa0dbf21c676d1c64e8ea Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 31 Aug 2012 09:54:04 +0300 Subject: Fix so will compile if no dynamic lib support. --- gawkapi.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index fe6eefc2..5d372bbe 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -38,6 +38,7 @@ static awk_bool_t api_get_argument(awk_ext_id_t id, size_t count, awk_valtype_t wanted, awk_value_t *result) { +#ifdef DYNAMIC NODE *arg; if (result == NULL) @@ -93,6 +94,9 @@ scalar: return false; return node_to_awk_value(arg, result, wanted); +#else + return false; +#endif } static awk_bool_t @@ -100,6 +104,7 @@ api_set_argument(awk_ext_id_t id, size_t count, awk_array_t new_array) { +#ifdef DYNAMIC NODE *arg; NODE *array = (NODE *) new_array; @@ -121,6 +126,9 @@ api_set_argument(awk_ext_id_t id, freenode(array); return true; +#else + return false; +#endif } /* awk_value_to_node --- convert a value into a NODE */ @@ -299,7 +307,11 @@ api_add_ext_func(awk_ext_id_t id, (void) id; (void) namespace; +#ifdef DYNAMIC return make_builtin(func); +#else + return false; +#endif } /* Stuff for exit handler - do it as linked list */ @@ -984,7 +996,7 @@ api_release_value(awk_ext_id_t id, awk_value_cookie_t value) * Register a version string for this extension with gawk. */ -static struct version_info { +struct version_info { const char *version; struct version_info *next; }; -- cgit v1.2.3 From fc9109734ddcf57c5f1faaedfadc432ec6841aa8 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 14 Sep 2012 00:16:48 +0300 Subject: Allow extensions read-only access to built-in vars. --- gawkapi.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 5d372bbe..dbb8549b 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -489,10 +489,12 @@ api_sym_lookup(awk_ext_id_t id, if ( name == NULL || *name == '\0' || result == NULL - || is_off_limits_var(name) /* most built-in vars not allowed */ || (node = lookup(name)) == NULL) return false; + if (is_off_limits_var(name)) /* a built-in variable */ + node->flags |= NO_EXT_SET; + return node_to_awk_value(node, result, wanted); } @@ -527,7 +529,6 @@ sym_update_real(awk_ext_id_t id, if ( name == NULL || *name == '\0' - || is_off_limits_var(name) /* most built-in vars not allowed */ || value == NULL) return false; @@ -573,6 +574,12 @@ sym_update_real(awk_ext_id_t id, * If we get here, then it exists already. Any valid type is * OK except for AWK_ARRAY. */ + if ( (node->flags & NO_EXT_SET) != 0 + || is_off_limits_var(name)) { /* most built-in vars not allowed */ + node->flags |= NO_EXT_SET; + return false; + } + if ( value->val_type != AWK_ARRAY && (node->type == Node_var || node->type == Node_var_new)) { unref(node->var_value); @@ -618,7 +625,8 @@ api_sym_update_scalar(awk_ext_id_t id, if (value == NULL || node == NULL - || node->type != Node_var) + || node->type != Node_var + || (node->flags & NO_EXT_SET) != 0) return false; /* @@ -766,6 +774,7 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, /* don't check for index len zero, null str is ok as index */ if ( array == NULL || array->type != Node_var_array + || (array->flags & NO_EXT_SET) != 0 || index == NULL || value == NULL || ! valid_subscript_type(index->val_type)) @@ -825,6 +834,7 @@ api_del_array_element(awk_ext_id_t id, array = (NODE *) a_cookie; if ( array == NULL || array->type != Node_var_array + || (array->flags & NO_EXT_SET) != 0 || index == NULL || ! valid_subscript_type(index->val_type)) return false; @@ -957,7 +967,8 @@ api_release_flattened_array(awk_ext_id_t id, /* free index nodes */ 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) { + if ( (data->elements[j].flags & AWK_ELEMENT_DELETE) != 0 + && (array->flags & NO_EXT_SET) == 0) { remove_element(array, list[i]); } unref(list[i]); -- cgit v1.2.3 From e7bdf5ebd4162172e79c00196061af625bd729f2 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 4 Oct 2012 12:52:26 +0200 Subject: Clean up make_str_node macro. --- gawkapi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index dbb8549b..3473a48c 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -634,7 +634,7 @@ api_sym_update_scalar(awk_ext_id_t id, * a number, we can avoid calling unref and then making a new node * by simply installing the new value. First, we follow the same * recipe used by node.c:r_unref to wipe the current values, and then - * we copy the logic from r_make_number or r_make_str_node to install + * we copy the logic from r_make_number or make_str_node to install * the new value. */ switch (value->val_type) { @@ -670,7 +670,7 @@ api_sym_update_scalar(awk_ext_id_t id, #endif free_wstr(r); - /* r_make_str_node(ALREADY_MALLOCED): */ + /* make_str_node(s, l, ALREADY_MALLOCED): */ r->numbr = 0; r->flags = (MALLOC|STRING|STRCUR); r->stfmt = -1; -- cgit v1.2.3 From 8eb78103a37e75819388c2a175caf40bf0f7b4c9 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 10 Oct 2012 14:46:22 +0200 Subject: Cleanups in gawkapi.h and adjustments for them. --- gawkapi.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 3473a48c..9f4c4f54 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -301,8 +301,8 @@ api_unset_ERRNO(awk_ext_id_t id) static awk_bool_t api_add_ext_func(awk_ext_id_t id, - const awk_ext_func_t *func, - const char *namespace) + const char *namespace, + const awk_ext_func_t *func) { (void) id; (void) namespace; @@ -1019,7 +1019,6 @@ static struct version_info *vi_head; static void api_register_ext_version(awk_ext_id_t id, const char *version) { - struct version_info *info; (void) id; @@ -1031,48 +1030,55 @@ api_register_ext_version(awk_ext_id_t id, const char *version) } gawk_api_t api_impl = { + /* data */ GAWK_API_MAJOR_VERSION, /* major and minor versions */ GAWK_API_MINOR_VERSION, { 0 }, /* do_flags */ - api_get_argument, - api_set_argument, + /* registration functions */ + api_add_ext_func, + api_register_input_parser, + api_register_output_wrapper, + api_register_two_way_processor, + api_awk_atexit, + api_register_ext_version, + /* message printing functions */ api_fatal, api_warning, api_lintwarn, - api_register_input_parser, - api_register_output_wrapper, - api_register_two_way_processor, - + /* updating ERRNO */ api_update_ERRNO_int, api_update_ERRNO_string, api_unset_ERRNO, - api_add_ext_func, - - api_awk_atexit, + /* Function arguments */ + api_get_argument, + api_set_argument, + /* Accessing and installing variables and constants */ api_sym_lookup, - api_sym_lookup_scalar, api_sym_update, api_sym_constant, + + /* Accessing and modifying variables via scalar cookies */ + api_sym_lookup_scalar, api_sym_update_scalar, + /* Cached values */ + api_create_value, + api_release_value, + + /* Array management */ + api_get_element_count, api_get_array_element, api_set_array_element, api_del_array_element, - api_get_element_count, api_create_array, api_clear_array, api_flatten_array, api_release_flattened_array, - - api_create_value, - api_release_value, - - api_register_ext_version, }; /* init_ext_api --- init the extension API */ -- cgit v1.2.3 From a92d9e310f119d61752b38bcb232e0cbe867c34f Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sat, 10 Nov 2012 21:09:32 +0200 Subject: Add null pointer checks in gawkapi.c. --- gawkapi.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 16 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 9f4c4f54..c9b2aced 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -29,11 +29,13 @@ static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype static void set_constant(); /* - * Get the count'th paramater, zero-based. + * api_get_argument --- get the count'th paramater, zero-based. + * * 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_bool_t api_get_argument(awk_ext_id_t id, size_t count, awk_valtype_t wanted, awk_value_t *result) @@ -99,6 +101,8 @@ scalar: #endif } +/* api_set_argument --- convert an argument to an array */ + static awk_bool_t api_set_argument(awk_ext_id_t id, size_t count, @@ -283,6 +287,9 @@ api_update_ERRNO_string(awk_ext_id_t id, { (void) id; + if (string == NULL) + return; + update_ERRNO_string(string); } @@ -307,6 +314,9 @@ api_add_ext_func(awk_ext_id_t id, (void) id; (void) namespace; + if (func == NULL) + return false; + #ifdef DYNAMIC return make_builtin(func); #else @@ -338,7 +348,7 @@ run_ext_exit_handlers(int exitval) list_head = NULL; } -/* api_awk_atexit --- add an exit call back, returns true upon success */ +/* api_awk_atexit --- add an exit call back */ static void api_awk_atexit(awk_ext_id_t id, @@ -349,6 +359,9 @@ api_awk_atexit(awk_ext_id_t id, (void) id; + if (funcp == NULL) + return; + /* allocate memory */ emalloc(p, struct ext_exit_handler *, sizeof(struct ext_exit_handler), "api_awk_atexit"); @@ -368,6 +381,12 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) { awk_bool_t ret = false; + if (node == NULL) + fatal(_("node_to_awk_value: received null node")); + + if (val == NULL) + fatal(_("node_to_awk_value: received null val")); + switch (node->type) { case Node_var_new: /* undefined variable */ val->val_type = AWK_UNDEFINED; @@ -695,9 +714,11 @@ api_sym_update_scalar(awk_ext_id_t id, } /* - * Test if a type is allowed for an array subscript. + * valid_subscript_type --- test if a type is allowed for an array subscript. + * * Any scalar value is fine, so only AWK_ARRAY (or an invalid type) is illegal. */ + static inline int valid_subscript_type(awk_valtype_t valtype) { @@ -715,9 +736,11 @@ valid_subscript_type(awk_valtype_t valtype) /* Array management */ /* - * Return the value of an element - read only! + * api_get_array_element --- teturn the value of an element - read only! + * * Use set_array_element to change it. */ + static awk_bool_t api_get_array_element(awk_ext_id_t id, awk_array_t a_cookie, @@ -758,9 +781,10 @@ api_get_array_element(awk_ext_id_t id, } /* - * Change (or create) element in existing array with - * element->index and element->value. + * api_set_array_element --- change (or create) element in existing array + * with element->index and element->value. */ + static awk_bool_t api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t *const index, @@ -805,6 +829,12 @@ remove_element(NODE *array, NODE *subscript) { NODE *val; + if (array == NULL) + fatal(_("remove_element: received null array")); + + if (subscript == NULL) + fatal(_("remove_element: received null subscript")); + val = in_array(array, subscript); if (val == NULL) @@ -822,9 +852,10 @@ remove_element(NODE *array, NODE *subscript) } /* - * Remove the element with the given index. - * Returns success if removed or if element did not exist. + * api_del_array_element --- remove the element with the given index. + * Return success if removed or if element did not exist. */ + static awk_bool_t api_del_array_element(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t* const index) @@ -847,9 +878,10 @@ api_del_array_element(awk_ext_id_t id, } /* - * Retrieve total number of elements in array. - * Returns false if some kind of error. + * api_get_element_count --- retrieve total number of elements in array. + * Return false if some kind of error. */ + static awk_bool_t api_get_element_count(awk_ext_id_t id, awk_array_t a_cookie, size_t *count) @@ -863,7 +895,8 @@ api_get_element_count(awk_ext_id_t id, return true; } -/* Create a new array cookie to which elements may be added */ +/* api_create_array --- create a new array cookie to which elements may be added */ + static awk_array_t api_create_array(awk_ext_id_t id) { @@ -876,13 +909,16 @@ api_create_array(awk_ext_id_t id) return (awk_array_t) n; } -/* Clear out an array */ +/* api_clear_array --- clear out an array */ + static awk_bool_t api_clear_array(awk_ext_id_t id, awk_array_t a_cookie) { NODE *node = (NODE *) a_cookie; - if (node == NULL || node->type != Node_var_array) + if ( node == NULL + || node->type != Node_var_array + || (node->flags & NO_EXT_SET) != 0) return false; assoc_clear(node); @@ -942,9 +978,11 @@ api_flatten_array(awk_ext_id_t id, } /* - * When done, release the memory, delete any marked elements - * Count must match what gawk thinks the size is. + * api_release_flattened_array --- release array memory, + * delete any marked elements. Count must match what + * gawk thinks the size is. */ + static awk_bool_t api_release_flattened_array(awk_ext_id_t id, awk_array_t a_cookie, @@ -980,10 +1018,15 @@ api_release_flattened_array(awk_ext_id_t id, return true; } +/* api_create_value --- create a cached value */ + static awk_bool_t api_create_value(awk_ext_id_t id, awk_value_t *value, awk_value_cookie_t *result) { + if (value == NULL || result == NULL) + return false; + switch (value->val_type) { case AWK_NUMBER: case AWK_STRING: @@ -996,10 +1039,17 @@ api_create_value(awk_ext_id_t id, awk_value_t *value, return (*result = awk_value_to_node(value)) != NULL; } +/* api_release_value --- release a cached value */ + static awk_bool_t api_release_value(awk_ext_id_t id, awk_value_cookie_t value) { - unref((NODE *) value); + NODE *val = (NODE *) value; + + if (val == NULL) + return false; + + unref(val); return true; } @@ -1021,6 +1071,9 @@ api_register_ext_version(awk_ext_id_t id, const char *version) { struct version_info *info; + if (version == NULL) + return; + (void) id; emalloc(info, struct version_info *, sizeof(struct version_info), "register_ext_version"); @@ -1029,6 +1082,7 @@ api_register_ext_version(awk_ext_id_t id, const char *version) vi_head = info; } +/* the struct api */ gawk_api_t api_impl = { /* data */ GAWK_API_MAJOR_VERSION, /* major and minor versions */ -- cgit v1.2.3 From c9e416d0703fc11828a1d175002805b326029735 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 14 Nov 2012 21:37:47 +0200 Subject: Minor cleanup in calls to mpfr routines. --- gawkapi.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index c9b2aced..ba3fc508 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -681,12 +681,8 @@ api_sym_update_scalar(awk_ext_id_t id, /* r_unref: */ if ((r->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR)) efree(r->stptr); -#ifdef HAVE_MPFR - if (is_mpg_float(r)) - mpfr_clear(r->mpg_numbr); - else if (is_mpg_integer(r)) - mpz_clear(r->mpg_i); -#endif + + mpfr_unset(r); free_wstr(r); /* make_str_node(s, l, ALREADY_MALLOCED): */ -- cgit v1.2.3