autoconf-patches
[Top][All Lists]
Advanced

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

Re: bad define semantics in GNU m4


From: Paul Eggert
Subject: Re: bad define semantics in GNU m4
Date: 03 Jul 2003 15:41:01 -0700
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3

Richard Stallman <address@hidden> writes:

>     How about if we modify m4 so that it disables incompatibilities with
>     POSIX if the POSIXLY_CORRECT environment variable is set?  This is
>     what the GNU coding standards suggest.
> 
> That is an ok solution.  I had thought that an option would be more
> convenient as an interface, but your argument in favor of using the
> envvar seems to make sense.

OK, here is a proposed patch against CVS m4 to implement this.  It
suppresses all the POSIX incompatibilities that I found in m4, if
POSIXLY_CORRECT is set.  Unfortunately I can't easily test this, as
CVS m4 requires a CVS libtool version that I don't have, and the
bootstrap fails with the latest released libtool.

2003-07-03  Gary V. Vaughan  <address@hidden>

        * tests/builtins.at: New test for smashed definitions.

2003-07-03  Paul Eggert  <address@hidden> and
            Gary V. Vaughan  <address@hidden>
        
        Conform to POSIX if the POSIXLY_CORRECT environment is set.
        --traditional `define' now smashes all the definitions.
        * NEWS: Explain this.
        * doc/m4.texinfo (Defn): `defn' takes any number of arguments.
        (Extensions): Explain that extensions that are incompatible with
        POSIX are disabled if POSIXLY_CORRECT is set.
        (Incompatibilities): Remove.
        (Define, Other Incompat): Explain difference
        between GNU and POSIX behavior of define, pushdef, popdef.
        * m4/m4.c (m4_get_posixly_correct_opt): New undef.
        * m4/m4module.h (m4_context_opt_bit_table): Add POSIXLY_CORRECT entry.
        * m4/m4private.h (M4_OPT_POSIXLY_CORRECT_BIT): New macro.
        (m4_get_posixly_correct_opt): New macro.
        * m4/m4macro.c (m4_process_macro): Disable $10, $abc etc. if
        POSIXLY_CORRECT.
        * modules/m4.c (builtin_functions): defn now takes any number of args.
        (M4BUILTIN_HANDLER (define)): Smash all the definitions if
        POSIXLY_CORRECT.
        (M4BUILTIN_HANDLER (defn)): Allow any number of arguments.
        (M4BUILTIN_HANDLER (undivert)): Do not allow nonnumeric arguments
        if POSIXLY_CORRECT.
        * src/main.c (main): Set posixly-correct behavior if either
        POSIXLY_CORRECT is set, or if -G is given.

Index: NEWS
===================================================================
RCS file: /cvsroot/m4/m4/NEWS,v
retrieving revision 1.8
diff -p -u -r1.8 NEWS
--- NEWS        4 Oct 2001 08:03:18 -0000       1.8
+++ NEWS        3 Jul 2003 22:37:15 -0000
@@ -1,6 +1,16 @@
 GNU m4 NEWS - History of user-visible changes.         -*- outline -*-
 Copyright 1992, 1993, 1994, 1998, 2000, 2001 Free Software Foundation, Inc.
 
+Version beta 1.4r - ???, by ???
+
+* If the POSIXLY_CORRECT environment variable is set, m4 now disables
+  GNU extensions that are incompatible with POSIX.
+
+* POSIXLY_CORRECT and `m4 --traditional' now makes the `define' builtin
+  replace all `pushdef'ed values of a macro, as POSIX requires.
+
+* The `defn' builtin now allows any number of arguments, as POSIX requires.
+
 Version beta 1.4q - August 2001, by Gary V. Vaughan
 
 * Support for the experimental `changeword' has been dropped.
Index: doc/m4.texinfo
===================================================================
RCS file: /cvsroot/m4/m4/doc/m4.texinfo,v
retrieving revision 1.17
diff -p -u -r1.17 m4.texinfo
--- doc/m4.texinfo      27 Jun 2003 14:00:25 -0000      1.17
+++ doc/m4.texinfo      3 Jul 2003 22:37:16 -0000
@@ -235,7 +235,6 @@ Miscellaneous builtin macros
 Compatibility with other versions of @code{m4}
 
 * Extensions::                  Extensions in GNU m4
-* Incompatibilities::           Facilities in System V m4 not in GNU m4
 * Other Incompat::              Other incompatibilities
 
 @end detailmenu
@@ -1032,6 +1031,14 @@ a part of the macro definition, and it i
 the output.  This can be avoided by use of the macro @code{dnl}.
 @xref{Dnl}, for details.
 
address@hidden GNU extensions
+GNU @code{m4} normally replaces only the @emph{topmost} definition of a
+macro if it has several definitions from @code{pushdef}.
address@hidden, , Temporarily redefining macros}, for an explanation of
address@hidden  Some other UNIX implementations replace all definitions
+of a macro with @code{define}.
address@hidden Incompat, , Other incompatibilities}, for more details.
+
 The first argument to @code{define} does not have to be a simple word.
 It can be any text string.  A macro with a non standard name cannot be
 invoked in the normal way, as the name is not recognised.  It can only
@@ -1245,6 +1252,11 @@ points to the builtin's internal definit
 meaningful as the second argument to @code{define} (and @code{pushdef}),
 and is ignored in any other context.
 
address@hidden can be given any number of arguments; it expands to the
+concatenation of the quoted definitions of each argument.  The
+usefulness of this behavior is unclear, but @acronym{POSIX} requires
+it.
+
 The macro @code{defn} is recognized only with parameters.
 @end deffn
 
@@ -3761,7 +3773,6 @@ is made to summarize these here.
 
 @menu
 * Extensions::                  Extensions in GNU m4
-* Incompatibilities::           Facilities in System V m4 not in GNU m4
 * Other Incompat::              Other incompatibilities
 @end menu
 
@@ -3769,10 +3780,16 @@ is made to summarize these here.
 @section Extensions in GNU @code{m4}
 
 @cindex GNU extensions
address@hidden @acronym{POSIX}
address@hidden @env{POSIXLY_CORRECT}
 This version of @code{m4} contains a few facilities, that do not exist
 in System V @code{m4}.  These extra facilities are all suppressed by
 using the @samp{-G} command line option, unless overridden by other
 command line options.
+Most of these extensions are compatible with
address@hidden://www.unix.org/single_unix_specification/,
address@hidden; the few exceptions are suppressed if the
address@hidden environment variable is set.
 
 @itemize @bullet
 @item
@@ -3780,6 +3797,8 @@ In the @address@hidden notation for macr
 several digits, while the System V @code{m4} only accepts one digit.
 This allows macros in GNU @code{m4} to take any number of arguments, and
 not only nine (@pxref{Arguments}).
address@hidden does not allow this extension, so it is disabled if
address@hidden is set.
 
 @item
 Files included with @code{include} and @code{sinclude} are sought in a
@@ -3790,6 +3809,8 @@ directory.  The search path is specified
 @item
 Arguments to @code{undivert} can be non-numeric, in which case the named
 file will be included uninterpreted in the output (@pxref{Undivert}).
address@hidden does not allow this extension, so it is disabled if
address@hidden is set.
 
 @item
 Formatted output is supported through the @code{format} builtin, which
@@ -3846,18 +3867,6 @@ description of these options.
 Also, the debugging and tracing facilities in GNU @code{m4} are much
 more extensive than in most other versions of @code{m4}.
 
address@hidden Incompatibilities
address@hidden Facilities in System V @code{m4} not in GNU @code{m4}
-
-The version of @code{m4} from System V contains a few facilities that
-have not been implemented in GNU @code{m4} yet.
-
address@hidden @bullet
address@hidden
-System V @code{m4} supports multiple arguments to @code{defn}.  This is
-not implemented in GNU @code{m4}.  Its usefulness is unclear to me.
address@hidden itemize
-
 @node Other Incompat
 @section Other incompatibilities
 
@@ -3908,6 +3917,15 @@ name would be a useless limitation.  Of 
 for the GNU @code{m4} user to hang himself!  Rescanning hangs may be
 avoided through careful programming, a little like for endless loops
 in traditional programming languages.
+
address@hidden
+Some implementations of @code{m4} (Solaris for example) conform to
address@hidden, which requires @code{define(@var{macro})} to behave
+like @code{undefine(@var{macro})pushdef(@var{macro})}.  Other
+implementations, including GNU @code{m4} without the @samp{-G} option
+and without @env{POSIXLY_CORRECT} set, treat
address@hidden(@var{macro})} as
address@hidden(@var{macro})pushdef(@var{macro})}.
 
 @item
 @findex __gnu__
Index: m4/m4.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4.c,v
retrieving revision 1.4
diff -p -u -r1.4 m4.c
--- m4/m4.c     26 Jun 2003 14:57:32 -0000      1.4
+++ m4/m4.c     3 Jul 2003 22:37:16 -0000
@@ -62,6 +62,7 @@ m4_delete (m4 *context)
 #undef m4_get_discard_comments_opt
 #undef m4_get_interactive_opt
 #undef m4_get_sync_output_opt
+#undef m4_get_posixly_correct_opt
 
 
 #define M4FIELD(type, base, field)                                     \
Index: m4/m4module.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4module.h,v
retrieving revision 1.53
diff -p -u -r1.53 m4module.h
--- m4/m4module.h       27 Jun 2003 14:00:25 -0000      1.53
+++ m4/m4module.h       3 Jul 2003 22:37:16 -0000
@@ -105,6 +105,7 @@ extern void         m4_delete       (m4 *);
        M4OPT_BIT(M4_OPT_DISCARD_COMMENTS_BIT,  discard_comments_opt)   \
        M4OPT_BIT(M4_OPT_INTERACTIVE_BIT,       interactive_opt)        \
        M4OPT_BIT(M4_OPT_SYNC_OUTPUT_BIT,       sync_output_opt)        \
+       M4OPT_BIT(M4_OPT_POSIXLY_CORRECT_BIT,   posixly_correct_opt)    \
 
 
 #define M4FIELD(type, base, field)                                     \
Index: m4/m4private.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4private.h,v
retrieving revision 1.26
diff -p -u -r1.26 m4private.h
--- m4/m4private.h      26 Jun 2003 14:57:32 -0000      1.26
+++ m4/m4private.h      3 Jul 2003 22:37:16 -0000
@@ -59,6 +59,7 @@ struct m4 {
 #define M4_OPT_DISCARD_COMMENTS_BIT    (1 << 2) /* -c */
 #define M4_OPT_INTERACTIVE_BIT         (1 << 3) /* -e */
 #define M4_OPT_SYNC_OUTPUT_BIT         (1 << 4) /* -s */
+#define M4_OPT_POSIXLY_CORRECT_BIT     (1 << 5) /* POSIXLY_CORRECT */
 
 #ifdef NDEBUG
 #  define m4_get_symbol_table(C)               ((C)->symtab)
@@ -79,6 +80,8 @@ struct m4 {
                (BIT_TEST((C)->opt_flags, M4_OPT_INTERACTIVE_BIT))
 #  define m4_get_sync_output_opt(C)                                    \
                (BIT_TEST((C)->opt_flags, M4_OPT_SYNC_OUTPUT_BIT))
+#  define m4_get_posixly_correct_opt(C)                                        
\
+               (BIT_TEST((C)->opt_flags, M4_OPT_POSIXLY_CORRECT_BIT))
 #endif
 
 
Index: m4/macro.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/macro.c,v
retrieving revision 1.31
diff -p -u -r1.31 macro.c
--- m4/macro.c  27 Jun 2003 14:00:25 -0000      1.31
+++ m4/macro.c  3 Jul 2003 22:37:16 -0000
@@ -343,7 +343,7 @@ m4_process_macro (m4 *context, m4_symbol
        {
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
-         if (m4_get_no_gnu_extensions_opt (context) || !isdigit(text[1]))
+         if (m4_get_posixly_correct_opt (context) || !isdigit(text[1]))
            {
              i = *text++ - '0';
            }
@@ -369,7 +369,7 @@ m4_process_macro (m4 *context, m4_symbol
          break;
 
        default:
-         if (m4_get_no_gnu_extensions_opt (context)
+         if (m4_get_posixly_correct_opt (context)
              || !SYMBOL_ARG_SIGNATURE (symbol))
            {
              obstack_1grow (obs, ch);
Index: modules/m4.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/m4.c,v
retrieving revision 1.45
diff -p -u -r1.45 m4.c
--- modules/m4.c        26 Jun 2003 14:57:32 -0000      1.45
+++ modules/m4.c        3 Jul 2003 22:37:16 -0000
@@ -56,7 +56,7 @@ extern int errno;
        BUILTIN(changequote,    FALSE,  FALSE,  1,      3  )    \
        BUILTIN(decr,           FALSE,  TRUE,   2,      2  )    \
        BUILTIN(define,         TRUE,   TRUE,   2,      3  )    \
-       BUILTIN(defn,           FALSE,  TRUE,   2,      2  )    \
+       BUILTIN(defn,           FALSE,  TRUE,   0,      -1 )    \
        BUILTIN(divert,         FALSE,  FALSE,  1,      2  )    \
        BUILTIN(divnum,         FALSE,  FALSE,  1,      1  )    \
        BUILTIN(dnl,            FALSE,  FALSE,  1,      1  )    \
@@ -161,6 +161,9 @@ M4BUILTIN_HANDLER (define)
       else
        m4_symbol_value_copy (value, argv[2]);
 
+      if (m4_get_posixly_correct_opt (context))
+       m4_symbol_delete (M4SYMTAB, M4ARG (1));
+
       m4_symbol_define (M4SYMTAB, M4ARG (1), value);
     }
 }
@@ -311,22 +314,24 @@ M4BUILTIN_HANDLER (dumpdef)
    macro-definition token on the input stack.  */
 M4BUILTIN_HANDLER (defn)
 {
-  m4_symbol *symbol;
+  int i;
 
-  symbol = m4_symbol_lookup (M4SYMTAB, M4ARG (1));
-  if (symbol == NULL)
+  for (i = 1; i < argc; i++)
     {
-      M4WARN ((m4_get_warning_status_opt (context), 0,
-              _("Warning: %s: undefined name: %s"), M4ARG (0), M4ARG (1)));
-      return;
-    }
+      const char *name = m4_get_symbol_value_text (argv[i]);
+      m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name);
 
-  if (m4_is_symbol_text (symbol))
-    m4_shipout_string (context, obs, m4_get_symbol_text (symbol), 0, TRUE);
-  else if (m4_is_symbol_func (symbol))
-    m4_push_builtin (m4_get_symbol_value (symbol));
-  else
-    assert (!"Bad token data type in m4_defn");
+      if (!symbol)
+       M4WARN ((m4_get_warning_status_opt (context), 0,
+                _("Warning: %s: undefined name: %s"),
+                m4_get_symbol_value_text (argv[0]), name));
+      else if (m4_is_symbol_text (symbol))
+       m4_shipout_string (context, obs, m4_get_symbol_text (symbol), 0, TRUE);
+      else if (m4_is_symbol_func (symbol))
+       m4_push_builtin (m4_get_symbol_value (symbol));
+      else
+       assert (!"Bad token data type in m4_defn");
+    }
 }
 
 
@@ -402,7 +407,7 @@ M4BUILTIN_HANDLER (undivert)
     {
       if (sscanf (M4ARG (1), "%d", &i) == 1)
        m4_insert_diversion (i);
-      else if (m4_get_no_gnu_extensions_opt (context))
+      else if (m4_get_posixly_correct_opt (context))
        m4_numeric_arg (context, argc, argv, 1, &i);
       else
        {
Index: src/main.c
===================================================================
RCS file: /cvsroot/m4/m4/src/main.c,v
retrieving revision 1.43
diff -p -u -r1.43 main.c
--- src/main.c  26 Jun 2003 14:57:32 -0000      1.43
+++ src/main.c  3 Jul 2003 22:37:16 -0000
@@ -240,6 +240,9 @@ main (int argc, char *const *argv, char 
   if (isatty (STDIN_FILENO))
     m4_set_interactive_opt (context, TRUE);
 
+  if (getenv ("POSIXLY_CORRECT"))
+    m4_set_posixly_correct_opt (context, TRUE);
+
   /* First, we decode the arguments, to size up tables and stuff.  */
 
   head = tail = NULL;
@@ -290,6 +293,7 @@ main (int argc, char *const *argv, char 
 
       case 'G':
        m4_set_no_gnu_extensions_opt (context, TRUE);
+       m4_set_posixly_correct_opt (context, TRUE);
        break;
 
       case 'I':
Index: tests/builtins.at
===================================================================
RCS file: /cvsroot/m4/m4/tests/builtins.at,v
retrieving revision 1.7
diff -p -u -r1.7 builtins.at
--- tests/builtins.at   13 Oct 2001 08:55:55 -0000      1.7
+++ tests/builtins.at   3 Jul 2003 22:37:16 -0000
@@ -20,6 +20,44 @@ AT_BANNER([Torturing builtins.])
 
 
 ## ------ ##
+## define ##
+## ------ ##
+
+AT_SETUP([[define]])
+
+AT_DATA([[define.m4]],
+[[undefine(`macro')dnl
+pushdef(`macro', `base value')dnl
+pushdef(`macro', `hello, world')dnl
+pushdef(`macro', `top value')dnl
+define(`macro', `new value')dnl
+macro.
+popdef(`macro')dnl
+macro.
+popdef(`macro')dnl
+macro.
+]])
+
+AT_CHECK_M4([define.m4], 0,
+[[new value.
+hello, world.
+base value.
+]], [[m4: define.m4: 1: Warning: undefine: undefined name: macro
+]])
+
+AT_CHECK_M4([--traditional define.m4], 0,
+[[new value.
+macro.
+macro.
+]], [[m4: define.m4: 1: Warning: undefine: undefined name: macro
+m4: define.m4: 9: Warning: popdef: undefined name: macro
+]])
+
+AT_CLEANUP
+
+
+
+## ------ ##
 ## divert ##
 ## ------ ##
 




reply via email to

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