[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: branch-1_4 and frozen files
From: |
Eric Blake |
Subject: |
Re: branch-1_4 and frozen files |
Date: |
Fri, 23 Jun 2006 07:19:48 -0600 |
User-agent: |
Thunderbird 1.5.0.4 (Windows/20060516) |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
According to Gary V. Vaughan on 6/23/2006 4:43 AM:
>>
>> * src/builtin.c: Unify error message style.
>
> Don't forget to update the error messages in the tests to match,
> or we will get spurious failures.
That, and I didn't complete the job. Sorry for mixing too many patches
into one commit previously. This is three separate commits.
patch 64:
2006-06-23 Eric Blake <address@hidden>
* src/builtin.c (builtin_tab): Make format and indir blind.
(substitute): Prefer "Warning:" vs. "ERROR:" in warnings.
* NEWS: Mention the change to builtins.
patch 65:
2006-06-23 Eric Blake <address@hidden>
Make error messages more consistent with GNU coding standards -
start with lower case, and don't end sentence with punctuation.
* src/debug.c (trace_pre): Update message wording.
* src/eval.c (evaluate, cmp_term, shift_term, mult_term):
Likewise.
* src/freeze.c (produce_frozen_state, issue_expect_message),
(reload_frozen_state): Likewise.
* src/input.c (push_string_init, pop_init, init_macro_token),
(peek_input, next_char_1, set_word_regexp, next_token): Likewise.
* src/m4.c (stackovf_handler, main): Likewise.
* src/macro.c (expand_token, expand_argument, call_macro),
(expand_macro): Likewise.
* src/output.c (make_room_for, output_text, insert_file),
(freeze_diversions): Likewise.
* src/symtab.c (symtab_init, lookup_symbol): Likewise.
patch 66:
2006-06-23 Eric Blake <address@hidden>
* doc/m4.texinfo: Quoting cleanup throughout - follow
autoconf-recommended style of one level of quote per parenthesis
in the normal case. Adjust error messages to match GNU coding
standards (and to allow 'make check' to pass again).
(Quoted strings, Inhibiting Invocation): Turn more examples into
tests.
(Comments): Resolve FIXME by adding example.
(Define): Add example about underquoting.
(Defn): Add example about use of $0.
(Indir, Format): Resolve FIXME done in last commit.
(Ifelse): Add example about creating blind macro.
(Debugging): Fix grammar.
(Dnl): Add example about dnl with arguments.
(M4wrap): Be explicit that LIFO order is non compliant, and will
change in m4 2.0.
(Undivert): Resolve FIXME by adding example.
(Frozen files): Document that m4wrap and sysval will not work
consistently until m4 2.0.
(Incompatibilities): Document another POSIX compliance bug, this
time with changequote. Document a traditional incompatibility
with partial input spanning file boundaries.
- --
Life is short - so eat dessert first!
Eric Blake address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFEm+p084KuGfSFAYARAmqpAKDOMGfFsc2La37Xb0ySRObHOdE3UQCgoHoP
Hly5SGkZfAneqBuqcTZtugQ=
=KlQK
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.1.1.1.2.24
diff -u -p -r1.1.1.1.2.24 NEWS
--- NEWS 22 Jun 2006 23:17:21 -0000 1.1.1.1.2.24
+++ NEWS 23 Jun 2006 12:56:34 -0000
@@ -15,6 +15,7 @@ Version 1.4.5 - ?? 2006, by ??? (CVS ve
warning is deferred until an attempt is made to actually use the builtin.
This allows downgrading from beta m4-1.4o to m4-1.4.5 without breaking
autoconf.
+* The format and indir macros are now recognized only with arguments.
Version 1.4.4b - 17 June 2006, by Eric Blake (CVS version 1.4.4a)
Index: src/builtin.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/builtin.c,v
retrieving revision 1.1.1.1.2.13
diff -u -p -r1.1.1.1.2.13 builtin.c
--- src/builtin.c 22 Jun 2006 23:17:22 -0000 1.1.1.1.2.13
+++ src/builtin.c 23 Jun 2006 12:56:35 -0000
@@ -111,13 +111,13 @@ builtin_tab[] =
{ "errprint", FALSE, FALSE, FALSE, m4_errprint },
{ "esyscmd", TRUE, FALSE, TRUE, m4_esyscmd },
{ "eval", FALSE, FALSE, TRUE, m4_eval },
- { "format", TRUE, FALSE, FALSE, m4_format },
+ { "format", TRUE, FALSE, TRUE, m4_format },
{ "ifdef", FALSE, FALSE, TRUE, m4_ifdef },
{ "ifelse", FALSE, FALSE, TRUE, m4_ifelse },
{ "include", FALSE, FALSE, TRUE, m4_include },
{ "incr", FALSE, FALSE, TRUE, m4_incr },
{ "index", FALSE, FALSE, TRUE, m4_index },
- { "indir", TRUE, FALSE, FALSE, m4_indir },
+ { "indir", TRUE, FALSE, TRUE, m4_indir },
{ "len", FALSE, FALSE, TRUE, m4_len },
{ "m4exit", FALSE, FALSE, FALSE, m4_m4exit },
{ "m4wrap", FALSE, FALSE, FALSE, m4_m4wrap },
@@ -1529,7 +1529,7 @@ substitute (struct obstack *obs, const c
if (!substitute_warned)
{
M4ERROR ((warning_status, 0, "\
-WARNING: \\0 will disappear, use \\& instead in replacements"));
+Warning: \\0 will disappear, use \\& instead in replacements"));
substitute_warned = 1;
}
/* Fall through. */
Index: src/debug.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/debug.c,v
retrieving revision 1.1.1.1.2.2
diff -u -p -p -r1.1.1.1.2.2 debug.c
--- src/debug.c 1 May 2005 11:54:12 -0000 1.1.1.1.2.2
+++ src/debug.c 23 Jun 2006 12:59:23 -0000
@@ -1,6 +1,7 @@
/* GNU m4 -- A simple macro processor
- Copyright (C) 1991, 1992, 1993, 1994, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1992, 1993, 1994, 2004, 2006 Free Software
+ Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -379,7 +380,7 @@ trace_pre (const char *name, int id, int
if (bp == NULL)
{
M4ERROR ((warning_status, 0, "\
-INTERNAL ERROR: Builtin not found in builtin table! (trace_pre ())"));
+INTERNAL ERROR: builtin not found in builtin table! (trace_pre ())"));
abort ();
}
trace_format ("<%s>", bp->name);
@@ -387,7 +388,7 @@ INTERNAL ERROR: Builtin not found in bui
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad token data type (trace_pre ())"));
+ "INTERNAL ERROR: bad token data type (trace_pre ())"));
abort ();
}
Index: src/eval.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/eval.c,v
retrieving revision 1.1.1.1.2.2
diff -u -p -p -r1.1.1.1.2.2 eval.c
--- src/eval.c 15 Jun 2006 21:51:37 -0000 1.1.1.1.2.2
+++ src/eval.c 23 Jun 2006 12:59:23 -0000
@@ -277,38 +277,38 @@ evaluate (const char *expr, eval_t *val)
case MISSING_RIGHT:
M4ERROR ((warning_status, 0,
- "Bad expression in eval (missing right parenthesis): %s",
+ "bad expression in eval (missing right parenthesis): %s",
expr));
break;
case SYNTAX_ERROR:
M4ERROR ((warning_status, 0,
- "Bad expression in eval: %s", expr));
+ "bad expression in eval: %s", expr));
break;
case UNKNOWN_INPUT:
M4ERROR ((warning_status, 0,
- "Bad expression in eval (bad input): %s", expr));
+ "bad expression in eval (bad input): %s", expr));
break;
case EXCESS_INPUT:
M4ERROR ((warning_status, 0,
- "Bad expression in eval (excess input): %s", expr));
+ "bad expression in eval (excess input): %s", expr));
break;
case DIVIDE_ZERO:
M4ERROR ((warning_status, 0,
- "Divide by zero in eval: %s", expr));
+ "divide by zero in eval: %s", expr));
break;
case MODULO_ZERO:
M4ERROR ((warning_status, 0,
- "Modulo by zero in eval: %s", expr));
+ "modulo by zero in eval: %s", expr));
break;
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad error code in evaluate ()"));
+ "INTERNAL ERROR: bad error code in evaluate ()"));
abort ();
}
@@ -548,7 +548,7 @@ cmp_term (eval_token et, eval_t *v1)
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad comparison operator in cmp_term ()"));
+ "INTERNAL ERROR: bad comparison operator in cmp_term ()"));
abort ();
}
}
@@ -591,7 +591,7 @@ shift_term (eval_token et, eval_t *v1)
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad shift operator in shift_term ()"));
+ "INTERNAL ERROR: bad shift operator in shift_term ()"));
abort ();
}
}
@@ -674,7 +674,7 @@ mult_term (eval_token et, eval_t *v1)
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad operator in mult_term ()"));
+ "INTERNAL ERROR: bad operator in mult_term ()"));
abort ();
}
}
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.1.1.1.2.6
diff -u -p -p -r1.1.1.1.2.6 freeze.c
--- src/freeze.c 22 Jun 2006 23:17:22 -0000 1.1.1.1.2.6
+++ src/freeze.c 23 Jun 2006 12:59:23 -0000
@@ -122,7 +122,7 @@ produce_frozen_state (const char *name)
if (bp == NULL)
{
M4ERROR ((warning_status, 0, "\
-INTERNAL ERROR: Builtin not found in builtin table!"));
+INTERNAL ERROR: builtin not found in builtin table!"));
abort ();
}
fprintf (file, "F%d,%d\n",
@@ -135,7 +135,7 @@ INTERNAL ERROR: Builtin not found in bui
default:
M4ERROR ((warning_status, 0, "\
-INTERNAL ERROR: Bad token data type in freeze_one_symbol ()"));
+INTERNAL ERROR: bad token data type in freeze_one_symbol ()"));
abort ();
break;
}
@@ -165,9 +165,9 @@ static void
issue_expect_message (int expected)
{
if (expected == '\n')
- M4ERROR ((EXIT_FAILURE, 0, "Expecting line feed in frozen file"));
+ M4ERROR ((EXIT_FAILURE, 0, "expecting line feed in frozen file"));
else
- M4ERROR ((EXIT_FAILURE, 0, "Expecting character `%c' in frozen file",
+ M4ERROR ((EXIT_FAILURE, 0, "expecting character `%c' in frozen file",
expected));
}
@@ -229,7 +229,7 @@ reload_frozen_state (const char *name)
file = path_search (name);
if (file == NULL)
- M4ERROR ((EXIT_FAILURE, errno, "Cannot open %s", name));
+ M4ERROR ((EXIT_FAILURE, errno, "cannot open %s", name));
allocated[0] = 100;
string[0] = xmalloc ((size_t) allocated[0]);
@@ -250,7 +250,7 @@ reload_frozen_state (const char *name)
switch (character)
{
default:
- M4ERROR ((EXIT_FAILURE, 0, "Ill-formed frozen file"));
+ M4ERROR ((EXIT_FAILURE, 0, "ill-formed frozen file"));
case 'C':
case 'D':
@@ -289,7 +289,7 @@ reload_frozen_state (const char *name)
if (number[0] > 0)
if (!fread (string[0], (size_t) number[0], 1, file))
- M4ERROR ((EXIT_FAILURE, 0, "Premature end of frozen file"));
+ M4ERROR ((EXIT_FAILURE, 0, "premature end of frozen file"));
string[0][number[0]] = '\0';
}
@@ -305,7 +305,7 @@ reload_frozen_state (const char *name)
if (number[1] > 0)
if (!fread (string[1], (size_t) number[1], 1, file))
- M4ERROR ((EXIT_FAILURE, 0, "Premature end of frozen file"));
+ M4ERROR ((EXIT_FAILURE, 0, "premature end of frozen file"));
string[1][number[1]] = '\0';
GET_CHARACTER;
Index: src/input.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/input.c,v
retrieving revision 1.1.1.1.2.7
diff -u -p -p -r1.1.1.1.2.7 input.c
--- src/input.c 22 Jun 2006 17:43:05 -0000 1.1.1.1.2.7
+++ src/input.c 23 Jun 2006 12:59:23 -0000
@@ -224,7 +224,7 @@ push_string_init (void)
if (next != NULL)
{
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Recursive push_string!"));
+ "INTERNAL ERROR: recursive push_string!"));
abort ();
}
@@ -318,7 +318,7 @@ pop_input (void)
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Input stack botch in pop_input ()"));
+ "INTERNAL ERROR: input stack botch in pop_input ()"));
abort ();
}
obstack_free (current_input, isp);
@@ -367,7 +367,7 @@ init_macro_token (token_data *td)
if (isp->type != INPUT_MACRO)
{
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad call to init_macro_token ()"));
+ "INTERNAL ERROR: bad call to init_macro_token ()"));
abort ();
}
@@ -415,7 +415,7 @@ peek_input (void)
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Input stack botch in peek_input ()"));
+ "INTERNAL ERROR: input stack botch in peek_input ()"));
abort ();
}
/* End of input source --- pop one level. */
@@ -479,7 +479,7 @@ next_char_1 (void)
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Input stack botch in next_char ()"));
+ "INTERNAL ERROR: input stack botch in next_char ()"));
abort ();
}
@@ -663,7 +663,7 @@ set_word_regexp (const char *regexp)
if (msg != NULL)
{
M4ERROR ((warning_status, 0,
- "Bad regular expression `%s': %s", regexp, msg));
+ "bad regular expression `%s': %s", regexp, msg));
return;
}
@@ -674,7 +674,7 @@ set_word_regexp (const char *regexp)
if (msg != NULL)
{
M4ERROR ((EXIT_FAILURE, 0,
- "Internal error: Expression recompilation `%s': %s",
+ "INTERNAL ERROR: expression recompilation `%s': %s",
regexp, msg));
}
@@ -816,7 +816,7 @@ next_token (token_data *td)
ch = next_char ();
if (ch == CHAR_EOF)
M4ERROR ((EXIT_FAILURE, 0,
- "ERROR: EOF in string"));
+ "ERROR: end of file in string"));
if (MATCH (ch, rquote.string))
{
Index: src/m4.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/m4.c,v
retrieving revision 1.1.1.1.2.11
diff -u -p -p -r1.1.1.1.2.11 m4.c
--- src/m4.c 22 Jun 2006 03:29:36 -0000 1.1.1.1.2.11
+++ src/m4.c 23 Jun 2006 12:59:23 -0000
@@ -110,7 +110,7 @@ static void
stackovf_handler (void)
{
M4ERROR ((EXIT_FAILURE, 0,
- "ERROR: Stack overflow. (Infinite define recursion?)"));
+ "ERROR: stack overflow. (Infinite define recursion?)"));
}
#endif /* USE_STACKOV */
@@ -445,7 +445,7 @@ warranty; not even for MERCHANTABILITY o
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad code in deferred arguments"));
+ "INTERNAL ERROR: bad code in deferred arguments"));
abort ();
}
Index: src/macro.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/macro.c,v
retrieving revision 1.1.1.1.2.4
diff -u -p -p -r1.1.1.1.2.4 macro.c
--- src/macro.c 15 Jun 2006 21:51:37 -0000 1.1.1.1.2.4
+++ src/macro.c 23 Jun 2006 12:59:23 -0000
@@ -92,7 +92,7 @@ expand_token (struct obstack *obs, token
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad token type in expand_token ()"));
+ "INTERNAL ERROR: bad token type in expand_token ()"));
abort ();
}
}
@@ -158,7 +158,7 @@ expand_argument (struct obstack *obs, to
case TOKEN_EOF:
M4ERROR ((EXIT_FAILURE, 0,
- "ERROR: EOF in argument list"));
+ "ERROR: end of file in argument list"));
break;
case TOKEN_WORD:
@@ -176,7 +176,7 @@ expand_argument (struct obstack *obs, to
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad token type in expand_argument ()"));
+ "INTERNAL ERROR: bad token type in expand_argument ()"));
abort ();
}
@@ -252,7 +252,7 @@ call_macro (symbol *sym, int argc, token
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Bad symbol type in call_macro ()"));
+ "INTERNAL ERROR: bad symbol type in call_macro ()"));
abort ();
}
}
@@ -283,7 +283,7 @@ expand_macro (symbol *sym)
expansion_level++;
if (expansion_level > nesting_limit)
M4ERROR ((EXIT_FAILURE, 0,
- "ERROR: Recursion limit of %d exceeded, use -L<N> to change it",
+ "ERROR: recursion limit of %d exceeded, use -L<N> to change it",
nesting_limit));
macro_call_id++;
Index: src/output.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/output.c,v
retrieving revision 1.1.1.1.2.5
diff -u -p -p -r1.1.1.1.2.5 output.c
--- src/output.c 22 Jun 2006 14:55:48 -0000 1.1.1.1.2.5
+++ src/output.c 23 Jun 2006 12:59:23 -0000
@@ -182,7 +182,7 @@ make_room_for (int length)
selected_diversion->file = tmpfile ();
if (selected_diversion->file == NULL)
M4ERROR ((EXIT_FAILURE, errno,
- "ERROR: Cannot create temporary file for diversion"));
+ "ERROR: cannot create temporary file for diversion"));
if (selected_diversion->used > 0)
{
@@ -192,7 +192,7 @@ make_room_for (int length)
selected_diversion->file);
if (count != 1)
M4ERROR ((EXIT_FAILURE, errno,
- "ERROR: Cannot flush diversion to temporary file"));
+ "ERROR: cannot flush diversion to temporary file"));
}
/* Reclaim the buffer space for other diversions. */
@@ -276,7 +276,7 @@ output_text (const char *text, int lengt
{
count = fwrite (text, length, 1, output_file);
if (count != 1)
- M4ERROR ((EXIT_FAILURE, errno, "ERROR: Copying inserted file"));
+ M4ERROR ((EXIT_FAILURE, errno, "ERROR: copying inserted file"));
}
else
{
@@ -458,7 +458,7 @@ insert_file (FILE *file)
{
length = fread (buffer, 1, COPY_BUFFER_SIZE, file);
if (ferror (file))
- M4ERROR ((EXIT_FAILURE, errno, "ERROR: Reading inserted file"));
+ M4ERROR ((EXIT_FAILURE, errno, "ERROR: reading inserted file"));
if (length == 0)
break;
output_text (buffer, length);
@@ -559,7 +559,7 @@ freeze_diversions (FILE *file)
{
fflush (diversion->file);
if (fstat (fileno (diversion->file), &file_stat) < 0)
- M4ERROR ((EXIT_FAILURE, errno, "Cannot stat diversion"));
+ M4ERROR ((EXIT_FAILURE, errno, "cannot stat diversion"));
fprintf (file, "D%d,%d", divnum, (int) file_stat.st_size);
}
else
Index: src/symtab.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/symtab.c,v
retrieving revision 1.1.1.1.2.10
diff -u -p -p -r1.1.1.1.2.10 symtab.c
--- src/symtab.c 22 Jun 2006 17:43:05 -0000 1.1.1.1.2.10
+++ src/symtab.c 23 Jun 2006 12:59:23 -0000
@@ -111,7 +111,7 @@ symtab_init (void)
int e = atexit(show_profile);
if (e != 0)
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Unable to show symtab profile"));
+ "INTERNAL ERROR: unable to show symtab profile"));
}
#endif /* DEBUG_SYM */
}
@@ -309,7 +309,7 @@ lookup_symbol (const char *name, symbol_
default:
M4ERROR ((warning_status, 0,
- "INTERNAL ERROR: Invalid mode to symbol_lookup ()"));
+ "INTERNAL ERROR: invalid mode to symbol_lookup ()"));
abort ();
}
}
Index: ChangeLog
===================================================================
RCS file: /sources/m4/m4/ChangeLog,v
retrieving revision 1.1.1.1.2.84
diff -u -p -r1.1.1.1.2.84 ChangeLog
--- ChangeLog 23 Jun 2006 13:06:10 -0000 1.1.1.1.2.84
+++ ChangeLog 23 Jun 2006 13:18:44 -0000
@@ -1,5 +1,27 @@
2006-06-23 Eric Blake <address@hidden>
+ * doc/m4.texinfo: Quoting cleanup throughout - follow
+ autoconf-recommended style of one level of quote per parenthesis
+ in the normal case. Adjust error messages to match GNU coding
+ standards (and to allow 'make check' to pass again).
+ (Quoted strings, Inhibiting Invocation): Turn more examples into
+ tests.
+ (Comments): Resolve FIXME by adding example.
+ (Define): Add example about underquoting.
+ (Defn): Add example about use of $0.
+ (Indir, Format): Resolve FIXME done in last commit.
+ (Ifelse): Add example about creating blind macro.
+ (Debugging): Fix grammar.
+ (Dnl): Add example about dnl with arguments.
+ (M4wrap): Be explicit that LIFO order is non compliant, and will
+ change in m4 2.0.
+ (Undivert): Resolve FIXME by adding example.
+ (Frozen files): Document that m4wrap and sysval will not work
+ consistently until m4 2.0.
+ (Incompatibilities): Document another POSIX compliance bug, this
+ time with changequote. Document a traditional incompatibility
+ with partial input spanning file boundaries.
+
Make error messages more consistent with GNU coding standards -
start with lower case, and don't end sentence with punctuation.
* src/debug.c (trace_pre): Update message wording.
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.1.1.1.2.23
diff -u -p -r1.1.1.1.2.23 m4.texinfo
--- doc/m4.texinfo 22 Jun 2006 23:17:22 -0000 1.1.1.1.2.23
+++ doc/m4.texinfo 23 Jun 2006 13:18:44 -0000
@@ -651,20 +651,16 @@ level of quotes stripped off. Thus
@comment ignore
@example
`'
address@hidden
@end example
-is the empty string, and
-
address@hidden ignore
address@hidden
address@hidden'@w{}'
address@hidden example
-
-is the string
address@hidden
+is the empty string, and double-quoting turns into single-quoting.
@comment ignore
@example
-`quoted'
+``quoted''
address@hidden'
@end example
The quote characters can be changed at any time, using the builtin macro
@@ -689,12 +685,17 @@ Comments cannot be nested, so the first
the comment. The commenting effect of the begin comment character
can be inhibited by quoting it.
address@hidden
+`quoted text' # `commented text'
address@hidden text # `commented text'
+`quoting inhibits' `#' `comments'
address@hidden inhibits # comments
address@hidden example
+
The comment delimiters can be changed to any string at any time, using
the builtin macro @code{changecom}. @xref{Changecom}, for more
information.
address@hidden FIXME: more examples would be useful here --ADR
-
@node Macros, Definitions, Syntax, Top
@chapter How to invoke macros
@@ -792,9 +793,13 @@ For example:
@comment ignore
@example
`divert'
address@hidden
`d'ivert
address@hidden
di`ver't
address@hidden
div`'ert
address@hidden
@end example
@noindent
@@ -803,7 +808,9 @@ all yield the string @samp{divert}. Whi
@comment ignore
@example
`'divert
address@hidden
divert`'
address@hidden
@end example
@noindent
@@ -811,12 +818,12 @@ the @code{divert} builtin macro will be
The output of macro evaluations is always rescanned. The following
example would yield the string @samp{de}, exactly as if @code{m4}
-has been given @address@hidden(abcde, 3, 2)}} as input:
+has been given @address@hidden(`abcde', `3', `2')}} as input:
@example
define(`x', `substr(ab')
@result{}
-define(`y', `cde, 3, 2)')
+define(`y', `cde, `3', `2')')
@result{}
x`'y
@result{}de
@@ -824,30 +831,32 @@ x`'y
Unquoted strings on either side of a quoted string are subject to
being recognized as macro names. In the following example, quoting the
-empty string allows for the @code{dnl} macro to be recognized as such:
+empty string allows for the second @code{macro} to be recognized as such:
address@hidden ignore
@example
-define(`macro', `di$1')
-macro(v)`'dnl
+define(`macro', `m')
address@hidden
+macro(`m')macro
address@hidden
+macro(`m')`'macro
address@hidden
@end example
address@hidden
-Without the quotes, this would rather yield the string @samp{divdnl}
-followed by an end of line.
-
Quoting may prevent recognizing as a macro name the concatenation of a
macro expansion with the surrounding characters. In this example:
address@hidden ignore
@example
define(`macro', `di$1')
-macro(v)`ert'
address@hidden
+macro(`v')`ert'
address@hidden
+macro(`v')ert
address@hidden
@end example
@noindent
-the input will produce the string @samp{divert}. If the quote was
-removed, the @code{divert} builtin would be called instead.
+the input will produce the string @samp{divert}. When the quotes were
+removed, the @code{divert} builtin was called instead.
@node Macro Arguments, Quoting Arguments, Inhibiting Invocation, Macros
@section Macro arguments
@@ -921,9 +930,13 @@ example with the parentheses, the `right
foo(`() (() (')
@end example
-It is, however, in certain cases necessary to leave out quotes for some
-arguments, and there is nothing wrong in doing it. It just makes life a
-bit harder, if you are not careful.
+It is, however, in certain cases necessary or convenient to leave out
+quotes for some arguments, and there is nothing wrong in doing it. It
+just makes life a bit harder, if you are not careful. For consistency,
+this manual follows the rule of thumb that each layer of parenthesis
+introduces another layer of single quoting, except when showing the
+consequences of quoting rules. This is done even when the quoted string
+cannot be a macro, such as with integers.
@node Macro expansion, , Quoting Arguments, Macros
@section Macro expansion
@@ -1001,6 +1014,20 @@ 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.
+The first argument to @code{define} should be quoted; otherwise, if the
+macro is already defined, you will be defining a different macro. This
+example shows the problems with underquoting, since we did not want to
+define @code{one}:
+
address@hidden
+define(foo, one)
address@hidden
+define(foo, two)
address@hidden
+one
address@hidden
address@hidden example
+
The macro @code{define} is recognized only with parameters.
@node Arguments, Pseudo Arguments, Define, Definitions
@@ -1010,13 +1037,15 @@ The macro @code{define} is recognized on
@cindex Arguments to macros
Macros can have arguments. The @var{n}th argument is denoted by
@code{$n} in the expansion text, and is replaced by the @var{n}th actual
-argument, when the macro is expanded. Here is an example of a macro with
+argument, when the macro is expanded. Replacement of arguments happens
+before rescanning, regardless of how many nesting levels of quoting
+appear in the expansion. Here is an example of a macro with
two arguments. It simply exchanges the order of the two arguments.
@example
define(`exch', `$2, $1')
@result{}
-exch(arg1, arg2)
+exch(`arg1', `arg2')
@result{}arg2, arg1
@end example
@@ -1084,7 +1113,7 @@ nargs
@result{}0
nargs()
@result{}1
-nargs(arg1, arg2, arg3)
+nargs(`arg1', `arg2', `arg3')
@result{}3
@end example
@@ -1121,8 +1150,12 @@ define(`foo', `This is macro `foo'.')
@result{}
echo1(foo)
@result{}This is macro This is macro foo..
+echo1(`foo')
address@hidden is macro foo.
echo2(foo)
@result{}This is macro foo.
+echo2(`foo')
address@hidden
@end example
@noindent
@@ -1233,6 +1266,19 @@ In this way, @code{defn} can be used to
definitions of builtin macros. Even if the original macro is removed,
the other name can still be used to access the definition.
+The fact that macro definitions can be transferred also explains why you
+should use @code{$0}, rather than retyping a macro's name in its
+definition:
+
address@hidden
+define(`foo', `This is `$0'')
address@hidden
+define(`bar', defn(`foo'))
address@hidden
+bar
address@hidden is bar
address@hidden example
+
The macro @code{defn} is recognized only with parameters.
@node Pushdef, Indir, Defn, Definitions
@@ -1347,7 +1393,7 @@ The point is, here, that larger macro pa
defined, that will not be called by accident. They can @emph{only} be
called through the builtin @code{indir}.
address@hidden FIXME: Why indir does not require at least one parameter?
+The macro @code{indir} is recognized only with parameters.
@node Builtin, , Indir, Definitions
@section Indirect call of builtins
@@ -1444,16 +1490,35 @@ If called with three or four arguments,
for character), otherwise it expands to @var{not-equal}.
@example
-ifelse(foo, bar, `true')
+ifelse(`foo', `bar', `true')
@result{}
-ifelse(foo, foo, `true')
+ifelse(`foo', `foo', `true')
@result{}true
-ifelse(foo, bar, `true', `false')
address@hidden
-ifelse(foo, foo, `true', `false')
+define(`foo', `bar')
address@hidden
+ifelse(foo, `bar', `true', `false')
@result{}true
+ifelse(foo, `foo', `true', `false')
address@hidden
@end example
+Notice how the first argument was used unquoted; it is common to compare
+the expansion of a macro with a string. With this macro, you can now
+reproduce the behavior of many of the builtins, where the macro is
+recognized only with arguments.
+
address@hidden
+define(`foo', `ifelse(`$#', `0', ``$0'', `arguments:$#')')
address@hidden
+foo
address@hidden
+foo()
address@hidden:1
+foo(`a', `b', `c')
address@hidden:3
address@hidden example
+
+
@cindex multibranches
However, @code{ifelse} can take more than four arguments. If given more
than four arguments, @code{ifelse} works like a @code{case} or @code{switch}
@@ -1463,7 +1528,7 @@ the procedure is repeated with the first
calls for an example:
@example
-ifelse(foo, bar, `third', gnu, gnats, `sixth', `seventh')
+ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth', `seventh')
@result{}seventh
@end example
@@ -1500,9 +1565,9 @@ It takes any number of arguments, and ex
argument, separated by commas, with each argument quoted.
@example
-shift(bar)
+shift(`bar')
@result{}
-shift(foo, bar, baz)
+shift(`foo', `bar', `baz')
@result{}bar,baz
@end example
@@ -1510,14 +1575,14 @@ An example of the use of @code{shift} is
order of its arguments:
@example
-define(`reverse', `ifelse($#, 0, , $#, 1, ``$1'',
+define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'',
`reverse(shift($@@)), `$1'')')
@result{}
reverse
@result{}
-reverse(foo)
+reverse(`foo')
@result{}foo
-reverse(foo, bar, gnats, and gnus)
+reverse(`foo', `bar', `gnats', `and gnus')
@result{}and gnus, gnats, bar, foo
@end example
@@ -1532,7 +1597,7 @@ can, for example, be used for simple cou
@comment ignore
@example
-forloop(`i', 1, 8, `i ')
+forloop(`i', `1', `8', `i ')
@result{}1 2 3 4 5 6 7 8
@end example
@@ -1545,7 +1610,7 @@ For-loops can be nested, like
@comment ignore
@example
-forloop(`i', 1, 4, `forloop(`j', 1, 8, `(i, j) ')
+forloop(`i', `1', `4', `forloop(`j', `1', `8', `(i, j) ')
')
@result{}(1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8)
@result{}(2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8)
@@ -1589,9 +1654,9 @@ a name. Correcting these errors are lef
@node Debugging, Input Control, Conditionals, Top
@chapter How to debug macros and input
-When writing macros for @code{m4}, most of the time they would not
-work as intended (as is the case with most programming languages).
-There is a little support for macro debugging in @code{m4}.
+When writing macros for @code{m4}, they often do not work as intended on
+the first try (as is the case with most programming languages).
+Fortunately, there is support for macro debugging in @code{m4}.
@menu
* Dumpdef:: Displaying macro definitions
@@ -1635,7 +1700,6 @@ dumpdef(`define')
@end example
The last example shows how builtin macros definitions are displayed.
-
The definition that is dumped corresponds to what would occur if the
macro were to be called at that point, even if other definitions are
still live due to redefining a macro during argument collection.
@@ -1647,7 +1711,7 @@ f(popdef(`f')dumpdef(`f'))
@error{}f:@tabchar{}``$0'1'
@result{}f2
f(popdef(`f')dumpdef(`f'))
address@hidden:7: m4: Undefined name f
address@hidden:7: m4: undefined macro `f'
@result{}f1
@end example
@@ -1673,7 +1737,7 @@ traceoff(...)
@noindent
When called without any arguments, @code{traceon} and @code{traceoff}
-will turn tracing on and off, respectively, for all defined macros.
+will turn tracing on and off, respectively, for all defined macros.
When called with arguments, only the named macros are affected.
The expansion of @code{traceon} and @code{traceoff} is void.
@@ -1723,7 +1787,7 @@ undefine(`foo')
ifdef(`foo', `yes', `no')
@result{}no
indir(`foo')
address@hidden:17: m4: Undefined macro `foo'
address@hidden:17: m4: undefined macro `foo'
@result{}
define(`foo', `blah')
@result{}
@@ -1904,6 +1968,14 @@ collection will take place. @code{dnl}
input following the matching close parenthesis up to and including the
next newline, on whatever line containing it, will still be discarded.
address@hidden
+dnl(`this is ignored',
+`so is this') and this too
address@hidden:3: m4: Warning: excess arguments to builtin `dnl' ignored
+but not this
address@hidden not this
address@hidden example
+
@node Changequote, Changecom, Dnl, Input Control
@section Changing the quote characters
@@ -1921,11 +1993,13 @@ changequote(opt @var{start}, opt @var{en
where @var{start} is the new start-quote delimiter and @var{end} is the
new end-quote delimiter. If any of the arguments are missing, the default
quotes (@code{`} and @code{'}) are used instead of the void arguments.
address@hidden FIXME POSIX requires that with one argument, the closing quote
address@hidden be set to newline, not '.
The expansion of @code{changequote} is void.
@example
-changequote([, ])
+changequote(`[', `]')
@result{}
define([foo], [Macro [foo].])
@result{}
@@ -1937,7 +2011,7 @@ If no single character is appropriate, @
of any length.
@example
-changequote([[[, ]]])
+changequote(`[[[', `]]]')
@result{}
define([[[foo]]], [[[Macro [[[[[foo]]]]].]]])
@result{}
@@ -1982,9 +2056,9 @@ changecom(opt @var{start}, opt @var{end}
@end example
@noindent
where @var{start} is the new start-comment delimiter and @var{end} is
-the new end-comment delimiter. If any of the arguments are void, the
-default comment delimiters (@code{#} and newline) are used instead of
-the void arguments. The comment delimiters can be of any length.
+the new end-comment delimiter. If only one argument is provided,
+newline becomes the new end-comment delimiter. The comment delimiters
+can be of any length.
The expansion of @code{changecom} is void.
@@ -2006,8 +2080,8 @@ Note how comments are copied to the outp
strings. If you want the text inside a comment expanded, quote the
start comment delimiter.
-Calling @code{changecom} without any arguments disables the commenting
-mechanism completely.
+Calling @code{changecom} without any arguments, or with an empty string
+for the first argument, disables the commenting mechanism completely.
@example
define(`comment', `COMMENT')
@@ -2051,7 +2125,7 @@ apply translations to a file of numbers:
@example
changeword(`[_a-zA-Z0-9]+')
@result{}
-define(1, 0)1
+define(`1', `0')1
@result{}0
@end example
@@ -2065,7 +2139,7 @@ define(`_indir', defn(`indir'))
@result{}
changeword(`_[_a-zA-Z0-9]*')
@result{}
-esyscmd(foo)
+esyscmd(`foo')
@result{}esyscmd(foo)
_indir(`esyscmd', `echo hi')
@result{}hi
@@ -2164,7 +2238,7 @@ which stores @var{string} and the rest o
to be reread when end of input is reached.
@example
-define(`cleanup', `This is the `cleanup' actions.
+define(`cleanup', `This is the `cleanup' action.
')
@result{}
m4wrap(`cleanup')
@@ -2172,7 +2246,7 @@ m4wrap(`cleanup')
This is the first and last normal input line.
@result{}This is the first and last normal input line.
^D
address@hidden is the cleanup actions.
address@hidden is the cleanup action.
@end example
The saved input is only reread when the end of normal input is seen, and
@@ -2185,7 +2259,9 @@ not if @code{m4exit} is used to exit @co
It is safe to call @code{m4wrap} from saved text, but then the order in
which the saved text is reread is undefined. If @code{m4wrap} is not used
recursively, the saved pieces of text are reread in the opposite order
-in which they were saved (LIFO---last in, first out).
+in which they were saved (LIFO---last in, first out). However, this
+behavior is likely to change in a future release, to match
address@hidden, so you should not depend on this order.
Here is an example of implementing a factorial function using
@code{m4wrap}:
@@ -2195,7 +2271,7 @@ define(`f', `ifelse(`$1', `0', `Answer:
', eval(`$1>1'), `0', `Answer: $2$1=eval(`$2$1')
', `m4wrap(`f(decr(`$1'), `$2$1*')')')')
@result{}
-f(10)
+f(`10')
@result{}
^D
@result{}Answer: 10*9*8*7*6*5*4*3*2*1=3628800
@@ -2243,7 +2319,7 @@ does not.
@example
include(`none')
@result{}
address@hidden:2: m4: Cannot open none: No such file or directory
address@hidden:2: m4: cannot open `none': No such file or directory
sinclude(`none')
@result{}
@end example
@@ -2364,7 +2440,7 @@ When all the @code{m4} input will have b
diversions are automatically undiverted, in numerical order.
@example
-divert(1)
+divert(`1')
This text is diverted.
divert
@result{}
@@ -2397,7 +2473,7 @@ example of unwanted output is the traili
definitions. Here is how to avoid them.
@example
-divert(-1)
+divert(`-1')
define(`foo', `Macro `foo'.')
define(`bar', `Macro `bar'.')
divert
@@ -2423,18 +2499,16 @@ which undiverts the diversions given by
given. If no arguments are supplied, all diversions are undiverted, in
numerical order.
address@hidden FIXME: Explain what happens when undiverting all to else than 0.
-
The expansion of @code{undivert} is void.
@example
-divert(1)
+divert(`1')
This text is diverted.
divert
@result{}
This text is not diverted.
@result{}This text is not diverted.
-undivert(1)
+undivert(`1')
@result{}
@result{}This text is diverted.
@result{}
@@ -2452,21 +2526,34 @@ When a diversion has been undiverted, th
and it is not possible to bring back diverted text more than once.
@example
-divert(1)
+divert(`1')
This text is diverted first.
-divert(0)undivert(1)dnl
+divert(`0')undivert(`1')dnl
@result{}
@result{}This text is diverted first.
-undivert(1)
+undivert(`1')
@result{}
-divert(1)
+divert(`1')
This text is also diverted but not appended.
-divert(0)undivert(1)dnl
+divert(`0')undivert(`1')dnl
@result{}
@result{}This text is also diverted but not appended.
@end example
-Attempts to undivert the current diversion are silently ignored.
+Attempts to undivert the current diversion are silently ignored. Thus,
+when the current diversion is not 0, the current diversion does not get
+rearranged among the other diversions.
+
address@hidden
+divert(`1')one
+divert(`2')two
+divert(`3')three
+divert(`2')undivert`'dnl
+divert`'undivert`'dnl
address@hidden
address@hidden
address@hidden
address@hidden example
@cindex GNU extensions
@cindex file inclusion
@@ -2506,12 +2593,10 @@ expands to the number of the current div
@example
Initial divnum
@result{}Initial 0
-divert(1)
+divert(`1')
Diversion one: divnum
-divert(2)
+divert(`2')
Diversion two: divnum
-divert
address@hidden
^D
@result{}
@result{}Diversion one: 1
@@ -2519,9 +2604,6 @@ divert
@result{}Diversion two: 2
@end example
-The last call of @code{divert} without argument is necessary, since the
-undiverted text would otherwise be diverted itself.
-
@node Cleardiv, , Divnum, Diversions
@section Discarding diverted text
@@ -2532,14 +2614,14 @@ text is actually needed. Since all non-
on the main output stream when the end of input is seen, a method of
discarding a diversion is needed. If all diversions should be
discarded, the easiest is to end the input to @code{m4} with
address@hidden(-1)} followed by an explicit @samp{undivert}:
address@hidden(`-1')} followed by an explicit @samp{undivert}:
@example
-divert(1)
+divert(`1')
Diversion one: divnum
-divert(2)
+divert(`2')
Diversion two: divnum
-divert(-1)
+divert(`-1')
undivert
^D
@end example
@@ -2551,7 +2633,7 @@ Clearing selected diversions can be done
@example
define(`cleardivert',
-`pushdef(`_n', divnum)divert(-1)undivert($@@)divert(_n)popdef(`_n')')
+`pushdef(`_n', divnum)divert(`-1')undivert($@@)divert(_n)popdef(`_n')')
@result{}
@end example
@@ -2696,9 +2778,9 @@ which expands to the substring of @var{s
is always 0.
@example
-substr(`gnus, gnats, and armadillos', 6)
+substr(`gnus, gnats, and armadillos', `6')
@result{}gnats, and armadillos
-substr(`gnus, gnats, and armadillos', 6, 5)
+substr(`gnus, gnats, and armadillos', `6', `5')
@result{}gnats
@end example
@@ -2852,7 +2934,7 @@ example shows how @code{format} can be u
@comment ignore
@example
-forloop(`i', 1, 10, `format(`%6d squared is %10d
+forloop(`i', `1', `10', `format(`%6d squared is %10d
', i, eval(i**2))')
@result{} 1 squared is 1
@result{} 2 squared is 4
@@ -2874,7 +2956,7 @@ modifiers @samp{+}, @samp{-}, @address@hidden
@samp{l}. For more details on the functioning of @code{printf}, see the
C Library Manual.
address@hidden FIXME: Why format does not require at least one argument?
+The macro @code{format} is recognized only with parameters.
@node Arithmetic, UNIX commands, Text handling, Top
@chapter Macros for doing arithmetic
@@ -2911,9 +2993,9 @@ which expand to the numerical value of @
or decremented, respectively, by one.
@example
-incr(4)
+incr(`4')
@result{}5
-decr(7)
+decr(`7')
@result{}6
@end example
@@ -2993,20 +3075,20 @@ relation return @code{0}.
Here are a few examples of use of @code{eval}.
@example
-eval(-3 * 5)
+eval(`-3 * 5')
@result{}-15
eval(index(`Hello world', `llo') >= 0)
@result{}1
-define(`square', `eval(($1)**2)')
+define(`square', `eval(`('$1`)**2')')
@result{}
-square(9)
+square(`9')
@result{}81
-square(square(5)+1)
+square(square(`5')`+1')
@result{}676
define(`foo', `666')
@result{}
-eval(`foo'/6)
address@hidden:14: m4: Bad expression in eval: foo/6
+eval(`foo/6')
address@hidden:14: m4: bad expression in eval: foo/6
@result{}
eval(foo/6)
@result{}111
@@ -3024,15 +3106,15 @@ output width. The result is zero-padded
requested width.
@example
-eval(666, 10)
+eval(`666', `10')
@result{}666
-eval(666, 11)
+eval(`666', `11')
@result{}556
-eval(666, 6)
+eval(`666', `6')
@result{}3030
-eval(666, 6, 10)
+eval(`666', `6', `10')
@result{}0000003030
-eval(-666, 6, 10)
+eval(`-666', `6', `10')
@result{}-000003030
@end example
@@ -3109,7 +3191,7 @@ Assume you are positioned into the @file
@code{m4} distribution, then:
@example
-define(`vice', `esyscmd(grep Vice ../COPYING)')
+define(`vice', `esyscmd(`grep Vice ../COPYING')')
@result{}
vice
@result{} Ty Coon, President of Vice
@@ -3142,7 +3224,7 @@ which expands to the exit status of the
@example
syscmd(`false')
@result{}
-ifelse(sysval, 0, zero, non-zero)
+ifelse(sysval, `0', `zero', `non-zero')
@result{}non-zero
syscmd(`exit 2')
@result{}
@@ -3261,9 +3343,9 @@ which expands to the quoted name of the
current input line number in that file.
@example
-errprint(`m4:'__file__:__line__: `Input error
+errprint(`m4:'__file__:__line__: `input error
')
address@hidden:m4.input:2: Input error
address@hidden:m4.input:2: input error
@result{}
@end example
@@ -3286,10 +3368,10 @@ which causes @code{m4} to exit, with exi
@example
define(`fatal_error',
`errprint(`m4: '__file__: __line__`: fatal error: $*
-')m4exit(1)')
+')m4exit(`1')')
@result{}
-fatal_error(`This is a BAD one, buster')
address@hidden: m4.input: 6: fatal error: This is a BAD one, buster
+fatal_error(`this is a BAD one, buster')
address@hidden: m4.input: 6: fatal error: this is a BAD one, buster
@end example
After this macro call, @code{m4} will exit with exit code 1. This macro
@@ -3390,11 +3472,13 @@ m4 -R file3.m4f file4.m4
Some care is necessary because not every effort has been made for
this to work in all cases. In particular, the trace attribute of
macros is not handled, nor the current setting of @code{changeword}.
+Currently, @code{m4wrap} and @code{sysval} also have problems.
Also, interactions for some options of @code{m4} being used in one call
and not for the next, have not been fully analyzed yet. On the other
end, you may be confident that stacks of @code{pushdef}'ed definitions
are handled correctly, so are @code{undefine}'d or renamed builtins,
-changed strings for quotes or comments.
+changed strings for quotes or comments. And future releases of GNU M4
+will improve on the utility of frozen files.
When an @code{m4} run is to be frozen, the automatic undiversion
which takes place at end of execution is inhibited. Instead, all
@@ -3637,6 +3721,11 @@ file for each invocation of @code{makete
of the macro is different even if the input is identical.
@item
address@hidden requires @code{changequote(@var{arg})}
+(@pxref{Changequote}) to use newline as the close quote, but GNU
address@hidden uses @samp{'} as the close quote.
+
address@hidden
Traditional @code{m4} treats @code{traceon} (@pxref{Trace}) without
arguments as a global variable, independent of named macro tracing.
Also, once a macro is undefined, named tracing of that macro is lost.
@@ -3647,6 +3736,13 @@ turns tracing off for all definitions re
also traced by name; and tracing by name, such as with @samp{-tfoo} at
the command line or @code{traceon(`foo')} in the input, is an attribute
that is preserved even if the macro is currently undefined.
+
address@hidden
+Traditional implementations allow argument collection, but not string
+processing, to span file boundaries. Thus, if @file{a.m4} contains
address@hidden(}, and @file{b.m4} contains @samp{abc)}, @kbd{m4 a.m4 b.m4}
+outputs @samp{3} with traditional @code{m4}, but gives an error message
+that the end of file was encountered inside a macro with GNU @code{m4}.
@end itemize
@node Other Incompatibilities, , Incompatibilities, Compatibility