]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Optimize clients of AS_REQUIRE.
authorEric Blake <ebb9@byu.net>
Thu, 23 Oct 2008 21:08:45 +0000 (15:08 -0600)
committerEric Blake <ebb9@byu.net>
Fri, 24 Oct 2008 13:13:17 +0000 (07:13 -0600)
* lib/m4sugar/m4sugar.m4 (m4_defun): Add undocumented third
argument.
(m4_defun_init): New undocumented macro.
* lib/m4sugar/m4sh.m4 (_AS_ECHO_LOG, AS_MESSAGE, AS_BASENAME)
(_AS_DIRNAME_EXPR, AS_DIRNAME, AS_ECHO, AS_ECHO_N, AS_TEST_X)
(AS_LN_S, AS_MKDIR_P, _AS_PATH_WALK, AS_VERSION_COMPARE)
(AS_TR_SH, AS_TR_CPP, AS_VAR_APPEND, AS_VAR_PUSHDEF): Use it to
simplify these macros once the one-shot initialization is
complete.
* tests/m4sugar.at (m4@&t@_require: one-shot initialization): New
test.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
lib/m4sugar/m4sh.m4
lib/m4sugar/m4sugar.m4
tests/m4sugar.at

index f8361b7955a49fb4ece9a0759730d9b14f8d5267..ac48cd9b64132ab9c98191e83d9ee2b62ee31958 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2008-10-24  Eric Blake  <ebb9@byu.net>
 
+       Optimize clients of AS_REQUIRE.
+       * lib/m4sugar/m4sugar.m4 (m4_defun): Add undocumented third
+       argument.
+       (m4_defun_init): New undocumented macro.
+       * lib/m4sugar/m4sh.m4 (_AS_ECHO_LOG, AS_MESSAGE, AS_BASENAME)
+       (_AS_DIRNAME_EXPR, AS_DIRNAME, AS_ECHO, AS_ECHO_N, AS_TEST_X)
+       (AS_LN_S, AS_MKDIR_P, _AS_PATH_WALK, AS_VERSION_COMPARE)
+       (AS_TR_SH, AS_TR_CPP, AS_VAR_APPEND, AS_VAR_PUSHDEF): Use it to
+       simplify these macros once the one-shot initialization is
+       complete.
+       * tests/m4sugar.at (m4@&t@_require: one-shot initialization): New
+       test.
+
        Improve m4_copy.
        * lib/m4sugar/m4sugar.m4 (m4_copy): Add second implementation for
        public use.
index b96ec09df5265a6c74313eed0f6f2ab6ca8649c2..6620a565c50c371159ef84e9d5e60ea37a12e15d 100644 (file)
@@ -648,8 +648,8 @@ m4_define([_AS_ECHO],
 # _AS_ECHO_LOG(STRING)
 # --------------------
 # Log the string to AS_MESSAGE_LOG_FD.
-m4_define([_AS_ECHO_LOG],
-[AS_REQUIRE([_AS_LINENO_PREPARE])]dnl
+m4_defun_init([_AS_ECHO_LOG],
+[AS_REQUIRE([_AS_LINENO_PREPARE])],
 [_AS_ECHO([$as_me:${as_lineno-$LINENO}: $1], [AS_MESSAGE_LOG_FD])])
 
 
@@ -685,8 +685,9 @@ m4_define([_AS_ECHO_N],
 
 # AS_MESSAGE(STRING, [FD = AS_MESSAGE_FD])
 # ----------------------------------------
-m4_define([AS_MESSAGE],
-[AS_REQUIRE([_AS_ME_PREPARE])]dnl
+# Output "`basename $0`: "STRING to the open file FD.
+m4_defun_init([AS_MESSAGE],
+[AS_REQUIRE([_AS_ME_PREPARE])],
 [m4_ifset([AS_MESSAGE_LOG_FD],
          [{ _AS_ECHO_LOG([$1])
 _AS_ECHO([$as_me: $1], [$2]);}],
@@ -757,8 +758,8 @@ m4_defun([_AS_BASENAME_SED],
          }
          s/.*/./; q']])
 
-m4_defun([AS_BASENAME],
-[AS_REQUIRE([_$0_PREPARE])]dnl
+m4_defun_init([AS_BASENAME],
+[AS_REQUIRE([_$0_PREPARE])],
 [$as_basename -- $1 ||
 _AS_BASENAME_EXPR([$1]) 2>/dev/null ||
 _AS_BASENAME_SED([$1])])
@@ -768,8 +769,7 @@ _AS_BASENAME_SED([$1])])
 # --------------------
 # Avoid Solaris 9 /usr/ucb/basename, as `basename /' outputs an empty line.
 # Also, traditional basename mishandles --.  Require here _AS_EXPR_PREPARE,
-# to avoid problems when _AS_BASENAME is called from the M4SH-INIT diversion
-# (AS_REQUIRE is nowhere near being as sophisticated as AC_REQUIRE).
+# to avoid problems when _AS_BASENAME is called from the M4SH-INIT diversion.
 m4_defun([_AS_BASENAME_PREPARE],
 [AS_REQUIRE([_AS_EXPR_PREPARE])]dnl
 [if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
@@ -791,8 +791,8 @@ fi
 # a silly length limit that causes expr to fail if the matched
 # substring is longer than 120 bytes.  So fall back on echo|sed if
 # expr fails.
-m4_defun([_AS_DIRNAME_EXPR],
-[AS_REQUIRE([_AS_EXPR_PREPARE])]dnl
+m4_defun_init([_AS_DIRNAME_EXPR],
+[AS_REQUIRE([_AS_EXPR_PREPARE])],
 [$as_expr X[]$1 : 'X\(.*[[^/]]\)//*[[^/][^/]]*/*$' \| \
         X[]$1 : 'X\(//\)[[^/]]' \| \
         X[]$1 : 'X\(//\)$' \| \
@@ -818,8 +818,8 @@ m4_defun([_AS_DIRNAME_SED],
          }
          s/.*/./; q']])
 
-m4_defun([AS_DIRNAME],
-[AS_REQUIRE([_$0_PREPARE])]dnl
+m4_defun_init([AS_DIRNAME],
+[AS_REQUIRE([_$0_PREPARE])],
 [$as_dirname -- $1 ||
 _AS_DIRNAME_EXPR([$1]) 2>/dev/null ||
 _AS_DIRNAME_SED([$1])])
@@ -842,16 +842,16 @@ fi
 # Output WORD followed by a newline.  WORD must be a single shell word
 # (typically a quoted string).  The bytes of WORD are output as-is, even
 # if it starts with "-" or contains "\".
-m4_defun([AS_ECHO],
-[AS_REQUIRE([_$0_PREPARE])]dnl
+m4_defun_init([AS_ECHO],
+[AS_REQUIRE([_$0_PREPARE])],
 [$as_echo $1])
 
 
 # AS_ECHO_N(WORD)
 # -------------
 # Like AS_ECHO(WORD), except do not output the trailing newline.
-m4_defun([AS_ECHO_N],
-[AS_REQUIRE([_AS_ECHO_PREPARE])]dnl
+m4_defun_init([AS_ECHO_N],
+[AS_REQUIRE([_AS_ECHO_PREPARE])],
 [$as_echo_n $1])
 
 
@@ -898,16 +898,16 @@ fi
 # AS_TEST_X
 # ---------
 # Check whether a file has executable or search permissions.
-m4_defun([AS_TEST_X],
-[AS_REQUIRE([_AS_TEST_PREPARE])]dnl
+m4_defun_init([AS_TEST_X],
+[AS_REQUIRE([_AS_TEST_PREPARE])],
 [$as_test_x $1[]])# AS_TEST_X
 
 
 # AS_EXECUTABLE_P
 # ---------------
 # Check whether a file is a regular file that has executable permissions.
-m4_defun([AS_EXECUTABLE_P],
-[AS_REQUIRE([_AS_TEST_PREPARE])]dnl
+m4_defun_init([AS_EXECUTABLE_P],
+[AS_REQUIRE([_AS_TEST_PREPARE])],
 [{ test -f $1 && AS_TEST_X([$1]); }])# AS_EXECUTABLE_P
 
 
@@ -1045,8 +1045,8 @@ rmdir conf$$.dir 2>/dev/null
 # -------------------
 # FIXME: Should we add the glue code to handle properly relative symlinks
 # simulated with `ln' or `cp'?
-m4_defun([AS_LN_S],
-[AS_REQUIRE([_AS_LN_S_PREPARE])]dnl
+m4_defun_init([AS_LN_S],
+[AS_REQUIRE([_AS_LN_S_PREPARE])],
 [$as_ln_s $1 $2])
 
 
@@ -1077,8 +1077,8 @@ m4_define([_AS_MKDIR_P],
 # AS_MKDIR_P(DIR)
 # ---------------
 # Emulate `mkdir -p' with plain `mkdir' if needed.
-m4_define([AS_MKDIR_P],
-[AS_REQUIRE([_$0_PREPARE])]dnl
+m4_defun_init([AS_MKDIR_P],
+[AS_REQUIRE([_$0_PREPARE])],
 [as_dir=$1; as_func_mkdir_p])# AS_MKDIR_P
 
 
@@ -1126,8 +1126,8 @@ fi
 # expansions, not on literal text.  This closes a longstanding sh security
 # hole.  Optimize it away when not needed, i.e., if there are no literal
 # path separators.
-m4_define([_AS_PATH_WALK],
-[AS_REQUIRE([_AS_PATH_SEPARATOR_PREPARE])]dnl
+m4_defun_init([_AS_PATH_WALK],
+[AS_REQUIRE([_AS_PATH_SEPARATOR_PREPARE])],
 [as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 m4_bmatch([$1], [[:;]],
 [as_dummy="$1"
@@ -1498,8 +1498,8 @@ m4_defun([_AS_VERSION_COMPARE_PREPARE],
 #
 # This usage is portable even to ancient awk,
 # so don't worry about finding a "nice" awk version.
-m4_defun([AS_VERSION_COMPARE],
-[AS_REQUIRE([_$0_PREPARE])]dnl
+m4_defun_init([AS_VERSION_COMPARE],
+[AS_REQUIRE([_$0_PREPARE])],
 [as_arg_v1=$1
 as_arg_v2=$2
 awk "$as_awk_strverscmp" v1="$as_arg_v1" v2="$as_arg_v2" /dev/null
@@ -1557,8 +1557,8 @@ as_tr_sh="eval sed 'y%*+%pp%;s%[[^_$as_cr_alnum]]%_%g'"
 # fact to skip worrying about the length of m4_cr_not_symbols2.
 #
 # For speed, we inline the literal definitions that can be computed up front.
-m4_defun([AS_TR_SH],
-[AS_REQUIRE([_$0_PREPARE])]dnl
+m4_defun_init([AS_TR_SH],
+[AS_REQUIRE([_$0_PREPARE])],
 [AS_LITERAL_IF([$1],
              [m4_translit([$1], [*+[]]]]dnl
 m4_dquote(m4_dquote(m4_defn([m4_cr_not_symbols2])))[[,
@@ -1584,8 +1584,8 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[[^_$as_cr_alnum]]%_%g
 # of `$as_tr_cpp' if you change this.
 #
 # See implementation comments in AS_TR_SH.
-m4_defun([AS_TR_CPP],
-[AS_REQUIRE([_$0_PREPARE])]dnl
+m4_defun_init([AS_TR_CPP],
+[AS_REQUIRE([_$0_PREPARE])],
 [AS_LITERAL_IF([$1],
              [m4_translit([$1], [*[]]]]dnl
 m4_dquote(m4_dquote(m4_defn([m4_cr_letters])m4_defn([m4_cr_not_symbols2])))[[,
@@ -1659,9 +1659,9 @@ m4_define([_AS_VAR_APPEND_WORKS],
 # contents of VAR outweigh the typical VALUE size of repeated appends.
 # Note that unlike AS_VAR_SET, VALUE must be properly quoted to avoid
 # field splitting and file name expansion.
-m4_define([AS_VAR_APPEND],
+m4_defun_init([AS_VAR_APPEND],
 [_AS_DETECT_SUGGESTED([_AS_VAR_APPEND_WORKS])]dnl
-[AS_REQUIRE([_AS_VAR_APPEND_PREPARE], [], [M4SH-INIT-FN])]dnl
+[AS_REQUIRE([_AS_VAR_APPEND_PREPARE], [], [M4SH-INIT-FN])],
 [as_func_append $1 $2])
 
 
@@ -1741,8 +1741,8 @@ m4_define([AS_VAR_POPDEF],
 # calls that trigger AS_LITERAL_IF([VARNAME]), and that macro performs
 # expansion inside an argument collection context, where diversions
 # don't work.  Therefore, we must require the preparation ourselves.
-m4_define([AS_VAR_PUSHDEF],
-[AS_REQUIRE([_AS_TR_SH_PREPARE])]dnl
+m4_defun_init([AS_VAR_PUSHDEF],
+[AS_REQUIRE([_AS_TR_SH_PREPARE])],
 [AS_LITERAL_IF([$2],
               [m4_pushdef([$1], [AS_TR_SH($2)])],
               [as_$1=AS_TR_SH($2)
index d0fe9adee2c05f92a7157ef3bac95c145bb03e3e..13a1ddb2bc67e29bef640f5afbf79b849f90617e 100644 (file)
@@ -1644,25 +1644,51 @@ m4_define([m4_divert_require],
   [_m4_require_call([$2], [$3], [$1])])])
 
 
-# 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_defun(NAME, EXPANSION, [MACRO = m4_define])
+# ----------------------------------------------
+# Define a macro NAME which automatically provides itself.  Add
+# machinery so the macro automatically switches expansion to the
+# diversion stack if it is not already using it, prior to EXPANSION.
+# 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.
+#
+# MACRO is an undocumented argument; when set to m4_pushdef, and NAME
+# is already defined, the new definition is added to the pushdef
+# stack, rather than overwriting the current definition.  It can thus
+# be used to write self-modifying macros, which pop themselves to a
+# previously m4_define'd definition so that subsequent use of the
+# macro is faster.
 m4_define([m4_defun],
 [m4_define([m4_location($1)], m4_location)dnl
-m4_define([$1],
+m4_default([$3], [m4_define])([$1],
          [_m4_defun_pro([$1])$2[]_m4_defun_epi([$1])])])
 
 
+# m4_defun_init(NAME, INIT, COMMON)
+# ---------------------------------
+# Like m4_defun, but split EXPANSION into two portions: INIT which is
+# done only the first time NAME is invoked, and COMMON which is
+# expanded every time.
+#
+# For now, the COMMON definition is always m4_define'd, giving an even
+# lighter-weight definition.  m4_defun allows self-providing, but once
+# a macro is provided, m4_require no longer cares if it is m4_define'd
+# or m4_defun'd.  m4_defun also provides location tracking to identify
+# dependency bugs, but once the INIT has been expanded, we know there
+# are no dependency bugs.  However, if a future use needs COMMON to be
+# m4_defun'd, we can add a parameter, similar to the third parameter
+# to m4_defun.
+m4_define([m4_defun_init],
+[m4_define([$1], [$3])m4_defun([$1],
+   [$2[]_m4_popdef(]m4_dquote([$][0])[)$][0($][@)], [m4_pushdef])])
+
+
 # m4_defun_once(NAME, EXPANSION)
 # ------------------------------
-# As m4_defun, but issues the EXPANSION only once, and warns if used
+# Like 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)dnl
index deb6f8ca453aa2e6640b8ba83eb47a94bd25a613..cfaed3bf6372e6dd9e8393944352c3ac5c2052c2 100644 (file)
@@ -195,6 +195,31 @@ autom4te: m4 failed with exit status: 1
 AT_CLEANUP
 
 
+## ---------------------- ##
+## m4_require: one-shot.  ##
+## ---------------------- ##
+
+AT_SETUP([m4@&t@_require: one-shot initialization])
+AT_KEYWORDS([m4@&t@_defun_init])
+
+AT_CHECK_M4SUGAR_TEXT([[
+m4_defun_init([a], [[init a
+]], [[common a]])dnl
+m4_defun([b], [[b]m4_require([a])])dnl
+m4_defun([c], [[c]m4_require([a])])dnl
+b
+c
+a
+]], [[
+init a
+common a
+b
+c
+common a
+]])
+AT_CLEANUP
+
+
 ## --------- ##
 ## m4_cond.  ##
 ## --------- ##