m4-patches
[Top][All Lists]
Advanced

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

FYI: 28-gary-refactor-debug-api.patch


From: Gary V. Vaughan
Subject: FYI: 28-gary-refactor-debug-api.patch
Date: Wed, 23 Jul 2003 12:53:13 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5a) Gecko/20030718

Applied to HEAD.
--
  ())_.  Gary V. Vaughan    gary@(oranda.demon.co.uk|gnu.org)
  ( '/   Research Scientist http://www.oranda.demon.co.uk       ,_())____
  / )=   GNU Hacker         http://www.gnu.org/software/libtool  \'      `&
`(_~)_   Tech' Author       http://sources.redhat.com/autobook   =`---d__/
Index: ChangeLog
from  Gary V. Vaughan  <address@hidden>

        More refactoring of the m4module.h API.  Replace #defines with an
        enum, and move non-public functions out of the public API.

        * m4/debug.c (stdarg.h, varargs.h): Remove variadic header
        inclusion.
        * m4/macro.c (stdarg.h): Add ANSI C variadic header.
        * m4/debug.c (m4_debug, trace): Moved...
        * m4/m4private.h (struct m4): ...to fields of this struct.
        (m4_get_debug_file, m4_get_trace_messages): New fast access macros
        for the new fields.
        * m4/debug.c (m4_debug_init, m4_debug_exit): Removed functions...
        * src/main.c (m4_debug_init, m4_debug_exit): ...invocations...
        * m4/m4.c (m4_create, m4_delete): ...and handled here instead.
        * m4/m4module.h (m4_context_field_table): Add entries for new
        debug_file and trace_messages fields.
        (M4_DEBUG_TRACE_ARGS, M4_DEBUG_TRACE_EXPANSION)
        (M4_DEBUG_TRACE_QUOTE, M4_DEBUG_TRACE_ALL, M4_DEBUG_TRACE_LINE)
        (M4_DEBUG_TRACE_FILE, M4_DEBUG_TRACE_PATH, M4_DEBUG_TRACE_CALL)
        (M4_DEBUG_TRACE_INPUT, M4_DEBUG_TRACE_CALLID)
        (M4_DEBUG_TRACE_VERBOSE): Replaced #defines with an enum.
        (m4_is_debug_bit): New macro to simplfy checks against the debug
        bits above.
        (m4_trace_format, m4_trace_header, m4_trace_flush)
        (m4_trace_prepre, m4_trace_pre, m4_trace_post): Removed
        prototypes.
        * m4/debug.c (m4_trace_format, m4_trace_header, m4_trace_flush)
        (m4_trace_prepre, m4_trace_pre, m4_trace_post): Moved...
        * m4/macro.c (trace_format, trace_header, trace_flush)
        (trace_prepre, trace_pre, trace_post): ...to these newly static
        functions, since they are only ever used from this file.  Changed
        all callers.

        `struct m4'; made `m4_symtab' a real datatype, so that its api
Index: m4/debug.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/debug.c,v
retrieving revision 1.15
diff -u -p -u -r1.15 debug.c
--- m4/debug.c 26 Jun 2003 14:57:32 -0000 1.15
+++ m4/debug.c 23 Jul 2003 11:50:53 -0000
@@ -20,42 +20,16 @@
 #include <stdio.h>
 #include <sys/stat.h>
 
-#if (defined __STDC__ && __STDC__) || defined PROTOTYPES
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
 #include "m4private.h"
 
-/* File for debugging output.  */
-FILE *m4_debug = NULL;
-
-/* Obstack for trace messages.  */
-static struct obstack trace;
-
-static void m4_debug_set_file (FILE *);
-
-/* Initialise the debugging module.  */
-void
-m4_debug_init (void)
-{
-  m4_debug_set_file (stderr);
-  obstack_init (&trace);
-}
-
-void
-m4_debug_exit (void)
-{
-  obstack_free (&trace, NULL);
-}
+static void set_debug_file (m4 *, FILE *);
 
 
 
 /* Function to decode the debugging flags OPTS.  Used by main while
    processing option -d, and by the builtin debugmode ().  */
 int
-m4_debug_decode (const char *opts)
+m4_debug_decode (m4 *context, const char *opts)
 {
   int level;
 
@@ -120,7 +94,8 @@ m4_debug_decode (const char *opts)
   /* This is to avoid screwing up the trace output due to changes in the
      debug_level.  */
 
-  obstack_free (&trace, obstack_finish (&trace));
+  obstack_free (&context->trace_messages,
+               obstack_finish (&context->trace_messages));
 
   return level;
 }
@@ -129,60 +104,73 @@ m4_debug_decode (const char *opts)
    same as stdout, use stdout instead so that debug messages appear in the
    correct relative position.  */
 static void
-m4_debug_set_file (FILE *fp)
+set_debug_file (m4 *context, FILE *fp)
 {
+  FILE *debug_file;
   struct stat stdout_stat, debug_stat;
 
-  if (m4_debug != NULL && m4_debug != stderr && m4_debug != stdout)
-    fclose (m4_debug);
-  m4_debug = fp;
+  assert (context);
+
+  debug_file = m4_get_debug_file (context);
+
+  if (debug_file != NULL && debug_file != stderr && debug_file != stdout)
+    fclose (debug_file);
+  m4_set_debug_file (context, fp);
 
-  if (m4_debug != NULL && m4_debug != stdout)
+  if (debug_file != NULL && debug_file != stdout)
     {
       if (fstat (fileno (stdout), &stdout_stat) < 0)
        return;
-      if (fstat (fileno (m4_debug), &debug_stat) < 0)
+      if (fstat (fileno (debug_file), &debug_stat) < 0)
        return;
 
       if (stdout_stat.st_ino == debug_stat.st_ino
          && stdout_stat.st_dev == debug_stat.st_dev)
        {
-         if (m4_debug != stderr)
-           fclose (m4_debug);
-         m4_debug = stdout;
+         if (debug_file != stderr)
+           fclose (debug_file);
+         m4_set_debug_file (context, stdout);
        }
     }
 }
 
 /* Serialize files.  Used before executing a system command.  */
 void
-m4_debug_flush_files (void)
+m4_debug_flush_files (m4 *context)
 {
+  FILE *debug_file;
+
+  assert (context);
+
+  debug_file = m4_get_debug_file (context);
+
   fflush (stdout);
   fflush (stderr);
-  if (m4_debug != NULL && m4_debug != stdout && m4_debug != stderr)
-    fflush (m4_debug);
+  if (debug_file != NULL && debug_file != stdout && debug_file != stderr)
+    fflush (debug_file);
 }
 
 /* Change the debug output to file NAME.  If NAME is NULL, debug output is
    reverted to stderr, and if empty debug output is discarded.  Return TRUE
    iff the output stream was changed.  */
 boolean
-m4_debug_set_output (const char *name)
+m4_debug_set_output (m4 *context, const char *name)
 {
   FILE *fp;
 
+  assert (context);
+
   if (name == NULL)
-    m4_debug_set_file (stderr);
+    set_debug_file (context, stderr);
   else if (*name == '\0')
-    m4_debug_set_file (NULL);
+    set_debug_file (context, NULL);
   else
     {
       fp = fopen (name, "a");
       if (fp == NULL)
        return FALSE;
 
-      m4_debug_set_file (fp);
+      set_debug_file (context, fp);
     }
   return TRUE;
 }
@@ -191,214 +179,14 @@ m4_debug_set_output (const char *name)
 void
 m4_debug_message_prefix (m4 *context)
 {
-  fprintf (m4_debug, "m4 debug: ");
-  if (BIT_TEST (m4_get_debug_level_opt (context), M4_DEBUG_TRACE_FILE))
-    fprintf (m4_debug, "%s: ", m4_current_file);
-  if (BIT_TEST (m4_get_debug_level_opt (context), M4_DEBUG_TRACE_LINE))
-    fprintf (m4_debug, "%d: ", m4_current_line);
-}
-
-
-/* The rest of this file contains the functions for macro tracing output.
-   All tracing output for a macro call is collected on an obstack TRACE,
-   and printed whenever the line is complete.  This prevents tracing
-   output from interfering with other debug messages generated by the
-   various builtins.  */
-
-/* Tracing output is formatted here, by a simplified printf-to-obstack
-  function trace_format ().  Understands only %S, %s, %d, %l (optional
-  left quote) and %r (optional right quote).  */
-#if (defined __STDC__ && __STDC__) || defined PROTOTYPES
-static void
-m4_trace_format (m4 *context, const char *fmt, ...)
-#else
-static void
-m4_trace_format (m4 *context, va_alist)
-     va_dcl
-#endif
-{
-#if ! ((defined __STDC__ && __STDC__) || defined PROTOTYPES)
-  const char *fmt;
-#endif
-  va_list args;
-  char ch;
-
-  int d;
-  char nbuf[32];
-  const char *s;
-  int slen;
-  int maxlen;
-
-#if (defined __STDC__ && __STDC__) || defined PROTOTYPES
-  va_start (args, fmt);
-#else
-  va_start (args);
-  fmt = va_arg (args, const char *);
-#endif
-
-  while (TRUE)
-    {
-      while ((ch = *fmt++) != '\0' && ch != '%')
-       obstack_1grow (&trace, ch);
-
-      if (ch == '\0')
-       break;
-
-      maxlen = 0;
-      switch (*fmt++)
-       {
-       case 'S':
-         maxlen = m4_get_max_debug_arg_length_opt (context);
-         /* fall through */
-
-       case 's':
-         s = va_arg (args, const char *);
-         break;
-
-       case 'l':
-         s = BIT_TEST(m4_get_debug_level_opt(context), M4_DEBUG_TRACE_QUOTE)
-               ? m4_get_syntax_lquote (M4SYNTAX)
-               : "";
-         break;
-
-       case 'r':
-         s = BIT_TEST(m4_get_debug_level_opt(context), M4_DEBUG_TRACE_QUOTE)
-               ? m4_get_syntax_rquote (M4SYNTAX)
-               : "";
-         break;
-
-       case 'd':
-         d = va_arg (args, int);
-         sprintf (nbuf, "%d", d);
-         s = nbuf;
-         break;
-
-       default:
-         s = "";
-         break;
-       }
-
-      slen = strlen (s);
-      if (maxlen == 0 || maxlen > slen)
-       obstack_grow (&trace, s, slen);
-      else
-       {
-         obstack_grow (&trace, s, maxlen);
-         obstack_grow (&trace, "...", 3);
-       }
-    }
-
-  va_end (args);
-}
-
-/* Format the standard header attached to all tracing output lines.  */
-static void
-m4_trace_header (m4 *context, int id)
-{
-  m4_trace_format (context, "m4trace:");
-  if (BIT_TEST(m4_get_debug_level_opt(context), M4_DEBUG_TRACE_FILE))
-    m4_trace_format (context, "%s:", m4_current_file);
-  if (BIT_TEST(m4_get_debug_level_opt(context), M4_DEBUG_TRACE_LINE))
-    m4_trace_format (context, "%d:", m4_current_line);
-  m4_trace_format (context, " -%d- ", m4_expansion_level);
-  if (BIT_TEST(m4_get_debug_level_opt(context), M4_DEBUG_TRACE_CALLID))
-    m4_trace_format (context, "id %d: ", id);
-}
-
-/* Print current tracing line, and clear the obstack.  */
-static void
-m4_trace_flush (void)
-{
-  char *line;
-
-  obstack_1grow (&trace, '\0');
-  line = obstack_finish (&trace);
-  M4_DEBUG_PRINT1 ("%s\n", line);
-  obstack_free (&trace, line);
-}
-
-/* Do pre-argument-collction tracing for macro NAME.  Used from
-   expand_macro ().  */
-void
-m4_trace_prepre (m4 *context, const char *name, int id)
-{
-  m4_trace_header (context, id);
-  m4_trace_format (context, "%s ...", name);
-  m4_trace_flush ();
-}
-
-/* Format the parts of a trace line, that can be made before the macro is
-   actually expanded.  Used from expand_macro ().  */
-void
-m4_trace_pre (m4 *context, const char *name, int id,
-             int argc, m4_symbol_value **argv)
-{
-  int i;
-  const m4_builtin *bp;
-
-  m4_trace_header (context, id);
-  m4_trace_format (context, "%s", name);
-
-  if (argc > 1
-      && BIT_TEST (m4_get_debug_level_opt (context), M4_DEBUG_TRACE_ARGS))
-    {
-      m4_trace_format (context, "(");
-
-      for (i = 1; i < argc; i++)
-       {
-         if (i != 1)
-           m4_trace_format (context, ", ");
-
-         if (m4_is_symbol_value_text (argv[i]))
-           {
-             m4_trace_format (context, "%l%S%r", M4ARG (i));
-           }
-         else if (m4_is_symbol_value_func (argv[i]))
-           {
-             bp = m4_builtin_find_by_func (NULL,
-                                           m4_get_symbol_value_func(argv[i]));
-             if (bp == NULL)
-               {
-                 M4ERROR ((m4_get_warning_status_opt (context), 0, "\
-INTERNAL ERROR: Builtin not found in builtin table! (m4_trace_pre ())"));
-                 abort ();
-               }
-             m4_trace_format (context, "<%s>", bp->name);
-           }
-         else
-           {
-             M4ERROR ((m4_get_warning_status_opt (context), 0,
-                       "INTERNAL ERROR: Bad token data type (m4_trace_pre 
())"));
-             abort ();
-           }
-       }
-      m4_trace_format (context, ")");
-    }
+  FILE *debug_file;
 
-  if (BIT_TEST (m4_get_debug_level_opt (context), M4_DEBUG_TRACE_CALL))
-    {
-      m4_trace_format (context, " -> ???");
-      m4_trace_flush ();
-    }
-}
-
-/* Format the final part of a trace line and print it all.  Used from
-   expand_macro ().  */
-void
-m4_trace_post (m4 *context, const char *name, int id,
-              int argc, m4_symbol_value **argv, const char *expanded)
-{
-  if (BIT_TEST (m4_get_debug_level_opt (context), M4_DEBUG_TRACE_CALL))
-    {
-      m4_trace_header (context, id);
-      m4_trace_format (context, "%s%s", name, (argc > 1) ? "(...)" : "");
-    }
-
-  if (expanded && (BIT_TEST (m4_get_debug_level_opt (context),
-                            M4_DEBUG_TRACE_EXPANSION)))
-    {
-      m4_trace_format (context, " -> %l%S%r", expanded);
-    }
+  assert (context);
 
-  m4_trace_flush ();
+  debug_file = m4_get_debug_file (context);
+  fprintf (debug_file, "m4 debug: ");
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_FILE))
+    fprintf (debug_file, "%s: ", m4_current_file);
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_LINE))
+    fprintf (debug_file, "%d: ", m4_current_line);
 }
Index: m4/input.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/input.c,v
retrieving revision 1.32
diff -u -p -u -r1.32 input.c
--- m4/input.c 17 Jul 2003 19:57:06 -0000 1.32
+++ m4/input.c 23 Jul 2003 11:50:53 -0000
@@ -227,7 +227,7 @@ file_unget (ch)
 static void
 file_clean (m4 *context)
 {
-  if (BIT_TEST (m4_get_debug_level_opt (context), M4_DEBUG_TRACE_INPUT))
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_INPUT))
     M4_DEBUG_MESSAGE2 (context, _("Input reverted to %s, line %d"),
                       isp->u.u_f.name, isp->u.u_f.lineno);
 
Index: m4/m4.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4.c,v
retrieving revision 1.5
diff -u -p -u -r1.5 m4.c
--- m4/m4.c 9 Jul 2003 12:32:41 -0000 1.5
+++ m4/m4.c 23 Jul 2003 11:50:53 -0000
@@ -27,6 +27,10 @@ m4_create (void)
 
   context->symtab = m4_symtab_create (0, &context->no_gnu_extensions);
   context->syntax = m4_syntax_create ();
+
+  context->debug_file   = stderr;
+  obstack_init (&context->trace_messages);
+
   context->nesting_limit = M4_DEFAULT_NESTING_LIMIT;
 
   return context;
@@ -42,6 +46,11 @@ m4_delete (m4 *context)
 
   if (context->syntax)
     m4_syntax_delete (context->syntax);
+
+  if (context->debug_file)
+    fclose (context->debug_file);
+
+  obstack_free (&context->trace_messages, NULL);
 
   xfree (context);
 }
Index: m4/m4module.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4module.h,v
retrieving revision 1.55
diff -u -p -u -r1.55 m4module.h
--- m4/m4module.h 17 Jul 2003 19:57:06 -0000 1.55
+++ m4/m4module.h 23 Jul 2003 11:50:53 -0000
@@ -92,6 +92,8 @@ extern void           m4_delete       (m4 *);
 #define m4_context_field_table                                                 
\
        M4FIELD(m4_symbol_table *, symbol_table,   symtab)              \
        M4FIELD(m4_syntax_table *, syntax_table,   syntax)              \
+       M4FIELD(FILE *,            debug_file,     debug_file)          \
+       M4FIELD(struct obstack,    trace_messages, trace_messages)      \
        M4FIELD(int,     warning_status_opt,       warning_status)      \
        M4FIELD(boolean, no_gnu_extensions_opt,    no_gnu_extensions)   \
        M4FIELD(int,     nesting_limit_opt,        nesting_limit)       \
@@ -218,85 +220,80 @@ extern void m4_dump_args (m4 *, struct o
 
 /* --- RUNTIME DEBUGGING --- */
 
-extern FILE *m4_debug;
+/* The value of debug_level is a bitmask of the following:  */
+enum {
+  /* a: show arglist in trace output */
+  M4_DEBUG_TRACE_ARGS          = (1 << 0),
+  /* e: show expansion in trace output */
+  M4_DEBUG_TRACE_EXPANSION     = (1 << 1),
+  /* q: quote args and expansion in trace output */
+  M4_DEBUG_TRACE_QUOTE         = (1 << 2),
+  /* t: trace all macros -- overrides trace{on,off} */
+  M4_DEBUG_TRACE_ALL           = (1 << 3),
+  /* l: add line numbers to trace output */
+  M4_DEBUG_TRACE_LINE          = (1 << 4),
+  /* f: add file name to trace output */
+  M4_DEBUG_TRACE_FILE          = (1 << 5),
+  /* p: trace path search of include files */
+  M4_DEBUG_TRACE_PATH          = (1 << 6),
+  /* c: show macro call before args collection */
+  M4_DEBUG_TRACE_CALL          = (1 << 7),
+  /* i: trace changes of input files */
+  M4_DEBUG_TRACE_INPUT         = (1 << 8),
+  /* x: add call id to trace output */
+  M4_DEBUG_TRACE_CALLID                = (1 << 9),
+
+  /* V: very verbose --  print everything */
+  M4_DEBUG_TRACE_VERBOSE       = (~0)
+};
 
-/* The value of debug_level is a bitmask of the following.  */
-
-/* a: show arglist in trace output */
-#define M4_DEBUG_TRACE_ARGS            (1 << 0)
-/* e: show expansion in trace output */
-#define M4_DEBUG_TRACE_EXPANSION       (1 << 1)
-/* q: quote args and expansion in trace output */
-#define M4_DEBUG_TRACE_QUOTE           (1 << 2)
-/* t: trace all macros -- overrides trace{on,off} */
-#define M4_DEBUG_TRACE_ALL             (1 << 3)
-/* l: add line numbers to trace output */
-#define M4_DEBUG_TRACE_LINE            (1 << 4)
-/* f: add file name to trace output */
-#define M4_DEBUG_TRACE_FILE            (1 << 5)
-/* p: trace path search of include files */
-#define M4_DEBUG_TRACE_PATH            (1 << 6)
-/* c: show macro call before args collection */
-#define M4_DEBUG_TRACE_CALL            (1 << 7)
-/* i: trace changes of input files */
-#define M4_DEBUG_TRACE_INPUT           (1 << 8)
-/* x: add call id to trace output */
-#define M4_DEBUG_TRACE_CALLID          (1 << 9)
-
-/* V: very verbose --  print everything */
-#define M4_DEBUG_TRACE_VERBOSE         1023
 /* default flags -- equiv: aeq */
 #define M4_DEBUG_TRACE_DEFAULT         \
        (M4_DEBUG_TRACE_ARGS|M4_DEBUG_TRACE_EXPANSION|M4_DEBUG_TRACE_QUOTE)
 
-#define M4_DEBUG_PRINT1(Fmt, Arg1)                     M4_STMT_START { \
-      if (m4_debug != NULL)                                            \
-       fprintf (m4_debug, Fmt, Arg1);                  } M4_STMT_END
+#define M4_DEBUG_PRINT1(C, Fmt, Arg1)                  M4_STMT_START { \
+      if (m4_get_debug_file (C) != NULL)                               \
+       fprintf (m4_get_debug_file (C), Fmt, Arg1);     } M4_STMT_END
 
 #define M4_DEBUG_PRINT2(Fmt, Arg1, Arg2)               M4_STMT_START { \
-      if (m4_debug != NULL)                                    \
-       fprintf (m4_debug, Fmt, Arg1, Arg2);            } M4_STMT_END
+      if (m4_get_debug_file (C) != NULL)                               \
+       fprintf (m4_get_debug_file (C), Fmt, Arg1, Arg2);} M4_STMT_END
 
 #define M4_DEBUG_PRINT3(Fmt, Arg1, Arg2, Arg3)         M4_STMT_START { \
-       if (m4_debug != NULL)                                           \
-       fprintf (m4_debug, Fmt, Arg1, Arg2, Arg3);      } M4_STMT_END
+       if (m4_get_debug_file (C) != NULL)                              \
+       fprintf (m4_get_debug_file (C), Fmt, Arg1, Arg2, Arg3); } M4_STMT_END
 
 #define M4_DEBUG_MESSAGE(C, Fmt)                       M4_STMT_START { \
-      if (m4_debug != NULL)                                            \
+      if (m4_get_debug_file (C) != NULL)                               \
        {                                                               \
          m4_debug_message_prefix (C);                                  \
-         fprintf (m4_debug, Fmt);                                      \
-         putc ('\n', m4_debug);                                        \
+         fprintf (m4_get_debug_file (C), Fmt);                         \
+         putc ('\n', m4_get_debug_file (C));                           \
        }                                               } M4_STMT_END
 
 #define M4_DEBUG_MESSAGE1(C, Fmt, Arg1)                        M4_STMT_START { 
\
-      if (m4_debug != NULL)                                            \
+      if (m4_get_debug_file (C) != NULL)                               \
        {                                                               \
          m4_debug_message_prefix (C);                                  \
-         fprintf (m4_debug, Fmt, Arg1);                                \
-         putc ('\n', m4_debug);                                        \
+         fprintf (m4_get_debug_file (C), Fmt, Arg1);                   \
+         putc ('\n', m4_get_debug_file (C));                           \
        }                                               } M4_STMT_END
 
 #define M4_DEBUG_MESSAGE2(C, Fmt, Arg1, Arg2)          M4_STMT_START { \
-      if (m4_debug != NULL)                                            \
+      if (m4_get_debug_file (C) != NULL)                               \
        {                                                               \
          m4_debug_message_prefix (C);                                  \
-         fprintf (m4_debug, Fmt, Arg1, Arg2);                          \
-         putc ('\n', m4_debug);                                        \
+         fprintf (m4_get_debug_file (C), Fmt, Arg1, Arg2);             \
+         putc ('\n', m4_get_debug_file (C));                           \
        }                                               } M4_STMT_END
 
-extern void m4_debug_init (void);
-extern void m4_debug_exit (void);
-extern int m4_debug_decode (const char *);
-extern void m4_debug_flush_files (void);
-extern boolean m4_debug_set_output (const char *);
+#define m4_is_debug_bit(C,B)   (BIT_TEST (m4_get_debug_level_opt (C), (B)))
+
+extern int m4_debug_decode (m4 *context, const char *);
+extern void m4_debug_flush_files (m4 *context);
+extern boolean m4_debug_set_output (m4 *context, const char *);
 extern void m4_debug_message_prefix (m4 *context);
 
-extern void m4_trace_prepre (m4 *context, const char *, int);
-extern void m4_trace_pre (m4 *context, const char *, int, int,
-                         m4_symbol_value **);
-extern void m4_trace_post (m4 *context, const char *, int, int,
-                          m4_symbol_value **, const char *);
 
 /* Exit code from last "syscmd" command.  */
 extern int m4_sysval;
Index: m4/m4private.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4private.h,v
retrieving revision 1.28
diff -u -p -u -r1.28 m4private.h
--- m4/m4private.h 15 Jul 2003 09:24:54 -0000 1.28
+++ m4/m4private.h 23 Jul 2003 11:50:53 -0000
@@ -45,6 +45,9 @@ struct m4 {
   m4_symbol_table *symtab;
   m4_syntax_table *syntax;
 
+  FILE *        debug_file;            /* File for debugging output.  */
+  struct obstack trace_messages;
+
   /* Option flags  (set in src/main.c).  */
   int          warning_status;                 /* -E */
   boolean      no_gnu_extensions;              /* -G */
@@ -64,6 +67,8 @@ struct m4 {
 #ifdef NDEBUG
 #  define m4_get_symbol_table(C)               ((C)->symtab)
 #  define m4_get_syntax_table(C)               ((C)->syntax)
+#  define m4_get_debug_file(C)                 ((C)->debug_file)
+#  define m4_get_trace_messages(C)             ((C)->trace_messages)
 #  define m4_get_warning_status_opt(C)         ((C)->warning_status)
 #  define m4_get_no_gnu_extensions_opt(C)      ((C)->no_gnu_extensions)
 #  define m4_get_nesting_limit_opt(C)          ((C)->nesting_limit)
Index: m4/macro.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/macro.c,v
retrieving revision 1.34
diff -u -p -u -r1.34 macro.c
--- m4/macro.c 17 Jul 2003 19:57:06 -0000 1.34
+++ m4/macro.c 23 Jul 2003 11:50:53 -0000
@@ -21,6 +21,8 @@
 /* This file contains the functions that perform the basic argument
    parsing and macro expansion.  */
 
+#include <stdarg.h>
+
 #include "m4.h"
 #include "m4private.h"
 
@@ -34,6 +36,17 @@ static void    expand_token      (m4 *co
 static boolean expand_argument   (m4 *context, struct obstack *obs,
                                  m4_symbol_value *argp);
 
+static void    trace_prepre     (m4 *context, const char *, int);
+static void    trace_pre        (m4 *context, const char *, int, int,
+                                 m4_symbol_value **);
+static void    trace_post       (m4 *context, const char *, int, int,
+                                 m4_symbol_value **, const char *);
+static void    trace_format     (m4 *, const char *, ...)
+                                                       M4_GNUC_PRINTF(2, 3);
+static void    trace_header     (m4 *, int);
+static void    trace_flush      (m4 *);
+
+
 /* Current recursion level in expand_macro ().  */
 int m4_expansion_level = 0;
 
@@ -218,16 +231,14 @@ ERROR: Recursion limit of %d exceeded, u
   macro_call_id++;
   my_call_id = macro_call_id;
 
-  traced = (boolean) ((BIT_TEST (m4_get_debug_level_opt (context),
-                                M4_DEBUG_TRACE_ALL))
+  traced = (boolean) (m4_is_debug_bit (context, M4_DEBUG_TRACE_ALL)
                      || m4_get_symbol_traced (symbol));
 
   obstack_init (&argptr);
   obstack_init (&arguments);
 
-  if (traced && (BIT_TEST (m4_get_debug_level_opt (context),
-                          M4_DEBUG_TRACE_CALL)))
-    m4_trace_prepre (context, name, my_call_id);
+  if (traced && m4_is_debug_bit (context, M4_DEBUG_TRACE_CALL))
+    trace_prepre (context, name, my_call_id);
 
   collect_arguments (context, name, symbol, &argptr, &arguments);
 
@@ -235,7 +246,7 @@ ERROR: Recursion limit of %d exceeded, u
   argv = (m4_symbol_value **) obstack_finish (&argptr);
 
   if (traced)
-    m4_trace_pre (context, name, my_call_id, argc, argv);
+    trace_pre (context, name, my_call_id, argc, argv);
 
   expansion = m4_push_string_init (context);
   if (!m4_bad_argc (context, argc, argv,
@@ -244,7 +255,7 @@ ERROR: Recursion limit of %d exceeded, u
   expanded = m4_push_string_finish ();
 
   if (traced)
-    m4_trace_post (context, name, my_call_id, argc, argv, expanded);
+    trace_post (context, name, my_call_id, argc, argv, expanded);
 
   --m4_expansion_level;
 
@@ -420,4 +431,194 @@ INTERNAL ERROR: %s: out of range referen
          break;
        }
     }
+}
+
+
+
+/* The rest of this file contains the functions for macro tracing output.
+   All tracing output for a macro call is collected on an obstack TRACE,
+   and printed whenever the line is complete.  This prevents tracing
+   output from interfering with other debug messages generated by the
+   various builtins.  */
+
+/* Tracing output is formatted here, by a simplified printf-to-obstack
+  function trace_format ().  Understands only %S, %s, %d, %l (optional
+  left quote) and %r (optional right quote).  */
+static void
+trace_format (m4 *context, const char *fmt, ...)
+{
+  va_list args;
+  char ch;
+
+  int d;
+  char nbuf[32];
+  const char *s;
+  int slen;
+  int maxlen;
+
+  va_start (args, fmt);
+
+  while (TRUE)
+    {
+      while ((ch = *fmt++) != '\0' && ch != '%')
+       obstack_1grow (&context->trace_messages, ch);
+
+      if (ch == '\0')
+       break;
+
+      maxlen = 0;
+      switch (*fmt++)
+       {
+       case 'S':
+         maxlen = m4_get_max_debug_arg_length_opt (context);
+         /* fall through */
+
+       case 's':
+         s = va_arg (args, const char *);
+         break;
+
+       case 'l':
+         s = m4_is_debug_bit (context, M4_DEBUG_TRACE_QUOTE)
+               ? m4_get_syntax_lquote (M4SYNTAX)
+               : "";
+         break;
+
+       case 'r':
+         s = m4_is_debug_bit(context, M4_DEBUG_TRACE_QUOTE)
+               ? m4_get_syntax_rquote (M4SYNTAX)
+               : "";
+         break;
+
+       case 'd':
+         d = va_arg (args, int);
+         sprintf (nbuf, "%d", d);
+         s = nbuf;
+         break;
+
+       default:
+         s = "";
+         break;
+       }
+
+      slen = strlen (s);
+      if (maxlen == 0 || maxlen > slen)
+       obstack_grow (&context->trace_messages, s, slen);
+      else
+       {
+         obstack_grow (&context->trace_messages, s, maxlen);
+         obstack_grow (&context->trace_messages, "...", 3);
+       }
+    }
+
+  va_end (args);
+}
+
+/* Format the standard header attached to all tracing output lines.  */
+static void
+trace_header (m4 *context, int id)
+{
+  trace_format (context, "m4trace:");
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_FILE))
+    trace_format (context, "%s:", m4_current_file);
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_LINE))
+    trace_format (context, "%d:", m4_current_line);
+  trace_format (context, " -%d- ", m4_expansion_level);
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_CALLID))
+    trace_format (context, "id %d: ", id);
+}
+
+/* Print current tracing line, and clear the obstack.  */
+static void
+trace_flush (m4 *context)
+{
+  char *line;
+
+  obstack_1grow (&context->trace_messages, '\0');
+  line = obstack_finish (&context->trace_messages);
+  M4_DEBUG_PRINT1 (context, "%s\n", line);
+  obstack_free (&context->trace_messages, line);
+}
+
+/* Do pre-argument-collction tracing for macro NAME.  Used from
+   expand_macro ().  */
+static void
+trace_prepre (m4 *context, const char *name, int id)
+{
+  trace_header (context, id);
+  trace_format (context, "%s ...", name);
+  trace_flush  (context);
+}
+
+/* Format the parts of a trace line, that can be made before the macro is
+   actually expanded.  Used from expand_macro ().  */
+static void
+trace_pre (m4 *context, const char *name, int id,
+          int argc, m4_symbol_value **argv)
+{
+  int i;
+  const m4_builtin *bp;
+
+  trace_header (context, id);
+  trace_format (context, "%s", name);
+
+  if ((argc > 1) && m4_is_debug_bit (context, M4_DEBUG_TRACE_ARGS))
+    {
+      trace_format (context, "(");
+
+      for (i = 1; i < argc; i++)
+       {
+         if (i != 1)
+           trace_format (context, ", ");
+
+         if (m4_is_symbol_value_text (argv[i]))
+           {
+             trace_format (context, "%l%S%r", M4ARG (i));
+           }
+         else if (m4_is_symbol_value_func (argv[i]))
+           {
+             bp = m4_builtin_find_by_func (NULL,
+                                           m4_get_symbol_value_func(argv[i]));
+             if (bp == NULL)
+               {
+                 M4ERROR ((m4_get_warning_status_opt (context), 0, "\
+INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())"));
+                 abort ();
+               }
+             trace_format (context, "<%s>", bp->name);
+           }
+         else
+           {
+             M4ERROR ((m4_get_warning_status_opt (context), 0,
+                       "INTERNAL ERROR: Bad token data type (trace_pre ())"));
+             abort ();
+           }
+       }
+      trace_format (context, ")");
+    }
+
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_CALL))
+    {
+      trace_format (context, " -> ???");
+      trace_flush  (context);
+    }
+}
+
+/* Format the final part of a trace line and print it all.  Used from
+   expand_macro ().  */
+static void
+trace_post (m4 *context, const char *name, int id,
+           int argc, m4_symbol_value **argv, const char *expanded)
+{
+  if (m4_is_debug_bit (context, M4_DEBUG_TRACE_CALL))
+    {
+      trace_header (context, id);
+      trace_format (context, "%s%s", name, (argc > 1) ? "(...)" : "");
+    }
+
+  if (expanded && m4_is_debug_bit (context, M4_DEBUG_TRACE_EXPANSION))
+    {
+      trace_format (context, " -> %l%S%r", expanded);
+    }
+
+  trace_flush (context);
 }
Index: modules/gnu.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/gnu.c,v
retrieving revision 1.24
diff -u -p -u -r1.24 gnu.c
--- modules/gnu.c 26 Jun 2003 14:57:32 -0000 1.24
+++ modules/gnu.c 23 Jul 2003 11:50:53 -0000
@@ -216,12 +216,12 @@ M4BUILTIN_HANDLER (debugmode)
       if (M4ARG (1)[0] == '+' || M4ARG (1)[0] == '-')
        {
          change_flag = M4ARG (1)[0];
-         new_debug_level = m4_debug_decode (M4ARG (1) + 1);
+         new_debug_level = m4_debug_decode (context, M4ARG (1) + 1);
        }
       else
        {
          change_flag = 0;
-         new_debug_level = m4_debug_decode (M4ARG (1));
+         new_debug_level = m4_debug_decode (context, M4ARG (1));
        }
 
       if (new_debug_level < 0)
@@ -256,8 +256,8 @@ M4BUILTIN_HANDLER (debugmode)
 M4BUILTIN_HANDLER (debugfile)
 {
   if (argc == 1)
-    m4_debug_set_output (NULL);
-  else if (!m4_debug_set_output (M4ARG (1)))
+    m4_debug_set_output (context, NULL);
+  else if (!m4_debug_set_output (context, M4ARG (1)))
     M4ERROR ((m4_get_warning_status_opt (context), errno,
              _("Cannot set error file: %s"), M4ARG (1)));
 }
@@ -509,7 +509,7 @@ M4BUILTIN_HANDLER (esyscmd)
   FILE *pin;
   int ch;
 
-  m4_debug_flush_files ();
+  m4_debug_flush_files (context);
   pin = popen (M4ARG (1), "r");
   if (pin == NULL)
     {
Index: modules/m4.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/m4.c,v
retrieving revision 1.46
diff -u -p -u -r1.46 m4.c
--- modules/m4.c 9 Jul 2003 12:32:41 -0000 1.46
+++ modules/m4.c 23 Jul 2003 11:50:53 -0000
@@ -339,7 +339,7 @@ M4BUILTIN_HANDLER (defn)
    and "sysval".  */
 M4BUILTIN_HANDLER (syscmd)
 {
-  m4_debug_flush_files ();
+  m4_debug_flush_files (context);
   m4_sysval = system (M4ARG (1));
 }
 
Index: src/main.c
===================================================================
RCS file: /cvsroot/m4/m4/src/main.c,v
retrieving revision 1.44
diff -u -p -u -r1.44 main.c
--- src/main.c 9 Jul 2003 12:32:41 -0000 1.44
+++ src/main.c 23 Jul 2003 11:50:53 -0000
@@ -230,7 +230,6 @@ main (int argc, char *const *argv, char 
   context = m4_create ();
 
   m4__module_init (context);
-  m4_debug_init ();
   m4_include_init ();
 
 #ifdef USE_STACKOVF
@@ -339,7 +338,7 @@ main (int argc, char *const *argv, char 
        break;
 
       case 'd':
-       m4_set_debug_level_opt (context, m4_debug_decode (optarg));
+       m4_set_debug_level_opt (context, m4_debug_decode (context, optarg));
        if (m4_get_debug_level_opt (context) < 0)
          {
            error (0, 0, _("Bad debug flags: `%s'"), optarg);
@@ -358,7 +357,7 @@ main (int argc, char *const *argv, char 
        break;
 
       case 'o':
-       if (!m4_debug_set_output (optarg))
+       if (!m4_debug_set_output (context, optarg))
          error (0, errno, "%s", optarg);
        break;
 
@@ -543,7 +542,6 @@ warranty; not even for MERCHANTABILITY o
   m4__module_exit (context);
   m4_output_exit ();
   m4_input_exit ();
-  m4_debug_exit ();
 
   m4_delete (context);
 

reply via email to

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