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.h | 253 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 200 insertions(+), 53 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index a09a10d7..2a14d334 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -31,11 +31,21 @@ #ifndef _GAWK_API_H #define _GAWK_API_H -/* Allow the use in C++ code. */ +/* + * General introduction: + * + * This API purposely restricts itself to C90 features. + * In paticular, no bool, no // comments, no use of the + * restrict keyword, or anything else, in order to provide + * maximal portability. + */ + +/* Allow use in C++ code. */ #ifdef __cplusplus extern "C" { #endif +/* struct used for reading records and managing buffers */ typedef struct iobuf { const char *name; /* filename */ int fd; /* file descriptor */ @@ -58,7 +68,7 @@ typedef struct iobuf { void *opaque; /* private data for open hooks */ int (*get_record)(char **out, struct iobuf *, int *errcode); - void (*close_func)(struct iobuf *); /* open and close hooks */ + void (*close_func)(struct iobuf *); /* open and close hooks */ int errcode; @@ -75,45 +85,92 @@ typedef struct iobuf { #define DO_FLAGS_SIZE 6 +/* + * This tag defines the type of a value. + * Values are associated with regular variables and with array elements. + * Since arrays can be multidimensional (as can regular variables) + * it's valid to have a "value" that is actually an array. + */ typedef enum { AWK_UNDEFINED, AWK_NUMBER, - AWK_CONST_STRING, AWK_STRING, AWK_ARRAY } awk_valtype_t; -typedef struct { - const char *const str; - const size_t len; -} awk_const_string_t; - +/* + * A mutable string. Gawk owns the memory pointed to if it supplied + * the value. Otherwise, it takes ownership of the memory pointed to. + */ typedef struct { char *str; size_t len; } awk_string_t; +/* Arrays are represented as an opaque type */ +typedef void *awk_array_t; + +/* + * An awk value. The val_type tag indicates what + * is in the union. + */ typedef struct { awk_valtype_t val_type; union { - awk_const_string cs; - awk_string s; - double d; - void* a; + awk_string_t s; + double d; + awk_array_t a; } u; -#define const_str_val u.cs -#define str_val u.s -#define num_val u.d +#define str_value u.s +#define num_value u.d #define array_cookie u.a } awk_value_t; +/* possible kinds of function parameters */ +typedef enum { + AWK_PARAM_STRING, /* expecting a scalar string */ + AWK_PARAM_NUMBER, /* expecting a scalar number */ + AWK_PARAM_ARRAY, /* expecting an array */ +} awk_param_type_t; + +/* + * A "flattened" array element. Gawk produces an array of these. + * ALL memory pointed to belongs to gawk. Individual elements may + * be marked for deletion. New elements must be added individually, + * one at a time, using the API for that purpose. + */ +typedef struct awk_element { + /* convenience linked list pointer, not used by gawk */ + struct awk_element *next; + enum { + AWK_ELEMENT_DEFAULT = 0, /* set by gawk */ + AWK_ELEMENT_DELETE = 1 /* set by extension if + should be deleted */ + } flags; + awk_string_t index; + awk_value_t value; +} awk_element_t; + +/* + * A record describing an extension function. Upon being + * loaded, the extension should pass in one of these for + * each C function. + */ typedef struct { const char *name; - size_t num_args; - void (*function)(int num_args); + int (*function)(int num_args_actual); + size_t num_args_expected; } awk_ext_func_t; +typedef int awk_bool_t; /* we don't use on purpose */ + +typedef void *awk_ext_id_t; /* opaque type for extension id */ + +/* + * The API into gawk. Lots of functions here. We hope that they are + * logically organized. + */ typedef struct gawk_api { int major_version; int minor_version; @@ -127,46 +184,112 @@ typedef struct gawk_api { #define gawk_do_debug 4 #define gawk_do_mpfr 5 - /* get the number of arguments passed in function call */ - /* FIXME: Needed? Won't we pass the count in the real call? */ - size_t (*get_curfunc_arg_count)(void *ext_id); - awk_value_t *(*get_curfunc_param)(void *ext_id, size_t count); + /* + * 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. + */ + awk_value_t *(*get_curfunc_param)(awk_ext_id_t id, size_t count, + awk_param_type_t wanted); - /* functions to print messages */ - void (*fatal)(void *ext_id, const char *format, ...); - void (*warning)(void *ext_id, const char *format, ...); - void (*lintwarn)(void *ext_id, const char *format, ...); + /* Set the return value. Gawk takes ownership of string memory */ + void (*set_return_value)(awk_ext_id_t id, const awk_value_t *retval); - /* register an open hook; for opening files read-only */ - int (*register_open_hook)(void *ext_id, - void* (*open_func)(IOBUF *)); + /* Functions to print messages */ + void (*api_fatal)(awk_ext_id_t id, const char *format, ...); + void (*api_warning)(awk_ext_id_t id, const char *format, ...); + void (*api_lintwarn)(awk_ext_id_t id, const char *format, ...); - /* functions to update ERRNO */ - void (*update_ERRNO_int)(void *ext_id, int); - void (*update_ERRNO_string)(void *ext_id, const char *string, - int translate); - void (*unset_ERRNO)(void *ext_id); + /* Register an open hook; for opening files read-only */ + awk_bool_t (*register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF *)); - /* check if a value received from gawk is the null string */ - int (*is_null_string)(void *ext_id, void *value); + /* Functions to update ERRNO */ + void (*update_ERRNO_int)(awk_ext_id_t id, int errno_val); + void (*update_ERRNO_string)(awk_ext_id_t id, const char *string, + awk_bool_t translate); + void (*unset_ERRNO)(awk_ext_id_t id); - /* add a function to the interpreter */ - int *(add_ext_func)(void *ext_id, const awk_ext_func_t *func); + /* Add a function to the interpreter, returns true upon success */ + awk_bool_t (*add_ext_func)(awk_ext_id_t id, const awk_ext_func_t *func); - /* add an exit call back */ - void (*awk_atexit)(void *ext_id, void (*funcp)(void *data, int exit_status), void *arg0); + /* Add an exit call back, returns true upon success */ + awk_bool_t (*awk_atexit)(awk_ext_id_t id, + void (*funcp)(void *data, int exit_status), + void *arg0); + + /* + * 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. + */ + const awk_value_t *const (*sym_lookup)(awk_ext_id_t id, const char *name); - /* Symbol table access */ - awk_value_t *(*sym_lookup)(void *ext_id, const char *name); - int (*sym_update)(void *ext_id, const char *name, awk_value_t *value); - int (*sym_remove)(void *ext_id, const char *name); + /* + * Update a value. Adds it to the symbol table if not there. + * Changing types is not allowed. + */ + awk_bool_t (*sym_update)(awk_ext_id_t id, const char *name, awk_value_t *value); /* Array management */ - awk_value_t *(*get_array_element)(void *ext_id, void *a_cookie, const awk_value_t* const index); - awk_value_t *(*set_array_element)(void *ext_id, void *a_cookie, - const awk_value_t* const index, const awk_value_t* const value); - awk_value_t *(*del_array_element)(void *ext_id, void *a_cookie, const awk_value_t* const index); - size_t (*get_element_count)(void *ext_id, void *a_cookie); + /* + * Return the value of an element - read only! + * Use set_array_element to change it. + */ + const awk_value_t *const (*get_array_element)(awk_ext_id_t id, + awk_array_t a_cookie, const awk_value_t *const index); + + /* + * Change (or create) element in existing array with + * element->index and element->value. + */ + awk_bool_t (*set_array_element)(awk_ext_id_t id, awk_array_t a_cookie, + awk_element_t *element); + + /* + * Remove the element with the given index. + * Returns success if removed or if element did not exist. + */ + awk_bool_t (*del_array_element)(awk_ext_id_t id, + awk_array_t a_cookie, const awk_value_t* const index); + + /* + * Retrieve total number of elements in array. + * Returns false if some kind of error. + */ + awk_bool_t (*get_element_count)(awk_ext_id_t id, + awk_array_t a_cookie, size_t *count); + + /* Create a new array cookie to which elements may be added */ + awk_array_t (*create_array)(awk_ext_id_t id); + + /* Clear out an array */ + awk_bool_t (*clear_array)(awk_ext_id_t id, awk_array_t a_cookie); + + /* Flatten out an array so that it can be looped over easily. */ + awk_bool_t (*flatten_array)(awk_ext_id_t id, + awk_array_t a_cookie, + size_t *count, + awk_element_t **data); + + /* + * When done, release the memory, delete any marked elements + * Count must match what gawk thinks the size is. + */ + awk_bool_t (*release_flattened_array)(awk_ext_id_t id, + awk_array_t a_cookie, + size_t count, + awk_element_t *data); + + /* Constructor functions */ + awk_value_t *(*make_string)(awk_ext_id_t id, + const char *string, size_t length); + awk_value_t *(*make_number)(awk_ext_id_t id, double num); } gawk_api_t; @@ -180,13 +303,14 @@ typedef struct gawk_api { #define do_profile api->do_flags[gawk_do_profile] #define do_sandbox api->do_flags[gawk_do_sandbox] #define do_debug api->do_flags[gawk_do_debug] +#define do_mpfr api->do_flags[gawk_do_mpfr] -#define get_curfunc_arg_count api->get_curfunc_arg_count #define get_curfunc_param api->get_curfunc_param +#define set_return_value api->set_return_value -#define fatal api->fatal -#define warning api->warning -#define lintwarn api->lintwarn +#define fatal api->api_fatal +#define warning api->api_warning +#define lintwarn api->api_lintwarn #define register_open_hook api->register_open_hook @@ -201,14 +325,37 @@ typedef struct gawk_api { #define sym_lookup api->sym_lookup #define sym_update api->sym_update -#define sym_remove api->sym_remove #define get_array_element api->get_array_element #define set_array_element api->set_array_element #define del_array_element api->del_array_element #define get_element_count api->get_element_count +#define clear_array api->clear_array +#define create_array api->create_array +#define flatten_array api->flatten_array +#define release_flattened_array api->release_flattened_array + +#define make_string api->make_string +#define make_number api->make_number + +#define emalloc(pointer, type, size, message) \ + do { \ + if ((pointer = (type) malloc(size)) == 0) \ + fatal(ext_id, "malloc of %d bytes failed\n", size); \ + } while(0) + #endif /* GAWK */ +/* + * Each extension must define a function with this prototype: + * + * int dl_load(gawk_api_t *api_p, awk_ext_id_t id) + * + * For the macros to work, the function should save api_p in a + * global variable named 'api'. The return value should be zero + * on failure and non-zero on success. + */ + #ifdef __cplusplus } #endif /* C++ */ -- 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.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 6 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 2a14d334..c3ddc388 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -210,7 +210,8 @@ typedef struct gawk_api { void (*unset_ERRNO)(awk_ext_id_t id); /* Add a function to the interpreter, returns true upon success */ - awk_bool_t (*add_ext_func)(awk_ext_id_t id, const awk_ext_func_t *func); + awk_bool_t (*add_ext_func)(awk_ext_id_t id, const awk_ext_func_t *func, + const char *namespace); /* Add an exit call back, returns true upon success */ awk_bool_t (*awk_atexit)(awk_ext_id_t id, @@ -287,9 +288,9 @@ typedef struct gawk_api { awk_element_t *data); /* Constructor functions */ - awk_value_t *(*make_string)(awk_ext_id_t id, - const char *string, size_t length); - awk_value_t *(*make_number)(awk_ext_id_t id, double num); + awk_value_t *(*api_make_string)(awk_ext_id_t id, + const char *string, size_t length, awk_bool_t duplicate); + awk_value_t *(*api_make_number)(awk_ext_id_t id, double num); } gawk_api_t; @@ -335,8 +336,9 @@ typedef struct gawk_api { #define flatten_array api->flatten_array #define release_flattened_array api->release_flattened_array -#define make_string api->make_string -#define make_number api->make_number +#define make_string(id, str, len) api->api_make_string(id, str, len, 0) +#define dup_string(id, str, len) api->api_make_string(id, str, len, 1) +#define make_number api->api_make_number #define emalloc(pointer, type, size, message) \ do { \ @@ -356,6 +358,50 @@ typedef struct gawk_api { * on failure and non-zero on success. */ +extern int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id); + + +/* TODO: Turn this into a macro... */ +#if 0 +/* Boiler plate code: */ + +static gawk_api_t *const api; +static awk_ext_id_t ext_id; + +int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id); +{ + static awk_ext_func_t func_table[] = { + { "name", do_name, 1 }, + /* ... */ + }; + size_t i, j; + int errors = 0; + + if (api->major_version != GAWK_API_MAJOR_VERSION + || api->minor_version < GAWK_API_MINOR_VERSION) { + fprintf(stderr, ": version mismatch with gawk!\n"); + fprintf(stderr, "\tmy version (%d, %d), gawk version (%d, %d)\n", + GAWK_API_MAJOR_VERSION, GAWK_API_MINOR_VERSION, + api->major_version, api->minor_version); + exit(1); + } + + api = api_p; + ext_id = id; + + /* load functions */ + for (i = 0, j = sizeof(func_table) / sizeof(func_table[0]); i < j; i++) { + if (! add_ext_func(ext_id, & func_table[i], "" /* "NAME" */)) { + warning(ext_id, ": could not add %s\n", + func_table[i].name); + errors++; + } + } + + return (errors == 0); +} +#endif + #ifdef __cplusplus } #endif /* C++ */ -- 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.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index c3ddc388..335e9628 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -201,7 +201,7 @@ typedef struct gawk_api { void (*api_lintwarn)(awk_ext_id_t id, const char *format, ...); /* Register an open hook; for opening files read-only */ - awk_bool_t (*register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF *)); + void (*register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF *)); /* Functions to update ERRNO */ void (*update_ERRNO_int)(awk_ext_id_t id, int errno_val); -- 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.h | 140 +++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 84 insertions(+), 56 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 335e9628..76c10260 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -228,6 +228,15 @@ typedef struct gawk_api { /* * Lookup a variable, return its value. No messing with the value * returned. Return value is NULL if the variable doesn't exist. + * + * Returns a pointer to a static variable. Correct usage is thus: + * + * awk_value_t val, *vp; + * vp = api->sym_lookup(id, name); + * if (vp == NULL) + * error_code(); + * val = *vp; + * // use val from here on */ const awk_value_t *const (*sym_lookup)(awk_ext_id_t id, const char *name); @@ -241,6 +250,9 @@ typedef struct gawk_api { /* * Return the value of an element - read only! * Use set_array_element to change it. + * + * As for sym_lookup(), this also returns a static pointer whose + * value should be copied before use. */ const awk_value_t *const (*get_array_element)(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t *const index); @@ -306,39 +318,55 @@ typedef struct gawk_api { #define do_debug api->do_flags[gawk_do_debug] #define do_mpfr api->do_flags[gawk_do_mpfr] -#define get_curfunc_param api->get_curfunc_param -#define set_return_value api->set_return_value +#define get_curfunc_param(count, wanted) \ + api->get_curfunc_param(ext_id, count, wanted) + +#define set_return_value(retval) \ + api->set_return_value(ext_id, retval) #define fatal api->api_fatal #define warning api->api_warning #define lintwarn api->api_lintwarn -#define register_open_hook api->register_open_hook +#define register_open_hook(func) api->register_open_hook(ext_id, func) -#define update_ERRNO_int api->update_ERRNO_int -#define update_ERRNO_string api->update_ERRNO_string +#define update_ERRNO_int(e) api->update_ERRNO_int(ext_id, e) +#define update_ERRNO_string(str, translate) \ + api->update_ERRNO_string(ext_id, str, translate) #define unset_ERRNO api->unset_ERRNO -#define is_null_string api->is_null_string +#define add_ext_func(func, ns) api->add_ext_func(ext_id, func, ns) +#define awk_atexit(funcp, arg0) api->awk_atexit(ext_id, funcp, arg0) + +#define sym_lookup(name) api->sym_lookup(ext_id, name) +#define sym_update(name, value) \ + api->sym_update(ext_id, name, value) + +#define get_array_element(array, element) \ + api->get_array_element(ext_id, array, element) + +#define set_array_element(array, element) \ + api->set_array_element(ext_id, array, element) + +#define del_array_element(array, index) \ + api->del_array_element(ext_id, array, index) + +#define get_element_count(array, count_p) \ + api->get_element_count(ext_id, array, count_p) -#define add_ext_func api->add_ext_func -#define awk_atexit api->awk_atexit +#define create_array() api->create_array(ext_id) -#define sym_lookup api->sym_lookup -#define sym_update api->sym_update +#define clear_array(array) api->clear_array(ext_id, array) -#define get_array_element api->get_array_element -#define set_array_element api->set_array_element -#define del_array_element api->del_array_element -#define get_element_count api->get_element_count -#define clear_array api->clear_array -#define create_array api->create_array -#define flatten_array api->flatten_array -#define release_flattened_array api->release_flattened_array +#define flatten_array(array, count, data) \ + api->flatten_array(ext_id, array, count, data) -#define make_string(id, str, len) api->api_make_string(id, str, len, 0) -#define dup_string(id, str, len) api->api_make_string(id, str, len, 1) -#define make_number api->api_make_number +#define release_flattened_array(array, count, data) \ + api->release_flattened_array(ext_id, array, count, data) + +#define make_string(str, len) api->api_make_string(ext_id, str, len, 0) +#define dup_string(str, len) api->api_make_string(ext_id, str, len, 1) +#define make_number(num) api->api_make_number(ext_id, num) #define emalloc(pointer, type, size, message) \ do { \ @@ -360,48 +388,48 @@ typedef struct gawk_api { extern int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id); - -/* TODO: Turn this into a macro... */ #if 0 /* Boiler plate code: */ - static gawk_api_t *const api; static awk_ext_id_t ext_id; +static awk_ext_func_t func_table[] = { + { "name", do_name, 1 }, + /* ... */ +}; -int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id); -{ - static awk_ext_func_t func_table[] = { - { "name", do_name, 1 }, - /* ... */ - }; - size_t i, j; - int errors = 0; - - if (api->major_version != GAWK_API_MAJOR_VERSION - || api->minor_version < GAWK_API_MINOR_VERSION) { - fprintf(stderr, ": version mismatch with gawk!\n"); - fprintf(stderr, "\tmy version (%d, %d), gawk version (%d, %d)\n", - GAWK_API_MAJOR_VERSION, GAWK_API_MINOR_VERSION, - api->major_version, api->minor_version); - exit(1); - } - - api = api_p; - ext_id = id; - - /* load functions */ - for (i = 0, j = sizeof(func_table) / sizeof(func_table[0]); i < j; i++) { - if (! add_ext_func(ext_id, & func_table[i], "" /* "NAME" */)) { - warning(ext_id, ": could not add %s\n", - func_table[i].name); - errors++; - } - } - - return (errors == 0); -} +dl_load_func(api, ext_id, func_table, some_name, "name_space_in_quotes") #endif +#define dl_load_func(global_api_p, global_ext_id, func_table, module, name_space) \ +int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) \ +{ \ + size_t i, j; \ + int errors = 0; \ + \ + if (api->major_version != GAWK_API_MAJOR_VERSION \ + || api->minor_version < GAWK_API_MINOR_VERSION) { \ + fprintf(stderr, #module ": version mismatch with gawk!\n"); \ + fprintf(stderr, "\tmy version (%d, %d), gawk version (%d, %d)\n", \ + GAWK_API_MAJOR_VERSION, GAWK_API_MINOR_VERSION, \ + api->major_version, api->minor_version); \ + exit(1); \ + } \ + \ + global_api_p = api_p; \ + global_ext_id = id; \ +\ + /* load functions */ \ + for (i = 0, j = sizeof(func_table) / sizeof(func_table[0]); i < j; i++) { \ + if (! add_ext_func(& func_table[i], name_space)) { \ + warning(ext_id, #module ": could not add %s\n", \ + func_table[i].name); \ + errors++; \ + } \ + } \ +\ + return (errors == 0); \ +} + #ifdef __cplusplus } #endif /* C++ */ -- 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.h | 108 ++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 60 insertions(+), 48 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 76c10260..3b52bff1 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -126,13 +126,6 @@ typedef struct { #define array_cookie u.a } awk_value_t; -/* possible kinds of function parameters */ -typedef enum { - AWK_PARAM_STRING, /* expecting a scalar string */ - AWK_PARAM_NUMBER, /* expecting a scalar number */ - AWK_PARAM_ARRAY, /* expecting an array */ -} awk_param_type_t; - /* * A "flattened" array element. Gawk produces an array of these. * ALL memory pointed to belongs to gawk. Individual elements may @@ -159,7 +152,7 @@ typedef struct awk_element { */ typedef struct { const char *name; - int (*function)(int num_args_actual); + awk_value_t *(*function)(int num_args_actual, awk_value_t *result); size_t num_args_expected; } awk_ext_func_t; @@ -190,10 +183,8 @@ typedef struct gawk_api { * does not match what is specified in wanted. */ awk_value_t *(*get_curfunc_param)(awk_ext_id_t id, size_t count, - awk_param_type_t wanted); - - /* Set the return value. Gawk takes ownership of string memory */ - void (*set_return_value)(awk_ext_id_t id, const awk_value_t *retval); + awk_valtype_t wanted, + awk_value_t *result); /* Functions to print messages */ void (*api_fatal)(awk_ext_id_t id, const char *format, ...); @@ -231,14 +222,14 @@ typedef struct gawk_api { * * Returns a pointer to a static variable. Correct usage is thus: * - * awk_value_t val, *vp; - * vp = api->sym_lookup(id, name); - * if (vp == NULL) + * awk_value_t val; + * if (api->sym_lookup(id, name, &val) == NULL) * error_code(); - * val = *vp; - * // use val from here on + * else { + * // safe to use val + * } */ - const awk_value_t *const (*sym_lookup)(awk_ext_id_t id, const char *name); + awk_value_t *(*sym_lookup)(awk_ext_id_t id, const char *name, awk_value_t *result); /* * Update a value. Adds it to the symbol table if not there. @@ -250,12 +241,10 @@ typedef struct gawk_api { /* * Return the value of an element - read only! * Use set_array_element to change it. - * - * As for sym_lookup(), this also returns a static pointer whose - * value should be copied before use. */ - const awk_value_t *const (*get_array_element)(awk_ext_id_t id, - awk_array_t a_cookie, const awk_value_t *const index); + awk_value_t *(*get_array_element)(awk_ext_id_t id, + awk_array_t a_cookie, const awk_value_t *const index, + awk_value_t *result); /* * Change (or create) element in existing array with @@ -298,12 +287,6 @@ typedef struct gawk_api { awk_array_t a_cookie, size_t count, awk_element_t *data); - - /* Constructor functions */ - awk_value_t *(*api_make_string)(awk_ext_id_t id, - const char *string, size_t length, awk_bool_t duplicate); - awk_value_t *(*api_make_number)(awk_ext_id_t id, double num); - } gawk_api_t; #ifndef GAWK /* these are not for the gawk code itself */ @@ -318,11 +301,8 @@ typedef struct gawk_api { #define do_debug api->do_flags[gawk_do_debug] #define do_mpfr api->do_flags[gawk_do_mpfr] -#define get_curfunc_param(count, wanted) \ - api->get_curfunc_param(ext_id, count, wanted) - -#define set_return_value(retval) \ - api->set_return_value(ext_id, retval) +#define get_curfunc_param(count, wanted, result) \ + api->get_curfunc_param(ext_id, count, wanted, result) #define fatal api->api_fatal #define warning api->api_warning @@ -338,12 +318,12 @@ typedef struct gawk_api { #define add_ext_func(func, ns) api->add_ext_func(ext_id, func, ns) #define awk_atexit(funcp, arg0) api->awk_atexit(ext_id, funcp, arg0) -#define sym_lookup(name) api->sym_lookup(ext_id, name) +#define sym_lookup(name, result) api->sym_lookup(ext_id, name, result) #define sym_update(name, value) \ api->sym_update(ext_id, name, value) -#define get_array_element(array, element) \ - api->get_array_element(ext_id, array, element) +#define get_array_element(array, element, result) \ + api->get_array_element(ext_id, array, element, result) #define set_array_element(array, element) \ api->set_array_element(ext_id, array, element) @@ -364,17 +344,47 @@ typedef struct gawk_api { #define release_flattened_array(array, count, data) \ api->release_flattened_array(ext_id, array, count, data) -#define make_string(str, len) api->api_make_string(ext_id, str, len, 0) -#define dup_string(str, len) api->api_make_string(ext_id, str, len, 1) -#define make_number(num) api->api_make_number(ext_id, num) - #define emalloc(pointer, type, size, message) \ do { \ if ((pointer = (type) malloc(size)) == 0) \ fatal(ext_id, "malloc of %d bytes failed\n", size); \ } while(0) -#endif /* GAWK */ +/* Constructor functions */ +static inline awk_value_t * +r_make_string(const gawk_api_t *api, + awk_ext_id_t *ext_id, + const char *string, + size_t length, + awk_bool_t duplicate, + awk_value_t *result) +{ + char *cp = NULL; + + result->val_type = AWK_STRING; + result->str_value.len = length; + + if (duplicate) { + emalloc(cp, char *, length + 2, "make_string"); + memcpy(cp, string, length); + cp[length] = '\0'; + result->str_value.str = cp; + } else { + result->str_value.str = (char *) string; + } + return result; +} + +#define make_string(str, len, result) r_make_string(api, ext_id, str, len, 0, result) +#define dup_string(str, len, result) r_make_string(api, ext_id, str, len, 1, result) + +static inline awk_value_t * +make_number(double num, awk_value_t *result) +{ + result->val_type = AWK_NUMBER; + result->num_value = num; + return result; +} /* * Each extension must define a function with this prototype: @@ -397,15 +407,18 @@ static awk_ext_func_t func_table[] = { /* ... */ }; -dl_load_func(api, ext_id, func_table, some_name, "name_space_in_quotes") +dl_load_func(func_table, some_name, "name_space_in_quotes") #endif -#define dl_load_func(global_api_p, global_ext_id, func_table, module, name_space) \ +#define dl_load_func(func_table, module, name_space) \ int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) \ { \ size_t i, j; \ int errors = 0; \ - \ +\ + api = api_p; \ + ext_id = id; \ +\ if (api->major_version != GAWK_API_MAJOR_VERSION \ || api->minor_version < GAWK_API_MINOR_VERSION) { \ fprintf(stderr, #module ": version mismatch with gawk!\n"); \ @@ -414,9 +427,6 @@ int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) \ api->major_version, api->minor_version); \ exit(1); \ } \ - \ - global_api_p = api_p; \ - global_ext_id = id; \ \ /* load functions */ \ for (i = 0, j = sizeof(func_table) / sizeof(func_table[0]); i < j; i++) { \ @@ -430,6 +440,8 @@ int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) \ return (errors == 0); \ } +#endif /* GAWK */ + #ifdef __cplusplus } #endif /* C++ */ -- 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.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 3b52bff1..54122cab 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -149,6 +149,11 @@ typedef struct awk_element { * A record describing an extension function. Upon being * loaded, the extension should pass in one of these for * each C function. + * + * Each called function must fill in the result with eiher a number + * or string. Gawk takes ownership of any string memory. + * + * The called function should return the value of `result'. */ typedef struct { const char *name; -- 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.h | 119 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 69 insertions(+), 50 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 54122cab..5fd2ebe1 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -34,10 +34,14 @@ /* * General introduction: * - * This API purposely restricts itself to C90 features. - * In paticular, no bool, no // comments, no use of the - * restrict keyword, or anything else, in order to provide - * maximal portability. + * This API purposely restricts itself to C90 features. In paticular, no + * bool, no // comments, no use of the restrict keyword, or anything else, + * in order to provide maximal portability. + * + * Exception: the "inline" keyword is used below in the "constructor" + * functions. If your compiler doesn't support it, you should either + * -Dinline='' on your command line, or use the autotools and include a + * config.h in your extensions. */ /* Allow use in C++ code. */ @@ -107,30 +111,27 @@ typedef struct { size_t len; } awk_string_t; -/* Arrays are represented as an opaque type */ +/* Arrays are represented as an opaque type. */ typedef void *awk_array_t; /* * An awk value. The val_type tag indicates what - * is in the union. + * is contained. For scalars, gawk fills in both kinds + * of values and val_type indicates the assigned type. + * For arrays, the scalar types will be set to zero. */ typedef struct { awk_valtype_t val_type; - union { - awk_string_t s; - double d; - awk_array_t a; - } u; -#define str_value u.s -#define num_value u.d -#define array_cookie u.a + awk_string_t str_value; + double num_value; + awk_array_t array_cookie; } awk_value_t; /* * A "flattened" array element. Gawk produces an array of these. * ALL memory pointed to belongs to gawk. Individual elements may * be marked for deletion. New elements must be added individually, - * one at a time, using the API for that purpose. + * one at a time, using the separate API for that purpose. */ typedef struct awk_element { @@ -154,6 +155,11 @@ typedef struct awk_element { * or string. Gawk takes ownership of any string memory. * * The called function should return the value of `result'. + * This is for the convenience of the calling code inside gawk. + * + * Each extension function may decide what to do if the number of + * arguments isn't what it expected. Following awk functions, it + * is likely OK to ignore extra arguments. */ typedef struct { const char *name; @@ -228,13 +234,14 @@ typedef struct gawk_api { * Returns a pointer to a static variable. Correct usage is thus: * * awk_value_t val; - * if (api->sym_lookup(id, name, &val) == NULL) + * if (api->sym_lookup(id, name, &val, wanted) == NULL) * error_code(); * else { * // safe to use val * } */ - awk_value_t *(*sym_lookup)(awk_ext_id_t id, const char *name, awk_value_t *result); + awk_value_t *(*sym_lookup)(awk_ext_id_t id, const char *name, awk_value_t *result, + awk_valtype_t wanted); /* * Update a value. Adds it to the symbol table if not there. @@ -245,11 +252,11 @@ typedef struct gawk_api { /* Array management */ /* * Return the value of an element - read only! - * Use set_array_element to change it. + * Use set_array_element() to change it. */ awk_value_t *(*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); /* * Change (or create) element in existing array with @@ -285,8 +292,9 @@ typedef struct gawk_api { awk_element_t **data); /* - * When done, release the memory, delete any marked elements + * When done, delete any marked elements, release the memory. * Count must match what gawk thinks the size is. + * Otherwise it's a fatal error. */ awk_bool_t (*release_flattened_array)(awk_ext_id_t id, awk_array_t a_cookie, @@ -294,60 +302,60 @@ typedef struct gawk_api { awk_element_t *data); } gawk_api_t; -#ifndef GAWK /* these are not for the gawk code itself */ +#ifndef GAWK /* these are not for the gawk code itself! */ /* - * Use these if you want to define a "global" variable named api - * to make the code a little easier to read. + * Use these if you want to define "global" variables named api + * and ext_id to make the code a little easier to read. */ -#define do_lint api->do_flags[gawk_do_lint] -#define do_traditional api->do_flags[gawk_do_traditional] -#define do_profile api->do_flags[gawk_do_profile] -#define do_sandbox api->do_flags[gawk_do_sandbox] -#define do_debug api->do_flags[gawk_do_debug] -#define do_mpfr api->do_flags[gawk_do_mpfr] +#define do_lint (api->do_flags[gawk_do_lint]) +#define do_traditional (api->do_flags[gawk_do_traditional]) +#define do_profile (api->do_flags[gawk_do_profile]) +#define do_sandbox (api->do_flags[gawk_do_sandbox]) +#define do_debug (api->do_flags[gawk_do_debug]) +#define do_mpfr (api->do_flags[gawk_do_mpfr]) #define get_curfunc_param(count, wanted, result) \ - api->get_curfunc_param(ext_id, count, wanted, result) + (api->get_curfunc_param(ext_id, count, wanted, result)) #define fatal api->api_fatal #define warning api->api_warning #define lintwarn api->api_lintwarn -#define register_open_hook(func) api->register_open_hook(ext_id, func) +#define register_open_hook(func) (api->register_open_hook(ext_id, func)) -#define update_ERRNO_int(e) api->update_ERRNO_int(ext_id, e) +#define update_ERRNO_int(e) (api->update_ERRNO_int(ext_id, e)) #define update_ERRNO_string(str, translate) \ - api->update_ERRNO_string(ext_id, str, translate) -#define unset_ERRNO api->unset_ERRNO + (api->update_ERRNO_string(ext_id, str, translate)) +#define unset_ERRNO() (api->unset_ERRNO(ext_id)) -#define add_ext_func(func, ns) api->add_ext_func(ext_id, func, ns) -#define awk_atexit(funcp, arg0) api->awk_atexit(ext_id, funcp, arg0) +#define add_ext_func(func, ns) (api->add_ext_func(ext_id, func, ns)) +#define awk_atexit(funcp, arg0) (api->awk_atexit(ext_id, funcp, arg0)) -#define sym_lookup(name, result) api->sym_lookup(ext_id, name, result) +#define sym_lookup(name, result, wanted) (api->sym_lookup(ext_id, name, result, wanted)) #define sym_update(name, value) \ - api->sym_update(ext_id, name, value) + (api->sym_update(ext_id, name, value)) -#define get_array_element(array, element, result) \ - api->get_array_element(ext_id, array, element, result) +#define get_array_element(array, element, result, wanted) \ + (api->get_array_element(ext_id, array, element, result, wanted)) #define set_array_element(array, element) \ - api->set_array_element(ext_id, array, element) + (api->set_array_element(ext_id, array, element)) #define del_array_element(array, index) \ - api->del_array_element(ext_id, array, index) + (api->del_array_element(ext_id, array, index)) #define get_element_count(array, count_p) \ - api->get_element_count(ext_id, array, count_p) + (api->get_element_count(ext_id, array, count_p)) -#define create_array() api->create_array(ext_id) +#define create_array() (api->create_array(ext_id)) -#define clear_array(array) api->clear_array(ext_id, array) +#define clear_array(array) (api->clear_array(ext_id, array)) #define flatten_array(array, count, data) \ - api->flatten_array(ext_id, array, count, data) + (api->flatten_array(ext_id, array, count, data)) #define release_flattened_array(array, count, data) \ - api->release_flattened_array(ext_id, array, count, data) + (api->release_flattened_array(ext_id, array, count, data)) #define emalloc(pointer, type, size, message) \ do { \ @@ -356,6 +364,9 @@ typedef struct gawk_api { } while(0) /* Constructor functions */ + +/* r_make_string --- make a string value in result from the passed-in string */ + static inline awk_value_t * r_make_string(const gawk_api_t *api, awk_ext_id_t *ext_id, @@ -366,6 +377,8 @@ r_make_string(const gawk_api_t *api, { char *cp = NULL; + memset(result, 0, sizeof(*result)); + result->val_type = AWK_STRING; result->str_value.len = length; @@ -377,17 +390,23 @@ r_make_string(const gawk_api_t *api, } else { result->str_value.str = (char *) string; } + return result; } #define make_string(str, len, result) r_make_string(api, ext_id, str, len, 0, result) #define dup_string(str, len, result) r_make_string(api, ext_id, str, len, 1, result) +/* make_number --- make a number value in result */ + static inline awk_value_t * make_number(double num, awk_value_t *result) { + memset(result, 0, sizeof(*result)); + result->val_type = AWK_NUMBER; result->num_value = num; + return result; } @@ -396,9 +415,9 @@ make_number(double num, awk_value_t *result) * * int dl_load(gawk_api_t *api_p, awk_ext_id_t id) * - * For the macros to work, the function should save api_p in a - * global variable named 'api'. The return value should be zero - * on failure and non-zero on success. + * For the macros to work, the function should save api_p in a global + * variable named 'api' and save id in a global variable named 'ext_id'. + * The return value should be zero on failure and non-zero on success. */ extern int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id); -- 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.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 5fd2ebe1..87d2d2f0 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -245,7 +245,9 @@ typedef struct gawk_api { /* * Update a value. Adds it to the symbol table if not there. - * Changing types is not allowed. + * Changing types (scalar <--> array) is not allowed. + * In fact, using this to update an array is not allowed, either. + * Such an attempt returns false. */ awk_bool_t (*sym_update)(awk_ext_id_t id, const char *name, awk_value_t *value); -- 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.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 87d2d2f0..09a1ce79 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -179,6 +179,11 @@ typedef struct gawk_api { int major_version; int minor_version; + /* + * These can change on the fly as things happen within gawk. + * Currently only do_lint is prone to change, but we reserve + * the right to allow the others also. + */ int do_flags[DO_FLAGS_SIZE]; /* Use these as indices into do_flags[] array to check the values */ #define gawk_do_lint 0 -- 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.h | 68 +++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 21 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 09a1ce79..7e6a66fc 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -116,15 +116,18 @@ typedef void *awk_array_t; /* * An awk value. The val_type tag indicates what - * is contained. For scalars, gawk fills in both kinds - * of values and val_type indicates the assigned type. - * For arrays, the scalar types will be set to zero. + * is in the union. */ typedef struct { awk_valtype_t val_type; - awk_string_t str_value; - double num_value; - awk_array_t array_cookie; + union { + awk_string_t s; + double d; + awk_array_t a; + } u; +#define str_value u.s +#define num_value u.d +#define array_cookie u.a } awk_value_t; /* @@ -195,10 +198,27 @@ typedef struct gawk_api { /* * 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 that case, + * result->val_type will hold the actual type of what was passed. + + Table entry is type returned: + + +-----------------------------------------+ + | Type Requested: | + +----------+----------+-------+-----------+ + | String | Number | Array | Undefined | + +---------+-----------+----------+----------+-------+-----------+ + | Type | String | String | false | false | String | + | of +-----------+----------+----------+-------+-----------+ + | Actual | Number | false | Number | false | Number | + | Value: +-----------+----------+----------+-------+-----------+ + | | Array | false | false | Array | Array | + | +-----------+----------+----------+-------+-----------+ + | | Undefined | false | false | false | Undefined | + +---------+-----------+----------+----------+-------+-----------+ */ - awk_value_t *(*get_curfunc_param)(awk_ext_id_t id, size_t count, + awk_bool_t (*get_argument)(awk_ext_id_t id, size_t count, awk_valtype_t wanted, awk_value_t *result); @@ -221,7 +241,7 @@ typedef struct gawk_api { const char *namespace); /* Add an exit call back, returns true upon success */ - awk_bool_t (*awk_atexit)(awk_ext_id_t id, + void (*awk_atexit)(awk_ext_id_t id, void (*funcp)(void *data, int exit_status), void *arg0); @@ -233,20 +253,23 @@ typedef struct gawk_api { * 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. - * - * Returns a pointer to a static variable. Correct usage is thus: + * 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. * * awk_value_t val; - * if (api->sym_lookup(id, name, &val, wanted) == NULL) + * if (! api->sym_lookup(id, name, wanted, & val)) * error_code(); * else { * // safe to use val * } */ - awk_value_t *(*sym_lookup)(awk_ext_id_t id, const char *name, awk_value_t *result, - awk_valtype_t wanted); + awk_bool_t (*sym_lookup)(awk_ext_id_t id, + const char *name, + awk_valtype_t wanted, + awk_value_t *result); /* * Update a value. Adds it to the symbol table if not there. @@ -260,10 +283,13 @@ typedef struct gawk_api { /* * Return the value of an element - read only! * Use set_array_element() to change it. + * Behavior for value and return is same as for get_argument + * and sym_lookup. */ - awk_value_t *(*get_array_element)(awk_ext_id_t id, + awk_bool_t (*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); /* * Change (or create) element in existing array with @@ -321,8 +347,8 @@ typedef struct gawk_api { #define do_debug (api->do_flags[gawk_do_debug]) #define do_mpfr (api->do_flags[gawk_do_mpfr]) -#define get_curfunc_param(count, wanted, result) \ - (api->get_curfunc_param(ext_id, count, wanted, result)) +#define get_argument(count, wanted, result) \ + (api->get_argument(ext_id, count, wanted, result)) #define fatal api->api_fatal #define warning api->api_warning -- 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.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 7e6a66fc..ca06cea3 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -287,8 +287,8 @@ typedef struct gawk_api { * and sym_lookup. */ awk_bool_t (*get_array_element)(awk_ext_id_t id, - awk_array_t a_cookie, const awk_value_t *const index, - awk_valtype_t wanted, + awk_array_t a_cookie, + const awk_value_t *const index, awk_value_t *result); /* @@ -364,12 +364,12 @@ typedef struct gawk_api { #define add_ext_func(func, ns) (api->add_ext_func(ext_id, func, ns)) #define awk_atexit(funcp, arg0) (api->awk_atexit(ext_id, funcp, arg0)) -#define sym_lookup(name, result, wanted) (api->sym_lookup(ext_id, name, result, wanted)) +#define sym_lookup(name, wanted, result) (api->sym_lookup(ext_id, name, wanted, result)) #define sym_update(name, value) \ (api->sym_update(ext_id, name, value)) -#define get_array_element(array, element, result, wanted) \ - (api->get_array_element(ext_id, array, element, result, wanted)) +#define get_array_element(array, index, result) \ + (api->get_array_element(ext_id, array, index, result)) #define set_array_element(array, element) \ (api->set_array_element(ext_id, array, element)) @@ -401,8 +401,8 @@ typedef struct gawk_api { /* r_make_string --- make a string value in result from the passed-in string */ static inline awk_value_t * -r_make_string(const gawk_api_t *api, - awk_ext_id_t *ext_id, +r_make_string(const gawk_api_t *api, /* needed for emalloc */ + awk_ext_id_t *ext_id, /* ditto */ const char *string, size_t length, awk_bool_t duplicate, -- 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.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index ca06cea3..7fdd7634 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -289,6 +289,7 @@ typedef struct gawk_api { awk_bool_t (*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); /* @@ -368,8 +369,8 @@ typedef struct gawk_api { #define sym_update(name, value) \ (api->sym_update(ext_id, name, value)) -#define get_array_element(array, index, result) \ - (api->get_array_element(ext_id, array, index, result)) +#define get_array_element(array, index, wanted, result) \ + (api->get_array_element(ext_id, array, index, wanted, result)) #define set_array_element(array, element) \ (api->set_array_element(ext_id, array, element)) -- 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.h | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 7fdd7634..8102f70e 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -145,10 +145,23 @@ typedef struct awk_element { AWK_ELEMENT_DELETE = 1 /* set by extension if should be deleted */ } flags; - awk_string_t index; + awk_value_t index; awk_value_t value; } awk_element_t; +#ifdef GAWK +#define awk_const +#else +#define awk_const const +#endif + +typedef struct awk_flat_array { + void *opaque1; /* private data for use by gawk */ + void *opaque2; /* private data for use by gawk */ + awk_const size_t count; /* how many elements */ + awk_element_t elements[1]; /* will be extended */ +} awk_flat_array_t; + /* * A record describing an extension function. Upon being * loaded, the extension should pass in one of these for @@ -222,6 +235,11 @@ typedef struct gawk_api { awk_valtype_t wanted, awk_value_t *result); + /* + * FIXME: Missing update_argument to convert an undefined + * argument into an array or scalar. + */ + /* Functions to print messages */ void (*api_fatal)(awk_ext_id_t id, const char *format, ...); void (*api_warning)(awk_ext_id_t id, const char *format, ...); @@ -257,7 +275,8 @@ typedef struct gawk_api { * 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. + * Built-in variables (except PROCINFO) may not be accessed by an + * extension. * * awk_value_t val; * if (! api->sym_lookup(id, name, wanted, & val)) @@ -322,8 +341,7 @@ typedef struct gawk_api { /* Flatten out an array so that it can be looped over easily. */ awk_bool_t (*flatten_array)(awk_ext_id_t id, awk_array_t a_cookie, - size_t *count, - awk_element_t **data); + awk_flat_array_t **data); /* * When done, delete any marked elements, release the memory. @@ -332,8 +350,7 @@ typedef struct gawk_api { */ awk_bool_t (*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); } gawk_api_t; #ifndef GAWK /* these are not for the gawk code itself! */ @@ -385,11 +402,11 @@ typedef struct gawk_api { #define clear_array(array) (api->clear_array(ext_id, array)) -#define flatten_array(array, count, data) \ - (api->flatten_array(ext_id, array, count, data)) +#define flatten_array(array, data) \ + (api->flatten_array(ext_id, array, data)) -#define release_flattened_array(array, count, data) \ - (api->release_flattened_array(ext_id, array, count, data)) +#define release_flattened_array(array, data) \ + (api->release_flattened_array(ext_id, array, data)) #define emalloc(pointer, type, size, message) \ do { \ -- 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.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 8102f70e..7973d7a8 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -131,7 +131,8 @@ typedef struct { } awk_value_t; /* - * A "flattened" array element. Gawk produces an array of these. + * A "flattened" array element. Gawk produces an array of these + * inside the awk_flattened_array_t. * ALL memory pointed to belongs to gawk. Individual elements may * be marked for deletion. New elements must be added individually, * one at a time, using the separate API for that purpose. @@ -149,15 +150,20 @@ typedef struct awk_element { awk_value_t value; } awk_element_t; +/* This is used to keep the extension from modifying certain fields. */ #ifdef GAWK #define awk_const #else #define awk_const const #endif +/* + * A "flattened" array. See the description above for how + * to use the elements contained herein. + */ typedef struct awk_flat_array { - void *opaque1; /* private data for use by gawk */ - void *opaque2; /* private data for use by gawk */ + awk_const void *opaque1; /* private data for use by gawk */ + awk_const void *opaque2; /* private data for use by gawk */ awk_const size_t count; /* how many elements */ awk_element_t elements[1]; /* will be extended */ } awk_flat_array_t; -- 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.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 7973d7a8..3325c454 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -242,9 +242,14 @@ typedef struct gawk_api { awk_value_t *result); /* - * FIXME: Missing update_argument to convert an undefined - * argument into an array or scalar. + * Convert a paramter that was undefined into an array + * (provide call-by-reference for arrays). Returns false + * if count is too big, or if the argument's type is + * not undefined. */ + awk_bool_t (*set_argument)(awk_ext_id_t id, + size_t count, + awk_array_t array); /* Functions to print messages */ void (*api_fatal)(awk_ext_id_t id, const char *format, ...); @@ -373,6 +378,8 @@ typedef struct gawk_api { #define get_argument(count, wanted, result) \ (api->get_argument(ext_id, count, wanted, result)) +#define set_argument(count, new_array) \ + (api->set_argument(ext_id, count, new_array)) #define fatal api->api_fatal #define warning api->api_warning -- 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.h | 44 +++++++++----------------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 3325c454..1954a5e4 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -49,40 +49,14 @@ extern "C" { #endif -/* struct used for reading records and managing buffers */ -typedef struct iobuf { - const char *name; /* filename */ - int fd; /* file descriptor */ - struct stat sbuf; /* stat buf */ - char *buf; /* start data buffer */ - char *off; /* start of current record in buffer */ - char *dataend; /* first byte in buffer to hold new data, - NULL if not read yet */ - char *end; /* end of buffer */ - size_t readsize; /* set from fstat call */ - size_t size; /* buffer size */ - ssize_t count; /* amount read last time */ - size_t scanoff; /* where we were in the buffer when we had - to regrow/refill */ - /* - * No argument prototype on read_func. See get_src_buf() - * in awkgram.y. - */ - ssize_t (*read_func)(); - - void *opaque; /* private data for open hooks */ - int (*get_record)(char **out, struct iobuf *, int *errcode); - void (*close_func)(struct iobuf *); /* open and close hooks */ - - int errcode; - - int flag; -# define IOP_IS_TTY 1 -# define IOP_NOFREE_OBJ 2 -# define IOP_AT_EOF 4 -# define IOP_CLOSED 8 -# define IOP_AT_START 16 -} IOBUF; +/* portions of IOBUF that should be accessible to extension functions: */ +typedef struct iobuf_public { + const char *name; /* filename */ + int fd; /* file descriptor */ + void *opaque; /* private data for open hooks */ + int (*get_record)(char **out, struct iobuf_public *, int *errcode); + void (*close_func)(struct iobuf_public *); +} IOBUF_PUBLIC; #define GAWK_API_MAJOR_VERSION 0 #define GAWK_API_MINOR_VERSION 0 @@ -257,7 +231,7 @@ typedef struct gawk_api { void (*api_lintwarn)(awk_ext_id_t id, const char *format, ...); /* Register an open hook; for opening files read-only */ - void (*register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF *)); + void (*register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF_PUBLIC *)); /* Functions to update ERRNO */ void (*update_ERRNO_int)(awk_ext_id_t id, int errno_val); -- cgit v1.2.3 From 33734338e34ed4588ca05cecd5324d5ab5a1a654 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 29 Jun 2012 12:55:37 +0300 Subject: Minor improvements in doc and in ordchr.c. --- gawkapi.h | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 1954a5e4..10f1e0c3 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -190,7 +190,10 @@ typedef struct gawk_api { #define gawk_do_mpfr 5 /* - * Get the count'th paramater, zero-based. + * All of the functions that return a value from inside gawk + * (get a parameter, get a global variable, get an array element) + * behave in the same way. + * * Returns false if count is out of range, or if actual paramater * does not match what is specified in wanted. In that case, * result->val_type will hold the actual type of what was passed. @@ -202,14 +205,25 @@ typedef struct gawk_api { +----------+----------+-------+-----------+ | String | Number | Array | Undefined | +---------+-----------+----------+----------+-------+-----------+ - | Type | String | String | false | false | String | + | Type | String | String | Number if| false | String | + | | | | it can be| | | + | | | |converted,| | | + | | | | else | | | + | | | | false | | | | of +-----------+----------+----------+-------+-----------+ - | Actual | Number | false | Number | false | Number | + | Actual | Number | String | Number | false | Number | | Value: +-----------+----------+----------+-------+-----------+ | | Array | false | false | Array | Array | | +-----------+----------+----------+-------+-----------+ | | Undefined | false | false | false | Undefined | +---------+-----------+----------+----------+-------+-----------+ + */ + + /* + * 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 that case, + * result->val_type is as described above. */ awk_bool_t (*get_argument)(awk_ext_id_t id, size_t count, awk_valtype_t wanted, @@ -258,8 +272,9 @@ typedef struct gawk_api { /* * 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. + * or if the wrong type was requested. + * In the latter case, fills in vaule->val_type with the real type, + * as described above. * Built-in variables (except PROCINFO) may not be accessed by an * extension. * -- 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.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 10f1e0c3..5be5ea08 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -316,7 +316,8 @@ typedef struct gawk_api { * element->index and element->value. */ awk_bool_t (*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); /* * Remove the element with the given index. @@ -391,8 +392,11 @@ typedef struct gawk_api { #define get_array_element(array, index, wanted, result) \ (api->get_array_element(ext_id, array, index, wanted, result)) -#define set_array_element(array, element) \ - (api->set_array_element(ext_id, array, element)) +#define set_array_element(array, index, value) \ + (api->set_array_element(ext_id, array, index, value)) + +#define set_array_element_by_elem(array, elem) \ + (set_array_element(array, & (elem)->index, & (elem)->value)) #define del_array_element(array, index) \ (api->del_array_element(ext_id, array, index)) -- 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.h | 179 +++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 59 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 5be5ea08..2bef258e 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -42,6 +42,26 @@ * functions. If your compiler doesn't support it, you should either * -Dinline='' on your command line, or use the autotools and include a * config.h in your extensions. + * + * Additional important information: + * + * 1. ALL string values in awk_value_t objects need to come from malloc(). + * Gawk will handle releasing the storage if necessary. This is slightly + * awkward, in that you can't take an awk_value_t that you got from gawk + * and reuse it directly, even for something that is conceptually pass + * by value. + * + * 2. The correct way to create new arrays is to work "bottom up". + * + * new_array = create_array(); + * // fill in new array with lots of subscripts and values + * val.val_type = AWK_ARRAY; + * val.array_cookie = new_array; + * sym_update("array", &val); // install array in the symbol table + * + * After doing so, do NOT make further use of the new_array variable; + * instead use sym_lookup to get the array_cookie if you need to do further + * manipulation of the array. */ /* Allow use in C++ code. */ @@ -73,7 +93,8 @@ typedef enum { AWK_UNDEFINED, AWK_NUMBER, AWK_STRING, - AWK_ARRAY + AWK_ARRAY, + AWK_SCALAR, /* opaque access to a variable */ } awk_valtype_t; /* @@ -88,6 +109,9 @@ typedef struct { /* Arrays are represented as an opaque type. */ typedef void *awk_array_t; +/* Scalars can be represented as an opaque type. */ +typedef void *awk_scalar_t; + /* * An awk value. The val_type tag indicates what * is in the union. @@ -98,10 +122,12 @@ typedef struct { awk_string_t s; double d; awk_array_t a; + awk_array_t scl; } u; #define str_value u.s #define num_value u.d #define array_cookie u.a +#define scalar_cookie u.scl } awk_value_t; /* @@ -200,23 +226,23 @@ typedef struct gawk_api { Table entry is type returned: - +-----------------------------------------+ - | Type Requested: | - +----------+----------+-------+-----------+ - | String | Number | Array | Undefined | - +---------+-----------+----------+----------+-------+-----------+ - | Type | String | String | Number if| false | String | - | | | | it can be| | | - | | | |converted,| | | - | | | | else | | | - | | | | false | | | - | of +-----------+----------+----------+-------+-----------+ - | Actual | Number | String | Number | false | Number | - | Value: +-----------+----------+----------+-------+-----------+ - | | Array | false | false | Array | Array | - | +-----------+----------+----------+-------+-----------+ - | | Undefined | false | false | false | Undefined | - +---------+-----------+----------+----------+-------+-----------+ + +---------------------------------------------------+ + | Type Requested: | + +----------+----------+-------+---------+-----------+ + | String | Number | Array | Scalar | Undefined | + +---------+-----------+----------+----------+-------+---------+-----------+ + | Type | String | String | Number if| false | Scalar | String | + | | | | it can be| | | | + | | | |converted,| | | | + | | | | else | | | | + | | | | false | | | | + | of +-----------+----------+----------+-------+---------+-----------+ + | Actual | Number | String | Number | false | Scalar | Number | + | Value: +-----------+----------+----------+-------+---------+-----------+ + | | Array | false | false | Array | false | Array | + | +-----------+----------+----------+-------+---------+-----------+ + | | Undefined | false | false | false | false | Undefined | + +---------+-----------+----------+----------+-------+---------+-----------+ */ /* @@ -225,7 +251,7 @@ typedef struct gawk_api { * does not match what is specified in wanted. In that case, * result->val_type is as described above. */ - awk_bool_t (*get_argument)(awk_ext_id_t id, size_t count, + awk_bool_t (*api_get_argument)(awk_ext_id_t id, size_t count, awk_valtype_t wanted, awk_value_t *result); @@ -235,7 +261,7 @@ typedef struct gawk_api { * if count is too big, or if the argument's type is * not undefined. */ - awk_bool_t (*set_argument)(awk_ext_id_t id, + awk_bool_t (*api_set_argument)(awk_ext_id_t id, size_t count, awk_array_t array); @@ -245,20 +271,20 @@ typedef struct gawk_api { void (*api_lintwarn)(awk_ext_id_t id, const char *format, ...); /* Register an open hook; for opening files read-only */ - void (*register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF_PUBLIC *)); + void (*api_register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF_PUBLIC *)); /* Functions to update ERRNO */ - void (*update_ERRNO_int)(awk_ext_id_t id, int errno_val); - void (*update_ERRNO_string)(awk_ext_id_t id, const char *string, + void (*api_update_ERRNO_int)(awk_ext_id_t id, int errno_val); + void (*api_update_ERRNO_string)(awk_ext_id_t id, const char *string, awk_bool_t translate); - void (*unset_ERRNO)(awk_ext_id_t id); + void (*api_unset_ERRNO)(awk_ext_id_t id); /* Add a function to the interpreter, returns true upon success */ - awk_bool_t (*add_ext_func)(awk_ext_id_t id, const awk_ext_func_t *func, + awk_bool_t (*api_add_ext_func)(awk_ext_id_t id, const awk_ext_func_t *func, const char *namespace); /* Add an exit call back, returns true upon success */ - void (*awk_atexit)(awk_ext_id_t id, + void (*api_awk_atexit)(awk_ext_id_t id, void (*funcp)(void *data, int exit_status), void *arg0); @@ -285,7 +311,7 @@ typedef struct gawk_api { * // safe to use val * } */ - awk_bool_t (*sym_lookup)(awk_ext_id_t id, + awk_bool_t (*api_sym_lookup)(awk_ext_id_t id, const char *name, awk_valtype_t wanted, awk_value_t *result); @@ -296,16 +322,32 @@ typedef struct gawk_api { * In fact, using this to update an array is not allowed, either. * Such an attempt returns false. */ - awk_bool_t (*sym_update)(awk_ext_id_t id, const char *name, awk_value_t *value); + awk_bool_t (*api_sym_update)(awk_ext_id_t id, const char *name, awk_value_t *value); + + /* + * Work with a scalar cookie. + * Flow is + * sym_lookup with wanted == AWK_SCALAR + * if returns false + * sym_update with real initial value + * sym_lookup again with AWK_SCALAR + * else + * use the scalar cookie + * + * Return will be false if the new value is not one of + * AWK_STRING or AWK_NUMBER. + */ + awk_bool_t (*api_sym_update_scalar)(awk_ext_id_t id, + awk_scalar_t cookie, awk_value_t *value); /* Array management */ /* * Return the value of an element - read only! * Use set_array_element() to change it. - * Behavior for value and return is same as for get_argument + * Behavior for value and return is same as for api_get_argument * and sym_lookup. */ - awk_bool_t (*get_array_element)(awk_ext_id_t id, + awk_bool_t (*api_get_array_element)(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t *const index, awk_valtype_t wanted, @@ -315,7 +357,7 @@ typedef struct gawk_api { * Change (or create) element in existing array with * element->index and element->value. */ - awk_bool_t (*set_array_element)(awk_ext_id_t id, awk_array_t a_cookie, + awk_bool_t (*api_set_array_element)(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t *const index, const awk_value_t *const value); @@ -323,24 +365,24 @@ typedef struct gawk_api { * Remove the element with the given index. * Returns success if removed or if element did not exist. */ - awk_bool_t (*del_array_element)(awk_ext_id_t id, + awk_bool_t (*api_del_array_element)(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t* const index); /* * Retrieve total number of elements in array. * Returns false if some kind of error. */ - awk_bool_t (*get_element_count)(awk_ext_id_t id, + awk_bool_t (*api_get_element_count)(awk_ext_id_t id, awk_array_t a_cookie, size_t *count); /* Create a new array cookie to which elements may be added */ - awk_array_t (*create_array)(awk_ext_id_t id); + awk_array_t (*api_create_array)(awk_ext_id_t id); /* Clear out an array */ - awk_bool_t (*clear_array)(awk_ext_id_t id, awk_array_t a_cookie); + awk_bool_t (*api_clear_array)(awk_ext_id_t id, awk_array_t a_cookie); /* Flatten out an array so that it can be looped over easily. */ - awk_bool_t (*flatten_array)(awk_ext_id_t id, + awk_bool_t (*api_flatten_array)(awk_ext_id_t id, awk_array_t a_cookie, awk_flat_array_t **data); @@ -349,7 +391,7 @@ typedef struct gawk_api { * Count must match what gawk thinks the size is. * Otherwise it's a fatal error. */ - awk_bool_t (*release_flattened_array)(awk_ext_id_t id, + awk_bool_t (*api_release_flattened_array)(awk_ext_id_t id, awk_array_t a_cookie, awk_flat_array_t *data); } gawk_api_t; @@ -367,52 +409,54 @@ typedef struct gawk_api { #define do_mpfr (api->do_flags[gawk_do_mpfr]) #define get_argument(count, wanted, result) \ - (api->get_argument(ext_id, count, wanted, result)) + (api->api_get_argument(ext_id, count, wanted, result)) #define set_argument(count, new_array) \ - (api->set_argument(ext_id, count, new_array)) + (api->api_set_argument(ext_id, count, new_array)) #define fatal api->api_fatal #define warning api->api_warning #define lintwarn api->api_lintwarn -#define register_open_hook(func) (api->register_open_hook(ext_id, func)) +#define register_open_hook(func) (api->api_register_open_hook(ext_id, func)) -#define update_ERRNO_int(e) (api->update_ERRNO_int(ext_id, e)) +#define update_ERRNO_int(e) (api->api_update_ERRNO_int(ext_id, e)) #define update_ERRNO_string(str, translate) \ - (api->update_ERRNO_string(ext_id, str, translate)) -#define unset_ERRNO() (api->unset_ERRNO(ext_id)) + (api->api_update_ERRNO_string(ext_id, str, translate)) +#define unset_ERRNO() (api->api_unset_ERRNO(ext_id)) -#define add_ext_func(func, ns) (api->add_ext_func(ext_id, func, ns)) -#define awk_atexit(funcp, arg0) (api->awk_atexit(ext_id, funcp, arg0)) +#define add_ext_func(func, ns) (api->api_add_ext_func(ext_id, func, ns)) +#define awk_atexit(funcp, arg0) (api->api_awk_atexit(ext_id, funcp, arg0)) -#define sym_lookup(name, wanted, result) (api->sym_lookup(ext_id, name, wanted, result)) +#define sym_lookup(name, wanted, result) (api->api_sym_lookup(ext_id, name, wanted, result)) #define sym_update(name, value) \ - (api->sym_update(ext_id, name, value)) + (api->api_sym_update(ext_id, name, value)) +#define sym_update_scalar(scalar_cookie, value) \ + (api->api_sym_update_scalar)(ext_id, scalar_cookie, value) #define get_array_element(array, index, wanted, result) \ - (api->get_array_element(ext_id, array, index, wanted, result)) + (api->api_get_array_element(ext_id, array, index, wanted, result)) #define set_array_element(array, index, value) \ - (api->set_array_element(ext_id, array, index, value)) + (api->api_set_array_element(ext_id, array, index, value)) #define set_array_element_by_elem(array, elem) \ - (set_array_element(array, & (elem)->index, & (elem)->value)) + (api->api_set_array_element(ext_id, array, & (elem)->index, & (elem)->value)) #define del_array_element(array, index) \ - (api->del_array_element(ext_id, array, index)) + (api->api_del_array_element(ext_id, array, index)) #define get_element_count(array, count_p) \ - (api->get_element_count(ext_id, array, count_p)) + (api->api_get_element_count(ext_id, array, count_p)) -#define create_array() (api->create_array(ext_id)) +#define create_array() (api->api_create_array(ext_id)) -#define clear_array(array) (api->clear_array(ext_id, array)) +#define clear_array(array) (api->api_clear_array(ext_id, array)) #define flatten_array(array, data) \ - (api->flatten_array(ext_id, array, data)) + (api->api_flatten_array(ext_id, array, data)) #define release_flattened_array(array, data) \ - (api->release_flattened_array(ext_id, array, data)) + (api->api_release_flattened_array(ext_id, array, data)) #define emalloc(pointer, type, size, message) \ do { \ @@ -420,6 +464,12 @@ typedef struct gawk_api { fatal(ext_id, "malloc of %d bytes failed\n", size); \ } while(0) +#define erealloc(pointer, type, size, message) \ + do { \ + if ((pointer = (type) realloc(pointer, size)) == 0) \ + fatal(ext_id, "realloc of %d bytes failed\n", size); \ + } while(0) + /* Constructor functions */ /* r_make_string --- make a string value in result from the passed-in string */ @@ -440,7 +490,7 @@ r_make_string(const gawk_api_t *api, /* needed for emalloc */ result->str_value.len = length; if (duplicate) { - emalloc(cp, char *, length + 2, "make_string"); + emalloc(cp, char *, length + 2, "r_make_string"); memcpy(cp, string, length); cp[length] = '\0'; result->str_value.str = cp; @@ -451,8 +501,19 @@ r_make_string(const gawk_api_t *api, /* needed for emalloc */ return result; } -#define make_string(str, len, result) r_make_string(api, ext_id, str, len, 0, result) -#define dup_string(str, len, result) r_make_string(api, ext_id, str, len, 1, result) +#define make_const_string(str, len, result) r_make_string(api, ext_id, str, len, 1, result) +#define make_malloced_string(str, len, result) r_make_string(api, ext_id, str, len, 0, result) + +/* make_null_string --- make a null string value */ + +static inline awk_value_t * +make_null_string(awk_value_t *result) +{ + memset(result, 0, sizeof(*result)); + result->val_type = AWK_UNDEFINED; + + return result; +} /* make_number --- make a number value in result */ -- cgit v1.2.3 From 73533707616e119778993fe18540098239ecbb2e Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 11 Jul 2012 21:41:54 +0300 Subject: Add ability to call an initialization routine. --- gawkapi.h | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 2bef258e..9f541cfc 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -533,9 +533,13 @@ make_number(double num, awk_value_t *result) * * int dl_load(gawk_api_t *api_p, awk_ext_id_t id) * + * The return value should be zero on failure and non-zero on success. + * * For the macros to work, the function should save api_p in a global * variable named 'api' and save id in a global variable named 'ext_id'. - * The return value should be zero on failure and non-zero on success. + * In addition, a global function pointer named 'init_func' should be + * defined and set to either NULL or an initialization function that + * returns non-zero on success and zero upon failure. */ extern int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id); @@ -549,6 +553,19 @@ static awk_ext_func_t func_table[] = { /* ... */ }; +/* EITHER: */ + +static awk_bool_t (*init_func)(void) = NULL; + +/* OR: */ + +static awk_bool_t init_my_module(void) +{ + ... +} + +static awk_bool_t (*init_func)(void) = init_my_module; + dl_load_func(func_table, some_name, "name_space_in_quotes") #endif @@ -578,6 +595,13 @@ int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) \ errors++; \ } \ } \ +\ + if (init_func != NULL) { \ + if (! init_func()) { \ + warning(ext_id, #module ": initialization function failed\n"); \ + errors++; \ + } \ + } \ \ return (errors == 0); \ } -- 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.h | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 9f541cfc..50ca327a 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -34,7 +34,7 @@ /* * General introduction: * - * This API purposely restricts itself to C90 features. In paticular, no + * This API purposely restricts itself to C90 features. In particular, no * bool, no // comments, no use of the restrict keyword, or anything else, * in order to provide maximal portability. * @@ -122,7 +122,7 @@ typedef struct { awk_string_t s; double d; awk_array_t a; - awk_array_t scl; + awk_scalar_t scl; } u; #define str_value u.s #define num_value u.d @@ -316,6 +316,18 @@ typedef struct gawk_api { awk_valtype_t wanted, awk_value_t *result); + /* + * Retrieve the current value of a scalar cookie. Once + * you have obtained a saclar_cookie using sym_lookup, you can + * use this function to get its value more efficiently. + * + * Return will be false if the value cannot be retrieved. + */ + awk_bool_t (*api_sym_lookup_scalar)(awk_ext_id_t id, + awk_scalar_t cookie, + awk_valtype_t wanted, + awk_value_t *result); + /* * Update a value. Adds it to the symbol table if not there. * Changing types (scalar <--> array) is not allowed. @@ -427,7 +439,10 @@ typedef struct gawk_api { #define add_ext_func(func, ns) (api->api_add_ext_func(ext_id, func, ns)) #define awk_atexit(funcp, arg0) (api->api_awk_atexit(ext_id, funcp, arg0)) -#define sym_lookup(name, wanted, result) (api->api_sym_lookup(ext_id, name, wanted, result)) +#define sym_lookup(name, wanted, result) \ + (api->api_sym_lookup(ext_id, name, wanted, result)) +#define sym_lookup_scalar(scalar_cookie, wanted, result) \ + (api->api_sym_lookup_scalar(ext_id, scalar_cookie, wanted, result)) #define sym_update(name, value) \ (api->api_sym_update(ext_id, name, value)) #define sym_update_scalar(scalar_cookie, value) \ -- 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.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 50ca327a..a84fbf52 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -334,7 +334,15 @@ typedef struct gawk_api { * In fact, using this to update an array is not allowed, either. * Such an attempt returns false. */ - awk_bool_t (*api_sym_update)(awk_ext_id_t id, const char *name, awk_value_t *value); + awk_bool_t (*api_sym_update)(awk_ext_id_t id, + const char *name, + awk_value_t *value); + /* + * Install a constant value. + */ + awk_bool_t (*api_sym_constant)(awk_ext_id_t id, + const char *name, + awk_value_t *value); /* * Work with a scalar cookie. @@ -445,6 +453,8 @@ typedef struct gawk_api { (api->api_sym_lookup_scalar(ext_id, scalar_cookie, wanted, result)) #define sym_update(name, value) \ (api->api_sym_update(ext_id, name, value)) +#define sym_constant(name, value) \ + (api->api_sym_constant(ext_id, name, value)) #define sym_update_scalar(scalar_cookie, value) \ (api->api_sym_update_scalar)(ext_id, scalar_cookie, value) -- 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.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index a84fbf52..29631cdd 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -95,6 +95,7 @@ typedef enum { AWK_STRING, AWK_ARRAY, AWK_SCALAR, /* opaque access to a variable */ + AWK_VALUE_COOKIE, /* for updating to a previously created value */ } awk_valtype_t; /* @@ -112,6 +113,9 @@ typedef void *awk_array_t; /* Scalars can be represented as an opaque type. */ typedef void *awk_scalar_t; +/* Any value can be stored as a cookie. */ +typedef void *awk_value_cookie_t; + /* * An awk value. The val_type tag indicates what * is in the union. @@ -123,11 +127,13 @@ typedef struct { double d; awk_array_t a; awk_scalar_t scl; + awk_value_cookie_t vc; } u; #define str_value u.s #define num_value u.d #define array_cookie u.a #define scalar_cookie u.scl +#define value_cookie u.vc } awk_value_t; /* @@ -414,6 +420,11 @@ typedef struct gawk_api { awk_bool_t (*api_release_flattened_array)(awk_ext_id_t id, awk_array_t a_cookie, awk_flat_array_t *data); + + awk_bool_t (*api_create_value)(awk_ext_id_t id, awk_value_t *value, + awk_value_cookie_t *result); + + awk_bool_t (*api_release_value)(awk_ext_id_t id, awk_value_cookie_t vc); } gawk_api_t; #ifndef GAWK /* these are not for the gawk code itself! */ @@ -483,6 +494,12 @@ typedef struct gawk_api { #define release_flattened_array(array, data) \ (api->api_release_flattened_array(ext_id, array, data)) +#define create_value(value, result) \ + (api->api_create_value(ext_id, value,result)) + +#define release_value(value) \ + (api->api_release_value(ext_id, value)) + #define emalloc(pointer, type, size, message) \ do { \ if ((pointer = (type) malloc(size)) == 0) \ -- 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.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 29631cdd..5d9936fb 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -421,9 +421,20 @@ typedef struct gawk_api { awk_array_t a_cookie, awk_flat_array_t *data); + /* + * Cache a string or numeric value for efficient later assignment. + * This improves performance when you want to assign the same value + * to one or more variables repeatedly. Only AWK_NUMBER and AWK_STRING + * values are allowed. Any other type is rejected. We disallow + * AWK_UNDEFINED since that case would result in inferior performance. + */ awk_bool_t (*api_create_value)(awk_ext_id_t id, awk_value_t *value, awk_value_cookie_t *result); + /* + * Release the memory associated with a cookie from api_create_value. + * Please call this to free memory when the value is no longer needed. + */ awk_bool_t (*api_release_value)(awk_ext_id_t id, awk_value_cookie_t vc); } gawk_api_t; -- 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.h | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 29631cdd..5cc8fc10 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -232,23 +232,28 @@ typedef struct gawk_api { Table entry is type returned: - +---------------------------------------------------+ - | Type Requested: | - +----------+----------+-------+---------+-----------+ - | String | Number | Array | Scalar | Undefined | - +---------+-----------+----------+----------+-------+---------+-----------+ - | Type | String | String | Number if| false | Scalar | String | - | | | | it can be| | | | - | | | |converted,| | | | - | | | | else | | | | - | | | | false | | | | - | of +-----------+----------+----------+-------+---------+-----------+ - | Actual | Number | String | Number | false | Scalar | Number | - | Value: +-----------+----------+----------+-------+---------+-----------+ - | | Array | false | false | Array | false | Array | - | +-----------+----------+----------+-------+---------+-----------+ - | | Undefined | false | false | false | false | Undefined | - +---------+-----------+----------+----------+-------+---------+-----------+ + + +-------------------------------------------------+ + | Type of Actual Value: | + +------------+------------+-----------+-----------+ + | String | Number | Array | Undefined | + +-----------+-----------+------------+------------+-----------+-----------+ + | | String | String | String | false | false | + | |-----------+------------+------------+-----------+-----------+ + | | Number | Number if | Number | false | false | + | | | can be | | | | + | | | converted, | | | | + | | | else false | | | | + | |-----------+------------+------------+-----------+-----------+ + | Type | Array | false | false | Array | false | + | Requested |-----------+------------+------------+-----------+-----------+ + | | Scalar | Scalar | Scalar | false | false | + | |-----------+------------+------------+-----------+-----------+ + | | Undefined | String | Number | Array | Undefined | + | |-----------+------------+------------+-----------+-----------+ + | | Value | false | false | false | false | + | | Cookie | | | | | + +-----------+-----------+------------+------------+-----------+-----------+ */ /* -- 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.h | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 90df6293..58162002 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -69,6 +69,13 @@ extern "C" { #endif +/* This is used to keep the extension from modifying certain fields in some structs. */ +#ifdef GAWK +#define awk_const +#else +#define awk_const const +#endif + /* portions of IOBUF that should be accessible to extension functions: */ typedef struct iobuf_public { const char *name; /* filename */ @@ -78,6 +85,14 @@ typedef struct iobuf_public { void (*close_func)(struct iobuf_public *); } IOBUF_PUBLIC; +typedef struct input_parser { + const char *name; /* name of parser */ + int (*can_take_file)(IOBUF_PUBLIC *iobuf); + int (*take_control_of)(IOBUF_PUBLIC *iobuf); + struct input_parser *awk_const next; /* for use by gawk */ +} awk_input_parser_t; + + #define GAWK_API_MAJOR_VERSION 0 #define GAWK_API_MINOR_VERSION 0 @@ -156,13 +171,6 @@ typedef struct awk_element { awk_value_t value; } awk_element_t; -/* This is used to keep the extension from modifying certain fields. */ -#ifdef GAWK -#define awk_const -#else -#define awk_const const -#endif - /* * A "flattened" array. See the description above for how * to use the elements contained herein. @@ -281,8 +289,8 @@ typedef struct gawk_api { void (*api_warning)(awk_ext_id_t id, const char *format, ...); void (*api_lintwarn)(awk_ext_id_t id, const char *format, ...); - /* Register an open hook; for opening files read-only */ - void (*api_register_open_hook)(awk_ext_id_t id, void* (*open_func)(IOBUF_PUBLIC *)); + /* Register an input parser; for opening files read-only */ + void (*api_register_input_parser)(awk_ext_id_t id, awk_input_parser_t *input_parser); /* Functions to update ERRNO */ void (*api_update_ERRNO_int)(awk_ext_id_t id, int errno_val); @@ -464,7 +472,7 @@ typedef struct gawk_api { #define warning api->api_warning #define lintwarn api->api_lintwarn -#define register_open_hook(func) (api->api_register_open_hook(ext_id, func)) +#define register_input_parser(parser) (api->api_register_input_parser(ext_id, parser)) #define update_ERRNO_int(e) (api->api_update_ERRNO_int(ext_id, e)) #define update_ERRNO_string(str, translate) \ -- 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.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 58162002..b8422db5 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -294,8 +294,7 @@ typedef struct gawk_api { /* Functions to update ERRNO */ void (*api_update_ERRNO_int)(awk_ext_id_t id, int errno_val); - void (*api_update_ERRNO_string)(awk_ext_id_t id, const char *string, - awk_bool_t translate); + void (*api_update_ERRNO_string)(awk_ext_id_t id, const char *string); void (*api_unset_ERRNO)(awk_ext_id_t id); /* Add a function to the interpreter, returns true upon success */ @@ -475,8 +474,8 @@ typedef struct gawk_api { #define register_input_parser(parser) (api->api_register_input_parser(ext_id, parser)) #define update_ERRNO_int(e) (api->api_update_ERRNO_int(ext_id, e)) -#define update_ERRNO_string(str, translate) \ - (api->api_update_ERRNO_string(ext_id, str, translate)) +#define update_ERRNO_string(str) \ + (api->api_update_ERRNO_string(ext_id, str)) #define unset_ERRNO() (api->api_unset_ERRNO(ext_id)) #define add_ext_func(func, ns) (api->api_add_ext_func(ext_id, func, ns)) -- cgit v1.2.3 From ca83de0ec92b56c712f7a7376b21a1a1337b3107 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 26 Jul 2012 11:56:00 -0400 Subject: Document the parser interface and remove some excessive readdir paranoia. --- gawkapi.h | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index b8422db5..bc7001c7 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -81,13 +81,45 @@ typedef struct iobuf_public { const char *name; /* filename */ int fd; /* file descriptor */ void *opaque; /* private data for open hooks */ + /* + * The get_record function is called to read the next record of data. + * It should return the length of the input record (or EOF), and + * it should set *out to point to the contents of $0. Note that + * gawk will make a copy of the record in *out, so the parser is + * responsible for managing its own memory buffer. If an error + * occurs, the function should return EOF and set *errcode + * to a non-zero value. In that case, if *errcode does not equal + * -1, gawk will automatically update the ERRNO variable based on + * the value of *errcode (e.g. setting *errcode = errno should do + * the right thing). It is guaranteed that errcode is a valid + * pointer, so there is no need to test for a NULL value. The + * caller sets *errcode to 0, so there is no need to set it unless + * an error occurs. + */ int (*get_record)(char **out, struct iobuf_public *, int *errcode); + /* + * The close_func is called to allow the parser to free private data. + * Gawk itself will close the fd unless close_func sets it to -1. + */ void (*close_func)(struct iobuf_public *); + } IOBUF_PUBLIC; typedef struct input_parser { const char *name; /* name of parser */ - int (*can_take_file)(IOBUF_PUBLIC *iobuf); + /* + * The can_take_file function should return non-zero if the parser + * would like to parse this file. It should not change any gawk + * state! + */ + int (*can_take_file)(const IOBUF_PUBLIC *iobuf); + /* + * If this parser is selected, then take_control_of will be called. + * It can assume that a previous call to can_take_file was successful, + * and no gawk state has changed since that call. It should populate + * the IOBUF_PUBLIC get_record, close_func, and opaque values as needed. + * It should return non-zero if successful. + */ int (*take_control_of)(IOBUF_PUBLIC *iobuf); struct input_parser *awk_const next; /* for use by gawk */ } awk_input_parser_t; -- 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.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index bc7001c7..db650fb2 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -324,6 +324,9 @@ typedef struct gawk_api { /* Register an input parser; for opening files read-only */ void (*api_register_input_parser)(awk_ext_id_t id, awk_input_parser_t *input_parser); + /* Set RT - pass AWK_UNDEFINED to set to null string */ + void (*api_set_RT)(awk_ext_id_t id, awk_value_t *value); + /* Functions to update ERRNO */ void (*api_update_ERRNO_int)(awk_ext_id_t id, int errno_val); void (*api_update_ERRNO_string)(awk_ext_id_t id, const char *string); @@ -504,6 +507,7 @@ typedef struct gawk_api { #define lintwarn api->api_lintwarn #define register_input_parser(parser) (api->api_register_input_parser(ext_id, parser)) +#define set_RT(value) (api->api_set_RT(ext_id, value)) #define update_ERRNO_int(e) (api->api_update_ERRNO_int(ext_id, e)) #define update_ERRNO_string(str) \ -- 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.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index db650fb2..0204053a 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -80,7 +80,7 @@ extern "C" { typedef struct iobuf_public { const char *name; /* filename */ int fd; /* file descriptor */ - void *opaque; /* private data for open hooks */ + void *opaque; /* private data for input parsers */ /* * The get_record function is called to read the next record of data. * It should return the length of the input record (or EOF), and -- 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.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 0204053a..7e20d3d1 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -94,9 +94,14 @@ typedef struct iobuf_public { * the right thing). It is guaranteed that errcode is a valid * pointer, so there is no need to test for a NULL value. The * caller sets *errcode to 0, so there is no need to set it unless - * an error occurs. + * an error occurs. The rt_start and rt_len arguments should be + * used to return RT to gawk. Gawk will make its own copy of RT, + * so the parser is responsible for managing this memory. If EOF is + * not returned, the parser must set *rt_len (and *rt_start if *rt_len + * is non-zero). */ - int (*get_record)(char **out, struct iobuf_public *, int *errcode); + int (*get_record)(char **out, struct iobuf_public *, int *errcode, + char **rt_start, size_t *rt_len); /* * The close_func is called to allow the parser to free private data. * Gawk itself will close the fd unless close_func sets it to -1. @@ -324,9 +329,6 @@ typedef struct gawk_api { /* Register an input parser; for opening files read-only */ void (*api_register_input_parser)(awk_ext_id_t id, awk_input_parser_t *input_parser); - /* Set RT - pass AWK_UNDEFINED to set to null string */ - void (*api_set_RT)(awk_ext_id_t id, awk_value_t *value); - /* Functions to update ERRNO */ void (*api_update_ERRNO_int)(awk_ext_id_t id, int errno_val); void (*api_update_ERRNO_string)(awk_ext_id_t id, const char *string); @@ -507,7 +509,6 @@ typedef struct gawk_api { #define lintwarn api->api_lintwarn #define register_input_parser(parser) (api->api_register_input_parser(ext_id, parser)) -#define set_RT(value) (api->api_set_RT(ext_id, value)) #define update_ERRNO_int(e) (api->api_update_ERRNO_int(ext_id, e)) #define update_ERRNO_string(str) \ -- 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.h | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index 7e20d3d1..f345d07a 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -51,17 +51,37 @@ * and reuse it directly, even for something that is conceptually pass * by value. * - * 2. The correct way to create new arrays is to work "bottom up". + * 2. Due to gawk internals, after using sym_update() to install an array + * into gawk, you have to retrieve the array cookie from the value + * passed in to sym_update(). Like so: * * new_array = create_array(); - * // fill in new array with lots of subscripts and values * val.val_type = AWK_ARRAY; * val.array_cookie = new_array; - * sym_update("array", &val); // install array in the symbol table + * sym_update("array", & val); // install array in the symbol table + * + * new_array = val.array_cookie; // MUST DO THIS + * + * // fill in new array with lots of subscripts and values + * + * Similarly, if installing a new array as a subarray of an existing + * array, you must add the new array to its parent before adding any + * elements to it. + * + * You must also retrieve the value of the array_cookie after the call + * to set_element(). + * + * Thus, the correct way to build an array is to work "top down". + * Create the array, and immediately install it in gawk's symbol table + * using sym_update(), or install it as an element in a previously + * existing array using set_element(). * - * After doing so, do NOT make further use of the new_array variable; - * instead use sym_lookup to get the array_cookie if you need to do further - * manipulation of the array. + * The new array must ultimately be rooted in a global symbol. This is + * necessary before installing any subarrays in it, due to gawk's + * internal implementation. Strictly speaking, this is required only + * for arrays that will have subarrays as elements; however it is + * a good idea to always do this. This restriction may be relaxed + * in a subsequent revision of the API. */ /* Allow use in C++ code. */ @@ -249,15 +269,15 @@ typedef void *awk_ext_id_t; /* opaque type for extension id */ * logically organized. */ typedef struct gawk_api { - int major_version; - int minor_version; + awk_const int major_version; + awk_const int minor_version; /* * These can change on the fly as things happen within gawk. * Currently only do_lint is prone to change, but we reserve * the right to allow the others also. */ - int do_flags[DO_FLAGS_SIZE]; + awk_const int do_flags[DO_FLAGS_SIZE]; /* Use these as indices into do_flags[] array to check the values */ #define gawk_do_lint 0 #define gawk_do_traditional 1 -- cgit v1.2.3 From 49658bfd0ef5d4efccd210c48560c43bf455ee16 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 8 Aug 2012 22:51:53 +0300 Subject: Move struct stat into IOBUF_PUBLIC. --- gawkapi.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index f345d07a..b516787a 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -100,6 +100,7 @@ extern "C" { typedef struct iobuf_public { const char *name; /* filename */ int fd; /* file descriptor */ +#define INVALID_HANDLE (-1) void *opaque; /* private data for input parsers */ /* * The get_record function is called to read the next record of data. @@ -127,6 +128,9 @@ typedef struct iobuf_public { * Gawk itself will close the fd unless close_func sets it to -1. */ void (*close_func)(struct iobuf_public *); + + /* put last, for alignment. bleah */ + struct stat sbuf; /* stat buf */ } IOBUF_PUBLIC; -- cgit v1.2.3 From 88f8278587c7f254d4c5bb2e8f996f3947da32e9 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 12 Aug 2012 11:00:42 +0300 Subject: Make api versions into enum, not defines. --- gawkapi.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'gawkapi.h') diff --git a/gawkapi.h b/gawkapi.h index b516787a..9b89e425 100644 --- a/gawkapi.h +++ b/gawkapi.h @@ -121,7 +121,7 @@ typedef struct iobuf_public { * not returned, the parser must set *rt_len (and *rt_start if *rt_len * is non-zero). */ - int (*get_record)(char **out, struct iobuf_public *, int *errcode, + int (*get_record)(char **out, struct iobuf_public *iobuf, int *errcode, char **rt_start, size_t *rt_len); /* * The close_func is called to allow the parser to free private data. @@ -154,8 +154,10 @@ typedef struct input_parser { } awk_input_parser_t; -#define GAWK_API_MAJOR_VERSION 0 -#define GAWK_API_MINOR_VERSION 0 +enum { + GAWK_API_MAJOR_VERSION = 0, + GAWK_API_MINOR_VERSION = 0 +}; #define DO_FLAGS_SIZE 6 -- cgit v1.2.3