Ralf Wildenhues wrote: > PPS: should the number of files used by a project exceed a few hundred, > it may make sense to exploit bash3's `+=' with a func_append, in order > to avoid the quadratic scaling associated with string enlargement:
Here's the patch I committed. 2006-09-17 Bruno Haible <[EMAIL PROTECTED]> * gnulib-tool (func_append): New function, stolen from libtool.m4. (func_modules_transitive_closure, func_modules_add_dummy, func_modules_to_filelist, func_import, func_create_testdir, func_create_megatestdir, ...): Use it wherever possible. Suggested by Ralf Wildenhues. *** gnulib-tool 2006-09-17 15:02:36.000000000 +0200 --- gnulib-tool 2006-09-17 15:31:19.000000000 +0200 *************** *** 210,215 **** --- 210,231 ---- } } + # func_append var value + # appends the given value to the shell variable var. + if ( foo=bar; foo+=baz && test "$foo" = barbaz ) >/dev/null 2>&1; then + # Use bash's += operator. It reduces complexity of appending repeatedly to + # a single variable from O(n^2) to O(n). + func_append () + { + eval "$1+=\"\$2\"" + } + else + func_append () + { + eval "$1=\"\$$1\$2\"" + } + fi + # func_fatal_error message # outputs to stderr a fatal error message, and terminates the program. func_fatal_error () *************** *** 505,514 **** if test $# = 0; then func_fatal_error "missing argument for --avoid" fi ! avoidlist="$avoidlist $1" shift ;; --avoid=* ) ! avoidlist="$avoidlist "`echo "X$1" | sed -e 's/^X--avoid=//'` shift ;; --lgpl ) lgpl=true --- 521,531 ---- if test $# = 0; then func_fatal_error "missing argument for --avoid" fi ! func_append avoidlist " $1" shift ;; --avoid=* ) ! arg=`echo "X$1" | sed -e 's/^X--avoid=//'` ! func_append " $arg" shift ;; --lgpl ) lgpl=true *************** *** 945,962 **** func_verify_module if test -n "$module"; then if func_acceptable $module; then ! outmodules="$outmodules $module" deps=`func_get_dependencies $module` # Duplicate dependencies are harmless, but Jim wants a warning. duplicated_deps=`echo "$deps" | LC_ALL=C sort | LC_ALL=C uniq -d` if test -n "$duplicated_deps"; then echo "warning: module $module has duplicated dependencies: "`echo $duplicated_deps` 1>&2 fi ! inmodules="$inmodules $deps" if test -n "$inctests"; then testsmodule=`func_get_tests_module $module` if test -n "$testsmodule"; then ! inmodules="$inmodules $testsmodule" fi fi fi --- 962,979 ---- func_verify_module if test -n "$module"; then if func_acceptable $module; then ! func_append outmodules " $module" deps=`func_get_dependencies $module` # Duplicate dependencies are harmless, but Jim wants a warning. duplicated_deps=`echo "$deps" | LC_ALL=C sort | LC_ALL=C uniq -d` if test -n "$duplicated_deps"; then echo "warning: module $module has duplicated dependencies: "`echo $duplicated_deps` 1>&2 fi ! func_append inmodules " $deps" if test -n "$inctests"; then testsmodule=`func_get_tests_module $module` if test -n "$testsmodule"; then ! func_append inmodules " $testsmodule" fi fi fi *************** *** 1002,1008 **** done # Add the dummy module, to make sure the library will be non-empty. if test -z "$have_lib_SOURCES"; then ! modules="$modules dummy" fi } --- 1019,1025 ---- done # Add the dummy module, to make sure the library will be non-empty. if test -z "$have_lib_SOURCES"; then ! func_append modules " dummy" fi } *************** *** 1018,1024 **** for module in $modules; do func_verify_module if test -n "$module"; then ! files="$files "`func_get_filelist $module` fi done files=`for f in $files; do echo $f; done | LC_ALL=C sort -u` --- 1035,1042 ---- for module in $modules; do func_verify_module if test -n "$module"; then ! fs=`func_get_filelist $module` ! func_append files " $fs" fi done files=`for f in $files; do echo $f; done | LC_ALL=C sort -u` *************** *** 1477,1483 **** new_files="$files m4/gnulib-tool.m4" old_files="$cached_files" if test -f "$destdir"/$m4base/gnulib-tool.m4; then ! old_files="$old_files m4/gnulib-tool.m4" fi # Create directories. --- 1495,1501 ---- new_files="$files m4/gnulib-tool.m4" old_files="$cached_files" if test -f "$destdir"/$m4base/gnulib-tool.m4; then ! func_append old_files " m4/gnulib-tool.m4" fi # Create directories. *************** *** 1666,1696 **** # Command-line invocation printed in a comment in generated gnulib-cache.m4. actioncmd="gnulib-tool --import" ! actioncmd="$actioncmd --dir=$destdir" if test -n "$local_gnulib_dir"; then ! actioncmd="$actioncmd --local-dir=$local_gnulib_dir" fi ! actioncmd="$actioncmd --lib=$libname" ! actioncmd="$actioncmd --source-base=$sourcebase" ! actioncmd="$actioncmd --m4-base=$m4base" ! actioncmd="$actioncmd --doc-base=$docbase" ! actioncmd="$actioncmd --aux-dir=$auxdir" for module in $avoidlist; do ! actioncmd="$actioncmd --avoid=$module" done if test -n "$lgpl"; then ! actioncmd="$actioncmd --lgpl" fi if test -n "$makefile_name"; then ! actioncmd="$actioncmd --makefile_name=$makefile_name" fi if test "$libtool" = true; then ! actioncmd="$actioncmd --libtool" else ! actioncmd="$actioncmd --no-libtool" fi ! actioncmd="$actioncmd --macro-prefix=$macro_prefix" ! actioncmd="$actioncmd `echo $specified_modules`" # Default the makefile name to Makefile.am. if test -n "$makefile_name"; then --- 1684,1714 ---- # Command-line invocation printed in a comment in generated gnulib-cache.m4. actioncmd="gnulib-tool --import" ! func_append actioncmd " --dir=$destdir" if test -n "$local_gnulib_dir"; then ! func_append actioncmd " --local-dir=$local_gnulib_dir" fi ! func_append actioncmd " --lib=$libname" ! func_append actioncmd " --source-base=$sourcebase" ! func_append actioncmd " --m4-base=$m4base" ! func_append actioncmd " --doc-base=$docbase" ! func_append actioncmd " --aux-dir=$auxdir" for module in $avoidlist; do ! func_append actioncmd " --avoid=$module" done if test -n "$lgpl"; then ! func_append actioncmd " --lgpl" fi if test -n "$makefile_name"; then ! func_append actioncmd " --makefile_name=$makefile_name" fi if test "$libtool" = true; then ! func_append actioncmd " --libtool" else ! func_append actioncmd " --no-libtool" fi ! func_append actioncmd " --macro-prefix=$macro_prefix" ! func_append actioncmd " `echo $specified_modules`" # Default the makefile name to Makefile.am. if test -n "$makefile_name"; then *************** *** 2083,2089 **** mkdir -p "$testdir/po" (echo "## Process this file with automake to produce Makefile.in." ) > "$testdir/po/Makefile.am" ! subdirs="$subdirs po" fi if test -n "$inctests"; then --- 2101,2107 ---- mkdir -p "$testdir/po" (echo "## Process this file with automake to produce Makefile.in." ) > "$testdir/po/Makefile.am" ! func_append subdirs " po" fi if test -n "$inctests"; then *************** *** 2178,2184 **** echo echo "AC_OUTPUT([Makefile])" ) > "$testdir/$testsbase/configure.ac" ! subdirs="$subdirs $testsbase" subdirs_with_configure_ac="$subdirs_with_configure_ac $testsbase" fi --- 2196,2202 ---- echo echo "AC_OUTPUT([Makefile])" ) > "$testdir/$testsbase/configure.ac" ! func_append subdirs " $testsbase" subdirs_with_configure_ac="$subdirs_with_configure_ac $testsbase" fi *************** *** 2279,2285 **** # configure.ac which creates the subdir's Makefile.am, not this one. case " $subdirs_with_configure_ac " in *" $d "*) ;; ! *) makefiles="$makefiles $d/Makefile" ;; esac done echo "AC_OUTPUT([$makefiles])" --- 2297,2303 ---- # configure.ac which creates the subdir's Makefile.am, not this one. case " $subdirs_with_configure_ac " in *" $d "*) ;; ! *) func_append makefiles " $d/Makefile" ;; esac done echo "AC_OUTPUT([$makefiles])" *************** *** 2318,2330 **** # First, all modules one by one. for onemodule in $allmodules; do func_create_testdir "$megatestdir/$onemodule" $onemodule ! megasubdirs="${megasubdirs}$onemodule " done # Then, all modules all together. # Except fnmatch-posix, which conflicts with fnmatch-gnu. FIXME. allmodules=`for m in $allmodules; do if test $m != fnmatch-posix; then echo $m; fi; done` func_create_testdir "$megatestdir/ALL" "$allmodules" ! megasubdirs="${megasubdirs}ALL" # Create Makefile.am. (echo "## Process this file with automake to produce Makefile.in." --- 2336,2348 ---- # First, all modules one by one. for onemodule in $allmodules; do func_create_testdir "$megatestdir/$onemodule" $onemodule ! func_append megasubdirs "$onemodule " done # Then, all modules all together. # Except fnmatch-posix, which conflicts with fnmatch-gnu. FIXME. allmodules=`for m in $allmodules; do if test $m != fnmatch-posix; then echo $m; fi; done` func_create_testdir "$megatestdir/ALL" "$allmodules" ! func_append megasubdirs "ALL" # Create Makefile.am. (echo "## Process this file with automake to produce Makefile.in." *************** *** 2441,2447 **** /*) ;; *) if test -f "$destdir/$arg"/gnulib-cache.m4; then ! m4dirs="$m4dirs $arg" m4dirs_count=`expr $m4dirs_count + 1` fi ;; --- 2459,2465 ---- /*) ;; *) if test -f "$destdir/$arg"/gnulib-cache.m4; then ! func_append m4dirs " $arg" m4dirs_count=`expr $m4dirs_count + 1` fi ;;