instead of a max number of iterations, record terms that have been seen
authorespie <espie@openbsd.org>
Mon, 6 Nov 2023 08:08:49 +0000 (08:08 +0000)
committerespie <espie@openbsd.org>
Mon, 6 Nov 2023 08:08:49 +0000 (08:08 +0000)
in a hash instead.
Side effect: we no longer parse the same tc again and again, leading
to a smaller result with the same capabilities but no duplicates.
(instead of parsing 36 entries for xterm, we end up with 10 entries, as
the "tc=" stuff is actually a tree instead of a list: xterm references
several intermediate tc that all lead to the same basic list !)

gnu/usr.bin/perl/cpan/Term-Cap/Cap.pm

index 7095c64..6ff3748 100644 (file)
@@ -169,7 +169,7 @@ sub Tgetent
     $self = {} unless defined $self;
     bless $self, $class;
 
-    my ( $term, $cap, $search, $field, $max, $tmp_term, $TERMCAP );
+    my ( $term, $cap, $search, $field, $tmp_term, $TERMCAP );
     my ( $state, $first, $entry ); 
     local $_;
 
@@ -220,6 +220,7 @@ sub Tgetent
 
     # $tmp_term is always the next term (possibly :tc=...:) we are looking for
     $tmp_term = $self->{TERM};
+    my $seen = {};
 
     my $foo = ( exists $ENV{TERMCAP} ? $ENV{TERMCAP} : '' );
 
@@ -227,6 +228,7 @@ sub Tgetent
     if ( ( $foo !~ m:^/:s ) && ( $foo =~ m/(^|\|)\Q$tmp_term\E[:|]/s ) )
     {
         $entry = $foo;
+       $seen->{$tmp_term} = 1;
     }
 
     my @termcap_path = termcap_path();
@@ -252,6 +254,7 @@ sub Tgetent
                         && ( $tmp =~ /(^|\|)\Q$tmp_term\E[:|]/s ) )
                     {
                         $entry = $tmp;
+                       $seen->{$tmp_term} = 1;
                     }
                 };
                 warn "Can't run infocmp to get a termcap entry: $@" if $@;
@@ -275,8 +278,6 @@ sub Tgetent
 
     $first = 0;    # first entry (keeps term name)
 
-    $max = 64;     # max :tc=...:'s
-
     if ($entry)
     {
 
@@ -308,7 +309,6 @@ sub Tgetent
 
             # do the same file again
             # prevent endless recursion
-            $max-- || croak "failed termcap loop at $tmp_term";
             $state = 1;    # ok, maybe do a new file next time
         }
 
@@ -319,6 +319,7 @@ sub Tgetent
                chomp;
                s/^[^:]*:// if $first++;
                $state = 0;
+               $seen->{$tmp_term} = 1;
                while (s/\\$//) {
                    defined(my $x = <$fh>) or last;
                    $_ .= $x; chomp;
@@ -331,7 +332,12 @@ sub Tgetent
         close $fh;
 
         # If :tc=...: found then search this file again
-        $entry =~ s/:tc=([^:]+):/:/ && ( $tmp_term = $1, $state = 2 );
+       while ($entry =~ s/:tc=([^:]+):/:/) {
+           $tmp_term = $1;
+           next if $seen->{$tmp_term};
+           $state = 2;
+           last;
+       }
     }
 
     croak "Can't find $term" if $entry eq '';