* gnulib-tool (sed_extract_prog): Match newline before each header, and rewrite header to a shell variable suffix. (func_cache_var, func_cache_lookup_module): New functions, to turn a module name into a cache variable prefix, and to look up and cache module metainformation. (func_get_description, func_get_status) (func_get_notice, func_get_applicability, func_get_filelist) (func_get_dependencies, func_get_autoconf_early_snippet) (func_get_autoconf_snippet, func_get_automake_snippet) (func_get_include_directive, func_get_link_directive) (func_get_license, func_get_maintainer): Use func_cache_lookup_module.
Signed-off-by: Ralf Wildenhues <ralf.wildenh...@gmx.de> --- This patch rebases the old version of the patch. A couple of new instances of function usage required a couple new hunks. The "unmaintainable" sed script still worked fine, but I hit HP-UX sed pattern space length limitations with it due to the size of the unistd module description, so I decided to rewrite it as two sed scripts, avoiding the need to slurp in a complete database field before writing it out. Whether that makes the variable-less state machine that is the sed script more or less readable and maintainable, I can't really judge, but I'm fairly confident that I haven't introduced arbitrary code execution possibilities with those eval statements. I've also added a few comments (outside the sed scripts, for portability reasons). Thanks, Ralf ChangeLog | 16 +++++ gnulib-tool | 216 ++++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 179 insertions(+), 53 deletions(-) diff --git a/ChangeLog b/ChangeLog index e3498fa..9959305 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2010-01-17 Ralf Wildenhues <ralf.wildenh...@gmx.de> + gnulib-tool: cache module metainformation. + * gnulib-tool (sed_extract_prog): Match newline before each + header, and rewrite header to a shell variable suffix. + (func_cache_var, func_cache_lookup_module): New functions, + to turn a module name into a cache variable prefix, and to + look up and cache module metainformation. + (func_get_description, func_get_status) + (func_get_notice, func_get_applicability, func_get_filelist) + (func_get_dependencies, func_get_autoconf_early_snippet) + (func_get_autoconf_snippet, func_get_automake_snippet) + (func_get_include_directive, func_get_link_directive) + (func_get_license, func_get_maintainer): Use + func_cache_lookup_module. + +2010-01-17 Ralf Wildenhues <ralf.wildenh...@gmx.de> + gnulib-tool: fix filelist for AIX, HP-UX ksh. * gnulib-tool (func_filter_filelist): Do not quote possibly-empty variables in shell case patterns, for AIX and HP-UX ksh. diff --git a/gnulib-tool b/gnulib-tool index ce1bbe9..bb040de 100755 --- a/gnulib-tool +++ b/gnulib-tool @@ -1342,35 +1342,141 @@ func_verify_tests_module () esac } -sed_extract_prog=':[ ]*$/ { - :a - n - s/^Description:[ ]*$// - s/^Status:[ ]*$// - s/^Notice:[ ]*$// - s/^Applicability:[ ]*$// - s/^Files:[ ]*$// - s/^Depends-on:[ ]*$// - s/^configure\.ac-early:[ ]*$// - s/^configure\.ac:[ ]*$// - s/^Makefile\.am:[ ]*$// - s/^Include:[ ]*$// - s/^Link:[ ]*$// - s/^License:[ ]*$// - s/^Maintainer:[ ]*$// - tb - p - ba - :b -}' +# func_cache_var file +# +# return the cache variable name corresponding to $file. +# Output: +# - cachevar +if test -n "$BASH_VERSION"; then + func_cache_var () + { + cachevar=c_${1//[!a-zA-Z0-9_]/_} + } +else + func_cache_var () + { + case $1 in + *[!a-zA-Z0-9_]*) + cachevar=c_`echo "$1" | LC_ALL=C sed 's/[^a-zA-Z0-9_]/_/g'` ;; + *) + cachevar=c_$1 ;; + esac + } +fi + +# Extract headers from module descriptions. +sed_extract_prog=" + s/^Description:[ ]*$/desc/ + s/^Status:[ ]*$/status/ + s/^Notice:[ ]*$/notice/ + s/^Applicability:[ ]*$/applicability/ + s/^Files:[ ]*$/files/ + s/^Depends-on:[ ]*$/deps/ + s/^configure\.ac-early:[ ]*$/config_early/ + s/^configure\.ac:[ ]*$/config/ + s/^Makefile\.am:[ ]*$/makefile/ + s/^Include:[ ]*$/include/ + s/^Link:[ ]*$/link/ + s/^License:[ ]*$/license/ + s/^Maintainer:[ ]*$/maint/" + +# func_cache_lookup_module file +# +# look up a module, like 'func_lookup_file modules/$file', and store all of its +# relevant data in a cache. If already cached, do not look it up again. +# Input: +# - file +# Output: +# - cachevar +# - ${cachevar}_cached +# - ${cachevar}_desc +# - ${cachevar}_status +# - ... +func_cache_lookup_module () +{ + func_cache_var "$1" + if eval test -z \"\$${cachevar}_cached\"; then + func_lookup_file "modules/$1" + # Turn module descriptions into shell script assignments, + # suitable to be eval'ed. All active characters are escaped. + # This script turns + # Description: + # Some module's description + # + # Files: + # lib/file.h + # into: + # c_MODULE_cached='yes + # ' + # c_MODULE_desc=\ + # 'Some module'\''s description + # + # ' + # c_MODULE_files=\ + # 'lib/file.h' + # The script consists of four parts: + # 1) Insert the "c_MODULE_cached='yes" line, + # 2) The 'match' loop, treating non-header lines by escaping single + # quotes and adding a closing quote in the last line, + # 3) The 'header' treatment, closing the last quote and inserting + # the "c_MODULE_HEADER=" assignment line as well starting the + # following line with an opening quote, if any. + # 4) Special treatment if two headers are only separated by one newline. + sed_cache_module=' + 1i\'$nl$cachevar'_cached='\''yes\'$nl' + + :match + t match + '"$sed_extract_prog"' + t hdr + s/'\''/&"'\''"&/g + :more + $s/$/'\''/ + n + b match + + :hdr + s/\([a-zA-Z0-9_]\{1,\}\)[ ]*$/'\'\\$nl${cachevar}_'\1=/ + $!s/$/\\/ + n + t clear + :clear + '"$sed_extract_prog"' + t hdr2 + s/'\''/&"'\''"&/g + s/^/'\''/ + b more + + :hdr2 + s/^/'\'\\$nl'/ + b hdr + ' + # Strip trailing newlines from quoted variable assignment strings. + sed_strip_trailing_nl=' + :more + $b cut + /\\$/{ + p + d + } + N + /\n$/b more + :cut + s/\n\n*\('\''\)$/\1/ + ' + cache_script=`sed "$sed_cache_module" < "$lookedup_file" \ + | sed "$sed_strip_trailing_nl"` + eval "$cache_script" + fi +} # func_get_description module # Input: # - local_gnulib_dir from --local-dir func_get_description () { - func_lookup_file "modules/$1" - sed -n -e "/^Description$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_desc\"" } # func_get_status module @@ -1378,8 +1484,8 @@ func_get_description () # - local_gnulib_dir from --local-dir func_get_status () { - func_lookup_file "modules/$1" - sed -n -e "/^Status$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_status\"" } # func_get_notice module @@ -1387,8 +1493,8 @@ func_get_status () # - local_gnulib_dir from --local-dir func_get_notice () { - func_lookup_file "modules/$1" - sed -n -e "/^Notice$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_notice\"" } # func_get_applicability module @@ -1397,14 +1503,17 @@ func_get_notice () # The expected result (on stdout) is either 'main', or 'tests', or 'all'. func_get_applicability () { - func_lookup_file "modules/$1" - { sed -n -e "/^Applicability$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval my_applicability=\$${cachevar}_applicability + if test -n "$my_applicability"; then + echo $my_applicability + else # The default is 'main' or 'tests', depending on the module's name. - case "$1" in - *-tests) echo "tests";; - *) echo "main";; + case $1 in + *-tests) echo tests;; + *) echo main;; esac - } | sed -e 's,^ *$,,' | sed -e 1q + fi } # func_get_filelist module @@ -1412,8 +1521,8 @@ func_get_applicability () # - local_gnulib_dir from --local-dir func_get_filelist () { - func_lookup_file "modules/$1" - sed -n -e "/^Files$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_files\"" echo m4/00gnulib.m4 echo m4/gnulib-common.m4 case "$autoconf_minversion" in @@ -1480,12 +1589,12 @@ func_get_dependencies () *-tests) fgd1="$1" func_remove_suffix fgd1 '-tests' - echo "$fgd1" + module_deps=$fgd1 ;; esac # Then the explicit dependencies listed in the module description. - func_lookup_file "modules/$1" - sed -n -e "/^Depends-on$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_deps\"" } # func_get_autoconf_early_snippet module @@ -1493,8 +1602,8 @@ func_get_dependencies () # - local_gnulib_dir from --local-dir func_get_autoconf_early_snippet () { - func_lookup_file "modules/$1" - sed -n -e "/^configure\.ac-early$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_config_early\"" } # func_get_autoconf_snippet module @@ -1502,8 +1611,8 @@ func_get_autoconf_early_snippet () # - local_gnulib_dir from --local-dir func_get_autoconf_snippet () { - func_lookup_file "modules/$1" - sed -n -e "/^configure\.ac$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_config\"" } # func_get_automake_snippet module @@ -1511,8 +1620,8 @@ func_get_autoconf_snippet () # - local_gnulib_dir from --local-dir func_get_automake_snippet () { - func_lookup_file "modules/$1" - sed -n -e "/^Makefile\.am$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_makefile\"" case "$1" in *-tests) # *-tests module live in tests/, not lib/. @@ -1536,7 +1645,7 @@ func_get_automake_snippet () }' sed_extract_mentioned_files='s/^lib_SOURCES[ ]*+=[ ]*//p' already_mentioned_files=` \ - sed -n -e "/^Makefile\.am$sed_extract_prog" < "$lookedup_file" \ + { eval 'echo "$'${cachevar}'_makefile"'; echo; } \ | sed -e "$sed_combine_lines" \ | sed -n -e "$sed_extract_mentioned_files" | sed -e 's/#.*//'` all_files=`func_get_filelist $1` @@ -1594,8 +1703,8 @@ func_get_automake_snippet () # - local_gnulib_dir from --local-dir func_get_include_directive () { - func_lookup_file "modules/$1" - sed -n -e "/^Include$sed_extract_prog" < "$lookedup_file" | \ + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_include\"" | \ sed -e 's/^\(["<]\)/#include \1/' } @@ -1604,8 +1713,8 @@ func_get_include_directive () # - local_gnulib_dir from --local-dir func_get_link_directive () { - func_lookup_file "modules/$1" - sed -n -e "/^Link$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_link\"" } # func_get_license module @@ -1613,8 +1722,9 @@ func_get_link_directive () # - local_gnulib_dir from --local-dir func_get_license () { - func_lookup_file "modules/$1" - { sed -n -e "/^License$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + { + eval "echo \"\$${cachevar}_license\"" # The default is GPL. echo "GPL" } | sed -e 's,^ *$,,' | sed -e 1q @@ -1625,8 +1735,8 @@ func_get_license () # - local_gnulib_dir from --local-dir func_get_maintainer () { - func_lookup_file "modules/$1" - sed -n -e "/^Maintainer$sed_extract_prog" < "$lookedup_file" + func_cache_lookup_module "$1" + eval "echo \"\$${cachevar}_maint\"" } # func_get_tests_module module -- 1.6.5.1.31.gad12b