diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2012-07-12 22:45:25 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2012-07-12 22:45:25 +0300 |
commit | 28daef44c3c08f16002c678319a30b816f6972fd (patch) | |
tree | 5bb3ed751db1d4c32b71a72e2fc87c52e1f46de9 | |
parent | 4319d9141a56cb8ed878d44d0e74bedee51085a6 (diff) | |
download | egawk-28daef44c3c08f16002c678319a30b816f6972fd.tar.gz egawk-28daef44c3c08f16002c678319a30b816f6972fd.tar.bz2 egawk-28daef44c3c08f16002c678319a30b816f6972fd.zip |
Allow creation of constants from extensions.
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | extension/ChangeLog | 3 | ||||
-rw-r--r-- | extension/fnmatch.c | 2 | ||||
-rw-r--r-- | extension/testext.c | 4 | ||||
-rw-r--r-- | gawkapi.c | 42 | ||||
-rw-r--r-- | gawkapi.h | 12 | ||||
-rw-r--r-- | test/ChangeLog | 3 | ||||
-rw-r--r-- | test/Makefile.am | 13 | ||||
-rw-r--r-- | test/Makefile.in | 13 | ||||
-rw-r--r-- | test/assignconst.awk | 58 | ||||
-rw-r--r-- | test/assignconst.ok | 42 |
11 files changed, 194 insertions, 10 deletions
@@ -1,3 +1,15 @@ +2012-07-12 Arnold D. Robbins <arnold@skeeve.com> + + Allow creation of constants. Thanks to John Haque for the + implementation concept. + + * gawk_api.h (api_sym_constant): Create a constant. + * gawk_api.h (api_sym_update_real): Renamed from api_sym_update. + Add is_const paramater and do the right thing if true. + (api_sym_update, api_sym_constant): Call api_sym_update_real + in the correct way. + (set_constant): New function. + 2012-07-11 Andrew J. Schorr <aschorr@telemetry-investments.com> * gawkapi.h: Fix typo in comment. diff --git a/extension/ChangeLog b/extension/ChangeLog index 4eab7d7a..ce8d6b78 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -4,6 +4,9 @@ * Makefile.am: Build fnmatch extension. * configure.ac: Look for fnmatch.h and fnmatch function. + * fnmatch.c (init_fnmatch): Use sym_constant for FNM_NOMATCH. + * testext.c (dl_load): Use sym_constant for answer_num. + 2012-07-11 Arnold D. Robbins <arnold@skeeve.com> * filefuncs.c (array_set, do_stat): Use make_const_string. diff --git a/extension/fnmatch.c b/extension/fnmatch.c index 7f050dcd..aa8a7307 100644 --- a/extension/fnmatch.c +++ b/extension/fnmatch.c @@ -137,7 +137,7 @@ init_fnmatch(void) awk_array_t new_array; int i; - if (! sym_update("FNM_NOMATCH", make_number(FNM_NOMATCH, & value))) { + if (! sym_constant("FNM_NOMATCH", make_number(FNM_NOMATCH, & value))) { warning(ext_id, "fnmatch init: could not add FNM_NOMATCH variable"); errors++; } diff --git a/extension/testext.c b/extension/testext.c index d446fb8e..dc3002a9 100644 --- a/extension/testext.c +++ b/extension/testext.c @@ -623,8 +623,8 @@ BEGIN { */ /* install some variables */ - if (! sym_update("answer_num", make_number(42, & value))) - printf("testext: sym_update(\"answer_num\") failed!\n"); + if (! sym_constant("answer_num", make_number(42, & value))) + printf("testext: sym_constant(\"answer_num\") failed!\n"); if (! sym_update("message_string", make_const_string(message, strlen(message), & value))) @@ -26,6 +26,7 @@ #include "awk.h" static awk_bool_t node_to_awk_value(NODE *node, awk_value_t *result, awk_valtype_t wanted); +static void set_constant(); /* * Get the count'th paramater, zero-based. @@ -460,10 +461,13 @@ api_sym_lookup_scalar(awk_ext_id_t id, return node_to_awk_value(node, result, wanted); } -/* api_sym_update --- update a symbol's value, see gawkapi.h for semantics */ +/* api_sym_update_real --- update a symbol's value, see gawkapi.h for semantics */ static awk_bool_t -api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) +sym_update_real(awk_ext_id_t id, + const char *name, + awk_value_t *value, + bool is_const) { NODE *node; NODE *array_node; @@ -503,6 +507,8 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) Node_var); unref(node->var_value); node->var_value = awk_value_to_node(value); + if (is_const) + node->var_assign = set_constant; } return true; } @@ -518,6 +524,9 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) if (node->type == Node_var || node->type == Node_var_new) { unref(node->var_value); node->var_value = awk_value_to_node(value); + /* let the extension change its own variable */ + if (is_const) + node->var_assign = set_constant; } else { return false; } @@ -530,6 +539,26 @@ api_sym_update(awk_ext_id_t id, const char *name, awk_value_t *value) return true; } +/* api_sym_update --- update a symbol, non-constant */ + +static awk_bool_t +api_sym_update(awk_ext_id_t id, + const char *name, + awk_value_t *value) +{ + return sym_update_real(id, name, value, false); +} + +/* api_sym_update --- update a symbol, constant */ + +static awk_bool_t +api_sym_constant(awk_ext_id_t id, + const char *name, + awk_value_t *value) +{ + return sym_update_real(id, name, value, true); +} + /* api_sym_update_scalar --- update a scalar cookie */ static awk_bool_t @@ -864,6 +893,7 @@ gawk_api_t api_impl = { api_sym_lookup, api_sym_lookup_scalar, api_sym_update, + api_sym_constant, api_sym_update_scalar, api_get_array_element, @@ -897,3 +927,11 @@ update_ext_api() { api_impl.do_flags[0] = (do_lint ? 1 : 0); } + +/* set_constant --- prevent awk code from changing a constant */ + +static void +set_constant() +{ + fatal(_("cannot assign to defined constant")); +} @@ -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) diff --git a/test/ChangeLog b/test/ChangeLog index 019d2f34..50dcd27c 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -3,6 +3,9 @@ * Makefile.am (fnmatch): New test. * fnmatch.awk, fnmatch.ok: New files. + * Makefile.am (assignconst): New test. + * assignconst.awk, assignconst.ok: New files. + 2012-06-28 Andrew J. Schorr <aschorr@telemetry-investments.com> * time.awk: Avoid possibly throwing a spurious error by protecting diff --git a/test/Makefile.am b/test/Makefile.am index a244c6a0..78fd3117 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -102,6 +102,8 @@ EXTRA_DIST = \ asort.ok \ asorti.awk \ asorti.ok \ + assignconst.awk \ + assignconst.ok \ awkpath.ok \ back89.awk \ back89.in \ @@ -891,8 +893,8 @@ LOCALE_CHARSET_TESTS = \ mbprintf1 mbprintf2 mbprintf3 rebt8b2 rtlenmb sort1 sprintfc SHLIB_TESTS = \ - fnmatch filefuncs fork fork2 ordchr ordchr2 readfile rwarray \ - testext time + assignconst fnmatch filefuncs fork fork2 ordchr ordchr2 \ + readfile rwarray testext time # List of the tests which should be run with --lint option: NEED_LINT = \ @@ -1594,6 +1596,13 @@ testext:: @$(AWK) -f testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ testext.awk +assignconst: + @echo $@ + @for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14; \ + do $(AWK) -f $(srcdir)/$@.awk $$i ; \ + done 2>&1 | grep -v at_exit > _$@ + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + # Targets generated for other tests: include Maketests diff --git a/test/Makefile.in b/test/Makefile.in index 61e32b1b..d12139cf 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -314,6 +314,8 @@ EXTRA_DIST = \ asort.ok \ asorti.awk \ asorti.ok \ + assignconst.awk \ + assignconst.ok \ awkpath.ok \ back89.awk \ back89.in \ @@ -1099,8 +1101,8 @@ LOCALE_CHARSET_TESTS = \ mbprintf1 mbprintf2 mbprintf3 rebt8b2 rtlenmb sort1 sprintfc SHLIB_TESTS = \ - fnmatch filefuncs fork fork2 ordchr ordchr2 readfile rwarray \ - testext time + assignconst fnmatch filefuncs fork fork2 ordchr ordchr2 \ + readfile rwarray testext time # List of the tests which should be run with --lint option: @@ -1975,6 +1977,13 @@ testext:: @$(AWK) '/^(@load|BEGIN)/,/^}/' $(top_srcdir)/extension/testext.c > testext.awk @$(AWK) -f testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ testext.awk + +assignconst: + @echo $@ + @for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14; \ + do $(AWK) -f $(srcdir)/$@.awk $$i ; \ + done 2>&1 | grep -v at_exit > _$@ + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ Gt-dummy: # file Maketests, generated from Makefile.am by the Gentests program addcomma: diff --git a/test/assignconst.awk b/test/assignconst.awk new file mode 100644 index 00000000..907987c7 --- /dev/null +++ b/test/assignconst.awk @@ -0,0 +1,58 @@ +@load "testext" + +BEGIN { + print "" + print "test:", ARGV[1] + switch (ARGV[1] + 0) { + case 1: + answer_num = 43 + break + case 2: + ++answer_num + break + case 3: + --answer_num + break + case 4: + answer_num++ + break + case 5: + answer_num-- + break + case 6: + answer_num += 1 + break + case 7: + answer_num -= 1 + break + case 8: + answer_num *= 1 + break + case 9: + answer_num /= 1 + break + case 10: + answer_num ^= 1 + break + case 11: + answer_num = answer_num "foo" + break + case 12: + sub(/2/, "3", answer_num) + break + case 13: + a[1] = 1 + for (answer_num in a) + print answer_num, a[answer_num] + break + case 14: + test_func(answer_num) + break + } +} + +function test_func(val) +{ + val++ + print "in test_func, val now =", val +} diff --git a/test/assignconst.ok b/test/assignconst.ok new file mode 100644 index 00000000..e2bc7494 --- /dev/null +++ b/test/assignconst.ok @@ -0,0 +1,42 @@ + +test: 1 +gawk: ./assignconst.awk:8: fatal: cannot assign to defined constant + +test: 2 +gawk: ./assignconst.awk:11: fatal: cannot assign to defined constant + +test: 3 +gawk: ./assignconst.awk:14: fatal: cannot assign to defined constant + +test: 4 +gawk: ./assignconst.awk:17: fatal: cannot assign to defined constant + +test: 5 +gawk: ./assignconst.awk:20: fatal: cannot assign to defined constant + +test: 6 +gawk: ./assignconst.awk:23: fatal: cannot assign to defined constant + +test: 7 +gawk: ./assignconst.awk:26: fatal: cannot assign to defined constant + +test: 8 +gawk: ./assignconst.awk:29: fatal: cannot assign to defined constant + +test: 9 +gawk: ./assignconst.awk:32: fatal: cannot assign to defined constant + +test: 10 +gawk: ./assignconst.awk:35: fatal: cannot assign to defined constant + +test: 11 +gawk: ./assignconst.awk:38: fatal: cannot assign to defined constant + +test: 12 +gawk: ./assignconst.awk:41: fatal: cannot assign to defined constant + +test: 13 +gawk: ./assignconst.awk:45: fatal: cannot assign to defined constant + +test: 14 +in test_func, val now = 43 |