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