manpagez: man pages & more
info autoconf
Home | html | info | man

File: autoconf.info,  Node: Diversion support,  Next: Conditional constructs,  Prev: Diagnostic Macros,  Up: Programming in M4sugar

8.3.3 Diversion support
-----------------------

M4sugar makes heavy use of diversions under the hood, because it is
often the case that text that must appear early in the output is not
discovered until late in the input.  Additionally, some of the
topological sorting algorithms used in resolving macro dependencies use
diversions.  However, most macros should not need to change diversions
directly, but rather rely on higher-level M4sugar macros to manage
diversions transparently.  If you change diversions improperly, you risk
generating a syntactically invalid script, because an incorrect
diversion will violate assumptions made by many macros about whether
prerequisite text has been previously output.  In short, if you manually
change the diversion, you should not expect any macros provided by the
Autoconf package to work until you have restored the diversion stack
back to its original state.

   In the rare case that it is necessary to write a macro that
explicitly outputs text to a different diversion, it is important to be
aware of an M4 limitation regarding diversions: text only goes to a
diversion if it is not part of argument collection.  Therefore, any
macro that changes the current diversion cannot be used as an unquoted
argument to another macro, but must be expanded at the top level.  The
macro ‘m4_expand’ will diagnose any attempt to change diversions, since
it is generally useful only as an argument to another macro.  The
following example shows what happens when diversion manipulation is
attempted within macro arguments:

     m4_do([normal text]
     m4_divert_push([KILL])unwanted[]m4_divert_pop([KILL])
     [m4_divert_push([KILL])discarded[]m4_divert_pop([KILL])])dnl
     ⇒normal text
     ⇒unwanted

Notice that the unquoted text ‘unwanted’ is output, even though it was
processed while the current diversion was ‘KILL’, because it was
collected as part of the argument to ‘m4_do’.  However, the text
‘discarded’ disappeared as desired, because the diversion changes were
single-quoted, and were not expanded until the top-level rescan of the
output of ‘m4_do’.

   To make diversion management easier, M4sugar uses the concept of
named diversions.  Rather than using diversion numbers directly, it is
nicer to associate a name with each diversion.  The diversion number
associated with a particular diversion name is an implementation detail,
and a syntax warning is issued if a diversion number is used instead of
a name.  In general, you should not output text to a named diversion
until after calling the appropriate initialization routine for your
language (‘m4_init’, ‘AS_INIT’, ‘AT_INIT’, ...), although there are some
exceptions documented below.

   M4sugar defines two named diversions.
‘KILL’
     Text written to this diversion is discarded.  This is the default
     diversion once M4sugar is initialized.
‘GROW’
     This diversion is used behind the scenes by topological sorting
     macros, such as ‘AC_REQUIRE’.

   M4sh adds several more named diversions.
‘BINSH’
     This diversion is reserved for the ‘#!’ interpreter line.
‘HEADER-REVISION’
     This diversion holds text from ‘AC_REVISION’.
‘HEADER-COMMENT’
     This diversion holds comments about the purpose of a file.
‘HEADER-COPYRIGHT’
     This diversion is managed by ‘AC_COPYRIGHT’.
‘M4SH-SANITIZE’
     This diversion contains M4sh sanitization code, used to ensure M4sh
     is executing in a reasonable shell environment.
‘M4SH-INIT’
     This diversion contains M4sh initialization code, initializing
     variables that are required by other M4sh macros.
‘BODY’
     This diversion contains the body of the shell code, and is the
     default diversion once M4sh is initialized.

   Autotest inherits diversions from M4sh, and changes the default
diversion from ‘BODY’ back to ‘KILL’.  It also adds several more named
diversions, with the following subset designed for developer use.
‘PREPARE_TESTS’
     This diversion contains initialization sequences which are executed
     after ‘atconfig’ and ‘atlocal’, and after all command line
     arguments have been parsed, but prior to running any tests.  It can
     be used to set up state that is required across all tests.  This
     diversion will work even before ‘AT_INIT’.

   Autoconf inherits diversions from M4sh, and adds the following named
diversions which developers can utilize.
‘DEFAULTS’
     This diversion contains shell variable assignments to set defaults
     that must be in place before arguments are parsed.  This diversion
     is placed early enough in ‘configure’ that it is unsafe to expand
     any autoconf macros into this diversion.
‘HELP_ENABLE’
     If ‘AC_PRESERVE_HELP_ORDER’ was used, then text placed in this
     diversion will be included as part of a quoted here-doc providing
     all of the ‘--help’ output of ‘configure’ related to options
     created by ‘AC_ARG_WITH’ and ‘AC_ARG_ENABLE’.
‘INIT_PREPARE’
     This diversion occurs after all command line options have been
     parsed, but prior to the main body of the ‘configure’ script.  This
     diversion is the last chance to insert shell code such as variable
     assignments or shell function declarations that will used by the
     expansion of other macros.

   For now, the remaining named diversions of Autoconf, Autoheader, and
Autotest are not documented.  In other words, intentionally outputting
text into an undocumented diversion is subject to breakage in a future
release of Autoconf.

 -- Macro: m4_cleardivert (DIVERSION...)
     Permanently discard any text that has been diverted into DIVERSION.

 -- Macro: m4_divert_once (DIVERSION, [CONTENT])
     Similar to ‘m4_divert_text’, except that CONTENT is only output to
     DIVERSION if this is the first time that ‘m4_divert_once’ has been
     called with its particular arguments.

 -- Macro: m4_divert_pop ([DIVERSION])
     If provided, check that the current diversion is indeed DIVERSION.
     Then change to the diversion located earlier on the stack, giving
     an error if an attempt is made to pop beyond the initial m4sugar
     diversion of ‘KILL’.

 -- Macro: m4_divert_push (DIVERSION)
     Remember the former diversion on the diversion stack, and output
     subsequent text into DIVERSION.  M4sugar maintains a diversion
     stack, and issues an error if there is not a matching pop for every
     push.

 -- Macro: m4_divert_text (DIVERSION, [CONTENT])
     Output CONTENT and a newline into DIVERSION, without affecting the
     current diversion.  Shorthand for:
          m4_divert_push([DIVERSION])CONTENT
          m4_divert_pop([DIVERSION])dnl

     One use of ‘m4_divert_text’ is to develop two related macros, where
     macro ‘MY_A’ does the work, but adjusts what work is performed
     based on whether the optional macro ‘MY_B’ has also been expanded.
     Of course, it is possible to use ‘AC_BEFORE’ within ‘MY_A’ to
     require that ‘MY_B’ occurs first, if it occurs at all.  But this
     imposes an ordering restriction on the user; it would be nicer if
     macros ‘MY_A’ and ‘MY_B’ can be invoked in either order.  The trick
     is to let ‘MY_B’ leave a breadcrumb in an early diversion, which
     ‘MY_A’ can then use to determine whether ‘MY_B’ has been expanded.

          AC_DEFUN([MY_A],
          [# various actions
          if test -n "$b_was_used"; then
            # extra action
          fi])
          AC_DEFUN([MY_B],
          [AC_REQUIRE([MY_A])dnl
          m4_divert_text([INIT_PREPARE], [b_was_used=true])])

 -- Macro: m4_init
     Initialize the M4sugar environment, setting up the default named
     diversion to be ‘KILL’.

© manpagez.com 2000-2025
Individual documents may contain additional copyright information.