gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gawk-diffs] [SCM] gawk branch, constants, created. 3450524c66dcb45083e7


From: Arnold Robbins
Subject: [gawk-diffs] [SCM] gawk branch, constants, created. 3450524c66dcb45083e755a10ee81bcf00ad1f28
Date: Mon, 04 Mar 2013 15:01:49 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, constants has been created
        at  3450524c66dcb45083e755a10ee81bcf00ad1f28 (commit)

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=3450524c66dcb45083e755a10ee81bcf00ad1f28

commit 3450524c66dcb45083e755a10ee81bcf00ad1f28
Author: Arnold D. Robbins <address@hidden>
Date:   Mon Mar 4 17:00:50 2013 +0200

    Add test and docs for sym_constant.

diff --git a/doc/ChangeLog b/doc/ChangeLog
index 34997fa..d535d21 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -2,6 +2,8 @@
 
        * gawk.texi (Getline/Pipe): Add a nice quote from BWK.
 
+       API doc: Restore sym_constant.
+
 2013-02-08         Arnold D. Robbins     <address@hidden>
 
        * gawk.texi: Restore centering of text images.
diff --git a/doc/gawk.info b/doc/gawk.info
index 25120dd..5695c7d 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -22578,6 +22578,21 @@ termed a "symbol table".
      an array.  This routine cannot be used to update any of the
      predefined variables (such as `ARGC' or `NF').
 
+`awk_bool_t sym_constant(const char *name, awk_value_t *value);'
+     Create a variable named by the string `name', which is a regular C
+     string, that has the constant value as given by `value'.
+     `awk'-level code cannot change the value of this variable.(1) The
+     extension may change the value of `name''s variable with
+     subsequent calls to this routine, and may also convert a variable
+     created by `sym_update()' into a constant.  However, once a
+     variable becomes a constant, it cannot later be reverted into a
+     mutable variable.
+
+   ---------- Footnotes ----------
+
+   (1) There (currently) is no `awk'-level feature that provides this
+ability.
+
 
 File: gawk.info,  Node: Symbol table by cookie,  Next: Cached values,  Prev: 
Symbol table by name,  Up: Symbol Table Access
 
@@ -32320,108 +32335,109 @@ Node: Updating `ERRNO'910686
 Node: Accessing Parameters911425
 Node: Symbol Table Access912655
 Node: Symbol table by name913167
-Node: Symbol table by cookie914740
-Ref: Symbol table by cookie-Footnote-1918869
-Node: Cached values918932
-Ref: Cached values-Footnote-1922375
-Node: Array Manipulation922466
-Ref: Array Manipulation-Footnote-1923564
-Node: Array Data Types923603
-Ref: Array Data Types-Footnote-1926306
-Node: Array Functions926398
-Node: Flattening Arrays930164
-Node: Creating Arrays937003
-Node: Extension API Variables941798
-Node: Extension Versioning942434
-Node: Extension API Informational Variables944335
-Node: Extension API Boilerplate945421
-Node: Finding Extensions949252
-Node: Extension Example949799
-Node: Internal File Description950537
-Node: Internal File Ops954225
-Ref: Internal File Ops-Footnote-1965672
-Node: Using Internal File Ops965812
-Ref: Using Internal File Ops-Footnote-1968165
-Node: Extension Samples968431
-Node: Extension Sample File Functions969955
-Node: Extension Sample Fnmatch978428
-Node: Extension Sample Fork980154
-Node: Extension Sample Inplace981372
-Node: Extension Sample Ord983164
-Node: Extension Sample Readdir983943
-Node: Extension Sample Revout985447
-Node: Extension Sample Rev2way986040
-Node: Extension Sample Read write array986730
-Node: Extension Sample Readfile988613
-Node: Extension Sample API Tests989370
-Node: Extension Sample Time989895
-Node: gawkextlib991202
-Node: Language History993583
-Node: V7/SVR3.1995105
-Node: SVR4997426
-Node: POSIX998868
-Node: BTL999876
-Node: POSIX/GNU1000681
-Node: Common Extensions1006216
-Node: Ranges and Locales1007323
-Ref: Ranges and Locales-Footnote-11011941
-Ref: Ranges and Locales-Footnote-21011968
-Ref: Ranges and Locales-Footnote-31012228
-Node: Contributors1012449
-Node: Installation1016745
-Node: Gawk Distribution1017639
-Node: Getting1018123
-Node: Extracting1018949
-Node: Distribution contents1020641
-Node: Unix Installation1025902
-Node: Quick Installation1026519
-Node: Additional Configuration Options1028481
-Node: Configuration Philosophy1029958
-Node: Non-Unix Installation1032300
-Node: PC Installation1032758
-Node: PC Binary Installation1034057
-Node: PC Compiling1035905
-Node: PC Testing1038849
-Node: PC Using1040025
-Node: Cygwin1044210
-Node: MSYS1045210
-Node: VMS Installation1045724
-Node: VMS Compilation1046327
-Ref: VMS Compilation-Footnote-11047334
-Node: VMS Installation Details1047392
-Node: VMS Running1049027
-Node: VMS Old Gawk1050634
-Node: Bugs1051108
-Node: Other Versions1054960
-Node: Notes1060290
-Node: Compatibility Mode1061090
-Node: Additions1061873
-Node: Accessing The Source1062800
-Node: Adding Code1064403
-Node: New Ports1070445
-Node: Derived Files1074580
-Ref: Derived Files-Footnote-11079901
-Ref: Derived Files-Footnote-21079935
-Ref: Derived Files-Footnote-31080535
-Node: Future Extensions1080633
-Node: Implementation Limitations1081214
-Node: Extension Design1082466
-Node: Old Extension Problems1083615
-Ref: Old Extension Problems-Footnote-11085123
-Node: Extension New Mechanism Goals1085180
-Ref: Extension New Mechanism Goals-Footnote-11088539
-Node: Extension Other Design Decisions1088725
-Node: Extension Future Growth1090831
-Node: Old Extension Mechansim1091652
-Node: Basic Concepts1093409
-Node: Basic High Level1094090
-Ref: figure-general-flow1094361
-Ref: figure-process-flow1094960
-Ref: Basic High Level-Footnote-11098189
-Node: Basic Data Typing1098374
-Node: Glossary1101729
-Node: Copying1127040
-Node: GNU Free Documentation License1164597
-Node: Index1189734
+Ref: Symbol table by name-Footnote-1915337
+Node: Symbol table by cookie915417
+Ref: Symbol table by cookie-Footnote-1919546
+Node: Cached values919609
+Ref: Cached values-Footnote-1923052
+Node: Array Manipulation923143
+Ref: Array Manipulation-Footnote-1924241
+Node: Array Data Types924280
+Ref: Array Data Types-Footnote-1926983
+Node: Array Functions927075
+Node: Flattening Arrays930841
+Node: Creating Arrays937680
+Node: Extension API Variables942475
+Node: Extension Versioning943111
+Node: Extension API Informational Variables945012
+Node: Extension API Boilerplate946098
+Node: Finding Extensions949929
+Node: Extension Example950476
+Node: Internal File Description951214
+Node: Internal File Ops954902
+Ref: Internal File Ops-Footnote-1966349
+Node: Using Internal File Ops966489
+Ref: Using Internal File Ops-Footnote-1968842
+Node: Extension Samples969108
+Node: Extension Sample File Functions970632
+Node: Extension Sample Fnmatch979105
+Node: Extension Sample Fork980831
+Node: Extension Sample Inplace982049
+Node: Extension Sample Ord983841
+Node: Extension Sample Readdir984620
+Node: Extension Sample Revout986124
+Node: Extension Sample Rev2way986717
+Node: Extension Sample Read write array987407
+Node: Extension Sample Readfile989290
+Node: Extension Sample API Tests990047
+Node: Extension Sample Time990572
+Node: gawkextlib991879
+Node: Language History994260
+Node: V7/SVR3.1995782
+Node: SVR4998103
+Node: POSIX999545
+Node: BTL1000553
+Node: POSIX/GNU1001358
+Node: Common Extensions1006893
+Node: Ranges and Locales1008000
+Ref: Ranges and Locales-Footnote-11012618
+Ref: Ranges and Locales-Footnote-21012645
+Ref: Ranges and Locales-Footnote-31012905
+Node: Contributors1013126
+Node: Installation1017422
+Node: Gawk Distribution1018316
+Node: Getting1018800
+Node: Extracting1019626
+Node: Distribution contents1021318
+Node: Unix Installation1026579
+Node: Quick Installation1027196
+Node: Additional Configuration Options1029158
+Node: Configuration Philosophy1030635
+Node: Non-Unix Installation1032977
+Node: PC Installation1033435
+Node: PC Binary Installation1034734
+Node: PC Compiling1036582
+Node: PC Testing1039526
+Node: PC Using1040702
+Node: Cygwin1044887
+Node: MSYS1045887
+Node: VMS Installation1046401
+Node: VMS Compilation1047004
+Ref: VMS Compilation-Footnote-11048011
+Node: VMS Installation Details1048069
+Node: VMS Running1049704
+Node: VMS Old Gawk1051311
+Node: Bugs1051785
+Node: Other Versions1055637
+Node: Notes1060967
+Node: Compatibility Mode1061767
+Node: Additions1062550
+Node: Accessing The Source1063477
+Node: Adding Code1065080
+Node: New Ports1071122
+Node: Derived Files1075257
+Ref: Derived Files-Footnote-11080578
+Ref: Derived Files-Footnote-21080612
+Ref: Derived Files-Footnote-31081212
+Node: Future Extensions1081310
+Node: Implementation Limitations1081891
+Node: Extension Design1083143
+Node: Old Extension Problems1084292
+Ref: Old Extension Problems-Footnote-11085800
+Node: Extension New Mechanism Goals1085857
+Ref: Extension New Mechanism Goals-Footnote-11089216
+Node: Extension Other Design Decisions1089402
+Node: Extension Future Growth1091508
+Node: Old Extension Mechansim1092329
+Node: Basic Concepts1094086
+Node: Basic High Level1094767
+Ref: figure-general-flow1095038
+Ref: figure-process-flow1095637
+Ref: Basic High Level-Footnote-11098866
+Node: Basic Data Typing1099051
+Node: Glossary1102406
+Node: Copying1127717
+Node: GNU Free Documentation License1165274
+Node: Index1190411
 
 End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index a5b5771..747e3d6 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -29533,6 +29533,17 @@ Changing types (scalar to array or vice versa) of an 
existing variable
 is @emph{not} allowed, nor may this routine be used to update an array.
 This routine cannot be used to update any of the predefined
 variables (such as @code{ARGC} or @code{NF}).
+
address@hidden awk_bool_t sym_constant(const char *name, awk_value_t *value);
+Create a variable named by the string @code{name}, which is
+a regular C string, that has the constant value as given by
address@hidden @command{awk}-level code cannot change the value of this
address@hidden (currently) is no @code{awk}-level feature that
+provides this ability.} The extension may change the value of @code{name}'s
+variable with subsequent calls to this routine, and may also convert
+a variable created by @code{sym_update()} into a constant.  However,
+once a variable becomes a constant, it cannot later be reverted into a
+mutable variable.
 @end table
 
 @node Symbol table by cookie
diff --git a/extension/ChangeLog b/extension/ChangeLog
index a73ccc1..d271529 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,5 +1,10 @@
 2013-03-04         Arnold D. Robbins     <address@hidden>
 
+       * filefuncs.c, fnmatch.c: Restore use of sym_constant.
+       * filefuncs.3am, fnmatch.3am: Restore documentation of constants.
+
+2013-03-04         Arnold D. Robbins     <address@hidden>
+
        * testext.c: Make answer_num a constant.
 
 2013-03-04         Arnold D. Robbins     <address@hidden>
diff --git a/extension/filefuncs.3am b/extension/filefuncs.3am
index d0eb2ac..34e079c 100644
--- a/extension/filefuncs.3am
+++ b/extension/filefuncs.3am
@@ -185,7 +185,7 @@ An array of filenames.  The element values are used; the 
index values are ignore
 .TP
 .B flags
 This should be the bitwise OR of one or more of the following
-predefined flag values.  At least one of
+predefined constant flag values.  At least one of
 .B FTS_LOGICAL
 or
 .B FTS_PHYSICAL
@@ -312,12 +312,6 @@ already provides powerful array sorting facilities.  While 
an
 interface could have been provided, this felt less natural than
 simply creating a multi-dimensional array to represent the file
 heirarchy and its information.
-.PP
-Nothing prevents AWK code from changing the predefined
-.BI FTS_ xx
-values, but doing so is may cause strange results when
-the changed values are passed to
-.BR fts() .
 .SH BUGS
 There are many more file-related functions for which AWK
 interfaces would be desirable.
diff --git a/extension/filefuncs.c b/extension/filefuncs.c
index 579b408..31a692c 100644
--- a/extension/filefuncs.c
+++ b/extension/filefuncs.c
@@ -433,8 +433,8 @@ init_filefuncs(void)
 
        for (i = 0; opentab[i].name != NULL; i++) {
                (void) make_number(opentab[i].value, & value);
-               if (! sym_update(opentab[i].name, & value)) {
-                       warning(ext_id, _("fts init: could not create variable 
%s"),
+               if (! sym_constant(opentab[i].name, & value)) {
+                       warning(ext_id, _("fts init: could not create constant 
%s"),
                                        opentab[i].name);
                        errors++;
                }
diff --git a/extension/fnmatch.3am b/extension/fnmatch.3am
index e2e8391..7a1d904 100644
--- a/extension/fnmatch.3am
+++ b/extension/fnmatch.3am
@@ -14,7 +14,7 @@ extension provides an AWK interface to the
 .IR fnmatch (3)
 routine.  It adds a single function named
 .BR fnmatch() ,
-one predefined variable
+one constant
 .RB ( FNM_NOMATCH ),
 and an array of flag values named
 .BR FNM .
@@ -68,11 +68,7 @@ Corresponds to the
 flag as defined in
 .IR fnmatch (3).
 .PP
-.SH NOTES
-Nothing prevents AWK code from changing the predefined
-variabale
-.BR FNM_NOMATCH ,
-but doing so may cause strange results.
+... .SH NOTES
 ... .SH BUGS
 .SH EXAMPLE
 .ft CW
diff --git a/extension/fnmatch.c b/extension/fnmatch.c
index 7f8ab8d..c6cf50f 100644
--- a/extension/fnmatch.c
+++ b/extension/fnmatch.c
@@ -155,7 +155,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/interpret.h b/interpret.h
index a2661e8..dcd61a9 100644
--- a/interpret.h
+++ b/interpret.h
@@ -193,7 +193,7 @@ uninitialized_scalar:
                        m = pc->memory;
                        if (m->type == Node_param_list)
                                m = GET_PARAM(m->param_cnt);
-                       if (m->type == Node_var) {
+                       if (m->type == Node_var || m->type == Node_var_const) {
                                m = m->var_value;
                                UPREF(m);
                                PUSH(m);
@@ -1064,7 +1064,10 @@ match_re:
                        f = pc->func_body;
                        if (f == NULL) {
                                f = lookup(pc->func_name);
-                               if (f == NULL || (f->type != Node_func && 
f->type != Node_ext_func && f->type != Node_old_ext_func))
+                               if (f == NULL ||
+                                  (f->type != Node_func &&
+                                   f->type != Node_ext_func
+                                   && f->type != Node_old_ext_func))
                                        fatal(_("function `%s' not defined"), 
pc->func_name);
                                pc->func_body = f;     /* save for next call */
                        }
diff --git a/test/ChangeLog b/test/ChangeLog
index 652480b..675d67f 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,10 @@
+2013-03-04         Arnold D. Robbins     <address@hidden>
+
+       * assignconst.awk, assignconst.ok: New file.
+       * Makefile.am (EXTRA_DIST): Added assignconst.awk, assignconst.ok.
+       (SHLIB_TESTS): Added assignconst.
+       (assignconst): Added test.
+
 2013-02-26         Arnold D. Robbins     <address@hidden>
 
        * parseme.ok: Update after change in grammar. Now with new and
diff --git a/test/Makefile.am b/test/Makefile.am
index c45be57..a0dfcf9 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 \
@@ -985,7 +987,7 @@ LOCALE_CHARSET_TESTS = \
        mbprintf1 mbprintf2 mbprintf3 rebt8b2 rtlenmb sort1 sprintfc
 
 SHLIB_TESTS = \
-       fnmatch filefuncs fork fork2 fts functab4 inplace1 inplace2 inplace3 \
+       assignconst fnmatch filefuncs fork fork2 fts functab4 inplace1 inplace2 
inplace3 \
        ordchr ordchr2 readdir readfile revout revtwoway rwarray testext time
 
 # List of the tests which should be run with --lint option:
@@ -1751,6 +1753,13 @@ testext::
        @$(AWK) -f testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@ testext.awk
 
+assignconst:
+       @echo $@
+       @for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14; \
+       do AWKPATH=$(srcdir) $(AWK) -f address@hidden $$i ; \
+       done 2>&1 | grep -v at_exit > _$@
+       @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
 readdir:
        @echo $@
        @$(AWK) -f $(srcdir)/readdir.awk $(top_srcdir) > _$@
diff --git a/test/Makefile.in b/test/Makefile.in
index e1a44a5..0c97877 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 \
@@ -1192,7 +1194,7 @@ LOCALE_CHARSET_TESTS = \
        mbprintf1 mbprintf2 mbprintf3 rebt8b2 rtlenmb sort1 sprintfc
 
 SHLIB_TESTS = \
-       fnmatch filefuncs fork fork2 fts functab4 inplace1 inplace2 inplace3 \
+       assignconst fnmatch filefuncs fork fork2 fts functab4 inplace1 inplace2 
inplace3 \
        ordchr ordchr2 readdir readfile revout revtwoway rwarray testext time
 
 
@@ -2131,6 +2133,13 @@ testext::
        @$(AWK) -f testext.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@
        @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@ testext.awk
 
+assignconst:
+       @echo $@
+       @for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14; \
+       do AWKPATH=$(srcdir) $(AWK) -f address@hidden $$i ; \
+       done 2>&1 | grep -v at_exit > _$@
+       @-$(CMP) $(srcdir)/address@hidden _$@ && rm -f _$@
+
 readdir:
        @echo $@
        @$(AWK) -f $(srcdir)/readdir.awk $(top_srcdir) > _$@
diff --git a/test/assignconst.awk b/test/assignconst.awk
new file mode 100644
index 0000000..202eae8
--- /dev/null
+++ b/test/assignconst.awk
@@ -0,0 +1,59 @@
address@hidden "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:
+               stopme()
+               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 0000000..97698b2
--- /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

http://git.sv.gnu.org/cgit/gawk.git/commit/?id=f3a939802f70c7e2ebc92558642eef9d962d55af

commit f3a939802f70c7e2ebc92558642eef9d962d55af
Author: Arnold D. Robbins <address@hidden>
Date:   Mon Mar 4 16:26:10 2013 +0200

    Enable the API to create constants.

diff --git a/ChangeLog b/ChangeLog
index 256c52f..4c40c3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2013-03-04         Arnold D. Robbins     <address@hidden>
+
+       Provide the API with the ability to create true constants.
+
+       * awk.h (Node_var_const): New nodetype.
+       * awkgram.y (statement): Don't allow a constant as the for loop
+       control variable.
+       * debug.c (print_symbol, do_set_var, watchpoint_triggered): Handle
+       Node_var_const.
+       (initialize_watch_item, print_memory, do_print_f): Ditto.
+       * eval.c (nodetypes, setup_frame): Add Node_var_const.
+       (r_get_lhs, op_assign): Assigning to constant is fatal error.
+       * gawkapi.c (sym_update_real): Renamed from api_sym_update_real,
+       add is_const parameter. Handle it.
+       (api_sym_update, api_sym_constant): Call sym_update_real.
+       (api_impl): Add new element.
+       * gawk_api.h: Add new function pointer for sym_constant.
+       (sym_constant): New macro.
+       * interpret.h: Support Node_var_const.
+       * profile.c (pprint): Support Node_var_const.
+       * symbol.c (destroy_symbol, make_symbol, print_vars): Support
+       Node_var_const.
+
 2013-02-28         Arnold D. Robbins     <address@hidden>
 
        Cause profiling / pretty printing to include a list of
diff --git a/awk.h b/awk.h
index 989f451..105ae2c 100644
--- a/awk.h
+++ b/awk.h
@@ -289,6 +289,7 @@ typedef enum nodevals {
 
        /* symbol table values */
        Node_var,               /* scalar variable, lnode is value */
+       Node_var_const,         /* unassignable scalar variable, lnode is value 
*/
        Node_var_array,         /* array is ptr to elements, table_size num of 
eles */
        Node_var_new,           /* newly created variable, may become an array 
*/
        Node_param_list,        /* lnode is a variable, rnode is more list */
diff --git a/awkgram.c b/awkgram.c
index 31f80bc..4c9d539 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -739,21 +739,21 @@ static const yytype_uint16 yyrline[] =
      247,   252,   260,   268,   270,   275,   283,   285,   291,   292,
      294,   320,   331,   342,   348,   357,   367,   369,   371,   377,
      382,   383,   387,   406,   405,   439,   441,   446,   447,   460,
-     465,   466,   470,   472,   474,   481,   571,   613,   655,   768,
-     775,   782,   792,   801,   810,   819,   830,   846,   845,   869,
-     881,   881,   979,   979,  1012,  1042,  1048,  1049,  1055,  1056,
-    1063,  1068,  1080,  1094,  1096,  1104,  1109,  1111,  1119,  1121,
-    1130,  1131,  1139,  1144,  1144,  1155,  1159,  1167,  1168,  1171,
-    1173,  1178,  1179,  1188,  1189,  1194,  1199,  1205,  1207,  1209,
-    1216,  1217,  1223,  1224,  1229,  1231,  1236,  1238,  1246,  1251,
-    1260,  1267,  1269,  1271,  1287,  1297,  1304,  1306,  1311,  1313,
-    1315,  1323,  1325,  1330,  1332,  1337,  1339,  1341,  1391,  1393,
-    1395,  1397,  1399,  1401,  1403,  1405,  1428,  1433,  1438,  1463,
-    1469,  1471,  1473,  1475,  1477,  1479,  1484,  1488,  1520,  1522,
-    1528,  1534,  1547,  1548,  1549,  1554,  1559,  1563,  1567,  1582,
-    1595,  1600,  1636,  1654,  1655,  1661,  1662,  1667,  1669,  1676,
-    1693,  1710,  1712,  1719,  1724,  1732,  1742,  1754,  1763,  1767,
-    1771,  1775,  1779,  1783,  1786,  1788,  1792,  1796,  1800
+     465,   466,   470,   472,   474,   481,   571,   613,   655,   771,
+     778,   785,   795,   804,   813,   822,   833,   849,   848,   872,
+     884,   884,   982,   982,  1015,  1045,  1051,  1052,  1058,  1059,
+    1066,  1071,  1083,  1097,  1099,  1107,  1112,  1114,  1122,  1124,
+    1133,  1134,  1142,  1147,  1147,  1158,  1162,  1170,  1171,  1174,
+    1176,  1181,  1182,  1191,  1192,  1197,  1202,  1208,  1210,  1212,
+    1219,  1220,  1226,  1227,  1232,  1234,  1239,  1241,  1249,  1254,
+    1263,  1270,  1272,  1274,  1290,  1300,  1307,  1309,  1314,  1316,
+    1318,  1326,  1328,  1333,  1335,  1340,  1342,  1344,  1394,  1396,
+    1398,  1400,  1402,  1404,  1406,  1408,  1431,  1436,  1441,  1466,
+    1472,  1474,  1476,  1478,  1480,  1482,  1487,  1491,  1523,  1525,
+    1531,  1537,  1550,  1551,  1552,  1557,  1562,  1566,  1570,  1585,
+    1598,  1603,  1639,  1657,  1658,  1664,  1665,  1670,  1672,  1679,
+    1696,  1713,  1715,  1722,  1727,  1735,  1745,  1757,  1766,  1770,
+    1774,  1778,  1782,  1786,  1789,  1791,  1795,  1799,  1803
 };
 #endif
 
@@ -2614,6 +2614,9 @@ yyreduce:
                INSTRUCTION *ip;
                char *var_name = (yyvsp[(3) - (8)])->lextok;
 
+               if ((yyvsp[(3) - (8)])->memory->type == Node_var_const)
+                       fatal(_("cannot use defined constant as loop variable 
in `for' statement"));
+
                if ((yyvsp[(8) - (8)]) != NULL
                                && (yyvsp[(8) - (8)])->lasti->opcode == 
Op_K_delete
                                && (yyvsp[(8) - (8)])->lasti->expr_count == 1
@@ -2726,7 +2729,7 @@ regular_loop:
 
   case 49:
 /* Line 1792 of yacc.c  */
-#line 769 "awkgram.y"
+#line 772 "awkgram.y"
     {
                (yyval) = mk_for_loop((yyvsp[(1) - (12)]), (yyvsp[(3) - (12)]), 
(yyvsp[(6) - (12)]), (yyvsp[(9) - (12)]), (yyvsp[(12) - (12)]));
 
@@ -2737,7 +2740,7 @@ regular_loop:
 
   case 50:
 /* Line 1792 of yacc.c  */
-#line 776 "awkgram.y"
+#line 779 "awkgram.y"
     {
                (yyval) = mk_for_loop((yyvsp[(1) - (11)]), (yyvsp[(3) - (11)]), 
(INSTRUCTION *) NULL, (yyvsp[(8) - (11)]), (yyvsp[(11) - (11)]));
 
@@ -2748,7 +2751,7 @@ regular_loop:
 
   case 51:
 /* Line 1792 of yacc.c  */
-#line 783 "awkgram.y"
+#line 786 "awkgram.y"
     {
                if (do_pretty_print)
                        (yyval) = list_prepend((yyvsp[(1) - (1)]), 
instruction(Op_exec_count));
@@ -2759,7 +2762,7 @@ regular_loop:
 
   case 52:
 /* Line 1792 of yacc.c  */
-#line 793 "awkgram.y"
+#line 796 "awkgram.y"
     { 
                if (! break_allowed)
                        error_ln((yyvsp[(1) - (2)])->source_line,
@@ -2772,7 +2775,7 @@ regular_loop:
 
   case 53:
 /* Line 1792 of yacc.c  */
-#line 802 "awkgram.y"
+#line 805 "awkgram.y"
     {
                if (! continue_allowed)
                        error_ln((yyvsp[(1) - (2)])->source_line,
@@ -2785,7 +2788,7 @@ regular_loop:
 
   case 54:
 /* Line 1792 of yacc.c  */
-#line 811 "awkgram.y"
+#line 814 "awkgram.y"
     {
                /* if inside function (rule = 0), resolve context at run-time */
                if (rule && rule != Rule)
@@ -2798,7 +2801,7 @@ regular_loop:
 
   case 55:
 /* Line 1792 of yacc.c  */
-#line 820 "awkgram.y"
+#line 823 "awkgram.y"
     {
                /* if inside function (rule = 0), resolve context at run-time */
                if (rule == BEGIN || rule == END || rule == ENDFILE)
@@ -2813,7 +2816,7 @@ regular_loop:
 
   case 56:
 /* Line 1792 of yacc.c  */
-#line 831 "awkgram.y"
+#line 834 "awkgram.y"
     {
                /* Initialize the two possible jump targets, the actual target
                 * is resolved at run-time. 
@@ -2832,7 +2835,7 @@ regular_loop:
 
   case 57:
 /* Line 1792 of yacc.c  */
-#line 846 "awkgram.y"
+#line 849 "awkgram.y"
     {
                if (! in_function)
                        yyerror(_("`return' used outside function context"));
@@ -2841,7 +2844,7 @@ regular_loop:
 
   case 58:
 /* Line 1792 of yacc.c  */
-#line 849 "awkgram.y"
+#line 852 "awkgram.y"
     {
                if ((yyvsp[(3) - (4)]) == NULL) {
                        (yyval) = list_create((yyvsp[(1) - (4)]));
@@ -2866,13 +2869,13 @@ regular_loop:
 
   case 60:
 /* Line 1792 of yacc.c  */
-#line 881 "awkgram.y"
+#line 884 "awkgram.y"
     { in_print = true; in_parens = 0; }
     break;
 
   case 61:
 /* Line 1792 of yacc.c  */
-#line 882 "awkgram.y"
+#line 885 "awkgram.y"
     {
                /*
                 * Optimization: plain `print' has no expression list, so $3 is 
null.
@@ -2973,13 +2976,13 @@ regular_print:
 
   case 62:
 /* Line 1792 of yacc.c  */
-#line 979 "awkgram.y"
+#line 982 "awkgram.y"
     { sub_counter = 0; }
     break;
 
   case 63:
 /* Line 1792 of yacc.c  */
-#line 980 "awkgram.y"
+#line 983 "awkgram.y"
     {
                char *arr = (yyvsp[(2) - (4)])->lextok;
 
@@ -3016,7 +3019,7 @@ regular_print:
 
   case 64:
 /* Line 1792 of yacc.c  */
-#line 1017 "awkgram.y"
+#line 1020 "awkgram.y"
     {
                static bool warned = false;
                char *arr = (yyvsp[(3) - (4)])->lextok;
@@ -3046,31 +3049,31 @@ regular_print:
 
   case 65:
 /* Line 1792 of yacc.c  */
-#line 1043 "awkgram.y"
+#line 1046 "awkgram.y"
     {  (yyval) = optimize_assignment((yyvsp[(1) - (1)])); }
     break;
 
   case 66:
 /* Line 1792 of yacc.c  */
-#line 1048 "awkgram.y"
+#line 1051 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 67:
 /* Line 1792 of yacc.c  */
-#line 1050 "awkgram.y"
+#line 1053 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 68:
 /* Line 1792 of yacc.c  */
-#line 1055 "awkgram.y"
+#line 1058 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 69:
 /* Line 1792 of yacc.c  */
-#line 1057 "awkgram.y"
+#line 1060 "awkgram.y"
     {
                if ((yyvsp[(1) - (2)]) == NULL)
                        (yyval) = list_create((yyvsp[(2) - (2)]));
@@ -3081,13 +3084,13 @@ regular_print:
 
   case 70:
 /* Line 1792 of yacc.c  */
-#line 1064 "awkgram.y"
+#line 1067 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 71:
 /* Line 1792 of yacc.c  */
-#line 1069 "awkgram.y"
+#line 1072 "awkgram.y"
     {
                INSTRUCTION *casestmt = (yyvsp[(5) - (5)]);
                if ((yyvsp[(5) - (5)]) == NULL)
@@ -3103,7 +3106,7 @@ regular_print:
 
   case 72:
 /* Line 1792 of yacc.c  */
-#line 1081 "awkgram.y"
+#line 1084 "awkgram.y"
     {
                INSTRUCTION *casestmt = (yyvsp[(4) - (4)]);
                if ((yyvsp[(4) - (4)]) == NULL)
@@ -3118,13 +3121,13 @@ regular_print:
 
   case 73:
 /* Line 1792 of yacc.c  */
-#line 1095 "awkgram.y"
+#line 1098 "awkgram.y"
     {  (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 74:
 /* Line 1792 of yacc.c  */
-#line 1097 "awkgram.y"
+#line 1100 "awkgram.y"
     { 
                NODE *n = (yyvsp[(2) - (2)])->memory;
                (void) force_number(n);
@@ -3136,7 +3139,7 @@ regular_print:
 
   case 75:
 /* Line 1792 of yacc.c  */
-#line 1105 "awkgram.y"
+#line 1108 "awkgram.y"
     {
                bcfree((yyvsp[(1) - (2)]));
                (yyval) = (yyvsp[(2) - (2)]);
@@ -3145,13 +3148,13 @@ regular_print:
 
   case 76:
 /* Line 1792 of yacc.c  */
-#line 1110 "awkgram.y"
+#line 1113 "awkgram.y"
     {  (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 77:
 /* Line 1792 of yacc.c  */
-#line 1112 "awkgram.y"
+#line 1115 "awkgram.y"
     {
                (yyvsp[(1) - (1)])->opcode = Op_push_re;
                (yyval) = (yyvsp[(1) - (1)]);
@@ -3160,19 +3163,19 @@ regular_print:
 
   case 78:
 /* Line 1792 of yacc.c  */
-#line 1120 "awkgram.y"
+#line 1123 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 79:
 /* Line 1792 of yacc.c  */
-#line 1122 "awkgram.y"
+#line 1125 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 81:
 /* Line 1792 of yacc.c  */
-#line 1132 "awkgram.y"
+#line 1135 "awkgram.y"
     {
                (yyval) = (yyvsp[(2) - (3)]);
          }
@@ -3180,7 +3183,7 @@ regular_print:
 
   case 82:
 /* Line 1792 of yacc.c  */
-#line 1139 "awkgram.y"
+#line 1142 "awkgram.y"
     {
                in_print = false;
                in_parens = 0;
@@ -3190,13 +3193,13 @@ regular_print:
 
   case 83:
 /* Line 1792 of yacc.c  */
-#line 1144 "awkgram.y"
+#line 1147 "awkgram.y"
     { in_print = false; in_parens = 0; }
     break;
 
   case 84:
 /* Line 1792 of yacc.c  */
-#line 1145 "awkgram.y"
+#line 1148 "awkgram.y"
     {
                if ((yyvsp[(1) - (3)])->redir_type == redirect_twoway
                        && (yyvsp[(3) - (3)])->lasti->opcode == 
Op_K_getline_redir
@@ -3208,7 +3211,7 @@ regular_print:
 
   case 85:
 /* Line 1792 of yacc.c  */
-#line 1156 "awkgram.y"
+#line 1159 "awkgram.y"
     {
                (yyval) = mk_condition((yyvsp[(3) - (6)]), (yyvsp[(1) - (6)]), 
(yyvsp[(6) - (6)]), NULL, NULL);
          }
@@ -3216,7 +3219,7 @@ regular_print:
 
   case 86:
 /* Line 1792 of yacc.c  */
-#line 1161 "awkgram.y"
+#line 1164 "awkgram.y"
     {
                (yyval) = mk_condition((yyvsp[(3) - (9)]), (yyvsp[(1) - (9)]), 
(yyvsp[(6) - (9)]), (yyvsp[(7) - (9)]), (yyvsp[(9) - (9)]));
          }
@@ -3224,13 +3227,13 @@ regular_print:
 
   case 91:
 /* Line 1792 of yacc.c  */
-#line 1178 "awkgram.y"
+#line 1181 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 92:
 /* Line 1792 of yacc.c  */
-#line 1180 "awkgram.y"
+#line 1183 "awkgram.y"
     {
                bcfree((yyvsp[(1) - (2)]));
                (yyval) = (yyvsp[(2) - (2)]);
@@ -3239,19 +3242,19 @@ regular_print:
 
   case 93:
 /* Line 1792 of yacc.c  */
-#line 1188 "awkgram.y"
+#line 1191 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 94:
 /* Line 1792 of yacc.c  */
-#line 1190 "awkgram.y"
+#line 1193 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]) ; }
     break;
 
   case 95:
 /* Line 1792 of yacc.c  */
-#line 1195 "awkgram.y"
+#line 1198 "awkgram.y"
     {
                (yyvsp[(1) - (1)])->param_count = 0;
                (yyval) = list_create((yyvsp[(1) - (1)]));
@@ -3260,7 +3263,7 @@ regular_print:
 
   case 96:
 /* Line 1792 of yacc.c  */
-#line 1200 "awkgram.y"
+#line 1203 "awkgram.y"
     {
                (yyvsp[(3) - (3)])->param_count =  (yyvsp[(1) - 
(3)])->lasti->param_count + 1;
                (yyval) = list_append((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]));
@@ -3270,55 +3273,55 @@ regular_print:
 
   case 97:
 /* Line 1792 of yacc.c  */
-#line 1206 "awkgram.y"
+#line 1209 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 98:
 /* Line 1792 of yacc.c  */
-#line 1208 "awkgram.y"
+#line 1211 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (2)]); }
     break;
 
   case 99:
 /* Line 1792 of yacc.c  */
-#line 1210 "awkgram.y"
+#line 1213 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (3)]); }
     break;
 
   case 100:
 /* Line 1792 of yacc.c  */
-#line 1216 "awkgram.y"
+#line 1219 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 101:
 /* Line 1792 of yacc.c  */
-#line 1218 "awkgram.y"
+#line 1221 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 102:
 /* Line 1792 of yacc.c  */
-#line 1223 "awkgram.y"
+#line 1226 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 103:
 /* Line 1792 of yacc.c  */
-#line 1225 "awkgram.y"
+#line 1228 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 104:
 /* Line 1792 of yacc.c  */
-#line 1230 "awkgram.y"
+#line 1233 "awkgram.y"
     {  (yyval) = mk_expression_list(NULL, (yyvsp[(1) - (1)])); }
     break;
 
   case 105:
 /* Line 1792 of yacc.c  */
-#line 1232 "awkgram.y"
+#line 1235 "awkgram.y"
     {
                (yyval) = mk_expression_list((yyvsp[(1) - (3)]), (yyvsp[(3) - 
(3)]));
                yyerrok;
@@ -3327,13 +3330,13 @@ regular_print:
 
   case 106:
 /* Line 1792 of yacc.c  */
-#line 1237 "awkgram.y"
+#line 1240 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 107:
 /* Line 1792 of yacc.c  */
-#line 1239 "awkgram.y"
+#line 1242 "awkgram.y"
     {
                /*
                 * Returning the expression list instead of NULL lets
@@ -3345,7 +3348,7 @@ regular_print:
 
   case 108:
 /* Line 1792 of yacc.c  */
-#line 1247 "awkgram.y"
+#line 1250 "awkgram.y"
     {
                /* Ditto */
                (yyval) = mk_expression_list((yyvsp[(1) - (3)]), (yyvsp[(3) - 
(3)]));
@@ -3354,7 +3357,7 @@ regular_print:
 
   case 109:
 /* Line 1792 of yacc.c  */
-#line 1252 "awkgram.y"
+#line 1255 "awkgram.y"
     {
                /* Ditto */
                (yyval) = (yyvsp[(1) - (3)]);
@@ -3363,7 +3366,7 @@ regular_print:
 
   case 110:
 /* Line 1792 of yacc.c  */
-#line 1261 "awkgram.y"
+#line 1264 "awkgram.y"
     {
                if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == 
Op_match_rec)
                        lintwarn_ln((yyvsp[(2) - (3)])->source_line,
@@ -3374,19 +3377,19 @@ regular_print:
 
   case 111:
 /* Line 1792 of yacc.c  */
-#line 1268 "awkgram.y"
+#line 1271 "awkgram.y"
     {  (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) 
- (3)])); }
     break;
 
   case 112:
 /* Line 1792 of yacc.c  */
-#line 1270 "awkgram.y"
+#line 1273 "awkgram.y"
     {  (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) 
- (3)])); }
     break;
 
   case 113:
 /* Line 1792 of yacc.c  */
-#line 1272 "awkgram.y"
+#line 1275 "awkgram.y"
     {
                if ((yyvsp[(1) - (3)])->lasti->opcode == Op_match_rec)
                        warning_ln((yyvsp[(2) - (3)])->source_line,
@@ -3406,7 +3409,7 @@ regular_print:
 
   case 114:
 /* Line 1792 of yacc.c  */
-#line 1288 "awkgram.y"
+#line 1291 "awkgram.y"
     {
                if (do_lint_old)
                        warning_ln((yyvsp[(2) - (3)])->source_line,
@@ -3420,7 +3423,7 @@ regular_print:
 
   case 115:
 /* Line 1792 of yacc.c  */
-#line 1298 "awkgram.y"
+#line 1301 "awkgram.y"
     {
                if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == 
Op_match_rec)
                        lintwarn_ln((yyvsp[(2) - (3)])->source_line,
@@ -3431,31 +3434,31 @@ regular_print:
 
   case 116:
 /* Line 1792 of yacc.c  */
-#line 1305 "awkgram.y"
+#line 1308 "awkgram.y"
     { (yyval) = mk_condition((yyvsp[(1) - (5)]), (yyvsp[(2) - (5)]), 
(yyvsp[(3) - (5)]), (yyvsp[(4) - (5)]), (yyvsp[(5) - (5)])); }
     break;
 
   case 117:
 /* Line 1792 of yacc.c  */
-#line 1307 "awkgram.y"
+#line 1310 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 118:
 /* Line 1792 of yacc.c  */
-#line 1312 "awkgram.y"
+#line 1315 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 119:
 /* Line 1792 of yacc.c  */
-#line 1314 "awkgram.y"
+#line 1317 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 120:
 /* Line 1792 of yacc.c  */
-#line 1316 "awkgram.y"
+#line 1319 "awkgram.y"
     {  
                (yyvsp[(2) - (2)])->opcode = Op_assign_quotient;
                (yyval) = (yyvsp[(2) - (2)]);
@@ -3464,43 +3467,43 @@ regular_print:
 
   case 121:
 /* Line 1792 of yacc.c  */
-#line 1324 "awkgram.y"
+#line 1327 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 122:
 /* Line 1792 of yacc.c  */
-#line 1326 "awkgram.y"
+#line 1329 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 123:
 /* Line 1792 of yacc.c  */
-#line 1331 "awkgram.y"
+#line 1334 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 124:
 /* Line 1792 of yacc.c  */
-#line 1333 "awkgram.y"
+#line 1336 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 125:
 /* Line 1792 of yacc.c  */
-#line 1338 "awkgram.y"
+#line 1341 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 126:
 /* Line 1792 of yacc.c  */
-#line 1340 "awkgram.y"
+#line 1343 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 127:
 /* Line 1792 of yacc.c  */
-#line 1342 "awkgram.y"
+#line 1345 "awkgram.y"
     {
                int count = 2;
                bool is_simple_var = false;
@@ -3551,43 +3554,43 @@ regular_print:
 
   case 129:
 /* Line 1792 of yacc.c  */
-#line 1394 "awkgram.y"
+#line 1397 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 130:
 /* Line 1792 of yacc.c  */
-#line 1396 "awkgram.y"
+#line 1399 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 131:
 /* Line 1792 of yacc.c  */
-#line 1398 "awkgram.y"
+#line 1401 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 132:
 /* Line 1792 of yacc.c  */
-#line 1400 "awkgram.y"
+#line 1403 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 133:
 /* Line 1792 of yacc.c  */
-#line 1402 "awkgram.y"
+#line 1405 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 134:
 /* Line 1792 of yacc.c  */
-#line 1404 "awkgram.y"
+#line 1407 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 135:
 /* Line 1792 of yacc.c  */
-#line 1406 "awkgram.y"
+#line 1409 "awkgram.y"
     {
                /*
                 * In BEGINFILE/ENDFILE, allow `getline var < file'
@@ -3614,7 +3617,7 @@ regular_print:
 
   case 136:
 /* Line 1792 of yacc.c  */
-#line 1429 "awkgram.y"
+#line 1432 "awkgram.y"
     {
                (yyvsp[(2) - (2)])->opcode = Op_postincrement;
                (yyval) = mk_assignment((yyvsp[(1) - (2)]), NULL, (yyvsp[(2) - 
(2)]));
@@ -3623,7 +3626,7 @@ regular_print:
 
   case 137:
 /* Line 1792 of yacc.c  */
-#line 1434 "awkgram.y"
+#line 1437 "awkgram.y"
     {
                (yyvsp[(2) - (2)])->opcode = Op_postdecrement;
                (yyval) = mk_assignment((yyvsp[(1) - (2)]), NULL, (yyvsp[(2) - 
(2)]));
@@ -3632,7 +3635,7 @@ regular_print:
 
   case 138:
 /* Line 1792 of yacc.c  */
-#line 1439 "awkgram.y"
+#line 1442 "awkgram.y"
     {
                if (do_lint_old) {
                    warning_ln((yyvsp[(4) - (5)])->source_line,
@@ -3656,7 +3659,7 @@ regular_print:
 
   case 139:
 /* Line 1792 of yacc.c  */
-#line 1464 "awkgram.y"
+#line 1467 "awkgram.y"
     {
                  (yyval) = mk_getline((yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), 
(yyvsp[(1) - (4)]), (yyvsp[(2) - (4)])->redir_type);
                  bcfree((yyvsp[(2) - (4)]));
@@ -3665,43 +3668,43 @@ regular_print:
 
   case 140:
 /* Line 1792 of yacc.c  */
-#line 1470 "awkgram.y"
+#line 1473 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 141:
 /* Line 1792 of yacc.c  */
-#line 1472 "awkgram.y"
+#line 1475 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 142:
 /* Line 1792 of yacc.c  */
-#line 1474 "awkgram.y"
+#line 1477 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 143:
 /* Line 1792 of yacc.c  */
-#line 1476 "awkgram.y"
+#line 1479 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 144:
 /* Line 1792 of yacc.c  */
-#line 1478 "awkgram.y"
+#line 1481 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 145:
 /* Line 1792 of yacc.c  */
-#line 1480 "awkgram.y"
+#line 1483 "awkgram.y"
     { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - 
(3)])); }
     break;
 
   case 146:
 /* Line 1792 of yacc.c  */
-#line 1485 "awkgram.y"
+#line 1488 "awkgram.y"
     {
                (yyval) = list_create((yyvsp[(1) - (1)]));
          }
@@ -3709,7 +3712,7 @@ regular_print:
 
   case 147:
 /* Line 1792 of yacc.c  */
-#line 1489 "awkgram.y"
+#line 1492 "awkgram.y"
     {
                if ((yyvsp[(2) - (2)])->opcode == Op_match_rec) {
                        (yyvsp[(2) - (2)])->opcode = Op_nomatch;
@@ -3745,13 +3748,13 @@ regular_print:
 
   case 148:
 /* Line 1792 of yacc.c  */
-#line 1521 "awkgram.y"
+#line 1524 "awkgram.y"
     { (yyval) = (yyvsp[(2) - (3)]); }
     break;
 
   case 149:
 /* Line 1792 of yacc.c  */
-#line 1523 "awkgram.y"
+#line 1526 "awkgram.y"
     {
                (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
                if ((yyval) == NULL)
@@ -3761,7 +3764,7 @@ regular_print:
 
   case 150:
 /* Line 1792 of yacc.c  */
-#line 1529 "awkgram.y"
+#line 1532 "awkgram.y"
     {
                (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)]));
                if ((yyval) == NULL)
@@ -3771,7 +3774,7 @@ regular_print:
 
   case 151:
 /* Line 1792 of yacc.c  */
-#line 1535 "awkgram.y"
+#line 1538 "awkgram.y"
     {
                static bool warned = false;
 
@@ -3788,7 +3791,7 @@ regular_print:
 
   case 154:
 /* Line 1792 of yacc.c  */
-#line 1550 "awkgram.y"
+#line 1553 "awkgram.y"
     {
                (yyvsp[(1) - (2)])->opcode = Op_preincrement;
                (yyval) = mk_assignment((yyvsp[(2) - (2)]), NULL, (yyvsp[(1) - 
(2)]));
@@ -3797,7 +3800,7 @@ regular_print:
 
   case 155:
 /* Line 1792 of yacc.c  */
-#line 1555 "awkgram.y"
+#line 1558 "awkgram.y"
     {
                (yyvsp[(1) - (2)])->opcode = Op_predecrement;
                (yyval) = mk_assignment((yyvsp[(2) - (2)]), NULL, (yyvsp[(1) - 
(2)]));
@@ -3806,7 +3809,7 @@ regular_print:
 
   case 156:
 /* Line 1792 of yacc.c  */
-#line 1560 "awkgram.y"
+#line 1563 "awkgram.y"
     {
                (yyval) = list_create((yyvsp[(1) - (1)]));
          }
@@ -3814,7 +3817,7 @@ regular_print:
 
   case 157:
 /* Line 1792 of yacc.c  */
-#line 1564 "awkgram.y"
+#line 1567 "awkgram.y"
     {
                (yyval) = list_create((yyvsp[(1) - (1)]));
          }
@@ -3822,7 +3825,7 @@ regular_print:
 
   case 158:
 /* Line 1792 of yacc.c  */
-#line 1568 "awkgram.y"
+#line 1571 "awkgram.y"
     {
                if ((yyvsp[(2) - (2)])->lasti->opcode == Op_push_i
                        && ((yyvsp[(2) - (2)])->lasti->memory->flags & 
(STRCUR|STRING)) == 0
@@ -3841,7 +3844,7 @@ regular_print:
 
   case 159:
 /* Line 1792 of yacc.c  */
-#line 1583 "awkgram.y"
+#line 1586 "awkgram.y"
     {
            /*
             * was: $$ = $2
@@ -3855,7 +3858,7 @@ regular_print:
 
   case 160:
 /* Line 1792 of yacc.c  */
-#line 1596 "awkgram.y"
+#line 1599 "awkgram.y"
     {
                func_use((yyvsp[(1) - (1)])->lasti->func_name, FUNC_USE);
                (yyval) = (yyvsp[(1) - (1)]);
@@ -3864,7 +3867,7 @@ regular_print:
 
   case 161:
 /* Line 1792 of yacc.c  */
-#line 1601 "awkgram.y"
+#line 1604 "awkgram.y"
     {
                /* indirect function call */
                INSTRUCTION *f, *t;
@@ -3901,7 +3904,7 @@ regular_print:
 
   case 162:
 /* Line 1792 of yacc.c  */
-#line 1637 "awkgram.y"
+#line 1640 "awkgram.y"
     {
                param_sanity((yyvsp[(3) - (4)]));
                (yyvsp[(1) - (4)])->opcode = Op_func_call;
@@ -3919,37 +3922,37 @@ regular_print:
 
   case 163:
 /* Line 1792 of yacc.c  */
-#line 1654 "awkgram.y"
+#line 1657 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 164:
 /* Line 1792 of yacc.c  */
-#line 1656 "awkgram.y"
+#line 1659 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 165:
 /* Line 1792 of yacc.c  */
-#line 1661 "awkgram.y"
+#line 1664 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 166:
 /* Line 1792 of yacc.c  */
-#line 1663 "awkgram.y"
+#line 1666 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (2)]); }
     break;
 
   case 167:
 /* Line 1792 of yacc.c  */
-#line 1668 "awkgram.y"
+#line 1671 "awkgram.y"
     {  (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 168:
 /* Line 1792 of yacc.c  */
-#line 1670 "awkgram.y"
+#line 1673 "awkgram.y"
     {
                (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
          }
@@ -3957,7 +3960,7 @@ regular_print:
 
   case 169:
 /* Line 1792 of yacc.c  */
-#line 1677 "awkgram.y"
+#line 1680 "awkgram.y"
     {
                INSTRUCTION *ip = (yyvsp[(1) - (1)])->lasti; 
                int count = ip->sub_count;      /* # of SUBSEP-seperated 
expressions */
@@ -3975,7 +3978,7 @@ regular_print:
 
   case 170:
 /* Line 1792 of yacc.c  */
-#line 1694 "awkgram.y"
+#line 1697 "awkgram.y"
     {
                INSTRUCTION *t = (yyvsp[(2) - (3)]);
                if ((yyvsp[(2) - (3)]) == NULL) {
@@ -3993,13 +3996,13 @@ regular_print:
 
   case 171:
 /* Line 1792 of yacc.c  */
-#line 1711 "awkgram.y"
+#line 1714 "awkgram.y"
     {  (yyval) = (yyvsp[(1) - (1)]); }
     break;
 
   case 172:
 /* Line 1792 of yacc.c  */
-#line 1713 "awkgram.y"
+#line 1716 "awkgram.y"
     {
                (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]));
          }
@@ -4007,13 +4010,13 @@ regular_print:
 
   case 173:
 /* Line 1792 of yacc.c  */
-#line 1720 "awkgram.y"
+#line 1723 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (2)]); }
     break;
 
   case 174:
 /* Line 1792 of yacc.c  */
-#line 1725 "awkgram.y"
+#line 1728 "awkgram.y"
     {
                char *var_name = (yyvsp[(1) - (1)])->lextok;
 
@@ -4025,7 +4028,7 @@ regular_print:
 
   case 175:
 /* Line 1792 of yacc.c  */
-#line 1733 "awkgram.y"
+#line 1736 "awkgram.y"
     {
                char *arr = (yyvsp[(1) - (2)])->lextok;
                (yyvsp[(1) - (2)])->memory = variable((yyvsp[(1) - 
(2)])->source_line, arr, Node_var_new);
@@ -4036,7 +4039,7 @@ regular_print:
 
   case 176:
 /* Line 1792 of yacc.c  */
-#line 1743 "awkgram.y"
+#line 1746 "awkgram.y"
     {
                INSTRUCTION *ip = (yyvsp[(1) - (1)])->nexti;
                if (ip->opcode == Op_push
@@ -4052,7 +4055,7 @@ regular_print:
 
   case 177:
 /* Line 1792 of yacc.c  */
-#line 1755 "awkgram.y"
+#line 1758 "awkgram.y"
     {
                (yyval) = list_append((yyvsp[(2) - (3)]), (yyvsp[(1) - (3)]));
                if ((yyvsp[(3) - (3)]) != NULL)
@@ -4062,7 +4065,7 @@ regular_print:
 
   case 178:
 /* Line 1792 of yacc.c  */
-#line 1764 "awkgram.y"
+#line 1767 "awkgram.y"
     {
                (yyvsp[(1) - (1)])->opcode = Op_postincrement;
          }
@@ -4070,7 +4073,7 @@ regular_print:
 
   case 179:
 /* Line 1792 of yacc.c  */
-#line 1768 "awkgram.y"
+#line 1771 "awkgram.y"
     {
                (yyvsp[(1) - (1)])->opcode = Op_postdecrement;
          }
@@ -4078,43 +4081,43 @@ regular_print:
 
   case 180:
 /* Line 1792 of yacc.c  */
-#line 1771 "awkgram.y"
+#line 1774 "awkgram.y"
     { (yyval) = NULL; }
     break;
 
   case 182:
 /* Line 1792 of yacc.c  */
-#line 1779 "awkgram.y"
+#line 1782 "awkgram.y"
     { yyerrok; }
     break;
 
   case 183:
 /* Line 1792 of yacc.c  */
-#line 1783 "awkgram.y"
+#line 1786 "awkgram.y"
     { yyerrok; }
     break;
 
   case 186:
 /* Line 1792 of yacc.c  */
-#line 1792 "awkgram.y"
+#line 1795 "awkgram.y"
     { yyerrok; }
     break;
 
   case 187:
 /* Line 1792 of yacc.c  */
-#line 1796 "awkgram.y"
+#line 1799 "awkgram.y"
     { (yyval) = (yyvsp[(1) - (1)]); yyerrok; }
     break;
 
   case 188:
 /* Line 1792 of yacc.c  */
-#line 1800 "awkgram.y"
+#line 1803 "awkgram.y"
     { yyerrok; }
     break;
 
 
 /* Line 1792 of yacc.c  */
-#line 4118 "awkgram.c"
+#line 4121 "awkgram.c"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -4346,7 +4349,7 @@ yyreturn:
 
 
 /* Line 2055 of yacc.c  */
-#line 1802 "awkgram.y"
+#line 1805 "awkgram.y"
 
 
 struct token {
diff --git a/awkgram.y b/awkgram.y
index 14520cd..7d2e11f 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -657,6 +657,9 @@ statement
                INSTRUCTION *ip;
                char *var_name = $3->lextok;
 
+               if ($3->memory->type == Node_var_const)
+                       fatal(_("cannot use defined constant as loop variable 
in `for' statement"));
+
                if ($8 != NULL
                                && $8->lasti->opcode == Op_K_delete
                                && $8->lasti->expr_count == 1
diff --git a/debug.c b/debug.c
index a69b7e3..ad7a058 100644
--- a/debug.c
+++ b/debug.c
@@ -398,6 +398,19 @@ d_error(const char *mesg, ...)
        va_end(args);
 }
 
+/* d_warning --- print a warning message */
+
+void
+d_warning(const char *mesg, ...)
+{
+       va_list args;
+       va_start(args, mesg);
+       fprintf(out_fp, _("warning: "));
+       vfprintf(out_fp, mesg, args);
+       fprintf(out_fp, "\n");
+       va_end(args);
+}
+
 /* find_lines --- find the positions of the lines in the source file. */
 
 static int
@@ -941,6 +954,10 @@ print_symbol(NODE *r, bool isparam)
                        r->var_update();
                valinfo(r->var_value, fprintf, out_fp);
                break;
+       case Node_var_const:
+               fprintf(out_fp, "defined constant ");
+               valinfo(r->var_value, fprintf, out_fp);
+               break;
        case Node_var_array:
                fprintf(out_fp, "array, %ld elements\n", assoc_length(r));
                break;
@@ -1214,6 +1231,9 @@ do_set_var(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
                        r->var_value = dupnode(Nnull_string);
                        /* fall through */
                case Node_var:
+               case Node_var_const:
+                       if (r->type == Node_var_const)
+                               d_warning(_("`%s' is a constant (changing 
anyway)"), name);
                        lhs = &r->var_value;
                        unref(*lhs);
                        *lhs = dupnode(val);
@@ -1691,6 +1711,7 @@ watchpoint_triggered(struct list_item *w)
        } else {
                switch (symbol->type) {
                case Node_var:
+               case Node_var_const:
                        t2 = symbol->var_value;
                        break;
                case Node_var_array:
@@ -1775,7 +1796,7 @@ initialize_watch_item(struct list_item *w)
        } else {
                if (symbol->type == Node_var_new)
                        w->cur_value = (NODE *) 0;
-               else if (symbol->type == Node_var) {
+               else if (symbol->type == Node_var || symbol->type == 
Node_var_const) {
                        r = symbol->var_value;
                        w->cur_value = dupnode(r);
                } else if (symbol->type == Node_var_array) {
@@ -3696,6 +3717,7 @@ print_memory(NODE *m, NODE *func, Func_print print_func, 
FILE *fp)
                        break;
 
                case Node_var:
+               case Node_var_const:
                case Node_var_new:
                case Node_var_array:
                        print_func(fp, "%s", m->vname);
@@ -4945,7 +4967,7 @@ do_print_f(CMDARG *arg, int cmd ATTRIBUTE_UNUSED)
                                goto done;
                        if (r->type == Node_var_new)
                                tmp[i] = Nnull_string;
-                       else if (r->type != Node_var) {
+                       else if (r->type != Node_var && r->type != 
Node_var_const) {
                                d_error(_("`%s' is not a scalar variable"), 
name);
                                goto done;
                        } else
diff --git a/eval.c b/eval.c
index afb6a45..5de4fae 100644
--- a/eval.c
+++ b/eval.c
@@ -235,6 +235,7 @@ static const char *const nodetypes[] = {
        "Node_regex",
        "Node_dynregex",
        "Node_var",
+       "Node_var_const",
        "Node_var_array",
        "Node_var_new",
        "Node_param_list",
@@ -1137,6 +1138,10 @@ r_get_lhs(NODE *n, bool reference)
        case Node_var:
                break;
 
+       case Node_var_const:
+               fatal(_("cannot assign to defined constant"));
+               break;
+
        default:
                cant_happen();
        }
@@ -1311,6 +1316,12 @@ setup_frame(INSTRUCTION *pc)
                        r->prev_array = m;
                        break;
 
+               case Node_var_const:
+                       /*
+                        * constant passed by value as parameter
+                        * becomes mutable in the function.
+                        */
+                       /* FALL THROUGH */
                case Node_var:
                        /* Untyped (Node_var_new) variable as param became a
                         * scalar during evaluation of expression for a
@@ -1539,6 +1550,9 @@ op_assign(OPCODE op)
        AWKNUM x = 0.0, x1, x2;
 
        lhs = POP_ADDRESS();
+       if ((*lhs)->type == Node_var_const)
+               fatal(_("cannot assign to defined constant"));
+
        t1 = *lhs;
        x1 = force_number(t1)->numbr;
 
diff --git a/extension/ChangeLog b/extension/ChangeLog
index fcaff2b..a73ccc1 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,5 +1,9 @@
 2013-03-04         Arnold D. Robbins     <address@hidden>
 
+       * testext.c: Make answer_num a constant.
+
+2013-03-04         Arnold D. Robbins     <address@hidden>
+
        * filefuncs.c (fill_stat_array): Adjust computation for block
        count for WIN32 systems after consultation with Eli Zaretskii.
 
diff --git a/extension/testext.c b/extension/testext.c
index f7bf08a..502eba3 100644
--- a/extension/testext.c
+++ b/extension/testext.c
@@ -853,7 +853,7 @@ BEGIN {
 */
 
        /* install some variables */
-       if (! sym_update("answer_num", make_number(42, & value)))
+       if (! sym_constant("answer_num", make_number(42, & value)))
                printf("testext: sym_update(\"answer_num\") failed!\n");
 
        if (! sym_update("message_string",
diff --git a/gawkapi.c b/gawkapi.c
index d17ee42..640db0d 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -538,12 +538,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 */
+/* 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,
+sym_update_real(awk_ext_id_t id,
                const char *name,
-               awk_value_t *value)
+               awk_value_t *value,
+               bool is_const)
 {
        NODE *node;
        NODE *array_node;
@@ -584,6 +585,8 @@ api_sym_update(awk_ext_id_t id,
                        node = install_symbol(estrdup((char *) name, 
strlen(name)),
                                        Node_var);
                        node->var_value = awk_value_to_node(value);
+                       if (is_const)
+                               node->type = Node_var_const;
                }
 
                return true;
@@ -603,8 +606,12 @@ api_sym_update(awk_ext_id_t id,
            && (node->type == Node_var || 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)
-                       node->type = Node_var;
+               if (value->val_type != AWK_UNDEFINED) {
+                       if (node->type == Node_var_new)
+                               node->type = Node_var;
+                       else if (is_const)
+                               node->type = Node_var_const;
+               }
 
                return true;
        }
@@ -709,6 +716,22 @@ valid_subscript_type(awk_valtype_t valtype)
        }
 }
 
+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);
+}
+
+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);
+}
+
 /* Array management */
 /*
  * api_get_array_element --- teturn the value of an element - read only!
@@ -1089,6 +1112,7 @@ gawk_api_t api_impl = {
        /* Accessing and installing variables and constants */
        api_sym_lookup,
        api_sym_update,
+       api_sym_constant,
 
        /* Accessing and modifying variables via scalar cookies */
        api_sym_lookup_scalar,
diff --git a/gawkapi.h b/gawkapi.h
index b2e5ed5..063b497 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -551,6 +551,13 @@ typedef struct gawk_api {
                                awk_value_t *value);
 
        /*
+        * Install a constant value.
+        */
+       awk_bool_t (*sym_constant)(awk_ext_id_t id,
+                               const char *name,
+                               awk_value_t *value);
+
+       /*
         * A ``scalar cookie'' is an opaque handle that provide access
         * to a global variable or array. It is an optimization that
         * avoids looking up variables in gawk's symbol table every time
@@ -710,6 +717,8 @@ typedef struct gawk_api {
        (api->api_sym_update(ext_id, name, value))
 #define sym_update_scalar(scalar_cookie, value) \
        (api->api_sym_update_scalar)(ext_id, scalar_cookie, value)
+#define sym_constant(name, value) \
+       (api->sym_constant(ext_id, name, value))
 
 #define get_array_element(array, index, wanted, result) \
        (api->api_get_array_element(ext_id, array, index, wanted, result))
diff --git a/interpret.h b/interpret.h
index 8e0fdee..a2661e8 100644
--- a/interpret.h
+++ b/interpret.h
@@ -151,6 +151,7 @@ top:
                                
                        switch (m->type) {
                        case Node_var:
+                       case Node_var_const:
                                if (do_lint && var_uninitialized(m))
                                        lintwarn(isparam ?
                                                _("reference to uninitialized 
argument `%s'") :
@@ -556,6 +557,8 @@ mod:
                case Op_predecrement:
                        x = op == Op_preincrement ? 1.0 : -1.0;
                        lhs = TOP_ADDRESS();
+                       if ((*lhs)->type == Node_var_const)
+                               fatal(_("cannot assign to defined constant"));
                        t1 = *lhs;
                        force_number(t1);
                        if (t1->valref == 1 && t1->flags == 
(MALLOC|NUMCUR|NUMBER)) {
@@ -574,6 +577,8 @@ mod:
                case Op_postdecrement:
                        x = op == Op_postincrement ? 1.0 : -1.0;
                        lhs = TOP_ADDRESS();
+                       if ((*lhs)->type == Node_var_const)
+                               fatal(_("cannot assign to defined constant"));
                        t1 = *lhs;
                        force_number(t1);
                        r = make_number(t1->numbr);
diff --git a/profile.c b/profile.c
index 4764fe0..1ea7573 100644
--- a/profile.c
+++ b/profile.c
@@ -259,6 +259,7 @@ pprint(INSTRUCTION *startp, INSTRUCTION *endp, bool 
in_for_header)
                                break;
 
                        case Node_var:
+                       case Node_var_const:
                        case Node_var_new:
                        case Node_var_array:
                                if (m->vname != NULL)
diff --git a/symbol.c b/symbol.c
index 354bfca..d84df62 100644
--- a/symbol.c
+++ b/symbol.c
@@ -257,6 +257,7 @@ destroy_symbol(NODE *r)
                break;
 
        case Node_var: 
+       case Node_var_const: 
                unref(r->var_value);
                break;
 
@@ -281,7 +282,7 @@ make_symbol(char *name, NODETYPE type)
        memset(r, '\0', sizeof(NODE));
        if (type == Node_var_array)
                null_array(r);
-       else if (type == Node_var)
+       else if (type == Node_var || type == Node_var_const)
                r->var_value = dupnode(Nnull_string);
        r->vname = name;
        r->type = type;
@@ -459,6 +460,10 @@ print_vars(NODE **table, int (*print_func)(FILE *, const 
char *, ...), FILE *fp)
                        print_func(fp, "untyped variable\n");
                else if (r->type == Node_var)
                        valinfo(r->var_value, print_func, fp);
+               else if (r->type == Node_var_const) {
+                       print_func(fp, "defined constant ");
+                       valinfo(r->var_value, print_func, fp);
+               }
        }
 }
 

-----------------------------------------------------------------------


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]