m4-patches
[Top][All Lists]
Advanced

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

[PATCH] Improve compatibility between M4 and CPP.


From: Raphael 'kena' Poss
Subject: [PATCH] Improve compatibility between M4 and CPP.
Date: Wed, 8 Jul 2009 11:16:03 +0200

* src/m4.c: Add new option `--synclines-cpp'.
* src/output.c: Change syncline format when --synclines-cpp is set.

* src/input.c: Allow to change input line number and file name.
* src/m4.h: Expose new primitives from input.c.
* src/builtin.c: Use them in __file__ and __line__.

* doc/m4.texinfo: Document the new features.
* NEWS: Announce them.
---
Hi Eric,

as you suggested I reworked the patch from 1.6, and included documentation
with example and test code. Let me know if there is anything else to improve.

Cheers,
k

 NEWS           |    6 ++++++
 doc/m4.texinfo |   48 +++++++++++++++++++++++++++++++++++++++++++-----
 src/builtin.c  |   26 ++++++++++++++++++++------
 src/input.c    |   19 +++++++++++++++++++
 src/m4.c       |    8 ++++++++
 src/m4.h       |    5 +++++
 src/output.c   |    2 +-
 7 files changed, 102 insertions(+), 12 deletions(-)

diff --git a/NEWS b/NEWS
index f1d641a..72f0d50 100644
--- a/NEWS
+++ b/NEWS
@@ -147,6 +147,12 @@ contains the following beta features that were deemed 
worth deferring until
    algorithms based on `$@' operate in linear, rather than quadratic, time
    and memory.
 
+** Enhance the `__file__' and `__line__' builtins so that the input
+   line number and file name can be reset.
+
+** A new `--synclines-cpp' option changes the format of synchronization
+   lines to mimic the C preprocessor.
+
 ** A number of portability improvements inherited from gnulib.
 
 * Noteworthy changes in Version 1.4.13 (2009-04-01) [stable]
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 0182979..0a4305f 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -780,6 +780,15 @@
 @result{}goodbye
 @end example
 
address@hidden --synclines-cpp
+
+This provides identical behavior to @option{-s} or @option{--synclines},
+but with a different synchronization line format suitable for a C
+compiler without a C preprocessor. With this option synchronization
+lines are of the form @samp{# @var{line} "@var{file}"}. This format is
+suitable when M4 is used as a substitute to the C preprocessor or as a
+filter between preprocessing and compilation.
+
 @item -U @var{name}
 @itemx address@hidden
 This deletes any predefined meaning @var{name} might have.  Obviously,
@@ -7711,11 +7720,12 @@
 Line numbers start at 1 for each file.  If the file was found due to the
 @option{-I} option or @env{M4PATH} environment variable, that is
 reflected in the file name.  The syncline option (@option{-s},
address@hidden features, , Invoking m4}), and the
address@hidden and @samp{l} flags of @code{debugmode} (@pxref{Debugmode}),
-also use this notion of current file and line.  Redefining the three
-location macros has no effect on syncline, debug, warning, or error
-message output.
address@hidden features, , Invoking m4}), and the @samp{f} and
address@hidden flags of @code{debugmode} (@pxref{Debugmode}), also use this
+notion of current file and line.  Redefining the three location macros
+has no effect on syncline, debug, warning, or error message output,
+although the line numbers and file names can be reset as described
+below.
 
 This example reuses the file @file{incl.m4} mentioned earlier
 (@pxref{Include}):
@@ -7773,6 +7783,34 @@
 @result{}12
 @end example
 
+The @address@hidden and @address@hidden macros take an optional
+argument which allow to reset the current input file name and line
+number, respectively. If @option{-s} is enabled, a synchronization line
+will be emitted at the next newline in the input. Input line numbers
+will autoincrement from the new value, and the file name will stay
+active for the current input source until the input source is exhausted
+or the name is reset again. This feature can be used when the input to
+M4 already contains synchronization information, as when M4 is used as a
+filter between a preprocessor and a compiler.
+
address@hidden options: -s
address@hidden
+$ @kbd{m4 -s}
+foo __line__(42)bar __line__
+baz __line__
+__line__
address@hidden 1 "stdin"
address@hidden bar 42
address@hidden 43
address@hidden 43
address@hidden
+foo __file__(`newname')bar __file__
+baz __file__
address@hidden bar newname
address@hidden 46 "newname"
address@hidden newname
address@hidden example
+
 The @address@hidden macro behaves like @samp{$0} in shell
 terminology.  If you invoke @code{m4} through an absolute path or a link
 with a different spelling, rather than by relying on a @env{PATH} search
diff --git a/src/builtin.c b/src/builtin.c
index 191e05d..f9f35a6 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -1700,17 +1700,31 @@ m4_errprint (struct obstack *obs, int argc, 
macro_arguments *argv)
 static void
 m4___file__ (struct obstack *obs, int argc, macro_arguments *argv)
 {
-  bad_argc (arg_info (argv), argc, 0, 0);
-  obstack_grow (obs, curr_quote.str1, curr_quote.len1);
-  obstack_grow (obs, current_file, strlen (current_file));
-  obstack_grow (obs, curr_quote.str2, curr_quote.len2);
+  bad_argc (arg_info (argv), argc, 0, 1);
+  if (argc > 1)
+    reset_file (ARG (1));
+  else
+    {
+      obstack_grow (obs, curr_quote.str1, curr_quote.len1);
+      obstack_grow (obs, current_file, strlen (current_file));
+      obstack_grow (obs, curr_quote.str2, curr_quote.len2);
+    }
 }
 
 static void
 m4___line__ (struct obstack *obs, int argc, macro_arguments *argv)
 {
-  bad_argc (arg_info (argv), argc, 0, 0);
-  shipout_int (obs, current_line);
+  int line;
+
+  bad_argc (arg_info (argv), argc, 0, 1);
+  if (argc > 1)
+    {
+      if (!numeric_arg (arg_info (argv), ARG (1), ARG_LEN (1), &line))
+       return;
+      reset_line (line);
+    }
+  else
+    shipout_int (obs, current_line);
 }
 
 static void
diff --git a/src/input.c b/src/input.c
index 129a5f2..940f975 100644
--- a/src/input.c
+++ b/src/input.c
@@ -2301,3 +2301,22 @@ lex_debug (void)
     print_token ("lex", t, &td);
 }
 #endif /* DEBUG_INPUT */
+
+/*---------------------------------.
+ | Reset the current line counter. |
+ `--------------------------------*/
+void reset_line(int line)
+{
+  isp->line = line;
+  input_change = true;
+}
+
+/*-------------------------------.
+ | Reset the current file title. |
+ `------------------------------*/
+void reset_file(const char *title)
+{
+  isp->file = (char *) obstack_copy0 (&file_names, title, strlen (title));
+  output_current_line = -1;
+  input_change = true;
+}
diff --git a/src/m4.c b/src/m4.c
index 0caf868..9189298 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -237,6 +237,7 @@ Preprocessor features:\n\
   -D, --define=NAME[=VALUE]    define NAME as having VALUE, or empty\n\
   -I, --include=DIRECTORY      append DIRECTORY to include path\n\
   -s, --synclines              generate `#line NUM \"FILE\"' lines\n\
+      --synclines-cpp          generate `# NUM \"FILE\" lines\n\
   -U, --undefine=NAME          undefine NAME\n\
 "), stdout);
       puts ("");
@@ -307,6 +308,7 @@ enum
 {
   DEBUGFILE_OPTION = CHAR_MAX + 1,     /* no short opt */
   WARN_MACRO_SEQUENCE_OPTION,          /* no short opt */
+  SYNCLINES_CPP_OPTION,                        /* no short opt */
 
   HELP_OPTION,                         /* no short opt */
   VERSION_OPTION                       /* no short opt */
@@ -331,6 +333,7 @@ static const struct option long_options[] =
   {"reload-state", required_argument, NULL, 'R'},
   {"silent", no_argument, NULL, 'Q'},
   {"synclines", no_argument, NULL, 's'},
+  {"synclines-cpp", no_argument, NULL, SYNCLINES_CPP_OPTION},
   {"trace", required_argument, NULL, 't'},
   {"traditional", no_argument, NULL, 'G'},
   {"undefine", required_argument, NULL, 'U'},
@@ -463,6 +466,7 @@ main (int argc, char *const *argv, char *const *envp)
       case 's':
       case 't':
       case DEBUGFILE_OPTION:
+      case SYNCLINES_CPP_OPTION:
       defer:
        /* Arguments that cannot be handled until later are accumulated.  */
 
@@ -652,6 +656,10 @@ main (int argc, char *const *argv, char *const *envp)
          sync_output = 1;
          break;
 
+       case SYNCLINES_CPP_OPTION:
+         sync_output = 2;
+         break;
+
        case '\1':
          process_file (arg);
          break;
diff --git a/src/m4.h b/src/m4.h
index 17184b2..6ed671d 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -562,6 +562,11 @@ void expand_format (struct obstack *, int, macro_arguments 
*);
 void produce_frozen_state (const char *);
 void reload_frozen_state (const char *);
 
+/* File: input.c --- input sources.  */
+
+void reset_line (int);
+void reset_file (const char *);
+
 /* Debugging the memory allocator.  */
 
 #ifdef WITH_DMALLOC
diff --git a/src/output.c b/src/output.c
index e31f94b..0c09c5b 100644
--- a/src/output.c
+++ b/src/output.c
@@ -665,7 +665,7 @@ divert_text (struct obstack *obs, const char *text, int 
length, int line)
          if (output_current_line != line)
            {
              static char line_buf[sizeof "#line " + INT_BUFSIZE_BOUND (line)];
-             sprintf (line_buf, "#line %d", line);
+             sprintf (line_buf, (sync_output == 1) ? "#line %d" : "# %d", 
line);
              output_text (line_buf, strlen (line_buf));
              assert (strlen (line_buf) < sizeof line_buf);
              if (output_current_line < 1 && current_file[0] != '\0')
-- 
1.6.3.2





reply via email to

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