📄 m4sugar.m4
字号:
# same as the one in which macro are expanded. (The bug above can# indeed be described as: a macro has been AC_PROVIDE'd, but it is# emitted after: the lack of correlation between emission and expansion# order is guilty).## How to do that? You keeping the stack of diversions to elaborate the# macros, but each time a macro is fully expanded, emit it immediately.## In the example above, when TEST2a is expanded, but it's epilogue is# not run yet, you have:## GROW - 2:# GROW - 1: TEST2a# GROW: Elaboration of TEST1# BODY:## The epilogue of TEST2a emits it immediately:## GROW - 2:# GROW - 1:# GROW: Elaboration of TEST1# BODY: TEST2a## TEST2b then requires TEST3, so right before the epilogue of TEST3, you# have:## GROW - 2: TEST3# GROW - 1: Elaboration of TEST2b# GROW: Elaboration of TEST1# BODY: TEST2a## The epilogue of TEST3 emits it:## GROW - 2:# GROW - 1: Elaboration of TEST2b# GROW: Elaboration of TEST1# BODY: TEST2a; TEST3## TEST2b is now completely expanded, and emitted:## GROW - 2:# GROW - 1:# GROW: Elaboration of TEST1# BODY: TEST2a; TEST3; TEST2b## and finally, TEST1 is finished and emitted:## GROW - 2:# GROW - 1:# GROW:# BODY: TEST2a; TEST3; TEST2b: TEST1## The idea, is simple, but the implementation is a bit evolved. If you# are like me, you will want to see the actual functioning of this# implementation to be convinced. The next section gives the full# details.### The Axel Thimm implementation at work# -------------------------------------## We consider the macros above, and this configure.ac:## AC_INIT# TEST1## You should keep the definitions of _m4_defun_pro, _m4_defun_epi, and# m4_require at hand to follow the steps.## This implements tries not to assume that of the current diversion is# BODY, so as soon as a macro (m4_defun'd) is expanded, we first# record the current diversion under the name _m4_divert_dump (denoted# DUMP below for short). This introduces an important difference with# the previous versions of Autoconf: you cannot use m4_require if you# were not inside an m4_defun'd macro, and especially, you cannot# m4_require directly from the top level.## We have not tried to simulate the old behavior (better yet, we# diagnose it), because it is too dangerous: a macro m4_require'd from# the top level is expanded before the body of `configure', i.e., before# any other test was run. I let you imagine the result of requiring# AC_STDC_HEADERS for instance, before AC_PROG_CC was actually run....## After AC_INIT was run, the current diversion is BODY.# * AC_INIT was run# DUMP: undefined# diversion stack: BODY |-## * TEST1 is expanded# The prologue of TEST1 sets AC_DIVERSION_DUMP, which is the diversion# where the current elaboration will be dumped, to the current# diversion. It also m4_divert_push to GROW, where the full# expansion of TEST1 and its dependencies will be elaborated.# DUMP: BODY# BODY: empty# diversions: GROW, BODY |-## * TEST1 requires TEST2a: prologue# m4_require m4_divert_pushes another temporary diversion GROW - 1 (in# fact, the diversion whose number is one less than the current# diversion), and expands TEST2a in there.# DUMP: BODY# BODY: empty# diversions: GROW-1, GROW, BODY |-## * TEST2a is expanded.# Its prologue pushes the current diversion again.# DUMP: BODY# BODY: empty# diversions: GROW - 1, GROW - 1, GROW, BODY |-# It is expanded in GROW - 1, and GROW - 1 is popped by the epilogue# of TEST2a.# DUMP: BODY# BODY: nothing# GROW - 1: TEST2a# diversions: GROW - 1, GROW, BODY |-## * TEST1 requires TEST2a: epilogue# The content of the current diversion is appended to DUMP (and removed# from the current diversion). A diversion is popped.# DUMP: BODY# BODY: TEST2a# diversions: GROW, BODY |-## * TEST1 requires TEST2b: prologue# m4_require pushes GROW - 1 and expands TEST2b.# DUMP: BODY# BODY: TEST2a# diversions: GROW - 1, GROW, BODY |-## * TEST2b is expanded.# Its prologue pushes the current diversion again.# DUMP: BODY# BODY: TEST2a# diversions: GROW - 1, GROW - 1, GROW, BODY |-# The body is expanded here.## * TEST2b requires TEST3: prologue# m4_require pushes GROW - 2 and expands TEST3.# DUMP: BODY# BODY: TEST2a# diversions: GROW - 2, GROW - 1, GROW - 1, GROW, BODY |-## * TEST3 is expanded.# Its prologue pushes the current diversion again.# DUMP: BODY# BODY: TEST2a# diversions: GROW-2, GROW-2, GROW-1, GROW-1, GROW, BODY |-# TEST3 requires TEST2a, but TEST2a has already been AC_PROVIDE'd, so# nothing happens. It's body is expanded here, and its epilogue pops a# diversion.# DUMP: BODY# BODY: TEST2a# GROW - 2: TEST3# diversions: GROW - 2, GROW - 1, GROW - 1, GROW, BODY |-## * TEST2b requires TEST3: epilogue# The current diversion is appended to DUMP, and a diversion is popped.# DUMP: BODY# BODY: TEST2a; TEST3# diversions: GROW - 1, GROW - 1, GROW, BODY |-# The content of TEST2b is expanded here.# DUMP: BODY# BODY: TEST2a; TEST3# GROW - 1: TEST2b,# diversions: GROW - 1, GROW - 1, GROW, BODY |-# The epilogue of TEST2b pops a diversion.# DUMP: BODY# BODY: TEST2a; TEST3# GROW - 1: TEST2b,# diversions: GROW - 1, GROW, BODY |-## * TEST1 requires TEST2b: epilogue# The current diversion is appended to DUMP, and a diversion is popped.# DUMP: BODY# BODY: TEST2a; TEST3; TEST2b# diversions: GROW, BODY |-## * TEST1 is expanded: epilogue# TEST1's own content is in GROW, and it's epilogue pops a diversion.# DUMP: BODY# BODY: TEST2a; TEST3; TEST2b# GROW: TEST1# diversions: BODY |-# Here, the epilogue of TEST1 notices the elaboration is done because# DUMP and the current diversion are the same, it then undiverts# GROW by hand, and undefines DUMP.# DUMP: undefined# BODY: TEST2a; TEST3; TEST2b; TEST1# diversions: BODY |-### 2. Keeping track of the expansion stack# =======================================## When M4 expansion goes wrong it is often extremely hard to find the# path amongst macros that drove to the failure. What is needed is# the stack of macro `calls'. One could imagine that GNU M4 would# maintain a stack of macro expansions, unfortunately it doesn't, so# we do it by hand. This is of course extremely costly, but the help# this stack provides is worth it. Nevertheless to limit the# performance penalty this is implemented only for m4_defun'd macros,# not for define'd macros.## The scheme is simplistic: each time we enter an m4_defun'd macros,# we prepend its name in m4_expansion_stack, and when we exit the# macro, we remove it (thanks to pushdef/popdef).## In addition, we want to use the expansion stack to detect circular# m4_require dependencies. This means we need to browse the stack to# check whether a macro being expanded is m4_require'd. For ease of# implementation, and certainly for the benefit of performances, we# don't browse the m4_expansion_stack, rather each time we expand a# macro FOO we define _m4_expanding(FOO). Then m4_require(BAR) simply# needs to check whether _m4_expanding(BAR) is defined to diagnose a# circular dependency.## To improve the diagnostic, in addition to keeping track of the stack# of macro calls, m4_expansion_stack also records the m4_require# stack. Note that therefore an m4_defun'd macro being required will# appear twice in the stack: the first time because it is required,# the second because it is expanded. We can avoid this, but it has# two small drawbacks: (i) the implementation is slightly more# complex, and (ii) it hides the difference between define'd macros# (which don't appear in m4_expansion_stack) and m4_defun'd macros# (which do). The more debugging information, the better.# m4_expansion_stack_push(TEXT)# -----------------------------m4_define([m4_expansion_stack_push],[m4_pushdef([m4_expansion_stack], [$1]m4_ifdef([m4_expansion_stack], [m4_defn([m4_expansion_stack])]))])# m4_expansion_stack_pop# ----------------------# Dump the expansion stack.m4_define([m4_expansion_stack_pop],[m4_popdef([m4_expansion_stack])])# m4_expansion_stack_dump# -----------------------# Dump the expansion stack.m4_define([m4_expansion_stack_dump],[m4_ifdef([m4_expansion_stack], [m4_errprintn(m4_defn([m4_expansion_stack]))])dnlm4_errprintn(m4_location[: the top level])])# _m4_divert(GROW)# ----------------# This diversion is used by the m4_defun/m4_require machinery. It is# important to keep room before GROW because for each nested# AC_REQUIRE we use an additional diversion (i.e., two m4_require's# will use GROW - 2. More than 3 levels has never seemed to be# needed.)## ...# - GROW - 2# m4_require'd code, 2 level deep# - GROW - 1# m4_require'd code, 1 level deep# - GROW# m4_defun'd macros are elaborated here.m4_define([_m4_divert(GROW)], 10000)# _m4_defun_pro(MACRO-NAME)# -------------------------# The prologue for Autoconf macros.m4_define([_m4_defun_pro],[m4_expansion_stack_push(m4_defn([m4_location($1)])[: $1 is expanded from...])dnlm4_pushdef([_m4_expanding($1)])dnlm4_ifdef([_m4_divert_dump], [m4_divert_push(m4_defn([_m4_divert_diversion]))], [m4_copy([_m4_divert_diversion], [_m4_divert_dump])dnlm4_divert_push([GROW])])dnl])# _m4_defun_epi(MACRO-NAME)# -------------------------# The Epilogue for Autoconf macros. MACRO-NAME only helps tracing# the PRO/EPI pairs.m4_define([_m4_defun_epi],[m4_divert_pop()dnlm4_if(_m4_divert_dump, _m4_divert_diversion, [m4_undivert([GROW])dnlm4_undefine([_m4_divert_dump])])dnlm4_expansion_stack_pop()dnlm4_popdef([_m4_expanding($1)])dnlm4_provide([$1])dnl])# m4_defun(NAME, EXPANSION)# -------------------------# Define a macro which automatically provides itself. Add machinery# so the macro automatically switches expansion to the diversion# stack if it is not already using it. In this case, once finished,# it will bring back all the code accumulated in the diversion stack.# This, combined with m4_require, achieves the topological ordering of# macros. We don't use this macro to define some frequently called# macros that are not involved in ordering constraints, to save m4# processing.m4_define([m4_defun],[m4_define([m4_location($1)], m4_location)dnlm4_define([$1], [_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])])])# m4_defun_once(NAME, EXPANSION)# ------------------------------# As m4_defun, but issues the EXPANSION only once, and warns if used# several times.m4_define([m4_defun_once],[m4_define([m4_location($1)], m4_location)dnlm4_define([$1], [m4_provide_if([$1], [m4_warn([syntax], [$1 invoked multiple times])], [_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])])])])# m4_pattern_forbid(ERE, [WHY])# -----------------------------# Declare that no token matching the extended regular expression ERE# should be seen in the output but if...m4_define([m4_pattern_forbid], [])# m4_pattern_allow(ERE)# ---------------------# ... but if that token matches the extended regular expression ERE.# Both used via traces.m4_define([m4_pattern_allow], [])## ----------------------------- #### Dependencies between macros. #### ----------------------------- ### m4_before(THIS-MACRO-NAME, CALLED-MACRO-NAME)# ---------------------------------------------m4_define([m4_before],[m4_provide_if([$2], [m4_warn([syntax], [$2 was called before $1])])])# m4_require(NAME-TO-CHECK, [BODY-TO-EXPAND = NAME-TO-CHECK])# -----------------------------------------------------------# If NAME-TO-CHECK has never been expanded (actually, if it is not# m4_provide'd), expand BODY-TO-EXPAND *before* the current macro# expansion. Once expanded, emit it in _m4_divert_dump. Keep track# of the m4_require chain in m4_expansion_stack.## The normal cases are:## - NAME-TO-CHECK == BODY-TO-EXPAND# Which you can use for regular macros with or without arguments, e.g.,# m4_require([AC_PROG_CC], [AC_PROG_CC])# m4_require([AC_CHECK_HEADERS(limits.h)], [AC_CHECK_HEADERS(limits.h)])# which is just the same as# m4_require([AC_PROG_CC])# m4_require([AC_CHECK_HEADERS(limits.h)])## - BODY-TO-EXPAND == m4_indir([NAME-TO-CHECK])# In the case of macros with irregular names. For instance:# m4_require([AC_LANG_COMPILER(C)], [indir([AC_LANG_COMPILER(C)])])# which means `if the macro named `AC_LANG_COMPILER(C)' (the parens are# part of the name, it is not an argument) has not been run, then# call it.'# Had you used# m4_require([AC_LANG_COMPILER(C)], [AC_LANG_COMPILER(C)])# then m4_require would have tried to expand `AC_LANG_COMPILER(C)', i.e.,# call the macro `AC_LANG_COMPILER' with `C' as argument.## You could argue that `AC_LANG_COMPILER', when it receives an argument# such as `C' should dispatch the call to `AC_LANG_COMPILER(C)'. But this# `extension' prevents `AC_LANG_COMPILER' from having actual arguments that# it passes to `AC_LANG_COMPILER(C)'.m4_define([m4_require],[m4_expansion_stack_push(m4_location[: $1 is required by...])dnlm4_ifdef([_m4_expanding($1)], [m4_fatal([$0: circular dependency of $1])])dnlm4_ifndef([_m4_divert_dump], [m4_fatal([$0: cannot be used outside of an m4_defun'd macro])])dnlm4_provide_if([$1], [], [m4_divert_push(m4_eval(m4_divnum - 1))dnlm4_default([$2], [$1])m4_divert(m4_defn([_m4_divert_dump]))dnlm4_undivert(m4_defn([_m4_divert_diversion]))dnlm4_divert_pop(m4_defn([_m4_divert_dump]))])dnlm4_provide_if([$1], [], [m4_warn([syntax], [$1 is m4_require'd but is not m4_defun'd])])dnlm4_expansion_stack_pop()dnl])# m4_expand_once(TEXT, [WITNESS = TEXT])# --------------------------------------# If TEXT has never been expanded, expand it *here*. Use WITNESS as# as a memory that TEXT has already been expanded.m4_define([m4_expand_once],[m4_provide_if(m4_ifval([$2], [[$2]], [[$1]]), [], [m4_provide(m4_ifval([$2], [[$2]], [[$1]]))[]$1])])# m4_provide(MACRO-NAME)# ----------------------m4_define([m4_provide],[m4_define([m4_provide($1)])])# m4_provide_if(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)# -------------------------------------------------------# If MACRO-NAME is provided do IF-PROVIDED, else IF-NOT-PROVIDED.# The purpose of this macro is to provide the user with a means to# check macros which are provided without letting her know how the# information is coded.m4_define([m4_provide_if],[m4_ifdef([m4_provide($1)], [$2], [$3])])## -------------------- #### 9. Text processing. #### -------------------- ### m4_cr_letters# m4_cr_LETTERS# m4_cr_Letters# -------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -