This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

bugs in autotools wrapper scripts


The autotools wrappers (automake 1.7.9-1, autoconf 2.59-1, and libtool
1.5b-1) all have argument parsing bugs.  They are trying to parse every
option known to either <autotool>-stable or <autotool>-devel, but fail in
several respects.

First, the wrappers are not robust to new options being added.  For example,
libtoolize 1.9f_20041024-1 treats --ltdl as a long-option with an optional
argument, but the wrapper rejects 'libtoolize --ltdl=libltdl'; likewise
aclocal 1.9.2-1 has a --force option which the wrapper rejects.

Second, the wrappers do not recognize multiple short options in a single
argument.  For example, 'automake -fiv' is not treated as equivalent to
'automake -f -i -v'.

And finally, the wrappers do not allow for option rearranging, like the
underlying tools do.  For example, 'automake Makefile --help' does not
recognize the help option and complains that no configure.ac file exists,
while '/usr/autotool/devel/bin/automake Makefile --help' prints the help in
a directory with no configure.ac.

I think it would be smarter to simplify the wrappers by just parsing for
help and version options rather than trying to track every option of the
underlying tool, since only help and version have the special behavior in
the wrapper.  That way the wrapper is immune to the underlying tool adding
options, and lets the underlying tool do multiple short options from
a single argument and option rearranging.  Attached is my proposed patch for
automake, something similar would apply to all the wrappers.  There are two
ambiguous corner cases where we cannot decide whether --help was requested
without tracking every option of the underlying tool; because we do not know
whether the previous option takes an argument.  My patch treats '--option --
--help' as not printing the wrapper help, even if it should mean
'--option=-- --help'; and treats '-zh' as not printing the wrapper help,
even if it should mean '-z -h'.  But this should be okay, as those two
ambiguous uses are rare in practice; and the result is the user will either
get a spurious warning about not having configure.ac, or the underlying tool
will correctly reparse the arguments and print the tool help.

If this approach is not considered satisfactory, and you really want to
maintain the wrappers to know all options of the underlying tool, I can also
prepare patches for that approach that know how to split multiple short
options and how to rearrange arguments.

--
Someday, I might put a cute statement here.

Eric Blake ebb9@byu.net


*** /usr/bin/automake.orig	Sat Nov 20 08:55:30 2004
--- /usr/bin/automake	Sat Nov 20 12:09:42 2004
***************
*** 1,211 ****
  #! /bin/bash
  AUTO_STABLE=${AUTO_STABLE:-/usr/autotool/stable}
  AUTO_DEVEL=${AUTO_DEVEL:-/usr/autotool/devel}
  
  me=`echo "$0" | sed -e 's,.*[\\/],,'`
  
- help="\
- Try \`$me --help' for more information."
- 
- exit_missing_arg="\
- echo \"$me: option \\\`\$1' requires an argument\" >&2
- echo \"\$help\" >&2
- exit 1"
- 
  # Set up variables
- unset autosense_input
  unset opt_version
  unset opt_help
! unset opt_verbose
! unset opt_libdir
! unset opt_gnu
! unset opt_gnits
! unset opt_cygnus
! unset opt_foreign
! unset opt_std_options
! unset opt_include_deps
! unset opt_ignore_deps
! unset opt_generate_deps
! unset opt_no_force
! unset opt_force_missing
! unset opt_output_dir
! unset opt_add_missing
! unset opt_copy
! unset opt_amdir
! unset opt_build_dir
! unset opt_srcdir_name
! unset opt_warnings
! unset warnings
! unset opt_stop
! # Parse command line.
  while test $# -gt 0 ; do
-   optarg=`expr "x$1" : 'x--[^=]*=\(.*\)' \| \
-                "x$1" : 'x-.\(.*\)'`
    case $1 in
! 
!     --version | -V ) 
         opt_version="--version"
-        shift ;;
- 
- 
-     --help | -h )
-        opt_help="--help"
-        shift ;;
- 
- 
-     --verbose | -v )
-        opt_verbose="--verbose"
-        shift ;;
- 
- 
-     --libdir=* )
-        opt_libdir="--libdir=$optarg"
-        shift ;;
-     --libdir )
-        test $# = 1 && eval "$exit_missing_arg"
-        shift
-        opt_libdir="--libdir=$1"
-        shift ;;
- 
- 
-     --gnu )
-        opt_gnu="--gnu"
-        shift ;;
- 
- 
-     --gnits )
-        opt_gnits="--gnits"
-        shift ;;
- 
- 
-     --cygnus )
-        opt_cygnus="--cygnus"
-        shift ;;
- 
- 
-     --foreign )
-        opt_foreign="--foreign"
-        shift ;;
- 
- 
-     --std-options )
-        opt_std_options="--std-options"
-        shift ;;
- 
- 
-     --include-deps )
-        opt_include_deps="--include-deps"
-        shift ;;
- 
- 
-     --ignore-deps | -i )
-        opt_ignore_deps="--ignore-deps"
-        shift ;;
- 
- 
-     --generate-deps )
-        opt_generate_deps="--generate-deps"
-        shift ;;
- 
- 
-     --no-force )
-        opt_no_force="--no-force"
-        shift ;;
- 
- 
-     --force-missing | -f )
-        opt_force_missing="--force-missing"
-        shift ;;
- 
- 
-     --output-dir=* | -o?* )
-        opt_output_dir="--output-dir=$optarg"
-        shift ;;
-     --output-dir | -o )
-        test $# = 1 && eval "$exit_missing_arg"
-        shift
-        opt_output_dir="--output-dir=$1"
-        shift ;;
-     
- 
-     --add-missing | -a )
-        opt_add_missing="--add-missing"
-        shift ;;
- 
- 
-     --copy | -c )
-        opt_copy="--copy"
-        shift ;;
- 
- 
-     --amdir=* )
-        opt_amdir="--amdir=$optarg"
-        shift ;;
-     --amdir )
-        test $# = 1 && eval "$exit_missing_arg"
-        shift
-        opt_amdir="--amdir=$1"
-        shift ;;
- 
- 
-     --build-dir=* )
-        opt_build_dir="--build-dir=$optarg"
-        shift ;;
-     --build-dir )
-        test $# = 1 && eval "$exit_missing_arg"
-        shift
-        opt_build_dir="--build-dir=$1"
-        shift ;;
- 
- 
-     --srcdir-name=* )
-        opt_srcdir_name="--srcdir-name=$optarg"
-        shift ;;
-     --srcdir-name )
-        test $# = 1 && eval "$exit_missing_arg"
-        shift
-        opt_srcdir_name="--srcdir-name=$1"
-        shift ;;
- 
- 
-     --warnings=* | -W?* )
-        warnings=$warnings,$optarg
-        shift ;;
-     --warnings | -W )
-        test $# = 1 && eval "$exit_missing_arg"
-        shift
-        warnings=$warnings,$1
-        shift ;;
- 
- 
-     -- )     # Stop option processing
-        shift
-        opt_stop="--"
         break ;;
! 
! 
!     - )      # Use stdin as input.
         break ;;
! 
! 
!     -* )
!        exec >&2
!        echo "$me: invalid option $1"
!        echo "$help"
!        exit 1 ;;
! 
! 
!     * )
         break ;;
    esac
  done
  
- # Special handling for the options that can be called 
- # multiple times.
- if [ "x$warnings" != "x" ] ; then
-   opt_warnings="--warnings=$warnings"
- fi
- 
  # some duplicated code (from setpath.frag), but oh well
  
  # Yes, this is very hackish.  But the main operational mode is
--- 1,43 ----
  #! /bin/bash
+ # This is a wrapper for automake that forwards to either the stable or
+ # devel version of the real tool according to the current project's needs.
  AUTO_STABLE=${AUTO_STABLE:-/usr/autotool/stable}
  AUTO_DEVEL=${AUTO_DEVEL:-/usr/autotool/devel}
  
  me=`echo "$0" | sed -e 's,.*[\\/],,'`
  
  # Set up variables
  unset opt_version
  unset opt_help
! unset options
! 
! # Parse command line.  This only looks for --help and --version.
! # There are two ambiguities we cannot resolve without knowledge of the
! # underlying tool, to know when options take arguments.  If --option
! # takes an argument, '--option -- --help' means '--option=-- --help'
! # and we should display wrapper help but don't.  Likewise, if -z does
! # not take an argument, '-zh' means '-z -h', and we should display
! # wrapper help but don't.
  while test $# -gt 0 ; do
    case $1 in
!     --version | -V* ) # Version was requested, no other options matter
         opt_version="--version"
         break ;;
!     --help | -h* )    # Help was requested, no other options matter
!        opt_help="--help"
         break ;;
!     -- )              # Stop option processing
         break ;;
+     * )               # Anything else passed unchanged
+        # Since we are combining multiple arguments into one variable, add
+        # single quotes around each argument, being careful of embedded '
+        sed_quote="s/'/'\\\"'\\\"'/g"
+        argument=`echo "x$1" | sed -e 1s/^x// -e "$sed_quote"`
+        options="$options '$argument'"
+        shift ;;
    esac
  done
  
  # some duplicated code (from setpath.frag), but oh well
  
  # Yes, this is very hackish.  But the main operational mode is
***************
*** 363,373 ****
  
  
  # exec the "real" automake
! exec automake $opt_version $opt_help \
! $opt_verbose $opt_libdir $opt_gnu \
! $opt_gnits $opt_cygnus $opt_foreign \
! $opt_std_options $opt_include_deps $opt_ignore_deps \
! $opt_no_force $opt_force_missing \
! $opt_output_dir $opt_add_missing \
! $opt_copy $opt_werror $opt_wno_error \
! $opt_stop $@
--- 195,198 ----
  
  
  # exec the "real" automake
! eval exec automake $options "$@"

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]