Sun Mar 22 05:50:12 2009 UTC ()
Oops. :)


(rillig)
diff -r1.802 -r1.803 pkgsrc/pkgtools/pkglint/files/pkglint.pl

cvs diff -r1.802 -r1.803 pkgsrc/pkgtools/pkglint/files/Attic/pkglint.pl (switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/pkglint.pl 2009/03/22 05:41:44 1.802
+++ pkgsrc/pkgtools/pkglint/files/Attic/pkglint.pl 2009/03/22 05:50:12 1.803
@@ -1,1001 +1,1001 @@ @@ -1,1001 +1,1001 @@
1#! @PERL@ 1#! @PERL@
2# $NetBSD: pkglint.pl,v 1.802 2009/03/22 05:41:44 rillig Exp $ 2# $NetBSD: pkglint.pl,v 1.803 2009/03/22 05:50:12 rillig Exp $
3# 3#
4 4
5# pkglint - static analyzer and checker for pkgsrc packages 5# pkglint - static analyzer and checker for pkgsrc packages
6# 6#
7# Written by: 7# Written by:
8# Roland Illig <rillig@NetBSD.org> 8# Roland Illig <rillig@NetBSD.org>
9# 9#
10# Based on work by: 10# Based on work by:
11# Hubert Feyrer <hubertf@NetBSD.org> 11# Hubert Feyrer <hubertf@NetBSD.org>
12# Thorsten Frueauf <frueauf@NetBSD.org> 12# Thorsten Frueauf <frueauf@NetBSD.org>
13# Thomas Klausner <wiz@NetBSD.org> 13# Thomas Klausner <wiz@NetBSD.org>
14# and others. 14# and others.
15# 15#
16# Based on FreeBSD's portlint by: 16# Based on FreeBSD's portlint by:
17# Jun-ichiro itojun Hagino <itojun@itojun.org> 17# Jun-ichiro itojun Hagino <itojun@itojun.org>
18# Yoshishige Arai <ryo2@on.rim.or.jp> 18# Yoshishige Arai <ryo2@on.rim.or.jp>
19# 19#
20# FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp 20# FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp
21# Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. 21# Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>.
22# All rights reserved. 22# All rights reserved.
23# Freely redistributable. Absolutely no warranty. 23# Freely redistributable. Absolutely no warranty.
24 24
25# To get an overview of the code, run: 25# To get an overview of the code, run:
26# sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl 26# sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl
27 27
28#========================================================================== 28#==========================================================================
29# Note: The @EXPORT clauses in the packages must be in a BEGIN block, 29# Note: The @EXPORT clauses in the packages must be in a BEGIN block,
30# because otherwise the names starting with an uppercase letter are not 30# because otherwise the names starting with an uppercase letter are not
31# recognized as subroutines but as file handles. 31# recognized as subroutines but as file handles.
32#========================================================================== 32#==========================================================================
33 33
34use strict; 34use strict;
35use warnings; 35use warnings;
36 36
37package PkgLint::Util; 37package PkgLint::Util;
38#========================================================================== 38#==========================================================================
39# This package is a catch-all for subroutines that are not application-spe- 39# This package is a catch-all for subroutines that are not application-spe-
40# cific. Currently it contains the boolean constants C<false> and C<true>, 40# cific. Currently it contains the boolean constants C<false> and C<true>,
41# as well as a function to print text in a table format, and a function 41# as well as a function to print text in a table format, and a function
42# that converts an array into a hash. The latter is just for convenience 42# that converts an array into a hash. The latter is just for convenience
43# because I don't know of a Perl operator similar to qw() that can be used 43# because I don't know of a Perl operator similar to qw() that can be used
44# for creating a hash. 44# for creating a hash.
45#========================================================================== 45#==========================================================================
46BEGIN { 46BEGIN {
47 use Exporter; 47 use Exporter;
48 use vars qw(@ISA @EXPORT_OK); 48 use vars qw(@ISA @EXPORT_OK);
49 @ISA = qw(Exporter); 49 @ISA = qw(Exporter);
50 @EXPORT_OK = qw( 50 @EXPORT_OK = qw(
51 assert 51 assert
52 false true dont_know doesnt_matter 52 false true dont_know doesnt_matter
53 min max 53 min max
54 array_to_hash normalize_pathname print_table 54 array_to_hash normalize_pathname print_table
55 ); 55 );
56} 56}
57 57
58use enum qw(false true dont_know doesnt_matter); 58use enum qw(false true dont_know doesnt_matter);
59 59
60sub assert($$) { 60sub assert($$) {
61 my ($cond, $msg) = @_; 61 my ($cond, $msg) = @_;
62 my (@callers, $n); 62 my (@callers, $n);
63 63
64 if (!$cond) { 64 if (!$cond) {
65 print STDERR ("FATAL: Assertion failed: ${msg}.\n"); 65 print STDERR ("FATAL: Assertion failed: ${msg}.\n");
66 66
67 for ($n = 0; my @info = caller($n); $n++) { 67 for ($n = 0; my @info = caller($n); $n++) {
68 push(@callers, [$info[2], $info[3]]); 68 push(@callers, [$info[2], $info[3]]);
69 } 69 }
70 70
71 for (my $i = $#callers; $i >= 0; $i--) { 71 for (my $i = $#callers; $i >= 0; $i--) {
72 my $info = $callers[$i]; 72 my $info = $callers[$i];
73 printf STDERR (" line %4d called %s\n", $info->[0], $info->[1]); 73 printf STDERR (" line %4d called %s\n", $info->[0], $info->[1]);
74 } 74 }
75 exit(1); 75 exit(1);
76 } 76 }
77} 77}
78 78
79sub min($$) { 79sub min($$) {
80 my ($a, $b) = @_; 80 my ($a, $b) = @_;
81 81
82 return ($a < $b) ? $a : $b; 82 return ($a < $b) ? $a : $b;
83} 83}
84 84
85sub max($$) { 85sub max($$) {
86 my ($a, $b) = @_; 86 my ($a, $b) = @_;
87 87
88 return ($a > $b) ? $a : $b; 88 return ($a > $b) ? $a : $b;
89} 89}
90 90
91# Prints the C<$table> on the C<$out> stream. The C<$table> shall be an 91# Prints the C<$table> on the C<$out> stream. The C<$table> shall be an
92# array of rows, each row shall be an array of cells, and each cell shall 92# array of rows, each row shall be an array of cells, and each cell shall
93# be a string. 93# be a string.
94sub print_table($$) { 94sub print_table($$) {
95 my ($out, $table) = @_; 95 my ($out, $table) = @_;
96 my (@width) = (); 96 my (@width) = ();
97 foreach my $row (@{$table}) { 97 foreach my $row (@{$table}) {
98 foreach my $i (0..$#{$row}) { 98 foreach my $i (0..$#{$row}) {
99 if (!defined($width[$i]) || length($row->[$i]) > $width[$i]) { 99 if (!defined($width[$i]) || length($row->[$i]) > $width[$i]) {
100 $width[$i] = length($row->[$i]); 100 $width[$i] = length($row->[$i]);
101 } 101 }
102 } 102 }
103 } 103 }
104 foreach my $row (@{$table}) { 104 foreach my $row (@{$table}) {
105 my ($max) = ($#{$row}); 105 my ($max) = ($#{$row});
106 foreach my $i (0..$max) { 106 foreach my $i (0..$max) {
107 if ($i != 0) { 107 if ($i != 0) {
108 print $out (" "); 108 print $out (" ");
109 } 109 }
110 print $out ($row->[$i]); 110 print $out ($row->[$i]);
111 if ($i != $max) { 111 if ($i != $max) {
112 print $out (" " x ($width[$i] - length($row->[$i]))); 112 print $out (" " x ($width[$i] - length($row->[$i])));
113 } 113 }
114 } 114 }
115 print $out ("\n"); 115 print $out ("\n");
116 } 116 }
117} 117}
118 118
119sub array_to_hash(@) { 119sub array_to_hash(@) {
120 my ($result) = {}; 120 my ($result) = {};
121 121
122 foreach my $arg (@_) { 122 foreach my $arg (@_) {
123 $result->{$arg} = 1; 123 $result->{$arg} = 1;
124 } 124 }
125 return $result; 125 return $result;
126} 126}
127 127
128sub normalize_pathname($) { 128sub normalize_pathname($) {
129 my ($fname) = @_; 129 my ($fname) = @_;
130 130
131 # strip "." path components 131 # strip "." path components
132 $fname =~ s,^(?:\./)+,,; 132 $fname =~ s,^(?:\./)+,,;
133 $fname =~ s,/(?:\./)+,/,g; 133 $fname =~ s,/(?:\./)+,/,g;
134 $fname =~ s,/+,/,g; 134 $fname =~ s,/+,/,g;
135 135
136 # strip intermediate "../.." path components 136 # strip intermediate "../.." path components
137 while ($fname =~ s,/[^.][^/]*/[^.][^/]*/\.\./\.\./,/,) { 137 while ($fname =~ s,/[^.][^/]*/[^.][^/]*/\.\./\.\./,/,) {
138 } 138 }
139 139
140 return $fname; 140 return $fname;
141} 141}
142#== End of PkgLint::Util ================================================== 142#== End of PkgLint::Util ==================================================
143 143
144package PkgLint::Logging; 144package PkgLint::Logging;
145#========================================================================== 145#==========================================================================
146# This package provides subroutines for printing messages to the user in a 146# This package provides subroutines for printing messages to the user in a
147# common format. The subroutines all have the parameters C<$fname>, 147# common format. The subroutines all have the parameters C<$fname>,
148# C<$lineno> and C<$message>. In case there's no appropriate filename for 148# C<$lineno> and C<$message>. In case there's no appropriate filename for
149# the message, NO_FILE may be passed, likewise for C<$lineno> and 149# the message, NO_FILE may be passed, likewise for C<$lineno> and
150# NO_LINES. Before printing, the filename is normalized, that is, 150# NO_LINES. Before printing, the filename is normalized, that is,
151# "/foo/bar/../../" components are removed, as well as "." components. 151# "/foo/bar/../../" components are removed, as well as "." components.
152# At the end of the program, the subroutine print_summary_and_exit should 152# At the end of the program, the subroutine print_summary_and_exit should
153# be called. 153# be called.
154# 154#
155# Examples: 155# Examples:
156# log_error(NO_FILE, NO_LINES, "Invalid command line."); 156# log_error(NO_FILE, NO_LINES, "Invalid command line.");
157# log_warning($fname, NO_LINES, "Not found."); 157# log_warning($fname, NO_LINES, "Not found.");
158# log_debug($fname, $lineno, sprintf("invalid character (0x%02x).", $c)); 158# log_debug($fname, $lineno, sprintf("invalid character (0x%02x).", $c));
159#========================================================================== 159#==========================================================================
160 160
161use strict; 161use strict;
162use warnings; 162use warnings;
163BEGIN { 163BEGIN {
164 use Exporter; 164 use Exporter;
165 use vars qw(@ISA @EXPORT_OK); 165 use vars qw(@ISA @EXPORT_OK);
166 @ISA = qw(Exporter); 166 @ISA = qw(Exporter);
167 @EXPORT_OK = qw( 167 @EXPORT_OK = qw(
168 NO_FILE NO_LINE_NUMBER NO_LINES 168 NO_FILE NO_LINE_NUMBER NO_LINES
169 log_fatal log_error log_warning log_note log_debug 169 log_fatal log_error log_warning log_note log_debug
170 explain_error explain_warning explain_info 170 explain_error explain_warning explain_info
171 print_summary_and_exit 171 print_summary_and_exit
172 set_explain set_gcc_output_format 172 set_explain set_gcc_output_format
173 get_show_source_flag set_show_source_flag 173 get_show_source_flag set_show_source_flag
174 ); 174 );
175 import PkgLint::Util qw( 175 import PkgLint::Util qw(
176 false true 176 false true
177 normalize_pathname 177 normalize_pathname
178 ); 178 );
179} 179}
180 180
181use constant NO_FILE => undef; 181use constant NO_FILE => undef;
182use constant NO_LINE_NUMBER => undef; 182use constant NO_LINE_NUMBER => undef;
183use constant NO_LINES => undef; 183use constant NO_LINES => undef;
184 184
185use enum qw(:LL_ FATAL ERROR WARNING NOTE DEBUG); 185use enum qw(:LL_ FATAL ERROR WARNING NOTE DEBUG);
186 186
187use constant traditional_type => ["FATAL", "ERROR", "WARN", "NOTE", "DEBUG"]; 187use constant traditional_type => ["FATAL", "ERROR", "WARN", "NOTE", "DEBUG"];
188use constant gcc_type => ["fatal", "error", "warning", "note", "debug"]; 188use constant gcc_type => ["fatal", "error", "warning", "note", "debug"];
189 189
190my $errors = 0; 190my $errors = 0;
191my $warnings = 0; 191my $warnings = 0;
192my $gcc_output_format = false; 192my $gcc_output_format = false;
193my $explain_flag = false; 193my $explain_flag = false;
194my $show_source_flag = false; 194my $show_source_flag = false;
195 195
196sub strxvis($) { 196sub strxvis($) {
197 my ($s) = @_; 197 my ($s) = @_;
198 198
199 $s =~ s/([^\x09\x20-\x7e])/"\\x" . unpack("H*", $1)/eg; 199 $s =~ s/([^\x09\x20-\x7e])/"\\x" . unpack("H*", $1)/eg;
200 return $s; 200 return $s;
201} 201}
202 202
203sub log_message { # no prototype due to Perl weirdness 203sub log_message { # no prototype due to Perl weirdness
204 my ($level, $fname, $lineno, $message) = @_; 204 my ($level, $fname, $lineno, $message) = @_;
205 my ($text, $sep); 205 my ($text, $sep);
206 206
207 if (defined($fname)) { 207 if (defined($fname)) {
208 $fname = normalize_pathname($fname); 208 $fname = normalize_pathname($fname);
209 } 209 }
210 210
211 $text = ""; 211 $text = "";
212 $sep = ""; 212 $sep = "";
213 if (!$gcc_output_format) { 213 if (!$gcc_output_format) {
214 $text .= "${sep}" . traditional_type->[$level] . ":"; 214 $text .= "${sep}" . traditional_type->[$level] . ":";
215 $sep = " "; 215 $sep = " ";
216 } 216 }
217 if (defined($fname)) { 217 if (defined($fname)) {
218 $text .= defined($lineno) 218 $text .= defined($lineno)
219 ? "${sep}${fname}:${lineno}" 219 ? "${sep}${fname}:${lineno}"
220 : "${sep}${fname}"; 220 : "${sep}${fname}";
221 $sep = ": "; 221 $sep = ": ";
222 } 222 }
223 if ($gcc_output_format) { 223 if ($gcc_output_format) {
224 $text .= "${sep}" . gcc_type->[$level] . ":"; 224 $text .= "${sep}" . gcc_type->[$level] . ":";
225 $sep = " "; 225 $sep = " ";
226 } 226 }
227 if (defined($message)) { 227 if (defined($message)) {
228 $text .= $sep . strxvis($message); 228 $text .= $sep . strxvis($message);
229 $sep = ""; 229 $sep = "";
230 } 230 }
231 231
232 if ($level == LL_FATAL) { 232 if ($level == LL_FATAL) {
233 print STDERR ("${text}\n"); 233 print STDERR ("${text}\n");
234 } else { 234 } else {
235 print STDOUT ("${text}\n"); 235 print STDOUT ("${text}\n");
236 } 236 }
237} 237}
238 238
239sub log_fatal($$$) { log_message(LL_FATAL, @_); exit(1); } 239sub log_fatal($$$) { log_message(LL_FATAL, @_); exit(1); }
240sub log_error($$$) { log_message(LL_ERROR, @_); $errors++; } 240sub log_error($$$) { log_message(LL_ERROR, @_); $errors++; }
241sub log_warning($$$) { log_message(LL_WARNING, @_); $warnings++; } 241sub log_warning($$$) { log_message(LL_WARNING, @_); $warnings++; }
242sub log_note($$$) { log_message(LL_NOTE, @_); } 242sub log_note($$$) { log_message(LL_NOTE, @_); }
243sub log_debug($$$) { log_message(LL_DEBUG, @_); } 243sub log_debug($$$) { log_message(LL_DEBUG, @_); }
244 244
245sub explain { # no prototype due to Perl weirdness 245sub explain { # no prototype due to Perl weirdness
246 my ($loglevel, $fname, $lines, @texts) = @_; 246 my ($loglevel, $fname, $lines, @texts) = @_;
247 my $out = ($loglevel == LL_FATAL) ? *STDERR : *STDOUT; 247 my $out = ($loglevel == LL_FATAL) ? *STDERR : *STDOUT;
248 248
249 if ($explain_flag) { 249 if ($explain_flag) {
250 foreach my $text ("", @texts, "") { 250 foreach my $text ("", @texts, "") {
251 print $out ("\t${text}\n"); 251 print $out ("\t${text}\n");
252 } 252 }
253 } 253 }
254} 254}
255sub explain_error($$@) { explain(LL_ERROR, @_); } 255sub explain_error($$@) { explain(LL_ERROR, @_); }
256sub explain_warning($$@) { explain(LL_WARNING, @_); } 256sub explain_warning($$@) { explain(LL_WARNING, @_); }
257sub explain_note($$@) { explain(LL_NOTE, @_); } 257sub explain_note($$@) { explain(LL_NOTE, @_); }
258 258
259sub print_summary_and_exit($) { 259sub print_summary_and_exit($) {
260 my ($quiet) = @_; 260 my ($quiet) = @_;
261 261
262 if (!$quiet) { 262 if (!$quiet) {
263 if ($errors != 0 || $warnings != 0) { 263 if ($errors != 0 || $warnings != 0) {
264 print("$errors errors and $warnings warnings found.\n"); 264 print("$errors errors and $warnings warnings found.\n");
265 } else { 265 } else {
266 print "looks fine.\n"; 266 print "looks fine.\n";
267 } 267 }
268 } 268 }
269 exit($errors != 0); 269 exit($errors != 0);
270} 270}
271 271
272sub set_explain() { $explain_flag = true; } 272sub set_explain() { $explain_flag = true; }
273sub set_gcc_output_format() { $gcc_output_format = true; } 273sub set_gcc_output_format() { $gcc_output_format = true; }
274sub get_show_source_flag() { return $show_source_flag; } 274sub get_show_source_flag() { return $show_source_flag; }
275sub set_show_source_flag() { $show_source_flag = true; } 275sub set_show_source_flag() { $show_source_flag = true; }
276 276
277#== End of PkgLint::Logging =============================================== 277#== End of PkgLint::Logging ===============================================
278 278
279#========================================================================== 279#==========================================================================
280# A SimpleMatch is the result of applying a regular expression to a Perl 280# A SimpleMatch is the result of applying a regular expression to a Perl
281# scalar value. It can return the range and the text of the captured 281# scalar value. It can return the range and the text of the captured
282# groups. 282# groups.
283#========================================================================== 283#==========================================================================
284package PkgLint::SimpleMatch; 284package PkgLint::SimpleMatch;
285 285
286use enum qw(STRING STARTS ENDS N); 286use enum qw(STRING STARTS ENDS N);
287 287
288sub new($$) { 288sub new($$) {
289 my ($class, $string, $starts, $ends) = @_; 289 my ($class, $string, $starts, $ends) = @_;
290 my ($self) = ([$string, [@{$starts}], [@{$ends}], $#{$ends}]); 290 my ($self) = ([$string, [@{$starts}], [@{$ends}], $#{$ends}]);
291 bless($self, $class); 291 bless($self, $class);
292 return $self; 292 return $self;
293} 293}
294 294
295sub string($) { return shift(@_)->[STRING]; } 295sub string($) { return shift(@_)->[STRING]; }
296sub n($) { return shift(@_)->[N]; } 296sub n($) { return shift(@_)->[N]; }
297 297
298sub has($$) { 298sub has($$) {
299 my ($self, $n) = @_; 299 my ($self, $n) = @_;
300 300
301 return 0 <= $n && $n <= $self->n 301 return 0 <= $n && $n <= $self->n
302 && defined($self->[STARTS]->[$n]) 302 && defined($self->[STARTS]->[$n])
303 && defined($self->[ENDS]->[$n]); 303 && defined($self->[ENDS]->[$n]);
304} 304}
305 305
306sub text($$) { 306sub text($$) {
307 my ($self, $n) = @_; 307 my ($self, $n) = @_;
308 308
309 my $start = $self->[STARTS]->[$n]; 309 my $start = $self->[STARTS]->[$n];
310 my $end = $self->[ENDS]->[$n]; 310 my $end = $self->[ENDS]->[$n];
311 return substr($self->string, $start, $end - $start); 311 return substr($self->string, $start, $end - $start);
312} 312}
313 313
314sub range($$) { 314sub range($$) {
315 my ($self, $n) = @_; 315 my ($self, $n) = @_;
316 316
317 return ($self->[STARTS]->[$n], $self->[ENDS]->[$n]); 317 return ($self->[STARTS]->[$n], $self->[ENDS]->[$n]);
318} 318}
319 319
320#========================================================================== 320#==========================================================================
321# When files are read in by pkglint, they are interpreted in terms of 321# When files are read in by pkglint, they are interpreted in terms of
322# lines. For Makefiles, line continuations are handled properly, allowing 322# lines. For Makefiles, line continuations are handled properly, allowing
323# multiple physical lines to end in a single logical line. For other files 323# multiple physical lines to end in a single logical line. For other files
324# there is a 1:1 translation. 324# there is a 1:1 translation.
325# 325#
326# A difference between the physical and the logical lines is that the 326# A difference between the physical and the logical lines is that the
327# physical lines include the line end sequence, whereas the logical lines 327# physical lines include the line end sequence, whereas the logical lines
328# do not. 328# do not.
329# 329#
330# A logical line is a class having the read-only fields C<file>, 330# A logical line is a class having the read-only fields C<file>,
331# C<lines>, C<text>, C<physlines> and C<is_changed>, as well as some 331# C<lines>, C<text>, C<physlines> and C<is_changed>, as well as some
332# methods for printing diagnostics easily. 332# methods for printing diagnostics easily.
333# 333#
334# Some other methods allow modification of the physical lines, but leave 334# Some other methods allow modification of the physical lines, but leave
335# the logical line (the C<text>) untouched. These methods are used in the 335# the logical line (the C<text>) untouched. These methods are used in the
336# --autofix mode. 336# --autofix mode.
337# 337#
338# A line can have some "extra" fields that allow the results of parsing to 338# A line can have some "extra" fields that allow the results of parsing to
339# be saved under a name. 339# be saved under a name.
340#========================================================================== 340#==========================================================================
341package PkgLint::Line; 341package PkgLint::Line;
342 342
343BEGIN { 343BEGIN {
344 import PkgLint::Util qw( 344 import PkgLint::Util qw(
345 false true 345 false true
346 assert 346 assert
347 ); 347 );
348} 348}
349 349
350use enum qw(FNAME LINES TEXT PHYSLINES CHANGED BEFORE AFTER EXTRA); 350use enum qw(FNAME LINES TEXT PHYSLINES CHANGED BEFORE AFTER EXTRA);
351 351
352sub new($$$$) { 352sub new($$$$) {
353 my ($class, $fname, $lines, $text, $physlines) = @_; 353 my ($class, $fname, $lines, $text, $physlines) = @_;
354 my ($self) = ([$fname, $lines, $text, $physlines, false, [], [], {}]); 354 my ($self) = ([$fname, $lines, $text, $physlines, false, [], [], {}]);
355 bless($self, $class); 355 bless($self, $class);
356 return $self; 356 return $self;
357} 357}
358 358
359sub fname($) { return shift(@_)->[FNAME]; } 359sub fname($) { return shift(@_)->[FNAME]; }
360sub lines($) { return shift(@_)->[LINES]; } 360sub lines($) { return shift(@_)->[LINES]; }
361sub text($) { return shift(@_)->[TEXT]; } 361sub text($) { return shift(@_)->[TEXT]; }
362# Note: physlines is _not_ a usual getter method. 362# Note: physlines is _not_ a usual getter method.
363sub is_changed($) { return shift(@_)->[CHANGED]; } 363sub is_changed($) { return shift(@_)->[CHANGED]; }
364 364
365# querying, getting and setting the extra values. 365# querying, getting and setting the extra values.
366sub has($$) { 366sub has($$) {
367 my ($self, $name) = @_; 367 my ($self, $name) = @_;
368 return exists($self->[EXTRA]->{$name}); 368 return exists($self->[EXTRA]->{$name});
369} 369}
370sub get($$) { 370sub get($$) {
371 my ($self, $name) = @_; 371 my ($self, $name) = @_;
372 assert(exists($self->[EXTRA]->{$name}), "Field ${name} does not exist."); 372 assert(exists($self->[EXTRA]->{$name}), "Field ${name} does not exist.");
373 return $self->[EXTRA]->{$name}; 373 return $self->[EXTRA]->{$name};
374} 374}
375sub set($$$) { 375sub set($$$) {
376 my ($self, $name, $value) = @_; 376 my ($self, $name, $value) = @_;
377 assert(!exists($self->[EXTRA]->{$name}), "Field ${name} already exists."); 377 assert(!exists($self->[EXTRA]->{$name}), "Field ${name} already exists.");
378 378
379 # Make sure that the line does not become a cyclic data structure. 379 # Make sure that the line does not become a cyclic data structure.
380 my $type = ref($value); 380 my $type = ref($value);
381 if ($type eq "") { 381 if ($type eq "") {
382 # ok 382 # ok
383 } elsif ($type eq "ARRAY") { 383 } elsif ($type eq "ARRAY") {
384 foreach my $element (@{$value}) { 384 foreach my $element (@{$value}) {
385 my $element_type = ref($element); 385 my $element_type = ref($element);
386 assert($element_type eq "" || $element_type eq "PkgLint::SimpleMatch", 386 assert($element_type eq "" || $element_type eq "PkgLint::SimpleMatch",
387 "Invalid array data type: name=${name}, type=${element_type}."); 387 "Invalid array data type: name=${name}, type=${element_type}.");
388 } 388 }
389 } else { 389 } else {
390 assert(false, "Invalid data: name=${name}, value=${value}."); 390 assert(false, "Invalid data: name=${name}, value=${value}.");
391 } 391 }
392 392
393 $self->[EXTRA]->{$name} = $value; 393 $self->[EXTRA]->{$name} = $value;
394} 394}
395 395
396sub physlines($) { 396sub physlines($) {
397 my ($self) = @_; 397 my ($self) = @_;
398 return [@{$self->[BEFORE]}, @{$self->[PHYSLINES]}, @{$self->[AFTER]}]; 398 return [@{$self->[BEFORE]}, @{$self->[PHYSLINES]}, @{$self->[AFTER]}];
399} 399}
400 400
401# Only for PkgLint::String support 401# Only for PkgLint::String support
402sub substring($$$$) { 402sub substring($$$$) {
403 my ($self, $line, $start, $end) = @_; 403 my ($self, $line, $start, $end) = @_;
404 my ($text, $physlines); 404 my ($text, $physlines);
405 405
406 return substr($self->[PHYSLINES]->[$line]->[1], $start, $end); 406 return substr($self->[PHYSLINES]->[$line]->[1], $start, $end);
407} 407}
408 408
409sub show_source($$) { 409sub show_source($$) {
410 my ($self, $out) = @_; 410 my ($self, $out) = @_;
411 411
412 if (PkgLint::Logging::get_show_source_flag()) { 412 if (PkgLint::Logging::get_show_source_flag()) {
413 foreach my $line (@{$self->physlines}) { 413 foreach my $line (@{$self->physlines}) {
414 print $out ("> " . $line->[1]); 414 print $out ("> " . $line->[1]);
415 } 415 }
416 } 416 }
417} 417}
418 418
419sub log_fatal($$) { 419sub log_fatal($$) {
420 my ($self, $text) = @_; 420 my ($self, $text) = @_;
421 421
422 $self->show_source(*STDERR); 422 $self->show_source(*STDERR);
423 PkgLint::Logging::log_fatal($self->fname, $self->[LINES], $text); 423 PkgLint::Logging::log_fatal($self->fname, $self->[LINES], $text);
424} 424}
425sub log_error($$) { 425sub log_error($$) {
426 my ($self, $text) = @_; 426 my ($self, $text) = @_;
427 427
428 $self->show_source(*STDOUT); 428 $self->show_source(*STDOUT);
429 PkgLint::Logging::log_error($self->fname, $self->[LINES], $text); 429 PkgLint::Logging::log_error($self->fname, $self->[LINES], $text);
430} 430}
431sub log_warning($$) { 431sub log_warning($$) {
432 my ($self, $text) = @_; 432 my ($self, $text) = @_;
433 433
434 $self->show_source(*STDOUT); 434 $self->show_source(*STDOUT);
435 PkgLint::Logging::log_warning($self->fname, $self->[LINES], $text); 435 PkgLint::Logging::log_warning($self->fname, $self->[LINES], $text);
436} 436}
437sub log_note($$) { 437sub log_note($$) {
438 my ($self, $text) = @_; 438 my ($self, $text) = @_;
439 439
440 $self->show_source(*STDOUT); 440 $self->show_source(*STDOUT);
441 PkgLint::Logging::log_note($self->fname, $self->[LINES], $text); 441 PkgLint::Logging::log_note($self->fname, $self->[LINES], $text);
442} 442}
443sub log_debug($$) { 443sub log_debug($$) {
444 my ($self, $text) = @_; 444 my ($self, $text) = @_;
445 445
446 $self->show_source(*STDOUT); 446 $self->show_source(*STDOUT);
447 PkgLint::Logging::log_debug($self->fname, $self->[LINES], $text); 447 PkgLint::Logging::log_debug($self->fname, $self->[LINES], $text);
448} 448}
449sub explain_error($@) { 449sub explain_error($@) {
450 my ($self, @texts) = @_; 450 my ($self, @texts) = @_;
451 451
452 PkgLint::Logging::explain_error($self->fname, $self->[LINES], @texts); 452 PkgLint::Logging::explain_error($self->fname, $self->[LINES], @texts);
453} 453}
454sub explain_warning($@) { 454sub explain_warning($@) {
455 my ($self, @texts) = @_; 455 my ($self, @texts) = @_;
456 456
457 PkgLint::Logging::explain_warning($self->fname, $self->[LINES], @texts); 457 PkgLint::Logging::explain_warning($self->fname, $self->[LINES], @texts);
458} 458}
459sub explain_note($@) { 459sub explain_note($@) {
460 my ($self, @texts) = @_; 460 my ($self, @texts) = @_;
461 461
462 PkgLint::Logging::explain_note($self->fname, $self->[LINES], @texts); 462 PkgLint::Logging::explain_note($self->fname, $self->[LINES], @texts);
463} 463}
464sub explain_info($@) { 464sub explain_info($@) {
465 my ($self, @texts) = @_; 465 my ($self, @texts) = @_;
466 466
467 PkgLint::Logging::explain_info($self->fname, $self->[LINES], @texts); 467 PkgLint::Logging::explain_info($self->fname, $self->[LINES], @texts);
468} 468}
469 469
470sub to_string($) { 470sub to_string($) {
471 my ($self) = @_; 471 my ($self) = @_;
472 472
473 return $self->fname . ":" . $self->[LINES] . ": " . $self->[TEXT]; 473 return $self->fname . ":" . $self->[LINES] . ": " . $self->[TEXT];
474} 474}
475 475
476sub prepend_before($$) { 476sub prepend_before($$) {
477 my ($self, $text) = @_; 477 my ($self, $text) = @_;
478 478
479 unshift(@{$self->[BEFORE]}, [0, "$text\n"]); 479 unshift(@{$self->[BEFORE]}, [0, "$text\n"]);
480 $self->[CHANGED] = true; 480 $self->[CHANGED] = true;
481} 481}
482sub append_before($$) { 482sub append_before($$) {
483 my ($self, $text) = @_; 483 my ($self, $text) = @_;
484 484
485 push(@{$self->[BEFORE]}, [0, "$text\n"]); 485 push(@{$self->[BEFORE]}, [0, "$text\n"]);
486 $self->[CHANGED] = true; 486 $self->[CHANGED] = true;
487} 487}
488sub prepend_after($$) { 488sub prepend_after($$) {
489 my ($self, $text) = @_; 489 my ($self, $text) = @_;
490 490
491 unshift(@{$self->[AFTER]}, [0, "$text\n"]); 491 unshift(@{$self->[AFTER]}, [0, "$text\n"]);
492 $self->[CHANGED] = true; 492 $self->[CHANGED] = true;
493} 493}
494sub append_after($$) { 494sub append_after($$) {
495 my ($self, $text) = @_; 495 my ($self, $text) = @_;
496 496
497 push(@{$self->[AFTER]}, [0, "$text\n"]); 497 push(@{$self->[AFTER]}, [0, "$text\n"]);
498 $self->[CHANGED] = true; 498 $self->[CHANGED] = true;
499} 499}
500sub delete($) { 500sub delete($) {
501 my ($self) = @_; 501 my ($self) = @_;
502 502
503 $self->[PHYSLINES] = []; 503 $self->[PHYSLINES] = [];
504 $self->[CHANGED] = true; 504 $self->[CHANGED] = true;
505} 505}
506sub replace($$$) { 506sub replace($$$) {
507 my ($self, $from, $to) = @_; 507 my ($self, $from, $to) = @_;
508 my $phys = $self->[PHYSLINES]; 508 my $phys = $self->[PHYSLINES];
509 509
510 foreach my $i (0..$#{$phys}) { 510 foreach my $i (0..$#{$phys}) {
511 if ($phys->[$i]->[0] != 0 && $phys->[$i]->[1] =~ s/\Q$from\E/$to/g) { 511 if ($phys->[$i]->[0] != 0 && $phys->[$i]->[1] =~ s/\Q$from\E/$to/g) {
512 $self->[CHANGED] = true; 512 $self->[CHANGED] = true;
513 } 513 }
514 } 514 }
515} 515}
516sub replace_regex($$$) { 516sub replace_regex($$$) {
517 my ($self, $from_re, $to) = @_; 517 my ($self, $from_re, $to) = @_;
518 my $phys = $self->[PHYSLINES]; 518 my $phys = $self->[PHYSLINES];
519 519
520 foreach my $i (0..$#{$phys}) { 520 foreach my $i (0..$#{$phys}) {
521 if ($phys->[$i]->[0] != 0 && $phys->[$i]->[1] =~ s/$from_re/$to/) { 521 if ($phys->[$i]->[0] != 0 && $phys->[$i]->[1] =~ s/$from_re/$to/) {
522 $self->[CHANGED] = true; 522 $self->[CHANGED] = true;
523 } 523 }
524 } 524 }
525} 525}
526sub set_text($$) { 526sub set_text($$) {
527 my ($self, $text) = @_; 527 my ($self, $text) = @_;
528 $self->[PHYSLINES] = [[0, "$text\n"]]; 528 $self->[PHYSLINES] = [[0, "$text\n"]];
529 $self->[CHANGED] = true; 529 $self->[CHANGED] = true;
530} 530}
531 531
532#== End of PkgLint::Line ================================================== 532#== End of PkgLint::Line ==================================================
533 533
534package PkgLint::FileUtil; 534package PkgLint::FileUtil;
535#========================================================================== 535#==========================================================================
536# This package provides subroutines for loading and saving line-oriented 536# This package provides subroutines for loading and saving line-oriented
537# files. The load_file() subroutine loads a file completely into memory, 537# files. The load_file() subroutine loads a file completely into memory,
538# optionally handling continuation line folding. The load_lines() subrou- 538# optionally handling continuation line folding. The load_lines() subrou-
539# tine is an abbreviation for the common case of loading files without 539# tine is an abbreviation for the common case of loading files without
540# continuation lines. The save_autofix_changes() subroutine examines an 540# continuation lines. The save_autofix_changes() subroutine examines an
541# array of lines if some of them have changed. It then saves the modified 541# array of lines if some of them have changed. It then saves the modified
542# files. 542# files.
543#========================================================================== 543#==========================================================================
544use strict; 544use strict;
545use warnings; 545use warnings;
546 546
547BEGIN { 547BEGIN {
548 use Exporter; 548 use Exporter;
549 use vars qw(@ISA @EXPORT_OK); 549 use vars qw(@ISA @EXPORT_OK);
550 @ISA = qw(Exporter); 550 @ISA = qw(Exporter);
551 @EXPORT_OK = qw( 551 @EXPORT_OK = qw(
552 load_file load_lines 552 load_file load_lines
553 save_autofix_changes 553 save_autofix_changes
554 ); 554 );
555 555
556 import PkgLint::Util qw( 556 import PkgLint::Util qw(
557 false true 557 false true
558 ); 558 );
559 import PkgLint::Logging qw( 559 import PkgLint::Logging qw(
560 NO_LINE_NUMBER 560 NO_LINE_NUMBER
561 log_error log_note 561 log_error log_note
562 ); 562 );
563} 563}
564 564
565sub load_physical_lines($) { 565sub load_physical_lines($) {
566 my ($fname) = @_; 566 my ($fname) = @_;
567 my ($physlines, $line, $lineno); 567 my ($physlines, $line, $lineno);
568 568
569 $physlines = []; 569 $physlines = [];
570 open(F, "< $fname") or return undef; 570 open(F, "< $fname") or return undef;
571 $lineno = 0; 571 $lineno = 0;
572 while (defined($line = <F>)) { 572 while (defined($line = <F>)) {
573 $lineno++; 573 $lineno++;
574 push(@{$physlines}, [$lineno, $line]); 574 push(@{$physlines}, [$lineno, $line]);
575 } 575 }
576 close(F) or return undef; 576 close(F) or return undef;
577 return $physlines; 577 return $physlines;
578} 578}
579 579
580sub get_logical_line($$$) { 580sub get_logical_line($$$) {
581 my ($fname, $lines, $ref_lineno) = @_; 581 my ($fname, $lines, $ref_lineno) = @_;
582 my ($value, $lineno, $first, $firstlineno, $lastlineno, $physlines); 582 my ($value, $lineno, $first, $firstlineno, $lastlineno, $physlines);
583 583
584 $value = ""; 584 $value = "";
585 $first = true; 585 $first = true;
586 $lineno = ${$ref_lineno}; 586 $lineno = ${$ref_lineno};
587 $firstlineno = $lines->[$lineno]->[0]; 587 $firstlineno = $lines->[$lineno]->[0];
588 $physlines = []; 588 $physlines = [];
589 589
590 for (; $lineno <= $#{$lines}; $lineno++) { 590 for (; $lineno <= $#{$lines}; $lineno++) {
591 if ($lines->[$lineno]->[1] =~ m"^([ \t]*)(.*?)([ \t]*)(\\?)\n?$") { 591 if ($lines->[$lineno]->[1] =~ m"^([ \t]*)(.*?)([ \t]*)(\\?)\n?$") {
592 my ($indent, $text, $outdent, $cont) = ($1, $2, $3, $4); 592 my ($indent, $text, $outdent, $cont) = ($1, $2, $3, $4);
593 593
594 if ($first) { 594 if ($first) {
595 $value .= $indent; 595 $value .= $indent;
596 $first = false; 596 $first = false;
597 } 597 }
598 598
599 $value .= $text; 599 $value .= $text;
600 push(@{$physlines}, $lines->[$lineno]); 600 push(@{$physlines}, $lines->[$lineno]);
601 601
602 if ($cont eq "\\") { 602 if ($cont eq "\\") {
603 $value .= " "; 603 $value .= " ";
604 } else { 604 } else {
605 $value .= $outdent; 605 $value .= $outdent;
606 last; 606 last;
607 } 607 }
608 } 608 }
609 } 609 }
610 610
611 if ($lineno > $#{$lines}) { 611 if ($lineno > $#{$lines}) {
612 # The last line in the file is a continuation line 612 # The last line in the file is a continuation line
613 $lineno--; 613 $lineno--;
614 } 614 }
615 $lastlineno = $lines->[$lineno]->[0]; 615 $lastlineno = $lines->[$lineno]->[0];
616 ${$ref_lineno} = $lineno + 1; 616 ${$ref_lineno} = $lineno + 1;
617 617
618 return PkgLint::Line->new($fname, 618 return PkgLint::Line->new($fname,
619 $firstlineno == $lastlineno 619 $firstlineno == $lastlineno
620 ? $firstlineno 620 ? $firstlineno
621 : "$firstlineno--$lastlineno", 621 : "$firstlineno--$lastlineno",
622 $value, 622 $value,
623 $physlines); 623 $physlines);
624} 624}
625 625
626sub load_lines($$) { 626sub load_lines($$) {
627 my ($fname, $fold_backslash_lines) = @_; 627 my ($fname, $fold_backslash_lines) = @_;
628 my ($physlines, $seen_newline, $loglines); 628 my ($physlines, $seen_newline, $loglines);
629 629
630 $physlines = load_physical_lines($fname); 630 $physlines = load_physical_lines($fname);
631 if (!$physlines) { 631 if (!$physlines) {
632 return false; 632 return false;
633 } 633 }
634 634
635 $seen_newline = true; 635 $seen_newline = true;
636 $loglines = []; 636 $loglines = [];
637 if ($fold_backslash_lines) { 637 if ($fold_backslash_lines) {
638 for (my $lineno = 0; $lineno <= $#{$physlines}; ) { 638 for (my $lineno = 0; $lineno <= $#{$physlines}; ) {
639 push(@{$loglines}, get_logical_line($fname, $physlines, \$lineno)); 639 push(@{$loglines}, get_logical_line($fname, $physlines, \$lineno));
640 } 640 }
641 } else { 641 } else {
642 foreach my $physline (@{$physlines}) { 642 foreach my $physline (@{$physlines}) {
643 my $text = $physline->[1]; 643 my $text = $physline->[1];
644 644
645 $text =~ s/\n$//; 645 $text =~ s/\n$//;
646 push(@{$loglines}, PkgLint::Line->new($fname, $physline->[0], $text, [$physline])); 646 push(@{$loglines}, PkgLint::Line->new($fname, $physline->[0], $text, [$physline]));
647 } 647 }
648 } 648 }
649 649
650 if (0 <= $#{$physlines} && $physlines->[-1]->[1] !~ m"\n$") { 650 if (0 <= $#{$physlines} && $physlines->[-1]->[1] !~ m"\n$") {
651 log_error($fname, $physlines->[-1]->[0], "File must end with a newline."); 651 log_error($fname, $physlines->[-1]->[0], "File must end with a newline.");
652 } 652 }
653 653
654 return $loglines; 654 return $loglines;
655} 655}
656 656
657sub load_file($) { 657sub load_file($) {
658 my ($fname) = @_; 658 my ($fname) = @_;
659 659
660 return load_lines($fname, false); 660 return load_lines($fname, false);
661} 661}
662 662
663sub save_autofix_changes($) { 663sub save_autofix_changes($) {
664 my ($lines) = @_; 664 my ($lines) = @_;
665 665
666 my (%changed, %physlines); 666 my (%changed, %physlines);
667 667
668 foreach my $line (@{$lines}) { 668 foreach my $line (@{$lines}) {
669 if ($line->is_changed) { 669 if ($line->is_changed) {
670 $changed{$line->fname}++; 670 $changed{$line->fname}++;
671 } 671 }
672 push(@{$physlines{$line->fname}}, @{$line->physlines}); 672 push(@{$physlines{$line->fname}}, @{$line->physlines});
673 } 673 }
674 674
675 foreach my $fname (sort(keys(%changed))) { 675 foreach my $fname (sort(keys(%changed))) {
676 my $new = "${fname}.pkglint.tmp"; 676 my $new = "${fname}.pkglint.tmp";
677 677
678 if (!open(F, ">", $new)) { 678 if (!open(F, ">", $new)) {
679 log_error($new, NO_LINE_NUMBER, "$!"); 679 log_error($new, NO_LINE_NUMBER, "$!");
680 next; 680 next;
681 } 681 }
682 foreach my $physline (@{$physlines{$fname}}) { 682 foreach my $physline (@{$physlines{$fname}}) {
683 print F ($physline->[1]); 683 print F ($physline->[1]);
684 } 684 }
685 if (!close(F)) { 685 if (!close(F)) {
686 log_error($new, NO_LINE_NUMBER, "$!"); 686 log_error($new, NO_LINE_NUMBER, "$!");
687 next; 687 next;
688 } 688 }
689 689
690 if (!rename($new, $fname)) { 690 if (!rename($new, $fname)) {
691 log_error($fname, NO_LINE_NUMBER, "$!"); 691 log_error($fname, NO_LINE_NUMBER, "$!");
692 next; 692 next;
693 } 693 }
694 log_note($fname, NO_LINE_NUMBER, "Has been autofixed. Please re-run pkglint."); 694 log_note($fname, NO_LINE_NUMBER, "Has been autofixed. Please re-run pkglint.");
695 } 695 }
696} 696}
697 697
698#== End of PkgLint::FileUtil ============================================== 698#== End of PkgLint::FileUtil ==============================================
699 699
700package PkgLint::Type; 700package PkgLint::Type;
701#========================================================================== 701#==========================================================================
702# A Type in pkglint is a combination of a data type and a permission 702# A Type in pkglint is a combination of a data type and a permission
703# specification. Further details can be found in the chapter ``The pkglint 703# specification. Further details can be found in the chapter ``The pkglint
704# type system'' of the pkglint book. 704# type system'' of the pkglint book.
705#========================================================================== 705#==========================================================================
706 706
707BEGIN { 707BEGIN {
708 import PkgLint::Util qw( 708 import PkgLint::Util qw(
709 false true 709 false true
710 ); 710 );
711 import PkgLint::Logging qw( 711 import PkgLint::Logging qw(
712 log_warning NO_LINES 712 log_warning NO_LINES
713 ); 713 );
714 use Exporter; 714 use Exporter;
715 use vars qw(@ISA @EXPORT_OK); 715 use vars qw(@ISA @EXPORT_OK);
716 @ISA = qw(Exporter); 716 @ISA = qw(Exporter);
717 @EXPORT_OK = qw( 717 @EXPORT_OK = qw(
718 LK_NONE LK_INTERNAL LK_EXTERNAL 718 LK_NONE LK_INTERNAL LK_EXTERNAL
719 GUESSED NOT_GUESSED 719 GUESSED NOT_GUESSED
720 ); 720 );
721} 721}
722 722
723use enum qw(KIND_OF_LIST BASIC_TYPE ACLS IS_GUESSED); 723use enum qw(KIND_OF_LIST BASIC_TYPE ACLS IS_GUESSED);
724use enum qw(:LK_ NONE INTERNAL EXTERNAL); 724use enum qw(:LK_ NONE INTERNAL EXTERNAL);
725use enum qw(:ACLE_ SUBJECT_RE PERMS); 725use enum qw(:ACLE_ SUBJECT_RE PERMS);
726use enum qw(NOT_GUESSED GUESSED); 726use enum qw(NOT_GUESSED GUESSED);
727 727
728sub new($$$) { 728sub new($$$) {
729 my ($class, $kind_of_list, $basic_type, $acls, $guessed) = @_; 729 my ($class, $kind_of_list, $basic_type, $acls, $guessed) = @_;
730 my ($self) = ([$kind_of_list, $basic_type, $acls, $guessed]); 730 my ($self) = ([$kind_of_list, $basic_type, $acls, $guessed]);
731 bless($self, $class); 731 bless($self, $class);
732 return $self; 732 return $self;
733} 733}
734 734
735sub kind_of_list($) { return shift(@_)->[KIND_OF_LIST]; } 735sub kind_of_list($) { return shift(@_)->[KIND_OF_LIST]; }
736sub basic_type($) { return shift(@_)->[BASIC_TYPE]; } 736sub basic_type($) { return shift(@_)->[BASIC_TYPE]; }
737# no getter method for acls 737# no getter method for acls
738sub is_guessed($) { return shift(@_)->[IS_GUESSED]; } 738sub is_guessed($) { return shift(@_)->[IS_GUESSED]; }
739 739
740sub perms($$) { 740sub perms($$) {
741 my ($self, $fname) = @_; 741 my ($self, $fname) = @_;
742 my ($perms); 742 my ($perms);
743 743
744 foreach my $acl_entry (@{$self->[ACLS]}) { 744 foreach my $acl_entry (@{$self->[ACLS]}) {
745 if ($fname =~ $acl_entry->[ACLE_SUBJECT_RE]) { 745 if ($fname =~ $acl_entry->[ACLE_SUBJECT_RE]) {
746 return $acl_entry->[ACLE_PERMS]; 746 return $acl_entry->[ACLE_PERMS];
747 } 747 }
748 } 748 }
749 return undef; 749 return undef;
750} 750}
751 751
752# Returns the union of all possible permissions. This can be used to 752# Returns the union of all possible permissions. This can be used to
753# check whether a variable may be defined or used at all, or if it is 753# check whether a variable may be defined or used at all, or if it is
754# read-only. 754# read-only.
755sub perms_union($) { 755sub perms_union($) {
756 my ($self) = @_; 756 my ($self) = @_;
757 my ($perms); 757 my ($perms);
758 758
759 $perms = ""; 759 $perms = "";
760 foreach my $acl_entry(@{$self->[ACLS]}) { 760 foreach my $acl_entry(@{$self->[ACLS]}) {
761 $perms .= $acl_entry->[ACLE_PERMS]; 761 $perms .= $acl_entry->[ACLE_PERMS];
762 } 762 }
763 return $perms; 763 return $perms;
764} 764}
765 765
766# Returns whether the type is considered an external list. All external 766# Returns whether the type is considered an external list. All external
767# lists are, of course, as well as some other data types that are not 767# lists are, of course, as well as some other data types that are not
768# defined as lists to make the implementation of checkline_mk_vartype 768# defined as lists to make the implementation of checkline_mk_vartype
769# easier. 769# easier.
770sub is_practically_a_list($) { 770sub is_practically_a_list($) {
771 my ($self) = @_; 771 my ($self) = @_;
772 772
773 return ($self->kind_of_list == LK_EXTERNAL) ? true 773 return ($self->kind_of_list == LK_EXTERNAL) ? true
774 : ($self->kind_of_list == LK_INTERNAL) ? false 774 : ($self->kind_of_list == LK_INTERNAL) ? false
775 : ($self->basic_type eq "BuildlinkPackages") ? true 775 : ($self->basic_type eq "BuildlinkPackages") ? true
776 : ($self->basic_type eq "SedCommands") ? true 776 : ($self->basic_type eq "SedCommands") ? true
777 : ($self->basic_type eq "ShellCommand") ? true 777 : ($self->basic_type eq "ShellCommand") ? true
778 : false; 778 : false;
779} 779}
780 780
781# Returns whether variables of this type may be extended using the "+=" 781# Returns whether variables of this type may be extended using the "+="
782# operator. 782# operator.
783sub may_use_plus_eq($) { 783sub may_use_plus_eq($) {
784 my ($self) = @_; 784 my ($self) = @_;
785 785
786 return ($self->kind_of_list != LK_NONE) ? true 786 return ($self->kind_of_list != LK_NONE) ? true
787 : ($self->basic_type eq "AwkCommand") ? true 787 : ($self->basic_type eq "AwkCommand") ? true
788 : ($self->basic_type eq "BuildlinkPackages") ? true 788 : ($self->basic_type eq "BuildlinkPackages") ? true
789 : ($self->basic_type eq "SedCommands") ? true 789 : ($self->basic_type eq "SedCommands") ? true
790 : false; 790 : false;
791} 791}
792 792
793sub to_string($) { 793sub to_string($) {
794 my ($self) = @_; 794 my ($self) = @_;
795 795
796 return (["", "InternalList of ", "List of "]->[$self->kind_of_list]) . $self->basic_type; 796 return (["", "InternalList of ", "List of "]->[$self->kind_of_list]) . $self->basic_type;
797} 797}
798 798
799#== End of PkgLint::Type ================================================== 799#== End of PkgLint::Type ==================================================
800 800
801package PkgLint::VarUseContext; 801package PkgLint::VarUseContext;
802#========================================================================== 802#==========================================================================
803# This class represents the various contexts in which make(1) variables can 803# This class represents the various contexts in which make(1) variables can
804# appear in pkgsrc. Further details can be found in the chapter ``The 804# appear in pkgsrc. Further details can be found in the chapter ``The
805# pkglint type system'' of the pkglint book. 805# pkglint type system'' of the pkglint book.
806#========================================================================== 806#==========================================================================
807 807
808BEGIN { 808BEGIN {
809 import PkgLint::Util qw( 809 import PkgLint::Util qw(
810 false true 810 false true
811 ); 811 );
812 import PkgLint::Logging qw( 812 import PkgLint::Logging qw(
813 log_warning NO_LINES 813 log_warning NO_LINES
814 ); 814 );
815 use Exporter; 815 use Exporter;
816 use vars qw(@ISA @EXPORT_OK); 816 use vars qw(@ISA @EXPORT_OK);
817 @ISA = qw(Exporter); 817 @ISA = qw(Exporter);
818 @EXPORT_OK = qw( 818 @EXPORT_OK = qw(
819 VUC_TIME_UNKNOWN VUC_TIME_LOAD VUC_TIME_RUN 819 VUC_TIME_UNKNOWN VUC_TIME_LOAD VUC_TIME_RUN
820 VUC_TYPE_UNKNOWN 820 VUC_TYPE_UNKNOWN
821 VUC_SHELLWORD_UNKNOWN VUC_SHELLWORD_PLAIN VUC_SHELLWORD_DQUOT 821 VUC_SHELLWORD_UNKNOWN VUC_SHELLWORD_PLAIN VUC_SHELLWORD_DQUOT
822 VUC_SHELLWORD_SQUOT VUC_SHELLWORD_BACKT VUC_SHELLWORD_FOR 822 VUC_SHELLWORD_SQUOT VUC_SHELLWORD_BACKT VUC_SHELLWORD_FOR
823 VUC_EXTENT_UNKNOWN VUC_EXTENT_FULL VUC_EXTENT_WORD 823 VUC_EXTENT_UNKNOWN VUC_EXTENT_FULL VUC_EXTENT_WORD
824 VUC_EXTENT_WORD_PART 824 VUC_EXTENT_WORD_PART
825 ); 825 );
826} 826}
827 827
828use enum qw(TIME TYPE SHELLWORD EXTENT); 828use enum qw(TIME TYPE SHELLWORD EXTENT);
829use enum qw(:VUC_TIME_ UNKNOWN LOAD RUN); 829use enum qw(:VUC_TIME_ UNKNOWN LOAD RUN);
830use constant VUC_TYPE_UNKNOWN => undef; 830use constant VUC_TYPE_UNKNOWN => undef;
831use enum qw(:VUC_SHELLWORD_ UNKNOWN PLAIN DQUOT SQUOT BACKT FOR); 831use enum qw(:VUC_SHELLWORD_ UNKNOWN PLAIN DQUOT SQUOT BACKT FOR);
832use enum qw(:VUC_EXTENT_ UNKNOWN FULL WORD WORD_PART); 832use enum qw(:VUC_EXTENT_ UNKNOWN FULL WORD WORD_PART);
833 833
834my $pool = {}; 834my $pool = {};
835 835
836sub new($$$$$) { 836sub new($$$$$) {
837 my ($class, $time, $type, $shellword, $extent) = @_; 837 my ($class, $time, $type, $shellword, $extent) = @_;
838 my ($self) = ([$time, $type, $shellword, $extent]); 838 my ($self) = ([$time, $type, $shellword, $extent]);
839 bless($self, $class); 839 bless($self, $class);
840 return $self; 840 return $self;
841} 841}
842sub new_from_pool($$$$$) { 842sub new_from_pool($$$$$) {
843 my ($class, $time, $type, $shellword, $extent) = @_; 843 my ($class, $time, $type, $shellword, $extent) = @_;
844 my $key = "${time}-${type}-${shellword}-${extent}"; 844 my $key = "${time}-${type}-${shellword}-${extent}";
845 845
846 if (!exists($pool->{$key})) { 846 if (!exists($pool->{$key})) {
847 $pool->{$key} = $class->new($time, $type, $shellword, $extent); 847 $pool->{$key} = $class->new($time, $type, $shellword, $extent);
848 } 848 }
849 return $pool->{$key}; 849 return $pool->{$key};
850} 850}
851 851
852sub time($) { return shift(@_)->[TIME]; } 852sub time($) { return shift(@_)->[TIME]; }
853sub type($) { return shift(@_)->[TYPE]; } 853sub type($) { return shift(@_)->[TYPE]; }
854sub shellword($) { return shift(@_)->[SHELLWORD]; } 854sub shellword($) { return shift(@_)->[SHELLWORD]; }
855sub extent($) { return shift(@_)->[EXTENT]; } 855sub extent($) { return shift(@_)->[EXTENT]; }
856 856
857sub to_string($) { 857sub to_string($) {
858 my ($self) = @_; 858 my ($self) = @_;
859 859
860 return sprintf("(%s %s %s %s)", 860 return sprintf("(%s %s %s %s)",
861 ["unknown-time", "load-time", "run-time"]->[$self->time], 861 ["unknown-time", "load-time", "run-time"]->[$self->time],
862 (defined($self->type) ? $self->type->to_string() : "no-type"), 862 (defined($self->type) ? $self->type->to_string() : "no-type"),
863 ["none", "plain", "squot", "dquot", "backt", "for"]->[$self->shellword], 863 ["none", "plain", "squot", "dquot", "backt", "for"]->[$self->shellword],
864 ["unknown", "full", "word", "word-part"]->[$self->extent]); 864 ["unknown", "full", "word", "word-part"]->[$self->extent]);
865} 865}
866 866
867#== End of PkgLint::VarUseContext ========================================= 867#== End of PkgLint::VarUseContext =========================================
868 868
869package PkgLint::SubstContext; 869package PkgLint::SubstContext;
870#========================================================================== 870#==========================================================================
871# This class records the state of a block of variable assignments that make 871# This class records the state of a block of variable assignments that make
872# up a SUBST class. As these variable assignments are not easy to get right 872# up a SUBST class. As these variable assignments are not easy to get right
873# unless you do it every day, and the possibility of typos is high, pkglint 873# unless you do it every day, and the possibility of typos is high, pkglint
874# provides additional checks for them. 874# provides additional checks for them.
875#========================================================================== 875#==========================================================================
876 876
877BEGIN { 877BEGIN {
878 import PkgLint::Util qw( 878 import PkgLint::Util qw(
879 false true 879 false true
880 ); 880 );
881 import PkgLint::Logging qw( 881 import PkgLint::Logging qw(
882 log_warning 882 log_warning
883 ); 883 );
884} 884}
885 885
886use enum qw(:SUBST_ ID CLASS STAGE MESSAGE FILES SED VARS FILTER_CMD); 886use enum qw(:SUBST_ ID CLASS STAGE MESSAGE FILES SED VARS FILTER_CMD);
887 887
888sub new($) { 888sub new($) {
889 my ($class) = @_; 889 my ($class) = @_;
890 my ($self) = ([undef, undef, undef, undef, [], [], [], undef]); 890 my ($self) = ([undef, undef, undef, undef, [], [], [], undef]);
891 bless($self, $class); 891 bless($self, $class);
892 return $self; 892 return $self;
893} 893}
894 894
895sub subst_class($) { return shift(@_)->[SUBST_CLASS]; } 895sub subst_class($) { return shift(@_)->[SUBST_CLASS]; }
896sub subst_stage($) { return shift(@_)->[SUBST_STAGE]; } 896sub subst_stage($) { return shift(@_)->[SUBST_STAGE]; }
897sub subst_message($) { return shift(@_)->[SUBST_MESSAGE]; } 897sub subst_message($) { return shift(@_)->[SUBST_MESSAGE]; }
898sub subst_files($) { return shift(@_)->[SUBST_FILES]; } 898sub subst_files($) { return shift(@_)->[SUBST_FILES]; }
899sub subst_sed($) { return shift(@_)->[SUBST_SED]; } 899sub subst_sed($) { return shift(@_)->[SUBST_SED]; }
900sub subst_vars($) { return shift(@_)->[SUBST_VARS]; } 900sub subst_vars($) { return shift(@_)->[SUBST_VARS]; }
901sub subst_filter_cmd($) { return shift(@_)->[SUBST_FILTER_CMD]; } 901sub subst_filter_cmd($) { return shift(@_)->[SUBST_FILTER_CMD]; }
902sub subst_id($) { return shift(@_)->[SUBST_ID]; } 902sub subst_id($) { return shift(@_)->[SUBST_ID]; }
903 903
904sub init($) { 904sub init($) {
905 my ($self) = @_; 905 my ($self) = @_;
906 906
907 $self->[SUBST_ID] = undef; 907 $self->[SUBST_ID] = undef;
908 $self->[SUBST_CLASS] = undef; 908 $self->[SUBST_CLASS] = undef;
909 $self->[SUBST_STAGE] = undef; 909 $self->[SUBST_STAGE] = undef;
910 $self->[SUBST_MESSAGE] = undef; 910 $self->[SUBST_MESSAGE] = undef;
911 $self->[SUBST_FILES] = []; 911 $self->[SUBST_FILES] = [];
912 $self->[SUBST_SED] = []; 912 $self->[SUBST_SED] = [];
913 $self->[SUBST_VARS] = []; 913 $self->[SUBST_VARS] = [];
914 $self->[SUBST_FILTER_CMD] = undef; 914 $self->[SUBST_FILTER_CMD] = undef;
915} 915}
916 916
917sub check_end($$) { 917sub check_end($$) {
918 my ($self, $line) = @_; 918 my ($self, $line) = @_;
919 919
920 return unless defined($self->subst_id); 920 return unless defined($self->subst_id);
921 921
922 if (!defined($self->subst_class)) { 922 if (!defined($self->subst_class)) {
923 $main::opt_warn_extra and $line->log_warning("Incomplete SUBST block: SUBST_CLASSES missing."); 923 $main::opt_warn_extra and $line->log_warning("Incomplete SUBST block: SUBST_CLASSES missing.");
924 } 924 }
925 if (!defined($self->subst_stage)) { 925 if (!defined($self->subst_stage)) {
926 $main::opt_warn_extra and $line->log_warning("Incomplete SUBST block: SUBST_STAGE missing."); 926 $main::opt_warn_extra and $line->log_warning("Incomplete SUBST block: SUBST_STAGE missing.");
927 } 927 }
928 if (@{$self->subst_files} == 0) { 928 if (@{$self->subst_files} == 0) {
929 $main::opt_warn_extra and $line->log_warning("Incomplete SUBST block: SUBST_FILES missing."); 929 $main::opt_warn_extra and $line->log_warning("Incomplete SUBST block: SUBST_FILES missing.");
930 } 930 }
931 if (@{$self->subst_sed} == 0 && @{$self->subst_vars} == 0 && !defined($self->subst_filter_cmd)) { 931 if (@{$self->subst_sed} == 0 && @{$self->subst_vars} == 0 && !defined($self->subst_filter_cmd)) {
932 $main::opt_warn_extra and $line->log_warning("Incomplete SUBST block: SUBST_SED or SUBST_VARS missing."); 932 $main::opt_warn_extra and $line->log_warning("Incomplete SUBST block: SUBST_SED or SUBST_VARS missing.");
933 } 933 }
934 $self->init(); 934 $self->init();
935} 935}
936 936
937sub is_complete($) { 937sub is_complete($) {
938 my ($self) = @_; 938 my ($self) = @_;
939 939
940 return false unless defined($self->subst_id); 940 return false unless defined($self->subst_id);
941 return false unless defined($self->subst_class); 941 return false unless defined($self->subst_class);
942 return false unless defined($self->subst_files); 942 return false unless defined($self->subst_files);
943 return false if @{$self->subst_sed} == 0 && @{$self->subst_vars} == 0; 943 return false if @{$self->subst_sed} == 0 && @{$self->subst_vars} == 0;
944 return true; 944 return true;
945} 945}
946 946
947sub check_varassign($$$$$) { 947sub check_varassign($$$$$) {
948 my ($self, $line, $varname, $op, $value) = @_; 948 my ($self, $line, $varname, $op, $value) = @_;
949 my ($varbase, $varparam, $id); 949 my ($varbase, $varparam, $id);
950 950
951 if ($varname eq "SUBST_CLASSES") { 951 if ($varname eq "SUBST_CLASSES") {
952 952
953 if ($value =~ m"^(\S+)\s") { 953 if ($value =~ m"^(\S+)\s") {
954 $main::opt_warn_extra and $line->log_warning("Please add only one class at a time to SUBST_CLASSES."); 954 $main::opt_warn_extra and $line->log_warning("Please add only one class at a time to SUBST_CLASSES.");
955 $self->[SUBST_CLASS] = $1; 955 $self->[SUBST_CLASS] = $1;
956 $self->[SUBST_ID] = $1; 956 $self->[SUBST_ID] = $1;
957 957
958 } else { 958 } else {
959 if (defined($self->subst_class)) { 959 if (defined($self->subst_class)) {
960 $main::opt_warn_extra and $line->log_warning("SUBST_CLASSES should only appear once in a SUBST block."); 960 $main::opt_warn_extra and $line->log_warning("SUBST_CLASSES should only appear once in a SUBST block.");
961 } 961 }
962 $self->[SUBST_CLASS] = $value; 962 $self->[SUBST_CLASS] = $value;
963 $self->[SUBST_ID] = $value; 963 $self->[SUBST_ID] = $value;
964 } 964 }
965 return; 965 return;
966 } 966 }
967 967
968 $id = $self->subst_id; 968 $id = $self->subst_id;
969 969
970 if ($varname =~ m"^(SUBST_(?:STAGE|MESSAGE|FILES|SED|VARS|FILTER_CMD))\.([\-\w_]+)$") { 970 if ($varname =~ m"^(SUBST_(?:STAGE|MESSAGE|FILES|SED|VARS|FILTER_CMD))\.([\-\w_]+)$") {
971 ($varbase, $varparam) = ($1, $2); 971 ($varbase, $varparam) = ($1, $2);
972 972
973 if (!defined($id)) { 973 if (!defined($id)) {
974 $main::opt_warn_extra and $line->log_note("SUBST_CLASSES should precede the definition of ${varbase}.${varparam}."); 974 $main::opt_warn_extra and $line->log_note("SUBST_CLASSES should precede the definition of ${varbase}.${varparam}.");
975 975
976 $id = $self->[SUBST_ID] = $varparam; 976 $id = $self->[SUBST_ID] = $varparam;
977 } 977 }
978 } else { 978 } else {
979 if (defined($id)) { 979 if (defined($id)) {
980 $main::opt_warn_extra and $line->log_warning("Foreign variable in SUBST block."); 980 $main::opt_warn_extra and $line->log_warning("Foreign variable in SUBST block.");
981 } 981 }
982 return; 982 return;
983 } 983 }
984 984
985 if ($varparam ne $id) { 985 if ($varparam ne $id) {
986 986
987 # XXX: This code sometimes produces weird warnings. See 987 # XXX: This code sometimes produces weird warnings. See
988 # meta-pkgs/xorg/Makefile.common 1.41 for an example. 988 # meta-pkgs/xorg/Makefile.common 1.41 for an example.
989 if ($self->is_complete()) { 989 if ($self->is_complete()) {
990 $self->check_end($line); 990 $self->check_end($line);
991 991
992 # The following assignment prevents an additional warning, 992 # The following assignment prevents an additional warning,
993 # but from a technically viewpoint, it is incorrect. 993 # but from a technically viewpoint, it is incorrect.
994 $self->[SUBST_CLASS] = $varparam; 994 $self->[SUBST_CLASS] = $varparam;
995 $self->[SUBST_ID] = $varparam; 995 $self->[SUBST_ID] = $varparam;
996 $id = $varparam; 996 $id = $varparam;
997 } else { 997 } else {
998 $main::opt_warn_extra and $line->log_warning("Variable parameter \"${varparam}\" does not match SUBST class \"${id}\"."); 998 $main::opt_warn_extra and $line->log_warning("Variable parameter \"${varparam}\" does not match SUBST class \"${id}\".");
999 } 999 }
1000 } 1000 }
1001 1001
@@ -5644,1999 +5644,1999 @@ sub checkline_mk_varassign($$$$$) { @@ -5644,1999 +5644,1999 @@ sub checkline_mk_varassign($$$$$) {
5644 my ($pkgvarname) = ($1); 5644 my ($pkgvarname) = ($1);
5645 if ($varname =~ m"^PKG_.*_REASON$") { 5645 if ($varname =~ m"^PKG_.*_REASON$") {
5646 # ok 5646 # ok
5647 } elsif ($varname =~ m"^(?:DIST_SUBDIR|WRKSRC)$") { 5647 } elsif ($varname =~ m"^(?:DIST_SUBDIR|WRKSRC)$") {
5648 $line->log_warning("${pkgvarname} should not be used in ${varname}, as it sometimes includes the PKGREVISION. Please use ${pkgvarname}_NOREV instead."); 5648 $line->log_warning("${pkgvarname} should not be used in ${varname}, as it sometimes includes the PKGREVISION. Please use ${pkgvarname}_NOREV instead.");
5649 } else { 5649 } else {
5650 $opt_debug_misc and $line->log_debug("Use of PKGNAME in ${varname}."); 5650 $opt_debug_misc and $line->log_debug("Use of PKGNAME in ${varname}.");
5651 } 5651 }
5652 } 5652 }
5653 5653
5654 if (exists(get_deprecated_map()->{$varname})) { 5654 if (exists(get_deprecated_map()->{$varname})) {
5655 $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varname}); 5655 $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varname});
5656 } elsif (exists(get_deprecated_map()->{$varcanon})) { 5656 } elsif (exists(get_deprecated_map()->{$varcanon})) {
5657 $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varcanon}); 5657 $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varcanon});
5658 } 5658 }
5659 5659
5660 if ($varname =~ m"^SITES_") { 5660 if ($varname =~ m"^SITES_") {
5661 $line->log_warning("SITES_* is deprecated. Please use SITES.* instead."); 5661 $line->log_warning("SITES_* is deprecated. Please use SITES.* instead.");
5662 } 5662 }
5663 5663
5664 if ($value =~ m"^[^=]\@comment") { 5664 if ($value =~ m"^[^=]\@comment") {
5665 $line->log_warning("Please don't use \@comment in ${varname}."); 5665 $line->log_warning("Please don't use \@comment in ${varname}.");
5666 $line->explain_warning( 5666 $line->explain_warning(
5667"Here you are defining a variable containing \@comment. As this value", 5667"Here you are defining a variable containing \@comment. As this value",
5668"typically includes a space as the last character you probably also used", 5668"typically includes a space as the last character you probably also used",
5669"quotes around the variable. This can lead to confusion when adding this", 5669"quotes around the variable. This can lead to confusion when adding this",
5670"variable to PLIST_SUBST, as all other variables are quoted using the :Q", 5670"variable to PLIST_SUBST, as all other variables are quoted using the :Q",
5671"operator when they are appended. As it is hard to check whether a", 5671"operator when they are appended. As it is hard to check whether a",
5672"variable that is appended to PLIST_SUBST is already quoted or not, you", 5672"variable that is appended to PLIST_SUBST is already quoted or not, you",
5673"should not have pre-quoted variables at all. To solve this, you should", 5673"should not have pre-quoted variables at all. To solve this, you should",
5674"directly use PLIST_SUBST+= ${varname}=${value} or use any other", 5674"directly use PLIST_SUBST+= ${varname}=${value} or use any other",
5675"variable for collecting the list of PLIST substitutions and later", 5675"variable for collecting the list of PLIST substitutions and later",
5676"append that variable with PLIST_SUBST+= \${MY_PLIST_SUBST}."); 5676"append that variable with PLIST_SUBST+= \${MY_PLIST_SUBST}.");
5677 } 5677 }
5678 5678
5679 # Mark the variable as PLIST condition. This is later used in 5679 # Mark the variable as PLIST condition. This is later used in
5680 # checkfile_PLIST. 5680 # checkfile_PLIST.
5681 if (defined($pkgctx_plist_subst_cond) && $value =~ m"(.+)=.*\@comment.*") { 5681 if (defined($pkgctx_plist_subst_cond) && $value =~ m"(.+)=.*\@comment.*") {
5682 $pkgctx_plist_subst_cond->{$1}++; 5682 $pkgctx_plist_subst_cond->{$1}++;
5683 } 5683 }
5684 5684
5685 use constant op_to_use_time => { 5685 use constant op_to_use_time => {
5686 ":=" => VUC_TIME_LOAD, 5686 ":=" => VUC_TIME_LOAD,
5687 "!=" => VUC_TIME_LOAD, 5687 "!=" => VUC_TIME_LOAD,
5688 "=" => VUC_TIME_RUN, 5688 "=" => VUC_TIME_RUN,
5689 "+=" => VUC_TIME_RUN, 5689 "+=" => VUC_TIME_RUN,
5690 "?=" => VUC_TIME_RUN 5690 "?=" => VUC_TIME_RUN
5691 }; 5691 };
5692  5692
5693 $used_vars = extract_used_variables($line, $value); 5693 $used_vars = extract_used_variables($line, $value);
5694 my $vuc = PkgLint::VarUseContext->new( 5694 my $vuc = PkgLint::VarUseContext->new(
5695 op_to_use_time->{$op}, 5695 op_to_use_time->{$op},
5696 get_variable_type($line, $varname), 5696 get_variable_type($line, $varname),
5697 VUC_SHELLWORD_UNKNOWN, # XXX: maybe PLAIN? 5697 VUC_SHELLWORD_UNKNOWN, # XXX: maybe PLAIN?
5698 VUC_EXTENT_UNKNOWN 5698 VUC_EXTENT_UNKNOWN
5699 ); 5699 );
5700 foreach my $used_var (@{$used_vars}) { 5700 foreach my $used_var (@{$used_vars}) {
5701 checkline_mk_varuse($line, $used_var, "", $vuc); 5701 checkline_mk_varuse($line, $used_var, "", $vuc);
5702 } 5702 }
5703} 5703}
5704 5704
5705# The bmake parser is way too sloppy about syntax, so we need to check 5705# The bmake parser is way too sloppy about syntax, so we need to check
5706# that here. 5706# that here.
5707# 5707#
5708sub checkline_mk_cond($$) { 5708sub checkline_mk_cond($$) {
5709 my ($line, $cond) = @_; 5709 my ($line, $cond) = @_;
5710 my ($op, $varname, $match, $value); 5710 my ($op, $varname, $match, $value);
5711 5711
5712 $opt_debug_trace and $line->log_debug("checkline_mk_cond($cond)"); 5712 $opt_debug_trace and $line->log_debug("checkline_mk_cond($cond)");
5713 my $tree = parse_mk_cond($line, $cond); 5713 my $tree = parse_mk_cond($line, $cond);
5714 if (tree_match($tree, ["not", ["empty", ["match", \$varname, \$match]]])) { 5714 if (tree_match($tree, ["not", ["empty", ["match", \$varname, \$match]]])) {
5715 #$line->log_note("tree_match: varname=$varname, match=$match"); 5715 #$line->log_note("tree_match: varname=$varname, match=$match");
5716 5716
5717 my $type = get_variable_type($line, $varname); 5717 my $type = get_variable_type($line, $varname);
5718 my $btype = defined($type) ? $type->basic_type : undef; 5718 my $btype = defined($type) ? $type->basic_type : undef;
5719 if (defined($btype) && ref($type->basic_type) eq "HASH") { 5719 if (defined($btype) && ref($type->basic_type) eq "HASH") {
5720 if ($match !~ m"[\$\[*]" && !exists($btype->{$match})) { 5720 if ($match !~ m"[\$\[*]" && !exists($btype->{$match})) {
5721 $line->log_warning("Invalid :M value \"$match\". Only { " . join(" ", sort keys %$btype) . " } are allowed."); 5721 $line->log_warning("Invalid :M value \"$match\". Only { " . join(" ", sort keys %$btype) . " } are allowed.");
5722 } 5722 }
5723 } 5723 }
5724 5724
5725 # Currently disabled because the valid options can also be defined in PKG_OPTIONS_GROUP.*. 5725 # Currently disabled because the valid options can also be defined in PKG_OPTIONS_GROUP.*.
5726 # Additionally, all these variables may have multiple assigments (+=). 5726 # Additionally, all these variables may have multiple assigments (+=).
5727 if (false && $varname eq "PKG_OPTIONS" && defined($pkgctx_vardef) && exists($pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"})) { 5727 if (false && $varname eq "PKG_OPTIONS" && defined($pkgctx_vardef) && exists($pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"})) {
5728 my $options = $pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"}->get("value"); 5728 my $options = $pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"}->get("value");
5729 5729
5730 if ($match !~ m"[\$\[*]" && index(" $options ", " $match ") == -1) { 5730 if ($match !~ m"[\$\[*]" && index(" $options ", " $match ") == -1) {
5731 $line->log_warning("Invalid option \"$match\". Only { $options } are allowed."); 5731 $line->log_warning("Invalid option \"$match\". Only { $options } are allowed.");
5732 } 5732 }
5733 } 5733 }
5734 5734
5735 # TODO: PKG_BUILD_OPTIONS. That requires loading the 5735 # TODO: PKG_BUILD_OPTIONS. That requires loading the
5736 # complete package definitition for the package "pkgbase" 5736 # complete package definitition for the package "pkgbase"
5737 # or some other database. If we could confine all option 5737 # or some other database. If we could confine all option
5738 # definitions to options.mk, this would become easier. 5738 # definitions to options.mk, this would become easier.
5739 5739
5740 } elsif (tree_match($tree, [\$op, ["var", \$varname], ["string", \$value]])) { 5740 } elsif (tree_match($tree, [\$op, ["var", \$varname], ["string", \$value]])) {
5741 checkline_mk_vartype($line, $varname, "use", $value, undef); 5741 checkline_mk_vartype($line, $varname, "use", $value, undef);
5742 5742
5743 } 5743 }
5744 # XXX: When adding new cases, be careful that the variables may have 5744 # XXX: When adding new cases, be careful that the variables may have
5745 # been partially initialized by previous calls to tree_match. 5745 # been partially initialized by previous calls to tree_match.
5746 # XXX: Maybe it is better to clear these references at the beginning 5746 # XXX: Maybe it is better to clear these references at the beginning
5747 # of tree_match. 5747 # of tree_match.
5748} 5748}
5749 5749
5750# 5750#
5751# Procedures to check an array of lines. 5751# Procedures to check an array of lines.
5752# 5752#
5753 5753
5754sub checklines_trailing_empty_lines($) { 5754sub checklines_trailing_empty_lines($) {
5755 my ($lines) = @_; 5755 my ($lines) = @_;
5756 my ($last, $max); 5756 my ($last, $max);
5757 5757
5758 $max = $#{$lines} + 1; 5758 $max = $#{$lines} + 1;
5759 for ($last = $max; $last > 1 && $lines->[$last - 1]->text eq ""; ) { 5759 for ($last = $max; $last > 1 && $lines->[$last - 1]->text eq ""; ) {
5760 $last--; 5760 $last--;
5761 } 5761 }
5762 if ($last != $max) { 5762 if ($last != $max) {
5763 $lines->[$last]->log_note("Trailing empty lines."); 5763 $lines->[$last]->log_note("Trailing empty lines.");
5764 } 5764 }
5765} 5765}
5766 5766
5767sub checklines_package_Makefile_varorder($) { 5767sub checklines_package_Makefile_varorder($) {
5768 my ($lines) = @_; 5768 my ($lines) = @_;
5769 5769
5770 return unless $opt_warn_varorder; 5770 return unless $opt_warn_varorder;
5771 5771
5772 use enum qw(once optional many); 5772 use enum qw(once optional many);
5773 my (@sections) = ( 5773 my (@sections) = (
5774 [ "Initial comments", once, 5774 [ "Initial comments", once,
5775 [ 5775 [
5776 ] 5776 ]
5777 ], 5777 ],
5778 [ "Unsorted stuff, part 1", once, 5778 [ "Unsorted stuff, part 1", once,
5779 [ 5779 [
5780 [ "DISTNAME", once ], 5780 [ "DISTNAME", once ],
5781 [ "PKGNAME", optional ], 5781 [ "PKGNAME", optional ],
5782 [ "PKGREVISION", optional ], 5782 [ "PKGREVISION", optional ],
5783 [ "SVR4_PKGNAME", optional ], 5783 [ "SVR4_PKGNAME", optional ],
5784 [ "CATEGORIES", once ], 5784 [ "CATEGORIES", once ],
5785 [ "MASTER_SITES", optional ], 5785 [ "MASTER_SITES", optional ],
5786 [ "DIST_SUBDIR", optional ], 5786 [ "DIST_SUBDIR", optional ],
5787 [ "EXTRACT_SUFX", optional ], 5787 [ "EXTRACT_SUFX", optional ],
5788 [ "DISTFILES", many ], 5788 [ "DISTFILES", many ],
5789 [ "SITES.*", many ], 5789 [ "SITES.*", many ],
5790 ] 5790 ]
5791 ], 5791 ],
5792 [ "Distribution patches", optional, 5792 [ "Distribution patches", optional,
5793 [ 5793 [
5794 [ "PATCH_SITES", optional ], # or once? 5794 [ "PATCH_SITES", optional ], # or once?
5795 [ "PATCH_SITE_SUBDIR", optional ], 5795 [ "PATCH_SITE_SUBDIR", optional ],
5796 [ "PATCHFILES", optional ], # or once? 5796 [ "PATCHFILES", optional ], # or once?
5797 [ "PATCH_DIST_ARGS", optional ], 5797 [ "PATCH_DIST_ARGS", optional ],
5798 [ "PATCH_DIST_STRIP", optional ], 5798 [ "PATCH_DIST_STRIP", optional ],
5799 [ "PATCH_DIST_CAT", optional ], 5799 [ "PATCH_DIST_CAT", optional ],
5800 ] 5800 ]
5801 ], 5801 ],
5802 [ "Unsorted stuff, part 2", once, 5802 [ "Unsorted stuff, part 2", once,
5803 [ 5803 [
5804 [ "MAINTAINER", optional ], 5804 [ "MAINTAINER", optional ],
5805 [ "OWNER", optional ], 5805 [ "OWNER", optional ],
5806 [ "HOMEPAGE", optional ], 5806 [ "HOMEPAGE", optional ],
5807 [ "COMMENT", once ], 5807 [ "COMMENT", once ],
5808 ] 5808 ]
5809 ], 5809 ],
5810 [ "Legal issues", optional, 5810 [ "Legal issues", optional,
5811 [ 5811 [
5812 [ "LICENSE", once ], 5812 [ "LICENSE", once ],
5813 [ "RESTRICTED", optional ], 5813 [ "RESTRICTED", optional ],
5814 [ "NO_BIN_ON_CDROM", optional ], 5814 [ "NO_BIN_ON_CDROM", optional ],
5815 [ "NO_BIN_ON_FTP", optional ], 5815 [ "NO_BIN_ON_FTP", optional ],
5816 [ "NO_SRC_ON_CDROM", optional ], 5816 [ "NO_SRC_ON_CDROM", optional ],
5817 [ "NO_SRC_ON_FTP", optional ], 5817 [ "NO_SRC_ON_FTP", optional ],
5818 ] 5818 ]
5819 ], 5819 ],
5820 [ "Technical restrictions", optional, 5820 [ "Technical restrictions", optional,
5821 [ 5821 [
5822 [ "NOT_FOR_PLATFORM", many ], 5822 [ "NOT_FOR_PLATFORM", many ],
5823 [ "ONLY_FOR_PLATFORM", many ], 5823 [ "ONLY_FOR_PLATFORM", many ],
5824 [ "NOT_FOR_COMPILER", many ], 5824 [ "NOT_FOR_COMPILER", many ],
5825 [ "ONLY_FOR_COMPILER", many ], 5825 [ "ONLY_FOR_COMPILER", many ],
5826 [ "NOT_FOR_UNPRIVILEGED", optional ], 5826 [ "NOT_FOR_UNPRIVILEGED", optional ],
5827 [ "ONLY_FOR_UNPRIVILEGED", optional ], 5827 [ "ONLY_FOR_UNPRIVILEGED", optional ],
5828 ] 5828 ]
5829 ], 5829 ],
5830 [ "Dependencies", optional, 5830 [ "Dependencies", optional,
5831 [ 5831 [
5832 [ "BUILD_DEPENDS", many ], 5832 [ "BUILD_DEPENDS", many ],
5833 [ "DEPENDS", many ], 5833 [ "DEPENDS", many ],
5834 ] 5834 ]
5835 ] 5835 ]
5836 ); 5836 );
5837 5837
5838 if (!defined($seen_Makefile_common) || $seen_Makefile_common) { 5838 if (!defined($seen_Makefile_common) || $seen_Makefile_common) {
5839 return; 5839 return;
5840 } 5840 }
5841 5841
5842 my ($lineno, $sectindex, $varindex) = (0, -1, 0); 5842 my ($lineno, $sectindex, $varindex) = (0, -1, 0);
5843 my ($next_section, $vars, $below, $below_what) = (true, undef, {}, undef); 5843 my ($next_section, $vars, $below, $below_what) = (true, undef, {}, undef);
5844 5844
5845 # If the current section is optional but contains non-optional 5845 # If the current section is optional but contains non-optional
5846 # fields, the complete section may be skipped as long as there 5846 # fields, the complete section may be skipped as long as there
5847 # has not been a non-optional variable. 5847 # has not been a non-optional variable.
5848 my $may_skip_section = false; 5848 my $may_skip_section = false;
5849 5849
5850 # In each iteration, one of the following becomes true: 5850 # In each iteration, one of the following becomes true:
5851 # - new.lineno > old.lineno 5851 # - new.lineno > old.lineno
5852 # - new.sectindex > old.sectindex 5852 # - new.sectindex > old.sectindex
5853 # - new.sectindex == old.sectindex && new.varindex > old.varindex 5853 # - new.sectindex == old.sectindex && new.varindex > old.varindex
5854 # - new.next_section == true && old.next_section == false 5854 # - new.next_section == true && old.next_section == false
5855 while ($lineno <= $#{$lines}) { 5855 while ($lineno <= $#{$lines}) {
5856 my $line = $lines->[$lineno]; 5856 my $line = $lines->[$lineno];
5857 my $text = $line->text; 5857 my $text = $line->text;
5858 5858
5859 $opt_debug_misc and $line->log_debug("[varorder] section ${sectindex} variable ${varindex}."); 5859 $opt_debug_misc and $line->log_debug("[varorder] section ${sectindex} variable ${varindex}.");
5860 5860
5861 if ($next_section) { 5861 if ($next_section) {
5862 $next_section = false; 5862 $next_section = false;
5863 $sectindex++; 5863 $sectindex++;
5864 last if ($sectindex > $#sections); 5864 last if ($sectindex > $#sections);
5865 $vars = $sections[$sectindex]->[2]; 5865 $vars = $sections[$sectindex]->[2];
5866 $may_skip_section = ($sections[$sectindex]->[1] == optional); 5866 $may_skip_section = ($sections[$sectindex]->[1] == optional);
5867 $varindex = 0; 5867 $varindex = 0;
5868 } 5868 }
5869 5869
5870 if ($text =~ m"^#") { 5870 if ($text =~ m"^#") {
5871 $lineno++; 5871 $lineno++;
5872 5872
5873 } elsif ($line->has("varcanon")) { 5873 } elsif ($line->has("varcanon")) {
5874 my $varcanon = $line->get("varcanon"); 5874 my $varcanon = $line->get("varcanon");
5875 5875
5876 if (exists($below->{$varcanon})) { 5876 if (exists($below->{$varcanon})) {
5877 if (defined($below->{$varcanon})) { 5877 if (defined($below->{$varcanon})) {
5878 $line->log_warning("${varcanon} appears too late. Please put it below $below->{$varcanon}."); 5878 $line->log_warning("${varcanon} appears too late. Please put it below $below->{$varcanon}.");
5879 } else { 5879 } else {
5880 $line->log_warning("${varcanon} appears too late. It should be the very first definition."); 5880 $line->log_warning("${varcanon} appears too late. It should be the very first definition.");
5881 } 5881 }
5882 $lineno++; 5882 $lineno++;
5883 next; 5883 next;
5884 } 5884 }
5885 5885
5886 while ($varindex <= $#{$vars} && $varcanon ne $vars->[$varindex]->[0] && ($vars->[$varindex]->[1] != once || $may_skip_section)) { 5886 while ($varindex <= $#{$vars} && $varcanon ne $vars->[$varindex]->[0] && ($vars->[$varindex]->[1] != once || $may_skip_section)) {
5887 if ($vars->[$varindex]->[1] == once) { 5887 if ($vars->[$varindex]->[1] == once) {
5888 $may_skip_section = false; 5888 $may_skip_section = false;
5889 } 5889 }
5890 $below->{$vars->[$varindex]->[0]} = $below_what; 5890 $below->{$vars->[$varindex]->[0]} = $below_what;
5891 $varindex++; 5891 $varindex++;
5892 } 5892 }
5893 if ($varindex > $#{$vars}) { 5893 if ($varindex > $#{$vars}) {
5894 if ($sections[$sectindex]->[1] != optional) { 5894 if ($sections[$sectindex]->[1] != optional) {
5895 $line->log_warning("Empty line expected."); 5895 $line->log_warning("Empty line expected.");
5896 } 5896 }
5897 $next_section = true; 5897 $next_section = true;
5898 5898
5899 } elsif ($varcanon ne $vars->[$varindex]->[0]) { 5899 } elsif ($varcanon ne $vars->[$varindex]->[0]) {
5900 $line->log_warning("Expected " . $vars->[$varindex]->[0] . ", but found " . $varcanon . "."); 5900 $line->log_warning("Expected " . $vars->[$varindex]->[0] . ", but found " . $varcanon . ".");
5901 $lineno++; 5901 $lineno++;
5902 5902
5903 } else { 5903 } else {
5904 if ($vars->[$varindex]->[1] != many) { 5904 if ($vars->[$varindex]->[1] != many) {
5905 $below->{$vars->[$varindex]->[0]} = $below_what; 5905 $below->{$vars->[$varindex]->[0]} = $below_what;
5906 $varindex++; 5906 $varindex++;
5907 } 5907 }
5908 $lineno++; 5908 $lineno++;
5909 } 5909 }
5910 $below_what = $varcanon; 5910 $below_what = $varcanon;
5911 5911
5912 } else { 5912 } else {
5913 while ($varindex <= $#{$vars}) { 5913 while ($varindex <= $#{$vars}) {
5914 if ($vars->[$varindex]->[1] == once && !$may_skip_section) { 5914 if ($vars->[$varindex]->[1] == once && !$may_skip_section) {
5915 $line->log_warning($vars->[$varindex]->[0] . " should be set here."); 5915 $line->log_warning($vars->[$varindex]->[0] . " should be set here.");
5916 } 5916 }
5917 $below->{$vars->[$varindex]->[0]} = $below_what; 5917 $below->{$vars->[$varindex]->[0]} = $below_what;
5918 $varindex++; 5918 $varindex++;
5919 } 5919 }
5920 $next_section = true; 5920 $next_section = true;
5921 if ($text eq "") { 5921 if ($text eq "") {
5922 $below_what = "the previous empty line"; 5922 $below_what = "the previous empty line";
5923 $lineno++; 5923 $lineno++;
5924 } 5924 }
5925 } 5925 }
5926 } 5926 }
5927} 5927}
5928 5928
5929sub checklines_mk($) { 5929sub checklines_mk($) {
5930 my ($lines) = @_; 5930 my ($lines) = @_;
5931 my ($allowed_targets) = ({}); 5931 my ($allowed_targets) = ({});
5932 my ($substcontext) = PkgLint::SubstContext->new(); 5932 my ($substcontext) = PkgLint::SubstContext->new();
5933 5933
5934 assert(@{$lines} != 0, "checklines_mk may only be called with non-empty lines."); 5934 assert(@{$lines} != 0, "checklines_mk may only be called with non-empty lines.");
5935 $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_mk()"); 5935 $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_mk()");
5936 5936
5937 # Define global variables for the Makefile context. 5937 # Define global variables for the Makefile context.
5938 $mkctx_indentations = [0]; 5938 $mkctx_indentations = [0];
5939 $mkctx_target = undef; 5939 $mkctx_target = undef;
5940 $mkctx_for_variables = {}; 5940 $mkctx_for_variables = {};
5941 $mkctx_vardef = {}; 5941 $mkctx_vardef = {};
5942 $mkctx_build_defs = {}; 5942 $mkctx_build_defs = {};
5943 $mkctx_plist_vars = {}; 5943 $mkctx_plist_vars = {};
5944 $mkctx_tools = {%{get_predefined_tool_names()}}; 5944 $mkctx_tools = {%{get_predefined_tool_names()}};
5945 $mkctx_varuse = {}; 5945 $mkctx_varuse = {};
5946 5946
5947 determine_used_variables($lines); 5947 determine_used_variables($lines);
5948 5948
5949 foreach my $prefix (qw(pre do post)) { 5949 foreach my $prefix (qw(pre do post)) {
5950 foreach my $action (qw(fetch extract patch tools wrapper configure build test install package clean)) { 5950 foreach my $action (qw(fetch extract patch tools wrapper configure build test install package clean)) {
5951 $allowed_targets->{"${prefix}-${action}"} = true; 5951 $allowed_targets->{"${prefix}-${action}"} = true;
5952 } 5952 }
5953 } 5953 }
5954 5954
5955 # 5955 #
5956 # In the first pass, all additions to BUILD_DEFS and USE_TOOLS 5956 # In the first pass, all additions to BUILD_DEFS and USE_TOOLS
5957 # are collected to make the order of the definitions irrelevant. 5957 # are collected to make the order of the definitions irrelevant.
5958 # 5958 #
5959 5959
5960 foreach my $line (@{$lines}) { 5960 foreach my $line (@{$lines}) {
5961 next unless $line->has("is_varassign"); 5961 next unless $line->has("is_varassign");
5962 my $varcanon = $line->get("varcanon"); 5962 my $varcanon = $line->get("varcanon");
5963 5963
5964 if ($varcanon eq "BUILD_DEFS" || $varcanon eq "PKG_GROUPS_VARS" || $varcanon eq "PKG_USERS_VARS") { 5964 if ($varcanon eq "BUILD_DEFS" || $varcanon eq "PKG_GROUPS_VARS" || $varcanon eq "PKG_USERS_VARS") {
5965 foreach my $varname (split(qr"\s+", $line->get("value"))) { 5965 foreach my $varname (split(qr"\s+", $line->get("value"))) {
5966 $mkctx_build_defs->{$varname} = true; 5966 $mkctx_build_defs->{$varname} = true;
5967 $opt_debug_misc and $line->log_debug("${varname} is added to BUILD_DEFS."); 5967 $opt_debug_misc and $line->log_debug("${varname} is added to BUILD_DEFS.");
5968 } 5968 }
5969 5969
5970 } elsif ($varcanon eq "PLIST_VARS") { 5970 } elsif ($varcanon eq "PLIST_VARS") {
5971 foreach my $id (split(qr"\s+", $line->get("value"))) { 5971 foreach my $id (split(qr"\s+", $line->get("value"))) {
5972 $mkctx_plist_vars->{"PLIST.$id"} = true; 5972 $mkctx_plist_vars->{"PLIST.$id"} = true;
5973 $opt_debug_misc and $line->log_debug("PLIST.${id} is added to PLIST_VARS."); 5973 $opt_debug_misc and $line->log_debug("PLIST.${id} is added to PLIST_VARS.");
5974 use_var($line, "PLIST.$id"); 5974 use_var($line, "PLIST.$id");
5975 } 5975 }
5976 5976
5977 } elsif ($varcanon eq "USE_TOOLS") { 5977 } elsif ($varcanon eq "USE_TOOLS") {
5978 foreach my $tool (split(qr"\s+", $line->get("value"))) { 5978 foreach my $tool (split(qr"\s+", $line->get("value"))) {
5979 $mkctx_tools->{$tool} = true; 5979 $mkctx_tools->{$tool} = true;
5980 $opt_debug_misc and $line->log_debug("${tool} is added to USE_TOOLS."); 5980 $opt_debug_misc and $line->log_debug("${tool} is added to USE_TOOLS.");
5981 } 5981 }
5982 5982
5983 } elsif ($varcanon eq "SUBST_VARS.*") { 5983 } elsif ($varcanon eq "SUBST_VARS.*") {
5984 foreach my $svar (split(/\s+/, $line->get("value"))) { 5984 foreach my $svar (split(/\s+/, $line->get("value"))) {
5985 use_var($svar, varname_canon($svar)); 5985 use_var($svar, varname_canon($svar));
5986 $opt_debug_misc and $line->log_debug("varuse $svar"); 5986 $opt_debug_misc and $line->log_debug("varuse $svar");
5987 } 5987 }
5988 } 5988 }
5989 } 5989 }
5990 5990
5991 # 5991 #
5992 # In the second pass, all "normal" checks are done. 5992 # In the second pass, all "normal" checks are done.
5993 # 5993 #
5994 5994
5995 if (0 <= $#{$lines}) { 5995 if (0 <= $#{$lines}) {
5996 checkline_rcsid_regex($lines->[0], qr"^#\s+", "# "); 5996 checkline_rcsid_regex($lines->[0], qr"^#\s+", "# ");
5997 } 5997 }
5998 5998
5999 foreach my $line (@{$lines}) { 5999 foreach my $line (@{$lines}) {
6000 my $text = $line->text; 6000 my $text = $line->text;
6001 6001
6002 checkline_trailing_whitespace($line); 6002 checkline_trailing_whitespace($line);
6003 checkline_spellcheck($line); 6003 checkline_spellcheck($line);
6004 6004
6005 if ($line->has("is_empty")) { 6005 if ($line->has("is_empty")) {
6006 $substcontext->check_end($line); 6006 $substcontext->check_end($line);
6007 6007
6008 } elsif ($line->has("is_comment")) { 6008 } elsif ($line->has("is_comment")) {
6009 # No further checks. 6009 # No further checks.
6010 6010
6011 } elsif ($text =~ regex_varassign) { 6011 } elsif ($text =~ regex_varassign) {
6012 my ($varname, $op, undef, $comment) = ($1, $2, $3, $4); 6012 my ($varname, $op, undef, $comment) = ($1, $2, $3, $4);
6013 my $space1 = substr($text, $+[1], $-[2] - $+[1]); 6013 my $space1 = substr($text, $+[1], $-[2] - $+[1]);
6014 my $align = substr($text, $+[2], $-[3] - $+[2]); 6014 my $align = substr($text, $+[2], $-[3] - $+[2]);
6015 my $value = $line->get("value"); 6015 my $value = $line->get("value");
6016 6016
6017 if ($align !~ m"^(\t*|[ ])$") { 6017 if ($align !~ m"^(\t*|[ ])$") {
6018 $opt_warn_space && $line->log_note("Alignment of variable values should be done with tabs, not spaces."); 6018 $opt_warn_space && $line->log_note("Alignment of variable values should be done with tabs, not spaces.");
6019 my $prefix = "${varname}${space1}${op}"; 6019 my $prefix = "${varname}${space1}${op}";
6020 my $aligned_len = tablen("${prefix}${align}"); 6020 my $aligned_len = tablen("${prefix}${align}");
6021 if ($aligned_len % 8 == 0) { 6021 if ($aligned_len % 8 == 0) {
6022 my $tabalign = ("\t" x (($aligned_len - tablen($prefix) + 7) / 8)); 6022 my $tabalign = ("\t" x (($aligned_len - tablen($prefix) + 7) / 8));
6023 $line->replace("${prefix}${align}", "${prefix}${tabalign}"); 6023 $line->replace("${prefix}${align}", "${prefix}${tabalign}");
6024 } 6024 }
6025 } 6025 }
6026 checkline_mk_varassign($line, $varname, $op, $value, $comment); 6026 checkline_mk_varassign($line, $varname, $op, $value, $comment);
6027 $substcontext->check_varassign($line, $varname, $op, $value); 6027 $substcontext->check_varassign($line, $varname, $op, $value);
6028 6028
6029 } elsif ($text =~ regex_mk_shellcmd) { 6029 } elsif ($text =~ regex_mk_shellcmd) {
6030 my ($shellcmd) = ($1); 6030 my ($shellcmd) = ($1);
6031 checkline_mk_shellcmd($line, $shellcmd); 6031 checkline_mk_shellcmd($line, $shellcmd);
6032 6032
6033 } elsif ($text =~ regex_mk_include) { 6033 } elsif ($text =~ regex_mk_include) {
6034 my ($include, $includefile) = ($1, $2); 6034 my ($include, $includefile) = ($1, $2);
6035 6035
6036 $opt_debug_include and $line->log_debug("includefile=${includefile}"); 6036 $opt_debug_include and $line->log_debug("includefile=${includefile}");
6037 checkline_relative_path($line, $includefile, $include eq "include"); 6037 checkline_relative_path($line, $includefile, $include eq "include");
6038 6038
6039 if ($includefile =~ m"../Makefile$") { 6039 if ($includefile =~ m"../Makefile$") {
6040 $line->log_error("Other Makefiles must not be included directly."); 6040 $line->log_error("Other Makefiles must not be included directly.");
6041 $line->explain_warning( 6041 $line->explain_warning(
6042"If you want to include portions of another Makefile, extract", 6042"If you want to include portions of another Makefile, extract",
6043"the common parts and put them into a Makefile.common. After", 6043"the common parts and put them into a Makefile.common. After",
6044"that, both this one and the other package should include the", 6044"that, both this one and the other package should include the",
6045"Makefile.common."); 6045"Makefile.common.");
6046 } 6046 }
6047 6047
6048 if ($includefile eq "../../mk/bsd.prefs.mk") { 6048 if ($includefile eq "../../mk/bsd.prefs.mk") {
6049 if ($line->fname =~ m"buildlink3\.mk$") { 6049 if ($line->fname =~ m"buildlink3\.mk$") {
6050 $line->log_note("For efficiency reasons, please include bsd.fast.prefs.mk instead of bsd.prefs.mk."); 6050 $line->log_note("For efficiency reasons, please include bsd.fast.prefs.mk instead of bsd.prefs.mk.");
6051 } 6051 }
6052 $seen_bsd_prefs_mk = true; 6052 $seen_bsd_prefs_mk = true;
6053 } elsif ($includefile eq "../../mk/bsd.fast.prefs.mk") { 6053 } elsif ($includefile eq "../../mk/bsd.fast.prefs.mk") {
6054 $seen_bsd_prefs_mk = true; 6054 $seen_bsd_prefs_mk = true;
6055 } 6055 }
6056 6056
6057 if ($includefile =~ m"/x11-links/buildlink3\.mk$") { 6057 if ($includefile =~ m"/x11-links/buildlink3\.mk$") {
6058 $line->log_error("${includefile} must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead."); 6058 $line->log_error("${includefile} must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead.");
6059 } 6059 }
6060 if ($includefile =~ m"/intltool/buildlink3\.mk$") { 6060 if ($includefile =~ m"/intltool/buildlink3\.mk$") {
6061 $line->log_warning("Please say \"USE_TOOLS+= intltool\" instead of this line."); 6061 $line->log_warning("Please say \"USE_TOOLS+= intltool\" instead of this line.");
6062 } 6062 }
6063 if ($includefile =~ m"(.*)/builtin\.mk$") { 6063 if ($includefile =~ m"(.*)/builtin\.mk$") {
6064 my ($dir) = ($1); 6064 my ($dir) = ($1);
6065 $line->log_error("${includefile} must not be included directly. Include \"${dir}/buildlink3.mk\" instead."); 6065 $line->log_error("${includefile} must not be included directly. Include \"${dir}/buildlink3.mk\" instead.");
6066 } 6066 }
6067 6067
6068 } elsif ($text =~ regex_mk_sysinclude) { 6068 } elsif ($text =~ regex_mk_sysinclude) {
6069 my ($includefile, $comment) = ($1, $2); 6069 my ($includefile, $comment) = ($1, $2);
6070 6070
6071 # No further action. 6071 # No further action.
6072 6072
6073 } elsif ($text =~ regex_mk_cond) { 6073 } elsif ($text =~ regex_mk_cond) {
6074 my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4); 6074 my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4);
6075 6075
6076 use constant regex_directives_with_args => qr"^(?:if|ifdef|ifndef|elif|for|undef)$"; 6076 use constant regex_directives_with_args => qr"^(?:if|ifdef|ifndef|elif|for|undef)$";
6077 6077
6078 if ($directive =~ m"^(?:endif|endfor|elif|else)$") { 6078 if ($directive =~ m"^(?:endif|endfor|elif|else)$") {
6079 if ($#{$mkctx_indentations} >= 1) { 6079 if ($#{$mkctx_indentations} >= 1) {
6080 pop(@{$mkctx_indentations}); 6080 pop(@{$mkctx_indentations});
6081 } else { 6081 } else {
6082 $line->log_error("Unmatched .${directive}."); 6082 $line->log_error("Unmatched .${directive}.");
6083 } 6083 }
6084 } 6084 }
6085 6085
6086 # Check the indentation 6086 # Check the indentation
6087 if ($indent ne " " x $mkctx_indentations->[-1]) { 6087 if ($indent ne " " x $mkctx_indentations->[-1]) {
6088 $opt_warn_space and $line->log_note("This directive should be indented by ".$mkctx_indentations->[-1]." spaces."); 6088 $opt_warn_space and $line->log_note("This directive should be indented by ".$mkctx_indentations->[-1]." spaces.");
6089 } 6089 }
6090 6090
6091 if ($directive eq "if" && $args =~ m"^!defined\([\w]+_MK\)$") { 6091 if ($directive eq "if" && $args =~ m"^!defined\([\w]+_MK\)$") {
6092 push(@{$mkctx_indentations}, $mkctx_indentations->[-1]); 6092 push(@{$mkctx_indentations}, $mkctx_indentations->[-1]);
6093 6093
6094 } elsif ($directive =~ m"^(?:if|ifdef|ifndef|for|elif|else)$") { 6094 } elsif ($directive =~ m"^(?:if|ifdef|ifndef|for|elif|else)$") {
6095 push(@{$mkctx_indentations}, $mkctx_indentations->[-1] + 2); 6095 push(@{$mkctx_indentations}, $mkctx_indentations->[-1] + 2);
6096 } 6096 }
6097 6097
6098 if ($directive =~ regex_directives_with_args && !defined($args)) { 6098 if ($directive =~ regex_directives_with_args && !defined($args)) {
6099 $line->log_error("\".${directive}\" must be given some arguments."); 6099 $line->log_error("\".${directive}\" must be given some arguments.");
6100 6100
6101 } elsif ($directive !~ regex_directives_with_args && defined($args)) { 6101 } elsif ($directive !~ regex_directives_with_args && defined($args)) {
6102 $line->log_error("\".${directive}\" does not take arguments."); 6102 $line->log_error("\".${directive}\" does not take arguments.");
6103 6103
6104 if ($directive eq "else") { 6104 if ($directive eq "else") {
6105 $line->log_note("If you meant \"else if\", use \".elif\"."); 6105 $line->log_note("If you meant \"else if\", use \".elif\".");
6106 } 6106 }
6107 6107
6108 } elsif ($directive eq "if" || $directive eq "elif") { 6108 } elsif ($directive eq "if" || $directive eq "elif") {
6109 checkline_mk_cond($line, $args); 6109 checkline_mk_cond($line, $args);
6110 6110
6111 } elsif ($directive eq "ifdef" || $directive eq "ifndef") { 6111 } elsif ($directive eq "ifdef" || $directive eq "ifndef") {
6112 if ($args =~ m"\s") { 6112 if ($args =~ m"\s") {
6113 $line->log_error("The \".${directive}\" directive can only handle _one_ argument."); 6113 $line->log_error("The \".${directive}\" directive can only handle _one_ argument.");
6114 } else { 6114 } else {
6115 $line->log_warning("The \".${directive}\" directive is deprecated. Please use \".if " 6115 $line->log_warning("The \".${directive}\" directive is deprecated. Please use \".if "
6116 . (($directive eq "ifdef" ? "" : "!")) 6116 . (($directive eq "ifdef" ? "" : "!"))
6117 . "defined(${args})\" instead."); 6117 . "defined(${args})\" instead.");
6118 } 6118 }
6119 6119
6120 } elsif ($directive eq "for") { 6120 } elsif ($directive eq "for") {
6121 if ($args =~ m"^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$") { 6121 if ($args =~ m"^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$") {
6122 my ($vars, $values) = ($1, $2); 6122 my ($vars, $values) = ($1, $2);
6123 6123
6124 foreach my $var (split(qr"\s+", $vars)) { 6124 foreach my $var (split(qr"\s+", $vars)) {
6125 if (!$is_internal && $var =~ m"^_") { 6125 if (!$is_internal && $var =~ m"^_") {
6126 $line->log_warning("Variable names starting with an underscore are reserved for internal pkgsrc use."); 6126 $line->log_warning("Variable names starting with an underscore are reserved for internal pkgsrc use.");
6127 } 6127 }
6128 6128
6129 if ($var =~ m"^[_a-z][_a-z0-9]*$") { 6129 if ($var =~ m"^[_a-z][_a-z0-9]*$") {
6130 # Fine. 6130 # Fine.
6131 } elsif ($var =~ m"[A-Z]") { 6131 } elsif ($var =~ m"[A-Z]") {
6132 $line->log_warning(".for variable names should not contain uppercase letters."); 6132 $line->log_warning(".for variable names should not contain uppercase letters.");
6133 } else { 6133 } else {
6134 $line->log_error("Invalid variable name \"${var}\"."); 6134 $line->log_error("Invalid variable name \"${var}\".");
6135 } 6135 }
6136 6136
6137 $mkctx_for_variables->{$var} = true; 6137 $mkctx_for_variables->{$var} = true;
6138 } 6138 }
6139 6139
6140 # Check if any of the value's types is not guessed. 6140 # Check if any of the value's types is not guessed.
6141 my $guessed = true; 6141 my $guessed = true;
6142 foreach my $value (split(qr"\s+", $values)) { # XXX: too simple 6142 foreach my $value (split(qr"\s+", $values)) { # XXX: too simple
6143 if ($value =~ m"^\$\{(.*)\}") { 6143 if ($value =~ m"^\$\{(.*)\}") {
6144 my $type = get_variable_type($line, $1); 6144 my $type = get_variable_type($line, $1);
6145 if (defined($type) && !$type->is_guessed()) { 6145 if (defined($type) && !$type->is_guessed()) {
6146 $guessed = false; 6146 $guessed = false;
6147 } 6147 }
6148 } 6148 }
6149 } 6149 }
6150 6150
6151 my $for_loop_type = PkgLint::Type->new( 6151 my $for_loop_type = PkgLint::Type->new(
6152 LK_INTERNAL, 6152 LK_INTERNAL,
6153 "Unchecked", 6153 "Unchecked",
6154 [[qr".*", "pu"]], 6154 [[qr".*", "pu"]],
6155 $guessed 6155 $guessed
6156 ); 6156 );
6157 my $for_loop_context = PkgLint::VarUseContext->new( 6157 my $for_loop_context = PkgLint::VarUseContext->new(
6158 VUC_TIME_LOAD, 6158 VUC_TIME_LOAD,
6159 $for_loop_type, 6159 $for_loop_type,
6160 VUC_SHELLWORD_FOR, 6160 VUC_SHELLWORD_FOR,
6161 VUC_EXTENT_WORD 6161 VUC_EXTENT_WORD
6162 ); 6162 );
6163 foreach my $var (@{extract_used_variables($line, $values)}) { 6163 foreach my $var (@{extract_used_variables($line, $values)}) {
6164 checkline_mk_varuse($line, $var, "", $for_loop_context); 6164 checkline_mk_varuse($line, $var, "", $for_loop_context);
6165 } 6165 }
6166 6166
6167 } 6167 }
6168 6168
6169 } elsif ($directive eq "undef" && defined($args)) { 6169 } elsif ($directive eq "undef" && defined($args)) {
6170 foreach my $var (split(qr"\s+", $args)) { 6170 foreach my $var (split(qr"\s+", $args)) {
6171 if (exists($mkctx_for_variables->{$var})) { 6171 if (exists($mkctx_for_variables->{$var})) {
6172 $line->log_note("Using \".undef\" after a \".for\" loop is unnecessary."); 6172 $line->log_note("Using \".undef\" after a \".for\" loop is unnecessary.");
6173 } 6173 }
6174 } 6174 }
6175 } 6175 }
6176 6176
6177 } elsif ($text =~ regex_mk_dependency) { 6177 } elsif ($text =~ regex_mk_dependency) {
6178 my ($targets, $dependencies) = ($1, $2); 6178 my ($targets, $dependencies) = ($1, $2);
6179 6179
6180 $opt_debug_misc and $line->log_debug("targets=${targets}, dependencies=${dependencies}"); 6180 $opt_debug_misc and $line->log_debug("targets=${targets}, dependencies=${dependencies}");
6181 $mkctx_target = $targets; 6181 $mkctx_target = $targets;
6182 6182
6183 foreach my $source (split(/\s+/, $dependencies)) { 6183 foreach my $source (split(/\s+/, $dependencies)) {
6184 if ($source eq ".PHONY") { 6184 if ($source eq ".PHONY") {
6185 foreach my $target (split(/\s+/, $targets)) { 6185 foreach my $target (split(/\s+/, $targets)) {
6186 $allowed_targets->{$target} = true; 6186 $allowed_targets->{$target} = true;
6187 } 6187 }
6188 } 6188 }
6189 } 6189 }
6190 6190
6191 foreach my $target (split(/\s+/, $targets)) { 6191 foreach my $target (split(/\s+/, $targets)) {
6192 if ($target eq ".PHONY") { 6192 if ($target eq ".PHONY") {
6193 foreach my $dep (split(qr"\s+", $dependencies)) { 6193 foreach my $dep (split(qr"\s+", $dependencies)) {
6194 $allowed_targets->{$dep} = true; 6194 $allowed_targets->{$dep} = true;
6195 } 6195 }
6196 6196
6197 } elsif ($target eq ".ORDER") { 6197 } elsif ($target eq ".ORDER") {
6198 # TODO: Check for spelling mistakes. 6198 # TODO: Check for spelling mistakes.
6199 6199
6200 } elsif (!exists($allowed_targets->{$target})) { 6200 } elsif (!exists($allowed_targets->{$target})) {
6201 $line->log_warning("Unusual target \"${target}\"."); 6201 $line->log_warning("Unusual target \"${target}\".");
6202 $line->explain_warning( 6202 $line->explain_warning(
6203"If you really want to define your own targets, you can \"declare\"", 6203"If you really want to define your own targets, you can \"declare\"",
6204"them by inserting a \".PHONY: my-target\" line before this line. This", 6204"them by inserting a \".PHONY: my-target\" line before this line. This",
6205"will tell make(1) to not interpret this target's name as a filename."); 6205"will tell make(1) to not interpret this target's name as a filename.");
6206 } 6206 }
6207 } 6207 }
6208 6208
6209 } elsif ($text =~ m"^\.\s*(\S*)") { 6209 } elsif ($text =~ m"^\.\s*(\S*)") {
6210 my ($directive) = ($1); 6210 my ($directive) = ($1);
6211 6211
6212 $line->log_error("Unknown directive \".${directive}\"."); 6212 $line->log_error("Unknown directive \".${directive}\".");
6213 6213
6214 } elsif ($text =~ m"^ ") { 6214 } elsif ($text =~ m"^ ") {
6215 $line->log_warning("Makefile lines should not start with space characters."); 6215 $line->log_warning("Makefile lines should not start with space characters.");
6216 $line->explain_warning( 6216 $line->explain_warning(
6217"If you want this line to contain a shell program, use a tab", 6217"If you want this line to contain a shell program, use a tab",
6218"character for indentation. Otherwise please remove the leading", 6218"character for indentation. Otherwise please remove the leading",
6219"white-space."); 6219"white-space.");
6220 6220
6221 } else { 6221 } else {
6222 $line->log_error("[Internal] Unknown line format: $text"); 6222 $line->log_error("[Internal] Unknown line format: $text");
6223 } 6223 }
6224 } 6224 }
6225 if (@{$lines} > 0) { 6225 if (@{$lines} > 0) {
6226 $substcontext->check_end($lines->[-1]); 6226 $substcontext->check_end($lines->[-1]);
6227 } 6227 }
6228 6228
6229 checklines_trailing_empty_lines($lines); 6229 checklines_trailing_empty_lines($lines);
6230 6230
6231 if ($#{$mkctx_indentations} != 0) { 6231 if ($#{$mkctx_indentations} != 0) {
6232 $lines->[-1]->log_error("Directive indentation is not 0, but ".$mkctx_indentations->[-1]." at EOF."); 6232 $lines->[-1]->log_error("Directive indentation is not 0, but ".$mkctx_indentations->[-1]." at EOF.");
6233 } 6233 }
6234 6234
6235 # Clean up global variables. 6235 # Clean up global variables.
6236 $mkctx_for_variables = undef; 6236 $mkctx_for_variables = undef;
6237 $mkctx_indentations = undef; 6237 $mkctx_indentations = undef;
6238 $mkctx_target = undef; 6238 $mkctx_target = undef;
6239 $mkctx_vardef = undef; 6239 $mkctx_vardef = undef;
6240 $mkctx_build_defs = undef; 6240 $mkctx_build_defs = undef;
6241 $mkctx_plist_vars = undef; 6241 $mkctx_plist_vars = undef;
6242 $mkctx_tools = undef; 6242 $mkctx_tools = undef;
6243 $mkctx_varuse = undef; 6243 $mkctx_varuse = undef;
6244} 6244}
6245 6245
6246sub checklines_buildlink3_inclusion($) { 6246sub checklines_buildlink3_inclusion($) {
6247 my ($lines) = @_; 6247 my ($lines) = @_;
6248 my ($included_files); 6248 my ($included_files);
6249 6249
6250 assert(@{$lines} != 0, "The lines array must be non-empty."); 6250 assert(@{$lines} != 0, "The lines array must be non-empty.");
6251 $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_buildlink3_inclusion()"); 6251 $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_buildlink3_inclusion()");
6252 6252
6253 if (!defined($pkgctx_bl3)) { 6253 if (!defined($pkgctx_bl3)) {
6254 return; 6254 return;
6255 } 6255 }
6256 6256
6257 # Collect all the included buildlink3.mk files from the file. 6257 # Collect all the included buildlink3.mk files from the file.
6258 $included_files = {}; 6258 $included_files = {};
6259 foreach my $line (@{$lines}) { 6259 foreach my $line (@{$lines}) {
6260 if ($line->text =~ regex_mk_include) { 6260 if ($line->text =~ regex_mk_include) {
6261 my (undef, $file, $comment) = ($1, $2, $3); 6261 my (undef, $file, $comment) = ($1, $2, $3);
6262 6262
6263 if ($file =~ m"^\.\./\.\./(.*)/buildlink3\.mk") { 6263 if ($file =~ m"^\.\./\.\./(.*)/buildlink3\.mk") {
6264 my ($bl3) = ($1); 6264 my ($bl3) = ($1);
6265 6265
6266 $included_files->{$bl3} = $line; 6266 $included_files->{$bl3} = $line;
6267 if (!exists($pkgctx_bl3->{$bl3})) { 6267 if (!exists($pkgctx_bl3->{$bl3})) {
6268 $line->log_warning("${bl3}/buildlink3.mk is included by this file but not by the package."); 6268 $line->log_warning("${bl3}/buildlink3.mk is included by this file but not by the package.");
6269 } 6269 }
6270 } 6270 }
6271 } 6271 }
6272 } 6272 }
6273 6273
6274 # Print debugging messages for all buildlink3.mk files that are 6274 # Print debugging messages for all buildlink3.mk files that are
6275 # included by the package but not by this buildlink3.mk file. 6275 # included by the package but not by this buildlink3.mk file.
6276 foreach my $package_bl3 (sort(keys(%{$pkgctx_bl3}))) { 6276 foreach my $package_bl3 (sort(keys(%{$pkgctx_bl3}))) {
6277 if (!exists($included_files->{$package_bl3})) { 6277 if (!exists($included_files->{$package_bl3})) {
6278 $opt_debug_misc and $pkgctx_bl3->{$package_bl3}->log_debug("${package_bl3}/buildlink3.mk is included by the package but not by the buildlink3.mk file."); 6278 $opt_debug_misc and $pkgctx_bl3->{$package_bl3}->log_debug("${package_bl3}/buildlink3.mk is included by the package but not by the buildlink3.mk file.");
6279 } 6279 }
6280 } 6280 }
6281} 6281}
6282 6282
6283# 6283#
6284# Procedures to check a single file. 6284# Procedures to check a single file.
6285# 6285#
6286 6286
6287sub checkfile_ALTERNATIVES($) { 6287sub checkfile_ALTERNATIVES($) {
6288 my ($fname) = @_; 6288 my ($fname) = @_;
6289 my ($lines); 6289 my ($lines);
6290 6290
6291 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_ALTERNATIVES()"); 6291 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_ALTERNATIVES()");
6292 6292
6293 checkperms($fname); 6293 checkperms($fname);
6294 if (!($lines = load_file($fname))) { 6294 if (!($lines = load_file($fname))) {
6295 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6295 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6296 return; 6296 return;
6297 } 6297 }
6298} 6298}
6299 6299
6300sub checklines_buildlink3_mk_2009($$$); 6300sub checklines_buildlink3_mk_2009($$$);
6301sub checklines_buildlink3_mk_pre2009($$); 6301sub checklines_buildlink3_mk_pre2009($$);
6302sub checkfile_buildlink3_mk($) { 6302sub checkfile_buildlink3_mk($) {
6303 my ($fname) = @_; 6303 my ($fname) = @_;
6304 my ($lines, $lineno, $m); 6304 my ($lines, $lineno, $m);
6305 6305
6306 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_buildlink3_mk()"); 6306 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_buildlink3_mk()");
6307 6307
6308 checkperms($fname); 6308 checkperms($fname);
6309 if (!($lines = load_lines($fname, true))) { 6309 if (!($lines = load_lines($fname, true))) {
6310 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6310 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6311 return; 6311 return;
6312 } 6312 }
6313 if (@{$lines} == 0) { 6313 if (@{$lines} == 0) {
6314 log_error($fname, NO_LINES, "Must not be empty."); 6314 log_error($fname, NO_LINES, "Must not be empty.");
6315 return; 6315 return;
6316 } 6316 }
6317 6317
6318 parselines_mk($lines); 6318 parselines_mk($lines);
6319 checklines_mk($lines); 6319 checklines_mk($lines);
6320 6320
6321 $lineno = 0; 6321 $lineno = 0;
6322 6322
6323 # Header comments 6323 # Header comments
6324 while ($lineno <= $#{$lines} && (my $text = $lines->[$lineno]->text) =~ m"^#") { 6324 while ($lineno <= $#{$lines} && (my $text = $lines->[$lineno]->text) =~ m"^#") {
6325 if ($text =~ m"^# XXX") { 6325 if ($text =~ m"^# XXX") {
6326 $lines->[$lineno]->log_note("Please read this comment and remove it if appropriate."); 6326 $lines->[$lineno]->log_note("Please read this comment and remove it if appropriate.");
6327 } 6327 }
6328 $lineno++; 6328 $lineno++;
6329 } 6329 }
6330 expect_empty_line($lines, \$lineno); 6330 expect_empty_line($lines, \$lineno);
6331 6331
6332 # This line does not belong here, but appears often. 6332 # This line does not belong here, but appears often.
6333 if (expect($lines, \$lineno, qr"^BUILDLINK_DEPMETHOD\.(\S+)\?=.*$")) { 6333 if (expect($lines, \$lineno, qr"^BUILDLINK_DEPMETHOD\.(\S+)\?=.*$")) {
6334 $lines->[$lineno - 1]->log_warning("This line belongs inside the .ifdef block."); 6334 $lines->[$lineno - 1]->log_warning("This line belongs inside the .ifdef block.");
6335 while ($lines->[$lineno]->text eq "") { 6335 while ($lines->[$lineno]->text eq "") {
6336 $lineno++; 6336 $lineno++;
6337 } 6337 }
6338 } 6338 }
6339 6339
6340 if (($m = expect($lines, \$lineno, qr"^BUILDLINK_TREE\+=\s*(\S+)$"))) { 6340 if (($m = expect($lines, \$lineno, qr"^BUILDLINK_TREE\+=\s*(\S+)$"))) {
6341 checklines_buildlink3_mk_2009($lines, $lineno, $m->text(1)); 6341 checklines_buildlink3_mk_2009($lines, $lineno, $m->text(1));
6342 } else { 6342 } else {
6343 checklines_buildlink3_mk_pre2009($lines, $lineno); 6343 checklines_buildlink3_mk_pre2009($lines, $lineno);
6344 } 6344 }
6345} 6345}
6346 6346
6347sub checklines_buildlink3_mk_pre2009($$) { 6347sub checklines_buildlink3_mk_pre2009($$) {
6348 my ($lines, $lineno) = @_; 6348 my ($lines, $lineno) = @_;
6349 my ($m); 6349 my ($m);
6350 my ($bl_PKGBASE_line, $bl_PKGBASE); 6350 my ($bl_PKGBASE_line, $bl_PKGBASE);
6351 my ($bl_pkgbase_line, $bl_pkgbase); 6351 my ($bl_pkgbase_line, $bl_pkgbase);
6352 my ($abi_line, $abi_pkg, $abi_version); 6352 my ($abi_line, $abi_pkg, $abi_version);
6353 my ($api_line, $api_pkg, $api_version); 6353 my ($api_line, $api_pkg, $api_version);
6354 6354
6355 # First paragraph: Reference counters. 6355 # First paragraph: Reference counters.
6356 if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH\}\+$")) { 6356 if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH\}\+$")) {
6357 # When none of the formats has been found, prefer the 2009 format. 6357 # When none of the formats has been found, prefer the 2009 format.
6358 lines_log_warning($lines, $lineno, "Expected BUILDLINK_TREE line."); 6358 lines_log_warning($lines, $lineno, "Expected BUILDLINK_TREE line.");
6359 return; 6359 return;
6360 } 6360 }
6361 if (($m = expect($lines, \$lineno, qr"^(.*)_BUILDLINK3_MK:=\t*\$\{\1_BUILDLINK3_MK\}\+$"))) { 6361 if (($m = expect($lines, \$lineno, qr"^(.*)_BUILDLINK3_MK:=\t*\$\{\1_BUILDLINK3_MK\}\+$"))) {
6362 $bl_PKGBASE_line = $lines->[$lineno - 1]; 6362 $bl_PKGBASE_line = $lines->[$lineno - 1];
6363 $bl_PKGBASE = $m->text(1); 6363 $bl_PKGBASE = $m->text(1);
6364 $opt_debug_misc and $bl_PKGBASE_line->log_debug("bl_PKGBASE=${bl_PKGBASE}"); 6364 $opt_debug_misc and $bl_PKGBASE_line->log_debug("bl_PKGBASE=${bl_PKGBASE}");
6365 } else { 6365 } else {
6366 lines_log_warning($lines, $lineno, "Expected {PKGNAME}_BUILDLINK3_MK:= \${{PKGNAME}_BUILDLINK3_MK}+."); 6366 lines_log_warning($lines, $lineno, "Expected {PKGNAME}_BUILDLINK3_MK:= \${{PKGNAME}_BUILDLINK3_MK}+.");
6367 return; 6367 return;
6368 } 6368 }
6369 expect_empty_line($lines, \$lineno); 6369 expect_empty_line($lines, \$lineno);
6370 6370
6371 # Second paragraph: Adding the dependency. 6371 # Second paragraph: Adding the dependency.
6372 if (!expect($lines, \$lineno, qr"^\.if !empty\(BUILDLINK_DEPTH:M\+\)$")) { 6372 if (!expect($lines, \$lineno, qr"^\.if !empty\(BUILDLINK_DEPTH:M\+\)$")) {
6373 if (!expect_text($lines, \$lineno, ".if \${BUILDLINK_DEPTH} == \"+\"")) { 6373 if (!expect_text($lines, \$lineno, ".if \${BUILDLINK_DEPTH} == \"+\"")) {
6374 return; 6374 return;
6375 } 6375 }
6376 } 6376 }
6377 if (($m = expect($lines, \$lineno, qr"^BUILDLINK_DEPENDS\+=\t+(\S+)$"))) { 6377 if (($m = expect($lines, \$lineno, qr"^BUILDLINK_DEPENDS\+=\t+(\S+)$"))) {
6378 $bl_pkgbase_line = $lines->[$lineno - 1]; 6378 $bl_pkgbase_line = $lines->[$lineno - 1];
6379 $bl_pkgbase = $m->text(1); 6379 $bl_pkgbase = $m->text(1);
6380 $opt_debug_misc and $bl_pkgbase_line->log_debug("bl_pkgbase=${bl_pkgbase}"); 6380 $opt_debug_misc and $bl_pkgbase_line->log_debug("bl_pkgbase=${bl_pkgbase}");
6381 } else { 6381 } else {
6382 lines_log_warning($lines, $lineno, "BUILDLINK_DEPENDS line expected."); 6382 lines_log_warning($lines, $lineno, "BUILDLINK_DEPENDS line expected.");
6383 return; 6383 return;
6384 } 6384 }
6385 6385
6386 my $norm_bl_pkgbase = $bl_pkgbase; 6386 my $norm_bl_pkgbase = $bl_pkgbase;
6387 $norm_bl_pkgbase =~ s/-/_/g; 6387 $norm_bl_pkgbase =~ s/-/_/g;
6388 $norm_bl_pkgbase = uc($norm_bl_pkgbase); 6388 $norm_bl_pkgbase = uc($norm_bl_pkgbase);
6389 if ($norm_bl_pkgbase ne $bl_PKGBASE) { 6389 if ($norm_bl_pkgbase ne $bl_PKGBASE) {
6390 $bl_PKGBASE_line->log_error("Package name mismatch between ${bl_PKGBASE} ..."); 6390 $bl_PKGBASE_line->log_error("Package name mismatch between ${bl_PKGBASE} ...");
6391 $bl_pkgbase_line->log_error("... and ${bl_pkgbase}."); 6391 $bl_pkgbase_line->log_error("... and ${bl_pkgbase}.");
6392 } 6392 }
6393 if (defined($effective_pkgbase) && $effective_pkgbase ne $bl_pkgbase) { 6393 if (defined($effective_pkgbase) && $effective_pkgbase ne $bl_pkgbase) {
6394 $bl_pkgbase_line->log_error("Package name mismatch between ${bl_pkgbase} ..."); 6394 $bl_pkgbase_line->log_error("Package name mismatch between ${bl_pkgbase} ...");
6395 $effective_pkgname_line->log_error("... and ${effective_pkgbase}."); 6395 $effective_pkgname_line->log_error("... and ${effective_pkgbase}.");
6396 } 6396 }
6397 6397
6398 if (!expect_text($lines, \$lineno, ".endif")) { 6398 if (!expect_text($lines, \$lineno, ".endif")) {
6399 return; 6399 return;
6400 } 6400 }
6401 expect_empty_line($lines, \$lineno); 6401 expect_empty_line($lines, \$lineno);
6402 6402
6403 # Third paragraph: Duplicate elimination. 6403 # Third paragraph: Duplicate elimination.
6404 if (expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES:=\t+\$\{BUILDLINK_PACKAGES:N\Q${bl_pkgbase}\E\}\s+\Q${bl_pkgbase}\E$")) { 6404 if (expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES:=\t+\$\{BUILDLINK_PACKAGES:N\Q${bl_pkgbase}\E\}\s+\Q${bl_pkgbase}\E$")) {
6405 # The compressed form of duplicate elimination. 6405 # The compressed form of duplicate elimination.
6406 6406
6407 } else { 6407 } else {
6408 if (!expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES:=\t+\$\{BUILDLINK_PACKAGES:N\Q${bl_pkgbase}\E\}$")) { 6408 if (!expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES:=\t+\$\{BUILDLINK_PACKAGES:N\Q${bl_pkgbase}\E\}$")) {
6409 lines_log_warning($lines, $lineno, "Expected BUILDLINK_PACKAGES:= \${BUILDLINK_PACKAGES:N${bl_pkgbase}} line."); 6409 lines_log_warning($lines, $lineno, "Expected BUILDLINK_PACKAGES:= \${BUILDLINK_PACKAGES:N${bl_pkgbase}} line.");
6410 return; 6410 return;
6411 } 6411 }
6412 if (!expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES\+=\t+\Q${bl_pkgbase}\E$")) { 6412 if (!expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES\+=\t+\Q${bl_pkgbase}\E$")) {
6413 lines_log_warning($lines, $lineno, "Expected BUILDLINK_PACKAGES+= ${bl_pkgbase} line."); 6413 lines_log_warning($lines, $lineno, "Expected BUILDLINK_PACKAGES+= ${bl_pkgbase} line.");
6414 return; 6414 return;
6415 } 6415 }
6416 } 6416 }
6417 expect_text($lines, \$lineno, "BUILDLINK_ORDER:=\t\${BUILDLINK_ORDER} \${BUILDLINK_DEPTH}${bl_pkgbase}"); 6417 expect_text($lines, \$lineno, "BUILDLINK_ORDER:=\t\${BUILDLINK_ORDER} \${BUILDLINK_DEPTH}${bl_pkgbase}");
6418 expect_empty_line($lines, \$lineno); 6418 expect_empty_line($lines, \$lineno);
6419 6419
6420 # Fourth paragraph: Package information. 6420 # Fourth paragraph: Package information.
6421 if (!expect($lines, \$lineno, qr"^\.if !empty\(\Q${bl_PKGBASE}\E_BUILDLINK3_MK:M\+\)$")) { 6421 if (!expect($lines, \$lineno, qr"^\.if !empty\(\Q${bl_PKGBASE}\E_BUILDLINK3_MK:M\+\)$")) {
6422 if (!expect_text($lines, \$lineno, ".if \${${bl_PKGBASE}_BUILDLINK3_MK} == \"+\"")) { 6422 if (!expect_text($lines, \$lineno, ".if \${${bl_PKGBASE}_BUILDLINK3_MK} == \"+\"")) {
6423 return; 6423 return;
6424 } 6424 }
6425 } 6425 }
6426 while (!expect($lines, \$lineno, qr"^\.endif.*$")) { 6426 while (!expect($lines, \$lineno, qr"^\.endif.*$")) {
6427 6427
6428 if ($lineno > $#{$lines}) { 6428 if ($lineno > $#{$lines}) {
6429 lines_log_warning($lines, $lineno, "Expected .endif"); 6429 lines_log_warning($lines, $lineno, "Expected .endif");
6430 return; 6430 return;
6431 } 6431 }
6432 6432
6433 my $line = $lines->[$lineno]; 6433 my $line = $lines->[$lineno];
6434 6434
6435 if (($m = expect($lines, \$lineno, regex_varassign))) { 6435 if (($m = expect($lines, \$lineno, regex_varassign))) {
6436 my ($varname, $value) = ($m->text(1), $m->text(3)); 6436 my ($varname, $value) = ($m->text(1), $m->text(3));
6437 my $do_check = false; 6437 my $do_check = false;
6438 6438
6439 if ($varname eq "BUILDLINK_ABI_DEPENDS.${bl_pkgbase}") { 6439 if ($varname eq "BUILDLINK_ABI_DEPENDS.${bl_pkgbase}") {
6440 $abi_line = $line; 6440 $abi_line = $line;
6441 if ($value =~ regex_dependency_gt) { 6441 if ($value =~ regex_dependency_gt) {
6442 ($abi_pkg, $abi_version) = ($1, $2); 6442 ($abi_pkg, $abi_version) = ($1, $2);
6443 } elsif ($value =~ regex_dependency_wildcard) { 6443 } elsif ($value =~ regex_dependency_wildcard) {
6444 ($abi_pkg) = ($1); 6444 ($abi_pkg) = ($1);
6445 } else { 6445 } else {
6446 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); 6446 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\".");
6447 } 6447 }
6448 $do_check = true; 6448 $do_check = true;
6449 } 6449 }
6450 if ($varname eq "BUILDLINK_API_DEPENDS.${bl_pkgbase}") { 6450 if ($varname eq "BUILDLINK_API_DEPENDS.${bl_pkgbase}") {
6451 $api_line = $line; 6451 $api_line = $line;
6452 if ($value =~ regex_dependency_gt) { 6452 if ($value =~ regex_dependency_gt) {
6453 ($api_pkg, $api_version) = ($1, $2); 6453 ($api_pkg, $api_version) = ($1, $2);
6454 } elsif ($value =~ regex_dependency_wildcard) { 6454 } elsif ($value =~ regex_dependency_wildcard) {
6455 ($api_pkg) = ($1); 6455 ($api_pkg) = ($1);
6456 } else { 6456 } else {
6457 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); 6457 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\".");
6458 } 6458 }
6459 $do_check = true; 6459 $do_check = true;
6460 } 6460 }
6461 if ($do_check && defined($abi_pkg) && defined($api_pkg)) { 6461 if ($do_check && defined($abi_pkg) && defined($api_pkg)) {
6462 if ($abi_pkg ne $api_pkg) { 6462 if ($abi_pkg ne $api_pkg) {
6463 $abi_line->log_warning("Package name mismatch between ${abi_pkg} ..."); 6463 $abi_line->log_warning("Package name mismatch between ${abi_pkg} ...");
6464 $api_line->log_warning("... and ${api_pkg}."); 6464 $api_line->log_warning("... and ${api_pkg}.");
6465 } 6465 }
6466 } 6466 }
6467 if ($do_check && defined($abi_version) && defined($api_version)) { 6467 if ($do_check && defined($abi_version) && defined($api_version)) {
6468 if (!dewey_cmp($abi_version, ">=", $api_version)) { 6468 if (!dewey_cmp($abi_version, ">=", $api_version)) {
6469 $abi_line->log_warning("ABI version (${abi_version}) should be at least ..."); 6469 $abi_line->log_warning("ABI version (${abi_version}) should be at least ...");
6470 $api_line->log_warning("... API version (${api_version})."); 6470 $api_line->log_warning("... API version (${api_version}).");
6471 } 6471 }
6472 } 6472 }
6473 6473
6474 if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") { 6474 if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") {
6475 my ($varparam) = ($1); 6475 my ($varparam) = ($1);
6476 6476
6477 if ($varparam ne $bl_pkgbase) { 6477 if ($varparam ne $bl_pkgbase) {
6478 $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file."); 6478 $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file.");
6479 } 6479 }
6480 } 6480 }
6481 6481
6482 # TODO: More checks. 6482 # TODO: More checks.
6483 6483
6484 } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) { 6484 } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) {
6485 # Comments and empty lines are fine here. 6485 # Comments and empty lines are fine here.
6486 6486
6487 } else { 6487 } else {
6488 $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in fourth paragraph."); 6488 $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in fourth paragraph.");
6489 $lineno++; 6489 $lineno++;
6490 } 6490 }
6491 } 6491 }
6492 if (!defined($api_line)) { 6492 if (!defined($api_line)) {
6493 $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing."); 6493 $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing.");
6494 } 6494 }
6495 expect_empty_line($lines, \$lineno); 6495 expect_empty_line($lines, \$lineno);
6496 6496
6497 # Before the fifth paragraph, it may be necessary to resolve the build 6497 # Before the fifth paragraph, it may be necessary to resolve the build
6498 # options of other packages. 6498 # options of other packages.
6499 if (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")) { 6499 if (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")) {
6500 do { 6500 do {
6501 expect_text($lines, \$lineno, ".include \"../../mk/pkg-build-options.mk\""); 6501 expect_text($lines, \$lineno, ".include \"../../mk/pkg-build-options.mk\"");
6502 } while (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")); 6502 } while (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$"));
6503 expect_empty_line($lines, \$lineno); 6503 expect_empty_line($lines, \$lineno);
6504 } 6504 }
6505 6505
6506 # Fifth paragraph (optional): Dependencies. 6506 # Fifth paragraph (optional): Dependencies.
6507 my $have_dependencies = false; 6507 my $have_dependencies = false;
6508 my $need_empty_line = false; 6508 my $need_empty_line = false;
6509 while (true) { 6509 while (true) {
6510 if (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$") 6510 if (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$")
6511 || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$") 6511 || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$")
6512 || expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$") 6512 || expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$")
6513 || expect($lines, \$lineno, qr"^\.endif$")) { 6513 || expect($lines, \$lineno, qr"^\.endif$")) {
6514 $have_dependencies = true; 6514 $have_dependencies = true;
6515 $need_empty_line = true; 6515 $need_empty_line = true;
6516 } elsif ($have_dependencies && expect($lines, \$lineno, qr"^$")) { 6516 } elsif ($have_dependencies && expect($lines, \$lineno, qr"^$")) {
6517 $need_empty_line = false; 6517 $need_empty_line = false;
6518 } else { 6518 } else {
6519 last; 6519 last;
6520 } 6520 }
6521 } 6521 }
6522 if ($need_empty_line) { 6522 if ($need_empty_line) {
6523 expect_empty_line($lines, \$lineno); 6523 expect_empty_line($lines, \$lineno);
6524 } 6524 }
6525 6525
6526 # Sixth paragraph: Reference counter. 6526 # Sixth paragraph: Reference counter.
6527 if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH:S/\+\$//\}$")) { 6527 if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH:S/\+\$//\}$")) {
6528 lines_log_warning($lines, $lineno, "Expected BUILDLINK_DEPTH:= \${BUILDLINK_DEPTH:S/+\$//}."); 6528 lines_log_warning($lines, $lineno, "Expected BUILDLINK_DEPTH:= \${BUILDLINK_DEPTH:S/+\$//}.");
6529 explain_warning($lines, $lineno, 6529 explain_warning($lines, $lineno,
6530 "Everything besides the .include lines for the buildlink3.mk files of", 6530 "Everything besides the .include lines for the buildlink3.mk files of",
6531 "dependencies should go between the .if !empty({PKGNAME}_BUILDLINK3_MK)", 6531 "dependencies should go between the .if !empty({PKGNAME}_BUILDLINK3_MK)",
6532 "and the corresponding .endif."); 6532 "and the corresponding .endif.");
6533 return; 6533 return;
6534 } 6534 }
6535 6535
6536 if ($lineno <= $#{$lines}) { 6536 if ($lineno <= $#{$lines}) {
6537 $lines->[$lineno]->log_warning("The file should end here."); 6537 $lines->[$lineno]->log_warning("The file should end here.");
6538 } 6538 }
6539 6539
6540 checklines_buildlink3_inclusion($lines); 6540 checklines_buildlink3_inclusion($lines);
6541} 6541}
6542 6542
6543# This code is copy-pasted from checklines_buildlink3_mk_pre2009, which 6543# This code is copy-pasted from checklines_buildlink3_mk_pre2009, which
6544# will disappear after branching 2010Q1. 6544# will disappear after branching 2010Q1.
6545# 6545#
6546# In 2009, the format of the buildlink3.mk files has been revised to 6546# In 2009, the format of the buildlink3.mk files has been revised to
6547# improve the speed of pkgsrc. As a result, the file format has improved 6547# improve the speed of pkgsrc. As a result, the file format has improved
6548# in legibility and size. 6548# in legibility and size.
6549sub checklines_buildlink3_mk_2009($$$) { 6549sub checklines_buildlink3_mk_2009($$$) {
6550 my ($lines, $lineno, $pkgid) = @_; 6550 my ($lines, $lineno, $pkgid) = @_;
6551 my ($m); 6551 my ($m);
6552 my ($bl_PKGBASE_line, $bl_PKGBASE); 6552 my ($bl_PKGBASE_line, $bl_PKGBASE);
6553 my ($bl_pkgbase_line, $bl_pkgbase); 6553 my ($bl_pkgbase_line, $bl_pkgbase);
6554 my ($abi_line, $abi_pkg, $abi_version); 6554 my ($abi_line, $abi_pkg, $abi_version);
6555 my ($api_line, $api_pkg, $api_version); 6555 my ($api_line, $api_pkg, $api_version);
6556 6556
6557 # First paragraph: Introduction of the package identifier 6557 # First paragraph: Introduction of the package identifier
6558 $bl_pkgbase_line = $lines->[$lineno - 1]; 6558 $bl_pkgbase_line = $lines->[$lineno - 1];
6559 $bl_pkgbase = $pkgid; 6559 $bl_pkgbase = $pkgid;
6560 $opt_debug_misc and $bl_pkgbase_line->log_debug("bl_pkgbase=${bl_pkgbase}"); 6560 $opt_debug_misc and $bl_pkgbase_line->log_debug("bl_pkgbase=${bl_pkgbase}");
6561 expect_empty_line($lines, \$lineno); 6561 expect_empty_line($lines, \$lineno);
6562  6562
6563 # Second paragraph: multiple inclusion protection and introduction 6563 # Second paragraph: multiple inclusion protection and introduction
6564 # of the uppercase package identifier. 6564 # of the uppercase package identifier.
6565 return unless ($m = expect_re($lines, \$lineno, qr"^\.if !defined\((\S+)_BUILDLINK3_MK\)$")); 6565 return unless ($m = expect_re($lines, \$lineno, qr"^\.if !defined\((\S+)_BUILDLINK3_MK\)$"));
6566 $bl_PKGBASE_line = $lines->[$lineno - 1]; 6566 $bl_PKGBASE_line = $lines->[$lineno - 1];
6567 $bl_PKGBASE = $m->text(1); 6567 $bl_PKGBASE = $m->text(1);
6568 $opt_debug_misc and $bl_PKGBASE_line->log_debug("bl_PKGBASE=${bl_PKGBASE}"); 6568 $opt_debug_misc and $bl_PKGBASE_line->log_debug("bl_PKGBASE=${bl_PKGBASE}");
6569 expect_re($lines, \$lineno, qr"^\Q$bl_PKGBASE\E_BUILDLINK3_MK:=$"); 6569 expect_re($lines, \$lineno, qr"^\Q$bl_PKGBASE\E_BUILDLINK3_MK:=$");
6570 expect_empty_line($lines, \$lineno); 6570 expect_empty_line($lines, \$lineno);
6571 6571
6572 my $norm_bl_pkgbase = $bl_pkgbase; 6572 my $norm_bl_pkgbase = $bl_pkgbase;
6573 $norm_bl_pkgbase =~ s/-/_/g; 6573 $norm_bl_pkgbase =~ s/-/_/g;
6574 $norm_bl_pkgbase = uc($norm_bl_pkgbase); 6574 $norm_bl_pkgbase = uc($norm_bl_pkgbase);
6575 if ($norm_bl_pkgbase ne $bl_PKGBASE) { 6575 if ($norm_bl_pkgbase ne $bl_PKGBASE) {
6576 $bl_PKGBASE_line->log_error("Package name mismatch between ${bl_PKGBASE} ..."); 6576 $bl_PKGBASE_line->log_error("Package name mismatch between ${bl_PKGBASE} ...");
6577 $bl_pkgbase_line->log_error("... and ${bl_pkgbase}."); 6577 $bl_pkgbase_line->log_error("... and ${bl_pkgbase}.");
6578 } 6578 }
6579 if (defined($effective_pkgbase) && $effective_pkgbase ne $bl_pkgbase) { 6579 if (defined($effective_pkgbase) && $effective_pkgbase ne $bl_pkgbase) {
6580 $bl_pkgbase_line->log_error("Package name mismatch between ${bl_pkgbase} ..."); 6580 $bl_pkgbase_line->log_error("Package name mismatch between ${bl_pkgbase} ...");
6581 $effective_pkgname_line->log_error("... and ${effective_pkgbase}."); 6581 $effective_pkgname_line->log_error("... and ${effective_pkgbase}.");
6582 } 6582 }
6583 6583
6584 # Third paragraph: Package information. 6584 # Third paragraph: Package information.
6585 my $if_level = 1; # the first .if is from the second paragraph. 6585 my $if_level = 1; # the first .if is from the second paragraph.
6586 while (true) { 6586 while (true) {
6587 6587
6588 if ($lineno > $#{$lines}) { 6588 if ($lineno > $#{$lines}) {
6589 lines_log_warning($lines, $lineno, "Expected .endif"); 6589 lines_log_warning($lines, $lineno, "Expected .endif");
6590 return; 6590 return;
6591 } 6591 }
6592 6592
6593 my $line = $lines->[$lineno]; 6593 my $line = $lines->[$lineno];
6594 6594
6595 if (($m = expect($lines, \$lineno, regex_varassign))) { 6595 if (($m = expect($lines, \$lineno, regex_varassign))) {
6596 my ($varname, $value) = ($m->text(1), $m->text(3)); 6596 my ($varname, $value) = ($m->text(1), $m->text(3));
6597 my $do_check = false; 6597 my $do_check = false;
6598 6598
6599 if ($varname eq "BUILDLINK_ABI_DEPENDS.${bl_pkgbase}") { 6599 if ($varname eq "BUILDLINK_ABI_DEPENDS.${bl_pkgbase}") {
6600 $abi_line = $line; 6600 $abi_line = $line;
6601 if ($value =~ regex_dependency_gt) { 6601 if ($value =~ regex_dependency_gt) {
6602 ($abi_pkg, $abi_version) = ($1, $2); 6602 ($abi_pkg, $abi_version) = ($1, $2);
6603 } elsif ($value =~ regex_dependency_wildcard) { 6603 } elsif ($value =~ regex_dependency_wildcard) {
6604 ($abi_pkg) = ($1); 6604 ($abi_pkg) = ($1);
6605 } else { 6605 } else {
6606 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); 6606 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\".");
6607 } 6607 }
6608 $do_check = true; 6608 $do_check = true;
6609 } 6609 }
6610 if ($varname eq "BUILDLINK_API_DEPENDS.${bl_pkgbase}") { 6610 if ($varname eq "BUILDLINK_API_DEPENDS.${bl_pkgbase}") {
6611 $api_line = $line; 6611 $api_line = $line;
6612 if ($value =~ regex_dependency_gt) { 6612 if ($value =~ regex_dependency_gt) {
6613 ($api_pkg, $api_version) = ($1, $2); 6613 ($api_pkg, $api_version) = ($1, $2);
6614 } elsif ($value =~ regex_dependency_wildcard) { 6614 } elsif ($value =~ regex_dependency_wildcard) {
6615 ($api_pkg) = ($1); 6615 ($api_pkg) = ($1);
6616 } else { 6616 } else {
6617 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); 6617 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\".");
6618 } 6618 }
6619 $do_check = true; 6619 $do_check = true;
6620 } 6620 }
6621 if ($do_check && defined($abi_pkg) && defined($api_pkg)) { 6621 if ($do_check && defined($abi_pkg) && defined($api_pkg)) {
6622 if ($abi_pkg ne $api_pkg) { 6622 if ($abi_pkg ne $api_pkg) {
6623 $abi_line->log_warning("Package name mismatch between ${abi_pkg} ..."); 6623 $abi_line->log_warning("Package name mismatch between ${abi_pkg} ...");
6624 $api_line->log_warning("... and ${api_pkg}."); 6624 $api_line->log_warning("... and ${api_pkg}.");
6625 } 6625 }
6626 } 6626 }
6627 if ($do_check && defined($abi_version) && defined($api_version)) { 6627 if ($do_check && defined($abi_version) && defined($api_version)) {
6628 if (!dewey_cmp($abi_version, ">=", $api_version)) { 6628 if (!dewey_cmp($abi_version, ">=", $api_version)) {
6629 $abi_line->log_warning("ABI version (${abi_version}) should be at least ..."); 6629 $abi_line->log_warning("ABI version (${abi_version}) should be at least ...");
6630 $api_line->log_warning("... API version (${api_version})."); 6630 $api_line->log_warning("... API version (${api_version}).");
6631 } 6631 }
6632 } 6632 }
6633 6633
6634 if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") { 6634 if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") {
6635 my ($varparam) = ($1); 6635 my ($varparam) = ($1);
6636 6636
6637 if ($varparam ne $bl_pkgbase) { 6637 if ($varparam ne $bl_pkgbase) {
6638 $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file."); 6638 $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file.");
6639 } 6639 }
6640 } 6640 }
6641 6641
6642 if ($varname eq "pkgbase") { 6642 if ($varname eq "pkgbase") {
6643 expect_re($lines, \$lineno, "^\.\s*include \"../../mk/pkg-build-options.mk\"$"); 6643 expect_re($lines, \$lineno, qr"^\.\s*include \"../../mk/pkg-build-options.mk\"$");
6644 } 6644 }
6645 6645
6646 # TODO: More checks. 6646 # TODO: More checks.
6647 6647
6648 } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) { 6648 } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) {
6649 # Comments and empty lines are fine here. 6649 # Comments and empty lines are fine here.
6650 6650
6651 } elsif (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$") 6651 } elsif (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$")
6652 || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$")) { 6652 || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$")) {
6653 # TODO: Maybe check dependency lines. 6653 # TODO: Maybe check dependency lines.
6654 6654
6655 } elsif (expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$")) { 6655 } elsif (expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$")) {
6656 $if_level++; 6656 $if_level++;
6657 6657
6658 } elsif (expect($lines, \$lineno, qr"^\.endif.*$")) { 6658 } elsif (expect($lines, \$lineno, qr"^\.endif.*$")) {
6659 $if_level--; 6659 $if_level--;
6660 last if $if_level == 0; 6660 last if $if_level == 0;
6661 6661
6662 } else { 6662 } else {
6663 $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in third paragraph."); 6663 $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in third paragraph.");
6664 $lineno++; 6664 $lineno++;
6665 } 6665 }
6666 } 6666 }
6667 if (!defined($api_line)) { 6667 if (!defined($api_line)) {
6668 $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing."); 6668 $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing.");
6669 } 6669 }
6670 expect_empty_line($lines, \$lineno); 6670 expect_empty_line($lines, \$lineno);
6671 6671
6672 # Fourth paragraph: Cleanup, corresponding to the first paragraph. 6672 # Fourth paragraph: Cleanup, corresponding to the first paragraph.
6673 return unless expect_re($lines, \$lineno, qr"^BUILDLINK_TREE\+=\s*-\Q$bl_pkgbase\E$"); 6673 return unless expect_re($lines, \$lineno, qr"^BUILDLINK_TREE\+=\s*-\Q$bl_pkgbase\E$");
6674 6674
6675 if ($lineno <= $#{$lines}) { 6675 if ($lineno <= $#{$lines}) {
6676 $lines->[$lineno]->log_warning("The file should end here."); 6676 $lines->[$lineno]->log_warning("The file should end here.");
6677 } 6677 }
6678 6678
6679 checklines_buildlink3_inclusion($lines); 6679 checklines_buildlink3_inclusion($lines);
6680} 6680}
6681 6681
6682sub checkfile_DESCR($) { 6682sub checkfile_DESCR($) {
6683 my ($fname) = @_; 6683 my ($fname) = @_;
6684 my ($maxchars, $maxlines) = (80, 24); 6684 my ($maxchars, $maxlines) = (80, 24);
6685 my ($lines); 6685 my ($lines);
6686 6686
6687 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_DESCR()"); 6687 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_DESCR()");
6688 6688
6689 checkperms($fname); 6689 checkperms($fname);
6690 if (!($lines = load_file($fname))) { 6690 if (!($lines = load_file($fname))) {
6691 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6691 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6692 return; 6692 return;
6693 } 6693 }
6694 if (@{$lines} == 0) { 6694 if (@{$lines} == 0) {
6695 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 6695 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
6696 return; 6696 return;
6697 } 6697 }
6698 6698
6699 foreach my $line (@{$lines}) { 6699 foreach my $line (@{$lines}) {
6700 checkline_length($line, $maxchars); 6700 checkline_length($line, $maxchars);
6701 checkline_trailing_whitespace($line); 6701 checkline_trailing_whitespace($line);
6702 checkline_valid_characters($line, regex_validchars); 6702 checkline_valid_characters($line, regex_validchars);
6703 checkline_spellcheck($line); 6703 checkline_spellcheck($line);
6704 if ($line->text =~ m"\$\{") { 6704 if ($line->text =~ m"\$\{") {
6705 $line->log_warning("Variables are not expanded in the DESCR file."); 6705 $line->log_warning("Variables are not expanded in the DESCR file.");
6706 } 6706 }
6707 } 6707 }
6708 checklines_trailing_empty_lines($lines); 6708 checklines_trailing_empty_lines($lines);
6709 6709
6710 if (@{$lines} > $maxlines) { 6710 if (@{$lines} > $maxlines) {
6711 my $line = $lines->[$maxlines]; 6711 my $line = $lines->[$maxlines];
6712 6712
6713 $line->log_warning("File too long (should be no more than $maxlines lines)."); 6713 $line->log_warning("File too long (should be no more than $maxlines lines).");
6714 $line->explain_warning( 6714 $line->explain_warning(
6715"A common terminal size is 80x25 characters. The DESCR file should", 6715"A common terminal size is 80x25 characters. The DESCR file should",
6716"fit on one screen. It is also intended to give a _brief_ summary", 6716"fit on one screen. It is also intended to give a _brief_ summary",
6717"about the package's contents."); 6717"about the package's contents.");
6718 } 6718 }
6719 autofix($lines); 6719 autofix($lines);
6720} 6720}
6721 6721
6722sub checkfile_distinfo($) { 6722sub checkfile_distinfo($) {
6723 my ($fname) = @_; 6723 my ($fname) = @_;
6724 my ($lines, %in_distinfo, $current_fname, $state, $patches_dir); 6724 my ($lines, %in_distinfo, $current_fname, $state, $patches_dir);
6725 my ($di_is_committed); 6725 my ($di_is_committed);
6726 6726
6727 use enum qw(:DIS_ start=0 SHA1=0 RMD160 Size); 6727 use enum qw(:DIS_ start=0 SHA1=0 RMD160 Size);
6728 6728
6729 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_distinfo()"); 6729 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_distinfo()");
6730 6730
6731 $di_is_committed = is_committed($fname); 6731 $di_is_committed = is_committed($fname);
6732 6732
6733 checkperms($fname); 6733 checkperms($fname);
6734 if (!($lines = load_file($fname))) { 6734 if (!($lines = load_file($fname))) {
6735 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6735 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6736 return; 6736 return;
6737 } 6737 }
6738 6738
6739 if (@{$lines} == 0) { 6739 if (@{$lines} == 0) {
6740 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 6740 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
6741 return; 6741 return;
6742 } 6742 }
6743 6743
6744 checkline_rcsid($lines->[0], ""); 6744 checkline_rcsid($lines->[0], "");
6745 if (1 <= $#{$lines} && $lines->[1]->text ne "") { 6745 if (1 <= $#{$lines} && $lines->[1]->text ne "") {
6746 $lines->[1]->log_note("Empty line expected."); 6746 $lines->[1]->log_note("Empty line expected.");
6747 $lines->[1]->explain_note("This is merely for aesthetical purposes."); 6747 $lines->[1]->explain_note("This is merely for aesthetical purposes.");
6748 } 6748 }
6749 6749
6750 $patches_dir = $patchdir; 6750 $patches_dir = $patchdir;
6751 if (!defined($patches_dir) && -d "${current_dir}/patches") { 6751 if (!defined($patches_dir) && -d "${current_dir}/patches") {
6752 $patches_dir = "patches"; 6752 $patches_dir = "patches";
6753 } else { 6753 } else {
6754 # it stays undefined. 6754 # it stays undefined.
6755 } 6755 }
6756 6756
6757 $current_fname = undef; 6757 $current_fname = undef;
6758 $state = DIS_start; 6758 $state = DIS_start;
6759 foreach my $line (@{$lines}[2..$#{$lines}]) { 6759 foreach my $line (@{$lines}[2..$#{$lines}]) {
6760 if ($line->text !~ m"^(\w+) \(([^)]+)\) = (.*)(?: bytes)?$") { 6760 if ($line->text !~ m"^(\w+) \(([^)]+)\) = (.*)(?: bytes)?$") {
6761 $line->log_error("Unknown line type."); 6761 $line->log_error("Unknown line type.");
6762 next; 6762 next;
6763 } 6763 }
6764 my ($alg, $chksum_fname, $sum) = ($1, $2, $3); 6764 my ($alg, $chksum_fname, $sum) = ($1, $2, $3);
6765 my $is_patch = (($chksum_fname =~ m"^patch-[A-Za-z0-9]+$") ? true : false); 6765 my $is_patch = (($chksum_fname =~ m"^patch-[A-Za-z0-9]+$") ? true : false);
6766 6766
6767 if ($chksum_fname !~ m"^\w") { 6767 if ($chksum_fname !~ m"^\w") {
6768 $line->log_error("All file names should start with a letter."); 6768 $line->log_error("All file names should start with a letter.");
6769 } 6769 }
6770 6770
6771 # Inter-package check for differing distfile checksums. 6771 # Inter-package check for differing distfile checksums.
6772 if ($opt_check_global && !$is_patch) { 6772 if ($opt_check_global && !$is_patch) {
6773 # Note: Perl-specific auto-population. 6773 # Note: Perl-specific auto-population.
6774 if (exists($ipc_distinfo->{$alg}->{$chksum_fname})) { 6774 if (exists($ipc_distinfo->{$alg}->{$chksum_fname})) {
6775 my $other = $ipc_distinfo->{$alg}->{$chksum_fname}; 6775 my $other = $ipc_distinfo->{$alg}->{$chksum_fname};
6776 6776
6777 if ($other->[1] eq $sum) { 6777 if ($other->[1] eq $sum) {
6778 # Fine. 6778 # Fine.
6779 } else { 6779 } else {
6780 $line->log_error("The ${alg} checksum for ${chksum_fname} differs ..."); 6780 $line->log_error("The ${alg} checksum for ${chksum_fname} differs ...");
6781 $other->[0]->log_error("... from this one."); 6781 $other->[0]->log_error("... from this one.");
6782 } 6782 }
6783 } else { 6783 } else {
6784 $ipc_distinfo->{$alg}->{$chksum_fname} = [$line, $sum]; 6784 $ipc_distinfo->{$alg}->{$chksum_fname} = [$line, $sum];
6785 } 6785 }
6786 } 6786 }
6787 6787
6788 if ($alg eq "MD5") { 6788 if ($alg eq "MD5") {
6789 $line->log_error("MD5 checksums are obsolete."); 6789 $line->log_error("MD5 checksums are obsolete.");
6790 $line->explain_error( 6790 $line->explain_error(
6791"Run \"".conf_make." makedistinfo\" to regenerate the distinfo file."); 6791"Run \"".conf_make." makedistinfo\" to regenerate the distinfo file.");
6792 next; 6792 next;
6793 } 6793 }
6794 6794
6795 if ($state == DIS_SHA1) { 6795 if ($state == DIS_SHA1) {
6796 if ($alg eq "SHA1") { 6796 if ($alg eq "SHA1") {
6797 $state = ($is_patch ? DIS_start : DIS_RMD160); 6797 $state = ($is_patch ? DIS_start : DIS_RMD160);
6798 $current_fname = $chksum_fname; 6798 $current_fname = $chksum_fname;
6799 } else { 6799 } else {
6800 $line->log_warning("Expected an SHA1 checksum."); 6800 $line->log_warning("Expected an SHA1 checksum.");
6801 } 6801 }
6802 6802
6803 } elsif ($state == DIS_RMD160) { 6803 } elsif ($state == DIS_RMD160) {
6804 $state = DIS_start; 6804 $state = DIS_start;
6805 if ($alg eq "RMD160") { 6805 if ($alg eq "RMD160") {
6806 if ($chksum_fname eq $current_fname) { 6806 if ($chksum_fname eq $current_fname) {
6807 $state = DIS_Size; 6807 $state = DIS_Size;
6808 } else { 6808 } else {
6809 $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not for ${chksum_fname}."); 6809 $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not for ${chksum_fname}.");
6810 } 6810 }
6811 } else { 6811 } else {
6812 if ($chksum_fname eq $current_fname) { 6812 if ($chksum_fname eq $current_fname) {
6813 # This is an error because this really should be fixed. 6813 # This is an error because this really should be fixed.
6814 $line->log_error("Expected an RMD160 checksum, not ${alg} for ${chksum_fname}."); 6814 $line->log_error("Expected an RMD160 checksum, not ${alg} for ${chksum_fname}.");
6815 } else { 6815 } else {
6816 $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); 6816 $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not ${alg} for ${chksum_fname}.");
6817 } 6817 }
6818 } 6818 }
6819 6819
6820 } elsif ($state == DIS_Size) { 6820 } elsif ($state == DIS_Size) {
6821 $state = DIS_start; 6821 $state = DIS_start;
6822 if ($alg eq "Size") { 6822 if ($alg eq "Size") {
6823 if ($chksum_fname ne $current_fname) { 6823 if ($chksum_fname ne $current_fname) {
6824 $line->log_warning("Expected a Size checksum for ${current_fname}, not for ${chksum_fname}."); 6824 $line->log_warning("Expected a Size checksum for ${current_fname}, not for ${chksum_fname}.");
6825 } 6825 }
6826 } else { 6826 } else {
6827 if ($chksum_fname eq $current_fname) { 6827 if ($chksum_fname eq $current_fname) {
6828 $line->log_warning("Expected a Size checksum, not ${alg} for ${chksum_fname}."); 6828 $line->log_warning("Expected a Size checksum, not ${alg} for ${chksum_fname}.");
6829 } else { 6829 } else {
6830 $line->log_warning("Expected a Size checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); 6830 $line->log_warning("Expected a Size checksum for ${current_fname}, not ${alg} for ${chksum_fname}.");
6831 } 6831 }
6832 } 6832 }
6833 } 6833 }
6834 6834
6835 if ($is_patch && defined($patches_dir) && !(defined($distinfo_file) && $distinfo_file eq "./../../lang/php5/distinfo")) { 6835 if ($is_patch && defined($patches_dir) && !(defined($distinfo_file) && $distinfo_file eq "./../../lang/php5/distinfo")) {
6836 my $fname = "${current_dir}/${patches_dir}/${chksum_fname}"; 6836 my $fname = "${current_dir}/${patches_dir}/${chksum_fname}";
6837 if ($di_is_committed && !is_committed($fname)) { 6837 if ($di_is_committed && !is_committed($fname)) {
6838 $line->log_warning("${patches_dir}/${chksum_fname} is registered in distinfo but not added to CVS."); 6838 $line->log_warning("${patches_dir}/${chksum_fname} is registered in distinfo but not added to CVS.");
6839 } 6839 }
6840 6840
6841 if (open(PATCH, "<", $fname)) { 6841 if (open(PATCH, "<", $fname)) {
6842 my $data = ""; 6842 my $data = "";
6843 foreach my $patchline (<PATCH>) { 6843 foreach my $patchline (<PATCH>) {
6844 $data .= $patchline unless $patchline =~ m"\$[N]etBSD"; 6844 $data .= $patchline unless $patchline =~ m"\$[N]etBSD";
6845 } 6845 }
6846 close(PATCH); 6846 close(PATCH);
6847 my $chksum = Digest::SHA1::sha1_hex($data); 6847 my $chksum = Digest::SHA1::sha1_hex($data);
6848 if ($sum ne $chksum) { 6848 if ($sum ne $chksum) {
6849 $line->log_error("${alg} checksum of ${chksum_fname} differs (expected ${sum}, got ${chksum}). Rerun '".conf_make." makepatchsum'."); 6849 $line->log_error("${alg} checksum of ${chksum_fname} differs (expected ${sum}, got ${chksum}). Rerun '".conf_make." makepatchsum'.");
6850 } 6850 }
6851 } elsif (true) { 6851 } elsif (true) {
6852 $line->log_warning("${chksum_fname} does not exist."); 6852 $line->log_warning("${chksum_fname} does not exist.");
6853 $line->explain_warning( 6853 $line->explain_warning(
6854"All patches that are mentioned in a distinfo file should actually exist.", 6854"All patches that are mentioned in a distinfo file should actually exist.",
6855"What's the use of a checksum if there is no file to check?"); 6855"What's the use of a checksum if there is no file to check?");
6856 } 6856 }
6857 } 6857 }
6858 $in_distinfo{$chksum_fname} = true; 6858 $in_distinfo{$chksum_fname} = true;
6859 } 6859 }
6860 checklines_trailing_empty_lines($lines); 6860 checklines_trailing_empty_lines($lines);
6861 6861
6862 if (defined($patches_dir)) { 6862 if (defined($patches_dir)) {
6863 foreach my $patch (<${current_dir}/${patches_dir}/patch-*>) { 6863 foreach my $patch (<${current_dir}/${patches_dir}/patch-*>) {
6864 $patch = basename($patch); 6864 $patch = basename($patch);
6865 if (!exists($in_distinfo{$patch})) { 6865 if (!exists($in_distinfo{$patch})) {
6866 log_error($fname, NO_LINE_NUMBER, "$patch is not recorded. Rerun '".conf_make." makepatchsum'."); 6866 log_error($fname, NO_LINE_NUMBER, "$patch is not recorded. Rerun '".conf_make." makepatchsum'.");
6867 } 6867 }
6868 } 6868 }
6869 } 6869 }
6870} 6870}
6871 6871
6872sub checkfile_extra($) { 6872sub checkfile_extra($) {
6873 my ($fname) = @_; 6873 my ($fname) = @_;
6874 my ($lines); 6874 my ($lines);
6875 6875
6876 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_extra()"); 6876 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_extra()");
6877 6877
6878 $lines = load_file($fname); 6878 $lines = load_file($fname);
6879 if (!$lines) { 6879 if (!$lines) {
6880 log_error($fname, NO_LINE_NUMBER, "Could not be read."); 6880 log_error($fname, NO_LINE_NUMBER, "Could not be read.");
6881 return; 6881 return;
6882 } 6882 }
6883 checklines_trailing_empty_lines($lines); 6883 checklines_trailing_empty_lines($lines);
6884 checkperms($fname); 6884 checkperms($fname);
6885} 6885}
6886 6886
6887sub checkfile_INSTALL($) { 6887sub checkfile_INSTALL($) {
6888 my ($fname) = @_; 6888 my ($fname) = @_;
6889 my ($lines); 6889 my ($lines);
6890 6890
6891 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); 6891 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()");
6892 6892
6893 checkperms($fname); 6893 checkperms($fname);
6894 if (!($lines = load_file($fname))) { 6894 if (!($lines = load_file($fname))) {
6895 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6895 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6896 return; 6896 return;
6897 } 6897 }
6898} 6898}
6899 6899
6900sub checkfile_MESSAGE($) { 6900sub checkfile_MESSAGE($) {
6901 my ($fname) = @_; 6901 my ($fname) = @_;
6902 my ($lines); 6902 my ($lines);
6903 6903
6904 my @explanation = ( 6904 my @explanation = (
6905 "A MESSAGE file should consist of a header line, having 75 \"=\"", 6905 "A MESSAGE file should consist of a header line, having 75 \"=\"",
6906 "characters, followed by a line containing only the RCS Id, then an", 6906 "characters, followed by a line containing only the RCS Id, then an",
6907 "empty line, your text and finally the footer line, which is the", 6907 "empty line, your text and finally the footer line, which is the",
6908 "same as the header line."); 6908 "same as the header line.");
6909 6909
6910 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); 6910 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()");
6911 6911
6912 checkperms($fname); 6912 checkperms($fname);
6913 if (!($lines = load_file($fname))) { 6913 if (!($lines = load_file($fname))) {
6914 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6914 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6915 return; 6915 return;
6916 } 6916 }
6917 6917
6918 if (@{$lines} < 3) { 6918 if (@{$lines} < 3) {
6919 log_warning($fname, NO_LINE_NUMBER, "File too short."); 6919 log_warning($fname, NO_LINE_NUMBER, "File too short.");
6920 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6920 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6921 return; 6921 return;
6922 } 6922 }
6923 if ($lines->[0]->text ne "=" x 75) { 6923 if ($lines->[0]->text ne "=" x 75) {
6924 $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); 6924 $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters.");
6925 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6925 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6926 } 6926 }
6927 checkline_rcsid($lines->[1], ""); 6927 checkline_rcsid($lines->[1], "");
6928 foreach my $line (@{$lines}) { 6928 foreach my $line (@{$lines}) {
6929 checkline_length($line, 80); 6929 checkline_length($line, 80);
6930 checkline_trailing_whitespace($line); 6930 checkline_trailing_whitespace($line);
6931 checkline_valid_characters($line, regex_validchars); 6931 checkline_valid_characters($line, regex_validchars);
6932 checkline_spellcheck($line); 6932 checkline_spellcheck($line);
6933 } 6933 }
6934 if ($lines->[-1]->text ne "=" x 75) { 6934 if ($lines->[-1]->text ne "=" x 75) {
6935 $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); 6935 $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters.");
6936 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6936 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6937 } 6937 }
6938 checklines_trailing_empty_lines($lines); 6938 checklines_trailing_empty_lines($lines);
6939} 6939}
6940 6940
6941sub checkfile_mk($) { 6941sub checkfile_mk($) {
6942 my ($fname) = @_; 6942 my ($fname) = @_;
6943 my ($lines); 6943 my ($lines);
6944 6944
6945 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); 6945 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()");
6946 6946
6947 checkperms($fname); 6947 checkperms($fname);
6948 if (!($lines = load_lines($fname, true))) { 6948 if (!($lines = load_lines($fname, true))) {
6949 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6949 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6950 return; 6950 return;
6951 } 6951 }
6952 6952
6953 parselines_mk($lines); 6953 parselines_mk($lines);
6954 checklines_mk($lines); 6954 checklines_mk($lines);
6955 autofix($lines); 6955 autofix($lines);
6956} 6956}
6957 6957
6958sub checkfile_package_Makefile($$) { 6958sub checkfile_package_Makefile($$) {
6959 my ($fname, $lines) = @_; 6959 my ($fname, $lines) = @_;
6960 6960
6961 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); 6961 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)");
6962 6962
6963 checkperms($fname); 6963 checkperms($fname);
6964 6964
6965 if (!exists($pkgctx_vardef->{"PKG_DESTDIR_SUPPORT"}) && !exists($pkgctx_vardef->{"META_PACKAGE"})) { 6965 if (!exists($pkgctx_vardef->{"PKG_DESTDIR_SUPPORT"}) && !exists($pkgctx_vardef->{"META_PACKAGE"})) {
6966 log_warning($fname, NO_LINE_NUMBER, "This package has not set PKG_DESTDIR_SUPPORT."); 6966 log_warning($fname, NO_LINE_NUMBER, "This package has not set PKG_DESTDIR_SUPPORT.");
6967 } 6967 }
6968 6968
6969 if (!exists($pkgctx_vardef->{"PLIST_SRC"}) 6969 if (!exists($pkgctx_vardef->{"PLIST_SRC"})
6970 && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) 6970 && !exists($pkgctx_vardef->{"GENERATE_PLIST"})
6971 && !exists($pkgctx_vardef->{"META_PACKAGE"}) 6971 && !exists($pkgctx_vardef->{"META_PACKAGE"})
6972 && defined($pkgdir) 6972 && defined($pkgdir)
6973 && !-f "${current_dir}/$pkgdir/PLIST" 6973 && !-f "${current_dir}/$pkgdir/PLIST"
6974 && !-f "${current_dir}/$pkgdir/PLIST.common") { 6974 && !-f "${current_dir}/$pkgdir/PLIST.common") {
6975 log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); 6975 log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?");
6976 } 6976 }
6977 6977
6978 if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { 6978 if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) {
6979 if (-f "${current_dir}/${distinfo_file}") { 6979 if (-f "${current_dir}/${distinfo_file}") {
6980 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); 6980 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set.");
6981 } 6981 }
6982 } else { 6982 } else {
6983 if (!-f "${current_dir}/${distinfo_file}") { 6983 if (!-f "${current_dir}/${distinfo_file}") {
6984 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); 6984 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'.");
6985 } 6985 }
6986 } 6986 }
6987 6987
6988 if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { 6988 if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) {
6989 $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); 6989 $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ...");
6990 $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); 6990 $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set.");
6991 } 6991 }
6992 6992
6993 if (exists($pkgctx_vardef->{"RESTRICTED"}) && !exists($pkgctx_vardef->{"LICENSE"})) { 6993 if (exists($pkgctx_vardef->{"RESTRICTED"}) && !exists($pkgctx_vardef->{"LICENSE"})) {
6994 $pkgctx_vardef->{"RESTRICTED"}->log_error("Restricted packages must have a LICENSE."); 6994 $pkgctx_vardef->{"RESTRICTED"}->log_error("Restricted packages must have a LICENSE.");
6995 } 6995 }
6996 6996
6997 if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { 6997 if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) {
6998 my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; 6998 my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"};
6999 my $value = $languages_line->get("value"); 6999 my $value = $languages_line->get("value");
7000 7000
7001 if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { 7001 if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) {
7002 # Don't emit a warning, since the comment 7002 # Don't emit a warning, since the comment
7003 # probably contains a statement that C is 7003 # probably contains a statement that C is
7004 # really not needed. 7004 # really not needed.
7005 7005
7006 } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { 7006 } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") {
7007 $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); 7007 $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ...");
7008 $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); 7008 $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES.");
7009 } 7009 }
7010 } 7010 }
7011 7011
7012 my $distname_line = $pkgctx_vardef->{"DISTNAME"}; 7012 my $distname_line = $pkgctx_vardef->{"DISTNAME"};
7013 my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; 7013 my $pkgname_line = $pkgctx_vardef->{"PKGNAME"};
7014 7014
7015 my $distname = defined($distname_line) ? $distname_line->get("value") : undef; 7015 my $distname = defined($distname_line) ? $distname_line->get("value") : undef;
7016 my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; 7016 my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef;
7017 my $nbpart = get_nbpart(); 7017 my $nbpart = get_nbpart();
7018 7018
7019 # Let's do some tricks to get the proper value of the package 7019 # Let's do some tricks to get the proper value of the package
7020 # name more often. 7020 # name more often.
7021 if (defined($distname) && defined($pkgname)) { 7021 if (defined($distname) && defined($pkgname)) {
7022 $pkgname =~ s/\$\{DISTNAME\}/$distname/; 7022 $pkgname =~ s/\$\{DISTNAME\}/$distname/;
7023 7023
7024 if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { 7024 if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") {
7025 my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); 7025 my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6);
7026 my $newname = $distname; 7026 my $newname = $distname;
7027 $old = quotemeta($old); 7027 $old = quotemeta($old);
7028 $old =~ s/^\\\^/^/; 7028 $old =~ s/^\\\^/^/;
7029 $old =~ s/\\\$$/\$/; 7029 $old =~ s/\\\$$/\$/;
7030 if ($mod eq "g") { 7030 if ($mod eq "g") {
7031 $newname =~ s/$old/$new/g; 7031 $newname =~ s/$old/$new/g;
7032 } else { 7032 } else {
7033 $newname =~ s/$old/$new/; 7033 $newname =~ s/$old/$new/;
7034 } 7034 }
7035 $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); 7035 $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname");
7036 $pkgname = $before . $newname . $after; 7036 $pkgname = $before . $newname . $after;
7037 $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); 7037 $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname");
7038 } 7038 }
7039 } 7039 }
7040 7040
7041 if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { 7041 if (defined($pkgname) && defined($distname) && $pkgname eq $distname) {
7042 $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); 7042 $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME.");
7043 } 7043 }
7044 7044
7045 if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { 7045 if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) {
7046 $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); 7046 $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly.");
7047 } 7047 }
7048 7048
7049 ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) 7049 ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion)
7050 = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) 7050 = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2)
7051 : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) 7051 : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2)
7052 : (undef, undef, undef, undef); 7052 : (undef, undef, undef, undef);
7053 if (defined($effective_pkgname_line)) { 7053 if (defined($effective_pkgname_line)) {
7054 $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); 7054 $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}.");
7055 # XXX: too many false positives 7055 # XXX: too many false positives
7056 if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) { 7056 if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) {
7057 $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1)."); 7057 $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1).");
7058 } 7058 }
7059 } 7059 }
7060 7060
7061 checkpackage_possible_downgrade(); 7061 checkpackage_possible_downgrade();
7062 7062
7063 if (!exists($pkgctx_vardef->{"COMMENT"})) { 7063 if (!exists($pkgctx_vardef->{"COMMENT"})) {
7064 log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); 7064 log_warning($fname, NO_LINE_NUMBER, "No COMMENT given.");
7065 } 7065 }
7066 7066
7067 if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { 7067 if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) {
7068 $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); 7068 $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ...");
7069 $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); 7069 $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous.");
7070 } 7070 }
7071 7071
7072 if (defined($effective_pkgbase)) { 7072 if (defined($effective_pkgbase)) {
7073 7073
7074 foreach my $suggested_update (@{get_suggested_package_updates()}) { 7074 foreach my $suggested_update (@{get_suggested_package_updates()}) {
7075 my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; 7075 my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update};
7076 my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); 7076 my $comment = (defined($suggcomm) ? " (${suggcomm})" : "");
7077 7077
7078 next unless $effective_pkgbase eq $suggbase; 7078 next unless $effective_pkgbase eq $suggbase;
7079 7079
7080 if (dewey_cmp($effective_pkgversion, "<", $suggver)) { 7080 if (dewey_cmp($effective_pkgversion, "<", $suggver)) {
7081 $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); 7081 $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}.");
7082 } 7082 }
7083 if (dewey_cmp($effective_pkgversion, "==", $suggver)) { 7083 if (dewey_cmp($effective_pkgversion, "==", $suggver)) {
7084 $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); 7084 $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done.");
7085 } 7085 }
7086 if (dewey_cmp($effective_pkgversion, ">", $suggver)) { 7086 if (dewey_cmp($effective_pkgversion, ">", $suggver)) {
7087 $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); 7087 $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}.");
7088 } 7088 }
7089 } 7089 }
7090 } 7090 }
7091 7091
7092 checklines_mk($lines); 7092 checklines_mk($lines);
7093 checklines_package_Makefile_varorder($lines); 7093 checklines_package_Makefile_varorder($lines);
7094 autofix($lines); 7094 autofix($lines);
7095} 7095}
7096 7096
7097sub checkfile_patch($) { 7097sub checkfile_patch($) {
7098 my ($fname) = @_; 7098 my ($fname) = @_;
7099 my ($lines); 7099 my ($lines);
7100 my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); 7100 my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks);
7101 my ($seen_comment, $current_fname, $current_ftype, $patched_files); 7101 my ($seen_comment, $current_fname, $current_ftype, $patched_files);
7102 my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); 7102 my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading);
7103 7103
7104 # Abbreviations used: 7104 # Abbreviations used:
7105 # style: [c] = context diff, [u] = unified diff 7105 # style: [c] = context diff, [u] = unified diff
7106 # scope: [f] = file, [h] = hunk, [l] = line 7106 # scope: [f] = file, [h] = hunk, [l] = line
7107 # action: [d] = delete, [m] = modify, [a] = add, [c] = context 7107 # action: [d] = delete, [m] = modify, [a] = add, [c] = context
7108 use constant re_patch_rcsid => qr"^\$.*\$$"; 7108 use constant re_patch_rcsid => qr"^\$.*\$$";
7109 use constant re_patch_text => qr"^(.+)$"; 7109 use constant re_patch_text => qr"^(.+)$";
7110 use constant re_patch_empty => qr"^$"; 7110 use constant re_patch_empty => qr"^$";
7111 use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; 7111 use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$";
7112 use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; 7112 use constant re_patch_cfa => qr"^---\s(\S+)(.*)$";
7113 use constant re_patch_ch => qr"^\*{15}(.*)$"; 7113 use constant re_patch_ch => qr"^\*{15}(.*)$";
7114 use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; 7114 use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$";
7115 use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; 7115 use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$";
7116 use constant re_patch_cld => qr"^(?:-\s(.*))?$"; 7116 use constant re_patch_cld => qr"^(?:-\s(.*))?$";
7117 use constant re_patch_clm => qr"^(?:!\s(.*))?$"; 7117 use constant re_patch_clm => qr"^(?:!\s(.*))?$";
7118 use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; 7118 use constant re_patch_cla => qr"^(?:\+\s(.*))?$";
7119 use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; 7119 use constant re_patch_clc => qr"^(?:\s\s(.*))?$";
7120 use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; 7120 use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$";
7121 use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; 7121 use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$";
7122 use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; 7122 use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$";
7123 use constant re_patch_uld => qr"^-(.*)$"; 7123 use constant re_patch_uld => qr"^-(.*)$";
7124 use constant re_patch_ula => qr"^\+(.*)$"; 7124 use constant re_patch_ula => qr"^\+(.*)$";
7125 use constant re_patch_ulc => qr"^\s(.*)$"; 7125 use constant re_patch_ulc => qr"^\s(.*)$";
7126 use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; 7126 use constant re_patch_ulnonl => qr"^\\ No newline at end of file$";
7127 7127
7128 use enum qw(:PST_ 7128 use enum qw(:PST_
7129 START CENTER TEXT 7129 START CENTER TEXT
7130 CFA CH CHD CLD0 CLD CLA0 CLA 7130 CFA CH CHD CLD0 CLD CLA0 CLA
7131 UFA UH UL 7131 UFA UH UL
7132 ); 7132 );
7133 7133
7134 my ($line, $m); 7134 my ($line, $m);
7135 7135
7136 my $check_text = sub($) { 7136 my $check_text = sub($) {
7137 my ($text) = @_; 7137 my ($text) = @_;
7138 7138
7139 if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { 7139 if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") {
7140 my ($tag) = ($2); 7140 my ($tag) = ($2);
7141 7141
7142 if ($text =~ re_patch_uh) { 7142 if ($text =~ re_patch_uh) {
7143 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); 7143 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it.");
7144 $line->set_text($1); 7144 $line->set_text($1);
7145 } else { 7145 } else {
7146 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); 7146 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\".");
7147 } 7147 }
7148 } 7148 }
7149 }; 7149 };
7150 7150
7151 my $check_contents = sub() { 7151 my $check_contents = sub() {
7152 7152
7153 if ($m->has(1)) { 7153 if ($m->has(1)) {
7154 $check_text->($m->text(1)); 7154 $check_text->($m->text(1));
7155 } 7155 }
7156 }; 7156 };
7157 7157
7158 my $check_added_contents = sub() { 7158 my $check_added_contents = sub() {
7159 my $text; 7159 my $text;
7160 7160
7161 return unless $m->has(1); 7161 return unless $m->has(1);
7162 $text = $m->text(1); 7162 $text = $m->text(1);
7163 checkline_cpp_macro_names($line, $text); 7163 checkline_cpp_macro_names($line, $text);
7164 checkline_spellcheck($line); 7164 checkline_spellcheck($line);
7165 7165
7166 # XXX: This check is not as accurate as the similar one in 7166 # XXX: This check is not as accurate as the similar one in
7167 # checkline_mk_shelltext(). 7167 # checkline_mk_shelltext().
7168 if (defined($current_fname)) { 7168 if (defined($current_fname)) {
7169 if ($current_ftype eq "shell" || $current_ftype eq "make") { 7169 if ($current_ftype eq "shell" || $current_ftype eq "make") {
7170 my ($mm, $rest) = match_all($text, $regex_shellword); 7170 my ($mm, $rest) = match_all($text, $regex_shellword);
7171 7171
7172 foreach my $m (@{$mm}) { 7172 foreach my $m (@{$mm}) {
7173 my $shellword = $m->text(1); 7173 my $shellword = $m->text(1);
7174 7174
7175 if ($shellword =~ m"^#") { 7175 if ($shellword =~ m"^#") {
7176 last; 7176 last;
7177 } 7177 }
7178 checkline_mk_absolute_pathname($line, $shellword); 7178 checkline_mk_absolute_pathname($line, $shellword);
7179 } 7179 }
7180 7180
7181 } elsif ($current_ftype eq "source") { 7181 } elsif ($current_ftype eq "source") {
7182 checkline_source_absolute_pathname($line, $text); 7182 checkline_source_absolute_pathname($line, $text);
7183 7183
7184 } elsif ($current_ftype eq "configure") { 7184 } elsif ($current_ftype eq "configure") {
7185 if ($text =~ m": Avoid regenerating within pkgsrc$") { 7185 if ($text =~ m": Avoid regenerating within pkgsrc$") {
7186 $line->log_error("This code must not be included in patches."); 7186 $line->log_error("This code must not be included in patches.");
7187 $line->explain_error( 7187 $line->explain_error(
7188"It is generated automatically by pkgsrc after the patch phase.", 7188"It is generated automatically by pkgsrc after the patch phase.",
7189"", 7189"",
7190"For more details, look for \"configure-scripts-override\" in", 7190"For more details, look for \"configure-scripts-override\" in",
7191"mk/configure/gnu-configure.mk."); 7191"mk/configure/gnu-configure.mk.");
7192 } 7192 }
7193 7193
7194 } elsif ($current_ftype eq "ignore") { 7194 } elsif ($current_ftype eq "ignore") {
7195 # Ignore it. 7195 # Ignore it.
7196 7196
7197 } else { 7197 } else {
7198 checkline_other_absolute_pathname($line, $text); 7198 checkline_other_absolute_pathname($line, $text);
7199 } 7199 }
7200 } 7200 }
7201 }; 7201 };
7202 7202
7203 my $check_hunk_end = sub($$$) { 7203 my $check_hunk_end = sub($$$) {
7204 my ($deldelta, $adddelta, $newstate) = @_; 7204 my ($deldelta, $adddelta, $newstate) = @_;
7205 7205
7206 if ($deldelta > 0 && $dellines == 0) { 7206 if ($deldelta > 0 && $dellines == 0) {
7207 $redostate = $newstate; 7207 $redostate = $newstate;
7208 if (defined($addlines) && $addlines > 0) { 7208 if (defined($addlines) && $addlines > 0) {
7209 $line->log_error("Expected ${addlines} more lines to be added."); 7209 $line->log_error("Expected ${addlines} more lines to be added.");
7210 } 7210 }
7211 } elsif ($adddelta > 0 && $addlines == 0) { 7211 } elsif ($adddelta > 0 && $addlines == 0) {
7212 $redostate = $newstate; 7212 $redostate = $newstate;
7213 if (defined($dellines) && $dellines > 0) { 7213 if (defined($dellines) && $dellines > 0) {
7214 $line->log_error("Expected ${dellines} more lines to be deleted."); 7214 $line->log_error("Expected ${dellines} more lines to be deleted.");
7215 } 7215 }
7216 } else { 7216 } else {
7217 if (defined($context_scanning_leading)) { 7217 if (defined($context_scanning_leading)) {
7218 if ($deldelta != 0 && $adddelta != 0) { 7218 if ($deldelta != 0 && $adddelta != 0) {
7219 if ($context_scanning_leading) { 7219 if ($context_scanning_leading) {
7220 $leading_context_lines++; 7220 $leading_context_lines++;
7221 } else { 7221 } else {
7222 $trailing_context_lines++; 7222 $trailing_context_lines++;
7223 } 7223 }
7224 } else { 7224 } else {
7225 if ($context_scanning_leading) { 7225 if ($context_scanning_leading) {
7226 $context_scanning_leading = false; 7226 $context_scanning_leading = false;
7227 } else { 7227 } else {
7228 $trailing_context_lines = 0; 7228 $trailing_context_lines = 0;
7229 } 7229 }
7230 } 7230 }
7231 } 7231 }
7232 7232
7233 if ($deldelta != 0) { 7233 if ($deldelta != 0) {
7234 $dellines -= $deldelta; 7234 $dellines -= $deldelta;
7235 } 7235 }
7236 if ($adddelta != 0) { 7236 if ($adddelta != 0) {
7237 $addlines -= $adddelta; 7237 $addlines -= $adddelta;
7238 } 7238 }
7239 if (!((defined($dellines) && $dellines > 0) || 7239 if (!((defined($dellines) && $dellines > 0) ||
7240 (defined($addlines) && $addlines > 0))) { 7240 (defined($addlines) && $addlines > 0))) {
7241 if (defined($context_scanning_leading)) { 7241 if (defined($context_scanning_leading)) {
7242 if ($leading_context_lines != $trailing_context_lines) { 7242 if ($leading_context_lines != $trailing_context_lines) {
7243 $opt_debug_patches and $line->log_warning("The hunk that ends here does not have as many leading (${leading_context_lines}) as trailing (${trailing_context_lines}) lines of context."); 7243 $opt_debug_patches and $line->log_warning("The hunk that ends here does not have as many leading (${leading_context_lines}) as trailing (${trailing_context_lines}) lines of context.");
7244 } 7244 }
7245 } 7245 }
7246 $nextstate = $newstate; 7246 $nextstate = $newstate;
7247 } 7247 }
7248 } 7248 }
7249 }; 7249 };
7250 7250
7251 # @param deldelta 7251 # @param deldelta
7252 # The number of lines that are deleted from the patched file. 7252 # The number of lines that are deleted from the patched file.
7253 # @param adddelta 7253 # @param adddelta
7254 # The number of lines that are added to the patched file. 7254 # The number of lines that are added to the patched file.
7255 # @param newstate 7255 # @param newstate
7256 # The follow-up state when this line is the last line to be 7256 # The follow-up state when this line is the last line to be
7257 # added in this hunk of the patch. 7257 # added in this hunk of the patch.
7258 # 7258 #
7259 my $check_hunk_line = sub($$$) { 7259 my $check_hunk_line = sub($$$) {
7260 my ($deldelta, $adddelta, $newstate) = @_; 7260 my ($deldelta, $adddelta, $newstate) = @_;
7261 7261
7262 $check_contents->(); 7262 $check_contents->();
7263 $check_hunk_end->($deldelta, $adddelta, $newstate); 7263 $check_hunk_end->($deldelta, $adddelta, $newstate);
7264 7264
7265 # If -Wextra is given, the context lines are checked for 7265 # If -Wextra is given, the context lines are checked for
7266 # absolute paths and similar things. If it is not given, 7266 # absolute paths and similar things. If it is not given,
7267 # only those lines that really add something to the patched 7267 # only those lines that really add something to the patched
7268 # file are checked. 7268 # file are checked.
7269 if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) { 7269 if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) {
7270 $check_added_contents->(); 7270 $check_added_contents->();
7271 } 7271 }
7272 }; 7272 };
7273 7273
7274 my $transitions = 7274 my $transitions =
7275 # [ from state, regex, to state, action ] 7275 # [ from state, regex, to state, action ]
7276 [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { 7276 [ [PST_START, re_patch_rcsid, PST_CENTER, sub() {
7277 checkline_rcsid($line, ""); 7277 checkline_rcsid($line, "");
7278 }], [PST_START, undef, PST_CENTER, sub() { 7278 }], [PST_START, undef, PST_CENTER, sub() {
7279 checkline_rcsid($line, ""); 7279 checkline_rcsid($line, "");
7280 }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { 7280 }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() {
7281 # 7281 #
7282 }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { 7282 }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() {
7283 if (!$seen_comment) { 7283 if (!$seen_comment) {
7284 $opt_warn_style and $line->log_warning("Comment expected."); 7284 $opt_warn_style and $line->log_warning("Comment expected.");
7285 } 7285 }
7286 $line->log_warning("Please use unified diffs (diff -u) for patches."); 7286 $line->log_warning("Please use unified diffs (diff -u) for patches.");
7287 }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { 7287 }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() {
7288 if (!$seen_comment) { 7288 if (!$seen_comment) {
7289 $opt_warn_style and $line->log_warning("Comment expected."); 7289 $opt_warn_style and $line->log_warning("Comment expected.");
7290 } 7290 }
7291 }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { 7291 }], [PST_TEXT, re_patch_text, PST_TEXT, sub() {
7292 $seen_comment = true; 7292 $seen_comment = true;
7293 }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { 7293 }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() {
7294 # 7294 #
7295 }], [PST_TEXT, undef, PST_TEXT, sub() { 7295 }], [PST_TEXT, undef, PST_TEXT, sub() {
7296 # 7296 #
7297 }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { 7297 }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() {
7298 if ($seen_comment) { 7298 if ($seen_comment) {
7299 $opt_warn_space and $line->log_note("Empty line expected."); 7299 $opt_warn_space and $line->log_note("Empty line expected.");
7300 } else { 7300 } else {
7301 $opt_warn_style and $line->log_warning("Comment expected."); 7301 $opt_warn_style and $line->log_warning("Comment expected.");
7302 } 7302 }
7303 $line->log_warning("Please use unified diffs (diff -u) for patches."); 7303 $line->log_warning("Please use unified diffs (diff -u) for patches.");
7304 }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { 7304 }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() {
7305 if ($seen_comment) { 7305 if ($seen_comment) {
7306 $opt_warn_space and $line->log_note("Empty line expected."); 7306 $opt_warn_space and $line->log_note("Empty line expected.");
7307 } else { 7307 } else {
7308 $opt_warn_style and $line->log_warning("Comment expected."); 7308 $opt_warn_style and $line->log_warning("Comment expected.");
7309 } 7309 }
7310 }], [PST_CENTER, undef, PST_TEXT, sub() { 7310 }], [PST_CENTER, undef, PST_TEXT, sub() {
7311 $opt_warn_space and $line->log_note("Empty line expected."); 7311 $opt_warn_space and $line->log_note("Empty line expected.");
7312 }], [PST_CFA, re_patch_cfa, PST_CH, sub() { 7312 }], [PST_CFA, re_patch_cfa, PST_CH, sub() {
7313 $current_fname = $m->text(1); 7313 $current_fname = $m->text(1);
7314 $current_ftype = get_filetype($line, $current_fname); 7314 $current_ftype = get_filetype($line, $current_fname);
7315 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); 7315 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype");
7316 $patched_files++; 7316 $patched_files++;
7317 $hunks = 0; 7317 $hunks = 0;
7318 }], [PST_CH, re_patch_ch, PST_CHD, sub() { 7318 }], [PST_CH, re_patch_ch, PST_CHD, sub() {
7319 $hunks++; 7319 $hunks++;
7320 }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { 7320 }], [PST_CHD, re_patch_chd, PST_CLD0, sub() {
7321 $dellines = ($m->has(2)) 7321 $dellines = ($m->has(2))
7322 ? (1 + $m->text(2) - $m->text(1)) 7322 ? (1 + $m->text(2) - $m->text(1))
7323 : ($m->text(1)); 7323 : ($m->text(1));
7324 }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { 7324 }], [PST_CLD0, re_patch_clc, PST_CLD, sub() {
7325 $check_hunk_line->(1, 0, PST_CLD0); 7325 $check_hunk_line->(1, 0, PST_CLD0);
7326 }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { 7326 }], [PST_CLD0, re_patch_cld, PST_CLD, sub() {
7327 $check_hunk_line->(1, 0, PST_CLD0); 7327 $check_hunk_line->(1, 0, PST_CLD0);
7328 }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { 7328 }], [PST_CLD0, re_patch_clm, PST_CLD, sub() {
7329 $check_hunk_line->(1, 0, PST_CLD0); 7329 $check_hunk_line->(1, 0, PST_CLD0);
7330 }], [PST_CLD, re_patch_clc, PST_CLD, sub() { 7330 }], [PST_CLD, re_patch_clc, PST_CLD, sub() {
7331 $check_hunk_line->(1, 0, PST_CLD0); 7331 $check_hunk_line->(1, 0, PST_CLD0);
7332 }], [PST_CLD, re_patch_cld, PST_CLD, sub() { 7332 }], [PST_CLD, re_patch_cld, PST_CLD, sub() {
7333 $check_hunk_line->(1, 0, PST_CLD0); 7333 $check_hunk_line->(1, 0, PST_CLD0);
7334 }], [PST_CLD, re_patch_clm, PST_CLD, sub() { 7334 }], [PST_CLD, re_patch_clm, PST_CLD, sub() {
7335 $check_hunk_line->(1, 0, PST_CLD0); 7335 $check_hunk_line->(1, 0, PST_CLD0);
7336 }], [PST_CLD, undef, PST_CLD0, sub() { 7336 }], [PST_CLD, undef, PST_CLD0, sub() {
7337 if ($dellines != 0) { 7337 if ($dellines != 0) {
7338 $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); 7338 $line->log_warning("Invalid number of deleted lines (${dellines} missing).");
7339 } 7339 }
7340 }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { 7340 }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() {
7341 $dellines = undef; 7341 $dellines = undef;
7342 $addlines = ($m->has(2)) 7342 $addlines = ($m->has(2))
7343 ? (1 + $m->text(2) - $m->text(1)) 7343 ? (1 + $m->text(2) - $m->text(1))
7344 : ($m->text(1)); 7344 : ($m->text(1));
7345 }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { 7345 }], [PST_CLA0, re_patch_clc, PST_CLA, sub() {
7346 $check_hunk_line->(0, 1, PST_CH); 7346 $check_hunk_line->(0, 1, PST_CH);
7347 }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { 7347 }], [PST_CLA0, re_patch_clm, PST_CLA, sub() {
7348 $check_hunk_line->(0, 1, PST_CH); 7348 $check_hunk_line->(0, 1, PST_CH);
7349 }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { 7349 }], [PST_CLA0, re_patch_cla, PST_CLA, sub() {
7350 $check_hunk_line->(0, 1, PST_CH); 7350 $check_hunk_line->(0, 1, PST_CH);
7351 }], [PST_CLA, re_patch_clc, PST_CLA, sub() { 7351 }], [PST_CLA, re_patch_clc, PST_CLA, sub() {
7352 $check_hunk_line->(0, 1, PST_CH); 7352 $check_hunk_line->(0, 1, PST_CH);
7353 }], [PST_CLA, re_patch_clm, PST_CLA, sub() { 7353 }], [PST_CLA, re_patch_clm, PST_CLA, sub() {
7354 $check_hunk_line->(0, 1, PST_CH); 7354 $check_hunk_line->(0, 1, PST_CH);
7355 }], [PST_CLA, re_patch_cla, PST_CLA, sub() { 7355 }], [PST_CLA, re_patch_cla, PST_CLA, sub() {
7356 $check_hunk_line->(0, 1, PST_CH); 7356 $check_hunk_line->(0, 1, PST_CH);
7357 }], [PST_CLA, undef, PST_CLA0, sub() { 7357 }], [PST_CLA, undef, PST_CLA0, sub() {
7358 if ($addlines != 0) { 7358 if ($addlines != 0) {
7359 $line->log_warning("Invalid number of added lines (${addlines} missing)."); 7359 $line->log_warning("Invalid number of added lines (${addlines} missing).");
7360 } 7360 }
7361 }], [PST_CLA0, undef, PST_CH, sub() { 7361 }], [PST_CLA0, undef, PST_CH, sub() {
7362 # 7362 #
7363 }], [PST_CH, undef, PST_TEXT, sub() { 7363 }], [PST_CH, undef, PST_TEXT, sub() {
7364 # 7364 #
7365 }], [PST_UFA, re_patch_ufa, PST_UH, sub() { 7365 }], [PST_UFA, re_patch_ufa, PST_UH, sub() {
7366 $current_fname = $m->text(1); 7366 $current_fname = $m->text(1);
7367 $current_ftype = get_filetype($line, $current_fname); 7367 $current_ftype = get_filetype($line, $current_fname);
7368 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); 7368 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype");
7369 $patched_files++; 7369 $patched_files++;
7370 $hunks = 0; 7370 $hunks = 0;
7371 }], [PST_UH, re_patch_uh, PST_UL, sub() { 7371 }], [PST_UH, re_patch_uh, PST_UL, sub() {
7372 $dellines = ($m->has(1) ? $m->text(2) : 1); 7372 $dellines = ($m->has(1) ? $m->text(2) : 1);
7373 $addlines = ($m->has(3) ? $m->text(4) : 1); 7373 $addlines = ($m->has(3) ? $m->text(4) : 1);
7374 $check_text->($line->text); 7374 $check_text->($line->text);
7375 if ($line->text =~ m"\r$") { 7375 if ($line->text =~ m"\r$") {
7376 $line->log_error("The hunk header must not end with a CR character."); 7376 $line->log_error("The hunk header must not end with a CR character.");
7377 $line->explain_error( 7377 $line->explain_error(
7378"The MacOS X patch utility cannot handle these."); 7378"The MacOS X patch utility cannot handle these.");
7379 } 7379 }
7380 $hunks++; 7380 $hunks++;
7381 $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); 7381 $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef);
7382 $leading_context_lines = 0; 7382 $leading_context_lines = 0;
7383 $trailing_context_lines = 0; 7383 $trailing_context_lines = 0;
7384 }], [PST_UL, re_patch_uld, PST_UL, sub() { 7384 }], [PST_UL, re_patch_uld, PST_UL, sub() {
7385 $check_hunk_line->(1, 0, PST_UH); 7385 $check_hunk_line->(1, 0, PST_UH);
7386 }], [PST_UL, re_patch_ula, PST_UL, sub() { 7386 }], [PST_UL, re_patch_ula, PST_UL, sub() {
7387 $check_hunk_line->(0, 1, PST_UH); 7387 $check_hunk_line->(0, 1, PST_UH);
7388 }], [PST_UL, re_patch_ulc, PST_UL, sub() { 7388 }], [PST_UL, re_patch_ulc, PST_UL, sub() {
7389 $check_hunk_line->(1, 1, PST_UH); 7389 $check_hunk_line->(1, 1, PST_UH);
7390 }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { 7390 }], [PST_UL, re_patch_ulnonl, PST_UL, sub() {
7391 # 7391 #
7392 }], [PST_UL, re_patch_empty, PST_UL, sub() { 7392 }], [PST_UL, re_patch_empty, PST_UL, sub() {
7393 $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); 7393 $opt_warn_space and $line->log_note("Leading white-space missing in hunk.");
7394 $check_hunk_line->(1, 1, PST_UH); 7394 $check_hunk_line->(1, 1, PST_UH);
7395 }], [PST_UL, undef, PST_UH, sub() { 7395 }], [PST_UL, undef, PST_UH, sub() {
7396 if ($dellines != 0 || $addlines != 0) { 7396 if ($dellines != 0 || $addlines != 0) {
7397 $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); 7397 $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected).");
7398 } 7398 }
7399 }], [PST_UH, undef, PST_TEXT, sub() { 7399 }], [PST_UH, undef, PST_TEXT, sub() {
7400 ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); 7400 ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}.");
7401 }]]; 7401 }]];
7402 7402
7403 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); 7403 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()");
7404 7404
7405 checkperms($fname); 7405 checkperms($fname);
7406 if (!($lines = load_lines($fname, false))) { 7406 if (!($lines = load_lines($fname, false))) {
7407 log_error($fname, NO_LINE_NUMBER, "Could not be read."); 7407 log_error($fname, NO_LINE_NUMBER, "Could not be read.");
7408 return; 7408 return;
7409 } 7409 }
7410 if (@{$lines} == 0) { 7410 if (@{$lines} == 0) {
7411 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 7411 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
7412 return; 7412 return;
7413 } 7413 }
7414 7414
7415 $state = PST_START; 7415 $state = PST_START;
7416 $dellines = undef; 7416 $dellines = undef;
7417 $addlines = undef; 7417 $addlines = undef;
7418 $patched_files = 0; 7418 $patched_files = 0;
7419 $seen_comment = false; 7419 $seen_comment = false;
7420 $current_fname = undef; 7420 $current_fname = undef;
7421 $current_ftype = undef; 7421 $current_ftype = undef;
7422 $hunks = undef; 7422 $hunks = undef;
7423 7423
7424 for (my $lineno = 0; $lineno <= $#{$lines}; ) { 7424 for (my $lineno = 0; $lineno <= $#{$lines}; ) {
7425 $line = $lines->[$lineno]; 7425 $line = $lines->[$lineno];
7426 my $text = $line->text; 7426 my $text = $line->text;
7427 7427
7428 $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); 7428 $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text");
7429 7429
7430 my $found = false; 7430 my $found = false;
7431 foreach my $t (@{$transitions}) { 7431 foreach my $t (@{$transitions}) {
7432 if ($state == $t->[0]) { 7432 if ($state == $t->[0]) {
7433 if (!defined($t->[1])) { 7433 if (!defined($t->[1])) {
7434 $m = undef; 7434 $m = undef;
7435 } elsif ($text =~ $t->[1]) { 7435 } elsif ($text =~ $t->[1]) {
7436 $opt_debug_patches and $line->log_debug($t->[1]); 7436 $opt_debug_patches and $line->log_debug($t->[1]);
7437 $m = PkgLint::SimpleMatch->new($text, \@-, \@+); 7437 $m = PkgLint::SimpleMatch->new($text, \@-, \@+);
7438 } else { 7438 } else {
7439 next; 7439 next;
7440 } 7440 }
7441 $redostate = undef; 7441 $redostate = undef;
7442 $nextstate = $t->[2]; 7442 $nextstate = $t->[2];
7443 $t->[3]->(); 7443 $t->[3]->();
7444 if (defined($redostate)) { 7444 if (defined($redostate)) {
7445 $state = $redostate; 7445 $state = $redostate;
7446 } else { 7446 } else {
7447 $state = $nextstate; 7447 $state = $nextstate;
7448 if (defined($t->[1])) { 7448 if (defined($t->[1])) {
7449 $lineno++; 7449 $lineno++;
7450 } 7450 }
7451 } 7451 }
7452 $found = true; 7452 $found = true;
7453 last; 7453 last;
7454 } 7454 }
7455 } 7455 }
7456 7456
7457 if (!$found) { 7457 if (!$found) {
7458 $line->log_error("Parse error: state=${state}"); 7458 $line->log_error("Parse error: state=${state}");
7459 $state = PST_TEXT; 7459 $state = PST_TEXT;
7460 $lineno++; 7460 $lineno++;
7461 } 7461 }
7462 } 7462 }
7463 7463
7464 while ($state != PST_TEXT) { 7464 while ($state != PST_TEXT) {
7465 $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); 7465 $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]");
7466 7466
7467 my $found = false; 7467 my $found = false;
7468 foreach my $t (@{$transitions}) { 7468 foreach my $t (@{$transitions}) {
7469 if ($state == $t->[0] && !defined($t->[1])) { 7469 if ($state == $t->[0] && !defined($t->[1])) {
7470 my $newstate; 7470 my $newstate;
7471 7471
7472 $m = undef; 7472 $m = undef;
7473 $redostate = undef; 7473 $redostate = undef;
7474 $nextstate = $t->[2]; 7474 $nextstate = $t->[2];
7475 $t->[3]->(); 7475 $t->[3]->();
7476 $newstate = (defined($redostate)) ? $redostate : $nextstate; 7476 $newstate = (defined($redostate)) ? $redostate : $nextstate;
7477 if ($newstate == $state) { 7477 if ($newstate == $state) {
7478 log_fatal($fname, "EOF", "Internal error in the patch transition table."); 7478 log_fatal($fname, "EOF", "Internal error in the patch transition table.");
7479 } 7479 }
7480 $state = $newstate; 7480 $state = $newstate;
7481 $found = true; 7481 $found = true;
7482 last; 7482 last;
7483 } 7483 }
7484 } 7484 }
7485 7485
7486 if (!$found) { 7486 if (!$found) {
7487 log_error($fname, "EOF", "Parse error: state=${state}"); 7487 log_error($fname, "EOF", "Parse error: state=${state}");
7488 $state = PST_TEXT; 7488 $state = PST_TEXT;
7489 } 7489 }
7490 } 7490 }
7491 7491
7492 if ($patched_files > 1) { 7492 if ($patched_files > 1) {
7493 log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); 7493 log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one.");
7494 7494
7495 } elsif ($patched_files == 0) { 7495 } elsif ($patched_files == 0) {
7496 log_error($fname, NO_LINE_NUMBER, "Contains no patch."); 7496 log_error($fname, NO_LINE_NUMBER, "Contains no patch.");
7497 } 7497 }
7498 7498
7499 checklines_trailing_empty_lines($lines); 7499 checklines_trailing_empty_lines($lines);
7500} 7500}
7501 7501
7502sub checkfile_PLIST($) { 7502sub checkfile_PLIST($) {
7503 my ($fname) = @_; 7503 my ($fname) = @_;
7504 my ($lines, $last_file_seen); 7504 my ($lines, $last_file_seen);
7505 7505
7506 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); 7506 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()");
7507 7507
7508 checkperms($fname); 7508 checkperms($fname);
7509 if (!($lines = load_file($fname))) { 7509 if (!($lines = load_file($fname))) {
7510 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 7510 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
7511 return; 7511 return;
7512 } 7512 }
7513 if (@{$lines} == 0) { 7513 if (@{$lines} == 0) {
7514 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 7514 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
7515 return; 7515 return;
7516 } 7516 }
7517 checkline_rcsid($lines->[0], "\@comment "); 7517 checkline_rcsid($lines->[0], "\@comment ");
7518 7518
7519 if (@$lines == 1) { 7519 if (@$lines == 1) {
7520 $lines->[0]->log_warning("PLIST files shouldn't be empty."); 7520 $lines->[0]->log_warning("PLIST files shouldn't be empty.");
7521 $lines->[0]->explain_warning( 7521 $lines->[0]->explain_warning(
7522"One reason for empty PLISTs is that this is a newly created package", 7522"One reason for empty PLISTs is that this is a newly created package",
7523"and that the author didn't run \"bmake print-PLIST\" after installing", 7523"and that the author didn't run \"bmake print-PLIST\" after installing",
7524"the files.", 7524"the files.",
7525"", 7525"",
7526"Another reason, common for Perl packages, is that the final PLIST is", 7526"Another reason, common for Perl packages, is that the final PLIST is",
7527"automatically generated. Since the source PLIST is not used at all,", 7527"automatically generated. Since the source PLIST is not used at all,",
7528"you can remove it.", 7528"you can remove it.",
7529"", 7529"",
7530"Meta packages also don't need a PLIST file."); 7530"Meta packages also don't need a PLIST file.");
7531 } 7531 }
7532 7532
7533 # Get the list of all files from the PLIST. 7533 # Get the list of all files from the PLIST.
7534 my $all_files = {}; 7534 my $all_files = {};
7535 my $all_dirs = {}; 7535 my $all_dirs = {};
7536 my $extra_lines = []; 7536 my $extra_lines = [];
7537 if (basename($fname) eq "PLIST.common_end") { 7537 if (basename($fname) eq "PLIST.common_end") {
7538 my $common_lines = load_file(dirname($fname) . "/PLIST.common"); 7538 my $common_lines = load_file(dirname($fname) . "/PLIST.common");
7539 if ($common_lines) { 7539 if ($common_lines) {
7540 $extra_lines = $common_lines; 7540 $extra_lines = $common_lines;
7541 } 7541 }
7542 } 7542 }
7543 7543
7544 foreach my $line (@{$extra_lines}, @{$lines}) { 7544 foreach my $line (@{$extra_lines}, @{$lines}) {
7545 my $text = $line->text; 7545 my $text = $line->text;
7546 7546
7547 if ($text =~ m"\$\{([\w_]+)\}(.*)") { 7547 if ($text =~ m"\$\{([\w_]+)\}(.*)") {
7548 if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { 7548 if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) {
7549 $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); 7549 $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1.");
7550 $text = $2; 7550 $text = $2;
7551 } 7551 }
7552 } 7552 }
7553  7553
7554 if ($text =~ m"^[\w\$]") { 7554 if ($text =~ m"^[\w\$]") {
7555 $all_files->{$text} = $line; 7555 $all_files->{$text} = $line;
7556 my $dir = $text; 7556 my $dir = $text;
7557 while ($dir =~ s,/[^/]+$,,) { 7557 while ($dir =~ s,/[^/]+$,,) {
7558 $all_dirs->{$dir} = $line; 7558 $all_dirs->{$dir} = $line;
7559 } 7559 }
7560 } 7560 }
7561 if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { 7561 if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") {
7562 my $dir = $1; 7562 my $dir = $1;
7563 do { 7563 do {
7564 $all_dirs->{$dir} = $line; 7564 $all_dirs->{$dir} = $line;
7565 } while ($dir =~ s,/[^/]+$,,); 7565 } while ($dir =~ s,/[^/]+$,,);
7566 } 7566 }
7567 } 7567 }
7568 7568
7569 foreach my $line (@{$lines}) { 7569 foreach my $line (@{$lines}) {
7570 my $text = $line->text; 7570 my $text = $line->text;
7571 7571
7572 if ($text =~ /\s$/) { 7572 if ($text =~ /\s$/) {
7573 $line->log_error("pkgsrc does not support filenames ending in white-space."); 7573 $line->log_error("pkgsrc does not support filenames ending in white-space.");
7574 $line->explain_error( 7574 $line->explain_error(
7575"Each character in the PLIST is relevant, even trailing white-space."); 7575"Each character in the PLIST is relevant, even trailing white-space.");
7576 } 7576 }
7577 7577
7578 # @foo directives. 7578 # @foo directives.
7579 if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { 7579 if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) {
7580 my ($cmd, $arg) = ($1, $2); 7580 my ($cmd, $arg) = ($1, $2);
7581 7581
7582 if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { 7582 if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") {
7583 my ($rmdir, $rest) = ($1, $2); 7583 my ($rmdir, $rest) = ($1, $2);
7584 if ($rest !~ m"(?:true|\$\{TRUE\})") { 7584 if ($rest !~ m"(?:true|\$\{TRUE\})") {
7585 $line->log_warning("Please use \"\@dirrm\" instead of \"\@unexec rmdir\"."); 7585 $line->log_warning("Please use \"\@dirrm\" instead of \"\@unexec rmdir\".");
7586 } 7586 }
7587 7587
7588 } elsif (($cmd eq "exec" || $cmd eq "unexec")) { 7588 } elsif (($cmd eq "exec" || $cmd eq "unexec")) {
7589 if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { 7589 if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) {
7590 $line->log_warning("\@exec/unexec install-info is deprecated."); 7590 $line->log_warning("\@exec/unexec install-info is deprecated.");
7591 7591
7592 } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { 7592 } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") {
7593 $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); 7593 $line->log_error("ldconfig must be used with \"||/usr/bin/true\".");
7594 } 7594 }
7595 7595
7596 } elsif ($cmd eq "comment") { 7596 } elsif ($cmd eq "comment") {
7597 # nothing to do 7597 # nothing to do
7598 7598
7599 } elsif ($cmd eq "dirrm") { 7599 } elsif ($cmd eq "dirrm") {
7600 my @ids = get_shared_dir_ids($line, $arg); 7600 my @ids = get_shared_dir_ids($line, $arg);
7601 if (@ids == 0) { 7601 if (@ids == 0) {
7602 # Nothing to do 7602 # Nothing to do
7603 } elsif (@ids == 1) { 7603 } elsif (@ids == 1) {
7604 $line->log_warning("Please add \"USE_DIRS+= $ids[0]\" to the package Makefile and remove this line."); 7604 $line->log_warning("Please add \"USE_DIRS+= $ids[0]\" to the package Makefile and remove this line.");
7605 } else { 7605 } else {
7606 my $s = join(" or ", map { "\"USE_DIRS+= $_\"" } @ids); 7606 my $s = join(" or ", map { "\"USE_DIRS+= $_\"" } @ids);
7607 $line->log_warning("Please add $s to the package Makefile and remove this line."); 7607 $line->log_warning("Please add $s to the package Makefile and remove this line.");
7608 } 7608 }
7609 if (!exists($all_dirs->{$arg})) { 7609 if (!exists($all_dirs->{$arg})) {
7610 $line->log_warning("The PLIST does not contain files for \"$arg\"."); 7610 $line->log_warning("The PLIST does not contain files for \"$arg\".");
7611 $line->explain_warning( 7611 $line->explain_warning(
7612"A package should only remove those directories that it created. When", 7612"A package should only remove those directories that it created. When",
7613"there are no files in the directory, it is unlikely that the package", 7613"there are no files in the directory, it is unlikely that the package",
7614"created the directory."); 7614"created the directory.");
7615 } 7615 }
7616 7616
7617 if ($pkgpath ne "graphics/hicolor-icon-theme" && $arg =~ m"^share/icons/hicolor(?:$|/)") { 7617 if ($pkgpath ne "graphics/hicolor-icon-theme" && $arg =~ m"^share/icons/hicolor(?:$|/)") {
7618 $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line."); 7618 $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line.");
7619 } 7619 }
7620 } elsif ($cmd eq "imake-man") { 7620 } elsif ($cmd eq "imake-man") {
7621 my (@args) = split(/\s+/, $arg); 7621 my (@args) = split(/\s+/, $arg);
7622 if (@args != 3) { 7622 if (@args != 3) {
7623 $line->log_warning("Invalid number of arguments for imake-man."); 7623 $line->log_warning("Invalid number of arguments for imake-man.");
7624 } else { 7624 } else {
7625 if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { 7625 if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") {
7626 warn_about_PLIST_imake_mannewsuffix($line); 7626 warn_about_PLIST_imake_mannewsuffix($line);
7627 } 7627 }
7628 } 7628 }
7629 7629
7630 } else { 7630 } else {
7631 $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); 7631 $line->log_warning("Unknown PLIST directive \"\@$cmd\".");
7632 } 7632 }
7633 7633
7634 # Pathnames. 7634 # Pathnames.
7635 } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { 7635 } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") {
7636 my ($dirname, $basename) = ($1, $2); 7636 my ($dirname, $basename) = ($1, $2);
7637 7637
7638 if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { 7638 if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) {
7639 if (defined($last_file_seen)) { 7639 if (defined($last_file_seen)) {
7640 if ($last_file_seen gt $text) { 7640 if ($last_file_seen gt $text) {
7641 $line->log_warning("${text} should be sorted before ${last_file_seen}."); 7641 $line->log_warning("${text} should be sorted before ${last_file_seen}.");
7642 } elsif ($last_file_seen eq $text) { 7642 } elsif ($last_file_seen eq $text) {