aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--extension/ChangeLog3
-rw-r--r--extension/fnmatch.c2
-rw-r--r--extension/testext.c4
-rw-r--r--gawkapi.c42
-rw-r--r--gawkapi.h12
-rw-r--r--test/ChangeLog3
-rw-r--r--test/Makefile.am13
-rw-r--r--test/Makefile.in13
-rw-r--r--test/assignconst.awk58
-rw-r--r--test/assignconst.ok42
11 files changed, 194 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 04bd15d1..bd444d2b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)))
diff --git a/gawkapi.c b/gawkapi.c
index b6d83acb..e8d50e8c 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -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"));
+}
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)
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