autoconf: Diversion support

1 
1 8.3.3 Diversion support
1 -----------------------
1 
1 M4sugar makes heavy use of diversions under the hood, because it is
1 often the case that text that must appear early in the output is not
1 discovered until late in the input.  Additionally, some of the
1 topological sorting algorithms used in resolving macro dependencies use
1 diversions.  However, most macros should not need to change diversions
1 directly, but rather rely on higher-level M4sugar macros to manage
1 diversions transparently.  If you change diversions improperly, you
1 risk generating a syntactically invalid script, because an incorrect
1 diversion will violate assumptions made by many macros about whether
1 prerequisite text has been previously output.  In short, if you
1 manually change the diversion, you should not expect any macros
1 provided by the Autoconf package to work until you have restored the
1 diversion stack back to its original state.
1 
1    In the rare case that it is necessary to write a macro that
1 explicitly outputs text to a different diversion, it is important to be
1 aware of an M4 limitation regarding diversions: text only goes to a
1 diversion if it is not part of argument collection.  Therefore, any
1 macro that changes the current diversion cannot be used as an unquoted
1 argument to another macro, but must be expanded at the top level.  The
1 macro `m4_expand' will diagnose any attempt to change diversions, since
1 it is generally useful only as an argument to another macro.  The
1 following example shows what happens when diversion manipulation is
1 attempted within macro arguments:
1 
1      m4_do([normal text]
1      m4_divert_push([KILL])unwanted[]m4_divert_pop([KILL])
1      [m4_divert_push([KILL])discarded[]m4_divert_pop([KILL])])dnl
1      =>normal text
1      =>unwanted
1 
1 Notice that the unquoted text `unwanted' is output, even though it was
1 processed while the current diversion was `KILL', because it was
1 collected as part of the argument to `m4_do'.  However, the text
1 `discarded' disappeared as desired, because the diversion changes were
1 single-quoted, and were not expanded until the top-level rescan of the
1 output of `m4_do'.
1 
1    To make diversion management easier, M4sugar uses the concept of
1 named diversions.  Rather than using diversion numbers directly, it is
1 nicer to associate a name with each diversion.  The diversion number
1 associated with a particular diversion name is an implementation
1 detail, and a syntax warning is issued if a diversion number is used
1 instead of a name.  In general, you should not output text to a named
1 diversion until after calling the appropriate initialization routine
1 for your language (`m4_init', `AS_INIT', `AT_INIT', ...), although
1 there are some exceptions documented below.
1 
1    M4sugar defines two named diversions.
1 `KILL'
1      Text written to this diversion is discarded.  This is the default
1      diversion once M4sugar is initialized.
1 
1 `GROW'
1      This diversion is used behind the scenes by topological sorting
1      macros, such as `AC_REQUIRE'.
1 
1    M4sh adds several more named diversions.
1 `BINSH'
1      This diversion is reserved for the `#!' interpreter line.
1 
1 `HEADER-REVISION'
1      This diversion holds text from `AC_REVISION'.
1 
1 `HEADER-COMMENT'
1      This diversion holds comments about the purpose of a file.
1 
1 `HEADER-COPYRIGHT'
1      This diversion is managed by `AC_COPYRIGHT'.
1 
1 `M4SH-SANITIZE'
1      This diversion contains M4sh sanitization code, used to ensure
1      M4sh is executing in a reasonable shell environment.
1 
1 `M4SH-INIT'
1      This diversion contains M4sh initialization code, initializing
1      variables that are required by other M4sh macros.
1 
1 `BODY'
1      This diversion contains the body of the shell code, and is the
1      default diversion once M4sh is initialized.
1 
1    Autotest inherits diversions from M4sh, and changes the default
1 diversion from `BODY' back to `KILL'.  It also adds several more named
1 diversions, with the following subset designed for developer use.
1 `PREPARE_TESTS'
1      This diversion contains initialization sequences which are executed
1      after `atconfig' and `atlocal', and after all command line
1      arguments have been parsed, but prior to running any tests.  It
1      can be used to set up state that is required across all tests.
1      This diversion will work even before `AT_INIT'.
1 
1    Autoconf inherits diversions from M4sh, and adds the following named
1 diversions which developers can utilize.
1 `DEFAULTS'
1      This diversion contains shell variable assignments to set defaults
1      that must be in place before arguments are parsed.  This diversion
1      is placed early enough in `configure' that it is unsafe to expand
1      any autoconf macros into this diversion.
1 
1 `HELP_ENABLE'
1      If `AC_PRESERVE_HELP_ORDER' was used, then text placed in this
1      diversion will be included as part of a quoted here-doc providing
1      all of the `--help' output of `configure' related to options
1      created by `AC_ARG_WITH' and `AC_ARG_ENABLE'.
1 
1 `INIT_PREPARE'
1      This diversion occurs after all command line options have been
1      parsed, but prior to the main body of the `configure' script.  This
1      diversion is the last chance to insert shell code such as variable
1      assignments or shell function declarations that will used by the
1      expansion of other macros.
1 
1    For now, the remaining named diversions of Autoconf, Autoheader, and
1 Autotest are not documented.  In other words, intentionally outputting
1 text into an undocumented diversion is subject to breakage in a future
1 release of Autoconf.
1 
1  -- Macro: m4_cleardivert (DIVERSION...)
1      Permanently discard any text that has been diverted into DIVERSION.
1 
1  -- Macro: m4_divert_once (DIVERSION, [CONTENT])
1      Similar to `m4_divert_text', except that CONTENT is only output to
1      DIVERSION if this is the first time that `m4_divert_once' has been
1      called with its particular arguments.
1 
1  -- Macro: m4_divert_pop ([DIVERSION])
1      If provided, check that the current diversion is indeed DIVERSION.
1      Then change to the diversion located earlier on the stack, giving
1      an error if an attempt is made to pop beyond the initial m4sugar
1      diversion of `KILL'.
1 
1  -- Macro: m4_divert_push (DIVERSION)
1      Remember the former diversion on the diversion stack, and output
1      subsequent text into DIVERSION.  M4sugar maintains a diversion
1      stack, and issues an error if there is not a matching pop for every
1      push.
1 
1  -- Macro: m4_divert_text (DIVERSION, [CONTENT])
1      Output CONTENT and a newline into DIVERSION, without affecting the
1      current diversion.  Shorthand for:
1           m4_divert_push([DIVERSION])CONTENT
1           m4_divert_pop([DIVERSION])dnl
1 
1      One use of `m4_divert_text' is to develop two related macros, where
1      macro `MY_A' does the work, but adjusts what work is performed
1      based on whether the optional macro `MY_B' has also been expanded.
1      Of course, it is possible to use `AC_BEFORE' within `MY_A' to
1      require that `MY_B' occurs first, if it occurs at all.  But this
1      imposes an ordering restriction on the user; it would be nicer if
1      macros `MY_A' and `MY_B' can be invoked in either order.  The trick
1      is to let `MY_B' leave a breadcrumb in an early diversion, which
1      `MY_A' can then use to determine whether `MY_B' has been expanded.
1 
1           AC_DEFUN([MY_A],
1           [# various actions
1           if test -n "$b_was_used"; then
1             # extra action
1           fi])
1           AC_DEFUN([MY_B],
1           [AC_REQUIRE([MY_A])dnl
1           m4_divert_text([INIT_PREPARE], [b_was_used=true])])
1 
1 
1  -- Macro: m4_init
1      Initialize the M4sugar environment, setting up the default named
1      diversion to be `KILL'.
1