[PATCH 5/5] use shell function for AS_BASENAME, AS_DIRNAME, AS_MKDIR_P

View: New views
4 Messages — Rating Filter:   Alert me  

[PATCH 5/5] use shell function for AS_BASENAME, AS_DIRNAME, AS_MKDIR_P

by Paolo Bonzini-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This patch defines shell functions for the various implementation
of basename/dirname/mkdir_p and changes macros such as AS_BASENAME
to simply dispatch to those macros.

Some care is needed to delay the definition of as_me, and to define
the shell functions in _AS_PREPARE for config.status.  There's also
a bug that _AS_LINENO_PREPARE was not using m4_defun.

I decided to stop having AS_PREPARE call _AS_PREPARE, because the
former can let _AS_BASENAME_PREPARE and friends expand shell functions,
while _AS_PREPARE (which is used for the prolog of config.status)
must do that on its own.

I made this into a single patch because it's a mess to separate
the initialization of shell functions in _AS_PREPARE.  Otherwise,
there's nothing that prevents from splitting it further.

2008-09-18  Paolo Bonzini  <bonzini@...>

        * m4sugar/m4sh.m4 (AS_SHELL_SANITIZE): Delay setting as_me
        until the M4SH-INIT diversion using _AS_ME_PREPARE.
        (_AS_PREPARE): Define shell functions.  Invoke _AS_EXPR_PREPARE
        before _AS_BASENAME_PREPARE (newly added) and _AS_DIRNAME_PREPARE, and
        _AS_BASENAME_PREPARE and _AS_ME_PREPARE before _AS_LINENO_PREPARE.
        (AS_PREPARE): Include all the AS_REQUIREs manually.
        (_AS_ME_PREPARE): New.
        (_AS_LINENO_PREPARE): Use m4_defun.

        (AS_BASENAME): Just dispatch to $as_basename.
        (_AS_BASENAME_EXPR): Do not require _AS_EXPR_PREPARE.
        (_AS_BASENAME_PREPARE): Do that here.  Test availability of
        basename and expr.  Define shell functions.

        (AS_DIRNAME): Just dispatch to $as_dirname.
        (_AS_DIRNAME_EXPR): Do not require _AS_EXPR_PREPARE.
        (_AS_DIRNAME_PREPARE): Do that here.  Test availability of
        basename and expr.  Define shell functions.

        (_AS_MKDIR_P): New, from AS_MKDIR_P.  Adjust meaning of as_mkdir_p
        to be `false' or a full `mkdir -p' command.
        (AS_MKDIR_P): Just dispatch to as_func_mkdir_p.
        (_AS_MKDIR_P_PREPARE): Set as_mkdir_p according to the above change.
        Define shell functions.
---
 lib/m4sugar/m4sh.m4 |   81 ++++++++++++++++++++++++++++++++++----------------
 1 files changed, 55 insertions(+), 26 deletions(-)

diff --git a/lib/m4sugar/m4sh.m4 b/lib/m4sugar/m4sh.m4
index a3ef690..4247144 100644
--- a/lib/m4sugar/m4sh.m4
+++ b/lib/m4sugar/m4sh.m4
@@ -396,12 +396,8 @@ export LC_ALL
 LANGUAGE=C
 export LANGUAGE
 
-# Required to use basename.
-_AS_EXPR_PREPARE
-_AS_BASENAME_PREPARE
-
-# Name of the executable.
-as_me=`AS_BASENAME("$[0]")`
+dnl Delay this until after shell functions are defined.
+AS_REQUIRE([_AS_ME_PREPARE])
 
 # CDPATH.
 $as_unset CDPATH
@@ -421,11 +417,32 @@ $as_unset CDPATH
 # there are so many _AS_PREPARE_* below, and that's also why it is
 # important not to forget some: config.status needs them.
 m4_defun([_AS_PREPARE],
-[_AS_LINENO_PREPARE
+[as_func_basename_expr() {
+  _AS_BASENAME_EXPR([$[]2])
+}
 
+as_func_basename_sed() {
+  _AS_BASENAME_SED([$[]2])
+}
+
+as_func_dirname_expr() {
+  _AS_DIRNAME_EXPR([$[]2])
+}
+
+as_func_dirname_sed() {
+  _AS_DIRNAME_SED([$[]2])
+}
+
+as_func_mkdir_p() {
+  _AS_MKDIR_P([$[]1])
+}
+
+_AS_EXPR_PREPARE
+_AS_BASENAME_PREPARE
 _AS_DIRNAME_PREPARE
+_AS_ME_PREPARE
+_AS_LINENO_PREPARE
 _AS_ECHO_N_PREPARE[]dnl We do not need this ourselves but user code might.
-_AS_EXPR_PREPARE
 _AS_LN_S_PREPARE
 _AS_MKDIR_P_PREPARE
 _AS_TEST_PREPARE
@@ -433,13 +450,23 @@ _AS_TR_CPP_PREPARE
 _AS_TR_SH_PREPARE
 ])
 
-
 # AS_PREPARE
 # ----------
 # Output all the M4sh possible initialization into the initialization
 # diversion.
 m4_defun([AS_PREPARE],
-[m4_divert_text([M4SH-INIT], [_AS_PREPARE])])
+[AS_REQUIRE([_AS_EXPR_PREPARE])
+AS_REQUIRE([_AS_BASENAME_PREPARE])
+AS_REQUIRE([_AS_DIRNAME_PREPARE])
+AS_REQUIRE([_AS_ME_PREPARE])
+AS_REQUIRE([_AS_LINENO_PREPARE])
+AS_REQUIRE([_AS_ECHO_N_PREPARE])
+AS_REQUIRE([_AS_LN_S_PREPARE])
+AS_REQUIRE([_AS_MKDIR_P_PREPARE])
+AS_REQUIRE([_AS_TEST_PREPARE])
+AS_REQUIRE([_AS_TR_CPP_PREPARE])
+AS_REQUIRE([_AS_TR_SH_PREPARE])
+])
 
 
 ## ----------------------------- ##
@@ -694,8 +721,7 @@ m4_define([AS_ERROR],
 # Also see the comments for AS_DIRNAME.
 
 m4_defun([_AS_BASENAME_EXPR],
-[AS_REQUIRE([_AS_EXPR_PREPARE])dnl
-$as_expr X/[]$1 : '.*/\([[^/][^/]*]\)/*$' \| \
+[$as_expr X/[]$1 : '.*/\([[^/][^/]*]\)/*$' \| \
  X[]$1 : 'X\(//\)$' \| \
  X[]$1 : 'X\(/\)' \| .])
 
@@ -717,9 +743,7 @@ m4_defun([_AS_BASENAME_SED],
 
 m4_defun([AS_BASENAME],
 [AS_REQUIRE([_$0_PREPARE])dnl
-$as_basename -- $1 ||
-_AS_BASENAME_EXPR([$1]) 2>/dev/null ||
-_AS_BASENAME_SED([$1])])
+$as_basename -- $1])
 
 
 # _AS_BASENAME_PREPARE
@@ -727,10 +751,17 @@ _AS_BASENAME_SED([$1])])
 # Avoid Solaris 9 /usr/ucb/basename, as `basename /' outputs an empty line.
 # Also, traditional basename mishandles --.
 m4_defun([_AS_BASENAME_PREPARE],
-[if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+[AS_REQUIRE([_AS_EXPR_PREPARE])dnl
+AS_REQUIRE_SHELL_FN([as_func_basename_expr],
+     [_AS_BASENAME_EXPR([$[]2]) 2>/dev/null])
+AS_REQUIRE_SHELL_FN([as_func_basename_sed],
+    [_AS_BASENAME_SED([$[]2])])
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
   as_basename=basename
+elif (as_func_basename_expr -- /) >/dev/null 2>&1; then
+  as_basename=as_func_basename_expr
 else
-  as_basename=false
+  as_basename=as_func_basename_sed
 fi
 ])# _AS_BASENAME_PREPARE
 
@@ -747,8 +778,7 @@ fi
 # 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
-$as_expr X[]$1 : 'X\(.*[[^/]]\)//*[[^/][^/]]*/*$' \| \
+[$as_expr X[]$1 : 'X\(.*[[^/]]\)//*[[^/][^/]]*/*$' \| \
  X[]$1 : 'X\(//\)[[^/]]' \| \
  X[]$1 : 'X\(//\)$' \| \
  X[]$1 : 'X\(/\)' \| .])
@@ -775,18 +805,23 @@ m4_defun([_AS_DIRNAME_SED],
 
 m4_defun([AS_DIRNAME],
 [AS_REQUIRE([_$0_PREPARE])dnl
-$as_dirname -- $1 ||
-_AS_DIRNAME_EXPR([$1]) 2>/dev/null ||
-_AS_DIRNAME_SED([$1])])
+$as_dirname -- $1])
 
 
 # _AS_DIRNAME_PREPARE
 # --------------------
 m4_defun([_AS_DIRNAME_PREPARE],
-[if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+[AS_REQUIRE([_AS_EXPR_PREPARE])dnl
+AS_REQUIRE_SHELL_FN([as_func_dirname_expr],
+     [_AS_DIRNAME_EXPR([$[]2]) 2>/dev/null])
+AS_REQUIRE_SHELL_FN([as_func_dirname_sed],
+    [_AS_DIRNAME_SED([$[]2])])
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
   as_dirname=dirname
+elif (as_func_dirname_expr -- /) >/dev/null 2>&1; then
+  as_dirname=as_func_dirname_expr
 else
-  as_dirname=false
+  as_dirname=as_func_dirname_sed
 fi
 ])# _AS_DIRNAME_PREPARE
 
@@ -882,6 +917,14 @@ fi
 ])# _AS_EXPR_PREPARE
 
 
+# _AS_ME_PREPARE
+# --------------
+# Define $as_me to the basename of the executable file's name.
+m4_defun([_AS_ME_PREPARE],
+[AS_REQUIRE([_AS_BASENAME_PREPARE])dnl
+as_me=`AS_BASENAME("$[0]")`
+])
+
 # _AS_LINENO_WORKS
 # ---------------
 # Succeed if the currently executing shell supports LINENO.
@@ -907,6 +950,7 @@ m4_define([_AS_LINENO_WORKS],
 # configure.
-m4_define([_AS_LINENO_PREPARE],
+m4_defun([_AS_LINENO_PREPARE],
 [AS_REQUIRE([_AS_CR_PREPARE])dnl
+AS_REQUIRE([_AS_ME_PREPARE])dnl
 _AS_DETECT_SUGGESTED([_AS_LINENO_WORKS])
 _AS_LINENO_WORKS || {
 
@@ -995,16 +1039,15 @@ $as_ln_s $1 $2
 ])
 
 
-# AS_MKDIR_P(DIR)
-# ---------------
-# Emulate `mkdir -p' with plain `mkdir'.
-m4_define([AS_MKDIR_P],
-[AS_REQUIRE([_$0_PREPARE])dnl
-{ as_dir=$1
+# _AS_MKDIR_P(DIR)
+# ----------------
+# Emulate `mkdir -p` with plain `mkdir'.
+m4_define([_AS_MKDIR_P],
+[as_dir=$1
   case $as_dir in #(
   -*) as_dir=./$as_dir;;
   esac
-  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+  test -d "$as_dir" || eval $as_mkdir_p || {
     as_dirs=
     while :; do
       case $as_dir in #(
@@ -1016,15 +1059,25 @@ m4_define([AS_MKDIR_P],
       test -d "$as_dir" && break
     done
     test -z "$as_dirs" || eval "mkdir $as_dirs"
-  } || test -d "$as_dir" || AS_ERROR([cannot create directory $as_dir]); }dnl
-])# AS_MKDIR_P
+  } || test -d "$as_dir" || AS_ERROR([cannot create directory $as_dir])
+])
+
+# AS_MKDIR_P(DIR)
+# ---------------
+# Emulate `mkdir -p' with plain `mkdir' if needed.
+m4_define([AS_MKDIR_P],
+[AS_REQUIRE([_$0_PREPARE])dnl
+as_dir=$1; as_func_mkdir_p "$as_dir"])# AS_MKDIR_P
 
 
 # _AS_MKDIR_P_PREPARE
 # -------------------
 m4_defun([_AS_MKDIR_P_PREPARE],
-[if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
+[AS_REQUIRE_SHELL_FN([as_func_mkdir_p], [
+  _AS_MKDIR_P([$[]1])
+])
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
 else
   test -d ./-p && rmdir ./-p
   as_mkdir_p=false



[PATCH 6/5] postscriptum

by Paolo Bonzini-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I know there is no documentation change. :-)

Paolo




Re: [PATCH 5/5] use shell function for AS_BASENAME, AS_DIRNAME, AS_MKDIR_P

by Eric Blake :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Paolo Bonzini on 9/18/2008 8:15 AM:
> This patch defines shell functions for the various implementation
> of basename/dirname/mkdir_p and changes macros such as AS_BASENAME
> to simply dispatch to those macros.

In general, I like where this is headed, but I'm not quite ready to apply
this as-is.

>
> Some care is needed to delay the definition of as_me, and to define
> the shell functions in _AS_PREPARE for config.status.  There's also
> a bug that _AS_LINENO_PREPARE was not using m4_defun.

Can some of this cleanup be separated out and applied first, so that the
actual patch adding shell functions is not doing other things at the same
time?

>
> I decided to stop having AS_PREPARE call _AS_PREPARE, because the
> former can let _AS_BASENAME_PREPARE and friends expand shell functions,
> while _AS_PREPARE (which is used for the prolog of config.status)
> must do that on its own.

For that matter, why should anyone except status.m4 be using AS_PREPARE?
The point of AS_REQUIRE is that the initialization will be emitted on an
as-needed basis (ie. if you write an m4sh script that doesn't use as_ln_s,
then why should the script be slowed down by emitting _AS_LN_S_PREPARE at
all?).  config.status is special because it is a script written by a
script, and not a script written in m4sh, so we have to do all of the
initializations rather than relying on lazy initialzation.

>
> (AS_BASENAME): Just dispatch to $as_basename.
> (_AS_BASENAME_EXPR): Do not require _AS_EXPR_PREPARE.
> (_AS_BASENAME_PREPARE): Do that here.  Test availability of
> basename and expr.  Define shell functions.

Here, does it really make sense to define two functions, one of which will
never be used?  Or would it be better to write a conditional function
definition:

if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/";
then
  as_func_basename ()
  {
    basename "$@"
  }
elif (as_func_basename_expr -- /) >/dev/null 2>&1; then
  as_func_basename ()
  {
    _AS_DIRNAME_EXPR([$[]2])
  }

and so forth.  For that matter, I would like to use XSI parameter
expansion, when available, to avoid forking (even using basename is slower
than doing things like ${2##.*/}, libtool has some examples of this).

On the other hand, your patch is an improvement in its own right, and
maybe changes like this can be follow-up patches.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             ebb9@...
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkjt/zwACgkQ84KuGfSFAYAswgCfVwjQrh+HwUvs5wamL7xfvmPM
JNoAnAghOzv00bbMMsECkjRB+mk7+ngx
=qS4G
-----END PGP SIGNATURE-----



Re: [PATCH 5/5] use shell function for AS_BASENAME, AS_DIRNAME, AS_MKDIR_P

by Paolo Bonzini-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


>> Some care is needed to delay the definition of as_me, and to define
>> the shell functions in _AS_PREPARE for config.status.  There's also
>> a bug that _AS_LINENO_PREPARE was not using m4_defun.
>
> Can some of this cleanup be separated out and applied first, so that the
> actual patch adding shell functions is not doing other things at the same
> time?

Yes, I'll look at separating some of the changes.

>> I decided to stop having AS_PREPARE call _AS_PREPARE, because the
>> former can let _AS_BASENAME_PREPARE and friends expand shell functions,
>> while _AS_PREPARE (which is used for the prolog of config.status)
>> must do that on its own.
>
> For that matter, why should anyone except status.m4 be using AS_PREPARE?

AS_PREPARE is used in the prolog of the configure script; _AS_PREPARE is
used in the prolog of config.status.

The problem is that we want the configure script's initialization to be
emitted in the right diversion, and that's why we cannot just use
_AS_PREPARE.

Or are you saying that AS_PREPARE is totally useless?  I'm not sure we
would not miss anything in the prolog of the configure script if
AS_PREPARE was not used.

>> (AS_BASENAME): Just dispatch to $as_basename.
>> (_AS_BASENAME_EXPR): Do not require _AS_EXPR_PREPARE.
>> (_AS_BASENAME_PREPARE): Do that here.  Test availability of
>> basename and expr.  Define shell functions.
>
> Here, does it really make sense to define two functions, one of which will
> never be used?

Can I leave the final patch to do this to you after I do the above
splitting?

> On the other hand, your patch is an improvement in its own right, and
> maybe changes like this can be follow-up patches.

No big deal, as long as it's not me the one who takes care of squashing
the follow-ups with this patch.

Paolo


LightInTheBox - Buy quality products at wholesale price!