[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] Line synchronisation output in comments
From: |
Eric Blake |
Subject: |
Re: [PATCH] Line synchronisation output in comments |
Date: |
Mon, 28 May 2007 15:47:06 -0600 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.10) Gecko/20070221 Thunderbird/1.5.0.10 Mnenhy/0.7.5.666 |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
According to Eric Blake on 5/25/2007 11:26 AM:
> Meanwhile, I have to port it to HEAD. And I would also like to fix the bug
> that I uncovered in the interactions between -s and divert (but probably only
> on head, as I think it will be pretty invasive for a stable branch). For an
> example of the bug, note that "#line 3" is not a preprocessor directive any
> more.
Here's the port to head; I'm still playing with improving the quality of
head's syncline reporting, but wanted to get this synced up first (yes
Gary, I'm trying to do better at keeping the branches synchronized in a
timely manner :).
2007-05-28 Eric Blake <address@hidden>
Fix sync line interaction with multiline comments.
* doc/m4.texinfo (Preprocessor features): Improve documentation.
(Syncoutput): Improve testsuite.
(Incompatibilities): Add testcase, and document bug.
* src/freeze.c (reload_frozen_state): Don't interfere with
synclines when reloading state.
* m4/input.c (m4__next_token): Report line where multiline tokens
start.
* m4/m4private.h (m4__token_type): Add parameter.
* m4/m4module.h (m4_output_text): Export.
(m4_shipout_text): Add parameter.
* src/macro.c (m4_macro_expand_input, expand_token)
(expand_argument): Adjust callers so that line is passed from
input to output.
* m4/output.c (output_text): Rename...
(m4_output_text): ...to this, and export.
(m4_insert_file, insert_diversion_helper): Update callers.
(m4_shipout_text): Take new parameter for start line of token.
Output at most one syncline per token.
Reported by Sergey Poznyakoff.
- --
Don't work too hard, make some time for fun as well!
Eric Blake address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD4DBQFGW03Z84KuGfSFAYARAv2wAJjZEoCZBNV6rVI+ZNU4MbIp5Nr9AJwLeHGl
sDrHB89+BiijT8R8CfSHCw==
=uRIA
-----END PGP SIGNATURE-----
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.103
diff -u -p -r1.103 m4.texinfo
--- doc/m4.texinfo 25 Apr 2007 14:16:21 -0000 1.103
+++ doc/m4.texinfo 28 May 2007 21:30:30 -0000
@@ -737,7 +737,7 @@ input came from. These features occur w
Make @code{m4} search @var{DIRECTORY} for included files, prior to
searching the current working directory. @xref{Search Path}, for more
details. This option may be given more than once. Some other
-implementations of @code{m4} use @code{-B @var{number}} to change their
+implementations of @code{m4} use @option{-B @var{number}} to change their
hard-coded limits, but that is unnecessary in @acronym{GNU} where the
only limit is your hardware capability. So although it is unlikely that
you will want to include a relative directory whose name is purely
@@ -805,10 +805,11 @@ the file name did not change from the pr
Synchronization directives are always given on complete lines by
themselves. When a synchronization discrepancy occurs in the middle of
an output line, the associated synchronization directive is delayed
-until the beginning of the next generated line. @xref{Syncoutput}, for
-runtime control. @var{TRUTH} is interpreted the same as the argument to
address@hidden; if @var{TRUTH} is omitted, or @option{--syncoutput}
-is not used, synchronization lines are disabled.
+until the next newline that does not occur in the middle of a quoted
+string or comment. @xref{Syncoutput}, for runtime control. @var{TRUTH}
+is interpreted the same as the argument to @code{syncoutput}; if
address@hidden is omitted, or @option{--syncoutput} is not used,
+synchronization lines are disabled.
@item -U @var{NAME}
@itemx address@hidden
@@ -3316,7 +3317,7 @@ f(popdef(`f')dumpdef(`f'))
@samp{s} flags affect the details of the display. Remember, the
@samp{q} flag is implied when the @option{--debug} option (@option{-d},
@pxref{Debugging options, , Invoking m4}) is used in the command line
-without arguments. Also, @code{--debuglen} (@pxref{Debuglen}) can affect
+without arguments. Also, @option{--debuglen} (@pxref{Debuglen}) can affect
output, by truncating longer strings.
@comment options: -ds -l3
@@ -3443,7 +3444,7 @@ foo
@result{}blah
@end example
-Tracing even works on builtins. However, @command{defn} (@pxref{Defn})
+Tracing even works on builtins. However, @code{defn} (@pxref{Defn})
does not transfer tracing status.
@example
@@ -4258,7 +4259,7 @@ the default flavor is reverted to the @c
with emacs.
@var{resyntax} can be any one of the values in the table below. Case is
-not important, and @kbd{-} or @kbd{ } can be substituted for @kbd{_} in
+not important, and @samp{-} or @samp{ } can be substituted for @samp{_} in
the given names. If @var{resyntax} is unrecognized, a warning is
issued and the default flavor is not changed.
@@ -7158,7 +7159,7 @@ It is possible to adjust whether synclin
@deffn {Builtin (gnu)} syncoutput (@var{truth})
If @var{truth} matches the extended regular expression
@samp{^[1yY]|^([oO][nN])}, it causes @code{m4} to emit sync lines of the
-form: @code{#line <number> ["<file>"]}.
+form: @samp{#line <number> ["<file>"]}.
If @var{truth} is empty, or matches the extended regular expression
@samp{^[0nN]|^([oO][fF])}, it causes @code{m4} to turn sync lines off.
@@ -7173,21 +7174,38 @@ This macro was added in M4 2.0.
define(`twoline', `1
2')
@result{}
+changecom(`/*', `*/')
address@hidden
+define(`comment', `/*1
+2*/')
address@hidden
twoline
@result{}1
@result{}2
dnl no line
syncoutput(`on')
address@hidden 5 "stdin"
address@hidden 8 "stdin"
@result{}
twoline
@result{}1
address@hidden 6
address@hidden 9
@result{}2
dnl no line
hello
address@hidden 8
address@hidden 11
@result{}hello
+comment
address@hidden/*1
address@hidden/
+one comment `two
+three'
address@hidden 13
address@hidden /*1
address@hidden/ two
address@hidden
+goodbye
address@hidden 15
address@hidden
syncoutput(`off')
@result{}
twoline
@@ -7281,14 +7299,14 @@ $ @kbd{m4 -R base.m4f input3.m4}
@end example
@noindent
-with the varying input. The first call, containing the @code{-F}
+with the varying input. The first call, containing the @option{-F}
option, only reads and executes file @file{base.m4}, defining
various application macros and computing other initializations.
Once the input file @file{base.m4} has been completely processed, @acronym{GNU}
@code{m4} produces in @file{base.m4f} a @dfn{frozen} file, that is, a
file which contains a kind of snapshot of the @code{m4} internal state.
-Later calls, containing the @code{-R} option, are able to reload
+Later calls, containing the @option{-R} option, are able to reload
the internal state of @code{m4}, from @file{base.m4f},
@emph{prior} to reading any other input files. This means
instead of starting with a virgin copy of @code{m4}, input will be
@@ -7299,7 +7317,7 @@ been read anew. However, this effect is
Only one frozen file may be created or read in any one @code{m4}
invocation. It is not possible to recover two frozen files at once.
However, frozen files may be updated incrementally, through using
address@hidden and @code{-F} options simultaneously. For example, if
address@hidden and @option{-F} options simultaneously. For example, if
some care is taken, the command:
@comment ignore
@@ -7365,7 +7383,7 @@ second machine uses the same, or a newer
These are simple (editable) text files, made up of directives,
each starting with a capital letter and ending with a newline
(@key{NL}). Wherever a directive is expected, the character
address@hidden introduces a comment line, empty lines are also ignored.
address@hidden introduces a comment line, empty lines are also ignored.
In the following descriptions, @var{length}s always refer to
corresponding @var{string}s. Numbers are always expressed in decimal.
The directives are:
@@ -7394,7 +7412,7 @@ Names a module which will be searched fo
and loaded. Modules loaded from a frozen file don't add their builtin entries
to the symbol table.
address@hidden F @var{length} @key{NL} @var{string} @key{ML}
address@hidden F @var{length} @key{NL} @var{string} @key{NL}
Defines, through @code{pushdef}, a definition for @var{string}
expanding to the function whose builtin name is also @var{string}. The builtin
name is searched for among the intrinsic builtin functions only.
@@ -7455,7 +7473,7 @@ is made to summarize these here.
@cindex @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
+using the @option{-G} command line option, unless overridden by other
command line options.
Most of these extensions are compatible with
@uref{http://www.unix.org/single_unix_specification/,
@@ -7474,7 +7492,7 @@ not only nine (@pxref{Arguments}).
@item
Files included with @code{include} and @code{sinclude} are sought in a
user specified search path, if they are not found in the working
-directory. The search path is specified by the @samp{-I} option and the
+directory. The search path is specified by the @option{-I} option and the
@samp{M4PATH} environment variable (@pxref{Search Path}).
@item
@@ -7538,7 +7556,7 @@ the first place.
@end itemize
Additionally, @acronym{POSIX} only requires support for the command line
-options @samp{-s}, @samp{-D}, and @samp{-U}, so all other options
+options @option{-s}, @option{-D}, and @option{-U}, so all other options
accepted by @acronym{GNU} M4 are extensions. @xref{Invoking m4},
for a description of these options.
@@ -7564,10 +7582,33 @@ diverted text as being generated by the
@code{undivert} call, whereas GNU @code{m4} regards the diverted text as
being generated at the time it is diverted.
-I expect the sync line option to be used mostly when using @code{m4} as
+The sync line option is used mostly when using @code{m4} as
a front end to a compiler. If a diverted line causes a compiler error,
the error messages should most probably refer to the place where the
-diversion were made, and not where it was inserted again.
+diversion was made, and not where it was inserted again.
+
address@hidden options: -s
address@hidden
+divert(2)2
+divert(1)1
+divert`'0
address@hidden 3 "stdin"
address@hidden
+^D
address@hidden 2 "stdin"
address@hidden
address@hidden 1 "stdin"
address@hidden
address@hidden example
+
address@hidden FIXME - this needs to be fixed before 2.0.
+The current @code{m4} implementation has a limitation that the syncline
+output at the start of each diversion occurs no matter what, even if the
+previous diversion did not end with a newline. This goes contrary to
+the claim that synclines appear on a line by themselves, so this
+limitation may be corrected in a future version of @code{m4}. In the
+meantime, when using @option{-s}, it is wisest to make sure all
+diversions end with newline.
@item
GNU @code{m4} makes no attempt at prohibiting self-referential definitions
Index: m4/input.c
===================================================================
RCS file: /sources/m4/m4/m4/input.c,v
retrieving revision 1.65
diff -u -p -r1.65 input.c
--- m4/input.c 8 Apr 2007 05:06:42 -0000 1.65
+++ m4/input.c 28 May 2007 21:30:30 -0000
@@ -987,10 +987,11 @@ m4_input_exit (void)
/* Parse and return a single token from the input stream. A token can
- either be M4_TOKEN_EOF, if the input_stack is empty; it can be
- M4_TOKEN_STRING for a quoted string; M4_TOKEN_WORD for something that
- is a potential macro name; and M4_TOKEN_SIMPLE for any single character
- that is not a part of any of the previous types.
+ be M4_TOKEN_EOF, if the input_stack is empty; it can be
+ M4_TOKEN_STRING for a quoted string; M4_TOKEN_WORD for something
+ that is a potential macro name; and M4_TOKEN_SIMPLE for any single
+ character that is not a part of any of the previous types. If LINE
+ is not NULL, set *LINE to the line number where the token starts.
M4__next_token () returns the token type, and passes back a pointer to
the token data through TOKEN. The token text is collected on the obstack
@@ -998,15 +999,17 @@ m4_input_exit (void)
The storage pointed to by the fields in TOKEN is therefore subject to
change the next time m4__next_token () is called. */
m4__token_type
-m4__next_token (m4 *context, m4_symbol_value *token)
+m4__next_token (m4 *context, m4_symbol_value *token, int *line)
{
int ch;
int quote_level;
m4__token_type type;
const char *file;
- int line;
+ int dummy;
assert (next == NULL);
+ if (!line)
+ line = &dummy;
do {
obstack_free (&token_stack, token_bottom);
@@ -1034,7 +1037,7 @@ m4__next_token (m4 *context, m4_symbol_v
next_char (context, true); /* Consume character we already peeked at. */
file = m4_get_current_file (context);
- line = m4_get_current_line (context);
+ *line = m4_get_current_line (context);
if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_ESCAPE))
{ /* ESCAPED WORD */
@@ -1065,7 +1068,7 @@ m4__next_token (m4 *context, m4_symbol_v
{
ch = next_char (context, true);
if (ch == CHAR_EOF)
- m4_error_at_line (context, EXIT_FAILURE, 0, file, line,
+ m4_error_at_line (context, EXIT_FAILURE, 0, file, *line,
_("end of file in string"));
if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_RQUOTE))
@@ -1092,7 +1095,7 @@ m4__next_token (m4 *context, m4_symbol_v
{
ch = next_char (context, true);
if (ch == CHAR_EOF)
- m4_error_at_line (context, EXIT_FAILURE, 0, file, line,
+ m4_error_at_line (context, EXIT_FAILURE, 0, file, *line,
_("end of file in string"));
if (MATCH (context, ch, context->syntax->rquote.string, true))
{
@@ -1121,7 +1124,7 @@ m4__next_token (m4 *context, m4_symbol_v
if (ch != CHAR_EOF)
obstack_1grow (&token_stack, ch);
else
- m4_error_at_line (context, EXIT_FAILURE, 0, file, line,
+ m4_error_at_line (context, EXIT_FAILURE, 0, file, *line,
_("end of file in comment"));
type = (m4_get_discard_comments_opt (context)
? M4_TOKEN_NONE : M4_TOKEN_STRING);
@@ -1138,7 +1141,7 @@ m4__next_token (m4 *context, m4_symbol_v
obstack_grow (&token_stack, context->syntax->ecomm.string,
context->syntax->ecomm.length);
else
- m4_error_at_line (context, EXIT_FAILURE, 0, file, line,
+ m4_error_at_line (context, EXIT_FAILURE, 0, file, *line,
_("end of file in comment"));
type = (m4_get_discard_comments_opt (context)
? M4_TOKEN_NONE : M4_TOKEN_STRING);
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.107
diff -u -p -r1.107 m4module.h
--- m4/m4module.h 2 Apr 2007 12:06:23 -0000 1.107
+++ m4/m4module.h 28 May 2007 21:30:30 -0000
@@ -418,7 +418,9 @@ extern void m4_input_print (m4 *, m4_obs
extern void m4_output_init (m4 *);
extern void m4_output_exit (void);
-extern void m4_shipout_text (m4 *, m4_obstack *, const char *, size_t);
+extern void m4_output_text (m4 *, const char *, size_t);
+extern void m4_shipout_text (m4 *, m4_obstack *, const char *, size_t,
+ int);
extern void m4_shipout_int (m4_obstack *, int);
extern void m4_shipout_string (m4 *, m4_obstack *, const char *,
size_t, bool);
Index: m4/m4private.h
===================================================================
RCS file: /sources/m4/m4/m4/m4private.h,v
retrieving revision 1.79
diff -u -p -r1.79 m4private.h
--- m4/m4private.h 8 Apr 2007 05:06:42 -0000 1.79
+++ m4/m4private.h 28 May 2007 21:30:30 -0000
@@ -326,7 +326,7 @@ typedef enum {
M4_TOKEN_MACDEF /* a macro's definition (see "defn") */
} m4__token_type;
-extern m4__token_type m4__next_token (m4 *, m4_symbol_value *);
+extern m4__token_type m4__next_token (m4 *, m4_symbol_value *, int *);
extern bool m4__next_token_is_open (m4 *);
Index: m4/macro.c
===================================================================
RCS file: /sources/m4/m4/m4/macro.c,v
retrieving revision 1.67
diff -u -p -r1.67 macro.c
--- m4/macro.c 8 Apr 2007 05:06:42 -0000 1.67
+++ m4/macro.c 28 May 2007 21:30:30 -0000
@@ -33,7 +33,7 @@ static void collect_arguments (m4 *,
m4_obstack *, m4_obstack *);
static void expand_macro (m4 *, const char *, m4_symbol *);
static void expand_token (m4 *, m4_obstack *, m4__token_type,
- m4_symbol_value *);
+ m4_symbol_value *, int);
static bool expand_argument (m4 *, m4_obstack *, m4_symbol_value *);
static void process_macro (m4 *, m4_symbol_value *, m4_obstack *, int,
m4_symbol_value **);
@@ -76,12 +76,13 @@ m4_macro_expand_input (m4 *context)
{
m4__token_type type;
m4_symbol_value token;
+ int line;
obstack_init (&argc_stack);
obstack_init (&argv_stack);
- while ((type = m4__next_token (context, &token)) != M4_TOKEN_EOF)
- expand_token (context, (m4_obstack *) NULL, type, &token);
+ while ((type = m4__next_token (context, &token, &line)) != M4_TOKEN_EOF)
+ expand_token (context, (m4_obstack *) NULL, type, &token, line);
obstack_free (&argc_stack, NULL);
obstack_free (&argv_stack, NULL);
@@ -94,7 +95,7 @@ m4_macro_expand_input (m4 *context)
the text are just copied to the output. */
static void
expand_token (m4 *context, m4_obstack *obs,
- m4__token_type type, m4_symbol_value *token)
+ m4__token_type type, m4_symbol_value *token, int line)
{
m4_symbol *symbol;
const char *text = (m4_is_symbol_value_text (token)
@@ -112,7 +113,7 @@ expand_token (m4 *context, m4_obstack *o
case M4_TOKEN_SIMPLE:
case M4_TOKEN_STRING:
case M4_TOKEN_SPACE:
- m4_shipout_text (context, obs, text, strlen (text));
+ m4_shipout_text (context, obs, text, strlen (text), line);
break;
case M4_TOKEN_WORD:
@@ -129,7 +130,7 @@ expand_token (m4 *context, m4_obstack *o
&& BIT_TEST (SYMBOL_FLAGS (symbol), VALUE_BLIND_ARGS_BIT)
&& ! m4__next_token_is_open (context)))
{
- m4_shipout_text (context, obs, text, strlen (text));
+ m4_shipout_text (context, obs, text, strlen (text), line);
}
else
expand_macro (context, textp, symbol);
@@ -165,7 +166,7 @@ expand_argument (m4 *context, m4_obstack
/* Skip leading white space. */
do
{
- type = m4__next_token (context, &token);
+ type = m4__next_token (context, &token, NULL);
}
while (type == M4_TOKEN_SPACE);
@@ -196,7 +197,7 @@ expand_argument (m4 *context, m4_obstack
paren_level++;
else if (type == M4_TOKEN_CLOSE)
paren_level--;
- expand_token (context, obs, type, &token);
+ expand_token (context, obs, type, &token, line);
break;
case M4_TOKEN_EOF:
@@ -207,7 +208,7 @@ expand_argument (m4 *context, m4_obstack
case M4_TOKEN_WORD:
case M4_TOKEN_SPACE:
case M4_TOKEN_STRING:
- expand_token (context, obs, type, &token);
+ expand_token (context, obs, type, &token, line);
break;
case M4_TOKEN_MACDEF:
@@ -220,7 +221,7 @@ expand_argument (m4 *context, m4_obstack
abort ();
}
- type = m4__next_token (context, &token);
+ type = m4__next_token (context, &token, NULL);
}
}
@@ -353,7 +354,7 @@ collect_arguments (m4 *context, const ch
if (m4__next_token_is_open (context))
{
- m4__next_token (context, &token); /* gobble parenthesis */
+ m4__next_token (context, &token, NULL); /* gobble parenthesis */
do
{
more_args = expand_argument (context, arguments, &token);
Index: m4/output.c
===================================================================
RCS file: /sources/m4/m4/m4/output.c,v
retrieving revision 1.43
diff -u -p -r1.43 output.c
--- m4/output.c 28 May 2007 20:10:01 -0000 1.43
+++ m4/output.c 28 May 2007 21:30:30 -0000
@@ -418,8 +418,8 @@ output_character_helper (m4 *context, in
/* Output one TEXT having LENGTH characters, when it is known that it goes
to a diversion file or an in-memory diversion buffer. */
-static void
-output_text (m4 *context, const char *text, size_t length)
+void
+m4_output_text (m4 *context, const char *text, size_t length)
{
size_t count;
@@ -441,20 +441,23 @@ output_text (m4 *context, const char *te
}
/* Add some text into an obstack OBS, taken from TEXT, having LENGTH
- characters. If OBS is NULL, rather output the text to an external file
- or an in-memory diversion buffer. If OBS is NULL, and there is no
- output file, the text is discarded.
-
- If we are generating sync lines, the output have to be examined, because
- we need to know how much output each input line generates. In general,
- sync lines are output whenever a single input lines generates several
- output lines, or when several input lines does not generate any output. */
+ characters. If OBS is NULL, output the text to an external file or
+ an in-memory diversion buffer instead. If OBS is NULL, and there
+ is no output file, the text is discarded. LINE is the line where
+ the token starts (not necessarily m4_get_output_line, in the case
+ of multiline tokens).
+
+ If we are generating sync lines, the output has to be examined,
+ because we need to know how much output each input line generates.
+ In general, sync lines are output whenever a single input line
+ generates several output lines, or when several input lines do not
+ generate any output. */
void
m4_shipout_text (m4 *context, m4_obstack *obs,
- const char *text, size_t length)
+ const char *text, size_t length, int line)
{
static bool start_of_output_line = true;
- char line[20];
+ char linebuf[20];
const char *cursor;
/* If output goes to an obstack, merely add TEXT to it. */
@@ -492,52 +495,71 @@ m4_shipout_text (m4 *context, m4_obstack
/* Optimize longer texts. */
default:
- output_text (context, text, length);
+ m4_output_text (context, text, length);
}
else
- for (; length-- > 0; text++)
- {
- if (start_of_output_line)
- {
- start_of_output_line = false;
- m4_set_output_line (context, m4_get_output_line (context) + 1);
+ {
+ /* Check for syncline only at the start of a token. Multiline
+ tokens, and tokens that are out of sync but in the middle of
+ the line, must wait until the next raw newline triggers a
+ syncline. */
+ if (start_of_output_line)
+ {
+ start_of_output_line = false;
+ m4_set_output_line (context, m4_get_output_line (context) + 1);
#ifdef DEBUG_OUTPUT
- fprintf (stderr, "DEBUG: cur %lu, cur out %lu\n",
- (unsigned long int) m4_get_current_line (context),
- (unsigned long int) m4_get_output_line (context));
+ fprintf (stderr, "DEBUG: line %d, cur %lu, cur out %lu\n", line,
+ (unsigned long int) m4_get_current_line (context),
+ (unsigned long int) m4_get_output_line (context));
#endif
- /* Output a `#line NUM' synchronization directive if needed.
- If output_line was previously given a negative
- value (invalidated), then output `#line NUM "FILE"'. */
-
- if (m4_get_output_line (context) != m4_get_current_line (context))
- {
- sprintf (line, "#line %lu",
- (unsigned long int) m4_get_current_line (context));
- for (cursor = line; *cursor; cursor++)
- OUTPUT_CHARACTER (*cursor);
- if (m4_get_output_line (context) < 1
- && m4_get_current_file (context)[0] != '\0')
- {
- OUTPUT_CHARACTER (' ');
- OUTPUT_CHARACTER ('"');
- for (cursor = m4_get_current_file (context);
- *cursor; cursor++)
- {
- OUTPUT_CHARACTER (*cursor);
- }
- OUTPUT_CHARACTER ('"');
- }
- OUTPUT_CHARACTER ('\n');
- m4_set_output_line (context, m4_get_current_line (context));
- }
- }
- OUTPUT_CHARACTER (*text);
- if (*text == '\n')
- start_of_output_line = true;
- }
+ /* Output a `#line NUM' synchronization directive if needed.
+ If output_line was previously given a negative
+ value (invalidated), then output `#line NUM "FILE"'. */
+
+ if (m4_get_output_line (context) != line)
+ {
+ sprintf (linebuf, "#line %lu",
+ (unsigned long int) m4_get_current_line (context));
+ for (cursor = linebuf; *cursor; cursor++)
+ OUTPUT_CHARACTER (*cursor);
+ if (m4_get_output_line (context) < 1
+ && m4_get_current_file (context)[0] != '\0')
+ {
+ OUTPUT_CHARACTER (' ');
+ OUTPUT_CHARACTER ('"');
+ for (cursor = m4_get_current_file (context);
+ *cursor; cursor++)
+ {
+ OUTPUT_CHARACTER (*cursor);
+ }
+ OUTPUT_CHARACTER ('"');
+ }
+ OUTPUT_CHARACTER ('\n');
+ m4_set_output_line (context, line);
+ }
+ }
+
+ /* Output the token, and track embedded newlines. */
+ for (; length-- > 0; text++)
+ {
+ if (start_of_output_line)
+ {
+ start_of_output_line = false;
+ m4_set_output_line (context, m4_get_output_line (context) + 1);
+
+#ifdef DEBUG_OUTPUT
+ fprintf (stderr, "DEBUG: line %d, cur %lu, cur out %lu\n", line,
+ (unsigned long int) m4_get_current_line (context),
+ (unsigned long int) m4_get_output_line (context));
+#endif
+ }
+ OUTPUT_CHARACTER (*text);
+ if (*text == '\n')
+ start_of_output_line = true;
+ }
+ }
}
/* Format an int VAL, and stuff it into an obstack OBS. Used for
@@ -697,7 +719,7 @@ m4_insert_file (m4 *context, FILE *file)
m4_error (context, EXIT_FAILURE, errno, _("reading inserted file"));
if (length == 0)
break;
- output_text (context, buffer, length);
+ m4_output_text (context, buffer, length);
}
}
@@ -714,7 +736,7 @@ insert_diversion_helper (m4 *context, m4
if (output_diversion)
{
if (diversion->size)
- output_text (context, diversion->u.buffer, diversion->used);
+ m4_output_text (context, diversion->u.buffer, diversion->used);
else
{
assert (diversion->used);
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.65
diff -u -p -r1.65 freeze.c
--- src/freeze.c 8 Apr 2007 05:06:42 -0000 1.65
+++ src/freeze.c 28 May 2007 21:30:30 -0000
@@ -691,7 +691,7 @@ ill-formed frozen file, version 2 direct
m4_make_diversion (context, number[0]);
if (number[1] > 0)
- m4_shipout_text (context, NULL, string[1], number[1]);
+ m4_output_text (context, string[1], number[1]);
break;
case 'Q':