| @@ -1,16 +1,16 @@ | | | @@ -1,16 +1,16 @@ |
1 | #!@PERL5@ | | 1 | #!@PERL5@ |
2 | | | 2 | |
3 | # $NetBSD: lintpkgsrc.pl,v 1.61 2022/08/09 19:31:57 rillig Exp $ | | 3 | # $NetBSD: lintpkgsrc.pl,v 1.62 2022/08/09 19:42:46 rillig Exp $ |
4 | | | 4 | |
5 | # Written by David Brownlee <abs@netbsd.org>. | | 5 | # Written by David Brownlee <abs@netbsd.org>. |
6 | # | | 6 | # |
7 | # Caveats: | | 7 | # Caveats: |
8 | # The 'Makefile parsing' algorithm used to obtain package versions and | | 8 | # The 'Makefile parsing' algorithm used to obtain package versions and |
9 | # DEPENDS information is geared towards speed rather than perfection, | | 9 | # DEPENDS information is geared towards speed rather than perfection, |
10 | # though it has gotten somewhat better over time, it only parses the | | 10 | # though it has gotten somewhat better over time, it only parses the |
11 | # simpler Makefile conditionals. | | 11 | # simpler Makefile conditionals. |
12 | # | | 12 | # |
13 | # TODO: Handle fun DEPENDS like avifile-devel with | | 13 | # TODO: Handle fun DEPENDS like avifile-devel with |
14 | # {qt2-designer>=2.2.4,qt2-designer-kde>=2.3.1nb1} | | 14 | # {qt2-designer>=2.2.4,qt2-designer-kde>=2.3.1nb1} |
15 | | | 15 | |
16 | use locale; | | 16 | use locale; |
| @@ -429,106 +429,106 @@ sub parse_makefile_line_include($$$$$$) | | | @@ -429,106 +429,106 @@ sub parse_makefile_line_include($$$$$$) |
429 | # At this point just skip any includes which we were | | 429 | # At this point just skip any includes which we were |
430 | # not able to fully expand. | | 430 | # not able to fully expand. |
431 | if ($incfile =~ m#/mk/bsd# | | 431 | if ($incfile =~ m#/mk/bsd# |
432 | || $incfile =~ /$magic_undefined/ | | 432 | || $incfile =~ /$magic_undefined/ |
433 | || $incfile =~ /\$\{/ | | 433 | || $incfile =~ /\$\{/ |
434 | || (!$opt{d} && $incfile =~ m#/(buildlink[^/]*\.mk)#)) { | | 434 | || (!$opt{d} && $incfile =~ m#/(buildlink[^/]*\.mk)#)) { |
435 | debug("$file: .include \"$incfile\" skipped\n"); | | 435 | debug("$file: .include \"$incfile\" skipped\n"); |
436 | return; | | 436 | return; |
437 | } | | 437 | } |
438 | | | 438 | |
439 | debug("$file: .include \"$incfile\"\n"); | | 439 | debug("$file: .include \"$incfile\"\n"); |
440 | | | 440 | |
441 | if (substr($incfile, 0, 1) ne '/') { | | 441 | if (substr($incfile, 0, 1) ne '/') { |
442 | foreach my $dir (keys %$incdirs) { | | 442 | foreach my $dir (reverse @$incdirs) { |
443 | if (-f "$dir/$incfile") { | | 443 | if (-f "$dir/$incfile") { |
444 | $incfile = "$dir/$incfile"; | | 444 | $incfile = "$dir/$incfile"; |
445 | last; | | 445 | last; |
446 | } | | 446 | } |
447 | } | | 447 | } |
448 | } | | 448 | } |
449 | | | 449 | |
450 | # perl 5.6.1 realpath() cannot handle files, only directories. | | 450 | # perl 5.6.1 realpath() cannot handle files, only directories. |
451 | # If the last component is a symlink, this will give a false | | 451 | # If the last component is a symlink, this will give a false |
452 | # negative, but that is not a problem, as the duplicate check | | 452 | # negative, but that is not a problem, as the duplicate check |
453 | # is for performance. | | 453 | # is for performance. |
454 | $incfile =~ m#^(.+)(/[^/]+)$#; | | 454 | $incfile =~ m#^(.+)(/[^/]+)$#; |
455 | | | 455 | |
456 | if (!-f $incfile) { | | 456 | if (!-f $incfile) { |
457 | $opt{L} or verbose("\n"); | | 457 | $opt{L} or verbose("\n"); |
458 | | | 458 | |
459 | my $dirs = join(' ', sort keys %$incdirs); | | 459 | my $dirs = join(' ', @$incdirs); |
460 | verbose("$file: Cannot locate $incfile in $dirs\n"); | | 460 | verbose("$file: Cannot locate $incfile in $dirs\n"); |
461 | return; | | 461 | return; |
462 | } | | 462 | } |
463 | | | 463 | |
464 | $incfile = realpath($1) . $2; | | 464 | $incfile = realpath($1) . $2; |
465 | return if $included->{$incfile}; | | 465 | return if $included->{$incfile}; |
466 | | | 466 | |
467 | $opt{L} and print "inc $incfile\n"; | | 467 | $opt{L} and print "inc $incfile\n"; |
468 | $included->{$incfile} = 1; | | 468 | $included->{$incfile} = 1; |
469 | | | 469 | |
470 | if (!open(FILE, $incfile)) { | | 470 | if (!open(FILE, $incfile)) { |
471 | verbose("Cannot open '$incfile' (from $file): $_ $!\n"); | | 471 | verbose("Cannot open '$incfile' (from $file): $_ $!\n"); |
472 | return; | | 472 | return; |
473 | } | | 473 | } |
474 | | | 474 | |
475 | my $NEWCURDIR = $incfile; | | 475 | my $NEWCURDIR = $incfile; |
476 | $NEWCURDIR =~ s#/[^/]*$##; | | 476 | $NEWCURDIR =~ s#/[^/]*$##; |
477 | $incdirs->{$NEWCURDIR} = 1; | | 477 | push(@$incdirs, $NEWCURDIR) |
| | | 478 | unless grep { $_ eq $NEWCURDIR } @$incdirs; |
478 | unshift(@$lines, ".CURDIR=" . $vars->{'.CURDIR'}); | | 479 | unshift(@$lines, ".CURDIR=" . $vars->{'.CURDIR'}); |
479 | chomp(my @inc_lines = <FILE>); | | 480 | chomp(my @inc_lines = <FILE>); |
480 | unshift(@$lines, @inc_lines); | | 481 | unshift(@$lines, @inc_lines); |
481 | unshift(@$lines, ".CURDIR=$NEWCURDIR"); | | 482 | unshift(@$lines, ".CURDIR=$NEWCURDIR"); |
482 | close(FILE); | | 483 | close(FILE); |
483 | } | | 484 | } |
484 | | | 485 | |
485 | # Extract variable assignments from Makefile | | 486 | # Extract variable assignments from Makefile |
486 | # Much unpalatable magic to avoid having to use make (all for speed) | | 487 | # Much unpalatable magic to avoid having to use make (all for speed) |
487 | # | | 488 | # |
488 | sub parse_makefile_vars($$) { | | 489 | sub parse_makefile_vars($$) { |
489 | my ($file, $cwd) = @_; | | 490 | my ($file, $cwd) = @_; |
490 | my ( | | 491 | |
491 | %vars, $plus, $value, | | 492 | my %vars; |
492 | %incfiles, # Cache of previously included fils | | 493 | my %incfiles; # Cache of previously included files |
493 | %incdirs, # Directories in which to check for includes | | 494 | my @incdirs; # Directories in which to check for includes |
494 | @if_false | | 495 | my @if_false; # 0:true 1:false 2:nested-false&nomore-elsif |
495 | ); # 0:true 1:false 2:nested-false&nomore-elsif | | | |
496 | my @lines; | | 496 | my @lines; |
497 | | | 497 | |
498 | open(FILE, $file) or return undef; | | 498 | open(FILE, $file) or return undef; |
499 | chomp(@lines = <FILE>); | | 499 | chomp(@lines = <FILE>); |
500 | close(FILE); | | 500 | close(FILE); |
501 | | | 501 | |
502 | $incdirs{'.'} = 1; | | 502 | push(@incdirs, '.'); |
503 | $incdirs{dirname($file)} = 1; | | 503 | push(@incdirs, dirname($file)); |
504 | | | 504 | |
505 | # Some Makefiles depend on these being set | | 505 | # Some Makefiles depend on these being set |
506 | if ($file eq '/etc/mk.conf') { | | 506 | if ($file eq '/etc/mk.conf') { |
507 | $vars{LINTPKGSRC} = 'YES'; | | 507 | $vars{LINTPKGSRC} = 'YES'; |
508 | } else { | | 508 | } else { |
509 | %vars = %{$default_vars}; | | 509 | %vars = %{$default_vars}; |
510 | } | | 510 | } |
511 | $vars{BSD_PKG_MK} = 'YES'; | | 511 | $vars{BSD_PKG_MK} = 'YES'; |
512 | | | 512 | |
513 | if ($cwd) { | | 513 | if ($cwd) { |
514 | $vars{'.CURDIR'} = $cwd; | | 514 | $vars{'.CURDIR'} = $cwd; |
515 | } elsif ($file =~ m#(.*)/#) { | | 515 | } elsif ($file =~ m#(.*)/#) { |
516 | $vars{'.CURDIR'} = $1; | | 516 | $vars{'.CURDIR'} = $1; |
517 | } else { | | 517 | } else { |
518 | $vars{'.CURDIR'} = getcwd; | | 518 | $vars{'.CURDIR'} = getcwd; |
519 | } | | 519 | } |
520 | | | 520 | |
521 | $incdirs{$vars{'.CURDIR'}} = 1; | | 521 | push(@incdirs, $vars{'.CURDIR'}); |
522 | if ($opt{L}) { | | 522 | if ($opt{L}) { |
523 | print "$file\n"; | | 523 | print "$file\n"; |
524 | } | | 524 | } |
525 | | | 525 | |
526 | while (defined($_ = shift(@lines))) { | | 526 | while (defined($_ = shift(@lines))) { |
527 | s/\s*[^\\]#.*//; | | 527 | s/\s*[^\\]#.*//; |
528 | | | 528 | |
529 | # Continuation lines | | 529 | # Continuation lines |
530 | # | | 530 | # |
531 | while (substr($_, -1) eq "\\" && @lines > 0) { | | 531 | while (substr($_, -1) eq "\\" && @lines > 0) { |
532 | substr($_, -2) = shift @lines; | | 532 | substr($_, -2) = shift @lines; |
533 | } | | 533 | } |
534 | | | 534 | |
| @@ -575,36 +575,32 @@ sub parse_makefile_vars($$) { | | | @@ -575,36 +575,32 @@ sub parse_makefile_vars($$) { |
575 | | | 575 | |
576 | if (m#^\.\s*endif\b#) { | | 576 | if (m#^\.\s*endif\b#) { |
577 | pop(@if_false); | | 577 | pop(@if_false); |
578 | debug("$file: .endif (! @if_false)\n"); | | 578 | debug("$file: .endif (! @if_false)\n"); |
579 | next; | | 579 | next; |
580 | } | | 580 | } |
581 | | | 581 | |
582 | $if_false[$#if_false] && next; | | 582 | $if_false[$#if_false] && next; |
583 | | | 583 | |
584 | if (m#^\.\s*include\s+"([^"]+)"#) { | | 584 | if (m#^\.\s*include\s+"([^"]+)"#) { |
585 | my $incfile = parse_expand_vars($1, \%vars); | | 585 | my $incfile = parse_expand_vars($1, \%vars); |
586 | | | 586 | |
587 | parse_makefile_line_include($file, $incfile, | | 587 | parse_makefile_line_include($file, $incfile, |
588 | \%incdirs, \%incfiles, \@lines, \%vars); | | 588 | \@incdirs, \%incfiles, \@lines, \%vars); |
589 | next; | | 589 | next; |
590 | } | | 590 | } |
591 | | | 591 | |
592 | if (/^ *([-\w\.]+)\s*([:+?]?)=\s*(.*)/) { | | 592 | if (/^ *([-\w\.]+)\s*([:+?]?)=\s*(.*)/) { |
593 | my ($key); | | 593 | my ($key, $plus, $value) = ($1, $2, $3); |
594 | | | | |
595 | $key = $1; | | | |
596 | $plus = $2; | | | |
597 | $value = $3; | | | |
598 | | | 594 | |
599 | if ($plus eq ':') { | | 595 | if ($plus eq ':') { |
600 | $vars{$key} = parse_expand_vars($value, \%vars); | | 596 | $vars{$key} = parse_expand_vars($value, \%vars); |
601 | } elsif ($plus eq '+' && defined $vars{$key}) { | | 597 | } elsif ($plus eq '+' && defined $vars{$key}) { |
602 | $vars{$key} .= " $value"; | | 598 | $vars{$key} .= " $value"; |
603 | } elsif ($plus ne '?' || !defined $vars{$key}) { | | 599 | } elsif ($plus ne '?' || !defined $vars{$key}) { |
604 | $vars{$key} = $value; | | 600 | $vars{$key} = $value; |
605 | } | | 601 | } |
606 | debug("assignment: $key$plus=[$value] ($vars{$key})\n"); | | 602 | debug("assignment: $key$plus=[$value] ($vars{$key})\n"); |
607 | | | 603 | |
608 | # Give python a little hand (XXX - do we wanna consider actually | | 604 | # Give python a little hand (XXX - do we wanna consider actually |
609 | # implementing make .for loops, etc? | | 605 | # implementing make .for loops, etc? |
610 | # | | 606 | # |