Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/local/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H  -I.  -I. -I./include -I./lib   -g -O2
uname output: Linux klokan 2.6.10-1.770_FC3 #1 Thu Feb 24 14:00:06 EST 2005 
i686 i686 i386 GNU/Linux
Machine Type: i686-pc-linux-gnu

Bash Version: 3.0
Patch Level: 0
Release Status: release

Description:
        word_list_split () from subst.c (and probably other functions)
        superfluously takes O(n^2) time, since it operates on a single
        linked list in a inefficient way.  Namely, it calls an O(n)
        function list_append () from list.c for each word added. This
        doesn't cause problems for most scripts etc., since the command
        line is usually short, but it's for example annoying when using
        certain functions of bash completion <http://www.caliban.org/bash/>.
        

Repeat-By:
        a) install bash completion and type
        
             $ man <tab>
        
           It will take a while until the "Display all X possibilities"
           prompt is displayed.
        
        b)
        #!/bin/bash
        a=( `perl -e "print \"abcdefghijkl \"x$1"` )
        echo "[EMAIL PROTECTED]" >/dev/null  # this is slow

        running time ./test 5000; time ./test 10000; time ./test 15000;
        etc.  shows that the time is +- quadratic.

Fix:

list.c externs.h
        - new function list_tail(GENERIC_LIST *), returning list tail or 0

subst.c
        - Make word_list_split O(n) instead of O(n^2). It was slowing down
          bash completion <http://www.caliban.org/bash/> for instance.
          From Michal Marek <[EMAIL PROTECTED]>

diff -rc bash-3.0/externs.h bash-3.0.new/externs.h
*** bash-3.0/externs.h  Tue Apr 13 05:30:08 2004
--- bash-3.0.new/externs.h      Thu Apr 28 23:09:46 2005
***************
*** 124,129 ****
--- 124,130 ----
  extern int list_length ();
  extern GENERIC_LIST *list_append ();
  extern GENERIC_LIST *list_remove ();
+ extern GENERIC_LIST *list_tail ();
  
  /* Declarations for functions defined in stringlib.c */
  extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
diff -rc bash-3.0/list.c bash-3.0.new/list.c
*** bash-3.0/list.c     Mon Mar 18 19:13:54 2002
--- bash-3.0.new/list.c Thu Apr 28 23:14:10 2005
***************
*** 103,108 ****
--- 103,123 ----
    return (head);
  }
  
+ /* When appending multiple times, make the O(n) walk only once.
+  * Ideally, we should have some more efficient structure, storing tail and
+  * length at least...
+  */
+ GENERIC_LIST *
+ list_tail (head)
+      GENERIC_LIST *head;
+ {
+   if (!head)
+     return NULL;
+   for (; head->next; head = head->next)
+     ;
+   return head;
+ }
+ 
  #ifdef INCLUDE_UNUSED
  /* Delete the element of LIST which satisfies the predicate function COMPARER.
     Returns the element that was deleted, so you can dispose of it, or -1 if
diff -rc bash-3.0/subst.c bash-3.0.new/subst.c
*** bash-3.0/subst.c    Sun Jul  4 19:56:13 2004
--- bash-3.0.new/subst.c        Thu Apr 28 23:56:47 2005
***************
*** 6834,6845 ****
  word_list_split (list)
       WORD_LIST *list;
  {
!   WORD_LIST *result, *t, *tresult;
  
!   for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
      {
        tresult = word_split (t->word, ifs_value);
!       result = (WORD_LIST *) list_append (result, tresult);
      }
    return (result);
  }
--- 6834,6848 ----
  word_list_split (list)
       WORD_LIST *list;
  {
!   WORD_LIST *result, *t, *tresult, *tail;
  
!   for (t = list, tail = result = (WORD_LIST *)NULL; t; t = t->next)
      {
        tresult = word_split (t->word, ifs_value);
!       if (!result)
!         result = tresult;
!       list_append(tail, tresult);
!       tail = (WORD_LIST *)list_tail(tresult);
      }
    return (result);
  }


_______________________________________________
Bug-bash mailing list
Bug-bash@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-bash

Reply via email to