| @@ -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 | |
34 | use strict; | | 34 | use strict; |
35 | use warnings; | | 35 | use warnings; |
36 | | | 36 | |
37 | package PkgLint::Util; | | 37 | package 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 | #========================================================================== |
46 | BEGIN { | | 46 | BEGIN { |
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 | |
58 | use enum qw(false true dont_know doesnt_matter); | | 58 | use enum qw(false true dont_know doesnt_matter); |
59 | | | 59 | |
60 | sub assert($$) { | | 60 | sub 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 | |
79 | sub min($$) { | | 79 | sub 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 | |
85 | sub max($$) { | | 85 | sub 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. |
94 | sub print_table($$) { | | 94 | sub 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 | |
119 | sub array_to_hash(@) { | | 119 | sub 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 | |
128 | sub normalize_pathname($) { | | 128 | sub 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 | |
144 | package PkgLint::Logging; | | 144 | package 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 | |
161 | use strict; | | 161 | use strict; |
162 | use warnings; | | 162 | use warnings; |
163 | BEGIN { | | 163 | BEGIN { |
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 | |
181 | use constant NO_FILE => undef; | | 181 | use constant NO_FILE => undef; |
182 | use constant NO_LINE_NUMBER => undef; | | 182 | use constant NO_LINE_NUMBER => undef; |
183 | use constant NO_LINES => undef; | | 183 | use constant NO_LINES => undef; |
184 | | | 184 | |
185 | use enum qw(:LL_ FATAL ERROR WARNING NOTE DEBUG); | | 185 | use enum qw(:LL_ FATAL ERROR WARNING NOTE DEBUG); |
186 | | | 186 | |
187 | use constant traditional_type => ["FATAL", "ERROR", "WARN", "NOTE", "DEBUG"]; | | 187 | use constant traditional_type => ["FATAL", "ERROR", "WARN", "NOTE", "DEBUG"]; |
188 | use constant gcc_type => ["fatal", "error", "warning", "note", "debug"]; | | 188 | use constant gcc_type => ["fatal", "error", "warning", "note", "debug"]; |
189 | | | 189 | |
190 | my $errors = 0; | | 190 | my $errors = 0; |
191 | my $warnings = 0; | | 191 | my $warnings = 0; |
192 | my $gcc_output_format = false; | | 192 | my $gcc_output_format = false; |
193 | my $explain_flag = false; | | 193 | my $explain_flag = false; |
194 | my $show_source_flag = false; | | 194 | my $show_source_flag = false; |
195 | | | 195 | |
196 | sub strxvis($) { | | 196 | sub 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 | |
203 | sub log_message { # no prototype due to Perl weirdness | | 203 | sub 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 | |
239 | sub log_fatal($$$) { log_message(LL_FATAL, @_); exit(1); } | | 239 | sub log_fatal($$$) { log_message(LL_FATAL, @_); exit(1); } |
240 | sub log_error($$$) { log_message(LL_ERROR, @_); $errors++; } | | 240 | sub log_error($$$) { log_message(LL_ERROR, @_); $errors++; } |
241 | sub log_warning($$$) { log_message(LL_WARNING, @_); $warnings++; } | | 241 | sub log_warning($$$) { log_message(LL_WARNING, @_); $warnings++; } |
242 | sub log_note($$$) { log_message(LL_NOTE, @_); } | | 242 | sub log_note($$$) { log_message(LL_NOTE, @_); } |
243 | sub log_debug($$$) { log_message(LL_DEBUG, @_); } | | 243 | sub log_debug($$$) { log_message(LL_DEBUG, @_); } |
244 | | | 244 | |
245 | sub explain { # no prototype due to Perl weirdness | | 245 | sub 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 | } |
255 | sub explain_error($$@) { explain(LL_ERROR, @_); } | | 255 | sub explain_error($$@) { explain(LL_ERROR, @_); } |
256 | sub explain_warning($$@) { explain(LL_WARNING, @_); } | | 256 | sub explain_warning($$@) { explain(LL_WARNING, @_); } |
257 | sub explain_note($$@) { explain(LL_NOTE, @_); } | | 257 | sub explain_note($$@) { explain(LL_NOTE, @_); } |
258 | | | 258 | |
259 | sub print_summary_and_exit($) { | | 259 | sub 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 | |
272 | sub set_explain() { $explain_flag = true; } | | 272 | sub set_explain() { $explain_flag = true; } |
273 | sub set_gcc_output_format() { $gcc_output_format = true; } | | 273 | sub set_gcc_output_format() { $gcc_output_format = true; } |
274 | sub get_show_source_flag() { return $show_source_flag; } | | 274 | sub get_show_source_flag() { return $show_source_flag; } |
275 | sub set_show_source_flag() { $show_source_flag = true; } | | 275 | sub 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 | #========================================================================== |
284 | package PkgLint::SimpleMatch; | | 284 | package PkgLint::SimpleMatch; |
285 | | | 285 | |
286 | use enum qw(STRING STARTS ENDS N); | | 286 | use enum qw(STRING STARTS ENDS N); |
287 | | | 287 | |
288 | sub new($$) { | | 288 | sub 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 | |
295 | sub string($) { return shift(@_)->[STRING]; } | | 295 | sub string($) { return shift(@_)->[STRING]; } |
296 | sub n($) { return shift(@_)->[N]; } | | 296 | sub n($) { return shift(@_)->[N]; } |
297 | | | 297 | |
298 | sub has($$) { | | 298 | sub 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 | |
306 | sub text($$) { | | 306 | sub 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 | |
314 | sub range($$) { | | 314 | sub 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 | #========================================================================== |
341 | package PkgLint::Line; | | 341 | package PkgLint::Line; |
342 | | | 342 | |
343 | BEGIN { | | 343 | BEGIN { |
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 | |
350 | use enum qw(FNAME LINES TEXT PHYSLINES CHANGED BEFORE AFTER EXTRA); | | 350 | use enum qw(FNAME LINES TEXT PHYSLINES CHANGED BEFORE AFTER EXTRA); |
351 | | | 351 | |
352 | sub new($$$$) { | | 352 | sub 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 | |
359 | sub fname($) { return shift(@_)->[FNAME]; } | | 359 | sub fname($) { return shift(@_)->[FNAME]; } |
360 | sub lines($) { return shift(@_)->[LINES]; } | | 360 | sub lines($) { return shift(@_)->[LINES]; } |
361 | sub text($) { return shift(@_)->[TEXT]; } | | 361 | sub text($) { return shift(@_)->[TEXT]; } |
362 | # Note: physlines is _not_ a usual getter method. | | 362 | # Note: physlines is _not_ a usual getter method. |
363 | sub is_changed($) { return shift(@_)->[CHANGED]; } | | 363 | sub is_changed($) { return shift(@_)->[CHANGED]; } |
364 | | | 364 | |
365 | # querying, getting and setting the extra values. | | 365 | # querying, getting and setting the extra values. |
366 | sub has($$) { | | 366 | sub has($$) { |
367 | my ($self, $name) = @_; | | 367 | my ($self, $name) = @_; |
368 | return exists($self->[EXTRA]->{$name}); | | 368 | return exists($self->[EXTRA]->{$name}); |
369 | } | | 369 | } |
370 | sub get($$) { | | 370 | sub 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 | } |
375 | sub set($$$) { | | 375 | sub 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 | |
396 | sub physlines($) { | | 396 | sub 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 |
402 | sub substring($$$$) { | | 402 | sub 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 | |
409 | sub show_source($$) { | | 409 | sub 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 | |
419 | sub log_fatal($$) { | | 419 | sub 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 | } |
425 | sub log_error($$) { | | 425 | sub 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 | } |
431 | sub log_warning($$) { | | 431 | sub 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 | } |
437 | sub log_note($$) { | | 437 | sub 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 | } |
443 | sub log_debug($$) { | | 443 | sub 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 | } |
449 | sub explain_error($@) { | | 449 | sub 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 | } |
454 | sub explain_warning($@) { | | 454 | sub 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 | } |
459 | sub explain_note($@) { | | 459 | sub 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 | } |
464 | sub explain_info($@) { | | 464 | sub 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 | |
470 | sub to_string($) { | | 470 | sub 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 | |
476 | sub prepend_before($$) { | | 476 | sub 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 | } |
482 | sub append_before($$) { | | 482 | sub 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 | } |
488 | sub prepend_after($$) { | | 488 | sub 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 | } |
494 | sub append_after($$) { | | 494 | sub 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 | } |
500 | sub delete($) { | | 500 | sub 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 | } |
506 | sub replace($$$) { | | 506 | sub 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 | } |
516 | sub replace_regex($$$) { | | 516 | sub 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 | } |
526 | sub set_text($$) { | | 526 | sub 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 | |
534 | package PkgLint::FileUtil; | | 534 | package 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 | #========================================================================== |
544 | use strict; | | 544 | use strict; |
545 | use warnings; | | 545 | use warnings; |
546 | | | 546 | |
547 | BEGIN { | | 547 | BEGIN { |
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 | |
565 | sub load_physical_lines($) { | | 565 | sub 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 | |
580 | sub get_logical_line($$$) { | | 580 | sub 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 | |
626 | sub load_lines($$) { | | 626 | sub 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 | |
657 | sub load_file($) { | | 657 | sub 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 | |
663 | sub save_autofix_changes($) { | | 663 | sub 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 | |
700 | package PkgLint::Type; | | 700 | package 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 | |
707 | BEGIN { | | 707 | BEGIN { |
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 | |
723 | use enum qw(KIND_OF_LIST BASIC_TYPE ACLS IS_GUESSED); | | 723 | use enum qw(KIND_OF_LIST BASIC_TYPE ACLS IS_GUESSED); |
724 | use enum qw(:LK_ NONE INTERNAL EXTERNAL); | | 724 | use enum qw(:LK_ NONE INTERNAL EXTERNAL); |
725 | use enum qw(:ACLE_ SUBJECT_RE PERMS); | | 725 | use enum qw(:ACLE_ SUBJECT_RE PERMS); |
726 | use enum qw(NOT_GUESSED GUESSED); | | 726 | use enum qw(NOT_GUESSED GUESSED); |
727 | | | 727 | |
728 | sub new($$$) { | | 728 | sub 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 | |
735 | sub kind_of_list($) { return shift(@_)->[KIND_OF_LIST]; } | | 735 | sub kind_of_list($) { return shift(@_)->[KIND_OF_LIST]; } |
736 | sub basic_type($) { return shift(@_)->[BASIC_TYPE]; } | | 736 | sub basic_type($) { return shift(@_)->[BASIC_TYPE]; } |
737 | # no getter method for acls | | 737 | # no getter method for acls |
738 | sub is_guessed($) { return shift(@_)->[IS_GUESSED]; } | | 738 | sub is_guessed($) { return shift(@_)->[IS_GUESSED]; } |
739 | | | 739 | |
740 | sub perms($$) { | | 740 | sub 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. |
755 | sub perms_union($) { | | 755 | sub 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. |
770 | sub is_practically_a_list($) { | | 770 | sub 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. |
783 | sub may_use_plus_eq($) { | | 783 | sub 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 | |
793 | sub to_string($) { | | 793 | sub 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 | |
801 | package PkgLint::VarUseContext; | | 801 | package 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 | |
808 | BEGIN { | | 808 | BEGIN { |
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 | |
828 | use enum qw(TIME TYPE SHELLWORD EXTENT); | | 828 | use enum qw(TIME TYPE SHELLWORD EXTENT); |
829 | use enum qw(:VUC_TIME_ UNKNOWN LOAD RUN); | | 829 | use enum qw(:VUC_TIME_ UNKNOWN LOAD RUN); |
830 | use constant VUC_TYPE_UNKNOWN => undef; | | 830 | use constant VUC_TYPE_UNKNOWN => undef; |
831 | use enum qw(:VUC_SHELLWORD_ UNKNOWN PLAIN DQUOT SQUOT BACKT FOR); | | 831 | use enum qw(:VUC_SHELLWORD_ UNKNOWN PLAIN DQUOT SQUOT BACKT FOR); |
832 | use enum qw(:VUC_EXTENT_ UNKNOWN FULL WORD WORD_PART); | | 832 | use enum qw(:VUC_EXTENT_ UNKNOWN FULL WORD WORD_PART); |
833 | | | 833 | |
834 | my $pool = {}; | | 834 | my $pool = {}; |
835 | | | 835 | |
836 | sub new($$$$$) { | | 836 | sub 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 | } |
842 | sub new_from_pool($$$$$) { | | 842 | sub 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 | |
852 | sub time($) { return shift(@_)->[TIME]; } | | 852 | sub time($) { return shift(@_)->[TIME]; } |
853 | sub type($) { return shift(@_)->[TYPE]; } | | 853 | sub type($) { return shift(@_)->[TYPE]; } |
854 | sub shellword($) { return shift(@_)->[SHELLWORD]; } | | 854 | sub shellword($) { return shift(@_)->[SHELLWORD]; } |
855 | sub extent($) { return shift(@_)->[EXTENT]; } | | 855 | sub extent($) { return shift(@_)->[EXTENT]; } |
856 | | | 856 | |
857 | sub to_string($) { | | 857 | sub 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 | |
869 | package PkgLint::SubstContext; | | 869 | package 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 | |
877 | BEGIN { | | 877 | BEGIN { |
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 | |
886 | use enum qw(:SUBST_ ID CLASS STAGE MESSAGE FILES SED VARS FILTER_CMD); | | 886 | use enum qw(:SUBST_ ID CLASS STAGE MESSAGE FILES SED VARS FILTER_CMD); |
887 | | | 887 | |
888 | sub new($) { | | 888 | sub 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 | |
895 | sub subst_class($) { return shift(@_)->[SUBST_CLASS]; } | | 895 | sub subst_class($) { return shift(@_)->[SUBST_CLASS]; } |
896 | sub subst_stage($) { return shift(@_)->[SUBST_STAGE]; } | | 896 | sub subst_stage($) { return shift(@_)->[SUBST_STAGE]; } |
897 | sub subst_message($) { return shift(@_)->[SUBST_MESSAGE]; } | | 897 | sub subst_message($) { return shift(@_)->[SUBST_MESSAGE]; } |
898 | sub subst_files($) { return shift(@_)->[SUBST_FILES]; } | | 898 | sub subst_files($) { return shift(@_)->[SUBST_FILES]; } |
899 | sub subst_sed($) { return shift(@_)->[SUBST_SED]; } | | 899 | sub subst_sed($) { return shift(@_)->[SUBST_SED]; } |
900 | sub subst_vars($) { return shift(@_)->[SUBST_VARS]; } | | 900 | sub subst_vars($) { return shift(@_)->[SUBST_VARS]; } |
901 | sub subst_filter_cmd($) { return shift(@_)->[SUBST_FILTER_CMD]; } | | 901 | sub subst_filter_cmd($) { return shift(@_)->[SUBST_FILTER_CMD]; } |
902 | sub subst_id($) { return shift(@_)->[SUBST_ID]; } | | 902 | sub subst_id($) { return shift(@_)->[SUBST_ID]; } |
903 | | | 903 | |
904 | sub init($) { | | 904 | sub 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 | |
917 | sub check_end($$) { | | 917 | sub 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 | |
937 | sub is_complete($) { | | 937 | sub 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 | |
947 | sub check_varassign($$$$$) { | | 947 | sub 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 | |
6510 | sub checkfile_DESCR($) { | | 6510 | sub 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 | |
6550 | sub checkfile_distinfo($) { | | 6550 | sub 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 | |
6700 | sub checkfile_extra($) { | | 6700 | sub 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 | |
6715 | sub checkfile_INSTALL($) { | | 6715 | sub 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 | |
6728 | sub checkfile_MESSAGE($) { | | 6728 | sub 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 | |
6769 | sub checkfile_mk($) { | | 6769 | sub 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 | |
6786 | sub checkfile_package_Makefile($$) { | | 6786 | sub 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 | |
6917 | sub checkfile_patch($) { | | 6917 | sub 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 | |
7308 | sub checkfile_PLIST($) { | | 7308 | sub 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 | |
7621 | sub checkfile($) { | | 7627 | sub 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 | |
7703 | sub my_split($$) { | | 7709 | sub 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 | # |
7720 | sub checkdir_CVS($) { | | 7726 | sub 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 | |
7741 | sub checkdir_root() { | | 7747 | sub 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 | |
7796 | sub checkdir_category() { | | 7802 | sub 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 | |
7968 | sub checkdir_package() { | | 7974 | sub 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 | |
8040 | cleanup: | | 8046 | cleanup: |
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 | |
8062 | sub checkitem($) { | | 8068 | sub 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 | |
8137 | sub main() { | | 8143 | sub 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 | |
8150 | main(); | | 8156 | main(); |