Sun Mar 2 08:39:01 2014 UTC ()
We can put any files in files/.


(obache)
diff -r1.862 -r1.863 pkgsrc/pkgtools/pkglint/files/pkglint.pl

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

--- pkgsrc/pkgtools/pkglint/files/Attic/pkglint.pl 2014/01/13 01:54:52 1.862
+++ pkgsrc/pkgtools/pkglint/files/Attic/pkglint.pl 2014/03/02 08:39:01 1.863
@@ -1,1001 +1,1001 @@ @@ -1,1001 +1,1001 @@
1#! @PERL@ 1#! @PERL@
2# $NetBSD: pkglint.pl,v 1.862 2014/01/13 01:54:52 cheusov Exp $ 2# $NetBSD: pkglint.pl,v 1.863 2014/03/02 08:39:01 obache Exp $
3# 3#
4 4
5# pkglint - static analyzer and checker for pkgsrc packages 5# pkglint - static analyzer and checker for pkgsrc packages
6# 6#
7# Written by: 7# Written by:
8# Roland Illig <rillig@NetBSD.org> 8# Roland Illig <rillig@NetBSD.org>
9# 9#
10# Based on work by: 10# Based on work by:
11# Hubert Feyrer <hubertf@NetBSD.org> 11# Hubert Feyrer <hubertf@NetBSD.org>
12# Thorsten Frueauf <frueauf@NetBSD.org> 12# Thorsten Frueauf <frueauf@NetBSD.org>
13# Thomas Klausner <wiz@NetBSD.org> 13# Thomas Klausner <wiz@NetBSD.org>
14# and others. 14# and others.
15# 15#
16# Based on FreeBSD's portlint by: 16# Based on FreeBSD's portlint by:
17# Jun-ichiro itojun Hagino <itojun@itojun.org> 17# Jun-ichiro itojun Hagino <itojun@itojun.org>
18# Yoshishige Arai <ryo2@on.rim.or.jp> 18# Yoshishige Arai <ryo2@on.rim.or.jp>
19# 19#
20# FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp 20# FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp
21# Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. 21# Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>.
22# All rights reserved. 22# All rights reserved.
23# Freely redistributable. Absolutely no warranty. 23# Freely redistributable. Absolutely no warranty.
24 24
25# To get an overview of the code, run: 25# To get an overview of the code, run:
26# sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl 26# sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl
27 27
28#========================================================================== 28#==========================================================================
29# Note: The @EXPORT clauses in the packages must be in a BEGIN block, 29# Note: The @EXPORT clauses in the packages must be in a BEGIN block,
30# because otherwise the names starting with an uppercase letter are not 30# because otherwise the names starting with an uppercase letter are not
31# recognized as subroutines but as file handles. 31# recognized as subroutines but as file handles.
32#========================================================================== 32#==========================================================================
33 33
34use strict; 34use strict;
35use warnings; 35use warnings;
36 36
37use PkgLint::Util; 37use PkgLint::Util;
38use PkgLint::Logging; 38use PkgLint::Logging;
39use PkgLint::SimpleMatch; 39use PkgLint::SimpleMatch;
40use PkgLint::Line; 40use PkgLint::Line;
41use PkgLint::FileUtil; 41use PkgLint::FileUtil;
42use PkgLint::Type; 42use PkgLint::Type;
43use PkgLint::VarUseContext; 43use PkgLint::VarUseContext;
44use PkgLint::SubstContext; 44use PkgLint::SubstContext;
45use PkgLint::CVS_Entry; 45use PkgLint::CVS_Entry;
46use PkgLint::Change; 46use PkgLint::Change;
47 47
48package pkglint; 48package pkglint;
49#========================================================================== 49#==========================================================================
50# This package contains the application-specific code of pkglint. 50# This package contains the application-specific code of pkglint.
51# Most subroutines in this package follow a strict naming convention: 51# Most subroutines in this package follow a strict naming convention:
52# 52#
53# The get_*() functions provide easy access to important non-trivial data 53# The get_*() functions provide easy access to important non-trivial data
54# structures that are loaded from external files and are therefore cached. 54# structures that are loaded from external files and are therefore cached.
55# 55#
56# The is_*() functions return a boolean value and have no side effects. 56# The is_*() functions return a boolean value and have no side effects.
57# 57#
58# The checkline_*() procedures check a single line for compliance with some 58# The checkline_*() procedures check a single line for compliance with some
59# rules. 59# rules.
60# 60#
61# The checklines_*() procedures check an array of lines for compliance. 61# The checklines_*() procedures check an array of lines for compliance.
62# Usually they make use of several checkline_*() procedures. 62# Usually they make use of several checkline_*() procedures.
63# 63#
64# The checkfile_*() procedures load a file and check the lines of that 64# The checkfile_*() procedures load a file and check the lines of that
65# file. Usually they make use of several checklines_*() and checkline_*() 65# file. Usually they make use of several checklines_*() and checkline_*()
66# procedures. 66# procedures.
67# 67#
68# The checkdir_*() procedures check the files of a directory and call 68# The checkdir_*() procedures check the files of a directory and call
69# checkfile_*() on them. 69# checkfile_*() on them.
70# 70#
71# Note: I have tried to order the subroutines so that there are no 71# Note: I have tried to order the subroutines so that there are no
72# back-references, that is, if you start reading the code from the top to 72# back-references, that is, if you start reading the code from the top to
73# the bottom you should not find a call to a subroutine you haven't yet 73# the bottom you should not find a call to a subroutine you haven't yet
74# seen. 74# seen.
75#========================================================================== 75#==========================================================================
76use strict; 76use strict;
77use warnings; 77use warnings;
78 78
79use Data::Dumper; 79use Data::Dumper;
80use Digest::SHA1; 80use Digest::SHA1;
81use Getopt::Long qw(:config no_ignore_case bundling require_order); 81use Getopt::Long qw(:config no_ignore_case bundling require_order);
82use Fcntl qw(:mode); 82use Fcntl qw(:mode);
83use File::Basename; 83use File::Basename;
84use File::stat; 84use File::stat;
85use Cwd; 85use Cwd;
86use pkgsrc::Dewey; 86use pkgsrc::Dewey;
87 87
88BEGIN { 88BEGIN {
89 import PkgLint::Util qw( 89 import PkgLint::Util qw(
90 array_to_hash assert 90 array_to_hash assert
91 false true dont_know doesnt_matter 91 false true dont_know doesnt_matter
92 normalize_pathname 92 normalize_pathname
93 ); 93 );
94 import PkgLint::Logging qw( 94 import PkgLint::Logging qw(
95 NO_FILE NO_LINE_NUMBER NO_LINES 95 NO_FILE NO_LINE_NUMBER NO_LINES
96 log_fatal log_error log_warning log_note log_debug 96 log_fatal log_error log_warning log_note log_debug
97 explain_error explain_warning explain_info 97 explain_error explain_warning explain_info
98 ); 98 );
99 import PkgLint::FileUtil qw( 99 import PkgLint::FileUtil qw(
100 load_file load_lines 100 load_file load_lines
101 save_autofix_changes 101 save_autofix_changes
102 ); 102 );
103 import PkgLint::Type qw( 103 import PkgLint::Type qw(
104 LK_NONE LK_INTERNAL LK_EXTERNAL 104 LK_NONE LK_INTERNAL LK_EXTERNAL
105 GUESSED NOT_GUESSED 105 GUESSED NOT_GUESSED
106 ); 106 );
107 import PkgLint::VarUseContext qw( 107 import PkgLint::VarUseContext qw(
108 VUC_TIME_UNKNOWN VUC_TIME_LOAD VUC_TIME_RUN 108 VUC_TIME_UNKNOWN VUC_TIME_LOAD VUC_TIME_RUN
109 VUC_TYPE_UNKNOWN 109 VUC_TYPE_UNKNOWN
110 VUC_SHELLWORD_UNKNOWN VUC_SHELLWORD_PLAIN VUC_SHELLWORD_DQUOT 110 VUC_SHELLWORD_UNKNOWN VUC_SHELLWORD_PLAIN VUC_SHELLWORD_DQUOT
111 VUC_SHELLWORD_SQUOT VUC_SHELLWORD_BACKT VUC_SHELLWORD_FOR 111 VUC_SHELLWORD_SQUOT VUC_SHELLWORD_BACKT VUC_SHELLWORD_FOR
112 VUC_EXTENT_UNKNOWN VUC_EXTENT_FULL VUC_EXTENT_WORD 112 VUC_EXTENT_UNKNOWN VUC_EXTENT_FULL VUC_EXTENT_WORD
113 VUC_EXTENT_WORD_PART 113 VUC_EXTENT_WORD_PART
114 ); 114 );
115} 115}
116 116
117# 117#
118# Buildtime configuration 118# Buildtime configuration
119# 119#
120 120
121use constant conf_distver => '@DISTVER@'; 121use constant conf_distver => '@DISTVER@';
122use constant conf_make => '@MAKE@'; 122use constant conf_make => '@MAKE@';
123use constant conf_datadir => '@DATADIR@'; 123use constant conf_datadir => '@DATADIR@';
124 124
125# 125#
126# Global variables that can be modified via command line options. 126# Global variables that can be modified via command line options.
127# 127#
128 128
129# The pkgsrc directory, relative to the current working directory of 129# The pkgsrc directory, relative to the current working directory of
130# pkglint. 130# pkglint.
131my $cwd_pkgsrcdir = undef; 131my $cwd_pkgsrcdir = undef;
132 132
133# The pkgsrc directory, relative to the directory that is currently 133# The pkgsrc directory, relative to the directory that is currently
134# checked. 134# checked.
135my $cur_pkgsrcdir = undef; 135my $cur_pkgsrcdir = undef;
136 136
137# 137#
138# Command Line Options 138# Command Line Options
139# 139#
140 140
141my $opt_check_ALTERNATIVES = true; 141my $opt_check_ALTERNATIVES = true;
142my $opt_check_bl3 = true; 142my $opt_check_bl3 = true;
143my $opt_check_DESCR = true; 143my $opt_check_DESCR = true;
144my $opt_check_distinfo = true; 144my $opt_check_distinfo = true;
145my $opt_check_extra = false; 145my $opt_check_extra = false;
146my $opt_check_global = false; 146my $opt_check_global = false;
147my $opt_check_INSTALL = true; 147my $opt_check_INSTALL = true;
148my $opt_check_Makefile = true; 148my $opt_check_Makefile = true;
149my $opt_check_MESSAGE = true; 149my $opt_check_MESSAGE = true;
150my $opt_check_mk = true; 150my $opt_check_mk = true;
151my $opt_check_patches = true; 151my $opt_check_patches = true;
152my $opt_check_PLIST = true; 152my $opt_check_PLIST = true;
153my (%checks) = ( 153my (%checks) = (
154 "ALTERNATIVES" => [\$opt_check_ALTERNATIVES, "check ALTERNATIVES files"], 154 "ALTERNATIVES" => [\$opt_check_ALTERNATIVES, "check ALTERNATIVES files"],
155 "bl3" => [\$opt_check_bl3, "check buildlink3 files"], 155 "bl3" => [\$opt_check_bl3, "check buildlink3 files"],
156 "DESCR" => [\$opt_check_DESCR, "check DESCR file"], 156 "DESCR" => [\$opt_check_DESCR, "check DESCR file"],
157 "distinfo" => [\$opt_check_distinfo, "check distinfo file"], 157 "distinfo" => [\$opt_check_distinfo, "check distinfo file"],
158 "extra" => [\$opt_check_extra, "check various additional files"], 158 "extra" => [\$opt_check_extra, "check various additional files"],
159 "global" => [\$opt_check_global, "inter-package checks"], 159 "global" => [\$opt_check_global, "inter-package checks"],
160 "INSTALL" => [\$opt_check_INSTALL, "check INSTALL and DEINSTALL scripts"], 160 "INSTALL" => [\$opt_check_INSTALL, "check INSTALL and DEINSTALL scripts"],
161 "Makefile" => [\$opt_check_Makefile, "check Makefiles"], 161 "Makefile" => [\$opt_check_Makefile, "check Makefiles"],
162 "MESSAGE" => [\$opt_check_MESSAGE, "check MESSAGE files"], 162 "MESSAGE" => [\$opt_check_MESSAGE, "check MESSAGE files"],
163 "mk" => [\$opt_check_mk, "check other .mk files"], 163 "mk" => [\$opt_check_mk, "check other .mk files"],
164 "patches" => [\$opt_check_patches, "check patches"], 164 "patches" => [\$opt_check_patches, "check patches"],
165 "PLIST" => [\$opt_check_PLIST, "check PLIST files"], 165 "PLIST" => [\$opt_check_PLIST, "check PLIST files"],
166); 166);
167 167
168my $opt_debug_include = false; 168my $opt_debug_include = false;
169my $opt_debug_misc = false; 169my $opt_debug_misc = false;
170my $opt_debug_patches = false; 170my $opt_debug_patches = false;
171my $opt_debug_quoting = false; 171my $opt_debug_quoting = false;
172my $opt_debug_shell = false; 172my $opt_debug_shell = false;
173my $opt_debug_tools = false; 173my $opt_debug_tools = false;
174my $opt_debug_trace = false; 174my $opt_debug_trace = false;
175my $opt_debug_unchecked = false; 175my $opt_debug_unchecked = false;
176my $opt_debug_unused = false; 176my $opt_debug_unused = false;
177my $opt_debug_vartypes = false; 177my $opt_debug_vartypes = false;
178my $opt_debug_varuse = false; 178my $opt_debug_varuse = false;
179my (%debug) = ( 179my (%debug) = (
180 "include" => [\$opt_debug_include, "included files"], 180 "include" => [\$opt_debug_include, "included files"],
181 "misc" => [\$opt_debug_misc, "all things that didn't fit elsewhere"], 181 "misc" => [\$opt_debug_misc, "all things that didn't fit elsewhere"],
182 "patches" => [\$opt_debug_patches, "the states of the patch parser"], 182 "patches" => [\$opt_debug_patches, "the states of the patch parser"],
183 "quoting" => [\$opt_debug_quoting, "additional information about quoting"], 183 "quoting" => [\$opt_debug_quoting, "additional information about quoting"],
184 "shell" => [\$opt_debug_shell, "the parsers for shell words and shell commands"], 184 "shell" => [\$opt_debug_shell, "the parsers for shell words and shell commands"],
185 "tools" => [\$opt_debug_tools, "the tools framework"], 185 "tools" => [\$opt_debug_tools, "the tools framework"],
186 "trace" => [\$opt_debug_trace, "follow subroutine calls"], 186 "trace" => [\$opt_debug_trace, "follow subroutine calls"],
187 "unchecked" => [\$opt_debug_unchecked, "show the current limitations of pkglint"], 187 "unchecked" => [\$opt_debug_unchecked, "show the current limitations of pkglint"],
188 "unused" => [\$opt_debug_unused, "unused variables"], 188 "unused" => [\$opt_debug_unused, "unused variables"],
189 "vartypes" => [\$opt_debug_vartypes, "additional type information"], 189 "vartypes" => [\$opt_debug_vartypes, "additional type information"],
190 "varuse" => [\$opt_debug_varuse, "contexts where variables are used"], 190 "varuse" => [\$opt_debug_varuse, "contexts where variables are used"],
191); 191);
192 192
193my $opt_warn_absname = true; 193my $opt_warn_absname = true;
194my $opt_warn_directcmd = true; 194my $opt_warn_directcmd = true;
195our $opt_warn_extra = false; # used by PkgLint::SubstContext 195our $opt_warn_extra = false; # used by PkgLint::SubstContext
196my $opt_warn_order = true; 196my $opt_warn_order = true;
197my $opt_warn_perm = false; 197my $opt_warn_perm = false;
198my $opt_warn_plist_depr = false; 198my $opt_warn_plist_depr = false;
199my $opt_warn_plist_sort = false; 199my $opt_warn_plist_sort = false;
200my $opt_warn_quoting = false; 200my $opt_warn_quoting = false;
201my $opt_warn_space = false; 201my $opt_warn_space = false;
202my $opt_warn_style = false; 202my $opt_warn_style = false;
203my $opt_warn_types = true; 203my $opt_warn_types = true;
204my $opt_warn_varorder = false; 204my $opt_warn_varorder = false;
205my (%warnings) = ( 205my (%warnings) = (
206 "absname" => [\$opt_warn_absname, "warn about use of absolute file names"], 206 "absname" => [\$opt_warn_absname, "warn about use of absolute file names"],
207 "directcmd" => [\$opt_warn_directcmd, "warn about use of direct command names instead of Make variables"], 207 "directcmd" => [\$opt_warn_directcmd, "warn about use of direct command names instead of Make variables"],
208 "extra" => [\$opt_warn_extra, "enable some extra warnings"], 208 "extra" => [\$opt_warn_extra, "enable some extra warnings"],
209 "order" => [\$opt_warn_order, "warn if Makefile entries are unordered"], 209 "order" => [\$opt_warn_order, "warn if Makefile entries are unordered"],
210 "perm" => [\$opt_warn_perm, "warn about unforeseen variable definition and use"], 210 "perm" => [\$opt_warn_perm, "warn about unforeseen variable definition and use"],
211 "plist-depr" => [\$opt_warn_plist_depr, "warn about deprecated paths in PLISTs"], 211 "plist-depr" => [\$opt_warn_plist_depr, "warn about deprecated paths in PLISTs"],
212 "plist-sort" => [\$opt_warn_plist_sort, "warn about unsorted entries in PLISTs"], 212 "plist-sort" => [\$opt_warn_plist_sort, "warn about unsorted entries in PLISTs"],
213 "quoting" => [\$opt_warn_quoting, "warn about quoting issues"], 213 "quoting" => [\$opt_warn_quoting, "warn about quoting issues"],
214 "space" => [\$opt_warn_space, "warn about inconsistent use of white-space"], 214 "space" => [\$opt_warn_space, "warn about inconsistent use of white-space"],
215 "style" => [\$opt_warn_style, "warn about stylistic issues"], 215 "style" => [\$opt_warn_style, "warn about stylistic issues"],
216 "types" => [\$opt_warn_types, "do some simple type checking in Makefiles"], 216 "types" => [\$opt_warn_types, "do some simple type checking in Makefiles"],
217 "varorder" => [\$opt_warn_varorder, "warn about the ordering of variables"], 217 "varorder" => [\$opt_warn_varorder, "warn about the ordering of variables"],
218); 218);
219 219
220my $opt_autofix = false; 220my $opt_autofix = false;
221my $opt_dumpmakefile = false; 221my $opt_dumpmakefile = false;
222my $opt_import = false; 222my $opt_import = false;
223my $opt_quiet = false; 223my $opt_quiet = false;
224my $opt_recursive = false; 224my $opt_recursive = false;
225my $opt_rcsidstring = "NetBSD"; 225my $opt_rcsidstring = "NetBSD";
226my (@options) = ( 226my (@options) = (
227 # [ usage-opt, usage-message, getopt-opt, getopt-action ] 227 # [ usage-opt, usage-message, getopt-opt, getopt-action ]
228 [ "-C{check,...}", "Enable or disable specific checks", 228 [ "-C{check,...}", "Enable or disable specific checks",
229 "check|C=s", 229 "check|C=s",
230 sub { 230 sub {
231 my ($opt, $val) = @_; 231 my ($opt, $val) = @_;
232 parse_multioption($val, \%checks); 232 parse_multioption($val, \%checks);
233 } ], 233 } ],
234 [ "-D{debug,...}", "Enable or disable debugging categories", 234 [ "-D{debug,...}", "Enable or disable debugging categories",
235 "debugging|D=s", 235 "debugging|D=s",
236 sub ($$) { 236 sub ($$) {
237 my ($opt, $val) = @_; 237 my ($opt, $val) = @_;
238 parse_multioption($val, \%debug); 238 parse_multioption($val, \%debug);
239 } ], 239 } ],
240 [ "-F|--autofix", "Try to automatically fix some errors (experimental)", 240 [ "-F|--autofix", "Try to automatically fix some errors (experimental)",
241 "autofix|F", \$opt_autofix ], 241 "autofix|F", \$opt_autofix ],
242 [ "-I|--dumpmakefile", "Dump the Makefile after parsing", 242 [ "-I|--dumpmakefile", "Dump the Makefile after parsing",
243 "dumpmakefile|I", \$opt_dumpmakefile ], 243 "dumpmakefile|I", \$opt_dumpmakefile ],
244 [ "-R|--rcsidstring", "Set the allowed RCS Id strings", 244 [ "-R|--rcsidstring", "Set the allowed RCS Id strings",
245 "rcsidstring|R=s", \$opt_rcsidstring ], 245 "rcsidstring|R=s", \$opt_rcsidstring ],
246 [ "-V|--version", "print the version number of pkglint", 246 [ "-V|--version", "print the version number of pkglint",
247 "version|V", 247 "version|V",
248 sub { 248 sub {
249 print(conf_distver . "\n"); 249 print(conf_distver . "\n");
250 exit(0); 250 exit(0);
251 } ], 251 } ],
252 [ "-W{warn,...}", "enable or disable specific warnings", 252 [ "-W{warn,...}", "enable or disable specific warnings",
253 "warning|W=s", 253 "warning|W=s",
254 sub { 254 sub {
255 my ($opt, $val) = @_; 255 my ($opt, $val) = @_;
256 parse_multioption($val, \%warnings); 256 parse_multioption($val, \%warnings);
257 } ], 257 } ],
258 [ "-e|--explain", "Explain the diagnostics or give further help", 258 [ "-e|--explain", "Explain the diagnostics or give further help",
259 "explain|e", sub { 259 "explain|e", sub {
260 PkgLint::Logging::set_explain(); 260 PkgLint::Logging::set_explain();
261 } ], 261 } ],
262 [ "-g|--gcc-output-format", "Mimic the gcc output format", 262 [ "-g|--gcc-output-format", "Mimic the gcc output format",
263 "gcc-output-format|g", 263 "gcc-output-format|g",
264 sub { 264 sub {
265 PkgLint::Logging::set_gcc_output_format(); 265 PkgLint::Logging::set_gcc_output_format();
266 } ], 266 } ],
267 [ "-h|--help", "print a detailed help message", 267 [ "-h|--help", "print a detailed help message",
268 "help|h", 268 "help|h",
269 sub { 269 sub {
270 help(*STDOUT, 0, 1); 270 help(*STDOUT, 0, 1);
271 } ], 271 } ],
272 [ "-i|--import", "Prepare the import of a wip package", 272 [ "-i|--import", "Prepare the import of a wip package",
273 "import|i", \$opt_import ], 273 "import|i", \$opt_import ],
274 # Note: This is intentionally undocumented. 274 # Note: This is intentionally undocumented.
275 [ "--pkgsrcdir", "Set the root directory of pkgsrc explicitly.", 275 [ "--pkgsrcdir", "Set the root directory of pkgsrc explicitly.",
276 "pkgsrcdir=s", \$cwd_pkgsrcdir ], 276 "pkgsrcdir=s", \$cwd_pkgsrcdir ],
277 [ "-q|--quiet", "Don't print a summary line when finishing", 277 [ "-q|--quiet", "Don't print a summary line when finishing",
278 "quiet|q", \$opt_quiet ], 278 "quiet|q", \$opt_quiet ],
279 [ "-r|--recursive", "Recursive---check subdirectories, too", 279 [ "-r|--recursive", "Recursive---check subdirectories, too",
280 "recursive|r", \$opt_recursive ], 280 "recursive|r", \$opt_recursive ],
281 [ "-s|--source", "Show the source lines together with diagnostics", 281 [ "-s|--source", "Show the source lines together with diagnostics",
282 "source|s", 282 "source|s",
283 sub { 283 sub {
284 PkgLint::Logging::set_show_source_flag(); 284 PkgLint::Logging::set_show_source_flag();
285 } ], 285 } ],
286); 286);
287 287
288our $program = $0; 288our $program = $0;
289 289
290# 290#
291# Commonly used regular expressions. 291# Commonly used regular expressions.
292# 292#
293 293
294use constant regex_dependency_lge => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d])+)[<>]=?(\d[^-*?\[\]]*)$"; 294use constant regex_dependency_lge => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d])+)[<>]=?(\d[^-*?\[\]]*)$";
295use constant regex_dependency_wildcard 295use constant regex_dependency_wildcard
296 => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d\[])+)-(?:\[0-9\]\*|\d[^-]*)$"; 296 => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d\[])+)-(?:\[0-9\]\*|\d[^-]*)$";
297use constant regex_gnu_configure_volatile_vars 297use constant regex_gnu_configure_volatile_vars
298 => qr"^(?:.*_)?(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$"; 298 => qr"^(?:.*_)?(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$";
299use constant regex_mk_comment => qr"^ *\s*#(.*)$"; 299use constant regex_mk_comment => qr"^ *\s*#(.*)$";
300use constant regex_mk_cond => qr"^\.(\s*)(if|ifdef|ifndef|else|elif|endif|for|endfor|undef)(?:\s+([^\s#][^#]*?))?\s*(?:#.*)?$"; 300use constant regex_mk_cond => qr"^\.(\s*)(if|ifdef|ifndef|else|elif|endif|for|endfor|undef)(?:\s+([^\s#][^#]*?))?\s*(?:#.*)?$";
301use constant regex_mk_dependency=> qr"^([^\s:]+(?:\s*[^\s:]+)*)(\s*):\s*([^#]*?)(?:\s*#.*)?$"; 301use constant regex_mk_dependency=> qr"^([^\s:]+(?:\s*[^\s:]+)*)(\s*):\s*([^#]*?)(?:\s*#.*)?$";
302use constant regex_mk_include => qr"^\.\s*(s?include)\s+\"([^\"]+)\"\s*(?:#.*)?$"; 302use constant regex_mk_include => qr"^\.\s*(s?include)\s+\"([^\"]+)\"\s*(?:#.*)?$";
303use constant regex_mk_sysinclude=> qr"^\.\s*s?include\s+<([^>]+)>\s*(?:#.*)?$"; 303use constant regex_mk_sysinclude=> qr"^\.\s*s?include\s+<([^>]+)>\s*(?:#.*)?$";
304use constant regex_mk_shellvaruse => qr"(?:^|[^\$])\$\$\{?(\w+)\}?"; # XXX: not perfect 304use constant regex_mk_shellvaruse => qr"(?:^|[^\$])\$\$\{?(\w+)\}?"; # XXX: not perfect
305use constant regex_pkgname => qr"^([\w\-.+]+)-(\d(?:\w|\.\d)*)$"; 305use constant regex_pkgname => qr"^([\w\-.+]+)-(\d(?:\w|\.\d)*)$";
306use constant regex_mk_shellcmd => qr"^\t(.*)$"; 306use constant regex_mk_shellcmd => qr"^\t(.*)$";
307use constant regex_rcs_conflict => qr"^(<<<<<<<|=======|>>>>>>>)"; 307use constant regex_rcs_conflict => qr"^(<<<<<<<|=======|>>>>>>>)";
308use constant regex_unresolved => qr"\$\{"; 308use constant regex_unresolved => qr"\$\{";
309use constant regex_validchars => qr"[\011\040-\176]"; 309use constant regex_validchars => qr"[\011\040-\176]";
310# Note: the following regular expression looks more complicated than 310# Note: the following regular expression looks more complicated than
311# necessary to avoid a stack overflow in the Perl interpreter. 311# necessary to avoid a stack overflow in the Perl interpreter.
312# The leading white-space may only consist of \040 characters, otherwise 312# The leading white-space may only consist of \040 characters, otherwise
313# the order of regex_varassign and regex_mk_shellcmd becomes important. 313# the order of regex_varassign and regex_mk_shellcmd becomes important.
314use constant regex_varassign => qr"^ *([-*+A-Z_a-z0-9.\${}\[]+?)\s*(=|\?=|\+=|:=|!=)\s*((?:[^\\#\s]+|\s+?|(?:\\#)+|\\)*?)(?:\s*(#.*))?$"; 314use constant regex_varassign => qr"^ *([-*+A-Z_a-z0-9.\${}\[]+?)\s*(=|\?=|\+=|:=|!=)\s*((?:[^\\#\s]+|\s+?|(?:\\#)+|\\)*?)(?:\s*(#.*))?$";
315use constant regex_sh_varassign => qr"^([A-Z_a-z][0-9A-Z_a-z]*)="; 315use constant regex_sh_varassign => qr"^([A-Z_a-z][0-9A-Z_a-z]*)=";
316 316
317# The following "constants" are often used in contexts where 317# The following "constants" are often used in contexts where
318# interpolation comes handy, so they are variables. Nevertheless they 318# interpolation comes handy, so they are variables. Nevertheless they
319# are not modified. 319# are not modified.
320 320
321# This regular expression cannot parse all kinds of shell programs, but 321# This regular expression cannot parse all kinds of shell programs, but
322# it will catch almost all shell programs that are portable enough to be 322# it will catch almost all shell programs that are portable enough to be
323# used in pkgsrc. 323# used in pkgsrc.
324my $regex_shellword = qr"\s*( 324my $regex_shellword = qr"\s*(
325 \#.* # shell comment 325 \#.* # shell comment
326 | 326 |
327 (?: '[^']*' # single quoted string 327 (?: '[^']*' # single quoted string
328 | \"(?:\\.|[^\"\\])*\" # double quoted string 328 | \"(?:\\.|[^\"\\])*\" # double quoted string
329 | \`[^\`]*\` # backticks string 329 | \`[^\`]*\` # backticks string
330 | \\\$\$ # an escaped dollar sign 330 | \\\$\$ # an escaped dollar sign
331 | \\[^\$] # other escaped characters 331 | \\[^\$] # other escaped characters
332 | \$[\w_] # one-character make(1) variable 332 | \$[\w_] # one-character make(1) variable
333 | \$\{[^{}]+\} # make(1) variable 333 | \$\{[^{}]+\} # make(1) variable
334 | \$\([^()]+\) # make(1) variable, $(...) 334 | \$\([^()]+\) # make(1) variable, $(...)
335 | \$[/\@<^] # special make(1) variables 335 | \$[/\@<^] # special make(1) variables
336 | \$\$[0-9A-Z_a-z]+ # shell variable 336 | \$\$[0-9A-Z_a-z]+ # shell variable
337 | \$\$[\#?@] # special shell variables 337 | \$\$[\#?@] # special shell variables
338 | \$\$\$\$ # the special pid shell variable 338 | \$\$\$\$ # the special pid shell variable
339 | \$\$\{[0-9A-Z_a-z]+\} # shell variable in braces 339 | \$\$\{[0-9A-Z_a-z]+\} # shell variable in braces
340 | \$\$\( # POSIX-style backticks replacement 340 | \$\$\( # POSIX-style backticks replacement
341 | [^\(\)'\"\\\s;&\|<>\`\$] # non-special character 341 | [^\(\)'\"\\\s;&\|<>\`\$] # non-special character
342 | \$\{[^\s\"'`]+ # HACK: nested make(1) variables 342 | \$\{[^\s\"'`]+ # HACK: nested make(1) variables
343 )+ | ;;? | &&? | \|\|? | \( | \) | >& | <<? | >>? | \#.*)"sx; 343 )+ | ;;? | &&? | \|\|? | \( | \) | >& | <<? | >>? | \#.*)"sx;
344my $regex_varname = qr"(?:[-*+.0-9A-Z_a-z{}\[]+|\$\{[\w_]+\})+"; 344my $regex_varname = qr"(?:[-*+.0-9A-Z_a-z{}\[]+|\$\{[\w_]+\})+";
345my $regex_pkgbase = qr"(?:[+.0-9A-Z_a-z]|-[A-Z_a-z])+"; 345my $regex_pkgbase = qr"(?:[+.0-9A-Z_a-z]|-[A-Z_a-z])+";
346my $regex_pkgversion = qr"\d(?:\w|\.\d)*"; 346my $regex_pkgversion = qr"\d(?:\w|\.\d)*";
347 347
348# 348#
349# Commonly used explanations for diagnostics. 349# Commonly used explanations for diagnostics.
350# 350#
351 351
352use constant expl_relative_dirs => ( 352use constant expl_relative_dirs => (
353 "Directories in the form \"../../category/package\" make it easier to", 353 "Directories in the form \"../../category/package\" make it easier to",
354 "move a package around in pkgsrc, for example from pkgsrc-wip to the", 354 "move a package around in pkgsrc, for example from pkgsrc-wip to the",
355 "main pkgsrc repository."); 355 "main pkgsrc repository.");
356 356
357# 357#
358# Global variables. 358# Global variables.
359# 359#
360 360
361my $current_dir; # The currently checked directory. 361my $current_dir; # The currently checked directory.
362my $is_wip; # Is the current directory from pkgsrc-wip? 362my $is_wip; # Is the current directory from pkgsrc-wip?
363my $is_internal; # Is the current item from the infrastructure? 363my $is_internal; # Is the current item from the infrastructure?
364 364
365# 365#
366# Variables for inter-package checks. 366# Variables for inter-package checks.
367# 367#
368 368
369my $ipc_distinfo; # Maps "$alg:$fname" => "checksum". 369my $ipc_distinfo; # Maps "$alg:$fname" => "checksum".
370my %ipc_used_licenses; # { license name => true } 370my %ipc_used_licenses; # { license name => true }
371my $ipc_checking_root_recursively; # For checking unused licenses 371my $ipc_checking_root_recursively; # For checking unused licenses
372 372
373# Context of the package that is currently checked. 373# Context of the package that is currently checked.
374my $pkgpath; # The relative path to the package within PKGSRC 374my $pkgpath; # The relative path to the package within PKGSRC
375my $pkgdir; # PKGDIR from the package Makefile 375my $pkgdir; # PKGDIR from the package Makefile
376my $filesdir; # FILESDIR from the package Makefile 376my $filesdir; # FILESDIR from the package Makefile
377my $patchdir; # PATCHDIR from the package Makefile 377my $patchdir; # PATCHDIR from the package Makefile
378my $distinfo_file; # DISTINFO_FILE from the package Makefile 378my $distinfo_file; # DISTINFO_FILE from the package Makefile
379my $effective_pkgname; # PKGNAME or DISTNAME from the package Makefile 379my $effective_pkgname; # PKGNAME or DISTNAME from the package Makefile
380my $effective_pkgbase; # The effective PKGNAME without the version 380my $effective_pkgbase; # The effective PKGNAME without the version
381my $effective_pkgversion; # The version part of the effective PKGNAME 381my $effective_pkgversion; # The version part of the effective PKGNAME
382my $effective_pkgname_line; # The origin of the three effective_* values 382my $effective_pkgname_line; # The origin of the three effective_* values
383my $seen_bsd_prefs_mk; # Has bsd.prefs.mk already been included? 383my $seen_bsd_prefs_mk; # Has bsd.prefs.mk already been included?
384 384
385my $pkgctx_vardef; # { varname => line } 385my $pkgctx_vardef; # { varname => line }
386my $pkgctx_varuse; # { varname => line } 386my $pkgctx_varuse; # { varname => line }
387my $pkgctx_bl3; # { buildlink3.mk name => line } (contains 387my $pkgctx_bl3; # { buildlink3.mk name => line } (contains
388 # only buildlink3.mk files that are directly 388 # only buildlink3.mk files that are directly
389 # included) 389 # included)
390my $pkgctx_plist_subst_cond; # { varname => 1 } list of all variables 390my $pkgctx_plist_subst_cond; # { varname => 1 } list of all variables
391 # that are used as conditionals (@comment 391 # that are used as conditionals (@comment
392 # or nothing) in PLISTs. 392 # or nothing) in PLISTs.
393my $pkgctx_included; # { fname => line } 393my $pkgctx_included; # { fname => line }
394my $seen_Makefile_common; # Does the package have any .includes? 394my $seen_Makefile_common; # Does the package have any .includes?
395 395
396# Context of the Makefile that is currently checked. 396# Context of the Makefile that is currently checked.
397my $mkctx_for_variables; # The variables currently used in .for loops 397my $mkctx_for_variables; # The variables currently used in .for loops
398my $mkctx_indentations; # Indentation depth of preprocessing directives 398my $mkctx_indentations; # Indentation depth of preprocessing directives
399my $mkctx_target; # Current make(1) target 399my $mkctx_target; # Current make(1) target
400my $mkctx_vardef; # { varname => line } for all variables that 400my $mkctx_vardef; # { varname => line } for all variables that
401 # are defined in the current file 401 # are defined in the current file
402my $mkctx_varuse; # { varname => line } for all variables 402my $mkctx_varuse; # { varname => line } for all variables
403 # that are used in the current file 403 # that are used in the current file
404my $mkctx_build_defs; # Set of variables that are registered in 404my $mkctx_build_defs; # Set of variables that are registered in
405 # BUILD_DEFS, to assure that all user-defined 405 # BUILD_DEFS, to assure that all user-defined
406 # variables are added to it. 406 # variables are added to it.
407my $mkctx_plist_vars; # The same for PLIST_VARS. 407my $mkctx_plist_vars; # The same for PLIST_VARS.
408my $mkctx_tools; # Set of tools that are declared to be used. 408my $mkctx_tools; # Set of tools that are declared to be used.
409 409
410my @todo_items; # The list of directory entries that still need 410my @todo_items; # The list of directory entries that still need
411 # to be checked. Mostly relevant with 411 # to be checked. Mostly relevant with
412 # --recursive. 412 # --recursive.
413 413
414# 414#
415# Command line parsing and handling. 415# Command line parsing and handling.
416# 416#
417 417
418sub help($$$) { 418sub help($$$) {
419 my ($out, $exitval, $show_all) = @_; 419 my ($out, $exitval, $show_all) = @_;
420 my ($prog) = (basename($program, '.pl')); 420 my ($prog) = (basename($program, '.pl'));
421 print $out ("usage: $prog [options] [package_directory]\n\n"); 421 print $out ("usage: $prog [options] [package_directory]\n\n");
422 422
423 my (@option_table) = (); 423 my (@option_table) = ();
424 foreach my $opt (@options) { 424 foreach my $opt (@options) {
425 push(@option_table, [" ", $opt->[0], $opt->[1]]); 425 push(@option_table, [" ", $opt->[0], $opt->[1]]);
426 } 426 }
427 print $out ("options:\n"); 427 print $out ("options:\n");
428 PkgLint::Util::print_table($out, \@option_table); 428 PkgLint::Util::print_table($out, \@option_table);
429 print $out ("\n"); 429 print $out ("\n");
430 430
431 if (!$show_all) { 431 if (!$show_all) {
432 exit($exitval); 432 exit($exitval);
433 } 433 }
434 434
435 my $categories = [ 435 my $categories = [
436 # options, leading text,  436 # options, leading text,
437 [ \%checks, "checks", "check" ], 437 [ \%checks, "checks", "check" ],
438 [ \%debug, "debugging options", "debug" ], 438 [ \%debug, "debugging options", "debug" ],
439 [ \%warnings, "warnings", "warning" ], 439 [ \%warnings, "warnings", "warning" ],
440 ]; 440 ];
441 foreach my $category (@{$categories}) { 441 foreach my $category (@{$categories}) {
442 my ($options, $leading, $name) = (@{$category}); 442 my ($options, $leading, $name) = (@{$category});
443 my $table = [ 443 my $table = [
444 [" ", "all", "", "enable all ".$category->[1]], 444 [" ", "all", "", "enable all ".$category->[1]],
445 [" ", "none", "", "disable all ".$category->[1]], 445 [" ", "none", "", "disable all ".$category->[1]],
446 ]; 446 ];
447 447
448 foreach my $opt (sort keys %{$options}) { 448 foreach my $opt (sort keys %{$options}) {
449 push(@{$table}, [ " ", $opt, 449 push(@{$table}, [ " ", $opt,
450 (${$options->{$opt}->[0]} ? "(enabled)" : "(disabled)"), 450 (${$options->{$opt}->[0]} ? "(enabled)" : "(disabled)"),
451 $options->{$opt}->[1]]); 451 $options->{$opt}->[1]]);
452 } 452 }
453 453
454 print $out ("${leading}: (use \"${name}\" to enable, \"no-${name}\" to disable)\n"); 454 print $out ("${leading}: (use \"${name}\" to enable, \"no-${name}\" to disable)\n");
455 PkgLint::Util::print_table($out, $table); 455 PkgLint::Util::print_table($out, $table);
456 print $out ("\n"); 456 print $out ("\n");
457 } 457 }
458 458
459 exit($exitval); 459 exit($exitval);
460} 460}
461 461
462sub parse_multioption($$) { 462sub parse_multioption($$) {
463 my ($value, $optdefs) = @_; 463 my ($value, $optdefs) = @_;
464 foreach my $opt (split(qr",", $value)) { 464 foreach my $opt (split(qr",", $value)) {
465 if ($opt eq "none") { 465 if ($opt eq "none") {
466 foreach my $key (keys %{$optdefs}) { 466 foreach my $key (keys %{$optdefs}) {
467 ${$optdefs->{$key}->[0]} = false; 467 ${$optdefs->{$key}->[0]} = false;
468 } 468 }
469 469
470 } elsif ($opt eq "all") { 470 } elsif ($opt eq "all") {
471 foreach my $key (keys %{$optdefs}) { 471 foreach my $key (keys %{$optdefs}) {
472 ${$optdefs->{$key}->[0]} = true; 472 ${$optdefs->{$key}->[0]} = true;
473 } 473 }
474 474
475 } else { 475 } else {
476 my ($value) = (($opt =~ s/^no-//) ? false : true); 476 my ($value) = (($opt =~ s/^no-//) ? false : true);
477 if (exists($optdefs->{$opt})) { 477 if (exists($optdefs->{$opt})) {
478 ${$optdefs->{$opt}->[0]} = $value; 478 ${$optdefs->{$opt}->[0]} = $value;
479 } else { 479 } else {
480 print STDERR ("Invalid option: ${opt}\n"); 480 print STDERR ("Invalid option: ${opt}\n");
481 help(*STDERR, 1, 0); 481 help(*STDERR, 1, 0);
482 } 482 }
483 } 483 }
484 } 484 }
485} 485}
486 486
487sub parse_command_line() { 487sub parse_command_line() {
488 my (%options); 488 my (%options);
489 489
490 foreach my $opt (@options) { 490 foreach my $opt (@options) {
491 $options{$opt->[2]} = $opt->[3]; 491 $options{$opt->[2]} = $opt->[3];
492 } 492 }
493 493
494 { 494 {
495 local $SIG{__WARN__} = sub {}; 495 local $SIG{__WARN__} = sub {};
496 if (!GetOptions(%options)) { 496 if (!GetOptions(%options)) {
497 help(*STDERR, 1, false); 497 help(*STDERR, 1, false);
498 } 498 }
499 } 499 }
500} 500}
501 501
502# 502#
503# Caching subroutines. 503# Caching subroutines.
504# 504#
505 505
506# The get_regex_plurals() function returns a regular expression that 506# The get_regex_plurals() function returns a regular expression that
507# matches for all make(1) variable names that are considered lists 507# matches for all make(1) variable names that are considered lists
508# of something. 508# of something.
509# 509#
510# Rationale: 510# Rationale:
511# 511#
512# The pkglint author thinks that variables containing lists of things 512# The pkglint author thinks that variables containing lists of things
513# should have a name indicating some plural form. Sadly, there are other 513# should have a name indicating some plural form. Sadly, there are other
514# reasons like backwards compatibility and other developer's 514# reasons like backwards compatibility and other developer's
515# expectations that make changes to most of the following variables 515# expectations that make changes to most of the following variables
516# highly unlikely. 516# highly unlikely.
517my $get_regex_plurals_value = undef; 517my $get_regex_plurals_value = undef;
518sub get_regex_plurals() { 518sub get_regex_plurals() {
519 519
520 if (defined($get_regex_plurals_value)) { 520 if (defined($get_regex_plurals_value)) {
521 return $get_regex_plurals_value; 521 return $get_regex_plurals_value;
522 } 522 }
523 523
524 my @plurals_ok = qw( 524 my @plurals_ok = qw(
525 .*S 525 .*S
526 .*LIST 526 .*LIST
527 .*_AWK 527 .*_AWK
528 .*_ENV 528 .*_ENV
529 .*_REQD 529 .*_REQD
530 .*_SED 530 .*_SED
531 .*_SKIP 531 .*_SKIP
532 BUILDLINK_LDADD 532 BUILDLINK_LDADD
533 COMMENT 533 COMMENT
534 EXTRACT_ONLY 534 EXTRACT_ONLY
535 FETCH_MESSAGE 535 FETCH_MESSAGE
536 GENERATE_PLIST 536 GENERATE_PLIST
537 PLIST_CAT 537 PLIST_CAT
538 PLIST_PRE 538 PLIST_PRE
539 PREPEND_PATH 539 PREPEND_PATH
540 ); 540 );
541 my @plurals_missing_an_s = qw( 541 my @plurals_missing_an_s = qw(
542 .*_OVERRIDE 542 .*_OVERRIDE
543 .*_PREREQ 543 .*_PREREQ
544 .*_SRC 544 .*_SRC
545 .*_SUBST 545 .*_SUBST
546 .*_TARGET 546 .*_TARGET
547 .*_TMPL 547 .*_TMPL
548 BUILDLINK_DEPMETHOD 548 BUILDLINK_DEPMETHOD
549 BUILDLINK_TRANSFORM 549 BUILDLINK_TRANSFORM
550 EVAL_PREFIX 550 EVAL_PREFIX
551 INTERACTIVE_STAGE 551 INTERACTIVE_STAGE
552 LICENSE 552 LICENSE
553 MASTER_SITE_.* 553 MASTER_SITE_.*
554 MASTER_SORT_REGEX 554 MASTER_SORT_REGEX
555 NOT_FOR_COMPILER 555 NOT_FOR_COMPILER
556 NOT_FOR_PLATFORM 556 NOT_FOR_PLATFORM
557 ONLY_FOR_COMPILER 557 ONLY_FOR_COMPILER
558 ONLY_FOR_PLATFORM 558 ONLY_FOR_PLATFORM
559 PERL5_PACKLIST 559 PERL5_PACKLIST
560 PKG_FAIL_REASON 560 PKG_FAIL_REASON
561 PKG_SKIP_REASON 561 PKG_SKIP_REASON
562 ); 562 );
563 my @plurals_reluctantly_accepted = qw( 563 my @plurals_reluctantly_accepted = qw(
564 CRYPTO 564 CRYPTO
565 DEINSTALL_TEMPLATE 565 DEINSTALL_TEMPLATE
566 FIX_RPATH 566 FIX_RPATH
567 INSTALL_TEMPLATE 567 INSTALL_TEMPLATE
568 PYTHON_VERSIONS_INCOMPATIBLE 568 PYTHON_VERSIONS_INCOMPATIBLE
569 REPLACE_INTERPRETER 569 REPLACE_INTERPRETER
570 REPLACE_PERL 570 REPLACE_PERL
571 REPLACE_RUBY 571 REPLACE_RUBY
572 RESTRICTED 572 RESTRICTED
573 SITES_.* 573 SITES_.*
574 TOOLS_ALIASES\.* 574 TOOLS_ALIASES\.*
575 TOOLS_BROKEN 575 TOOLS_BROKEN
576 TOOLS_CREATE 576 TOOLS_CREATE
577 TOOLS_GNU_MISSING 577 TOOLS_GNU_MISSING
578 TOOLS_NOOP 578 TOOLS_NOOP
579 ); 579 );
580 my $plurals = join("|", 580 my $plurals = join("|",
581 @plurals_ok, 581 @plurals_ok,
582 @plurals_missing_an_s, 582 @plurals_missing_an_s,
583 @plurals_reluctantly_accepted 583 @plurals_reluctantly_accepted
584 ); 584 );
585 585
586 $get_regex_plurals_value = qr"^(?:${plurals})$"; 586 $get_regex_plurals_value = qr"^(?:${plurals})$";
587 return $get_regex_plurals_value; 587 return $get_regex_plurals_value;
588} 588}
589 589
590# 590#
591# Loading pkglint-specific data from files. 591# Loading pkglint-specific data from files.
592# 592#
593 593
594# The symbol table for ACL definitions maps ACL names to ACLs. 594# The symbol table for ACL definitions maps ACL names to ACLs.
595my $acl_definitions = {}; 595my $acl_definitions = {};
596 596
597sub parse_acls($$) { 597sub parse_acls($$) {
598 my ($line, $acltext) = @_; 598 my ($line, $acltext) = @_;
599 my ($acls); 599 my ($acls);
600 600
601 use constant ACL_shortcuts => { 601 use constant ACL_shortcuts => {
602 "b" => qr"(?:^|/)buildlink3\.mk$", 602 "b" => qr"(?:^|/)buildlink3\.mk$",
603 "c" => qr"(?:^|/)Makefile\.common$", 603 "c" => qr"(?:^|/)Makefile\.common$",
604 "h" => qr"(?:^|/)hacks\.mk$", 604 "h" => qr"(?:^|/)hacks\.mk$",
605 "m" => qr"(?:^|/)Makefile$", 605 "m" => qr"(?:^|/)Makefile$",
606 "o" => qr"(?:^|/)options\.mk$", 606 "o" => qr"(?:^|/)options\.mk$",
607 }; 607 };
608 608
609 my $regex_acl_entry = qr"^(?: 609 my $regex_acl_entry = qr"^(?:
610 \$([\w_]+) # $acl_name 610 \$([\w_]+) # $acl_name
611 | ([\w.*]+|_):([adpsu]*) # file*mask:perms 611 | ([\w.*]+|_):([adpsu]*) # file*mask:perms
612 ) (?:\,\s*|$)"x; 612 ) (?:\,\s*|$)"x;
613 613
614 if (!defined($acltext)) { 614 if (!defined($acltext)) {
615 return undef; 615 return undef;
616 } 616 }
617 617
618 $acls = []; 618 $acls = [];
619 while ($acltext =~ s,$regex_acl_entry,,) { 619 while ($acltext =~ s,$regex_acl_entry,,) {
620 my ($acldef, $subject, $perms) = ($1, $2, $3); 620 my ($acldef, $subject, $perms) = ($1, $2, $3);
621 621
622 if (defined($acldef)) { 622 if (defined($acldef)) {
623 if (!exists($acl_definitions->{$acldef})) { 623 if (!exists($acl_definitions->{$acldef})) {
624 $line->log_fatal("ACL definition ${acldef} not found."); 624 $line->log_fatal("ACL definition ${acldef} not found.");
625 } else { 625 } else {
626 push(@{$acls}, @{$acl_definitions->{$acldef}}); 626 push(@{$acls}, @{$acl_definitions->{$acldef}});
627 } 627 }
628 628
629 } else { 629 } else {
630 # Transform $subject to a regular expression. 630 # Transform $subject to a regular expression.
631 $subject =~ s/\./[.]/g; 631 $subject =~ s/\./[.]/g;
632 $subject =~ s/\*/.*/g; 632 $subject =~ s/\*/.*/g;
633 633
634 push(@{$acls}, [exists(ACL_shortcuts->{$subject}) ? ACL_shortcuts->{$subject} : qr"(?:^|/)${subject}$", $perms]); 634 push(@{$acls}, [exists(ACL_shortcuts->{$subject}) ? ACL_shortcuts->{$subject} : qr"(?:^|/)${subject}$", $perms]);
635 } 635 }
636 } 636 }
637 if ($acltext ne "") { 637 if ($acltext ne "") {
638 $line->log_fatal("Invalid ACL: ${acltext}."); 638 $line->log_fatal("Invalid ACL: ${acltext}.");
639 } 639 }
640 640
641 return $acls; 641 return $acls;
642} 642}
643 643
644my $get_vartypes_basictypes_result = undef; 644my $get_vartypes_basictypes_result = undef;
645sub get_vartypes_basictypes() { 645sub get_vartypes_basictypes() {
646 if (defined($get_vartypes_basictypes_result)) { 646 if (defined($get_vartypes_basictypes_result)) {
647 return $get_vartypes_basictypes_result; 647 return $get_vartypes_basictypes_result;
648 } 648 }
649 649
650 my $lines = load_file($program); 650 my $lines = load_file($program);
651 my $types = {}; 651 my $types = {};
652 assert($lines, "Couldn't load pkglint.pl from $program"); 652 assert($lines, "Couldn't load pkglint.pl from $program");
653 foreach my $line (@$lines) { 653 foreach my $line (@$lines) {
654 if ($line->text =~ m"^\s+(\w+) => sub \{$") { 654 if ($line->text =~ m"^\s+(\w+) => sub \{$") {
655 # XXX lookup in %type_dispatch instead 655 # XXX lookup in %type_dispatch instead
656 $types->{$1} = 1; 656 $types->{$1} = 1;
657 } 657 }
658 } 658 }
659 return ($get_vartypes_basictypes_result = $types); 659 return ($get_vartypes_basictypes_result = $types);
660} 660}
661 661
662my $get_vartypes_map_result = undef; 662my $get_vartypes_map_result = undef;
663sub get_vartypes_map() { 663sub get_vartypes_map() {
664 my ($fname, $vartypes); 664 my ($fname, $vartypes);
665 665
666 if (defined($get_vartypes_map_result)) { 666 if (defined($get_vartypes_map_result)) {
667 return $get_vartypes_map_result; 667 return $get_vartypes_map_result;
668 } 668 }
669 669
670 use constant re_acl_def => qr"^ 670 use constant re_acl_def => qr"^
671 acl \s+ 671 acl \s+
672 (\w+) \s+ # ACL name 672 (\w+) \s+ # ACL name
673 = \s+ 673 = \s+
674 \[ ([^\]]*) \] # ACL value 674 \[ ([^\]]*) \] # ACL value
675 (?:\s*\#.*)? # optional comment 675 (?:\s*\#.*)? # optional comment
676 $"x; 676 $"x;
677 677
678 use constant re_vartypedef => qr"^ 678 use constant re_vartypedef => qr"^
679 ([\w\d_.]+?) # $1 = variable name 679 ([\w\d_.]+?) # $1 = variable name
680 (\*|\.\*|) \s+ # $2 = parameterized? 680 (\*|\.\*|) \s+ # $2 = parameterized?
681 (?:(InternalList|List) \s+ of \s+)? # $3 ?= kind of list 681 (?:(InternalList|List) \s+ of \s+)? # $3 ?= kind of list
682 (?:([\w\d_]+) # $4 ?= basic type 682 (?:([\w\d_]+) # $4 ?= basic type
683 | \{\s*([\w\d_+,\-.\s]+?)\s*\}) # $5 ?= enumeration values 683 | \{\s*([\w\d_+,\-.\s]+?)\s*\}) # $5 ?= enumeration values
684 (?:\s+ \[ ([^\]]*) \])? # $6 ?= optional ACL 684 (?:\s+ \[ ([^\]]*) \])? # $6 ?= optional ACL
685 (?:\s*\#.*)? # $7 ?= optional comment 685 (?:\s*\#.*)? # $7 ?= optional comment
686 $"x; 686 $"x;
687 687
688 $fname = conf_datadir."/makevars.map"; 688 $fname = conf_datadir."/makevars.map";
689 $vartypes = {}; 689 $vartypes = {};
690 690
691 if ((my $lines = load_lines($fname, true))) { 691 if ((my $lines = load_lines($fname, true))) {
692 foreach my $line (@{$lines}) { 692 foreach my $line (@{$lines}) {
693 if ($line->text =~ m"^(?:#.*|\s*)$") { 693 if ($line->text =~ m"^(?:#.*|\s*)$") {
694 # ignore empty and comment lines 694 # ignore empty and comment lines
695 695
696 } elsif ($line->text =~ re_acl_def) { 696 } elsif ($line->text =~ re_acl_def) {
697 my ($aclname, $aclvalue) = ($1, $2); 697 my ($aclname, $aclvalue) = ($1, $2);
698 698
699 $acl_definitions->{$aclname} = parse_acls($line, $aclvalue); 699 $acl_definitions->{$aclname} = parse_acls($line, $aclvalue);
700 700
701 } elsif ($line->text =~ re_vartypedef) { 701 } elsif ($line->text =~ re_vartypedef) {
702 my ($varname, $par, $kind_of_list_text, $typename, $enums, $acltext) = ($1, $2, $3, $4, $5, $6); 702 my ($varname, $par, $kind_of_list_text, $typename, $enums, $acltext) = ($1, $2, $3, $4, $5, $6);
703 my $kind_of_list = !defined($kind_of_list_text) ? LK_NONE 703 my $kind_of_list = !defined($kind_of_list_text) ? LK_NONE
704 : ($kind_of_list_text eq "List") ? LK_EXTERNAL 704 : ($kind_of_list_text eq "List") ? LK_EXTERNAL
705 : LK_INTERNAL; 705 : LK_INTERNAL;
706 706
707 if (defined($typename) && !exists(get_vartypes_basictypes()->{$typename})) { 707 if (defined($typename) && !exists(get_vartypes_basictypes()->{$typename})) {
708 $line->log_fatal("Unknown basic type \"$typename\" for variable $varname. " 708 $line->log_fatal("Unknown basic type \"$typename\" for variable $varname. "
709 . "Valid basic types are " 709 . "Valid basic types are "
710 . join(", ", sort keys %{get_vartypes_basictypes()}) 710 . join(", ", sort keys %{get_vartypes_basictypes()})
711 . "."); 711 . ".");
712 } 712 }
713 713
714 my $basic_type = defined($enums) 714 my $basic_type = defined($enums)
715 ? array_to_hash(split(qr"\s+", $enums)) 715 ? array_to_hash(split(qr"\s+", $enums))
716 : $typename; 716 : $typename;
717 my $type = PkgLint::Type->new($kind_of_list, $basic_type, parse_acls($line, $acltext), NOT_GUESSED); 717 my $type = PkgLint::Type->new($kind_of_list, $basic_type, parse_acls($line, $acltext), NOT_GUESSED);
718 if ($par eq "" || $par eq "*") { 718 if ($par eq "" || $par eq "*") {
719 $vartypes->{$varname} = $type; 719 $vartypes->{$varname} = $type;
720 } 720 }
721 if ($par eq "*" || $par eq ".*") { 721 if ($par eq "*" || $par eq ".*") {
722 $vartypes->{"${varname}.*"} = $type; 722 $vartypes->{"${varname}.*"} = $type;
723 } 723 }
724 724
725 } else { 725 } else {
726 $line->log_fatal("Unknown line format."); 726 $line->log_fatal("Unknown line format.");
727 } 727 }
728 } 728 }
729 } else { 729 } else {
730 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); 730 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read.");
731 } 731 }
732 732
733# TODO: Enable when the time is ripe. 733# TODO: Enable when the time is ripe.
734if (false) { 734if (false) {
735 # Additionally, scan mk/defaults/mk.conf for variable 735 # Additionally, scan mk/defaults/mk.conf for variable
736 # definitions. All these variables are reserved for the user and 736 # definitions. All these variables are reserved for the user and
737 # must not be set within packages. 737 # must not be set within packages.
738 $fname = "${cwd_pkgsrcdir}/mk/defaults/mk.conf"; 738 $fname = "${cwd_pkgsrcdir}/mk/defaults/mk.conf";
739 if ((my $lines = load_file($fname))) { 739 if ((my $lines = load_file($fname))) {
740 foreach my $line (@{$lines}) { 740 foreach my $line (@{$lines}) {
741 if ($line->text =~ m"^#?([\w_]+)\?=") { 741 if ($line->text =~ m"^#?([\w_]+)\?=") {
742 my ($varname) = ($1); 742 my ($varname) = ($1);
743 $opt_debug_misc and $line->log_debug("Found user-definable variable ${varname}."); 743 $opt_debug_misc and $line->log_debug("Found user-definable variable ${varname}.");
744 $vartypes->{$varname} = "Userdefined"; # FIXME: type error 744 $vartypes->{$varname} = "Userdefined"; # FIXME: type error
745 } 745 }
746 } 746 }
747 } else { 747 } else {
748 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); 748 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read.");
749 } 749 }
750} 750}
751 751
752 return ($get_vartypes_map_result = $vartypes); 752 return ($get_vartypes_map_result = $vartypes);
753} 753}
754 754
755my $get_deprecated_map_result = undef; 755my $get_deprecated_map_result = undef;
756sub get_deprecated_map() { 756sub get_deprecated_map() {
757 my ($fname, $lines, $vars); 757 my ($fname, $lines, $vars);
758 758
759 if (defined($get_deprecated_map_result)) { 759 if (defined($get_deprecated_map_result)) {
760 return $get_deprecated_map_result; 760 return $get_deprecated_map_result;
761 } 761 }
762 762
763 $fname = conf_datadir."/deprecated.map"; 763 $fname = conf_datadir."/deprecated.map";
764 if (!($lines = load_file($fname))) { 764 if (!($lines = load_file($fname))) {
765 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); 765 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read.");
766 } 766 }
767 767
768 $vars = {}; 768 $vars = {};
769 foreach my $line (@{$lines}) { 769 foreach my $line (@{$lines}) {
770 if ($line->text =~ m"^#" || $line->text =~ m"^\s*$") { 770 if ($line->text =~ m"^#" || $line->text =~ m"^\s*$") {
771 # Ignore empty and comment lines. 771 # Ignore empty and comment lines.
772 772
773 } elsif ($line->text =~ m"^(\S+)\s+(.*)$") { 773 } elsif ($line->text =~ m"^(\S+)\s+(.*)$") {
774 $vars->{$1} = $2; 774 $vars->{$1} = $2;
775 775
776 } else { 776 } else {
777 $line->log_fatal("Unknown line format."); 777 $line->log_fatal("Unknown line format.");
778 } 778 }
779 } 779 }
780 return ($get_deprecated_map_result = $vars); 780 return ($get_deprecated_map_result = $vars);
781} 781}
782 782
783my $load_dist_sites_url2name = undef; 783my $load_dist_sites_url2name = undef;
784my $load_dist_sites_names = undef; 784my $load_dist_sites_names = undef;
785sub load_dist_sites() { 785sub load_dist_sites() {
786 my ($fname) = ("${cwd_pkgsrcdir}/mk/fetch/sites.mk"); 786 my ($fname) = ("${cwd_pkgsrcdir}/mk/fetch/sites.mk");
787 my ($lines) = load_file($fname); 787 my ($lines) = load_file($fname);
788 my ($varname) = undef; 788 my ($varname) = undef;
789 my ($ignoring) = false; 789 my ($ignoring) = false;
790 my ($url2name) = {}; 790 my ($url2name) = {};
791 my ($names) = {}; 791 my ($names) = {};
792 792
793 if (!$lines) { 793 if (!$lines) {
794 log_error($fname, NO_LINE_NUMBER, "Could not be read."); 794 log_error($fname, NO_LINE_NUMBER, "Could not be read.");
795 $load_dist_sites_url2name = $url2name; 795 $load_dist_sites_url2name = $url2name;
796 $load_dist_sites_names = $names; 796 $load_dist_sites_names = $names;
797 return; 797 return;
798 } 798 }
799 foreach my $line (@{$lines}) { 799 foreach my $line (@{$lines}) {
800 my $text = $line->text; 800 my $text = $line->text;
801 801
802 if ($text =~ m"^(MASTER_SITE_\w+)\+=\s*\\$"o) { 802 if ($text =~ m"^(MASTER_SITE_\w+)\+=\s*\\$"o) {
803 $varname = $1; 803 $varname = $1;
804 $names->{$varname} = true; 804 $names->{$varname} = true;
805 $ignoring = false; 805 $ignoring = false;
806 806
807 } elsif ($text eq "MASTER_SITE_BACKUP?=\t\\") { 807 } elsif ($text eq "MASTER_SITE_BACKUP?=\t\\") {
808 $ignoring = true; 808 $ignoring = true;
809 809
810 } elsif ($text =~ m"^\t((?:http://|ftp://)\S+/)(?:|\s*\\)$"o) { 810 } elsif ($text =~ m"^\t((?:http://|ftp://)\S+/)(?:|\s*\\)$"o) {
811 if (!$ignoring) { 811 if (!$ignoring) {
812 if (defined($varname)) { 812 if (defined($varname)) {
813 $url2name->{$1} = $varname; 813 $url2name->{$1} = $varname;
814 } else { 814 } else {
815 $line->log_error("Lonely URL found."); 815 $line->log_error("Lonely URL found.");
816 } 816 }
817 } 817 }
818 818
819 } elsif ($text =~ m"^(?:#.*|\s*)$") { 819 } elsif ($text =~ m"^(?:#.*|\s*)$") {
820 # ignore empty and comment lines 820 # ignore empty and comment lines
821 821
822 } elsif ($text =~ m"BSD_SITES_MK") { 822 } elsif ($text =~ m"BSD_SITES_MK") {
823 # ignore multiple inclusion guards 823 # ignore multiple inclusion guards
824 824
825 } else { 825 } else {
826 $line->log_fatal("Unknown line type."); 826 $line->log_fatal("Unknown line type.");
827 } 827 }
828 } 828 }
829 829
830 # Explicitly allowed, although not defined in mk/fetch/sites.mk. 830 # Explicitly allowed, although not defined in mk/fetch/sites.mk.
831 $names->{"MASTER_SITE_SUSE_UPD"} = true; 831 $names->{"MASTER_SITE_SUSE_UPD"} = true;
832 $names->{"MASTER_SITE_LOCAL"} = true; 832 $names->{"MASTER_SITE_LOCAL"} = true;
833 833
834 $opt_debug_misc and log_debug($fname, NO_LINES, "Loaded " . scalar(keys(%{$url2name})) . " MASTER_SITE_* definitions."); 834 $opt_debug_misc and log_debug($fname, NO_LINES, "Loaded " . scalar(keys(%{$url2name})) . " MASTER_SITE_* definitions.");
835 $load_dist_sites_url2name = $url2name; 835 $load_dist_sites_url2name = $url2name;
836 $load_dist_sites_names = $names; 836 $load_dist_sites_names = $names;
837} 837}
838 838
839sub get_dist_sites() { 839sub get_dist_sites() {
840 if (!defined($load_dist_sites_url2name)) { 840 if (!defined($load_dist_sites_url2name)) {
841 load_dist_sites(); 841 load_dist_sites();
842 } 842 }
843 return $load_dist_sites_url2name; 843 return $load_dist_sites_url2name;
844} 844}
845 845
846sub get_dist_sites_names() { 846sub get_dist_sites_names() {
847 if (!defined($load_dist_sites_names)) { 847 if (!defined($load_dist_sites_names)) {
848 load_dist_sites(); 848 load_dist_sites();
849 } 849 }
850 return $load_dist_sites_names; 850 return $load_dist_sites_names;
851} 851}
852 852
853my $get_pkg_options_result = undef; 853my $get_pkg_options_result = undef;
854sub get_pkg_options() { 854sub get_pkg_options() {
855 855
856 if (defined($get_pkg_options_result)) { 856 if (defined($get_pkg_options_result)) {
857 return $get_pkg_options_result; 857 return $get_pkg_options_result;
858 } 858 }
859 859
860 my ($fname) = ("${cwd_pkgsrcdir}/mk/defaults/options.description"); 860 my ($fname) = ("${cwd_pkgsrcdir}/mk/defaults/options.description");
861 my ($lines, $options); 861 my ($lines, $options);
862 862
863 if (!($lines = load_file($fname))) { 863 if (!($lines = load_file($fname))) {
864 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); 864 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read.");
865 } 865 }
866 866
867 $options = {}; 867 $options = {};
868 foreach my $line (@{$lines}) { 868 foreach my $line (@{$lines}) {
869 if ($line->text =~ m"^([-0-9a-z_+]+)(?:\s+(.*))?$") { 869 if ($line->text =~ m"^([-0-9a-z_+]+)(?:\s+(.*))?$") {
870 my ($optname, $optdescr) = ($1, $2); 870 my ($optname, $optdescr) = ($1, $2);
871 871
872 $options->{$optname} = defined($optdescr) 872 $options->{$optname} = defined($optdescr)
873 ? $optdescr 873 ? $optdescr
874 : ""; 874 : "";
875 } else { 875 } else {
876 $line->log_error("Unknown line format."); 876 $line->log_error("Unknown line format.");
877 } 877 }
878 } 878 }
879 879
880 return ($get_pkg_options_result = $options); 880 return ($get_pkg_options_result = $options);
881} 881}
882 882
883my $load_tool_names_system_build_defs = undef; # XXX: misplaced, but works 883my $load_tool_names_system_build_defs = undef; # XXX: misplaced, but works
884my $load_tool_names_tools = undef; 884my $load_tool_names_tools = undef;
885my $load_tool_names_vartools = undef; 885my $load_tool_names_vartools = undef;
886my $load_tool_names_varname_to_toolname = undef; 886my $load_tool_names_varname_to_toolname = undef;
887my $load_tool_names_predefined_tools = undef; 887my $load_tool_names_predefined_tools = undef;
888sub load_tool_names() { 888sub load_tool_names() {
889 my ($tools, $vartools, $predefined_tools, $varname_to_toolname, @tool_files); 889 my ($tools, $vartools, $predefined_tools, $varname_to_toolname, @tool_files);
890 my ($system_build_defs); 890 my ($system_build_defs);
891 891
892 # 892 #
893 # Get the list of files that define the tools from bsd.tools.mk. 893 # Get the list of files that define the tools from bsd.tools.mk.
894 # 894 #
895 895
896 @tool_files = ("defaults.mk"); 896 @tool_files = ("defaults.mk");
897 { 897 {
898 my $fname = "${cwd_pkgsrcdir}/mk/tools/bsd.tools.mk"; 898 my $fname = "${cwd_pkgsrcdir}/mk/tools/bsd.tools.mk";
899 my $lines = load_lines($fname, true); 899 my $lines = load_lines($fname, true);
900 if (!$lines) { 900 if (!$lines) {
901 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); 901 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read.");
902 } 902 }
903 903
904 foreach my $line (@{$lines}) { 904 foreach my $line (@{$lines}) {
905 if ($line->text =~ regex_mk_include) { 905 if ($line->text =~ regex_mk_include) {
906 my (undef, $includefile) = ($1, $2); 906 my (undef, $includefile) = ($1, $2);
907 if ($includefile =~ m"^(?:\$\{PKGSRCDIR\}/mk/tools/)?([^/]+)$") { 907 if ($includefile =~ m"^(?:\$\{PKGSRCDIR\}/mk/tools/)?([^/]+)$") {
908 push(@tool_files, $1); 908 push(@tool_files, $1);
909 } 909 }
910 } 910 }
911 } 911 }
912 } 912 }
913 assert(scalar(@tool_files) > 1, "Too few tool files. Maybe the files have been renamed again?"); 913 assert(scalar(@tool_files) > 1, "Too few tool files. Maybe the files have been renamed again?");
914 914
915 # 915 #
916 # Scan the tool files for the actual definitions of the tools. 916 # Scan the tool files for the actual definitions of the tools.
917 # 917 #
918 918
919 $tools = {}; 919 $tools = {};
920 $vartools = {}; 920 $vartools = {};
921 $predefined_tools = {}; 921 $predefined_tools = {};
922 $varname_to_toolname = {}; 922 $varname_to_toolname = {};
923 $system_build_defs = {}; 923 $system_build_defs = {};
924 foreach my $basename (@tool_files) { 924 foreach my $basename (@tool_files) {
925 my $fname = "${cwd_pkgsrcdir}/mk/tools/${basename}"; 925 my $fname = "${cwd_pkgsrcdir}/mk/tools/${basename}";
926 my $lines = load_lines($fname, true); 926 my $lines = load_lines($fname, true);
927 927
928 if (!$lines) { 928 if (!$lines) {
929 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); 929 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read.");
930 } 930 }
931 931
932 foreach my $line (@{$lines}) { 932 foreach my $line (@{$lines}) {
933 if ($line->text =~ regex_varassign) { 933 if ($line->text =~ regex_varassign) {
934 my ($varname, undef, $value, undef) = ($1, $2, $3, $4); 934 my ($varname, undef, $value, undef) = ($1, $2, $3, $4);
935 if ($varname eq "TOOLS_CREATE" && $value =~ m"^([-\w.]+|\[)$") { 935 if ($varname eq "TOOLS_CREATE" && $value =~ m"^([-\w.]+|\[)$") {
936 $tools->{$value} = true; 936 $tools->{$value} = true;
937 937
938 } elsif ($varname =~ m"^(?:_TOOLS_VARNAME)\.([-\w.]+|\[)$") { 938 } elsif ($varname =~ m"^(?:_TOOLS_VARNAME)\.([-\w.]+|\[)$") {
939 $tools->{$1} = true; 939 $tools->{$1} = true;
940 $vartools->{$1} = $value; 940 $vartools->{$1} = $value;
941 $varname_to_toolname->{$value} = $1; 941 $varname_to_toolname->{$value} = $1;
942 942
943 } elsif ($varname =~ m"^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$") { 943 } elsif ($varname =~ m"^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$") {
944 $tools->{$1} = true; 944 $tools->{$1} = true;
945 945
946 } elsif ($varname =~ m"^_TOOLS\.(.*)") { 946 } elsif ($varname =~ m"^_TOOLS\.(.*)") {
947 $tools->{$1} = true; 947 $tools->{$1} = true;
948 foreach my $tool (split(qr"\s+", $value)) { 948 foreach my $tool (split(qr"\s+", $value)) {
949 $tools->{$tool} = true; 949 $tools->{$tool} = true;
950 } 950 }
951 } 951 }
952 } 952 }
953 } 953 }
954 } 954 }
955 955
956 foreach my $basename ("bsd.pkg.mk") { 956 foreach my $basename ("bsd.pkg.mk") {
957 my $fname = "${cwd_pkgsrcdir}/mk/${basename}"; 957 my $fname = "${cwd_pkgsrcdir}/mk/${basename}";
958 my $lines = load_lines($fname, true); 958 my $lines = load_lines($fname, true);
959 my $cond_depth = 0; 959 my $cond_depth = 0;
960 960
961 if (!$lines) { 961 if (!$lines) {
962 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); 962 log_fatal($fname, NO_LINE_NUMBER, "Cannot be read.");
963 } 963 }
964 964
965 foreach my $line (@{$lines}) { 965 foreach my $line (@{$lines}) {
966 my $text = $line->text; 966 my $text = $line->text;
967 967
968 if ($text =~ regex_varassign) { 968 if ($text =~ regex_varassign) {
969 my ($varname, undef, $value, undef) = ($1, $2, $3, $4); 969 my ($varname, undef, $value, undef) = ($1, $2, $3, $4);
970 970
971 if ($varname eq "USE_TOOLS") { 971 if ($varname eq "USE_TOOLS") {
972 $opt_debug_tools and $line->log_debug("[cond_depth=${cond_depth}] $value"); 972 $opt_debug_tools and $line->log_debug("[cond_depth=${cond_depth}] $value");
973 if ($cond_depth == 0) { 973 if ($cond_depth == 0) {
974 foreach my $tool (split(qr"\s+", $value)) { 974 foreach my $tool (split(qr"\s+", $value)) {
975 if ($tool !~ regex_unresolved && exists($tools->{$tool})) { 975 if ($tool !~ regex_unresolved && exists($tools->{$tool})) {
976 $predefined_tools->{$tool} = true; 976 $predefined_tools->{$tool} = true;
977 # The path (without arguments) to the tool 977 # The path (without arguments) to the tool
978 $predefined_tools->{"TOOLS_${tool}"} = true; 978 $predefined_tools->{"TOOLS_${tool}"} = true;
979 } 979 }
980 } 980 }
981 } 981 }
982 } elsif ($varname eq "_BUILD_DEFS") { 982 } elsif ($varname eq "_BUILD_DEFS") {
983 foreach my $bdvar (split(qr"\s+", $value)) { 983 foreach my $bdvar (split(qr"\s+", $value)) {
984 $system_build_defs->{$bdvar} = true; 984 $system_build_defs->{$bdvar} = true;
985 } 985 }
986 } 986 }
987 987
988 } elsif ($text =~ regex_mk_cond) { 988 } elsif ($text =~ regex_mk_cond) {
989 my ($indent, $cond, $args, $comment) = ($1, $2, $3, $4); 989 my ($indent, $cond, $args, $comment) = ($1, $2, $3, $4);
990 990
991 if ($cond =~ m"^(?:if|ifdef|ifndef|for)$") { 991 if ($cond =~ m"^(?:if|ifdef|ifndef|for)$") {
992 $cond_depth++; 992 $cond_depth++;
993 } elsif ($cond =~ m"^(?:endif|endfor)$") { 993 } elsif ($cond =~ m"^(?:endif|endfor)$") {
994 $cond_depth--; 994 $cond_depth--;
995 } 995 }
996 } 996 }
997 } 997 }
998 } 998 }
999 999
1000 $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known tools: ".join(" ", sort(keys(%{$tools})))); 1000 $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known tools: ".join(" ", sort(keys(%{$tools}))));
1001 $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known vartools: ".join(" ", sort(keys(%{$vartools})))); 1001 $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known vartools: ".join(" ", sort(keys(%{$vartools}))));
@@ -6066,1520 +6066,1524 @@ sub checkfile_extra($) { @@ -6066,1520 +6066,1524 @@ sub checkfile_extra($) {
6066 checklines_trailing_empty_lines($lines); 6066 checklines_trailing_empty_lines($lines);
6067 checkperms($fname); 6067 checkperms($fname);
6068} 6068}
6069 6069
6070sub checkfile_INSTALL($) { 6070sub checkfile_INSTALL($) {
6071 my ($fname) = @_; 6071 my ($fname) = @_;
6072 my ($lines); 6072 my ($lines);
6073 6073
6074 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); 6074 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()");
6075 6075
6076 checkperms($fname); 6076 checkperms($fname);
6077 if (!($lines = load_file($fname))) { 6077 if (!($lines = load_file($fname))) {
6078 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6078 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6079 return; 6079 return;
6080 } 6080 }
6081} 6081}
6082 6082
6083sub checkfile_MESSAGE($) { 6083sub checkfile_MESSAGE($) {
6084 my ($fname) = @_; 6084 my ($fname) = @_;
6085 my ($lines); 6085 my ($lines);
6086 6086
6087 my @explanation = ( 6087 my @explanation = (
6088 "A MESSAGE file should consist of a header line, having 75 \"=\"", 6088 "A MESSAGE file should consist of a header line, having 75 \"=\"",
6089 "characters, followed by a line containing only the RCS Id, then an", 6089 "characters, followed by a line containing only the RCS Id, then an",
6090 "empty line, your text and finally the footer line, which is the", 6090 "empty line, your text and finally the footer line, which is the",
6091 "same as the header line."); 6091 "same as the header line.");
6092 6092
6093 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); 6093 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()");
6094 6094
6095 checkperms($fname); 6095 checkperms($fname);
6096 if (!($lines = load_file($fname))) { 6096 if (!($lines = load_file($fname))) {
6097 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6097 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6098 return; 6098 return;
6099 } 6099 }
6100 6100
6101 if (@{$lines} < 3) { 6101 if (@{$lines} < 3) {
6102 log_warning($fname, NO_LINE_NUMBER, "File too short."); 6102 log_warning($fname, NO_LINE_NUMBER, "File too short.");
6103 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6103 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6104 return; 6104 return;
6105 } 6105 }
6106 if ($lines->[0]->text ne "=" x 75) { 6106 if ($lines->[0]->text ne "=" x 75) {
6107 $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); 6107 $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters.");
6108 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6108 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6109 } 6109 }
6110 checkline_rcsid($lines->[1], ""); 6110 checkline_rcsid($lines->[1], "");
6111 foreach my $line (@{$lines}) { 6111 foreach my $line (@{$lines}) {
6112 checkline_length($line, 80); 6112 checkline_length($line, 80);
6113 checkline_trailing_whitespace($line); 6113 checkline_trailing_whitespace($line);
6114 checkline_valid_characters($line, regex_validchars); 6114 checkline_valid_characters($line, regex_validchars);
6115 checkline_spellcheck($line); 6115 checkline_spellcheck($line);
6116 } 6116 }
6117 if ($lines->[-1]->text ne "=" x 75) { 6117 if ($lines->[-1]->text ne "=" x 75) {
6118 $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); 6118 $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters.");
6119 explain_warning($fname, NO_LINE_NUMBER, @explanation); 6119 explain_warning($fname, NO_LINE_NUMBER, @explanation);
6120 } 6120 }
6121 checklines_trailing_empty_lines($lines); 6121 checklines_trailing_empty_lines($lines);
6122} 6122}
6123 6123
6124sub checkfile_mk($) { 6124sub checkfile_mk($) {
6125 my ($fname) = @_; 6125 my ($fname) = @_;
6126 my ($lines); 6126 my ($lines);
6127 6127
6128 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); 6128 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()");
6129 6129
6130 checkperms($fname); 6130 checkperms($fname);
6131 if (!($lines = load_lines($fname, true))) { 6131 if (!($lines = load_lines($fname, true))) {
6132 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6132 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6133 return; 6133 return;
6134 } 6134 }
6135 6135
6136 parselines_mk($lines); 6136 parselines_mk($lines);
6137 checklines_mk($lines); 6137 checklines_mk($lines);
6138 autofix($lines); 6138 autofix($lines);
6139} 6139}
6140 6140
6141sub checkfile_package_Makefile($$) { 6141sub checkfile_package_Makefile($$) {
6142 my ($fname, $lines) = @_; 6142 my ($fname, $lines) = @_;
6143 6143
6144 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); 6144 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)");
6145 6145
6146 checkperms($fname); 6146 checkperms($fname);
6147 6147
6148 if (!exists($pkgctx_vardef->{"PLIST_SRC"}) 6148 if (!exists($pkgctx_vardef->{"PLIST_SRC"})
6149 && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) 6149 && !exists($pkgctx_vardef->{"GENERATE_PLIST"})
6150 && !exists($pkgctx_vardef->{"META_PACKAGE"}) 6150 && !exists($pkgctx_vardef->{"META_PACKAGE"})
6151 && defined($pkgdir) 6151 && defined($pkgdir)
6152 && !-f "${current_dir}/$pkgdir/PLIST" 6152 && !-f "${current_dir}/$pkgdir/PLIST"
6153 && !-f "${current_dir}/$pkgdir/PLIST.common") { 6153 && !-f "${current_dir}/$pkgdir/PLIST.common") {
6154 log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); 6154 log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?");
6155 } 6155 }
6156 6156
6157 if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { 6157 if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) {
6158 if (-f "${current_dir}/${distinfo_file}") { 6158 if (-f "${current_dir}/${distinfo_file}") {
6159 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); 6159 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set.");
6160 } 6160 }
6161 } else { 6161 } else {
6162 if (!-f "${current_dir}/${distinfo_file}") { 6162 if (!-f "${current_dir}/${distinfo_file}") {
6163 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); 6163 log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'.");
6164 } 6164 }
6165 } 6165 }
6166 6166
6167 if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { 6167 if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) {
6168 $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); 6168 $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ...");
6169 $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); 6169 $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set.");
6170 } 6170 }
6171 6171
6172 if (!exists($pkgctx_vardef->{"LICENSE"})) { 6172 if (!exists($pkgctx_vardef->{"LICENSE"})) {
6173 log_error($fname, NO_LINE_NUMBER, "Each package must define its LICENSE."); 6173 log_error($fname, NO_LINE_NUMBER, "Each package must define its LICENSE.");
6174 } 6174 }
6175 6175
6176 if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { 6176 if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) {
6177 my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; 6177 my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"};
6178 my $value = $languages_line->get("value"); 6178 my $value = $languages_line->get("value");
6179 6179
6180 if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { 6180 if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) {
6181 # Don't emit a warning, since the comment 6181 # Don't emit a warning, since the comment
6182 # probably contains a statement that C is 6182 # probably contains a statement that C is
6183 # really not needed. 6183 # really not needed.
6184 6184
6185 } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { 6185 } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") {
6186 $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); 6186 $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ...");
6187 $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); 6187 $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES.");
6188 } 6188 }
6189 } 6189 }
6190 6190
6191 my $distname_line = $pkgctx_vardef->{"DISTNAME"}; 6191 my $distname_line = $pkgctx_vardef->{"DISTNAME"};
6192 my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; 6192 my $pkgname_line = $pkgctx_vardef->{"PKGNAME"};
6193 6193
6194 my $distname = defined($distname_line) ? $distname_line->get("value") : undef; 6194 my $distname = defined($distname_line) ? $distname_line->get("value") : undef;
6195 my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; 6195 my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef;
6196 my $nbpart = get_nbpart(); 6196 my $nbpart = get_nbpart();
6197 6197
6198 # Let's do some tricks to get the proper value of the package 6198 # Let's do some tricks to get the proper value of the package
6199 # name more often. 6199 # name more often.
6200 if (defined($distname) && defined($pkgname)) { 6200 if (defined($distname) && defined($pkgname)) {
6201 $pkgname =~ s/\$\{DISTNAME\}/$distname/; 6201 $pkgname =~ s/\$\{DISTNAME\}/$distname/;
6202 6202
6203 if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { 6203 if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") {
6204 my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); 6204 my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6);
6205 my $newname = $distname; 6205 my $newname = $distname;
6206 $old = quotemeta($old); 6206 $old = quotemeta($old);
6207 $old =~ s/^\\\^/^/; 6207 $old =~ s/^\\\^/^/;
6208 $old =~ s/\\\$$/\$/; 6208 $old =~ s/\\\$$/\$/;
6209 if ($mod eq "g") { 6209 if ($mod eq "g") {
6210 $newname =~ s/$old/$new/g; 6210 $newname =~ s/$old/$new/g;
6211 } else { 6211 } else {
6212 $newname =~ s/$old/$new/; 6212 $newname =~ s/$old/$new/;
6213 } 6213 }
6214 $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); 6214 $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname");
6215 $pkgname = $before . $newname . $after; 6215 $pkgname = $before . $newname . $after;
6216 $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); 6216 $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname");
6217 } 6217 }
6218 } 6218 }
6219 6219
6220 if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { 6220 if (defined($pkgname) && defined($distname) && $pkgname eq $distname) {
6221 $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); 6221 $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME.");
6222 } 6222 }
6223 6223
6224 if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { 6224 if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) {
6225 $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); 6225 $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly.");
6226 } 6226 }
6227 6227
6228 ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) 6228 ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion)
6229 = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) 6229 = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2)
6230 : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) 6230 : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2)
6231 : (undef, undef, undef, undef); 6231 : (undef, undef, undef, undef);
6232 if (defined($effective_pkgname_line)) { 6232 if (defined($effective_pkgname_line)) {
6233 $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); 6233 $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}.");
6234 # XXX: too many false positives 6234 # XXX: too many false positives
6235 if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) { 6235 if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) {
6236 $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1)."); 6236 $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1).");
6237 } 6237 }
6238 } 6238 }
6239 6239
6240 checkpackage_possible_downgrade(); 6240 checkpackage_possible_downgrade();
6241 6241
6242 if (!exists($pkgctx_vardef->{"COMMENT"})) { 6242 if (!exists($pkgctx_vardef->{"COMMENT"})) {
6243 log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); 6243 log_warning($fname, NO_LINE_NUMBER, "No COMMENT given.");
6244 } 6244 }
6245 6245
6246 if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { 6246 if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) {
6247 $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); 6247 $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ...");
6248 $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); 6248 $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous.");
6249 } 6249 }
6250 6250
6251 if (defined($effective_pkgbase)) { 6251 if (defined($effective_pkgbase)) {
6252 6252
6253 foreach my $suggested_update (@{get_suggested_package_updates()}) { 6253 foreach my $suggested_update (@{get_suggested_package_updates()}) {
6254 my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; 6254 my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update};
6255 my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); 6255 my $comment = (defined($suggcomm) ? " (${suggcomm})" : "");
6256 6256
6257 next unless $effective_pkgbase eq $suggbase; 6257 next unless $effective_pkgbase eq $suggbase;
6258 6258
6259 if (dewey_cmp($effective_pkgversion, "<", $suggver)) { 6259 if (dewey_cmp($effective_pkgversion, "<", $suggver)) {
6260 $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); 6260 $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}.");
6261 $effective_pkgname_line->explain_warning( 6261 $effective_pkgname_line->explain_warning(
6262"The wishlist for package updates in doc/TODO mentions that a newer", 6262"The wishlist for package updates in doc/TODO mentions that a newer",
6263"version of this package is available."); 6263"version of this package is available.");
6264 } 6264 }
6265 if (dewey_cmp($effective_pkgversion, "==", $suggver)) { 6265 if (dewey_cmp($effective_pkgversion, "==", $suggver)) {
6266 $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); 6266 $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done.");
6267 } 6267 }
6268 if (dewey_cmp($effective_pkgversion, ">", $suggver)) { 6268 if (dewey_cmp($effective_pkgversion, ">", $suggver)) {
6269 $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); 6269 $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}.");
6270 } 6270 }
6271 } 6271 }
6272 } 6272 }
6273 6273
6274 checklines_mk($lines); 6274 checklines_mk($lines);
6275 checklines_package_Makefile_varorder($lines); 6275 checklines_package_Makefile_varorder($lines);
6276 autofix($lines); 6276 autofix($lines);
6277} 6277}
6278 6278
6279sub checkfile_patch($) { 6279sub checkfile_patch($) {
6280 my ($fname) = @_; 6280 my ($fname) = @_;
6281 my ($lines); 6281 my ($lines);
6282 my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); 6282 my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks);
6283 my ($seen_comment, $current_fname, $current_ftype, $patched_files); 6283 my ($seen_comment, $current_fname, $current_ftype, $patched_files);
6284 my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); 6284 my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading);
6285 6285
6286 # Abbreviations used: 6286 # Abbreviations used:
6287 # style: [c] = context diff, [u] = unified diff 6287 # style: [c] = context diff, [u] = unified diff
6288 # scope: [f] = file, [h] = hunk, [l] = line 6288 # scope: [f] = file, [h] = hunk, [l] = line
6289 # action: [d] = delete, [m] = modify, [a] = add, [c] = context 6289 # action: [d] = delete, [m] = modify, [a] = add, [c] = context
6290 use constant re_patch_rcsid => qr"^\$.*\$$"; 6290 use constant re_patch_rcsid => qr"^\$.*\$$";
6291 use constant re_patch_text => qr"^(.+)$"; 6291 use constant re_patch_text => qr"^(.+)$";
6292 use constant re_patch_empty => qr"^$"; 6292 use constant re_patch_empty => qr"^$";
6293 use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; 6293 use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$";
6294 use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; 6294 use constant re_patch_cfa => qr"^---\s(\S+)(.*)$";
6295 use constant re_patch_ch => qr"^\*{15}(.*)$"; 6295 use constant re_patch_ch => qr"^\*{15}(.*)$";
6296 use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; 6296 use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$";
6297 use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; 6297 use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$";
6298 use constant re_patch_cld => qr"^(?:-\s(.*))?$"; 6298 use constant re_patch_cld => qr"^(?:-\s(.*))?$";
6299 use constant re_patch_clm => qr"^(?:!\s(.*))?$"; 6299 use constant re_patch_clm => qr"^(?:!\s(.*))?$";
6300 use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; 6300 use constant re_patch_cla => qr"^(?:\+\s(.*))?$";
6301 use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; 6301 use constant re_patch_clc => qr"^(?:\s\s(.*))?$";
6302 use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; 6302 use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$";
6303 use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; 6303 use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$";
6304 use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; 6304 use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$";
6305 use constant re_patch_uld => qr"^-(.*)$"; 6305 use constant re_patch_uld => qr"^-(.*)$";
6306 use constant re_patch_ula => qr"^\+(.*)$"; 6306 use constant re_patch_ula => qr"^\+(.*)$";
6307 use constant re_patch_ulc => qr"^\s(.*)$"; 6307 use constant re_patch_ulc => qr"^\s(.*)$";
6308 use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; 6308 use constant re_patch_ulnonl => qr"^\\ No newline at end of file$";
6309 6309
6310 use enum qw(:PST_ 6310 use enum qw(:PST_
6311 START CENTER TEXT 6311 START CENTER TEXT
6312 CFA CH CHD CLD0 CLD CLA0 CLA 6312 CFA CH CHD CLD0 CLD CLA0 CLA
6313 UFA UH UL 6313 UFA UH UL
6314 ); 6314 );
6315 6315
6316 my @comment_explanation = ( 6316 my @comment_explanation = (
6317"Each patch must document why it is necessary. If it has been applied", 6317"Each patch must document why it is necessary. If it has been applied",
6318"because of a security issue, a reference to the CVE should be mentioned", 6318"because of a security issue, a reference to the CVE should be mentioned",
6319"as well.", 6319"as well.",
6320"", 6320"",
6321"Since it is our goal to have as few patches as possible, all patches", 6321"Since it is our goal to have as few patches as possible, all patches",
6322"should be sent to the upstream maintainers of the package. After you", 6322"should be sent to the upstream maintainers of the package. After you",
6323"have done so, you should add a reference to the bug report containing", 6323"have done so, you should add a reference to the bug report containing",
6324"the patch."); 6324"the patch.");
6325 6325
6326 my ($line, $m); 6326 my ($line, $m);
6327 6327
6328 my $check_text = sub($) { 6328 my $check_text = sub($) {
6329 my ($text) = @_; 6329 my ($text) = @_;
6330 6330
6331 if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { 6331 if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") {
6332 my ($tag) = ($2); 6332 my ($tag) = ($2);
6333 6333
6334 if ($text =~ re_patch_uh) { 6334 if ($text =~ re_patch_uh) {
6335 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); 6335 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it.");
6336 $line->set_text($1); 6336 $line->set_text($1);
6337 } else { 6337 } else {
6338 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); 6338 $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\".");
6339 } 6339 }
6340 } 6340 }
6341 }; 6341 };
6342 6342
6343 my $check_contents = sub() { 6343 my $check_contents = sub() {
6344 6344
6345 if ($m->has(1)) { 6345 if ($m->has(1)) {
6346 $check_text->($m->text(1)); 6346 $check_text->($m->text(1));
6347 } 6347 }
6348 }; 6348 };
6349 6349
6350 my $check_added_contents = sub() { 6350 my $check_added_contents = sub() {
6351 my $text; 6351 my $text;
6352 6352
6353 return unless $m->has(1); 6353 return unless $m->has(1);
6354 $text = $m->text(1); 6354 $text = $m->text(1);
6355 checkline_cpp_macro_names($line, $text); 6355 checkline_cpp_macro_names($line, $text);
6356 checkline_spellcheck($line); 6356 checkline_spellcheck($line);
6357 6357
6358 # XXX: This check is not as accurate as the similar one in 6358 # XXX: This check is not as accurate as the similar one in
6359 # checkline_mk_shelltext(). 6359 # checkline_mk_shelltext().
6360 if (defined($current_fname)) { 6360 if (defined($current_fname)) {
6361 if ($current_ftype eq "shell" || $current_ftype eq "make") { 6361 if ($current_ftype eq "shell" || $current_ftype eq "make") {
6362 my ($mm, $rest) = match_all($text, $regex_shellword); 6362 my ($mm, $rest) = match_all($text, $regex_shellword);
6363 6363
6364 foreach my $m (@{$mm}) { 6364 foreach my $m (@{$mm}) {
6365 my $shellword = $m->text(1); 6365 my $shellword = $m->text(1);
6366 6366
6367 if ($shellword =~ m"^#") { 6367 if ($shellword =~ m"^#") {
6368 last; 6368 last;
6369 } 6369 }
6370 checkline_mk_absolute_pathname($line, $shellword); 6370 checkline_mk_absolute_pathname($line, $shellword);
6371 } 6371 }
6372 6372
6373 } elsif ($current_ftype eq "source") { 6373 } elsif ($current_ftype eq "source") {
6374 checkline_source_absolute_pathname($line, $text); 6374 checkline_source_absolute_pathname($line, $text);
6375 6375
6376 } elsif ($current_ftype eq "configure") { 6376 } elsif ($current_ftype eq "configure") {
6377 if ($text =~ m": Avoid regenerating within pkgsrc$") { 6377 if ($text =~ m": Avoid regenerating within pkgsrc$") {
6378 $line->log_error("This code must not be included in patches."); 6378 $line->log_error("This code must not be included in patches.");
6379 $line->explain_error( 6379 $line->explain_error(
6380"It is generated automatically by pkgsrc after the patch phase.", 6380"It is generated automatically by pkgsrc after the patch phase.",
6381"", 6381"",
6382"For more details, look for \"configure-scripts-override\" in", 6382"For more details, look for \"configure-scripts-override\" in",
6383"mk/configure/gnu-configure.mk."); 6383"mk/configure/gnu-configure.mk.");
6384 } 6384 }
6385 6385
6386 } elsif ($current_ftype eq "ignore") { 6386 } elsif ($current_ftype eq "ignore") {
6387 # Ignore it. 6387 # Ignore it.
6388 6388
6389 } else { 6389 } else {
6390 checkline_other_absolute_pathname($line, $text); 6390 checkline_other_absolute_pathname($line, $text);
6391 } 6391 }
6392 } 6392 }
6393 }; 6393 };
6394 6394
6395 my $check_hunk_end = sub($$$) { 6395 my $check_hunk_end = sub($$$) {
6396 my ($deldelta, $adddelta, $newstate) = @_; 6396 my ($deldelta, $adddelta, $newstate) = @_;
6397 6397
6398 if ($deldelta > 0 && $dellines == 0) { 6398 if ($deldelta > 0 && $dellines == 0) {
6399 $redostate = $newstate; 6399 $redostate = $newstate;
6400 if (defined($addlines) && $addlines > 0) { 6400 if (defined($addlines) && $addlines > 0) {
6401 $line->log_error("Expected ${addlines} more lines to be added."); 6401 $line->log_error("Expected ${addlines} more lines to be added.");
6402 } 6402 }
6403 } elsif ($adddelta > 0 && $addlines == 0) { 6403 } elsif ($adddelta > 0 && $addlines == 0) {
6404 $redostate = $newstate; 6404 $redostate = $newstate;
6405 if (defined($dellines) && $dellines > 0) { 6405 if (defined($dellines) && $dellines > 0) {
6406 $line->log_error("Expected ${dellines} more lines to be deleted."); 6406 $line->log_error("Expected ${dellines} more lines to be deleted.");
6407 } 6407 }
6408 } else { 6408 } else {
6409 if (defined($context_scanning_leading)) { 6409 if (defined($context_scanning_leading)) {
6410 if ($deldelta != 0 && $adddelta != 0) { 6410 if ($deldelta != 0 && $adddelta != 0) {
6411 if ($context_scanning_leading) { 6411 if ($context_scanning_leading) {
6412 $leading_context_lines++; 6412 $leading_context_lines++;
6413 } else { 6413 } else {
6414 $trailing_context_lines++; 6414 $trailing_context_lines++;
6415 } 6415 }
6416 } else { 6416 } else {
6417 if ($context_scanning_leading) { 6417 if ($context_scanning_leading) {
6418 $context_scanning_leading = false; 6418 $context_scanning_leading = false;
6419 } else { 6419 } else {
6420 $trailing_context_lines = 0; 6420 $trailing_context_lines = 0;
6421 } 6421 }
6422 } 6422 }
6423 } 6423 }
6424 6424
6425 if ($deldelta != 0) { 6425 if ($deldelta != 0) {
6426 $dellines -= $deldelta; 6426 $dellines -= $deldelta;
6427 } 6427 }
6428 if ($adddelta != 0) { 6428 if ($adddelta != 0) {
6429 $addlines -= $adddelta; 6429 $addlines -= $adddelta;
6430 } 6430 }
6431 if (!((defined($dellines) && $dellines > 0) || 6431 if (!((defined($dellines) && $dellines > 0) ||
6432 (defined($addlines) && $addlines > 0))) { 6432 (defined($addlines) && $addlines > 0))) {
6433 if (defined($context_scanning_leading)) { 6433 if (defined($context_scanning_leading)) {
6434 if ($leading_context_lines != $trailing_context_lines) { 6434 if ($leading_context_lines != $trailing_context_lines) {
6435 $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."); 6435 $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.");
6436 } 6436 }
6437 } 6437 }
6438 $nextstate = $newstate; 6438 $nextstate = $newstate;
6439 } 6439 }
6440 } 6440 }
6441 }; 6441 };
6442 6442
6443 # @param deldelta 6443 # @param deldelta
6444 # The number of lines that are deleted from the patched file. 6444 # The number of lines that are deleted from the patched file.
6445 # @param adddelta 6445 # @param adddelta
6446 # The number of lines that are added to the patched file. 6446 # The number of lines that are added to the patched file.
6447 # @param newstate 6447 # @param newstate
6448 # The follow-up state when this line is the last line to be 6448 # The follow-up state when this line is the last line to be
6449 # added in this hunk of the patch. 6449 # added in this hunk of the patch.
6450 # 6450 #
6451 my $check_hunk_line = sub($$$) { 6451 my $check_hunk_line = sub($$$) {
6452 my ($deldelta, $adddelta, $newstate) = @_; 6452 my ($deldelta, $adddelta, $newstate) = @_;
6453 6453
6454 $check_contents->(); 6454 $check_contents->();
6455 $check_hunk_end->($deldelta, $adddelta, $newstate); 6455 $check_hunk_end->($deldelta, $adddelta, $newstate);
6456 6456
6457 # If -Wextra is given, the context lines are checked for 6457 # If -Wextra is given, the context lines are checked for
6458 # absolute paths and similar things. If it is not given, 6458 # absolute paths and similar things. If it is not given,
6459 # only those lines that really add something to the patched 6459 # only those lines that really add something to the patched
6460 # file are checked. 6460 # file are checked.
6461 if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) { 6461 if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) {
6462 $check_added_contents->(); 6462 $check_added_contents->();
6463 } 6463 }
6464 }; 6464 };
6465 6465
6466 my $transitions = 6466 my $transitions =
6467 # [ from state, regex, to state, action ] 6467 # [ from state, regex, to state, action ]
6468 [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { 6468 [ [PST_START, re_patch_rcsid, PST_CENTER, sub() {
6469 checkline_rcsid($line, ""); 6469 checkline_rcsid($line, "");
6470 }], [PST_START, undef, PST_CENTER, sub() { 6470 }], [PST_START, undef, PST_CENTER, sub() {
6471 checkline_rcsid($line, ""); 6471 checkline_rcsid($line, "");
6472 }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { 6472 }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() {
6473 # 6473 #
6474 }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { 6474 }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() {
6475 if (!$seen_comment) { 6475 if (!$seen_comment) {
6476 $line->log_error("Comment expected."); 6476 $line->log_error("Comment expected.");
6477 $line->explain_error(@comment_explanation); 6477 $line->explain_error(@comment_explanation);
6478 } 6478 }
6479 $line->log_warning("Please use unified diffs (diff -u) for patches."); 6479 $line->log_warning("Please use unified diffs (diff -u) for patches.");
6480 }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { 6480 }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() {
6481 if (!$seen_comment) { 6481 if (!$seen_comment) {
6482 $line->log_error("Comment expected."); 6482 $line->log_error("Comment expected.");
6483 $line->explain_error(@comment_explanation); 6483 $line->explain_error(@comment_explanation);
6484 } 6484 }
6485 }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { 6485 }], [PST_TEXT, re_patch_text, PST_TEXT, sub() {
6486 $seen_comment = true; 6486 $seen_comment = true;
6487 }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { 6487 }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() {
6488 # 6488 #
6489 }], [PST_TEXT, undef, PST_TEXT, sub() { 6489 }], [PST_TEXT, undef, PST_TEXT, sub() {
6490 # 6490 #
6491 }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { 6491 }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() {
6492 if ($seen_comment) { 6492 if ($seen_comment) {
6493 $opt_warn_space and $line->log_note("Empty line expected."); 6493 $opt_warn_space and $line->log_note("Empty line expected.");
6494 } else { 6494 } else {
6495 $line->log_error("Comment expected."); 6495 $line->log_error("Comment expected.");
6496 $line->explain_error(@comment_explanation); 6496 $line->explain_error(@comment_explanation);
6497 } 6497 }
6498 $line->log_warning("Please use unified diffs (diff -u) for patches."); 6498 $line->log_warning("Please use unified diffs (diff -u) for patches.");
6499 }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { 6499 }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() {
6500 if ($seen_comment) { 6500 if ($seen_comment) {
6501 $opt_warn_space and $line->log_note("Empty line expected."); 6501 $opt_warn_space and $line->log_note("Empty line expected.");
6502 } else { 6502 } else {
6503 $line->log_error("Comment expected."); 6503 $line->log_error("Comment expected.");
6504 $line->explain_error(@comment_explanation); 6504 $line->explain_error(@comment_explanation);
6505 } 6505 }
6506 }], [PST_CENTER, undef, PST_TEXT, sub() { 6506 }], [PST_CENTER, undef, PST_TEXT, sub() {
6507 $opt_warn_space and $line->log_note("Empty line expected."); 6507 $opt_warn_space and $line->log_note("Empty line expected.");
6508 }], [PST_CFA, re_patch_cfa, PST_CH, sub() { 6508 }], [PST_CFA, re_patch_cfa, PST_CH, sub() {
6509 $current_fname = $m->text(1); 6509 $current_fname = $m->text(1);
6510 $current_ftype = get_filetype($line, $current_fname); 6510 $current_ftype = get_filetype($line, $current_fname);
6511 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); 6511 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype");
6512 $patched_files++; 6512 $patched_files++;
6513 $hunks = 0; 6513 $hunks = 0;
6514 }], [PST_CH, re_patch_ch, PST_CHD, sub() { 6514 }], [PST_CH, re_patch_ch, PST_CHD, sub() {
6515 $hunks++; 6515 $hunks++;
6516 }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { 6516 }], [PST_CHD, re_patch_chd, PST_CLD0, sub() {
6517 $dellines = ($m->has(2)) 6517 $dellines = ($m->has(2))
6518 ? (1 + $m->text(2) - $m->text(1)) 6518 ? (1 + $m->text(2) - $m->text(1))
6519 : ($m->text(1)); 6519 : ($m->text(1));
6520 }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { 6520 }], [PST_CLD0, re_patch_clc, PST_CLD, sub() {
6521 $check_hunk_line->(1, 0, PST_CLD0); 6521 $check_hunk_line->(1, 0, PST_CLD0);
6522 }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { 6522 }], [PST_CLD0, re_patch_cld, PST_CLD, sub() {
6523 $check_hunk_line->(1, 0, PST_CLD0); 6523 $check_hunk_line->(1, 0, PST_CLD0);
6524 }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { 6524 }], [PST_CLD0, re_patch_clm, PST_CLD, sub() {
6525 $check_hunk_line->(1, 0, PST_CLD0); 6525 $check_hunk_line->(1, 0, PST_CLD0);
6526 }], [PST_CLD, re_patch_clc, PST_CLD, sub() { 6526 }], [PST_CLD, re_patch_clc, PST_CLD, sub() {
6527 $check_hunk_line->(1, 0, PST_CLD0); 6527 $check_hunk_line->(1, 0, PST_CLD0);
6528 }], [PST_CLD, re_patch_cld, PST_CLD, sub() { 6528 }], [PST_CLD, re_patch_cld, PST_CLD, sub() {
6529 $check_hunk_line->(1, 0, PST_CLD0); 6529 $check_hunk_line->(1, 0, PST_CLD0);
6530 }], [PST_CLD, re_patch_clm, PST_CLD, sub() { 6530 }], [PST_CLD, re_patch_clm, PST_CLD, sub() {
6531 $check_hunk_line->(1, 0, PST_CLD0); 6531 $check_hunk_line->(1, 0, PST_CLD0);
6532 }], [PST_CLD, undef, PST_CLD0, sub() { 6532 }], [PST_CLD, undef, PST_CLD0, sub() {
6533 if ($dellines != 0) { 6533 if ($dellines != 0) {
6534 $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); 6534 $line->log_warning("Invalid number of deleted lines (${dellines} missing).");
6535 } 6535 }
6536 }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { 6536 }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() {
6537 $dellines = undef; 6537 $dellines = undef;
6538 $addlines = ($m->has(2)) 6538 $addlines = ($m->has(2))
6539 ? (1 + $m->text(2) - $m->text(1)) 6539 ? (1 + $m->text(2) - $m->text(1))
6540 : ($m->text(1)); 6540 : ($m->text(1));
6541 }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { 6541 }], [PST_CLA0, re_patch_clc, PST_CLA, sub() {
6542 $check_hunk_line->(0, 1, PST_CH); 6542 $check_hunk_line->(0, 1, PST_CH);
6543 }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { 6543 }], [PST_CLA0, re_patch_clm, PST_CLA, sub() {
6544 $check_hunk_line->(0, 1, PST_CH); 6544 $check_hunk_line->(0, 1, PST_CH);
6545 }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { 6545 }], [PST_CLA0, re_patch_cla, PST_CLA, sub() {
6546 $check_hunk_line->(0, 1, PST_CH); 6546 $check_hunk_line->(0, 1, PST_CH);
6547 }], [PST_CLA, re_patch_clc, PST_CLA, sub() { 6547 }], [PST_CLA, re_patch_clc, PST_CLA, sub() {
6548 $check_hunk_line->(0, 1, PST_CH); 6548 $check_hunk_line->(0, 1, PST_CH);
6549 }], [PST_CLA, re_patch_clm, PST_CLA, sub() { 6549 }], [PST_CLA, re_patch_clm, PST_CLA, sub() {
6550 $check_hunk_line->(0, 1, PST_CH); 6550 $check_hunk_line->(0, 1, PST_CH);
6551 }], [PST_CLA, re_patch_cla, PST_CLA, sub() { 6551 }], [PST_CLA, re_patch_cla, PST_CLA, sub() {
6552 $check_hunk_line->(0, 1, PST_CH); 6552 $check_hunk_line->(0, 1, PST_CH);
6553 }], [PST_CLA, undef, PST_CLA0, sub() { 6553 }], [PST_CLA, undef, PST_CLA0, sub() {
6554 if ($addlines != 0) { 6554 if ($addlines != 0) {
6555 $line->log_warning("Invalid number of added lines (${addlines} missing)."); 6555 $line->log_warning("Invalid number of added lines (${addlines} missing).");
6556 } 6556 }
6557 }], [PST_CLA0, undef, PST_CH, sub() { 6557 }], [PST_CLA0, undef, PST_CH, sub() {
6558 # 6558 #
6559 }], [PST_CH, undef, PST_TEXT, sub() { 6559 }], [PST_CH, undef, PST_TEXT, sub() {
6560 # 6560 #
6561 }], [PST_UFA, re_patch_ufa, PST_UH, sub() { 6561 }], [PST_UFA, re_patch_ufa, PST_UH, sub() {
6562 $current_fname = $m->text(1); 6562 $current_fname = $m->text(1);
6563 $current_ftype = get_filetype($line, $current_fname); 6563 $current_ftype = get_filetype($line, $current_fname);
6564 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); 6564 $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype");
6565 $patched_files++; 6565 $patched_files++;
6566 $hunks = 0; 6566 $hunks = 0;
6567 }], [PST_UH, re_patch_uh, PST_UL, sub() { 6567 }], [PST_UH, re_patch_uh, PST_UL, sub() {
6568 $dellines = ($m->has(1) ? $m->text(2) : 1); 6568 $dellines = ($m->has(1) ? $m->text(2) : 1);
6569 $addlines = ($m->has(3) ? $m->text(4) : 1); 6569 $addlines = ($m->has(3) ? $m->text(4) : 1);
6570 $check_text->($line->text); 6570 $check_text->($line->text);
6571 if ($line->text =~ m"\r$") { 6571 if ($line->text =~ m"\r$") {
6572 $line->log_error("The hunk header must not end with a CR character."); 6572 $line->log_error("The hunk header must not end with a CR character.");
6573 $line->explain_error( 6573 $line->explain_error(
6574"The MacOS X patch utility cannot handle these."); 6574"The MacOS X patch utility cannot handle these.");
6575 } 6575 }
6576 $hunks++; 6576 $hunks++;
6577 $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); 6577 $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef);
6578 $leading_context_lines = 0; 6578 $leading_context_lines = 0;
6579 $trailing_context_lines = 0; 6579 $trailing_context_lines = 0;
6580 }], [PST_UL, re_patch_uld, PST_UL, sub() { 6580 }], [PST_UL, re_patch_uld, PST_UL, sub() {
6581 $check_hunk_line->(1, 0, PST_UH); 6581 $check_hunk_line->(1, 0, PST_UH);
6582 }], [PST_UL, re_patch_ula, PST_UL, sub() { 6582 }], [PST_UL, re_patch_ula, PST_UL, sub() {
6583 $check_hunk_line->(0, 1, PST_UH); 6583 $check_hunk_line->(0, 1, PST_UH);
6584 }], [PST_UL, re_patch_ulc, PST_UL, sub() { 6584 }], [PST_UL, re_patch_ulc, PST_UL, sub() {
6585 $check_hunk_line->(1, 1, PST_UH); 6585 $check_hunk_line->(1, 1, PST_UH);
6586 }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { 6586 }], [PST_UL, re_patch_ulnonl, PST_UL, sub() {
6587 # 6587 #
6588 }], [PST_UL, re_patch_empty, PST_UL, sub() { 6588 }], [PST_UL, re_patch_empty, PST_UL, sub() {
6589 $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); 6589 $opt_warn_space and $line->log_note("Leading white-space missing in hunk.");
6590 $check_hunk_line->(1, 1, PST_UH); 6590 $check_hunk_line->(1, 1, PST_UH);
6591 }], [PST_UL, undef, PST_UH, sub() { 6591 }], [PST_UL, undef, PST_UH, sub() {
6592 if ($dellines != 0 || $addlines != 0) { 6592 if ($dellines != 0 || $addlines != 0) {
6593 $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); 6593 $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected).");
6594 } 6594 }
6595 }], [PST_UH, undef, PST_TEXT, sub() { 6595 }], [PST_UH, undef, PST_TEXT, sub() {
6596 ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); 6596 ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}.");
6597 }]]; 6597 }]];
6598 6598
6599 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); 6599 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()");
6600 6600
6601 checkperms($fname); 6601 checkperms($fname);
6602 if (!($lines = load_lines($fname, false))) { 6602 if (!($lines = load_lines($fname, false))) {
6603 log_error($fname, NO_LINE_NUMBER, "Could not be read."); 6603 log_error($fname, NO_LINE_NUMBER, "Could not be read.");
6604 return; 6604 return;
6605 } 6605 }
6606 if (@{$lines} == 0) { 6606 if (@{$lines} == 0) {
6607 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 6607 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
6608 return; 6608 return;
6609 } 6609 }
6610 6610
6611 $state = PST_START; 6611 $state = PST_START;
6612 $dellines = undef; 6612 $dellines = undef;
6613 $addlines = undef; 6613 $addlines = undef;
6614 $patched_files = 0; 6614 $patched_files = 0;
6615 $seen_comment = false; 6615 $seen_comment = false;
6616 $current_fname = undef; 6616 $current_fname = undef;
6617 $current_ftype = undef; 6617 $current_ftype = undef;
6618 $hunks = undef; 6618 $hunks = undef;
6619 6619
6620 for (my $lineno = 0; $lineno <= $#{$lines}; ) { 6620 for (my $lineno = 0; $lineno <= $#{$lines}; ) {
6621 $line = $lines->[$lineno]; 6621 $line = $lines->[$lineno];
6622 my $text = $line->text; 6622 my $text = $line->text;
6623 6623
6624 $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); 6624 $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text");
6625 6625
6626 my $found = false; 6626 my $found = false;
6627 foreach my $t (@{$transitions}) { 6627 foreach my $t (@{$transitions}) {
6628 if ($state == $t->[0]) { 6628 if ($state == $t->[0]) {
6629 if (!defined($t->[1])) { 6629 if (!defined($t->[1])) {
6630 $m = undef; 6630 $m = undef;
6631 } elsif ($text =~ $t->[1]) { 6631 } elsif ($text =~ $t->[1]) {
6632 $opt_debug_patches and $line->log_debug($t->[1]); 6632 $opt_debug_patches and $line->log_debug($t->[1]);
6633 $m = PkgLint::SimpleMatch->new($text, \@-, \@+); 6633 $m = PkgLint::SimpleMatch->new($text, \@-, \@+);
6634 } else { 6634 } else {
6635 next; 6635 next;
6636 } 6636 }
6637 $redostate = undef; 6637 $redostate = undef;
6638 $nextstate = $t->[2]; 6638 $nextstate = $t->[2];
6639 $t->[3]->(); 6639 $t->[3]->();
6640 if (defined($redostate)) { 6640 if (defined($redostate)) {
6641 $state = $redostate; 6641 $state = $redostate;
6642 } else { 6642 } else {
6643 $state = $nextstate; 6643 $state = $nextstate;
6644 if (defined($t->[1])) { 6644 if (defined($t->[1])) {
6645 $lineno++; 6645 $lineno++;
6646 } 6646 }
6647 } 6647 }
6648 $found = true; 6648 $found = true;
6649 last; 6649 last;
6650 } 6650 }
6651 } 6651 }
6652 6652
6653 if (!$found) { 6653 if (!$found) {
6654 $line->log_error("Parse error: state=${state}"); 6654 $line->log_error("Parse error: state=${state}");
6655 $state = PST_TEXT; 6655 $state = PST_TEXT;
6656 $lineno++; 6656 $lineno++;
6657 } 6657 }
6658 } 6658 }
6659 6659
6660 while ($state != PST_TEXT) { 6660 while ($state != PST_TEXT) {
6661 $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); 6661 $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]");
6662 6662
6663 my $found = false; 6663 my $found = false;
6664 foreach my $t (@{$transitions}) { 6664 foreach my $t (@{$transitions}) {
6665 if ($state == $t->[0] && !defined($t->[1])) { 6665 if ($state == $t->[0] && !defined($t->[1])) {
6666 my $newstate; 6666 my $newstate;
6667 6667
6668 $m = undef; 6668 $m = undef;
6669 $redostate = undef; 6669 $redostate = undef;
6670 $nextstate = $t->[2]; 6670 $nextstate = $t->[2];
6671 $t->[3]->(); 6671 $t->[3]->();
6672 $newstate = (defined($redostate)) ? $redostate : $nextstate; 6672 $newstate = (defined($redostate)) ? $redostate : $nextstate;
6673 if ($newstate == $state) { 6673 if ($newstate == $state) {
6674 log_fatal($fname, "EOF", "Internal error in the patch transition table."); 6674 log_fatal($fname, "EOF", "Internal error in the patch transition table.");
6675 } 6675 }
6676 $state = $newstate; 6676 $state = $newstate;
6677 $found = true; 6677 $found = true;
6678 last; 6678 last;
6679 } 6679 }
6680 } 6680 }
6681 6681
6682 if (!$found) { 6682 if (!$found) {
6683 log_error($fname, "EOF", "Parse error: state=${state}"); 6683 log_error($fname, "EOF", "Parse error: state=${state}");
6684 $state = PST_TEXT; 6684 $state = PST_TEXT;
6685 } 6685 }
6686 } 6686 }
6687 6687
6688 if ($patched_files > 1) { 6688 if ($patched_files > 1) {
6689 log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); 6689 log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one.");
6690 6690
6691 } elsif ($patched_files == 0) { 6691 } elsif ($patched_files == 0) {
6692 log_error($fname, NO_LINE_NUMBER, "Contains no patch."); 6692 log_error($fname, NO_LINE_NUMBER, "Contains no patch.");
6693 } 6693 }
6694 6694
6695 checklines_trailing_empty_lines($lines); 6695 checklines_trailing_empty_lines($lines);
6696} 6696}
6697 6697
6698sub checkfile_PLIST($) { 6698sub checkfile_PLIST($) {
6699 my ($fname) = @_; 6699 my ($fname) = @_;
6700 my ($lines, $last_file_seen); 6700 my ($lines, $last_file_seen);
6701 6701
6702 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); 6702 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()");
6703 6703
6704 checkperms($fname); 6704 checkperms($fname);
6705 if (!($lines = load_file($fname))) { 6705 if (!($lines = load_file($fname))) {
6706 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 6706 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
6707 return; 6707 return;
6708 } 6708 }
6709 if (@{$lines} == 0) { 6709 if (@{$lines} == 0) {
6710 log_error($fname, NO_LINE_NUMBER, "Must not be empty."); 6710 log_error($fname, NO_LINE_NUMBER, "Must not be empty.");
6711 return; 6711 return;
6712 } 6712 }
6713 checkline_rcsid($lines->[0], "\@comment "); 6713 checkline_rcsid($lines->[0], "\@comment ");
6714 6714
6715 if (@$lines == 1) { 6715 if (@$lines == 1) {
6716 $lines->[0]->log_warning("PLIST files shouldn't be empty."); 6716 $lines->[0]->log_warning("PLIST files shouldn't be empty.");
6717 $lines->[0]->explain_warning( 6717 $lines->[0]->explain_warning(
6718"One reason for empty PLISTs is that this is a newly created package", 6718"One reason for empty PLISTs is that this is a newly created package",
6719"and that the author didn't run \"bmake print-PLIST\" after installing", 6719"and that the author didn't run \"bmake print-PLIST\" after installing",
6720"the files.", 6720"the files.",
6721"", 6721"",
6722"Another reason, common for Perl packages, is that the final PLIST is", 6722"Another reason, common for Perl packages, is that the final PLIST is",
6723"automatically generated. Since the source PLIST is not used at all,", 6723"automatically generated. Since the source PLIST is not used at all,",
6724"you can remove it.", 6724"you can remove it.",
6725"", 6725"",
6726"Meta packages also don't need a PLIST file."); 6726"Meta packages also don't need a PLIST file.");
6727 } 6727 }
6728 6728
6729 # Get the list of all files from the PLIST. 6729 # Get the list of all files from the PLIST.
6730 my $all_files = {}; 6730 my $all_files = {};
6731 my $all_dirs = {}; 6731 my $all_dirs = {};
6732 my $extra_lines = []; 6732 my $extra_lines = [];
6733 if (basename($fname) eq "PLIST.common_end") { 6733 if (basename($fname) eq "PLIST.common_end") {
6734 my $common_lines = load_file(dirname($fname) . "/PLIST.common"); 6734 my $common_lines = load_file(dirname($fname) . "/PLIST.common");
6735 if ($common_lines) { 6735 if ($common_lines) {
6736 $extra_lines = $common_lines; 6736 $extra_lines = $common_lines;
6737 } 6737 }
6738 } 6738 }
6739 6739
6740 foreach my $line (@{$extra_lines}, @{$lines}) { 6740 foreach my $line (@{$extra_lines}, @{$lines}) {
6741 my $text = $line->text; 6741 my $text = $line->text;
6742 6742
6743 if ($text =~ m"\$\{([\w_]+)\}(.*)") { 6743 if ($text =~ m"\$\{([\w_]+)\}(.*)") {
6744 if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { 6744 if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) {
6745 $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); 6745 $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1.");
6746 $text = $2; 6746 $text = $2;
6747 } 6747 }
6748 } 6748 }
6749  6749
6750 if ($text =~ m"^[\w\$]") { 6750 if ($text =~ m"^[\w\$]") {
6751 $all_files->{$text} = $line; 6751 $all_files->{$text} = $line;
6752 my $dir = $text; 6752 my $dir = $text;
6753 while ($dir =~ s,/[^/]+$,,) { 6753 while ($dir =~ s,/[^/]+$,,) {
6754 $all_dirs->{$dir} = $line; 6754 $all_dirs->{$dir} = $line;
6755 } 6755 }
6756 } 6756 }
6757 if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { 6757 if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") {
6758 my $dir = $1; 6758 my $dir = $1;
6759 do { 6759 do {
6760 $all_dirs->{$dir} = $line; 6760 $all_dirs->{$dir} = $line;
6761 } while ($dir =~ s,/[^/]+$,,); 6761 } while ($dir =~ s,/[^/]+$,,);
6762 } 6762 }
6763 } 6763 }
6764 6764
6765 foreach my $line (@{$lines}) { 6765 foreach my $line (@{$lines}) {
6766 my $text = $line->text; 6766 my $text = $line->text;
6767 6767
6768 if ($text =~ /\s$/) { 6768 if ($text =~ /\s$/) {
6769 $line->log_error("pkgsrc does not support filenames ending in white-space."); 6769 $line->log_error("pkgsrc does not support filenames ending in white-space.");
6770 $line->explain_error( 6770 $line->explain_error(
6771"Each character in the PLIST is relevant, even trailing white-space."); 6771"Each character in the PLIST is relevant, even trailing white-space.");
6772 } 6772 }
6773 6773
6774 # @foo directives. 6774 # @foo directives.
6775 if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { 6775 if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) {
6776 my ($cmd, $arg) = ($1, $2); 6776 my ($cmd, $arg) = ($1, $2);
6777 6777
6778 if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { 6778 if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") {
6779 my ($rmdir, $rest) = ($1, $2); 6779 my ($rmdir, $rest) = ($1, $2);
6780 if ($rest !~ m"(?:true|\$\{TRUE\})") { 6780 if ($rest !~ m"(?:true|\$\{TRUE\})") {
6781 $line->log_warning("Please remove this line. It is no longer necessary."); 6781 $line->log_warning("Please remove this line. It is no longer necessary.");
6782 } 6782 }
6783 6783
6784 } elsif (($cmd eq "exec" || $cmd eq "unexec")) { 6784 } elsif (($cmd eq "exec" || $cmd eq "unexec")) {
6785 if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { 6785 if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) {
6786 $line->log_warning("\@exec/unexec install-info is deprecated."); 6786 $line->log_warning("\@exec/unexec install-info is deprecated.");
6787 6787
6788 } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { 6788 } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") {
6789 $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); 6789 $line->log_error("ldconfig must be used with \"||/usr/bin/true\".");
6790 } 6790 }
6791 6791
6792 } elsif ($cmd eq "comment") { 6792 } elsif ($cmd eq "comment") {
6793 # nothing to do 6793 # nothing to do
6794 6794
6795 } elsif ($cmd eq "dirrm") { 6795 } elsif ($cmd eq "dirrm") {
6796 $line->log_warning("\@dirrm is obsolete. Please remove this line."); 6796 $line->log_warning("\@dirrm is obsolete. Please remove this line.");
6797 $line->explain_warning( 6797 $line->explain_warning(
6798"Directories are removed automatically when they are empty.", 6798"Directories are removed automatically when they are empty.",
6799"When a package needs an empty directory, it can use the \@pkgdir", 6799"When a package needs an empty directory, it can use the \@pkgdir",
6800"command in the PLIST"); 6800"command in the PLIST");
6801 } elsif ($cmd eq "imake-man") { 6801 } elsif ($cmd eq "imake-man") {
6802 my (@args) = split(/\s+/, $arg); 6802 my (@args) = split(/\s+/, $arg);
6803 if (@args != 3) { 6803 if (@args != 3) {
6804 $line->log_warning("Invalid number of arguments for imake-man."); 6804 $line->log_warning("Invalid number of arguments for imake-man.");
6805 } else { 6805 } else {
6806 if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { 6806 if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") {
6807 warn_about_PLIST_imake_mannewsuffix($line); 6807 warn_about_PLIST_imake_mannewsuffix($line);
6808 } 6808 }
6809 } 6809 }
6810 6810
6811 } elsif ($cmd eq "pkgdir") { 6811 } elsif ($cmd eq "pkgdir") {
6812 # TODO: What can we check here? 6812 # TODO: What can we check here?
6813 6813
6814 } else { 6814 } else {
6815 $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); 6815 $line->log_warning("Unknown PLIST directive \"\@$cmd\".");
6816 } 6816 }
6817 6817
6818 # Pathnames. 6818 # Pathnames.
6819 } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { 6819 } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") {
6820 my ($dirname, $basename) = ($1, $2); 6820 my ($dirname, $basename) = ($1, $2);
6821 6821
6822 if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { 6822 if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) {
6823 if (defined($last_file_seen)) { 6823 if (defined($last_file_seen)) {
6824 if ($last_file_seen gt $text) { 6824 if ($last_file_seen gt $text) {
6825 $line->log_warning("${text} should be sorted before ${last_file_seen}."); 6825 $line->log_warning("${text} should be sorted before ${last_file_seen}.");
6826 $line->explain_warning( 6826 $line->explain_warning(
6827"For aesthetic reasons, the files in the PLIST should be sorted", 6827"For aesthetic reasons, the files in the PLIST should be sorted",
6828"alphabetically."); 6828"alphabetically.");
6829 } elsif ($last_file_seen eq $text) { 6829 } elsif ($last_file_seen eq $text) {
6830 $line->log_warning("Duplicate filename."); 6830 $line->log_warning("Duplicate filename.");
6831 } 6831 }
6832 } 6832 }
6833 $last_file_seen = $text; 6833 $last_file_seen = $text;
6834 } 6834 }
6835 6835
6836 if ($basename =~ m"\$\{IMAKE_MANNEWSUFFIX\}") { 6836 if ($basename =~ m"\$\{IMAKE_MANNEWSUFFIX\}") {
6837 warn_about_PLIST_imake_mannewsuffix($line); 6837 warn_about_PLIST_imake_mannewsuffix($line);
6838 } 6838 }
6839 6839
6840 if ($dirname =~ m"^bin/") { 6840 if ($dirname =~ m"^bin/") {
6841 $line->log_warning("The bin/ directory should not have subdirectories."); 6841 $line->log_warning("The bin/ directory should not have subdirectories.");
6842 6842
6843 } elsif ($dirname eq "bin") { 6843 } elsif ($dirname eq "bin") {
6844 6844
6845 if (exists($all_files->{"man/man1/${basename}.1"})) { 6845 if (exists($all_files->{"man/man1/${basename}.1"})) {
6846 # Fine. 6846 # Fine.
6847 } elsif (exists($all_files->{"man/man6/${basename}.6"})) { 6847 } elsif (exists($all_files->{"man/man6/${basename}.6"})) {
6848 # Fine. 6848 # Fine.
6849 } elsif (exists($all_files->{"\${IMAKE_MAN_DIR}/${basename}.\${IMAKE_MANNEWSUFFIX}"})) { 6849 } elsif (exists($all_files->{"\${IMAKE_MAN_DIR}/${basename}.\${IMAKE_MANNEWSUFFIX}"})) {
6850 # Fine. 6850 # Fine.
6851 } else { 6851 } else {
6852 $opt_warn_extra and $line->log_warning("Manual page missing for bin/${basename}."); 6852 $opt_warn_extra and $line->log_warning("Manual page missing for bin/${basename}.");
6853 $opt_warn_extra and $line->explain_warning( 6853 $opt_warn_extra and $line->explain_warning(
6854"All programs that can be run directly by the user should have a manual", 6854"All programs that can be run directly by the user should have a manual",
6855"page for quick reference. The programs in the bin/ directory should have", 6855"page for quick reference. The programs in the bin/ directory should have",
6856"corresponding manual pages in section 1 (filename program.1), not in", 6856"corresponding manual pages in section 1 (filename program.1), not in",
6857"section 8."); 6857"section 8.");
6858 } 6858 }
6859 6859
6860 } elsif ($text =~ m"^doc/") { 6860 } elsif ($text =~ m"^doc/") {
6861 $line->log_error("Documentation must be installed under share/doc, not doc."); 6861 $line->log_error("Documentation must be installed under share/doc, not doc.");
6862 6862
6863 } elsif ($text =~ m"^etc/rc\.d/") { 6863 } elsif ($text =~ m"^etc/rc\.d/") {
6864 $line->log_error("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework."); 6864 $line->log_error("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework.");
6865 6865
6866 } elsif ($text =~ m"^etc/") { 6866 } elsif ($text =~ m"^etc/") {
6867 my $f = "mk/pkginstall/bsd.pkginstall.mk"; 6867 my $f = "mk/pkginstall/bsd.pkginstall.mk";
6868 6868
6869 assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file."); 6869 assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file.");
6870 $line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}."); 6870 $line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}.");
6871 6871
6872 } elsif ($text =~ m"^include/.*\.(?:h|hpp)$") { 6872 } elsif ($text =~ m"^include/.*\.(?:h|hpp)$") {
6873 # Fine. 6873 # Fine.
6874 6874
6875 } elsif ($text eq "info/dir") { 6875 } elsif ($text eq "info/dir") {
6876 $line->log_error("\"info/dir\" must not be listed. Use install-info to add/remove an entry."); 6876 $line->log_error("\"info/dir\" must not be listed. Use install-info to add/remove an entry.");
6877 6877
6878 } elsif ($text =~ m"^info/.+$") { 6878 } elsif ($text =~ m"^info/.+$") {
6879 if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"INFO_FILES"})) { 6879 if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"INFO_FILES"})) {
6880 $line->log_warning("Packages that install info files should set INFO_FILES."); 6880 $line->log_warning("Packages that install info files should set INFO_FILES.");
6881 } 6881 }
6882 6882
6883 } elsif (defined($effective_pkgbase) && $text =~ m"^lib/\Q${effective_pkgbase}\E/") { 6883 } elsif (defined($effective_pkgbase) && $text =~ m"^lib/\Q${effective_pkgbase}\E/") {
6884 # Fine. 6884 # Fine.
6885 6885
6886 } elsif ($text =~ m"^lib/locale/") { 6886 } elsif ($text =~ m"^lib/locale/") {
6887 $line->log_error("\"lib/locale\" must not be listed. Use \${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead."); 6887 $line->log_error("\"lib/locale\" must not be listed. Use \${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead.");
6888 6888
6889 } elsif ($text =~ m"^(lib/(?:.*/)*)([^/]+)\.(so|a|la)$") { 6889 } elsif ($text =~ m"^(lib/(?:.*/)*)([^/]+)\.(so|a|la)$") {
6890 my ($dir, $lib, $ext) = ($1, $2, $3); 6890 my ($dir, $lib, $ext) = ($1, $2, $3);
6891 6891
6892 if ($dir eq "lib/" && $lib !~ m"^lib") { 6892 if ($dir eq "lib/" && $lib !~ m"^lib") {
6893 $opt_warn_extra and $line->log_warning("Library filename does not start with \"lib\"."); 6893 $opt_warn_extra and $line->log_warning("Library filename does not start with \"lib\".");
6894 } 6894 }
6895 if ($ext eq "la") { 6895 if ($ext eq "la") {
6896 if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_LIBTOOL"})) { 6896 if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_LIBTOOL"})) {
6897 $line->log_warning("Packages that install libtool libraries should define USE_LIBTOOL."); 6897 $line->log_warning("Packages that install libtool libraries should define USE_LIBTOOL.");
6898 } 6898 }
6899 } 6899 }
6900 6900
6901 } elsif ($text =~ m"^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$") { 6901 } elsif ($text =~ m"^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$") {
6902 my ($cat_or_man, $section, $manpage, $ext, $gz) = ($1, $2, $3, $4, $5); 6902 my ($cat_or_man, $section, $manpage, $ext, $gz) = ($1, $2, $3, $4, $5);
6903 6903
6904 if ($section !~ m"^[\dln]$") { 6904 if ($section !~ m"^[\dln]$") {
6905 $line->log_warning("Unknown section \"${section}\" for manual page."); 6905 $line->log_warning("Unknown section \"${section}\" for manual page.");
6906 } 6906 }
6907 6907
6908 if ($cat_or_man eq "cat" && !exists($all_files->{"man/man${section}/${manpage}.${section}"})) { 6908 if ($cat_or_man eq "cat" && !exists($all_files->{"man/man${section}/${manpage}.${section}"})) {
6909 $line->log_warning("Preformatted manual page without unformatted one."); 6909 $line->log_warning("Preformatted manual page without unformatted one.");
6910 } 6910 }
6911 6911
6912 if ($cat_or_man eq "cat") { 6912 if ($cat_or_man eq "cat") {
6913 if ($ext ne "0") { 6913 if ($ext ne "0") {
6914 $line->log_warning("Preformatted manual pages should end in \".0\"."); 6914 $line->log_warning("Preformatted manual pages should end in \".0\".");
6915 } 6915 }
6916 } else { 6916 } else {
6917 if ($section ne $ext) { 6917 if ($section ne $ext) {
6918 $line->log_warning("Mismatch between the section (${section}) and extension (${ext}) of the manual page."); 6918 $line->log_warning("Mismatch between the section (${section}) and extension (${ext}) of the manual page.");
6919 } 6919 }
6920 } 6920 }
6921 6921
6922 if (defined($gz)) { 6922 if (defined($gz)) {
6923 $line->log_note("The .gz extension is unnecessary for manual pages."); 6923 $line->log_note("The .gz extension is unnecessary for manual pages.");
6924 $line->explain_note( 6924 $line->explain_note(
6925"Whether the manual pages are installed in compressed form or not is", 6925"Whether the manual pages are installed in compressed form or not is",
6926"configured by the pkgsrc user. Compression and decompression takes place", 6926"configured by the pkgsrc user. Compression and decompression takes place",
6927"automatically, no matter if the .gz extension is mentioned in the PLIST", 6927"automatically, no matter if the .gz extension is mentioned in the PLIST",
6928"or not."); 6928"or not.");
6929 } 6929 }
6930 6930
6931 } elsif ($text =~ m"^man/cat") { 6931 } elsif ($text =~ m"^man/cat") {
6932 $line->log_warning("Invalid filename \"${text}\" for preformatted manual page."); 6932 $line->log_warning("Invalid filename \"${text}\" for preformatted manual page.");
6933 6933
6934 } elsif ($text =~ m"^man/man") { 6934 } elsif ($text =~ m"^man/man") {
6935 $line->log_warning("Invalid filename \"${text}\" for unformatted manual page."); 6935 $line->log_warning("Invalid filename \"${text}\" for unformatted manual page.");
6936 6936
6937 } elsif ($text =~ m"^sbin/(.*)") { 6937 } elsif ($text =~ m"^sbin/(.*)") {
6938 my ($binname) = ($1); 6938 my ($binname) = ($1);
6939 6939
6940 if (!exists($all_files->{"man/man8/${binname}.8"})) { 6940 if (!exists($all_files->{"man/man8/${binname}.8"})) {
6941 $opt_warn_extra and $line->log_warning("Manual page missing for sbin/${binname}."); 6941 $opt_warn_extra and $line->log_warning("Manual page missing for sbin/${binname}.");
6942 $opt_warn_extra and $line->explain_warning( 6942 $opt_warn_extra and $line->explain_warning(
6943"All programs that can be run directly by the user should have a manual", 6943"All programs that can be run directly by the user should have a manual",
6944"page for quick reference. The programs in the sbin/ directory should have", 6944"page for quick reference. The programs in the sbin/ directory should have",
6945"corresponding manual pages in section 8 (filename program.8), not in", 6945"corresponding manual pages in section 8 (filename program.8), not in",
6946"section 1."); 6946"section 1.");
6947 } 6947 }
6948 6948
6949 } elsif ($text =~ m"^share/applications/.*\.desktop$") { 6949 } elsif ($text =~ m"^share/applications/.*\.desktop$") {
6950 my $f = "../../sysutils/desktop-file-utils/desktopdb.mk"; 6950 my $f = "../../sysutils/desktop-file-utils/desktopdb.mk";
6951 if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { 6951 if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) {
6952 $line->log_warning("Packages that install a .desktop entry may .include \"$f\"."); 6952 $line->log_warning("Packages that install a .desktop entry may .include \"$f\".");
6953 $line->explain_warning( 6953 $line->explain_warning(
6954"If *.desktop files contain MimeType keys, global MIME Type registory DB", 6954"If *.desktop files contain MimeType keys, global MIME Type registory DB",
6955"must be updated by desktop-file-utils.", 6955"must be updated by desktop-file-utils.",
6956"Otherwise, this warning is harmless."); 6956"Otherwise, this warning is harmless.");
6957 } 6957 }
6958 6958
6959 } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor(?:$|/)") { 6959 } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor(?:$|/)") {
6960 my $f = "../../graphics/hicolor-icon-theme/buildlink3.mk"; 6960 my $f = "../../graphics/hicolor-icon-theme/buildlink3.mk";
6961 if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { 6961 if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) {
6962 $line->log_error("Please .include \"$f\" in the Makefile"); 6962 $line->log_error("Please .include \"$f\" in the Makefile");
6963 $line->explain_error( 6963 $line->explain_error(
6964"If hicolor icon themes are installed, icon theme cache must be", 6964"If hicolor icon themes are installed, icon theme cache must be",
6965"maintained. The hicolor-icon-theme package takes care of that."); 6965"maintained. The hicolor-icon-theme package takes care of that.");
6966 } 6966 }
6967 6967
6968 } elsif ($pkgpath ne "graphics/gnome-icon-theme" && $text =~ m"^share/icons/gnome(?:$|/)") { 6968 } elsif ($pkgpath ne "graphics/gnome-icon-theme" && $text =~ m"^share/icons/gnome(?:$|/)") {
6969 my $f = "../../graphics/gnome-icon-theme/buildlink3.mk"; 6969 my $f = "../../graphics/gnome-icon-theme/buildlink3.mk";
6970 if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { 6970 if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) {
6971 $line->log_error("Please .include \"$f\""); 6971 $line->log_error("Please .include \"$f\"");
6972 $line->explain_error( 6972 $line->explain_error(
6973"If Gnome icon themes are installed, icon theme cache must be maintained."); 6973"If Gnome icon themes are installed, icon theme cache must be maintained.");
6974 } 6974 }
6975 } elsif ($dirname eq "share/aclocal" && $basename =~ m"\.m4$") { 6975 } elsif ($dirname eq "share/aclocal" && $basename =~ m"\.m4$") {
6976 # Fine. 6976 # Fine.
6977 6977
6978 } elsif ($text =~ m"^share/doc/html/") { 6978 } elsif ($text =~ m"^share/doc/html/") {
6979 $opt_warn_plist_depr and $line->log_warning("Use of \"share/doc/html\" is deprecated. Use \"share/doc/\${PKGBASE}\" instead."); 6979 $opt_warn_plist_depr and $line->log_warning("Use of \"share/doc/html\" is deprecated. Use \"share/doc/\${PKGBASE}\" instead.");
6980 6980
6981 } elsif (defined($effective_pkgbase) && $text =~ m"^share/doc/\Q${effective_pkgbase}\E/") { 6981 } elsif (defined($effective_pkgbase) && $text =~ m"^share/doc/\Q${effective_pkgbase}\E/") {
6982 # Fine. 6982 # Fine.
6983 6983
6984 } elsif (defined($effective_pkgbase) && $text =~ m"^share/examples/\Q${effective_pkgbase}\E/") { 6984 } elsif (defined($effective_pkgbase) && $text =~ m"^share/examples/\Q${effective_pkgbase}\E/") {
6985 # Fine. 6985 # Fine.
6986 6986
6987 } elsif (defined($effective_pkgbase) && $text =~ m"^share/\Q${effective_pkgbase}\E/") { 6987 } elsif (defined($effective_pkgbase) && $text =~ m"^share/\Q${effective_pkgbase}\E/") {
6988 # Fine. 6988 # Fine.
6989 6989
6990 } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor/icon-theme\.cache") { 6990 } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor/icon-theme\.cache") {
6991 $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line."); 6991 $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line.");
6992 6992
6993 } elsif ($text =~ m"^share/info/") { 6993 } elsif ($text =~ m"^share/info/") {
6994 $line->log_warning("Info pages should be installed into info/, not share/info/."); 6994 $line->log_warning("Info pages should be installed into info/, not share/info/.");
6995 $line->explain_warning( 6995 $line->explain_warning(
6996"To fix this, you should add INFO_FILES=yes to the package Makefile."); 6996"To fix this, you should add INFO_FILES=yes to the package Makefile.");
6997 6997
6998 } elsif ($text =~ m"^share/locale/[\w\@_]+/LC_MESSAGES/[^/]+\.mo$") { 6998 } elsif ($text =~ m"^share/locale/[\w\@_]+/LC_MESSAGES/[^/]+\.mo$") {
6999 # Fine. 6999 # Fine.
7000 7000
7001 } elsif ($text =~ m"^share/man/") { 7001 } elsif ($text =~ m"^share/man/") {
7002 $line->log_warning("Man pages should be installed into man/, not share/man/."); 7002 $line->log_warning("Man pages should be installed into man/, not share/man/.");
7003 7003
7004 } else { 7004 } else {
7005 $opt_debug_unchecked and $line->log_debug("Unchecked pathname \"${text}\"."); 7005 $opt_debug_unchecked and $line->log_debug("Unchecked pathname \"${text}\".");
7006 } 7006 }
7007 7007
7008 if ($text =~ /\${PKGLOCALEDIR}/ && defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_PKGLOCALEDIR"})) { 7008 if ($text =~ /\${PKGLOCALEDIR}/ && defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_PKGLOCALEDIR"})) {
7009 $line->log_warning("PLIST contains \${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found."); 7009 $line->log_warning("PLIST contains \${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found.");
7010 } 7010 }
7011 7011
7012 if ($text =~ m"/CVS/") { 7012 if ($text =~ m"/CVS/") {
7013 $line->log_warning("CVS files should not be in the PLIST."); 7013 $line->log_warning("CVS files should not be in the PLIST.");
7014 } 7014 }
7015 if ($text =~ m"\.orig$") { 7015 if ($text =~ m"\.orig$") {
7016 $line->log_warning(".orig files should not be in the PLIST."); 7016 $line->log_warning(".orig files should not be in the PLIST.");
7017 } 7017 }
7018 if ($text =~ m"/perllocal\.pod$") { 7018 if ($text =~ m"/perllocal\.pod$") {
7019 $line->log_warning("perllocal.pod files should not be in the PLIST."); 7019 $line->log_warning("perllocal.pod files should not be in the PLIST.");
7020 $line->explain_warning( 7020 $line->explain_warning(
7021"This file is handled automatically by the INSTALL/DEINSTALL scripts,", 7021"This file is handled automatically by the INSTALL/DEINSTALL scripts,",
7022"since its contents changes frequently."); 7022"since its contents changes frequently.");
7023 } 7023 }
7024 7024
7025 if ($text =~ m"^(.*)(\.a|\.so[0-9.]*)$") { 7025 if ($text =~ m"^(.*)(\.a|\.so[0-9.]*)$") {
7026 my ($basename, $ext) = ($1, $2); 7026 my ($basename, $ext) = ($1, $2);
7027 7027
7028 if (exists($all_files->{"${basename}.la"})) { 7028 if (exists($all_files->{"${basename}.la"})) {
7029 $line->log_warning("Redundant library found. The libtool library is in line " . $all_files->{"${basename}.la"}->lines . "."); 7029 $line->log_warning("Redundant library found. The libtool library is in line " . $all_files->{"${basename}.la"}->lines . ".");
7030 } 7030 }
7031 } 7031 }
7032 7032
7033 } elsif ($text =~ m"^\$\{[\w_]+\}$") { 7033 } elsif ($text =~ m"^\$\{[\w_]+\}$") {
7034 # A variable on its own line. 7034 # A variable on its own line.
7035 7035
7036 } else { 7036 } else {
7037 $line->log_error("Unknown line type."); 7037 $line->log_error("Unknown line type.");
7038 } 7038 }
7039 } 7039 }
7040 checklines_trailing_empty_lines($lines); 7040 checklines_trailing_empty_lines($lines);
7041 autofix($lines); 7041 autofix($lines);
7042} 7042}
7043 7043
7044sub checkfile($) { 7044sub checkfile($) {
7045 my ($fname) = @_; 7045 my ($fname) = @_;
7046 my ($st, $basename); 7046 my ($st, $basename);
7047 7047
7048 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile()"); 7048 $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile()");
7049 7049
7050 $basename = basename($fname); 7050 $basename = basename($fname);
7051 if ($basename =~ m"^(?:work.*|.*~|.*\.orig|.*\.rej)$") { 7051 if ($basename =~ m"^(?:work.*|.*~|.*\.orig|.*\.rej)$") {
7052 if ($opt_import) { 7052 if ($opt_import) {
7053 log_error($fname, NO_LINE_NUMBER, "Must be cleaned up before committing the package."); 7053 log_error($fname, NO_LINE_NUMBER, "Must be cleaned up before committing the package.");
7054 } 7054 }
7055 return; 7055 return;
7056 } 7056 }
7057 7057
7058 if (!($st = lstat($fname))) { 7058 if (!($st = lstat($fname))) {
7059 log_error($fname, NO_LINE_NUMBER, "$!"); 7059 log_error($fname, NO_LINE_NUMBER, "$!");
7060 return; 7060 return;
7061 } 7061 }
7062 if (S_ISDIR($st->mode)) { 7062 if (S_ISDIR($st->mode)) {
7063 if ($basename eq "files" || $basename eq "patches" || $basename eq "CVS") { 7063 if ($basename eq "files" || $basename eq "patches" || $basename eq "CVS") {
7064 # Ok 7064 # Ok
 7065 } elsif ($fname =~ m"(?:^|/)files/[^/]*$") {
 7066 # Ok
7065 7067
7066 } elsif (!is_emptydir($fname)) { 7068 } elsif (!is_emptydir($fname)) {
7067 log_warning($fname, NO_LINE_NUMBER, "Unknown directory name."); 7069 log_warning($fname, NO_LINE_NUMBER, "Unknown directory name.");
7068 } 7070 }
7069 7071
7070 } elsif (S_ISLNK($st->mode)) { 7072 } elsif (S_ISLNK($st->mode)) {
7071 if ($basename !~ m"^work") { 7073 if ($basename !~ m"^work") {
7072 log_warning($fname, NO_LINE_NUMBER, "Unknown symlink name."); 7074 log_warning($fname, NO_LINE_NUMBER, "Unknown symlink name.");
7073 } 7075 }
7074 7076
7075 } elsif (!S_ISREG($st->mode)) { 7077 } elsif (!S_ISREG($st->mode)) {
7076 log_error($fname, NO_LINE_NUMBER, "Only files and directories are allowed in pkgsrc."); 7078 log_error($fname, NO_LINE_NUMBER, "Only files and directories are allowed in pkgsrc.");
7077 7079
7078 } elsif ($basename eq "ALTERNATIVES") { 7080 } elsif ($basename eq "ALTERNATIVES") {
7079 $opt_check_ALTERNATIVES and checkfile_ALTERNATIVES($fname); 7081 $opt_check_ALTERNATIVES and checkfile_ALTERNATIVES($fname);
7080 7082
7081 } elsif ($basename eq "buildlink3.mk") { 7083 } elsif ($basename eq "buildlink3.mk") {
7082 $opt_check_bl3 and checkfile_buildlink3_mk($fname); 7084 $opt_check_bl3 and checkfile_buildlink3_mk($fname);
7083 7085
7084 } elsif ($basename =~ m"^DESCR") { 7086 } elsif ($basename =~ m"^DESCR") {
7085 $opt_check_DESCR and checkfile_DESCR($fname); 7087 $opt_check_DESCR and checkfile_DESCR($fname);
7086 7088
7087 } elsif ($basename =~ m"^distinfo") { 7089 } elsif ($basename =~ m"^distinfo") {
7088 $opt_check_distinfo and checkfile_distinfo($fname); 7090 $opt_check_distinfo and checkfile_distinfo($fname);
7089 7091
7090 } elsif ($basename eq "DEINSTALL" || $basename eq "INSTALL") { 7092 } elsif ($basename eq "DEINSTALL" || $basename eq "INSTALL") {
7091 $opt_check_INSTALL and checkfile_INSTALL($fname); 7093 $opt_check_INSTALL and checkfile_INSTALL($fname);
7092 7094
7093 } elsif ($basename =~ m"^MESSAGE") { 7095 } elsif ($basename =~ m"^MESSAGE") {
7094 $opt_check_MESSAGE and checkfile_MESSAGE($fname); 7096 $opt_check_MESSAGE and checkfile_MESSAGE($fname);
7095 7097
7096 } elsif ($basename =~ m"^patch-[-A-Za-z0-9_.~+]*[A-Za-z0-9_]$") { 7098 } elsif ($basename =~ m"^patch-[-A-Za-z0-9_.~+]*[A-Za-z0-9_]$") {
7097 $opt_check_patches and checkfile_patch($fname); 7099 $opt_check_patches and checkfile_patch($fname);
7098 7100
7099 } elsif ($fname =~ m"(?:^|/)patches/manual[^/]*$") { 7101 } elsif ($fname =~ m"(?:^|/)patches/manual[^/]*$") {
7100 $opt_debug_unchecked and log_debug($fname, NO_LINE_NUMBER, "Unchecked file \"${fname}\"."); 7102 $opt_debug_unchecked and log_debug($fname, NO_LINE_NUMBER, "Unchecked file \"${fname}\".");
7101 7103
7102 } elsif ($fname =~ m"(?:^|/)patches/[^/]*$") { 7104 } elsif ($fname =~ m"(?:^|/)patches/[^/]*$") {
7103 log_warning($fname, NO_LINE_NUMBER, "Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only."); 7105 log_warning($fname, NO_LINE_NUMBER, "Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only.");
7104 7106
7105 } elsif ($basename =~ m"^(?:.*\.mk|Makefile.*)$" and not $fname =~ m,files/, and not $fname =~ m,patches/,) { 7107 } elsif ($basename =~ m"^(?:.*\.mk|Makefile.*)$" and not $fname =~ m,files/, and not $fname =~ m,patches/,) {
7106 $opt_check_mk and checkfile_mk($fname); 7108 $opt_check_mk and checkfile_mk($fname);
7107 7109
7108 } elsif ($basename =~ m"^PLIST") { 7110 } elsif ($basename =~ m"^PLIST") {
7109 $opt_check_PLIST and checkfile_PLIST($fname); 7111 $opt_check_PLIST and checkfile_PLIST($fname);
7110 7112
7111 } elsif ($basename eq "TODO" || $basename eq "README") { 7113 } elsif ($basename eq "TODO" || $basename eq "README") {
7112 # Ok 7114 # Ok
7113 7115
7114 } elsif ($basename =~ m"^CHANGES-.*") { 7116 } elsif ($basename =~ m"^CHANGES-.*") {
7115 load_doc_CHANGES($fname); 7117 load_doc_CHANGES($fname);
7116 7118
7117 } elsif (!-T $fname) { 7119 } elsif (!-T $fname) {
7118 log_warning($fname, NO_LINE_NUMBER, "Unexpectedly found a binary file."); 7120 log_warning($fname, NO_LINE_NUMBER, "Unexpectedly found a binary file.");
7119 7121
 7122 } elsif ($fname =~ m"(?:^|/)files/[^/]*$") {
 7123 # Ok
7120 } else { 7124 } else {
7121 log_warning($fname, NO_LINE_NUMBER, "Unexpected file found."); 7125 log_warning($fname, NO_LINE_NUMBER, "Unexpected file found.");
7122 $opt_check_extra and checkfile_extra($fname); 7126 $opt_check_extra and checkfile_extra($fname);
7123 } 7127 }
7124} 7128}
7125 7129
7126sub my_split($$) { 7130sub my_split($$) {
7127 my ($delimiter, $s) = @_; 7131 my ($delimiter, $s) = @_;
7128 my ($pos, $next, @result); 7132 my ($pos, $next, @result);
7129 7133
7130 $pos = 0; 7134 $pos = 0;
7131 for ($pos = 0; $pos != -1; $pos = $next) { 7135 for ($pos = 0; $pos != -1; $pos = $next) {
7132 $next = index($s, $delimiter, $pos); 7136 $next = index($s, $delimiter, $pos);
7133 push @result, (($next == -1) ? substr($s, $pos) : substr($s, $pos, $next - $pos)); 7137 push @result, (($next == -1) ? substr($s, $pos) : substr($s, $pos, $next - $pos));
7134 if ($next != -1) { 7138 if ($next != -1) {
7135 $next += length($delimiter); 7139 $next += length($delimiter);
7136 } 7140 }
7137 } 7141 }
7138 return @result; 7142 return @result;
7139} 7143}
7140 7144
7141# Checks that the files in the directory are in sync with CVS's status. 7145# Checks that the files in the directory are in sync with CVS's status.
7142# 7146#
7143sub checkdir_CVS($) { 7147sub checkdir_CVS($) {
7144 my ($fname) = @_; 7148 my ($fname) = @_;
7145 7149
7146 my $cvs_entries = load_file("$fname/CVS/Entries"); 7150 my $cvs_entries = load_file("$fname/CVS/Entries");
7147 my $cvs_entries_log = load_file("$fname/CVS/Entries.Log"); 7151 my $cvs_entries_log = load_file("$fname/CVS/Entries.Log");
7148 return unless $cvs_entries; 7152 return unless $cvs_entries;
7149 7153
7150 foreach my $line (@$cvs_entries) { 7154 foreach my $line (@$cvs_entries) {
7151 my ($type, $fname, $mtime, $date, $keyword_mode, $tag, $undef) = my_split("/", $line->text); 7155 my ($type, $fname, $mtime, $date, $keyword_mode, $tag, $undef) = my_split("/", $line->text);
7152 next if ($type eq "D" && !defined($fname)); 7156 next if ($type eq "D" && !defined($fname));
7153 assert($type eq "" || $type eq "D", "Unknown line format: " . $line->text); 7157 assert($type eq "" || $type eq "D", "Unknown line format: " . $line->text);
7154 assert(defined($tag), "Unknown line format: " . $line->text); 7158 assert(defined($tag), "Unknown line format: " . $line->text);
7155 assert(defined($keyword_mode), "Unknown line format: " . $line->text); 7159 assert(defined($keyword_mode), "Unknown line format: " . $line->text);
7156 assert(!defined($undef), "Unknown line format: " . $line->text); 7160 assert(!defined($undef), "Unknown line format: " . $line->text);
7157 } 7161 }
7158} 7162}
7159 7163
7160# 7164#
7161# Procedures to check a directory including the files in it. 7165# Procedures to check a directory including the files in it.
7162# 7166#
7163 7167
7164sub checkdir_root() { 7168sub checkdir_root() {
7165 my ($fname) = "${current_dir}/Makefile"; 7169 my ($fname) = "${current_dir}/Makefile";
7166 my ($lines, $prev_subdir, @subdirs); 7170 my ($lines, $prev_subdir, @subdirs);
7167 7171
7168 $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_root()"); 7172 $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_root()");
7169 7173
7170 if (!($lines = load_lines($fname, true))) { 7174 if (!($lines = load_lines($fname, true))) {
7171 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 7175 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
7172 return; 7176 return;
7173 } 7177 }
7174 7178
7175 parselines_mk($lines); 7179 parselines_mk($lines);
7176 if (0 <= $#{$lines}) { 7180 if (0 <= $#{$lines}) {
7177 checkline_rcsid_regex($lines->[0], qr"#\s+", "# "); 7181 checkline_rcsid_regex($lines->[0], qr"#\s+", "# ");
7178 } 7182 }
7179 7183
7180 foreach my $line (@{$lines}) { 7184 foreach my $line (@{$lines}) {
7181 if ($line->text =~ m"^(#?)SUBDIR\s*\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { 7185 if ($line->text =~ m"^(#?)SUBDIR\s*\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") {
7182 my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); 7186 my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4);
7183 7187
7184 if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { 7188 if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) {
7185 $line->log_warning("${subdir} commented out without giving a reason."); 7189 $line->log_warning("${subdir} commented out without giving a reason.");
7186 } 7190 }
7187 7191
7188 if ($indentation ne "\t") { 7192 if ($indentation ne "\t") {
7189 $line->log_warning("Indentation should be a single tab character."); 7193 $line->log_warning("Indentation should be a single tab character.");
7190 } 7194 }
7191 7195
7192 if ($subdir =~ m"\$" || !-f "${current_dir}/${subdir}/Makefile") { 7196 if ($subdir =~ m"\$" || !-f "${current_dir}/${subdir}/Makefile") {
7193 next; 7197 next;
7194 } 7198 }
7195 7199
7196 if (!defined($prev_subdir) || $subdir gt $prev_subdir) { 7200 if (!defined($prev_subdir) || $subdir gt $prev_subdir) {
7197 # correctly ordered 7201 # correctly ordered
7198 } elsif ($subdir eq $prev_subdir) { 7202 } elsif ($subdir eq $prev_subdir) {
7199 $line->log_error("${subdir} must only appear once."); 7203 $line->log_error("${subdir} must only appear once.");
7200 } elsif ($prev_subdir eq "x11" && $subdir eq "archivers") { 7204 } elsif ($prev_subdir eq "x11" && $subdir eq "archivers") {
7201 # ignore that one, since it is documented in the top-level Makefile 7205 # ignore that one, since it is documented in the top-level Makefile
7202 } else { 7206 } else {
7203 $line->log_warning("${subdir} should come before ${prev_subdir}."); 7207 $line->log_warning("${subdir} should come before ${prev_subdir}.");
7204 } 7208 }
7205 7209
7206 $prev_subdir = $subdir; 7210 $prev_subdir = $subdir;
7207 7211
7208 if ($comment_flag eq "") { 7212 if ($comment_flag eq "") {
7209 push(@subdirs, "${current_dir}/${subdir}"); 7213 push(@subdirs, "${current_dir}/${subdir}");
7210 } 7214 }
7211 } 7215 }
7212 } 7216 }
7213 7217
7214 checklines_mk($lines); 7218 checklines_mk($lines);
7215 7219
7216 if ($opt_recursive) { 7220 if ($opt_recursive) {
7217 $ipc_checking_root_recursively = true; 7221 $ipc_checking_root_recursively = true;
7218 push(@todo_items, @subdirs); 7222 push(@todo_items, @subdirs);
7219 } 7223 }
7220} 7224}
7221 7225
7222sub checkdir_category() { 7226sub checkdir_category() {
7223 my $fname = "${current_dir}/Makefile"; 7227 my $fname = "${current_dir}/Makefile";
7224 my ($lines, $lineno); 7228 my ($lines, $lineno);
7225 7229
7226 $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_category()"); 7230 $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_category()");
7227 7231
7228 if (!($lines = load_lines($fname, true))) { 7232 if (!($lines = load_lines($fname, true))) {
7229 log_error($fname, NO_LINE_NUMBER, "Cannot be read."); 7233 log_error($fname, NO_LINE_NUMBER, "Cannot be read.");
7230 return; 7234 return;
7231 } 7235 }
7232 parselines_mk($lines); 7236 parselines_mk($lines);
7233 7237
7234 $lineno = 0; 7238 $lineno = 0;
7235 7239
7236 # The first line must contain the RCS Id 7240 # The first line must contain the RCS Id
7237 if ($lineno <= $#{$lines} && checkline_rcsid_regex($lines->[$lineno], qr"#\s+", "# ")) { 7241 if ($lineno <= $#{$lines} && checkline_rcsid_regex($lines->[$lineno], qr"#\s+", "# ")) {
7238 $lineno++; 7242 $lineno++;
7239 } 7243 }
7240 7244
7241 # Then, arbitrary comments may follow 7245 # Then, arbitrary comments may follow
7242 while ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^#") { 7246 while ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^#") {
7243 $lineno++; 7247 $lineno++;
7244 } 7248 }
7245 7249
7246 # Then we need an empty line 7250 # Then we need an empty line
7247 expect_empty_line($lines, \$lineno); 7251 expect_empty_line($lines, \$lineno);
7248 7252
7249 # Then comes the COMMENT line 7253 # Then comes the COMMENT line
7250 if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^COMMENT=\t*(.*)") { 7254 if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^COMMENT=\t*(.*)") {
7251 my ($comment) = ($1); 7255 my ($comment) = ($1);
7252 7256
7253 checkline_valid_characters_in_variable($lines->[$lineno], qr"[-\040'(),/0-9A-Za-z]"); 7257 checkline_valid_characters_in_variable($lines->[$lineno], qr"[-\040'(),/0-9A-Za-z]");
7254 $lineno++; 7258 $lineno++;
7255 } else { 7259 } else {
7256 $lines->[$lineno]->log_error("COMMENT= line expected."); 7260 $lines->[$lineno]->log_error("COMMENT= line expected.");
7257 } 7261 }
7258 7262
7259 # Then we need an empty line 7263 # Then we need an empty line
7260 expect_empty_line($lines, \$lineno); 7264 expect_empty_line($lines, \$lineno);
7261 7265
7262 # And now to the most complicated part of the category Makefiles, 7266 # And now to the most complicated part of the category Makefiles,
7263 # the (hopefully) sorted list of SUBDIRs. The first step is to 7267 # the (hopefully) sorted list of SUBDIRs. The first step is to
7264 # collect the SUBDIRs in the Makefile and in the file system. 7268 # collect the SUBDIRs in the Makefile and in the file system.
7265 7269
7266 my (@f_subdirs, @m_subdirs); 7270 my (@f_subdirs, @m_subdirs);
7267 7271
7268 @f_subdirs = sort(get_subdirs($current_dir)); 7272 @f_subdirs = sort(get_subdirs($current_dir));
7269 7273
7270 my $prev_subdir = undef; 7274 my $prev_subdir = undef;
7271 while ($lineno <= $#{$lines}) { 7275 while ($lineno <= $#{$lines}) {
7272 my $line = $lines->[$lineno]; 7276 my $line = $lines->[$lineno];
7273 7277
7274 if ($line->text =~ m"^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { 7278 if ($line->text =~ m"^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") {
7275 my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); 7279 my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4);
7276 7280
7277 if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { 7281 if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) {
7278 $line->log_warning("${subdir} commented out without giving a reason."); 7282 $line->log_warning("${subdir} commented out without giving a reason.");
7279 } 7283 }
7280 7284
7281 if ($indentation ne "\t") { 7285 if ($indentation ne "\t") {
7282 $line->log_warning("Indentation should be a single tab character."); 7286 $line->log_warning("Indentation should be a single tab character.");
7283 } 7287 }
7284 7288
7285 if (defined($prev_subdir) && $subdir eq $prev_subdir) { 7289 if (defined($prev_subdir) && $subdir eq $prev_subdir) {
7286 $line->log_error("${subdir} must only appear once."); 7290 $line->log_error("${subdir} must only appear once.");
7287 } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) { 7291 } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) {
7288 $line->log_warning("${subdir} should come before ${prev_subdir}."); 7292 $line->log_warning("${subdir} should come before ${prev_subdir}.");
7289 } else { 7293 } else {
7290 # correctly ordered 7294 # correctly ordered
7291 } 7295 }
7292 7296
7293 push(@m_subdirs, [$subdir, $line, $comment_flag ? false : true]); 7297 push(@m_subdirs, [$subdir, $line, $comment_flag ? false : true]);
7294 $prev_subdir = $subdir; 7298 $prev_subdir = $subdir;
7295 $lineno++; 7299 $lineno++;
7296 7300
7297 } else { 7301 } else {
7298 if ($line->text ne "") { 7302 if ($line->text ne "") {
7299 $line->log_error("SUBDIR+= line or empty line expected."); 7303 $line->log_error("SUBDIR+= line or empty line expected.");
7300 } 7304 }
7301 last; 7305 last;
7302 } 7306 }
7303 } 7307 }
7304 7308
7305 # To prevent unnecessary warnings about subdirectories that are 7309 # To prevent unnecessary warnings about subdirectories that are
7306 # in one list, but not in the other, we generate the sets of 7310 # in one list, but not in the other, we generate the sets of
7307 # subdirs of each list. 7311 # subdirs of each list.
7308 my (%f_check, %m_check); 7312 my (%f_check, %m_check);
7309 foreach my $f (@f_subdirs) { $f_check{$f} = true; } 7313 foreach my $f (@f_subdirs) { $f_check{$f} = true; }
7310 foreach my $m (@m_subdirs) { $m_check{$m->[0]} = true; } 7314 foreach my $m (@m_subdirs) { $m_check{$m->[0]} = true; }
7311 7315
7312 my ($f_index, $f_atend, $f_neednext, $f_current) = (0, false, true, undef, undef); 7316 my ($f_index, $f_atend, $f_neednext, $f_current) = (0, false, true, undef, undef);
7313 my ($m_index, $m_atend, $m_neednext, $m_current) = (0, false, true, undef, undef); 7317 my ($m_index, $m_atend, $m_neednext, $m_current) = (0, false, true, undef, undef);
7314 my ($line, $m_recurse); 7318 my ($line, $m_recurse);
7315 my (@subdirs); 7319 my (@subdirs);
7316 7320
7317 while (!($m_atend && $f_atend)) { 7321 while (!($m_atend && $f_atend)) {
7318 7322
7319 if (!$m_atend && $m_neednext) { 7323 if (!$m_atend && $m_neednext) {
7320 $m_neednext = false; 7324 $m_neednext = false;
7321 if ($m_index > $#m_subdirs) { 7325 if ($m_index > $#m_subdirs) {
7322 $m_atend = true; 7326 $m_atend = true;
7323 $line = $lines->[$lineno]; 7327 $line = $lines->[$lineno];
7324 next; 7328 next;
7325 } else { 7329 } else {
7326 $m_current = $m_subdirs[$m_index]->[0]; 7330 $m_current = $m_subdirs[$m_index]->[0];
7327 $line = $m_subdirs[$m_index]->[1]; 7331 $line = $m_subdirs[$m_index]->[1];
7328 $m_recurse = $m_subdirs[$m_index]->[2]; 7332 $m_recurse = $m_subdirs[$m_index]->[2];
7329 $m_index++; 7333 $m_index++;
7330 } 7334 }
7331 } 7335 }
7332 7336
7333 if (!$f_atend && $f_neednext) { 7337 if (!$f_atend && $f_neednext) {
7334 $f_neednext = false; 7338 $f_neednext = false;
7335 if ($f_index > $#f_subdirs) { 7339 if ($f_index > $#f_subdirs) {
7336 $f_atend = true; 7340 $f_atend = true;
7337 next; 7341 next;
7338 } else { 7342 } else {
7339 $f_current = $f_subdirs[$f_index++]; 7343 $f_current = $f_subdirs[$f_index++];
7340 } 7344 }
7341 } 7345 }
7342 7346
7343 if (!$f_atend && ($m_atend || $f_current lt $m_current)) { 7347 if (!$f_atend && ($m_atend || $f_current lt $m_current)) {
7344 if (!exists($m_check{$f_current})) { 7348 if (!exists($m_check{$f_current})) {
7345 $line->log_error("${f_current} exists in the file system, but not in the Makefile."); 7349 $line->log_error("${f_current} exists in the file system, but not in the Makefile.");
7346 $line->append_before("SUBDIR+=\t${f_current}"); 7350 $line->append_before("SUBDIR+=\t${f_current}");
7347 } 7351 }
7348 $f_neednext = true; 7352 $f_neednext = true;
7349 7353
7350 } elsif (!$m_atend && ($f_atend || $m_current lt $f_current)) { 7354 } elsif (!$m_atend && ($f_atend || $m_current lt $f_current)) {
7351 if (!exists($f_check{$m_current})) { 7355 if (!exists($f_check{$m_current})) {
7352 $line->log_error("${m_current} exists in the Makefile, but not in the file system."); 7356 $line->log_error("${m_current} exists in the Makefile, but not in the file system.");
7353 $line->delete(); 7357 $line->delete();
7354 } 7358 }
7355 $m_neednext = true; 7359 $m_neednext = true;
7356 7360
7357 } else { # $f_current eq $m_current 7361 } else { # $f_current eq $m_current
7358 $f_neednext = true; 7362 $f_neednext = true;
7359 $m_neednext = true; 7363 $m_neednext = true;
7360 if ($m_recurse) { 7364 if ($m_recurse) {
7361 push(@subdirs, "${current_dir}/${m_current}"); 7365 push(@subdirs, "${current_dir}/${m_current}");
7362 } 7366 }
7363 } 7367 }
7364 } 7368 }
7365 7369
7366 # the wip category Makefile may have its own targets for generating 7370 # the wip category Makefile may have its own targets for generating
7367 # indexes and READMEs. Just skip them. 7371 # indexes and READMEs. Just skip them.
7368 if ($is_wip) { 7372 if ($is_wip) {
7369 while ($lineno <= $#{$lines} - 2) { 7373 while ($lineno <= $#{$lines} - 2) {
7370 $lineno++; 7374 $lineno++;
7371 } 7375 }
7372 } 7376 }
7373 7377
7374 expect_empty_line($lines, \$lineno); 7378 expect_empty_line($lines, \$lineno);
7375 7379
7376 # And, last but not least, the .include line 7380 # And, last but not least, the .include line
7377 my $final_line = ".include \"../mk/bsd.pkg.subdir.mk\""; 7381 my $final_line = ".include \"../mk/bsd.pkg.subdir.mk\"";
7378 expect($lines, \$lineno, qr"\Q$final_line\E") 7382 expect($lines, \$lineno, qr"\Q$final_line\E")
7379 || expect_text($lines, \$lineno, ".include \"../mk/misc/category.mk\""); 7383 || expect_text($lines, \$lineno, ".include \"../mk/misc/category.mk\"");
7380 7384
7381 if ($lineno <= $#{$lines}) { 7385 if ($lineno <= $#{$lines}) {
7382 $lines->[$lineno]->log_error("The file should end here."); 7386 $lines->[$lineno]->log_error("The file should end here.");
7383 } 7387 }
7384 7388
7385 checklines_mk($lines); 7389 checklines_mk($lines);
7386 7390
7387 autofix($lines); 7391 autofix($lines);
7388 7392
7389 if ($opt_recursive) { 7393 if ($opt_recursive) {
7390 unshift(@todo_items, @subdirs); 7394 unshift(@todo_items, @subdirs);
7391 } 7395 }
7392} 7396}
7393 7397
7394sub checkdir_package() { 7398sub checkdir_package() {
7395 my ($lines, $have_distinfo, $have_patches); 7399 my ($lines, $have_distinfo, $have_patches);
7396 7400
7397 # Initialize global variables 7401 # Initialize global variables
7398 $pkgdir = undef; 7402 $pkgdir = undef;
7399 $filesdir = "files"; 7403 $filesdir = "files";
7400 $patchdir = "patches"; 7404 $patchdir = "patches";
7401 $distinfo_file = "distinfo"; 7405 $distinfo_file = "distinfo";
7402 $effective_pkgname = undef; 7406 $effective_pkgname = undef;
7403 $effective_pkgbase = undef; 7407 $effective_pkgbase = undef;
7404 $effective_pkgversion = undef; 7408 $effective_pkgversion = undef;
7405 $effective_pkgname_line = undef; 7409 $effective_pkgname_line = undef;
7406 $seen_bsd_prefs_mk = false; 7410 $seen_bsd_prefs_mk = false;
7407 $pkgctx_vardef = {%{get_userdefined_variables()}}; 7411 $pkgctx_vardef = {%{get_userdefined_variables()}};
7408 $pkgctx_varuse = {}; 7412 $pkgctx_varuse = {};
7409 $pkgctx_bl3 = {}; 7413 $pkgctx_bl3 = {};
7410 $pkgctx_plist_subst_cond = {}; 7414 $pkgctx_plist_subst_cond = {};
7411 $pkgctx_included = {}; 7415 $pkgctx_included = {};
7412 $seen_Makefile_common = false; 7416 $seen_Makefile_common = false;
7413 7417
7414 # we need to handle the Makefile first to get some variables 7418 # we need to handle the Makefile first to get some variables
7415 if (!load_package_Makefile("${current_dir}/Makefile", \$lines)) { 7419 if (!load_package_Makefile("${current_dir}/Makefile", \$lines)) {
7416 log_error("${current_dir}/Makefile", NO_LINE_NUMBER, "Cannot be read."); 7420 log_error("${current_dir}/Makefile", NO_LINE_NUMBER, "Cannot be read.");
7417 goto cleanup; 7421 goto cleanup;
7418 } 7422 }
7419 7423
7420 my @files = <${current_dir}/*>; 7424 my @files = <${current_dir}/*>;
7421 if ($pkgdir ne ".") { 7425 if ($pkgdir ne ".") {
7422 push(@files, <${current_dir}/${pkgdir}/*>); 7426 push(@files, <${current_dir}/${pkgdir}/*>);
7423 } 7427 }
7424 if ($opt_check_extra) { 7428 if ($opt_check_extra) {
7425 push(@files, <${current_dir}/${filesdir}/*>); 7429 push(@files, <${current_dir}/${filesdir}/*>);
7426 } 7430 }
7427 push(@files, <${current_dir}/${patchdir}/*>); 7431 push(@files, <${current_dir}/${patchdir}/*>);
7428 if ($distinfo_file !~ m"^(?:\./)?distinfo$") { 7432 if ($distinfo_file !~ m"^(?:\./)?distinfo$") {
7429 push(@files, "${current_dir}/${distinfo_file}"); 7433 push(@files, "${current_dir}/${distinfo_file}");
7430 } 7434 }
7431 $have_distinfo = false; 7435 $have_distinfo = false;
7432 $have_patches = false; 7436 $have_patches = false;
7433 7437
7434 # Determine the used variables before checking any of the 7438 # Determine the used variables before checking any of the
7435 # Makefile fragments. 7439 # Makefile fragments.
7436 foreach my $fname (@files) { 7440 foreach my $fname (@files) {
7437 if (($fname =~ m"^((?:.*/)?Makefile\..*|.*\.mk)$") 7441 if (($fname =~ m"^((?:.*/)?Makefile\..*|.*\.mk)$")
7438 && (not $fname =~ m"patch-") 7442 && (not $fname =~ m"patch-")
7439 && (not $fname =~ m"${pkgdir}/") 7443 && (not $fname =~ m"${pkgdir}/")
7440 && (not $fname =~ m"${filesdir}/") 7444 && (not $fname =~ m"${filesdir}/")
7441 && (defined(my $lines = load_lines($fname, true)))) { 7445 && (defined(my $lines = load_lines($fname, true)))) {
7442 parselines_mk($lines); 7446 parselines_mk($lines);
7443 determine_used_variables($lines); 7447 determine_used_variables($lines);
7444 } 7448 }
7445 } 7449 }
7446 7450
7447 foreach my $fname (@files) { 7451 foreach my $fname (@files) {
7448 if ($fname eq "${current_dir}/Makefile") { 7452 if ($fname eq "${current_dir}/Makefile") {
7449 $opt_check_Makefile and checkfile_package_Makefile($fname, $lines); 7453 $opt_check_Makefile and checkfile_package_Makefile($fname, $lines);
7450 } else { 7454 } else {
7451 checkfile($fname); 7455 checkfile($fname);
7452 } 7456 }
7453 if ($fname =~ m"/patches/patch-*$") { 7457 if ($fname =~ m"/patches/patch-*$") {
7454 $have_patches = true; 7458 $have_patches = true;
7455 } elsif ($fname =~ m"/distinfo$") { 7459 } elsif ($fname =~ m"/distinfo$") {
7456 $have_distinfo = true; 7460 $have_distinfo = true;
7457 } 7461 }
7458 } 7462 }
7459 7463
7460 if ($opt_check_distinfo && $opt_check_patches) { 7464 if ($opt_check_distinfo && $opt_check_patches) {
7461 if ($have_patches && ! $have_distinfo) { 7465 if ($have_patches && ! $have_distinfo) {
7462 log_warning("${current_dir}/$distinfo_file", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makepatchsum'."); 7466 log_warning("${current_dir}/$distinfo_file", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makepatchsum'.");
7463 } 7467 }
7464 } 7468 }
7465 7469
7466 if (!is_emptydir("${current_dir}/scripts")) { 7470 if (!is_emptydir("${current_dir}/scripts")) {
7467 log_warning("${current_dir}/scripts", NO_LINE_NUMBER, "This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's Makefile."); 7471 log_warning("${current_dir}/scripts", NO_LINE_NUMBER, "This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's Makefile.");
7468 } 7472 }
7469 7473
7470cleanup: 7474cleanup:
7471 # Clean up global variables. 7475 # Clean up global variables.
7472 $pkgdir = undef; 7476 $pkgdir = undef;
7473 $filesdir = undef; 7477 $filesdir = undef;
7474 $patchdir = undef; 7478 $patchdir = undef;
7475 $distinfo_file = undef; 7479 $distinfo_file = undef;
7476 $effective_pkgname = undef; 7480 $effective_pkgname = undef;
7477 $effective_pkgbase = undef; 7481 $effective_pkgbase = undef;
7478 $effective_pkgversion = undef; 7482 $effective_pkgversion = undef;
7479 $effective_pkgname_line = undef; 7483 $effective_pkgname_line = undef;
7480 $seen_bsd_prefs_mk = undef; 7484 $seen_bsd_prefs_mk = undef;
7481 $pkgctx_vardef = undef; 7485 $pkgctx_vardef = undef;
7482 $pkgctx_varuse = undef; 7486 $pkgctx_varuse = undef;
7483 $pkgctx_bl3 = undef; 7487 $pkgctx_bl3 = undef;
7484 $pkgctx_plist_subst_cond = undef; 7488 $pkgctx_plist_subst_cond = undef;
7485 $pkgctx_included = undef; 7489 $pkgctx_included = undef;
7486 $seen_Makefile_common = undef; 7490 $seen_Makefile_common = undef;
7487} 7491}
7488 7492
7489# 7493#
7490# Selecting the proper checking procedures for a directory entry. 7494# Selecting the proper checking procedures for a directory entry.
7491# 7495#
7492 7496
7493sub checkitem($) { 7497sub checkitem($) {
7494 my ($item) = @_; 7498 my ($item) = @_;
7495 my ($st, $is_dir, $is_reg); 7499 my ($st, $is_dir, $is_reg);
7496 7500
7497 if (!($st = lstat($item))) { 7501 if (!($st = lstat($item))) {
7498 log_error($item, NO_LINE_NUMBER, "Does not exist."); 7502 log_error($item, NO_LINE_NUMBER, "Does not exist.");
7499 return; 7503 return;
7500 } 7504 }
7501 7505
7502 $is_dir = S_ISDIR($st->mode); 7506 $is_dir = S_ISDIR($st->mode);
7503 $is_reg = S_ISREG($st->mode); 7507 $is_reg = S_ISREG($st->mode);
7504 if (!$is_reg && !$is_dir) { 7508 if (!$is_reg && !$is_dir) {
7505 log_error($item, NO_LINE_NUMBER, "Must be a file or directory."); 7509 log_error($item, NO_LINE_NUMBER, "Must be a file or directory.");
7506 return; 7510 return;
7507 } 7511 }
7508 7512
7509 $current_dir = $is_dir ? $item : dirname($item); 7513 $current_dir = $is_dir ? $item : dirname($item);
7510 my $abs_current_dir = Cwd::abs_path($current_dir); 7514 my $abs_current_dir = Cwd::abs_path($current_dir);
7511 $is_wip = !$opt_import && ($abs_current_dir =~ m"/wip(?:/|$)"); 7515 $is_wip = !$opt_import && ($abs_current_dir =~ m"/wip(?:/|$)");
7512 $is_internal = ($abs_current_dir =~ m"/mk(?:/|$)"); 7516 $is_internal = ($abs_current_dir =~ m"/mk(?:/|$)");
7513 7517
7514 # Determine the root directory of pkgsrc. By only overwriting 7518 # Determine the root directory of pkgsrc. By only overwriting
7515 # the global variable $cwd_pkgsrcdir when we are checking inside 7519 # the global variable $cwd_pkgsrcdir when we are checking inside
7516 # a pkgsrc tree, the user can specify a tree with the 7520 # a pkgsrc tree, the user can specify a tree with the
7517 # --pkgsrcdir option and then check files (but not directories) 7521 # --pkgsrcdir option and then check files (but not directories)
7518 # outside of any pkgsrc tree. 7522 # outside of any pkgsrc tree.
7519 $cur_pkgsrcdir = undef; 7523 $cur_pkgsrcdir = undef;
7520 $pkgpath = undef; 7524 $pkgpath = undef;
7521 foreach my $d (".", "..", "../..", "../../..") { 7525 foreach my $d (".", "..", "../..", "../../..") {
7522 if (-f "${current_dir}/${d}/mk/bsd.pkg.mk") { 7526 if (-f "${current_dir}/${d}/mk/bsd.pkg.mk") {
7523 $cur_pkgsrcdir = $d; 7527 $cur_pkgsrcdir = $d;
7524 $pkgpath = relative_path("${current_dir}/${d}", $current_dir); 7528 $pkgpath = relative_path("${current_dir}/${d}", $current_dir);
7525 } 7529 }
7526 } 7530 }
7527 if (!defined($cwd_pkgsrcdir) && defined($cur_pkgsrcdir)) { 7531 if (!defined($cwd_pkgsrcdir) && defined($cur_pkgsrcdir)) {
7528 $cwd_pkgsrcdir = "${current_dir}/${cur_pkgsrcdir}"; 7532 $cwd_pkgsrcdir = "${current_dir}/${cur_pkgsrcdir}";
7529 } 7533 }
7530 7534
7531 if (!defined($cwd_pkgsrcdir)) { 7535 if (!defined($cwd_pkgsrcdir)) {
7532 log_error($item, NO_LINE_NUMBER, "Cannot determine the pkgsrc root directory."); 7536 log_error($item, NO_LINE_NUMBER, "Cannot determine the pkgsrc root directory.");
7533 return; 7537 return;
7534 } 7538 }
7535 7539
7536 check_pkglint_version(); # (needs $cwd_pkgsrcdir) 7540 check_pkglint_version(); # (needs $cwd_pkgsrcdir)
7537 7541
7538 return if $is_dir && is_emptydir($item); 7542 return if $is_dir && is_emptydir($item);
7539 7543
7540 if ($is_dir) { 7544 if ($is_dir) {
7541 checkdir_CVS($item); 7545 checkdir_CVS($item);
7542 } 7546 }
7543 7547
7544 if ($is_reg) { 7548 if ($is_reg) {
7545 checkfile($item); 7549 checkfile($item);
7546 7550
7547 } elsif (!defined($cur_pkgsrcdir)) { 7551 } elsif (!defined($cur_pkgsrcdir)) {
7548 log_error($item, NO_LINES, "Cannot check directories outside a pkgsrc tree."); 7552 log_error($item, NO_LINES, "Cannot check directories outside a pkgsrc tree.");
7549 7553
7550 } elsif ($cur_pkgsrcdir eq "../..") { 7554 } elsif ($cur_pkgsrcdir eq "../..") {
7551 checkdir_package(); 7555 checkdir_package();
7552 7556
7553 } elsif ($cur_pkgsrcdir eq "..") { 7557 } elsif ($cur_pkgsrcdir eq "..") {
7554 checkdir_category(); 7558 checkdir_category();
7555 7559
7556 } elsif ($cur_pkgsrcdir eq ".") { 7560 } elsif ($cur_pkgsrcdir eq ".") {
7557 checkdir_root(); 7561 checkdir_root();
7558 7562
7559 } else { 7563 } else {
7560 log_error($item, NO_LINE_NUMBER, "Don't know how to check this directory."); 7564 log_error($item, NO_LINE_NUMBER, "Don't know how to check this directory.");
7561 } 7565 }
7562} 7566}
7563 7567
7564# 7568#
7565# The main program 7569# The main program
7566# 7570#
7567 7571
7568sub main() { 7572sub main() {
7569 7573
7570 $| = true; 7574 $| = true;
7571 parse_command_line(); 7575 parse_command_line();
7572 7576
7573 @todo_items = (@ARGV != 0) ? @ARGV : ("."); 7577 @todo_items = (@ARGV != 0) ? @ARGV : (".");
7574 while (@todo_items != 0) { 7578 while (@todo_items != 0) {
7575 checkitem(shift(@todo_items)); 7579 checkitem(shift(@todo_items));
7576 } 7580 }
7577 7581
7578 if ($ipc_checking_root_recursively) { 7582 if ($ipc_checking_root_recursively) {
7579 check_unused_licenses(); 7583 check_unused_licenses();
7580 } 7584 }
7581 7585
7582 PkgLint::Logging::print_summary_and_exit($opt_quiet); 7586 PkgLint::Logging::print_summary_and_exit($opt_quiet);
7583} 7587}
7584 7588
7585main() unless caller(); 7589main() unless caller();