m4: Incompatibilities
1
1 16.2 Facilities in System V 'm4' not in GNU 'm4'
1 ================================================
1
1 The version of 'm4' from System V contains a few facilities that have
1 not been implemented in GNU 'm4' yet. Additionally, POSIX requires some
1 behaviors that GNU 'm4' has not implemented yet. Relying on these
1 behaviors is non-portable, as a future release of GNU 'm4' may change.
1
1 * POSIX requires support for multiple arguments to 'defn', without
1 any clarification on how 'defn' behaves when one of the multiple
1 arguments names a builtin. System V 'm4' and some other
1 implementations allow mixing builtins and text macros into a single
1 macro. GNU 'm4' only supports joining multiple text arguments,
1 although a future implementation may lift this restriction to
1 behave more like System V. The only portable way to join text
1 macros with builtins is via helper macros and implicit
1 concatenation of macro results.
1
1 * POSIX requires an application to exit with non-zero status if it
1 wrote an error message to stderr. This has not yet been
1 consistently implemented for the various builtins that are required
1 to issue an error (such as 'eval' (⇒Eval) when an argument
1 cannot be parsed).
1
1 * Some traditional implementations only allow reading standard input
1 once, but GNU 'm4' correctly handles multiple instances of '-' on
1 the command line.
1
1 * POSIX requires 'm4wrap' (⇒M4wrap) to act in FIFO (first-in,
1 first-out) order, but GNU 'm4' currently uses LIFO order.
1 Furthermore, POSIX states that only the first argument to 'm4wrap'
1 is saved for later evaluation, but GNU 'm4' saves and processes all
1 arguments, with output separated by spaces.
1
1 * POSIX states that builtins that require arguments, but are called
1 without arguments, have undefined behavior. Traditional
1 implementations simply behave as though empty strings had been
1 passed. For example, 'a`'define`'b' would expand to 'ab'. But GNU
1 'm4' ignores certain builtins if they have missing arguments,
1 giving 'adefineb' for the above example.
1
11 * Traditional implementations handle 'define(`f',`1')' (⇒
Define) by undefining the entire stack of previous definitions,
1 and if doing 'undefine(`f')' first. GNU 'm4' replaces just the top
1 definition on the stack, as if doing 'popdef(`f')' followed by
1 'pushdef(`f',`1')'. POSIX allows either behavior.
1
1 * POSIX 2001 requires 'syscmd' (⇒Syscmd) to evaluate command
1 output for macro expansion, but this was a mistake that is
1 anticipated to be corrected in the next version of POSIX. GNU 'm4'
1 follows traditional behavior in 'syscmd' where output is not
1 rescanned, and provides the extension 'esyscmd' that does scan the
1 output.
1
11 * At one point, POSIX required 'changequote(ARG)' (⇒
Changequote) to use newline as the close quote, but this was a
1 bug, and the next version of POSIX is anticipated to state that
1 using empty strings or just one argument is unspecified.
1 Meanwhile, the GNU 'm4' behavior of treating an empty end-quote
1 delimiter as ''' is not portable, as Solaris treats it as repeating
1 the start-quote delimiter, and BSD treats it as leaving the
1 previous end-quote delimiter unchanged. For predictable results,
1 never call changequote with just one argument, or with empty
1 strings for arguments.
1
1 * At one point, POSIX required 'changecom(ARG,)' (⇒Changecom)
1 to make it impossible to end a comment, but this is a bug, and the
1 next version of POSIX is anticipated to state that using empty
1 strings is unspecified. Meanwhile, the GNU 'm4' behavior of
1 treating an empty end-comment delimiter as newline is not portable,
1 as BSD treats it as leaving the previous end-comment delimiter
1 unchanged. It is also impossible in BSD implementations to disable
1 comments, even though that is required by POSIX. For predictable
1 results, never call changecom with empty strings for arguments.
1
1 * Most implementations of 'm4' give macros a higher precedence than
1 comments when parsing, meaning that if the start delimiter given to
1 'changecom' (⇒Changecom) starts with a macro name, comments
1 are effectively disabled. POSIX does not specify what the
1 precedence is, so this version of GNU 'm4' parser recognizes
1 comments, then macros, then quoted strings.
1
1 * Traditional implementations allow argument collection, but not
1 string and comment processing, to span file boundaries. Thus, if
1 'a.m4' contains 'len(', and 'b.m4' contains 'abc)', 'm4 a.m4 b.m4'
1 outputs '3' with traditional 'm4', but gives an error message that
1 the end of file was encountered inside a macro with GNU 'm4'. On
1 the other hand, traditional implementations do end of file
11 processing for files included with 'include' or 'sinclude' (⇒
Include), while GNU 'm4' seamlessly integrates the content of
1 those files. Thus 'include(`a.m4')include(`b.m4')' will output '3'
1 instead of giving an error.
1
1 * Traditional 'm4' treats 'traceon' (⇒Trace) without arguments
1 as a global variable, independent of named macro tracing. Also,
1 once a macro is undefined, named tracing of that macro is lost. On
1 the other hand, when GNU 'm4' encounters 'traceon' without
1 arguments, it turns tracing on for all existing definitions at the
1 time, but does not trace future definitions; 'traceoff' without
1 arguments turns tracing off for all definitions regardless of
1 whether they were also traced by name; and tracing by name, such as
1 with '-tfoo' at the command line or 'traceon(`foo')' in the input,
1 is an attribute that is preserved even if the macro is currently
1 undefined.
1
1 Additionally, while POSIX requires trace output, it makes no
1 demands on the formatting of that output. Parsing trace output is
1 not guaranteed to be reliable, even between different releases of
1 GNU M4; however, the intent is that any future changes in trace
1 output will only occur under the direction of additional
1 'debugmode' flags (⇒Debug Levels).
1
1 * POSIX requires 'eval' (⇒Eval) to treat all operators with
1 the same precedence as C. However, earlier versions of GNU 'm4'
1 followed the traditional behavior of other 'm4' implementations,
1 where bitwise and logical negation ('~' and '!') have lower
1 precedence than equality operators; and where equality operators
1 ('==' and '!=') had the same precedence as relational operators
1 (such as '<'). Use explicit parentheses to ensure proper
1 precedence. As extensions to POSIX, GNU 'm4' gives well-defined
1 semantics to operations that C leaves undefined, such as when
1 overflow occurs, when shifting negative numbers, or when performing
1 division by zero. POSIX also requires '=' to cause an error, but
1 many traditional implementations allowed it as an alias for '=='.
1
1 * POSIX 2001 requires 'translit' (⇒Translit) to treat each
1 character of the second and third arguments literally. However, it
1 is anticipated that the next version of POSIX will allow the GNU
1 'm4' behavior of treating '-' as a range operator.
1
1 * POSIX requires 'm4' to honor the locale environment variables of
1 'LANG', 'LC_ALL', 'LC_CTYPE', 'LC_MESSAGES', and 'NLSPATH', but
1 this has not yet been implemented in GNU 'm4'.
1
1 * POSIX states that only unquoted leading newlines and blanks (that
1 is, space and tab) are ignored when collecting macro arguments.
1 However, this appears to be a bug in POSIX, since most traditional
1 implementations also ignore all whitespace (formfeed, carriage
1 return, and vertical tab). GNU 'm4' follows tradition and ignores
1 all leading unquoted whitespace.
1
1 * A strictly-compliant POSIX client is not allowed to use
1 command-line arguments not specified by POSIX. However, since this
1 version of M4 ignores 'POSIXLY_CORRECT' and enables the option
1 '--gnu' by default (⇒Invoking m4 Limits control.), a client
1 desiring to be strictly compliant has no way to disable GNU
1 extensions that conflict with POSIX when directly invoking the
1 compiled 'm4'. A future version of 'GNU' M4 will honor the
1 environment variable 'POSIXLY_CORRECT', implicitly enabling
1 '--traditional' if it is set, in order to allow a
1 strictly-compliant client. In the meantime, a client needing
1 strict POSIX compliance can use the workaround of invoking a shell
1 script wrapper, where the wrapper then adds '--traditional' to the
1 arguments passed to the compiled 'm4'.
1