gawk-diffs
[Top][All Lists]
Advanced

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

[gawk-diffs] [SCM] gawk branch, master, updated. 30d53f88beb52e2682fa981


From: Arnold Robbins
Subject: [gawk-diffs] [SCM] gawk branch, master, updated. 30d53f88beb52e2682fa9814bad25f803a856c54
Date: Sat, 01 Dec 2012 20:22:22 +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, master has been updated
       via  30d53f88beb52e2682fa9814bad25f803a856c54 (commit)
       via  79796c4b5882e559a6a5f5453e47f8936df6a397 (commit)
       via  787d93719e61e44aa1ab66c8ecca9cd6ff4fddbf (commit)
      from  242ee720a6387f87e05d3eb8e30d2c7061cbf8ef (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

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

commit 30d53f88beb52e2682fa9814bad25f803a856c54
Author: Arnold D. Robbins <address@hidden>
Date:   Sat Dec 1 22:22:03 2012 +0200

    Doc updates.

diff --git a/README.git b/README.git
index 7dbc24c..7d0d260 100644
--- a/README.git
+++ b/README.git
@@ -1,4 +1,4 @@
-Sun Aug  5 16:25:58 IDT 2012
+Sat Dec  1 21:53:02 IST 2012
 ============================
 
 If you are reading this, you have retrieved the gawk code base via
@@ -327,3 +327,26 @@ turn, followed by "bzr pull" to sync the branch.
 
 It depends upon if you have pushed the commit or not. Lots of good
 info is at http://stackoverflow.com/questions/927358/git-undo-last-commit .
+
+- What is the difference between using `git rebase' and `git merge' ?
+
+Both of these can be used to bring one branch up to date with respect
+to another.  For example, if you are working on a feature branch based
+off master, and master has since progressed, you can use
+
+       git checkout feature
+       git merge master
+
+or
+
+       git checkout feature
+       git rebase master
+
+In the end, you will have your changes on top of the current version of
+master in the feature branch.
+
+So which to use?  The answer depends on whether your feature branch
+has been pushed up to the Savannah repo or not.
+
+If your branch is completely local to your machine, use `git rebase'.
+Otherwise, use `git merge'.
diff --git a/TODO b/TODO
index 676e56a..b14a002 100644
--- a/TODO
+++ b/TODO
@@ -19,12 +19,12 @@ Minor Cleanups and Code Improvements
        Make GAWKDEBUG pass the test suite.
 
        API:
-               awk_true and awk_false ???
+               DONE: awk_true and awk_false
                DONE: Update doc to use gcc -o filefuncs.so -shared filefuncs.o
                        instead of ld ...
                ??? #if !defined(GAWK) && !defined(GAWK_OMIT_CONVENIENCE_MACROS)
 
-       Make fflush() and fflush("") both flush all files, as in BWK awk.
+       DONE: Make fflush() and fflush("") both flush all files, as in BWK awk.
 
        ?? Add debugger commands to reference card
 
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 21a1c97..1d4a9e3 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,7 @@
+2012-12-01         Arnold D. Robbins     <address@hidden>
+
+       * gawk.texi: API chapter. Sync with gawkapi.h
+
 2012-11-27         Arnold D. Robbins     <address@hidden>
 
        * gawk.texi: API chapter. Change command for making shared libs
diff --git a/doc/gawk.info b/doc/gawk.info
index ca98646..724ae20 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -21920,11 +21920,16 @@ that use them.
      in the API data structures unwritable from extension code, while
      allowing `gawk' to use them as it needs to.
 
-`typedef int awk_bool_t;'
-     A simple boolean type. At the moment, the API does not define
-     special "true" and "false" values, although perhaps it should.
+`typedef enum awk_bool {'
 
-`typedef struct {'
+`    awk_false = 0,'
+
+`    awk_true'
+
+`} awk_bool_t;'
+     A simple boolean type.
+
+`typedef struct awk_string {'
 `    char *str;      /* data */'
 `    size_t len;     /* length thereof, in chars */'
 `} awk_string_t;'
@@ -21946,7 +21951,7 @@ that use them.
      This `enum' indicates the type of a value.  It is used in the
      following `struct'.
 
-`typedef struct {'
+`typedef struct awk_value {'
 `    awk_valtype_t   val_type;'
 `    union {'
 `        awk_string_t       s;'
@@ -22166,7 +22171,7 @@ File: gawk.info,  Node: Extension Functions,  Next: 
Exit Callback Functions,  Up
 
 Extension functions are described by the following record:
 
-     typedef struct {
+     typedef struct awk_ext_func {
          const char *name;
          awk_value_t *(*function)(int num_actual_args, awk_value_t *result);
          size_t num_expected_args;
@@ -22285,11 +22290,11 @@ used for `RT', if any.
    Your extension should package these functions inside an
 `awk_input_parser_t', which looks like this:
 
-     typedef struct input_parser {
+     typedef struct awk_input_parser {
          const char *name;   /* name of parser */
          awk_bool_t (*can_take_file)(const awk_input_buf_t *iobuf);
          awk_bool_t (*take_control_of)(awk_input_buf_t *iobuf);
-         awk_const struct input_parser *awk_const next;    /* for use by gawk 
*/
+         awk_const struct awk_input_parser *awk_const next;    /* for use by 
gawk */
      } awk_input_parser_t;
 
    The fields are:
@@ -22456,11 +22461,11 @@ an extension to take over the output to a file opened 
with the `>' or
 
    The output wrapper is very similar to the input parser structure:
 
-     typedef struct output_wrapper {
+     typedef struct awk_output_wrapper {
          const char *name;   /* name of the wrapper */
          awk_bool_t (*can_take_file)(const awk_output_buf_t *outbuf);
          awk_bool_t (*take_control_of)(awk_output_buf_t *outbuf);
-         awk_const struct output_wrapper *awk_const next;  /* for use by gawk 
*/
+         awk_const struct awk_output_wrapper *awk_const next;  /* for use by 
gawk */
      } awk_output_wrapper_t;
 
    The members are as follows:
@@ -22487,7 +22492,7 @@ an extension to take over the output to a file opened 
with the `>' or
 
    The `awk_output_buf_t' structure looks like this:
 
-     typedef struct {
+     typedef struct awk_output_buf {
          const char *name;   /* name of output file */
          const char *mode;   /* mode argument to fopen */
          FILE *fp;           /* stdio file pointer */
@@ -22563,13 +22568,13 @@ structures as described earlier.
 
    A two-way processor is represented by the following structure:
 
-     typedef struct two_way_processor {
+     typedef struct awk_two_way_processor {
          const char *name;   /* name of the two-way processor */
          awk_bool_t (*can_take_two_way)(const char *name);
          awk_bool_t (*take_control_of)(const char *name,
                                        awk_input_buf_t *inbuf,
                                        awk_output_buf_t *outbuf);
-         awk_const struct two_way_processor *awk_const next;  /* for use by 
gawk */
+         awk_const struct awk_two_way_processor *awk_const next;  /* for use 
by gawk */
      } awk_two_way_processor_t;
 
    The fields are as follows:
@@ -23612,8 +23617,8 @@ in the `gawkapi.h' header file:
      If you need to do some initialization work, you should define a
      function that does it (creates variables, opens files, etc.)  and
      then define the `init_func' pointer to point to your function.
-     The function should return zero (false) upon failure, non-zero
-     (success) if everything goes well.
+     The function should return `awk_false' upon failure, or `awk_true'
+     if everything goes well.
 
      If you don't need to do any initialization, define the pointer and
      initialize it to `NULL'.
@@ -23634,7 +23639,7 @@ standard work. It does the following:
      to load, it prints a warning message but continues on.
 
   3. If the `init_func' pointer is not `NULL', call the function it
-     points to. If it returns non-zero, print a warning message.
+     points to. If it returns `awk_false', print a warning message.
 
   4. If `ext_version' is not `NULL', register the version string with
      `gawk'.
@@ -32167,117 +32172,117 @@ Node: Extension Future Growth878591
 Node: Extension API Description879409
 Node: Extension API Functions Introduction880737
 Node: General Data Types885437
-Ref: General Data Types-Footnote-1891070
-Node: Requesting Values891369
-Ref: table-value-types-returned892100
-Node: Constructor Functions893054
-Node: Registration Functions896050
-Node: Extension Functions896735
-Node: Exit Callback Functions898554
-Node: Extension Version String899797
-Node: Input Parsers900447
-Node: Output Wrappers909026
-Node: Two-way processors913419
-Node: Printing Messages915541
-Ref: Printing Messages-Footnote-1916618
-Node: Updating `ERRNO'916770
-Node: Accessing Parameters917509
-Node: Symbol Table Access918739
-Node: Symbol table by name919251
-Ref: Symbol table by name-Footnote-1921421
-Node: Symbol table by cookie921501
-Ref: Symbol table by cookie-Footnote-1925630
-Node: Cached values925693
-Ref: Cached values-Footnote-1929136
-Node: Array Manipulation929227
-Ref: Array Manipulation-Footnote-1930325
-Node: Array Data Types930364
-Ref: Array Data Types-Footnote-1933067
-Node: Array Functions933159
-Node: Flattening Arrays936925
-Node: Creating Arrays943758
-Node: Extension API Variables948553
-Node: Extension Versioning949189
-Node: Extension API Informational Variables951090
-Node: Extension API Boilerplate952176
-Node: Finding Extensions956010
-Node: Extension Example956557
-Node: Internal File Description957295
-Node: Internal File Ops960983
-Ref: Internal File Ops-Footnote-1972430
-Node: Using Internal File Ops972570
-Ref: Using Internal File Ops-Footnote-1974923
-Node: Extension Samples975189
-Node: Extension Sample File Functions976632
-Node: Extension Sample Fnmatch985105
-Node: Extension Sample Fork986831
-Node: Extension Sample Ord988045
-Node: Extension Sample Readdir988821
-Node: Extension Sample Revout990325
-Node: Extension Sample Rev2way990918
-Node: Extension Sample Read write array991608
-Node: Extension Sample Readfile993491
-Node: Extension Sample API Tests994246
-Node: Extension Sample Time994771
-Node: gawkextlib996078
-Node: Language History998459
-Node: V7/SVR3.1999981
-Node: SVR41002302
-Node: POSIX1003744
-Node: BTL1004752
-Node: POSIX/GNU1005486
-Node: Common Extensions1011021
-Node: Ranges and Locales1012128
-Ref: Ranges and Locales-Footnote-11016746
-Ref: Ranges and Locales-Footnote-21016773
-Ref: Ranges and Locales-Footnote-31017033
-Node: Contributors1017254
-Node: Installation1021550
-Node: Gawk Distribution1022444
-Node: Getting1022928
-Node: Extracting1023754
-Node: Distribution contents1025446
-Node: Unix Installation1030668
-Node: Quick Installation1031285
-Node: Additional Configuration Options1033247
-Node: Configuration Philosophy1034724
-Node: Non-Unix Installation1037066
-Node: PC Installation1037524
-Node: PC Binary Installation1038823
-Node: PC Compiling1040671
-Node: PC Testing1043615
-Node: PC Using1044791
-Node: Cygwin1048976
-Node: MSYS1049976
-Node: VMS Installation1050490
-Node: VMS Compilation1051093
-Ref: VMS Compilation-Footnote-11052100
-Node: VMS Installation Details1052158
-Node: VMS Running1053793
-Node: VMS Old Gawk1055400
-Node: Bugs1055874
-Node: Other Versions1059726
-Node: Notes1065041
-Node: Compatibility Mode1065700
-Node: Additions1066483
-Node: Accessing The Source1067410
-Node: Adding Code1069013
-Node: New Ports1075055
-Node: Derived Files1079190
-Ref: Derived Files-Footnote-11084498
-Ref: Derived Files-Footnote-21084532
-Ref: Derived Files-Footnote-31085132
-Node: Future Extensions1085230
-Node: Implementation Limitations1085811
-Node: Basic Concepts1087038
-Node: Basic High Level1087719
-Ref: figure-general-flow1087990
-Ref: figure-process-flow1088589
-Ref: Basic High Level-Footnote-11091818
-Node: Basic Data Typing1092003
-Node: Glossary1095358
-Node: Copying1120669
-Node: GNU Free Documentation License1158226
-Node: Index1183363
+Ref: General Data Types-Footnote-1891039
+Node: Requesting Values891338
+Ref: table-value-types-returned892069
+Node: Constructor Functions893023
+Node: Registration Functions896019
+Node: Extension Functions896704
+Node: Exit Callback Functions898536
+Node: Extension Version String899779
+Node: Input Parsers900429
+Node: Output Wrappers909016
+Node: Two-way processors913432
+Node: Printing Messages915562
+Ref: Printing Messages-Footnote-1916639
+Node: Updating `ERRNO'916791
+Node: Accessing Parameters917530
+Node: Symbol Table Access918760
+Node: Symbol table by name919272
+Ref: Symbol table by name-Footnote-1921442
+Node: Symbol table by cookie921522
+Ref: Symbol table by cookie-Footnote-1925651
+Node: Cached values925714
+Ref: Cached values-Footnote-1929157
+Node: Array Manipulation929248
+Ref: Array Manipulation-Footnote-1930346
+Node: Array Data Types930385
+Ref: Array Data Types-Footnote-1933088
+Node: Array Functions933180
+Node: Flattening Arrays936946
+Node: Creating Arrays943779
+Node: Extension API Variables948574
+Node: Extension Versioning949210
+Node: Extension API Informational Variables951111
+Node: Extension API Boilerplate952197
+Node: Finding Extensions956028
+Node: Extension Example956575
+Node: Internal File Description957313
+Node: Internal File Ops961001
+Ref: Internal File Ops-Footnote-1972448
+Node: Using Internal File Ops972588
+Ref: Using Internal File Ops-Footnote-1974941
+Node: Extension Samples975207
+Node: Extension Sample File Functions976650
+Node: Extension Sample Fnmatch985123
+Node: Extension Sample Fork986849
+Node: Extension Sample Ord988063
+Node: Extension Sample Readdir988839
+Node: Extension Sample Revout990343
+Node: Extension Sample Rev2way990936
+Node: Extension Sample Read write array991626
+Node: Extension Sample Readfile993509
+Node: Extension Sample API Tests994264
+Node: Extension Sample Time994789
+Node: gawkextlib996096
+Node: Language History998477
+Node: V7/SVR3.1999999
+Node: SVR41002320
+Node: POSIX1003762
+Node: BTL1004770
+Node: POSIX/GNU1005504
+Node: Common Extensions1011039
+Node: Ranges and Locales1012146
+Ref: Ranges and Locales-Footnote-11016764
+Ref: Ranges and Locales-Footnote-21016791
+Ref: Ranges and Locales-Footnote-31017051
+Node: Contributors1017272
+Node: Installation1021568
+Node: Gawk Distribution1022462
+Node: Getting1022946
+Node: Extracting1023772
+Node: Distribution contents1025464
+Node: Unix Installation1030686
+Node: Quick Installation1031303
+Node: Additional Configuration Options1033265
+Node: Configuration Philosophy1034742
+Node: Non-Unix Installation1037084
+Node: PC Installation1037542
+Node: PC Binary Installation1038841
+Node: PC Compiling1040689
+Node: PC Testing1043633
+Node: PC Using1044809
+Node: Cygwin1048994
+Node: MSYS1049994
+Node: VMS Installation1050508
+Node: VMS Compilation1051111
+Ref: VMS Compilation-Footnote-11052118
+Node: VMS Installation Details1052176
+Node: VMS Running1053811
+Node: VMS Old Gawk1055418
+Node: Bugs1055892
+Node: Other Versions1059744
+Node: Notes1065059
+Node: Compatibility Mode1065718
+Node: Additions1066501
+Node: Accessing The Source1067428
+Node: Adding Code1069031
+Node: New Ports1075073
+Node: Derived Files1079208
+Ref: Derived Files-Footnote-11084516
+Ref: Derived Files-Footnote-21084550
+Ref: Derived Files-Footnote-31085150
+Node: Future Extensions1085248
+Node: Implementation Limitations1085829
+Node: Basic Concepts1087056
+Node: Basic High Level1087737
+Ref: figure-general-flow1088008
+Ref: figure-process-flow1088607
+Ref: Basic High Level-Footnote-11091836
+Node: Basic Data Typing1092021
+Node: Glossary1095376
+Node: Copying1120687
+Node: GNU Free Documentation License1158244
+Node: Index1183381
 
 End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 6abc337..02b7623 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -28818,11 +28818,13 @@ and to nothing when compiling @command{gawk} itself.  
This makes
 certain fields in the API data structures unwritable from extension code,
 while allowing @command{gawk} to use them as it needs to.
 
address@hidden typedef int awk_bool_t;
-A simple boolean type. At the moment, the API does not define special
-``true'' and ``false'' values, although perhaps it should.
address@hidden typedef enum awk_bool @{
address@hidden @ @ @ @ awk_false = 0,
address@hidden @ @ @ @ awk_true
address@hidden @} awk_bool_t;
+A simple boolean type.
 
address@hidden typedef struct @{
address@hidden typedef struct awk_string @{
 @itemx @ @ @ @ char *str;@ @ @ @ @ @ /* data */
 @itemx @ @ @ @ size_t len;@ @ @ @ @ /* length thereof, in chars */
 @itemx @} awk_string_t;
@@ -28845,7 +28847,7 @@ multibyte encoding.
 This @code{enum} indicates the type of a value.
 It is used in the following @code{struct}.
 
address@hidden typedef struct @{
address@hidden typedef struct awk_value @{
 @itemx @ @ @ @ awk_valtype_t   val_type;
 @itemx @ @ @ @ union @{
 @itemx @ @ @ @ @ @ @ @ awk_string_t@ @ @ @ @ @ @ s;
@@ -29091,7 +29093,7 @@ registering parts of your extension with @command{gawk}.
 Extension functions are described by the following record:
 
 @example
-typedef struct @{
+typedef struct awk_ext_func @{
 @ @ @ @ const char *name;
 @ @ @ @ awk_value_t *(*function)(int num_actual_args, awk_value_t *result);
 @ @ @ @ size_t num_expected_args;
@@ -29220,11 +29222,11 @@ Your extension should package these functions inside 
an
 @code{awk_input_parser_t}, which looks like this:
 
 @example
-typedef struct input_parser @{
+typedef struct awk_input_parser @{
     const char *name;   /* name of parser */
     awk_bool_t (*can_take_file)(const awk_input_buf_t *iobuf);
     awk_bool_t (*take_control_of)(awk_input_buf_t *iobuf);
-    awk_const struct input_parser *awk_const next;    /* for use by gawk */
+    awk_const struct awk_input_parser *awk_const next;    /* for use by gawk */
 @} awk_input_parser_t;
 @end example
 
@@ -29413,11 +29415,11 @@ with the @samp{>} or @samp{>>} operators 
(@pxref{Redirection}).
 The output wrapper is very similar to the input parser structure:
 
 @example
-typedef struct output_wrapper @{
+typedef struct awk_output_wrapper @{
     const char *name;   /* name of the wrapper */
     awk_bool_t (*can_take_file)(const awk_output_buf_t *outbuf);
     awk_bool_t (*take_control_of)(awk_output_buf_t *outbuf);
-    awk_const struct output_wrapper *awk_const next;  /* for use by gawk */
+    awk_const struct awk_output_wrapper *awk_const next;  /* for use by gawk */
 @} awk_output_wrapper_t;
 @end example
 
@@ -29447,7 +29449,7 @@ This is for use by @command{gawk}.
 The @code{awk_output_buf_t} structure looks like this:
 
 @example
-typedef struct @{
+typedef struct awk_output_buf @{
     const char *name;   /* name of output file */
     const char *mode;   /* mode argument to fopen */
     FILE *fp;           /* stdio file pointer */
@@ -29526,13 +29528,13 @@ as described earlier.
 A two-way processor is represented by the following structure:
 
 @example
-typedef struct two_way_processor @{
+typedef struct awk_two_way_processor @{
     const char *name;   /* name of the two-way processor */
     awk_bool_t (*can_take_two_way)(const char *name);
     awk_bool_t (*take_control_of)(const char *name,
                                   awk_input_buf_t *inbuf,
                                   awk_output_buf_t *outbuf);
-    awk_const struct two_way_processor *awk_const next;  /* for use by gawk */
+    awk_const struct awk_two_way_processor *awk_const next;  /* for use by 
gawk */
 @} awk_two_way_processor_t;
 @end example
 
@@ -30432,7 +30434,7 @@ static awk_bool_t init_testarray(void)
 @{
     create_new_array();
 
-    return 1;
+    return awk_true;
 @}
 
 static awk_bool_t (*init_func)(void) = init_testarray;
@@ -30650,8 +30652,8 @@ If you need to do some initialization work, you should 
define a
 function that does it (creates variables, opens files, etc.)
 and then define the @code{init_func} pointer to point to your
 function.
-The function should return zero (false) upon failure, non-zero
-(success) if everything goes well.
+The function should return @code{awk_false} upon failure, or @code{awk_true}
+if everything goes well.
 
 If you don't need to do any initialization, define the pointer and
 initialize it to @code{NULL}.
@@ -30678,7 +30680,7 @@ continues on.
 
 @item
 If the @code{init_func} pointer is not @code{NULL}, call the
-function it points to. If it returns non-zero, print a
+function it points to. If it returns @code{awk_false}, print a
 warning message.
 
 @item

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

commit 79796c4b5882e559a6a5f5453e47f8936df6a397
Merge: 242ee72 787d937
Author: Arnold D. Robbins <address@hidden>
Date:   Sat Dec 1 22:06:37 2012 +0200

    Merge branch 'gawk-4.0-stable'

diff --cc ChangeLog
index 36af31c,0b2b7f4..c87c1cc
--- a/ChangeLog
+++ b/ChangeLog
@@@ -1,80 -1,11 +1,88 @@@
+ 2012-12-01         Arnold D. Robbins     <address@hidden>
+ 
 -      * eval.c (r_interpret): For op_assign_concat, if both strings
++      * interpret.h: For op_assign_concat, if both strings
+       have WSTRCUR, then do the realloc() and append for the
+       wide string too.  Thanks to Janis Papanagnou
+       <address@hidden> for the discussion in
+       comp.lang.awk.
+ 
 +2012-11-30         Arnold D. Robbins     <address@hidden>
 +
 +      * regcomp.c, regex.c, regex_internal.h, regexec.c: Sync
 +      with GLIBC.  Why not.
 +
 +      * gawkapi.c (awk_bool_t): Change into an enum with awk_false and
 +      awk_true values.
 +
 +2012-01-30         Andrew J. Schorr     <address@hidden>
 +
 +      Further cleanups of macros in awk.h
 +
 +      * awk.h (_r, _t): Remove declarations.
 +      (unref, m_force_string): Remove macros.
 +      (r_unref): Move declaration.
 +      (r_force_string): Remove declaration.
 +      (DEREF, force_string, force_number, unref): Now inline functions.
 +      (POP_STRING, TOP_STRING): Back to macros.
 +      * eval.c (_t): Remove definition.
 +      * main.c (_r): Remove definition.
 +      * node.c (r_force_string): Remove.
 +
 +2012-11-27         Arnold D. Robbins     <address@hidden>
 +
 +      * builtin.c (do_fflush): Make fflush() and fflush("") both
 +      flush everything. See the comment in the code.
 +
 +2012-11-24         Arnold D. Robbins     <address@hidden>
 +
 +      Directory cleanup.
 +
 +      * TODO.xgawk, FUTURES: Merged into TODO.
 +      * TODO: More stuff added.
 +      * Makefile.am (EXTRA_DIST): Updated.
 +
 +2012-11-22         Arnold D. Robbins     <address@hidden>
 +
 +      Cleanup of awk.h.
 +
 +      * array.c (r_in_array): Removed.
 +      * awk.h (MALLOC_ARG_T): Replaced with size_t everywhere.
 +      (S_ISREG, setsid): Moved to io.c.
 +      (__extension__): Removed.
 +      (INT32_BIT): Moved to cint_array.c.
 +      (_t): Always declare.
 +      (DO_LINT_INVALID, et al): Moved into an enum.
 +      (POP_ARRAY, POP_PARAM, POP_SCALAR, TOP_SCALAR, dupnode, in_array):
 +      Moved into inline functions.
 +      (force_number, force_string): Simplified.
 +      (ZOS_USS): Remove undef of DYNAMIC, it's handled in configure.ac.
 +      * io.c (S_ISREG, setsid): Moved to here.
 +      * cint_array.c (INT32_BIT): Moved to here.
 +      * eval.c (_t): Always define.
 +      * protos.h: Use size_t directly instead of MALLOC_ARG_T.
 +
 +      Unrelated:
 +
 +      * gawkapi.h: Add `awk_' prefix to structure tags where they
 +      were missing.  Document the full list of include files needed.
 +
 +2012-11-14         Arnold D. Robbins     <address@hidden>
 +
 +      * io.c (do_find_source): On VMS, don't add the `/' separater.
 +      Thanks to Anders Wallin.
 +
 +      MPFR minor cleanup:
 +
 +      * awk.h (mpfr_unset): Declare new function.
 +      * mpfr.c (mpfr_unset): New function.
 +      * node.c (r_unref): Call it instead of inline code.
 +      * gawk_api.c (api_sym_update_scalar): Call it instead of inline code.
 +
 +2012-11-13         Arnold D. Robbins     <address@hidden>
 +
 +      * symbol.c (get_symbols): Check type, not vname. Keeps
 +      valgrind happy. Thanks to Andrew Schorr for noticing the problem.
 +
  2012-11-10         Arnold D. Robbins     <address@hidden>
  
        * Update to bison 2.6.5. Various files regenerated.
diff --cc interpret.h
index 26725a2,0000000..21cd9a8
mode 100644,000000..100644
--- a/interpret.h
+++ b/interpret.h
@@@ -1,1273 -1,0 +1,1285 @@@
 +/*
 + * interpret.h ---  run a list of instructions.
 + */
 +
 +/* 
 + * Copyright (C) 1986, 1988, 1989, 1991-2012 the Free Software Foundation, 
Inc.
 + * 
 + * This file is part of GAWK, the GNU implementation of the
 + * AWK Programming Language.
 + * 
 + * GAWK is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 3 of the License, or
 + * (at your option) any later version.
 + * 
 + * GAWK is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA
 + */
 +
 +
 +int
 +r_interpret(INSTRUCTION *code)
 +{
 +      INSTRUCTION *pc;   /* current instruction */
 +      OPCODE op;      /* current opcode */
 +      NODE *r = NULL;
 +      NODE *m;
 +      INSTRUCTION *ni;
 +      NODE *t1, *t2;
 +      NODE **lhs;
 +      AWKNUM x, x2;
 +      int di;
 +      Regexp *rp;
 +
 +/* array subscript */
 +#define mk_sub(n)     (n == 1 ? POP_SCALAR() : concat_exp(n, true))
 +
 +#ifdef EXEC_HOOK
 +#define JUMPTO(x)     do { if (post_execute) post_execute(pc); pc = (x); goto 
top; } while (false)
 +#else
 +#define JUMPTO(x)     do { pc = (x); goto top; } while (false)
 +#endif
 +
 +      pc = code;
 +
 +      /* N.B.: always use JUMPTO for next instruction, otherwise bad things
 +       * may happen. DO NOT add a real loop (for/while) below to
 +       * replace ' forever {'; this catches failure to use JUMPTO to execute
 +       * next instruction (e.g. continue statement).
 +       */
 +
 +      /* loop until hit Op_stop instruction */
 +
 +      /* forever {  */
 +top:
 +              if (pc->source_line > 0)
 +                      sourceline = pc->source_line;
 +
 +#ifdef EXEC_HOOK
 +              for (di = 0; di < num_exec_hook; di++) {
 +                      if (! pre_execute[di](& pc))
 +                              goto top;
 +              }
 +#endif
 +
 +              switch ((op = pc->opcode)) {
 +              case Op_rule:
 +                      currule = pc->in_rule;   /* for sole use in Op_K_next, 
Op_K_nextfile, Op_K_getline */
 +                      /* fall through */
 +              case Op_func:
 +                      source = pc->source_file;
 +                      break;
 +
 +              case Op_atexit:
 +              {
 +                      bool stdio_problem = false;
 +
 +                      /* avoid false source indications */
 +                      source = NULL;
 +                      sourceline = 0;
 +                      (void) nextfile(& curfile, true);       /* close input 
data file */ 
 +                      /*
 +                       * This used to be:
 +                       *
 +                       * if (close_io() != 0 && ! exiting && exit_val == 0)
 +                       *      exit_val = 1;
 +                       *
 +                       * Other awks don't care about problems closing open 
files
 +                       * and pipes, in that it doesn't affect their exit 
status.
 +                       * So we no longer do either.
 +                       */
 +                      (void) close_io(& stdio_problem);
 +                      /*
 +                       * However, we do want to exit non-zero if there was a 
problem
 +                       * with stdout/stderr, so we reinstate a slightly 
different
 +                       * version of the above:
 +                       */
 +                      if (stdio_problem && ! exiting && exit_val == 0)
 +                              exit_val = 1;
 +              }
 +                      break;
 +
 +              case Op_stop:
 +                      return 0;
 +
 +              case Op_push_i:
 +                      m = pc->memory;
 +                      if (! do_traditional && (m->flags & INTLSTR) != 0) {
 +                              char *orig, *trans, save;
 +
 +                              save = m->stptr[m->stlen];
 +                              m->stptr[m->stlen] = '\0';
 +                              orig = m->stptr;
 +                              trans = dgettext(TEXTDOMAIN, orig);
 +                              m->stptr[m->stlen] = save;
 +                              m = make_string(trans, strlen(trans));
 +                      } else
 +                              UPREF(m);
 +                      PUSH(m);
 +                      break;
 +
 +              case Op_push:
 +              case Op_push_arg:
 +              {
 +                      NODE *save_symbol;
 +                      bool isparam = false;
 +
 +                      save_symbol = m = pc->memory;
 +                      if (m->type == Node_param_list) {
 +                              isparam = true;
 +                              save_symbol = m = GET_PARAM(m->param_cnt);
 +                              if (m->type == Node_array_ref)
 +                                      m = m->orig_array;
 +                      }
 +                              
 +                      switch (m->type) {
 +                      case Node_var:
 +                              if (do_lint && var_uninitialized(m))
 +                                      lintwarn(isparam ?
 +                                              _("reference to uninitialized 
argument `%s'") :
 +                                              _("reference to uninitialized 
variable `%s'"),
 +                                                              
save_symbol->vname);
 +                              m = m->var_value;
 +                              UPREF(m);
 +                              PUSH(m);
 +                              break;
 +
 +                      case Node_var_new:
 +                              m->type = Node_var;
 +                              m->var_value = dupnode(Nnull_string);
 +                              if (do_lint)
 +                                      lintwarn(isparam ?
 +                                              _("reference to uninitialized 
argument `%s'") :
 +                                              _("reference to uninitialized 
variable `%s'"),
 +                                                              
save_symbol->vname);
 +                              m = dupnode(Nnull_string);
 +                              PUSH(m);
 +                              break;
 +
 +                      case Node_var_array:
 +                              if (op == Op_push_arg)
 +                                      PUSH(m);
 +                              else
 +                                      fatal(_("attempt to use array `%s' in a 
scalar context"),
 +                                                      
array_vname(save_symbol));
 +                              break;
 +
 +                      default:
 +                              cant_happen();
 +                      }
 +              }
 +                      break;  
 +
 +              case Op_push_param:             /* function argument */
 +                      m = pc->memory;
 +                      if (m->type == Node_param_list)
 +                              m = GET_PARAM(m->param_cnt);
 +                      if (m->type == Node_var) {
 +                              m = m->var_value;
 +                              UPREF(m);
 +                              PUSH(m);
 +                              break;
 +                      }
 +                      /* else
 +                              fall through */
 +              case Op_push_array:
 +                      PUSH(pc->memory);
 +                      break;
 +
 +              case Op_push_lhs:
 +                      lhs = get_lhs(pc->memory, pc->do_reference);
 +                      PUSH_ADDRESS(lhs);
 +                      break;
 +
 +              case Op_subscript:
 +                      t2 = mk_sub(pc->sub_count);
 +                      t1 = POP_ARRAY();
 +
 +                      if (do_lint && in_array(t1, t2) == NULL) {
 +                              t2 = force_string(t2);
 +                              lintwarn(_("reference to uninitialized element 
`%s[\"%.*s\"]'"),
 +                                      array_vname(t1), (int) t2->stlen, 
t2->stptr);
 +                              if (t2->stlen == 0)
 +                                      lintwarn(_("subscript of array `%s' is 
null string"), array_vname(t1));
 +                      }
 +
 +                      /* for FUNCTAB, get the name as the element value */
 +                      if (t1 == func_table) {
 +                              static bool warned = false;
 +                              
 +                              if (do_lint && ! warned) {
 +                                      warned = true;
 +                                      lintwarn(_("FUNCTAB is a gawk 
extension"));
 +                              }
 +                              r = t2;
 +                      } else {
 +                              r = *assoc_lookup(t1, t2);
 +                      }
 +                      DEREF(t2);
 +
 +                      /* for SYMTAB, step through to the actual variable */
 +                      if (t1 == symbol_table) {
 +                              static bool warned = false;
 +                              
 +                              if (do_lint && ! warned) {
 +                                      warned = true;
 +                                      lintwarn(_("SYMTAB is a gawk 
extension"));
 +                              }
 +                              if (r->type == Node_var)
 +                                      r = r->var_value;
 +                      }
 +
 +                      if (r->type == Node_val)
 +                              UPREF(r);
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_sub_array:
 +                      t2 = mk_sub(pc->sub_count);
 +                      t1 = POP_ARRAY();
 +                      r = in_array(t1, t2);
 +                      if (r == NULL) {
 +                              r = make_array();
 +                              r->parent_array = t1;
 +                              *assoc_lookup(t1, t2) = r;
 +                              t2 = force_string(t2);
 +                              r->vname = estrdup(t2->stptr, t2->stlen);       
/* the subscript in parent array */
 +                      } else if (r->type != Node_var_array) {
 +                              t2 = force_string(t2);
 +                              fatal(_("attempt to use scalar `%s[\"%.*s\"]' 
as an array"),
 +                                              array_vname(t1), (int) 
t2->stlen, t2->stptr);
 +                      }
 +
 +                      DEREF(t2);
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_subscript_lhs:
 +                      t2 = mk_sub(pc->sub_count);
 +                      t1 = POP_ARRAY();
 +                      if (do_lint && in_array(t1, t2) == NULL) {
 +                              t2 = force_string(t2);
 +                              if (pc->do_reference) 
 +                                      lintwarn(_("reference to uninitialized 
element `%s[\"%.*s\"]'"),
 +                                              array_vname(t1), (int) 
t2->stlen, t2->stptr);
 +                              if (t2->stlen == 0)
 +                                      lintwarn(_("subscript of array `%s' is 
null string"), array_vname(t1));
 +                      }
 +
 +                      lhs = assoc_lookup(t1, t2);
 +                      if ((*lhs)->type == Node_var_array) {
 +                              t2 = force_string(t2);
 +                              fatal(_("attempt to use array `%s[\"%.*s\"]' in 
a scalar context"),
 +                                              array_vname(t1), (int) 
t2->stlen, t2->stptr);
 +                      }
 +
 +                      DEREF(t2);
 +                      PUSH_ADDRESS(lhs);
 +                      break;
 +
 +              case Op_field_spec:
 +                      t1 = TOP_SCALAR();
 +                      lhs = r_get_field(t1, (Func_ptr *) 0, true);
 +                      decr_sp();
 +                      DEREF(t1);
 +                      r = dupnode(*lhs);     /* can't use UPREF here */
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_field_spec_lhs:
 +                      t1 = TOP_SCALAR();
 +                      lhs = r_get_field(t1, &pc->target_assign->field_assign, 
pc->do_reference);
 +                      decr_sp();
 +                      DEREF(t1);
 +                      PUSH_ADDRESS(lhs);
 +                      break;
 +
 +              case Op_lint:
 +                      if (do_lint) {
 +                              switch (pc->lint_type) {
 +                              case LINT_assign_in_cond:
 +                                      lintwarn(_("assignment used in 
conditional context"));
 +                                      break;
 +
 +                              case LINT_no_effect:
 +                                      lintwarn(_("statement has no effect"));
 +                                      break;
 +
 +                              default:
 +                                      cant_happen();
 +                              }
 +                      }
 +                      break;
 +
 +              case Op_K_break:
 +              case Op_K_continue:
 +              case Op_jmp:
 +                      assert(pc->target_jmp != NULL);
 +                      JUMPTO(pc->target_jmp);
 +
 +              case Op_jmp_false:
 +                      r = POP_SCALAR();
 +                      di = eval_condition(r);
 +                      DEREF(r);
 +                      if (! di)
 +                              JUMPTO(pc->target_jmp);
 +                      break;
 +
 +              case Op_jmp_true:
 +                      r = POP_SCALAR();
 +                      di = eval_condition(r);
 +                      DEREF(r);                       
 +                      if (di)
 +                              JUMPTO(pc->target_jmp);
 +                      break;
 +
 +              case Op_and:
 +              case Op_or:
 +                      t1 = POP_SCALAR();
 +                      di = eval_condition(t1);
 +                      DEREF(t1);
 +                      if ((op == Op_and && di) || (op == Op_or && ! di))
 +                              break;
 +                      r = node_Boolean[di];
 +                      UPREF(r);
 +                      PUSH(r);
 +                      ni = pc->target_jmp;
 +                      JUMPTO(ni->nexti);
 +
 +              case Op_and_final:
 +              case Op_or_final:
 +                      t1 = TOP_SCALAR();
 +                      r = node_Boolean[eval_condition(t1)];
 +                      DEREF(t1);
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_not:
 +                      t1 = TOP_SCALAR();
 +                      r = node_Boolean[! eval_condition(t1)];
 +                      DEREF(t1);
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_equal:
 +                      r = node_Boolean[cmp_scalars() == 0];
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_notequal:
 +                      r = node_Boolean[cmp_scalars() != 0];
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_less:
 +                      r = node_Boolean[cmp_scalars() < 0];
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_greater:
 +                      r = node_Boolean[cmp_scalars() > 0];
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_leq:
 +                      r = node_Boolean[cmp_scalars() <= 0];
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_geq:
 +                      r = node_Boolean[cmp_scalars() >= 0];
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_plus_i:
 +                      x2 = force_number(pc->memory)->numbr;
 +                      goto plus;
 +              case Op_plus:
 +                      t2 = POP_NUMBER();
 +                      x2 = t2->numbr;
 +                      DEREF(t2);
 +plus:
 +                      t1 = TOP_NUMBER();
 +                      r = make_number(t1->numbr + x2);
 +                      DEREF(t1);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_minus_i:
 +                      x2 = force_number(pc->memory)->numbr;
 +                      goto minus;
 +              case Op_minus:
 +                      t2 = POP_NUMBER();
 +                      x2 = t2->numbr;
 +                      DEREF(t2);                      
 +minus:
 +                      t1 = TOP_NUMBER();
 +                      r = make_number(t1->numbr - x2);
 +                      DEREF(t1);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_times_i:
 +                      x2 = force_number(pc->memory)->numbr;
 +                      goto times;
 +              case Op_times:
 +                      t2 = POP_NUMBER();
 +                      x2 = t2->numbr;
 +                      DEREF(t2);
 +times:
 +                      t1 = TOP_NUMBER();
 +                      r = make_number(t1->numbr * x2);
 +                      DEREF(t1);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_exp_i:
 +                      x2 = force_number(pc->memory)->numbr;
 +                      goto exp;
 +              case Op_exp:
 +                      t2 = POP_NUMBER();
 +                      x2 = t2->numbr;
 +                      DEREF(t2);
 +exp:
 +                      t1 = TOP_NUMBER();
 +                      r = make_number(calc_exp(t1->numbr, x2));
 +                      DEREF(t1);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_quotient_i:
 +                      x2 = force_number(pc->memory)->numbr;
 +                      goto quotient;
 +              case Op_quotient:
 +                      t2 = POP_NUMBER();
 +                      x2 = t2->numbr;
 +                      DEREF(t2);
 +quotient:
 +                      t1 = TOP_NUMBER();
 +                      if (x2 == 0)
 +                              fatal(_("division by zero attempted"));
 +                      r = make_number(t1->numbr / x2);
 +                      DEREF(t1);
 +                      REPLACE(r);
 +                      break;          
 +
 +              case Op_mod_i:
 +                      x2 = force_number(pc->memory)->numbr;
 +                      goto mod;
 +              case Op_mod:
 +                      t2 = POP_NUMBER();
 +                      x2 = t2->numbr;
 +                      DEREF(t2);
 +mod:
 +                      t1 = TOP_NUMBER();
 +                      if (x2 == 0)
 +                              fatal(_("division by zero attempted in `%%'"));
 +#ifdef HAVE_FMOD
 +                      x = fmod(t1->numbr, x2);
 +#else /* ! HAVE_FMOD */
 +                      (void) modf(t1->numbr / x2, &x);
 +                      x = t1->numbr - x * x2;
 +#endif        /* ! HAVE_FMOD */
 +                      r = make_number(x);
 +
 +                      DEREF(t1);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_preincrement:
 +              case Op_predecrement:
 +                      x = op == Op_preincrement ? 1.0 : -1.0;
 +                      lhs = TOP_ADDRESS();
 +                      t1 = *lhs;
 +                      force_number(t1);
 +                      if (t1->valref == 1 && t1->flags == 
(MALLOC|NUMCUR|NUMBER)) {
 +                              /* optimization */
 +                              t1->numbr += x;
 +                              r = t1;
 +                      } else {
 +                              r = *lhs = make_number(t1->numbr + x);
 +                              unref(t1);
 +                      }
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_postincrement:
 +              case Op_postdecrement:
 +                      x = op == Op_postincrement ? 1.0 : -1.0;
 +                      lhs = TOP_ADDRESS();
 +                      t1 = *lhs;
 +                      force_number(t1);
 +                      r = make_number(t1->numbr);
 +                      if (t1->valref == 1 && t1->flags == 
(MALLOC|NUMCUR|NUMBER)) {
 +                              /* optimization */
 +                              t1->numbr += x;
 +                      } else {
 +                              *lhs = make_number(t1->numbr + x);
 +                              unref(t1);
 +                      }
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_unary_minus:
 +                      t1 = TOP_NUMBER();
 +                      r = make_number(-t1->numbr);
 +                      DEREF(t1);
 +                      REPLACE(r);
 +                      break;
 +
 +              case Op_store_sub:
 +                      /* array[sub] assignment optimization,
 +                       * see awkgram.y (optimize_assignment)
 +                       */
 +                      t1 = get_array(pc->memory, true);       /* array */
 +                      t2 = mk_sub(pc->expr_count);    /* subscript */
 +                      lhs = assoc_lookup(t1, t2);
 +                      if ((*lhs)->type == Node_var_array) {
 +                              t2 = force_string(t2);
 +                              fatal(_("attempt to use array `%s[\"%.*s\"]' in 
a scalar context"),
 +                                              array_vname(t1), (int) 
t2->stlen, t2->stptr);
 +                      }
 +                      DEREF(t2);
 +
 +                      /*
 +                       * Changing something in FUNCTAB is not allowed.
 +                       *
 +                       * SYMTAB is a little more messy.  Three kinds of 
values may
 +                       * be stored in SYMTAB:
 +                       *      1. Variables that don"t yet have a value 
(Node_var_new)
 +                       *      2. Variables that have a value (Node_var)
 +                       *      3. Values that awk code stuck into SYMTAB not 
related to variables (Node_value)
 +                       * For 1, since we are giving it a value, we have to 
change the type to Node_var.
 +                       * For 1 and 2, we have to step through the Node_var to 
get to the value.
 +                       * For 3, we just us the value we got from 
assoc_lookup(), above.
 +                       */
 +                      if (t1 == func_table)
 +                              fatal(_("cannot assign to elements of 
FUNCTAB"));
 +                      else if (   t1 == symbol_table
 +                               && (   (*lhs)->type == Node_var
 +                                   || (*lhs)->type == Node_var_new)) {
 +                              (*lhs)->type = Node_var;        /* in case was 
Node_var_new */
 +                              lhs = & ((*lhs)->var_value);    /* extra level 
of indirection */
 +                      }
 +
 +                      unref(*lhs);
 +                      *lhs = POP_SCALAR();
 +                      break;
 +
 +              case Op_store_var:
 +                      /* simple variable assignment optimization,
 +                       * see awkgram.y (optimize_assignment)
 +                       */
 +      
 +                      lhs = get_lhs(pc->memory, false);
 +                      unref(*lhs);
 +                      r = pc->initval;        /* constant initializer */
 +                      if (r == NULL)
 +                              *lhs = POP_SCALAR();
 +                      else {
 +                              UPREF(r);
 +                              *lhs = r;
 +                      }
 +                      break;
 +
 +              case Op_store_field:
 +              {
 +                      /* field assignment optimization,
 +                       * see awkgram.y (optimize_assignment)
 +                       */
 +
 +                      Func_ptr assign;
 +                      t1 = TOP_SCALAR();
 +                      lhs = r_get_field(t1, & assign, false);
 +                      decr_sp();
 +                      DEREF(t1);
 +                      unref(*lhs);
 +                      *lhs = POP_SCALAR();
 +                      assert(assign != NULL);
 +                      assign();
 +              }
 +                      break;
 +
 +              case Op_assign_concat:
 +                      /* x = x ... string concatenation optimization */
 +                      lhs = get_lhs(pc->memory, false);
 +                      t1 = force_string(*lhs);
 +                      t2 = POP_STRING();
 +
-                       free_wstr(*lhs);
- 
 +                      if (t1 != *lhs) {
 +                              unref(*lhs);
 +                              *lhs = dupnode(t1);
 +                      }
 +
 +                      if (t1 != t2 && t1->valref == 1 && (t1->flags & MPFN) 
== 0) {
 +                              size_t nlen = t1->stlen + t2->stlen;
 +
 +                              erealloc(t1->stptr, char *, nlen + 2, 
"r_interpret");
 +                              memcpy(t1->stptr + t1->stlen, t2->stptr, 
t2->stlen);
 +                              t1->stlen = nlen;
 +                              t1->stptr[nlen] = '\0';
 +                              t1->flags &= ~(NUMCUR|NUMBER|NUMINT);
++
++#if MBS_SUPPORT
++                              if ((t1->flags & WSTRCUR) != 0 && (t2->flags & 
WSTRCUR) != 0) {
++                                      size_t wlen = t1->wstlen + t2->wstlen;
++
++                                      erealloc(t1->wstptr, wchar_t *,
++                                                      sizeof(wchar_t) * (wlen 
+ 2), "r_interpret");
++                                      memcpy(t1->wstptr + t1->wstlen, 
t2->wstptr, t2->wstlen);
++                                      t1->wstlen = wlen;
++                                      t1->wstptr[wlen] = L'\0';
++                                      t1->flags |= WSTRCUR;
++                              } else
++                                      free_wstr(*lhs);
++#endif
 +                      } else {
 +                              size_t nlen = t1->stlen + t2->stlen;  
 +                              char *p;
 +
 +                              emalloc(p, char *, nlen + 2, "r_interpret");
 +                              memcpy(p, t1->stptr, t1->stlen);
 +                              memcpy(p + t1->stlen, t2->stptr, t2->stlen);
 +                              unref(*lhs);
 +                              t1 = *lhs = make_str_node(p, nlen, 
ALREADY_MALLOCED); 
 +                      }
 +                      DEREF(t2);
 +                      break;
 +
 +              case Op_assign:
 +                      lhs = POP_ADDRESS();
 +                      r = TOP_SCALAR();
 +                      unref(*lhs);
 +                      *lhs = r;
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      break;
 +
 +              /* numeric assignments */
 +              case Op_assign_plus:
 +              case Op_assign_minus:
 +              case Op_assign_times:
 +              case Op_assign_quotient:
 +              case Op_assign_mod:
 +              case Op_assign_exp:
 +                      op_assign(op);
 +                      break;
 +
 +              case Op_var_update:        /* update value of NR, FNR or NF */
 +                      pc->update_var();
 +                      break;
 +
 +              case Op_var_assign:
 +              case Op_field_assign:
 +                      r = TOP();
 +                      if (pc->assign_ctxt == Op_sub_builtin
 +                              && get_number_si(r) == 0        /* top of stack 
has a number == 0 */
 +                      ) {
 +                              /* There wasn't any substitutions. If the 
target is a FIELD,
 +                               * this means no field re-splitting or $0 
reconstruction.
 +                               * Skip the set_FOO routine if the target is a 
special variable.
 +                               */
 +
 +                              break;
 +                      } else if ((pc->assign_ctxt == Op_K_getline
 +                                      || pc->assign_ctxt == 
Op_K_getline_redir)
 +                              && get_number_si(r) <= 0        /* top of stack 
has a number <= 0 */
 +                      ) {
 +                              /* getline returned EOF or error */
 +
 +                              break;
 +                      }
 +
 +                      if (op == Op_var_assign)
 +                              pc->assign_var();
 +                      else
 +                              pc->field_assign();
 +                      break;
 +
 +              case Op_concat:
 +                      r = concat_exp(pc->expr_count, pc->concat_flag & 
CSUBSEP);
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_K_case:
 +                      if ((pc + 1)->match_exp) {
 +                              /* match a constant regex against switch 
expression instead of $0. */
 +
 +                              m = POP();      /* regex */
 +                              t2 = TOP_SCALAR();      /* switch expression */
 +                              t2 = force_string(t2);
 +                              rp = re_update(m);
 +                              di = (research(rp, t2->stptr, 0, t2->stlen,
 +                                                      avoid_dfa(m, t2->stptr, 
t2->stlen)) >= 0);
 +                      } else {
 +                              t1 = POP_SCALAR();      /* case value */
 +                              t2 = TOP_SCALAR();      /* switch expression */
 +                              di = (cmp_nodes(t2, t1) == 0);
 +                              DEREF(t1);
 +                      }
 +
 +                      if (di) {
 +                              /* match found */
 +                              t2 = POP_SCALAR();
 +                              DEREF(t2);
 +                              JUMPTO(pc->target_jmp);
 +                      }
 +                      break;
 +
 +              case Op_K_delete:
 +                      t1 = POP_ARRAY();
 +                      do_delete(t1, pc->expr_count);
 +                      stack_adj(-pc->expr_count);
 +                      break;
 +
 +              case Op_K_delete_loop:
 +                      t1 = POP_ARRAY();
 +                      lhs = POP_ADDRESS();    /* item */
 +                      do_delete_loop(t1, lhs);
 +                      break;
 +
 +              case Op_in_array:
 +                      t1 = POP_ARRAY();
 +                      t2 = mk_sub(pc->expr_count);
 +                      r = node_Boolean[(in_array(t1, t2) != NULL)];
 +                      DEREF(t2);
 +                      UPREF(r);
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_arrayfor_init:
 +              {
 +                      NODE **list = NULL;
 +                      NODE *array, *sort_str;
 +                      size_t num_elems = 0;
 +                      static NODE *sorted_in = NULL;
 +                      const char *how_to_sort = "@unsorted";
 +
 +                      /* get the array */
 +                      array = POP_ARRAY();
 +
 +                      /* sanity: check if empty */
 +                      if (array_empty(array))
 +                              goto arrayfor;
 +
 +                      num_elems = array->table_size;
 +
 +                      if (sorted_in == NULL)          /* do this once */
 +                              sorted_in = make_string("sorted_in", 9);
 +
 +                      sort_str = NULL;
 +                      /*
 +                       * If posix, or if there's no PROCINFO[],
 +                       * there's no ["sorted_in"], so no sorting
 +                       */
 +                      if (! do_posix && PROCINFO_node != NULL)
 +                              sort_str = in_array(PROCINFO_node, sorted_in);
 +
 +                      if (sort_str != NULL) {
 +                              sort_str = force_string(sort_str);
 +                              if (sort_str->stlen > 0)
 +                                      how_to_sort = sort_str->stptr;
 +                      }
 +
 +                      list = assoc_list(array, how_to_sort, SORTED_IN);
 +
 +arrayfor:
 +                      getnode(r);
 +                      r->type = Node_arrayfor;
 +                      r->for_list = list;
 +                      r->for_list_size = num_elems;           /* # of 
elements in list */
 +                      r->cur_idx = -1;                        /* current 
index */
 +                      r->for_array = array;           /* array */
 +                      PUSH(r);
 +
 +                      if (num_elems == 0)
 +                              JUMPTO(pc->target_jmp);   /* Op_arrayfor_final 
*/
 +              }
 +                      break;
 +
 +              case Op_arrayfor_incr:
 +                      r = TOP();      /* Node_arrayfor */
 +                      if (++r->cur_idx == r->for_list_size) {
 +                              NODE *array;
 +                              array = r->for_array;   /* actual array */
 +                              if (do_lint && array->table_size != 
r->for_list_size)
 +                                      lintwarn(_("for loop: array `%s' 
changed size from %ld to %ld during loop execution"),
 +                                              array_vname(array), (long) 
r->for_list_size, (long) array->table_size);
 +                              JUMPTO(pc->target_jmp); /* Op_arrayfor_final */
 +                      }
 +
 +                      t1 = r->for_list[r->cur_idx];
 +                      lhs = get_lhs(pc->array_var, false);
 +                      unref(*lhs);
 +                      *lhs = dupnode(t1);
 +                      break;
 +
 +              case Op_arrayfor_final:
 +                      r = POP();
 +                      assert(r->type == Node_arrayfor);
 +                      free_arrayfor(r);
 +                      break;
 +
 +              case Op_builtin:
 +                      r = pc->builtin(pc->expr_count);
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_ext_builtin:
 +              {
 +                      int arg_count = pc->expr_count;
 +                      awk_value_t result;
 +
 +                      PUSH_CODE(pc);
 +                      r = awk_value_to_node(pc->extfunc(arg_count, & result));
 +                      (void) POP_CODE();
 +                      while (arg_count-- > 0) {
 +                              t1 = POP();
 +                              if (t1->type == Node_val)
 +                                      DEREF(t1);
 +                      }
 +                      PUSH(r);
 +              }
 +                      break;
 +
 +              case Op_sub_builtin:    /* sub, gsub and gensub */
 +                      r = do_sub(pc->expr_count, pc->sub_flags);
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_K_print:
 +                      do_print(pc->expr_count, pc->redir_type);
 +                      break;
 +
 +              case Op_K_printf:
 +                      do_printf(pc->expr_count, pc->redir_type);
 +                      break;
 +
 +              case Op_K_print_rec:
 +                      do_print_rec(pc->expr_count, pc->redir_type);
 +                      break;
 +
 +              case Op_push_re:
 +                      m = pc->memory;
 +                      if (m->type == Node_dynregex) {
 +                              r = POP_STRING();
 +                              unref(m->re_exp);
 +                              m->re_exp = r;
 +                      }
 +                      PUSH(m);
 +                      break;
 +                      
 +              case Op_match_rec:
 +                      m = pc->memory;
 +                      t1 = *get_field(0, (Func_ptr *) 0);
 +match_re:
 +                      rp = re_update(m);
 +                      /*
 +                       * Any place where research() is called with a last 
parameter of
 +                       * zero, we need to use the avoid_dfa test. This 
appears here and
 +                       * in the code for Op_K_case.
 +                       *
 +                       * A new or improved dfa that distinguishes 
beginning/end of
 +                       * string from beginning/end of line will allow us to 
get rid of
 +                       * this hack.
 +                       *
 +                       * The avoid_dfa() function is in re.c; it is not very 
smart.
 +                       */
 +
 +                      di = research(rp, t1->stptr, 0, t1->stlen,
 +                                                              avoid_dfa(m, 
t1->stptr, t1->stlen));
 +                      di = (di == -1) ^ (op != Op_nomatch);
 +                      if (op != Op_match_rec) {
 +                              decr_sp();
 +                              DEREF(t1);
 +                      }
 +                      r = node_Boolean[di];
 +                      UPREF(r);
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_nomatch:
 +                      /* fall through */
 +              case Op_match:
 +                      m = pc->memory;
 +                      t1 = TOP_STRING();
 +                      if (m->type == Node_dynregex) {
 +                              unref(m->re_exp);
 +                              m->re_exp = t1;
 +                              decr_sp();
 +                              t1 = TOP_STRING();
 +                      }
 +                      goto match_re;
 +                      break;
 +
 +              case Op_indirect_func_call:
 +              {
 +                      NODE *f = NULL;
 +                      int arg_count;
 +
 +                      arg_count = (pc + 1)->expr_count;
 +                      t1 = PEEK(arg_count);   /* indirect var */
 +
 +                      if (t1->type != Node_val)       /* @a[1](p) not allowed 
in grammar */
 +                              fatal(_("indirect function call requires a 
simple scalar value"));
 +
 +                      t1 = force_string(t1);
 +                      if (t1->stlen > 0) {
 +                              /* retrieve function definition node */
 +                              f = pc->func_body;
 +                              if (f != NULL && strcmp(f->vname, t1->stptr) == 
0) {
 +                                      /* indirect var hasn't been reassigned 
*/
 +
 +                                      ni = setup_frame(pc);
 +                                      JUMPTO(ni);     /* Op_func */
 +                              }
 +                              f = lookup(t1->stptr);
 +                      }
 +
 +                      if (f == NULL || f->type != Node_func) {
 +                              if (f->type == Node_ext_func)
 +                                      fatal(_("cannot (yet) call extension 
functions indirectly"));
 +                              else
 +                                      fatal(_("function called indirectly 
through `%s' does not exist"),
 +                                                      pc->func_name); 
 +                      }
 +                      pc->func_body = f;     /* save for next call */
 +
 +                      ni = setup_frame(pc);
 +                      JUMPTO(ni);     /* Op_func */
 +              }
 +
 +              case Op_func_call:
 +              {
 +                      NODE *f;
 +
 +                      /* retrieve function definition node */
 +                      f = pc->func_body;
 +                      if (f == NULL) {
 +                              f = lookup(pc->func_name);
 +                              if (f == NULL || (f->type != Node_func && 
f->type != Node_ext_func))
 +                                      fatal(_("function `%s' not defined"), 
pc->func_name);
 +                              pc->func_body = f;     /* save for next call */
 +                      }
 +
 +                      if (f->type == Node_ext_func) {
 +                              INSTRUCTION *bc;
 +                              char *fname = pc->func_name;
 +                              int arg_count = (pc + 1)->expr_count;
 +
 +                              bc = f->code_ptr;
 +                              assert(bc->opcode == Op_symbol);
 +                              pc->opcode = Op_ext_builtin;    /* self 
modifying code */
 +                              pc->extfunc = bc->extfunc;
 +                              pc->expr_count = arg_count;             /* 
actual argument count */
 +                              (pc + 1)->func_name = fname;    /* name of the 
builtin */
 +                              (pc + 1)->expr_count = bc->expr_count;  /* 
defined max # of arguments */
 +                              ni = pc; 
 +                              JUMPTO(ni);
 +                      }
 +
 +                      ni = setup_frame(pc);
 +                      JUMPTO(ni);     /* Op_func */
 +              }
 +
 +              case Op_K_return:
 +                      m = POP_SCALAR();       /* return value */
 +
 +                      ni = pop_fcall();
 +      
 +                      /* put the return value back on stack */
 +                      PUSH(m);
 +
 +                      JUMPTO(ni);
 +
 +              case Op_K_getline_redir:
 +                      if ((currule == BEGINFILE || currule == ENDFILE)
 +                                      && pc->into_var == false
 +                                      && pc->redir_type == redirect_input)
 +                              fatal(_("`getline' invalid inside `%s' rule"), 
ruletab[currule]);
 +                      r = do_getline_redir(pc->into_var, pc->redir_type);
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_K_getline:      /* no redirection */
 +                      if (! currule || currule == BEGINFILE || currule == 
ENDFILE)
 +                              fatal(_("non-redirected `getline' invalid 
inside `%s' rule"),
 +                                              ruletab[currule]);
 +
 +                      do {
 +                              int ret;
 +                              ret = nextfile(& curfile, false);
 +                              if (ret <= 0)
 +                                      r = do_getline(pc->into_var, curfile);
 +                              else {
 +
 +                                      /* Save execution state so that we can 
return to it
 +                                       * from Op_after_beginfile or 
Op_after_endfile.
 +                                       */ 
 +
 +                                      push_exec_state(pc, currule, source, 
stack_ptr);
 +
 +                                      if (curfile == NULL)
 +                                              JUMPTO((pc + 
1)->target_endfile);
 +                                      else
 +                                              JUMPTO((pc + 
1)->target_beginfile);
 +                              }
 +                      } while (r == NULL);    /* EOF */
 +
 +                      PUSH(r);
 +                      break;
 +
 +              case Op_after_endfile:
 +                      /* Find the execution state to return to */
 +                      ni = pop_exec_state(& currule, & source, NULL);
 +
 +                      assert(ni->opcode == Op_newfile || ni->opcode == 
Op_K_getline);
 +                      JUMPTO(ni);
 +
 +              case Op_after_beginfile:
 +                      after_beginfile(& curfile);
 +
 +                      /* Find the execution state to return to */
 +                      ni = pop_exec_state(& currule, & source, NULL);
 +
 +                      assert(ni->opcode == Op_newfile || ni->opcode == 
Op_K_getline);
 +                      if (ni->opcode == Op_K_getline
 +                                      || curfile == NULL      /* skipping 
directory argument */
 +                      )
 +                              JUMPTO(ni);
 +
 +                      break;  /* read a record, Op_get_record */
 +
 +              case Op_newfile:
 +              {
 +                      int ret;
 +
 +                      ret = nextfile(& curfile, false);
 +
 +                      if (ret < 0)    /* end of input */
 +                              JUMPTO(pc->target_jmp); /* end block or 
Op_atexit */
 +
 +                      if (ret == 0) /* read a record */
 +                              JUMPTO((pc + 1)->target_get_record);
 +
 +                      /* ret > 0 */
 +                      /* Save execution state for use in Op_after_beginfile 
or Op_after_endfile. */
 +
 +                      push_exec_state(pc, currule, source, stack_ptr);
 +
 +                      if (curfile == NULL)    /* EOF */
 +                              JUMPTO(pc->target_endfile);
 +                      /* else
 +                              execute beginfile block */
 +              }
 +                      break;
 +                      
 +              case Op_get_record:             
 +              {
 +                      int errcode = 0;
 +
 +                      ni = pc->target_newfile;
 +                      if (curfile == NULL) {
 +                              /* from non-redirected getline, e.g.:
 +                               *  {
 +                               *              while (getline > 0) ;
 +                               *  }
 +                               */
 +
 +                              ni = ni->target_jmp;    /* end_block or 
Op_atexit */
 +                              JUMPTO(ni);
 +                      }
 +
 +                      if (inrec(curfile, & errcode) != 0) {
 +                              if (errcode > 0 && (do_traditional || ! 
pc->has_endfile))
 +                                      fatal(_("error reading input file `%s': 
%s"),
 +                                              curfile->public.name, 
strerror(errcode));
 +
 +                              JUMPTO(ni);
 +                      } /* else
 +                              prog (rule) block */
 +              }
 +                      break;
 +
 +              case Op_K_nextfile:
 +              {
 +                      int ret;
 +
 +                      if (currule != Rule && currule != BEGINFILE)
 +                              fatal(_("`nextfile' cannot be called from a 
`%s' rule"),
 +                                      ruletab[currule]);
 +
 +                      ret = nextfile(& curfile, true);        /* skip current 
file */
 +
 +                      if (currule == BEGINFILE) {
 +                              long stack_size;
 +
 +                              ni = pop_exec_state(& currule, & source, & 
stack_size);
 +
 +                              assert(ni->opcode == Op_K_getline || ni->opcode 
== Op_newfile);
 +
 +                              /* pop stack returning to the state of 
Op_K_getline or Op_newfile. */
 +                              unwind_stack(stack_size);
 +
 +                              if (ret == 0) {
 +                                      /* There was an error opening the file;
 +                                       * don't run ENDFILE block(s).
 +                                       */
 +
 +                                      JUMPTO(ni);
 +                              } else {
 +                                      /* do run ENDFILE block(s) first. */
 +                                      
 +                                      /* Execution state to return to in 
Op_after_endfile. */
 +                                      push_exec_state(ni, currule, source, 
stack_ptr);
 +
 +                                      JUMPTO(pc->target_endfile);
 +                              }                               
 +                      } /* else 
 +                              Start over with the first rule. */
 +
 +                      /* empty the run-time stack to avoid memory leak */
 +                      pop_stack();
 +
 +                      /* Push an execution state for Op_after_endfile to 
return to */
 +                      push_exec_state(pc->target_newfile, currule, source, 
stack_ptr);
 +
 +                      JUMPTO(pc->target_endfile);
 +              }
 +                      break;
 +
 +              case Op_K_exit:
 +                      /* exit not allowed in user-defined comparison 
functions for "sorted_in";
 +                       * This is done so that END blocks aren't executed more 
than once.
 +                       */
 +                      if (! currule)
 +                              fatal(_("`exit' cannot be called in the current 
context"));
 +
 +                      exiting = true;
 +                      t1 = POP_NUMBER();
 +                      exit_val = (int) get_number_si(t1);
 +                      DEREF(t1);
 +#ifdef VMS
 +                      if (exit_val == 0)
 +                              exit_val = EXIT_SUCCESS;
 +                      else if (exit_val == 1)
 +                              exit_val = EXIT_FAILURE;
 +                      /* else
 +                              just pass anything else on through */
 +#endif
 +
 +                      if (currule == BEGINFILE || currule == ENDFILE) {
 +
 +                              /* Find the rule of the saved execution state 
(Op_K_getline/Op_newfile).
 +                               * This is needed to prevent multiple execution 
of any END rules:
 +                               *      gawk 'BEGINFILE { exit(1) } \
 +                               *         END { while (getline > 0); }' in1 in2
 +                               */
 +
 +                              (void) pop_exec_state(& currule, & source, 
NULL);
 +                      }
 +
 +                      pop_stack();    /* empty stack, don't leak memory */
 +
 +                      /* Jump to either the first END block instruction
 +                       * or to Op_atexit.
 +                       */
 +
 +                      if (currule == END)
 +                              ni = pc->target_atexit;
 +                      else
 +                              ni = pc->target_end;
 +                      JUMPTO(ni);
 +
 +              case Op_K_next:
 +                      if (currule != Rule)
 +                              fatal(_("`next' cannot be called from a `%s' 
rule"), ruletab[currule]);
 +
 +                      pop_stack();
 +                      JUMPTO(pc->target_jmp); /* Op_get_record, read next 
record */
 +
 +              case Op_pop:
 +                      r = POP_SCALAR();
 +                      DEREF(r);
 +                      break;
 +
 +              case Op_line_range:
 +                      if (pc->triggered)              /* evaluate right 
expression */
 +                              JUMPTO(pc->target_jmp);
 +                      /* else
 +                              evaluate left expression */
 +                      break;
 +
 +              case Op_cond_pair:
 +              {
 +                      int result;
 +                      INSTRUCTION *ip;
 +
 +                      t1 = TOP_SCALAR();   /* from right hand side expression 
*/
 +                      di = (eval_condition(t1) != 0);
 +                      DEREF(t1);
 +
 +                      ip = pc->line_range;            /* Op_line_range */
 +
 +                      if (! ip->triggered && di) {
 +                              /* not already triggered and left expression is 
true */
 +                              decr_sp();
 +                              ip->triggered = true;
 +                              JUMPTO(ip->target_jmp); /* evaluate right 
expression */ 
 +                      }
 +
 +                      result = ip->triggered || di;
 +                      ip->triggered ^= di;          /* update triggered flag 
*/
 +                      r = node_Boolean[result];      /* final value of 
condition pair */
 +                      UPREF(r);
 +                      REPLACE(r);
 +                      JUMPTO(pc->target_jmp);
 +              }
 +
 +              case Op_exec_count:
 +                      if (do_profile)
 +                              pc->exec_count++;
 +                      break;
 +
 +              case Op_no_op:
 +              case Op_K_do:
 +              case Op_K_while:
 +              case Op_K_for:
 +              case Op_K_arrayfor:
 +              case Op_K_switch:
 +              case Op_K_default:
 +              case Op_K_if:
 +              case Op_K_else:
 +              case Op_cond_exp:
 +                      break;
 +
 +              default:
 +                      fatal(_("Sorry, don't know how to interpret `%s'"), 
opcode2str(op));
 +              }
 +
 +              JUMPTO(pc->nexti);
 +
 +/*    } forever */
 +
 +      /* not reached */
 +      return 0;
 +
 +#undef mk_sub
 +#undef JUMPTO
 +}

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

Summary of changes:
 ChangeLog     |    8 ++
 README.git    |   25 +++++-
 TODO          |    4 +-
 doc/ChangeLog |    4 +
 doc/gawk.info |  261 +++++++++++++++++++++++++++++----------------------------
 doc/gawk.texi |   36 ++++----
 interpret.h   |   16 +++-
 7 files changed, 204 insertions(+), 150 deletions(-)


hooks/post-receive
-- 
gawk



reply via email to

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