From bf847b770dec8fd2e364a56abc8618987b9de917 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 29 Nov 2016 20:32:29 +0200 Subject: Add regex value support to API. Update rwarr extension and test. --- gawkapi.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 958c3c16..76d80e64 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -164,6 +164,10 @@ awk_value_to_node(const awk_value_t *retval) ext_ret_val = make_str_node(retval->str_value.str, retval->str_value.len, ALREADY_MALLOCED); break; + case AWK_REGEX: + ext_ret_val = make_typed_regex(retval->str_value.str, + retval->str_value.len); + break; case AWK_SCALAR: v = (NODE *) retval->scalar_cookie; if (v->type != Node_var) @@ -440,6 +444,15 @@ assign_string(NODE *node, awk_value_t *val) val->str_value.len = node->stlen; } +/* assign_regex --- return a regex node */ + +static inline void +assign_regex(NODE *node, awk_value_t *val) +{ + assign_string(node, val); + val->val_type = AWK_REGEX; +} + /* node_to_awk_value --- convert a node into a value for an extension */ static awk_bool_t @@ -489,12 +502,19 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) ret = awk_true; break; + case AWK_REGEX: + assign_regex(node, val); + ret = awk_true; + break; + case AWK_SCALAR: fixtype(node); if ((node->flags & NUMBER) != 0) { val->val_type = AWK_NUMBER; } else if ((node->flags & STRING) != 0) { val->val_type = AWK_STRING; + } else if ((node->flags & REGEX) != 0) { + val->val_type = AWK_REGEX; } else val->val_type = AWK_UNDEFINED; ret = awk_false; @@ -513,6 +533,9 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) } else if ((node->flags & STRING) != 0) { assign_string(node, val); ret = awk_true; + } else if ((node->flags & REGEX) != 0) { + assign_regex(node, val); + ret = awk_true; } else val->val_type = AWK_UNDEFINED; break; @@ -618,6 +641,7 @@ api_sym_update(awk_ext_id_t id, switch (value->val_type) { case AWK_NUMBER: case AWK_STRING: + case AWK_REGEX: case AWK_UNDEFINED: case AWK_ARRAY: case AWK_SCALAR: @@ -715,6 +739,7 @@ api_sym_update_scalar(awk_ext_id_t id, return awk_true; } break; + case AWK_STRING: if (node->var_value->valref == 1) { NODE *r = node->var_value; @@ -735,11 +760,14 @@ api_sym_update_scalar(awk_ext_id_t id, return awk_true; } break; + + case AWK_REGEX: case AWK_UNDEFINED: case AWK_SCALAR: case AWK_VALUE_COOKIE: break; + default: /* AWK_ARRAY or invalid type */ return awk_false; } @@ -763,6 +791,7 @@ valid_subscript_type(awk_valtype_t valtype) case AWK_UNDEFINED: case AWK_NUMBER: case AWK_STRING: + case AWK_REGEX: case AWK_SCALAR: case AWK_VALUE_COOKIE: return true; @@ -1005,6 +1034,8 @@ api_flatten_array(awk_ext_id_t id, * index to be a string, since indices are always * conceptually strings, regardless of internal optimizations * to treat them as integers in some cases. + * + * Regexes are forced to string too. */ if (! node_to_awk_value(index, & (*data)->elements[j].index, AWK_STRING)) { @@ -1073,6 +1104,7 @@ api_create_value(awk_ext_id_t id, awk_value_t *value, switch (value->val_type) { case AWK_NUMBER: case AWK_STRING: + case AWK_REGEX: break; default: /* reject anything other than a simple scalar */ -- cgit v1.2.3 From 2b9a30b2ab91ea465a649be0fd0927c2aebc67ff Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 4 Dec 2016 16:30:34 -0500 Subject: Add flatten_array_typed to the API. --- gawkapi.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 76d80e64..4b4b584e 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -995,9 +995,10 @@ api_clear_array(awk_ext_id_t id, awk_array_t a_cookie) /* api_flatten_array --- flatten out an array so that it can be looped over easily. */ static awk_bool_t -api_flatten_array(awk_ext_id_t id, +api_flatten_array_typed(awk_ext_id_t id, awk_array_t a_cookie, - awk_flat_array_t **data) + awk_flat_array_t **data, + awk_valtype_t index_type, awk_valtype_t value_type) { NODE **list; size_t i, j; @@ -1014,7 +1015,7 @@ api_flatten_array(awk_ext_id_t id, (array->table_size - 1) * sizeof(awk_element_t); emalloc(*data, awk_flat_array_t *, alloc_size, - "api_flatten_array"); + "api_flatten_array_typed"); memset(*data, 0, alloc_size); list = assoc_list(array, "@unsorted", ASORTI); @@ -1029,28 +1030,34 @@ api_flatten_array(awk_ext_id_t id, index = list[i]; value = list[i + 1]; /* number or string or subarray */ - /* - * Convert index and value to ext types. Force the - * index to be a string, since indices are always - * conceptually strings, regardless of internal optimizations - * to treat them as integers in some cases. - * - * Regexes are forced to string too. - */ + /* Convert index and value to ext types. */ if (! node_to_awk_value(index, - & (*data)->elements[j].index, AWK_STRING)) { - fatal(_("api_flatten_array: could not convert index %d\n"), - (int) i); + & (*data)->elements[j].index, index_type)) { + fatal(_("api_flatten_array_typed: could not convert index %d to %d\n"), + (int) i, (int) index_type); } if (! node_to_awk_value(value, - & (*data)->elements[j].value, AWK_UNDEFINED)) { - fatal(_("api_flatten_array: could not convert value %d\n"), - (int) i); + & (*data)->elements[j].value, value_type)) { + fatal(_("api_flatten_array_typed: could not convert value %d to %d\n"), + (int) i, (int) value_type); } } return awk_true; } +/* + * api_flatten_array -- replaced by api_flatten_array_typed. This function + * is retained only for binary compatibility. + */ + +static awk_bool_t +api_flatten_array(awk_ext_id_t id, + awk_array_t a_cookie, + awk_flat_array_t **data) +{ + return api_flatten_array_typed(id, a_cookie, data, AWK_STRING, AWK_UNDEFINED); +} + /* * api_release_flattened_array --- release array memory, * delete any marked elements. Count must match what @@ -1298,7 +1305,7 @@ gawk_api_t api_impl = { api_del_array_element, api_create_array, api_clear_array, - api_flatten_array, + api_flatten_array, /* for legacy binary compatibility */ api_release_flattened_array, /* Memory allocation */ @@ -1312,6 +1319,9 @@ gawk_api_t api_impl = { /* Print nonfatal error message */ api_nonfatal, + + /* New array flattening function */ + api_flatten_array_typed, }; /* init_ext_api --- init the extension API */ -- cgit v1.2.3 From 16761af5b3cec40f1e341cb33787af33cb2b45c2 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 4 Dec 2016 16:50:50 -0500 Subject: Improve API regex support. --- gawkapi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 4b4b584e..8fe57fc7 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -449,7 +449,11 @@ assign_string(NODE *node, awk_value_t *val) static inline void assign_regex(NODE *node, awk_value_t *val) { - assign_string(node, val); + /* a REGEX node cannot be an unterminated field string */ + assert((node->flags & MALLOC) != 0); + assert(node->stptr[node->stlen] == '\0'); + val->str_value.str = node->stptr; + val->str_value.len = node->stlen; val->val_type = AWK_REGEX; } -- cgit v1.2.3 From 352af50d54071be81f6be1c4d93bfd791f473755 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Mon, 5 Dec 2016 14:47:51 -0500 Subject: Add strnum support to API. Update rwarray extension and test. --- gawkapi.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 24 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 8fe57fc7..aaac24ab 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -164,6 +164,11 @@ awk_value_to_node(const awk_value_t *retval) ext_ret_val = make_str_node(retval->str_value.str, retval->str_value.len, ALREADY_MALLOCED); break; + case AWK_STRNUM: + ext_ret_val = make_str_node(retval->str_value.str, + retval->str_value.len, ALREADY_MALLOCED); + ext_ret_val->flags |= USER_INPUT; + break; case AWK_REGEX: ext_ret_val = make_typed_regex(retval->str_value.str, retval->str_value.len); @@ -415,9 +420,9 @@ free_api_string_copies() /* assign_string --- return a string node with NUL termination */ static inline void -assign_string(NODE *node, awk_value_t *val) +assign_string(NODE *node, awk_value_t *val, awk_valtype_t val_type) { - val->val_type = AWK_STRING; + val->val_type = val_type; if (node->stptr[node->stlen] != '\0') { /* * This is an unterminated field string, so make a copy. @@ -493,55 +498,139 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) /* a scalar value */ switch (wanted) { case AWK_NUMBER: - val->val_type = AWK_NUMBER; + if (node->flags & REGEX) + val->val_type = AWK_REGEX; + else { + val->val_type = AWK_NUMBER; + (void) force_number(node); + val->num_value = get_number_d(node); + ret = awk_true; + } + break; - (void) force_number(node); - val->num_value = get_number_d(node); - ret = awk_true; + case AWK_STRNUM: + switch (fixtype(node)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) { + case STRING: + val->val_type = AWK_STRING; + break; + case NUMBER: + (void) force_string(node); + assign_string(node, val, AWK_STRNUM); + ret = awk_true; + break; + case NUMBER|USER_INPUT: + assign_string(node, val, AWK_STRNUM); + ret = awk_true; + break; + case REGEX: + val->val_type = AWK_REGEX; + break; + case NUMBER|STRING: + if (node == Nnull_string) { + val->val_type = AWK_UNDEFINED; + break; + } + /* fall through */ + default: + warning(_("node_to_awk_value detected invalid flags combination `%s'; please file a bug report."), flags2str(node->flags)); + val->val_type = AWK_UNDEFINED; + break; + } break; case AWK_STRING: (void) force_string(node); - assign_string(node, val); + assign_string(node, val, AWK_STRING); ret = awk_true; break; case AWK_REGEX: - assign_regex(node, val); - ret = awk_true; + switch (fixtype(node)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) { + case STRING: + val->val_type = AWK_STRING; + break; + case NUMBER: + val->val_type = AWK_NUMBER; + break; + case NUMBER|USER_INPUT: + val->val_type = AWK_STRNUM; + break; + case REGEX: + assign_regex(node, val); + ret = awk_true; + break; + case NUMBER|STRING: + if (node == Nnull_string) { + val->val_type = AWK_UNDEFINED; + break; + } + /* fall through */ + default: + warning(_("node_to_awk_value detected invalid flags combination `%s'; please file a bug report."), flags2str(node->flags)); + val->val_type = AWK_UNDEFINED; + break; + } break; case AWK_SCALAR: - fixtype(node); - if ((node->flags & NUMBER) != 0) { - val->val_type = AWK_NUMBER; - } else if ((node->flags & STRING) != 0) { + switch (fixtype(node)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) { + case STRING: val->val_type = AWK_STRING; - } else if ((node->flags & REGEX) != 0) { + break; + case NUMBER: + val->val_type = AWK_NUMBER; + break; + case NUMBER|USER_INPUT: + val->val_type = AWK_STRNUM; + break; + case REGEX: val->val_type = AWK_REGEX; - } else + break; + case NUMBER|STRING: + if (node == Nnull_string) { + val->val_type = AWK_UNDEFINED; + break; + } + /* fall through */ + default: + warning(_("node_to_awk_value detected invalid flags combination `%s'; please file a bug report."), flags2str(node->flags)); val->val_type = AWK_UNDEFINED; - ret = awk_false; + break; + } break; case AWK_UNDEFINED: /* return true and actual type for request of undefined */ - fixtype(node); - if (node == Nnull_string) { - val->val_type = AWK_UNDEFINED; + switch (fixtype(node)->flags & (STRING|NUMBER|USER_INPUT|REGEX)) { + case STRING: + assign_string(node, val, AWK_STRING); ret = awk_true; - } else if ((node->flags & NUMBER) != 0) { + break; + case NUMBER: val->val_type = AWK_NUMBER; val->num_value = get_number_d(node); ret = awk_true; - } else if ((node->flags & STRING) != 0) { - assign_string(node, val); + break; + case NUMBER|USER_INPUT: + assign_string(node, val, AWK_STRNUM); ret = awk_true; - } else if ((node->flags & REGEX) != 0) { + break; + case REGEX: assign_regex(node, val); ret = awk_true; - } else + break; + case NUMBER|STRING: + if (node == Nnull_string) { + val->val_type = AWK_UNDEFINED; + ret = awk_true; + break; + } + /* fall through */ + default: + warning(_("node_to_awk_value detected invalid flags combination `%s'; please file a bug report."), flags2str(node->flags)); val->val_type = AWK_UNDEFINED; + break; + } break; case AWK_ARRAY: @@ -644,6 +733,7 @@ api_sym_update(awk_ext_id_t id, switch (value->val_type) { case AWK_NUMBER: + case AWK_STRNUM: case AWK_STRING: case AWK_REGEX: case AWK_UNDEFINED: @@ -745,6 +835,7 @@ api_sym_update_scalar(awk_ext_id_t id, break; case AWK_STRING: + case AWK_STRNUM: if (node->var_value->valref == 1) { NODE *r = node->var_value; @@ -758,6 +849,8 @@ api_sym_update_scalar(awk_ext_id_t id, /* make_str_node(s, l, ALREADY_MALLOCED): */ r->numbr = 0; r->flags = (MALLOC|STRING|STRCUR); + if (value->val_type == AWK_STRNUM) + r->flags |= USER_INPUT; r->stfmt = STFMT_UNUSED; r->stptr = value->str_value.str; r->stlen = value->str_value.len; @@ -794,6 +887,7 @@ valid_subscript_type(awk_valtype_t valtype) switch (valtype) { case AWK_UNDEFINED: case AWK_NUMBER: + case AWK_STRNUM: case AWK_STRING: case AWK_REGEX: case AWK_SCALAR: @@ -1114,6 +1208,7 @@ api_create_value(awk_ext_id_t id, awk_value_t *value, switch (value->val_type) { case AWK_NUMBER: + case AWK_STRNUM: case AWK_STRING: case AWK_REGEX: break; -- cgit v1.2.3 From af31a6de1bd15d4d5f5520ebfcb1d24239b9a683 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Thu, 22 Dec 2016 18:30:05 +0200 Subject: Doc cleanups after merge. Totally break binary compat in the API. --- gawkapi.c | 66 +++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 29 deletions(-) (limited to 'gawkapi.c') diff --git a/gawkapi.c b/gawkapi.c index 72797e0c..4c6a2f8f 100644 --- a/gawkapi.c +++ b/gawkapi.c @@ -31,6 +31,7 @@ extern INSTRUCTION *main_beginfile; extern int currule; static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted); +static char *valtype2str(awk_valtype_t type); /* * api_get_argument --- get the count'th paramater, zero-based. @@ -515,9 +516,7 @@ node_to_awk_value(NODE *node, awk_value_t *val, awk_valtype_t wanted) break; case NUMBER: (void) force_string(node); - assign_string(node, val, AWK_STRNUM); - ret = awk_true; - break; + /* fall through */ case NUMBER|USER_INPUT: assign_string(node, val, AWK_STRNUM); ret = awk_true; @@ -1090,7 +1089,7 @@ api_clear_array(awk_ext_id_t id, awk_array_t a_cookie) return awk_true; } -/* api_flatten_array --- flatten out an array so that it can be looped over easily. */ +/* api_flatten_array_typed --- flatten out an array so that it can be looped over easily. */ static awk_bool_t api_flatten_array_typed(awk_ext_id_t id, @@ -1128,34 +1127,21 @@ api_flatten_array_typed(awk_ext_id_t id, index = list[i]; value = list[i + 1]; /* number or string or subarray */ - /* Convert index and value to ext types. */ + /* Convert index and value to API types. */ if (! node_to_awk_value(index, & (*data)->elements[j].index, index_type)) { - fatal(_("api_flatten_array_typed: could not convert index %d to %d\n"), - (int) i, (int) index_type); + fatal(_("api_flatten_array_typed: could not convert index %d to %s\n"), + (int) i, valtype2str(index_type)); } if (! node_to_awk_value(value, & (*data)->elements[j].value, value_type)) { - fatal(_("api_flatten_array_typed: could not convert value %d to %d\n"), - (int) i, (int) value_type); + fatal(_("api_flatten_array_typed: could not convert value %d to %s\n"), + (int) i, valtype2str(value_type)); } } return awk_true; } -/* - * api_flatten_array -- replaced by api_flatten_array_typed. This function - * is retained only for binary compatibility. - */ - -static awk_bool_t -api_flatten_array(awk_ext_id_t id, - awk_array_t a_cookie, - awk_flat_array_t **data) -{ - return api_flatten_array_typed(id, a_cookie, data, AWK_STRING, AWK_UNDEFINED); -} - /* * api_release_flattened_array --- release array memory, * delete any marked elements. Count must match what @@ -1375,6 +1361,7 @@ gawk_api_t api_impl = { api_fatal, api_warning, api_lintwarn, + api_nonfatal, /* updating ERRNO */ api_update_ERRNO_int, @@ -1404,7 +1391,7 @@ gawk_api_t api_impl = { api_del_array_element, api_create_array, api_clear_array, - api_flatten_array, /* for legacy binary compatibility */ + api_flatten_array_typed, api_release_flattened_array, /* Memory allocation */ @@ -1415,12 +1402,6 @@ gawk_api_t api_impl = { /* Find/open a file */ api_get_file, - - /* Print nonfatal error message */ - api_nonfatal, - - /* New array flattening function */ - api_flatten_array_typed, }; /* init_ext_api --- init the extension API */ @@ -1455,3 +1436,30 @@ print_ext_versions(void) for (p = vi_head; p != NULL; p = p->next) printf("%s\n", p->version); } + +/* valtype2str --- return a printable representation of a value type */ + +static char * +valtype2str(awk_valtype_t type) +{ + static char buf[100]; + + // Important: keep in same order as in gawkapi.h! + static char *values[] = { + "AWK_UNDEFINED", + "AWK_NUMBER", + "AWK_STRING", + "AWK_REGEX", + "AWK_STRNUM", + "AWK_ARRAY", + "AWK_SCALAR", + "AWK_VALUE_COOKIE", + }; + + if (AWK_UNDEFINED <= type && type <= AWK_VALUE_COOKIE) + return values[(int) type]; + + sprintf(buf, "unknown type! (%d)", (int) type); + + return buf; +} -- cgit v1.2.3