bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/5] gnulib-tool: cache module metainformation.


From: Ralf Wildenhues
Subject: [PATCH 1/5] gnulib-tool: cache module metainformation.
Date: Sun, 17 Jan 2010 10:49:34 +0100
User-agent: Mutt/1.5.20 (2009-10-28)

* 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 <address@hidden>
---

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  <address@hidden>
 
+       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  <address@hidden>
+
        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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]