| @@ -1,1001 +1,1001 @@ | | | @@ -1,1001 +1,1001 @@ |
1 | #! @PERL@ | | 1 | #! @PERL@ |
2 | # $NetBSD: pkglint.pl,v 1.802 2009/03/22 05:41:44 rillig Exp $ | | 2 | # $NetBSD: pkglint.pl,v 1.803 2009/03/22 05:50:12 rillig Exp $ |
3 | # | | 3 | # |
4 | | | 4 | |
5 | # pkglint - static analyzer and checker for pkgsrc packages | | 5 | # pkglint - static analyzer and checker for pkgsrc packages |
6 | # | | 6 | # |
7 | # Written by: | | 7 | # Written by: |
8 | # Roland Illig <rillig@NetBSD.org> | | 8 | # Roland Illig <rillig@NetBSD.org> |
9 | # | | 9 | # |
10 | # Based on work by: | | 10 | # Based on work by: |
11 | # Hubert Feyrer <hubertf@NetBSD.org> | | 11 | # Hubert Feyrer <hubertf@NetBSD.org> |
12 | # Thorsten Frueauf <frueauf@NetBSD.org> | | 12 | # Thorsten Frueauf <frueauf@NetBSD.org> |
13 | # Thomas Klausner <wiz@NetBSD.org> | | 13 | # Thomas Klausner <wiz@NetBSD.org> |
14 | # and others. | | 14 | # and others. |
15 | # | | 15 | # |
16 | # Based on FreeBSD's portlint by: | | 16 | # Based on FreeBSD's portlint by: |
17 | # Jun-ichiro itojun Hagino <itojun@itojun.org> | | 17 | # Jun-ichiro itojun Hagino <itojun@itojun.org> |
18 | # Yoshishige Arai <ryo2@on.rim.or.jp> | | 18 | # Yoshishige Arai <ryo2@on.rim.or.jp> |
19 | # | | 19 | # |
20 | # FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp | | 20 | # FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp |
21 | # Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. | | 21 | # Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. |
22 | # All rights reserved. | | 22 | # All rights reserved. |
23 | # Freely redistributable. Absolutely no warranty. | | 23 | # Freely redistributable. Absolutely no warranty. |
24 | | | 24 | |
25 | # To get an overview of the code, run: | | 25 | # To get an overview of the code, run: |
26 | # sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl | | 26 | # sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl |
27 | | | 27 | |
28 | #========================================================================== | | 28 | #========================================================================== |
29 | # Note: The @EXPORT clauses in the packages must be in a BEGIN block, | | 29 | # Note: The @EXPORT clauses in the packages must be in a BEGIN block, |
30 | # because otherwise the names starting with an uppercase letter are not | | 30 | # because otherwise the names starting with an uppercase letter are not |
31 | # recognized as subroutines but as file handles. | | 31 | # recognized as subroutines but as file handles. |
32 | #========================================================================== | | 32 | #========================================================================== |
33 | | | 33 | |
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 | |
| @@ -5644,1999 +5644,1999 @@ sub checkline_mk_varassign($$$$$) { | | | @@ -5644,1999 +5644,1999 @@ sub checkline_mk_varassign($$$$$) { |
5644 | my ($pkgvarname) = ($1); | | 5644 | my ($pkgvarname) = ($1); |
5645 | if ($varname =~ m"^PKG_.*_REASON$") { | | 5645 | if ($varname =~ m"^PKG_.*_REASON$") { |
5646 | # ok | | 5646 | # ok |
5647 | } elsif ($varname =~ m"^(?:DIST_SUBDIR|WRKSRC)$") { | | 5647 | } elsif ($varname =~ m"^(?:DIST_SUBDIR|WRKSRC)$") { |
5648 | $line->log_warning("${pkgvarname} should not be used in ${varname}, as it sometimes includes the PKGREVISION. Please use ${pkgvarname}_NOREV instead."); | | 5648 | $line->log_warning("${pkgvarname} should not be used in ${varname}, as it sometimes includes the PKGREVISION. Please use ${pkgvarname}_NOREV instead."); |
5649 | } else { | | 5649 | } else { |
5650 | $opt_debug_misc and $line->log_debug("Use of PKGNAME in ${varname}."); | | 5650 | $opt_debug_misc and $line->log_debug("Use of PKGNAME in ${varname}."); |
5651 | } | | 5651 | } |
5652 | } | | 5652 | } |
5653 | | | 5653 | |
5654 | if (exists(get_deprecated_map()->{$varname})) { | | 5654 | if (exists(get_deprecated_map()->{$varname})) { |
5655 | $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varname}); | | 5655 | $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varname}); |
5656 | } elsif (exists(get_deprecated_map()->{$varcanon})) { | | 5656 | } elsif (exists(get_deprecated_map()->{$varcanon})) { |
5657 | $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varcanon}); | | 5657 | $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varcanon}); |
5658 | } | | 5658 | } |
5659 | | | 5659 | |
5660 | if ($varname =~ m"^SITES_") { | | 5660 | if ($varname =~ m"^SITES_") { |
5661 | $line->log_warning("SITES_* is deprecated. Please use SITES.* instead."); | | 5661 | $line->log_warning("SITES_* is deprecated. Please use SITES.* instead."); |
5662 | } | | 5662 | } |
5663 | | | 5663 | |
5664 | if ($value =~ m"^[^=]\@comment") { | | 5664 | if ($value =~ m"^[^=]\@comment") { |
5665 | $line->log_warning("Please don't use \@comment in ${varname}."); | | 5665 | $line->log_warning("Please don't use \@comment in ${varname}."); |
5666 | $line->explain_warning( | | 5666 | $line->explain_warning( |
5667 | "Here you are defining a variable containing \@comment. As this value", | | 5667 | "Here you are defining a variable containing \@comment. As this value", |
5668 | "typically includes a space as the last character you probably also used", | | 5668 | "typically includes a space as the last character you probably also used", |
5669 | "quotes around the variable. This can lead to confusion when adding this", | | 5669 | "quotes around the variable. This can lead to confusion when adding this", |
5670 | "variable to PLIST_SUBST, as all other variables are quoted using the :Q", | | 5670 | "variable to PLIST_SUBST, as all other variables are quoted using the :Q", |
5671 | "operator when they are appended. As it is hard to check whether a", | | 5671 | "operator when they are appended. As it is hard to check whether a", |
5672 | "variable that is appended to PLIST_SUBST is already quoted or not, you", | | 5672 | "variable that is appended to PLIST_SUBST is already quoted or not, you", |
5673 | "should not have pre-quoted variables at all. To solve this, you should", | | 5673 | "should not have pre-quoted variables at all. To solve this, you should", |
5674 | "directly use PLIST_SUBST+= ${varname}=${value} or use any other", | | 5674 | "directly use PLIST_SUBST+= ${varname}=${value} or use any other", |
5675 | "variable for collecting the list of PLIST substitutions and later", | | 5675 | "variable for collecting the list of PLIST substitutions and later", |
5676 | "append that variable with PLIST_SUBST+= \${MY_PLIST_SUBST}."); | | 5676 | "append that variable with PLIST_SUBST+= \${MY_PLIST_SUBST}."); |
5677 | } | | 5677 | } |
5678 | | | 5678 | |
5679 | # Mark the variable as PLIST condition. This is later used in | | 5679 | # Mark the variable as PLIST condition. This is later used in |
5680 | # checkfile_PLIST. | | 5680 | # checkfile_PLIST. |
5681 | if (defined($pkgctx_plist_subst_cond) && $value =~ m"(.+)=.*\@comment.*") { | | 5681 | if (defined($pkgctx_plist_subst_cond) && $value =~ m"(.+)=.*\@comment.*") { |
5682 | $pkgctx_plist_subst_cond->{$1}++; | | 5682 | $pkgctx_plist_subst_cond->{$1}++; |
5683 | } | | 5683 | } |
5684 | | | 5684 | |
5685 | use constant op_to_use_time => { | | 5685 | use constant op_to_use_time => { |
5686 | ":=" => VUC_TIME_LOAD, | | 5686 | ":=" => VUC_TIME_LOAD, |
5687 | "!=" => VUC_TIME_LOAD, | | 5687 | "!=" => VUC_TIME_LOAD, |
5688 | "=" => VUC_TIME_RUN, | | 5688 | "=" => VUC_TIME_RUN, |
5689 | "+=" => VUC_TIME_RUN, | | 5689 | "+=" => VUC_TIME_RUN, |
5690 | "?=" => VUC_TIME_RUN | | 5690 | "?=" => VUC_TIME_RUN |
5691 | }; | | 5691 | }; |
5692 | | | 5692 | |
5693 | $used_vars = extract_used_variables($line, $value); | | 5693 | $used_vars = extract_used_variables($line, $value); |
5694 | my $vuc = PkgLint::VarUseContext->new( | | 5694 | my $vuc = PkgLint::VarUseContext->new( |
5695 | op_to_use_time->{$op}, | | 5695 | op_to_use_time->{$op}, |
5696 | get_variable_type($line, $varname), | | 5696 | get_variable_type($line, $varname), |
5697 | VUC_SHELLWORD_UNKNOWN, # XXX: maybe PLAIN? | | 5697 | VUC_SHELLWORD_UNKNOWN, # XXX: maybe PLAIN? |
5698 | VUC_EXTENT_UNKNOWN | | 5698 | VUC_EXTENT_UNKNOWN |
5699 | ); | | 5699 | ); |
5700 | foreach my $used_var (@{$used_vars}) { | | 5700 | foreach my $used_var (@{$used_vars}) { |
5701 | checkline_mk_varuse($line, $used_var, "", $vuc); | | 5701 | checkline_mk_varuse($line, $used_var, "", $vuc); |
5702 | } | | 5702 | } |
5703 | } | | 5703 | } |
5704 | | | 5704 | |
5705 | # The bmake parser is way too sloppy about syntax, so we need to check | | 5705 | # The bmake parser is way too sloppy about syntax, so we need to check |
5706 | # that here. | | 5706 | # that here. |
5707 | # | | 5707 | # |
5708 | sub checkline_mk_cond($$) { | | 5708 | sub checkline_mk_cond($$) { |
5709 | my ($line, $cond) = @_; | | 5709 | my ($line, $cond) = @_; |
5710 | my ($op, $varname, $match, $value); | | 5710 | my ($op, $varname, $match, $value); |
5711 | | | 5711 | |
5712 | $opt_debug_trace and $line->log_debug("checkline_mk_cond($cond)"); | | 5712 | $opt_debug_trace and $line->log_debug("checkline_mk_cond($cond)"); |
5713 | my $tree = parse_mk_cond($line, $cond); | | 5713 | my $tree = parse_mk_cond($line, $cond); |
5714 | if (tree_match($tree, ["not", ["empty", ["match", \$varname, \$match]]])) { | | 5714 | if (tree_match($tree, ["not", ["empty", ["match", \$varname, \$match]]])) { |
5715 | #$line->log_note("tree_match: varname=$varname, match=$match"); | | 5715 | #$line->log_note("tree_match: varname=$varname, match=$match"); |
5716 | | | 5716 | |
5717 | my $type = get_variable_type($line, $varname); | | 5717 | my $type = get_variable_type($line, $varname); |
5718 | my $btype = defined($type) ? $type->basic_type : undef; | | 5718 | my $btype = defined($type) ? $type->basic_type : undef; |
5719 | if (defined($btype) && ref($type->basic_type) eq "HASH") { | | 5719 | if (defined($btype) && ref($type->basic_type) eq "HASH") { |
5720 | if ($match !~ m"[\$\[*]" && !exists($btype->{$match})) { | | 5720 | if ($match !~ m"[\$\[*]" && !exists($btype->{$match})) { |
5721 | $line->log_warning("Invalid :M value \"$match\". Only { " . join(" ", sort keys %$btype) . " } are allowed."); | | 5721 | $line->log_warning("Invalid :M value \"$match\". Only { " . join(" ", sort keys %$btype) . " } are allowed."); |
5722 | } | | 5722 | } |
5723 | } | | 5723 | } |
5724 | | | 5724 | |
5725 | # Currently disabled because the valid options can also be defined in PKG_OPTIONS_GROUP.*. | | 5725 | # Currently disabled because the valid options can also be defined in PKG_OPTIONS_GROUP.*. |
5726 | # Additionally, all these variables may have multiple assigments (+=). | | 5726 | # Additionally, all these variables may have multiple assigments (+=). |
5727 | if (false && $varname eq "PKG_OPTIONS" && defined($pkgctx_vardef) && exists($pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"})) { | | 5727 | if (false && $varname eq "PKG_OPTIONS" && defined($pkgctx_vardef) && exists($pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"})) { |
5728 | my $options = $pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"}->get("value"); | | 5728 | my $options = $pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"}->get("value"); |
5729 | | | 5729 | |
5730 | if ($match !~ m"[\$\[*]" && index(" $options ", " $match ") == -1) { | | 5730 | if ($match !~ m"[\$\[*]" && index(" $options ", " $match ") == -1) { |
5731 | $line->log_warning("Invalid option \"$match\". Only { $options } are allowed."); | | 5731 | $line->log_warning("Invalid option \"$match\". Only { $options } are allowed."); |
5732 | } | | 5732 | } |
5733 | } | | 5733 | } |
5734 | | | 5734 | |
5735 | # TODO: PKG_BUILD_OPTIONS. That requires loading the | | 5735 | # TODO: PKG_BUILD_OPTIONS. That requires loading the |
5736 | # complete package definitition for the package "pkgbase" | | 5736 | # complete package definitition for the package "pkgbase" |
5737 | # or some other database. If we could confine all option | | 5737 | # or some other database. If we could confine all option |
5738 | # definitions to options.mk, this would become easier. | | 5738 | # definitions to options.mk, this would become easier. |
5739 | | | 5739 | |
5740 | } elsif (tree_match($tree, [\$op, ["var", \$varname], ["string", \$value]])) { | | 5740 | } elsif (tree_match($tree, [\$op, ["var", \$varname], ["string", \$value]])) { |
5741 | checkline_mk_vartype($line, $varname, "use", $value, undef); | | 5741 | checkline_mk_vartype($line, $varname, "use", $value, undef); |
5742 | | | 5742 | |
5743 | } | | 5743 | } |
5744 | # XXX: When adding new cases, be careful that the variables may have | | 5744 | # XXX: When adding new cases, be careful that the variables may have |
5745 | # been partially initialized by previous calls to tree_match. | | 5745 | # been partially initialized by previous calls to tree_match. |
5746 | # XXX: Maybe it is better to clear these references at the beginning | | 5746 | # XXX: Maybe it is better to clear these references at the beginning |
5747 | # of tree_match. | | 5747 | # of tree_match. |
5748 | } | | 5748 | } |
5749 | | | 5749 | |
5750 | # | | 5750 | # |
5751 | # Procedures to check an array of lines. | | 5751 | # Procedures to check an array of lines. |
5752 | # | | 5752 | # |
5753 | | | 5753 | |
5754 | sub checklines_trailing_empty_lines($) { | | 5754 | sub checklines_trailing_empty_lines($) { |
5755 | my ($lines) = @_; | | 5755 | my ($lines) = @_; |
5756 | my ($last, $max); | | 5756 | my ($last, $max); |
5757 | | | 5757 | |
5758 | $max = $#{$lines} + 1; | | 5758 | $max = $#{$lines} + 1; |
5759 | for ($last = $max; $last > 1 && $lines->[$last - 1]->text eq ""; ) { | | 5759 | for ($last = $max; $last > 1 && $lines->[$last - 1]->text eq ""; ) { |
5760 | $last--; | | 5760 | $last--; |
5761 | } | | 5761 | } |
5762 | if ($last != $max) { | | 5762 | if ($last != $max) { |
5763 | $lines->[$last]->log_note("Trailing empty lines."); | | 5763 | $lines->[$last]->log_note("Trailing empty lines."); |
5764 | } | | 5764 | } |
5765 | } | | 5765 | } |
5766 | | | 5766 | |
5767 | sub checklines_package_Makefile_varorder($) { | | 5767 | sub checklines_package_Makefile_varorder($) { |
5768 | my ($lines) = @_; | | 5768 | my ($lines) = @_; |
5769 | | | 5769 | |
5770 | return unless $opt_warn_varorder; | | 5770 | return unless $opt_warn_varorder; |
5771 | | | 5771 | |
5772 | use enum qw(once optional many); | | 5772 | use enum qw(once optional many); |
5773 | my (@sections) = ( | | 5773 | my (@sections) = ( |
5774 | [ "Initial comments", once, | | 5774 | [ "Initial comments", once, |
5775 | [ | | 5775 | [ |
5776 | ] | | 5776 | ] |
5777 | ], | | 5777 | ], |
5778 | [ "Unsorted stuff, part 1", once, | | 5778 | [ "Unsorted stuff, part 1", once, |
5779 | [ | | 5779 | [ |
5780 | [ "DISTNAME", once ], | | 5780 | [ "DISTNAME", once ], |
5781 | [ "PKGNAME", optional ], | | 5781 | [ "PKGNAME", optional ], |
5782 | [ "PKGREVISION", optional ], | | 5782 | [ "PKGREVISION", optional ], |
5783 | [ "SVR4_PKGNAME", optional ], | | 5783 | [ "SVR4_PKGNAME", optional ], |
5784 | [ "CATEGORIES", once ], | | 5784 | [ "CATEGORIES", once ], |
5785 | [ "MASTER_SITES", optional ], | | 5785 | [ "MASTER_SITES", optional ], |
5786 | [ "DIST_SUBDIR", optional ], | | 5786 | [ "DIST_SUBDIR", optional ], |
5787 | [ "EXTRACT_SUFX", optional ], | | 5787 | [ "EXTRACT_SUFX", optional ], |
5788 | [ "DISTFILES", many ], | | 5788 | [ "DISTFILES", many ], |
5789 | [ "SITES.*", many ], | | 5789 | [ "SITES.*", many ], |
5790 | ] | | 5790 | ] |
5791 | ], | | 5791 | ], |
5792 | [ "Distribution patches", optional, | | 5792 | [ "Distribution patches", optional, |
5793 | [ | | 5793 | [ |
5794 | [ "PATCH_SITES", optional ], # or once? | | 5794 | [ "PATCH_SITES", optional ], # or once? |
5795 | [ "PATCH_SITE_SUBDIR", optional ], | | 5795 | [ "PATCH_SITE_SUBDIR", optional ], |
5796 | [ "PATCHFILES", optional ], # or once? | | 5796 | [ "PATCHFILES", optional ], # or once? |
5797 | [ "PATCH_DIST_ARGS", optional ], | | 5797 | [ "PATCH_DIST_ARGS", optional ], |
5798 | [ "PATCH_DIST_STRIP", optional ], | | 5798 | [ "PATCH_DIST_STRIP", optional ], |
5799 | [ "PATCH_DIST_CAT", optional ], | | 5799 | [ "PATCH_DIST_CAT", optional ], |
5800 | ] | | 5800 | ] |
5801 | ], | | 5801 | ], |
5802 | [ "Unsorted stuff, part 2", once, | | 5802 | [ "Unsorted stuff, part 2", once, |
5803 | [ | | 5803 | [ |
5804 | [ "MAINTAINER", optional ], | | 5804 | [ "MAINTAINER", optional ], |
5805 | [ "OWNER", optional ], | | 5805 | [ "OWNER", optional ], |
5806 | [ "HOMEPAGE", optional ], | | 5806 | [ "HOMEPAGE", optional ], |
5807 | [ "COMMENT", once ], | | 5807 | [ "COMMENT", once ], |
5808 | ] | | 5808 | ] |
5809 | ], | | 5809 | ], |
5810 | [ "Legal issues", optional, | | 5810 | [ "Legal issues", optional, |
5811 | [ | | 5811 | [ |
5812 | [ "LICENSE", once ], | | 5812 | [ "LICENSE", once ], |
5813 | [ "RESTRICTED", optional ], | | 5813 | [ "RESTRICTED", optional ], |
5814 | [ "NO_BIN_ON_CDROM", optional ], | | 5814 | [ "NO_BIN_ON_CDROM", optional ], |
5815 | [ "NO_BIN_ON_FTP", optional ], | | 5815 | [ "NO_BIN_ON_FTP", optional ], |
5816 | [ "NO_SRC_ON_CDROM", optional ], | | 5816 | [ "NO_SRC_ON_CDROM", optional ], |
5817 | [ "NO_SRC_ON_FTP", optional ], | | 5817 | [ "NO_SRC_ON_FTP", optional ], |
5818 | ] | | 5818 | ] |
5819 | ], | | 5819 | ], |
5820 | [ "Technical restrictions", optional, | | 5820 | [ "Technical restrictions", optional, |
5821 | [ | | 5821 | [ |
5822 | [ "NOT_FOR_PLATFORM", many ], | | 5822 | [ "NOT_FOR_PLATFORM", many ], |
5823 | [ "ONLY_FOR_PLATFORM", many ], | | 5823 | [ "ONLY_FOR_PLATFORM", many ], |
5824 | [ "NOT_FOR_COMPILER", many ], | | 5824 | [ "NOT_FOR_COMPILER", many ], |
5825 | [ "ONLY_FOR_COMPILER", many ], | | 5825 | [ "ONLY_FOR_COMPILER", many ], |
5826 | [ "NOT_FOR_UNPRIVILEGED", optional ], | | 5826 | [ "NOT_FOR_UNPRIVILEGED", optional ], |
5827 | [ "ONLY_FOR_UNPRIVILEGED", optional ], | | 5827 | [ "ONLY_FOR_UNPRIVILEGED", optional ], |
5828 | ] | | 5828 | ] |
5829 | ], | | 5829 | ], |
5830 | [ "Dependencies", optional, | | 5830 | [ "Dependencies", optional, |
5831 | [ | | 5831 | [ |
5832 | [ "BUILD_DEPENDS", many ], | | 5832 | [ "BUILD_DEPENDS", many ], |
5833 | [ "DEPENDS", many ], | | 5833 | [ "DEPENDS", many ], |
5834 | ] | | 5834 | ] |
5835 | ] | | 5835 | ] |
5836 | ); | | 5836 | ); |
5837 | | | 5837 | |
5838 | if (!defined($seen_Makefile_common) || $seen_Makefile_common) { | | 5838 | if (!defined($seen_Makefile_common) || $seen_Makefile_common) { |
5839 | return; | | 5839 | return; |
5840 | } | | 5840 | } |
5841 | | | 5841 | |
5842 | my ($lineno, $sectindex, $varindex) = (0, -1, 0); | | 5842 | my ($lineno, $sectindex, $varindex) = (0, -1, 0); |
5843 | my ($next_section, $vars, $below, $below_what) = (true, undef, {}, undef); | | 5843 | my ($next_section, $vars, $below, $below_what) = (true, undef, {}, undef); |
5844 | | | 5844 | |
5845 | # If the current section is optional but contains non-optional | | 5845 | # If the current section is optional but contains non-optional |
5846 | # fields, the complete section may be skipped as long as there | | 5846 | # fields, the complete section may be skipped as long as there |
5847 | # has not been a non-optional variable. | | 5847 | # has not been a non-optional variable. |
5848 | my $may_skip_section = false; | | 5848 | my $may_skip_section = false; |
5849 | | | 5849 | |
5850 | # In each iteration, one of the following becomes true: | | 5850 | # In each iteration, one of the following becomes true: |
5851 | # - new.lineno > old.lineno | | 5851 | # - new.lineno > old.lineno |
5852 | # - new.sectindex > old.sectindex | | 5852 | # - new.sectindex > old.sectindex |
5853 | # - new.sectindex == old.sectindex && new.varindex > old.varindex | | 5853 | # - new.sectindex == old.sectindex && new.varindex > old.varindex |
5854 | # - new.next_section == true && old.next_section == false | | 5854 | # - new.next_section == true && old.next_section == false |
5855 | while ($lineno <= $#{$lines}) { | | 5855 | while ($lineno <= $#{$lines}) { |
5856 | my $line = $lines->[$lineno]; | | 5856 | my $line = $lines->[$lineno]; |
5857 | my $text = $line->text; | | 5857 | my $text = $line->text; |
5858 | | | 5858 | |
5859 | $opt_debug_misc and $line->log_debug("[varorder] section ${sectindex} variable ${varindex}."); | | 5859 | $opt_debug_misc and $line->log_debug("[varorder] section ${sectindex} variable ${varindex}."); |
5860 | | | 5860 | |
5861 | if ($next_section) { | | 5861 | if ($next_section) { |
5862 | $next_section = false; | | 5862 | $next_section = false; |
5863 | $sectindex++; | | 5863 | $sectindex++; |
5864 | last if ($sectindex > $#sections); | | 5864 | last if ($sectindex > $#sections); |
5865 | $vars = $sections[$sectindex]->[2]; | | 5865 | $vars = $sections[$sectindex]->[2]; |
5866 | $may_skip_section = ($sections[$sectindex]->[1] == optional); | | 5866 | $may_skip_section = ($sections[$sectindex]->[1] == optional); |
5867 | $varindex = 0; | | 5867 | $varindex = 0; |
5868 | } | | 5868 | } |
5869 | | | 5869 | |
5870 | if ($text =~ m"^#") { | | 5870 | if ($text =~ m"^#") { |
5871 | $lineno++; | | 5871 | $lineno++; |
5872 | | | 5872 | |
5873 | } elsif ($line->has("varcanon")) { | | 5873 | } elsif ($line->has("varcanon")) { |
5874 | my $varcanon = $line->get("varcanon"); | | 5874 | my $varcanon = $line->get("varcanon"); |
5875 | | | 5875 | |
5876 | if (exists($below->{$varcanon})) { | | 5876 | if (exists($below->{$varcanon})) { |
5877 | if (defined($below->{$varcanon})) { | | 5877 | if (defined($below->{$varcanon})) { |
5878 | $line->log_warning("${varcanon} appears too late. Please put it below $below->{$varcanon}."); | | 5878 | $line->log_warning("${varcanon} appears too late. Please put it below $below->{$varcanon}."); |
5879 | } else { | | 5879 | } else { |
5880 | $line->log_warning("${varcanon} appears too late. It should be the very first definition."); | | 5880 | $line->log_warning("${varcanon} appears too late. It should be the very first definition."); |
5881 | } | | 5881 | } |
5882 | $lineno++; | | 5882 | $lineno++; |
5883 | next; | | 5883 | next; |
5884 | } | | 5884 | } |
5885 | | | 5885 | |
5886 | while ($varindex <= $#{$vars} && $varcanon ne $vars->[$varindex]->[0] && ($vars->[$varindex]->[1] != once || $may_skip_section)) { | | 5886 | while ($varindex <= $#{$vars} && $varcanon ne $vars->[$varindex]->[0] && ($vars->[$varindex]->[1] != once || $may_skip_section)) { |
5887 | if ($vars->[$varindex]->[1] == once) { | | 5887 | if ($vars->[$varindex]->[1] == once) { |
5888 | $may_skip_section = false; | | 5888 | $may_skip_section = false; |
5889 | } | | 5889 | } |
5890 | $below->{$vars->[$varindex]->[0]} = $below_what; | | 5890 | $below->{$vars->[$varindex]->[0]} = $below_what; |
5891 | $varindex++; | | 5891 | $varindex++; |
5892 | } | | 5892 | } |
5893 | if ($varindex > $#{$vars}) { | | 5893 | if ($varindex > $#{$vars}) { |
5894 | if ($sections[$sectindex]->[1] != optional) { | | 5894 | if ($sections[$sectindex]->[1] != optional) { |
5895 | $line->log_warning("Empty line expected."); | | 5895 | $line->log_warning("Empty line expected."); |
5896 | } | | 5896 | } |
5897 | $next_section = true; | | 5897 | $next_section = true; |
5898 | | | 5898 | |
5899 | } elsif ($varcanon ne $vars->[$varindex]->[0]) { | | 5899 | } elsif ($varcanon ne $vars->[$varindex]->[0]) { |
5900 | $line->log_warning("Expected " . $vars->[$varindex]->[0] . ", but found " . $varcanon . "."); | | 5900 | $line->log_warning("Expected " . $vars->[$varindex]->[0] . ", but found " . $varcanon . "."); |
5901 | $lineno++; | | 5901 | $lineno++; |
5902 | | | 5902 | |
5903 | } else { | | 5903 | } else { |
5904 | if ($vars->[$varindex]->[1] != many) { | | 5904 | if ($vars->[$varindex]->[1] != many) { |
5905 | $below->{$vars->[$varindex]->[0]} = $below_what; | | 5905 | $below->{$vars->[$varindex]->[0]} = $below_what; |
5906 | $varindex++; | | 5906 | $varindex++; |
5907 | } | | 5907 | } |
5908 | $lineno++; | | 5908 | $lineno++; |
5909 | } | | 5909 | } |
5910 | $below_what = $varcanon; | | 5910 | $below_what = $varcanon; |
5911 | | | 5911 | |
5912 | } else { | | 5912 | } else { |
5913 | while ($varindex <= $#{$vars}) { | | 5913 | while ($varindex <= $#{$vars}) { |
5914 | if ($vars->[$varindex]->[1] == once && !$may_skip_section) { | | 5914 | if ($vars->[$varindex]->[1] == once && !$may_skip_section) { |
5915 | $line->log_warning($vars->[$varindex]->[0] . " should be set here."); | | 5915 | $line->log_warning($vars->[$varindex]->[0] . " should be set here."); |
5916 | } | | 5916 | } |
5917 | $below->{$vars->[$varindex]->[0]} = $below_what; | | 5917 | $below->{$vars->[$varindex]->[0]} = $below_what; |
5918 | $varindex++; | | 5918 | $varindex++; |
5919 | } | | 5919 | } |
5920 | $next_section = true; | | 5920 | $next_section = true; |
5921 | if ($text eq "") { | | 5921 | if ($text eq "") { |
5922 | $below_what = "the previous empty line"; | | 5922 | $below_what = "the previous empty line"; |
5923 | $lineno++; | | 5923 | $lineno++; |
5924 | } | | 5924 | } |
5925 | } | | 5925 | } |
5926 | } | | 5926 | } |
5927 | } | | 5927 | } |
5928 | | | 5928 | |
5929 | sub checklines_mk($) { | | 5929 | sub checklines_mk($) { |
5930 | my ($lines) = @_; | | 5930 | my ($lines) = @_; |
5931 | my ($allowed_targets) = ({}); | | 5931 | my ($allowed_targets) = ({}); |
5932 | my ($substcontext) = PkgLint::SubstContext->new(); | | 5932 | my ($substcontext) = PkgLint::SubstContext->new(); |
5933 | | | 5933 | |
5934 | assert(@{$lines} != 0, "checklines_mk may only be called with non-empty lines."); | | 5934 | assert(@{$lines} != 0, "checklines_mk may only be called with non-empty lines."); |
5935 | $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_mk()"); | | 5935 | $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_mk()"); |
5936 | | | 5936 | |
5937 | # Define global variables for the Makefile context. | | 5937 | # Define global variables for the Makefile context. |
5938 | $mkctx_indentations = [0]; | | 5938 | $mkctx_indentations = [0]; |
5939 | $mkctx_target = undef; | | 5939 | $mkctx_target = undef; |
5940 | $mkctx_for_variables = {}; | | 5940 | $mkctx_for_variables = {}; |
5941 | $mkctx_vardef = {}; | | 5941 | $mkctx_vardef = {}; |
5942 | $mkctx_build_defs = {}; | | 5942 | $mkctx_build_defs = {}; |
5943 | $mkctx_plist_vars = {}; | | 5943 | $mkctx_plist_vars = {}; |
5944 | $mkctx_tools = {%{get_predefined_tool_names()}}; | | 5944 | $mkctx_tools = {%{get_predefined_tool_names()}}; |
5945 | $mkctx_varuse = {}; | | 5945 | $mkctx_varuse = {}; |
5946 | | | 5946 | |
5947 | determine_used_variables($lines); | | 5947 | determine_used_variables($lines); |
5948 | | | 5948 | |
5949 | foreach my $prefix (qw(pre do post)) { | | 5949 | foreach my $prefix (qw(pre do post)) { |
5950 | foreach my $action (qw(fetch extract patch tools wrapper configure build test install package clean)) { | | 5950 | foreach my $action (qw(fetch extract patch tools wrapper configure build test install package clean)) { |
5951 | $allowed_targets->{"${prefix}-${action}"} = true; | | 5951 | $allowed_targets->{"${prefix}-${action}"} = true; |
5952 | } | | 5952 | } |
5953 | } | | 5953 | } |
5954 | | | 5954 | |
5955 | # | | 5955 | # |
5956 | # In the first pass, all additions to BUILD_DEFS and USE_TOOLS | | 5956 | # In the first pass, all additions to BUILD_DEFS and USE_TOOLS |
5957 | # are collected to make the order of the definitions irrelevant. | | 5957 | # are collected to make the order of the definitions irrelevant. |
5958 | # | | 5958 | # |
5959 | | | 5959 | |
5960 | foreach my $line (@{$lines}) { | | 5960 | foreach my $line (@{$lines}) { |
5961 | next unless $line->has("is_varassign"); | | 5961 | next unless $line->has("is_varassign"); |
5962 | my $varcanon = $line->get("varcanon"); | | 5962 | my $varcanon = $line->get("varcanon"); |
5963 | | | 5963 | |
5964 | if ($varcanon eq "BUILD_DEFS" || $varcanon eq "PKG_GROUPS_VARS" || $varcanon eq "PKG_USERS_VARS") { | | 5964 | if ($varcanon eq "BUILD_DEFS" || $varcanon eq "PKG_GROUPS_VARS" || $varcanon eq "PKG_USERS_VARS") { |
5965 | foreach my $varname (split(qr"\s+", $line->get("value"))) { | | 5965 | foreach my $varname (split(qr"\s+", $line->get("value"))) { |
5966 | $mkctx_build_defs->{$varname} = true; | | 5966 | $mkctx_build_defs->{$varname} = true; |
5967 | $opt_debug_misc and $line->log_debug("${varname} is added to BUILD_DEFS."); | | 5967 | $opt_debug_misc and $line->log_debug("${varname} is added to BUILD_DEFS."); |
5968 | } | | 5968 | } |
5969 | | | 5969 | |
5970 | } elsif ($varcanon eq "PLIST_VARS") { | | 5970 | } elsif ($varcanon eq "PLIST_VARS") { |
5971 | foreach my $id (split(qr"\s+", $line->get("value"))) { | | 5971 | foreach my $id (split(qr"\s+", $line->get("value"))) { |
5972 | $mkctx_plist_vars->{"PLIST.$id"} = true; | | 5972 | $mkctx_plist_vars->{"PLIST.$id"} = true; |
5973 | $opt_debug_misc and $line->log_debug("PLIST.${id} is added to PLIST_VARS."); | | 5973 | $opt_debug_misc and $line->log_debug("PLIST.${id} is added to PLIST_VARS."); |
5974 | use_var($line, "PLIST.$id"); | | 5974 | use_var($line, "PLIST.$id"); |
5975 | } | | 5975 | } |
5976 | | | 5976 | |
5977 | } elsif ($varcanon eq "USE_TOOLS") { | | 5977 | } elsif ($varcanon eq "USE_TOOLS") { |
5978 | foreach my $tool (split(qr"\s+", $line->get("value"))) { | | 5978 | foreach my $tool (split(qr"\s+", $line->get("value"))) { |
5979 | $mkctx_tools->{$tool} = true; | | 5979 | $mkctx_tools->{$tool} = true; |
5980 | $opt_debug_misc and $line->log_debug("${tool} is added to USE_TOOLS."); | | 5980 | $opt_debug_misc and $line->log_debug("${tool} is added to USE_TOOLS."); |
5981 | } | | 5981 | } |
5982 | | | 5982 | |
5983 | } elsif ($varcanon eq "SUBST_VARS.*") { | | 5983 | } elsif ($varcanon eq "SUBST_VARS.*") { |
5984 | foreach my $svar (split(/\s+/, $line->get("value"))) { | | 5984 | foreach my $svar (split(/\s+/, $line->get("value"))) { |
5985 | use_var($svar, varname_canon($svar)); | | 5985 | use_var($svar, varname_canon($svar)); |
5986 | $opt_debug_misc and $line->log_debug("varuse $svar"); | | 5986 | $opt_debug_misc and $line->log_debug("varuse $svar"); |
5987 | } | | 5987 | } |
5988 | } | | 5988 | } |
5989 | } | | 5989 | } |
5990 | | | 5990 | |
5991 | # | | 5991 | # |
5992 | # In the second pass, all "normal" checks are done. | | 5992 | # In the second pass, all "normal" checks are done. |
5993 | # | | 5993 | # |
5994 | | | 5994 | |
5995 | if (0 <= $#{$lines}) { | | 5995 | if (0 <= $#{$lines}) { |
5996 | checkline_rcsid_regex($lines->[0], qr"^#\s+", "# "); | | 5996 | checkline_rcsid_regex($lines->[0], qr"^#\s+", "# "); |
5997 | } | | 5997 | } |
5998 | | | 5998 | |
5999 | foreach my $line (@{$lines}) { | | 5999 | foreach my $line (@{$lines}) { |
6000 | my $text = $line->text; | | 6000 | my $text = $line->text; |
6001 | | | 6001 | |
6002 | checkline_trailing_whitespace($line); | | 6002 | checkline_trailing_whitespace($line); |
6003 | checkline_spellcheck($line); | | 6003 | checkline_spellcheck($line); |
6004 | | | 6004 | |
6005 | if ($line->has("is_empty")) { | | 6005 | if ($line->has("is_empty")) { |
6006 | $substcontext->check_end($line); | | 6006 | $substcontext->check_end($line); |
6007 | | | 6007 | |
6008 | } elsif ($line->has("is_comment")) { | | 6008 | } elsif ($line->has("is_comment")) { |
6009 | # No further checks. | | 6009 | # No further checks. |
6010 | | | 6010 | |
6011 | } elsif ($text =~ regex_varassign) { | | 6011 | } elsif ($text =~ regex_varassign) { |
6012 | my ($varname, $op, undef, $comment) = ($1, $2, $3, $4); | | 6012 | my ($varname, $op, undef, $comment) = ($1, $2, $3, $4); |
6013 | my $space1 = substr($text, $+[1], $-[2] - $+[1]); | | 6013 | my $space1 = substr($text, $+[1], $-[2] - $+[1]); |
6014 | my $align = substr($text, $+[2], $-[3] - $+[2]); | | 6014 | my $align = substr($text, $+[2], $-[3] - $+[2]); |
6015 | my $value = $line->get("value"); | | 6015 | my $value = $line->get("value"); |
6016 | | | 6016 | |
6017 | if ($align !~ m"^(\t*|[ ])$") { | | 6017 | if ($align !~ m"^(\t*|[ ])$") { |
6018 | $opt_warn_space && $line->log_note("Alignment of variable values should be done with tabs, not spaces."); | | 6018 | $opt_warn_space && $line->log_note("Alignment of variable values should be done with tabs, not spaces."); |
6019 | my $prefix = "${varname}${space1}${op}"; | | 6019 | my $prefix = "${varname}${space1}${op}"; |
6020 | my $aligned_len = tablen("${prefix}${align}"); | | 6020 | my $aligned_len = tablen("${prefix}${align}"); |
6021 | if ($aligned_len % 8 == 0) { | | 6021 | if ($aligned_len % 8 == 0) { |
6022 | my $tabalign = ("\t" x (($aligned_len - tablen($prefix) + 7) / 8)); | | 6022 | my $tabalign = ("\t" x (($aligned_len - tablen($prefix) + 7) / 8)); |
6023 | $line->replace("${prefix}${align}", "${prefix}${tabalign}"); | | 6023 | $line->replace("${prefix}${align}", "${prefix}${tabalign}"); |
6024 | } | | 6024 | } |
6025 | } | | 6025 | } |
6026 | checkline_mk_varassign($line, $varname, $op, $value, $comment); | | 6026 | checkline_mk_varassign($line, $varname, $op, $value, $comment); |
6027 | $substcontext->check_varassign($line, $varname, $op, $value); | | 6027 | $substcontext->check_varassign($line, $varname, $op, $value); |
6028 | | | 6028 | |
6029 | } elsif ($text =~ regex_mk_shellcmd) { | | 6029 | } elsif ($text =~ regex_mk_shellcmd) { |
6030 | my ($shellcmd) = ($1); | | 6030 | my ($shellcmd) = ($1); |
6031 | checkline_mk_shellcmd($line, $shellcmd); | | 6031 | checkline_mk_shellcmd($line, $shellcmd); |
6032 | | | 6032 | |
6033 | } elsif ($text =~ regex_mk_include) { | | 6033 | } elsif ($text =~ regex_mk_include) { |
6034 | my ($include, $includefile) = ($1, $2); | | 6034 | my ($include, $includefile) = ($1, $2); |
6035 | | | 6035 | |
6036 | $opt_debug_include and $line->log_debug("includefile=${includefile}"); | | 6036 | $opt_debug_include and $line->log_debug("includefile=${includefile}"); |
6037 | checkline_relative_path($line, $includefile, $include eq "include"); | | 6037 | checkline_relative_path($line, $includefile, $include eq "include"); |
6038 | | | 6038 | |
6039 | if ($includefile =~ m"../Makefile$") { | | 6039 | if ($includefile =~ m"../Makefile$") { |
6040 | $line->log_error("Other Makefiles must not be included directly."); | | 6040 | $line->log_error("Other Makefiles must not be included directly."); |
6041 | $line->explain_warning( | | 6041 | $line->explain_warning( |
6042 | "If you want to include portions of another Makefile, extract", | | 6042 | "If you want to include portions of another Makefile, extract", |
6043 | "the common parts and put them into a Makefile.common. After", | | 6043 | "the common parts and put them into a Makefile.common. After", |
6044 | "that, both this one and the other package should include the", | | 6044 | "that, both this one and the other package should include the", |
6045 | "Makefile.common."); | | 6045 | "Makefile.common."); |
6046 | } | | 6046 | } |
6047 | | | 6047 | |
6048 | if ($includefile eq "../../mk/bsd.prefs.mk") { | | 6048 | if ($includefile eq "../../mk/bsd.prefs.mk") { |
6049 | if ($line->fname =~ m"buildlink3\.mk$") { | | 6049 | if ($line->fname =~ m"buildlink3\.mk$") { |
6050 | $line->log_note("For efficiency reasons, please include bsd.fast.prefs.mk instead of bsd.prefs.mk."); | | 6050 | $line->log_note("For efficiency reasons, please include bsd.fast.prefs.mk instead of bsd.prefs.mk."); |
6051 | } | | 6051 | } |
6052 | $seen_bsd_prefs_mk = true; | | 6052 | $seen_bsd_prefs_mk = true; |
6053 | } elsif ($includefile eq "../../mk/bsd.fast.prefs.mk") { | | 6053 | } elsif ($includefile eq "../../mk/bsd.fast.prefs.mk") { |
6054 | $seen_bsd_prefs_mk = true; | | 6054 | $seen_bsd_prefs_mk = true; |
6055 | } | | 6055 | } |
6056 | | | 6056 | |
6057 | if ($includefile =~ m"/x11-links/buildlink3\.mk$") { | | 6057 | if ($includefile =~ m"/x11-links/buildlink3\.mk$") { |
6058 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead."); | | 6058 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead."); |
6059 | } | | 6059 | } |
6060 | if ($includefile =~ m"/intltool/buildlink3\.mk$") { | | 6060 | if ($includefile =~ m"/intltool/buildlink3\.mk$") { |
6061 | $line->log_warning("Please say \"USE_TOOLS+= intltool\" instead of this line."); | | 6061 | $line->log_warning("Please say \"USE_TOOLS+= intltool\" instead of this line."); |
6062 | } | | 6062 | } |
6063 | if ($includefile =~ m"(.*)/builtin\.mk$") { | | 6063 | if ($includefile =~ m"(.*)/builtin\.mk$") { |
6064 | my ($dir) = ($1); | | 6064 | my ($dir) = ($1); |
6065 | $line->log_error("${includefile} must not be included directly. Include \"${dir}/buildlink3.mk\" instead."); | | 6065 | $line->log_error("${includefile} must not be included directly. Include \"${dir}/buildlink3.mk\" instead."); |
6066 | } | | 6066 | } |
6067 | | | 6067 | |
6068 | } elsif ($text =~ regex_mk_sysinclude) { | | 6068 | } elsif ($text =~ regex_mk_sysinclude) { |
6069 | my ($includefile, $comment) = ($1, $2); | | 6069 | my ($includefile, $comment) = ($1, $2); |
6070 | | | 6070 | |
6071 | # No further action. | | 6071 | # No further action. |
6072 | | | 6072 | |
6073 | } elsif ($text =~ regex_mk_cond) { | | 6073 | } elsif ($text =~ regex_mk_cond) { |
6074 | my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4); | | 6074 | my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4); |
6075 | | | 6075 | |
6076 | use constant regex_directives_with_args => qr"^(?:if|ifdef|ifndef|elif|for|undef)$"; | | 6076 | use constant regex_directives_with_args => qr"^(?:if|ifdef|ifndef|elif|for|undef)$"; |
6077 | | | 6077 | |
6078 | if ($directive =~ m"^(?:endif|endfor|elif|else)$") { | | 6078 | if ($directive =~ m"^(?:endif|endfor|elif|else)$") { |
6079 | if ($#{$mkctx_indentations} >= 1) { | | 6079 | if ($#{$mkctx_indentations} >= 1) { |
6080 | pop(@{$mkctx_indentations}); | | 6080 | pop(@{$mkctx_indentations}); |
6081 | } else { | | 6081 | } else { |
6082 | $line->log_error("Unmatched .${directive}."); | | 6082 | $line->log_error("Unmatched .${directive}."); |
6083 | } | | 6083 | } |
6084 | } | | 6084 | } |
6085 | | | 6085 | |
6086 | # Check the indentation | | 6086 | # Check the indentation |
6087 | if ($indent ne " " x $mkctx_indentations->[-1]) { | | 6087 | if ($indent ne " " x $mkctx_indentations->[-1]) { |
6088 | $opt_warn_space and $line->log_note("This directive should be indented by ".$mkctx_indentations->[-1]." spaces."); | | 6088 | $opt_warn_space and $line->log_note("This directive should be indented by ".$mkctx_indentations->[-1]." spaces."); |
6089 | } | | 6089 | } |
6090 | | | 6090 | |
6091 | if ($directive eq "if" && $args =~ m"^!defined\([\w]+_MK\)$") { | | 6091 | if ($directive eq "if" && $args =~ m"^!defined\([\w]+_MK\)$") { |
6092 | push(@{$mkctx_indentations}, $mkctx_indentations->[-1]); | | 6092 | push(@{$mkctx_indentations}, $mkctx_indentations->[-1]); |
6093 | | | 6093 | |
6094 | } elsif ($directive =~ m"^(?:if|ifdef|ifndef|for|elif|else)$") { | | 6094 | } elsif ($directive =~ m"^(?:if|ifdef|ifndef|for|elif|else)$") { |
6095 | push(@{$mkctx_indentations}, $mkctx_indentations->[-1] + 2); | | 6095 | push(@{$mkctx_indentations}, $mkctx_indentations->[-1] + 2); |
6096 | } | | 6096 | } |
6097 | | | 6097 | |
6098 | if ($directive =~ regex_directives_with_args && !defined($args)) { | | 6098 | if ($directive =~ regex_directives_with_args && !defined($args)) { |
6099 | $line->log_error("\".${directive}\" must be given some arguments."); | | 6099 | $line->log_error("\".${directive}\" must be given some arguments."); |
6100 | | | 6100 | |
6101 | } elsif ($directive !~ regex_directives_with_args && defined($args)) { | | 6101 | } elsif ($directive !~ regex_directives_with_args && defined($args)) { |
6102 | $line->log_error("\".${directive}\" does not take arguments."); | | 6102 | $line->log_error("\".${directive}\" does not take arguments."); |
6103 | | | 6103 | |
6104 | if ($directive eq "else") { | | 6104 | if ($directive eq "else") { |
6105 | $line->log_note("If you meant \"else if\", use \".elif\"."); | | 6105 | $line->log_note("If you meant \"else if\", use \".elif\"."); |
6106 | } | | 6106 | } |
6107 | | | 6107 | |
6108 | } elsif ($directive eq "if" || $directive eq "elif") { | | 6108 | } elsif ($directive eq "if" || $directive eq "elif") { |
6109 | checkline_mk_cond($line, $args); | | 6109 | checkline_mk_cond($line, $args); |
6110 | | | 6110 | |
6111 | } elsif ($directive eq "ifdef" || $directive eq "ifndef") { | | 6111 | } elsif ($directive eq "ifdef" || $directive eq "ifndef") { |
6112 | if ($args =~ m"\s") { | | 6112 | if ($args =~ m"\s") { |
6113 | $line->log_error("The \".${directive}\" directive can only handle _one_ argument."); | | 6113 | $line->log_error("The \".${directive}\" directive can only handle _one_ argument."); |
6114 | } else { | | 6114 | } else { |
6115 | $line->log_warning("The \".${directive}\" directive is deprecated. Please use \".if " | | 6115 | $line->log_warning("The \".${directive}\" directive is deprecated. Please use \".if " |
6116 | . (($directive eq "ifdef" ? "" : "!")) | | 6116 | . (($directive eq "ifdef" ? "" : "!")) |
6117 | . "defined(${args})\" instead."); | | 6117 | . "defined(${args})\" instead."); |
6118 | } | | 6118 | } |
6119 | | | 6119 | |
6120 | } elsif ($directive eq "for") { | | 6120 | } elsif ($directive eq "for") { |
6121 | if ($args =~ m"^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$") { | | 6121 | if ($args =~ m"^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$") { |
6122 | my ($vars, $values) = ($1, $2); | | 6122 | my ($vars, $values) = ($1, $2); |
6123 | | | 6123 | |
6124 | foreach my $var (split(qr"\s+", $vars)) { | | 6124 | foreach my $var (split(qr"\s+", $vars)) { |
6125 | if (!$is_internal && $var =~ m"^_") { | | 6125 | if (!$is_internal && $var =~ m"^_") { |
6126 | $line->log_warning("Variable names starting with an underscore are reserved for internal pkgsrc use."); | | 6126 | $line->log_warning("Variable names starting with an underscore are reserved for internal pkgsrc use."); |
6127 | } | | 6127 | } |
6128 | | | 6128 | |
6129 | if ($var =~ m"^[_a-z][_a-z0-9]*$") { | | 6129 | if ($var =~ m"^[_a-z][_a-z0-9]*$") { |
6130 | # Fine. | | 6130 | # Fine. |
6131 | } elsif ($var =~ m"[A-Z]") { | | 6131 | } elsif ($var =~ m"[A-Z]") { |
6132 | $line->log_warning(".for variable names should not contain uppercase letters."); | | 6132 | $line->log_warning(".for variable names should not contain uppercase letters."); |
6133 | } else { | | 6133 | } else { |
6134 | $line->log_error("Invalid variable name \"${var}\"."); | | 6134 | $line->log_error("Invalid variable name \"${var}\"."); |
6135 | } | | 6135 | } |
6136 | | | 6136 | |
6137 | $mkctx_for_variables->{$var} = true; | | 6137 | $mkctx_for_variables->{$var} = true; |
6138 | } | | 6138 | } |
6139 | | | 6139 | |
6140 | # Check if any of the value's types is not guessed. | | 6140 | # Check if any of the value's types is not guessed. |
6141 | my $guessed = true; | | 6141 | my $guessed = true; |
6142 | foreach my $value (split(qr"\s+", $values)) { # XXX: too simple | | 6142 | foreach my $value (split(qr"\s+", $values)) { # XXX: too simple |
6143 | if ($value =~ m"^\$\{(.*)\}") { | | 6143 | if ($value =~ m"^\$\{(.*)\}") { |
6144 | my $type = get_variable_type($line, $1); | | 6144 | my $type = get_variable_type($line, $1); |
6145 | if (defined($type) && !$type->is_guessed()) { | | 6145 | if (defined($type) && !$type->is_guessed()) { |
6146 | $guessed = false; | | 6146 | $guessed = false; |
6147 | } | | 6147 | } |
6148 | } | | 6148 | } |
6149 | } | | 6149 | } |
6150 | | | 6150 | |
6151 | my $for_loop_type = PkgLint::Type->new( | | 6151 | my $for_loop_type = PkgLint::Type->new( |
6152 | LK_INTERNAL, | | 6152 | LK_INTERNAL, |
6153 | "Unchecked", | | 6153 | "Unchecked", |
6154 | [[qr".*", "pu"]], | | 6154 | [[qr".*", "pu"]], |
6155 | $guessed | | 6155 | $guessed |
6156 | ); | | 6156 | ); |
6157 | my $for_loop_context = PkgLint::VarUseContext->new( | | 6157 | my $for_loop_context = PkgLint::VarUseContext->new( |
6158 | VUC_TIME_LOAD, | | 6158 | VUC_TIME_LOAD, |
6159 | $for_loop_type, | | 6159 | $for_loop_type, |
6160 | VUC_SHELLWORD_FOR, | | 6160 | VUC_SHELLWORD_FOR, |
6161 | VUC_EXTENT_WORD | | 6161 | VUC_EXTENT_WORD |
6162 | ); | | 6162 | ); |
6163 | foreach my $var (@{extract_used_variables($line, $values)}) { | | 6163 | foreach my $var (@{extract_used_variables($line, $values)}) { |
6164 | checkline_mk_varuse($line, $var, "", $for_loop_context); | | 6164 | checkline_mk_varuse($line, $var, "", $for_loop_context); |
6165 | } | | 6165 | } |
6166 | | | 6166 | |
6167 | } | | 6167 | } |
6168 | | | 6168 | |
6169 | } elsif ($directive eq "undef" && defined($args)) { | | 6169 | } elsif ($directive eq "undef" && defined($args)) { |
6170 | foreach my $var (split(qr"\s+", $args)) { | | 6170 | foreach my $var (split(qr"\s+", $args)) { |
6171 | if (exists($mkctx_for_variables->{$var})) { | | 6171 | if (exists($mkctx_for_variables->{$var})) { |
6172 | $line->log_note("Using \".undef\" after a \".for\" loop is unnecessary."); | | 6172 | $line->log_note("Using \".undef\" after a \".for\" loop is unnecessary."); |
6173 | } | | 6173 | } |
6174 | } | | 6174 | } |
6175 | } | | 6175 | } |
6176 | | | 6176 | |
6177 | } elsif ($text =~ regex_mk_dependency) { | | 6177 | } elsif ($text =~ regex_mk_dependency) { |
6178 | my ($targets, $dependencies) = ($1, $2); | | 6178 | my ($targets, $dependencies) = ($1, $2); |
6179 | | | 6179 | |
6180 | $opt_debug_misc and $line->log_debug("targets=${targets}, dependencies=${dependencies}"); | | 6180 | $opt_debug_misc and $line->log_debug("targets=${targets}, dependencies=${dependencies}"); |
6181 | $mkctx_target = $targets; | | 6181 | $mkctx_target = $targets; |
6182 | | | 6182 | |
6183 | foreach my $source (split(/\s+/, $dependencies)) { | | 6183 | foreach my $source (split(/\s+/, $dependencies)) { |
6184 | if ($source eq ".PHONY") { | | 6184 | if ($source eq ".PHONY") { |
6185 | foreach my $target (split(/\s+/, $targets)) { | | 6185 | foreach my $target (split(/\s+/, $targets)) { |
6186 | $allowed_targets->{$target} = true; | | 6186 | $allowed_targets->{$target} = true; |
6187 | } | | 6187 | } |
6188 | } | | 6188 | } |
6189 | } | | 6189 | } |
6190 | | | 6190 | |
6191 | foreach my $target (split(/\s+/, $targets)) { | | 6191 | foreach my $target (split(/\s+/, $targets)) { |
6192 | if ($target eq ".PHONY") { | | 6192 | if ($target eq ".PHONY") { |
6193 | foreach my $dep (split(qr"\s+", $dependencies)) { | | 6193 | foreach my $dep (split(qr"\s+", $dependencies)) { |
6194 | $allowed_targets->{$dep} = true; | | 6194 | $allowed_targets->{$dep} = true; |
6195 | } | | 6195 | } |
6196 | | | 6196 | |
6197 | } elsif ($target eq ".ORDER") { | | 6197 | } elsif ($target eq ".ORDER") { |
6198 | # TODO: Check for spelling mistakes. | | 6198 | # TODO: Check for spelling mistakes. |
6199 | | | 6199 | |
6200 | } elsif (!exists($allowed_targets->{$target})) { | | 6200 | } elsif (!exists($allowed_targets->{$target})) { |
6201 | $line->log_warning("Unusual target \"${target}\"."); | | 6201 | $line->log_warning("Unusual target \"${target}\"."); |
6202 | $line->explain_warning( | | 6202 | $line->explain_warning( |
6203 | "If you really want to define your own targets, you can \"declare\"", | | 6203 | "If you really want to define your own targets, you can \"declare\"", |
6204 | "them by inserting a \".PHONY: my-target\" line before this line. This", | | 6204 | "them by inserting a \".PHONY: my-target\" line before this line. This", |
6205 | "will tell make(1) to not interpret this target's name as a filename."); | | 6205 | "will tell make(1) to not interpret this target's name as a filename."); |
6206 | } | | 6206 | } |
6207 | } | | 6207 | } |
6208 | | | 6208 | |
6209 | } elsif ($text =~ m"^\.\s*(\S*)") { | | 6209 | } elsif ($text =~ m"^\.\s*(\S*)") { |
6210 | my ($directive) = ($1); | | 6210 | my ($directive) = ($1); |
6211 | | | 6211 | |
6212 | $line->log_error("Unknown directive \".${directive}\"."); | | 6212 | $line->log_error("Unknown directive \".${directive}\"."); |
6213 | | | 6213 | |
6214 | } elsif ($text =~ m"^ ") { | | 6214 | } elsif ($text =~ m"^ ") { |
6215 | $line->log_warning("Makefile lines should not start with space characters."); | | 6215 | $line->log_warning("Makefile lines should not start with space characters."); |
6216 | $line->explain_warning( | | 6216 | $line->explain_warning( |
6217 | "If you want this line to contain a shell program, use a tab", | | 6217 | "If you want this line to contain a shell program, use a tab", |
6218 | "character for indentation. Otherwise please remove the leading", | | 6218 | "character for indentation. Otherwise please remove the leading", |
6219 | "white-space."); | | 6219 | "white-space."); |
6220 | | | 6220 | |
6221 | } else { | | 6221 | } else { |
6222 | $line->log_error("[Internal] Unknown line format: $text"); | | 6222 | $line->log_error("[Internal] Unknown line format: $text"); |
6223 | } | | 6223 | } |
6224 | } | | 6224 | } |
6225 | if (@{$lines} > 0) { | | 6225 | if (@{$lines} > 0) { |
6226 | $substcontext->check_end($lines->[-1]); | | 6226 | $substcontext->check_end($lines->[-1]); |
6227 | } | | 6227 | } |
6228 | | | 6228 | |
6229 | checklines_trailing_empty_lines($lines); | | 6229 | checklines_trailing_empty_lines($lines); |
6230 | | | 6230 | |
6231 | if ($#{$mkctx_indentations} != 0) { | | 6231 | if ($#{$mkctx_indentations} != 0) { |
6232 | $lines->[-1]->log_error("Directive indentation is not 0, but ".$mkctx_indentations->[-1]." at EOF."); | | 6232 | $lines->[-1]->log_error("Directive indentation is not 0, but ".$mkctx_indentations->[-1]." at EOF."); |
6233 | } | | 6233 | } |
6234 | | | 6234 | |
6235 | # Clean up global variables. | | 6235 | # Clean up global variables. |
6236 | $mkctx_for_variables = undef; | | 6236 | $mkctx_for_variables = undef; |
6237 | $mkctx_indentations = undef; | | 6237 | $mkctx_indentations = undef; |
6238 | $mkctx_target = undef; | | 6238 | $mkctx_target = undef; |
6239 | $mkctx_vardef = undef; | | 6239 | $mkctx_vardef = undef; |
6240 | $mkctx_build_defs = undef; | | 6240 | $mkctx_build_defs = undef; |
6241 | $mkctx_plist_vars = undef; | | 6241 | $mkctx_plist_vars = undef; |
6242 | $mkctx_tools = undef; | | 6242 | $mkctx_tools = undef; |
6243 | $mkctx_varuse = undef; | | 6243 | $mkctx_varuse = undef; |
6244 | } | | 6244 | } |
6245 | | | 6245 | |
6246 | sub checklines_buildlink3_inclusion($) { | | 6246 | sub checklines_buildlink3_inclusion($) { |
6247 | my ($lines) = @_; | | 6247 | my ($lines) = @_; |
6248 | my ($included_files); | | 6248 | my ($included_files); |
6249 | | | 6249 | |
6250 | assert(@{$lines} != 0, "The lines array must be non-empty."); | | 6250 | assert(@{$lines} != 0, "The lines array must be non-empty."); |
6251 | $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_buildlink3_inclusion()"); | | 6251 | $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_buildlink3_inclusion()"); |
6252 | | | 6252 | |
6253 | if (!defined($pkgctx_bl3)) { | | 6253 | if (!defined($pkgctx_bl3)) { |
6254 | return; | | 6254 | return; |
6255 | } | | 6255 | } |
6256 | | | 6256 | |
6257 | # Collect all the included buildlink3.mk files from the file. | | 6257 | # Collect all the included buildlink3.mk files from the file. |
6258 | $included_files = {}; | | 6258 | $included_files = {}; |
6259 | foreach my $line (@{$lines}) { | | 6259 | foreach my $line (@{$lines}) { |
6260 | if ($line->text =~ regex_mk_include) { | | 6260 | if ($line->text =~ regex_mk_include) { |
6261 | my (undef, $file, $comment) = ($1, $2, $3); | | 6261 | my (undef, $file, $comment) = ($1, $2, $3); |
6262 | | | 6262 | |
6263 | if ($file =~ m"^\.\./\.\./(.*)/buildlink3\.mk") { | | 6263 | if ($file =~ m"^\.\./\.\./(.*)/buildlink3\.mk") { |
6264 | my ($bl3) = ($1); | | 6264 | my ($bl3) = ($1); |
6265 | | | 6265 | |
6266 | $included_files->{$bl3} = $line; | | 6266 | $included_files->{$bl3} = $line; |
6267 | if (!exists($pkgctx_bl3->{$bl3})) { | | 6267 | if (!exists($pkgctx_bl3->{$bl3})) { |
6268 | $line->log_warning("${bl3}/buildlink3.mk is included by this file but not by the package."); | | 6268 | $line->log_warning("${bl3}/buildlink3.mk is included by this file but not by the package."); |
6269 | } | | 6269 | } |
6270 | } | | 6270 | } |
6271 | } | | 6271 | } |
6272 | } | | 6272 | } |
6273 | | | 6273 | |
6274 | # Print debugging messages for all buildlink3.mk files that are | | 6274 | # Print debugging messages for all buildlink3.mk files that are |
6275 | # included by the package but not by this buildlink3.mk file. | | 6275 | # included by the package but not by this buildlink3.mk file. |
6276 | foreach my $package_bl3 (sort(keys(%{$pkgctx_bl3}))) { | | 6276 | foreach my $package_bl3 (sort(keys(%{$pkgctx_bl3}))) { |
6277 | if (!exists($included_files->{$package_bl3})) { | | 6277 | if (!exists($included_files->{$package_bl3})) { |
6278 | $opt_debug_misc and $pkgctx_bl3->{$package_bl3}->log_debug("${package_bl3}/buildlink3.mk is included by the package but not by the buildlink3.mk file."); | | 6278 | $opt_debug_misc and $pkgctx_bl3->{$package_bl3}->log_debug("${package_bl3}/buildlink3.mk is included by the package but not by the buildlink3.mk file."); |
6279 | } | | 6279 | } |
6280 | } | | 6280 | } |
6281 | } | | 6281 | } |
6282 | | | 6282 | |
6283 | # | | 6283 | # |
6284 | # Procedures to check a single file. | | 6284 | # Procedures to check a single file. |
6285 | # | | 6285 | # |
6286 | | | 6286 | |
6287 | sub checkfile_ALTERNATIVES($) { | | 6287 | sub checkfile_ALTERNATIVES($) { |
6288 | my ($fname) = @_; | | 6288 | my ($fname) = @_; |
6289 | my ($lines); | | 6289 | my ($lines); |
6290 | | | 6290 | |
6291 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_ALTERNATIVES()"); | | 6291 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_ALTERNATIVES()"); |
6292 | | | 6292 | |
6293 | checkperms($fname); | | 6293 | checkperms($fname); |
6294 | if (!($lines = load_file($fname))) { | | 6294 | if (!($lines = load_file($fname))) { |
6295 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6295 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6296 | return; | | 6296 | return; |
6297 | } | | 6297 | } |
6298 | } | | 6298 | } |
6299 | | | 6299 | |
6300 | sub checklines_buildlink3_mk_2009($$$); | | 6300 | sub checklines_buildlink3_mk_2009($$$); |
6301 | sub checklines_buildlink3_mk_pre2009($$); | | 6301 | sub checklines_buildlink3_mk_pre2009($$); |
6302 | sub checkfile_buildlink3_mk($) { | | 6302 | sub checkfile_buildlink3_mk($) { |
6303 | my ($fname) = @_; | | 6303 | my ($fname) = @_; |
6304 | my ($lines, $lineno, $m); | | 6304 | my ($lines, $lineno, $m); |
6305 | | | 6305 | |
6306 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_buildlink3_mk()"); | | 6306 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_buildlink3_mk()"); |
6307 | | | 6307 | |
6308 | checkperms($fname); | | 6308 | checkperms($fname); |
6309 | if (!($lines = load_lines($fname, true))) { | | 6309 | if (!($lines = load_lines($fname, true))) { |
6310 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6310 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6311 | return; | | 6311 | return; |
6312 | } | | 6312 | } |
6313 | if (@{$lines} == 0) { | | 6313 | if (@{$lines} == 0) { |
6314 | log_error($fname, NO_LINES, "Must not be empty."); | | 6314 | log_error($fname, NO_LINES, "Must not be empty."); |
6315 | return; | | 6315 | return; |
6316 | } | | 6316 | } |
6317 | | | 6317 | |
6318 | parselines_mk($lines); | | 6318 | parselines_mk($lines); |
6319 | checklines_mk($lines); | | 6319 | checklines_mk($lines); |
6320 | | | 6320 | |
6321 | $lineno = 0; | | 6321 | $lineno = 0; |
6322 | | | 6322 | |
6323 | # Header comments | | 6323 | # Header comments |
6324 | while ($lineno <= $#{$lines} && (my $text = $lines->[$lineno]->text) =~ m"^#") { | | 6324 | while ($lineno <= $#{$lines} && (my $text = $lines->[$lineno]->text) =~ m"^#") { |
6325 | if ($text =~ m"^# XXX") { | | 6325 | if ($text =~ m"^# XXX") { |
6326 | $lines->[$lineno]->log_note("Please read this comment and remove it if appropriate."); | | 6326 | $lines->[$lineno]->log_note("Please read this comment and remove it if appropriate."); |
6327 | } | | 6327 | } |
6328 | $lineno++; | | 6328 | $lineno++; |
6329 | } | | 6329 | } |
6330 | expect_empty_line($lines, \$lineno); | | 6330 | expect_empty_line($lines, \$lineno); |
6331 | | | 6331 | |
6332 | # This line does not belong here, but appears often. | | 6332 | # This line does not belong here, but appears often. |
6333 | if (expect($lines, \$lineno, qr"^BUILDLINK_DEPMETHOD\.(\S+)\?=.*$")) { | | 6333 | if (expect($lines, \$lineno, qr"^BUILDLINK_DEPMETHOD\.(\S+)\?=.*$")) { |
6334 | $lines->[$lineno - 1]->log_warning("This line belongs inside the .ifdef block."); | | 6334 | $lines->[$lineno - 1]->log_warning("This line belongs inside the .ifdef block."); |
6335 | while ($lines->[$lineno]->text eq "") { | | 6335 | while ($lines->[$lineno]->text eq "") { |
6336 | $lineno++; | | 6336 | $lineno++; |
6337 | } | | 6337 | } |
6338 | } | | 6338 | } |
6339 | | | 6339 | |
6340 | if (($m = expect($lines, \$lineno, qr"^BUILDLINK_TREE\+=\s*(\S+)$"))) { | | 6340 | if (($m = expect($lines, \$lineno, qr"^BUILDLINK_TREE\+=\s*(\S+)$"))) { |
6341 | checklines_buildlink3_mk_2009($lines, $lineno, $m->text(1)); | | 6341 | checklines_buildlink3_mk_2009($lines, $lineno, $m->text(1)); |
6342 | } else { | | 6342 | } else { |
6343 | checklines_buildlink3_mk_pre2009($lines, $lineno); | | 6343 | checklines_buildlink3_mk_pre2009($lines, $lineno); |
6344 | } | | 6344 | } |
6345 | } | | 6345 | } |
6346 | | | 6346 | |
6347 | sub checklines_buildlink3_mk_pre2009($$) { | | 6347 | sub checklines_buildlink3_mk_pre2009($$) { |
6348 | my ($lines, $lineno) = @_; | | 6348 | my ($lines, $lineno) = @_; |
6349 | my ($m); | | 6349 | my ($m); |
6350 | my ($bl_PKGBASE_line, $bl_PKGBASE); | | 6350 | my ($bl_PKGBASE_line, $bl_PKGBASE); |
6351 | my ($bl_pkgbase_line, $bl_pkgbase); | | 6351 | my ($bl_pkgbase_line, $bl_pkgbase); |
6352 | my ($abi_line, $abi_pkg, $abi_version); | | 6352 | my ($abi_line, $abi_pkg, $abi_version); |
6353 | my ($api_line, $api_pkg, $api_version); | | 6353 | my ($api_line, $api_pkg, $api_version); |
6354 | | | 6354 | |
6355 | # First paragraph: Reference counters. | | 6355 | # First paragraph: Reference counters. |
6356 | if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH\}\+$")) { | | 6356 | if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH\}\+$")) { |
6357 | # When none of the formats has been found, prefer the 2009 format. | | 6357 | # When none of the formats has been found, prefer the 2009 format. |
6358 | lines_log_warning($lines, $lineno, "Expected BUILDLINK_TREE line."); | | 6358 | lines_log_warning($lines, $lineno, "Expected BUILDLINK_TREE line."); |
6359 | return; | | 6359 | return; |
6360 | } | | 6360 | } |
6361 | if (($m = expect($lines, \$lineno, qr"^(.*)_BUILDLINK3_MK:=\t*\$\{\1_BUILDLINK3_MK\}\+$"))) { | | 6361 | if (($m = expect($lines, \$lineno, qr"^(.*)_BUILDLINK3_MK:=\t*\$\{\1_BUILDLINK3_MK\}\+$"))) { |
6362 | $bl_PKGBASE_line = $lines->[$lineno - 1]; | | 6362 | $bl_PKGBASE_line = $lines->[$lineno - 1]; |
6363 | $bl_PKGBASE = $m->text(1); | | 6363 | $bl_PKGBASE = $m->text(1); |
6364 | $opt_debug_misc and $bl_PKGBASE_line->log_debug("bl_PKGBASE=${bl_PKGBASE}"); | | 6364 | $opt_debug_misc and $bl_PKGBASE_line->log_debug("bl_PKGBASE=${bl_PKGBASE}"); |
6365 | } else { | | 6365 | } else { |
6366 | lines_log_warning($lines, $lineno, "Expected {PKGNAME}_BUILDLINK3_MK:= \${{PKGNAME}_BUILDLINK3_MK}+."); | | 6366 | lines_log_warning($lines, $lineno, "Expected {PKGNAME}_BUILDLINK3_MK:= \${{PKGNAME}_BUILDLINK3_MK}+."); |
6367 | return; | | 6367 | return; |
6368 | } | | 6368 | } |
6369 | expect_empty_line($lines, \$lineno); | | 6369 | expect_empty_line($lines, \$lineno); |
6370 | | | 6370 | |
6371 | # Second paragraph: Adding the dependency. | | 6371 | # Second paragraph: Adding the dependency. |
6372 | if (!expect($lines, \$lineno, qr"^\.if !empty\(BUILDLINK_DEPTH:M\+\)$")) { | | 6372 | if (!expect($lines, \$lineno, qr"^\.if !empty\(BUILDLINK_DEPTH:M\+\)$")) { |
6373 | if (!expect_text($lines, \$lineno, ".if \${BUILDLINK_DEPTH} == \"+\"")) { | | 6373 | if (!expect_text($lines, \$lineno, ".if \${BUILDLINK_DEPTH} == \"+\"")) { |
6374 | return; | | 6374 | return; |
6375 | } | | 6375 | } |
6376 | } | | 6376 | } |
6377 | if (($m = expect($lines, \$lineno, qr"^BUILDLINK_DEPENDS\+=\t+(\S+)$"))) { | | 6377 | if (($m = expect($lines, \$lineno, qr"^BUILDLINK_DEPENDS\+=\t+(\S+)$"))) { |
6378 | $bl_pkgbase_line = $lines->[$lineno - 1]; | | 6378 | $bl_pkgbase_line = $lines->[$lineno - 1]; |
6379 | $bl_pkgbase = $m->text(1); | | 6379 | $bl_pkgbase = $m->text(1); |
6380 | $opt_debug_misc and $bl_pkgbase_line->log_debug("bl_pkgbase=${bl_pkgbase}"); | | 6380 | $opt_debug_misc and $bl_pkgbase_line->log_debug("bl_pkgbase=${bl_pkgbase}"); |
6381 | } else { | | 6381 | } else { |
6382 | lines_log_warning($lines, $lineno, "BUILDLINK_DEPENDS line expected."); | | 6382 | lines_log_warning($lines, $lineno, "BUILDLINK_DEPENDS line expected."); |
6383 | return; | | 6383 | return; |
6384 | } | | 6384 | } |
6385 | | | 6385 | |
6386 | my $norm_bl_pkgbase = $bl_pkgbase; | | 6386 | my $norm_bl_pkgbase = $bl_pkgbase; |
6387 | $norm_bl_pkgbase =~ s/-/_/g; | | 6387 | $norm_bl_pkgbase =~ s/-/_/g; |
6388 | $norm_bl_pkgbase = uc($norm_bl_pkgbase); | | 6388 | $norm_bl_pkgbase = uc($norm_bl_pkgbase); |
6389 | if ($norm_bl_pkgbase ne $bl_PKGBASE) { | | 6389 | if ($norm_bl_pkgbase ne $bl_PKGBASE) { |
6390 | $bl_PKGBASE_line->log_error("Package name mismatch between ${bl_PKGBASE} ..."); | | 6390 | $bl_PKGBASE_line->log_error("Package name mismatch between ${bl_PKGBASE} ..."); |
6391 | $bl_pkgbase_line->log_error("... and ${bl_pkgbase}."); | | 6391 | $bl_pkgbase_line->log_error("... and ${bl_pkgbase}."); |
6392 | } | | 6392 | } |
6393 | if (defined($effective_pkgbase) && $effective_pkgbase ne $bl_pkgbase) { | | 6393 | if (defined($effective_pkgbase) && $effective_pkgbase ne $bl_pkgbase) { |
6394 | $bl_pkgbase_line->log_error("Package name mismatch between ${bl_pkgbase} ..."); | | 6394 | $bl_pkgbase_line->log_error("Package name mismatch between ${bl_pkgbase} ..."); |
6395 | $effective_pkgname_line->log_error("... and ${effective_pkgbase}."); | | 6395 | $effective_pkgname_line->log_error("... and ${effective_pkgbase}."); |
6396 | } | | 6396 | } |
6397 | | | 6397 | |
6398 | if (!expect_text($lines, \$lineno, ".endif")) { | | 6398 | if (!expect_text($lines, \$lineno, ".endif")) { |
6399 | return; | | 6399 | return; |
6400 | } | | 6400 | } |
6401 | expect_empty_line($lines, \$lineno); | | 6401 | expect_empty_line($lines, \$lineno); |
6402 | | | 6402 | |
6403 | # Third paragraph: Duplicate elimination. | | 6403 | # Third paragraph: Duplicate elimination. |
6404 | if (expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES:=\t+\$\{BUILDLINK_PACKAGES:N\Q${bl_pkgbase}\E\}\s+\Q${bl_pkgbase}\E$")) { | | 6404 | if (expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES:=\t+\$\{BUILDLINK_PACKAGES:N\Q${bl_pkgbase}\E\}\s+\Q${bl_pkgbase}\E$")) { |
6405 | # The compressed form of duplicate elimination. | | 6405 | # The compressed form of duplicate elimination. |
6406 | | | 6406 | |
6407 | } else { | | 6407 | } else { |
6408 | if (!expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES:=\t+\$\{BUILDLINK_PACKAGES:N\Q${bl_pkgbase}\E\}$")) { | | 6408 | if (!expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES:=\t+\$\{BUILDLINK_PACKAGES:N\Q${bl_pkgbase}\E\}$")) { |
6409 | lines_log_warning($lines, $lineno, "Expected BUILDLINK_PACKAGES:= \${BUILDLINK_PACKAGES:N${bl_pkgbase}} line."); | | 6409 | lines_log_warning($lines, $lineno, "Expected BUILDLINK_PACKAGES:= \${BUILDLINK_PACKAGES:N${bl_pkgbase}} line."); |
6410 | return; | | 6410 | return; |
6411 | } | | 6411 | } |
6412 | if (!expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES\+=\t+\Q${bl_pkgbase}\E$")) { | | 6412 | if (!expect($lines, \$lineno, qr"^BUILDLINK_PACKAGES\+=\t+\Q${bl_pkgbase}\E$")) { |
6413 | lines_log_warning($lines, $lineno, "Expected BUILDLINK_PACKAGES+= ${bl_pkgbase} line."); | | 6413 | lines_log_warning($lines, $lineno, "Expected BUILDLINK_PACKAGES+= ${bl_pkgbase} line."); |
6414 | return; | | 6414 | return; |
6415 | } | | 6415 | } |
6416 | } | | 6416 | } |
6417 | expect_text($lines, \$lineno, "BUILDLINK_ORDER:=\t\${BUILDLINK_ORDER} \${BUILDLINK_DEPTH}${bl_pkgbase}"); | | 6417 | expect_text($lines, \$lineno, "BUILDLINK_ORDER:=\t\${BUILDLINK_ORDER} \${BUILDLINK_DEPTH}${bl_pkgbase}"); |
6418 | expect_empty_line($lines, \$lineno); | | 6418 | expect_empty_line($lines, \$lineno); |
6419 | | | 6419 | |
6420 | # Fourth paragraph: Package information. | | 6420 | # Fourth paragraph: Package information. |
6421 | if (!expect($lines, \$lineno, qr"^\.if !empty\(\Q${bl_PKGBASE}\E_BUILDLINK3_MK:M\+\)$")) { | | 6421 | if (!expect($lines, \$lineno, qr"^\.if !empty\(\Q${bl_PKGBASE}\E_BUILDLINK3_MK:M\+\)$")) { |
6422 | if (!expect_text($lines, \$lineno, ".if \${${bl_PKGBASE}_BUILDLINK3_MK} == \"+\"")) { | | 6422 | if (!expect_text($lines, \$lineno, ".if \${${bl_PKGBASE}_BUILDLINK3_MK} == \"+\"")) { |
6423 | return; | | 6423 | return; |
6424 | } | | 6424 | } |
6425 | } | | 6425 | } |
6426 | while (!expect($lines, \$lineno, qr"^\.endif.*$")) { | | 6426 | while (!expect($lines, \$lineno, qr"^\.endif.*$")) { |
6427 | | | 6427 | |
6428 | if ($lineno > $#{$lines}) { | | 6428 | if ($lineno > $#{$lines}) { |
6429 | lines_log_warning($lines, $lineno, "Expected .endif"); | | 6429 | lines_log_warning($lines, $lineno, "Expected .endif"); |
6430 | return; | | 6430 | return; |
6431 | } | | 6431 | } |
6432 | | | 6432 | |
6433 | my $line = $lines->[$lineno]; | | 6433 | my $line = $lines->[$lineno]; |
6434 | | | 6434 | |
6435 | if (($m = expect($lines, \$lineno, regex_varassign))) { | | 6435 | if (($m = expect($lines, \$lineno, regex_varassign))) { |
6436 | my ($varname, $value) = ($m->text(1), $m->text(3)); | | 6436 | my ($varname, $value) = ($m->text(1), $m->text(3)); |
6437 | my $do_check = false; | | 6437 | my $do_check = false; |
6438 | | | 6438 | |
6439 | if ($varname eq "BUILDLINK_ABI_DEPENDS.${bl_pkgbase}") { | | 6439 | if ($varname eq "BUILDLINK_ABI_DEPENDS.${bl_pkgbase}") { |
6440 | $abi_line = $line; | | 6440 | $abi_line = $line; |
6441 | if ($value =~ regex_dependency_gt) { | | 6441 | if ($value =~ regex_dependency_gt) { |
6442 | ($abi_pkg, $abi_version) = ($1, $2); | | 6442 | ($abi_pkg, $abi_version) = ($1, $2); |
6443 | } elsif ($value =~ regex_dependency_wildcard) { | | 6443 | } elsif ($value =~ regex_dependency_wildcard) { |
6444 | ($abi_pkg) = ($1); | | 6444 | ($abi_pkg) = ($1); |
6445 | } else { | | 6445 | } else { |
6446 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); | | 6446 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); |
6447 | } | | 6447 | } |
6448 | $do_check = true; | | 6448 | $do_check = true; |
6449 | } | | 6449 | } |
6450 | if ($varname eq "BUILDLINK_API_DEPENDS.${bl_pkgbase}") { | | 6450 | if ($varname eq "BUILDLINK_API_DEPENDS.${bl_pkgbase}") { |
6451 | $api_line = $line; | | 6451 | $api_line = $line; |
6452 | if ($value =~ regex_dependency_gt) { | | 6452 | if ($value =~ regex_dependency_gt) { |
6453 | ($api_pkg, $api_version) = ($1, $2); | | 6453 | ($api_pkg, $api_version) = ($1, $2); |
6454 | } elsif ($value =~ regex_dependency_wildcard) { | | 6454 | } elsif ($value =~ regex_dependency_wildcard) { |
6455 | ($api_pkg) = ($1); | | 6455 | ($api_pkg) = ($1); |
6456 | } else { | | 6456 | } else { |
6457 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); | | 6457 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); |
6458 | } | | 6458 | } |
6459 | $do_check = true; | | 6459 | $do_check = true; |
6460 | } | | 6460 | } |
6461 | if ($do_check && defined($abi_pkg) && defined($api_pkg)) { | | 6461 | if ($do_check && defined($abi_pkg) && defined($api_pkg)) { |
6462 | if ($abi_pkg ne $api_pkg) { | | 6462 | if ($abi_pkg ne $api_pkg) { |
6463 | $abi_line->log_warning("Package name mismatch between ${abi_pkg} ..."); | | 6463 | $abi_line->log_warning("Package name mismatch between ${abi_pkg} ..."); |
6464 | $api_line->log_warning("... and ${api_pkg}."); | | 6464 | $api_line->log_warning("... and ${api_pkg}."); |
6465 | } | | 6465 | } |
6466 | } | | 6466 | } |
6467 | if ($do_check && defined($abi_version) && defined($api_version)) { | | 6467 | if ($do_check && defined($abi_version) && defined($api_version)) { |
6468 | if (!dewey_cmp($abi_version, ">=", $api_version)) { | | 6468 | if (!dewey_cmp($abi_version, ">=", $api_version)) { |
6469 | $abi_line->log_warning("ABI version (${abi_version}) should be at least ..."); | | 6469 | $abi_line->log_warning("ABI version (${abi_version}) should be at least ..."); |
6470 | $api_line->log_warning("... API version (${api_version})."); | | 6470 | $api_line->log_warning("... API version (${api_version})."); |
6471 | } | | 6471 | } |
6472 | } | | 6472 | } |
6473 | | | 6473 | |
6474 | if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") { | | 6474 | if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") { |
6475 | my ($varparam) = ($1); | | 6475 | my ($varparam) = ($1); |
6476 | | | 6476 | |
6477 | if ($varparam ne $bl_pkgbase) { | | 6477 | if ($varparam ne $bl_pkgbase) { |
6478 | $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file."); | | 6478 | $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file."); |
6479 | } | | 6479 | } |
6480 | } | | 6480 | } |
6481 | | | 6481 | |
6482 | # TODO: More checks. | | 6482 | # TODO: More checks. |
6483 | | | 6483 | |
6484 | } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) { | | 6484 | } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) { |
6485 | # Comments and empty lines are fine here. | | 6485 | # Comments and empty lines are fine here. |
6486 | | | 6486 | |
6487 | } else { | | 6487 | } else { |
6488 | $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in fourth paragraph."); | | 6488 | $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in fourth paragraph."); |
6489 | $lineno++; | | 6489 | $lineno++; |
6490 | } | | 6490 | } |
6491 | } | | 6491 | } |
6492 | if (!defined($api_line)) { | | 6492 | if (!defined($api_line)) { |
6493 | $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing."); | | 6493 | $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing."); |
6494 | } | | 6494 | } |
6495 | expect_empty_line($lines, \$lineno); | | 6495 | expect_empty_line($lines, \$lineno); |
6496 | | | 6496 | |
6497 | # Before the fifth paragraph, it may be necessary to resolve the build | | 6497 | # Before the fifth paragraph, it may be necessary to resolve the build |
6498 | # options of other packages. | | 6498 | # options of other packages. |
6499 | if (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")) { | | 6499 | if (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")) { |
6500 | do { | | 6500 | do { |
6501 | expect_text($lines, \$lineno, ".include \"../../mk/pkg-build-options.mk\""); | | 6501 | expect_text($lines, \$lineno, ".include \"../../mk/pkg-build-options.mk\""); |
6502 | } while (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")); | | 6502 | } while (expect($lines, \$lineno, qr"^pkgbase\s*:=\s*(\S+)$")); |
6503 | expect_empty_line($lines, \$lineno); | | 6503 | expect_empty_line($lines, \$lineno); |
6504 | } | | 6504 | } |
6505 | | | 6505 | |
6506 | # Fifth paragraph (optional): Dependencies. | | 6506 | # Fifth paragraph (optional): Dependencies. |
6507 | my $have_dependencies = false; | | 6507 | my $have_dependencies = false; |
6508 | my $need_empty_line = false; | | 6508 | my $need_empty_line = false; |
6509 | while (true) { | | 6509 | while (true) { |
6510 | if (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$") | | 6510 | if (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$") |
6511 | || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$") | | 6511 | || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$") |
6512 | || expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$") | | 6512 | || expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$") |
6513 | || expect($lines, \$lineno, qr"^\.endif$")) { | | 6513 | || expect($lines, \$lineno, qr"^\.endif$")) { |
6514 | $have_dependencies = true; | | 6514 | $have_dependencies = true; |
6515 | $need_empty_line = true; | | 6515 | $need_empty_line = true; |
6516 | } elsif ($have_dependencies && expect($lines, \$lineno, qr"^$")) { | | 6516 | } elsif ($have_dependencies && expect($lines, \$lineno, qr"^$")) { |
6517 | $need_empty_line = false; | | 6517 | $need_empty_line = false; |
6518 | } else { | | 6518 | } else { |
6519 | last; | | 6519 | last; |
6520 | } | | 6520 | } |
6521 | } | | 6521 | } |
6522 | if ($need_empty_line) { | | 6522 | if ($need_empty_line) { |
6523 | expect_empty_line($lines, \$lineno); | | 6523 | expect_empty_line($lines, \$lineno); |
6524 | } | | 6524 | } |
6525 | | | 6525 | |
6526 | # Sixth paragraph: Reference counter. | | 6526 | # Sixth paragraph: Reference counter. |
6527 | if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH:S/\+\$//\}$")) { | | 6527 | if (!expect($lines, \$lineno, qr"^BUILDLINK_DEPTH:=\t+\$\{BUILDLINK_DEPTH:S/\+\$//\}$")) { |
6528 | lines_log_warning($lines, $lineno, "Expected BUILDLINK_DEPTH:= \${BUILDLINK_DEPTH:S/+\$//}."); | | 6528 | lines_log_warning($lines, $lineno, "Expected BUILDLINK_DEPTH:= \${BUILDLINK_DEPTH:S/+\$//}."); |
6529 | explain_warning($lines, $lineno, | | 6529 | explain_warning($lines, $lineno, |
6530 | "Everything besides the .include lines for the buildlink3.mk files of", | | 6530 | "Everything besides the .include lines for the buildlink3.mk files of", |
6531 | "dependencies should go between the .if !empty({PKGNAME}_BUILDLINK3_MK)", | | 6531 | "dependencies should go between the .if !empty({PKGNAME}_BUILDLINK3_MK)", |
6532 | "and the corresponding .endif."); | | 6532 | "and the corresponding .endif."); |
6533 | return; | | 6533 | return; |
6534 | } | | 6534 | } |
6535 | | | 6535 | |
6536 | if ($lineno <= $#{$lines}) { | | 6536 | if ($lineno <= $#{$lines}) { |
6537 | $lines->[$lineno]->log_warning("The file should end here."); | | 6537 | $lines->[$lineno]->log_warning("The file should end here."); |
6538 | } | | 6538 | } |
6539 | | | 6539 | |
6540 | checklines_buildlink3_inclusion($lines); | | 6540 | checklines_buildlink3_inclusion($lines); |
6541 | } | | 6541 | } |
6542 | | | 6542 | |
6543 | # This code is copy-pasted from checklines_buildlink3_mk_pre2009, which | | 6543 | # This code is copy-pasted from checklines_buildlink3_mk_pre2009, which |
6544 | # will disappear after branching 2010Q1. | | 6544 | # will disappear after branching 2010Q1. |
6545 | # | | 6545 | # |
6546 | # In 2009, the format of the buildlink3.mk files has been revised to | | 6546 | # In 2009, the format of the buildlink3.mk files has been revised to |
6547 | # improve the speed of pkgsrc. As a result, the file format has improved | | 6547 | # improve the speed of pkgsrc. As a result, the file format has improved |
6548 | # in legibility and size. | | 6548 | # in legibility and size. |
6549 | sub checklines_buildlink3_mk_2009($$$) { | | 6549 | sub checklines_buildlink3_mk_2009($$$) { |
6550 | my ($lines, $lineno, $pkgid) = @_; | | 6550 | my ($lines, $lineno, $pkgid) = @_; |
6551 | my ($m); | | 6551 | my ($m); |
6552 | my ($bl_PKGBASE_line, $bl_PKGBASE); | | 6552 | my ($bl_PKGBASE_line, $bl_PKGBASE); |
6553 | my ($bl_pkgbase_line, $bl_pkgbase); | | 6553 | my ($bl_pkgbase_line, $bl_pkgbase); |
6554 | my ($abi_line, $abi_pkg, $abi_version); | | 6554 | my ($abi_line, $abi_pkg, $abi_version); |
6555 | my ($api_line, $api_pkg, $api_version); | | 6555 | my ($api_line, $api_pkg, $api_version); |
6556 | | | 6556 | |
6557 | # First paragraph: Introduction of the package identifier | | 6557 | # First paragraph: Introduction of the package identifier |
6558 | $bl_pkgbase_line = $lines->[$lineno - 1]; | | 6558 | $bl_pkgbase_line = $lines->[$lineno - 1]; |
6559 | $bl_pkgbase = $pkgid; | | 6559 | $bl_pkgbase = $pkgid; |
6560 | $opt_debug_misc and $bl_pkgbase_line->log_debug("bl_pkgbase=${bl_pkgbase}"); | | 6560 | $opt_debug_misc and $bl_pkgbase_line->log_debug("bl_pkgbase=${bl_pkgbase}"); |
6561 | expect_empty_line($lines, \$lineno); | | 6561 | expect_empty_line($lines, \$lineno); |
6562 | | | 6562 | |
6563 | # Second paragraph: multiple inclusion protection and introduction | | 6563 | # Second paragraph: multiple inclusion protection and introduction |
6564 | # of the uppercase package identifier. | | 6564 | # of the uppercase package identifier. |
6565 | return unless ($m = expect_re($lines, \$lineno, qr"^\.if !defined\((\S+)_BUILDLINK3_MK\)$")); | | 6565 | return unless ($m = expect_re($lines, \$lineno, qr"^\.if !defined\((\S+)_BUILDLINK3_MK\)$")); |
6566 | $bl_PKGBASE_line = $lines->[$lineno - 1]; | | 6566 | $bl_PKGBASE_line = $lines->[$lineno - 1]; |
6567 | $bl_PKGBASE = $m->text(1); | | 6567 | $bl_PKGBASE = $m->text(1); |
6568 | $opt_debug_misc and $bl_PKGBASE_line->log_debug("bl_PKGBASE=${bl_PKGBASE}"); | | 6568 | $opt_debug_misc and $bl_PKGBASE_line->log_debug("bl_PKGBASE=${bl_PKGBASE}"); |
6569 | expect_re($lines, \$lineno, qr"^\Q$bl_PKGBASE\E_BUILDLINK3_MK:=$"); | | 6569 | expect_re($lines, \$lineno, qr"^\Q$bl_PKGBASE\E_BUILDLINK3_MK:=$"); |
6570 | expect_empty_line($lines, \$lineno); | | 6570 | expect_empty_line($lines, \$lineno); |
6571 | | | 6571 | |
6572 | my $norm_bl_pkgbase = $bl_pkgbase; | | 6572 | my $norm_bl_pkgbase = $bl_pkgbase; |
6573 | $norm_bl_pkgbase =~ s/-/_/g; | | 6573 | $norm_bl_pkgbase =~ s/-/_/g; |
6574 | $norm_bl_pkgbase = uc($norm_bl_pkgbase); | | 6574 | $norm_bl_pkgbase = uc($norm_bl_pkgbase); |
6575 | if ($norm_bl_pkgbase ne $bl_PKGBASE) { | | 6575 | if ($norm_bl_pkgbase ne $bl_PKGBASE) { |
6576 | $bl_PKGBASE_line->log_error("Package name mismatch between ${bl_PKGBASE} ..."); | | 6576 | $bl_PKGBASE_line->log_error("Package name mismatch between ${bl_PKGBASE} ..."); |
6577 | $bl_pkgbase_line->log_error("... and ${bl_pkgbase}."); | | 6577 | $bl_pkgbase_line->log_error("... and ${bl_pkgbase}."); |
6578 | } | | 6578 | } |
6579 | if (defined($effective_pkgbase) && $effective_pkgbase ne $bl_pkgbase) { | | 6579 | if (defined($effective_pkgbase) && $effective_pkgbase ne $bl_pkgbase) { |
6580 | $bl_pkgbase_line->log_error("Package name mismatch between ${bl_pkgbase} ..."); | | 6580 | $bl_pkgbase_line->log_error("Package name mismatch between ${bl_pkgbase} ..."); |
6581 | $effective_pkgname_line->log_error("... and ${effective_pkgbase}."); | | 6581 | $effective_pkgname_line->log_error("... and ${effective_pkgbase}."); |
6582 | } | | 6582 | } |
6583 | | | 6583 | |
6584 | # Third paragraph: Package information. | | 6584 | # Third paragraph: Package information. |
6585 | my $if_level = 1; # the first .if is from the second paragraph. | | 6585 | my $if_level = 1; # the first .if is from the second paragraph. |
6586 | while (true) { | | 6586 | while (true) { |
6587 | | | 6587 | |
6588 | if ($lineno > $#{$lines}) { | | 6588 | if ($lineno > $#{$lines}) { |
6589 | lines_log_warning($lines, $lineno, "Expected .endif"); | | 6589 | lines_log_warning($lines, $lineno, "Expected .endif"); |
6590 | return; | | 6590 | return; |
6591 | } | | 6591 | } |
6592 | | | 6592 | |
6593 | my $line = $lines->[$lineno]; | | 6593 | my $line = $lines->[$lineno]; |
6594 | | | 6594 | |
6595 | if (($m = expect($lines, \$lineno, regex_varassign))) { | | 6595 | if (($m = expect($lines, \$lineno, regex_varassign))) { |
6596 | my ($varname, $value) = ($m->text(1), $m->text(3)); | | 6596 | my ($varname, $value) = ($m->text(1), $m->text(3)); |
6597 | my $do_check = false; | | 6597 | my $do_check = false; |
6598 | | | 6598 | |
6599 | if ($varname eq "BUILDLINK_ABI_DEPENDS.${bl_pkgbase}") { | | 6599 | if ($varname eq "BUILDLINK_ABI_DEPENDS.${bl_pkgbase}") { |
6600 | $abi_line = $line; | | 6600 | $abi_line = $line; |
6601 | if ($value =~ regex_dependency_gt) { | | 6601 | if ($value =~ regex_dependency_gt) { |
6602 | ($abi_pkg, $abi_version) = ($1, $2); | | 6602 | ($abi_pkg, $abi_version) = ($1, $2); |
6603 | } elsif ($value =~ regex_dependency_wildcard) { | | 6603 | } elsif ($value =~ regex_dependency_wildcard) { |
6604 | ($abi_pkg) = ($1); | | 6604 | ($abi_pkg) = ($1); |
6605 | } else { | | 6605 | } else { |
6606 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); | | 6606 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); |
6607 | } | | 6607 | } |
6608 | $do_check = true; | | 6608 | $do_check = true; |
6609 | } | | 6609 | } |
6610 | if ($varname eq "BUILDLINK_API_DEPENDS.${bl_pkgbase}") { | | 6610 | if ($varname eq "BUILDLINK_API_DEPENDS.${bl_pkgbase}") { |
6611 | $api_line = $line; | | 6611 | $api_line = $line; |
6612 | if ($value =~ regex_dependency_gt) { | | 6612 | if ($value =~ regex_dependency_gt) { |
6613 | ($api_pkg, $api_version) = ($1, $2); | | 6613 | ($api_pkg, $api_version) = ($1, $2); |
6614 | } elsif ($value =~ regex_dependency_wildcard) { | | 6614 | } elsif ($value =~ regex_dependency_wildcard) { |
6615 | ($api_pkg) = ($1); | | 6615 | ($api_pkg) = ($1); |
6616 | } else { | | 6616 | } else { |
6617 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); | | 6617 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern \"${value}\"."); |
6618 | } | | 6618 | } |
6619 | $do_check = true; | | 6619 | $do_check = true; |
6620 | } | | 6620 | } |
6621 | if ($do_check && defined($abi_pkg) && defined($api_pkg)) { | | 6621 | if ($do_check && defined($abi_pkg) && defined($api_pkg)) { |
6622 | if ($abi_pkg ne $api_pkg) { | | 6622 | if ($abi_pkg ne $api_pkg) { |
6623 | $abi_line->log_warning("Package name mismatch between ${abi_pkg} ..."); | | 6623 | $abi_line->log_warning("Package name mismatch between ${abi_pkg} ..."); |
6624 | $api_line->log_warning("... and ${api_pkg}."); | | 6624 | $api_line->log_warning("... and ${api_pkg}."); |
6625 | } | | 6625 | } |
6626 | } | | 6626 | } |
6627 | if ($do_check && defined($abi_version) && defined($api_version)) { | | 6627 | if ($do_check && defined($abi_version) && defined($api_version)) { |
6628 | if (!dewey_cmp($abi_version, ">=", $api_version)) { | | 6628 | if (!dewey_cmp($abi_version, ">=", $api_version)) { |
6629 | $abi_line->log_warning("ABI version (${abi_version}) should be at least ..."); | | 6629 | $abi_line->log_warning("ABI version (${abi_version}) should be at least ..."); |
6630 | $api_line->log_warning("... API version (${api_version})."); | | 6630 | $api_line->log_warning("... API version (${api_version})."); |
6631 | } | | 6631 | } |
6632 | } | | 6632 | } |
6633 | | | 6633 | |
6634 | if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") { | | 6634 | if ($varname =~ m"^BUILDLINK_[\w_]+\.(.*)$") { |
6635 | my ($varparam) = ($1); | | 6635 | my ($varparam) = ($1); |
6636 | | | 6636 | |
6637 | if ($varparam ne $bl_pkgbase) { | | 6637 | if ($varparam ne $bl_pkgbase) { |
6638 | $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file."); | | 6638 | $line->log_warning("Only buildlink variables for ${bl_pkgbase}, not ${varparam} may be set in this file."); |
6639 | } | | 6639 | } |
6640 | } | | 6640 | } |
6641 | | | 6641 | |
6642 | if ($varname eq "pkgbase") { | | 6642 | if ($varname eq "pkgbase") { |
6643 | expect_re($lines, \$lineno, "^\.\s*include \"../../mk/pkg-build-options.mk\"$"); | | 6643 | expect_re($lines, \$lineno, qr"^\.\s*include \"../../mk/pkg-build-options.mk\"$"); |
6644 | } | | 6644 | } |
6645 | | | 6645 | |
6646 | # TODO: More checks. | | 6646 | # TODO: More checks. |
6647 | | | 6647 | |
6648 | } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) { | | 6648 | } elsif (expect($lines, \$lineno, qr"^(?:#.*)?$")) { |
6649 | # Comments and empty lines are fine here. | | 6649 | # Comments and empty lines are fine here. |
6650 | | | 6650 | |
6651 | } elsif (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$") | | 6651 | } elsif (expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./([^/]+/[^/]+)/buildlink3\.mk\"$") |
6652 | || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$")) { | | 6652 | || expect($lines, \$lineno, qr"^\.\s*include \"\.\./\.\./mk/(\S+)\.buildlink3\.mk\"$")) { |
6653 | # TODO: Maybe check dependency lines. | | 6653 | # TODO: Maybe check dependency lines. |
6654 | | | 6654 | |
6655 | } elsif (expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$")) { | | 6655 | } elsif (expect($lines, \$lineno, qr"^\.if !empty\(PKG_BUILD_OPTIONS\.\Q${bl_pkgbase}\E:M\S+\)$")) { |
6656 | $if_level++; | | 6656 | $if_level++; |
6657 | | | 6657 | |
6658 | } elsif (expect($lines, \$lineno, qr"^\.endif.*$")) { | | 6658 | } elsif (expect($lines, \$lineno, qr"^\.endif.*$")) { |
6659 | $if_level--; | | 6659 | $if_level--; |
6660 | last if $if_level == 0; | | 6660 | last if $if_level == 0; |
6661 | | | 6661 | |
6662 | } else { | | 6662 | } else { |
6663 | $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in third paragraph."); | | 6663 | $opt_debug_unchecked and lines_log_warning($lines, $lineno, "Unchecked line in third paragraph."); |
6664 | $lineno++; | | 6664 | $lineno++; |
6665 | } | | 6665 | } |
6666 | } | | 6666 | } |
6667 | if (!defined($api_line)) { | | 6667 | if (!defined($api_line)) { |
6668 | $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing."); | | 6668 | $lines->[$lineno - 1]->log_warning("Definition of BUILDLINK_API_DEPENDS is missing."); |
6669 | } | | 6669 | } |
6670 | expect_empty_line($lines, \$lineno); | | 6670 | expect_empty_line($lines, \$lineno); |
6671 | | | 6671 | |
6672 | # Fourth paragraph: Cleanup, corresponding to the first paragraph. | | 6672 | # Fourth paragraph: Cleanup, corresponding to the first paragraph. |
6673 | return unless expect_re($lines, \$lineno, qr"^BUILDLINK_TREE\+=\s*-\Q$bl_pkgbase\E$"); | | 6673 | return unless expect_re($lines, \$lineno, qr"^BUILDLINK_TREE\+=\s*-\Q$bl_pkgbase\E$"); |
6674 | | | 6674 | |
6675 | if ($lineno <= $#{$lines}) { | | 6675 | if ($lineno <= $#{$lines}) { |
6676 | $lines->[$lineno]->log_warning("The file should end here."); | | 6676 | $lines->[$lineno]->log_warning("The file should end here."); |
6677 | } | | 6677 | } |
6678 | | | 6678 | |
6679 | checklines_buildlink3_inclusion($lines); | | 6679 | checklines_buildlink3_inclusion($lines); |
6680 | } | | 6680 | } |
6681 | | | 6681 | |
6682 | sub checkfile_DESCR($) { | | 6682 | sub checkfile_DESCR($) { |
6683 | my ($fname) = @_; | | 6683 | my ($fname) = @_; |
6684 | my ($maxchars, $maxlines) = (80, 24); | | 6684 | my ($maxchars, $maxlines) = (80, 24); |
6685 | my ($lines); | | 6685 | my ($lines); |
6686 | | | 6686 | |
6687 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_DESCR()"); | | 6687 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_DESCR()"); |
6688 | | | 6688 | |
6689 | checkperms($fname); | | 6689 | checkperms($fname); |
6690 | if (!($lines = load_file($fname))) { | | 6690 | if (!($lines = load_file($fname))) { |
6691 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6691 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6692 | return; | | 6692 | return; |
6693 | } | | 6693 | } |
6694 | if (@{$lines} == 0) { | | 6694 | if (@{$lines} == 0) { |
6695 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); | | 6695 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); |
6696 | return; | | 6696 | return; |
6697 | } | | 6697 | } |
6698 | | | 6698 | |
6699 | foreach my $line (@{$lines}) { | | 6699 | foreach my $line (@{$lines}) { |
6700 | checkline_length($line, $maxchars); | | 6700 | checkline_length($line, $maxchars); |
6701 | checkline_trailing_whitespace($line); | | 6701 | checkline_trailing_whitespace($line); |
6702 | checkline_valid_characters($line, regex_validchars); | | 6702 | checkline_valid_characters($line, regex_validchars); |
6703 | checkline_spellcheck($line); | | 6703 | checkline_spellcheck($line); |
6704 | if ($line->text =~ m"\$\{") { | | 6704 | if ($line->text =~ m"\$\{") { |
6705 | $line->log_warning("Variables are not expanded in the DESCR file."); | | 6705 | $line->log_warning("Variables are not expanded in the DESCR file."); |
6706 | } | | 6706 | } |
6707 | } | | 6707 | } |
6708 | checklines_trailing_empty_lines($lines); | | 6708 | checklines_trailing_empty_lines($lines); |
6709 | | | 6709 | |
6710 | if (@{$lines} > $maxlines) { | | 6710 | if (@{$lines} > $maxlines) { |
6711 | my $line = $lines->[$maxlines]; | | 6711 | my $line = $lines->[$maxlines]; |
6712 | | | 6712 | |
6713 | $line->log_warning("File too long (should be no more than $maxlines lines)."); | | 6713 | $line->log_warning("File too long (should be no more than $maxlines lines)."); |
6714 | $line->explain_warning( | | 6714 | $line->explain_warning( |
6715 | "A common terminal size is 80x25 characters. The DESCR file should", | | 6715 | "A common terminal size is 80x25 characters. The DESCR file should", |
6716 | "fit on one screen. It is also intended to give a _brief_ summary", | | 6716 | "fit on one screen. It is also intended to give a _brief_ summary", |
6717 | "about the package's contents."); | | 6717 | "about the package's contents."); |
6718 | } | | 6718 | } |
6719 | autofix($lines); | | 6719 | autofix($lines); |
6720 | } | | 6720 | } |
6721 | | | 6721 | |
6722 | sub checkfile_distinfo($) { | | 6722 | sub checkfile_distinfo($) { |
6723 | my ($fname) = @_; | | 6723 | my ($fname) = @_; |
6724 | my ($lines, %in_distinfo, $current_fname, $state, $patches_dir); | | 6724 | my ($lines, %in_distinfo, $current_fname, $state, $patches_dir); |
6725 | my ($di_is_committed); | | 6725 | my ($di_is_committed); |
6726 | | | 6726 | |
6727 | use enum qw(:DIS_ start=0 SHA1=0 RMD160 Size); | | 6727 | use enum qw(:DIS_ start=0 SHA1=0 RMD160 Size); |
6728 | | | 6728 | |
6729 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_distinfo()"); | | 6729 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_distinfo()"); |
6730 | | | 6730 | |
6731 | $di_is_committed = is_committed($fname); | | 6731 | $di_is_committed = is_committed($fname); |
6732 | | | 6732 | |
6733 | checkperms($fname); | | 6733 | checkperms($fname); |
6734 | if (!($lines = load_file($fname))) { | | 6734 | if (!($lines = load_file($fname))) { |
6735 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6735 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6736 | return; | | 6736 | return; |
6737 | } | | 6737 | } |
6738 | | | 6738 | |
6739 | if (@{$lines} == 0) { | | 6739 | if (@{$lines} == 0) { |
6740 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); | | 6740 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); |
6741 | return; | | 6741 | return; |
6742 | } | | 6742 | } |
6743 | | | 6743 | |
6744 | checkline_rcsid($lines->[0], ""); | | 6744 | checkline_rcsid($lines->[0], ""); |
6745 | if (1 <= $#{$lines} && $lines->[1]->text ne "") { | | 6745 | if (1 <= $#{$lines} && $lines->[1]->text ne "") { |
6746 | $lines->[1]->log_note("Empty line expected."); | | 6746 | $lines->[1]->log_note("Empty line expected."); |
6747 | $lines->[1]->explain_note("This is merely for aesthetical purposes."); | | 6747 | $lines->[1]->explain_note("This is merely for aesthetical purposes."); |
6748 | } | | 6748 | } |
6749 | | | 6749 | |
6750 | $patches_dir = $patchdir; | | 6750 | $patches_dir = $patchdir; |
6751 | if (!defined($patches_dir) && -d "${current_dir}/patches") { | | 6751 | if (!defined($patches_dir) && -d "${current_dir}/patches") { |
6752 | $patches_dir = "patches"; | | 6752 | $patches_dir = "patches"; |
6753 | } else { | | 6753 | } else { |
6754 | # it stays undefined. | | 6754 | # it stays undefined. |
6755 | } | | 6755 | } |
6756 | | | 6756 | |
6757 | $current_fname = undef; | | 6757 | $current_fname = undef; |
6758 | $state = DIS_start; | | 6758 | $state = DIS_start; |
6759 | foreach my $line (@{$lines}[2..$#{$lines}]) { | | 6759 | foreach my $line (@{$lines}[2..$#{$lines}]) { |
6760 | if ($line->text !~ m"^(\w+) \(([^)]+)\) = (.*)(?: bytes)?$") { | | 6760 | if ($line->text !~ m"^(\w+) \(([^)]+)\) = (.*)(?: bytes)?$") { |
6761 | $line->log_error("Unknown line type."); | | 6761 | $line->log_error("Unknown line type."); |
6762 | next; | | 6762 | next; |
6763 | } | | 6763 | } |
6764 | my ($alg, $chksum_fname, $sum) = ($1, $2, $3); | | 6764 | my ($alg, $chksum_fname, $sum) = ($1, $2, $3); |
6765 | my $is_patch = (($chksum_fname =~ m"^patch-[A-Za-z0-9]+$") ? true : false); | | 6765 | my $is_patch = (($chksum_fname =~ m"^patch-[A-Za-z0-9]+$") ? true : false); |
6766 | | | 6766 | |
6767 | if ($chksum_fname !~ m"^\w") { | | 6767 | if ($chksum_fname !~ m"^\w") { |
6768 | $line->log_error("All file names should start with a letter."); | | 6768 | $line->log_error("All file names should start with a letter."); |
6769 | } | | 6769 | } |
6770 | | | 6770 | |
6771 | # Inter-package check for differing distfile checksums. | | 6771 | # Inter-package check for differing distfile checksums. |
6772 | if ($opt_check_global && !$is_patch) { | | 6772 | if ($opt_check_global && !$is_patch) { |
6773 | # Note: Perl-specific auto-population. | | 6773 | # Note: Perl-specific auto-population. |
6774 | if (exists($ipc_distinfo->{$alg}->{$chksum_fname})) { | | 6774 | if (exists($ipc_distinfo->{$alg}->{$chksum_fname})) { |
6775 | my $other = $ipc_distinfo->{$alg}->{$chksum_fname}; | | 6775 | my $other = $ipc_distinfo->{$alg}->{$chksum_fname}; |
6776 | | | 6776 | |
6777 | if ($other->[1] eq $sum) { | | 6777 | if ($other->[1] eq $sum) { |
6778 | # Fine. | | 6778 | # Fine. |
6779 | } else { | | 6779 | } else { |
6780 | $line->log_error("The ${alg} checksum for ${chksum_fname} differs ..."); | | 6780 | $line->log_error("The ${alg} checksum for ${chksum_fname} differs ..."); |
6781 | $other->[0]->log_error("... from this one."); | | 6781 | $other->[0]->log_error("... from this one."); |
6782 | } | | 6782 | } |
6783 | } else { | | 6783 | } else { |
6784 | $ipc_distinfo->{$alg}->{$chksum_fname} = [$line, $sum]; | | 6784 | $ipc_distinfo->{$alg}->{$chksum_fname} = [$line, $sum]; |
6785 | } | | 6785 | } |
6786 | } | | 6786 | } |
6787 | | | 6787 | |
6788 | if ($alg eq "MD5") { | | 6788 | if ($alg eq "MD5") { |
6789 | $line->log_error("MD5 checksums are obsolete."); | | 6789 | $line->log_error("MD5 checksums are obsolete."); |
6790 | $line->explain_error( | | 6790 | $line->explain_error( |
6791 | "Run \"".conf_make." makedistinfo\" to regenerate the distinfo file."); | | 6791 | "Run \"".conf_make." makedistinfo\" to regenerate the distinfo file."); |
6792 | next; | | 6792 | next; |
6793 | } | | 6793 | } |
6794 | | | 6794 | |
6795 | if ($state == DIS_SHA1) { | | 6795 | if ($state == DIS_SHA1) { |
6796 | if ($alg eq "SHA1") { | | 6796 | if ($alg eq "SHA1") { |
6797 | $state = ($is_patch ? DIS_start : DIS_RMD160); | | 6797 | $state = ($is_patch ? DIS_start : DIS_RMD160); |
6798 | $current_fname = $chksum_fname; | | 6798 | $current_fname = $chksum_fname; |
6799 | } else { | | 6799 | } else { |
6800 | $line->log_warning("Expected an SHA1 checksum."); | | 6800 | $line->log_warning("Expected an SHA1 checksum."); |
6801 | } | | 6801 | } |
6802 | | | 6802 | |
6803 | } elsif ($state == DIS_RMD160) { | | 6803 | } elsif ($state == DIS_RMD160) { |
6804 | $state = DIS_start; | | 6804 | $state = DIS_start; |
6805 | if ($alg eq "RMD160") { | | 6805 | if ($alg eq "RMD160") { |
6806 | if ($chksum_fname eq $current_fname) { | | 6806 | if ($chksum_fname eq $current_fname) { |
6807 | $state = DIS_Size; | | 6807 | $state = DIS_Size; |
6808 | } else { | | 6808 | } else { |
6809 | $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not for ${chksum_fname}."); | | 6809 | $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not for ${chksum_fname}."); |
6810 | } | | 6810 | } |
6811 | } else { | | 6811 | } else { |
6812 | if ($chksum_fname eq $current_fname) { | | 6812 | if ($chksum_fname eq $current_fname) { |
6813 | # This is an error because this really should be fixed. | | 6813 | # This is an error because this really should be fixed. |
6814 | $line->log_error("Expected an RMD160 checksum, not ${alg} for ${chksum_fname}."); | | 6814 | $line->log_error("Expected an RMD160 checksum, not ${alg} for ${chksum_fname}."); |
6815 | } else { | | 6815 | } else { |
6816 | $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); | | 6816 | $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); |
6817 | } | | 6817 | } |
6818 | } | | 6818 | } |
6819 | | | 6819 | |
6820 | } elsif ($state == DIS_Size) { | | 6820 | } elsif ($state == DIS_Size) { |
6821 | $state = DIS_start; | | 6821 | $state = DIS_start; |
6822 | if ($alg eq "Size") { | | 6822 | if ($alg eq "Size") { |
6823 | if ($chksum_fname ne $current_fname) { | | 6823 | if ($chksum_fname ne $current_fname) { |
6824 | $line->log_warning("Expected a Size checksum for ${current_fname}, not for ${chksum_fname}."); | | 6824 | $line->log_warning("Expected a Size checksum for ${current_fname}, not for ${chksum_fname}."); |
6825 | } | | 6825 | } |
6826 | } else { | | 6826 | } else { |
6827 | if ($chksum_fname eq $current_fname) { | | 6827 | if ($chksum_fname eq $current_fname) { |
6828 | $line->log_warning("Expected a Size checksum, not ${alg} for ${chksum_fname}."); | | 6828 | $line->log_warning("Expected a Size checksum, not ${alg} for ${chksum_fname}."); |
6829 | } else { | | 6829 | } else { |
6830 | $line->log_warning("Expected a Size checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); | | 6830 | $line->log_warning("Expected a Size checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); |
6831 | } | | 6831 | } |
6832 | } | | 6832 | } |
6833 | } | | 6833 | } |
6834 | | | 6834 | |
6835 | if ($is_patch && defined($patches_dir) && !(defined($distinfo_file) && $distinfo_file eq "./../../lang/php5/distinfo")) { | | 6835 | if ($is_patch && defined($patches_dir) && !(defined($distinfo_file) && $distinfo_file eq "./../../lang/php5/distinfo")) { |
6836 | my $fname = "${current_dir}/${patches_dir}/${chksum_fname}"; | | 6836 | my $fname = "${current_dir}/${patches_dir}/${chksum_fname}"; |
6837 | if ($di_is_committed && !is_committed($fname)) { | | 6837 | if ($di_is_committed && !is_committed($fname)) { |
6838 | $line->log_warning("${patches_dir}/${chksum_fname} is registered in distinfo but not added to CVS."); | | 6838 | $line->log_warning("${patches_dir}/${chksum_fname} is registered in distinfo but not added to CVS."); |
6839 | } | | 6839 | } |
6840 | | | 6840 | |
6841 | if (open(PATCH, "<", $fname)) { | | 6841 | if (open(PATCH, "<", $fname)) { |
6842 | my $data = ""; | | 6842 | my $data = ""; |
6843 | foreach my $patchline (<PATCH>) { | | 6843 | foreach my $patchline (<PATCH>) { |
6844 | $data .= $patchline unless $patchline =~ m"\$[N]etBSD"; | | 6844 | $data .= $patchline unless $patchline =~ m"\$[N]etBSD"; |
6845 | } | | 6845 | } |
6846 | close(PATCH); | | 6846 | close(PATCH); |
6847 | my $chksum = Digest::SHA1::sha1_hex($data); | | 6847 | my $chksum = Digest::SHA1::sha1_hex($data); |
6848 | if ($sum ne $chksum) { | | 6848 | if ($sum ne $chksum) { |
6849 | $line->log_error("${alg} checksum of ${chksum_fname} differs (expected ${sum}, got ${chksum}). Rerun '".conf_make." makepatchsum'."); | | 6849 | $line->log_error("${alg} checksum of ${chksum_fname} differs (expected ${sum}, got ${chksum}). Rerun '".conf_make." makepatchsum'."); |
6850 | } | | 6850 | } |
6851 | } elsif (true) { | | 6851 | } elsif (true) { |
6852 | $line->log_warning("${chksum_fname} does not exist."); | | 6852 | $line->log_warning("${chksum_fname} does not exist."); |
6853 | $line->explain_warning( | | 6853 | $line->explain_warning( |
6854 | "All patches that are mentioned in a distinfo file should actually exist.", | | 6854 | "All patches that are mentioned in a distinfo file should actually exist.", |
6855 | "What's the use of a checksum if there is no file to check?"); | | 6855 | "What's the use of a checksum if there is no file to check?"); |
6856 | } | | 6856 | } |
6857 | } | | 6857 | } |
6858 | $in_distinfo{$chksum_fname} = true; | | 6858 | $in_distinfo{$chksum_fname} = true; |
6859 | } | | 6859 | } |
6860 | checklines_trailing_empty_lines($lines); | | 6860 | checklines_trailing_empty_lines($lines); |
6861 | | | 6861 | |
6862 | if (defined($patches_dir)) { | | 6862 | if (defined($patches_dir)) { |
6863 | foreach my $patch (<${current_dir}/${patches_dir}/patch-*>) { | | 6863 | foreach my $patch (<${current_dir}/${patches_dir}/patch-*>) { |
6864 | $patch = basename($patch); | | 6864 | $patch = basename($patch); |
6865 | if (!exists($in_distinfo{$patch})) { | | 6865 | if (!exists($in_distinfo{$patch})) { |
6866 | log_error($fname, NO_LINE_NUMBER, "$patch is not recorded. Rerun '".conf_make." makepatchsum'."); | | 6866 | log_error($fname, NO_LINE_NUMBER, "$patch is not recorded. Rerun '".conf_make." makepatchsum'."); |
6867 | } | | 6867 | } |
6868 | } | | 6868 | } |
6869 | } | | 6869 | } |
6870 | } | | 6870 | } |
6871 | | | 6871 | |
6872 | sub checkfile_extra($) { | | 6872 | sub checkfile_extra($) { |
6873 | my ($fname) = @_; | | 6873 | my ($fname) = @_; |
6874 | my ($lines); | | 6874 | my ($lines); |
6875 | | | 6875 | |
6876 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_extra()"); | | 6876 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_extra()"); |
6877 | | | 6877 | |
6878 | $lines = load_file($fname); | | 6878 | $lines = load_file($fname); |
6879 | if (!$lines) { | | 6879 | if (!$lines) { |
6880 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); | | 6880 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); |
6881 | return; | | 6881 | return; |
6882 | } | | 6882 | } |
6883 | checklines_trailing_empty_lines($lines); | | 6883 | checklines_trailing_empty_lines($lines); |
6884 | checkperms($fname); | | 6884 | checkperms($fname); |
6885 | } | | 6885 | } |
6886 | | | 6886 | |
6887 | sub checkfile_INSTALL($) { | | 6887 | sub checkfile_INSTALL($) { |
6888 | my ($fname) = @_; | | 6888 | my ($fname) = @_; |
6889 | my ($lines); | | 6889 | my ($lines); |
6890 | | | 6890 | |
6891 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); | | 6891 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); |
6892 | | | 6892 | |
6893 | checkperms($fname); | | 6893 | checkperms($fname); |
6894 | if (!($lines = load_file($fname))) { | | 6894 | if (!($lines = load_file($fname))) { |
6895 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6895 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6896 | return; | | 6896 | return; |
6897 | } | | 6897 | } |
6898 | } | | 6898 | } |
6899 | | | 6899 | |
6900 | sub checkfile_MESSAGE($) { | | 6900 | sub checkfile_MESSAGE($) { |
6901 | my ($fname) = @_; | | 6901 | my ($fname) = @_; |
6902 | my ($lines); | | 6902 | my ($lines); |
6903 | | | 6903 | |
6904 | my @explanation = ( | | 6904 | my @explanation = ( |
6905 | "A MESSAGE file should consist of a header line, having 75 \"=\"", | | 6905 | "A MESSAGE file should consist of a header line, having 75 \"=\"", |
6906 | "characters, followed by a line containing only the RCS Id, then an", | | 6906 | "characters, followed by a line containing only the RCS Id, then an", |
6907 | "empty line, your text and finally the footer line, which is the", | | 6907 | "empty line, your text and finally the footer line, which is the", |
6908 | "same as the header line."); | | 6908 | "same as the header line."); |
6909 | | | 6909 | |
6910 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); | | 6910 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); |
6911 | | | 6911 | |
6912 | checkperms($fname); | | 6912 | checkperms($fname); |
6913 | if (!($lines = load_file($fname))) { | | 6913 | if (!($lines = load_file($fname))) { |
6914 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6914 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6915 | return; | | 6915 | return; |
6916 | } | | 6916 | } |
6917 | | | 6917 | |
6918 | if (@{$lines} < 3) { | | 6918 | if (@{$lines} < 3) { |
6919 | log_warning($fname, NO_LINE_NUMBER, "File too short."); | | 6919 | log_warning($fname, NO_LINE_NUMBER, "File too short."); |
6920 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6920 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6921 | return; | | 6921 | return; |
6922 | } | | 6922 | } |
6923 | if ($lines->[0]->text ne "=" x 75) { | | 6923 | if ($lines->[0]->text ne "=" x 75) { |
6924 | $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); | | 6924 | $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); |
6925 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6925 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6926 | } | | 6926 | } |
6927 | checkline_rcsid($lines->[1], ""); | | 6927 | checkline_rcsid($lines->[1], ""); |
6928 | foreach my $line (@{$lines}) { | | 6928 | foreach my $line (@{$lines}) { |
6929 | checkline_length($line, 80); | | 6929 | checkline_length($line, 80); |
6930 | checkline_trailing_whitespace($line); | | 6930 | checkline_trailing_whitespace($line); |
6931 | checkline_valid_characters($line, regex_validchars); | | 6931 | checkline_valid_characters($line, regex_validchars); |
6932 | checkline_spellcheck($line); | | 6932 | checkline_spellcheck($line); |
6933 | } | | 6933 | } |
6934 | if ($lines->[-1]->text ne "=" x 75) { | | 6934 | if ($lines->[-1]->text ne "=" x 75) { |
6935 | $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); | | 6935 | $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); |
6936 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6936 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6937 | } | | 6937 | } |
6938 | checklines_trailing_empty_lines($lines); | | 6938 | checklines_trailing_empty_lines($lines); |
6939 | } | | 6939 | } |
6940 | | | 6940 | |
6941 | sub checkfile_mk($) { | | 6941 | sub checkfile_mk($) { |
6942 | my ($fname) = @_; | | 6942 | my ($fname) = @_; |
6943 | my ($lines); | | 6943 | my ($lines); |
6944 | | | 6944 | |
6945 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); | | 6945 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); |
6946 | | | 6946 | |
6947 | checkperms($fname); | | 6947 | checkperms($fname); |
6948 | if (!($lines = load_lines($fname, true))) { | | 6948 | if (!($lines = load_lines($fname, true))) { |
6949 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6949 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6950 | return; | | 6950 | return; |
6951 | } | | 6951 | } |
6952 | | | 6952 | |
6953 | parselines_mk($lines); | | 6953 | parselines_mk($lines); |
6954 | checklines_mk($lines); | | 6954 | checklines_mk($lines); |
6955 | autofix($lines); | | 6955 | autofix($lines); |
6956 | } | | 6956 | } |
6957 | | | 6957 | |
6958 | sub checkfile_package_Makefile($$) { | | 6958 | sub checkfile_package_Makefile($$) { |
6959 | my ($fname, $lines) = @_; | | 6959 | my ($fname, $lines) = @_; |
6960 | | | 6960 | |
6961 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); | | 6961 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); |
6962 | | | 6962 | |
6963 | checkperms($fname); | | 6963 | checkperms($fname); |
6964 | | | 6964 | |
6965 | if (!exists($pkgctx_vardef->{"PKG_DESTDIR_SUPPORT"}) && !exists($pkgctx_vardef->{"META_PACKAGE"})) { | | 6965 | if (!exists($pkgctx_vardef->{"PKG_DESTDIR_SUPPORT"}) && !exists($pkgctx_vardef->{"META_PACKAGE"})) { |
6966 | log_warning($fname, NO_LINE_NUMBER, "This package has not set PKG_DESTDIR_SUPPORT."); | | 6966 | log_warning($fname, NO_LINE_NUMBER, "This package has not set PKG_DESTDIR_SUPPORT."); |
6967 | } | | 6967 | } |
6968 | | | 6968 | |
6969 | if (!exists($pkgctx_vardef->{"PLIST_SRC"}) | | 6969 | if (!exists($pkgctx_vardef->{"PLIST_SRC"}) |
6970 | && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) | | 6970 | && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) |
6971 | && !exists($pkgctx_vardef->{"META_PACKAGE"}) | | 6971 | && !exists($pkgctx_vardef->{"META_PACKAGE"}) |
6972 | && defined($pkgdir) | | 6972 | && defined($pkgdir) |
6973 | && !-f "${current_dir}/$pkgdir/PLIST" | | 6973 | && !-f "${current_dir}/$pkgdir/PLIST" |
6974 | && !-f "${current_dir}/$pkgdir/PLIST.common") { | | 6974 | && !-f "${current_dir}/$pkgdir/PLIST.common") { |
6975 | log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); | | 6975 | log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); |
6976 | } | | 6976 | } |
6977 | | | 6977 | |
6978 | if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { | | 6978 | if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { |
6979 | if (-f "${current_dir}/${distinfo_file}") { | | 6979 | if (-f "${current_dir}/${distinfo_file}") { |
6980 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); | | 6980 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); |
6981 | } | | 6981 | } |
6982 | } else { | | 6982 | } else { |
6983 | if (!-f "${current_dir}/${distinfo_file}") { | | 6983 | if (!-f "${current_dir}/${distinfo_file}") { |
6984 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); | | 6984 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); |
6985 | } | | 6985 | } |
6986 | } | | 6986 | } |
6987 | | | 6987 | |
6988 | if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { | | 6988 | if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { |
6989 | $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); | | 6989 | $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); |
6990 | $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); | | 6990 | $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); |
6991 | } | | 6991 | } |
6992 | | | 6992 | |
6993 | if (exists($pkgctx_vardef->{"RESTRICTED"}) && !exists($pkgctx_vardef->{"LICENSE"})) { | | 6993 | if (exists($pkgctx_vardef->{"RESTRICTED"}) && !exists($pkgctx_vardef->{"LICENSE"})) { |
6994 | $pkgctx_vardef->{"RESTRICTED"}->log_error("Restricted packages must have a LICENSE."); | | 6994 | $pkgctx_vardef->{"RESTRICTED"}->log_error("Restricted packages must have a LICENSE."); |
6995 | } | | 6995 | } |
6996 | | | 6996 | |
6997 | if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { | | 6997 | if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { |
6998 | my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; | | 6998 | my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; |
6999 | my $value = $languages_line->get("value"); | | 6999 | my $value = $languages_line->get("value"); |
7000 | | | 7000 | |
7001 | if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { | | 7001 | if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { |
7002 | # Don't emit a warning, since the comment | | 7002 | # Don't emit a warning, since the comment |
7003 | # probably contains a statement that C is | | 7003 | # probably contains a statement that C is |
7004 | # really not needed. | | 7004 | # really not needed. |
7005 | | | 7005 | |
7006 | } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { | | 7006 | } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { |
7007 | $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); | | 7007 | $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); |
7008 | $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); | | 7008 | $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); |
7009 | } | | 7009 | } |
7010 | } | | 7010 | } |
7011 | | | 7011 | |
7012 | my $distname_line = $pkgctx_vardef->{"DISTNAME"}; | | 7012 | my $distname_line = $pkgctx_vardef->{"DISTNAME"}; |
7013 | my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; | | 7013 | my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; |
7014 | | | 7014 | |
7015 | my $distname = defined($distname_line) ? $distname_line->get("value") : undef; | | 7015 | my $distname = defined($distname_line) ? $distname_line->get("value") : undef; |
7016 | my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; | | 7016 | my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; |
7017 | my $nbpart = get_nbpart(); | | 7017 | my $nbpart = get_nbpart(); |
7018 | | | 7018 | |
7019 | # Let's do some tricks to get the proper value of the package | | 7019 | # Let's do some tricks to get the proper value of the package |
7020 | # name more often. | | 7020 | # name more often. |
7021 | if (defined($distname) && defined($pkgname)) { | | 7021 | if (defined($distname) && defined($pkgname)) { |
7022 | $pkgname =~ s/\$\{DISTNAME\}/$distname/; | | 7022 | $pkgname =~ s/\$\{DISTNAME\}/$distname/; |
7023 | | | 7023 | |
7024 | if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { | | 7024 | if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { |
7025 | my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); | | 7025 | my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); |
7026 | my $newname = $distname; | | 7026 | my $newname = $distname; |
7027 | $old = quotemeta($old); | | 7027 | $old = quotemeta($old); |
7028 | $old =~ s/^\\\^/^/; | | 7028 | $old =~ s/^\\\^/^/; |
7029 | $old =~ s/\\\$$/\$/; | | 7029 | $old =~ s/\\\$$/\$/; |
7030 | if ($mod eq "g") { | | 7030 | if ($mod eq "g") { |
7031 | $newname =~ s/$old/$new/g; | | 7031 | $newname =~ s/$old/$new/g; |
7032 | } else { | | 7032 | } else { |
7033 | $newname =~ s/$old/$new/; | | 7033 | $newname =~ s/$old/$new/; |
7034 | } | | 7034 | } |
7035 | $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); | | 7035 | $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); |
7036 | $pkgname = $before . $newname . $after; | | 7036 | $pkgname = $before . $newname . $after; |
7037 | $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); | | 7037 | $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); |
7038 | } | | 7038 | } |
7039 | } | | 7039 | } |
7040 | | | 7040 | |
7041 | if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { | | 7041 | if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { |
7042 | $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); | | 7042 | $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); |
7043 | } | | 7043 | } |
7044 | | | 7044 | |
7045 | if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { | | 7045 | if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { |
7046 | $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); | | 7046 | $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); |
7047 | } | | 7047 | } |
7048 | | | 7048 | |
7049 | ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) | | 7049 | ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) |
7050 | = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) | | 7050 | = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) |
7051 | : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) | | 7051 | : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) |
7052 | : (undef, undef, undef, undef); | | 7052 | : (undef, undef, undef, undef); |
7053 | if (defined($effective_pkgname_line)) { | | 7053 | if (defined($effective_pkgname_line)) { |
7054 | $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); | | 7054 | $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); |
7055 | # XXX: too many false positives | | 7055 | # XXX: too many false positives |
7056 | if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) { | | 7056 | if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) { |
7057 | $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1)."); | | 7057 | $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1)."); |
7058 | } | | 7058 | } |
7059 | } | | 7059 | } |
7060 | | | 7060 | |
7061 | checkpackage_possible_downgrade(); | | 7061 | checkpackage_possible_downgrade(); |
7062 | | | 7062 | |
7063 | if (!exists($pkgctx_vardef->{"COMMENT"})) { | | 7063 | if (!exists($pkgctx_vardef->{"COMMENT"})) { |
7064 | log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); | | 7064 | log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); |
7065 | } | | 7065 | } |
7066 | | | 7066 | |
7067 | if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { | | 7067 | if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { |
7068 | $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); | | 7068 | $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); |
7069 | $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); | | 7069 | $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); |
7070 | } | | 7070 | } |
7071 | | | 7071 | |
7072 | if (defined($effective_pkgbase)) { | | 7072 | if (defined($effective_pkgbase)) { |
7073 | | | 7073 | |
7074 | foreach my $suggested_update (@{get_suggested_package_updates()}) { | | 7074 | foreach my $suggested_update (@{get_suggested_package_updates()}) { |
7075 | my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; | | 7075 | my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; |
7076 | my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); | | 7076 | my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); |
7077 | | | 7077 | |
7078 | next unless $effective_pkgbase eq $suggbase; | | 7078 | next unless $effective_pkgbase eq $suggbase; |
7079 | | | 7079 | |
7080 | if (dewey_cmp($effective_pkgversion, "<", $suggver)) { | | 7080 | if (dewey_cmp($effective_pkgversion, "<", $suggver)) { |
7081 | $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); | | 7081 | $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); |
7082 | } | | 7082 | } |
7083 | if (dewey_cmp($effective_pkgversion, "==", $suggver)) { | | 7083 | if (dewey_cmp($effective_pkgversion, "==", $suggver)) { |
7084 | $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); | | 7084 | $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); |
7085 | } | | 7085 | } |
7086 | if (dewey_cmp($effective_pkgversion, ">", $suggver)) { | | 7086 | if (dewey_cmp($effective_pkgversion, ">", $suggver)) { |
7087 | $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); | | 7087 | $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); |
7088 | } | | 7088 | } |
7089 | } | | 7089 | } |
7090 | } | | 7090 | } |
7091 | | | 7091 | |
7092 | checklines_mk($lines); | | 7092 | checklines_mk($lines); |
7093 | checklines_package_Makefile_varorder($lines); | | 7093 | checklines_package_Makefile_varorder($lines); |
7094 | autofix($lines); | | 7094 | autofix($lines); |
7095 | } | | 7095 | } |
7096 | | | 7096 | |
7097 | sub checkfile_patch($) { | | 7097 | sub checkfile_patch($) { |
7098 | my ($fname) = @_; | | 7098 | my ($fname) = @_; |
7099 | my ($lines); | | 7099 | my ($lines); |
7100 | my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); | | 7100 | my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); |
7101 | my ($seen_comment, $current_fname, $current_ftype, $patched_files); | | 7101 | my ($seen_comment, $current_fname, $current_ftype, $patched_files); |
7102 | my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); | | 7102 | my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); |
7103 | | | 7103 | |
7104 | # Abbreviations used: | | 7104 | # Abbreviations used: |
7105 | # style: [c] = context diff, [u] = unified diff | | 7105 | # style: [c] = context diff, [u] = unified diff |
7106 | # scope: [f] = file, [h] = hunk, [l] = line | | 7106 | # scope: [f] = file, [h] = hunk, [l] = line |
7107 | # action: [d] = delete, [m] = modify, [a] = add, [c] = context | | 7107 | # action: [d] = delete, [m] = modify, [a] = add, [c] = context |
7108 | use constant re_patch_rcsid => qr"^\$.*\$$"; | | 7108 | use constant re_patch_rcsid => qr"^\$.*\$$"; |
7109 | use constant re_patch_text => qr"^(.+)$"; | | 7109 | use constant re_patch_text => qr"^(.+)$"; |
7110 | use constant re_patch_empty => qr"^$"; | | 7110 | use constant re_patch_empty => qr"^$"; |
7111 | use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; | | 7111 | use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; |
7112 | use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; | | 7112 | use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; |
7113 | use constant re_patch_ch => qr"^\*{15}(.*)$"; | | 7113 | use constant re_patch_ch => qr"^\*{15}(.*)$"; |
7114 | use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; | | 7114 | use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; |
7115 | use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; | | 7115 | use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; |
7116 | use constant re_patch_cld => qr"^(?:-\s(.*))?$"; | | 7116 | use constant re_patch_cld => qr"^(?:-\s(.*))?$"; |
7117 | use constant re_patch_clm => qr"^(?:!\s(.*))?$"; | | 7117 | use constant re_patch_clm => qr"^(?:!\s(.*))?$"; |
7118 | use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; | | 7118 | use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; |
7119 | use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; | | 7119 | use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; |
7120 | use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; | | 7120 | use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; |
7121 | use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; | | 7121 | use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; |
7122 | use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; | | 7122 | use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; |
7123 | use constant re_patch_uld => qr"^-(.*)$"; | | 7123 | use constant re_patch_uld => qr"^-(.*)$"; |
7124 | use constant re_patch_ula => qr"^\+(.*)$"; | | 7124 | use constant re_patch_ula => qr"^\+(.*)$"; |
7125 | use constant re_patch_ulc => qr"^\s(.*)$"; | | 7125 | use constant re_patch_ulc => qr"^\s(.*)$"; |
7126 | use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; | | 7126 | use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; |
7127 | | | 7127 | |
7128 | use enum qw(:PST_ | | 7128 | use enum qw(:PST_ |
7129 | START CENTER TEXT | | 7129 | START CENTER TEXT |
7130 | CFA CH CHD CLD0 CLD CLA0 CLA | | 7130 | CFA CH CHD CLD0 CLD CLA0 CLA |
7131 | UFA UH UL | | 7131 | UFA UH UL |
7132 | ); | | 7132 | ); |
7133 | | | 7133 | |
7134 | my ($line, $m); | | 7134 | my ($line, $m); |
7135 | | | 7135 | |
7136 | my $check_text = sub($) { | | 7136 | my $check_text = sub($) { |
7137 | my ($text) = @_; | | 7137 | my ($text) = @_; |
7138 | | | 7138 | |
7139 | if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { | | 7139 | if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { |
7140 | my ($tag) = ($2); | | 7140 | my ($tag) = ($2); |
7141 | | | 7141 | |
7142 | if ($text =~ re_patch_uh) { | | 7142 | if ($text =~ re_patch_uh) { |
7143 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); | | 7143 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); |
7144 | $line->set_text($1); | | 7144 | $line->set_text($1); |
7145 | } else { | | 7145 | } else { |
7146 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); | | 7146 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); |
7147 | } | | 7147 | } |
7148 | } | | 7148 | } |
7149 | }; | | 7149 | }; |
7150 | | | 7150 | |
7151 | my $check_contents = sub() { | | 7151 | my $check_contents = sub() { |
7152 | | | 7152 | |
7153 | if ($m->has(1)) { | | 7153 | if ($m->has(1)) { |
7154 | $check_text->($m->text(1)); | | 7154 | $check_text->($m->text(1)); |
7155 | } | | 7155 | } |
7156 | }; | | 7156 | }; |
7157 | | | 7157 | |
7158 | my $check_added_contents = sub() { | | 7158 | my $check_added_contents = sub() { |
7159 | my $text; | | 7159 | my $text; |
7160 | | | 7160 | |
7161 | return unless $m->has(1); | | 7161 | return unless $m->has(1); |
7162 | $text = $m->text(1); | | 7162 | $text = $m->text(1); |
7163 | checkline_cpp_macro_names($line, $text); | | 7163 | checkline_cpp_macro_names($line, $text); |
7164 | checkline_spellcheck($line); | | 7164 | checkline_spellcheck($line); |
7165 | | | 7165 | |
7166 | # XXX: This check is not as accurate as the similar one in | | 7166 | # XXX: This check is not as accurate as the similar one in |
7167 | # checkline_mk_shelltext(). | | 7167 | # checkline_mk_shelltext(). |
7168 | if (defined($current_fname)) { | | 7168 | if (defined($current_fname)) { |
7169 | if ($current_ftype eq "shell" || $current_ftype eq "make") { | | 7169 | if ($current_ftype eq "shell" || $current_ftype eq "make") { |
7170 | my ($mm, $rest) = match_all($text, $regex_shellword); | | 7170 | my ($mm, $rest) = match_all($text, $regex_shellword); |
7171 | | | 7171 | |
7172 | foreach my $m (@{$mm}) { | | 7172 | foreach my $m (@{$mm}) { |
7173 | my $shellword = $m->text(1); | | 7173 | my $shellword = $m->text(1); |
7174 | | | 7174 | |
7175 | if ($shellword =~ m"^#") { | | 7175 | if ($shellword =~ m"^#") { |
7176 | last; | | 7176 | last; |
7177 | } | | 7177 | } |
7178 | checkline_mk_absolute_pathname($line, $shellword); | | 7178 | checkline_mk_absolute_pathname($line, $shellword); |
7179 | } | | 7179 | } |
7180 | | | 7180 | |
7181 | } elsif ($current_ftype eq "source") { | | 7181 | } elsif ($current_ftype eq "source") { |
7182 | checkline_source_absolute_pathname($line, $text); | | 7182 | checkline_source_absolute_pathname($line, $text); |
7183 | | | 7183 | |
7184 | } elsif ($current_ftype eq "configure") { | | 7184 | } elsif ($current_ftype eq "configure") { |
7185 | if ($text =~ m": Avoid regenerating within pkgsrc$") { | | 7185 | if ($text =~ m": Avoid regenerating within pkgsrc$") { |
7186 | $line->log_error("This code must not be included in patches."); | | 7186 | $line->log_error("This code must not be included in patches."); |
7187 | $line->explain_error( | | 7187 | $line->explain_error( |
7188 | "It is generated automatically by pkgsrc after the patch phase.", | | 7188 | "It is generated automatically by pkgsrc after the patch phase.", |
7189 | "", | | 7189 | "", |
7190 | "For more details, look for \"configure-scripts-override\" in", | | 7190 | "For more details, look for \"configure-scripts-override\" in", |
7191 | "mk/configure/gnu-configure.mk."); | | 7191 | "mk/configure/gnu-configure.mk."); |
7192 | } | | 7192 | } |
7193 | | | 7193 | |
7194 | } elsif ($current_ftype eq "ignore") { | | 7194 | } elsif ($current_ftype eq "ignore") { |
7195 | # Ignore it. | | 7195 | # Ignore it. |
7196 | | | 7196 | |
7197 | } else { | | 7197 | } else { |
7198 | checkline_other_absolute_pathname($line, $text); | | 7198 | checkline_other_absolute_pathname($line, $text); |
7199 | } | | 7199 | } |
7200 | } | | 7200 | } |
7201 | }; | | 7201 | }; |
7202 | | | 7202 | |
7203 | my $check_hunk_end = sub($$$) { | | 7203 | my $check_hunk_end = sub($$$) { |
7204 | my ($deldelta, $adddelta, $newstate) = @_; | | 7204 | my ($deldelta, $adddelta, $newstate) = @_; |
7205 | | | 7205 | |
7206 | if ($deldelta > 0 && $dellines == 0) { | | 7206 | if ($deldelta > 0 && $dellines == 0) { |
7207 | $redostate = $newstate; | | 7207 | $redostate = $newstate; |
7208 | if (defined($addlines) && $addlines > 0) { | | 7208 | if (defined($addlines) && $addlines > 0) { |
7209 | $line->log_error("Expected ${addlines} more lines to be added."); | | 7209 | $line->log_error("Expected ${addlines} more lines to be added."); |
7210 | } | | 7210 | } |
7211 | } elsif ($adddelta > 0 && $addlines == 0) { | | 7211 | } elsif ($adddelta > 0 && $addlines == 0) { |
7212 | $redostate = $newstate; | | 7212 | $redostate = $newstate; |
7213 | if (defined($dellines) && $dellines > 0) { | | 7213 | if (defined($dellines) && $dellines > 0) { |
7214 | $line->log_error("Expected ${dellines} more lines to be deleted."); | | 7214 | $line->log_error("Expected ${dellines} more lines to be deleted."); |
7215 | } | | 7215 | } |
7216 | } else { | | 7216 | } else { |
7217 | if (defined($context_scanning_leading)) { | | 7217 | if (defined($context_scanning_leading)) { |
7218 | if ($deldelta != 0 && $adddelta != 0) { | | 7218 | if ($deldelta != 0 && $adddelta != 0) { |
7219 | if ($context_scanning_leading) { | | 7219 | if ($context_scanning_leading) { |
7220 | $leading_context_lines++; | | 7220 | $leading_context_lines++; |
7221 | } else { | | 7221 | } else { |
7222 | $trailing_context_lines++; | | 7222 | $trailing_context_lines++; |
7223 | } | | 7223 | } |
7224 | } else { | | 7224 | } else { |
7225 | if ($context_scanning_leading) { | | 7225 | if ($context_scanning_leading) { |
7226 | $context_scanning_leading = false; | | 7226 | $context_scanning_leading = false; |
7227 | } else { | | 7227 | } else { |
7228 | $trailing_context_lines = 0; | | 7228 | $trailing_context_lines = 0; |
7229 | } | | 7229 | } |
7230 | } | | 7230 | } |
7231 | } | | 7231 | } |
7232 | | | 7232 | |
7233 | if ($deldelta != 0) { | | 7233 | if ($deldelta != 0) { |
7234 | $dellines -= $deldelta; | | 7234 | $dellines -= $deldelta; |
7235 | } | | 7235 | } |
7236 | if ($adddelta != 0) { | | 7236 | if ($adddelta != 0) { |
7237 | $addlines -= $adddelta; | | 7237 | $addlines -= $adddelta; |
7238 | } | | 7238 | } |
7239 | if (!((defined($dellines) && $dellines > 0) || | | 7239 | if (!((defined($dellines) && $dellines > 0) || |
7240 | (defined($addlines) && $addlines > 0))) { | | 7240 | (defined($addlines) && $addlines > 0))) { |
7241 | if (defined($context_scanning_leading)) { | | 7241 | if (defined($context_scanning_leading)) { |
7242 | if ($leading_context_lines != $trailing_context_lines) { | | 7242 | if ($leading_context_lines != $trailing_context_lines) { |
7243 | $opt_debug_patches and $line->log_warning("The hunk that ends here does not have as many leading (${leading_context_lines}) as trailing (${trailing_context_lines}) lines of context."); | | 7243 | $opt_debug_patches and $line->log_warning("The hunk that ends here does not have as many leading (${leading_context_lines}) as trailing (${trailing_context_lines}) lines of context."); |
7244 | } | | 7244 | } |
7245 | } | | 7245 | } |
7246 | $nextstate = $newstate; | | 7246 | $nextstate = $newstate; |
7247 | } | | 7247 | } |
7248 | } | | 7248 | } |
7249 | }; | | 7249 | }; |
7250 | | | 7250 | |
7251 | # @param deldelta | | 7251 | # @param deldelta |
7252 | # The number of lines that are deleted from the patched file. | | 7252 | # The number of lines that are deleted from the patched file. |
7253 | # @param adddelta | | 7253 | # @param adddelta |
7254 | # The number of lines that are added to the patched file. | | 7254 | # The number of lines that are added to the patched file. |
7255 | # @param newstate | | 7255 | # @param newstate |
7256 | # The follow-up state when this line is the last line to be | | 7256 | # The follow-up state when this line is the last line to be |
7257 | # added in this hunk of the patch. | | 7257 | # added in this hunk of the patch. |
7258 | # | | 7258 | # |
7259 | my $check_hunk_line = sub($$$) { | | 7259 | my $check_hunk_line = sub($$$) { |
7260 | my ($deldelta, $adddelta, $newstate) = @_; | | 7260 | my ($deldelta, $adddelta, $newstate) = @_; |
7261 | | | 7261 | |
7262 | $check_contents->(); | | 7262 | $check_contents->(); |
7263 | $check_hunk_end->($deldelta, $adddelta, $newstate); | | 7263 | $check_hunk_end->($deldelta, $adddelta, $newstate); |
7264 | | | 7264 | |
7265 | # If -Wextra is given, the context lines are checked for | | 7265 | # If -Wextra is given, the context lines are checked for |
7266 | # absolute paths and similar things. If it is not given, | | 7266 | # absolute paths and similar things. If it is not given, |
7267 | # only those lines that really add something to the patched | | 7267 | # only those lines that really add something to the patched |
7268 | # file are checked. | | 7268 | # file are checked. |
7269 | if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) { | | 7269 | if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) { |
7270 | $check_added_contents->(); | | 7270 | $check_added_contents->(); |
7271 | } | | 7271 | } |
7272 | }; | | 7272 | }; |
7273 | | | 7273 | |
7274 | my $transitions = | | 7274 | my $transitions = |
7275 | # [ from state, regex, to state, action ] | | 7275 | # [ from state, regex, to state, action ] |
7276 | [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { | | 7276 | [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { |
7277 | checkline_rcsid($line, ""); | | 7277 | checkline_rcsid($line, ""); |
7278 | }], [PST_START, undef, PST_CENTER, sub() { | | 7278 | }], [PST_START, undef, PST_CENTER, sub() { |
7279 | checkline_rcsid($line, ""); | | 7279 | checkline_rcsid($line, ""); |
7280 | }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { | | 7280 | }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { |
7281 | # | | 7281 | # |
7282 | }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { | | 7282 | }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { |
7283 | if (!$seen_comment) { | | 7283 | if (!$seen_comment) { |
7284 | $opt_warn_style and $line->log_warning("Comment expected."); | | 7284 | $opt_warn_style and $line->log_warning("Comment expected."); |
7285 | } | | 7285 | } |
7286 | $line->log_warning("Please use unified diffs (diff -u) for patches."); | | 7286 | $line->log_warning("Please use unified diffs (diff -u) for patches."); |
7287 | }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { | | 7287 | }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { |
7288 | if (!$seen_comment) { | | 7288 | if (!$seen_comment) { |
7289 | $opt_warn_style and $line->log_warning("Comment expected."); | | 7289 | $opt_warn_style and $line->log_warning("Comment expected."); |
7290 | } | | 7290 | } |
7291 | }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { | | 7291 | }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { |
7292 | $seen_comment = true; | | 7292 | $seen_comment = true; |
7293 | }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { | | 7293 | }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { |
7294 | # | | 7294 | # |
7295 | }], [PST_TEXT, undef, PST_TEXT, sub() { | | 7295 | }], [PST_TEXT, undef, PST_TEXT, sub() { |
7296 | # | | 7296 | # |
7297 | }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { | | 7297 | }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { |
7298 | if ($seen_comment) { | | 7298 | if ($seen_comment) { |
7299 | $opt_warn_space and $line->log_note("Empty line expected."); | | 7299 | $opt_warn_space and $line->log_note("Empty line expected."); |
7300 | } else { | | 7300 | } else { |
7301 | $opt_warn_style and $line->log_warning("Comment expected."); | | 7301 | $opt_warn_style and $line->log_warning("Comment expected."); |
7302 | } | | 7302 | } |
7303 | $line->log_warning("Please use unified diffs (diff -u) for patches."); | | 7303 | $line->log_warning("Please use unified diffs (diff -u) for patches."); |
7304 | }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { | | 7304 | }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { |
7305 | if ($seen_comment) { | | 7305 | if ($seen_comment) { |
7306 | $opt_warn_space and $line->log_note("Empty line expected."); | | 7306 | $opt_warn_space and $line->log_note("Empty line expected."); |
7307 | } else { | | 7307 | } else { |
7308 | $opt_warn_style and $line->log_warning("Comment expected."); | | 7308 | $opt_warn_style and $line->log_warning("Comment expected."); |
7309 | } | | 7309 | } |
7310 | }], [PST_CENTER, undef, PST_TEXT, sub() { | | 7310 | }], [PST_CENTER, undef, PST_TEXT, sub() { |
7311 | $opt_warn_space and $line->log_note("Empty line expected."); | | 7311 | $opt_warn_space and $line->log_note("Empty line expected."); |
7312 | }], [PST_CFA, re_patch_cfa, PST_CH, sub() { | | 7312 | }], [PST_CFA, re_patch_cfa, PST_CH, sub() { |
7313 | $current_fname = $m->text(1); | | 7313 | $current_fname = $m->text(1); |
7314 | $current_ftype = get_filetype($line, $current_fname); | | 7314 | $current_ftype = get_filetype($line, $current_fname); |
7315 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); | | 7315 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); |
7316 | $patched_files++; | | 7316 | $patched_files++; |
7317 | $hunks = 0; | | 7317 | $hunks = 0; |
7318 | }], [PST_CH, re_patch_ch, PST_CHD, sub() { | | 7318 | }], [PST_CH, re_patch_ch, PST_CHD, sub() { |
7319 | $hunks++; | | 7319 | $hunks++; |
7320 | }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { | | 7320 | }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { |
7321 | $dellines = ($m->has(2)) | | 7321 | $dellines = ($m->has(2)) |
7322 | ? (1 + $m->text(2) - $m->text(1)) | | 7322 | ? (1 + $m->text(2) - $m->text(1)) |
7323 | : ($m->text(1)); | | 7323 | : ($m->text(1)); |
7324 | }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { | | 7324 | }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { |
7325 | $check_hunk_line->(1, 0, PST_CLD0); | | 7325 | $check_hunk_line->(1, 0, PST_CLD0); |
7326 | }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { | | 7326 | }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { |
7327 | $check_hunk_line->(1, 0, PST_CLD0); | | 7327 | $check_hunk_line->(1, 0, PST_CLD0); |
7328 | }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { | | 7328 | }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { |
7329 | $check_hunk_line->(1, 0, PST_CLD0); | | 7329 | $check_hunk_line->(1, 0, PST_CLD0); |
7330 | }], [PST_CLD, re_patch_clc, PST_CLD, sub() { | | 7330 | }], [PST_CLD, re_patch_clc, PST_CLD, sub() { |
7331 | $check_hunk_line->(1, 0, PST_CLD0); | | 7331 | $check_hunk_line->(1, 0, PST_CLD0); |
7332 | }], [PST_CLD, re_patch_cld, PST_CLD, sub() { | | 7332 | }], [PST_CLD, re_patch_cld, PST_CLD, sub() { |
7333 | $check_hunk_line->(1, 0, PST_CLD0); | | 7333 | $check_hunk_line->(1, 0, PST_CLD0); |
7334 | }], [PST_CLD, re_patch_clm, PST_CLD, sub() { | | 7334 | }], [PST_CLD, re_patch_clm, PST_CLD, sub() { |
7335 | $check_hunk_line->(1, 0, PST_CLD0); | | 7335 | $check_hunk_line->(1, 0, PST_CLD0); |
7336 | }], [PST_CLD, undef, PST_CLD0, sub() { | | 7336 | }], [PST_CLD, undef, PST_CLD0, sub() { |
7337 | if ($dellines != 0) { | | 7337 | if ($dellines != 0) { |
7338 | $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); | | 7338 | $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); |
7339 | } | | 7339 | } |
7340 | }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { | | 7340 | }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { |
7341 | $dellines = undef; | | 7341 | $dellines = undef; |
7342 | $addlines = ($m->has(2)) | | 7342 | $addlines = ($m->has(2)) |
7343 | ? (1 + $m->text(2) - $m->text(1)) | | 7343 | ? (1 + $m->text(2) - $m->text(1)) |
7344 | : ($m->text(1)); | | 7344 | : ($m->text(1)); |
7345 | }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { | | 7345 | }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { |
7346 | $check_hunk_line->(0, 1, PST_CH); | | 7346 | $check_hunk_line->(0, 1, PST_CH); |
7347 | }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { | | 7347 | }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { |
7348 | $check_hunk_line->(0, 1, PST_CH); | | 7348 | $check_hunk_line->(0, 1, PST_CH); |
7349 | }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { | | 7349 | }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { |
7350 | $check_hunk_line->(0, 1, PST_CH); | | 7350 | $check_hunk_line->(0, 1, PST_CH); |
7351 | }], [PST_CLA, re_patch_clc, PST_CLA, sub() { | | 7351 | }], [PST_CLA, re_patch_clc, PST_CLA, sub() { |
7352 | $check_hunk_line->(0, 1, PST_CH); | | 7352 | $check_hunk_line->(0, 1, PST_CH); |
7353 | }], [PST_CLA, re_patch_clm, PST_CLA, sub() { | | 7353 | }], [PST_CLA, re_patch_clm, PST_CLA, sub() { |
7354 | $check_hunk_line->(0, 1, PST_CH); | | 7354 | $check_hunk_line->(0, 1, PST_CH); |
7355 | }], [PST_CLA, re_patch_cla, PST_CLA, sub() { | | 7355 | }], [PST_CLA, re_patch_cla, PST_CLA, sub() { |
7356 | $check_hunk_line->(0, 1, PST_CH); | | 7356 | $check_hunk_line->(0, 1, PST_CH); |
7357 | }], [PST_CLA, undef, PST_CLA0, sub() { | | 7357 | }], [PST_CLA, undef, PST_CLA0, sub() { |
7358 | if ($addlines != 0) { | | 7358 | if ($addlines != 0) { |
7359 | $line->log_warning("Invalid number of added lines (${addlines} missing)."); | | 7359 | $line->log_warning("Invalid number of added lines (${addlines} missing)."); |
7360 | } | | 7360 | } |
7361 | }], [PST_CLA0, undef, PST_CH, sub() { | | 7361 | }], [PST_CLA0, undef, PST_CH, sub() { |
7362 | # | | 7362 | # |
7363 | }], [PST_CH, undef, PST_TEXT, sub() { | | 7363 | }], [PST_CH, undef, PST_TEXT, sub() { |
7364 | # | | 7364 | # |
7365 | }], [PST_UFA, re_patch_ufa, PST_UH, sub() { | | 7365 | }], [PST_UFA, re_patch_ufa, PST_UH, sub() { |
7366 | $current_fname = $m->text(1); | | 7366 | $current_fname = $m->text(1); |
7367 | $current_ftype = get_filetype($line, $current_fname); | | 7367 | $current_ftype = get_filetype($line, $current_fname); |
7368 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); | | 7368 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); |
7369 | $patched_files++; | | 7369 | $patched_files++; |
7370 | $hunks = 0; | | 7370 | $hunks = 0; |
7371 | }], [PST_UH, re_patch_uh, PST_UL, sub() { | | 7371 | }], [PST_UH, re_patch_uh, PST_UL, sub() { |
7372 | $dellines = ($m->has(1) ? $m->text(2) : 1); | | 7372 | $dellines = ($m->has(1) ? $m->text(2) : 1); |
7373 | $addlines = ($m->has(3) ? $m->text(4) : 1); | | 7373 | $addlines = ($m->has(3) ? $m->text(4) : 1); |
7374 | $check_text->($line->text); | | 7374 | $check_text->($line->text); |
7375 | if ($line->text =~ m"\r$") { | | 7375 | if ($line->text =~ m"\r$") { |
7376 | $line->log_error("The hunk header must not end with a CR character."); | | 7376 | $line->log_error("The hunk header must not end with a CR character."); |
7377 | $line->explain_error( | | 7377 | $line->explain_error( |
7378 | "The MacOS X patch utility cannot handle these."); | | 7378 | "The MacOS X patch utility cannot handle these."); |
7379 | } | | 7379 | } |
7380 | $hunks++; | | 7380 | $hunks++; |
7381 | $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); | | 7381 | $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); |
7382 | $leading_context_lines = 0; | | 7382 | $leading_context_lines = 0; |
7383 | $trailing_context_lines = 0; | | 7383 | $trailing_context_lines = 0; |
7384 | }], [PST_UL, re_patch_uld, PST_UL, sub() { | | 7384 | }], [PST_UL, re_patch_uld, PST_UL, sub() { |
7385 | $check_hunk_line->(1, 0, PST_UH); | | 7385 | $check_hunk_line->(1, 0, PST_UH); |
7386 | }], [PST_UL, re_patch_ula, PST_UL, sub() { | | 7386 | }], [PST_UL, re_patch_ula, PST_UL, sub() { |
7387 | $check_hunk_line->(0, 1, PST_UH); | | 7387 | $check_hunk_line->(0, 1, PST_UH); |
7388 | }], [PST_UL, re_patch_ulc, PST_UL, sub() { | | 7388 | }], [PST_UL, re_patch_ulc, PST_UL, sub() { |
7389 | $check_hunk_line->(1, 1, PST_UH); | | 7389 | $check_hunk_line->(1, 1, PST_UH); |
7390 | }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { | | 7390 | }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { |
7391 | # | | 7391 | # |
7392 | }], [PST_UL, re_patch_empty, PST_UL, sub() { | | 7392 | }], [PST_UL, re_patch_empty, PST_UL, sub() { |
7393 | $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); | | 7393 | $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); |
7394 | $check_hunk_line->(1, 1, PST_UH); | | 7394 | $check_hunk_line->(1, 1, PST_UH); |
7395 | }], [PST_UL, undef, PST_UH, sub() { | | 7395 | }], [PST_UL, undef, PST_UH, sub() { |
7396 | if ($dellines != 0 || $addlines != 0) { | | 7396 | if ($dellines != 0 || $addlines != 0) { |
7397 | $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); | | 7397 | $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); |
7398 | } | | 7398 | } |
7399 | }], [PST_UH, undef, PST_TEXT, sub() { | | 7399 | }], [PST_UH, undef, PST_TEXT, sub() { |
7400 | ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); | | 7400 | ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); |
7401 | }]]; | | 7401 | }]]; |
7402 | | | 7402 | |
7403 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); | | 7403 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); |
7404 | | | 7404 | |
7405 | checkperms($fname); | | 7405 | checkperms($fname); |
7406 | if (!($lines = load_lines($fname, false))) { | | 7406 | if (!($lines = load_lines($fname, false))) { |
7407 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); | | 7407 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); |
7408 | return; | | 7408 | return; |
7409 | } | | 7409 | } |
7410 | if (@{$lines} == 0) { | | 7410 | if (@{$lines} == 0) { |
7411 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); | | 7411 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); |
7412 | return; | | 7412 | return; |
7413 | } | | 7413 | } |
7414 | | | 7414 | |
7415 | $state = PST_START; | | 7415 | $state = PST_START; |
7416 | $dellines = undef; | | 7416 | $dellines = undef; |
7417 | $addlines = undef; | | 7417 | $addlines = undef; |
7418 | $patched_files = 0; | | 7418 | $patched_files = 0; |
7419 | $seen_comment = false; | | 7419 | $seen_comment = false; |
7420 | $current_fname = undef; | | 7420 | $current_fname = undef; |
7421 | $current_ftype = undef; | | 7421 | $current_ftype = undef; |
7422 | $hunks = undef; | | 7422 | $hunks = undef; |
7423 | | | 7423 | |
7424 | for (my $lineno = 0; $lineno <= $#{$lines}; ) { | | 7424 | for (my $lineno = 0; $lineno <= $#{$lines}; ) { |
7425 | $line = $lines->[$lineno]; | | 7425 | $line = $lines->[$lineno]; |
7426 | my $text = $line->text; | | 7426 | my $text = $line->text; |
7427 | | | 7427 | |
7428 | $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); | | 7428 | $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); |
7429 | | | 7429 | |
7430 | my $found = false; | | 7430 | my $found = false; |
7431 | foreach my $t (@{$transitions}) { | | 7431 | foreach my $t (@{$transitions}) { |
7432 | if ($state == $t->[0]) { | | 7432 | if ($state == $t->[0]) { |
7433 | if (!defined($t->[1])) { | | 7433 | if (!defined($t->[1])) { |
7434 | $m = undef; | | 7434 | $m = undef; |
7435 | } elsif ($text =~ $t->[1]) { | | 7435 | } elsif ($text =~ $t->[1]) { |
7436 | $opt_debug_patches and $line->log_debug($t->[1]); | | 7436 | $opt_debug_patches and $line->log_debug($t->[1]); |
7437 | $m = PkgLint::SimpleMatch->new($text, \@-, \@+); | | 7437 | $m = PkgLint::SimpleMatch->new($text, \@-, \@+); |
7438 | } else { | | 7438 | } else { |
7439 | next; | | 7439 | next; |
7440 | } | | 7440 | } |
7441 | $redostate = undef; | | 7441 | $redostate = undef; |
7442 | $nextstate = $t->[2]; | | 7442 | $nextstate = $t->[2]; |
7443 | $t->[3]->(); | | 7443 | $t->[3]->(); |
7444 | if (defined($redostate)) { | | 7444 | if (defined($redostate)) { |
7445 | $state = $redostate; | | 7445 | $state = $redostate; |
7446 | } else { | | 7446 | } else { |
7447 | $state = $nextstate; | | 7447 | $state = $nextstate; |
7448 | if (defined($t->[1])) { | | 7448 | if (defined($t->[1])) { |
7449 | $lineno++; | | 7449 | $lineno++; |
7450 | } | | 7450 | } |
7451 | } | | 7451 | } |
7452 | $found = true; | | 7452 | $found = true; |
7453 | last; | | 7453 | last; |
7454 | } | | 7454 | } |
7455 | } | | 7455 | } |
7456 | | | 7456 | |
7457 | if (!$found) { | | 7457 | if (!$found) { |
7458 | $line->log_error("Parse error: state=${state}"); | | 7458 | $line->log_error("Parse error: state=${state}"); |
7459 | $state = PST_TEXT; | | 7459 | $state = PST_TEXT; |
7460 | $lineno++; | | 7460 | $lineno++; |
7461 | } | | 7461 | } |
7462 | } | | 7462 | } |
7463 | | | 7463 | |
7464 | while ($state != PST_TEXT) { | | 7464 | while ($state != PST_TEXT) { |
7465 | $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); | | 7465 | $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); |
7466 | | | 7466 | |
7467 | my $found = false; | | 7467 | my $found = false; |
7468 | foreach my $t (@{$transitions}) { | | 7468 | foreach my $t (@{$transitions}) { |
7469 | if ($state == $t->[0] && !defined($t->[1])) { | | 7469 | if ($state == $t->[0] && !defined($t->[1])) { |
7470 | my $newstate; | | 7470 | my $newstate; |
7471 | | | 7471 | |
7472 | $m = undef; | | 7472 | $m = undef; |
7473 | $redostate = undef; | | 7473 | $redostate = undef; |
7474 | $nextstate = $t->[2]; | | 7474 | $nextstate = $t->[2]; |
7475 | $t->[3]->(); | | 7475 | $t->[3]->(); |
7476 | $newstate = (defined($redostate)) ? $redostate : $nextstate; | | 7476 | $newstate = (defined($redostate)) ? $redostate : $nextstate; |
7477 | if ($newstate == $state) { | | 7477 | if ($newstate == $state) { |
7478 | log_fatal($fname, "EOF", "Internal error in the patch transition table."); | | 7478 | log_fatal($fname, "EOF", "Internal error in the patch transition table."); |
7479 | } | | 7479 | } |
7480 | $state = $newstate; | | 7480 | $state = $newstate; |
7481 | $found = true; | | 7481 | $found = true; |
7482 | last; | | 7482 | last; |
7483 | } | | 7483 | } |
7484 | } | | 7484 | } |
7485 | | | 7485 | |
7486 | if (!$found) { | | 7486 | if (!$found) { |
7487 | log_error($fname, "EOF", "Parse error: state=${state}"); | | 7487 | log_error($fname, "EOF", "Parse error: state=${state}"); |
7488 | $state = PST_TEXT; | | 7488 | $state = PST_TEXT; |
7489 | } | | 7489 | } |
7490 | } | | 7490 | } |
7491 | | | 7491 | |
7492 | if ($patched_files > 1) { | | 7492 | if ($patched_files > 1) { |
7493 | log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); | | 7493 | log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); |
7494 | | | 7494 | |
7495 | } elsif ($patched_files == 0) { | | 7495 | } elsif ($patched_files == 0) { |
7496 | log_error($fname, NO_LINE_NUMBER, "Contains no patch."); | | 7496 | log_error($fname, NO_LINE_NUMBER, "Contains no patch."); |
7497 | } | | 7497 | } |
7498 | | | 7498 | |
7499 | checklines_trailing_empty_lines($lines); | | 7499 | checklines_trailing_empty_lines($lines); |
7500 | } | | 7500 | } |
7501 | | | 7501 | |
7502 | sub checkfile_PLIST($) { | | 7502 | sub checkfile_PLIST($) { |
7503 | my ($fname) = @_; | | 7503 | my ($fname) = @_; |
7504 | my ($lines, $last_file_seen); | | 7504 | my ($lines, $last_file_seen); |
7505 | | | 7505 | |
7506 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); | | 7506 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); |
7507 | | | 7507 | |
7508 | checkperms($fname); | | 7508 | checkperms($fname); |
7509 | if (!($lines = load_file($fname))) { | | 7509 | if (!($lines = load_file($fname))) { |
7510 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 7510 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
7511 | return; | | 7511 | return; |
7512 | } | | 7512 | } |
7513 | if (@{$lines} == 0) { | | 7513 | if (@{$lines} == 0) { |
7514 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); | | 7514 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); |
7515 | return; | | 7515 | return; |
7516 | } | | 7516 | } |
7517 | checkline_rcsid($lines->[0], "\@comment "); | | 7517 | checkline_rcsid($lines->[0], "\@comment "); |
7518 | | | 7518 | |
7519 | if (@$lines == 1) { | | 7519 | if (@$lines == 1) { |
7520 | $lines->[0]->log_warning("PLIST files shouldn't be empty."); | | 7520 | $lines->[0]->log_warning("PLIST files shouldn't be empty."); |
7521 | $lines->[0]->explain_warning( | | 7521 | $lines->[0]->explain_warning( |
7522 | "One reason for empty PLISTs is that this is a newly created package", | | 7522 | "One reason for empty PLISTs is that this is a newly created package", |
7523 | "and that the author didn't run \"bmake print-PLIST\" after installing", | | 7523 | "and that the author didn't run \"bmake print-PLIST\" after installing", |
7524 | "the files.", | | 7524 | "the files.", |
7525 | "", | | 7525 | "", |
7526 | "Another reason, common for Perl packages, is that the final PLIST is", | | 7526 | "Another reason, common for Perl packages, is that the final PLIST is", |
7527 | "automatically generated. Since the source PLIST is not used at all,", | | 7527 | "automatically generated. Since the source PLIST is not used at all,", |
7528 | "you can remove it.", | | 7528 | "you can remove it.", |
7529 | "", | | 7529 | "", |
7530 | "Meta packages also don't need a PLIST file."); | | 7530 | "Meta packages also don't need a PLIST file."); |
7531 | } | | 7531 | } |
7532 | | | 7532 | |
7533 | # Get the list of all files from the PLIST. | | 7533 | # Get the list of all files from the PLIST. |
7534 | my $all_files = {}; | | 7534 | my $all_files = {}; |
7535 | my $all_dirs = {}; | | 7535 | my $all_dirs = {}; |
7536 | my $extra_lines = []; | | 7536 | my $extra_lines = []; |
7537 | if (basename($fname) eq "PLIST.common_end") { | | 7537 | if (basename($fname) eq "PLIST.common_end") { |
7538 | my $common_lines = load_file(dirname($fname) . "/PLIST.common"); | | 7538 | my $common_lines = load_file(dirname($fname) . "/PLIST.common"); |
7539 | if ($common_lines) { | | 7539 | if ($common_lines) { |
7540 | $extra_lines = $common_lines; | | 7540 | $extra_lines = $common_lines; |
7541 | } | | 7541 | } |
7542 | } | | 7542 | } |
7543 | | | 7543 | |
7544 | foreach my $line (@{$extra_lines}, @{$lines}) { | | 7544 | foreach my $line (@{$extra_lines}, @{$lines}) { |
7545 | my $text = $line->text; | | 7545 | my $text = $line->text; |
7546 | | | 7546 | |
7547 | if ($text =~ m"\$\{([\w_]+)\}(.*)") { | | 7547 | if ($text =~ m"\$\{([\w_]+)\}(.*)") { |
7548 | if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { | | 7548 | if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { |
7549 | $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); | | 7549 | $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); |
7550 | $text = $2; | | 7550 | $text = $2; |
7551 | } | | 7551 | } |
7552 | } | | 7552 | } |
7553 | | | 7553 | |
7554 | if ($text =~ m"^[\w\$]") { | | 7554 | if ($text =~ m"^[\w\$]") { |
7555 | $all_files->{$text} = $line; | | 7555 | $all_files->{$text} = $line; |
7556 | my $dir = $text; | | 7556 | my $dir = $text; |
7557 | while ($dir =~ s,/[^/]+$,,) { | | 7557 | while ($dir =~ s,/[^/]+$,,) { |
7558 | $all_dirs->{$dir} = $line; | | 7558 | $all_dirs->{$dir} = $line; |
7559 | } | | 7559 | } |
7560 | } | | 7560 | } |
7561 | if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { | | 7561 | if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { |
7562 | my $dir = $1; | | 7562 | my $dir = $1; |
7563 | do { | | 7563 | do { |
7564 | $all_dirs->{$dir} = $line; | | 7564 | $all_dirs->{$dir} = $line; |
7565 | } while ($dir =~ s,/[^/]+$,,); | | 7565 | } while ($dir =~ s,/[^/]+$,,); |
7566 | } | | 7566 | } |
7567 | } | | 7567 | } |
7568 | | | 7568 | |
7569 | foreach my $line (@{$lines}) { | | 7569 | foreach my $line (@{$lines}) { |
7570 | my $text = $line->text; | | 7570 | my $text = $line->text; |
7571 | | | 7571 | |
7572 | if ($text =~ /\s$/) { | | 7572 | if ($text =~ /\s$/) { |
7573 | $line->log_error("pkgsrc does not support filenames ending in white-space."); | | 7573 | $line->log_error("pkgsrc does not support filenames ending in white-space."); |
7574 | $line->explain_error( | | 7574 | $line->explain_error( |
7575 | "Each character in the PLIST is relevant, even trailing white-space."); | | 7575 | "Each character in the PLIST is relevant, even trailing white-space."); |
7576 | } | | 7576 | } |
7577 | | | 7577 | |
7578 | # @foo directives. | | 7578 | # @foo directives. |
7579 | if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { | | 7579 | if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { |
7580 | my ($cmd, $arg) = ($1, $2); | | 7580 | my ($cmd, $arg) = ($1, $2); |
7581 | | | 7581 | |
7582 | if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { | | 7582 | if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { |
7583 | my ($rmdir, $rest) = ($1, $2); | | 7583 | my ($rmdir, $rest) = ($1, $2); |
7584 | if ($rest !~ m"(?:true|\$\{TRUE\})") { | | 7584 | if ($rest !~ m"(?:true|\$\{TRUE\})") { |
7585 | $line->log_warning("Please use \"\@dirrm\" instead of \"\@unexec rmdir\"."); | | 7585 | $line->log_warning("Please use \"\@dirrm\" instead of \"\@unexec rmdir\"."); |
7586 | } | | 7586 | } |
7587 | | | 7587 | |
7588 | } elsif (($cmd eq "exec" || $cmd eq "unexec")) { | | 7588 | } elsif (($cmd eq "exec" || $cmd eq "unexec")) { |
7589 | if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { | | 7589 | if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { |
7590 | $line->log_warning("\@exec/unexec install-info is deprecated."); | | 7590 | $line->log_warning("\@exec/unexec install-info is deprecated."); |
7591 | | | 7591 | |
7592 | } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { | | 7592 | } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { |
7593 | $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); | | 7593 | $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); |
7594 | } | | 7594 | } |
7595 | | | 7595 | |
7596 | } elsif ($cmd eq "comment") { | | 7596 | } elsif ($cmd eq "comment") { |
7597 | # nothing to do | | 7597 | # nothing to do |
7598 | | | 7598 | |
7599 | } elsif ($cmd eq "dirrm") { | | 7599 | } elsif ($cmd eq "dirrm") { |
7600 | my @ids = get_shared_dir_ids($line, $arg); | | 7600 | my @ids = get_shared_dir_ids($line, $arg); |
7601 | if (@ids == 0) { | | 7601 | if (@ids == 0) { |
7602 | # Nothing to do | | 7602 | # Nothing to do |
7603 | } elsif (@ids == 1) { | | 7603 | } elsif (@ids == 1) { |
7604 | $line->log_warning("Please add \"USE_DIRS+= $ids[0]\" to the package Makefile and remove this line."); | | 7604 | $line->log_warning("Please add \"USE_DIRS+= $ids[0]\" to the package Makefile and remove this line."); |
7605 | } else { | | 7605 | } else { |
7606 | my $s = join(" or ", map { "\"USE_DIRS+= $_\"" } @ids); | | 7606 | my $s = join(" or ", map { "\"USE_DIRS+= $_\"" } @ids); |
7607 | $line->log_warning("Please add $s to the package Makefile and remove this line."); | | 7607 | $line->log_warning("Please add $s to the package Makefile and remove this line."); |
7608 | } | | 7608 | } |
7609 | if (!exists($all_dirs->{$arg})) { | | 7609 | if (!exists($all_dirs->{$arg})) { |
7610 | $line->log_warning("The PLIST does not contain files for \"$arg\"."); | | 7610 | $line->log_warning("The PLIST does not contain files for \"$arg\"."); |
7611 | $line->explain_warning( | | 7611 | $line->explain_warning( |
7612 | "A package should only remove those directories that it created. When", | | 7612 | "A package should only remove those directories that it created. When", |
7613 | "there are no files in the directory, it is unlikely that the package", | | 7613 | "there are no files in the directory, it is unlikely that the package", |
7614 | "created the directory."); | | 7614 | "created the directory."); |
7615 | } | | 7615 | } |
7616 | | | 7616 | |
7617 | if ($pkgpath ne "graphics/hicolor-icon-theme" && $arg =~ m"^share/icons/hicolor(?:$|/)") { | | 7617 | if ($pkgpath ne "graphics/hicolor-icon-theme" && $arg =~ m"^share/icons/hicolor(?:$|/)") { |
7618 | $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line."); | | 7618 | $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line."); |
7619 | } | | 7619 | } |
7620 | } elsif ($cmd eq "imake-man") { | | 7620 | } elsif ($cmd eq "imake-man") { |
7621 | my (@args) = split(/\s+/, $arg); | | 7621 | my (@args) = split(/\s+/, $arg); |
7622 | if (@args != 3) { | | 7622 | if (@args != 3) { |
7623 | $line->log_warning("Invalid number of arguments for imake-man."); | | 7623 | $line->log_warning("Invalid number of arguments for imake-man."); |
7624 | } else { | | 7624 | } else { |
7625 | if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { | | 7625 | if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { |
7626 | warn_about_PLIST_imake_mannewsuffix($line); | | 7626 | warn_about_PLIST_imake_mannewsuffix($line); |
7627 | } | | 7627 | } |
7628 | } | | 7628 | } |
7629 | | | 7629 | |
7630 | } else { | | 7630 | } else { |
7631 | $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); | | 7631 | $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); |
7632 | } | | 7632 | } |
7633 | | | 7633 | |
7634 | # Pathnames. | | 7634 | # Pathnames. |
7635 | } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { | | 7635 | } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { |
7636 | my ($dirname, $basename) = ($1, $2); | | 7636 | my ($dirname, $basename) = ($1, $2); |
7637 | | | 7637 | |
7638 | if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { | | 7638 | if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { |
7639 | if (defined($last_file_seen)) { | | 7639 | if (defined($last_file_seen)) { |
7640 | if ($last_file_seen gt $text) { | | 7640 | if ($last_file_seen gt $text) { |
7641 | $line->log_warning("${text} should be sorted before ${last_file_seen}."); | | 7641 | $line->log_warning("${text} should be sorted before ${last_file_seen}."); |
7642 | } elsif ($last_file_seen eq $text) { | | 7642 | } elsif ($last_file_seen eq $text) { |