diff options
author | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2021-12-08 14:07:00 -0500 |
---|---|---|
committer | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2021-12-08 14:07:00 -0500 |
commit | c4b80d4a006d3cbcce3aaca1c598a094de936f8b (patch) | |
tree | 0444a9dacd4482fc568fddd7a45834618d8eb841 | |
parent | 322381086cf947e540e454bd427c214b1eaf6ed1 (diff) | |
download | egawk-c4b80d4a006d3cbcce3aaca1c598a094de936f8b.tar.gz egawk-c4b80d4a006d3cbcce3aaca1c598a094de936f8b.tar.bz2 egawk-c4b80d4a006d3cbcce3aaca1c598a094de936f8b.zip |
Patch API to allow extensions to convert undefined variables to arrays, and add a test case.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | extension/ChangeLog | 9 | ||||
-rw-r--r-- | extension/testext.c | 77 | ||||
-rw-r--r-- | gawkapi.c | 6 | ||||
-rw-r--r-- | pc/ChangeLog | 4 | ||||
-rw-r--r-- | pc/Makefile.tst | 8 | ||||
-rw-r--r-- | test/ChangeLog | 8 | ||||
-rw-r--r-- | test/Makefile.am | 8 | ||||
-rw-r--r-- | test/Makefile.in | 8 | ||||
-rw-r--r-- | test/testext-mpfr.ok | 2 | ||||
-rw-r--r-- | test/testext.ok | 2 |
11 files changed, 123 insertions, 17 deletions
@@ -1,3 +1,11 @@ +2021-12-08 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * gawkapi.c (api_sym_update): Allow undefined Node_var_new variables + to be converted to arrays, otherwise API functions have no way + of creating an array that is referenced in an undefined fashion in + the program. This is somewhat comparable to how the set_argument + API allows an undefined argument variable to be converted to an array. + 2021-12-02 Andrew J. Schorr <aschorr@telemetry-investments.com> * builtin.c (efwrite): Don't use return in call of function diff --git a/extension/ChangeLog b/extension/ChangeLog index 15a2f5b1..03391534 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -1,5 +1,14 @@ 2021-12-08 Andrew J. Schorr <aschorr@telemetry-investments.com> + * testext.c (test_array_create): New function to create an array + by name that enables testing whether an undefined variable can + be converted by the API into an array. + (populate_array): New helper function. + (fill_in_array): Use populate_array to fill in the elements. + (func_table): Add test_array_create. + +2021-12-08 Andrew J. Schorr <aschorr@telemetry-investments.com> + * rwarray.c (write_number): Since mpfr_fpif_export is experimental and not available in older versions of mpfr, add an ifdef to use mpfr_out_str instead. diff --git a/extension/testext.c b/extension/testext.c index bfaa8637..18465f2a 100644 --- a/extension/testext.c +++ b/extension/testext.c @@ -48,6 +48,7 @@ static const char *ext_version = "testext extension: version 1.0"; int plugin_is_GPL_compatible; static void fill_in_array(awk_value_t *value); +static int populate_array(awk_array_t); #ifdef __MINGW32__ unsigned int @@ -666,6 +667,54 @@ out: } /* +function tfunc(f) { + if (isarray(f)) + print "good: we have an array" +} + +BEGIN { + printf "test_array_create returned %d\n", test_array_create("testarr") + tfunc(testarr) +} +*/ + +static awk_value_t * +test_array_create(int nargs, awk_value_t *result, struct awk_ext_func *unused) +{ + awk_value_t new_array; + awk_value_t arg0; + + (void) nargs; /* silence warnings */ + make_number(0.0, result); + + if (! get_argument(0, AWK_STRING, & arg0)) { + printf("test_array_create: could not get argument\n"); + goto out; + } + + if (arg0.val_type != AWK_STRING) { + printf("test_array_create: argument is not string (%d)\n", + arg0.val_type); + goto out; + } + + new_array.val_type = AWK_ARRAY; + new_array.array_cookie = create_array(); + if (! sym_update(arg0.str_value.str, & new_array)) { + printf("test_array_create: sym_update(\"%s\") failed!\n", arg0.str_value.str); + goto out; + } + if (populate_array(new_array.array_cookie) < 0) { + printf("test_array_create: populate(\"%s\") failed!\n", arg0.str_value.str); + goto out; + } + + make_number(1.0, result); +out: + return result; +} + +/* BEGIN { printf("Initial value of LINT is %d\n", LINT) ret = print_do_lint(); @@ -958,29 +1007,40 @@ do_get_file(int nargs, awk_value_t *result, struct awk_ext_func *unused) return make_number(1.0, result); } -/* fill_in_array --- fill in a new array */ +/* populate_array --- fill in some array values */ -static void -fill_in_array(awk_value_t *new_array) +static int +populate_array(awk_array_t a_cookie) { - awk_array_t a_cookie; awk_value_t index, value; - a_cookie = create_array(); - (void) make_const_string("hello", 5, & index); (void) make_const_string("world", 5, & value); if (! set_array_element(a_cookie, & index, & value)) { printf("fill_in_array:%d: set_array_element failed\n", __LINE__); - return; + return -1; } (void) make_const_string("answer", 6, & index); (void) make_number(42.0, & value); if (! set_array_element(a_cookie, & index, & value)) { printf("fill_in_array:%d: set_array_element failed\n", __LINE__); - return; + return -1; } + return 0; +} + +/* fill_in_array --- fill in a new array */ + +static void +fill_in_array(awk_value_t *new_array) +{ + awk_array_t a_cookie; + + a_cookie = create_array(); + + if (populate_array(a_cookie) < 0) + return; new_array->val_type = AWK_ARRAY; new_array->array_cookie = a_cookie; @@ -1061,6 +1121,7 @@ static awk_ext_func_t func_table[] = { { "test_array_size", test_array_size, 1, 1, awk_false, NULL }, { "test_array_elem", test_array_elem, 2, 2, awk_false, NULL }, { "test_array_param", test_array_param, 1, 1, awk_false, NULL }, + { "test_array_create", test_array_create, 1, 1, awk_false, NULL }, { "print_do_lint", print_do_lint, 0, 0, awk_false, NULL }, { "test_scalar", test_scalar, 1, 1, awk_false, NULL }, { "test_scalar_reserved", test_scalar_reserved, 0, 0, awk_false, NULL }, @@ -881,7 +881,8 @@ api_sym_update(awk_ext_id_t id, /* * If we get here, then it exists already. Any valid type is - * OK except for AWK_ARRAY. + * OK except for AWK_ARRAY (unless it is in Node_var_new undefined + * state, in which case an array is OK). */ if ( (node->flags & NO_EXT_SET) != 0 || is_off_limits_var(full_name)) { /* most built-in vars not allowed */ @@ -892,8 +893,7 @@ api_sym_update(awk_ext_id_t id, efree((void *) full_name); - if ( value->val_type != AWK_ARRAY - && (node->type == Node_var || node->type == Node_var_new)) { + if ((node->type == Node_var && value->val_type != AWK_ARRAY) || node->type == Node_var_new) { unref(node->var_value); node->var_value = awk_value_to_node(value); if (node->type == Node_var_new && value->val_type != AWK_UNDEFINED) diff --git a/pc/ChangeLog b/pc/ChangeLog index d1acbf50..951b7d53 100644 --- a/pc/ChangeLog +++ b/pc/ChangeLog @@ -1,3 +1,7 @@ +2021-12-08 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * Makefile.tst: Regenerated. + 2021-12-01 Arnold D. Robbins <arnold@skeeve.com> * gawkmisc.pc (os_maybe_set_errno): Renamed from diff --git a/pc/Makefile.tst b/pc/Makefile.tst index f76a38cf..a25aec77 100644 --- a/pc/Makefile.tst +++ b/pc/Makefile.tst @@ -1025,7 +1025,7 @@ inplace3bcomp:: testext:: @echo $@ - @-$(AWK) ' /^(@load|BEGIN)/,/^}/' "$(top_srcdir)"/extension/testext.c > testext.awk + @-$(AWK) ' /^(@load|BEGIN|function)/,/^}/' "$(top_srcdir)"/extension/testext.c > testext.awk @-$(AWK) -f ./testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-if echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null; \ then $(CMP) "$(srcdir)"/$@-mpfr.ok _$@ && rm -f _$@ testext.awk testexttmp.txt ; \ @@ -3678,7 +3678,11 @@ diffout: if [ "$$i" != "_*" ]; then \ echo ============== $$i ============= ; \ base=`echo $$i | sed 's/^_//'` ; \ - if [ -r $${base}.ok ]; then \ + if echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null && [ -r $${base}-mpfr.ok ]; then \ + diff -u $${base}-mpfr.ok $$i ; \ + elif echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null && [ -r "$(srcdir)"/$${base}-mpfr.ok ]; then \ + diff -u "$(srcdir)"/$${base}-mpfr.ok $$i ; \ + elif [ -r $${base}.ok ]; then \ diff -u $${base}.ok $$i ; \ else \ diff -u "$(srcdir)"/$${base}.ok $$i ; \ diff --git a/test/ChangeLog b/test/ChangeLog index 034cc63b..67637641 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,11 @@ +2021-12-08 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * Makefile.am (testext): Change awk pattern to include functions in + testext.awk. + (diffout): If running MPFR tests and there's an mpfr.ok file, compare + to that instead of to the regular ok file. + * testext.ok, testext-mpfr.ok: Update for new test_array_create test. + 2021-12-07 Andrew J. Schorr <aschorr@telemetry-investments.com> * iolint.awk, iolint.ok: Reorder "cat" pipe/output file test to reduce diff --git a/test/Makefile.am b/test/Makefile.am index 10c5c812..f9cdfd40 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -2281,7 +2281,7 @@ inplace3bcomp:: testext:: @echo $@ - @-$(AWK) ' /^(@load|BEGIN)/,/^}/' "$(top_srcdir)"/extension/testext.c > testext.awk + @-$(AWK) ' /^(@load|BEGIN|function)/,/^}/' "$(top_srcdir)"/extension/testext.c > testext.awk @-$(AWK) -f ./testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-if echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null; \ then $(CMP) "$(srcdir)"/$@-mpfr.ok _$@ && rm -f _$@ testext.awk testexttmp.txt ; \ @@ -2518,7 +2518,11 @@ diffout: if [ "$$i" != "_*" ]; then \ echo ============== $$i ============= ; \ base=`echo $$i | sed 's/^_//'` ; \ - if [ -r $${base}.ok ]; then \ + if echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null && [ -r $${base}-mpfr.ok ]; then \ + diff -u $${base}-mpfr.ok $$i ; \ + elif echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null && [ -r "$(srcdir)"/$${base}-mpfr.ok ]; then \ + diff -u "$(srcdir)"/$${base}-mpfr.ok $$i ; \ + elif [ -r $${base}.ok ]; then \ diff -u $${base}.ok $$i ; \ else \ diff -u "$(srcdir)"/$${base}.ok $$i ; \ diff --git a/test/Makefile.in b/test/Makefile.in index 6144e749..a4d27586 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -2735,7 +2735,7 @@ inplace3bcomp:: testext:: @echo $@ - @-$(AWK) ' /^(@load|BEGIN)/,/^}/' "$(top_srcdir)"/extension/testext.c > testext.awk + @-$(AWK) ' /^(@load|BEGIN|function)/,/^}/' "$(top_srcdir)"/extension/testext.c > testext.awk @-$(AWK) -f ./testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-if echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null; \ then $(CMP) "$(srcdir)"/$@-mpfr.ok _$@ && rm -f _$@ testext.awk testexttmp.txt ; \ @@ -5345,7 +5345,11 @@ diffout: if [ "$$i" != "_*" ]; then \ echo ============== $$i ============= ; \ base=`echo $$i | sed 's/^_//'` ; \ - if [ -r $${base}.ok ]; then \ + if echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null && [ -r $${base}-mpfr.ok ]; then \ + diff -u $${base}-mpfr.ok $$i ; \ + elif echo "$$GAWK_TEST_ARGS" | egrep -e '-M|--bignum' > /dev/null && [ -r "$(srcdir)"/$${base}-mpfr.ok ]; then \ + diff -u "$(srcdir)"/$${base}-mpfr.ok $$i ; \ + elif [ -r $${base}.ok ]; then \ diff -u $${base}.ok $$i ; \ else \ diff -u "$(srcdir)"/$${base}.ok $$i ; \ diff --git a/test/testext-mpfr.ok b/test/testext-mpfr.ok index 2c616c67..ec584216 100644 --- a/test/testext-mpfr.ok +++ b/test/testext-mpfr.ok @@ -48,6 +48,8 @@ test_array_param: argument is not undefined (1) test_array_param() returned 0 isarray(a_scalar) = 0 +test_array_create returned 1 +good: we have an array Initial value of LINT is 0 print_do_lint: lint = 0 print_do_lint() returned 1 diff --git a/test/testext.ok b/test/testext.ok index fbc3c263..1d058302 100644 --- a/test/testext.ok +++ b/test/testext.ok @@ -48,6 +48,8 @@ test_array_param: argument is not undefined (1) test_array_param() returned 0 isarray(a_scalar) = 0 +test_array_create returned 1 +good: we have an array Initial value of LINT is 0 print_do_lint: lint = 0 print_do_lint() returned 1 |