diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2012-09-14 00:16:48 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2012-09-14 00:16:48 +0300 |
commit | fc9109734ddcf57c5f1faaedfadc432ec6841aa8 (patch) | |
tree | 476ccba6d5a68fea0da94f69783e6284db155371 | |
parent | 99290f5ca37cb905f7f1dab9be416b2e2057d243 (diff) | |
download | egawk-fc9109734ddcf57c5f1faaedfadc432ec6841aa8.tar.gz egawk-fc9109734ddcf57c5f1faaedfadc432ec6841aa8.tar.bz2 egawk-fc9109734ddcf57c5f1faaedfadc432ec6841aa8.zip |
Allow extensions read-only access to built-in vars.
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | awk.h | 1 | ||||
-rw-r--r-- | extension/ChangeLog | 6 | ||||
-rw-r--r-- | extension/testext.c | 151 | ||||
-rw-r--r-- | gawkapi.c | 19 | ||||
-rw-r--r-- | gawkapi.h | 10 | ||||
-rw-r--r-- | test/ChangeLog | 4 | ||||
-rw-r--r-- | test/testext.ok | 11 |
8 files changed, 202 insertions, 11 deletions
@@ -1,3 +1,14 @@ +2012-09-14 Arnold D. Robbins <arnold@skeeve.com> + + Allow read-only access to built-in variables from extensions. + + * awk.h (NO_EXT_SET): New flag. + * gawkapi.c (api_sym_lookup, api_sym_update_real): Set flag if off + limits variable instead of failing. Adjust logic. + (api_sym_update_scalar, api_set_array_element, api_del_array_element, + api_release_flattened_array): Adjust logic. + * gawkapi.h: Adjust documentation. + 2012-09-13 Arnold D. Robbins <arnold@skeeve.com> * configure.ac: Determination of DYNAMIC adjusted. Hopefully is @@ -447,6 +447,7 @@ typedef struct exp_node { # define WSTRCUR 0x0400 /* wide str value is current */ # define MPFN 0x0800 /* arbitrary-precision floating-point number */ # define MPZN 0x1000 /* arbitrary-precision integer */ +# define NO_EXT_SET 0x2000 /* extension cannot set a value for this variable */ /* type = Node_var_array */ # define ARRAYMAXED 0x2000 /* array is at max size */ diff --git a/extension/ChangeLog b/extension/ChangeLog index 1a32961a..2552a383 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -1,3 +1,9 @@ +2012-09-14 Arnold D. Robbins <arnold@skeeve.com> + + * testext.c (try_modify_environ): New function and test. + (var_test): Modified ARGC test, added additional. + (test_scalar_reserved): New function and test. + 2012-09-13 Dave Pitts <dpitts@cozx.com> * gawkfts.c: Add defines and ifdefs for z/OS. diff --git a/extension/testext.c b/extension/testext.c index bb62fa01..c11a4c85 100644 --- a/extension/testext.c +++ b/extension/testext.c @@ -186,6 +186,101 @@ out: /* BEGIN { + ENVIRON["testext"]++ + try_modify_environ() + if ("testext" in ENVIRON) + print "try_del_environ() could not delete element - pass" + else + print "try_del_environ() deleted element! - fail" + if ("testext2" in ENVIRON) + print "try_del_environ() added an element - fail" + else + print "try_del_environ() could not add an element - pass" +} +*/ + +static awk_value_t * +try_modify_environ(int nargs, awk_value_t *result) +{ + awk_value_t value, index, newvalue; + awk_flat_array_t *flat_array; + size_t count; + int i; + + assert(result != NULL); + make_number(0.0, result); + + if (nargs != 0) { + printf("try_modify_environ: nargs not right (%d should be 0)\n", nargs); + goto out; + } + + /* get ENVIRON array */ + if (sym_lookup("ENVIRON", AWK_ARRAY, & value)) + printf("try_modify_environ: sym_lookup of ENVIRON passed\n"); + else { + printf("try_modify_environ: sym_lookup of ENVIRON failed\n"); + goto out; + } + + if (! get_element_count(value.array_cookie, & count)) { + printf("try_modify_environ: get_element_count failed\n"); + goto out; + } + + printf("try_modify_environ: incoming size is %lu\n", (unsigned long) count); + + /* setting an array element should fail */ + (void) make_const_string("testext2", 8, & index); + (void) make_const_string("a value", 7, & value); + if (set_array_element(value.array_cookie, & index, & newvalue)) { + printf("try_modify_environ: set_array_element of ENVIRON passed\n"); + } else { + printf("try_modify_environ: set_array_element of ENVIRON failed\n"); + free(index.str_value.str); + free(value.str_value.str); + } + + if (! flatten_array(value.array_cookie, & flat_array)) { + printf("try_modify_environ: could not flatten array\n"); + goto out; + } + + if (flat_array->count != count) { + printf("try_modify_environ: flat_array->count (%lu) != count (%lu)\n", + (unsigned long) flat_array->count, + (unsigned long) count); + goto out; + } + + for (i = 0; i < flat_array->count; i++) { + /* don't print */ + /* + printf("\t%s[\"%.*s\"] = %s\n", + name, + (int) flat_array->elements[i].index.str_value.len, + flat_array->elements[i].index.str_value.str, + valrep2str(& flat_array->elements[i].value)); + */ + if (strcmp("testext", flat_array->elements[i].index.str_value.str) == 0) { + flat_array->elements[i].flags |= AWK_ELEMENT_DELETE; + printf("try_modify_environ: marking element \"%s\" for deletion\n", + flat_array->elements[i].index.str_value.str); + } + } + + if (! release_flattened_array(value.array_cookie, flat_array)) { + printf("try_modify_environ: could not release flattened array\n"); + goto out; + } + + make_number(1.0, result); +out: + return result; +} + +/* +BEGIN { testvar = "One Adam Twelve" ret = var_test("testvar") printf "var_test() returned %d, test_var = %s\n", ret, testvar @@ -207,11 +302,18 @@ var_test(int nargs, awk_value_t *result) goto out; } - /* look up a reserved variable - should fail */ + /* look up a reserved variable - should pass */ if (sym_lookup("ARGC", AWK_NUMBER, & value)) - printf("var_test: sym_lookup of ARGC failed - got a value!\n"); + printf("var_test: sym_lookup of ARGC passed - got a value!\n"); + else + printf("var_test: sym_lookup of ARGC failed - did not get a value\n"); + + /* now try to set it - should fail */ + value.num_value++; + if (sym_update("ARGC", & value)) + printf("var_test: sym_update of ARGC passed and should not have!\n"); else - printf("var_test: sym_lookup of ARGC passed - did not get a value\n"); + printf("var_test: sym_update of ARGC failed - correctly\n"); /* look up variable whose name is passed in, should pass */ if (get_argument(0, AWK_STRING, & value)) { @@ -535,6 +637,47 @@ test_scalar(int nargs, awk_value_t *result) } if (! sym_update_scalar(the_scalar.scalar_cookie, & new_value2)) { + printf("test_scalar: could not update new_value2!\n"); + goto out; + } + + make_number(1.0, result); + +out: + return result; +} + +/* +BEGIN { + test_scalar_reserved() +} +*/ + +/* test_scalar_reserved --- test scalar cookie on special variable */ + +static awk_value_t * +test_scalar_reserved(int nargs, awk_value_t *result) +{ + awk_value_t new_value; + awk_value_t the_scalar; + + make_number(0.0, result); + + /* look up a reserved variable - should pass */ + if (sym_lookup("ARGC", AWK_SCALAR, & the_scalar)) { + printf("test_scalar_reserved: sym_lookup of ARGC passed - got a value!\n"); + } else { + printf("test_scalar_reserved: sym_lookup of ARGC failed - did not get a value\n"); + goto out; + } + + /* updating it should fail */ + make_number(42.0, & new_value); + if (! sym_update_scalar(the_scalar.scalar_cookie, & new_value)) { + printf("test_scalar_reserved: could not update new_value2 for ARGC - pass\n"); + } else { + printf("test_scalar_reserved: was able to update new_value2 for ARGC - fail\n"); + goto out; } make_number(1.0, result); @@ -628,6 +771,7 @@ static void at_exit2(void *data, int exit_status) static awk_ext_func_t func_table[] = { { "dump_array_and_delete", dump_array_and_delete, 2 }, + { "try_modify_environ", try_modify_environ, 0 }, { "var_test", var_test, 1 }, { "test_errno", test_errno, 0 }, { "test_array_size", test_array_size, 1 }, @@ -635,6 +779,7 @@ static awk_ext_func_t func_table[] = { { "test_array_param", test_array_param, 1 }, { "print_do_lint", print_do_lint, 0 }, { "test_scalar", test_scalar, 1 }, + { "test_scalar_reserved", test_scalar_reserved, 0 }, }; /* init_testext --- additional initialization function */ @@ -489,10 +489,12 @@ api_sym_lookup(awk_ext_id_t id, if ( name == NULL || *name == '\0' || result == NULL - || is_off_limits_var(name) /* most built-in vars not allowed */ || (node = lookup(name)) == NULL) return false; + if (is_off_limits_var(name)) /* a built-in variable */ + node->flags |= NO_EXT_SET; + return node_to_awk_value(node, result, wanted); } @@ -527,7 +529,6 @@ sym_update_real(awk_ext_id_t id, if ( name == NULL || *name == '\0' - || is_off_limits_var(name) /* most built-in vars not allowed */ || value == NULL) return false; @@ -573,6 +574,12 @@ sym_update_real(awk_ext_id_t id, * If we get here, then it exists already. Any valid type is * OK except for AWK_ARRAY. */ + if ( (node->flags & NO_EXT_SET) != 0 + || is_off_limits_var(name)) { /* most built-in vars not allowed */ + node->flags |= NO_EXT_SET; + return false; + } + if ( value->val_type != AWK_ARRAY && (node->type == Node_var || node->type == Node_var_new)) { unref(node->var_value); @@ -618,7 +625,8 @@ api_sym_update_scalar(awk_ext_id_t id, if (value == NULL || node == NULL - || node->type != Node_var) + || node->type != Node_var + || (node->flags & NO_EXT_SET) != 0) return false; /* @@ -766,6 +774,7 @@ api_set_array_element(awk_ext_id_t id, awk_array_t a_cookie, /* don't check for index len zero, null str is ok as index */ if ( array == NULL || array->type != Node_var_array + || (array->flags & NO_EXT_SET) != 0 || index == NULL || value == NULL || ! valid_subscript_type(index->val_type)) @@ -825,6 +834,7 @@ api_del_array_element(awk_ext_id_t id, array = (NODE *) a_cookie; if ( array == NULL || array->type != Node_var_array + || (array->flags & NO_EXT_SET) != 0 || index == NULL || ! valid_subscript_type(index->val_type)) return false; @@ -957,7 +967,8 @@ api_release_flattened_array(awk_ext_id_t id, /* free index nodes */ for (i = j = 0, k = 2 * array->table_size; i < k; i += 2, j++) { /* Delete items flagged for delete. */ - if ((data->elements[j].flags & AWK_ELEMENT_DELETE) != 0) { + if ( (data->elements[j].flags & AWK_ELEMENT_DELETE) != 0 + && (array->flags & NO_EXT_SET) == 0) { remove_element(array, list[i]); } unref(list[i]); @@ -447,8 +447,8 @@ typedef struct gawk_api { * 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. + * Built-in variables may be accessed by an extension, but, with + * the exception of PROCINFO, they may not be modified. * * awk_value_t val; * if (! api->sym_lookup(id, name, wanted, & val)) @@ -495,13 +495,15 @@ typedef struct gawk_api { * Flow is * sym_lookup with wanted == AWK_SCALAR * if returns false - * sym_update with real initial value + * sym_update with real initial value to install it * 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. + * + * Here too, the built-in variables may not be updated. */ awk_bool_t (*api_sym_update_scalar)(awk_ext_id_t id, awk_scalar_t cookie, awk_value_t *value); @@ -522,6 +524,8 @@ typedef struct gawk_api { /* * Change (or create) element in existing array with * element->index and element->value. + * + * ARGV and ENVIRON may not be updated. */ awk_bool_t (*api_set_array_element)(awk_ext_id_t id, awk_array_t a_cookie, const awk_value_t *const index, diff --git a/test/ChangeLog b/test/ChangeLog index ff992365..4bab4796 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,7 @@ +2012-09-14 Arnold D. Robbins <arnold@skeeve.com> + + * testext.ok: Updated. + 2012-09-11 Arnold D. Robbins <arnold@skeeve.com> * Makefile.am (shlib-tests): Check if DYNAMIC is enabled and diff --git a/test/testext.ok b/test/testext.ok index 132179c2..d291f721 100644 --- a/test/testext.ok +++ b/test/testext.ok @@ -10,7 +10,14 @@ dump_array_and_delete: marking element "3" for deletion dump_array_and_delete(pets) returned 1 dump_array_and_delete() did remove index "3"! -var_test: sym_lookup of ARGC passed - did not get a value +try_modify_environ: sym_lookup of ENVIRON passed +try_modify_environ: incoming size is 60 +try_modify_environ: set_array_element of ENVIRON failed +try_modify_environ: could not flatten array +try_del_environ() could not delete element - pass +try_del_environ() could not add an element - pass +var_test: sym_lookup of ARGC passed - got a value! +var_test: sym_update of ARGC failed - correctly var_test: sym_update("testvar") succeeded var_test() returned 1, test_var = 42 @@ -57,6 +64,8 @@ test_scalar(over) returned 1, the_scalar is over test_scalar(the) returned 1, the_scalar is the test_scalar(lazy) returned 1, the_scalar is lazy test_scalar(dog) returned 1, the_scalar is dog +test_scalar_reserved: sym_lookup of ARGC passed - got a value! +test_scalar_reserved: could not update new_value2 for ARGC - pass answer_num = 42 message_string = hello, world new_array["hello"] = "world" |