On Monday 05 of October 2015 09:47:05 Pavel Raiskup wrote:
> On Monday 05 of October 2015 01:25:24 Pavel Raiskup wrote:
> > On Monday 05 of October 2015 00:45:50 Pavel Raiskup wrote:
> > > > should we test the size of the string first ? i've written such raw
> > > > shell
> > > > string parsing functions before, and once you hit a certain size (like
> > > > 1k+
> > > > iirc), forking out to sed is way faster, especially when running in
> > > > multibyte
> > > > locales (like UTF8) which most people are doing nowadays.
> > > > -mike
> > >
> > > Well, that optimization would require (fast) strlen()-like construct.
> > > Anyway, the vast majority of calls to func_quote () function will have
> > > short ARG, and its complexity is still "just" linear. We could optimize
> > > later if that was a real issue.
> > >
> > > I would like to propose solution based on Eric's one, without using of
> > > '${VAR%.}' and '${VAR#.}' constructs -- sounds like this could be even
> > > more portable while it keeps almost the same speed (if we can use += its
> > > even faster).
> > >
> > > I have yet a another patch trying to minimize option-parser overhead
> > > (that is focused on the POV of Richard, but that needs to be cleaned up a
> > > bit, I'll post hopefully tomorrow).
> > >
> > > Any comment is welcome!
> >
> > Re-attached (fixes for 'make syntax-check' and fixed one comment).
>
> Hmm, one might-be-a-problem with this (catched by testsuite), when you
> have:
>
> $ cat build-aux/test-quoting
> . `echo "$0" |${SED-sed} 's|[^/]*$||'`/funclib.sh
> # source this for "GNU m4" detection methods
> . `echo "$0" |${SED-sed} 's|[^/]*$||'`/extract-trace
>
> func_quote_for_eval "$@"
> echo "$func_quote_for_eval_result"
>
> Then:
>
> $ ./build-aux/test-quoting '"a b"' # fine
> "\"a b\""
>
> $ ./build-aux/test-quoting '"*tool"' # broken
> ./build-aux/test-quoting '"*tool"'
> \"libtool\"
>
> We would like to have an output \"*\". I'm not aware of portable way
> how to disable wildcard expansion in shell, and autoconf 'Shellology'
> section haven't helped me. In particular, the problem is here:
>
> x='a"[a-z]*"c'
> IFS='"'
> for i in $x; do # Here we wan't to disable wildcard expansion
> echo $i
> done
>
> Any idea other than fallback to $sed_quote_subst in case of '*' or '['
> exists in ARG?
Attaching two (yet to be cleaned) patches doing the optimization. Is
anybody able to test/comment on this particular solution? That would be
really appreciated.
Pavel
>From 1b89ae66f88c3822b2afec128f288d409287780f Mon Sep 17 00:00:00 2001
From: Pavel Raiskup <[email protected]>
Date: Sun, 4 Oct 2015 21:55:03 +0200
Subject: [PATCH 1/2] libtool: mitigate the $sed_quote_subst slowdown
When it is reasonably possible, use shell implementation for
quoting.
References:
http://lists.gnu.org/archive/html/libtool/2015-03/msg00005.html
http://lists.gnu.org/archive/html/libtool/2015-02/msg00000.html
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=20006
* gl/build-aux/funclib.sh (func_quote): New function that can be
used as substitution for '$SED $sed_quote_subst' call.
* build-aux/ltmain.in (func_emit_wrapper): Use func_quote instead
of '$SED $sed_quote_subst'.
(func_mode_link): Likewise.
* NEWS: Document.
* bootstrap: Sync with funclib.sh.
---
NEWS | 3 +++
bootstrap | 56 +++++++++++++++++++++++++++++++++++++++++++++++--
build-aux/ltmain.in | 10 +++++----
gl/build-aux/funclib.sh | 56 +++++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 117 insertions(+), 8 deletions(-)
diff --git a/NEWS b/NEWS
index a3c5b12..7c23d03 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,9 @@ NEWS - list of user-visible changes between releases of GNU Libtool
- Fix significant slowdown of libtoolize for certain projects (regression
introduced in 2.4.3 release) caused by infinite m4 macro recursion.
+ - Mitigate the slowdown of libtool script (introduced in v2.4.3) caused by
+ increased number of calls to '$SED $sed_quote_subst' (bug#20006).
+
* Noteworthy changes in release 2.4.6 (2015-02-15) [stable]
** New features:
diff --git a/bootstrap b/bootstrap
index c179f51..2649478 100755
--- a/bootstrap
+++ b/bootstrap
@@ -230,7 +230,7 @@ vc_ignore=
# Source required external libraries:
# Set a version string for this script.
-scriptversion=2015-01-20.17; # UTC
+scriptversion=2015-10-04.22; # UTC
# General shell script boiler plate, and helper functions.
# Written by Gary V. Vaughan, 2004
@@ -1257,6 +1257,57 @@ func_relative_path ()
}
+# func_quote ARG
+# --------------
+# Aesthetically quote one ARG, store the result into $func_quote_result. Note
+# that we keep attention to performance here (so far O(N) complexity as long as
+# func_append is O(1)).
+func_quote ()
+{
+ $debug_cmd
+
+ func_quote_result=$1
+
+ case $func_quote_result in
+ *[\\\`\"\$]*)
+ case $func_quote_result in
+ *'*'*|*'['*)
+ func_quote_result=`$ECHO "$func_quote_result" | $SED "$sed_quote_subst"`
+ return 0
+ ;;
+ esac
+
+ func_quote_old_IFS=$IFS
+ for _G_char in '\' '`' '"' '$'
+ do
+ # STATE($1) PREV($2) SEPARATOR($3)
+ set start "" ""
+ func_quote_result=dummy"$_G_char$func_quote_result$_G_char"dummy
+ IFS=$_G_char
+ for _G_part in $func_quote_result
+ do
+ case $1 in
+ quote)
+ func_append func_quote_result "$3$2"
+ set quote "$_G_part" "\\$_G_char"
+ ;;
+ start)
+ set first "" ""
+ func_quote_result=
+ ;;
+ first)
+ set quote "$_G_part" ""
+ ;;
+ esac
+ done
+ IFS=$func_quote_old_IFS
+ done
+ ;;
+ *) ;;
+ esac
+}
+
+
# func_quote_for_eval ARG...
# --------------------------
# Aesthetically quote ARGs to be evaled later.
@@ -1275,7 +1326,8 @@ func_quote_for_eval ()
while test 0 -lt $#; do
case $1 in
*[\\\`\"\$]*)
- _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;;
+ func_quote "$1"
+ _G_unquoted_arg=$func_quote_result ;;
*)
_G_unquoted_arg=$1 ;;
esac
diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in
index 0c40da0..24acefd 100644
--- a/build-aux/ltmain.in
+++ b/build-aux/ltmain.in
@@ -3346,7 +3346,8 @@ else
if test \"\$libtool_execute_magic\" != \"$magic\"; then
file=\"\$0\""
- qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+ func_quote "$ECHO"
+ qECHO=$func_quote_result
$ECHO "\
# A function that is used when there is no print builtin or printf.
@@ -8596,8 +8597,8 @@ EOF
relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
fi
done
- relink_command="(cd `pwd`; $relink_command)"
- relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+ func_quote "(cd `pwd`; $relink_command)"
+ relink_command=$func_quote_result
fi
# Only actually do things if not in dry run mode.
@@ -8843,7 +8844,8 @@ EOF
done
# Quote the link command for shipping.
relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
- relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+ func_quote "$relink_command"
+ relink_command=$func_quote_result
if test yes = "$hardcode_automatic"; then
relink_command=
fi
diff --git a/gl/build-aux/funclib.sh b/gl/build-aux/funclib.sh
index 39d972e..8032e6b 100644
--- a/gl/build-aux/funclib.sh
+++ b/gl/build-aux/funclib.sh
@@ -1,5 +1,5 @@
# Set a version string for this script.
-scriptversion=2015-01-20.17; # UTC
+scriptversion=2015-10-04.22; # UTC
# General shell script boiler plate, and helper functions.
# Written by Gary V. Vaughan, 2004
@@ -1026,6 +1026,57 @@ func_relative_path ()
}
+# func_quote ARG
+# --------------
+# Aesthetically quote one ARG, store the result into $func_quote_result. Note
+# that we keep attention to performance here (so far O(N) complexity as long as
+# func_append is O(1)).
+func_quote ()
+{
+ $debug_cmd
+
+ func_quote_result=$1
+
+ case $func_quote_result in
+ *[\\\`\"\$]*)
+ case $func_quote_result in
+ *'*'*|*'['*)
+ func_quote_result=`$ECHO "$func_quote_result" | $SED "$sed_quote_subst"`
+ return 0
+ ;;
+ esac
+
+ func_quote_old_IFS=$IFS
+ for _G_char in '\' '`' '"' '$'
+ do
+ # STATE($1) PREV($2) SEPARATOR($3)
+ set start "" ""
+ func_quote_result=dummy"$_G_char$func_quote_result$_G_char"dummy
+ IFS=$_G_char
+ for _G_part in $func_quote_result
+ do
+ case $1 in
+ quote)
+ func_append func_quote_result "$3$2"
+ set quote "$_G_part" "\\$_G_char"
+ ;;
+ start)
+ set first "" ""
+ func_quote_result=
+ ;;
+ first)
+ set quote "$_G_part" ""
+ ;;
+ esac
+ done
+ IFS=$func_quote_old_IFS
+ done
+ ;;
+ *) ;;
+ esac
+}
+
+
# func_quote_for_eval ARG...
# --------------------------
# Aesthetically quote ARGs to be evaled later.
@@ -1044,7 +1095,8 @@ func_quote_for_eval ()
while test 0 -lt $#; do
case $1 in
*[\\\`\"\$]*)
- _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;;
+ func_quote "$1"
+ _G_unquoted_arg=$func_quote_result ;;
*)
_G_unquoted_arg=$1 ;;
esac
--
2.5.0
>From c283b8a8e7540b65fd7a7d32fceec6ed42b5b2a7 Mon Sep 17 00:00:00 2001
From: Pavel Raiskup <[email protected]>
Date: Mon, 5 Oct 2015 13:16:08 +0200
Subject: [PATCH 2/2] libbtool: optimize parse-options calls
Its not necessary to re-escape-for-eval in each function in the
hook-able function tree -- usually is enough if the leaf function
executes func_quote_for_eval() and its caller just re-uses the
CALLEE_return value.
* gl/build-aux/options-parser (func_run_hooks): Propagate 0 return
code down to caller if any $_G_hook succeeded. Don't re-quote
the result as that has already been done by the succeeding hook
itself.
(func_parse_options): Quote only if we changed something and
use appropriate return code.
(func_validate_options): Likewise.
(func_options_prep): Likewise.
(func_options_finish): New hook-caller for 'func_options' hooks.
(func_options): Propagate return value down to top-level caller,
but pay attention we have always set $func_options_result.
* build-aux/ltmain.in (libtool_options_prep): Quote only if we
changed something and use appropriate return code.
(libtool_parse_options): Likewise.
* bootstrap: Sync gl/build-aux/with option-parser.
---
bootstrap | 128 +++++++++++++++++++++++++++++++++-----------
build-aux/ltmain.in | 33 +++++++++---
gl/build-aux/options-parser | 128 +++++++++++++++++++++++++++++++++-----------
3 files changed, 220 insertions(+), 69 deletions(-)
diff --git a/bootstrap b/bootstrap
index 2649478..c4de711 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1744,10 +1744,17 @@ func_remove_hook ()
# than a whitespace-delimited list of legal shell function names, and
# no effort is wasted trying to catch shell meta-characters or preserve
# whitespace.
+# If at least one hook returns 0 (exit success) upon execution,
+# func_run_hooks () returns zero too. Otherwise 1 is returned.
+# All hooks are expected to correctly return $HOOKNAME_result variable
+# upon success exection. The output variable $func_run_hooks_result
+# is set to latest (successful) $HOOKNAME_result.
func_run_hooks ()
{
$debug_cmd
+ _G_rc_run_hooks=false
+
case " $hookable_fns " in
*" $1 "*) ;;
*) func_fatal_error "'$1' does not support hook funcions.n" ;;
@@ -1756,16 +1763,24 @@ func_run_hooks ()
eval _G_hook_fns=\$$1_hooks; shift
for _G_hook in $_G_hook_fns; do
- eval $_G_hook '"$@"'
+ _G_hook_unchanged=${_G_hook}_unchanged
+ eval $_G_hook_unchanged=false
- # store returned options list back into positional
- # parameters for next 'cmd' execution.
- eval _G_hook_result=\$${_G_hook}_result
- eval set dummy "$_G_hook_result"; shift
+ if eval $_G_hook '"$@"'; then
+ # store returned options list back into positional
+ # parameters for next 'cmd' execution.
+ eval _G_hook_result=\$${_G_hook}_result
+ eval set dummy "$_G_hook_result"; shift
+ _G_rc_run_hooks=true
+ fi
done
- func_quote_for_eval ${1+"$@"}
- func_run_hooks_result=$func_quote_for_eval_result
+ if $_G_rc_run_hooks; then
+ # No need to re-quote by func_quoteh
+ func_run_hooks_result=$_G_hook_result
+ fi
+
+ $_G_rc_run_hooks
}
@@ -1839,6 +1854,24 @@ func_run_hooks ()
# multiple option parsing hooks can be added safely.
+# func_options_finish [ARG]...
+# ----------------------------
+# All finishing suff required after the option parse loop. This executes
+# all 'func_options' hooks.
+func_options_finish ()
+{
+ $debug_cmd
+
+ _G_func_options_finish_exit=false
+ if func_run_hooks func_options ${1+"$@"}; then
+ func_options_finish_result=$func_run_hooks_result
+ _G_func_options_finish_exit=:
+ fi
+
+ $_G_func_options_finish_exit
+}
+
+
# func_options [ARG]...
# ---------------------
# All the functions called inside func_options are hookable. See the
@@ -1848,17 +1881,26 @@ func_options ()
{
$debug_cmd
- func_options_prep ${1+"$@"}
- eval func_parse_options \
- ${func_options_prep_result+"$func_options_prep_result"}
- eval func_validate_options \
- ${func_parse_options_result+"$func_parse_options_result"}
+ _G_rc_options=false
- eval func_run_hooks func_options \
- ${func_validate_options_result+"$func_validate_options_result"}
+ for my_func in options_prep parse_options validate_options options_finish
+ do
+ if eval func_$my_func '${1+"$@"}'; then
+ eval _G_res_var='$'"func_${my_func}_result"
+ eval set dummy "$_G_res_var" ; shift
+ _G_rc_options=:
+ fi
+ done
- # save modified positional parameters for caller
- func_options_result=$func_run_hooks_result
+ if $_G_rc_options; then
+ func_options_result=$_G_res_var
+ else
+ # As a top-level function, we need *always* set the *_result
+ func_quote_for_eval ${1+"$@"}
+ func_options_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_options
}
@@ -1869,7 +1911,9 @@ func_options ()
# positional parameters. If a hook function modifies that list, and
# needs to propogate that back to rest of this script, then the complete
# modified list must be put in 'func_run_hooks_result' before
-# returning.
+# returning and 0 returned. If no changes were done, script might return
+# 1 and caller of the hook will not read the 'func_run_hooks_result'
+# value.
func_hookable func_options_prep
func_options_prep ()
{
@@ -1879,10 +1923,14 @@ func_options_prep ()
opt_verbose=false
opt_warning_types=
- func_run_hooks func_options_prep ${1+"$@"}
+ _G_rc_options_prep=false
+ if func_run_hooks func_options_prep ${1+"$@"}; then
+ _G_rc_options_prep=:
+ # save modified positional parameters for caller
+ func_options_prep_result=$func_run_hooks_result
+ fi
- # save modified positional parameters for caller
- func_options_prep_result=$func_run_hooks_result
+ $_G_rc_options_prep
}
@@ -1896,18 +1944,21 @@ func_parse_options ()
func_parse_options_result=
+ _G_rc_parse_options=false
# this just eases exit handling
while test $# -gt 0; do
# Defer to hook functions for initial option parsing, so they
# get priority in the event of reusing an option name.
- func_run_hooks func_parse_options ${1+"$@"}
-
- # Adjust func_parse_options positional parameters to match
- eval set dummy "$func_run_hooks_result"; shift
+ if func_run_hooks func_parse_options ${1+"$@"}; then
+ # Adjust func_parse_options positional parameters to match
+ eval set dummy "$func_run_hooks_result"; shift
+ _G_rc_parse_options=:
+ fi
# Break out of the loop if we already parsed every option.
test $# -gt 0 || break
+ _G_match_parse_options=:
_G_opt=$1
shift
case $_G_opt in
@@ -1977,13 +2028,23 @@ func_parse_options ()
--) break ;;
-*) func_fatal_help "unrecognised option: '$_G_opt'" ;;
- *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+ *) set dummy "$_G_opt" ${1+"$@"} ; shift
+ _G_match_parse_options=false
+ break
+ ;;
esac
+
+ $_G_match_parse_options && _G_rc_parse_options=:
done
- # save modified positional parameters for caller
- func_quote_for_eval ${1+"$@"}
- func_parse_options_result=$func_quote_for_eval_result
+
+ if $_G_rc_parse_options; then
+ # save modified positional parameters for caller
+ func_quote_for_eval ${1+"$@"}
+ func_parse_options_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_parse_options
}
@@ -1996,16 +2057,21 @@ func_validate_options ()
{
$debug_cmd
+ _G_rc_validate_options=false
+
# Display all warnings if -W was not given.
test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
- func_run_hooks func_validate_options ${1+"$@"}
+ if func_run_hooks func_validate_options ${1+"$@"}; then
+ # save modified positional parameters for caller
+ func_validate_options_result=$func_run_hooks_result
+ _G_rc_validate_options=:
+ fi
# Bail if the options were screwed!
$exit_cmd $EXIT_FAILURE
- # save modified positional parameters for caller
- func_validate_options_result=$func_run_hooks_result
+ $_G_rc_validate_options
}
diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in
index 24acefd..e57042a 100644
--- a/build-aux/ltmain.in
+++ b/build-aux/ltmain.in
@@ -358,6 +358,8 @@ libtool_options_prep ()
nonopt=
preserve_args=
+ _G_rc_libtool_options_prep=:
+
# Shorthand for --mode=foo, only valid as the first argument
case $1 in
clean|clea|cle|cl)
@@ -381,11 +383,18 @@ libtool_options_prep ()
uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
shift; set dummy --mode uninstall ${1+"$@"}; shift
;;
+ *)
+ _G_rc_libtool_options_prep=false
+ ;;
esac
- # Pass back the list of options.
- func_quote_for_eval ${1+"$@"}
- libtool_options_prep_result=$func_quote_for_eval_result
+ if $_G_rc_libtool_options_prep; then
+ # Pass back the list of options.
+ func_quote_for_eval ${1+"$@"}
+ libtool_options_prep_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_libtool_options_prep
}
func_add_hook func_options_prep libtool_options_prep
@@ -397,9 +406,12 @@ libtool_parse_options ()
{
$debug_cmd
+ _G_rc_lt_parse_options=false
+
# Perform our own loop to consume as many options as possible in
# each iteration.
while test $# -gt 0; do
+ _G_match_lt_parse_options=:
_G_opt=$1
shift
case $_G_opt in
@@ -475,14 +487,21 @@ libtool_parse_options ()
;;
# An option not handled by this hook function:
- *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+ *) set dummy "$_G_opt" ${1+"$@"} ; shift
+ _G_match_lt_parse_options=false
+ break
+ ;;
esac
+ $_G_match_lt_parse_options && _G_rc_lt_parse_options=:
done
+ if $_G_rc_lt_parse_options; then
+ # save modified positional parameters for caller
+ func_quote_for_eval ${1+"$@"}
+ libtool_parse_options_result=$func_quote_for_eval_result
+ fi
- # save modified positional parameters for caller
- func_quote_for_eval ${1+"$@"}
- libtool_parse_options_result=$func_quote_for_eval_result
+ $_G_rc_lt_parse_options
}
func_add_hook func_parse_options libtool_parse_options
diff --git a/gl/build-aux/options-parser b/gl/build-aux/options-parser
index d651f1d..73db1e3 100644
--- a/gl/build-aux/options-parser
+++ b/gl/build-aux/options-parser
@@ -157,10 +157,17 @@ func_remove_hook ()
# than a whitespace-delimited list of legal shell function names, and
# no effort is wasted trying to catch shell meta-characters or preserve
# whitespace.
+# If at least one hook returns 0 (exit success) upon execution,
+# func_run_hooks () returns zero too. Otherwise 1 is returned.
+# All hooks are expected to correctly return $HOOKNAME_result variable
+# upon success exection. The output variable $func_run_hooks_result
+# is set to latest (successful) $HOOKNAME_result.
func_run_hooks ()
{
$debug_cmd
+ _G_rc_run_hooks=false
+
case " $hookable_fns " in
*" $1 "*) ;;
*) func_fatal_error "'$1' does not support hook funcions.n" ;;
@@ -169,16 +176,24 @@ func_run_hooks ()
eval _G_hook_fns=\$$1_hooks; shift
for _G_hook in $_G_hook_fns; do
- eval $_G_hook '"$@"'
+ _G_hook_unchanged=${_G_hook}_unchanged
+ eval $_G_hook_unchanged=false
- # store returned options list back into positional
- # parameters for next 'cmd' execution.
- eval _G_hook_result=\$${_G_hook}_result
- eval set dummy "$_G_hook_result"; shift
+ if eval $_G_hook '"$@"'; then
+ # store returned options list back into positional
+ # parameters for next 'cmd' execution.
+ eval _G_hook_result=\$${_G_hook}_result
+ eval set dummy "$_G_hook_result"; shift
+ _G_rc_run_hooks=true
+ fi
done
- func_quote_for_eval ${1+"$@"}
- func_run_hooks_result=$func_quote_for_eval_result
+ if $_G_rc_run_hooks; then
+ # No need to re-quote by func_quoteh
+ func_run_hooks_result=$_G_hook_result
+ fi
+
+ $_G_rc_run_hooks
}
@@ -252,6 +267,24 @@ func_run_hooks ()
# multiple option parsing hooks can be added safely.
+# func_options_finish [ARG]...
+# ----------------------------
+# All finishing suff required after the option parse loop. This executes
+# all 'func_options' hooks.
+func_options_finish ()
+{
+ $debug_cmd
+
+ _G_func_options_finish_exit=false
+ if func_run_hooks func_options ${1+"$@"}; then
+ func_options_finish_result=$func_run_hooks_result
+ _G_func_options_finish_exit=:
+ fi
+
+ $_G_func_options_finish_exit
+}
+
+
# func_options [ARG]...
# ---------------------
# All the functions called inside func_options are hookable. See the
@@ -261,17 +294,26 @@ func_options ()
{
$debug_cmd
- func_options_prep ${1+"$@"}
- eval func_parse_options \
- ${func_options_prep_result+"$func_options_prep_result"}
- eval func_validate_options \
- ${func_parse_options_result+"$func_parse_options_result"}
+ _G_rc_options=false
- eval func_run_hooks func_options \
- ${func_validate_options_result+"$func_validate_options_result"}
+ for my_func in options_prep parse_options validate_options options_finish
+ do
+ if eval func_$my_func '${1+"$@"}'; then
+ eval _G_res_var='$'"func_${my_func}_result"
+ eval set dummy "$_G_res_var" ; shift
+ _G_rc_options=:
+ fi
+ done
- # save modified positional parameters for caller
- func_options_result=$func_run_hooks_result
+ if $_G_rc_options; then
+ func_options_result=$_G_res_var
+ else
+ # As a top-level function, we need *always* set the *_result
+ func_quote_for_eval ${1+"$@"}
+ func_options_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_options
}
@@ -282,7 +324,9 @@ func_options ()
# positional parameters. If a hook function modifies that list, and
# needs to propogate that back to rest of this script, then the complete
# modified list must be put in 'func_run_hooks_result' before
-# returning.
+# returning and 0 returned. If no changes were done, script might return
+# 1 and caller of the hook will not read the 'func_run_hooks_result'
+# value.
func_hookable func_options_prep
func_options_prep ()
{
@@ -292,10 +336,14 @@ func_options_prep ()
opt_verbose=false
opt_warning_types=
- func_run_hooks func_options_prep ${1+"$@"}
+ _G_rc_options_prep=false
+ if func_run_hooks func_options_prep ${1+"$@"}; then
+ _G_rc_options_prep=:
+ # save modified positional parameters for caller
+ func_options_prep_result=$func_run_hooks_result
+ fi
- # save modified positional parameters for caller
- func_options_prep_result=$func_run_hooks_result
+ $_G_rc_options_prep
}
@@ -309,18 +357,21 @@ func_parse_options ()
func_parse_options_result=
+ _G_rc_parse_options=false
# this just eases exit handling
while test $# -gt 0; do
# Defer to hook functions for initial option parsing, so they
# get priority in the event of reusing an option name.
- func_run_hooks func_parse_options ${1+"$@"}
-
- # Adjust func_parse_options positional parameters to match
- eval set dummy "$func_run_hooks_result"; shift
+ if func_run_hooks func_parse_options ${1+"$@"}; then
+ # Adjust func_parse_options positional parameters to match
+ eval set dummy "$func_run_hooks_result"; shift
+ _G_rc_parse_options=:
+ fi
# Break out of the loop if we already parsed every option.
test $# -gt 0 || break
+ _G_match_parse_options=:
_G_opt=$1
shift
case $_G_opt in
@@ -390,13 +441,23 @@ func_parse_options ()
--) break ;;
-*) func_fatal_help "unrecognised option: '$_G_opt'" ;;
- *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+ *) set dummy "$_G_opt" ${1+"$@"} ; shift
+ _G_match_parse_options=false
+ break
+ ;;
esac
+
+ $_G_match_parse_options && _G_rc_parse_options=:
done
- # save modified positional parameters for caller
- func_quote_for_eval ${1+"$@"}
- func_parse_options_result=$func_quote_for_eval_result
+
+ if $_G_rc_parse_options; then
+ # save modified positional parameters for caller
+ func_quote_for_eval ${1+"$@"}
+ func_parse_options_result=$func_quote_for_eval_result
+ fi
+
+ $_G_rc_parse_options
}
@@ -409,16 +470,21 @@ func_validate_options ()
{
$debug_cmd
+ _G_rc_validate_options=false
+
# Display all warnings if -W was not given.
test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
- func_run_hooks func_validate_options ${1+"$@"}
+ if func_run_hooks func_validate_options ${1+"$@"}; then
+ # save modified positional parameters for caller
+ func_validate_options_result=$func_run_hooks_result
+ _G_rc_validate_options=:
+ fi
# Bail if the options were screwed!
$exit_cmd $EXIT_FAILURE
- # save modified positional parameters for caller
- func_validate_options_result=$func_run_hooks_result
+ $_G_rc_validate_options
}
--
2.5.0
_______________________________________________
https://lists.gnu.org/mailman/listinfo/libtool