Next: Other Incompatibilities, Previous: Extensions, Up: Compatibility
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.
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.
include
(see Include) when a file is unreadable,
eval
(see Eval) when an argument cannot be parsed, or using
m4exit
(see M4exit) with a non-numeric argument).
m4
correctly handles multiple instances
of `-' on the command line.
m4wrap
(see M4wrap) 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
a`'define`'b
would expand to ab
.
But GNU m4
ignores certain builtins if they have missing
arguments, giving adefineb
for the above example.
define(`f',`1')
(see Define)
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')
.
syscmd
(see Syscmd) 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.
maketemp
(see Maketemp) 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.
changequote(
arg)
(see Changequote) 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.
m4
give macros a higher precedence than
comments when parsing, meaning that if the start delimiter given to
changecom
(see Changecom) 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.
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 Include), 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.
m4
treats traceon
(see 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.
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.
eval
(see Eval) 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 `**'.
translit
(see Translit) to treat
each character of the second and third arguments literally, but GNU
m4
treats `-' as a range operator.
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
.