On Sat, Jul 22, 2017 at 04:26:56PM +0300, Vadim Zhukov wrote:
> This patch fixes some long-standing problems with our libtool,
> even allowing it to link more stuff. Antoine, could you please put this
> one in the bulk build instead of previous one?
> 
> FYI, here is a list of ports that could be built without GNU libtool
> with this patch applied:
> 
>  mail/alpine
>  net/libtorrent
>  security/libotr
>  x11/vlc
> 
> Some ports using GNU libtool currently still fail with ours, and some
> ports are in try queue yet. I won't proceed committing there until
> the patch below gets tested, of course.
> 
> I've also found and fixed issue in lang/datalog, the patch is on review.

That's awesome.
Trying it right away, result tomorrow morning.



> 
> --
> WBR,
>   Vadim Zhukov
> 
> 
> Index: LT/UList.pm
> ===================================================================
> RCS file: /cvs/src/usr.bin/libtool/LT/UList.pm,v
> retrieving revision 1.3
> diff -u -p -r1.3 UList.pm
> --- LT/UList.pm       25 Dec 2016 13:46:18 -0000      1.3
> +++ LT/UList.pm       22 Jul 2017 13:17:27 -0000
> @@ -35,7 +35,7 @@ sub _translate_num_key($$;$) {
>       } else {
>               $_[1] += 1;
>       }
> -     die "invalid index" if $_[1] - int($_[2] // 0) >= @{$_[0]};
> +     die "invalid index $_[1]" if $_[1] - int($_[2] // 0) >= @{$_[0]};
>  }
>  
>  # Construct new UList and returnes reference to the array,
> @@ -140,73 +140,53 @@ sub SPLICE
>  
>       my $length = shift;
>       if (defined $length) {
> -             $length = $maxrm - (-$length) if $length < 0;
> -             $length = $maxrm if $length > $maxrm;
> +             if ($length < 0) {
> +                     $length = $maxrm - (-$length);
> +                     $length = 0 if $length < 0;
> +             } elsif ($length > $maxrm) {
> +                     $length = $maxrm;
> +             }
>       } else {
>               $length = $maxrm;
>       }
>  
> -     my $i = @$self;
> -
> -     # make sure no duplicates get added
> -     @_ = grep { !exists $self->[0] or
> -                 $self->[0]->{$_} >= $offset &&
> -                 $self->[0]->{$_} < $offset + $length } @_;
> -
> -     for (@_) {
> -             # set up index
> -             $self->[0]->{$_} = $i++;
> -     }
> +     # trailing elemenets positions to be renumbered by adding $delta
> +     my $delta = -$length;
>  
>       #
> -     # Renumber (in advance) trailing items, in case something gets added
> -     # and number of added and removed items differs.
> +     # First, always remove elements; then add one by one.
> +     # This way we can be sure to not add duplicates, even if
> +     # they exist in added elements, e.g., adding ("-lfoo", "-lfoo").
>       #
> -     my $delta = scalar(@_) - $length;
> -     if (scalar(@_) and $delta) {
> -             for $i ($offset + $length .. scalar(@$self)) {
> -                     $self->[0]->{$self->[$i]} += $delta;
> -             }
> -     }
> -
> -     my @ret = splice(@$self, $offset, $length, @_);
>  
> +     my @ret = splice(@$self, $offset, $length);
>       for (@ret) {
>               delete $self->[0]->{$_};
>       }
> -     for ($offset .. scalar(@$self) - 1) {
> -             $self->[0]->{$self->[$_]} -= $length;
> -     }
>  
> -     return @ret unless scalar(@_);
> -
> -     if ($length == $maxrm) {
> -             # simply add items to the end
> -             $self->PUSH(@_);
> -             return @ret;
> -     }
> -
> -     my $newpos = $offset;
> +     my $i = 0;
> +     my %seen;
>       for (@_) {
> -             my $index = $self->[0]->{$_};
> -             if (defined $index) {
> -                     if ($index < $offset) {
> -                             # skip current item totally
> -                             continue;
> -                     } elsif ($index == $offset) {
> -                             # skip adding but act as if added
> -                             $self->[0]->{$_} += $newpos - $offset;
> -                             $newpos++;
> +             next if exists $seen{$_};       # skip already added items
> +             $seen{$_} = 1;
> +             if (exists $self->[0]->{$_}) {
> +                     if ($self->[0]->{$_} >= $offset + $length) {
> +                             # "move" from tail to new position
> +                             splice(@$self, $self->[0]->{$_} - $length + $i, 
> 1);
> +                     } else {
>                               next;
>                       }
> -                     splice(@$self, $index, 1);
>               }
> -             splice(@$self, $newpos, 0, $_);
> -             $self->[0]->{$_} = $newpos++;
> +             splice(@$self, $offset + $i, 0, $_);
> +             $self->[0]->{$_} = $offset + $i;
> +             $i++;
> +             $delta++;
>       }
> -     for ($newpos .. scalar(@$self) - 1) {
> -             $self->[0]->{$self->[$_]} += $newpos - $offset;
> +
> +     for $i ($offset + scalar(@_) .. @$self - 1) {
> +             $self->[0]->{$self->[$i]} = $i;
>       }
> +
>       return @ret;
>  }
>  
> @@ -214,18 +194,64 @@ sub SPLICE
>  =head1 test
>  package main;
>  
> +sub compare_ulists {
> +     my ($list1, $list2) = @_;
> +     return 0 if scalar(@$list1) != scalar(@$list2);
> +     for my $i (0 .. scalar(@$list1) - 1) {
> +             return 0 if $list1->[$i] ne $list2->[$i];
> +     }
> +     return 1;
> +}
> +
>  my $r = ['/path0', '/path1'];
>  tie(@$r, 'LT::UList');
> -#push(@$r, '/path0');
> -#push(@$r, '/path1');
> +push(@$r, '/path0');
> +push(@$r, '/path1');
>  push(@$r, '/path2');
>  push(@$r, '/path3');
>  push(@$r, '/path4');
>  push(@$r, '/path3');
>  push(@$r, '/path1');
>  push(@$r, '/path5');
> -say "spliced: ".join(", ", splice(@$r, 2, 2, '/pathAdd1', '/pathAdd2', 
> '/pathAdd1'));
> -#say "a: ".join(", ", @a);
> -say "r: ".join(", ", @$r);
> -#say "r2: ".join(", ", @$r2);
> +
> +my @tests = (
> +     # offset, length, args,
> +     # expected resulting array
> +
> +     [
> +             3, 0, [],
> +             ['/path0', '/path1', '/path2', '/path3', '/path4', '/path5']
> +     ],
> +
> +     [
> +             3, 2, [],
> +             ['/path0', '/path1', '/path2', '/path5']
> +     ],
> +
> +     [
> +             0, 3, ['/path0', '/path1', '/path2'],
> +             ['/path0', '/path1', '/path2', '/path5']
> +     ],
> +
> +     [
> +             0, 3, ['/path0', '/path5', '/path5', '/path2'],
> +             ['/path0', '/path5', '/path2']
> +     ],
> +
> +     [
> +             0, 3, [],
> +             []
> +     ],
> +
> +);
> +
> +for my $t (@tests) {
> +     splice(@$r, $t->[0], $t->[1], @{$t->[2]});
> +     if (!compare_ulists($r, $t->[3])) {
> +             say "expected: ".join(", ", @{$t->[2]});
> +             say "     got: ".join(", ", @$r);
> +             exit 1;
> +     }
> +}
> +exit 0;
>  =cut
> 

-- 
Antoine

Reply via email to