m4-patches
[Top][All Lists]
Advanced

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

head: Re: branch-1_4 off-by-one in line reporting


From: Eric Blake
Subject: head: Re: branch-1_4 off-by-one in line reporting
Date: Fri, 13 Oct 2006 16:46:24 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Eric Blake <ebb9 <at> byu.net> writes:

> 
> And here's the port of all three patches in this thread to head.  It's big, 
but 
> I couldn't really break it up.

This broke some of the relatively new features on head, even though it passed 
the testsuite (for example, tracing include(foo) with the 'e' flag was showing 
the wrong filename).  So the obvious course of action - beef up the testsuite, 
then fix the fallout :)

I also pulled in the branch fix for making indir and builtin grok macro 
arguments.

2006-10-13  Eric Blake  <address@hidden>

        * configure.ac (AC_CONFIG_HEADERS): Name the template config.hin,
        not config-h.in.
        * modules/gnu.c (builtin, indir): Transparently handle builtin
        tokens from defn.
        * doc/m4.texinfo (Indir, Builtin): Remerge from branch.
        * m4/input.c (m4_pop_wrapup): Display debug message when switching
        to wrapped text.
        (m4_input_init): No need to use empty file any more.
        (file_print): Display correct file name.
        * m4/utility.c (m4_error, m4_warn): Ensure we don't try to
        dereference a NULL file name.
        * m4/m4module.h (m4_pop_wrapup): New parameter.
        (m4_symbol_value_groks_macro, m4_symbol_groks_macro): New
        prototypes.
        * m4/m4private.h (m4_symbol_value_groks_macro): Faster version.
        * m4/symtab.c (m4_symbol_value_groks_macro): New method.
        * src/main.c (main): Adjust caller.
        * tests/options.at (--debugmode): Test more output from -dV.

Index: configure.ac
===================================================================
RCS file: /sources/m4/m4/configure.ac,v
retrieving revision 1.57
diff -u -r1.57 configure.ac
--- configure.ac        6 Oct 2006 18:24:31 -0000       1.57
+++ configure.ac        13 Oct 2006 16:40:29 -0000
@@ -29,7 +29,7 @@
 AC_CONFIG_MACRO_DIR([ltdl/m4])
 AC_CONFIG_LIBOBJ_DIR([gnu])
 AC_CONFIG_TESTDIR([tests])
-AC_CONFIG_HEADERS([gnu/config.h:gnu/config-h.in])
+AC_CONFIG_HEADERS([gnu/config.h:gnu/config.hin])
 AC_CONFIG_FILES([tests/m4], [chmod +x tests/m4])
 
 
@@ -57,8 +57,7 @@
 dnl Autoconf recommends that packages use lowercase for their package-specific
 dnl prefix for cache variables.  But in the case of m4, that collides with
 dnl the m4_ namespace provided by m4sugar, so we prefer M4_ as our
-dnl package-specific prefix.  FIXME - consistently use M4_ in the m4 macros
-dnl that feed the creation of configure.
+dnl package-specific prefix.
 m4_pattern_forbid([^M4_[A-Z]])
 
 AC_DEFUN([M4_DEFAULT_PRELOAD], [m4 traditional gnu])
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.63
diff -u -r1.63 m4.texinfo
--- doc/m4.texinfo      12 Oct 2006 21:14:49 -0000      1.63
+++ doc/m4.texinfo      13 Oct 2006 16:40:29 -0000
@@ -2106,6 +2106,7 @@
 used.
 
 @example
+$ @kbd{m4 -d}
 define(`f', `1')
 @result{}
 f(define(`f', `2'))
@@ -2117,6 +2118,28 @@
 @result{}
 @end example
 
+When handed the result of @code{defn} (@pxref{Defn}) as one of its
+arguments, @code{indir} defers to the invoked @var{name} for whether a
+token representing a builtin is recognized or flattened to the empty
+string.
+
address@hidden
+$ @kbd{m4 -d}
+indir(defn(`defn'), `divnum')
address@hidden:stdin:1: Warning: indir: invalid macro name ignored
address@hidden
+indir(`define', defn(`defn'), `divnum')
address@hidden:stdin:2: Warning: define: invalid macro name ignored
address@hidden
+indir(`define', `foo', defn(`divnum'))
address@hidden
+foo
address@hidden
+indir(`divert', defn(`foo'))
address@hidden:stdin:5: Warning: divert: empty string treated as 0
address@hidden
address@hidden example
+
 @node Builtin
 @section Indirect call of builtins
 
@@ -2147,6 +2170,10 @@
 @result{}hidden
 foo
 @result{}foo
+builtin(`define', `foo', defn(`divnum'))
address@hidden
+foo
address@hidden
 builtin(`define', `foo', `BAR')
 @result{}
 foo
Index: m4/input.c
===================================================================
RCS file: /sources/m4/m4/m4/input.c,v
retrieving revision 1.52
diff -u -r1.52 input.c
--- m4/input.c  12 Oct 2006 23:21:34 -0000      1.52
+++ m4/input.c  13 Oct 2006 16:40:29 -0000
@@ -314,7 +314,8 @@
 static void
 file_print (m4_input_block *me, m4 *context, m4_obstack *obs)
 {
-  const char *text = m4_get_current_file (context);
+  const char *text = (me->funcs == &file_init_funcs ? me->u.u_f.name
+                     : m4_get_current_file (context));
   obstack_grow (obs, "<file: ", strlen ("<file: "));
   obstack_grow (obs, text, strlen (text));
   obstack_1grow (obs, '>');
@@ -646,8 +647,10 @@
    Since wrapup text can install new wrapup text, pop_wrapup () returns
    false when there is no wrapup text on the stack, and true otherwise.  */
 bool
-m4_pop_wrapup (void)
+m4_pop_wrapup (m4 *context)
 {
+  static size_t level = 0;
+
   next = NULL;
   obstack_free (current_input, NULL);
   free (current_input);
@@ -655,11 +658,18 @@
   if (wsp == NULL)
     {
       obstack_free (wrapup_stack, NULL);
+      m4_set_current_file (context, NULL);
+      m4_set_current_line (context, 0);
+      m4_debug_message (context, M4_DEBUG_TRACE_INPUT,
+                       _("input from m4wrap exhausted"));
       current_input = NULL;
       DELETE (wrapup_stack);
       return false;
     }
 
+  m4_debug_message (context, M4_DEBUG_TRACE_INPUT,
+                   _("input from m4wrap recursion level %d"), ++level);
+
   current_input = wrapup_stack;
   wrapup_stack = (m4_obstack *) xmalloc (sizeof (m4_obstack));
   obstack_init (wrapup_stack);
@@ -897,19 +907,15 @@
 void
 m4_input_init (m4 *context)
 {
-  /* FIXME: The user should never be able to see the empty string as a
-     file name, even during m4wrap expansion.  */
-  m4_set_current_file (context, "");
+  obstack_init (&file_names);
+  m4_set_current_file (context, NULL);
   m4_set_current_line (context, 0);
 
-
   current_input = (m4_obstack *) xmalloc (sizeof (m4_obstack));
   obstack_init (current_input);
   wrapup_stack = (m4_obstack *) xmalloc (sizeof (m4_obstack));
   obstack_init (wrapup_stack);
 
-  obstack_init (&file_names);
-
   /* Allocate an object in the current chunk, so that obstack_free
      will always work even if the first token parsed spills to a new
      chunk.  */
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.94
diff -u -r1.94 m4module.h
--- m4/m4module.h       12 Oct 2006 21:14:50 -0000      1.94
+++ m4/m4module.h       13 Oct 2006 16:40:29 -0000
@@ -229,6 +229,7 @@
 extern void    m4_symbol_print         (m4_symbol *, m4_obstack *, bool,
                                         const char *, const char *, bool,
                                         size_t, bool);
+extern bool    m4_symbol_value_groks_macro     (m4_symbol_value *);
 
 #define m4_is_symbol_void(symbol)                                      \
        (m4_is_symbol_value_void (m4_get_symbol_value (symbol)))
@@ -244,6 +245,8 @@
        (m4_get_symbol_value_func (m4_get_symbol_value (symbol)))
 #define m4_get_symbol_placeholder(symbol)                              \
        (m4_get_symbol_value_placeholder (m4_get_symbol_value (symbol)))
+#define m4_symbol_groks_macro(symbol)                                  \
+       (m4_symbol_value_groks_macro (m4_get_symbol_value (symbol)))
 
 extern m4_symbol_value *m4_symbol_value_create   (void);
 extern void            m4_symbol_value_delete    (m4_symbol_value *);
@@ -401,7 +404,7 @@
 extern m4_obstack      *m4_push_string_init    (m4 *);
 extern m4_input_block  *m4_push_string_finish  (void);
 extern void    m4_push_wrapup  (m4 *, const char *);
-extern bool    m4_pop_wrapup   (void);
+extern bool    m4_pop_wrapup   (m4 *);
 extern void    m4_input_print  (m4 *, m4_obstack *, m4_input_block *);
 
 
Index: m4/m4private.h
===================================================================
RCS file: /sources/m4/m4/m4/m4private.h,v
retrieving revision 1.66
diff -u -r1.66 m4private.h
--- m4/m4private.h      12 Oct 2006 21:14:50 -0000      1.66
+++ m4/m4private.h      13 Oct 2006 16:40:29 -0000
@@ -220,6 +220,8 @@
 #  define m4_get_symbol_value_func(V)  ((V)->u.func)
 #  define m4_get_symbol_value_placeholder(V)                           \
                                        ((V)->u.text)
+#  define m4_symbol_value_groks_macro(V) (BIT_TEST ((V)->flags,        
        \
+                                                    VALUE_MACRO_ARGS_BIT))
 
 #  define m4_set_symbol_value_text(V, T)                               \
        ((V)->type = M4_SYMBOL_TEXT, (V)->u.text = (T))
Index: m4/symtab.c
===================================================================
RCS file: /sources/m4/m4/m4/symtab.c,v
retrieving revision 1.63
diff -u -r1.63 symtab.c
--- m4/symtab.c 28 Sep 2006 04:22:33 -0000      1.63
+++ m4/symtab.c 13 Oct 2006 16:40:29 -0000
@@ -580,6 +580,14 @@
   return xzalloc (sizeof (m4_symbol_value));
 }
 
+#undef m4_symbol_groks_macro
+bool
+m4_symbol_value_groks_macro (m4_symbol_value *value)
+{
+  assert (value);
+  return BIT_TEST (value->flags, VALUE_MACRO_ARGS_BIT);
+}
+
 #undef m4_get_symbol_value
 m4_symbol_value *
 m4_get_symbol_value (m4_symbol *symbol)
Index: m4/utility.c
===================================================================
RCS file: /sources/m4/m4/m4/utility.c,v
retrieving revision 1.53
diff -u -r1.53 utility.c
--- m4/utility.c        12 Oct 2006 21:14:50 -0000      1.53
+++ m4/utility.c        13 Oct 2006 16:40:29 -0000
@@ -127,6 +127,7 @@
 {
   va_list args;
   int line = m4_get_current_line (context);
+  assert (m4_get_current_file (context) || ! line);
   va_start (args, format);
   if (status == EXIT_SUCCESS && m4_get_fatal_warnings_opt (context))
     status = EXIT_FAILURE;
@@ -170,6 +171,8 @@
       int status = EXIT_SUCCESS;
       int line = m4_get_current_line (context);
       char *full_format = xasprintf(_("Warning: %s"), format);
+
+      assert (m4_get_current_file (context) || ! line);
       va_start (args, format);
       if (m4_get_fatal_warnings_opt (context))
        status = EXIT_FAILURE;
Index: modules/gnu.c
===================================================================
RCS file: /sources/m4/m4/modules/gnu.c,v
retrieving revision 1.63
diff -u -r1.63 gnu.c
--- modules/gnu.c       9 Oct 2006 21:00:32 -0000       1.63
+++ modules/gnu.c       13 Oct 2006 16:40:29 -0000
@@ -46,7 +46,7 @@
   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 (builtin,    true,   true,   false,  1,      -1 )    \
   BUILTIN (changeresyntax,false,true,  false,  1,      1  )    \
   BUILTIN (changesyntax,false, true,   false,  1,      -1 )    \
   BUILTIN (debugfile,  false,  false,  false,  0,      1  )    \
@@ -54,7 +54,7 @@
   BUILTIN (debugmode,  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 (indir,      true,   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  )    \
@@ -329,17 +329,27 @@
  **/
 M4BUILTIN_HANDLER (builtin)
 {
-  const m4_builtin *bp = NULL;
-  const char *name = M4ARG (1);
-
-  bp = m4_builtin_find_by_name (NULL, name);
+  if (! m4_is_symbol_value_text (argv[1]))
+    m4_warn (context, 0, _("%s: invalid macro name ignored"), M4ARG (0));
+  else
+    {
+      const char *name = M4ARG (1);
+      const m4_builtin *bp = m4_builtin_find_by_name (NULL, name);
 
-  if (bp == NULL)
-    m4_warn (context, 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->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
-    bp->func (context, obs, argc - 1, argv + 1);
+      if (bp == NULL)
+       m4_warn (context, 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->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
+       {
+         int i;
+         if ((bp->flags & M4_BUILTIN_GROKS_MACRO) == 0)
+           for (i = 2; i < argc; i++)
+             if (! m4_is_symbol_value_text (argv[i]))
+               m4_set_symbol_value_text (argv[i], "");
+         bp->func (context, obs, argc - 1, argv + 1);
+       }
+    }
 }
 
 
@@ -537,14 +547,26 @@
  **/
 M4BUILTIN_HANDLER (indir)
 {
-  const char * name   = M4ARG (1);
-  m4_symbol *  symbol = m4_symbol_lookup (M4SYMTAB, name);
-
-  if (symbol == NULL)
-    m4_warn (context, 0, _("%s: undefined macro `%s'"), M4ARG (0), name);
+  if (! m4_is_symbol_value_text (argv[1]))
+    m4_warn (context, 0, _("%s: invalid macro name ignored"), M4ARG (0));
   else
-    m4_macro_call (context, m4_get_symbol_value (symbol), obs,
-                  argc - 1, argv + 1);
+    {
+      const char *name = M4ARG (1);
+      m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name);
+
+      if (symbol == NULL)
+       m4_warn (context, 0, _("%s: undefined macro `%s'"), M4ARG (0), name);
+      else
+       {
+         int i;
+         if (! m4_symbol_groks_macro (symbol))
+           for (i = 2; i < argc; i++)
+             if (! m4_is_symbol_value_text (argv[i]))
+               m4_set_symbol_value_text (argv[i], "");
+         m4_macro_call (context, m4_get_symbol_value (symbol), obs,
+                        argc - 1, argv + 1);
+       }
+    }
 }
 
 
Index: src/main.c
===================================================================
RCS file: /sources/m4/m4/src/main.c,v
retrieving revision 1.96
diff -u -r1.96 main.c
--- src/main.c  12 Oct 2006 02:44:27 -0000      1.96
+++ src/main.c  13 Oct 2006 16:40:29 -0000
@@ -652,7 +652,7 @@
       }
 
   /* Now handle wrapup text.  */
-  while (m4_pop_wrapup ())
+  while (m4_pop_wrapup (context))
     m4_macro_expand_input (context);
 
   if (frozen_file_to_write)
Index: tests/options.at
===================================================================
RCS file: /sources/m4/m4/tests/options.at,v
retrieving revision 1.20
diff -u -r1.20 options.at
--- tests/options.at    12 Oct 2006 21:14:50 -0000      1.20
+++ tests/options.at    13 Oct 2006 16:40:29 -0000
@@ -243,19 +243,24 @@
 AT_SETUP([--debugmode])
 
 AT_DATA([[in]],
-[[divnum
+[[include(`nested')dnl
 len(`abc')
 ]])
 
+AT_DATA([[nested]],
+[[m4wrap(`divnum
+')dnl
+]])
+
 dnl AT_CHECK_M4 starts life with -d.  Make sure it looks like -daeq.
-AT_CHECK_M4([-tlen in], [0], [[0
-3
+AT_CHECK_M4([-tlen in], [0], [[3
+0
 ]], [[m4trace: -1- len(`abc') -> `3'
 ]])
 
 dnl Test all flags.
-AT_CHECK_M4([-dV in], [0], [[0
-3
+AT_CHECK_M4([-dV in], [0], [[3
+0
 ]], [[m4debug: module m4: opening file
 m4debug: module m4: init hook called
 m4debug: module m4: opened
@@ -266,11 +271,25 @@
 m4debug: module gnu: macros loaded
 m4debug: path search for `in' found `in'
 m4debug: input read from in
-m4trace:in:1: -1- id 1: divnum ... = <divnum>{m4}
-m4trace:in:1: -1- id 1: divnum -> `0'
-m4trace:in:2: -1- id 2: len ... = <len>{m4}
-m4trace:in:2: -1- id 2: len(`abc') -> `3'
+m4trace:in:1: -1- id 1: include ... = <include>{m4}
+m4debug:in:1: path search for `nested' found `nested'
+m4debug:in:1: input read from nested
+m4trace:in:1: -1- id 1: include(`nested') -> <file: nested>
+m4trace:nested:1: -1- id 2: m4wrap ... = <m4wrap>{m4}
+m4trace:nested:1: -1- id 2: m4wrap(`divnum
+') -> `'
+m4trace:nested:2: -1- id 3: dnl ... = <dnl>{m4}
+m4trace:nested:2: -1- id 3: dnl -> `'
+m4debug:nested:3: input reverted to in, line 1
+m4trace:in:1: -1- id 4: dnl ... = <dnl>{m4}
+m4trace:in:1: -1- id 4: dnl -> `'
+m4trace:in:2: -1- id 5: len ... = <len>{m4}
+m4trace:in:2: -1- id 5: len(`abc') -> `3'
 m4debug:in:3: input exhausted
+m4debug: input from m4wrap recursion level 1
+m4trace:nested:1: -1- id 6: divnum ... = <divnum>{m4}
+m4trace:nested:1: -1- id 6: divnum -> `0'
+m4debug: input from m4wrap exhausted
 m4debug: module gnu: symbols unloaded
 m4debug: module gnu: finish hook called
 m4debug: module gnu: closed
@@ -279,10 +298,15 @@
 ]])
 
 dnl Test addition and subtraction of flags.
-AT_CHECK_M4([--debug=-e --debugmode=+xt in], [0], [[0
-3
-]], [[m4trace: -1- id 1: divnum
-m4trace: -1- id 2: len(`abc')
+AT_CHECK_M4([--debug=-e --debugmode=+xt in], [0], [[3
+0
+]], [[m4trace: -1- id 1: include(`nested')
+m4trace: -1- id 2: m4wrap(`divnum
+')
+m4trace: -1- id 3: dnl
+m4trace: -1- id 4: dnl
+m4trace: -1- id 5: len(`abc')
+m4trace: -1- id 6: divnum
 ]])
 
 dnl Test that shorter prefix is ambiguous.






reply via email to

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