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

Eric Blake <[email protected]>
Newsgroups gmane.comp.gnu.m4.patches
Message-ID <[email protected]>
-----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  <[email protected]>

	* 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             [email protected]
-----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-----

_______________________________________________
M4-patches mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/m4-patches
m4.patch140 (text/plain, 35 KB)
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')
-@result{}0
+@result{}1
 @end example
 
 Macros are expanded normally during argument collection, and whatever
@@ -1964,7 +1964,7 @@ argument, separated by commas, with each
 
 @example
 shift
-@result{}
+@result{}shift
 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*', `(\&)')
-@result{}(GNUs)() (not)() (Unix)
+@result{}(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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.