Thu Dec 4 18:07:52 2008 UTC ()
Added explicit checks for share/icons/hicolor directories in PLISTs, as
suggested by wiz.


(rillig)
diff -r1.792 -r1.793 pkgsrc/pkgtools/pkglint/files/pkglint.pl

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

--- pkgsrc/pkgtools/pkglint/files/Attic/pkglint.pl 2008/12/02 09:00:28 1.792
+++ pkgsrc/pkgtools/pkglint/files/Attic/pkglint.pl 2008/12/04 18:07:52 1.793
@@ -1,1001 +1,1001 @@ @@ -1,1001 +1,1001 @@
1#! @PERL@ 1#! @PERL@
2# $NetBSD: pkglint.pl,v 1.792 2008/12/02 09:00:28 rillig Exp $ 2# $NetBSD: pkglint.pl,v 1.793 2008/12/04 18:07:52 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' 26# sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p'
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
@@ -6424,1727 +6424,1733 @@ sub checkfile_buildlink3_mk($) { @@ -6424,1727 +6424,1733 @@ sub checkfile_buildlink3_mk($) {
6424 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); 6424 $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\".");
6425 } 6425 }
6426 $do_check = true; 6426 $do_check = true;
6427 } 6427 }
6428 if ($do_check && defined($abi_pkg) && defined($api_pkg)) { 6428 if ($do_check && defined($abi_pkg) && defined($api_pkg)) {
6429 if ($abi_pkg ne $api_pkg) { 6429 if ($abi_pkg ne $api_pkg) {
6430 $abi_line->log_warning("Package name mismatch between ${abi_pkg} ..."); 6430 $abi_line->log_warning("Package name mismatch between ${abi_pkg} ...");
6431 $api_line->log_warning("... and ${api_pkg}."); 6431 $api_line->log_warning("... and ${api_pkg}.");
6432 } 6432 }
6433 } 6433 }
6434 if ($do_check && defined($abi_version) && defined($api_version)) { 6434 if ($do_check && defined($abi_version) && defined($api_version)) {
6435 if (!dewey_cmp($abi_version, ">=", $api_version)) { 6435 if (!dewey_cmp($abi_version, ">=", $api_version)) {
6436 $abi_line->log_warning("ABI version (${abi_version}) should be at least ..."); 6436 $abi_line->log_warning("ABI version (${abi_version}) should be at least ...");
6437 $api_line->log_warning("... API version (${api_version})."); 6437 $api_line->log_warning("... API version (${api_version}).");
6438 } 6438 }
6439 } 6439 }
6440 6440
6441 if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") { 6441 if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") {
6442 my ($varparam) = ($1); 6442 my ($varparam) = ($1);
6443 6443
6444 if ($varparam ne $bl_pkgbase) { 6444 if ($varparam ne $bl_pkgbase) {
6445 $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file."); 6445 $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file.");
6446 } 6446 }
6447 } 6447 }
6448 6448
6449 # TODO: More checks. 6449 # TODO: More checks.
6450 6450
6451 } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) { 6451 } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) {
6452 # Comments and empty lines are fine here. 6452 # Comments and empty lines are fine here.
6453 6453
6454 } else { 6454 } else {
6455 $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in fourth paragraph."); 6455 $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in fourth paragraph.");
6456 $lineno++; 6456 $lineno++;
6457 } 6457 }
6458 } 6458 }
6459 if (!defined($api_line)) { 6459 if (!defined($api_line)) {
6460 $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing."); 6460 $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing.");
6461 } 6461 }
6462 expect_empty_line($lines, \$lineno); 6462 expect_empty_line($lines, \$lineno);
6463 6463
6464 # Before the fifth paragraph, it may be necessary to resolve the build 6464 # Before the fifth paragraph, it may be necessary to resolve the build
6465 # options of other packages. 6465 # options of other packages.
6466 if (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")) { 6466 if (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")) {
6467 do { 6467 do {
6468 expect_text($lines, \$lineno, ".include \"../../mk/pkg-build-options.mk\""); 6468 expect_text($lines, \$lineno, ".include \"../../mk/pkg-build-options.mk\"");
6469 } while (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")); 6469 } while (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$"));
6470 expect_empty_line($lines, \$lineno); 6470 expect_empty_line($lines, \$lineno);
6471 } 6471 }
6472 6472
6473 # Fifth paragraph (optional): Dependencies. 6473 # Fifth paragraph (optional): Dependencies.
6474 my $have_dependencies = false; 6474 my $have_dependencies = false;
6475 my $need_empty_line = false; 6475 my $need_empty_line = false;
6476 while (true) { 6476 while (true) {
6477 if (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$") 6477 if (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$")
6478 || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$") 6478 || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$")
6479 || expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$") 6479 || expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$")
6480 || expect($lines, \$lineno, qr"^\.endif$")) { 6480 || expect($lines, \$lineno, qr"^\.endif$")) {
6481 $have_dependencies = true; 6481 $have_dependencies = true;
6482 $need_empty_line = true; 6482 $need_empty_line = true;
6483 } elsif ($have_dependencies && expect($lines, \$lineno, qr"^$")) { 6483 } elsif ($have_dependencies && expect($lines, \$lineno, qr"^$")) {
6484 $need_empty_line = false; 6484 $need_empty_line = false;
6485 } else { 6485 } else {
6486 last; 6486 last;
6487 } 6487 }
6488 } 6488 }
6489 if ($need_empty_line) { 6489 if ($need_empty_line) {
6490 expect_empty_line($lines, \$lineno); 6490 expect_empty_line($lines, \$lineno);
6491 } 6491 }
6492 6492
6493 # Sixth paragraph: Reference counter. 6493 # Sixth paragraph: Reference counter.
6494 if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH:S/\+\$//\}$")) { 6494 if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH:S/\+\$//\}$")) {
6495 lines_log_warning($lines, $lineno, "Expected BUILDLINK_DEPTH:= \${BUILDLINK_DEPTH:S/+\$//}."); 6495 lines_log_warning($lines, $lineno, "Expected BUILDLINK_DEPTH:= \${BUILDLINK_DEPTH:S/+\$//}.");
6496 explain_warning($lines, $lineno, 6496 explain_warning($lines, $lineno,
6497 "Everything besides the .include lines for the buildlink3.mk files of", 6497 "Everything besides the .include lines for the buildlink3.mk files of",
6498 "dependencies should go between the .if !empty({PKGNAME}_BUILDLINK3_MK)", 6498 "dependencies should go between the .if !empty({PKGNAME}_BUILDLINK3_MK)",
6499 "and the corresponding .endif."); 6499 "and the corresponding .endif.");
6500 return; 6500 return;
6501 } 6501 }
6502 6502
6503 if ($lineno <= $#{$lines}) { 6503 if ($lineno <= $#{$lines}) {
6504 $lines->[$lineno]->log_warning("The file should end here."); 6504 $lines->[$lineno]->log_warning("The file should end here.");
6505 } 6505 }
6506 6506
6507 checklines_buildlink3_inclusion($lines); 6507 checklines_buildlink3_inclusion($lines);
6508} 6508}
6509 6509
6510sub checkfile_DESCR($) { 6510sub checkfile_DESCR($) {
6511 my ($fname) = @_; 6511 my ($fname) = @_;
6512 my ($maxchars, $maxlines) = (80, 24); 6512 my ($maxchars, $maxlines) = (80, 24);
6513 my ($lines); 6513 my ($lines);
6514 6514
6515 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_DESCR()"); 6515 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_DESCR()");
6516 6516
6517 checkperms($fname); 6517 checkperms($fname);
6518 if (!($lines = load_file($fname))) { 6518 if (!($lines = load_file($fname))) {
6519 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6519 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6520 return; 6520 return;
6521 } 6521 }
6522 if (@{$lines} == 0) { 6522 if (@{$lines} == 0) {
6523 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 6523 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
6524 return; 6524 return;
6525 } 6525 }
6526 6526
6527 foreach my $line (@{$lines}) { 6527 foreach my $line (@{$lines}) {
6528 checkline_length($line, $maxchars); 6528 checkline_length($line, $maxchars);
6529 checkline_trailing_whitespace($line); 6529 checkline_trailing_whitespace($line);
6530 checkline_valid_characters($line, regex_validchars); 6530 checkline_valid_characters($line, regex_validchars);
6531 checkline_spellcheck($line); 6531 checkline_spellcheck($line);
6532 if ($line->text =~ m"\$\{") { 6532 if ($line->text =~ m"\$\{") {
6533 $line->log_warning("Variables are not expanded in the DESCR file."); 6533 $line->log_warning("Variables are not expanded in the DESCR file.");
6534 } 6534 }
6535 } 6535 }
6536 checklines_trailing_empty_lines($lines); 6536 checklines_trailing_empty_lines($lines);
6537 6537
6538 if (@{$lines} > $maxlines) { 6538 if (@{$lines} > $maxlines) {
6539 my $line = $lines->[$maxlines]; 6539 my $line = $lines->[$maxlines];
6540 6540
6541 $line->log_warning("File too long (should be no more than $maxlines lines)."); 6541 $line->log_warning("File too long (should be no more than $maxlines lines).");
6542 $line->explain_warning( 6542 $line->explain_warning(
6543"A common terminal size is 80x25 characters. The DESCR file should", 6543"A common terminal size is 80x25 characters. The DESCR file should",
6544"fit on one screen. It is also intended to give a _brief_ summary", 6544"fit on one screen. It is also intended to give a _brief_ summary",
6545"about the package's contents."); 6545"about the package's contents.");
6546 } 6546 }
6547 autofix($lines); 6547 autofix($lines);
6548} 6548}
6549 6549
6550sub checkfile_distinfo($) { 6550sub checkfile_distinfo($) {
6551 my ($fname) = @_; 6551 my ($fname) = @_;
6552 my ($lines, %in_distinfo, $current_fname, $state, $patches_dir); 6552 my ($lines, %in_distinfo, $current_fname, $state, $patches_dir);
6553 my ($di_is_committed); 6553 my ($di_is_committed);
6554 6554
6555 use enum qw(:DIS_ start=0 SHA1=0 RMD160 Size); 6555 use enum qw(:DIS_ start=0 SHA1=0 RMD160 Size);
6556 6556
6557 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_distinfo()"); 6557 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_distinfo()");
6558 6558
6559 $di_is_committed = is_committed($fname); 6559 $di_is_committed = is_committed($fname);
6560 6560
6561 checkperms($fname); 6561 checkperms($fname);
6562 if (!($lines = load_file($fname))) { 6562 if (!($lines = load_file($fname))) {
6563 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6563 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6564 return; 6564 return;
6565 } 6565 }
6566 6566
6567 if (@{$lines} == 0) { 6567 if (@{$lines} == 0) {
6568 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 6568 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
6569 return; 6569 return;
6570 } 6570 }
6571 6571
6572 checkline_rcsid($lines->[0], ""); 6572 checkline_rcsid($lines->[0], "");
6573 if (1 <= $#{$lines} && $lines->[1]->text ne "") { 6573 if (1 <= $#{$lines} && $lines->[1]->text ne "") {
6574 $lines->[1]->log_note("Empty line expected."); 6574 $lines->[1]->log_note("Empty line expected.");
6575 $lines->[1]->explain_note("This is merely for aesthetical purposes."); 6575 $lines->[1]->explain_note("This is merely for aesthetical purposes.");
6576 } 6576 }
6577 6577
6578 $patches_dir = $patchdir; 6578 $patches_dir = $patchdir;
6579 if (!defined($patches_dir) && -d "${current_dir}/patches") { 6579 if (!defined($patches_dir) && -d "${current_dir}/patches") {
6580 $patches_dir = "patches"; 6580 $patches_dir = "patches";
6581 } else { 6581 } else {
6582 # it stays undefined. 6582 # it stays undefined.
6583 } 6583 }
6584 6584
6585 $current_fname = undef; 6585 $current_fname = undef;
6586 $state = DIS_start; 6586 $state = DIS_start;
6587 foreach my $line (@{$lines}[2..$#{$lines}]) { 6587 foreach my $line (@{$lines}[2..$#{$lines}]) {
6588 if ($line->text !~ m"^(\w+) \(([^)]+)\) = (.*)(?: bytes)?$") { 6588 if ($line->text !~ m"^(\w+) \(([^)]+)\) = (.*)(?: bytes)?$") {
6589 $line->log_error("Unknown line type."); 6589 $line->log_error("Unknown line type.");
6590 next; 6590 next;
6591 } 6591 }
6592 my ($alg, $chksum_fname, $sum) = ($1, $2, $3); 6592 my ($alg, $chksum_fname, $sum) = ($1, $2, $3);
6593 my $is_patch = (($chksum_fname =~ m"^patch-[A-Za-z0-9]+$") ? true : false); 6593 my $is_patch = (($chksum_fname =~ m"^patch-[A-Za-z0-9]+$") ? true : false);
6594 6594
6595 if ($chksum_fname !~ m"^\w") { 6595 if ($chksum_fname !~ m"^\w") {
6596 $line->log_error("All file names should start with a letter."); 6596 $line->log_error("All file names should start with a letter.");
6597 } 6597 }
6598 6598
6599 # Inter-package check for differing distfile checksums. 6599 # Inter-package check for differing distfile checksums.
6600 if ($opt_check_global && !$is_patch) { 6600 if ($opt_check_global && !$is_patch) {
6601 # Note: Perl-specific auto-population. 6601 # Note: Perl-specific auto-population.
6602 if (exists($ipc_distinfo->{$alg}->{$chksum_fname})) { 6602 if (exists($ipc_distinfo->{$alg}->{$chksum_fname})) {
6603 my $other = $ipc_distinfo->{$alg}->{$chksum_fname}; 6603 my $other = $ipc_distinfo->{$alg}->{$chksum_fname};
6604 6604
6605 if ($other->[1] eq $sum) { 6605 if ($other->[1] eq $sum) {
6606 # Fine. 6606 # Fine.
6607 } else { 6607 } else {
6608 $line->log_error("The ${alg} checksum for ${chksum_fname} differs ..."); 6608 $line->log_error("The ${alg} checksum for ${chksum_fname} differs ...");
6609 $other->[0]->log_error("... from this one."); 6609 $other->[0]->log_error("... from this one.");
6610 } 6610 }
6611 } else { 6611 } else {
6612 $ipc_distinfo->{$alg}->{$chksum_fname} = [$line, $sum]; 6612 $ipc_distinfo->{$alg}->{$chksum_fname} = [$line, $sum];
6613 } 6613 }
6614 } 6614 }
6615 6615
6616 if ($alg eq "MD5") { 6616 if ($alg eq "MD5") {
6617 $line->log_error("MD5 checksums are obsolete."); 6617 $line->log_error("MD5 checksums are obsolete.");
6618 $line->explain_error( 6618 $line->explain_error(
6619"Run \"".conf_make." makedistinfo\" to regenerate the distinfo file."); 6619"Run \"".conf_make." makedistinfo\" to regenerate the distinfo file.");
6620 next; 6620 next;
6621 } 6621 }
6622 6622
6623 if ($state == DIS_SHA1) { 6623 if ($state == DIS_SHA1) {
6624 if ($alg eq "SHA1") { 6624 if ($alg eq "SHA1") {
6625 $state = ($is_patch ? DIS_start : DIS_RMD160); 6625 $state = ($is_patch ? DIS_start : DIS_RMD160);
6626 $current_fname = $chksum_fname; 6626 $current_fname = $chksum_fname;
6627 } else { 6627 } else {
6628 $line->log_warning("Expected an SHA1 checksum."); 6628 $line->log_warning("Expected an SHA1 checksum.");
6629 } 6629 }
6630 6630
6631 } elsif ($state == DIS_RMD160) { 6631 } elsif ($state == DIS_RMD160) {
6632 $state = DIS_start; 6632 $state = DIS_start;
6633 if ($alg eq "RMD160") { 6633 if ($alg eq "RMD160") {
6634 if ($chksum_fname eq $current_fname) { 6634 if ($chksum_fname eq $current_fname) {
6635 $state = DIS_Size; 6635 $state = DIS_Size;
6636 } else { 6636 } else {
6637 $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not for ${chksum_fname}."); 6637 $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not for ${chksum_fname}.");
6638 } 6638 }
6639 } else { 6639 } else {
6640 if ($chksum_fname eq $current_fname) { 6640 if ($chksum_fname eq $current_fname) {
6641 # This is an error because this really should be fixed. 6641 # This is an error because this really should be fixed.
6642 $line->log_error("Expected an RMD160 checksum, not ${alg} for ${chksum_fname}."); 6642 $line->log_error("Expected an RMD160 checksum, not ${alg} for ${chksum_fname}.");
6643 } else { 6643 } else {
6644 $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); 6644 $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not ${alg} for ${chksum_fname}.");
6645 } 6645 }
6646 } 6646 }
6647 6647
6648 } elsif ($state == DIS_Size) { 6648 } elsif ($state == DIS_Size) {
6649 $state = DIS_start; 6649 $state = DIS_start;
6650 if ($alg eq "Size") { 6650 if ($alg eq "Size") {
6651 if ($chksum_fname ne $current_fname) { 6651 if ($chksum_fname ne $current_fname) {
6652 $line->log_warning("Expected a Size checksum for ${current_fname}, not for ${chksum_fname}."); 6652 $line->log_warning("Expected a Size checksum for ${current_fname}, not for ${chksum_fname}.");
6653 } 6653 }
6654 } else { 6654 } else {
6655 if ($chksum_fname eq $current_fname) { 6655 if ($chksum_fname eq $current_fname) {
6656 $line->log_warning("Expected a Size checksum, not ${alg} for ${chksum_fname}."); 6656 $line->log_warning("Expected a Size checksum, not ${alg} for ${chksum_fname}.");
6657 } else { 6657 } else {
6658 $line->log_warning("Expected a Size checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); 6658 $line->log_warning("Expected a Size checksum for ${current_fname}, not ${alg} for ${chksum_fname}.");
6659 } 6659 }
6660 } 6660 }
6661 } 6661 }
6662 6662
6663 if ($is_patch && defined($patches_dir) && !(defined($distinfo_file) && $distinfo_file eq "./../../lang/php5/distinfo")) { 6663 if ($is_patch && defined($patches_dir) && !(defined($distinfo_file) && $distinfo_file eq "./../../lang/php5/distinfo")) {
6664 my $fname = "${current_dir}/${patches_dir}/${chksum_fname}"; 6664 my $fname = "${current_dir}/${patches_dir}/${chksum_fname}";
6665 if ($di_is_committed && !is_committed($fname)) { 6665 if ($di_is_committed && !is_committed($fname)) {
6666 $line->log_warning("${patches_dir}/${chksum_fname} is registered in distinfo but not added to CVS."); 6666 $line->log_warning("${patches_dir}/${chksum_fname} is registered in distinfo but not added to CVS.");
6667 } 6667 }
6668 6668
6669 if (open(PATCH, "<", $fname)) { 6669 if (open(PATCH, "<", $fname)) {
6670 my $data = ""; 6670 my $data = "";
6671 foreach my $patchline (<PATCH>) { 6671 foreach my $patchline (<PATCH>) {
6672 $data .= $patchline unless $patchline =~ m"\$[N]etBSD"; 6672 $data .= $patchline unless $patchline =~ m"\$[N]etBSD";
6673 } 6673 }
6674 close(PATCH); 6674 close(PATCH);
6675 my $chksum = Digest::SHA1::sha1_hex($data); 6675 my $chksum = Digest::SHA1::sha1_hex($data);
6676 if ($sum ne $chksum) { 6676 if ($sum ne $chksum) {
6677 $line->log_error("${alg} checksum of ${chksum_fname} differs (expected ${sum}, got ${chksum}). Rerun '".conf_make." makepatchsum'."); 6677 $line->log_error("${alg} checksum of ${chksum_fname} differs (expected ${sum}, got ${chksum}). Rerun '".conf_make." makepatchsum'.");
6678 } 6678 }
6679 } elsif (true) { 6679 } elsif (true) {
6680 $line->log_warning("${chksum_fname} does not exist."); 6680 $line->log_warning("${chksum_fname} does not exist.");
6681 $line->explain_warning( 6681 $line->explain_warning(
6682"All patches that are mentioned in a distinfo file should actually exist.", 6682"All patches that are mentioned in a distinfo file should actually exist.",
6683"What's the use of a checksum if there is no file to check?"); 6683"What's the use of a checksum if there is no file to check?");
6684 } 6684 }
6685 } 6685 }
6686 $in_distinfo{$chksum_fname} = true; 6686 $in_distinfo{$chksum_fname} = true;
6687 } 6687 }
6688 checklines_trailing_empty_lines($lines); 6688 checklines_trailing_empty_lines($lines);
6689 6689
6690 if (defined($patches_dir)) { 6690 if (defined($patches_dir)) {
6691 foreach my $patch (<${current_dir}/${patches_dir}/patch-*>) { 6691 foreach my $patch (<${current_dir}/${patches_dir}/patch-*>) {
6692 $patch = basename($patch); 6692 $patch = basename($patch);
6693 if (!exists($in_distinfo{$patch})) { 6693 if (!exists($in_distinfo{$patch})) {
6694 log_error($fname, NO_LINE_NUMBER, "$patch is not recorded. Rerun '".conf_make." makepatchsum'."); 6694 log_error($fname, NO_LINE_NUMBER, "$patch is not recorded. Rerun '".conf_make." makepatchsum'.");
6695 } 6695 }
6696 } 6696 }
6697 } 6697 }
6698} 6698}
6699 6699
6700sub checkfile_extra($) { 6700sub checkfile_extra($) {
6701 my ($fname) = @_; 6701 my ($fname) = @_;
6702 my ($lines); 6702 my ($lines);
6703 6703
6704 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_extra()"); 6704 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_extra()");
6705 6705
6706 $lines = load_file($fname); 6706 $lines = load_file($fname);
6707 if (!$lines) { 6707 if (!$lines) {
6708 log_error($fname, NO_LINE_NUMBER, "Could not be read."); 6708 log_error($fname, NO_LINE_NUMBER, "Could not be read.");
6709 return; 6709 return;
6710 } 6710 }
6711 checklines_trailing_empty_lines($lines); 6711 checklines_trailing_empty_lines($lines);
6712 checkperms($fname); 6712 checkperms($fname);
6713} 6713}
6714 6714
6715sub checkfile_INSTALL($) { 6715sub checkfile_INSTALL($) {
6716 my ($fname) = @_; 6716 my ($fname) = @_;
6717 my ($lines); 6717 my ($lines);
6718 6718
6719 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); 6719 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()");
6720 6720
6721 checkperms($fname); 6721 checkperms($fname);
6722 if (!($lines = load_file($fname))) { 6722 if (!($lines = load_file($fname))) {
6723 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6723 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6724 return; 6724 return;
6725 } 6725 }
6726} 6726}
6727 6727
6728sub checkfile_MESSAGE($) { 6728sub checkfile_MESSAGE($) {
6729 my ($fname) = @_; 6729 my ($fname) = @_;
6730 my ($lines); 6730 my ($lines);
6731 6731
6732 my @explanation = ( 6732 my @explanation = (
6733 "A MESSAGE file should consist of a header line, having 75 \"=\"", 6733 "A MESSAGE file should consist of a header line, having 75 \"=\"",
6734 "characters, followed by a line containing only the RCS Id, then an", 6734 "characters, followed by a line containing only the RCS Id, then an",
6735 "empty line, your text and finally the footer line, which is the", 6735 "empty line, your text and finally the footer line, which is the",
6736 "same as the header line."); 6736 "same as the header line.");
6737 6737
6738 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); 6738 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()");
6739 6739
6740 checkperms($fname); 6740 checkperms($fname);
6741 if (!($lines = load_file($fname))) { 6741 if (!($lines = load_file($fname))) {
6742 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6742 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6743 return; 6743 return;
6744 } 6744 }
6745 6745
6746 if (@{$lines} < 3) { 6746 if (@{$lines} < 3) {
6747 log_warning($fname, NO_LINE_NUMBER, "File too short."); 6747 log_warning($fname, NO_LINE_NUMBER, "File too short.");
6748 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6748 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6749 return; 6749 return;
6750 } 6750 }
6751 if ($lines->[0]->text ne "=" x 75) { 6751 if ($lines->[0]->text ne "=" x 75) {
6752 $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); 6752 $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters.");
6753 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6753 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6754 } 6754 }
6755 checkline_rcsid($lines->[1], ""); 6755 checkline_rcsid($lines->[1], "");
6756 foreach my $line (@{$lines}) { 6756 foreach my $line (@{$lines}) {
6757 checkline_length($line, 80); 6757 checkline_length($line, 80);
6758 checkline_trailing_whitespace($line); 6758 checkline_trailing_whitespace($line);
6759 checkline_valid_characters($line, regex_validchars); 6759 checkline_valid_characters($line, regex_validchars);
6760 checkline_spellcheck($line); 6760 checkline_spellcheck($line);
6761 } 6761 }
6762 if ($lines->[-1]->text ne "=" x 75) { 6762 if ($lines->[-1]->text ne "=" x 75) {
6763 $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); 6763 $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters.");
6764 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6764 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6765 } 6765 }
6766 checklines_trailing_empty_lines($lines); 6766 checklines_trailing_empty_lines($lines);
6767} 6767}
6768 6768
6769sub checkfile_mk($) { 6769sub checkfile_mk($) {
6770 my ($fname) = @_; 6770 my ($fname) = @_;
6771 my ($lines); 6771 my ($lines);
6772 6772
6773 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); 6773 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()");
6774 6774
6775 checkperms($fname); 6775 checkperms($fname);
6776 if (!($lines = load_lines($fname, true))) { 6776 if (!($lines = load_lines($fname, true))) {
6777 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6777 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6778 return; 6778 return;
6779 } 6779 }
6780 6780
6781 parselines_mk($lines); 6781 parselines_mk($lines);
6782 checklines_mk($lines); 6782 checklines_mk($lines);
6783 autofix($lines); 6783 autofix($lines);
6784} 6784}
6785 6785
6786sub checkfile_package_Makefile($$) { 6786sub checkfile_package_Makefile($$) {
6787 my ($fname, $lines) = @_; 6787 my ($fname, $lines) = @_;
6788 6788
6789 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); 6789 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)");
6790 6790
6791 checkperms($fname); 6791 checkperms($fname);
6792 6792
6793 if (!exists($pkgctx_vardef->{"PLIST_SRC"}) 6793 if (!exists($pkgctx_vardef->{"PLIST_SRC"})
6794 && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) 6794 && !exists($pkgctx_vardef->{"GENERATE_PLIST"})
6795 && !exists($pkgctx_vardef->{"META_PACKAGE"}) 6795 && !exists($pkgctx_vardef->{"META_PACKAGE"})
6796 && defined($pkgdir) 6796 && defined($pkgdir)
6797 && !-f "${current_dir}/$pkgdir/PLIST" 6797 && !-f "${current_dir}/$pkgdir/PLIST"
6798 && !-f "${current_dir}/$pkgdir/PLIST.common") { 6798 && !-f "${current_dir}/$pkgdir/PLIST.common") {
6799 log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); 6799 log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?");
6800 } 6800 }
6801 6801
6802 if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { 6802 if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) {
6803 if (-f "${current_dir}/${distinfo_file}") { 6803 if (-f "${current_dir}/${distinfo_file}") {
6804 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); 6804 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set.");
6805 } 6805 }
6806 } else { 6806 } else {
6807 if (!-f "${current_dir}/${distinfo_file}") { 6807 if (!-f "${current_dir}/${distinfo_file}") {
6808 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); 6808 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'.");
6809 } 6809 }
6810 } 6810 }
6811 6811
6812 if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { 6812 if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) {
6813 $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); 6813 $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ...");
6814 $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); 6814 $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set.");
6815 } 6815 }
6816 6816
6817 if (exists($pkgctx_vardef->{"RESTRICTED"}) && !exists($pkgctx_vardef->{"LICENSE"})) { 6817 if (exists($pkgctx_vardef->{"RESTRICTED"}) && !exists($pkgctx_vardef->{"LICENSE"})) {
6818 $pkgctx_vardef->{"RESTRICTED"}->log_error("Restricted packages must have a LICENSE."); 6818 $pkgctx_vardef->{"RESTRICTED"}->log_error("Restricted packages must have a LICENSE.");
6819 } 6819 }
6820 6820
6821 if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { 6821 if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) {
6822 my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; 6822 my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"};
6823 my $value = $languages_line->get("value"); 6823 my $value = $languages_line->get("value");
6824 6824
6825 if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { 6825 if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) {
6826 # Don't emit a warning, since the comment 6826 # Don't emit a warning, since the comment
6827 # probably contains a statement that C is 6827 # probably contains a statement that C is
6828 # really not needed. 6828 # really not needed.
6829 6829
6830 } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { 6830 } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") {
6831 $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); 6831 $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ...");
6832 $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); 6832 $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES.");
6833 } 6833 }
6834 } 6834 }
6835 6835
6836 my $distname_line = $pkgctx_vardef->{"DISTNAME"}; 6836 my $distname_line = $pkgctx_vardef->{"DISTNAME"};
6837 my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; 6837 my $pkgname_line = $pkgctx_vardef->{"PKGNAME"};
6838 6838
6839 my $distname = defined($distname_line) ? $distname_line->get("value") : undef; 6839 my $distname = defined($distname_line) ? $distname_line->get("value") : undef;
6840 my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; 6840 my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef;
6841 my $nbpart = get_nbpart(); 6841 my $nbpart = get_nbpart();
6842 6842
6843 # Let's do some tricks to get the proper value of the package 6843 # Let's do some tricks to get the proper value of the package
6844 # name more often. 6844 # name more often.
6845 if (defined($distname) && defined($pkgname)) { 6845 if (defined($distname) && defined($pkgname)) {
6846 $pkgname =~ s/\$\{DISTNAME\}/$distname/; 6846 $pkgname =~ s/\$\{DISTNAME\}/$distname/;
6847 6847
6848 if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { 6848 if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") {
6849 my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); 6849 my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6);
6850 my $newname = $distname; 6850 my $newname = $distname;
6851 $old = quotemeta($old); 6851 $old = quotemeta($old);
6852 $old =~ s/^\\\^/^/; 6852 $old =~ s/^\\\^/^/;
6853 $old =~ s/\\\$$/\$/; 6853 $old =~ s/\\\$$/\$/;
6854 if ($mod eq "g") { 6854 if ($mod eq "g") {
6855 $newname =~ s/$old/$new/g; 6855 $newname =~ s/$old/$new/g;
6856 } else { 6856 } else {
6857 $newname =~ s/$old/$new/; 6857 $newname =~ s/$old/$new/;
6858 } 6858 }
6859 $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); 6859 $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname");
6860 $pkgname = $before . $newname . $after; 6860 $pkgname = $before . $newname . $after;
6861 $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); 6861 $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname");
6862 } 6862 }
6863 } 6863 }
6864 6864
6865 if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { 6865 if (defined($pkgname) && defined($distname) && $pkgname eq $distname) {
6866 $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); 6866 $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME.");
6867 } 6867 }
6868 6868
6869 if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { 6869 if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) {
6870 $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); 6870 $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly.");
6871 } 6871 }
6872 6872
6873 ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) 6873 ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion)
6874 = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) 6874 = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2)
6875 : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) 6875 : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2)
6876 : (undef, undef, undef, undef); 6876 : (undef, undef, undef, undef);
6877 if (defined($effective_pkgname_line)) { 6877 if (defined($effective_pkgname_line)) {
6878 $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); 6878 $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}.");
6879 } 6879 }
6880 6880
6881 checkpackage_possible_downgrade(); 6881 checkpackage_possible_downgrade();
6882 6882
6883 if (!exists($pkgctx_vardef->{"COMMENT"})) { 6883 if (!exists($pkgctx_vardef->{"COMMENT"})) {
6884 log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); 6884 log_warning($fname, NO_LINE_NUMBER, "No COMMENT given.");
6885 } 6885 }
6886 6886
6887 if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { 6887 if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) {
6888 $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); 6888 $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ...");
6889 $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); 6889 $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous.");
6890 } 6890 }
6891 6891
6892 if (defined($effective_pkgbase)) { 6892 if (defined($effective_pkgbase)) {
6893 6893
6894 foreach my $suggested_update (@{get_suggested_package_updates()}) { 6894 foreach my $suggested_update (@{get_suggested_package_updates()}) {
6895 my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; 6895 my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update};
6896 my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); 6896 my $comment = (defined($suggcomm) ? " (${suggcomm})" : "");
6897 6897
6898 next unless $effective_pkgbase eq $suggbase; 6898 next unless $effective_pkgbase eq $suggbase;
6899 6899
6900 if (dewey_cmp($effective_pkgversion, "<", $suggver)) { 6900 if (dewey_cmp($effective_pkgversion, "<", $suggver)) {
6901 $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); 6901 $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}.");
6902 } 6902 }
6903 if (dewey_cmp($effective_pkgversion, "==", $suggver)) { 6903 if (dewey_cmp($effective_pkgversion, "==", $suggver)) {
6904 $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); 6904 $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done.");
6905 } 6905 }
6906 if (dewey_cmp($effective_pkgversion, ">", $suggver)) { 6906 if (dewey_cmp($effective_pkgversion, ">", $suggver)) {
6907 $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); 6907 $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}.");
6908 } 6908 }
6909 } 6909 }
6910 } 6910 }
6911 6911
6912 checklines_mk($lines); 6912 checklines_mk($lines);
6913 checklines_package_Makefile_varorder($lines); 6913 checklines_package_Makefile_varorder($lines);
6914 autofix($lines); 6914 autofix($lines);
6915} 6915}
6916 6916
6917sub checkfile_patch($) { 6917sub checkfile_patch($) {
6918 my ($fname) = @_; 6918 my ($fname) = @_;
6919 my ($lines); 6919 my ($lines);
6920 my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); 6920 my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks);
6921 my ($seen_comment, $current_fname, $current_ftype, $patched_files); 6921 my ($seen_comment, $current_fname, $current_ftype, $patched_files);
6922 my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); 6922 my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading);
6923 6923
6924 # Abbreviations used: 6924 # Abbreviations used:
6925 # style: [c] = context diff, [u] = unified diff 6925 # style: [c] = context diff, [u] = unified diff
6926 # scope: [f] = file, [h] = hunk, [l] = line 6926 # scope: [f] = file, [h] = hunk, [l] = line
6927 # action: [d] = delete, [m] = modify, [a] = add, [c] = context 6927 # action: [d] = delete, [m] = modify, [a] = add, [c] = context
6928 use constant re_patch_rcsid => qr"^\$.*\$$"; 6928 use constant re_patch_rcsid => qr"^\$.*\$$";
6929 use constant re_patch_text => qr"^(.+)$"; 6929 use constant re_patch_text => qr"^(.+)$";
6930 use constant re_patch_empty => qr"^$"; 6930 use constant re_patch_empty => qr"^$";
6931 use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; 6931 use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$";
6932 use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; 6932 use constant re_patch_cfa => qr"^---\s(\S+)(.*)$";
6933 use constant re_patch_ch => qr"^\*{15}(.*)$"; 6933 use constant re_patch_ch => qr"^\*{15}(.*)$";
6934 use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; 6934 use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$";
6935 use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; 6935 use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$";
6936 use constant re_patch_cld => qr"^(?:-\s(.*))?$"; 6936 use constant re_patch_cld => qr"^(?:-\s(.*))?$";
6937 use constant re_patch_clm => qr"^(?:!\s(.*))?$"; 6937 use constant re_patch_clm => qr"^(?:!\s(.*))?$";
6938 use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; 6938 use constant re_patch_cla => qr"^(?:\+\s(.*))?$";
6939 use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; 6939 use constant re_patch_clc => qr"^(?:\s\s(.*))?$";
6940 use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; 6940 use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$";
6941 use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; 6941 use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$";
6942 use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; 6942 use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$";
6943 use constant re_patch_uld => qr"^-(.*)$"; 6943 use constant re_patch_uld => qr"^-(.*)$";
6944 use constant re_patch_ula => qr"^\+(.*)$"; 6944 use constant re_patch_ula => qr"^\+(.*)$";
6945 use constant re_patch_ulc => qr"^\s(.*)$"; 6945 use constant re_patch_ulc => qr"^\s(.*)$";
6946 use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; 6946 use constant re_patch_ulnonl => qr"^\\ No newline at end of file$";
6947 6947
6948 use enum qw(:PST_ 6948 use enum qw(:PST_
6949 START CENTER TEXT 6949 START CENTER TEXT
6950 CFA CH CHD CLD0 CLD CLA0 CLA 6950 CFA CH CHD CLD0 CLD CLA0 CLA
6951 UFA UH UL 6951 UFA UH UL
6952 ); 6952 );
6953 6953
6954 my ($line, $m); 6954 my ($line, $m);
6955 6955
6956 my $check_text = sub($) { 6956 my $check_text = sub($) {
6957 my ($text) = @_; 6957 my ($text) = @_;
6958 6958
6959 if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { 6959 if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") {
6960 my ($tag) = ($2); 6960 my ($tag) = ($2);
6961 6961
6962 if ($text =~ re_patch_uh) { 6962 if ($text =~ re_patch_uh) {
6963 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); 6963 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it.");
6964 $line->set_text($1); 6964 $line->set_text($1);
6965 } else { 6965 } else {
6966 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); 6966 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\".");
6967 } 6967 }
6968 } 6968 }
6969 }; 6969 };
6970 6970
6971 my $check_contents = sub() { 6971 my $check_contents = sub() {
6972 6972
6973 if ($m->has(1)) { 6973 if ($m->has(1)) {
6974 $check_text->($m->text(1)); 6974 $check_text->($m->text(1));
6975 } 6975 }
6976 }; 6976 };
6977 6977
6978 my $check_added_contents = sub() { 6978 my $check_added_contents = sub() {
6979 my $text; 6979 my $text;
6980 6980
6981 return unless $m->has(1); 6981 return unless $m->has(1);
6982 $text = $m->text(1); 6982 $text = $m->text(1);
6983 checkline_cpp_macro_names($line, $text); 6983 checkline_cpp_macro_names($line, $text);
6984 checkline_spellcheck($line); 6984 checkline_spellcheck($line);
6985 6985
6986 # XXX: This check is not as accurate as the similar one in 6986 # XXX: This check is not as accurate as the similar one in
6987 # checkline_mk_shelltext(). 6987 # checkline_mk_shelltext().
6988 if (defined($current_fname)) { 6988 if (defined($current_fname)) {
6989 if ($current_ftype eq "shell" || $current_ftype eq "make") { 6989 if ($current_ftype eq "shell" || $current_ftype eq "make") {
6990 my ($mm, $rest) = match_all($text, $regex_shellword); 6990 my ($mm, $rest) = match_all($text, $regex_shellword);
6991 6991
6992 foreach my $m (@{$mm}) { 6992 foreach my $m (@{$mm}) {
6993 my $shellword = $m->text(1); 6993 my $shellword = $m->text(1);
6994 6994
6995 if ($shellword =~ m"^#") { 6995 if ($shellword =~ m"^#") {
6996 last; 6996 last;
6997 } 6997 }
6998 checkline_mk_absolute_pathname($line, $shellword); 6998 checkline_mk_absolute_pathname($line, $shellword);
6999 } 6999 }
7000 7000
7001 } elsif ($current_ftype eq "source") { 7001 } elsif ($current_ftype eq "source") {
7002 checkline_source_absolute_pathname($line, $text); 7002 checkline_source_absolute_pathname($line, $text);
7003 7003
7004 } elsif ($current_ftype eq "configure") { 7004 } elsif ($current_ftype eq "configure") {
7005 if ($text =~ m": Avoid regenerating within pkgsrc$") { 7005 if ($text =~ m": Avoid regenerating within pkgsrc$") {
7006 $line->log_error("This code must not be included in patches."); 7006 $line->log_error("This code must not be included in patches.");
7007 $line->explain_error( 7007 $line->explain_error(
7008"It is generated automatically by pkgsrc after the patch phase.", 7008"It is generated automatically by pkgsrc after the patch phase.",
7009"", 7009"",
7010"For more details, look for \"configure-scripts-override\" in", 7010"For more details, look for \"configure-scripts-override\" in",
7011"mk/configure/gnu-configure.mk."); 7011"mk/configure/gnu-configure.mk.");
7012 } 7012 }
7013 7013
7014 } elsif ($current_ftype eq "ignore") { 7014 } elsif ($current_ftype eq "ignore") {
7015 # Ignore it. 7015 # Ignore it.
7016 7016
7017 } else { 7017 } else {
7018 checkline_other_absolute_pathname($line, $text); 7018 checkline_other_absolute_pathname($line, $text);
7019 } 7019 }
7020 } 7020 }
7021 }; 7021 };
7022 7022
7023 my $check_hunk_end = sub($$$) { 7023 my $check_hunk_end = sub($$$) {
7024 my ($deldelta, $adddelta, $newstate) = @_; 7024 my ($deldelta, $adddelta, $newstate) = @_;
7025 7025
7026 if ($deldelta > 0 && $dellines == 0) { 7026 if ($deldelta > 0 && $dellines == 0) {
7027 $redostate = $newstate; 7027 $redostate = $newstate;
7028 if (defined($addlines) && $addlines > 0) { 7028 if (defined($addlines) && $addlines > 0) {
7029 $line->log_error("Expected ${addlines} more lines to be added."); 7029 $line->log_error("Expected ${addlines} more lines to be added.");
7030 } 7030 }
7031 } elsif ($adddelta > 0 && $addlines == 0) { 7031 } elsif ($adddelta > 0 && $addlines == 0) {
7032 $redostate = $newstate; 7032 $redostate = $newstate;
7033 if (defined($dellines) && $dellines > 0) { 7033 if (defined($dellines) && $dellines > 0) {
7034 $line->log_error("Expected ${dellines} more lines to be deleted."); 7034 $line->log_error("Expected ${dellines} more lines to be deleted.");
7035 } 7035 }
7036 } else { 7036 } else {
7037 if (defined($context_scanning_leading)) { 7037 if (defined($context_scanning_leading)) {
7038 if ($deldelta != 0 && $adddelta != 0) { 7038 if ($deldelta != 0 && $adddelta != 0) {
7039 if ($context_scanning_leading) { 7039 if ($context_scanning_leading) {
7040 $leading_context_lines++; 7040 $leading_context_lines++;
7041 } else { 7041 } else {
7042 $trailing_context_lines++; 7042 $trailing_context_lines++;
7043 } 7043 }
7044 } else { 7044 } else {
7045 if ($context_scanning_leading) { 7045 if ($context_scanning_leading) {
7046 $context_scanning_leading = false; 7046 $context_scanning_leading = false;
7047 } else { 7047 } else {
7048 $trailing_context_lines = 0; 7048 $trailing_context_lines = 0;
7049 } 7049 }
7050 } 7050 }
7051 } 7051 }
7052 7052
7053 if ($deldelta != 0) { 7053 if ($deldelta != 0) {
7054 $dellines -= $deldelta; 7054 $dellines -= $deldelta;
7055 } 7055 }
7056 if ($adddelta != 0) { 7056 if ($adddelta != 0) {
7057 $addlines -= $adddelta; 7057 $addlines -= $adddelta;
7058 } 7058 }
7059 if (!((defined($dellines) && $dellines > 0) || 7059 if (!((defined($dellines) && $dellines > 0) ||
7060 (defined($addlines) && $addlines > 0))) { 7060 (defined($addlines) && $addlines > 0))) {
7061 if (defined($context_scanning_leading)) { 7061 if (defined($context_scanning_leading)) {
7062 if ($leading_context_lines != $trailing_context_lines) { 7062 if ($leading_context_lines != $trailing_context_lines) {
7063 $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."); 7063 $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.");
7064 } 7064 }
7065 } 7065 }
7066 $nextstate = $newstate; 7066 $nextstate = $newstate;
7067 } 7067 }
7068 } 7068 }
7069 }; 7069 };
7070 7070
7071 my $check_hunk_line = sub($$$$) { 7071 my $check_hunk_line = sub($$$$) {
7072 my ($deldelta, $adddelta, $newstate, $check_added) = @_; 7072 my ($deldelta, $adddelta, $newstate, $check_added) = @_;
7073 7073
7074 $check_contents->(); 7074 $check_contents->();
7075 $check_hunk_end->($deldelta, $adddelta, $newstate); 7075 $check_hunk_end->($deldelta, $adddelta, $newstate);
7076 if ($check_added) { 7076 if ($check_added) {
7077 $check_added_contents->(); 7077 $check_added_contents->();
7078 } 7078 }
7079 }; 7079 };
7080 7080
7081 my $transitions = 7081 my $transitions =
7082 [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { 7082 [ [PST_START, re_patch_rcsid, PST_CENTER, sub() {
7083 checkline_rcsid($line, ""); 7083 checkline_rcsid($line, "");
7084 }], [PST_START, undef, PST_CENTER, sub() { 7084 }], [PST_START, undef, PST_CENTER, sub() {
7085 checkline_rcsid($line, ""); 7085 checkline_rcsid($line, "");
7086 }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { 7086 }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() {
7087 # 7087 #
7088 }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { 7088 }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() {
7089 if (!$seen_comment) { 7089 if (!$seen_comment) {
7090 $opt_warn_style and $line->log_warning("Comment expected."); 7090 $opt_warn_style and $line->log_warning("Comment expected.");
7091 } 7091 }
7092 $line->log_warning("Please use unified diffs (diff -u) for patches."); 7092 $line->log_warning("Please use unified diffs (diff -u) for patches.");
7093 }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { 7093 }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() {
7094 if (!$seen_comment) { 7094 if (!$seen_comment) {
7095 $opt_warn_style and $line->log_warning("Comment expected."); 7095 $opt_warn_style and $line->log_warning("Comment expected.");
7096 } 7096 }
7097 }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { 7097 }], [PST_TEXT, re_patch_text, PST_TEXT, sub() {
7098 $seen_comment = true; 7098 $seen_comment = true;
7099 }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { 7099 }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() {
7100 # 7100 #
7101 }], [PST_TEXT, undef, PST_TEXT, sub() { 7101 }], [PST_TEXT, undef, PST_TEXT, sub() {
7102 # 7102 #
7103 }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { 7103 }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() {
7104 if ($seen_comment) { 7104 if ($seen_comment) {
7105 $opt_warn_space and $line->log_note("Empty line expected."); 7105 $opt_warn_space and $line->log_note("Empty line expected.");
7106 } else { 7106 } else {
7107 $opt_warn_style and $line->log_warning("Comment expected."); 7107 $opt_warn_style and $line->log_warning("Comment expected.");
7108 } 7108 }
7109 $line->log_warning("Please use unified diffs (diff -u) for patches."); 7109 $line->log_warning("Please use unified diffs (diff -u) for patches.");
7110 }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { 7110 }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() {
7111 if ($seen_comment) { 7111 if ($seen_comment) {
7112 $opt_warn_space and $line->log_note("Empty line expected."); 7112 $opt_warn_space and $line->log_note("Empty line expected.");
7113 } else { 7113 } else {
7114 $opt_warn_style and $line->log_warning("Comment expected."); 7114 $opt_warn_style and $line->log_warning("Comment expected.");
7115 } 7115 }
7116 }], [PST_CENTER, undef, PST_TEXT, sub() { 7116 }], [PST_CENTER, undef, PST_TEXT, sub() {
7117 $opt_warn_space and $line->log_note("Empty line expected."); 7117 $opt_warn_space and $line->log_note("Empty line expected.");
7118 }], [PST_CFA, re_patch_cfa, PST_CH, sub() { 7118 }], [PST_CFA, re_patch_cfa, PST_CH, sub() {
7119 $current_fname = $m->text(1); 7119 $current_fname = $m->text(1);
7120 $current_ftype = get_filetype($line, $current_fname); 7120 $current_ftype = get_filetype($line, $current_fname);
7121 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); 7121 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype");
7122 $patched_files++; 7122 $patched_files++;
7123 $hunks = 0; 7123 $hunks = 0;
7124 }], [PST_CH, re_patch_ch, PST_CHD, sub() { 7124 }], [PST_CH, re_patch_ch, PST_CHD, sub() {
7125 $hunks++; 7125 $hunks++;
7126 }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { 7126 }], [PST_CHD, re_patch_chd, PST_CLD0, sub() {
7127 $dellines = ($m->has(2)) 7127 $dellines = ($m->has(2))
7128 ? (1 + $m->text(2) - $m->text(1)) 7128 ? (1 + $m->text(2) - $m->text(1))
7129 : ($m->text(1)); 7129 : ($m->text(1));
7130 }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { 7130 }], [PST_CLD0, re_patch_clc, PST_CLD, sub() {
7131 $check_hunk_line->(1, 0, PST_CLD0, false); 7131 $check_hunk_line->(1, 0, PST_CLD0, false);
7132 }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { 7132 }], [PST_CLD0, re_patch_cld, PST_CLD, sub() {
7133 $check_hunk_line->(1, 0, PST_CLD0, false); 7133 $check_hunk_line->(1, 0, PST_CLD0, false);
7134 }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { 7134 }], [PST_CLD0, re_patch_clm, PST_CLD, sub() {
7135 $check_hunk_line->(1, 0, PST_CLD0, false); 7135 $check_hunk_line->(1, 0, PST_CLD0, false);
7136 }], [PST_CLD, re_patch_clc, PST_CLD, sub() { 7136 }], [PST_CLD, re_patch_clc, PST_CLD, sub() {
7137 $check_hunk_line->(1, 0, PST_CLD0, false); 7137 $check_hunk_line->(1, 0, PST_CLD0, false);
7138 }], [PST_CLD, re_patch_cld, PST_CLD, sub() { 7138 }], [PST_CLD, re_patch_cld, PST_CLD, sub() {
7139 $check_hunk_line->(1, 0, PST_CLD0, false); 7139 $check_hunk_line->(1, 0, PST_CLD0, false);
7140 }], [PST_CLD, re_patch_clm, PST_CLD, sub() { 7140 }], [PST_CLD, re_patch_clm, PST_CLD, sub() {
7141 $check_hunk_line->(1, 0, PST_CLD0, false); 7141 $check_hunk_line->(1, 0, PST_CLD0, false);
7142 }], [PST_CLD, undef, PST_CLD0, sub() { 7142 }], [PST_CLD, undef, PST_CLD0, sub() {
7143 if ($dellines != 0) { 7143 if ($dellines != 0) {
7144 $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); 7144 $line->log_warning("Invalid number of deleted lines (${dellines} missing).");
7145 } 7145 }
7146 }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { 7146 }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() {
7147 $dellines = undef; 7147 $dellines = undef;
7148 $addlines = ($m->has(2)) 7148 $addlines = ($m->has(2))
7149 ? (1 + $m->text(2) - $m->text(1)) 7149 ? (1 + $m->text(2) - $m->text(1))
7150 : ($m->text(1)); 7150 : ($m->text(1));
7151 }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { 7151 }], [PST_CLA0, re_patch_clc, PST_CLA, sub() {
7152 $check_hunk_line->(0, 1, PST_CH, true); 7152 $check_hunk_line->(0, 1, PST_CH, true);
7153 }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { 7153 }], [PST_CLA0, re_patch_clm, PST_CLA, sub() {
7154 $check_hunk_line->(0, 1, PST_CH, true); 7154 $check_hunk_line->(0, 1, PST_CH, true);
7155 }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { 7155 }], [PST_CLA0, re_patch_cla, PST_CLA, sub() {
7156 $check_hunk_line->(0, 1, PST_CH, true); 7156 $check_hunk_line->(0, 1, PST_CH, true);
7157 }], [PST_CLA, re_patch_clc, PST_CLA, sub() { 7157 }], [PST_CLA, re_patch_clc, PST_CLA, sub() {
7158 $check_hunk_line->(0, 1, PST_CH, true); 7158 $check_hunk_line->(0, 1, PST_CH, true);
7159 }], [PST_CLA, re_patch_clm, PST_CLA, sub() { 7159 }], [PST_CLA, re_patch_clm, PST_CLA, sub() {
7160 $check_hunk_line->(0, 1, PST_CH, true); 7160 $check_hunk_line->(0, 1, PST_CH, true);
7161 }], [PST_CLA, re_patch_cla, PST_CLA, sub() { 7161 }], [PST_CLA, re_patch_cla, PST_CLA, sub() {
7162 $check_hunk_line->(0, 1, PST_CH, true); 7162 $check_hunk_line->(0, 1, PST_CH, true);
7163 }], [PST_CLA, undef, PST_CLA0, sub() { 7163 }], [PST_CLA, undef, PST_CLA0, sub() {
7164 if ($addlines != 0) { 7164 if ($addlines != 0) {
7165 $line->log_warning("Invalid number of added lines (${addlines} missing)."); 7165 $line->log_warning("Invalid number of added lines (${addlines} missing).");
7166 } 7166 }
7167 }], [PST_CLA0, undef, PST_CH, sub() { 7167 }], [PST_CLA0, undef, PST_CH, sub() {
7168 # 7168 #
7169 }], [PST_CH, undef, PST_TEXT, sub() { 7169 }], [PST_CH, undef, PST_TEXT, sub() {
7170 # 7170 #
7171 }], [PST_UFA, re_patch_ufa, PST_UH, sub() { 7171 }], [PST_UFA, re_patch_ufa, PST_UH, sub() {
7172 $current_fname = $m->text(1); 7172 $current_fname = $m->text(1);
7173 $current_ftype = get_filetype($line, $current_fname); 7173 $current_ftype = get_filetype($line, $current_fname);
7174 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); 7174 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype");
7175 $patched_files++; 7175 $patched_files++;
7176 $hunks = 0; 7176 $hunks = 0;
7177 }], [PST_UH, re_patch_uh, PST_UL, sub() { 7177 }], [PST_UH, re_patch_uh, PST_UL, sub() {
7178 $dellines = ($m->has(1) ? $m->text(2) : 1); 7178 $dellines = ($m->has(1) ? $m->text(2) : 1);
7179 $addlines = ($m->has(3) ? $m->text(4) : 1); 7179 $addlines = ($m->has(3) ? $m->text(4) : 1);
7180 $check_text->($line->text); 7180 $check_text->($line->text);
7181 if ($line->text =~ m"\r$") { 7181 if ($line->text =~ m"\r$") {
7182 $line->log_error("The hunk header must not end with a CR character."); 7182 $line->log_error("The hunk header must not end with a CR character.");
7183 $line->explain_error( 7183 $line->explain_error(
7184"The MacOS X patch utility cannot handle these."); 7184"The MacOS X patch utility cannot handle these.");
7185 } 7185 }
7186 $hunks++; 7186 $hunks++;
7187 $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); 7187 $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef);
7188 $leading_context_lines = 0; 7188 $leading_context_lines = 0;
7189 $trailing_context_lines = 0; 7189 $trailing_context_lines = 0;
7190 }], [PST_UL, re_patch_uld, PST_UL, sub() { 7190 }], [PST_UL, re_patch_uld, PST_UL, sub() {
7191 $check_hunk_line->(1, 0, PST_UH, false); 7191 $check_hunk_line->(1, 0, PST_UH, false);
7192 }], [PST_UL, re_patch_ula, PST_UL, sub() { 7192 }], [PST_UL, re_patch_ula, PST_UL, sub() {
7193 $check_hunk_line->(0, 1, PST_UH, true); 7193 $check_hunk_line->(0, 1, PST_UH, true);
7194 }], [PST_UL, re_patch_ulc, PST_UL, sub() { 7194 }], [PST_UL, re_patch_ulc, PST_UL, sub() {
7195 $check_hunk_line->(1, 1, PST_UH, true); 7195 $check_hunk_line->(1, 1, PST_UH, true);
7196 }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { 7196 }], [PST_UL, re_patch_ulnonl, PST_UL, sub() {
7197 # 7197 #
7198 }], [PST_UL, re_patch_empty, PST_UL, sub() { 7198 }], [PST_UL, re_patch_empty, PST_UL, sub() {
7199 $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); 7199 $opt_warn_space and $line->log_note("Leading white-space missing in hunk.");
7200 $check_hunk_line->(1, 1, PST_UH, false); 7200 $check_hunk_line->(1, 1, PST_UH, false);
7201 }], [PST_UL, undef, PST_UH, sub() { 7201 }], [PST_UL, undef, PST_UH, sub() {
7202 if ($dellines != 0 || $addlines != 0) { 7202 if ($dellines != 0 || $addlines != 0) {
7203 $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); 7203 $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected).");
7204 } 7204 }
7205 }], [PST_UH, undef, PST_TEXT, sub() { 7205 }], [PST_UH, undef, PST_TEXT, sub() {
7206 ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); 7206 ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}.");
7207 }]]; 7207 }]];
7208 7208
7209 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); 7209 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()");
7210 7210
7211 checkperms($fname); 7211 checkperms($fname);
7212 if (!($lines = load_lines($fname, false))) { 7212 if (!($lines = load_lines($fname, false))) {
7213 log_error($fname, NO_LINE_NUMBER, "Could not be read."); 7213 log_error($fname, NO_LINE_NUMBER, "Could not be read.");
7214 return; 7214 return;
7215 } 7215 }
7216 if (@{$lines} == 0) { 7216 if (@{$lines} == 0) {
7217 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 7217 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
7218 return; 7218 return;
7219 } 7219 }
7220 7220
7221 $state = PST_START; 7221 $state = PST_START;
7222 $dellines = undef; 7222 $dellines = undef;
7223 $addlines = undef; 7223 $addlines = undef;
7224 $patched_files = 0; 7224 $patched_files = 0;
7225 $seen_comment = false; 7225 $seen_comment = false;
7226 $current_fname = undef; 7226 $current_fname = undef;
7227 $current_ftype = undef; 7227 $current_ftype = undef;
7228 $hunks = undef; 7228 $hunks = undef;
7229 7229
7230 for (my $lineno = 0; $lineno <= $#{$lines}; ) { 7230 for (my $lineno = 0; $lineno <= $#{$lines}; ) {
7231 $line = $lines->[$lineno]; 7231 $line = $lines->[$lineno];
7232 my $text = $line->text; 7232 my $text = $line->text;
7233 7233
7234 $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); 7234 $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text");
7235 7235
7236 my $found = false; 7236 my $found = false;
7237 foreach my $t (@{$transitions}) { 7237 foreach my $t (@{$transitions}) {
7238 if ($state == $t->[0]) { 7238 if ($state == $t->[0]) {
7239 if (!defined($t->[1])) { 7239 if (!defined($t->[1])) {
7240 $m = undef; 7240 $m = undef;
7241 } elsif ($text =~ $t->[1]) { 7241 } elsif ($text =~ $t->[1]) {
7242 $opt_debug_patches and $line->log_debug($t->[1]); 7242 $opt_debug_patches and $line->log_debug($t->[1]);
7243 $m = PkgLint::SimpleMatch->new($text, \@-, \@+); 7243 $m = PkgLint::SimpleMatch->new($text, \@-, \@+);
7244 } else { 7244 } else {
7245 next; 7245 next;
7246 } 7246 }
7247 $redostate = undef; 7247 $redostate = undef;
7248 $nextstate = $t->[2]; 7248 $nextstate = $t->[2];
7249 $t->[3]->(); 7249 $t->[3]->();
7250 if (defined($redostate)) { 7250 if (defined($redostate)) {
7251 $state = $redostate; 7251 $state = $redostate;
7252 } else { 7252 } else {
7253 $state = $nextstate; 7253 $state = $nextstate;
7254 if (defined($t->[1])) { 7254 if (defined($t->[1])) {
7255 $lineno++; 7255 $lineno++;
7256 } 7256 }
7257 } 7257 }
7258 $found = true; 7258 $found = true;
7259 last; 7259 last;
7260 } 7260 }
7261 } 7261 }
7262 7262
7263 if (!$found) { 7263 if (!$found) {
7264 $line->log_error("Parse error: state=${state}"); 7264 $line->log_error("Parse error: state=${state}");
7265 $state = PST_TEXT; 7265 $state = PST_TEXT;
7266 $lineno++; 7266 $lineno++;
7267 } 7267 }
7268 } 7268 }
7269 7269
7270 while ($state != PST_TEXT) { 7270 while ($state != PST_TEXT) {
7271 $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); 7271 $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]");
7272 7272
7273 my $found = false; 7273 my $found = false;
7274 foreach my $t (@{$transitions}) { 7274 foreach my $t (@{$transitions}) {
7275 if ($state == $t->[0] && !defined($t->[1])) { 7275 if ($state == $t->[0] && !defined($t->[1])) {
7276 my $newstate; 7276 my $newstate;
7277 7277
7278 $m = undef; 7278 $m = undef;
7279 $redostate = undef; 7279 $redostate = undef;
7280 $nextstate = $t->[2]; 7280 $nextstate = $t->[2];
7281 $t->[3]->(); 7281 $t->[3]->();
7282 $newstate = (defined($redostate)) ? $redostate : $nextstate; 7282 $newstate = (defined($redostate)) ? $redostate : $nextstate;
7283 if ($newstate == $state) { 7283 if ($newstate == $state) {
7284 log_fatal($fname, "EOF", "Internal error in the patch transition table."); 7284 log_fatal($fname, "EOF", "Internal error in the patch transition table.");
7285 } 7285 }
7286 $state = $newstate; 7286 $state = $newstate;
7287 $found = true; 7287 $found = true;
7288 last; 7288 last;
7289 } 7289 }
7290 } 7290 }
7291 7291
7292 if (!$found) { 7292 if (!$found) {
7293 log_error($fname, "EOF", "Parse error: state=${state}"); 7293 log_error($fname, "EOF", "Parse error: state=${state}");
7294 $state = PST_TEXT; 7294 $state = PST_TEXT;
7295 } 7295 }
7296 } 7296 }
7297 7297
7298 if ($patched_files > 1) { 7298 if ($patched_files > 1) {
7299 log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); 7299 log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one.");
7300 7300
7301 } elsif ($patched_files == 0) { 7301 } elsif ($patched_files == 0) {
7302 log_error($fname, NO_LINE_NUMBER, "Contains no patch."); 7302 log_error($fname, NO_LINE_NUMBER, "Contains no patch.");
7303 } 7303 }
7304 7304
7305 checklines_trailing_empty_lines($lines); 7305 checklines_trailing_empty_lines($lines);
7306} 7306}
7307 7307
7308sub checkfile_PLIST($) { 7308sub checkfile_PLIST($) {
7309 my ($fname) = @_; 7309 my ($fname) = @_;
7310 my ($lines, $last_file_seen); 7310 my ($lines, $last_file_seen);
7311 7311
7312 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); 7312 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()");
7313 7313
7314 checkperms($fname); 7314 checkperms($fname);
7315 if (!($lines = load_file($fname))) { 7315 if (!($lines = load_file($fname))) {
7316 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 7316 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
7317 return; 7317 return;
7318 } 7318 }
7319 if (@{$lines} == 0) { 7319 if (@{$lines} == 0) {
7320 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 7320 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
7321 return; 7321 return;
7322 } 7322 }
7323 checkline_rcsid($lines->[0], "\@comment "); 7323 checkline_rcsid($lines->[0], "\@comment ");
7324 7324
7325 if (@$lines == 1) { 7325 if (@$lines == 1) {
7326 $lines->[0]->log_warning("PLIST files shouldn't be empty."); 7326 $lines->[0]->log_warning("PLIST files shouldn't be empty.");
7327 $lines->[0]->explain_warning( 7327 $lines->[0]->explain_warning(
7328"One reason for empty PLISTs is that this is a newly created package", 7328"One reason for empty PLISTs is that this is a newly created package",
7329"and that the author didn't run \"bmake print-PLIST\" after installing", 7329"and that the author didn't run \"bmake print-PLIST\" after installing",
7330"the files.", 7330"the files.",
7331"", 7331"",
7332"Another reason, common for Perl packages, is that the final PLIST is", 7332"Another reason, common for Perl packages, is that the final PLIST is",
7333"automatically generated. Since the source PLIST is not used at all,", 7333"automatically generated. Since the source PLIST is not used at all,",
7334"you can remove it.", 7334"you can remove it.",
7335"", 7335"",
7336"Meta packages also don't need a PLIST file."); 7336"Meta packages also don't need a PLIST file.");
7337 } 7337 }
7338 7338
7339 # Get the list of all files from the PLIST. 7339 # Get the list of all files from the PLIST.
7340 my $all_files = {}; 7340 my $all_files = {};
7341 my $all_dirs = {}; 7341 my $all_dirs = {};
7342 my $extra_lines = []; 7342 my $extra_lines = [];
7343 if (basename($fname) eq "PLIST.common_end") { 7343 if (basename($fname) eq "PLIST.common_end") {
7344 my $common_lines = load_file(dirname($fname) . "/PLIST.common"); 7344 my $common_lines = load_file(dirname($fname) . "/PLIST.common");
7345 if ($common_lines) { 7345 if ($common_lines) {
7346 $extra_lines = $common_lines; 7346 $extra_lines = $common_lines;
7347 } 7347 }
7348 } 7348 }
7349 7349
7350 foreach my $line (@{$extra_lines}, @{$lines}) { 7350 foreach my $line (@{$extra_lines}, @{$lines}) {
7351 my $text = $line->text; 7351 my $text = $line->text;
7352 7352
7353 if ($text =~ m"\$\{([\w_]+)\}(.*)") { 7353 if ($text =~ m"\$\{([\w_]+)\}(.*)") {
7354 if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { 7354 if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) {
7355 $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); 7355 $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1.");
7356 $text = $2; 7356 $text = $2;
7357 } 7357 }
7358 } 7358 }
7359  7359
7360 if ($text =~ m"^[\w\$]") { 7360 if ($text =~ m"^[\w\$]") {
7361 $all_files->{$text} = $line; 7361 $all_files->{$text} = $line;
7362 my $dir = $text; 7362 my $dir = $text;
7363 while ($dir =~ s,/[^/]+$,,) { 7363 while ($dir =~ s,/[^/]+$,,) {
7364 $all_dirs->{$dir} = $line; 7364 $all_dirs->{$dir} = $line;
7365 } 7365 }
7366 } 7366 }
7367 if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { 7367 if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") {
7368 my $dir = $1; 7368 my $dir = $1;
7369 do { 7369 do {
7370 $all_dirs->{$dir} = $line; 7370 $all_dirs->{$dir} = $line;
7371 } while ($dir =~ s,/[^/]+$,,); 7371 } while ($dir =~ s,/[^/]+$,,);
7372 } 7372 }
7373 } 7373 }
7374 7374
7375 foreach my $line (@{$lines}) { 7375 foreach my $line (@{$lines}) {
7376 my $text = $line->text; 7376 my $text = $line->text;
7377 7377
7378 if ($text =~ /\s$/) { 7378 if ($text =~ /\s$/) {
7379 $line->log_error("pkgsrc does not support filenames ending in white-space."); 7379 $line->log_error("pkgsrc does not support filenames ending in white-space.");
7380 $line->explain_error( 7380 $line->explain_error(
7381"Each character in the PLIST is relevant, even trailing white-space."); 7381"Each character in the PLIST is relevant, even trailing white-space.");
7382 } 7382 }
7383 7383
7384 # @foo directives. 7384 # @foo directives.
7385 if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { 7385 if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) {
7386 my ($cmd, $arg) = ($1, $2); 7386 my ($cmd, $arg) = ($1, $2);
7387 7387
7388 if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { 7388 if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") {
7389 my ($rmdir, $rest) = ($1, $2); 7389 my ($rmdir, $rest) = ($1, $2);
7390 if ($rest !~ m"(?:true|\$\{TRUE\})") { 7390 if ($rest !~ m"(?:true|\$\{TRUE\})") {
7391 $line->log_warning("Please use \"\@dirrm\" instead of \"\@unexec rmdir\"."); 7391 $line->log_warning("Please use \"\@dirrm\" instead of \"\@unexec rmdir\".");
7392 } 7392 }
7393 7393
7394 } elsif (($cmd eq "exec" || $cmd eq "unexec")) { 7394 } elsif (($cmd eq "exec" || $cmd eq "unexec")) {
7395 if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { 7395 if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) {
7396 $line->log_warning("\@exec/unexec install-info is deprecated."); 7396 $line->log_warning("\@exec/unexec install-info is deprecated.");
7397 7397
7398 } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { 7398 } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") {
7399 $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); 7399 $line->log_error("ldconfig must be used with \"||/usr/bin/true\".");
7400 } 7400 }
7401 7401
7402 } elsif ($cmd eq "comment") { 7402 } elsif ($cmd eq "comment") {
7403 # nothing to do 7403 # nothing to do
7404 7404
7405 } elsif ($cmd eq "dirrm") { 7405 } elsif ($cmd eq "dirrm") {
7406 my @ids = get_shared_dir_ids($line, $arg); 7406 my @ids = get_shared_dir_ids($line, $arg);
7407 if (@ids == 0) { 7407 if (@ids == 0) {
7408 # Nothing to do 7408 # Nothing to do
7409 } elsif (@ids == 1) { 7409 } elsif (@ids == 1) {
7410 $line->log_warning("Please add \"USE_DIRS+= $ids[0]\" to the package Makefile and remove this line."); 7410 $line->log_warning("Please add \"USE_DIRS+= $ids[0]\" to the package Makefile and remove this line.");
7411 } else { 7411 } else {
7412 my $s = join(" or ", map { "\"USE_DIRS+= $_\"" } @ids); 7412 my $s = join(" or ", map { "\"USE_DIRS+= $_\"" } @ids);
7413 $line->log_warning("Please add $s to the package Makefile and remove this line."); 7413 $line->log_warning("Please add $s to the package Makefile and remove this line.");
7414 } 7414 }
7415 if (!exists($all_dirs->{$arg})) { 7415 if (!exists($all_dirs->{$arg})) {
7416 $line->log_warning("The PLIST does not contain files for \"$arg\"."); 7416 $line->log_warning("The PLIST does not contain files for \"$arg\".");
7417 $line->explain_warning( 7417 $line->explain_warning(
7418"A package should only remove those directories that it created. When", 7418"A package should only remove those directories that it created. When",
7419"there are no files in the directory, it is unlikely that the package", 7419"there are no files in the directory, it is unlikely that the package",
7420"created the directory."); 7420"created the directory.");
7421 } 7421 }
7422 7422
 7423 if ($pkgpath ne "graphics/hicolor-icon-theme" && $arg =~ m"^share/icons/hicolor(?:$|/)") {
 7424 $line->log_warning("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line.");
 7425 }
7423 } elsif ($cmd eq "imake-man") { 7426 } elsif ($cmd eq "imake-man") {
7424 my (@args) = split(/\s+/, $arg); 7427 my (@args) = split(/\s+/, $arg);
7425 if (@args != 3) { 7428 if (@args != 3) {
7426 $line->log_warning("Invalid number of arguments for imake-man."); 7429 $line->log_warning("Invalid number of arguments for imake-man.");
7427 } else { 7430 } else {
7428 if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { 7431 if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") {
7429 warn_about_PLIST_imake_mannewsuffix($line); 7432 warn_about_PLIST_imake_mannewsuffix($line);
7430 } 7433 }
7431 } 7434 }
7432 7435
7433 } else { 7436 } else {
7434 $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); 7437 $line->log_warning("Unknown PLIST directive \"\@$cmd\".");
7435 } 7438 }
7436 7439
7437 # Pathnames. 7440 # Pathnames.
7438 } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { 7441 } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") {
7439 my ($dirname, $basename) = ($1, $2); 7442 my ($dirname, $basename) = ($1, $2);
7440 7443
7441 if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { 7444 if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) {
7442 if (defined($last_file_seen)) { 7445 if (defined($last_file_seen)) {
7443 if ($last_file_seen gt $text) { 7446 if ($last_file_seen gt $text) {
7444 $line->log_warning("${text} should be sorted before ${last_file_seen}."); 7447 $line->log_warning("${text} should be sorted before ${last_file_seen}.");
7445 } elsif ($last_file_seen eq $text) { 7448 } elsif ($last_file_seen eq $text) {
7446 $line->log_warning("Duplicate filename."); 7449 $line->log_warning("Duplicate filename.");
7447 } 7450 }
7448 } 7451 }
7449 $last_file_seen = $text; 7452 $last_file_seen = $text;
7450 } 7453 }
7451 7454
7452 if ($basename =~ m"\$\{IMAKE_MANNEWSUFFIX\}") { 7455 if ($basename =~ m"\$\{IMAKE_MANNEWSUFFIX\}") {
7453 warn_about_PLIST_imake_mannewsuffix($line); 7456 warn_about_PLIST_imake_mannewsuffix($line);
7454 } 7457 }
7455 7458
7456 if ($dirname =~ m"^bin/") { 7459 if ($dirname =~ m"^bin/") {
7457 $line->log_warning("The bin/ directory should not have subdirectories."); 7460 $line->log_warning("The bin/ directory should not have subdirectories.");
7458 7461
7459 } elsif ($dirname eq "bin") { 7462 } elsif ($dirname eq "bin") {
7460 7463
7461 if (exists($all_files->{"man/man1/${basename}.1"})) { 7464 if (exists($all_files->{"man/man1/${basename}.1"})) {
7462 # Fine. 7465 # Fine.
7463 } elsif (exists($all_files->{"man/man6/${basename}.6"})) { 7466 } elsif (exists($all_files->{"man/man6/${basename}.6"})) {
7464 # Fine. 7467 # Fine.
7465 } elsif (exists($all_files->{"\${IMAKE_MAN_DIR}/${basename}.\${IMAKE_MANNEWSUFFIX}"})) { 7468 } elsif (exists($all_files->{"\${IMAKE_MAN_DIR}/${basename}.\${IMAKE_MANNEWSUFFIX}"})) {
7466 # Fine. 7469 # Fine.
7467 } else { 7470 } else {
7468 $opt_warn_extra and $line->log_warning("Manual page missing for bin/${basename}."); 7471 $opt_warn_extra and $line->log_warning("Manual page missing for bin/${basename}.");
7469 } 7472 }
7470 7473
7471 } elsif ($text =~ m"^doc/") { 7474 } elsif ($text =~ m"^doc/") {
7472 $line->log_error("Documentation must be installed under share/doc, not doc."); 7475 $line->log_error("Documentation must be installed under share/doc, not doc.");
7473 7476
7474 } elsif ($text =~ m"^etc/rc\.d/") { 7477 } elsif ($text =~ m"^etc/rc\.d/") {
7475 $line->log_error("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework."); 7478 $line->log_error("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework.");
7476 7479
7477 } elsif ($text =~ m"^etc/") { 7480 } elsif ($text =~ m"^etc/") {
7478 my $f = "mk/pkginstall/bsd.pkginstall.mk"; 7481 my $f = "mk/pkginstall/bsd.pkginstall.mk";
7479 7482
7480 assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file."); 7483 assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file.");
7481 $line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}."); 7484 $line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}.");
7482 7485
7483 } elsif ($text =~ m"^include/.*\.(?:h|hpp)$") { 7486 } elsif ($text =~ m"^include/.*\.(?:h|hpp)$") {
7484 # Fine. 7487 # Fine.
7485 7488
7486 } elsif ($text eq "info/dir") { 7489 } elsif ($text eq "info/dir") {
7487 $line->log_error("\"info/dir\" must not be listed. Use install-info to add/remove an entry."); 7490 $line->log_error("\"info/dir\" must not be listed. Use install-info to add/remove an entry.");
7488 7491
7489 } elsif ($text =~ m"^info/.+$") { 7492 } elsif ($text =~ m"^info/.+$") {
7490 if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"INFO_FILES"})) { 7493 if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"INFO_FILES"})) {
7491 $line->log_warning("Packages that install info files should set INFO_FILES."); 7494 $line->log_warning("Packages that install info files should set INFO_FILES.");
7492 } 7495 }
7493 7496
7494 } elsif (defined($effective_pkgbase) && $text =~ m"^lib/\Q${effective_pkgbase}\E/") { 7497 } elsif (defined($effective_pkgbase) && $text =~ m"^lib/\Q${effective_pkgbase}\E/") {
7495 # Fine. 7498 # Fine.
7496 7499
7497 } elsif ($text =~ m"^lib/locale/") { 7500 } elsif ($text =~ m"^lib/locale/") {
7498 $line->log_error("\"lib/locale\" must not be listed. Use \${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead."); 7501 $line->log_error("\"lib/locale\" must not be listed. Use \${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead.");
7499 7502
7500 } elsif ($text =~ m"^(lib/(?:.*/)*)([^/]+)\.(so|a|la)$") { 7503 } elsif ($text =~ m"^(lib/(?:.*/)*)([^/]+)\.(so|a|la)$") {
7501 my ($dir, $lib, $ext) = ($1, $2, $3); 7504 my ($dir, $lib, $ext) = ($1, $2, $3);
7502 7505
7503 if ($dir eq "lib/" && $lib !~ m"^lib") { 7506 if ($dir eq "lib/" && $lib !~ m"^lib") {
7504 $opt_warn_extra and $line->log_warning("Library filename does not start with \"lib\"."); 7507 $opt_warn_extra and $line->log_warning("Library filename does not start with \"lib\".");
7505 } 7508 }
7506 if ($ext eq "la") { 7509 if ($ext eq "la") {
7507 if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_LIBTOOL"})) { 7510 if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_LIBTOOL"})) {
7508 $line->log_warning("Packages that install libtool libraries should define USE_LIBTOOL."); 7511 $line->log_warning("Packages that install libtool libraries should define USE_LIBTOOL.");
7509 } 7512 }
7510 } 7513 }
7511 7514
7512 } elsif ($text =~ m"^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$") { 7515 } elsif ($text =~ m"^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$") {
7513 my ($cat_or_man, $section, $manpage, $ext, $gz) = ($1, $2, $3, $4, $5); 7516 my ($cat_or_man, $section, $manpage, $ext, $gz) = ($1, $2, $3, $4, $5);
7514 7517
7515 if ($section !~ m"^[\dln]$") { 7518 if ($section !~ m"^[\dln]$") {
7516 $line->log_warning("Unknown section \"${section}\" for manual page."); 7519 $line->log_warning("Unknown section \"${section}\" for manual page.");
7517 } 7520 }
7518 7521
7519 if ($cat_or_man eq "cat" && !exists($all_files->{"man/man${section}/${manpage}.${section}"})) { 7522 if ($cat_or_man eq "cat" && !exists($all_files->{"man/man${section}/${manpage}.${section}"})) {
7520 $line->log_warning("Preformatted manual page without unformatted one."); 7523 $line->log_warning("Preformatted manual page without unformatted one.");
7521 } 7524 }
7522 7525
7523 if ($cat_or_man eq "cat") { 7526 if ($cat_or_man eq "cat") {
7524 if ($ext ne "0") { 7527 if ($ext ne "0") {
7525 $line->log_warning("Preformatted manual pages should end in \".0\"."); 7528 $line->log_warning("Preformatted manual pages should end in \".0\".");
7526 } 7529 }
7527 } else { 7530 } else {
7528 if ($section ne $ext) { 7531 if ($section ne $ext) {
7529 $line->log_warning("Mismatch between the section (${section}) and extension (${ext}) of the manual page."); 7532 $line->log_warning("Mismatch between the section (${section}) and extension (${ext}) of the manual page.");
7530 } 7533 }
7531 } 7534 }
7532 7535
7533 if (defined($gz)) { 7536 if (defined($gz)) {
7534 $line->log_note("The .gz extension is unnecessary for manual pages."); 7537 $line->log_note("The .gz extension is unnecessary for manual pages.");
7535 $line->explain_note( 7538 $line->explain_note(
7536"Whether the manual pages are installed in compressed form or not is", 7539"Whether the manual pages are installed in compressed form or not is",
7537"configured by the pkgsrc user. Compression and decompression takes place", 7540"configured by the pkgsrc user. Compression and decompression takes place",
7538"automatically, no matter if the .gz extension is mentioned in the PLIST", 7541"automatically, no matter if the .gz extension is mentioned in the PLIST",
7539"or not."); 7542"or not.");
7540 } 7543 }
7541 7544
7542 } elsif ($text =~ m"^man/cat") { 7545 } elsif ($text =~ m"^man/cat") {
7543 $line->log_warning("Invalid filename \"${text}\" for preformatted manual page."); 7546 $line->log_warning("Invalid filename \"${text}\" for preformatted manual page.");
7544 7547
7545 } elsif ($text =~ m"^man/man") { 7548 } elsif ($text =~ m"^man/man") {
7546 $line->log_warning("Invalid filename \"${text}\" for unformatted manual page."); 7549 $line->log_warning("Invalid filename \"${text}\" for unformatted manual page.");
7547 7550
7548 } elsif ($text =~ m"^sbin/(.*)") { 7551 } elsif ($text =~ m"^sbin/(.*)") {
7549 my ($binname) = ($1); 7552 my ($binname) = ($1);
7550 7553
7551 if (!exists($all_files->{"man/man8/${binname}.8"})) { 7554 if (!exists($all_files->{"man/man8/${binname}.8"})) {
7552 $opt_warn_extra and $line->log_warning("Manual page missing for sbin/${binname}."); 7555 $opt_warn_extra and $line->log_warning("Manual page missing for sbin/${binname}.");
7553 } 7556 }
7554 7557
7555 } elsif ($dirname eq "share/aclocal" && $basename =~ m"\.m4$") { 7558 } elsif ($dirname eq "share/aclocal" && $basename =~ m"\.m4$") {
7556 # Fine. 7559 # Fine.
7557 7560
7558 } elsif ($text =~ m"^share/doc/html/") { 7561 } elsif ($text =~ m"^share/doc/html/") {
7559 $opt_warn_plist_depr and $line->log_warning("Use of \"share/doc/html\" is deprecated. Use \"share/doc/\${PKGBASE}\" instead."); 7562 $opt_warn_plist_depr and $line->log_warning("Use of \"share/doc/html\" is deprecated. Use \"share/doc/\${PKGBASE}\" instead.");
7560 7563
7561 } elsif (defined($effective_pkgbase) && $text =~ m"^share/doc/\Q${effective_pkgbase}\E/") { 7564 } elsif (defined($effective_pkgbase) && $text =~ m"^share/doc/\Q${effective_pkgbase}\E/") {
7562 # Fine. 7565 # Fine.
7563 7566
7564 } elsif (defined($effective_pkgbase) && $text =~ m"^share/examples/\Q${effective_pkgbase}\E/") { 7567 } elsif (defined($effective_pkgbase) && $text =~ m"^share/examples/\Q${effective_pkgbase}\E/") {
7565 # Fine. 7568 # Fine.
7566 7569
7567 } elsif (defined($effective_pkgbase) && $text =~ m"^share/\Q${effective_pkgbase}\E/") { 7570 } elsif (defined($effective_pkgbase) && $text =~ m"^share/\Q${effective_pkgbase}\E/") {
7568 # Fine. 7571 # Fine.
7569 7572
 7573 } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor/icon-theme\.cache") {
 7574 $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line.");
 7575
7570 } elsif ($text =~ m"^share/info/") { 7576 } elsif ($text =~ m"^share/info/") {
7571 $line->log_warning("Info pages should be installed into info/, not share/info/."); 7577 $line->log_warning("Info pages should be installed into info/, not share/info/.");
7572 $line->explain_warning( 7578 $line->explain_warning(
7573"To fix this, you should add INFO_FILES=yes to the package Makefile."); 7579"To fix this, you should add INFO_FILES=yes to the package Makefile.");
7574 7580
7575 } elsif ($text =~ m"^share/locale/[\w\@_]+/LC_MESSAGES/[^/]+\.mo$") { 7581 } elsif ($text =~ m"^share/locale/[\w\@_]+/LC_MESSAGES/[^/]+\.mo$") {
7576 # Fine. 7582 # Fine.
7577 7583
7578 } elsif ($text =~ m"^share/man/") { 7584 } elsif ($text =~ m"^share/man/") {
7579 $line->log_warning("Man pages should be installed into man/, not share/man/."); 7585 $line->log_warning("Man pages should be installed into man/, not share/man/.");
7580 7586
7581 } else { 7587 } else {
7582 $opt_debug_unchecked and $line->log_debug("Unchecked pathname \"${text}\"."); 7588 $opt_debug_unchecked and $line->log_debug("Unchecked pathname \"${text}\".");
7583 } 7589 }
7584 7590
7585 if ($text =~ /\${PKGLOCALEDIR}/ && defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_PKGLOCALEDIR"})) { 7591 if ($text =~ /\${PKGLOCALEDIR}/ && defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_PKGLOCALEDIR"})) {
7586 $line->log_warning("PLIST contains \${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found."); 7592 $line->log_warning("PLIST contains \${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found.");
7587 } 7593 }
7588 7594
7589 if ($text =~ m"/CVS/") { 7595 if ($text =~ m"/CVS/") {
7590 $line->log_warning("CVS files should not be in the PLIST."); 7596 $line->log_warning("CVS files should not be in the PLIST.");
7591 } 7597 }
7592 if ($text =~ m"\.orig$") { 7598 if ($text =~ m"\.orig$") {
7593 $line->log_warning(".orig files should not be in the PLIST."); 7599 $line->log_warning(".orig files should not be in the PLIST.");
7594 } 7600 }
7595 if ($text =~ m"/perllocal\.pod$") { 7601 if ($text =~ m"/perllocal\.pod$") {
7596 $line->log_warning("perllocal.pod files should not be in the PLIST."); 7602 $line->log_warning("perllocal.pod files should not be in the PLIST.");
7597 $line->explain_warning( 7603 $line->explain_warning(
7598"This file is handled automatically by the INSTALL/DEINSTALL scripts,", 7604"This file is handled automatically by the INSTALL/DEINSTALL scripts,",
7599"since its contents changes frequently."); 7605"since its contents changes frequently.");
7600 } 7606 }
7601 7607
7602 if ($text =~ m"^(.*)(\.a|\.so[0-9.]*)$") { 7608 if ($text =~ m"^(.*)(\.a|\.so[0-9.]*)$") {
7603 my ($basename, $ext) = ($1, $2); 7609 my ($basename, $ext) = ($1, $2);
7604 7610
7605 if (exists($all_files->{"${basename}.la"})) { 7611 if (exists($all_files->{"${basename}.la"})) {
7606 $line->log_warning("Redundant library found. The libtool library is in line " . $all_files->{"${basename}.la"}->lines . "."); 7612 $line->log_warning("Redundant library found. The libtool library is in line " . $all_files->{"${basename}.la"}->lines . ".");
7607 } 7613 }
7608 } 7614 }
7609 7615
7610 } elsif ($text =~ m"^\$\{[\w_]+\}$") { 7616 } elsif ($text =~ m"^\$\{[\w_]+\}$") {
7611 # A variable on its own line. 7617 # A variable on its own line.
7612 7618
7613 } else { 7619 } else {
7614 $line->log_error("Unknown line type."); 7620 $line->log_error("Unknown line type.");
7615 } 7621 }
7616 } 7622 }
7617 checklines_trailing_empty_lines($lines); 7623 checklines_trailing_empty_lines($lines);
7618 autofix($lines); 7624 autofix($lines);
7619} 7625}
7620 7626
7621sub checkfile($) { 7627sub checkfile($) {
7622 my ($fname) = @_; 7628 my ($fname) = @_;
7623 my ($st, $basename); 7629 my ($st, $basename);
7624 7630
7625 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile()"); 7631 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile()");
7626 7632
7627 $basename = basename($fname); 7633 $basename = basename($fname);
7628 if ($basename =~ m"^(?:work.*|.*~|.*\.orig|.*\.rej)$") { 7634 if ($basename =~ m"^(?:work.*|.*~|.*\.orig|.*\.rej)$") {
7629 if ($opt_import) { 7635 if ($opt_import) {
7630 log_error($fname, NO_LINE_NUMBER, "Must be cleaned up before committing the package."); 7636 log_error($fname, NO_LINE_NUMBER, "Must be cleaned up before committing the package.");
7631 } 7637 }
7632 return; 7638 return;
7633 } 7639 }
7634 7640
7635 if (!($st = lstat($fname))) { 7641 if (!($st = lstat($fname))) {
7636 log_error($fname, NO_LINE_NUMBER, "$!"); 7642 log_error($fname, NO_LINE_NUMBER, "$!");
7637 return; 7643 return;
7638 } 7644 }
7639 if (S_ISDIR($st->mode)) { 7645 if (S_ISDIR($st->mode)) {
7640 if ($basename eq "files" || $basename eq "patches" || $basename eq "CVS") { 7646 if ($basename eq "files" || $basename eq "patches" || $basename eq "CVS") {
7641 # Ok 7647 # Ok
7642 7648
7643 } elsif (!is_emptydir($fname)) { 7649 } elsif (!is_emptydir($fname)) {
7644 log_warning($fname, NO_LINE_NUMBER, "Unknown directory name."); 7650 log_warning($fname, NO_LINE_NUMBER, "Unknown directory name.");
7645 } 7651 }
7646 7652
7647 } elsif (S_ISLNK($st->mode)) { 7653 } elsif (S_ISLNK($st->mode)) {
7648 if ($basename !~ m"^work") { 7654 if ($basename !~ m"^work") {
7649 log_warning($fname, NO_LINE_NUMBER, "Unknown symlink name."); 7655 log_warning($fname, NO_LINE_NUMBER, "Unknown symlink name.");
7650 } 7656 }
7651 7657
7652 } elsif (!S_ISREG($st->mode)) { 7658 } elsif (!S_ISREG($st->mode)) {
7653 log_error($fname, NO_LINE_NUMBER, "Only files and directories are allowed in pkgsrc."); 7659 log_error($fname, NO_LINE_NUMBER, "Only files and directories are allowed in pkgsrc.");
7654 7660
7655 } elsif ($basename eq "ALTERNATIVES") { 7661 } elsif ($basename eq "ALTERNATIVES") {
7656 $opt_check_ALTERNATIVES and checkfile_ALTERNATIVES($fname); 7662 $opt_check_ALTERNATIVES and checkfile_ALTERNATIVES($fname);
7657 7663
7658 } elsif ($basename eq "buildlink3.mk") { 7664 } elsif ($basename eq "buildlink3.mk") {
7659 $opt_check_bl3 and checkfile_buildlink3_mk($fname); 7665 $opt_check_bl3 and checkfile_buildlink3_mk($fname);
7660 7666
7661 } elsif ($basename =~ m"^(?:.*\.mk|Makefile.*)$") { 7667 } elsif ($basename =~ m"^(?:.*\.mk|Makefile.*)$") {
7662 $opt_check_mk and checkfile_mk($fname); 7668 $opt_check_mk and checkfile_mk($fname);
7663 7669
7664 } elsif ($basename =~ m"^DESCR") { 7670 } elsif ($basename =~ m"^DESCR") {
7665 $opt_check_DESCR and checkfile_DESCR($fname); 7671 $opt_check_DESCR and checkfile_DESCR($fname);
7666 7672
7667 } elsif ($basename =~ m"^distinfo") { 7673 } elsif ($basename =~ m"^distinfo") {
7668 $opt_check_distinfo and checkfile_distinfo($fname); 7674 $opt_check_distinfo and checkfile_distinfo($fname);
7669 7675
7670 } elsif ($basename eq "DEINSTALL" || $basename eq "INSTALL") { 7676 } elsif ($basename eq "DEINSTALL" || $basename eq "INSTALL") {
7671 $opt_check_INSTALL and checkfile_INSTALL($fname); 7677 $opt_check_INSTALL and checkfile_INSTALL($fname);
7672 7678
7673 } elsif ($basename =~ m"^MESSAGE") { 7679 } elsif ($basename =~ m"^MESSAGE") {
7674 $opt_check_MESSAGE and checkfile_MESSAGE($fname); 7680 $opt_check_MESSAGE and checkfile_MESSAGE($fname);
7675 7681
7676 } elsif ($basename =~ m"^patch-[A-Za-z0-9]*$") { 7682 } elsif ($basename =~ m"^patch-[A-Za-z0-9]*$") {
7677 $opt_check_patches and checkfile_patch($fname); 7683 $opt_check_patches and checkfile_patch($fname);
7678 7684
7679 } elsif ($fname =~ m"(?:^|/)patches/manual-[^/]*$") { 7685 } elsif ($fname =~ m"(?:^|/)patches/manual-[^/]*$") {
7680 $opt_debug_unchecked and log_debug($fname, NO_LINE_NUMBER, "Unchecked file \"${fname}\"."); 7686 $opt_debug_unchecked and log_debug($fname, NO_LINE_NUMBER, "Unchecked file \"${fname}\".");
7681 7687
7682 } elsif ($fname =~ m"(?:^|/)patches/[^/]*$") { 7688 } elsif ($fname =~ m"(?:^|/)patches/[^/]*$") {
7683 log_warning($fname, NO_LINE_NUMBER, "Patch files should be named \"patch-\", followed by letters and digits only."); 7689 log_warning($fname, NO_LINE_NUMBER, "Patch files should be named \"patch-\", followed by letters and digits only.");
7684 7690
7685 } elsif ($basename =~ m"^PLIST") { 7691 } elsif ($basename =~ m"^PLIST") {
7686 $opt_check_PLIST and checkfile_PLIST($fname); 7692 $opt_check_PLIST and checkfile_PLIST($fname);
7687 7693
7688 } elsif ($basename eq "TODO" || $basename eq "README") { 7694 } elsif ($basename eq "TODO" || $basename eq "README") {
7689 # Ok 7695 # Ok
7690 7696
7691 } elsif ($basename =~ m"^CHANGES-.*") { 7697 } elsif ($basename =~ m"^CHANGES-.*") {
7692 load_doc_CHANGES($fname); 7698 load_doc_CHANGES($fname);
7693 7699
7694 } elsif (!-T $fname) { 7700 } elsif (!-T $fname) {
7695 log_warning($fname, NO_LINE_NUMBER, "Unexpectedly found a binary file."); 7701 log_warning($fname, NO_LINE_NUMBER, "Unexpectedly found a binary file.");
7696 7702
7697 } else { 7703 } else {
7698 log_warning($fname, NO_LINE_NUMBER, "Unexpected file found."); 7704 log_warning($fname, NO_LINE_NUMBER, "Unexpected file found.");
7699 $opt_check_extra and checkfile_extra($fname); 7705 $opt_check_extra and checkfile_extra($fname);
7700 } 7706 }
7701} 7707}
7702 7708
7703sub my_split($$) { 7709sub my_split($$) {
7704 my ($delimiter, $s) = @_; 7710 my ($delimiter, $s) = @_;
7705 my ($pos, $next, @result); 7711 my ($pos, $next, @result);
7706 7712
7707 $pos = 0; 7713 $pos = 0;
7708 for ($pos = 0; $pos != -1; $pos = $next) { 7714 for ($pos = 0; $pos != -1; $pos = $next) {
7709 $next = index($s, $delimiter, $pos); 7715 $next = index($s, $delimiter, $pos);
7710 push @result, (($next == -1) ? substr($s, $pos) : substr($s, $pos, $next - $pos)); 7716 push @result, (($next == -1) ? substr($s, $pos) : substr($s, $pos, $next - $pos));
7711 if ($next != -1) { 7717 if ($next != -1) {
7712 $next += length($delimiter); 7718 $next += length($delimiter);
7713 } 7719 }
7714 } 7720 }
7715 return @result; 7721 return @result;
7716} 7722}
7717 7723
7718# Checks that the files in the directory are in sync with CVS's status. 7724# Checks that the files in the directory are in sync with CVS's status.
7719# 7725#
7720sub checkdir_CVS($) { 7726sub checkdir_CVS($) {
7721 my ($fname) = @_; 7727 my ($fname) = @_;
7722 7728
7723 my $cvs_entries = load_file("$fname/CVS/Entries"); 7729 my $cvs_entries = load_file("$fname/CVS/Entries");
7724 my $cvs_entries_log = load_file("$fname/CVS/Entries.Log"); 7730 my $cvs_entries_log = load_file("$fname/CVS/Entries.Log");
7725 return unless $cvs_entries; 7731 return unless $cvs_entries;
7726 7732
7727 foreach my $line (@$cvs_entries) { 7733 foreach my $line (@$cvs_entries) {
7728 my ($type, $fname, $mtime, $date, $keyword_mode, $tag, $undef) = my_split("/", $line->text); 7734 my ($type, $fname, $mtime, $date, $keyword_mode, $tag, $undef) = my_split("/", $line->text);
7729 next if ($type eq "D" && !defined($fname)); 7735 next if ($type eq "D" && !defined($fname));
7730 assert($type eq "" || $type eq "D", "Unknown line format: " . $line->text); 7736 assert($type eq "" || $type eq "D", "Unknown line format: " . $line->text);
7731 assert(defined($tag), "Unknown line format: " . $line->text); 7737 assert(defined($tag), "Unknown line format: " . $line->text);
7732 assert(defined($keyword_mode), "Unknown line format: " . $line->text); 7738 assert(defined($keyword_mode), "Unknown line format: " . $line->text);
7733 assert(!defined($undef), "Unknown line format: " . $line->text); 7739 assert(!defined($undef), "Unknown line format: " . $line->text);
7734 } 7740 }
7735} 7741}
7736 7742
7737# 7743#
7738# Procedures to check a directory including the files in it. 7744# Procedures to check a directory including the files in it.
7739# 7745#
7740 7746
7741sub checkdir_root() { 7747sub checkdir_root() {
7742 my ($fname) = "${current_dir}/Makefile"; 7748 my ($fname) = "${current_dir}/Makefile";
7743 my ($lines, $prev_subdir, @subdirs); 7749 my ($lines, $prev_subdir, @subdirs);
7744 7750
7745 $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_root()"); 7751 $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_root()");
7746 7752
7747 if (!($lines = load_lines($fname, true))) { 7753 if (!($lines = load_lines($fname, true))) {
7748 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 7754 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
7749 return; 7755 return;
7750 } 7756 }
7751 7757
7752 parselines_mk($lines); 7758 parselines_mk($lines);
7753 if (0 <= $#{$lines}) { 7759 if (0 <= $#{$lines}) {
7754 checkline_rcsid_regex($lines->[0], qr"#\s+", "# "); 7760 checkline_rcsid_regex($lines->[0], qr"#\s+", "# ");
7755 } 7761 }
7756 7762
7757 foreach my $line (@{$lines}) { 7763 foreach my $line (@{$lines}) {
7758 if ($line->text =~ m"^(#?)SUBDIR\s*\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { 7764 if ($line->text =~ m"^(#?)SUBDIR\s*\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") {
7759 my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); 7765 my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4);
7760 7766
7761 if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { 7767 if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) {
7762 $line->log_warning("${subdir} commented out without giving a reason."); 7768 $line->log_warning("${subdir} commented out without giving a reason.");
7763 } 7769 }
7764 7770
7765 if ($indentation ne "\t") { 7771 if ($indentation ne "\t") {
7766 $line->log_warning("Indentation should be a single tab character."); 7772 $line->log_warning("Indentation should be a single tab character.");
7767 } 7773 }
7768 7774
7769 if ($subdir =~ m"\$" || !-f "${current_dir}/${subdir}/Makefile") { 7775 if ($subdir =~ m"\$" || !-f "${current_dir}/${subdir}/Makefile") {
7770 next; 7776 next;
7771 } 7777 }
7772 7778
7773 if (defined($prev_subdir) && $subdir eq $prev_subdir) { 7779 if (defined($prev_subdir) && $subdir eq $prev_subdir) {
7774 $line->log_error("${subdir} must only appear once."); 7780 $line->log_error("${subdir} must only appear once.");
7775 } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) { 7781 } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) {
7776 $line->log_warning("${subdir} should come before ${prev_subdir}."); 7782 $line->log_warning("${subdir} should come before ${prev_subdir}.");
7777 } else { 7783 } else {
7778 # correctly ordered 7784 # correctly ordered
7779 } 7785 }
7780 7786
7781 $prev_subdir = $subdir; 7787 $prev_subdir = $subdir;
7782 7788
7783 if ($comment_flag eq "") { 7789 if ($comment_flag eq "") {
7784 push(@subdirs, "${current_dir}/${subdir}"); 7790 push(@subdirs, "${current_dir}/${subdir}");
7785 } 7791 }
7786 } 7792 }
7787 } 7793 }
7788 7794
7789 checklines_mk($lines); 7795 checklines_mk($lines);
7790 7796
7791 if ($opt_recursive) { 7797 if ($opt_recursive) {
7792 push(@todo_items, @subdirs); 7798 push(@todo_items, @subdirs);
7793 } 7799 }
7794} 7800}
7795 7801
7796sub checkdir_category() { 7802sub checkdir_category() {
7797 my $fname = "${current_dir}/Makefile"; 7803 my $fname = "${current_dir}/Makefile";
7798 my ($lines, $lineno); 7804 my ($lines, $lineno);
7799 7805
7800 $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_category()"); 7806 $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_category()");
7801 7807
7802 if (!($lines = load_lines($fname, true))) { 7808 if (!($lines = load_lines($fname, true))) {
7803 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 7809 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
7804 return; 7810 return;
7805 } 7811 }
7806 parselines_mk($lines); 7812 parselines_mk($lines);
7807 7813
7808 $lineno = 0; 7814 $lineno = 0;
7809 7815
7810 # The first line must contain the RCS Id 7816 # The first line must contain the RCS Id
7811 if ($lineno <= $#{$lines} && checkline_rcsid_regex($lines->[$lineno], qr"#\s+", "# ")) { 7817 if ($lineno <= $#{$lines} && checkline_rcsid_regex($lines->[$lineno], qr"#\s+", "# ")) {
7812 $lineno++; 7818 $lineno++;
7813 } 7819 }
7814 7820
7815 # Then, arbitrary comments may follow 7821 # Then, arbitrary comments may follow
7816 while ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^#") { 7822 while ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^#") {
7817 $lineno++; 7823 $lineno++;
7818 } 7824 }
7819 7825
7820 # Then we need an empty line 7826 # Then we need an empty line
7821 expect_empty_line($lines, \$lineno); 7827 expect_empty_line($lines, \$lineno);
7822 7828
7823 # Then comes the COMMENT line 7829 # Then comes the COMMENT line
7824 if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^COMMENT=\t*(.*)") { 7830 if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^COMMENT=\t*(.*)") {
7825 my ($comment) = ($1); 7831 my ($comment) = ($1);
7826 7832
7827 checkline_valid_characters_in_variable($lines->[$lineno], qr"[-\040'(),/0-9A-Za-z]"); 7833 checkline_valid_characters_in_variable($lines->[$lineno], qr"[-\040'(),/0-9A-Za-z]");
7828 $lineno++; 7834 $lineno++;
7829 } else { 7835 } else {
7830 $lines->[$lineno]->log_error("COMMENT= line expected."); 7836 $lines->[$lineno]->log_error("COMMENT= line expected.");
7831 } 7837 }
7832 7838
7833 # Then we need an empty line 7839 # Then we need an empty line
7834 expect_empty_line($lines, \$lineno); 7840 expect_empty_line($lines, \$lineno);
7835 7841
7836 # And now to the most complicated part of the category Makefiles, 7842 # And now to the most complicated part of the category Makefiles,
7837 # the (hopefully) sorted list of SUBDIRs. The first step is to 7843 # the (hopefully) sorted list of SUBDIRs. The first step is to
7838 # collect the SUBDIRs in the Makefile and in the file system. 7844 # collect the SUBDIRs in the Makefile and in the file system.
7839 7845
7840 my (@f_subdirs, @m_subdirs); 7846 my (@f_subdirs, @m_subdirs);
7841 7847
7842 @f_subdirs = sort(get_subdirs($current_dir)); 7848 @f_subdirs = sort(get_subdirs($current_dir));
7843 7849
7844 my $prev_subdir = undef; 7850 my $prev_subdir = undef;
7845 while ($lineno <= $#{$lines}) { 7851 while ($lineno <= $#{$lines}) {
7846 my $line = $lines->[$lineno]; 7852 my $line = $lines->[$lineno];
7847 7853
7848 if ($line->text =~ m"^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { 7854 if ($line->text =~ m"^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") {
7849 my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); 7855 my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4);
7850 7856
7851 if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { 7857 if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) {
7852 $line->log_warning("${subdir} commented out without giving a reason."); 7858 $line->log_warning("${subdir} commented out without giving a reason.");
7853 } 7859 }
7854 7860
7855 if ($indentation ne "\t") { 7861 if ($indentation ne "\t") {
7856 $line->log_warning("Indentation should be a single tab character."); 7862 $line->log_warning("Indentation should be a single tab character.");
7857 } 7863 }
7858 7864
7859 if (defined($prev_subdir) && $subdir eq $prev_subdir) { 7865 if (defined($prev_subdir) && $subdir eq $prev_subdir) {
7860 $line->log_error("${subdir} must only appear once."); 7866 $line->log_error("${subdir} must only appear once.");
7861 } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) { 7867 } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) {
7862 $line->log_warning("${subdir} should come before ${prev_subdir}."); 7868 $line->log_warning("${subdir} should come before ${prev_subdir}.");
7863 } else { 7869 } else {
7864 # correctly ordered 7870 # correctly ordered
7865 } 7871 }
7866 7872
7867 push(@m_subdirs, [$subdir, $line, $comment_flag ? false : true]); 7873 push(@m_subdirs, [$subdir, $line, $comment_flag ? false : true]);
7868 $prev_subdir = $subdir; 7874 $prev_subdir = $subdir;
7869 $lineno++; 7875 $lineno++;
7870 7876
7871 } else { 7877 } else {
7872 if ($line->text ne "") { 7878 if ($line->text ne "") {
7873 $line->log_error("SUBDIR+= line or empty line expected."); 7879 $line->log_error("SUBDIR+= line or empty line expected.");
7874 } 7880 }
7875 last; 7881 last;
7876 } 7882 }
7877 } 7883 }
7878 7884
7879 # To prevent unnecessary warnings about subdirectories that are 7885 # To prevent unnecessary warnings about subdirectories that are
7880 # in one list, but not in the other, we generate the sets of 7886 # in one list, but not in the other, we generate the sets of
7881 # subdirs of each list. 7887 # subdirs of each list.
7882 my (%f_check, %m_check); 7888 my (%f_check, %m_check);
7883 foreach my $f (@f_subdirs) { $f_check{$f} = true; } 7889 foreach my $f (@f_subdirs) { $f_check{$f} = true; }
7884 foreach my $m (@m_subdirs) { $m_check{$m->[0]} = true; } 7890 foreach my $m (@m_subdirs) { $m_check{$m->[0]} = true; }
7885 7891
7886 my ($f_index, $f_atend, $f_neednext, $f_current) = (0, false, true, undef, undef); 7892 my ($f_index, $f_atend, $f_neednext, $f_current) = (0, false, true, undef, undef);
7887 my ($m_index, $m_atend, $m_neednext, $m_current) = (0, false, true, undef, undef); 7893 my ($m_index, $m_atend, $m_neednext, $m_current) = (0, false, true, undef, undef);
7888 my ($line, $m_recurse); 7894 my ($line, $m_recurse);
7889 my (@subdirs); 7895 my (@subdirs);
7890 7896
7891 while (!($m_atend && $f_atend)) { 7897 while (!($m_atend && $f_atend)) {
7892 7898
7893 if (!$m_atend && $m_neednext) { 7899 if (!$m_atend && $m_neednext) {
7894 $m_neednext = false; 7900 $m_neednext = false;
7895 if ($m_index > $#m_subdirs) { 7901 if ($m_index > $#m_subdirs) {
7896 $m_atend = true; 7902 $m_atend = true;
7897 $line = $lines->[$lineno]; 7903 $line = $lines->[$lineno];
7898 next; 7904 next;
7899 } else { 7905 } else {
7900 $m_current = $m_subdirs[$m_index]->[0]; 7906 $m_current = $m_subdirs[$m_index]->[0];
7901 $line = $m_subdirs[$m_index]->[1]; 7907 $line = $m_subdirs[$m_index]->[1];
7902 $m_recurse = $m_subdirs[$m_index]->[2]; 7908 $m_recurse = $m_subdirs[$m_index]->[2];
7903 $m_index++; 7909 $m_index++;
7904 } 7910 }
7905 } 7911 }
7906 7912
7907 if (!$f_atend && $f_neednext) { 7913 if (!$f_atend && $f_neednext) {
7908 $f_neednext = false; 7914 $f_neednext = false;
7909 if ($f_index > $#f_subdirs) { 7915 if ($f_index > $#f_subdirs) {
7910 $f_atend = true; 7916 $f_atend = true;
7911 next; 7917 next;
7912 } else { 7918 } else {
7913 $f_current = $f_subdirs[$f_index++]; 7919 $f_current = $f_subdirs[$f_index++];
7914 } 7920 }
7915 } 7921 }
7916 7922
7917 if (!$f_atend && ($m_atend || $f_current lt $m_current)) { 7923 if (!$f_atend && ($m_atend || $f_current lt $m_current)) {
7918 if (!exists($m_check{$f_current})) { 7924 if (!exists($m_check{$f_current})) {
7919 $line->log_error("${f_current} exists in the file system, but not in the Makefile."); 7925 $line->log_error("${f_current} exists in the file system, but not in the Makefile.");
7920 $line->append_before("SUBDIR+=\t${f_current}"); 7926 $line->append_before("SUBDIR+=\t${f_current}");
7921 } 7927 }
7922 $f_neednext = true; 7928 $f_neednext = true;
7923 7929
7924 } elsif (!$m_atend && ($f_atend || $m_current lt $f_current)) { 7930 } elsif (!$m_atend && ($f_atend || $m_current lt $f_current)) {
7925 if (!exists($f_check{$m_current})) { 7931 if (!exists($f_check{$m_current})) {
7926 $line->log_error("${m_current} exists in the Makefile, but not in the file system."); 7932 $line->log_error("${m_current} exists in the Makefile, but not in the file system.");
7927 $line->delete(); 7933 $line->delete();
7928 } 7934 }
7929 $m_neednext = true; 7935 $m_neednext = true;
7930 7936
7931 } else { # $f_current eq $m_current 7937 } else { # $f_current eq $m_current
7932 $f_neednext = true; 7938 $f_neednext = true;
7933 $m_neednext = true; 7939 $m_neednext = true;
7934 if ($m_recurse) { 7940 if ($m_recurse) {
7935 push(@subdirs, "${current_dir}/${m_current}"); 7941 push(@subdirs, "${current_dir}/${m_current}");
7936 } 7942 }
7937 } 7943 }
7938 } 7944 }
7939 7945
7940 # the wip category Makefile may have its own targets for generating 7946 # the wip category Makefile may have its own targets for generating
7941 # indexes and READMEs. Just skip them. 7947 # indexes and READMEs. Just skip them.
7942 if ($is_wip) { 7948 if ($is_wip) {
7943 while ($lineno <= $#{$lines} - 2) { 7949 while ($lineno <= $#{$lines} - 2) {
7944 $lineno++; 7950 $lineno++;
7945 } 7951 }
7946 } 7952 }
7947 7953
7948 expect_empty_line($lines, \$lineno); 7954 expect_empty_line($lines, \$lineno);
7949 7955
7950 # And, last but not least, the .include line 7956 # And, last but not least, the .include line
7951 my $final_line = ".include \"../mk/bsd.pkg.subdir.mk\""; 7957 my $final_line = ".include \"../mk/bsd.pkg.subdir.mk\"";
7952 expect($lines, \$lineno, qr"\Q$final_line\E") 7958 expect($lines, \$lineno, qr"\Q$final_line\E")
7953 || expect_text($lines, \$lineno, ".include \"../mk/misc/category.mk\""); 7959 || expect_text($lines, \$lineno, ".include \"../mk/misc/category.mk\"");
7954 7960
7955 if ($lineno <= $#{$lines}) { 7961 if ($lineno <= $#{$lines}) {
7956 $lines->[$lineno]->log_error("The file should end here."); 7962 $lines->[$lineno]->log_error("The file should end here.");
7957 } 7963 }
7958 7964
7959 checklines_mk($lines); 7965 checklines_mk($lines);
7960 7966
7961 autofix($lines); 7967 autofix($lines);
7962 7968
7963 if ($opt_recursive) { 7969 if ($opt_recursive) {
7964 unshift(@todo_items, @subdirs); 7970 unshift(@todo_items, @subdirs);
7965 } 7971 }
7966} 7972}
7967 7973
7968sub checkdir_package() { 7974sub checkdir_package() {
7969 my ($lines, $have_distinfo, $have_patches); 7975 my ($lines, $have_distinfo, $have_patches);
7970 7976
7971 # Initialize global variables 7977 # Initialize global variables
7972 $pkgdir = undef; 7978 $pkgdir = undef;
7973 $filesdir = "files"; 7979 $filesdir = "files";
7974 $patchdir = "patches"; 7980 $patchdir = "patches";
7975 $distinfo_file = "distinfo"; 7981 $distinfo_file = "distinfo";
7976 $effective_pkgname = undef; 7982 $effective_pkgname = undef;
7977 $effective_pkgbase = undef; 7983 $effective_pkgbase = undef;
7978 $effective_pkgversion = undef; 7984 $effective_pkgversion = undef;
7979 $effective_pkgname_line = undef; 7985 $effective_pkgname_line = undef;
7980 $seen_bsd_prefs_mk = false; 7986 $seen_bsd_prefs_mk = false;
7981 $pkgctx_vardef = {%{get_userdefined_variables()}}; 7987 $pkgctx_vardef = {%{get_userdefined_variables()}};
7982 $pkgctx_varuse = {}; 7988 $pkgctx_varuse = {};
7983 $pkgctx_bl3 = {}; 7989 $pkgctx_bl3 = {};
7984 $pkgctx_plist_subst_cond = {}; 7990 $pkgctx_plist_subst_cond = {};
7985 $seen_Makefile_common = false; 7991 $seen_Makefile_common = false;
7986 7992
7987 # we need to handle the Makefile first to get some variables 7993 # we need to handle the Makefile first to get some variables
7988 if (!load_package_Makefile("${current_dir}/Makefile", \$lines)) { 7994 if (!load_package_Makefile("${current_dir}/Makefile", \$lines)) {
7989 log_error("${current_dir}/Makefile", NO_LINE_NUMBER, "Cannot be read."); 7995 log_error("${current_dir}/Makefile", NO_LINE_NUMBER, "Cannot be read.");
7990 goto cleanup; 7996 goto cleanup;
7991 } 7997 }
7992 7998
7993 my @files = <${current_dir}/*>; 7999 my @files = <${current_dir}/*>;
7994 if ($pkgdir ne ".") { 8000 if ($pkgdir ne ".") {
7995 push(@files, <${current_dir}/${pkgdir}/*>); 8001 push(@files, <${current_dir}/${pkgdir}/*>);
7996 } 8002 }
7997 if ($opt_check_extra) { 8003 if ($opt_check_extra) {
7998 push(@files, <${current_dir}/${filesdir}/*>); 8004 push(@files, <${current_dir}/${filesdir}/*>);
7999 } 8005 }
8000 push(@files, <${current_dir}/${patchdir}/*>); 8006 push(@files, <${current_dir}/${patchdir}/*>);
8001 if ($distinfo_file !~ m"^(?:\./)?distinfo$") { 8007 if ($distinfo_file !~ m"^(?:\./)?distinfo$") {
8002 push(@files, "${current_dir}/${distinfo_file}"); 8008 push(@files, "${current_dir}/${distinfo_file}");
8003 } 8009 }
8004 $have_distinfo = false; 8010 $have_distinfo = false;
8005 $have_patches = false; 8011 $have_patches = false;
8006 8012
8007 # Determine the used variables before checking any of the 8013 # Determine the used variables before checking any of the
8008 # Makefile fragments. 8014 # Makefile fragments.
8009 foreach my $fname (@files) { 8015 foreach my $fname (@files) {
8010 if ($fname =~ m"^((?:.*/)?Makefile\..*|.*\.mk)$" 8016 if ($fname =~ m"^((?:.*/)?Makefile\..*|.*\.mk)$"
8011 && (defined(my $lines = load_lines($fname, true)))) { 8017 && (defined(my $lines = load_lines($fname, true)))) {
8012 parselines_mk($lines); 8018 parselines_mk($lines);
8013 determine_used_variables($lines); 8019 determine_used_variables($lines);
8014 } 8020 }
8015 } 8021 }
8016 8022
8017 foreach my $fname (@files) { 8023 foreach my $fname (@files) {
8018 if ($fname eq "${current_dir}/Makefile") { 8024 if ($fname eq "${current_dir}/Makefile") {
8019 $opt_check_Makefile and checkfile_package_Makefile($fname, $lines); 8025 $opt_check_Makefile and checkfile_package_Makefile($fname, $lines);
8020 } else { 8026 } else {
8021 checkfile($fname); 8027 checkfile($fname);
8022 } 8028 }
8023 if ($fname =~ m"/patches/patch-[A-Za-z0-9]*$") { 8029 if ($fname =~ m"/patches/patch-[A-Za-z0-9]*$") {
8024 $have_patches = true; 8030 $have_patches = true;
8025 } elsif ($fname =~ m"/distinfo$") { 8031 } elsif ($fname =~ m"/distinfo$") {
8026 $have_distinfo = true; 8032 $have_distinfo = true;
8027 } 8033 }
8028 } 8034 }
8029 8035
8030 if ($opt_check_distinfo && $opt_check_patches) { 8036 if ($opt_check_distinfo && $opt_check_patches) {
8031 if ($have_patches && ! $have_distinfo) { 8037 if ($have_patches && ! $have_distinfo) {
8032 log_warning("${current_dir}/$distinfo_file", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makepatchsum'."); 8038 log_warning("${current_dir}/$distinfo_file", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makepatchsum'.");
8033 } 8039 }
8034 } 8040 }
8035 8041
8036 if (!is_emptydir("${current_dir}/scripts")) { 8042 if (!is_emptydir("${current_dir}/scripts")) {
8037 log_warning("${current_dir}/scripts", NO_LINE_NUMBER, "This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's Makefile."); 8043 log_warning("${current_dir}/scripts", NO_LINE_NUMBER, "This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's Makefile.");
8038 } 8044 }
8039 8045
8040cleanup: 8046cleanup:
8041 # Clean up global variables. 8047 # Clean up global variables.
8042 $pkgdir = undef; 8048 $pkgdir = undef;
8043 $filesdir = undef; 8049 $filesdir = undef;
8044 $patchdir = undef; 8050 $patchdir = undef;
8045 $distinfo_file = undef; 8051 $distinfo_file = undef;
8046 $effective_pkgname = undef; 8052 $effective_pkgname = undef;
8047 $effective_pkgbase = undef; 8053 $effective_pkgbase = undef;
8048 $effective_pkgversion = undef; 8054 $effective_pkgversion = undef;
8049 $effective_pkgname_line = undef; 8055 $effective_pkgname_line = undef;
8050 $seen_bsd_prefs_mk = undef; 8056 $seen_bsd_prefs_mk = undef;
8051 $pkgctx_vardef = undef; 8057 $pkgctx_vardef = undef;
8052 $pkgctx_varuse = undef; 8058 $pkgctx_varuse = undef;
8053 $pkgctx_bl3 = undef; 8059 $pkgctx_bl3 = undef;
8054 $pkgctx_plist_subst_cond = undef; 8060 $pkgctx_plist_subst_cond = undef;
8055 $seen_Makefile_common = undef; 8061 $seen_Makefile_common = undef;
8056} 8062}
8057 8063
8058# 8064#
8059# Selecting the proper checking procedures for a directory entry. 8065# Selecting the proper checking procedures for a directory entry.
8060# 8066#
8061 8067
8062sub checkitem($) { 8068sub checkitem($) {
8063 my ($item) = @_; 8069 my ($item) = @_;
8064 my ($st, $is_dir, $is_reg); 8070 my ($st, $is_dir, $is_reg);
8065 8071
8066 if (!($st = lstat($item))) { 8072 if (!($st = lstat($item))) {
8067 log_error($item, NO_LINE_NUMBER, "Does not exist."); 8073 log_error($item, NO_LINE_NUMBER, "Does not exist.");
8068 return; 8074 return;
8069 } 8075 }
8070 8076
8071 $is_dir = S_ISDIR($st->mode); 8077 $is_dir = S_ISDIR($st->mode);
8072 $is_reg = S_ISREG($st->mode); 8078 $is_reg = S_ISREG($st->mode);
8073 if (!$is_reg && !$is_dir) { 8079 if (!$is_reg && !$is_dir) {
8074 log_error($item, NO_LINE_NUMBER, "Must be a file or directory."); 8080 log_error($item, NO_LINE_NUMBER, "Must be a file or directory.");
8075 return; 8081 return;
8076 } 8082 }
8077 8083
8078 $current_dir = $is_dir ? $item : dirname($item); 8084 $current_dir = $is_dir ? $item : dirname($item);
8079 my $abs_current_dir = Cwd::abs_path($current_dir); 8085 my $abs_current_dir = Cwd::abs_path($current_dir);
8080 $is_wip = !$opt_import && ($abs_current_dir =~ m"/wip(?:/|$)"); 8086 $is_wip = !$opt_import && ($abs_current_dir =~ m"/wip(?:/|$)");
8081 $is_internal = ($abs_current_dir =~ m"/mk(?:/|$)"); 8087 $is_internal = ($abs_current_dir =~ m"/mk(?:/|$)");
8082 8088
8083 # Determine the root directory of pkgsrc. By only overwriting 8089 # Determine the root directory of pkgsrc. By only overwriting
8084 # the global variable $cwd_pkgsrcdir when we are checking inside 8090 # the global variable $cwd_pkgsrcdir when we are checking inside
8085 # a pkgsrc tree, the user can specify a tree with the 8091 # a pkgsrc tree, the user can specify a tree with the
8086 # --pkgsrcdir option and then check files (but not directories) 8092 # --pkgsrcdir option and then check files (but not directories)
8087 # outside of any pkgsrc tree. 8093 # outside of any pkgsrc tree.
8088 $cur_pkgsrcdir = undef; 8094 $cur_pkgsrcdir = undef;
8089 $pkgpath = undef; 8095 $pkgpath = undef;
8090 foreach my $d (".", "..", "../..", "../../..") { 8096 foreach my $d (".", "..", "../..", "../../..") {
8091 if (-f "${current_dir}/${d}/mk/bsd.pkg.mk") { 8097 if (-f "${current_dir}/${d}/mk/bsd.pkg.mk") {
8092 $cur_pkgsrcdir = $d; 8098 $cur_pkgsrcdir = $d;
8093 $pkgpath = relative_path("${current_dir}/${d}", $current_dir); 8099 $pkgpath = relative_path("${current_dir}/${d}", $current_dir);
8094 } 8100 }
8095 } 8101 }
8096 if (!defined($cwd_pkgsrcdir) && defined($cur_pkgsrcdir)) { 8102 if (!defined($cwd_pkgsrcdir) && defined($cur_pkgsrcdir)) {
8097 $cwd_pkgsrcdir = "${current_dir}/${cur_pkgsrcdir}"; 8103 $cwd_pkgsrcdir = "${current_dir}/${cur_pkgsrcdir}";
8098 } 8104 }
8099 8105
8100 if (!defined($cwd_pkgsrcdir)) { 8106 if (!defined($cwd_pkgsrcdir)) {
8101 log_error($item, NO_LINE_NUMBER, "Cannot determine the pkgsrc root directory."); 8107 log_error($item, NO_LINE_NUMBER, "Cannot determine the pkgsrc root directory.");
8102 return; 8108 return;
8103 } 8109 }
8104 8110
8105 check_pkglint_version(); # (needs $cwd_pkgsrcdir) 8111 check_pkglint_version(); # (needs $cwd_pkgsrcdir)
8106 8112
8107 return if $is_dir && is_emptydir($item); 8113 return if $is_dir && is_emptydir($item);
8108 8114
8109 if ($is_dir) { 8115 if ($is_dir) {
8110 checkdir_CVS($item); 8116 checkdir_CVS($item);
8111 } 8117 }
8112 8118
8113 if ($is_reg) { 8119 if ($is_reg) {
8114 checkfile($item); 8120 checkfile($item);
8115 8121
8116 } elsif (!defined($cur_pkgsrcdir)) { 8122 } elsif (!defined($cur_pkgsrcdir)) {
8117 log_error($item, NO_LINES, "Cannot check directories outside a pkgsrc tree."); 8123 log_error($item, NO_LINES, "Cannot check directories outside a pkgsrc tree.");
8118 8124
8119 } elsif ($cur_pkgsrcdir eq "../..") { 8125 } elsif ($cur_pkgsrcdir eq "../..") {
8120 checkdir_package(); 8126 checkdir_package();
8121 8127
8122 } elsif ($cur_pkgsrcdir eq "..") { 8128 } elsif ($cur_pkgsrcdir eq "..") {
8123 checkdir_category(); 8129 checkdir_category();
8124 8130
8125 } elsif ($cur_pkgsrcdir eq ".") { 8131 } elsif ($cur_pkgsrcdir eq ".") {
8126 checkdir_root(); 8132 checkdir_root();
8127 8133
8128 } else { 8134 } else {
8129 log_error($item, NO_LINE_NUMBER, "Don't know how to check this directory."); 8135 log_error($item, NO_LINE_NUMBER, "Don't know how to check this directory.");
8130 } 8136 }
8131} 8137}
8132 8138
8133# 8139#
8134# The main program 8140# The main program
8135# 8141#
8136 8142
8137sub main() { 8143sub main() {
8138 8144
8139 $| = true; 8145 $| = true;
8140 parse_command_line(); 8146 parse_command_line();
8141 8147
8142 @todo_items = (@ARGV != 0) ? @ARGV : ("."); 8148 @todo_items = (@ARGV != 0) ? @ARGV : (".");
8143 while (@todo_items != 0) { 8149 while (@todo_items != 0) {
8144 checkitem(shift(@todo_items)); 8150 checkitem(shift(@todo_items));
8145 } 8151 }
8146 8152
8147 PkgLint::Logging::print_summary_and_exit($opt_quiet); 8153 PkgLint::Logging::print_summary_and_exit($opt_quiet);
8148} 8154}
8149 8155
8150main(); 8156main();