[Top][All Lists]
[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.