m4-patches
[Top][All Lists]
Advanced

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

head - Re: branch-1_4 patsubst bug, and missing arguments


From: Eric Blake
Subject: head - Re: branch-1_4 patsubst bug, and missing arguments
Date: Fri, 25 Aug 2006 16:06:02 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.5) Gecko/20060719 Thunderbird/1.5.0.5 Mnenhy/0.7.4.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 8/24/2006 8:24 AM:
> 
> Head has similar issues in both cases, but I would like to clean up
> argument handling there first - it has always bothered me that min_args
> and max_args are off by 1 (ie. m4_bad_argc(..., 2, 2) means a macro takes
> exactly one argument); the confusion shows in modules/m4.c where some
> builtins had 0 and others 1 for min_arg when a macro is not blind.  In the
> process of fixing that, I can consolidate the groks_macro_args and
> blind_if_no_args bools into a bitfield, making it more extensible to add
> other bools to each builtin.  I envision adding a bool of whether having
> too few args results in an empty expansion or not, so that macros like
> regexp can still produce output with too few args without having to also
> call m4_bad_argc (also fixing my current hack to make syscmd/esyscmd still
> change sysval when there are too few args).  This would be a
> binary-incompatible change with any existing modules built against
> m4-1.4o, but I believe it is okay to change the interface right up until
> 2.0 is released, as we have documented all along that beta releases are
> subject to change.

And with that declaration, here goes.  This patch touches a lot of files,
but the core things it does are fix struct m4_builtin to be 0-based, add a
bit to state when a macro must be called for side effects even when
warning about too few arguments, then fix patsubst to be reliable, and fix
the fallout.  There are still a number of issues in modules/m4.c that need
porting, but I think modules/gnu.c is now fully ported.

2006-08-25  Eric Blake  <address@hidden>

        * m4/m4module.h (M4_BUILTIN_GROKS_MACRO, M4_BUILTIN_BLIND)
        (M4_BUILTIN_SIDE_EFFECT): New enumerators.
        (struct m4_builtin): New member flags replaces groks_macro_args,
        blind_if_no_args.  min_args and max_args are now 0-based.
        Rearrange members to reduce size on platforms where function
        pointers are 64 bits but regular pointers are 32.
        (m4_bad_argc): Add argument.
        * m4/m4private.h (VALUE_SIDE_EFFECT_ARGS_BIT): New define.
        * m4/utility.c (m4_bad_argc): Simplify calculation, and take side
        effect into account.
        * m4/module.c (install_builtin_table): Adjust all users affected
        by this API change.
        * m4/macro.c (m4_macro_call): Likewise.
        * src/freeze.c (reload_frozen_state): Likewise.
        * modules/m4.c (builtin_functions, ifelse, syscmd): Likewise.
        * modules/gnu.c (builtin_functions, builtin, esyscmd): Likewise.
        * modules/import.c (builtin_functions): Likewise.
        * modules/load.c (builtin_functions): Likewise.
        * modules/modtest.c (builtin_functions): Likewise.
        * modules/mpeval.c (builtin_functions): Likewise.
        * modules/perl.c (builtin_functions): Likewise.
        * modules/shadow.c (builtin_functions): Likewise.
        * modules/stdlib.c (builtin_functions): Likewise.
        * modules/time.c (builtin_functions, mktime_functions)
        (strftime_functions): Likewise.
        * doc/m4.texinfo (Loops): Update test now that shift is blind.
        (Macro Arguments): Fix typo in test.
        (Patsubst): Fix typo in test.
        * modules/gnu.c (m4_regexp_substitute): Don't skip empty match at
        end of string.  Fix return value when ignore_duplicates.
        * tests/builtins.at (patsubst): Fix typo in test.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFE73RK84KuGfSFAYARAmc4AKCXQti4yMbg89FK5Ba97o1aTzn7YgCg1mRN
u6hUOLnXPYUOVhl9BvWBdlM=
=i854
-----END PGP SIGNATURE-----
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.35
diff -u -p -r1.35 m4.texinfo
--- doc/m4.texinfo      25 Aug 2006 19:23:02 -0000      1.35
+++ doc/m4.texinfo      25 Aug 2006 22:03:14 -0000
@@ -1219,7 +1219,7 @@ index(`abc')
 index(`abc',)
 @result{}0
 index(`abc', `b', `ignored')
address@hidden
address@hidden
 @end example
 
 Macros are expanded normally during argument collection, and whatever
@@ -1964,7 +1964,7 @@ argument, separated by commas, with each
 
 @example
 shift
address@hidden
address@hidden
 shift(`bar')
 @result{}
 shift(`foo', `bar', `baz')
@@ -3645,7 +3645,7 @@ patsubst(`GNUs not Unix', `^', `OBS: ')
 patsubst(`GNUs not Unix', `\<', `OBS: ')
 @result{}OBS: GNUs OBS: not OBS: Unix
 patsubst(`GNUs not Unix', `\w*', `(\&)')
address@hidden(GNUs)() (not)() (Unix)
address@hidden(GNUs)() (not)() (Unix)()
 patsubst(`GNUs not Unix', `\w+', `(\&)')
 @result{}(GNUs) (not) (Unix)
 patsubst(`GNUs not Unix', `[A-Z][a-z]+')
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.79
diff -u -p -r1.79 m4module.h
--- m4/m4module.h       25 Aug 2006 19:23:02 -0000      1.79
+++ m4/m4module.h       25 Aug 2006 22:03:14 -0000
@@ -42,12 +42,23 @@ typedef lt_dlsymlist                m4_export;
 
 typedef void   m4_builtin_func  (m4 *, m4_obstack *, int, m4_symbol_value **);
 
+/* The value of m4_builtin flags is built from these:  */
+enum {
+  /* set if macro can handle non-text tokens, such as builtin macro tokens */
+  M4_BUILTIN_GROKS_MACRO       = (1 << 0),
+  /* set if macro should only be recognized with arguments */
+  M4_BUILTIN_BLIND             = (1 << 1),
+  /* set if macro has side effects even when there are too few arguments */
+  M4_BUILTIN_SIDE_EFFECT       = (1 << 2)
+};
+
 struct m4_builtin
 {
-  const char *     name;
-  m4_builtin_func * func;
-  bool     groks_macro_args, blind_if_no_args;
-  int              min_args, max_args;
+  m4_builtin_func * func;      /* implementation of the builtin */
+  const char *     name;       /* name found by builtin, printed by dumpdef */
+  int              flags;      /* bitwise OR of M4_BUILTIN_* bits */
+  unsigned int     min_args;   /* 0-based minimum number of arguments */
+  unsigned int     max_args;   /* max arguments, UINT_MAX if unlimited */
 };
 
 struct m4_macro
@@ -84,7 +95,7 @@ struct m4_macro
 #define M4ARG(i)       (argc > (i) ? m4_get_symbol_value_text (argv[i]) : "")
 
 extern bool        m4_bad_argc       (m4 *, int, m4_symbol_value **,
-                                      int, int);
+                                      unsigned int, unsigned int, bool);
 extern bool        m4_numeric_arg    (m4 *, int, m4_symbol_value **,
                                       int, int *);
 extern void        m4_dump_args      (m4 *, m4_obstack *, int,
Index: m4/m4private.h
===================================================================
RCS file: /sources/m4/m4/m4/m4private.h,v
retrieving revision 1.55
diff -u -p -r1.55 m4private.h
--- m4/m4private.h      25 Aug 2006 19:23:02 -0000      1.55
+++ m4/m4private.h      25 Aug 2006 22:03:14 -0000
@@ -219,10 +219,15 @@ struct m4_symbol_value {
 
 
 
-/* m4_symbol_value.flags bit masks:  */
-
-#define VALUE_MACRO_ARGS_BIT   (1 << 0)
-#define VALUE_BLIND_ARGS_BIT   (1 << 1)
+/* m4_symbol_value.flags bit masks.  Be sure these are consistent with
+   M4_BUILTIN_* bit masks, so we can copy m4_builtin.flags to
+   m4_symbol_arg.flags.  However, if we ever add blind support to user
+   macros, then these names are better for use in the symbol
+   table:  */
+
+#define VALUE_MACRO_ARGS_BIT           (1 << 0)
+#define VALUE_BLIND_ARGS_BIT           (1 << 1)
+#define VALUE_SIDE_EFFECT_ARGS_BIT     (1 << 2)
 
 
 struct m4_symbol_arg {
Index: m4/macro.c
===================================================================
RCS file: /sources/m4/m4/m4/macro.c,v
retrieving revision 1.49
diff -u -p -r1.49 macro.c
--- m4/macro.c  21 Aug 2006 02:37:45 -0000      1.49
+++ m4/macro.c  25 Aug 2006 22:03:14 -0000
@@ -318,7 +318,9 @@ m4_macro_call (m4 *context, m4_symbol *s
               int argc, m4_symbol_value **argv)
 {
   if (m4_bad_argc (context, argc, argv,
-                  SYMBOL_MIN_ARGS (symbol), SYMBOL_MAX_ARGS (symbol)))
+                  SYMBOL_MIN_ARGS (symbol), SYMBOL_MAX_ARGS (symbol),
+                  BIT_TEST (SYMBOL_FLAGS (symbol),
+                            VALUE_SIDE_EFFECT_ARGS_BIT)))
     return;
   if (m4_is_symbol_text (symbol))
     {
Index: m4/module.c
===================================================================
RCS file: /sources/m4/m4/m4/module.c,v
retrieving revision 1.39
diff -u -p -r1.39 module.c
--- m4/module.c 9 Aug 2006 21:33:24 -0000       1.39
+++ m4/module.c 25 Aug 2006 22:03:15 -0000
@@ -147,14 +147,10 @@ install_builtin_table (m4 *context, lt_d
 
          m4_set_symbol_value_func (value, bp->func);
          VALUE_HANDLE   (value)        = handle;
+         VALUE_FLAGS    (value)        = bp->flags;
          VALUE_MIN_ARGS (value)        = bp->min_args;
          VALUE_MAX_ARGS (value)        = bp->max_args;
 
-         if (bp->groks_macro_args)
-           BIT_SET (VALUE_FLAGS (value), VALUE_MACRO_ARGS_BIT);
-         if (bp->blind_if_no_args)
-           BIT_SET (VALUE_FLAGS (value), VALUE_BLIND_ARGS_BIT);
-
          if (m4_get_prefix_builtins_opt (context))
            {
              static const char prefix[] = "m4_";
Index: m4/utility.c
===================================================================
RCS file: /sources/m4/m4/m4/utility.c,v
retrieving revision 1.44
diff -u -p -r1.44 utility.c
--- m4/utility.c        22 Aug 2006 16:16:48 -0000      1.44
+++ m4/utility.c        25 Aug 2006 22:03:15 -0000
@@ -31,27 +31,31 @@ static const char * skip_space (m4 *, co
 
 
 /* Give friendly warnings if a builtin macro is passed an
-   inappropriate number of arguments.  ARGC/ARGV are the arguments,
-   MIN is the minimum number of acceptable arguments, negative if not
-   applicable, MAX is the maximum number, negative if not applicable.
-   ARGC, MIN, and MAX count ARGV[0], the name of the macro.  Return
-   true if there are too few arguments, false otherwise.  */
+   inappropriate number of arguments.  MIN is the 0-based minimum
+   number of acceptable arguments, MAX is the 0-based maximum number
+   or UINT_MAX if not applicable, and SIDE_EFFECT is true if the macro
+   has side effects even if min is not satisfied.  ARGC is the 1-based
+   count of ARGV, where ARGV[0] is the name of the macro.  Return true
+   if the macro is guaranteed to expand to the empty string, false
+   otherwise.  */
 bool
-m4_bad_argc (m4 *context, int argc, m4_symbol_value **argv, int min, int max)
+m4_bad_argc (m4 *context, int argc, m4_symbol_value **argv,
+            unsigned int min, unsigned int max, bool side_effect)
 {
-  if (min > 0 && argc < min)
+  assert (min <= max);
+  assert (min > 0 || ! side_effect);
+
+  if (argc - 1 < min)
     {
       m4_warn (context, 0, _("Warning: %s: too few arguments: %d < %d"),
-              M4ARG (0), argc - 1, min - 1);
-      return true;
+              M4ARG (0), argc - 1, min);
+      return ! side_effect;
     }
 
-  if (max > 0 && argc > max)
+  if (argc - 1 > max)
     {
       m4_warn (context, 0, _("Warning: %s: extra arguments ignored: %d > %d"),
-              M4ARG (0), argc - 1, max - 1);
-      /* Return false, otherwise it is not exactly `ignored'. */
-      return false;
+              M4ARG (0), argc - 1, max);
     }
 
   return false;
Index: modules/gnu.c
===================================================================
RCS file: /sources/m4/m4/modules/gnu.c,v
retrieving revision 1.50
diff -u -p -r1.50 gnu.c
--- modules/gnu.c       23 Aug 2006 11:39:26 -0000      1.50
+++ modules/gnu.c       25 Aug 2006 22:03:15 -0000
@@ -43,28 +43,28 @@
 /* Maintain each of the builtins implemented in this modules along
    with their details in a single table for easy maintenance.
 
-               function        macros  blind argmin  argmax */
+          function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                      \
-       BUILTIN(__file__,       false,  false,  1,      1  )    \
-       BUILTIN(__line__,       false,  false,  1,      1  )    \
-       BUILTIN(__program__,    false,  false,  1,      1  )    \
-       BUILTIN(builtin,        false,  true,   2,      -1 )    \
-       BUILTIN(changeresyntax, false,  true,   1,      2  )    \
-       BUILTIN(changesyntax,   false,  true,   1,      -1 )    \
-       BUILTIN(debugmode,      false,  false,  1,      2  )    \
-       BUILTIN(debugfile,      false,  false,  1,      2  )    \
-       BUILTIN(esyscmd,        false,  true,   -1,     2  )    \
-       BUILTIN(format,         false,  true,   2,      -1 )    \
-       BUILTIN(indir,          false,  true,   2,      -1 )    \
-       BUILTIN(patsubst,       false,  true,   3,      5  )    \
-       BUILTIN(regexp,         false,  true,   3,      5  )    \
-       BUILTIN(renamesyms,     false,  true,   3,      4  )    \
-       BUILTIN(symbols,        false,  false,  1,      -1 )    \
-       BUILTIN(syncoutput,     false,  true,   2,      2  )    \
+  BUILTIN (__file__,   false,  false,  false,  0,      0 )     \
+  BUILTIN (__line__,   false,  false,  false,  0,      0  )    \
+  BUILTIN (__program__,        false,  false,  false,  0,      0  )    \
+  BUILTIN (builtin,    false,  true,   false,  1,      -1 )    \
+  BUILTIN (changeresyntax,false,true,  false,  0,      1  )    \
+  BUILTIN (changesyntax,false, true,   false,  0,      -1 )    \
+  BUILTIN (debugmode,  false,  false,  false,  0,      1  )    \
+  BUILTIN (debugfile,  false,  false,  false,  0,      1  )    \
+  BUILTIN (esyscmd,    false,  true,   true,   1,      1  )    \
+  BUILTIN (format,     false,  true,   false,  1,      -1 )    \
+  BUILTIN (indir,      false,  true,   false,  1,      -1 )    \
+  BUILTIN (patsubst,   false,  true,   true,   2,      4  )    \
+  BUILTIN (regexp,     false,  true,   true,   2,      4  )    \
+  BUILTIN (renamesyms, false,  true,   false,  2,      3  )    \
+  BUILTIN (symbols,    false,  false,  false,  0,      -1 )    \
+  BUILTIN (syncoutput, false,  true,   false,  1,      1  )    \
 
 
 /* Generate prototypes for each builtin handler function. */
-#define BUILTIN(handler, macros, blind, min, max)  M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, side, min, max)  M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
@@ -72,12 +72,16 @@
 /* Generate a table for mapping m4 symbol names to handler functions. */
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 
@@ -93,7 +97,7 @@ m4_macro m4_macro_table[] =
   { "__gnu__",                 "" },
   { "__m4_version__",          VERSION/**/TIMESTAMP },
 
-  { 0, 0 },
+  { NULL, NULL },
 };
 
 
@@ -212,9 +216,12 @@ substitute (m4 *context, m4_obstack *obs
 }
 
 
-/* For each match against compiled REGEXP (held in BUF -- as returned by
-   m4_regexp_compile) in VICTIM, substitute REPLACE.  Non-matching
-   characters are copied verbatim, and the result copied to the obstack.  */
+/* For each match against compiled REGEXP (held in BUF -- as returned
+   by m4_regexp_compile) in VICTIM, substitute REPLACE.  Non-matching
+   characters are copied verbatim, and the result copied to the
+   obstack.  Errors are reported on behalf of CALLER.  Return true if
+   a substitution was made.  If IGNORE_DUPLICATES is set, don't worry
+   about completing the obstack when returning false.  */
 
 static bool
 m4_regexp_substitute (m4 *context, m4_obstack *obs, const char *caller,
@@ -225,8 +232,9 @@ m4_regexp_substitute (m4 *context, m4_ob
   int matchpos = 0;            /* start position of match */
   int offset   = 0;            /* current match offset */
   int length   = strlen (victim);
+  bool subst   = false;        /* if a substitution has been made */
 
-  while (offset < length)
+  while (offset <= length)
     {
       matchpos = m4_regexp_search (buf, victim, length,
                                   offset, length - offset);
@@ -255,6 +263,7 @@ m4_regexp_substitute (m4 *context, m4_ob
       /* Handle the part of the string that was covered by the match.  */
 
       substitute (context, obs, caller, victim, replace, buf);
+      subst = true;
 
       /* Update the offset to the end of the match.  If the regexp
         matched a null string, advance offset one more, to avoid
@@ -265,10 +274,10 @@ m4_regexp_substitute (m4 *context, m4_ob
        obstack_1grow (obs, victim[offset++]);
     }
 
-  if (!ignore_duplicates || (matchpos >= 0))
+  if (!ignore_duplicates || subst)
     obstack_1grow (obs, '\0');
 
-  return (matchpos >= 0);
+  return subst;
 }
 
 
@@ -318,7 +327,8 @@ M4BUILTIN_HANDLER (builtin)
   if (bp == NULL)
     m4_error (context, 0, 0, _("%s: undefined builtin `%s'"), M4ARG (0), name);
   else if (!m4_bad_argc (context, argc - 1, argv + 1,
-                        bp->min_args, bp->max_args))
+                        bp->min_args, bp->max_args,
+                        (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
     bp->func (context, obs, argc - 1, argv + 1);
 }
 
@@ -442,11 +452,8 @@ M4BUILTIN_HANDLER (esyscmd)
       FILE *pin;
       int ch;
 
-      /* Calling with no arguments triggers a warning, but must also
-         set sysval to 0 as if the empty command had been executed.
-         Therefore, we must manually check min args ourselves rather
-         than relying on the macro calling engine.  */
-      if (m4_bad_argc (context, argc, argv, 2, -1))
+      /* Optimize the empty command.  */
+      if (*M4ARG (1) == '\0')
         {
           m4_set_sysval (0);
           return;
Index: modules/import.c
===================================================================
RCS file: /sources/m4/m4/modules/import.c,v
retrieving revision 1.4
diff -u -p -r1.4 import.c
--- modules/import.c    1 May 2005 11:10:05 -0000       1.4
+++ modules/import.c    25 Aug 2006 22:03:15 -0000
@@ -1,5 +1,5 @@
 /* GNU m4 -- A simple macro processor
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -27,25 +27,29 @@
 
 #define m4_builtin_table       import_LTX_m4_builtin_table
 
-/*             function        macros  blind minargs maxargs */
+/*        function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                      \
-       BUILTIN (import,        false,  false,  1,      2)      \
-       BUILTIN (symbol_fail,   false,  false,  1,      2)      \
-       BUILTIN (module_fail,   false,  false,  1,      2)
+  BUILTIN (import,     false,  false,  false,  0,      1)      \
+  BUILTIN (symbol_fail,        false,  false,  false,  0,      1)      \
+  BUILTIN (module_fail,        false,  false,  false,  0,      1)      \
 
-#define BUILTIN(handler, macros,  blind, min, max) M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
 
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 
Index: modules/load.c
===================================================================
RCS file: /sources/m4/m4/modules/load.c,v
retrieving revision 1.17
diff -u -p -r1.17 load.c
--- modules/load.c      9 Aug 2006 21:33:24 -0000       1.17
+++ modules/load.c      25 Aug 2006 22:03:15 -0000
@@ -32,15 +32,15 @@
 /* Maintain each of the builtins implemented in this modules along
    with their details in a single table for easy maintenance.
 
-               function        macros  blind minargs maxargs */
-#define builtin_functions                      \
-       BUILTIN(modules,        false,  false,  1,      1  )    \
-       BUILTIN(load,           false,  true,   2,      2  )    \
-       BUILTIN(unload,         false,  true,   2,      2  )    \
+          function     macros  blind   side    minargs maxargs */
+#define builtin_functions                                      \
+  BUILTIN (modules,    false,  false,  false,  0,      0  )    \
+  BUILTIN (load,       false,  true,   false,  1,      1  )    \
+  BUILTIN (unload,     false,  true,   false,  1,      1  )    \
 
 
 /* Generate prototypes for each builtin handler function. */
-#define BUILTIN(handler, macros,  blind, min, max) M4BUILTIN(handler)
+#define BUILTIN(handler, macros,  blind, side, min, max) M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
@@ -48,12 +48,16 @@
 /* Generate a table for mapping m4 symbol names to handler functions. */
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 
@@ -62,7 +66,7 @@ m4_macro m4_macro_table[] =
 {
   /* name                      text */
   { "__modules__",             "" },
-  { 0, 0 },
+  { NULL, NULL },
 };
 
 
Index: modules/m4.c
===================================================================
RCS file: /sources/m4/m4/modules/m4.c,v
retrieving revision 1.65
diff -u -p -r1.65 m4.c
--- modules/m4.c        21 Aug 2006 12:46:24 -0000      1.65
+++ modules/m4.c        25 Aug 2006 22:03:15 -0000
@@ -59,40 +59,40 @@ extern const char *m4_expand_ranges (con
 /* Maintain each of the builtins implemented in this modules along
    with their details in a single table for easy maintenance.
 
-               function        macros  blind minargs maxargs */
+          function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                      \
-       BUILTIN(changecom,      false,  false,  1,      3  )    \
-       BUILTIN(changequote,    false,  false,  1,      3  )    \
-       BUILTIN(decr,           false,  true,   2,      2  )    \
-       BUILTIN(define,         true,   true,   2,      3  )    \
-       BUILTIN(defn,           false,  true,   0,      -1 )    \
-       BUILTIN(divert,         false,  false,  1,      2  )    \
-       BUILTIN(divnum,         false,  false,  1,      1  )    \
-       BUILTIN(dnl,            false,  false,  1,      1  )    \
-       BUILTIN(dumpdef,        false,  false,  0,      -1 )    \
-       BUILTIN(errprint,       false,  false,  0,      -1 )    \
-       BUILTIN(eval,           false,  true,   2,      4  )    \
-       BUILTIN(ifdef,          false,  true,   3,      4  )    \
-       BUILTIN(ifelse,         false,  true,   -1,     -1 )    \
-       BUILTIN(include,        false,  true,   2,      2  )    \
-       BUILTIN(incr,           false,  true,   2,      2  )    \
-       BUILTIN(index,          false,  true,   3,      3  )    \
-       BUILTIN(len,            false,  true,   2,      2  )    \
-       BUILTIN(m4exit,         false,  false,  1,      2  )    \
-       BUILTIN(m4wrap,         false,  false,  0,      -1 )    \
-       BUILTIN(maketemp,       false,  true,   2,      2  )    \
-       BUILTIN(popdef,         false,  true,   2,      2  )    \
-       BUILTIN(pushdef,        true,   true,   2,      3  )    \
-       BUILTIN(shift,          false,  false,  0,      -1 )    \
-       BUILTIN(sinclude,       false,  true,   2,      2  )    \
-       BUILTIN(substr,         false,  true,   3,      4  )    \
-       BUILTIN(syscmd,         false,  true,   -1,     2  )    \
-       BUILTIN(sysval,         false,  false,  0,      -1 )    \
-       BUILTIN(traceoff,       false,  false,  0,      -1 )    \
-       BUILTIN(traceon,        false,  false,  0,      -1 )    \
-       BUILTIN(translit,       false,  true,   3,      4  )    \
-       BUILTIN(undefine,       false,  true,   2,      2  )    \
-       BUILTIN(undivert,       false,  false,  0,      -1 )    \
+  BUILTIN (changecom,  false,  false,  false,  0,      2  )    \
+  BUILTIN (changequote,        false,  false,  false,  0,      2  )    \
+  BUILTIN (decr,       false,  true,   true,   1,      1  )    \
+  BUILTIN (define,     true,   true,   false,  1,      2  )    \
+  BUILTIN (defn,       false,  true,   false,  1,      -1 )    \
+  BUILTIN (divert,     false,  false,  false,  0,      1  )    \
+  BUILTIN (divnum,     false,  false,  false,  0,      0  )    \
+  BUILTIN (dnl,                false,  false,  false,  0,      0  )    \
+  BUILTIN (dumpdef,    false,  false,  false,  0,      -1 )    \
+  BUILTIN (errprint,   false,  true,   false,  1,      -1 )    \
+  BUILTIN (eval,       false,  true,   true,   1,      3  )    \
+  BUILTIN (ifdef,      false,  true,   false,  2,      3  )    \
+  BUILTIN (ifelse,     false,  true,   false,  1,      -1 )    \
+  BUILTIN (include,    false,  true,   false,  1,      1  )    \
+  BUILTIN (incr,       false,  true,   true,   1,      1  )    \
+  BUILTIN (index,      false,  true,   true,   2,      2  )    \
+  BUILTIN (len,                false,  true,   true,   1,      1  )    \
+  BUILTIN (m4exit,     false,  false,  false,  0,      1  )    \
+  BUILTIN (m4wrap,     false,  true,   false,  1,      -1 )    \
+  BUILTIN (maketemp,   false,  true,   false,  1,      1  )    \
+  BUILTIN (popdef,     false,  true,   false,  1,      -1 )    \
+  BUILTIN (pushdef,    true,   true,   false,  1,      2  )    \
+  BUILTIN (shift,      false,  true,   false,  1,      -1 )    \
+  BUILTIN (sinclude,   false,  true,   false,  1,      1  )    \
+  BUILTIN (substr,     false,  true,   true,   2,      3  )    \
+  BUILTIN (syscmd,     false,  true,   true,   1,      1  )    \
+  BUILTIN (sysval,     false,  false,  false,  0,      0  )    \
+  BUILTIN (traceoff,   false,  false,  false,  0,      -1 )    \
+  BUILTIN (traceon,    false,  false,  false,  0,      -1 )    \
+  BUILTIN (translit,   false,  true,   true,   2,      3  )    \
+  BUILTIN (undefine,   false,  true,   false,  1,      -1 )    \
+  BUILTIN (undivert,   false,  false,  false,  0,      -1 )    \
 
 
 #if defined(SIZEOF_LONG_LONG_INT) && SIZEOF_LONG_LONG_INT > 0
@@ -117,7 +117,7 @@ static void numb_obstack    (m4_obstack *ob
 
 
 /* Generate prototypes for each builtin handler function. */
-#define BUILTIN(handler, macros,  blind, min, max) M4BUILTIN(handler)
+#define BUILTIN(handler, macros,  blind, side, min, max) M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
@@ -125,12 +125,16 @@ static void       numb_obstack    (m4_obstack *ob
 /* Generate a table for mapping m4 symbol names to handler functions. */
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 
@@ -243,11 +247,11 @@ M4BUILTIN_HANDLER (ifelse)
   if (argc == 2)
     return;
 
-  if (m4_bad_argc (context, argc, argv, 4, -1))
+  if (m4_bad_argc (context, argc, argv, 3, -1, false))
     return;
   else
     /* Diagnose excess arguments if 5, 8, 11, etc., actual arguments.  */
-    m4_bad_argc (context, (argc + 2) % 3, argv, -1, 1);
+    m4_bad_argc (context, (argc % 3) + 1, argv, 0, 2, false);
 
   argv++;
   argc--;
@@ -474,11 +478,8 @@ m4_sysval_flush (m4 *context)
 
 M4BUILTIN_HANDLER (syscmd)
 {
-  /* Calling with no arguments triggers a warning, but must also set
-     sysval to 0 as if the empty command had been executed.
-     Therefore, we must manually check min args ourselves rather than
-     relying on the macro calling engine.  */
-  if (m4_bad_argc (context, argc, argv, 2, -1))
+  /* Optimize the empty command.  */
+  if (*M4ARG (1) == '\0')
     {
       m4_set_sysval (0);
       return;
Index: modules/modtest.c
===================================================================
RCS file: /sources/m4/m4/modules/modtest.c,v
retrieving revision 1.12
diff -u -p -r1.12 modtest.c
--- modules/modtest.c   1 May 2005 11:10:05 -0000       1.12
+++ modules/modtest.c   25 Aug 2006 22:03:15 -0000
@@ -1,5 +1,5 @@
 /* GNU m4 -- A simple macro processor
-   Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2003, 2004, 2006 Free Software Foundation, 
Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -32,30 +32,34 @@
 
 extern bool export_test (const char *foo);
 
-/*             function        macros  blind minargs maxargs */
+/*        function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                      \
-       BUILTIN (test,          false,  false,  1,      1)
+  BUILTIN (test,       false,  false,  false,  0,      0)
 
-#define BUILTIN(handler, macros,  blind, min, max) M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
 
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 m4_macro m4_macro_table[] =
 {
   /* name              text */
   { "__test__",                "`modtest'" },
-  { 0,                 0 },
+  { NULL,              NULL },
 };
 
 
Index: modules/mpeval.c
===================================================================
RCS file: /sources/m4/m4/modules/mpeval.c,v
retrieving revision 1.18
diff -u -p -r1.18 mpeval.c
--- modules/mpeval.c    9 Aug 2006 21:33:24 -0000       1.18
+++ modules/mpeval.c    25 Aug 2006 22:03:15 -0000
@@ -36,9 +36,9 @@
 /* Maintain each of the builtins implemented in this modules along
    with their details in a single table for easy maintenance.
 
-               function        macros  blind minargs maxargs */
+          function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                      \
-       BUILTIN(mpeval,         false,  true,   2,      4  )    \
+  BUILTIN (mpeval,     false,  true,   true,   1,      3  )    \
 
 
 
@@ -79,7 +79,7 @@
 #define numb_decr(n) numb_minus(n,numb_ONE)
 
 /* Generate prototypes for each builtin handler function. */
-#define BUILTIN(handler, macros,  blind, min, max)  M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, side, min, max)  M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
@@ -87,12 +87,16 @@
 /* Generate a table for mapping m4 symbol names to handler functions. */
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)                        
\
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 
Index: modules/perl.c
===================================================================
RCS file: /sources/m4/m4/modules/perl.c,v
retrieving revision 1.14
diff -u -p -r1.14 perl.c
--- modules/perl.c      1 May 2005 11:10:05 -0000       1.14
+++ modules/perl.c      25 Aug 2006 22:03:15 -0000
@@ -1,5 +1,5 @@
 /* GNU m4 -- A simple macro processor
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -31,24 +31,28 @@
 #define m4_builtin_table       perl_LTX_m4_builtin_table
 #define m4_macro_table         perl_LTX_m4_macro_table
 
-/*             function        macros  blind minargs maxargs */
+/*        function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                      \
-       BUILTIN (perleval,      false,  false,  0,      -1  )   \
+  BUILTIN (perleval,   false,  false,  false,  0,      -1  )   \
 
 
-#define BUILTIN(handler, macros,  blind, min, max)  M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, side, min, max)  M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
 
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 /* A table for mapping m4 symbol names to simple expansion text. */
@@ -56,7 +60,7 @@ m4_macro m4_macro_table[] =
 {
   /* name                      text */
   { "__perleval__",            "" },
-  { 0, 0 },
+  { NULL, NULL },
 };
 
 
Index: modules/shadow.c
===================================================================
RCS file: /sources/m4/m4/modules/shadow.c,v
retrieving revision 1.11
diff -u -p -r1.11 shadow.c
--- modules/shadow.c    1 May 2005 11:10:05 -0000       1.11
+++ modules/shadow.c    25 Aug 2006 22:03:15 -0000
@@ -1,5 +1,5 @@
 /* GNU m4 -- A simple macro processor
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -28,32 +28,36 @@
 #define m4_builtin_table       shadow_LTX_m4_builtin_table
 #define m4_macro_table         shadow_LTX_m4_macro_table
 
-/*             function        macros  blind minargs maxargs */
+/*        function     macros  blind   side    minargs maxargs */
 #define builtin_functions                      \
-       BUILTIN (shadow,        false,  false,  0,      -1 )    \
-       BUILTIN (test,          false,  false,  0,      -1 )    \
+  BUILTIN (shadow,     false,  false,  false,  0,      -1 )    \
+  BUILTIN (test,       false,  false,  false,  0,      -1 )    \
 
 
-#define BUILTIN(handler, macros,  blind, min, max) M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN(handler)
   builtin_functions
 #undef BUILTIN
 
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
 
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 m4_macro m4_macro_table[] =
 {
   /* name              text */
   { "__test__",                "`shadow'" },
-  { 0,                 0 },
+  { NULL, NULL },
 };
 
 
Index: modules/stdlib.c
===================================================================
RCS file: /sources/m4/m4/modules/stdlib.c,v
retrieving revision 1.13
diff -u -p -r1.13 stdlib.c
--- modules/stdlib.c    1 May 2005 11:10:05 -0000       1.13
+++ modules/stdlib.c    25 Aug 2006 22:03:15 -0000
@@ -1,5 +1,5 @@
 /* GNU m4 -- A simple macro processor
-   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -36,37 +36,41 @@
 
 #define m4_builtin_table       stdlib_LTX_m4_builtin_table
 
-/*             function        macros  blind minargs maxargs */
+/*        function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                      \
-       BUILTIN (getcwd,        false,  false,  1,      1  )    \
-       BUILTIN (getenv,        false,  true,   2,      2  )    \
-       BUILTIN (getlogin,      false,  false,  1,      1  )    \
-       BUILTIN (getpid,        false,  false,  1,      1  )    \
-       BUILTIN (getppid,       false,  false,  1,      1  )    \
-       BUILTIN (getuid,        false,  false,  1,      1  )    \
-       BUILTIN (getpwnam,      false,  true,   2,      2  )    \
-       BUILTIN (getpwuid,      false,  true,   2,      2  )    \
-       BUILTIN (hostname,      false,  false,  1,      1  )    \
-       BUILTIN (rand,          false,  false,  1,      1  )    \
-       BUILTIN (srand,         false,  false,  1,      2  )    \
-       BUILTIN (setenv,        false,  true,   3,      4  )    \
-       BUILTIN (unsetenv,      false,  true,   2,      2  )    \
-       BUILTIN (uname,         false,  false,  1,      1  )    \
+  BUILTIN (getcwd,     false,  false,  false,  0,      0  )    \
+    BUILTIN (getenv,   false,  true,   false,  1,      1  )    \
+    BUILTIN (getlogin, false,  false,  false,  0,      0  )    \
+    BUILTIN (getpid,   false,  false,  false,  0,      0  )    \
+    BUILTIN (getppid,  false,  false,  false,  0,      0  )    \
+    BUILTIN (getuid,   false,  false,  false,  0,      0  )    \
+    BUILTIN (getpwnam, false,  true,   false,  1,      1  )    \
+    BUILTIN (getpwuid, false,  true,   false,  1,      1  )    \
+    BUILTIN (hostname, false,  false,  false,  0,      0  )    \
+    BUILTIN (rand,     false,  false,  false,  0,      0  )    \
+    BUILTIN (srand,    false,  false,  false,  0,      1  )    \
+    BUILTIN (setenv,   false,  true,   false,  2,      3  )    \
+    BUILTIN (unsetenv, false,  true,   false,  1,      1  )    \
+    BUILTIN (uname,    false,  false,  false,  0,      0  )    \
 
 
-#define BUILTIN(handler, macros,  blind, min, max) M4BUILTIN(handler);
+#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN(handler);
   builtin_functions
 #undef BUILTIN
 
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
 
   builtin_functions
 #undef BUILTIN
 
-  { 0, 0, false, false, 0, 0 },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 /**
Index: modules/time.c
===================================================================
RCS file: /sources/m4/m4/modules/time.c,v
retrieving revision 1.14
diff -u -p -r1.14 time.c
--- modules/time.c      10 Jun 2006 13:10:57 -0000      1.14
+++ modules/time.c      25 Aug 2006 22:03:15 -0000
@@ -33,21 +33,21 @@
 
 #define m4_builtin_table       time_LTX_m4_builtin_table
 
-/*             function        macros  blind minargs maxargs */
+/*        function     macros  blind   side    minargs maxargs */
 #define builtin_functions                                      \
-       BUILTIN (currenttime,   false,  false,  1,      1  )    \
-       BUILTIN (ctime,         false,  false,  1,      2  )    \
-       BUILTIN (gmtime,        false,  true,   2,      2  )    \
-       BUILTIN (localtime,     false,  true,   2,      2  )    \
+  BUILTIN (currenttime,        false,  false,  false,  0,      0  )    \
+  BUILTIN (ctime,      false,  false,  false,  0,      1  )    \
+  BUILTIN (gmtime,     false,  true,   false,  1,      1  )    \
+  BUILTIN (localtime,  false,  true,   false,  1,      1  )    \
 
 #define mktime_functions                                       \
-       BUILTIN (mktime,        false,  true,   7,      8  )    \
+  BUILTIN (mktime,     false,  true,   false,  6,      7  )    \
 
 #define strftime_functions                                     \
-       BUILTIN (strftime,      false,  true,   3,      3  )    \
+  BUILTIN (strftime,   false,  true,   false,  2,      2  )    \
 
 
-#define BUILTIN(handler, macros,  blind, min, max)  M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, side, min, max)  M4BUILTIN(handler)
   builtin_functions
 # if HAVE_MKTIME
   mktime_functions
@@ -59,8 +59,12 @@
 
 m4_builtin m4_builtin_table[] =
 {
-#define BUILTIN(handler, macros, blind, min, max)              \
-       { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+#define BUILTIN(handler, macros, blind, side, min, max)        \
+  { CONC(builtin_, handler), STR(handler),             \
+    ((macros ? M4_BUILTIN_GROKS_MACRO : 0)             \
+     | (blind ? M4_BUILTIN_BLIND : 0)                  \
+     | (side ? M4_BUILTIN_SIDE_EFFECT : 0)),           \
+    min, max },
 
   builtin_functions
 # if HAVE_MKTIME
@@ -71,7 +75,7 @@ m4_builtin m4_builtin_table[] =
 # endif
 #undef BUILTIN
 
-  { 0, 0, false, false },
+  { NULL, NULL, 0, 0, 0 },
 };
 
 /**
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.48
diff -u -p -r1.48 freeze.c
--- src/freeze.c        9 Aug 2006 21:33:24 -0000       1.48
+++ src/freeze.c        25 Aug 2006 22:03:15 -0000
@@ -545,19 +545,15 @@ ill-formed frozen file, version 2 direct
 
            if (bp)
              {
-               if (bp->groks_macro_args)
-                 BIT_SET (VALUE_FLAGS (token), VALUE_MACRO_ARGS_BIT);
-               if (bp->blind_if_no_args)
-                 BIT_SET (VALUE_FLAGS (token), VALUE_BLIND_ARGS_BIT);
-
                m4_set_symbol_value_func (token, bp->func);
+               VALUE_FLAGS    (token)  = bp->flags;
                VALUE_MIN_ARGS (token)  = bp->min_args;
                VALUE_MAX_ARGS (token)  = bp->max_args;
              }
            else
              {
                m4_set_symbol_value_placeholder (token, xstrdup (string[1]));
-               VALUE_MIN_ARGS (token) = -1;
+               VALUE_MIN_ARGS (token) = 0;
                VALUE_MAX_ARGS (token) = -1;
              }
            m4_symbol_pushdef (M4SYMTAB, string[0], token);
Index: tests/builtins.at
===================================================================
RCS file: /sources/m4/m4/tests/builtins.at,v
retrieving revision 1.13
diff -u -p -r1.13 builtins.at
--- tests/builtins.at   22 Aug 2006 16:16:48 -0000      1.13
+++ tests/builtins.at   25 Aug 2006 22:03:15 -0000
@@ -477,7 +477,7 @@ AT_DATA([[expout]],
 OBS: GNUs not Unix.
 OBS: GNUs OBS: not OBS: Unix.
 G=NUs n=ot U=nix.
-(GNUs)() (not)() (Unix)().
+(GNUs)() (not)() (Unix)().()
 (GNUs) (not) (Unix).
   .
 GNUs not Unix.

reply via email to

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