[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
m4
This chapter describes the differences between this implementation of
m4
, and the implementation found under UNIX, notably System V,
Release 3.
There are also differences in BSD flavors of m4
. No attempt
is made to summarize these here.
15.1 Extensions in GNU m4 | Extensions in GNU M4 | |
15.2 Facilities in System V m4 not in GNU m4 | Facilities in System V m4 not in GNU M4 | |
15.3 Other incompatibilities |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
m4
This version of m4
contains a few facilities that do not exist
in System V m4
. These extra facilities are all suppressed by
using the `-G' command line option (see section Invoking m4
), unless
overridden by other command line options.
In the $
n notation for macro arguments, n can contain
several digits, while the System V m4
only accepts one digit.
This allows macros in GNU m4
to take any number of
arguments, and not only nine (see section Arguments to macros).
This means that define(`foo', `$11')
is ambiguous between
implementations. To portably choose between grabbing the first
parameter and appending 1 to the expansion, or grabbing the eleventh
parameter, you can do the following:
define(`a1', `A1') ⇒ dnl First argument, concatenated with 1 define(`_1', `$1')define(`first1', `_1($@)1') ⇒ dnl Eleventh argument, portable define(`_9', `$9')define(`eleventh', `_9(shift(shift($@)))') ⇒ dnl Eleventh argument, GNU style define(`Eleventh', `$11') ⇒ first1(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') ⇒A1 eleventh(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') ⇒k Eleventh(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k') ⇒k |
The divert
(see section Diverting output) macro can manage more than 9
diversions. GNU m4
treats all positive numbers as valid
diversions, rather than discarding diversions greater than 9.
Files included with include
and 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 `-I' option and the
M4PATH
environment variable (see section Searching for include files).
Arguments to undivert
can be non-numeric, in which case the named
file will be included uninterpreted in the output (see section Undiverting output).
Formatted output is supported through the format
builtin, which
is modeled after the C library function printf
(see section Formatted output).
Searches and text substitution through regular expressions are
supported by the regexp
(see section Searching for regular expressions) and patsubst
(see section Substituting text by regular expression) builtins.
The output of shell commands can be read into m4
with
esyscmd
(see section Reading the output of commands).
There is indirect access to any builtin macro with builtin
(see section Indirect call of builtins).
Macros can be called indirectly through indir
(see section Indirect call of macros).
The name of the program, the current input file, and the current input
line number are accessible through the builtins __program__
,
__file__
, and __line__
(see section Printing current location).
The format of the output from dumpdef
and macro tracing can be
controlled with debugmode
(see section Controlling debugging output).
The destination of trace and debug output can be controlled with
debugfile
(see section Saving debugging output).
In addition to the above extensions, GNU m4
implements the
following command line options: `-F', `-G', `-I',
`-L', `-R', `-V', `-W', `-d',
`-l', `-o' and `-t'. See section Invoking m4
, for a
description of these options.
Also, the debugging and tracing facilities in GNU m4
are much
more extensive than in most other versions of m4
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
m4
not in GNU m4
The version of m4
from System V contains a few facilities that
have not been implemented in GNU m4
yet. Additionally,
POSIX requires some behaviors that GNU m4
has not
implemented yet. Relying on these behaviors is non-portable, as a
future release of GNU m4
may change.
System V m4
supports multiple arguments to defn
, and
POSIX requires it. This is not yet implemented in GNU
m4
. Unfortunately, this means it is not possible to mix builtins
and other text into a single macro; a helper macro is required.
POSIX requires an application to exit with non-zero status if
it wrote an error message to stderr. This has not yet been consistently
implemented for the various builtins that are required to issue an error
(such as include
(see section Including named files) when a file is unreadable,
eval
(see section Evaluating integer expressions) when an argument cannot be parsed, or using
m4exit
(see section Exiting from m4
) with a non-numeric argument).
POSIX requires m4wrap
(see section Saving input) to act in FIFO
(first-in, first-out) order, but GNU m4
currently uses
LIFO order. Furthermore, POSIX states that only the first
argument to m4wrap
is saved for later evaluation, bug
GNU m4
saves and processes all arguments, with output
separated by spaces.
However, it is possible to emulate POSIX behavior by including the file `examples/wrapfifo.m4' from the distribution:
undivert(`wrapfifo.m4')dnl ⇒dnl Redefine m4wrap to have FIFO semantics. ⇒define(`_m4wrap_level', `0')dnl ⇒define(`m4wrap', ⇒`ifdef(`m4wrap'_m4wrap_level, ⇒ `define(`m4wrap'_m4wrap_level, ⇒ defn(`m4wrap'_m4wrap_level)`$1')', ⇒ `builtin(`m4wrap', `define(`_m4wrap_level', ⇒ incr(_m4wrap_level))dnl ⇒m4wrap'_m4wrap_level)dnl ⇒define(`m4wrap'_m4wrap_level, `$1')')')dnl include(`wrapfifo.m4') ⇒ m4wrap(`a`'m4wrap(`c ', `d')')m4wrap(`b') ⇒ ^D ⇒abc |
POSIX requires that all builtins that require arguments, but
are called without arguments, behave as though empty strings had been
passed. For example, a`'define`'b
would expand to ab
.
But GNU m4
ignores certain builtins if they have missing
arguments, giving adefineb
for the above example.
Traditional implementations handle define(`f',`1')
(see section Defining a macro)
by undefining the entire stack of previous definitions, and if doing
undefine(`f')
first. GNU m4
replaces just the top
definition on the stack, as if doing popdef(`f')
followed by
pushdef(`f',`1')
.
POSIX requires syscmd
(see section Executing simple commands) to evaluate
command output for macro expansion, but this appears to be a mistake
in POSIX since traditional implementations did not do this.
GNU m4
follows traditional behavior in syscmd
, and
provides the extension esyscmd
that provides the POSIX
semantics.
POSIX requires maketemp
(see section Making names for temporary files) to replace
the trailing `X' characters with the m4
process id, giving
the same result on identical input, without creating any files, which
leaves the door open for a data race in which other processes can create
a file by the same name. GNU m4
actually creates a temporary
file for each invocation of maketemp
, which means that the output
of the macro is different even if the input is identical.
POSIX requires changequote(arg)
(see section Changing the quote characters) to use newline as the close quote, but GNU
m4
uses `'' as the close quote. Meanwhile, some
traditional implementations use arg as the close quote, making it
impossible to nest quotes. For predictable results, never call
changequote with just one argument.
Some implementations of m4
give macros a higher precedence than
comments when parsing, meaning that if the start delimiter given to
changecom
(see section Changing comment delimiters) starts with a macro name, comments
are effectively disabled. POSIX does not specify what the
precedence is, so the GNU m4
parser recognizes comments, then
macros, then quoted strings.
Traditional implementations allow argument collection, but not string
and comment processing, to span file boundaries. Thus, if `a.m4'
contains `len(', and `b.m4' contains `abc)',
m4 a.m4 b.m4 outputs `3' with traditional m4
, but
gives an error message that the end of file was encountered inside a
macro with GNU m4
. On the other hand, traditional
implementations do end of file processing for files included with
include
or sinclude
(see section Including named files), while GNU
m4
seamlessly integrates the content of those files. Thus
include(`a.m4')include(`b.m4')
will output `3' instead of
giving an error.
Traditional m4
treats traceon
(see section Tracing macro calls) without
arguments as a global variable, independent of named macro tracing.
Also, once a macro is undefined, named tracing of that macro is lost.
On the other hand, when GNU m4
encounters
traceon
without
arguments, it turns tracing on for all existing definitions at the time,
but does not trace future definitions; traceoff
without arguments
turns tracing off for all definitions regardless of whether they were
also traced by name; and tracing by name, such as with `-tfoo' at
the command line or traceon(`foo')
in the input, is an attribute
that is preserved even if the macro is currently undefined.
POSIX requires eval
(see section Evaluating integer expressions) to treat all
operators with the same precedence as C. However, GNU m4
currently follows the traditional precedence of other m4
implementations, where bitwise and logical negation (`~' and
`!') have lower precedence than equality operators, rather than
equal precedence with other unary operators. Use explicit parentheses
to ensure proper precedence. As extensions to POSIX, GNU
m4
treats the shift operators `<<' and `>>' as
well-defined on signed integers (even though they are not in C), and
adds the exponentiation operator `**'.
POSIX requires translit
(see section Translating characters) to treat
each character of the second and third arguments literally, but GNU
m4
treats `-' as a range operator.
POSIX requires m4
to honor the locale environment
variables of LANG
, LC_ALL
, LC_CTYPE
,
LC_MESSAGES
, and NLSPATH
, but this has not yet been
implemented in GNU m4
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are a few other incompatibilities between this implementation of
m4
, and the System V version.
GNU m4
implements sync lines differently from System V
m4
, when text is being diverted. GNU m4
outputs
the sync lines when the text is being diverted, and System V m4
when the diverted text is being brought back.
The problem is which lines and file names should be attached to text that
is being, or has been, diverted. System V m4
regards all the
diverted text as being generated by the source line containing the
undivert
call, whereas GNU m4
regards the
diverted text as being generated at the time it is diverted.
The sync line option is used mostly when using 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.
GNU m4
makes no attempt at prohibiting self-referential
definitions like:
define(`x', `x') ⇒ define(`x', `x ') ⇒ |
There is nothing inherently wrong with defining `x' to
return `x'. The wrong thing is to expand `x' unquoted.
In m4
, one might use macros to hold strings, as we do for
variables in other programming languages, further checking them with:
ifelse(defn(`holder'), `value', …) |
In cases like this one, an interdiction for a macro to hold its own
name would be a useless limitation. Of course, this leaves more rope
for the GNU m4
user to hang himself! Rescanning hangs may be
avoided through careful programming, a little like for endless loops
in traditional programming languages.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by System Administrator on September, 23 2007 using texi2html 1.70.