| @@ -1,1001 +1,1001 @@ | | | @@ -1,1001 +1,1001 @@ |
1 | #! @PERL@ | | 1 | #! @PERL@ |
2 | # $NetBSD: pkglint.pl,v 1.857 2013/08/15 20:30:43 rillig Exp $ | | 2 | # $NetBSD: pkglint.pl,v 1.858 2013/08/31 18:14:28 rillig Exp $ |
3 | # | | 3 | # |
4 | | | 4 | |
5 | # pkglint - static analyzer and checker for pkgsrc packages | | 5 | # pkglint - static analyzer and checker for pkgsrc packages |
6 | # | | 6 | # |
7 | # Written by: | | 7 | # Written by: |
8 | # Roland Illig <rillig@NetBSD.org> | | 8 | # Roland Illig <rillig@NetBSD.org> |
9 | # | | 9 | # |
10 | # Based on work by: | | 10 | # Based on work by: |
11 | # Hubert Feyrer <hubertf@NetBSD.org> | | 11 | # Hubert Feyrer <hubertf@NetBSD.org> |
12 | # Thorsten Frueauf <frueauf@NetBSD.org> | | 12 | # Thorsten Frueauf <frueauf@NetBSD.org> |
13 | # Thomas Klausner <wiz@NetBSD.org> | | 13 | # Thomas Klausner <wiz@NetBSD.org> |
14 | # and others. | | 14 | # and others. |
15 | # | | 15 | # |
16 | # Based on FreeBSD's portlint by: | | 16 | # Based on FreeBSD's portlint by: |
17 | # Jun-ichiro itojun Hagino <itojun@itojun.org> | | 17 | # Jun-ichiro itojun Hagino <itojun@itojun.org> |
18 | # Yoshishige Arai <ryo2@on.rim.or.jp> | | 18 | # Yoshishige Arai <ryo2@on.rim.or.jp> |
19 | # | | 19 | # |
20 | # FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp | | 20 | # FreeBSD Id: portlint.pl,v 1.64 1998/02/28 02:34:05 itojun Exp |
21 | # Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. | | 21 | # Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>. |
22 | # All rights reserved. | | 22 | # All rights reserved. |
23 | # Freely redistributable. Absolutely no warranty. | | 23 | # Freely redistributable. Absolutely no warranty. |
24 | | | 24 | |
25 | # To get an overview of the code, run: | | 25 | # To get an overview of the code, run: |
26 | # sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl | | 26 | # sed -n -e 's,^\(sub .*\) {.*, \1,p' -e '/^package/p' pkglint.pl |
27 | | | 27 | |
28 | #========================================================================== | | 28 | #========================================================================== |
29 | # Note: The @EXPORT clauses in the packages must be in a BEGIN block, | | 29 | # Note: The @EXPORT clauses in the packages must be in a BEGIN block, |
30 | # because otherwise the names starting with an uppercase letter are not | | 30 | # because otherwise the names starting with an uppercase letter are not |
31 | # recognized as subroutines but as file handles. | | 31 | # recognized as subroutines but as file handles. |
32 | #========================================================================== | | 32 | #========================================================================== |
33 | | | 33 | |
34 | use strict; | | 34 | use strict; |
35 | use warnings; | | 35 | use warnings; |
36 | | | 36 | |
37 | use PkgLint::Util; | | 37 | use PkgLint::Util; |
38 | use PkgLint::Logging; | | 38 | use PkgLint::Logging; |
39 | use PkgLint::SimpleMatch; | | 39 | use PkgLint::SimpleMatch; |
40 | use PkgLint::Line; | | 40 | use PkgLint::Line; |
41 | use PkgLint::FileUtil; | | 41 | use PkgLint::FileUtil; |
42 | use PkgLint::Type; | | 42 | use PkgLint::Type; |
43 | use PkgLint::VarUseContext; | | 43 | use PkgLint::VarUseContext; |
44 | use PkgLint::SubstContext; | | 44 | use PkgLint::SubstContext; |
45 | use PkgLint::CVS_Entry; | | 45 | use PkgLint::CVS_Entry; |
46 | use PkgLint::Change; | | 46 | use PkgLint::Change; |
47 | | | 47 | |
48 | package pkglint; | | 48 | package 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 | #========================================================================== |
76 | use strict; | | 76 | use strict; |
77 | use warnings; | | 77 | use warnings; |
78 | | | 78 | |
79 | use Data::Dumper; | | 79 | use Data::Dumper; |
80 | use Digest::SHA1; | | 80 | use Digest::SHA1; |
81 | use Getopt::Long qw(:config no_ignore_case bundling require_order); | | 81 | use Getopt::Long qw(:config no_ignore_case bundling require_order); |
82 | use Fcntl qw(:mode); | | 82 | use Fcntl qw(:mode); |
83 | use File::Basename; | | 83 | use File::Basename; |
84 | use File::stat; | | 84 | use File::stat; |
85 | use Cwd; | | 85 | use Cwd; |
86 | use pkgsrc::Dewey; | | 86 | use pkgsrc::Dewey; |
87 | | | 87 | |
88 | BEGIN { | | 88 | BEGIN { |
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 | |
121 | use constant conf_distver => '@DISTVER@'; | | 121 | use constant conf_distver => '@DISTVER@'; |
122 | use constant conf_make => '@MAKE@'; | | 122 | use constant conf_make => '@MAKE@'; |
123 | use constant conf_datadir => '@DATADIR@'; | | 123 | use 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. |
131 | my $cwd_pkgsrcdir = undef; | | 131 | my $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. |
135 | my $cur_pkgsrcdir = undef; | | 135 | my $cur_pkgsrcdir = undef; |
136 | | | 136 | |
137 | # | | 137 | # |
138 | # Command Line Options | | 138 | # Command Line Options |
139 | # | | 139 | # |
140 | | | 140 | |
141 | my $opt_check_ALTERNATIVES = true; | | 141 | my $opt_check_ALTERNATIVES = true; |
142 | my $opt_check_bl3 = true; | | 142 | my $opt_check_bl3 = true; |
143 | my $opt_check_DESCR = true; | | 143 | my $opt_check_DESCR = true; |
144 | my $opt_check_distinfo = true; | | 144 | my $opt_check_distinfo = true; |
145 | my $opt_check_extra = false; | | 145 | my $opt_check_extra = false; |
146 | my $opt_check_global = false; | | 146 | my $opt_check_global = false; |
147 | my $opt_check_INSTALL = true; | | 147 | my $opt_check_INSTALL = true; |
148 | my $opt_check_Makefile = true; | | 148 | my $opt_check_Makefile = true; |
149 | my $opt_check_MESSAGE = true; | | 149 | my $opt_check_MESSAGE = true; |
150 | my $opt_check_mk = true; | | 150 | my $opt_check_mk = true; |
151 | my $opt_check_patches = true; | | 151 | my $opt_check_patches = true; |
152 | my $opt_check_PLIST = true; | | 152 | my $opt_check_PLIST = true; |
153 | my (%checks) = ( | | 153 | my (%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 | |
168 | my $opt_debug_include = false; | | 168 | my $opt_debug_include = false; |
169 | my $opt_debug_misc = false; | | 169 | my $opt_debug_misc = false; |
170 | my $opt_debug_patches = false; | | 170 | my $opt_debug_patches = false; |
171 | my $opt_debug_quoting = false; | | 171 | my $opt_debug_quoting = false; |
172 | my $opt_debug_shell = false; | | 172 | my $opt_debug_shell = false; |
173 | my $opt_debug_tools = false; | | 173 | my $opt_debug_tools = false; |
174 | my $opt_debug_trace = false; | | 174 | my $opt_debug_trace = false; |
175 | my $opt_debug_unchecked = false; | | 175 | my $opt_debug_unchecked = false; |
176 | my $opt_debug_unused = false; | | 176 | my $opt_debug_unused = false; |
177 | my $opt_debug_vartypes = false; | | 177 | my $opt_debug_vartypes = false; |
178 | my $opt_debug_varuse = false; | | 178 | my $opt_debug_varuse = false; |
179 | my (%debug) = ( | | 179 | my (%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 | |
193 | my $opt_warn_absname = true; | | 193 | my $opt_warn_absname = true; |
194 | my $opt_warn_directcmd = true; | | 194 | my $opt_warn_directcmd = true; |
195 | our $opt_warn_extra = false; # used by PkgLint::SubstContext | | 195 | our $opt_warn_extra = false; # used by PkgLint::SubstContext |
196 | my $opt_warn_order = true; | | 196 | my $opt_warn_order = true; |
197 | my $opt_warn_perm = false; | | 197 | my $opt_warn_perm = false; |
198 | my $opt_warn_plist_depr = false; | | 198 | my $opt_warn_plist_depr = false; |
199 | my $opt_warn_plist_sort = false; | | 199 | my $opt_warn_plist_sort = false; |
200 | my $opt_warn_quoting = false; | | 200 | my $opt_warn_quoting = false; |
201 | my $opt_warn_space = false; | | 201 | my $opt_warn_space = false; |
202 | my $opt_warn_style = false; | | 202 | my $opt_warn_style = false; |
203 | my $opt_warn_types = true; | | 203 | my $opt_warn_types = true; |
204 | my $opt_warn_varorder = false; | | 204 | my $opt_warn_varorder = false; |
205 | my (%warnings) = ( | | 205 | my (%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 | |
220 | my $opt_autofix = false; | | 220 | my $opt_autofix = false; |
221 | my $opt_dumpmakefile = false; | | 221 | my $opt_dumpmakefile = false; |
222 | my $opt_import = false; | | 222 | my $opt_import = false; |
223 | my $opt_quiet = false; | | 223 | my $opt_quiet = false; |
224 | my $opt_recursive = false; | | 224 | my $opt_recursive = false; |
225 | my $opt_rcsidstring = "NetBSD"; | | 225 | my $opt_rcsidstring = "NetBSD"; |
226 | my (@options) = ( | | 226 | my (@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 | |
288 | our $program = $0; | | 288 | our $program = $0; |
289 | | | 289 | |
290 | # | | 290 | # |
291 | # Commonly used regular expressions. | | 291 | # Commonly used regular expressions. |
292 | # | | 292 | # |
293 | | | 293 | |
294 | use constant regex_dependency_gt => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d])+)>=(\d[^-]*)$"; | | 294 | use constant regex_dependency_gt => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d])+)>=(\d[^-]*)$"; |
295 | use constant regex_dependency_wildcard | | 295 | use constant regex_dependency_wildcard |
296 | => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d\[])+)-(?:\[0-9\]\*|\d[^-]*)$"; | | 296 | => qr"^((?:\$\{[\w_]+\}|[\w_\.]|-[^\d\[])+)-(?:\[0-9\]\*|\d[^-]*)$"; |
297 | use constant regex_gnu_configure_volatile_vars | | 297 | use constant regex_gnu_configure_volatile_vars |
298 | => qr"^(?:.*_)?(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$"; | | 298 | => qr"^(?:.*_)?(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$"; |
299 | use constant regex_mk_comment => qr"^ *\s*#(.*)$"; | | 299 | use constant regex_mk_comment => qr"^ *\s*#(.*)$"; |
300 | use constant regex_mk_cond => qr"^\.(\s*)(if|ifdef|ifndef|else|elif|endif|for|endfor|undef)(?:\s+([^\s#][^#]*?))?\s*(?:#.*)?$"; | | 300 | use constant regex_mk_cond => qr"^\.(\s*)(if|ifdef|ifndef|else|elif|endif|for|endfor|undef)(?:\s+([^\s#][^#]*?))?\s*(?:#.*)?$"; |
301 | use constant regex_mk_dependency=> qr"^([^\s:]+(?:\s*[^\s:]+)*)(\s*):\s*([^#]*?)(?:\s*#.*)?$"; | | 301 | use constant regex_mk_dependency=> qr"^([^\s:]+(?:\s*[^\s:]+)*)(\s*):\s*([^#]*?)(?:\s*#.*)?$"; |
302 | use constant regex_mk_include => qr"^\.\s*(s?include)\s+\"([^\"]+)\"\s*(?:#.*)?$"; | | 302 | use constant regex_mk_include => qr"^\.\s*(s?include)\s+\"([^\"]+)\"\s*(?:#.*)?$"; |
303 | use constant regex_mk_sysinclude=> qr"^\.\s*s?include\s+<([^>]+)>\s*(?:#.*)?$"; | | 303 | use constant regex_mk_sysinclude=> qr"^\.\s*s?include\s+<([^>]+)>\s*(?:#.*)?$"; |
304 | use constant regex_mk_shellvaruse => qr"(?:^|[^\$])\$\$\{?(\w+)\}?"; # XXX: not perfect | | 304 | use constant regex_mk_shellvaruse => qr"(?:^|[^\$])\$\$\{?(\w+)\}?"; # XXX: not perfect |
305 | use constant regex_pkgname => qr"^([\w\-.+]+)-(\d(?:\w|\.\d)*)$"; | | 305 | use constant regex_pkgname => qr"^([\w\-.+]+)-(\d(?:\w|\.\d)*)$"; |
306 | use constant regex_mk_shellcmd => qr"^\t(.*)$"; | | 306 | use constant regex_mk_shellcmd => qr"^\t(.*)$"; |
307 | use constant regex_rcs_conflict => qr"^(<<<<<<<|=======|>>>>>>>)"; | | 307 | use constant regex_rcs_conflict => qr"^(<<<<<<<|=======|>>>>>>>)"; |
308 | use constant regex_unresolved => qr"\$\{"; | | 308 | use constant regex_unresolved => qr"\$\{"; |
309 | use constant regex_validchars => qr"[\011\040-\176]"; | | 309 | use 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. |
314 | use constant regex_varassign => qr"^ *([-*+A-Z_a-z0-9.\${}\[]+?)\s*(=|\?=|\+=|:=|!=)\s*((?:[^\\#\s]+|\s+?|(?:\\#)+|\\)*?)(?:\s*(#.*))?$"; | | 314 | use constant regex_varassign => qr"^ *([-*+A-Z_a-z0-9.\${}\[]+?)\s*(=|\?=|\+=|:=|!=)\s*((?:[^\\#\s]+|\s+?|(?:\\#)+|\\)*?)(?:\s*(#.*))?$"; |
315 | use constant regex_sh_varassign => qr"^([A-Z_a-z][0-9A-Z_a-z]*)="; | | 315 | use 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. |
324 | my $regex_shellword = qr"\s*( | | 324 | my $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; |
344 | my $regex_varname = qr"(?:[-*+.0-9A-Z_a-z{}\[]+|\$\{[\w_]+\})+"; | | 344 | my $regex_varname = qr"(?:[-*+.0-9A-Z_a-z{}\[]+|\$\{[\w_]+\})+"; |
345 | my $regex_pkgbase = qr"(?:[+.0-9A-Z_a-z]|-[A-Z_a-z])+"; | | 345 | my $regex_pkgbase = qr"(?:[+.0-9A-Z_a-z]|-[A-Z_a-z])+"; |
346 | my $regex_pkgversion = qr"\d(?:\w|\.\d)*"; | | 346 | my $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 | |
352 | use constant expl_relative_dirs => ( | | 352 | use 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 | |
361 | my $current_dir; # The currently checked directory. | | 361 | my $current_dir; # The currently checked directory. |
362 | my $is_wip; # Is the current directory from pkgsrc-wip? | | 362 | my $is_wip; # Is the current directory from pkgsrc-wip? |
363 | my $is_internal; # Is the current item from the infrastructure? | | 363 | my $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 | |
369 | my $ipc_distinfo; # Maps "$alg:$fname" => "checksum". | | 369 | my $ipc_distinfo; # Maps "$alg:$fname" => "checksum". |
370 | | | 370 | |
371 | # Context of the package that is currently checked. | | 371 | # Context of the package that is currently checked. |
372 | my $pkgpath; # The relative path to the package within PKGSRC. | | 372 | my $pkgpath; # The relative path to the package within PKGSRC. |
373 | my $pkgdir; # PKGDIR from the package Makefile | | 373 | my $pkgdir; # PKGDIR from the package Makefile |
374 | my $filesdir; # FILESDIR from the package Makefile | | 374 | my $filesdir; # FILESDIR from the package Makefile |
375 | my $patchdir; # PATCHDIR from the package Makefile | | 375 | my $patchdir; # PATCHDIR from the package Makefile |
376 | my $distinfo_file; # DISTINFO_FILE from the package Makefile | | 376 | my $distinfo_file; # DISTINFO_FILE from the package Makefile |
377 | my $effective_pkgname; # PKGNAME or DISTNAME from the package Makefile | | 377 | my $effective_pkgname; # PKGNAME or DISTNAME from the package Makefile |
378 | my $effective_pkgbase; # The effective PKGNAME without the version | | 378 | my $effective_pkgbase; # The effective PKGNAME without the version |
379 | my $effective_pkgversion; # The version part of the effective PKGNAME | | 379 | my $effective_pkgversion; # The version part of the effective PKGNAME |
380 | my $effective_pkgname_line; # The origin of the three effective_* values | | 380 | my $effective_pkgname_line; # The origin of the three effective_* values |
381 | my $seen_bsd_prefs_mk; # Has bsd.prefs.mk already been included? | | 381 | my $seen_bsd_prefs_mk; # Has bsd.prefs.mk already been included? |
382 | | | 382 | |
383 | my $pkgctx_vardef; # { varname => line } | | 383 | my $pkgctx_vardef; # { varname => line } |
384 | my $pkgctx_varuse; # { varname => line } | | 384 | my $pkgctx_varuse; # { varname => line } |
385 | my $pkgctx_bl3; # { buildlink3.mk name => line } (contains | | 385 | my $pkgctx_bl3; # { buildlink3.mk name => line } (contains |
386 | # only buildlink3.mk files that are directly | | 386 | # only buildlink3.mk files that are directly |
387 | # included) | | 387 | # included) |
388 | my $pkgctx_plist_subst_cond; # { varname => 1 } list of all variables | | 388 | my $pkgctx_plist_subst_cond; # { varname => 1 } list of all variables |
389 | # that are used as conditionals (@comment | | 389 | # that are used as conditionals (@comment |
390 | # or nothing) in PLISTs. | | 390 | # or nothing) in PLISTs. |
391 | my $pkgctx_included; # { fname => line } | | 391 | my $pkgctx_included; # { fname => line } |
392 | my $seen_Makefile_common; # Does the package have any .includes? | | 392 | my $seen_Makefile_common; # Does the package have any .includes? |
393 | | | 393 | |
394 | # Context of the Makefile that is currently checked. | | 394 | # Context of the Makefile that is currently checked. |
395 | my $mkctx_for_variables; # The variables currently used in .for loops | | 395 | my $mkctx_for_variables; # The variables currently used in .for loops |
396 | my $mkctx_indentations; # Indentation depth of preprocessing directives | | 396 | my $mkctx_indentations; # Indentation depth of preprocessing directives |
397 | my $mkctx_target; # Current make(1) target | | 397 | my $mkctx_target; # Current make(1) target |
398 | my $mkctx_vardef; # { varname => line } for all variables that | | 398 | my $mkctx_vardef; # { varname => line } for all variables that |
399 | # are defined in the current file | | 399 | # are defined in the current file |
400 | my $mkctx_varuse; # { varname => line } for all variables | | 400 | my $mkctx_varuse; # { varname => line } for all variables |
401 | # that are used in the current file | | 401 | # that are used in the current file |
402 | my $mkctx_build_defs; # Set of variables that are registered in | | 402 | my $mkctx_build_defs; # Set of variables that are registered in |
403 | # BUILD_DEFS, to assure that all user-defined | | 403 | # BUILD_DEFS, to assure that all user-defined |
404 | # variables are added to it. | | 404 | # variables are added to it. |
405 | my $mkctx_plist_vars; # The same for PLIST_VARS. | | 405 | my $mkctx_plist_vars; # The same for PLIST_VARS. |
406 | my $mkctx_tools; # Set of tools that are declared to be used. | | 406 | my $mkctx_tools; # Set of tools that are declared to be used. |
407 | | | 407 | |
408 | my @todo_items; # The list of directory entries that still need | | 408 | my @todo_items; # The list of directory entries that still need |
409 | # to be checked. Mostly relevant with | | 409 | # to be checked. Mostly relevant with |
410 | # --recursive. | | 410 | # --recursive. |
411 | | | 411 | |
412 | # | | 412 | # |
413 | # Command line parsing and handling. | | 413 | # Command line parsing and handling. |
414 | # | | 414 | # |
415 | | | 415 | |
416 | sub help($$$) { | | 416 | sub help($$$) { |
417 | my ($out, $exitval, $show_all) = @_; | | 417 | my ($out, $exitval, $show_all) = @_; |
418 | my ($prog) = (basename($program, '.pl')); | | 418 | my ($prog) = (basename($program, '.pl')); |
419 | print $out ("usage: $prog [options] [package_directory]\n\n"); | | 419 | print $out ("usage: $prog [options] [package_directory]\n\n"); |
420 | | | 420 | |
421 | my (@option_table) = (); | | 421 | my (@option_table) = (); |
422 | foreach my $opt (@options) { | | 422 | foreach my $opt (@options) { |
423 | push(@option_table, [" ", $opt->[0], $opt->[1]]); | | 423 | push(@option_table, [" ", $opt->[0], $opt->[1]]); |
424 | } | | 424 | } |
425 | print $out ("options:\n"); | | 425 | print $out ("options:\n"); |
426 | PkgLint::Util::print_table($out, \@option_table); | | 426 | PkgLint::Util::print_table($out, \@option_table); |
427 | print $out ("\n"); | | 427 | print $out ("\n"); |
428 | | | 428 | |
429 | if (!$show_all) { | | 429 | if (!$show_all) { |
430 | exit($exitval); | | 430 | exit($exitval); |
431 | } | | 431 | } |
432 | | | 432 | |
433 | my $categories = [ | | 433 | my $categories = [ |
434 | # options, leading text, | | 434 | # options, leading text, |
435 | [ \%checks, "checks", "check" ], | | 435 | [ \%checks, "checks", "check" ], |
436 | [ \%debug, "debugging options", "debug" ], | | 436 | [ \%debug, "debugging options", "debug" ], |
437 | [ \%warnings, "warnings", "warning" ], | | 437 | [ \%warnings, "warnings", "warning" ], |
438 | ]; | | 438 | ]; |
439 | foreach my $category (@{$categories}) { | | 439 | foreach my $category (@{$categories}) { |
440 | my ($options, $leading, $name) = (@{$category}); | | 440 | my ($options, $leading, $name) = (@{$category}); |
441 | my $table = [ | | 441 | my $table = [ |
442 | [" ", "all", "", "enable all ".$category->[1]], | | 442 | [" ", "all", "", "enable all ".$category->[1]], |
443 | [" ", "none", "", "disable all ".$category->[1]], | | 443 | [" ", "none", "", "disable all ".$category->[1]], |
444 | ]; | | 444 | ]; |
445 | | | 445 | |
446 | foreach my $opt (sort keys %{$options}) { | | 446 | foreach my $opt (sort keys %{$options}) { |
447 | push(@{$table}, [ " ", $opt, | | 447 | push(@{$table}, [ " ", $opt, |
448 | (${$options->{$opt}->[0]} ? "(enabled)" : "(disabled)"), | | 448 | (${$options->{$opt}->[0]} ? "(enabled)" : "(disabled)"), |
449 | $options->{$opt}->[1]]); | | 449 | $options->{$opt}->[1]]); |
450 | } | | 450 | } |
451 | | | 451 | |
452 | print $out ("${leading}: (use \"${name}\" to enable, \"no-${name}\" to disable)\n"); | | 452 | print $out ("${leading}: (use \"${name}\" to enable, \"no-${name}\" to disable)\n"); |
453 | PkgLint::Util::print_table($out, $table); | | 453 | PkgLint::Util::print_table($out, $table); |
454 | print $out ("\n"); | | 454 | print $out ("\n"); |
455 | } | | 455 | } |
456 | | | 456 | |
457 | exit($exitval); | | 457 | exit($exitval); |
458 | } | | 458 | } |
459 | | | 459 | |
460 | sub parse_multioption($$) { | | 460 | sub parse_multioption($$) { |
461 | my ($value, $optdefs) = @_; | | 461 | my ($value, $optdefs) = @_; |
462 | foreach my $opt (split(qr",", $value)) { | | 462 | foreach my $opt (split(qr",", $value)) { |
463 | if ($opt eq "none") { | | 463 | if ($opt eq "none") { |
464 | foreach my $key (keys %{$optdefs}) { | | 464 | foreach my $key (keys %{$optdefs}) { |
465 | ${$optdefs->{$key}->[0]} = false; | | 465 | ${$optdefs->{$key}->[0]} = false; |
466 | } | | 466 | } |
467 | | | 467 | |
468 | } elsif ($opt eq "all") { | | 468 | } elsif ($opt eq "all") { |
469 | foreach my $key (keys %{$optdefs}) { | | 469 | foreach my $key (keys %{$optdefs}) { |
470 | ${$optdefs->{$key}->[0]} = true; | | 470 | ${$optdefs->{$key}->[0]} = true; |
471 | } | | 471 | } |
472 | | | 472 | |
473 | } else { | | 473 | } else { |
474 | my ($value) = (($opt =~ s/^no-//) ? false : true); | | 474 | my ($value) = (($opt =~ s/^no-//) ? false : true); |
475 | if (exists($optdefs->{$opt})) { | | 475 | if (exists($optdefs->{$opt})) { |
476 | ${$optdefs->{$opt}->[0]} = $value; | | 476 | ${$optdefs->{$opt}->[0]} = $value; |
477 | } else { | | 477 | } else { |
478 | print STDERR ("Invalid option: ${opt}\n"); | | 478 | print STDERR ("Invalid option: ${opt}\n"); |
479 | help(*STDERR, 1, 0); | | 479 | help(*STDERR, 1, 0); |
480 | } | | 480 | } |
481 | } | | 481 | } |
482 | } | | 482 | } |
483 | } | | 483 | } |
484 | | | 484 | |
485 | sub parse_command_line() { | | 485 | sub parse_command_line() { |
486 | my (%options); | | 486 | my (%options); |
487 | | | 487 | |
488 | foreach my $opt (@options) { | | 488 | foreach my $opt (@options) { |
489 | $options{$opt->[2]} = $opt->[3]; | | 489 | $options{$opt->[2]} = $opt->[3]; |
490 | } | | 490 | } |
491 | | | 491 | |
492 | { | | 492 | { |
493 | local $SIG{__WARN__} = sub {}; | | 493 | local $SIG{__WARN__} = sub {}; |
494 | if (!GetOptions(%options)) { | | 494 | if (!GetOptions(%options)) { |
495 | help(*STDERR, 1, false); | | 495 | help(*STDERR, 1, false); |
496 | } | | 496 | } |
497 | } | | 497 | } |
498 | } | | 498 | } |
499 | | | 499 | |
500 | # | | 500 | # |
501 | # Caching subroutines. | | 501 | # Caching subroutines. |
502 | # | | 502 | # |
503 | | | 503 | |
504 | # The get_regex_plurals() function returns a regular expression that | | 504 | # The get_regex_plurals() function returns a regular expression that |
505 | # matches for all make(1) variable names that are considered lists | | 505 | # matches for all make(1) variable names that are considered lists |
506 | # of something. | | 506 | # of something. |
507 | # | | 507 | # |
508 | # Rationale: | | 508 | # Rationale: |
509 | # | | 509 | # |
510 | # The pkglint author thinks that variables containing lists of things | | 510 | # The pkglint author thinks that variables containing lists of things |
511 | # should have a name indicating some plural form. Sadly, there are other | | 511 | # should have a name indicating some plural form. Sadly, there are other |
512 | # reasons like backwards compatibility and other developer's | | 512 | # reasons like backwards compatibility and other developer's |
513 | # expectations that make changes to most of the following variables | | 513 | # expectations that make changes to most of the following variables |
514 | # highly unlikely. | | 514 | # highly unlikely. |
515 | my $get_regex_plurals_value = undef; | | 515 | my $get_regex_plurals_value = undef; |
516 | sub get_regex_plurals() { | | 516 | sub get_regex_plurals() { |
517 | | | 517 | |
518 | if (defined($get_regex_plurals_value)) { | | 518 | if (defined($get_regex_plurals_value)) { |
519 | return $get_regex_plurals_value; | | 519 | return $get_regex_plurals_value; |
520 | } | | 520 | } |
521 | | | 521 | |
522 | my @plurals_ok = qw( | | 522 | my @plurals_ok = qw( |
523 | .*S | | 523 | .*S |
524 | .*LIST | | 524 | .*LIST |
525 | .*_AWK | | 525 | .*_AWK |
526 | .*_ENV | | 526 | .*_ENV |
527 | .*_REQD | | 527 | .*_REQD |
528 | .*_SED | | 528 | .*_SED |
529 | .*_SKIP | | 529 | .*_SKIP |
530 | BUILDLINK_LDADD | | 530 | BUILDLINK_LDADD |
531 | COMMENT | | 531 | COMMENT |
532 | EXTRACT_ONLY | | 532 | EXTRACT_ONLY |
533 | FETCH_MESSAGE | | 533 | FETCH_MESSAGE |
534 | GENERATE_PLIST | | 534 | GENERATE_PLIST |
535 | PLIST_CAT | | 535 | PLIST_CAT |
536 | PLIST_PRE | | 536 | PLIST_PRE |
537 | PREPEND_PATH | | 537 | PREPEND_PATH |
538 | ); | | 538 | ); |
539 | my @plurals_missing_an_s = qw( | | 539 | my @plurals_missing_an_s = qw( |
540 | .*_OVERRIDE | | 540 | .*_OVERRIDE |
541 | .*_PREREQ | | 541 | .*_PREREQ |
542 | .*_SRC | | 542 | .*_SRC |
543 | .*_SUBST | | 543 | .*_SUBST |
544 | .*_TARGET | | 544 | .*_TARGET |
545 | .*_TMPL | | 545 | .*_TMPL |
546 | BUILDLINK_DEPMETHOD | | 546 | BUILDLINK_DEPMETHOD |
547 | BUILDLINK_TRANSFORM | | 547 | BUILDLINK_TRANSFORM |
548 | EVAL_PREFIX | | 548 | EVAL_PREFIX |
549 | INTERACTIVE_STAGE | | 549 | INTERACTIVE_STAGE |
550 | LICENSE | | 550 | LICENSE |
551 | MASTER_SITE_.* | | 551 | MASTER_SITE_.* |
552 | MASTER_SORT_REGEX | | 552 | MASTER_SORT_REGEX |
553 | NOT_FOR_COMPILER | | 553 | NOT_FOR_COMPILER |
554 | NOT_FOR_PLATFORM | | 554 | NOT_FOR_PLATFORM |
555 | ONLY_FOR_COMPILER | | 555 | ONLY_FOR_COMPILER |
556 | ONLY_FOR_PLATFORM | | 556 | ONLY_FOR_PLATFORM |
557 | PERL5_PACKLIST | | 557 | PERL5_PACKLIST |
558 | PKG_FAIL_REASON | | 558 | PKG_FAIL_REASON |
559 | PKG_SKIP_REASON | | 559 | PKG_SKIP_REASON |
560 | ); | | 560 | ); |
561 | my @plurals_reluctantly_accepted = qw( | | 561 | my @plurals_reluctantly_accepted = qw( |
562 | CRYPTO | | 562 | CRYPTO |
563 | DEINSTALL_TEMPLATE | | 563 | DEINSTALL_TEMPLATE |
564 | FIX_RPATH | | 564 | FIX_RPATH |
565 | INSTALL_TEMPLATE | | 565 | INSTALL_TEMPLATE |
566 | PYTHON_VERSIONS_INCOMPATIBLE | | 566 | PYTHON_VERSIONS_INCOMPATIBLE |
567 | REPLACE_INTERPRETER | | 567 | REPLACE_INTERPRETER |
568 | REPLACE_PERL | | 568 | REPLACE_PERL |
569 | REPLACE_RUBY | | 569 | REPLACE_RUBY |
570 | RESTRICTED | | 570 | RESTRICTED |
571 | SITES_.* | | 571 | SITES_.* |
572 | TOOLS_ALIASES\.* | | 572 | TOOLS_ALIASES\.* |
573 | TOOLS_BROKEN | | 573 | TOOLS_BROKEN |
574 | TOOLS_CREATE | | 574 | TOOLS_CREATE |
575 | TOOLS_GNU_MISSING | | 575 | TOOLS_GNU_MISSING |
576 | TOOLS_NOOP | | 576 | TOOLS_NOOP |
577 | ); | | 577 | ); |
578 | my $plurals = join("|", | | 578 | my $plurals = join("|", |
579 | @plurals_ok, | | 579 | @plurals_ok, |
580 | @plurals_missing_an_s, | | 580 | @plurals_missing_an_s, |
581 | @plurals_reluctantly_accepted | | 581 | @plurals_reluctantly_accepted |
582 | ); | | 582 | ); |
583 | | | 583 | |
584 | $get_regex_plurals_value = qr"^(?:${plurals})$"; | | 584 | $get_regex_plurals_value = qr"^(?:${plurals})$"; |
585 | return $get_regex_plurals_value; | | 585 | return $get_regex_plurals_value; |
586 | } | | 586 | } |
587 | | | 587 | |
588 | # | | 588 | # |
589 | # Loading pkglint-specific data from files. | | 589 | # Loading pkglint-specific data from files. |
590 | # | | 590 | # |
591 | | | 591 | |
592 | # The symbol table for ACL definitions maps ACL names to ACLs. | | 592 | # The symbol table for ACL definitions maps ACL names to ACLs. |
593 | my $acl_definitions = {}; | | 593 | my $acl_definitions = {}; |
594 | | | 594 | |
595 | sub parse_acls($$) { | | 595 | sub parse_acls($$) { |
596 | my ($line, $acltext) = @_; | | 596 | my ($line, $acltext) = @_; |
597 | my ($acls); | | 597 | my ($acls); |
598 | | | 598 | |
599 | use constant ACL_shortcuts => { | | 599 | use constant ACL_shortcuts => { |
600 | "b" => qr"(?:^|/)buildlink3\.mk$", | | 600 | "b" => qr"(?:^|/)buildlink3\.mk$", |
601 | "c" => qr"(?:^|/)Makefile\.common$", | | 601 | "c" => qr"(?:^|/)Makefile\.common$", |
602 | "h" => qr"(?:^|/)hacks\.mk$", | | 602 | "h" => qr"(?:^|/)hacks\.mk$", |
603 | "m" => qr"(?:^|/)Makefile$", | | 603 | "m" => qr"(?:^|/)Makefile$", |
604 | "o" => qr"(?:^|/)options\.mk$", | | 604 | "o" => qr"(?:^|/)options\.mk$", |
605 | }; | | 605 | }; |
606 | | | 606 | |
607 | my $regex_acl_entry = qr"^(?: | | 607 | my $regex_acl_entry = qr"^(?: |
608 | \$([\w_]+) # $acl_name | | 608 | \$([\w_]+) # $acl_name |
609 | | ([\w.*]+|_):([adpsu]*) # file*mask:perms | | 609 | | ([\w.*]+|_):([adpsu]*) # file*mask:perms |
610 | ) (?:\,\s*|$)"x; | | 610 | ) (?:\,\s*|$)"x; |
611 | | | 611 | |
612 | if (!defined($acltext)) { | | 612 | if (!defined($acltext)) { |
613 | return undef; | | 613 | return undef; |
614 | } | | 614 | } |
615 | | | 615 | |
616 | $acls = []; | | 616 | $acls = []; |
617 | while ($acltext =~ s,$regex_acl_entry,,) { | | 617 | while ($acltext =~ s,$regex_acl_entry,,) { |
618 | my ($acldef, $subject, $perms) = ($1, $2, $3); | | 618 | my ($acldef, $subject, $perms) = ($1, $2, $3); |
619 | | | 619 | |
620 | if (defined($acldef)) { | | 620 | if (defined($acldef)) { |
621 | if (!exists($acl_definitions->{$acldef})) { | | 621 | if (!exists($acl_definitions->{$acldef})) { |
622 | $line->log_fatal("ACL definition ${acldef} not found."); | | 622 | $line->log_fatal("ACL definition ${acldef} not found."); |
623 | } else { | | 623 | } else { |
624 | push(@{$acls}, @{$acl_definitions->{$acldef}}); | | 624 | push(@{$acls}, @{$acl_definitions->{$acldef}}); |
625 | } | | 625 | } |
626 | | | 626 | |
627 | } else { | | 627 | } else { |
628 | # Transform $subject to a regular expression. | | 628 | # Transform $subject to a regular expression. |
629 | $subject =~ s/\./[.]/g; | | 629 | $subject =~ s/\./[.]/g; |
630 | $subject =~ s/\*/.*/g; | | 630 | $subject =~ s/\*/.*/g; |
631 | | | 631 | |
632 | push(@{$acls}, [exists(ACL_shortcuts->{$subject}) ? ACL_shortcuts->{$subject} : qr"(?:^|/)${subject}$", $perms]); | | 632 | push(@{$acls}, [exists(ACL_shortcuts->{$subject}) ? ACL_shortcuts->{$subject} : qr"(?:^|/)${subject}$", $perms]); |
633 | } | | 633 | } |
634 | } | | 634 | } |
635 | if ($acltext ne "") { | | 635 | if ($acltext ne "") { |
636 | $line->log_fatal("Invalid ACL: ${acltext}."); | | 636 | $line->log_fatal("Invalid ACL: ${acltext}."); |
637 | } | | 637 | } |
638 | | | 638 | |
639 | return $acls; | | 639 | return $acls; |
640 | } | | 640 | } |
641 | | | 641 | |
642 | my $get_vartypes_basictypes_result = undef; | | 642 | my $get_vartypes_basictypes_result = undef; |
643 | sub get_vartypes_basictypes() { | | 643 | sub get_vartypes_basictypes() { |
644 | if (defined($get_vartypes_basictypes_result)) { | | 644 | if (defined($get_vartypes_basictypes_result)) { |
645 | return $get_vartypes_basictypes_result; | | 645 | return $get_vartypes_basictypes_result; |
646 | } | | 646 | } |
647 | | | 647 | |
648 | my $lines = load_file($program); | | 648 | my $lines = load_file($program); |
649 | my $types = {}; | | 649 | my $types = {}; |
650 | assert($lines, "Couldn't load pkglint.pl from $program"); | | 650 | assert($lines, "Couldn't load pkglint.pl from $program"); |
651 | foreach my $line (@$lines) { | | 651 | foreach my $line (@$lines) { |
652 | if ($line->text =~ m"^\s+(\w+) => sub \{$") { | | 652 | if ($line->text =~ m"^\s+(\w+) => sub \{$") { |
653 | # XXX lookup in %type_dispatch instead | | 653 | # XXX lookup in %type_dispatch instead |
654 | $types->{$1} = 1; | | 654 | $types->{$1} = 1; |
655 | } | | 655 | } |
656 | } | | 656 | } |
657 | return ($get_vartypes_basictypes_result = $types); | | 657 | return ($get_vartypes_basictypes_result = $types); |
658 | } | | 658 | } |
659 | | | 659 | |
660 | my $get_vartypes_map_result = undef; | | 660 | my $get_vartypes_map_result = undef; |
661 | sub get_vartypes_map() { | | 661 | sub get_vartypes_map() { |
662 | my ($fname, $vartypes); | | 662 | my ($fname, $vartypes); |
663 | | | 663 | |
664 | if (defined($get_vartypes_map_result)) { | | 664 | if (defined($get_vartypes_map_result)) { |
665 | return $get_vartypes_map_result; | | 665 | return $get_vartypes_map_result; |
666 | } | | 666 | } |
667 | | | 667 | |
668 | use constant re_acl_def => qr"^ | | 668 | use constant re_acl_def => qr"^ |
669 | acl \s+ | | 669 | acl \s+ |
670 | (\w+) \s+ # ACL name | | 670 | (\w+) \s+ # ACL name |
671 | = \s+ | | 671 | = \s+ |
672 | \[ ([^\]]*) \] # ACL value | | 672 | \[ ([^\]]*) \] # ACL value |
673 | (?:\s*\#.*)? # optional comment | | 673 | (?:\s*\#.*)? # optional comment |
674 | $"x; | | 674 | $"x; |
675 | | | 675 | |
676 | use constant re_vartypedef => qr"^ | | 676 | use constant re_vartypedef => qr"^ |
677 | ([\w\d_.]+?) # $1 = variable name | | 677 | ([\w\d_.]+?) # $1 = variable name |
678 | (\*|\.\*|) \s+ # $2 = parameterized? | | 678 | (\*|\.\*|) \s+ # $2 = parameterized? |
679 | (?:(InternalList|List) \s+ of \s+)? # $3 ?= kind of list | | 679 | (?:(InternalList|List) \s+ of \s+)? # $3 ?= kind of list |
680 | (?:([\w\d_]+) # $4 ?= basic type | | 680 | (?:([\w\d_]+) # $4 ?= basic type |
681 | | \{\s*([\w\d_+,\-.\s]+?)\s*\}) # $5 ?= enumeration values | | 681 | | \{\s*([\w\d_+,\-.\s]+?)\s*\}) # $5 ?= enumeration values |
682 | (?:\s+ \[ ([^\]]*) \])? # $6 ?= optional ACL | | 682 | (?:\s+ \[ ([^\]]*) \])? # $6 ?= optional ACL |
683 | (?:\s*\#.*)? # $7 ?= optional comment | | 683 | (?:\s*\#.*)? # $7 ?= optional comment |
684 | $"x; | | 684 | $"x; |
685 | | | 685 | |
686 | $fname = conf_datadir."/makevars.map"; | | 686 | $fname = conf_datadir."/makevars.map"; |
687 | $vartypes = {}; | | 687 | $vartypes = {}; |
688 | | | 688 | |
689 | if ((my $lines = load_lines($fname, true))) { | | 689 | if ((my $lines = load_lines($fname, true))) { |
690 | foreach my $line (@{$lines}) { | | 690 | foreach my $line (@{$lines}) { |
691 | if ($line->text =~ m"^(?:#.*|\s*)$") { | | 691 | if ($line->text =~ m"^(?:#.*|\s*)$") { |
692 | # ignore empty and comment lines | | 692 | # ignore empty and comment lines |
693 | | | 693 | |
694 | } elsif ($line->text =~ re_acl_def) { | | 694 | } elsif ($line->text =~ re_acl_def) { |
695 | my ($aclname, $aclvalue) = ($1, $2); | | 695 | my ($aclname, $aclvalue) = ($1, $2); |
696 | | | 696 | |
697 | $acl_definitions->{$aclname} = parse_acls($line, $aclvalue); | | 697 | $acl_definitions->{$aclname} = parse_acls($line, $aclvalue); |
698 | | | 698 | |
699 | } elsif ($line->text =~ re_vartypedef) { | | 699 | } elsif ($line->text =~ re_vartypedef) { |
700 | my ($varname, $par, $kind_of_list_text, $typename, $enums, $acltext) = ($1, $2, $3, $4, $5, $6); | | 700 | my ($varname, $par, $kind_of_list_text, $typename, $enums, $acltext) = ($1, $2, $3, $4, $5, $6); |
701 | my $kind_of_list = !defined($kind_of_list_text) ? LK_NONE | | 701 | my $kind_of_list = !defined($kind_of_list_text) ? LK_NONE |
702 | : ($kind_of_list_text eq "List") ? LK_EXTERNAL | | 702 | : ($kind_of_list_text eq "List") ? LK_EXTERNAL |
703 | : LK_INTERNAL; | | 703 | : LK_INTERNAL; |
704 | | | 704 | |
705 | if (defined($typename) && !exists(get_vartypes_basictypes()->{$typename})) { | | 705 | if (defined($typename) && !exists(get_vartypes_basictypes()->{$typename})) { |
706 | $line->log_fatal("Unknown basic type \"$typename\" for variable $varname. " | | 706 | $line->log_fatal("Unknown basic type \"$typename\" for variable $varname. " |
707 | . "Valid basic types are " | | 707 | . "Valid basic types are " |
708 | . join(", ", sort keys %{get_vartypes_basictypes()}) | | 708 | . join(", ", sort keys %{get_vartypes_basictypes()}) |
709 | . "."); | | 709 | . "."); |
710 | } | | 710 | } |
711 | | | 711 | |
712 | my $basic_type = defined($enums) | | 712 | my $basic_type = defined($enums) |
713 | ? array_to_hash(split(qr"\s+", $enums)) | | 713 | ? array_to_hash(split(qr"\s+", $enums)) |
714 | : $typename; | | 714 | : $typename; |
715 | my $type = PkgLint::Type->new($kind_of_list, $basic_type, parse_acls($line, $acltext), NOT_GUESSED); | | 715 | my $type = PkgLint::Type->new($kind_of_list, $basic_type, parse_acls($line, $acltext), NOT_GUESSED); |
716 | if ($par eq "" || $par eq "*") { | | 716 | if ($par eq "" || $par eq "*") { |
717 | $vartypes->{$varname} = $type; | | 717 | $vartypes->{$varname} = $type; |
718 | } | | 718 | } |
719 | if ($par eq "*" || $par eq ".*") { | | 719 | if ($par eq "*" || $par eq ".*") { |
720 | $vartypes->{"${varname}.*"} = $type; | | 720 | $vartypes->{"${varname}.*"} = $type; |
721 | } | | 721 | } |
722 | | | 722 | |
723 | } else { | | 723 | } else { |
724 | $line->log_fatal("Unknown line format."); | | 724 | $line->log_fatal("Unknown line format."); |
725 | } | | 725 | } |
726 | } | | 726 | } |
727 | } else { | | 727 | } else { |
728 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 728 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
729 | } | | 729 | } |
730 | | | 730 | |
731 | # TODO: Enable when the time is ripe. | | 731 | # TODO: Enable when the time is ripe. |
732 | if (false) { | | 732 | if (false) { |
733 | # Additionally, scan mk/defaults/mk.conf for variable | | 733 | # Additionally, scan mk/defaults/mk.conf for variable |
734 | # definitions. All these variables are reserved for the user and | | 734 | # definitions. All these variables are reserved for the user and |
735 | # must not be set within packages. | | 735 | # must not be set within packages. |
736 | $fname = "${cwd_pkgsrcdir}/mk/defaults/mk.conf"; | | 736 | $fname = "${cwd_pkgsrcdir}/mk/defaults/mk.conf"; |
737 | if ((my $lines = load_file($fname))) { | | 737 | if ((my $lines = load_file($fname))) { |
738 | foreach my $line (@{$lines}) { | | 738 | foreach my $line (@{$lines}) { |
739 | if ($line->text =~ m"^#?([\w_]+)\?=") { | | 739 | if ($line->text =~ m"^#?([\w_]+)\?=") { |
740 | my ($varname) = ($1); | | 740 | my ($varname) = ($1); |
741 | $opt_debug_misc and $line->log_debug("Found user-definable variable ${varname}."); | | 741 | $opt_debug_misc and $line->log_debug("Found user-definable variable ${varname}."); |
742 | $vartypes->{$varname} = "Userdefined"; # FIXME: type error | | 742 | $vartypes->{$varname} = "Userdefined"; # FIXME: type error |
743 | } | | 743 | } |
744 | } | | 744 | } |
745 | } else { | | 745 | } else { |
746 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 746 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
747 | } | | 747 | } |
748 | } | | 748 | } |
749 | | | 749 | |
750 | return ($get_vartypes_map_result = $vartypes); | | 750 | return ($get_vartypes_map_result = $vartypes); |
751 | } | | 751 | } |
752 | | | 752 | |
753 | my $get_deprecated_map_result = undef; | | 753 | my $get_deprecated_map_result = undef; |
754 | sub get_deprecated_map() { | | 754 | sub get_deprecated_map() { |
755 | my ($fname, $lines, $vars); | | 755 | my ($fname, $lines, $vars); |
756 | | | 756 | |
757 | if (defined($get_deprecated_map_result)) { | | 757 | if (defined($get_deprecated_map_result)) { |
758 | return $get_deprecated_map_result; | | 758 | return $get_deprecated_map_result; |
759 | } | | 759 | } |
760 | | | 760 | |
761 | $fname = conf_datadir."/deprecated.map"; | | 761 | $fname = conf_datadir."/deprecated.map"; |
762 | if (!($lines = load_file($fname))) { | | 762 | if (!($lines = load_file($fname))) { |
763 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 763 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
764 | } | | 764 | } |
765 | | | 765 | |
766 | $vars = {}; | | 766 | $vars = {}; |
767 | foreach my $line (@{$lines}) { | | 767 | foreach my $line (@{$lines}) { |
768 | if ($line->text =~ m"^#" || $line->text =~ m"^\s*$") { | | 768 | if ($line->text =~ m"^#" || $line->text =~ m"^\s*$") { |
769 | # Ignore empty and comment lines. | | 769 | # Ignore empty and comment lines. |
770 | | | 770 | |
771 | } elsif ($line->text =~ m"^(\S+)\s+(.*)$") { | | 771 | } elsif ($line->text =~ m"^(\S+)\s+(.*)$") { |
772 | $vars->{$1} = $2; | | 772 | $vars->{$1} = $2; |
773 | | | 773 | |
774 | } else { | | 774 | } else { |
775 | $line->log_fatal("Unknown line format."); | | 775 | $line->log_fatal("Unknown line format."); |
776 | } | | 776 | } |
777 | } | | 777 | } |
778 | return ($get_deprecated_map_result = $vars); | | 778 | return ($get_deprecated_map_result = $vars); |
779 | } | | 779 | } |
780 | | | 780 | |
781 | my $load_dist_sites_url2name = undef; | | 781 | my $load_dist_sites_url2name = undef; |
782 | my $load_dist_sites_names = undef; | | 782 | my $load_dist_sites_names = undef; |
783 | sub load_dist_sites() { | | 783 | sub load_dist_sites() { |
784 | my ($fname) = ("${cwd_pkgsrcdir}/mk/fetch/sites.mk"); | | 784 | my ($fname) = ("${cwd_pkgsrcdir}/mk/fetch/sites.mk"); |
785 | my ($lines) = load_file($fname); | | 785 | my ($lines) = load_file($fname); |
786 | my ($varname) = undef; | | 786 | my ($varname) = undef; |
787 | my ($ignoring) = false; | | 787 | my ($ignoring) = false; |
788 | my ($url2name) = {}; | | 788 | my ($url2name) = {}; |
789 | my ($names) = {}; | | 789 | my ($names) = {}; |
790 | | | 790 | |
791 | if (!$lines) { | | 791 | if (!$lines) { |
792 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); | | 792 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); |
793 | $load_dist_sites_url2name = $url2name; | | 793 | $load_dist_sites_url2name = $url2name; |
794 | $load_dist_sites_names = $names; | | 794 | $load_dist_sites_names = $names; |
795 | return; | | 795 | return; |
796 | } | | 796 | } |
797 | foreach my $line (@{$lines}) { | | 797 | foreach my $line (@{$lines}) { |
798 | my $text = $line->text; | | 798 | my $text = $line->text; |
799 | | | 799 | |
800 | if ($text =~ m"^(MASTER_SITE_\w+)\+=\s*\\$"o) { | | 800 | if ($text =~ m"^(MASTER_SITE_\w+)\+=\s*\\$"o) { |
801 | $varname = $1; | | 801 | $varname = $1; |
802 | $names->{$varname} = true; | | 802 | $names->{$varname} = true; |
803 | $ignoring = false; | | 803 | $ignoring = false; |
804 | | | 804 | |
805 | } elsif ($text eq "MASTER_SITE_BACKUP?=\t\\") { | | 805 | } elsif ($text eq "MASTER_SITE_BACKUP?=\t\\") { |
806 | $ignoring = true; | | 806 | $ignoring = true; |
807 | | | 807 | |
808 | } elsif ($text =~ m"^\t((?:http://|ftp://)\S+/)(?:|\s*\\)$"o) { | | 808 | } elsif ($text =~ m"^\t((?:http://|ftp://)\S+/)(?:|\s*\\)$"o) { |
809 | if (!$ignoring) { | | 809 | if (!$ignoring) { |
810 | if (defined($varname)) { | | 810 | if (defined($varname)) { |
811 | $url2name->{$1} = $varname; | | 811 | $url2name->{$1} = $varname; |
812 | } else { | | 812 | } else { |
813 | $line->log_error("Lonely URL found."); | | 813 | $line->log_error("Lonely URL found."); |
814 | } | | 814 | } |
815 | } | | 815 | } |
816 | | | 816 | |
817 | } elsif ($text =~ m"^(?:#.*|\s*)$") { | | 817 | } elsif ($text =~ m"^(?:#.*|\s*)$") { |
818 | # ignore empty and comment lines | | 818 | # ignore empty and comment lines |
819 | | | 819 | |
820 | } elsif ($text =~ m"BSD_SITES_MK") { | | 820 | } elsif ($text =~ m"BSD_SITES_MK") { |
821 | # ignore multiple inclusion guards | | 821 | # ignore multiple inclusion guards |
822 | | | 822 | |
823 | } else { | | 823 | } else { |
824 | $line->log_fatal("Unknown line type."); | | 824 | $line->log_fatal("Unknown line type."); |
825 | } | | 825 | } |
826 | } | | 826 | } |
827 | | | 827 | |
828 | # Explicitly allowed, although not defined in mk/fetch/sites.mk. | | 828 | # Explicitly allowed, although not defined in mk/fetch/sites.mk. |
829 | $names->{"MASTER_SITE_SUSE_UPD"} = true; | | 829 | $names->{"MASTER_SITE_SUSE_UPD"} = true; |
830 | $names->{"MASTER_SITE_LOCAL"} = true; | | 830 | $names->{"MASTER_SITE_LOCAL"} = true; |
831 | | | 831 | |
832 | $opt_debug_misc and log_debug($fname, NO_LINES, "Loaded " . scalar(keys(%{$url2name})) . " MASTER_SITE_* definitions."); | | 832 | $opt_debug_misc and log_debug($fname, NO_LINES, "Loaded " . scalar(keys(%{$url2name})) . " MASTER_SITE_* definitions."); |
833 | $load_dist_sites_url2name = $url2name; | | 833 | $load_dist_sites_url2name = $url2name; |
834 | $load_dist_sites_names = $names; | | 834 | $load_dist_sites_names = $names; |
835 | } | | 835 | } |
836 | | | 836 | |
837 | sub get_dist_sites() { | | 837 | sub get_dist_sites() { |
838 | if (!defined($load_dist_sites_url2name)) { | | 838 | if (!defined($load_dist_sites_url2name)) { |
839 | load_dist_sites(); | | 839 | load_dist_sites(); |
840 | } | | 840 | } |
841 | return $load_dist_sites_url2name; | | 841 | return $load_dist_sites_url2name; |
842 | } | | 842 | } |
843 | | | 843 | |
844 | sub get_dist_sites_names() { | | 844 | sub get_dist_sites_names() { |
845 | if (!defined($load_dist_sites_names)) { | | 845 | if (!defined($load_dist_sites_names)) { |
846 | load_dist_sites(); | | 846 | load_dist_sites(); |
847 | } | | 847 | } |
848 | return $load_dist_sites_names; | | 848 | return $load_dist_sites_names; |
849 | } | | 849 | } |
850 | | | 850 | |
851 | my $get_pkg_options_result = undef; | | 851 | my $get_pkg_options_result = undef; |
852 | sub get_pkg_options() { | | 852 | sub get_pkg_options() { |
853 | | | 853 | |
854 | if (defined($get_pkg_options_result)) { | | 854 | if (defined($get_pkg_options_result)) { |
855 | return $get_pkg_options_result; | | 855 | return $get_pkg_options_result; |
856 | } | | 856 | } |
857 | | | 857 | |
858 | my ($fname) = ("${cwd_pkgsrcdir}/mk/defaults/options.description"); | | 858 | my ($fname) = ("${cwd_pkgsrcdir}/mk/defaults/options.description"); |
859 | my ($lines, $options); | | 859 | my ($lines, $options); |
860 | | | 860 | |
861 | if (!($lines = load_file($fname))) { | | 861 | if (!($lines = load_file($fname))) { |
862 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 862 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
863 | } | | 863 | } |
864 | | | 864 | |
865 | $options = {}; | | 865 | $options = {}; |
866 | foreach my $line (@{$lines}) { | | 866 | foreach my $line (@{$lines}) { |
867 | if ($line->text =~ m"^([-0-9a-z_+]+)(?:\s+(.*))?$") { | | 867 | if ($line->text =~ m"^([-0-9a-z_+]+)(?:\s+(.*))?$") { |
868 | my ($optname, $optdescr) = ($1, $2); | | 868 | my ($optname, $optdescr) = ($1, $2); |
869 | | | 869 | |
870 | $options->{$optname} = defined($optdescr) | | 870 | $options->{$optname} = defined($optdescr) |
871 | ? $optdescr | | 871 | ? $optdescr |
872 | : ""; | | 872 | : ""; |
873 | } else { | | 873 | } else { |
874 | $line->log_error("Unknown line format."); | | 874 | $line->log_error("Unknown line format."); |
875 | } | | 875 | } |
876 | } | | 876 | } |
877 | | | 877 | |
878 | return ($get_pkg_options_result = $options); | | 878 | return ($get_pkg_options_result = $options); |
879 | } | | 879 | } |
880 | | | 880 | |
881 | my $load_tool_names_system_build_defs = undef; # XXX: misplaced, but works | | 881 | my $load_tool_names_system_build_defs = undef; # XXX: misplaced, but works |
882 | my $load_tool_names_tools = undef; | | 882 | my $load_tool_names_tools = undef; |
883 | my $load_tool_names_vartools = undef; | | 883 | my $load_tool_names_vartools = undef; |
884 | my $load_tool_names_varname_to_toolname = undef; | | 884 | my $load_tool_names_varname_to_toolname = undef; |
885 | my $load_tool_names_predefined_tools = undef; | | 885 | my $load_tool_names_predefined_tools = undef; |
886 | sub load_tool_names() { | | 886 | sub load_tool_names() { |
887 | my ($tools, $vartools, $predefined_tools, $varname_to_toolname, @tool_files); | | 887 | my ($tools, $vartools, $predefined_tools, $varname_to_toolname, @tool_files); |
888 | my ($system_build_defs); | | 888 | my ($system_build_defs); |
889 | | | 889 | |
890 | # | | 890 | # |
891 | # Get the list of files that define the tools from bsd.tools.mk. | | 891 | # Get the list of files that define the tools from bsd.tools.mk. |
892 | # | | 892 | # |
893 | | | 893 | |
894 | @tool_files = ("defaults.mk"); | | 894 | @tool_files = ("defaults.mk"); |
895 | { | | 895 | { |
896 | my $fname = "${cwd_pkgsrcdir}/mk/tools/bsd.tools.mk"; | | 896 | my $fname = "${cwd_pkgsrcdir}/mk/tools/bsd.tools.mk"; |
897 | my $lines = load_lines($fname, true); | | 897 | my $lines = load_lines($fname, true); |
898 | if (!$lines) { | | 898 | if (!$lines) { |
899 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 899 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
900 | } | | 900 | } |
901 | | | 901 | |
902 | foreach my $line (@{$lines}) { | | 902 | foreach my $line (@{$lines}) { |
903 | if ($line->text =~ regex_mk_include) { | | 903 | if ($line->text =~ regex_mk_include) { |
904 | my (undef, $includefile) = ($1, $2); | | 904 | my (undef, $includefile) = ($1, $2); |
905 | if ($includefile =~ m"^(?:\$\{PKGSRCDIR\}/mk/tools/)?([^/]+)$") { | | 905 | if ($includefile =~ m"^(?:\$\{PKGSRCDIR\}/mk/tools/)?([^/]+)$") { |
906 | push(@tool_files, $1); | | 906 | push(@tool_files, $1); |
907 | } | | 907 | } |
908 | } | | 908 | } |
909 | } | | 909 | } |
910 | } | | 910 | } |
911 | assert(scalar(@tool_files) > 1, "Too few tool files. Maybe the files have been renamed again?"); | | 911 | assert(scalar(@tool_files) > 1, "Too few tool files. Maybe the files have been renamed again?"); |
912 | | | 912 | |
913 | # | | 913 | # |
914 | # Scan the tool files for the actual definitions of the tools. | | 914 | # Scan the tool files for the actual definitions of the tools. |
915 | # | | 915 | # |
916 | | | 916 | |
917 | $tools = {}; | | 917 | $tools = {}; |
918 | $vartools = {}; | | 918 | $vartools = {}; |
919 | $predefined_tools = {}; | | 919 | $predefined_tools = {}; |
920 | $varname_to_toolname = {}; | | 920 | $varname_to_toolname = {}; |
921 | $system_build_defs = {}; | | 921 | $system_build_defs = {}; |
922 | foreach my $basename (@tool_files) { | | 922 | foreach my $basename (@tool_files) { |
923 | my $fname = "${cwd_pkgsrcdir}/mk/tools/${basename}"; | | 923 | my $fname = "${cwd_pkgsrcdir}/mk/tools/${basename}"; |
924 | my $lines = load_lines($fname, true); | | 924 | my $lines = load_lines($fname, true); |
925 | | | 925 | |
926 | if (!$lines) { | | 926 | if (!$lines) { |
927 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 927 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
928 | } | | 928 | } |
929 | | | 929 | |
930 | foreach my $line (@{$lines}) { | | 930 | foreach my $line (@{$lines}) { |
931 | if ($line->text =~ regex_varassign) { | | 931 | if ($line->text =~ regex_varassign) { |
932 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); | | 932 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); |
933 | if ($varname eq "TOOLS_CREATE" && $value =~ m"^([-\w.]+|\[)$") { | | 933 | if ($varname eq "TOOLS_CREATE" && $value =~ m"^([-\w.]+|\[)$") { |
934 | $tools->{$value} = true; | | 934 | $tools->{$value} = true; |
935 | | | 935 | |
936 | } elsif ($varname =~ m"^(?:_TOOLS_VARNAME)\.([-\w.]+|\[)$") { | | 936 | } elsif ($varname =~ m"^(?:_TOOLS_VARNAME)\.([-\w.]+|\[)$") { |
937 | $tools->{$1} = true; | | 937 | $tools->{$1} = true; |
938 | $vartools->{$1} = $value; | | 938 | $vartools->{$1} = $value; |
939 | $varname_to_toolname->{$value} = $1; | | 939 | $varname_to_toolname->{$value} = $1; |
940 | | | 940 | |
941 | } elsif ($varname =~ m"^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$") { | | 941 | } elsif ($varname =~ m"^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$") { |
942 | $tools->{$1} = true; | | 942 | $tools->{$1} = true; |
943 | | | 943 | |
944 | } elsif ($varname =~ m"^_TOOLS\.(.*)") { | | 944 | } elsif ($varname =~ m"^_TOOLS\.(.*)") { |
945 | $tools->{$1} = true; | | 945 | $tools->{$1} = true; |
946 | foreach my $tool (split(qr"\s+", $value)) { | | 946 | foreach my $tool (split(qr"\s+", $value)) { |
947 | $tools->{$tool} = true; | | 947 | $tools->{$tool} = true; |
948 | } | | 948 | } |
949 | } | | 949 | } |
950 | } | | 950 | } |
951 | } | | 951 | } |
952 | } | | 952 | } |
953 | | | 953 | |
954 | foreach my $basename ("bsd.pkg.mk") { | | 954 | foreach my $basename ("bsd.pkg.mk") { |
955 | my $fname = "${cwd_pkgsrcdir}/mk/${basename}"; | | 955 | my $fname = "${cwd_pkgsrcdir}/mk/${basename}"; |
956 | my $lines = load_lines($fname, true); | | 956 | my $lines = load_lines($fname, true); |
957 | my $cond_depth = 0; | | 957 | my $cond_depth = 0; |
958 | | | 958 | |
959 | if (!$lines) { | | 959 | if (!$lines) { |
960 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); | | 960 | log_fatal($fname, NO_LINE_NUMBER, "Cannot be read."); |
961 | } | | 961 | } |
962 | | | 962 | |
963 | foreach my $line (@{$lines}) { | | 963 | foreach my $line (@{$lines}) { |
964 | my $text = $line->text; | | 964 | my $text = $line->text; |
965 | | | 965 | |
966 | if ($text =~ regex_varassign) { | | 966 | if ($text =~ regex_varassign) { |
967 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); | | 967 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); |
968 | | | 968 | |
969 | if ($varname eq "USE_TOOLS") { | | 969 | if ($varname eq "USE_TOOLS") { |
970 | $opt_debug_tools and $line->log_debug("[cond_depth=${cond_depth}] $value"); | | 970 | $opt_debug_tools and $line->log_debug("[cond_depth=${cond_depth}] $value"); |
971 | if ($cond_depth == 0) { | | 971 | if ($cond_depth == 0) { |
972 | foreach my $tool (split(qr"\s+", $value)) { | | 972 | foreach my $tool (split(qr"\s+", $value)) { |
973 | if ($tool !~ regex_unresolved && exists($tools->{$tool})) { | | 973 | if ($tool !~ regex_unresolved && exists($tools->{$tool})) { |
974 | $predefined_tools->{$tool} = true; | | 974 | $predefined_tools->{$tool} = true; |
975 | # The path (without arguments) to the tool | | 975 | # The path (without arguments) to the tool |
976 | $predefined_tools->{"TOOLS_${tool}"} = true; | | 976 | $predefined_tools->{"TOOLS_${tool}"} = true; |
977 | } | | 977 | } |
978 | } | | 978 | } |
979 | } | | 979 | } |
980 | } elsif ($varname eq "_BUILD_DEFS") { | | 980 | } elsif ($varname eq "_BUILD_DEFS") { |
981 | foreach my $bdvar (split(qr"\s+", $value)) { | | 981 | foreach my $bdvar (split(qr"\s+", $value)) { |
982 | $system_build_defs->{$bdvar} = true; | | 982 | $system_build_defs->{$bdvar} = true; |
983 | } | | 983 | } |
984 | } | | 984 | } |
985 | | | 985 | |
986 | } elsif ($text =~ regex_mk_cond) { | | 986 | } elsif ($text =~ regex_mk_cond) { |
987 | my ($indent, $cond, $args, $comment) = ($1, $2, $3, $4); | | 987 | my ($indent, $cond, $args, $comment) = ($1, $2, $3, $4); |
988 | | | 988 | |
989 | if ($cond =~ m"^(?:if|ifdef|ifndef|for)$") { | | 989 | if ($cond =~ m"^(?:if|ifdef|ifndef|for)$") { |
990 | $cond_depth++; | | 990 | $cond_depth++; |
991 | } elsif ($cond =~ m"^(?:endif|endfor)$") { | | 991 | } elsif ($cond =~ m"^(?:endif|endfor)$") { |
992 | $cond_depth--; | | 992 | $cond_depth--; |
993 | } | | 993 | } |
994 | } | | 994 | } |
995 | } | | 995 | } |
996 | } | | 996 | } |
997 | | | 997 | |
998 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known tools: ".join(" ", sort(keys(%{$tools})))); | | 998 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known tools: ".join(" ", sort(keys(%{$tools})))); |
999 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known vartools: ".join(" ", sort(keys(%{$vartools})))); | | 999 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known vartools: ".join(" ", sort(keys(%{$vartools})))); |
1000 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Predefined tools: " . join(" ", sort(keys(%{$predefined_tools})))); | | 1000 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Predefined tools: " . join(" ", sort(keys(%{$predefined_tools})))); |
1001 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known varnames: " . join(" ", sort(keys(%{$varname_to_toolname})))); | | 1001 | $opt_debug_tools and log_debug(NO_FILE, NO_LINE_NUMBER, "Known varnames: " . join(" ", sort(keys(%{$varname_to_toolname})))); |
| @@ -1531,3871 +1531,3881 @@ sub resolve_variable_rec2($$) { | | | @@ -1531,3871 +1531,3881 @@ sub resolve_variable_rec2($$) { |
1531 | $expanded =~ s/\$\{(\w+)\}/resolve_variable_rec1($1, $visited)/eg; | | 1531 | $expanded =~ s/\$\{(\w+)\}/resolve_variable_rec1($1, $visited)/eg; |
1532 | return $expanded; | | 1532 | return $expanded; |
1533 | } | | 1533 | } |
1534 | | | 1534 | |
1535 | sub expand_variable($) { | | 1535 | sub expand_variable($) { |
1536 | my ($varname) = @_; | | 1536 | my ($varname) = @_; |
1537 | | | 1537 | |
1538 | return unless exists($pkgctx_vardef->{$varname}); | | 1538 | return unless exists($pkgctx_vardef->{$varname}); |
1539 | my $line = $pkgctx_vardef->{$varname}; | | 1539 | my $line = $pkgctx_vardef->{$varname}; |
1540 | my $value = $line->get("value"); | | 1540 | my $value = $line->get("value"); |
1541 | | | 1541 | |
1542 | $value = resolve_relative_path($value, true); | | 1542 | $value = resolve_relative_path($value, true); |
1543 | if ($value =~ regex_unresolved) { | | 1543 | if ($value =~ regex_unresolved) { |
1544 | $opt_debug_misc and log_debug(NO_FILE, NO_LINES, "[expand_variable] Trying harder to resolve variable references in ${varname}=\"${value}\"."); | | 1544 | $opt_debug_misc and log_debug(NO_FILE, NO_LINES, "[expand_variable] Trying harder to resolve variable references in ${varname}=\"${value}\"."); |
1545 | $value = resolve_variable_rec2($value, {}); | | 1545 | $value = resolve_variable_rec2($value, {}); |
1546 | if ($value =~ regex_unresolved) { | | 1546 | if ($value =~ regex_unresolved) { |
1547 | $opt_debug_misc and log_debug(NO_FILE, NO_LINES, "[expand_variable] Failed to resolve ${varname}=\"${value}\"."); | | 1547 | $opt_debug_misc and log_debug(NO_FILE, NO_LINES, "[expand_variable] Failed to resolve ${varname}=\"${value}\"."); |
1548 | } | | 1548 | } |
1549 | } | | 1549 | } |
1550 | return $value; | | 1550 | return $value; |
1551 | } | | 1551 | } |
1552 | | | 1552 | |
1553 | sub set_default_value($$) { | | 1553 | sub set_default_value($$) { |
1554 | my ($varref, $value) = @_; | | 1554 | my ($varref, $value) = @_; |
1555 | | | 1555 | |
1556 | if (!defined(${$varref}) || ${$varref} =~ regex_unresolved) { | | 1556 | if (!defined(${$varref}) || ${$varref} =~ regex_unresolved) { |
1557 | ${$varref} = $value; | | 1557 | ${$varref} = $value; |
1558 | } | | 1558 | } |
1559 | } | | 1559 | } |
1560 | | | 1560 | |
1561 | sub strip_mk_comment($) { | | 1561 | sub strip_mk_comment($) { |
1562 | my ($text) = @_; | | 1562 | my ($text) = @_; |
1563 | | | 1563 | |
1564 | $text =~ s/(^|[^\\])#.*/$1/; | | 1564 | $text =~ s/(^|[^\\])#.*/$1/; |
1565 | $text =~ s/\\#/#/g; | | 1565 | $text =~ s/\\#/#/g; |
1566 | return $text; | | 1566 | return $text; |
1567 | } | | 1567 | } |
1568 | | | 1568 | |
1569 | # Returns the value of a shell word, with one level of quoting removed. | | 1569 | # Returns the value of a shell word, with one level of quoting removed. |
1570 | # This makes pattern matching easier when the interesting part is not | | 1570 | # This makes pattern matching easier when the interesting part is not |
1571 | # what make(1) or sh(1) sees, but the command that is called by the | | 1571 | # what make(1) or sh(1) sees, but the command that is called by the |
1572 | # shell. This function does not resolve or replace any variables. | | 1572 | # shell. This function does not resolve or replace any variables. |
1573 | sub unescape_shellword($) { | | 1573 | sub unescape_shellword($) { |
1574 | my ($text) = @_; | | 1574 | my ($text) = @_; |
1575 | | | 1575 | |
1576 | # TODO: implement this. | | 1576 | # TODO: implement this. |
1577 | assert(false, "unescape_shellword is not yet implemented."); | | 1577 | assert(false, "unescape_shellword is not yet implemented."); |
1578 | } | | 1578 | } |
1579 | | | 1579 | |
1580 | # Removes all uses of make variables from a string. | | 1580 | # Removes all uses of make variables from a string. |
1581 | sub remove_variables($) { | | 1581 | sub remove_variables($) { |
1582 | my ($text) = @_; | | 1582 | my ($text) = @_; |
1583 | | | 1583 | |
1584 | while ($text =~ s/\$\{([^{}]*)\}//g) { | | 1584 | while ($text =~ s/\$\{([^{}]*)\}//g) { |
1585 | } | | 1585 | } |
1586 | return $text; | | 1586 | return $text; |
1587 | } | | 1587 | } |
1588 | | | 1588 | |
1589 | sub backtrace($) { | | 1589 | sub backtrace($) { |
1590 | my $msg = shift(); | | 1590 | my $msg = shift(); |
1591 | my (@callers); | | 1591 | my (@callers); |
1592 | | | 1592 | |
1593 | my $n = 0; | | 1593 | my $n = 0; |
1594 | while (my @info = caller($n)) { | | 1594 | while (my @info = caller($n)) { |
1595 | push(@callers, [$info[2], $info[3]]); | | 1595 | push(@callers, [$info[2], $info[3]]); |
1596 | $n++; | | 1596 | $n++; |
1597 | } | | 1597 | } |
1598 | | | 1598 | |
1599 | log_debug(NO_FILE, NO_LINE_NUMBER, $msg); | | 1599 | log_debug(NO_FILE, NO_LINE_NUMBER, $msg); |
1600 | for (my $i = $#callers; $i >= 0; $i--) { | | 1600 | for (my $i = $#callers; $i >= 0; $i--) { |
1601 | my $info = $callers[$i]; | | 1601 | my $info = $callers[$i]; |
1602 | log_debug(NO_FILE, NO_LINE_NUMBER, sprintf(" line %4d called %s", $info->[0], $info->[1])); | | 1602 | log_debug(NO_FILE, NO_LINE_NUMBER, sprintf(" line %4d called %s", $info->[0], $info->[1])); |
1603 | } | | 1603 | } |
1604 | } | | 1604 | } |
1605 | | | 1605 | |
1606 | # Returns the number of columns that a string occupies when printed with | | 1606 | # Returns the number of columns that a string occupies when printed with |
1607 | # a tabulator size of 8. | | 1607 | # a tabulator size of 8. |
1608 | sub tablen($) { | | 1608 | sub tablen($) { |
1609 | my ($s) = @_; | | 1609 | my ($s) = @_; |
1610 | my ($len); | | 1610 | my ($len); |
1611 | | | 1611 | |
1612 | $len = 0; | | 1612 | $len = 0; |
1613 | foreach my $c (split(qr"", $s)) { | | 1613 | foreach my $c (split(qr"", $s)) { |
1614 | if ($c eq "\t") { | | 1614 | if ($c eq "\t") { |
1615 | $len = ($len + 7) & ~7; | | 1615 | $len = ($len + 7) & ~7; |
1616 | } else { | | 1616 | } else { |
1617 | $len++; | | 1617 | $len++; |
1618 | } | | 1618 | } |
1619 | } | | 1619 | } |
1620 | return $len; | | 1620 | return $len; |
1621 | } | | 1621 | } |
1622 | | | 1622 | |
1623 | sub shell_split($) { | | 1623 | sub shell_split($) { |
1624 | my ($text) = @_; | | 1624 | my ($text) = @_; |
1625 | my ($words); | | 1625 | my ($words); |
1626 | | | 1626 | |
1627 | $words = []; | | 1627 | $words = []; |
1628 | while ($text =~ s/^$regex_shellword//) { | | 1628 | while ($text =~ s/^$regex_shellword//) { |
1629 | push(@{$words}, $1); | | 1629 | push(@{$words}, $1); |
1630 | } | | 1630 | } |
1631 | return (($text =~ m"^\s*$") ? $words : false); | | 1631 | return (($text =~ m"^\s*$") ? $words : false); |
1632 | } | | 1632 | } |
1633 | | | 1633 | |
1634 | sub varname_base($) { | | 1634 | sub varname_base($) { |
1635 | my ($varname) = @_; | | 1635 | my ($varname) = @_; |
1636 | | | 1636 | |
1637 | return ($varname =~ m"^(.*?)\..*$") ? $1 : $varname; | | 1637 | return ($varname =~ m"^(.*?)\..*$") ? $1 : $varname; |
1638 | } | | 1638 | } |
1639 | | | 1639 | |
1640 | sub varname_canon($) { | | 1640 | sub varname_canon($) { |
1641 | my ($varname) = @_; | | 1641 | my ($varname) = @_; |
1642 | | | 1642 | |
1643 | return ($varname =~ m"^(.*?)\..*$") ? "$1.*" : $varname; | | 1643 | return ($varname =~ m"^(.*?)\..*$") ? "$1.*" : $varname; |
1644 | } | | 1644 | } |
1645 | | | 1645 | |
1646 | sub varname_param($) { | | 1646 | sub varname_param($) { |
1647 | my ($varname) = @_; | | 1647 | my ($varname) = @_; |
1648 | | | 1648 | |
1649 | return ($varname =~ m"^.*?\.(.*)$") ? $2 : undef; | | 1649 | return ($varname =~ m"^.*?\.(.*)$") ? $2 : undef; |
1650 | } | | 1650 | } |
1651 | | | 1651 | |
1652 | sub use_var($$) { | | 1652 | sub use_var($$) { |
1653 | my ($line, $varname) = @_; | | 1653 | my ($line, $varname) = @_; |
1654 | my $varcanon = varname_canon($varname); | | 1654 | my $varcanon = varname_canon($varname); |
1655 | | | 1655 | |
1656 | if (defined($mkctx_varuse)) { | | 1656 | if (defined($mkctx_varuse)) { |
1657 | $mkctx_varuse->{$varname} = $line; | | 1657 | $mkctx_varuse->{$varname} = $line; |
1658 | $mkctx_varuse->{$varcanon} = $line; | | 1658 | $mkctx_varuse->{$varcanon} = $line; |
1659 | } | | 1659 | } |
1660 | | | 1660 | |
1661 | if (defined($pkgctx_varuse)) { | | 1661 | if (defined($pkgctx_varuse)) { |
1662 | $pkgctx_varuse->{$varname} = $line; | | 1662 | $pkgctx_varuse->{$varname} = $line; |
1663 | $pkgctx_varuse->{$varcanon} = $line; | | 1663 | $pkgctx_varuse->{$varcanon} = $line; |
1664 | } | | 1664 | } |
1665 | } | | 1665 | } |
1666 | | | 1666 | |
1667 | sub var_is_used($) { | | 1667 | sub var_is_used($) { |
1668 | my ($varname) = @_; | | 1668 | my ($varname) = @_; |
1669 | my $varcanon = varname_canon($varname); | | 1669 | my $varcanon = varname_canon($varname); |
1670 | | | 1670 | |
1671 | if (defined($mkctx_varuse)) { | | 1671 | if (defined($mkctx_varuse)) { |
1672 | return $mkctx_varuse->{$varname} if exists($mkctx_varuse->{$varname}); | | 1672 | return $mkctx_varuse->{$varname} if exists($mkctx_varuse->{$varname}); |
1673 | return $mkctx_varuse->{$varcanon} if exists($mkctx_varuse->{$varcanon}); | | 1673 | return $mkctx_varuse->{$varcanon} if exists($mkctx_varuse->{$varcanon}); |
1674 | } | | 1674 | } |
1675 | if (defined($pkgctx_varuse)) { | | 1675 | if (defined($pkgctx_varuse)) { |
1676 | return $pkgctx_varuse->{$varname} if exists($pkgctx_varuse->{$varname}); | | 1676 | return $pkgctx_varuse->{$varname} if exists($pkgctx_varuse->{$varname}); |
1677 | return $pkgctx_varuse->{$varcanon} if exists($pkgctx_varuse->{$varcanon}); | | 1677 | return $pkgctx_varuse->{$varcanon} if exists($pkgctx_varuse->{$varcanon}); |
1678 | } | | 1678 | } |
1679 | return false; | | 1679 | return false; |
1680 | } | | 1680 | } |
1681 | | | 1681 | |
1682 | sub def_var($$) { | | 1682 | sub def_var($$) { |
1683 | my ($line, $varname) = @_; | | 1683 | my ($line, $varname) = @_; |
1684 | my $varcanon = varname_canon($varname); | | 1684 | my $varcanon = varname_canon($varname); |
1685 | | | 1685 | |
1686 | if (defined($mkctx_vardef)) { | | 1686 | if (defined($mkctx_vardef)) { |
1687 | $mkctx_vardef->{$varname} = $line; | | 1687 | $mkctx_vardef->{$varname} = $line; |
1688 | $mkctx_vardef->{$varcanon} = $line; | | 1688 | $mkctx_vardef->{$varcanon} = $line; |
1689 | } | | 1689 | } |
1690 | | | 1690 | |
1691 | if (defined($pkgctx_vardef)) { | | 1691 | if (defined($pkgctx_vardef)) { |
1692 | $pkgctx_vardef->{$varname} = $line; | | 1692 | $pkgctx_vardef->{$varname} = $line; |
1693 | $pkgctx_vardef->{$varcanon} = $line; | | 1693 | $pkgctx_vardef->{$varcanon} = $line; |
1694 | } | | 1694 | } |
1695 | } | | 1695 | } |
1696 | | | 1696 | |
1697 | sub var_is_defined($) { | | 1697 | sub var_is_defined($) { |
1698 | my ($varname) = @_; | | 1698 | my ($varname) = @_; |
1699 | my $varcanon = varname_canon($varname); | | 1699 | my $varcanon = varname_canon($varname); |
1700 | | | 1700 | |
1701 | if (defined($mkctx_vardef)) { | | 1701 | if (defined($mkctx_vardef)) { |
1702 | return $mkctx_vardef->{$varname} if exists($mkctx_vardef->{$varname}); | | 1702 | return $mkctx_vardef->{$varname} if exists($mkctx_vardef->{$varname}); |
1703 | return $mkctx_vardef->{$varcanon} if exists($mkctx_vardef->{$varcanon}); | | 1703 | return $mkctx_vardef->{$varcanon} if exists($mkctx_vardef->{$varcanon}); |
1704 | } | | 1704 | } |
1705 | if (defined($pkgctx_vardef)) { | | 1705 | if (defined($pkgctx_vardef)) { |
1706 | return $pkgctx_vardef->{$varname} if exists($pkgctx_vardef->{$varname}); | | 1706 | return $pkgctx_vardef->{$varname} if exists($pkgctx_vardef->{$varname}); |
1707 | return $pkgctx_vardef->{$varcanon} if exists($pkgctx_vardef->{$varcanon}); | | 1707 | return $pkgctx_vardef->{$varcanon} if exists($pkgctx_vardef->{$varcanon}); |
1708 | } | | 1708 | } |
1709 | return false; | | 1709 | return false; |
1710 | } | | 1710 | } |
1711 | | | 1711 | |
1712 | sub determine_used_variables($) { | | 1712 | sub determine_used_variables($) { |
1713 | my ($lines) = @_; | | 1713 | my ($lines) = @_; |
1714 | my ($rest); | | 1714 | my ($rest); |
1715 | | | 1715 | |
1716 | foreach my $line (@{$lines}) { | | 1716 | foreach my $line (@{$lines}) { |
1717 | $rest = $line->text; | | 1717 | $rest = $line->text; |
1718 | while ($rest =~ s/(?:\$\{|\$\(|defined\(|empty\()([0-9+.A-Z_a-z]+)[:})]//) { | | 1718 | while ($rest =~ s/(?:\$\{|\$\(|defined\(|empty\()([0-9+.A-Z_a-z]+)[:})]//) { |
1719 | my ($varname) = ($1); | | 1719 | my ($varname) = ($1); |
1720 | use_var($line, $varname); | | 1720 | use_var($line, $varname); |
1721 | $opt_debug_unused and $line->log_debug("Variable ${varname} is used."); | | 1721 | $opt_debug_unused and $line->log_debug("Variable ${varname} is used."); |
1722 | } | | 1722 | } |
1723 | } | | 1723 | } |
1724 | } | | 1724 | } |
1725 | | | 1725 | |
1726 | sub extract_used_variables($$) { | | 1726 | sub extract_used_variables($$) { |
1727 | my ($line, $text) = @_; | | 1727 | my ($line, $text) = @_; |
1728 | my ($rest, $result); | | 1728 | my ($rest, $result); |
1729 | | | 1729 | |
1730 | $rest = $text; | | 1730 | $rest = $text; |
1731 | $result = []; | | 1731 | $result = []; |
1732 | while ($rest =~ s/^(?:[^\$]+|\$[\$*<>?\@]|\$\{([.0-9A-Z_a-z]+)(?::(?:[^\${}]|\$[^{])+)?\})//) { | | 1732 | while ($rest =~ s/^(?:[^\$]+|\$[\$*<>?\@]|\$\{([.0-9A-Z_a-z]+)(?::(?:[^\${}]|\$[^{])+)?\})//) { |
1733 | my ($varname) = ($1); | | 1733 | my ($varname) = ($1); |
1734 | | | 1734 | |
1735 | if (defined($varname)) { | | 1735 | if (defined($varname)) { |
1736 | push(@{$result}, $varname); | | 1736 | push(@{$result}, $varname); |
1737 | } | | 1737 | } |
1738 | } | | 1738 | } |
1739 | | | 1739 | |
1740 | if ($rest ne "") { | | 1740 | if ($rest ne "") { |
1741 | $opt_debug_misc and $line->log_warning("Could not extract variables: ${rest}"); | | 1741 | $opt_debug_misc and $line->log_warning("Could not extract variables: ${rest}"); |
1742 | } | | 1742 | } |
1743 | | | 1743 | |
1744 | return $result; | | 1744 | return $result; |
1745 | } | | 1745 | } |
1746 | | | 1746 | |
1747 | sub get_nbpart() { | | 1747 | sub get_nbpart() { |
1748 | my $line = $pkgctx_vardef->{"PKGREVISION"}; | | 1748 | my $line = $pkgctx_vardef->{"PKGREVISION"}; |
1749 | return "" unless defined($line); | | 1749 | return "" unless defined($line); |
1750 | my $pkgrevision = $line->get("value"); | | 1750 | my $pkgrevision = $line->get("value"); |
1751 | return "" unless $pkgrevision =~ m"^\d+$"; | | 1751 | return "" unless $pkgrevision =~ m"^\d+$"; |
1752 | return "" unless $pkgrevision + 0 != 0; | | 1752 | return "" unless $pkgrevision + 0 != 0; |
1753 | return "nb$pkgrevision"; | | 1753 | return "nb$pkgrevision"; |
1754 | } | | 1754 | } |
1755 | | | 1755 | |
1756 | my $check_pkglint_version_done = false; | | 1756 | my $check_pkglint_version_done = false; |
1757 | sub check_pkglint_version() { | | 1757 | sub check_pkglint_version() { |
1758 | | | 1758 | |
1759 | return if $check_pkglint_version_done; | | 1759 | return if $check_pkglint_version_done; |
1760 | $check_pkglint_version_done = true; | | 1760 | $check_pkglint_version_done = true; |
1761 | | | 1761 | |
1762 | my $lines = load_lines("${cwd_pkgsrcdir}/pkgtools/pkglint/Makefile", true); | | 1762 | my $lines = load_lines("${cwd_pkgsrcdir}/pkgtools/pkglint/Makefile", true); |
1763 | return unless $lines; | | 1763 | return unless $lines; |
1764 | | | 1764 | |
1765 | my $pkglint_version = undef; | | 1765 | my $pkglint_version = undef; |
1766 | foreach my $line (@{$lines}) { | | 1766 | foreach my $line (@{$lines}) { |
1767 | if ($line->text =~ regex_varassign) { | | 1767 | if ($line->text =~ regex_varassign) { |
1768 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); | | 1768 | my ($varname, undef, $value, undef) = ($1, $2, $3, $4); |
1769 | | | 1769 | |
1770 | if ($varname eq "DISTNAME" || $varname eq "PKGNAME") { | | 1770 | if ($varname eq "DISTNAME" || $varname eq "PKGNAME") { |
1771 | if ($value =~ regex_pkgname) { | | 1771 | if ($value =~ regex_pkgname) { |
1772 | $pkglint_version = $2; | | 1772 | $pkglint_version = $2; |
1773 | } | | 1773 | } |
1774 | } | | 1774 | } |
1775 | } | | 1775 | } |
1776 | } | | 1776 | } |
1777 | return unless defined($pkglint_version); | | 1777 | return unless defined($pkglint_version); |
1778 | | | 1778 | |
1779 | if (dewey_cmp($pkglint_version, ">", conf_distver)) { | | 1779 | if (dewey_cmp($pkglint_version, ">", conf_distver)) { |
1780 | log_note(NO_FILE, NO_LINE_NUMBER, "A newer version of pkglint is available."); | | 1780 | log_note(NO_FILE, NO_LINE_NUMBER, "A newer version of pkglint is available."); |
1781 | } elsif (dewey_cmp($pkglint_version, "<", conf_distver)) { | | 1781 | } elsif (dewey_cmp($pkglint_version, "<", conf_distver)) { |
1782 | log_error(NO_FILE, NO_LINE_NUMBER, "The pkglint version is newer than the tree to check."); | | 1782 | log_error(NO_FILE, NO_LINE_NUMBER, "The pkglint version is newer than the tree to check."); |
1783 | } | | 1783 | } |
1784 | } | | 1784 | } |
1785 | | | 1785 | |
1786 | # When processing a file using the expect* subroutines below, it may | | 1786 | # When processing a file using the expect* subroutines below, it may |
1787 | # happen that $lineno points past the end of the file. In that case, | | 1787 | # happen that $lineno points past the end of the file. In that case, |
1788 | # print the warning without associated source code. | | 1788 | # print the warning without associated source code. |
1789 | sub lines_log_warning($$$) { | | 1789 | sub lines_log_warning($$$) { |
1790 | my ($lines, $lineno, $msg) = @_; | | 1790 | my ($lines, $lineno, $msg) = @_; |
1791 | | | 1791 | |
1792 | assert(0 <= $lineno, "The line number is negative (${lineno})."); | | 1792 | assert(0 <= $lineno, "The line number is negative (${lineno})."); |
1793 | assert(@{$lines} != 0, "The lines may not be empty."); | | 1793 | assert(@{$lines} != 0, "The lines may not be empty."); |
1794 | | | 1794 | |
1795 | if ($lineno <= $#{$lines}) { | | 1795 | if ($lineno <= $#{$lines}) { |
1796 | $lines->[$lineno]->log_warning($msg); | | 1796 | $lines->[$lineno]->log_warning($msg); |
1797 | } else { | | 1797 | } else { |
1798 | log_warning($lines->[0]->fname, "EOF", $msg); | | 1798 | log_warning($lines->[0]->fname, "EOF", $msg); |
1799 | } | | 1799 | } |
1800 | } | | 1800 | } |
1801 | | | 1801 | |
1802 | # Checks if the current line ($lines->{${$lineno_ref}}) matches the | | 1802 | # Checks if the current line ($lines->{${$lineno_ref}}) matches the |
1803 | # regular expression, and if it does, increments ${${lineno_ref}}. | | 1803 | # regular expression, and if it does, increments ${${lineno_ref}}. |
1804 | # @param $lines | | 1804 | # @param $lines |
1805 | # The lines that are checked. | | 1805 | # The lines that are checked. |
1806 | # @param $lineno_ref | | 1806 | # @param $lineno_ref |
1807 | # A reference to the line number, an integer variable. | | 1807 | # A reference to the line number, an integer variable. |
1808 | # @param $regex | | 1808 | # @param $regex |
1809 | # The regular expression to be checked. | | 1809 | # The regular expression to be checked. |
1810 | # @return | | 1810 | # @return |
1811 | # The result of the regular expression match or false. | | 1811 | # The result of the regular expression match or false. |
1812 | sub expect($$$) { | | 1812 | sub expect($$$) { |
1813 | my ($lines, $lineno_ref, $regex) = @_; | | 1813 | my ($lines, $lineno_ref, $regex) = @_; |
1814 | my $lineno = ${$lineno_ref}; | | 1814 | my $lineno = ${$lineno_ref}; |
1815 | | | 1815 | |
1816 | if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ $regex) { | | 1816 | if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ $regex) { |
1817 | ${$lineno_ref}++; | | 1817 | ${$lineno_ref}++; |
1818 | return PkgLint::SimpleMatch->new($lines->[$lineno]->text, \@-, \@+); | | 1818 | return PkgLint::SimpleMatch->new($lines->[$lineno]->text, \@-, \@+); |
1819 | } else { | | 1819 | } else { |
1820 | return false; | | 1820 | return false; |
1821 | } | | 1821 | } |
1822 | } | | 1822 | } |
1823 | | | 1823 | |
1824 | sub expect_empty_line($$) { | | 1824 | sub expect_empty_line($$) { |
1825 | my ($lines, $lineno_ref) = @_; | | 1825 | my ($lines, $lineno_ref) = @_; |
1826 | | | 1826 | |
1827 | if (expect($lines, $lineno_ref, qr"^$")) { | | 1827 | if (expect($lines, $lineno_ref, qr"^$")) { |
1828 | return true; | | 1828 | return true; |
1829 | } else { | | 1829 | } else { |
1830 | $opt_warn_space and $lines->[${$lineno_ref}]->log_note("Empty line expected."); | | 1830 | $opt_warn_space and $lines->[${$lineno_ref}]->log_note("Empty line expected."); |
1831 | return false; | | 1831 | return false; |
1832 | } | | 1832 | } |
1833 | } | | 1833 | } |
1834 | | | 1834 | |
1835 | sub expect_text($$$) { | | 1835 | sub expect_text($$$) { |
1836 | my ($lines, $lineno_ref, $text) = @_; | | 1836 | my ($lines, $lineno_ref, $text) = @_; |
1837 | | | 1837 | |
1838 | my $rv = expect($lines, $lineno_ref, qr"^\Q${text}\E$"); | | 1838 | my $rv = expect($lines, $lineno_ref, qr"^\Q${text}\E$"); |
1839 | $rv or lines_log_warning($lines, ${$lineno_ref}, "Expected \"${text}\"."); | | 1839 | $rv or lines_log_warning($lines, ${$lineno_ref}, "Expected \"${text}\"."); |
1840 | return $rv; | | 1840 | return $rv; |
1841 | } | | 1841 | } |
1842 | | | 1842 | |
1843 | sub expect_re($$$) { | | 1843 | sub expect_re($$$) { |
1844 | my ($lines, $lineno_ref, $re) = @_; | | 1844 | my ($lines, $lineno_ref, $re) = @_; |
1845 | | | 1845 | |
1846 | my $rv = expect($lines, $lineno_ref, $re); | | 1846 | my $rv = expect($lines, $lineno_ref, $re); |
1847 | $rv or lines_log_warning($lines, ${$lineno_ref}, "Expected text matching $re."); | | 1847 | $rv or lines_log_warning($lines, ${$lineno_ref}, "Expected text matching $re."); |
1848 | return $rv; | | 1848 | return $rv; |
1849 | } | | 1849 | } |
1850 | | | 1850 | |
1851 | # Returns an object of type Pkglint::Type that represents the type of | | 1851 | # Returns an object of type Pkglint::Type that represents the type of |
1852 | # the variable (maybe guessed based on the variable name), or undef if | | 1852 | # the variable (maybe guessed based on the variable name), or undef if |
1853 | # the type cannot even be guessed. | | 1853 | # the type cannot even be guessed. |
1854 | # | | 1854 | # |
1855 | sub get_variable_type($$) { | | 1855 | sub get_variable_type($$) { |
1856 | my ($line, $varname) = @_; | | 1856 | my ($line, $varname) = @_; |
1857 | my ($type); | | 1857 | my ($type); |
1858 | | | 1858 | |
1859 | assert(defined($varname), "The varname parameter must be defined."); | | 1859 | assert(defined($varname), "The varname parameter must be defined."); |
1860 | | | 1860 | |
1861 | if (exists(get_vartypes_map()->{$varname})) { | | 1861 | if (exists(get_vartypes_map()->{$varname})) { |
1862 | return get_vartypes_map()->{$varname}; | | 1862 | return get_vartypes_map()->{$varname}; |
1863 | } | | 1863 | } |
1864 | | | 1864 | |
1865 | my $varcanon = varname_canon($varname); | | 1865 | my $varcanon = varname_canon($varname); |
1866 | if (exists(get_vartypes_map()->{$varcanon})) { | | 1866 | if (exists(get_vartypes_map()->{$varcanon})) { |
1867 | return get_vartypes_map()->{$varcanon}; | | 1867 | return get_vartypes_map()->{$varcanon}; |
1868 | } | | 1868 | } |
1869 | | | 1869 | |
1870 | if (exists(get_varname_to_toolname()->{$varname})) { | | 1870 | if (exists(get_varname_to_toolname()->{$varname})) { |
1871 | return PkgLint::Type->new(LK_NONE, "ShellCommand", [[ qr".*", "u" ]], NOT_GUESSED); | | 1871 | return PkgLint::Type->new(LK_NONE, "ShellCommand", [[ qr".*", "u" ]], NOT_GUESSED); |
1872 | } | | 1872 | } |
1873 | | | 1873 | |
1874 | if ($varname =~ m"^TOOLS_(.*)" && exists(get_varname_to_toolname()->{$1})) { | | 1874 | if ($varname =~ m"^TOOLS_(.*)" && exists(get_varname_to_toolname()->{$1})) { |
1875 | return PkgLint::Type->new(LK_NONE, "Pathname", [[ qr".*", "u" ]], NOT_GUESSED); | | 1875 | return PkgLint::Type->new(LK_NONE, "Pathname", [[ qr".*", "u" ]], NOT_GUESSED); |
1876 | } | | 1876 | } |
1877 | | | 1877 | |
1878 | use constant allow_all => [[ qr".*", "adpsu" ]]; | | 1878 | use constant allow_all => [[ qr".*", "adpsu" ]]; |
1879 | use constant allow_runtime => [[ qr".*", "adsu" ]]; | | 1879 | use constant allow_runtime => [[ qr".*", "adsu" ]]; |
1880 | | | 1880 | |
1881 | # Guess the datatype of the variable based on | | 1881 | # Guess the datatype of the variable based on |
1882 | # naming conventions. | | 1882 | # naming conventions. |
1883 | $type = ($varname =~ m"DIRS$") ? PkgLint::Type->new(LK_EXTERNAL, "Pathmask", allow_runtime, GUESSED) | | 1883 | $type = ($varname =~ m"DIRS$") ? PkgLint::Type->new(LK_EXTERNAL, "Pathmask", allow_runtime, GUESSED) |
1884 | : ($varname =~ m"(?:DIR|_HOME)$") ? PkgLint::Type->new(LK_NONE, "Pathname", allow_runtime, GUESSED) | | 1884 | : ($varname =~ m"(?:DIR|_HOME)$") ? PkgLint::Type->new(LK_NONE, "Pathname", allow_runtime, GUESSED) |
1885 | : ($varname =~ m"FILES$") ? PkgLint::Type->new(LK_EXTERNAL, "Pathmask", allow_runtime, GUESSED) | | 1885 | : ($varname =~ m"FILES$") ? PkgLint::Type->new(LK_EXTERNAL, "Pathmask", allow_runtime, GUESSED) |
1886 | : ($varname =~ m"FILE$") ? PkgLint::Type->new(LK_NONE, "Pathname", allow_runtime, GUESSED) | | 1886 | : ($varname =~ m"FILE$") ? PkgLint::Type->new(LK_NONE, "Pathname", allow_runtime, GUESSED) |
1887 | : ($varname =~ m"PATH$") ? PkgLint::Type->new(LK_NONE, "Pathlist", allow_runtime, GUESSED) | | 1887 | : ($varname =~ m"PATH$") ? PkgLint::Type->new(LK_NONE, "Pathlist", allow_runtime, GUESSED) |
1888 | : ($varname =~ m"PATHS$") ? PkgLint::Type->new(LK_EXTERNAL, "Pathname", allow_runtime, GUESSED) | | 1888 | : ($varname =~ m"PATHS$") ? PkgLint::Type->new(LK_EXTERNAL, "Pathname", allow_runtime, GUESSED) |
1889 | : ($varname =~ m"_USER$") ? PkgLint::Type->new(LK_NONE, "UserGroupName", allow_all, GUESSED) | | 1889 | : ($varname =~ m"_USER$") ? PkgLint::Type->new(LK_NONE, "UserGroupName", allow_all, GUESSED) |
1890 | : ($varname =~ m"_GROUP$") ? PkgLint::Type->new(LK_NONE, "UserGroupName", allow_all, GUESSED) | | 1890 | : ($varname =~ m"_GROUP$") ? PkgLint::Type->new(LK_NONE, "UserGroupName", allow_all, GUESSED) |
1891 | : ($varname =~ m"_ENV$") ? PkgLint::Type->new(LK_EXTERNAL, "ShellWord", allow_runtime, GUESSED) | | 1891 | : ($varname =~ m"_ENV$") ? PkgLint::Type->new(LK_EXTERNAL, "ShellWord", allow_runtime, GUESSED) |
1892 | : ($varname =~ m"_CMD$") ? PkgLint::Type->new(LK_NONE, "ShellCommand", allow_runtime, GUESSED) | | 1892 | : ($varname =~ m"_CMD$") ? PkgLint::Type->new(LK_NONE, "ShellCommand", allow_runtime, GUESSED) |
1893 | : ($varname =~ m"_ARGS$") ? PkgLint::Type->new(LK_EXTERNAL, "ShellWord", allow_runtime, GUESSED) | | 1893 | : ($varname =~ m"_ARGS$") ? PkgLint::Type->new(LK_EXTERNAL, "ShellWord", allow_runtime, GUESSED) |
1894 | : ($varname =~ m"_(?:C|CPP|CXX|LD|)FLAGS$") ? PkgLint::Type->new(LK_EXTERNAL, "ShellWord", allow_runtime, GUESSED) | | 1894 | : ($varname =~ m"_(?:C|CPP|CXX|LD|)FLAGS$") ? PkgLint::Type->new(LK_EXTERNAL, "ShellWord", allow_runtime, GUESSED) |
1895 | : ($varname =~ m"_MK$") ? PkgLint::Type->new(LK_NONE, "Unchecked", allow_all, GUESSED) | | 1895 | : ($varname =~ m"_MK$") ? PkgLint::Type->new(LK_NONE, "Unchecked", allow_all, GUESSED) |
1896 | : ($varname =~ m"^PLIST.") ? PkgLint::Type->new(LK_NONE, "Yes", allow_all, GUESSED) | | 1896 | : ($varname =~ m"^PLIST.") ? PkgLint::Type->new(LK_NONE, "Yes", allow_all, GUESSED) |
1897 | : undef; | | 1897 | : undef; |
1898 | | | 1898 | |
1899 | if (defined($type)) { | | 1899 | if (defined($type)) { |
1900 | $opt_debug_vartypes and $line->log_debug("The guessed type of ${varname} is \"" . $type->to_string . "\"."); | | 1900 | $opt_debug_vartypes and $line->log_debug("The guessed type of ${varname} is \"" . $type->to_string . "\"."); |
1901 | return $type; | | 1901 | return $type; |
1902 | } | | 1902 | } |
1903 | | | 1903 | |
1904 | $opt_debug_vartypes and $line->log_debug("No type definition found for ${varcanon}."); | | 1904 | $opt_debug_vartypes and $line->log_debug("No type definition found for ${varcanon}."); |
1905 | return undef; | | 1905 | return undef; |
1906 | } | | 1906 | } |
1907 | | | 1907 | |
1908 | sub get_variable_perms($$) { | | 1908 | sub get_variable_perms($$) { |
1909 | my ($line, $varname) = @_; | | 1909 | my ($line, $varname) = @_; |
1910 | | | 1910 | |
1911 | my $type = get_variable_type($line, $varname); | | 1911 | my $type = get_variable_type($line, $varname); |
1912 | if (!defined($type)) { | | 1912 | if (!defined($type)) { |
1913 | $opt_debug_misc and $line->log_debug("No type definition found for ${varname}."); | | 1913 | $opt_debug_misc and $line->log_debug("No type definition found for ${varname}."); |
1914 | return "adpsu"; | | 1914 | return "adpsu"; |
1915 | } | | 1915 | } |
1916 | | | 1916 | |
1917 | my $perms = $type->perms($line->fname, $varname); | | 1917 | my $perms = $type->perms($line->fname, $varname); |
1918 | if (!defined($perms)) { | | 1918 | if (!defined($perms)) { |
1919 | $opt_debug_misc and $line->log_debug("No permissions specified for ${varname}."); | | 1919 | $opt_debug_misc and $line->log_debug("No permissions specified for ${varname}."); |
1920 | return "?"; | | 1920 | return "?"; |
1921 | } | | 1921 | } |
1922 | return $perms; | | 1922 | return $perms; |
1923 | } | | 1923 | } |
1924 | | | 1924 | |
1925 | # This function returns whether a variable needs the :Q operator in a | | 1925 | # This function returns whether a variable needs the :Q operator in a |
1926 | # certain context. There are four possible outcomes: | | 1926 | # certain context. There are four possible outcomes: |
1927 | # | | 1927 | # |
1928 | # false: The variable should not be quoted. | | 1928 | # false: The variable should not be quoted. |
1929 | # true: The variable should be quoted. | | 1929 | # true: The variable should be quoted. |
1930 | # doesnt_matter: | | 1930 | # doesnt_matter: |
1931 | # Since the values of the variable usually don't contain | | 1931 | # Since the values of the variable usually don't contain |
1932 | # special characters, it does not matter whether the | | 1932 | # special characters, it does not matter whether the |
1933 | # variable is quoted or not. | | 1933 | # variable is quoted or not. |
1934 | # dont_know: pkglint cannot say whether the variable should be quoted | | 1934 | # dont_know: pkglint cannot say whether the variable should be quoted |
1935 | # or not, most likely because type information is missing. | | 1935 | # or not, most likely because type information is missing. |
1936 | # | | 1936 | # |
1937 | sub variable_needs_quoting($$$) { | | 1937 | sub variable_needs_quoting($$$) { |
1938 | my ($line, $varname, $context) = @_; | | 1938 | my ($line, $varname, $context) = @_; |
1939 | my $type = get_variable_type($line, $varname); | | 1939 | my $type = get_variable_type($line, $varname); |
1940 | my ($want_list, $have_list); | | 1940 | my ($want_list, $have_list); |
1941 | | | 1941 | |
1942 | $opt_debug_trace and $line->log_debug("variable_needs_quoting($varname, " . $context->to_string() . ")"); | | 1942 | $opt_debug_trace and $line->log_debug("variable_needs_quoting($varname, " . $context->to_string() . ")"); |
1943 | | | 1943 | |
1944 | use constant safe_types => array_to_hash(qw( | | 1944 | use constant safe_types => array_to_hash(qw( |
1945 | DistSuffix | | 1945 | DistSuffix |
1946 | FileMode Filename | | 1946 | FileMode Filename |
1947 | Identifier | | 1947 | Identifier |
1948 | Option | | 1948 | Option |
1949 | Pathname PkgName PkgOptionsVar PkgRevision | | 1949 | Pathname PkgName PkgOptionsVar PkgRevision |
1950 | RelativePkgDir RelativePkgPath | | 1950 | RelativePkgDir RelativePkgPath |
1951 | UserGroupName | | 1951 | UserGroupName |
1952 | Varname Version | | 1952 | Varname Version |
1953 | WrkdirSubdirectory | | 1953 | WrkdirSubdirectory |
1954 | )); | | 1954 | )); |
1955 | | | 1955 | |
1956 | if (!defined($type) || !defined($context->type)) { | | 1956 | if (!defined($type) || !defined($context->type)) { |
1957 | return dont_know; | | 1957 | return dont_know; |
1958 | } | | 1958 | } |
1959 | | | 1959 | |
1960 | # Variables of certain predefined types, as well as all | | 1960 | # Variables of certain predefined types, as well as all |
1961 | # enumerations, are expected to not require the :Q operator. | | 1961 | # enumerations, are expected to not require the :Q operator. |
1962 | if (ref($type->basic_type) eq "HASH" || exists(safe_types->{$type->basic_type})) { | | 1962 | if (ref($type->basic_type) eq "HASH" || exists(safe_types->{$type->basic_type})) { |
1963 | if ($type->kind_of_list == LK_NONE) { | | 1963 | if ($type->kind_of_list == LK_NONE) { |
1964 | return doesnt_matter; | | 1964 | return doesnt_matter; |
1965 | | | 1965 | |
1966 | } elsif ($type->kind_of_list == LK_EXTERNAL && $context->extent != VUC_EXTENT_WORD_PART) { | | 1966 | } elsif ($type->kind_of_list == LK_EXTERNAL && $context->extent != VUC_EXTENT_WORD_PART) { |
1967 | return false; | | 1967 | return false; |
1968 | } | | 1968 | } |
1969 | } | | 1969 | } |
1970 | | | 1970 | |
1971 | # In .for loops, the :Q operator is always misplaced, since | | 1971 | # In .for loops, the :Q operator is always misplaced, since |
1972 | # the items are broken up at white-space, not as shell words | | 1972 | # the items are broken up at white-space, not as shell words |
1973 | # like in all other parts of make(1). | | 1973 | # like in all other parts of make(1). |
1974 | if ($context->shellword == VUC_SHELLWORD_FOR) { | | 1974 | if ($context->shellword == VUC_SHELLWORD_FOR) { |
1975 | return false; | | 1975 | return false; |
1976 | } | | 1976 | } |
1977 | | | 1977 | |
1978 | # Determine whether the context expects a list of shell words or | | 1978 | # Determine whether the context expects a list of shell words or |
1979 | # not. | | 1979 | # not. |
1980 | $want_list = $context->type->is_practically_a_list() && ($context->shellword == VUC_SHELLWORD_BACKT || $context->extent != VUC_EXTENT_WORD_PART); | | 1980 | $want_list = $context->type->is_practically_a_list() && ($context->shellword == VUC_SHELLWORD_BACKT || $context->extent != VUC_EXTENT_WORD_PART); |
1981 | $have_list = $type->is_practically_a_list(); | | 1981 | $have_list = $type->is_practically_a_list(); |
1982 | | | 1982 | |
1983 | $opt_debug_quoting and $line->log_debug("[variable_needs_quoting]" | | 1983 | $opt_debug_quoting and $line->log_debug("[variable_needs_quoting]" |
1984 | . " varname=$varname" | | 1984 | . " varname=$varname" |
1985 | . " context=" . $context->to_string() | | 1985 | . " context=" . $context->to_string() |
1986 | . " type=" . $type->to_string() | | 1986 | . " type=" . $type->to_string() |
1987 | . " want_list=" . ($want_list ? "yes" : "no") | | 1987 | . " want_list=" . ($want_list ? "yes" : "no") |
1988 | . " have_list=" . ($have_list ? "yes" : "no") | | 1988 | . " have_list=" . ($have_list ? "yes" : "no") |
1989 | . "."); | | 1989 | . "."); |
1990 | | | 1990 | |
1991 | # A shell word may appear as part of a shell word, for example | | 1991 | # A shell word may appear as part of a shell word, for example |
1992 | # COMPILER_RPATH_FLAG. | | 1992 | # COMPILER_RPATH_FLAG. |
1993 | if ($context->extent == VUC_EXTENT_WORD_PART && $context->shellword == VUC_SHELLWORD_PLAIN) { | | 1993 | if ($context->extent == VUC_EXTENT_WORD_PART && $context->shellword == VUC_SHELLWORD_PLAIN) { |
1994 | if ($type->kind_of_list == LK_NONE && $type->basic_type eq "ShellWord") { | | 1994 | if ($type->kind_of_list == LK_NONE && $type->basic_type eq "ShellWord") { |
1995 | return false; | | 1995 | return false; |
1996 | } | | 1996 | } |
1997 | } | | 1997 | } |
1998 | | | 1998 | |
1999 | # Assume that the tool definitions don't include very special | | 1999 | # Assume that the tool definitions don't include very special |
2000 | # characters, so they can safely be used inside any quotes. | | 2000 | # characters, so they can safely be used inside any quotes. |
2001 | if (exists(get_varname_to_toolname()->{$varname})) { | | 2001 | if (exists(get_varname_to_toolname()->{$varname})) { |
2002 | my $sw = $context->shellword; | | 2002 | my $sw = $context->shellword; |
2003 | | | 2003 | |
2004 | if ($sw == VUC_SHELLWORD_PLAIN && $context->extent != VUC_EXTENT_WORD_PART) { | | 2004 | if ($sw == VUC_SHELLWORD_PLAIN && $context->extent != VUC_EXTENT_WORD_PART) { |
2005 | return false; | | 2005 | return false; |
2006 | | | 2006 | |
2007 | } elsif ($sw == VUC_SHELLWORD_BACKT) { | | 2007 | } elsif ($sw == VUC_SHELLWORD_BACKT) { |
2008 | return false; | | 2008 | return false; |
2009 | | | 2009 | |
2010 | } elsif ($sw == VUC_SHELLWORD_DQUOT || $sw == VUC_SHELLWORD_SQUOT) { | | 2010 | } elsif ($sw == VUC_SHELLWORD_DQUOT || $sw == VUC_SHELLWORD_SQUOT) { |
2011 | return doesnt_matter; | | 2011 | return doesnt_matter; |
2012 | | | 2012 | |
2013 | } else { | | 2013 | } else { |
2014 | # Let the other rules decide. | | 2014 | # Let the other rules decide. |
2015 | } | | 2015 | } |
2016 | } | | 2016 | } |
2017 | | | 2017 | |
2018 | # Variables that appear as parts of shell words generally need | | 2018 | # Variables that appear as parts of shell words generally need |
2019 | # to be quoted. An exception is in the case of backticks, | | 2019 | # to be quoted. An exception is in the case of backticks, |
2020 | # because the whole backticks expression is parsed as a single | | 2020 | # because the whole backticks expression is parsed as a single |
2021 | # shell word by pkglint. | | 2021 | # shell word by pkglint. |
2022 | # | | 2022 | # |
2023 | # XXX: When the shell word parser gets rewritten the next time, | | 2023 | # XXX: When the shell word parser gets rewritten the next time, |
2024 | # this test can be refined. | | 2024 | # this test can be refined. |
2025 | if ($context->extent == VUC_EXTENT_WORD_PART && $context->shellword != VUC_SHELLWORD_BACKT) { | | 2025 | if ($context->extent == VUC_EXTENT_WORD_PART && $context->shellword != VUC_SHELLWORD_BACKT) { |
2026 | return true; | | 2026 | return true; |
2027 | } | | 2027 | } |
2028 | | | 2028 | |
2029 | # Assigning lists to lists does not require any quoting, though | | 2029 | # Assigning lists to lists does not require any quoting, though |
2030 | # there may be cases like "CONFIGURE_ARGS+= -libs ${LDFLAGS:Q}" | | 2030 | # there may be cases like "CONFIGURE_ARGS+= -libs ${LDFLAGS:Q}" |
2031 | # where quoting is necessary. So let's hope that no developer | | 2031 | # where quoting is necessary. So let's hope that no developer |
2032 | # ever makes the mistake of using :Q when appending a list to | | 2032 | # ever makes the mistake of using :Q when appending a list to |
2033 | # a list. | | 2033 | # a list. |
2034 | if ($want_list && $have_list) { | | 2034 | if ($want_list && $have_list) { |
2035 | return doesnt_matter; | | 2035 | return doesnt_matter; |
2036 | } | | 2036 | } |
2037 | | | 2037 | |
2038 | # Appending elements to a list requires quoting, as well as | | 2038 | # Appending elements to a list requires quoting, as well as |
2039 | # assigning a list value to a non-list variable. | | 2039 | # assigning a list value to a non-list variable. |
2040 | if ($want_list != $have_list) { | | 2040 | if ($want_list != $have_list) { |
2041 | return true; | | 2041 | return true; |
2042 | } | | 2042 | } |
2043 | | | 2043 | |
2044 | $opt_debug_quoting and $line->log_debug("Don't know whether :Q is needed for ${varname}."); | | 2044 | $opt_debug_quoting and $line->log_debug("Don't know whether :Q is needed for ${varname}."); |
2045 | return dont_know; | | 2045 | return dont_know; |
2046 | } | | 2046 | } |
2047 | | | 2047 | |
2048 | # | | 2048 | # |
2049 | # Parsing. | | 2049 | # Parsing. |
2050 | # | | 2050 | # |
2051 | | | 2051 | |
2052 | # Checks whether $tree matches $pattern, and if so, instanciates the | | 2052 | # Checks whether $tree matches $pattern, and if so, instanciates the |
2053 | # variables in $pattern. If they don't match, some variables may be | | 2053 | # variables in $pattern. If they don't match, some variables may be |
2054 | # instanciated nevertheless, but the exact behavior is unspecified. | | 2054 | # instanciated nevertheless, but the exact behavior is unspecified. |
2055 | # | | 2055 | # |
2056 | sub tree_match($$); | | 2056 | sub tree_match($$); |
2057 | sub tree_match($$) { | | 2057 | sub tree_match($$) { |
2058 | my ($tree, $pattern) = @_; | | 2058 | my ($tree, $pattern) = @_; |
2059 | | | 2059 | |
2060 | my $d1 = Data::Dumper->new([$tree, $pattern])->Terse(true)->Indent(0); | | 2060 | my $d1 = Data::Dumper->new([$tree, $pattern])->Terse(true)->Indent(0); |
2061 | my $d2 = Data::Dumper->new([$pattern])->Terse(true)->Indent(0); | | 2061 | my $d2 = Data::Dumper->new([$pattern])->Terse(true)->Indent(0); |
2062 | $opt_debug_trace and log_debug(NO_FILE, NO_LINES, sprintf("tree_match(%s, %s)", $d1->Dump, $d2->Dump)); | | 2062 | $opt_debug_trace and log_debug(NO_FILE, NO_LINES, sprintf("tree_match(%s, %s)", $d1->Dump, $d2->Dump)); |
2063 | | | 2063 | |
2064 | return true if (!defined($tree) && !defined($pattern)); | | 2064 | return true if (!defined($tree) && !defined($pattern)); |
2065 | return false if (!defined($tree) || !defined($pattern)); | | 2065 | return false if (!defined($tree) || !defined($pattern)); |
2066 | my $aref = ref($tree); | | 2066 | my $aref = ref($tree); |
2067 | my $pref = ref($pattern); | | 2067 | my $pref = ref($pattern); |
2068 | if ($pref eq "SCALAR" && !defined($$pattern)) { | | 2068 | if ($pref eq "SCALAR" && !defined($$pattern)) { |
2069 | $$pattern = $tree; | | 2069 | $$pattern = $tree; |
2070 | return true; | | 2070 | return true; |
2071 | } | | 2071 | } |
2072 | if ($aref eq "" && ($pref eq "" || $pref eq "SCALAR")) { | | 2072 | if ($aref eq "" && ($pref eq "" || $pref eq "SCALAR")) { |
2073 | return $tree eq $pattern; | | 2073 | return $tree eq $pattern; |
2074 | } | | 2074 | } |
2075 | if ($aref eq "ARRAY" && $pref eq "ARRAY") { | | 2075 | if ($aref eq "ARRAY" && $pref eq "ARRAY") { |
2076 | return false if scalar(@$tree) != scalar(@$pattern); | | 2076 | return false if scalar(@$tree) != scalar(@$pattern); |
2077 | for (my $i = 0; $i < scalar(@$tree); $i++) { | | 2077 | for (my $i = 0; $i < scalar(@$tree); $i++) { |
2078 | return false unless tree_match($tree->[$i], $pattern->[$i]); | | 2078 | return false unless tree_match($tree->[$i], $pattern->[$i]); |
2079 | } | | 2079 | } |
2080 | return true; | | 2080 | return true; |
2081 | } | | 2081 | } |
2082 | return false; | | 2082 | return false; |
2083 | } | | 2083 | } |
2084 | | | 2084 | |
2085 | # TODO: Needs to be redesigned to handle more complex expressions. | | 2085 | # TODO: Needs to be redesigned to handle more complex expressions. |
2086 | sub parse_mk_cond($$); | | 2086 | sub parse_mk_cond($$); |
2087 | sub parse_mk_cond($$) { | | 2087 | sub parse_mk_cond($$) { |
2088 | my ($line, $cond) = @_; | | 2088 | my ($line, $cond) = @_; |
2089 | | | 2089 | |
2090 | $opt_debug_trace and $line->log_debug("parse_mk_cond(\"${cond}\")"); | | 2090 | $opt_debug_trace and $line->log_debug("parse_mk_cond(\"${cond}\")"); |
2091 | | | 2091 | |
2092 | my $re_simple_varname = qr"[A-Z_][A-Z0-9_]*(?:\.[\w_+\-]+)?"; | | 2092 | my $re_simple_varname = qr"[A-Z_][A-Z0-9_]*(?:\.[\w_+\-]+)?"; |
2093 | while ($cond ne "") { | | 2093 | while ($cond ne "") { |
2094 | if ($cond =~ s/^!//) { | | 2094 | if ($cond =~ s/^!//) { |
2095 | return ["not", parse_mk_cond($line, $cond)]; | | 2095 | return ["not", parse_mk_cond($line, $cond)]; |
2096 | } elsif ($cond =~ s/^defined\((${re_simple_varname})\)$//) { | | 2096 | } elsif ($cond =~ s/^defined\((${re_simple_varname})\)$//) { |
2097 | return ["defined", $1]; | | 2097 | return ["defined", $1]; |
2098 | } elsif ($cond =~ s/^empty\((${re_simple_varname})\)$//) { | | 2098 | } elsif ($cond =~ s/^empty\((${re_simple_varname})\)$//) { |
2099 | return ["empty", $1]; | | 2099 | return ["empty", $1]; |
2100 | } elsif ($cond =~ s/^empty\((${re_simple_varname}):M([^\$:{})]+)\)$//) { | | 2100 | } elsif ($cond =~ s/^empty\((${re_simple_varname}):M([^\$:{})]+)\)$//) { |
2101 | return ["empty", ["match", $1, $2]]; | | 2101 | return ["empty", ["match", $1, $2]]; |
2102 | } elsif ($cond =~ s/^\$\{(${re_simple_varname})\}\s+(==|!=)\s+"([^"\$\\]*)"$//) { | | 2102 | } elsif ($cond =~ s/^\$\{(${re_simple_varname})\}\s+(==|!=)\s+"([^"\$\\]*)"$//) { |
2103 | return [$2, ["var", $1], ["string", $3]]; | | 2103 | return [$2, ["var", $1], ["string", $3]]; |
2104 | } else { | | 2104 | } else { |
2105 | $opt_debug_unchecked and $line->log_debug("parse_mk_cond: ${cond}"); | | 2105 | $opt_debug_unchecked and $line->log_debug("parse_mk_cond: ${cond}"); |
2106 | return ["unknown", $cond]; | | 2106 | return ["unknown", $cond]; |
2107 | } | | 2107 | } |
2108 | } | | 2108 | } |
2109 | } | | 2109 | } |
2110 | | | 2110 | |
2111 | sub parse_licenses($) { | | 2111 | sub parse_licenses($) { |
2112 | my ($licenses) = @_; | | 2112 | my ($licenses) = @_; |
2113 | | | 2113 | |
2114 | # XXX: this is clearly cheating | | 2114 | # XXX: this is clearly cheating |
2115 | $licenses =~ s,\${PERL5_LICENSE},gnu-gpl-v2 OR artistic,g; | | 2115 | $licenses =~ s,\${PERL5_LICENSE},gnu-gpl-v2 OR artistic,g; |
2116 | $licenses =~ s,[()]|AND|OR,,g; | | 2116 | $licenses =~ s,[()]|AND|OR,,g; |
2117 | my @licenses = split(/\s+/, $licenses); | | 2117 | my @licenses = split(/\s+/, $licenses); |
2118 | return \@licenses; | | 2118 | return \@licenses; |
2119 | } | | 2119 | } |
2120 | | | 2120 | |
2121 | # This procedure fills in the extra fields of a line, depending on the | | 2121 | # This procedure fills in the extra fields of a line, depending on the |
2122 | # line type. These fields can later be queried without having to parse | | 2122 | # line type. These fields can later be queried without having to parse |
2123 | # them again and again. | | 2123 | # them again and again. |
2124 | # | | 2124 | # |
2125 | sub parseline_mk($) { | | 2125 | sub parseline_mk($) { |
2126 | my ($line) = @_; | | 2126 | my ($line) = @_; |
2127 | my $text = $line->text; | | 2127 | my $text = $line->text; |
2128 | | | 2128 | |
2129 | if ($text =~ regex_varassign) { | | 2129 | if ($text =~ regex_varassign) { |
2130 | my ($varname, $op, $value, $comment) = ($1, $2, $3, $4); | | 2130 | my ($varname, $op, $value, $comment) = ($1, $2, $3, $4); |
2131 | | | 2131 | |
2132 | # In variable assignments, a '#' character is preceded | | 2132 | # In variable assignments, a '#' character is preceded |
2133 | # by a backslash. In shell commands, it is interpreted | | 2133 | # by a backslash. In shell commands, it is interpreted |
2134 | # literally. | | 2134 | # literally. |
2135 | $value =~ s/\\\#/\#/g; | | 2135 | $value =~ s/\\\#/\#/g; |
2136 | | | 2136 | |
2137 | $line->set("is_varassign", true); | | 2137 | $line->set("is_varassign", true); |
2138 | $line->set("varname", $varname); | | 2138 | $line->set("varname", $varname); |
2139 | $line->set("varcanon", varname_canon($varname)); | | 2139 | $line->set("varcanon", varname_canon($varname)); |
2140 | my $varparam = varname_param($varname); | | 2140 | my $varparam = varname_param($varname); |
2141 | defined($varparam) and $line->set("varparam", $varparam); | | 2141 | defined($varparam) and $line->set("varparam", $varparam); |
2142 | $line->set("op", $op); | | 2142 | $line->set("op", $op); |
2143 | $line->set("value", $value); | | 2143 | $line->set("value", $value); |
2144 | defined($comment) and $line->set("comment", $comment); | | 2144 | defined($comment) and $line->set("comment", $comment); |
2145 | | | 2145 | |
2146 | } elsif ($text =~ regex_mk_shellcmd) { | | 2146 | } elsif ($text =~ regex_mk_shellcmd) { |
2147 | my ($shellcmd) = ($1); | | 2147 | my ($shellcmd) = ($1); |
2148 | | | 2148 | |
2149 | # Shell command lines cannot have embedded comments. | | 2149 | # Shell command lines cannot have embedded comments. |
2150 | $line->set("is_shellcmd", true); | | 2150 | $line->set("is_shellcmd", true); |
2151 | $line->set("shellcmd", $shellcmd); | | 2151 | $line->set("shellcmd", $shellcmd); |
2152 | | | 2152 | |
2153 | my ($shellwords, $rest) = match_all($shellcmd, $regex_shellword); | | 2153 | my ($shellwords, $rest) = match_all($shellcmd, $regex_shellword); |
2154 | $line->set("shellwords", $shellwords); | | 2154 | $line->set("shellwords", $shellwords); |
2155 | if ($rest !~ m"^\s*$") { | | 2155 | if ($rest !~ m"^\s*$") { |
2156 | $line->set("shellwords_rest", $rest); | | 2156 | $line->set("shellwords_rest", $rest); |
2157 | } | | 2157 | } |
2158 | | | 2158 | |
2159 | } elsif ($text =~ regex_mk_comment) { | | 2159 | } elsif ($text =~ regex_mk_comment) { |
2160 | my ($comment) = ($1); | | 2160 | my ($comment) = ($1); |
2161 | | | 2161 | |
2162 | $line->set("is_comment", true); | | 2162 | $line->set("is_comment", true); |
2163 | $line->set("comment", $comment); | | 2163 | $line->set("comment", $comment); |
2164 | | | 2164 | |
2165 | } elsif ($text =~ m"^\s*$") { | | 2165 | } elsif ($text =~ m"^\s*$") { |
2166 | | | 2166 | |
2167 | $line->set("is_empty", true); | | 2167 | $line->set("is_empty", true); |
2168 | | | 2168 | |
2169 | } elsif ($text =~ regex_mk_cond) { | | 2169 | } elsif ($text =~ regex_mk_cond) { |
2170 | my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4); | | 2170 | my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4); |
2171 | | | 2171 | |
2172 | $line->set("is_cond", true); | | 2172 | $line->set("is_cond", true); |
2173 | $line->set("indent", $indent); | | 2173 | $line->set("indent", $indent); |
2174 | $line->set("directive", $directive); | | 2174 | $line->set("directive", $directive); |
2175 | defined($args) and $line->set("args", $args); | | 2175 | defined($args) and $line->set("args", $args); |
2176 | defined($comment) and $line->set("comment", $comment); | | 2176 | defined($comment) and $line->set("comment", $comment); |
2177 | | | 2177 | |
2178 | } elsif ($text =~ regex_mk_include) { | | 2178 | } elsif ($text =~ regex_mk_include) { |
2179 | my (undef, $includefile, $comment) = ($1, $2, $3); | | 2179 | my (undef, $includefile, $comment) = ($1, $2, $3); |
2180 | | | 2180 | |
2181 | $line->set("is_include", true); | | 2181 | $line->set("is_include", true); |
2182 | $line->set("includefile", $includefile); | | 2182 | $line->set("includefile", $includefile); |
2183 | defined($comment) and $line->set("comment", $comment); | | 2183 | defined($comment) and $line->set("comment", $comment); |
2184 | | | 2184 | |
2185 | } elsif ($text =~ regex_mk_sysinclude) { | | 2185 | } elsif ($text =~ regex_mk_sysinclude) { |
2186 | my ($includefile, $comment) = ($1, $2); | | 2186 | my ($includefile, $comment) = ($1, $2); |
2187 | | | 2187 | |
2188 | $line->set("is_sysinclude", true); | | 2188 | $line->set("is_sysinclude", true); |
2189 | $line->set("includefile", $includefile); | | 2189 | $line->set("includefile", $includefile); |
2190 | defined($comment) and $line->set("comment", $comment); | | 2190 | defined($comment) and $line->set("comment", $comment); |
2191 | | | 2191 | |
2192 | } elsif ($text =~ regex_mk_dependency) { | | 2192 | } elsif ($text =~ regex_mk_dependency) { |
2193 | my ($targets, $whitespace, $sources, $comment) = ($1, $2, $3, $4); | | 2193 | my ($targets, $whitespace, $sources, $comment) = ($1, $2, $3, $4); |
2194 | | | 2194 | |
2195 | $line->set("is_dependency", true); | | 2195 | $line->set("is_dependency", true); |
2196 | $line->set("targets", $targets); | | 2196 | $line->set("targets", $targets); |
2197 | $line->set("sources", $sources); | | 2197 | $line->set("sources", $sources); |
2198 | $line->log_warning("Space before colon in dependency line: " . $line->to_string()) if ($whitespace); | | 2198 | $line->log_warning("Space before colon in dependency line: " . $line->to_string()) if ($whitespace); |
2199 | defined($comment) and $line->set("comment", $comment); | | 2199 | defined($comment) and $line->set("comment", $comment); |
2200 | | | 2200 | |
2201 | } elsif ($text =~ regex_rcs_conflict) { | | 2201 | } elsif ($text =~ regex_rcs_conflict) { |
2202 | # This line is useless | | 2202 | # This line is useless |
2203 | | | 2203 | |
2204 | } else { | | 2204 | } else { |
2205 | $line->log_fatal("Unknown line format: " . $line->to_string()); | | 2205 | $line->log_fatal("Unknown line format: " . $line->to_string()); |
2206 | } | | 2206 | } |
2207 | } | | 2207 | } |
2208 | | | 2208 | |
2209 | sub parselines_mk($) { | | 2209 | sub parselines_mk($) { |
2210 | my ($lines) = @_; | | 2210 | my ($lines) = @_; |
2211 | | | 2211 | |
2212 | foreach my $line (@{$lines}) { | | 2212 | foreach my $line (@{$lines}) { |
2213 | parseline_mk($line); | | 2213 | parseline_mk($line); |
2214 | } | | 2214 | } |
2215 | } | | 2215 | } |
2216 | | | 2216 | |
2217 | # | | 2217 | # |
2218 | # Loading package-specific data from files. | | 2218 | # Loading package-specific data from files. |
2219 | # | | 2219 | # |
2220 | | | 2220 | |
2221 | sub readmakefile($$$$); | | 2221 | sub readmakefile($$$$); |
2222 | sub readmakefile($$$$) { | | 2222 | sub readmakefile($$$$) { |
2223 | my ($fname, $main_lines, $all_lines, $seen_Makefile_include) = @_; | | 2223 | my ($fname, $main_lines, $all_lines, $seen_Makefile_include) = @_; |
2224 | my ($includefile, $dirname, $lines, $is_main_Makefile); | | 2224 | my ($includefile, $dirname, $lines, $is_main_Makefile); |
2225 | | | 2225 | |
2226 | $lines = load_lines($fname, true); | | 2226 | $lines = load_lines($fname, true); |
2227 | if (!$lines) { | | 2227 | if (!$lines) { |
2228 | return false; | | 2228 | return false; |
2229 | } | | 2229 | } |
2230 | parselines_mk($lines); | | 2230 | parselines_mk($lines); |
2231 | | | 2231 | |
2232 | $is_main_Makefile = (@{$main_lines} == 0); | | 2232 | $is_main_Makefile = (@{$main_lines} == 0); |
2233 | | | 2233 | |
2234 | foreach my $line (@{$lines}) { | | 2234 | foreach my $line (@{$lines}) { |
2235 | my $text = $line->text; | | 2235 | my $text = $line->text; |
2236 | | | 2236 | |
2237 | if ($is_main_Makefile) { | | 2237 | if ($is_main_Makefile) { |
2238 | push(@{$main_lines}, $line); | | 2238 | push(@{$main_lines}, $line); |
2239 | } | | 2239 | } |
2240 | push(@{$all_lines}, $line); | | 2240 | push(@{$all_lines}, $line); |
2241 | | | 2241 | |
2242 | # try to get any included file | | 2242 | # try to get any included file |
2243 | my $is_include_line = false; | | 2243 | my $is_include_line = false; |
2244 | if ($text =~ m"^\.\s*include\s+\"(.*)\"$") { | | 2244 | if ($text =~ m"^\.\s*include\s+\"(.*)\"$") { |
2245 | $includefile = resolve_relative_path($1, true); | | 2245 | $includefile = resolve_relative_path($1, true); |
2246 | if ($includefile =~ regex_unresolved) { | | 2246 | if ($includefile =~ regex_unresolved) { |
2247 | if ($fname !~ m"/mk/") { | | 2247 | if ($fname !~ m"/mk/") { |
2248 | $line->log_note("Skipping include file \"${includefile}\". This may result in false warnings."); | | 2248 | $line->log_note("Skipping include file \"${includefile}\". This may result in false warnings."); |
2249 | } | | 2249 | } |
2250 | | | 2250 | |
2251 | } else { | | 2251 | } else { |
2252 | $is_include_line = true; | | 2252 | $is_include_line = true; |
2253 | } | | 2253 | } |
2254 | } | | 2254 | } |
2255 | | | 2255 | |
2256 | if ($is_include_line) { | | 2256 | if ($is_include_line) { |
2257 | if ($fname !~ m"buildlink3\.mk$" && $includefile =~ m"^\.\./\.\./(.*)/buildlink3\.mk$") { | | 2257 | if ($fname !~ m"buildlink3\.mk$" && $includefile =~ m"^\.\./\.\./(.*)/buildlink3\.mk$") { |
2258 | my ($bl3_file) = ($1); | | 2258 | my ($bl3_file) = ($1); |
2259 | | | 2259 | |
2260 | $pkgctx_bl3->{$bl3_file} = $line; | | 2260 | $pkgctx_bl3->{$bl3_file} = $line; |
2261 | $opt_debug_misc and $line->log_debug("Buildlink3 file in package: ${bl3_file}"); | | 2261 | $opt_debug_misc and $line->log_debug("Buildlink3 file in package: ${bl3_file}"); |
2262 | } | | 2262 | } |
2263 | } | | 2263 | } |
2264 | | | 2264 | |
2265 | if ($is_include_line && !exists($seen_Makefile_include->{$includefile})) { | | 2265 | if ($is_include_line && !exists($seen_Makefile_include->{$includefile})) { |
2266 | $seen_Makefile_include->{$includefile} = true; | | 2266 | $seen_Makefile_include->{$includefile} = true; |
2267 | | | 2267 | |
2268 | if ($includefile =~ m"^\.\./[^./][^/]*/[^/]+") { | | 2268 | if ($includefile =~ m"^\.\./[^./][^/]*/[^/]+") { |
2269 | $line->log_warning("Relative directories should look like \"../../category/package\", not \"../package\"."); | | 2269 | $line->log_warning("Relative directories should look like \"../../category/package\", not \"../package\"."); |
2270 | $line->explain_warning(expl_relative_dirs); | | 2270 | $line->explain_warning(expl_relative_dirs); |
2271 | } | | 2271 | } |
2272 | if ($includefile =~ m"(?:^|/)Makefile.common$" | | 2272 | if ($includefile =~ m"(?:^|/)Makefile.common$" |
2273 | || ($includefile =~ m"^(?:\.\./(\.\./[^/]+/)?[^/]+/)?([^/]+)$" | | 2273 | || ($includefile =~ m"^(?:\.\./(\.\./[^/]+/)?[^/]+/)?([^/]+)$" |
2274 | && (!defined($1) || $1 ne "../mk") | | 2274 | && (!defined($1) || $1 ne "../mk") |
2275 | && $2 ne "buildlink3.mk" | | 2275 | && $2 ne "buildlink3.mk" |
2276 | && $2 ne "options.mk")) { | | 2276 | && $2 ne "options.mk")) { |
2277 | $opt_debug_include and $line->log_debug("including ${includefile} sets seen_Makefile_common."); | | 2277 | $opt_debug_include and $line->log_debug("including ${includefile} sets seen_Makefile_common."); |
2278 | $seen_Makefile_common = true; | | 2278 | $seen_Makefile_common = true; |
2279 | } | | 2279 | } |
2280 | if ($includefile =~ m"/mk/") { | | 2280 | if ($includefile =~ m"/mk/") { |
2281 | # skip these files | | 2281 | # skip these files |
2282 | | | 2282 | |
2283 | } else { | | 2283 | } else { |
2284 | $dirname = dirname($fname); | | 2284 | $dirname = dirname($fname); |
2285 | # Only look in the directory relative to the | | 2285 | # Only look in the directory relative to the |
2286 | # current file and in the current working directory. | | 2286 | # current file and in the current working directory. |
2287 | # We don't have an include dir list, like make(1) does. | | 2287 | # We don't have an include dir list, like make(1) does. |
2288 | if (!-f "$dirname/$includefile") { | | 2288 | if (!-f "$dirname/$includefile") { |
2289 | $dirname = $current_dir; | | 2289 | $dirname = $current_dir; |
2290 | } | | 2290 | } |
2291 | if (!-f "$dirname/$includefile") { | | 2291 | if (!-f "$dirname/$includefile") { |
2292 | $line->log_error("Cannot read $dirname/$includefile."); | | 2292 | $line->log_error("Cannot read $dirname/$includefile."); |
2293 | } else { | | 2293 | } else { |
2294 | $opt_debug_include and $line->log_debug("Including \"$dirname/$includefile\"."); | | 2294 | $opt_debug_include and $line->log_debug("Including \"$dirname/$includefile\"."); |
2295 | my $last_lineno = $#{$all_lines}; | | 2295 | my $last_lineno = $#{$all_lines}; |
2296 | readmakefile("$dirname/$includefile", $main_lines, $all_lines, $seen_Makefile_include) or return false; | | 2296 | readmakefile("$dirname/$includefile", $main_lines, $all_lines, $seen_Makefile_include) or return false; |
2297 | | | 2297 | |
2298 | # Check that there is a comment in each | | 2298 | # Check that there is a comment in each |
2299 | # Makefile.common that says which files | | 2299 | # Makefile.common that says which files |
2300 | # include it. | | 2300 | # include it. |
2301 | if ($includefile =~ m"/Makefile\.common$") { | | 2301 | if ($includefile =~ m"/Makefile\.common$") { |
2302 | my @mc_lines = @{$all_lines}[$last_lineno+1 .. $#{$all_lines}]; | | 2302 | my @mc_lines = @{$all_lines}[$last_lineno+1 .. $#{$all_lines}]; |
2303 | my $expected = "# used by " . relative_path($cwd_pkgsrcdir, $fname); | | 2303 | my $expected = "# used by " . relative_path($cwd_pkgsrcdir, $fname); |
2304 | | | 2304 | |
2305 | if (!(grep { $_->text eq $expected } @mc_lines)) { | | 2305 | if (!(grep { $_->text eq $expected } @mc_lines)) { |
2306 | my $lineno = 0; | | 2306 | my $lineno = 0; |
2307 | while ($lineno < $#mc_lines && $mc_lines[$lineno]->has("is_comment")) { | | 2307 | while ($lineno < $#mc_lines && $mc_lines[$lineno]->has("is_comment")) { |
2308 | $lineno++; | | 2308 | $lineno++; |
2309 | } | | 2309 | } |
2310 | my $iline = $mc_lines[$lineno]; | | 2310 | my $iline = $mc_lines[$lineno]; |
2311 | $iline->log_warning("Please add a line \"$expected\" here."); | | 2311 | $iline->log_warning("Please add a line \"$expected\" here."); |
2312 | $iline->explain_warning( | | 2312 | $iline->explain_warning( |
2313 | "Since Makefile.common files usually don't have any comments and", | | 2313 | "Since Makefile.common files usually don't have any comments and", |
2314 | "therefore not a clearly defined interface, they should at least contain", | | 2314 | "therefore not a clearly defined interface, they should at least contain", |
2315 | "references to all files that include them, so that it is easier to see", | | 2315 | "references to all files that include them, so that it is easier to see", |
2316 | "what effects future changes may have.", | | 2316 | "what effects future changes may have.", |
2317 | "", | | 2317 | "", |
2318 | "If there are more than five packages that use a Makefile.common,", | | 2318 | "If there are more than five packages that use a Makefile.common,", |
2319 | "you should think about giving it a proper name (maybe plugin.mk) and", | | 2319 | "you should think about giving it a proper name (maybe plugin.mk) and", |
2320 | "documenting its interface."); | | 2320 | "documenting its interface."); |
2321 | $iline->append_before($expected); | | 2321 | $iline->append_before($expected); |
2322 | autofix(\@mc_lines); | | 2322 | autofix(\@mc_lines); |
2323 | } | | 2323 | } |
2324 | } | | 2324 | } |
2325 | } | | 2325 | } |
2326 | } | | 2326 | } |
2327 | | | 2327 | |
2328 | } elsif ($line->has("is_varassign")) { | | 2328 | } elsif ($line->has("is_varassign")) { |
2329 | my ($varname, $op, $value) = ($line->get("varname"), $line->get("op"), $line->get("value")); | | 2329 | my ($varname, $op, $value) = ($line->get("varname"), $line->get("op"), $line->get("value")); |
2330 | | | 2330 | |
2331 | # Record all variables that are defined in these lines, so that they | | 2331 | # Record all variables that are defined in these lines, so that they |
2332 | # are not reported as "used but not defined". | | 2332 | # are not reported as "used but not defined". |
2333 | if ($op ne "?=" || !exists($pkgctx_vardef->{$varname})) { | | 2333 | if ($op ne "?=" || !exists($pkgctx_vardef->{$varname})) { |
2334 | $opt_debug_misc and $line->log_debug("varassign(${varname}, ${op}, ${value})"); | | 2334 | $opt_debug_misc and $line->log_debug("varassign(${varname}, ${op}, ${value})"); |
2335 | $pkgctx_vardef->{$varname} = $line; | | 2335 | $pkgctx_vardef->{$varname} = $line; |
2336 | } | | 2336 | } |
2337 | } | | 2337 | } |
2338 | } | | 2338 | } |
2339 | | | 2339 | |
2340 | return true; | | 2340 | return true; |
2341 | } | | 2341 | } |
2342 | | | 2342 | |
2343 | sub load_package_Makefile($$) { | | 2343 | sub load_package_Makefile($$) { |
2344 | my ($fname, $ref_lines) = @_; | | 2344 | my ($fname, $ref_lines) = @_; |
2345 | my ($subr) = "load_package_Makefile"; | | 2345 | my ($subr) = "load_package_Makefile"; |
2346 | my ($lines, $all_lines, $seen_php_pecl_version); | | 2346 | my ($lines, $all_lines, $seen_php_pecl_version); |
2347 | | | 2347 | |
2348 | $opt_debug_trace and log_debug($fname, NO_LINES, "load_package_Makefile()"); | | 2348 | $opt_debug_trace and log_debug($fname, NO_LINES, "load_package_Makefile()"); |
2349 | | | 2349 | |
2350 | if (!readmakefile($fname, $lines = [], $all_lines = [], $pkgctx_included = {})) { | | 2350 | if (!readmakefile($fname, $lines = [], $all_lines = [], $pkgctx_included = {})) { |
2351 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 2351 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
2352 | return false; | | 2352 | return false; |
2353 | } | | 2353 | } |
2354 | | | 2354 | |
2355 | if ($opt_dumpmakefile) { | | 2355 | if ($opt_dumpmakefile) { |
2356 | log_debug(NO_FILE, NO_LINES, "Whole Makefile (with all included files) follows:"); | | 2356 | log_debug(NO_FILE, NO_LINES, "Whole Makefile (with all included files) follows:"); |
2357 | foreach my $line (@{$all_lines}) { | | 2357 | foreach my $line (@{$all_lines}) { |
2358 | print($line->to_string() . "\n"); | | 2358 | print($line->to_string() . "\n"); |
2359 | } | | 2359 | } |
2360 | } | | 2360 | } |
2361 | | | 2361 | |
2362 | determine_used_variables($all_lines); | | 2362 | determine_used_variables($all_lines); |
2363 | | | 2363 | |
2364 | $pkgdir = expand_variable("PKGDIR"); | | 2364 | $pkgdir = expand_variable("PKGDIR"); |
2365 | set_default_value(\$pkgdir, "."); | | 2365 | set_default_value(\$pkgdir, "."); |
2366 | $distinfo_file = expand_variable("DISTINFO_FILE"); | | 2366 | $distinfo_file = expand_variable("DISTINFO_FILE"); |
2367 | set_default_value(\$distinfo_file, "distinfo"); | | 2367 | set_default_value(\$distinfo_file, "distinfo"); |
2368 | $filesdir = expand_variable("FILESDIR"); | | 2368 | $filesdir = expand_variable("FILESDIR"); |
2369 | set_default_value(\$filesdir, "files"); | | 2369 | set_default_value(\$filesdir, "files"); |
2370 | $patchdir = expand_variable("PATCHDIR"); | | 2370 | $patchdir = expand_variable("PATCHDIR"); |
2371 | set_default_value(\$patchdir, "patches"); | | 2371 | set_default_value(\$patchdir, "patches"); |
2372 | | | 2372 | |
2373 | if (var_is_defined("PHPEXT_MK")) { | | 2373 | if (var_is_defined("PHPEXT_MK")) { |
2374 | if (!var_is_defined("USE_PHP_EXT_PATCHES")) { | | 2374 | if (!var_is_defined("USE_PHP_EXT_PATCHES")) { |
2375 | $patchdir = "patches"; | | 2375 | $patchdir = "patches"; |
2376 | } | | 2376 | } |
2377 | if (var_is_defined("PECL_VERSION")) { | | 2377 | if (var_is_defined("PECL_VERSION")) { |
2378 | $distinfo_file = "distinfo"; | | 2378 | $distinfo_file = "distinfo"; |
2379 | } | | 2379 | } |
2380 | } | | 2380 | } |
2381 | | | 2381 | |
2382 | $opt_debug_misc and log_debug(NO_FILE, NO_LINE_NUMBER, "[${subr}] DISTINFO_FILE=$distinfo_file"); | | 2382 | $opt_debug_misc and log_debug(NO_FILE, NO_LINE_NUMBER, "[${subr}] DISTINFO_FILE=$distinfo_file"); |
2383 | $opt_debug_misc and log_debug(NO_FILE, NO_LINE_NUMBER, "[${subr}] FILESDIR=$filesdir"); | | 2383 | $opt_debug_misc and log_debug(NO_FILE, NO_LINE_NUMBER, "[${subr}] FILESDIR=$filesdir"); |
2384 | $opt_debug_misc and log_debug(NO_FILE, NO_LINE_NUMBER, "[${subr}] PATCHDIR=$patchdir"); | | 2384 | $opt_debug_misc and log_debug(NO_FILE, NO_LINE_NUMBER, "[${subr}] PATCHDIR=$patchdir"); |
2385 | $opt_debug_misc and log_debug(NO_FILE, NO_LINE_NUMBER, "[${subr}] PKGDIR=$pkgdir"); | | 2385 | $opt_debug_misc and log_debug(NO_FILE, NO_LINE_NUMBER, "[${subr}] PKGDIR=$pkgdir"); |
2386 | | | 2386 | |
2387 | ${$ref_lines} = $lines; | | 2387 | ${$ref_lines} = $lines; |
2388 | return true; | | 2388 | return true; |
2389 | } | | 2389 | } |
2390 | | | 2390 | |
2391 | sub warn_about_PLIST_imake_mannewsuffix($) { | | 2391 | sub warn_about_PLIST_imake_mannewsuffix($) { |
2392 | my ($line) = @_; | | 2392 | my ($line) = @_; |
2393 | | | 2393 | |
2394 | $line->log_warning("IMAKE_MANNEWSUFFIX is not meant to appear in PLISTs."); | | 2394 | $line->log_warning("IMAKE_MANNEWSUFFIX is not meant to appear in PLISTs."); |
2395 | $line->explain_warning( | | 2395 | $line->explain_warning( |
2396 | "This is the result of a print-PLIST call that has _not_ been checked", | | 2396 | "This is the result of a print-PLIST call that has _not_ been checked", |
2397 | "thoroughly by the developer. Please replace the IMAKE_MANNEWSUFFIX with", | | 2397 | "thoroughly by the developer. Please replace the IMAKE_MANNEWSUFFIX with", |
2398 | "", | | 2398 | "", |
2399 | "\tIMAKE_MAN_SUFFIX for programs,", | | 2399 | "\tIMAKE_MAN_SUFFIX for programs,", |
2400 | "\tIMAKE_LIBMAN_SUFFIX for library functions,", | | 2400 | "\tIMAKE_LIBMAN_SUFFIX for library functions,", |
2401 | "\tIMAKE_FILEMAN_SUFFIX for file formats,", | | 2401 | "\tIMAKE_FILEMAN_SUFFIX for file formats,", |
2402 | "\tIMAKE_GAMEMAN_SUFFIX for games,", | | 2402 | "\tIMAKE_GAMEMAN_SUFFIX for games,", |
2403 | "\tIMAKE_MISCMAN_SUFFIX for other man pages."); | | 2403 | "\tIMAKE_MISCMAN_SUFFIX for other man pages."); |
2404 | } | | 2404 | } |
2405 | | | 2405 | |
2406 | # | | 2406 | # |
2407 | # Subroutines to check part of a single line. | | 2407 | # Subroutines to check part of a single line. |
2408 | # | | 2408 | # |
2409 | | | 2409 | |
2410 | sub checkword_absolute_pathname($$) { | | 2410 | sub checkword_absolute_pathname($$) { |
2411 | my ($line, $word) = @_; | | 2411 | my ($line, $word) = @_; |
2412 | | | 2412 | |
2413 | $opt_debug_trace and $line->log_debug("checkword_absolute_pathname(\"${word}\")"); | | 2413 | $opt_debug_trace and $line->log_debug("checkword_absolute_pathname(\"${word}\")"); |
2414 | | | 2414 | |
2415 | if ($word =~ m"^/dev/(?:null|tty|zero)$") { | | 2415 | if ($word =~ m"^/dev/(?:null|tty|zero)$") { |
2416 | # These are defined by POSIX. | | 2416 | # These are defined by POSIX. |
2417 | | | 2417 | |
2418 | } elsif ($word eq "/bin/sh") { | | 2418 | } elsif ($word eq "/bin/sh") { |
2419 | # This is usually correct, although on Solaris, it's pretty | | 2419 | # This is usually correct, although on Solaris, it's pretty |
2420 | # feature-crippled. | | 2420 | # feature-crippled. |
2421 | | | 2421 | |
2422 | } elsif ($word !~ m"/(?:[a-z]|\$[({])") { | | 2422 | } elsif ($word !~ m"/(?:[a-z]|\$[({])") { |
2423 | # Assume that all pathnames start with a lowercase letter. | | 2423 | # Assume that all pathnames start with a lowercase letter. |
2424 | | | 2424 | |
2425 | } else { | | 2425 | } else { |
2426 | $line->log_warning("Found absolute pathname: ${word}"); | | 2426 | $line->log_warning("Found absolute pathname: ${word}"); |
2427 | $line->explain_warning( | | 2427 | $line->explain_warning( |
2428 | "Absolute pathnames are often an indicator for unportable code. As", | | 2428 | "Absolute pathnames are often an indicator for unportable code. As", |
2429 | "pkgsrc aims to be a portable system, absolute pathnames should be", | | 2429 | "pkgsrc aims to be a portable system, absolute pathnames should be", |
2430 | "avoided whenever possible.", | | 2430 | "avoided whenever possible.", |
2431 | "", | | 2431 | "", |
2432 | "A special variable in this context is \${DESTDIR}, which is used in GNU", | | 2432 | "A special variable in this context is \${DESTDIR}, which is used in GNU", |
2433 | "projects to specify a different directory for installation than what", | | 2433 | "projects to specify a different directory for installation than what", |
2434 | "the programs see later when they are executed. Usually it is empty, so", | | 2434 | "the programs see later when they are executed. Usually it is empty, so", |
2435 | "if anything after that variable starts with a slash, it is considered", | | 2435 | "if anything after that variable starts with a slash, it is considered", |
2436 | "an absolute pathname."); | | 2436 | "an absolute pathname."); |
2437 | } | | 2437 | } |
2438 | } | | 2438 | } |
2439 | | | 2439 | |
2440 | sub checkpackage_possible_downgrade() { | | 2440 | sub checkpackage_possible_downgrade() { |
2441 | | | 2441 | |
2442 | $opt_debug_trace and log_debug(NO_FILE, NO_LINES, "checkpackage_possible_downgrade"); | | 2442 | $opt_debug_trace and log_debug(NO_FILE, NO_LINES, "checkpackage_possible_downgrade"); |
2443 | | | 2443 | |
2444 | return unless defined $effective_pkgname; | | 2444 | return unless defined $effective_pkgname; |
2445 | return unless $effective_pkgname =~ regex_pkgname; | | 2445 | return unless $effective_pkgname =~ regex_pkgname; |
2446 | my ($pkgbase, $pkgversion) = ($1, $2); | | 2446 | my ($pkgbase, $pkgversion) = ($1, $2); |
2447 | my $line = $effective_pkgname_line; | | 2447 | my $line = $effective_pkgname_line; |
2448 | | | 2448 | |
2449 | my @changes = get_doc_CHANGES($pkgpath); | | 2449 | my @changes = get_doc_CHANGES($pkgpath); |
2450 | if (@changes == 0) { | | 2450 | if (@changes == 0) { |
2451 | $opt_debug_misc and $line->log_debug("No changes have been recorded for package $pkgpath."); | | 2451 | $opt_debug_misc and $line->log_debug("No changes have been recorded for package $pkgpath."); |
2452 | return; | | 2452 | return; |
2453 | } | | 2453 | } |
2454 | | | 2454 | |
2455 | my $last_change = $changes[-1]; | | 2455 | my $last_change = $changes[-1]; |
2456 | return unless $last_change->action eq "Updated"; | | 2456 | return unless $last_change->action eq "Updated"; |
2457 | | | 2457 | |
2458 | my $last_version = $last_change->version; | | 2458 | my $last_version = $last_change->version; |
2459 | | | 2459 | |
2460 | if (dewey_cmp($pkgversion, "<", $last_version)) { | | 2460 | if (dewey_cmp($pkgversion, "<", $last_version)) { |
2461 | $line->log_warning("The package is being downgraded from $last_version to $pkgversion."); | | 2461 | $line->log_warning("The package is being downgraded from $last_version to $pkgversion."); |
2462 | } | | 2462 | } |
2463 | } | | 2463 | } |
2464 | | | 2464 | |
2465 | # | | 2465 | # |
2466 | # Subroutines to check a single line. | | 2466 | # Subroutines to check a single line. |
2467 | # | | 2467 | # |
2468 | | | 2468 | |
2469 | sub checkline_length($$) { | | 2469 | sub checkline_length($$) { |
2470 | my ($line, $maxlength) = @_; | | 2470 | my ($line, $maxlength) = @_; |
2471 | | | 2471 | |
2472 | if (length($line->text) > $maxlength) { | | 2472 | if (length($line->text) > $maxlength) { |
2473 | $line->log_warning("Line too long (should be no more than $maxlength characters)."); | | 2473 | $line->log_warning("Line too long (should be no more than $maxlength characters)."); |
2474 | $line->explain_warning( | | 2474 | $line->explain_warning( |
2475 | "Back in the old time, terminals with 80x25 characters were common.", | | 2475 | "Back in the old time, terminals with 80x25 characters were common.", |
2476 | "And this is still the default size of many terminal emulators.", | | 2476 | "And this is still the default size of many terminal emulators.", |
2477 | "Moderately short lines also make reading easier."); | | 2477 | "Moderately short lines also make reading easier."); |
2478 | } | | 2478 | } |
2479 | } | | 2479 | } |
2480 | | | 2480 | |
2481 | sub checkline_valid_characters($$) { | | 2481 | sub checkline_valid_characters($$) { |
2482 | my ($line, $re_validchars) = @_; | | 2482 | my ($line, $re_validchars) = @_; |
2483 | my ($rest); | | 2483 | my ($rest); |
2484 | | | 2484 | |
2485 | ($rest = $line->text) =~ s/$re_validchars//g; | | 2485 | ($rest = $line->text) =~ s/$re_validchars//g; |
2486 | if ($rest ne "") { | | 2486 | if ($rest ne "") { |
2487 | my @chars = map { $_ = sprintf("0x%02x", ord($_)); } split(//, $rest); | | 2487 | my @chars = map { $_ = sprintf("0x%02x", ord($_)); } split(//, $rest); |
2488 | $line->log_warning("Line contains invalid characters (" . join(", ", @chars) . ")."); | | 2488 | $line->log_warning("Line contains invalid characters (" . join(", ", @chars) . ")."); |
2489 | } | | 2489 | } |
2490 | } | | 2490 | } |
2491 | | | 2491 | |
2492 | sub checkline_valid_characters_in_variable($$) { | | 2492 | sub checkline_valid_characters_in_variable($$) { |
2493 | my ($line, $re_validchars) = @_; | | 2493 | my ($line, $re_validchars) = @_; |
2494 | my ($varname, $rest); | | 2494 | my ($varname, $rest); |
2495 | | | 2495 | |
2496 | $varname = $line->get("varname"); | | 2496 | $varname = $line->get("varname"); |
2497 | $rest = $line->get("value"); | | 2497 | $rest = $line->get("value"); |
2498 | | | 2498 | |
2499 | $rest =~ s/$re_validchars//g; | | 2499 | $rest =~ s/$re_validchars//g; |
2500 | if ($rest ne "") { | | 2500 | if ($rest ne "") { |
2501 | my @chars = map { $_ = sprintf("0x%02x", ord($_)); } split(//, $rest); | | 2501 | my @chars = map { $_ = sprintf("0x%02x", ord($_)); } split(//, $rest); |
2502 | $line->log_warning("${varname} contains invalid characters (" . join(", ", @chars) . ")."); | | 2502 | $line->log_warning("${varname} contains invalid characters (" . join(", ", @chars) . ")."); |
2503 | } | | 2503 | } |
2504 | } | | 2504 | } |
2505 | | | 2505 | |
2506 | sub checkline_trailing_whitespace($) { | | 2506 | sub checkline_trailing_whitespace($) { |
2507 | my ($line) = @_; | | 2507 | my ($line) = @_; |
2508 | | | 2508 | |
2509 | $opt_debug_trace and $line->log_debug("checkline_trailing_whitespace()"); | | 2509 | $opt_debug_trace and $line->log_debug("checkline_trailing_whitespace()"); |
2510 | | | 2510 | |
2511 | if ($line->text =~ /\s+$/) { | | 2511 | if ($line->text =~ /\s+$/) { |
2512 | $line->log_note("Trailing white-space."); | | 2512 | $line->log_note("Trailing white-space."); |
2513 | $line->explain_note( | | 2513 | $line->explain_note( |
2514 | "When a line ends with some white-space, that space is in most cases", | | 2514 | "When a line ends with some white-space, that space is in most cases", |
2515 | "irrelevant and can be removed, leading to a \"normal form\" syntax.", | | 2515 | "irrelevant and can be removed, leading to a \"normal form\" syntax.", |
2516 | "", | | 2516 | "", |
2517 | "Note: This is mostly for aesthetic reasons."); | | 2517 | "Note: This is mostly for aesthetic reasons."); |
2518 | $line->replace_regex(qr"\s+\n$", "\n"); | | 2518 | $line->replace_regex(qr"\s+\n$", "\n"); |
2519 | } | | 2519 | } |
2520 | } | | 2520 | } |
2521 | | | 2521 | |
2522 | sub checkline_rcsid_regex($$$) { | | 2522 | sub checkline_rcsid_regex($$$) { |
2523 | my ($line, $prefix_regex, $prefix) = @_; | | 2523 | my ($line, $prefix_regex, $prefix) = @_; |
2524 | my ($id) = ($opt_rcsidstring . ($is_wip ? "|Id" : "")); | | 2524 | my ($id) = ($opt_rcsidstring . ($is_wip ? "|Id" : "")); |
2525 | | | 2525 | |
2526 | $opt_debug_trace and $line->log_debug("checkline_rcsid_regex(${prefix_regex}, ${prefix})"); | | 2526 | $opt_debug_trace and $line->log_debug("checkline_rcsid_regex(${prefix_regex}, ${prefix})"); |
2527 | | | 2527 | |
2528 | if ($line->text !~ m"^${prefix_regex}\$(${id})(?::[^\$]+|)\$$") { | | 2528 | if ($line->text !~ m"^${prefix_regex}\$(${id})(?::[^\$]+|)\$$") { |
2529 | $line->log_error("\"${prefix}\$${opt_rcsidstring}\$\" expected."); | | 2529 | $line->log_error("\"${prefix}\$${opt_rcsidstring}\$\" expected."); |
| | | 2530 | $line->explain_error( |
| | | 2531 | "Several files in pkgsrc must contain the CVS Id, so that their current", |
| | | 2532 | "version can be traced back later from a binary package. This is to", |
| | | 2533 | "ensure reproducible builds, for example for finding bugs.", |
| | | 2534 | "", |
| | | 2535 | "Please insert the text from the above error message (without the quotes)", |
| | | 2536 | "at this position in the file."); |
2530 | return false; | | 2537 | return false; |
2531 | } | | 2538 | } |
2532 | return true; | | 2539 | return true; |
2533 | } | | 2540 | } |
2534 | | | 2541 | |
2535 | sub checkline_rcsid($$) { | | 2542 | sub checkline_rcsid($$) { |
2536 | my ($line, $prefix) = @_; | | 2543 | my ($line, $prefix) = @_; |
2537 | | | 2544 | |
2538 | checkline_rcsid_regex($line, quotemeta($prefix), $prefix); | | 2545 | checkline_rcsid_regex($line, quotemeta($prefix), $prefix); |
2539 | } | | 2546 | } |
2540 | | | 2547 | |
2541 | # Checks whether the line contains text that looks like absolute | | 2548 | # Checks whether the line contains text that looks like absolute |
2542 | # pathnames, assuming that the file uses the common syntax with | | 2549 | # pathnames, assuming that the file uses the common syntax with |
2543 | # single or double quotes to represent strings. | | 2550 | # single or double quotes to represent strings. |
2544 | # | | 2551 | # |
2545 | sub checkline_source_absolute_pathname($$) { | | 2552 | sub checkline_source_absolute_pathname($$) { |
2546 | my ($line, $text) = @_; | | 2553 | my ($line, $text) = @_; |
2547 | my ($abspath); | | 2554 | my ($abspath); |
2548 | | | 2555 | |
2549 | $opt_debug_trace and $line->log_debug("checkline_source_absolute_pathname(${text})"); | | 2556 | $opt_debug_trace and $line->log_debug("checkline_source_absolute_pathname(${text})"); |
2550 | | | 2557 | |
2551 | if ($text =~ m"(.*)([\"'])(/[^\"']*)\2") { | | 2558 | if ($text =~ m"(.*)([\"'])(/[^\"']*)\2") { |
2552 | my ($before, $delim, $string) = ($1, $2, $3); | | 2559 | my ($before, $delim, $string) = ($1, $2, $3); |
2553 | | | 2560 | |
2554 | $opt_debug_misc and $line->log_debug("checkline_source_absolute_pathname(before=${before}, string=${string})"); | | 2561 | $opt_debug_misc and $line->log_debug("checkline_source_absolute_pathname(before=${before}, string=${string})"); |
2555 | if ($before =~ m"[A-Z_]+\s*$") { | | 2562 | if ($before =~ m"[A-Z_]+\s*$") { |
2556 | # allowed: PREFIX "/bin/foo" | | 2563 | # allowed: PREFIX "/bin/foo" |
2557 | | | 2564 | |
2558 | } elsif ($string =~ m"^/[*/]") { | | 2565 | } elsif ($string =~ m"^/[*/]") { |
2559 | # This is more likely to be a C or C++ comment. | | 2566 | # This is more likely to be a C or C++ comment. |
2560 | | | 2567 | |
2561 | } elsif ($string !~ m"^/\w") { | | 2568 | } elsif ($string !~ m"^/\w") { |
2562 | # Assume that pathnames start with a letter or digit. | | 2569 | # Assume that pathnames start with a letter or digit. |
2563 | | | 2570 | |
2564 | } elsif ($before =~ m"\+\s*$") { | | 2571 | } elsif ($before =~ m"\+\s*$") { |
2565 | # Something like foodir + '/lib' | | 2572 | # Something like foodir + '/lib' |
2566 | | | 2573 | |
2567 | } else { | | 2574 | } else { |
2568 | $abspath = $string; | | 2575 | $abspath = $string; |
2569 | } | | 2576 | } |
2570 | } | | 2577 | } |
2571 | | | 2578 | |
2572 | if (defined($abspath)) { | | 2579 | if (defined($abspath)) { |
2573 | checkword_absolute_pathname($line, $abspath); | | 2580 | checkword_absolute_pathname($line, $abspath); |
2574 | } | | 2581 | } |
2575 | } | | 2582 | } |
2576 | | | 2583 | |
2577 | sub checkline_mk_absolute_pathname($$) { | | 2584 | sub checkline_mk_absolute_pathname($$) { |
2578 | my ($line, $text) = @_; | | 2585 | my ($line, $text) = @_; |
2579 | my $abspath; | | 2586 | my $abspath; |
2580 | | | 2587 | |
2581 | $opt_debug_trace and $line->log_debug("checkline_mk_absolute_pathname(${text})"); | | 2588 | $opt_debug_trace and $line->log_debug("checkline_mk_absolute_pathname(${text})"); |
2582 | | | 2589 | |
2583 | # In the GNU coding standards, DESTDIR is defined as a (usually | | 2590 | # In the GNU coding standards, DESTDIR is defined as a (usually |
2584 | # empty) prefix that can be used to install files to a different | | 2591 | # empty) prefix that can be used to install files to a different |
2585 | # location from what they have been built for. Therefore | | 2592 | # location from what they have been built for. Therefore |
2586 | # everything following it is considered an absolute pathname. | | 2593 | # everything following it is considered an absolute pathname. |
2587 | # Another commonly used context is in assignments like | | 2594 | # Another commonly used context is in assignments like |
2588 | # "bindir=/bin". | | 2595 | # "bindir=/bin". |
2589 | if ($text =~ m"(?:^|\$\{DESTDIR\}|\$\(DESTDIR\)|[\w_]+\s*=\s*)(/(?:[^\"'\`\s]|\"[^\"*]\"|'[^']*'|\`[^\`]*\`)*)") { | | 2596 | if ($text =~ m"(?:^|\$\{DESTDIR\}|\$\(DESTDIR\)|[\w_]+\s*=\s*)(/(?:[^\"'\`\s]|\"[^\"*]\"|'[^']*'|\`[^\`]*\`)*)") { |
2590 | my $path = $1; | | 2597 | my $path = $1; |
2591 | | | 2598 | |
2592 | if ($path =~ m"^/\w") { | | 2599 | if ($path =~ m"^/\w") { |
2593 | $abspath = $path; | | 2600 | $abspath = $path; |
2594 | } | | 2601 | } |
2595 | } | | 2602 | } |
2596 | | | 2603 | |
2597 | if (defined($abspath)) { | | 2604 | if (defined($abspath)) { |
2598 | checkword_absolute_pathname($line, $abspath); | | 2605 | checkword_absolute_pathname($line, $abspath); |
2599 | } | | 2606 | } |
2600 | } | | 2607 | } |
2601 | | | 2608 | |
2602 | # Last resort if the file does not look like a Makefile or typical | | 2609 | # Last resort if the file does not look like a Makefile or typical |
2603 | # source code. All strings that look like pathnames and start with | | 2610 | # source code. All strings that look like pathnames and start with |
2604 | # one of the typical Unix prefixes are found. | | 2611 | # one of the typical Unix prefixes are found. |
2605 | # | | 2612 | # |
2606 | sub checkline_other_absolute_pathname($$) { | | 2613 | sub checkline_other_absolute_pathname($$) { |
2607 | my ($line, $text) = @_; | | 2614 | my ($line, $text) = @_; |
2608 | | | 2615 | |
2609 | $opt_debug_trace and $line->log_debug("checkline_other_absolute_pathname(\"${text}\")"); | | 2616 | $opt_debug_trace and $line->log_debug("checkline_other_absolute_pathname(\"${text}\")"); |
2610 | | | 2617 | |
2611 | if ($text =~ m"^#[^!]") { | | 2618 | if ($text =~ m"^#[^!]") { |
2612 | # Don't warn for absolute pathnames in comments, | | 2619 | # Don't warn for absolute pathnames in comments, |
2613 | # except for shell interpreters. | | 2620 | # except for shell interpreters. |
2614 | | | 2621 | |
2615 | } elsif ($text =~ m"^(.*?)((?:/[\w.]+)*/(?:bin|dev|etc|home|lib|mnt|opt|proc|sbin|tmp|usr|var)\b[\w./\-]*)(.*)$") { | | 2622 | } elsif ($text =~ m"^(.*?)((?:/[\w.]+)*/(?:bin|dev|etc|home|lib|mnt|opt|proc|sbin|tmp|usr|var)\b[\w./\-]*)(.*)$") { |
2616 | my ($before, $path, $after) = ($1, $2, $3); | | 2623 | my ($before, $path, $after) = ($1, $2, $3); |
2617 | | | 2624 | |
2618 | if ($before =~ m"\@$") { | | 2625 | if ($before =~ m"\@$") { |
2619 | # Something like @PREFIX@/bin | | 2626 | # Something like @PREFIX@/bin |
2620 | | | 2627 | |
2621 | } elsif ($before =~ m"[)}]$") { | | 2628 | } elsif ($before =~ m"[)}]$") { |
2622 | # Something like ${prefix}/bin or $(PREFIX)/bin | | 2629 | # Something like ${prefix}/bin or $(PREFIX)/bin |
2623 | | | 2630 | |
2624 | } elsif ($before =~ m"\+\s*[\"']$") { | | 2631 | } elsif ($before =~ m"\+\s*[\"']$") { |
2625 | # Something like foodir + '/lib' | | 2632 | # Something like foodir + '/lib' |
2626 | | | 2633 | |
2627 | } elsif ($before =~ m"\w$") { | | 2634 | } elsif ($before =~ m"\w$") { |
2628 | # Something like $dir/lib | | 2635 | # Something like $dir/lib |
2629 | | | 2636 | |
2630 | } elsif ($before =~ m"\.$") { | | 2637 | } elsif ($before =~ m"\.$") { |
2631 | # ../foo is not an absolute pathname. | | 2638 | # ../foo is not an absolute pathname. |
2632 | | | 2639 | |
2633 | } else { | | 2640 | } else { |
2634 | $opt_debug_misc and $line->log_debug("before=${before}"); | | 2641 | $opt_debug_misc and $line->log_debug("before=${before}"); |
2635 | checkword_absolute_pathname($line, $path); | | 2642 | checkword_absolute_pathname($line, $path); |
2636 | } | | 2643 | } |
2637 | } | | 2644 | } |
2638 | } | | 2645 | } |
2639 | | | 2646 | |
2640 | sub checkline_relative_path($$$) { | | 2647 | sub checkline_relative_path($$$) { |
2641 | my ($line, $path, $must_exist) = @_; | | 2648 | my ($line, $path, $must_exist) = @_; |
2642 | my ($res_path); | | 2649 | my ($res_path); |
2643 | | | 2650 | |
2644 | if (!$is_wip && $path =~ m"/wip/") { | | 2651 | if (!$is_wip && $path =~ m"/wip/") { |
2645 | $line->log_error("A pkgsrc package must not depend on any outside package."); | | 2652 | $line->log_error("A pkgsrc package must not depend on any outside package."); |
2646 | } | | 2653 | } |
2647 | $res_path = resolve_relative_path($path, true); | | 2654 | $res_path = resolve_relative_path($path, true); |
2648 | if ($res_path =~ regex_unresolved) { | | 2655 | if ($res_path =~ regex_unresolved) { |
2649 | $opt_debug_unchecked and $line->log_debug("Unchecked path: \"${path}\"."); | | 2656 | $opt_debug_unchecked and $line->log_debug("Unchecked path: \"${path}\"."); |
2650 | } elsif (!-e ((($res_path =~ m"^/") ? "" : "${current_dir}/") . $res_path)) { | | 2657 | } elsif (!-e ((($res_path =~ m"^/") ? "" : "${current_dir}/") . $res_path)) { |
2651 | $must_exist and $line->log_error("\"${res_path}\" does not exist."); | | 2658 | $must_exist and $line->log_error("\"${res_path}\" does not exist."); |
2652 | } elsif ($path =~ m"^\.\./\.\./([^/]+)/([^/]+)(.*)") { | | 2659 | } elsif ($path =~ m"^\.\./\.\./([^/]+)/([^/]+)(.*)") { |
2653 | my ($cat, $pkg, $rest) = ($1, $2, $3); | | 2660 | my ($cat, $pkg, $rest) = ($1, $2, $3); |
2654 | } elsif ($path =~ m"^\.\./\.\./mk/") { | | 2661 | } elsif ($path =~ m"^\.\./\.\./mk/") { |
2655 | # There need not be two directory levels for mk/ files. | | 2662 | # There need not be two directory levels for mk/ files. |
2656 | } elsif ($path =~ m"^\.\./mk/" && $cur_pkgsrcdir eq "..") { | | 2663 | } elsif ($path =~ m"^\.\./mk/" && $cur_pkgsrcdir eq "..") { |
2657 | # That's fine for category Makefiles. | | 2664 | # That's fine for category Makefiles. |
2658 | } elsif ($path =~ m"^\.\.") { | | 2665 | } elsif ($path =~ m"^\.\.") { |
2659 | $line->log_warning("Invalid relative path \"${path}\"."); | | 2666 | $line->log_warning("Invalid relative path \"${path}\"."); |
2660 | } | | 2667 | } |
2661 | } | | 2668 | } |
2662 | | | 2669 | |
2663 | sub checkline_relative_pkgdir($$) { | | 2670 | sub checkline_relative_pkgdir($$) { |
2664 | my ($line, $path) = @_; | | 2671 | my ($line, $path) = @_; |
2665 | | | 2672 | |
2666 | checkline_relative_path($line, $path, true); | | 2673 | checkline_relative_path($line, $path, true); |
2667 | $path = resolve_relative_path($path, false); | | 2674 | $path = resolve_relative_path($path, false); |
2668 | | | 2675 | |
2669 | if ($path =~ m"^(?:\./)?\.\./\.\./([^/]+/[^/]+)$") { | | 2676 | if ($path =~ m"^(?:\./)?\.\./\.\./([^/]+/[^/]+)$") { |
2670 | my $otherpkgpath = $1; | | 2677 | my $otherpkgpath = $1; |
2671 | if (! -f "$cwd_pkgsrcdir/$otherpkgpath/Makefile") { | | 2678 | if (! -f "$cwd_pkgsrcdir/$otherpkgpath/Makefile") { |
2672 | $line->log_error("There is no package in $otherpkgpath."); | | 2679 | $line->log_error("There is no package in $otherpkgpath."); |
2673 | } | | 2680 | } |
2674 | | | 2681 | |
2675 | } else { | | 2682 | } else { |
2676 | $line->log_warning("\"${path}\" is not a valid relative package directory."); | | 2683 | $line->log_warning("\"${path}\" is not a valid relative package directory."); |
2677 | $line->explain_warning( | | 2684 | $line->explain_warning( |
2678 | "A relative pathname always starts with \"../../\", followed", | | 2685 | "A relative pathname always starts with \"../../\", followed", |
2679 | "by a category, a slash and a the directory name of the package.", | | 2686 | "by a category, a slash and a the directory name of the package.", |
2680 | "For example, \"../../misc/screen\" is a valid relative pathname."); | | 2687 | "For example, \"../../misc/screen\" is a valid relative pathname."); |
2681 | } | | 2688 | } |
2682 | } | | 2689 | } |
2683 | | | 2690 | |
2684 | sub checkline_spellcheck($) { | | 2691 | sub checkline_spellcheck($) { |
2685 | my ($line) = @_; | | 2692 | my ($line) = @_; |
2686 | | | 2693 | |
2687 | if ($line->text =~ m"existant") { | | 2694 | if ($line->text =~ m"existant") { |
2688 | $line->log_warning("The word \"existant\" is nonexistent in the m-w dictionary."); | | 2695 | $line->log_warning("The word \"existant\" is nonexistent in the m-w dictionary."); |
2689 | $line->explain_warning("Please use \"existent\" instead."); | | 2696 | $line->explain_warning("Please use \"existent\" instead."); |
2690 | } | | 2697 | } |
2691 | } | | 2698 | } |
2692 | | | 2699 | |
2693 | sub checkline_cpp_macro_names($$) { | | 2700 | sub checkline_cpp_macro_names($$) { |
2694 | my ($line, $text) = @_; | | 2701 | my ($line, $text) = @_; |
2695 | my ($rest); | | 2702 | my ($rest); |
2696 | | | 2703 | |
2697 | use constant good_macros => PkgLint::Util::array_to_hash(qw( | | 2704 | use constant good_macros => PkgLint::Util::array_to_hash(qw( |
2698 | __STDC__ | | 2705 | __STDC__ |
2699 | | | 2706 | |
2700 | __GNUC__ __GNUC_MINOR__ | | 2707 | __GNUC__ __GNUC_MINOR__ |
2701 | __SUNPRO_C | | 2708 | __SUNPRO_C |
2702 | | | 2709 | |
2703 | __i386 | | 2710 | __i386 |
2704 | __mips | | 2711 | __mips |
2705 | __sparc | | 2712 | __sparc |
2706 | | | 2713 | |
2707 | __APPLE__ | | 2714 | __APPLE__ |
2708 | __bsdi__ | | 2715 | __bsdi__ |
2709 | __CYGWIN__ | | 2716 | __CYGWIN__ |
2710 | __DragonFly__ | | 2717 | __DragonFly__ |
2711 | __FreeBSD__ __FreeBSD_version | | 2718 | __FreeBSD__ __FreeBSD_version |
2712 | __INTERIX | | 2719 | __INTERIX |
2713 | __linux__ | | 2720 | __linux__ |
2714 | __MINGW32__ | | 2721 | __MINGW32__ |
2715 | __NetBSD__ __NetBSD_Version__ | | 2722 | __NetBSD__ __NetBSD_Version__ |
2716 | __OpenBSD__ | | 2723 | __OpenBSD__ |
2717 | __SVR4 | | 2724 | __SVR4 |
2718 | __sgi | | 2725 | __sgi |
2719 | __sun | | 2726 | __sun |
2720 | | | 2727 | |
2721 | __GLIBC__ | | 2728 | __GLIBC__ |
2722 | )); | | 2729 | )); |
2723 | use constant bad_macros => { | | 2730 | use constant bad_macros => { |
2724 | "__sgi__" => "__sgi", | | 2731 | "__sgi__" => "__sgi", |
2725 | "__sparc__" => "__sparc", | | 2732 | "__sparc__" => "__sparc", |
2726 | "__sparc_v9__" => "__sparcv9", | | 2733 | "__sparc_v9__" => "__sparcv9", |
2727 | "__sun__" => "__sun", | | 2734 | "__sun__" => "__sun", |
2728 | "__svr4__" => "__SVR4", | | 2735 | "__svr4__" => "__SVR4", |
2729 | }; | | 2736 | }; |
2730 | | | 2737 | |
2731 | $rest = $text; | | 2738 | $rest = $text; |
2732 | while ($rest =~ s/defined\((__[\w_]+)\)// || $rest =~ s/\b(_\w+)\(//) { | | 2739 | while ($rest =~ s/defined\((__[\w_]+)\)// || $rest =~ s/\b(_\w+)\(//) { |
2733 | my ($macro) = ($1); | | 2740 | my ($macro) = ($1); |
2734 | | | 2741 | |
2735 | if (exists(good_macros->{$macro})) { | | 2742 | if (exists(good_macros->{$macro})) { |
2736 | $opt_debug_misc and $line->log_debug("Found good macro \"${macro}\"."); | | 2743 | $opt_debug_misc and $line->log_debug("Found good macro \"${macro}\"."); |
2737 | } elsif (exists(bad_macros->{$macro})) { | | 2744 | } elsif (exists(bad_macros->{$macro})) { |
2738 | $line->log_warning("The macro \"${macro}\" is not portable enough. Please use \"".bad_macros->{$macro}."\" instead."); | | 2745 | $line->log_warning("The macro \"${macro}\" is not portable enough. Please use \"".bad_macros->{$macro}."\" instead."); |
2739 | $line->explain_warning("See the pkgsrc guide, section \"CPP defines\" for details."); | | 2746 | $line->explain_warning("See the pkgsrc guide, section \"CPP defines\" for details."); |
2740 | | | 2747 | |
2741 | } elsif ($macro eq "__NetBSD_Prereq__") { | | 2748 | } elsif ($macro eq "__NetBSD_Prereq__") { |
2742 | $line->log_warning("Please use __NetBSD_Version__ instead of __NetBSD_Prereq__."); | | 2749 | $line->log_warning("Please use __NetBSD_Version__ instead of __NetBSD_Prereq__."); |
2743 | $line->explain_warning( | | 2750 | $line->explain_warning( |
2744 | "The __NetBSD_Prereq__ macro is pretty new. It was born in NetBSD", | | 2751 | "The __NetBSD_Prereq__ macro is pretty new. It was born in NetBSD", |
2745 | "4.99.3, and maybe it won't survive for long. A better (and compatible)", | | 2752 | "4.99.3, and maybe it won't survive for long. A better (and compatible)", |
2746 | "way is to compare __NetBSD_Version__ directly to the required version", | | 2753 | "way is to compare __NetBSD_Version__ directly to the required version", |
2747 | "number."); | | 2754 | "number."); |
2748 | | | 2755 | |
2749 | } elsif ($macro =~ m"^_+NetBSD_+Version_+$"i && $macro ne "__NetBSD_Version__") { | | 2756 | } elsif ($macro =~ m"^_+NetBSD_+Version_+$"i && $macro ne "__NetBSD_Version__") { |
2750 | $line->log_warning("Misspelled variant \"${macro}\" of \"__NetBSD_Version__\"."); | | 2757 | $line->log_warning("Misspelled variant \"${macro}\" of \"__NetBSD_Version__\"."); |
2751 | | | 2758 | |
2752 | } else { | | 2759 | } else { |
2753 | $opt_debug_unchecked and $line->log_debug("Unchecked macro \"${macro}\"."); | | 2760 | $opt_debug_unchecked and $line->log_debug("Unchecked macro \"${macro}\"."); |
2754 | } | | 2761 | } |
2755 | } | | 2762 | } |
2756 | } | | 2763 | } |
2757 | | | 2764 | |
2758 | sub checkline_mk_varuse($$$$) { | | 2765 | sub checkline_mk_varuse($$$$) { |
2759 | my ($line, $varname, $mod, $context) = @_; | | 2766 | my ($line, $varname, $mod, $context) = @_; |
2760 | | | 2767 | |
2761 | assert(defined($varname), "The varname parameter must be defined"); | | 2768 | assert(defined($varname), "The varname parameter must be defined"); |
2762 | assert(defined($context), "The context parameter must be defined"); | | 2769 | assert(defined($context), "The context parameter must be defined"); |
2763 | $opt_debug_trace and $line->log_debug("checkline_mk_varuse(\"${varname}\", \"${mod}\", ".$context->to_string().")"); | | 2770 | $opt_debug_trace and $line->log_debug("checkline_mk_varuse(\"${varname}\", \"${mod}\", ".$context->to_string().")"); |
2764 | | | 2771 | |
2765 | # Check for spelling mistakes. | | 2772 | # Check for spelling mistakes. |
2766 | my $type = get_variable_type($line, $varname); | | 2773 | my $type = get_variable_type($line, $varname); |
2767 | if (defined($type) && !($type->is_guessed)) { | | 2774 | if (defined($type) && !($type->is_guessed)) { |
2768 | # Great. | | 2775 | # Great. |
2769 | | | 2776 | |
2770 | } elsif (var_is_used($varname)) { | | 2777 | } elsif (var_is_used($varname)) { |
2771 | # Fine. | | 2778 | # Fine. |
2772 | | | 2779 | |
2773 | } elsif (defined($mkctx_for_variables) && exists($mkctx_for_variables->{$varname})) { | | 2780 | } elsif (defined($mkctx_for_variables) && exists($mkctx_for_variables->{$varname})) { |
2774 | # Variables defined in .for loops are also ok. | | 2781 | # Variables defined in .for loops are also ok. |
2775 | | | 2782 | |
2776 | } else { | | 2783 | } else { |
2777 | $opt_warn_extra and $line->log_warning("${varname} is used but not defined. Spelling mistake?"); | | 2784 | $opt_warn_extra and $line->log_warning("${varname} is used but not defined. Spelling mistake?"); |
2778 | } | | 2785 | } |
2779 | | | 2786 | |
2780 | if ($opt_warn_perm) { | | 2787 | if ($opt_warn_perm) { |
2781 | my $perms = get_variable_perms($line, $varname); | | 2788 | my $perms = get_variable_perms($line, $varname); |
2782 | my $is_load_time; # Will the variable be used at load time? | | 2789 | my $is_load_time; # Will the variable be used at load time? |
2783 | my $is_indirect; # Might the variable be used indirectly at load time, | | 2790 | my $is_indirect; # Might the variable be used indirectly at load time, |
2784 | # for example by assigning it to another variable | | 2791 | # for example by assigning it to another variable |
2785 | # which then gets evaluated? | | 2792 | # which then gets evaluated? |
2786 | | | 2793 | |
2787 | # Don't warn about variables that are not recorded in the | | 2794 | # Don't warn about variables that are not recorded in the |
2788 | # pkglint variable definition. | | 2795 | # pkglint variable definition. |
2789 | if (defined($context->type) && $context->type->is_guessed()) { | | 2796 | if (defined($context->type) && $context->type->is_guessed()) { |
2790 | $is_load_time = false; | | 2797 | $is_load_time = false; |
2791 | | | 2798 | |
2792 | } elsif ($context->time == VUC_TIME_LOAD && $perms !~ m"p") { | | 2799 | } elsif ($context->time == VUC_TIME_LOAD && $perms !~ m"p") { |
2793 | $is_load_time = true; | | 2800 | $is_load_time = true; |
2794 | $is_indirect = false; | | 2801 | $is_indirect = false; |
2795 | | | 2802 | |
2796 | } elsif (defined($context->type) && $context->type->perms_union() =~ m"p" && $perms !~ m"p") { | | 2803 | } elsif (defined($context->type) && $context->type->perms_union() =~ m"p" && $perms !~ m"p") { |
2797 | $is_load_time = true; | | 2804 | $is_load_time = true; |
2798 | $is_indirect = true; | | 2805 | $is_indirect = true; |
2799 | | | 2806 | |
2800 | } else { | | 2807 | } else { |
2801 | $is_load_time = false; | | 2808 | $is_load_time = false; |
2802 | } | | 2809 | } |
2803 | | | 2810 | |
2804 | if ($is_load_time && !$is_indirect) { | | 2811 | if ($is_load_time && !$is_indirect) { |
2805 | $line->log_warning("${varname} should not be evaluated at load time."); | | 2812 | $line->log_warning("${varname} should not be evaluated at load time."); |
2806 | $line->explain_warning( | | 2813 | $line->explain_warning( |
2807 | "Many variables, especially lists of something, get their values", | | 2814 | "Many variables, especially lists of something, get their values", |
2808 | "incrementally. Therefore it is generally unsafe to rely on their value", | | 2815 | "incrementally. Therefore it is generally unsafe to rely on their value", |
2809 | "until it is clear that it will never change again. This point is", | | 2816 | "until it is clear that it will never change again. This point is", |
2810 | "reached when the whole package Makefile is loaded and execution of the", | | 2817 | "reached when the whole package Makefile is loaded and execution of the", |
2811 | "shell commands starts, in some cases earlier.", | | 2818 | "shell commands starts, in some cases earlier.", |
2812 | "", | | 2819 | "", |
2813 | "Additionally, when using the \":=\" operator, each \$\$ is replaced", | | 2820 | "Additionally, when using the \":=\" operator, each \$\$ is replaced", |
2814 | "with a single \$, so variables that have references to shell variables", | | 2821 | "with a single \$, so variables that have references to shell variables", |
2815 | "or regular expressions are modified in a subtle way."); | | 2822 | "or regular expressions are modified in a subtle way."); |
2816 | } | | 2823 | } |
2817 | if ($is_load_time && $is_indirect) { | | 2824 | if ($is_load_time && $is_indirect) { |
2818 | $line->log_warning("${varname} should not be evaluated indirectly at load time."); | | 2825 | $line->log_warning("${varname} should not be evaluated indirectly at load time."); |
2819 | $line->explain_warning( | | 2826 | $line->explain_warning( |
2820 | "The variable on the left-hand side may be evaluated at load time, but", | | 2827 | "The variable on the left-hand side may be evaluated at load time, but", |
2821 | "the variable on the right-hand side may not. Due to this assignment, it", | | 2828 | "the variable on the right-hand side may not. Due to this assignment, it", |
2822 | "might be used indirectly at load-time, when it is not guaranteed to be", | | 2829 | "might be used indirectly at load-time, when it is not guaranteed to be", |
2823 | "properly defined."); | | 2830 | "properly defined."); |
2824 | } | | 2831 | } |
2825 | | | 2832 | |
2826 | if ($perms !~ m"p" && $perms !~ m"u") { | | 2833 | if ($perms !~ m"p" && $perms !~ m"u") { |
2827 | $line->log_warning("${varname} may not be used in this file."); | | 2834 | $line->log_warning("${varname} may not be used in this file."); |
2828 | } | | 2835 | } |
2829 | } | | 2836 | } |
2830 | | | 2837 | |
2831 | if ($varname eq "LOCALBASE" && !$is_internal) { | | 2838 | if ($varname eq "LOCALBASE" && !$is_internal) { |
2832 | $line->log_warning("The LOCALBASE variable should not be used by packages."); | | 2839 | $line->log_warning("The LOCALBASE variable should not be used by packages."); |
2833 | $line->explain_warning( | | 2840 | $line->explain_warning( |
2834 | # from jlam via private mail. | | 2841 | # from jlam via private mail. |
2835 | "Currently, LOCALBASE is typically used in these cases:", | | 2842 | "Currently, LOCALBASE is typically used in these cases:", |
2836 | "", | | 2843 | "", |
2837 | "(1) To locate a file or directory from another package.", | | 2844 | "(1) To locate a file or directory from another package.", |
2838 | "(2) To refer to own files after installation.", | | 2845 | "(2) To refer to own files after installation.", |
2839 | "", | | 2846 | "", |
2840 | "In the first case, the example is:", | | 2847 | "In the first case, the example is:", |
2841 | "", | | 2848 | "", |
2842 | " STRLIST= \${LOCALBASE}/bin/strlist", | | 2849 | " STRLIST= \${LOCALBASE}/bin/strlist", |
2843 | " do-build:", | | 2850 | " do-build:", |
2844 | " cd \${WRKSRC} && \${STRLIST} *.str", | | 2851 | " cd \${WRKSRC} && \${STRLIST} *.str", |
2845 | "", | | 2852 | "", |
2846 | "This should really be:", | | 2853 | "This should really be:", |
2847 | "", | | 2854 | "", |
2848 | " EVAL_PREFIX= STRLIST_PREFIX=strlist", | | 2855 | " EVAL_PREFIX= STRLIST_PREFIX=strlist", |
2849 | " STRLIST= \${STRLIST_PREFIX}/bin/strlist", | | 2856 | " STRLIST= \${STRLIST_PREFIX}/bin/strlist", |
2850 | " do-build:", | | 2857 | " do-build:", |
2851 | " cd \${WRKSRC} && \${STRLIST} *.str", | | 2858 | " cd \${WRKSRC} && \${STRLIST} *.str", |
2852 | "", | | 2859 | "", |
2853 | "In the second case, the example is:", | | 2860 | "In the second case, the example is:", |
2854 | "", | | 2861 | "", |
2855 | " CONFIGURE_ENV+= --with-datafiles=\${LOCALBASE}/share/battalion", | | 2862 | " CONFIGURE_ENV+= --with-datafiles=\${LOCALBASE}/share/battalion", |
2856 | "", | | 2863 | "", |
2857 | "This should really be:", | | 2864 | "This should really be:", |
2858 | "", | | 2865 | "", |
2859 | " CONFIGURE_ENV+= --with-datafiles=\${PREFIX}/share/battalion"); | | 2866 | " CONFIGURE_ENV+= --with-datafiles=\${PREFIX}/share/battalion"); |
2860 | } | | 2867 | } |
2861 | | | 2868 | |
2862 | my $needs_quoting = variable_needs_quoting($line, $varname, $context); | | 2869 | my $needs_quoting = variable_needs_quoting($line, $varname, $context); |
2863 | | | 2870 | |
2864 | if ($context->shellword == VUC_SHELLWORD_FOR) { | | 2871 | if ($context->shellword == VUC_SHELLWORD_FOR) { |
2865 | if (!defined($type)) { | | 2872 | if (!defined($type)) { |
2866 | # Cannot check anything here. | | 2873 | # Cannot check anything here. |
2867 | | | 2874 | |
2868 | } elsif ($type->kind_of_list == LK_INTERNAL) { | | 2875 | } elsif ($type->kind_of_list == LK_INTERNAL) { |
2869 | # Fine. | | 2876 | # Fine. |
2870 | | | 2877 | |
2871 | } elsif ($needs_quoting == doesnt_matter || $needs_quoting == false) { | | 2878 | } elsif ($needs_quoting == doesnt_matter || $needs_quoting == false) { |
2872 | # Fine, these variables are assumed to not | | 2879 | # Fine, these variables are assumed to not |
2873 | # contain special characters. | | 2880 | # contain special characters. |
2874 | | | 2881 | |
2875 | } else { | | 2882 | } else { |
2876 | $line->log_warning("The variable ${varname} should not be used in .for loops."); | | 2883 | $line->log_warning("The variable ${varname} should not be used in .for loops."); |
2877 | $line->explain_warning( | | 2884 | $line->explain_warning( |
2878 | "The .for loop splits its argument at sequences of white-space, as", | | 2885 | "The .for loop splits its argument at sequences of white-space, as", |
2879 | "opposed to all other places in make(1), which act like the shell.", | | 2886 | "opposed to all other places in make(1), which act like the shell.", |
2880 | "Therefore only variables that are specifically designed to match this", | | 2887 | "Therefore only variables that are specifically designed to match this", |
2881 | "requirement should be used here."); | | 2888 | "requirement should be used here."); |
2882 | } | | 2889 | } |
2883 | } | | 2890 | } |
2884 | | | 2891 | |
2885 | if ($opt_warn_quoting and $context->shellword != VUC_SHELLWORD_UNKNOWN && $needs_quoting != dont_know) { | | 2892 | if ($opt_warn_quoting and $context->shellword != VUC_SHELLWORD_UNKNOWN && $needs_quoting != dont_know) { |
2886 | | | 2893 | |
2887 | # In GNU configure scripts, a few variables need to be | | 2894 | # In GNU configure scripts, a few variables need to be |
2888 | # passed through the :M* operator before they reach the | | 2895 | # passed through the :M* operator before they reach the |
2889 | # configure scripts. | | 2896 | # configure scripts. |
2890 | my $need_mstar = false; | | 2897 | my $need_mstar = false; |
2891 | if ($varname =~ regex_gnu_configure_volatile_vars) { | | 2898 | if ($varname =~ regex_gnu_configure_volatile_vars) { |
2892 | # When we are not checking a package, but some other file, | | 2899 | # When we are not checking a package, but some other file, |
2893 | # the :M* operator is needed for safety. | | 2900 | # the :M* operator is needed for safety. |
2894 | if (!defined($pkgctx_vardef) || exists($pkgctx_vardef->{"GNU_CONFIGURE"})) { | | 2901 | if (!defined($pkgctx_vardef) || exists($pkgctx_vardef->{"GNU_CONFIGURE"})) { |
2895 | $need_mstar = true; | | 2902 | $need_mstar = true; |
2896 | } | | 2903 | } |
2897 | } | | 2904 | } |
2898 | | | 2905 | |
2899 | my $stripped_mod = ($mod =~ m"(.*?)(?::M\*)?(?::Q)?$") ? $1 : $mod; | | 2906 | my $stripped_mod = ($mod =~ m"(.*?)(?::M\*)?(?::Q)?$") ? $1 : $mod; |
2900 | my $correct_mod = $stripped_mod . ($need_mstar ? ":M*:Q" : ":Q"); | | 2907 | my $correct_mod = $stripped_mod . ($need_mstar ? ":M*:Q" : ":Q"); |
2901 | | | 2908 | |
2902 | if ($mod eq ":M*:Q" && !$need_mstar) { | | 2909 | if ($mod eq ":M*:Q" && !$need_mstar) { |
2903 | $line->log_note("The :M* modifier is not needed here."); | | 2910 | $line->log_note("The :M* modifier is not needed here."); |
2904 | | | 2911 | |
2905 | } elsif ($mod ne $correct_mod && $needs_quoting == true) { | | 2912 | } elsif ($mod ne $correct_mod && $needs_quoting == true) { |
2906 | if ($context->shellword == VUC_SHELLWORD_PLAIN) { | | 2913 | if ($context->shellword == VUC_SHELLWORD_PLAIN) { |
2907 | $line->log_warning("Please use \${${varname}${correct_mod}} instead of \${${varname}${mod}}."); | | 2914 | $line->log_warning("Please use \${${varname}${correct_mod}} instead of \${${varname}${mod}}."); |
2908 | #$line->replace("\${${varname}}", "\${${varname}:Q}"); | | 2915 | #$line->replace("\${${varname}}", "\${${varname}:Q}"); |
2909 | } else { | | 2916 | } else { |
2910 | $line->log_warning("Please use \${${varname}${correct_mod}} instead of \${${varname}${mod}} and make sure the variable appears outside of any quoting characters."); | | 2917 | $line->log_warning("Please use \${${varname}${correct_mod}} instead of \${${varname}${mod}} and make sure the variable appears outside of any quoting characters."); |
2911 | } | | 2918 | } |
2912 | $line->explain_warning("See the pkgsrc guide, section \"quoting guideline\", for details."); | | 2919 | $line->explain_warning("See the pkgsrc guide, section \"quoting guideline\", for details."); |
2913 | } | | 2920 | } |
2914 | | | 2921 | |
2915 | if ($mod =~ m":Q$") { | | 2922 | if ($mod =~ m":Q$") { |
2916 | my @expl = ( | | 2923 | my @expl = ( |
2917 | "Many variables in pkgsrc do not need the :Q operator, since they", | | 2924 | "Many variables in pkgsrc do not need the :Q operator, since they", |
2918 | "are not expected to contain white-space or other evil characters.", | | 2925 | "are not expected to contain white-space or other evil characters.", |
2919 | "", | | 2926 | "", |
2920 | "Another case is when a variable of type ShellWord appears in a context", | | 2927 | "Another case is when a variable of type ShellWord appears in a context", |
2921 | "that expects a shell word, it does not need to have a :Q operator. Even", | | 2928 | "that expects a shell word, it does not need to have a :Q operator. Even", |
2922 | "when it is concatenated with another variable, it still stays _one_ word.", | | 2929 | "when it is concatenated with another variable, it still stays _one_ word.", |
2923 | "", | | 2930 | "", |
2924 | "Example:", | | 2931 | "Example:", |
2925 | "\tWORD1= Have\\ fun # 1 word", | | 2932 | "\tWORD1= Have\\ fun # 1 word", |
2926 | "\tWORD2= \"with BSD Make\" # 1 word, too", | | 2933 | "\tWORD2= \"with BSD Make\" # 1 word, too", |
2927 | "", | | 2934 | "", |
2928 | "\tdemo:", | | 2935 | "\tdemo:", |
2929 | "\t\techo \${WORD1}\${WORD2} # still 1 word"); | | 2936 | "\t\techo \${WORD1}\${WORD2} # still 1 word"); |
2930 | | | 2937 | |
2931 | if ($needs_quoting == false) { | | 2938 | if ($needs_quoting == false) { |
2932 | $line->log_warning("The :Q operator should not be used for \${${varname}} here."); | | 2939 | $line->log_warning("The :Q operator should not be used for \${${varname}} here."); |
2933 | $line->explain_warning(@expl); | | 2940 | $line->explain_warning(@expl); |
2934 | } elsif ($needs_quoting == doesnt_matter) { | | 2941 | } elsif ($needs_quoting == doesnt_matter) { |
2935 | $line->log_note("The :Q operator isn't necessary for \${${varname}} here."); | | 2942 | $line->log_note("The :Q operator isn't necessary for \${${varname}} here."); |
2936 | $line->explain_note(@expl); | | 2943 | $line->explain_note(@expl); |
2937 | } | | 2944 | } |
2938 | } | | 2945 | } |
2939 | } | | 2946 | } |
2940 | | | 2947 | |
2941 | assert(defined($mkctx_build_defs), "The build_defs variable must be defined here."); | | 2948 | assert(defined($mkctx_build_defs), "The build_defs variable must be defined here."); |
2942 | if (exists(get_userdefined_variables()->{$varname}) && !exists(get_system_build_defs()->{$varname}) && !exists($mkctx_build_defs->{$varname})) { | | 2949 | if (exists(get_userdefined_variables()->{$varname}) && !exists(get_system_build_defs()->{$varname}) && !exists($mkctx_build_defs->{$varname})) { |
2943 | $line->log_warning("The user-defined variable ${varname} is used but not added to BUILD_DEFS."); | | 2950 | $line->log_warning("The user-defined variable ${varname} is used but not added to BUILD_DEFS."); |
2944 | $line->explain_warning( | | 2951 | $line->explain_warning( |
2945 | "When a pkgsrc package is built, many things can be configured by the", | | 2952 | "When a pkgsrc package is built, many things can be configured by the", |
2946 | "pkgsrc user in the mk.conf file. All these configurations should be", | | 2953 | "pkgsrc user in the mk.conf file. All these configurations should be", |
2947 | "recorded in the binary package, so the package can be reliably rebuilt.", | | 2954 | "recorded in the binary package, so the package can be reliably rebuilt.", |
2948 | "The BUILD_DEFS variable contains a list of all these user-settable", | | 2955 | "The BUILD_DEFS variable contains a list of all these user-settable", |
2949 | "variables, so please add your variable to it, too."); | | 2956 | "variables, so please add your variable to it, too."); |
2950 | } | | 2957 | } |
2951 | } | | 2958 | } |
2952 | | | 2959 | |
2953 | sub checkline_mk_text($$) { | | 2960 | sub checkline_mk_text($$) { |
2954 | my ($line, $text) = @_; | | 2961 | my ($line, $text) = @_; |
2955 | my ($rest, $state, $vartools, $depr_map); | | 2962 | my ($rest, $state, $vartools, $depr_map); |
2956 | | | 2963 | |
2957 | if ($text =~ m"^(?:[^#]*[^\$])?\$(\w+)") { | | 2964 | if ($text =~ m"^(?:[^#]*[^\$])?\$(\w+)") { |
2958 | my ($varname) = ($1); | | 2965 | my ($varname) = ($1); |
2959 | $line->log_warning("\$$varname is ambiguous. Use \${$varname} if you mean a Makefile variable or \$\$$varname if you mean a shell variable."); | | 2966 | $line->log_warning("\$$varname is ambiguous. Use \${$varname} if you mean a Makefile variable or \$\$$varname if you mean a shell variable."); |
2960 | } | | 2967 | } |
2961 | | | 2968 | |
2962 | if ($line->lines eq "1") { | | 2969 | if ($line->lines eq "1") { |
2963 | checkline_rcsid_regex($line, qr"#\s+", "# "); | | 2970 | checkline_rcsid_regex($line, qr"#\s+", "# "); |
2964 | } | | 2971 | } |
2965 | | | 2972 | |
2966 | if ($text =~ m"\$\{WRKSRC\}/\.\./") { | | 2973 | if ($text =~ m"\$\{WRKSRC\}/\.\./") { |
2967 | $line->log_warning("Using \"\${WRKSRC}/..\" is conceptually wrong. Please use a combination of WRKSRC, CONFIGURE_DIRS and BUILD_DIRS instead."); | | 2974 | $line->log_warning("Using \"\${WRKSRC}/..\" is conceptually wrong. Please use a combination of WRKSRC, CONFIGURE_DIRS and BUILD_DIRS instead."); |
2968 | $line->explain_warning( | | 2975 | $line->explain_warning( |
2969 | "You should define WRKSRC such that all of CONFIGURE_DIRS, BUILD_DIRS", | | 2976 | "You should define WRKSRC such that all of CONFIGURE_DIRS, BUILD_DIRS", |
2970 | "and INSTALL_DIRS are subdirectories of it."); | | 2977 | "and INSTALL_DIRS are subdirectories of it."); |
2971 | } | | 2978 | } |
2972 | | | 2979 | |
2973 | if ($text =~ m"\b(-Wl,--rpath,|-Wl,-rpath-link,|-Wl,-rpath,|-Wl,-R)\b") { | | 2980 | if ($text =~ m"\b(-Wl,--rpath,|-Wl,-rpath-link,|-Wl,-rpath,|-Wl,-R)\b") { |
2974 | $line->log_warning("Please use \${COMPILER_RPATH_FLAG} instead of $1."); | | 2981 | $line->log_warning("Please use \${COMPILER_RPATH_FLAG} instead of $1."); |
2975 | } | | 2982 | } |
2976 | # Note: A simple -R is not detected, as the rate of false | | 2983 | # Note: A simple -R is not detected, as the rate of false |
2977 | # positives is too high. | | 2984 | # positives is too high. |
2978 | | | 2985 | |
2979 | $rest = $text; | | 2986 | $rest = $text; |
2980 | $depr_map = get_deprecated_map(); | | 2987 | $depr_map = get_deprecated_map(); |
2981 | while ($rest =~ s/(?:^|[^\$])\$\{([-A-Z0-9a-z_]+)(\.[\-0-9A-Z_a-z]+)?(?::[^\}]+)?\}//) { | | 2988 | while ($rest =~ s/(?:^|[^\$])\$\{([-A-Z0-9a-z_]+)(\.[\-0-9A-Z_a-z]+)?(?::[^\}]+)?\}//) { |
2982 | my ($varbase, $varext) = ($1, $2); | | 2989 | my ($varbase, $varext) = ($1, $2); |
2983 | my $varname = $varbase . (defined($varext) ? $varext : ""); | | 2990 | my $varname = $varbase . (defined($varext) ? $varext : ""); |
2984 | my $varcanon = varname_canon($varname); | | 2991 | my $varcanon = varname_canon($varname); |
2985 | my $instead = | | 2992 | my $instead = |
2986 | (exists($depr_map->{$varname})) ? $depr_map->{$varname} | | 2993 | (exists($depr_map->{$varname})) ? $depr_map->{$varname} |
2987 | : (exists($depr_map->{$varcanon})) ? $depr_map->{$varcanon} | | 2994 | : (exists($depr_map->{$varcanon})) ? $depr_map->{$varcanon} |
2988 | : undef; | | 2995 | : undef; |
2989 | | | 2996 | |
2990 | if (defined($instead)) { | | 2997 | if (defined($instead)) { |
2991 | $line->log_warning("Use of ${varname} is deprecated. ${instead}"); | | 2998 | $line->log_warning("Use of ${varname} is deprecated. ${instead}"); |
2992 | } | | 2999 | } |
2993 | } | | 3000 | } |
2994 | | | 3001 | |
2995 | # Don't enforce purely aesthetic changes before more correct behaviour is implemented: | | 3002 | # Don't enforce purely aesthetic changes before more correct behaviour is implemented: |
2996 | # $rest = $text; | | 3003 | # $rest = $text; |
2997 | # while ($rest =~ s/(?:^|[^\$])\$\(([-A-Z0-9a-z_]+)(?::[^\}]+)?\)//) { | | 3004 | # while ($rest =~ s/(?:^|[^\$])\$\(([-A-Z0-9a-z_]+)(?::[^\}]+)?\)//) { |
2998 | # my ($varname) = ($1); | | 3005 | # my ($varname) = ($1); |
2999 | | | 3006 | |
3000 | # $line->log_warning("Please use \${${varname}\} instead of \$(${varname})."); | | 3007 | # $line->log_warning("Please use \${${varname}\} instead of \$(${varname})."); |
3001 | # } | | 3008 | # } |
3002 | | | 3009 | |
3003 | } | | 3010 | } |
3004 | | | 3011 | |
3005 | sub checkline_mk_shellword($$$) { | | 3012 | sub checkline_mk_shellword($$$) { |
3006 | my ($line, $shellword, $check_quoting) = @_; | | 3013 | my ($line, $shellword, $check_quoting) = @_; |
3007 | my ($rest, $state, $value); | | 3014 | my ($rest, $state, $value); |
3008 | | | 3015 | |
3009 | $opt_debug_trace and $line->log_debug("checkline_mk_shellword(\"${shellword}\", ${check_quoting})."); | | 3016 | $opt_debug_trace and $line->log_debug("checkline_mk_shellword(\"${shellword}\", ${check_quoting})."); |
3010 | use constant shellcommand_context_type => PkgLint::Type->new( | | 3017 | use constant shellcommand_context_type => PkgLint::Type->new( |
3011 | LK_NONE, "ShellCommand", [[ qr".*", "adsu" ]], NOT_GUESSED | | 3018 | LK_NONE, "ShellCommand", [[ qr".*", "adsu" ]], NOT_GUESSED |
3012 | ); | | 3019 | ); |
3013 | use constant shellword_vuc => PkgLint::VarUseContext->new( | | 3020 | use constant shellword_vuc => PkgLint::VarUseContext->new( |
3014 | VUC_TIME_UNKNOWN, | | 3021 | VUC_TIME_UNKNOWN, |
3015 | shellcommand_context_type, | | 3022 | shellcommand_context_type, |
3016 | VUC_SHELLWORD_PLAIN, | | 3023 | VUC_SHELLWORD_PLAIN, |
3017 | VUC_EXTENT_WORD | | 3024 | VUC_EXTENT_WORD |
3018 | ); | | 3025 | ); |
3019 | | | 3026 | |
3020 | if ($shellword =~ m"^\$\{(${regex_varname})(:[^{}]+)?\}$") { | | 3027 | if ($shellword =~ m"^\$\{(${regex_varname})(:[^{}]+)?\}$") { |
3021 | my ($varname, $mod) = ($1, $2); | | 3028 | my ($varname, $mod) = ($1, $2); |
3022 | | | 3029 | |
3023 | checkline_mk_varuse($line, $varname, defined($mod) ? $mod : "", shellword_vuc); | | 3030 | checkline_mk_varuse($line, $varname, defined($mod) ? $mod : "", shellword_vuc); |
3024 | return; | | 3031 | return; |
3025 | } | | 3032 | } |
3026 | | | 3033 | |
3027 | if ($shellword =~ m"\$\{PREFIX\}/man(?:$|/)") { | | 3034 | if ($shellword =~ m"\$\{PREFIX\}/man(?:$|/)") { |
3028 | $line->log_warning("Please use \${PKGMANDIR} instead of \"man\"."); | | 3035 | $line->log_warning("Please use \${PKGMANDIR} instead of \"man\"."); |
3029 | } | | 3036 | } |
3030 | | | 3037 | |
3031 | if ($shellword =~ m"etc/rc\.d") { | | 3038 | if ($shellword =~ m"etc/rc\.d") { |
3032 | $line->log_warning("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to \${RCD_SCRIPTS_EXAMPLEDIR}."); | | 3039 | $line->log_warning("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to \${RCD_SCRIPTS_EXAMPLEDIR}."); |
3033 | } | | 3040 | } |
3034 | | | 3041 | |
3035 | # Note: SWST means [S]hell[W]ord [ST]ate | | 3042 | # Note: SWST means [S]hell[W]ord [ST]ate |
3036 | use enum qw(:SWST_ PLAIN SQUOT DQUOT DQUOT_BACKT BACKT); | | 3043 | use enum qw(:SWST_ PLAIN SQUOT DQUOT DQUOT_BACKT BACKT); |
3037 | use constant statename => [ | | 3044 | use constant statename => [ |
3038 | "SWST_PLAIN", "SWST_SQUOT", "SWST_DQUOT", | | 3045 | "SWST_PLAIN", "SWST_SQUOT", "SWST_DQUOT", |
3039 | "SWST_DQUOT_BACKT", "SWST_BACKT", | | 3046 | "SWST_DQUOT_BACKT", "SWST_BACKT", |
3040 | ]; | | 3047 | ]; |
3041 | use constant user_statename => [ | | 3048 | use constant user_statename => [ |
3042 | "unquoted string", "single quoted string", | | 3049 | "unquoted string", "single quoted string", |
3043 | "double quoted string", "backticks inside double quoted string", | | 3050 | "double quoted string", "backticks inside double quoted string", |
3044 | "backticks", | | 3051 | "backticks", |
3045 | ]; | | 3052 | ]; |
3046 | | | 3053 | |
3047 | $rest = ($shellword =~ m"^#") ? "" : $shellword; | | 3054 | $rest = ($shellword =~ m"^#") ? "" : $shellword; |
3048 | $state = SWST_PLAIN; | | 3055 | $state = SWST_PLAIN; |
3049 | while ($rest ne "") { | | 3056 | while ($rest ne "") { |
3050 | | | 3057 | |
3051 | $opt_debug_shell and $line->log_debug(statename->[$state] . ": ${rest}"); | | 3058 | $opt_debug_shell and $line->log_debug(statename->[$state] . ": ${rest}"); |
3052 | | | 3059 | |
3053 | # When we are parsing inside backticks, it is more | | 3060 | # When we are parsing inside backticks, it is more |
3054 | # reasonable to check the whole shell command | | 3061 | # reasonable to check the whole shell command |
3055 | # recursively, instead of splitting off the first | | 3062 | # recursively, instead of splitting off the first |
3056 | # make(1) variable (see the elsif below). | | 3063 | # make(1) variable (see the elsif below). |
3057 | if ($state == SWST_BACKT || $state == SWST_DQUOT_BACKT) { | | 3064 | if ($state == SWST_BACKT || $state == SWST_DQUOT_BACKT) { |
3058 | | | 3065 | |
3059 | # Scan for the end of the backticks, checking | | 3066 | # Scan for the end of the backticks, checking |
3060 | # for single backslashes and removing one level | | 3067 | # for single backslashes and removing one level |
3061 | # of backslashes. Backslashes are only removed | | 3068 | # of backslashes. Backslashes are only removed |
3062 | # before a dollar, a backslash or a backtick. | | 3069 | # before a dollar, a backslash or a backtick. |
3063 | # | | 3070 | # |
3064 | # References: | | 3071 | # References: |
3065 | # * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03 | | 3072 | # * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03 |
3066 | my $stripped = ""; | | 3073 | my $stripped = ""; |
3067 | while ($rest ne "") { | | 3074 | while ($rest ne "") { |
3068 | if ($rest =~ s/^\`//) { | | 3075 | if ($rest =~ s/^\`//) { |
3069 | $state = ($state == SWST_BACKT) ? SWST_PLAIN : SWST_DQUOT; | | 3076 | $state = ($state == SWST_BACKT) ? SWST_PLAIN : SWST_DQUOT; |
3070 | goto end_of_backquotes; | | 3077 | goto end_of_backquotes; |
3071 | } elsif ($rest =~ s/^\\([\\\`\$])//) { | | 3078 | } elsif ($rest =~ s/^\\([\\\`\$])//) { |
3072 | $stripped .= $1; | | 3079 | $stripped .= $1; |
3073 | } elsif ($rest =~ s/^(\\)//) { | | 3080 | } elsif ($rest =~ s/^(\\)//) { |
3074 | $line->log_warning("Backslashes should be doubled inside backticks."); | | 3081 | $line->log_warning("Backslashes should be doubled inside backticks."); |
3075 | $stripped .= $1; | | 3082 | $stripped .= $1; |
3076 | } elsif ($state == SWST_DQUOT_BACKT && $rest =~ s/^"//) { | | 3083 | } elsif ($state == SWST_DQUOT_BACKT && $rest =~ s/^"//) { |
3077 | $line->log_warning("Double quotes inside backticks inside double quotes are error prone."); | | 3084 | $line->log_warning("Double quotes inside backticks inside double quotes are error prone."); |
3078 | $line->explain_warning( | | 3085 | $line->explain_warning( |
3079 | "According to the SUSv3, they produce undefined results.", | | 3086 | "According to the SUSv3, they produce undefined results.", |
3080 | "", | | 3087 | "", |
3081 | "See the paragraph starting \"Within the backquoted ...\" in", | | 3088 | "See the paragraph starting \"Within the backquoted ...\" in", |
3082 | "http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html"); | | 3089 | "http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html"); |
3083 | } elsif ($rest =~ s/^([^\\\`]+)//) { | | 3090 | } elsif ($rest =~ s/^([^\\\`]+)//) { |
3084 | $stripped .= $1; | | 3091 | $stripped .= $1; |
3085 | } else { | | 3092 | } else { |
3086 | assert(false, "rest=$rest"); | | 3093 | assert(false, "rest=$rest"); |
3087 | } | | 3094 | } |
3088 | } | | 3095 | } |
3089 | $line->log_error("Unfinished backquotes: rest=$rest"); | | 3096 | $line->log_error("Unfinished backquotes: rest=$rest"); |
3090 | | | 3097 | |
3091 | end_of_backquotes: | | 3098 | end_of_backquotes: |
3092 | # Check the resulting command. | | 3099 | # Check the resulting command. |
3093 | checkline_mk_shelltext($line, $stripped); | | 3100 | checkline_mk_shelltext($line, $stripped); |
3094 | | | 3101 | |
3095 | # make(1) variables have the same syntax, no matter in | | 3102 | # make(1) variables have the same syntax, no matter in |
3096 | # which state we are currently. | | 3103 | # which state we are currently. |
3097 | } elsif ($rest =~ s/^\$\{(${regex_varname}|[\@])(:[^\{]+)?\}// | | 3104 | } elsif ($rest =~ s/^\$\{(${regex_varname}|[\@])(:[^\{]+)?\}// |
3098 | || $rest =~ s/^\$\((${regex_varname}|[\@])(:[^\)]+)?\)// | | 3105 | || $rest =~ s/^\$\((${regex_varname}|[\@])(:[^\)]+)?\)// |
3099 | || $rest =~ s/^\$([\w\@])//) { | | 3106 | || $rest =~ s/^\$([\w\@])//) { |
3100 | my ($varname, $mod) = ($1, $2); | | 3107 | my ($varname, $mod) = ($1, $2); |
3101 | | | 3108 | |
3102 | if ($varname eq "\@") { | | 3109 | if ($varname eq "\@") { |
3103 | $line->log_warning("Please use \"\${.TARGET}\" instead of \"\$\@\"."); | | 3110 | $line->log_warning("Please use \"\${.TARGET}\" instead of \"\$\@\"."); |
3104 | $line->explain_warning( | | 3111 | $line->explain_warning( |
3105 | "The variable \$\@ can easily be confused with the shell variable of the", | | 3112 | "The variable \$\@ can easily be confused with the shell variable of the", |
3106 | "same name, which has a completely different meaning."); | | 3113 | "same name, which has a completely different meaning."); |
3107 | $varname = ".TARGET"; | | 3114 | $varname = ".TARGET"; |
3108 | } | | 3115 | } |
3109 | | | 3116 | |
3110 | if ($state == SWST_PLAIN && defined($mod) && $mod =~ m":Q$") { | | 3117 | if ($state == SWST_PLAIN && defined($mod) && $mod =~ m":Q$") { |
3111 | # Fine. | | 3118 | # Fine. |
3112 | | | 3119 | |
3113 | } elsif ($state == SWST_BACKT) { | | 3120 | } elsif ($state == SWST_BACKT) { |
3114 | # Don't check here, to avoid false positives | | 3121 | # Don't check here, to avoid false positives |
3115 | # for tool names. | | 3122 | # for tool names. |
3116 | | | 3123 | |
3117 | } elsif (($state == SWST_SQUOT || $state == SWST_DQUOT) && $varname =~ m"^(?:.*DIR|.*FILE|.*PATH|.*_VAR|PREFIX|.*BASE|PKGNAME)$") { | | 3124 | } elsif (($state == SWST_SQUOT || $state == SWST_DQUOT) && $varname =~ m"^(?:.*DIR|.*FILE|.*PATH|.*_VAR|PREFIX|.*BASE|PKGNAME)$") { |
3118 | # This is ok if we don't allow these | | 3125 | # This is ok if we don't allow these |
3119 | # variables to have embedded [\$\\\"\'\`]. | | 3126 | # variables to have embedded [\$\\\"\'\`]. |
3120 | | | 3127 | |
3121 | } elsif ($state == SWST_DQUOT && defined($mod) && $mod =~ m":Q$") { | | 3128 | } elsif ($state == SWST_DQUOT && defined($mod) && $mod =~ m":Q$") { |
3122 | $line->log_warning("Please don't use the :Q operator in double quotes."); | | 3129 | $line->log_warning("Please don't use the :Q operator in double quotes."); |
3123 | $line->explain_warning( | | 3130 | $line->explain_warning( |
3124 | "Either remove the :Q or the double quotes. In most cases, it is more", | | 3131 | "Either remove the :Q or the double quotes. In most cases, it is more", |
3125 | "appropriate to remove the double quotes."); | | 3132 | "appropriate to remove the double quotes."); |
3126 | | | 3133 | |
3127 | } | | 3134 | } |
3128 | | | 3135 | |
3129 | my $ctx = PkgLint::VarUseContext->new_from_pool( | | 3136 | my $ctx = PkgLint::VarUseContext->new_from_pool( |
3130 | VUC_TIME_UNKNOWN, | | 3137 | VUC_TIME_UNKNOWN, |
3131 | shellcommand_context_type, | | 3138 | shellcommand_context_type, |
3132 | ($state == SWST_PLAIN) ? VUC_SHELLWORD_PLAIN | | 3139 | ($state == SWST_PLAIN) ? VUC_SHELLWORD_PLAIN |
3133 | : ($state == SWST_DQUOT) ? VUC_SHELLWORD_DQUOT | | 3140 | : ($state == SWST_DQUOT) ? VUC_SHELLWORD_DQUOT |
3134 | : ($state == SWST_SQUOT) ? VUC_SHELLWORD_SQUOT | | 3141 | : ($state == SWST_SQUOT) ? VUC_SHELLWORD_SQUOT |
3135 | : ($state == SWST_BACKT) ? VUC_SHELLWORD_BACKT | | 3142 | : ($state == SWST_BACKT) ? VUC_SHELLWORD_BACKT |
3136 | : VUC_SHELLWORD_UNKNOWN, | | 3143 | : VUC_SHELLWORD_UNKNOWN, |
3137 | VUC_EXTENT_WORD_PART | | 3144 | VUC_EXTENT_WORD_PART |
3138 | ); | | 3145 | ); |
3139 | if ($varname ne "\@") { | | 3146 | if ($varname ne "\@") { |
3140 | checkline_mk_varuse($line, $varname, defined($mod) ? $mod : "", $ctx); | | 3147 | checkline_mk_varuse($line, $varname, defined($mod) ? $mod : "", $ctx); |
3141 | } | | 3148 | } |
3142 | | | 3149 | |
3143 | # The syntax of the variable modifiers can get quite | | 3150 | # The syntax of the variable modifiers can get quite |
3144 | # hairy. In lack of motivation, we just skip anything | | 3151 | # hairy. In lack of motivation, we just skip anything |
3145 | # complicated, hoping that at least the braces are | | 3152 | # complicated, hoping that at least the braces are |
3146 | # balanced. | | 3153 | # balanced. |
3147 | } elsif ($rest =~ s/^\$\{//) { | | 3154 | } elsif ($rest =~ s/^\$\{//) { |
3148 | my $braces = 1; | | 3155 | my $braces = 1; |
3149 | while ($rest ne "" && $braces > 0) { | | 3156 | while ($rest ne "" && $braces > 0) { |
3150 | if ($rest =~ s/^\}//) { | | 3157 | if ($rest =~ s/^\}//) { |
3151 | $braces--; | | 3158 | $braces--; |
3152 | } elsif ($rest =~ s/^\{//) { | | 3159 | } elsif ($rest =~ s/^\{//) { |
3153 | $braces++; | | 3160 | $braces++; |
3154 | } elsif ($rest =~ s/^[^{}]+//) { | | 3161 | } elsif ($rest =~ s/^[^{}]+//) { |
3155 | # Nothing to do here. | | 3162 | # Nothing to do here. |
3156 | } else { | | 3163 | } else { |
3157 | last; | | 3164 | last; |
3158 | } | | 3165 | } |
3159 | } | | 3166 | } |
3160 | | | 3167 | |
3161 | } elsif ($state == SWST_PLAIN) { | | 3168 | } elsif ($state == SWST_PLAIN) { |
3162 | | | 3169 | |
3163 | # XXX: This is only true for the "first" word in a | | 3170 | # XXX: This is only true for the "first" word in a |
3164 | # shell command, not for every word. For example, | | 3171 | # shell command, not for every word. For example, |
3165 | # FOO_ENV+= VAR=`command` may be underquoted. | | 3172 | # FOO_ENV+= VAR=`command` may be underquoted. |
3166 | if (false && $rest =~ m"([\w_]+)=\"\`") { | | 3173 | if (false && $rest =~ m"([\w_]+)=\"\`") { |
3167 | $line->log_note("In the assignment to \"$1\", you don't need double quotes around backticks."); | | 3174 | $line->log_note("In the assignment to \"$1\", you don't need double quotes around backticks."); |
3168 | $line->explain_note( | | 3175 | $line->explain_note( |
3169 | "Assignments are a special context, where no double quotes are needed", | | 3176 | "Assignments are a special context, where no double quotes are needed", |
3170 | "around backticks. In other contexts, the double quotes are necessary."); | | 3177 | "around backticks. In other contexts, the double quotes are necessary."); |
3171 | } | | 3178 | } |
3172 | | | 3179 | |
3173 | if ($rest =~ s/^[!#\%&\(\)*+,\-.\/0-9:;<=>?\@A-Z\[\]^_a-z{|}~]+//) { | | 3180 | if ($rest =~ s/^[!#\%&\(\)*+,\-.\/0-9:;<=>?\@A-Z\[\]^_a-z{|}~]+//) { |
3174 | } elsif ($rest =~ s/^\'//) { | | 3181 | } elsif ($rest =~ s/^\'//) { |
3175 | $state = SWST_SQUOT; | | 3182 | $state = SWST_SQUOT; |
3176 | } elsif ($rest =~ s/^\"//) { | | 3183 | } elsif ($rest =~ s/^\"//) { |
3177 | $state = SWST_DQUOT; | | 3184 | $state = SWST_DQUOT; |
3178 | } elsif ($rest =~ s/^\`//) { | | 3185 | } elsif ($rest =~ s/^\`//) { |
3179 | $state = SWST_BACKT; | | 3186 | $state = SWST_BACKT; |
3180 | } elsif ($rest =~ s/^\\(?:[ !"#'\(\)*;?\\^{|}]|\$\$)//) { | | 3187 | } elsif ($rest =~ s/^\\(?:[ !"#'\(\)*;?\\^{|}]|\$\$)//) { |
3181 | } elsif ($rest =~ s/^\$\$([0-9A-Z_a-z]+|\#)// | | 3188 | } elsif ($rest =~ s/^\$\$([0-9A-Z_a-z]+|\#)// |
3182 | || $rest =~ s/^\$\$\{([0-9A-Z_a-z]+|\#)\}// | | 3189 | || $rest =~ s/^\$\$\{([0-9A-Z_a-z]+|\#)\}// |
3183 | || $rest =~ s/^\$\$(\$)\$//) { | | 3190 | || $rest =~ s/^\$\$(\$)\$//) { |
3184 | my ($shvarname) = ($1); | | 3191 | my ($shvarname) = ($1); |
3185 | if ($opt_warn_quoting && $check_quoting) { | | 3192 | if ($opt_warn_quoting && $check_quoting) { |
3186 | $line->log_warning("Unquoted shell variable \"${shvarname}\"."); | | 3193 | $line->log_warning("Unquoted shell variable \"${shvarname}\"."); |
3187 | $line->explain_warning( | | 3194 | $line->explain_warning( |
3188 | "When a shell variable contains white-space, it is expanded (split into", | | 3195 | "When a shell variable contains white-space, it is expanded (split into", |
3189 | "multiple words) when it is written as \$variable in a shell script.", | | 3196 | "multiple words) when it is written as \$variable in a shell script.", |
3190 | "If that is not intended, you should add quotation marks around it,", | | 3197 | "If that is not intended, you should add quotation marks around it,", |
3191 | "like \"\$variable\". Then, the variable will always expand to a single", | | 3198 | "like \"\$variable\". Then, the variable will always expand to a single", |
3192 | "word, preserving all white-space and other special characters.", | | 3199 | "word, preserving all white-space and other special characters.", |
3193 | "", | | 3200 | "", |
3194 | "Example:", | | 3201 | "Example:", |
3195 | "\tfname=\"Curriculum vitae.doc\"", | | 3202 | "\tfname=\"Curriculum vitae.doc\"", |
3196 | "\tcp \$fname /tmp", | | 3203 | "\tcp \$fname /tmp", |
3197 | "\t# tries to copy the two files \"Curriculum\" and \"Vitae.doc\"", | | 3204 | "\t# tries to copy the two files \"Curriculum\" and \"Vitae.doc\"", |
3198 | "\tcp \"\$fname\" /tmp", | | 3205 | "\tcp \"\$fname\" /tmp", |
3199 | "\t# copies one file, as intended"); | | 3206 | "\t# copies one file, as intended"); |
3200 | } | | 3207 | } |
3201 | | | 3208 | |
3202 | } elsif ($rest =~ s/^\$\@//) { | | 3209 | } elsif ($rest =~ s/^\$\@//) { |
3203 | $line->log_warning("Please use \"\${.TARGET}\" instead of \"\$@\"."); | | 3210 | $line->log_warning("Please use \"\${.TARGET}\" instead of \"\$@\"."); |
3204 | $line->explain_warning( | | 3211 | $line->explain_warning( |
3205 | "It is more readable and prevents confusion with the shell variable of", | | 3212 | "It is more readable and prevents confusion with the shell variable of", |
3206 | "the same name."); | | 3213 | "the same name."); |
3207 | | | 3214 | |
3208 | } elsif ($rest =~ s/^\$\$\@//) { | | 3215 | } elsif ($rest =~ s/^\$\$\@//) { |
3209 | $line->log_warning("The \$@ shell variable should only be used in double quotes."); | | 3216 | $line->log_warning("The \$@ shell variable should only be used in double quotes."); |
3210 | | | 3217 | |
3211 | } elsif ($rest =~ s/^\$\$\?//) { | | 3218 | } elsif ($rest =~ s/^\$\$\?//) { |
3212 | $line->log_warning("The \$? shell variable is often not available in \"set -e\" mode."); | | 3219 | $line->log_warning("The \$? shell variable is often not available in \"set -e\" mode."); |
3213 | | | 3220 | |
3214 | } elsif ($rest =~ s/^\$\$\(/(/) { | | 3221 | } elsif ($rest =~ s/^\$\$\(/(/) { |
3215 | $line->log_warning("Invoking subshells via \$(...) is not portable enough."); | | 3222 | $line->log_warning("Invoking subshells via \$(...) is not portable enough."); |
3216 | $line->explain_warning( | | 3223 | $line->explain_warning( |
3217 | "The Solaris /bin/sh does not know this way to execute a command in a", | | 3224 | "The Solaris /bin/sh does not know this way to execute a command in a", |
3218 | "subshell. Please use backticks (\`...\`) as a replacement."); | | 3225 | "subshell. Please use backticks (\`...\`) as a replacement."); |
3219 | | | 3226 | |
3220 | } else { | | 3227 | } else { |
3221 | last; | | 3228 | last; |
3222 | } | | 3229 | } |
3223 | | | 3230 | |
3224 | } elsif ($state == SWST_SQUOT) { | | 3231 | } elsif ($state == SWST_SQUOT) { |
3225 | if ($rest =~ s/^\'//) { | | 3232 | if ($rest =~ s/^\'//) { |
3226 | $state = SWST_PLAIN; | | 3233 | $state = SWST_PLAIN; |
3227 | } elsif ($rest =~ s/^[^\$\']+//) { | | 3234 | } elsif ($rest =~ s/^[^\$\']+//) { |
3228 | } elsif ($rest =~ s/^\$\$//) { | | 3235 | } elsif ($rest =~ s/^\$\$//) { |
3229 | } else { | | 3236 | } else { |
3230 | last; | | 3237 | last; |
3231 | } | | 3238 | } |
3232 | | | 3239 | |
3233 | } elsif ($state == SWST_DQUOT) { | | 3240 | } elsif ($state == SWST_DQUOT) { |
3234 | if ($rest =~ s/^\"//) { | | 3241 | if ($rest =~ s/^\"//) { |
3235 | $state = SWST_PLAIN; | | 3242 | $state = SWST_PLAIN; |
3236 | } elsif ($rest =~ s/^\`//) { | | 3243 | } elsif ($rest =~ s/^\`//) { |
3237 | $state = SWST_DQUOT_BACKT; | | 3244 | $state = SWST_DQUOT_BACKT; |
3238 | } elsif ($rest =~ s/^[^\$"\\\`]+//) { | | 3245 | } elsif ($rest =~ s/^[^\$"\\\`]+//) { |
3239 | } elsif ($rest =~ s/^\\(?:[\\\"\`]|\$\$)//) { | | 3246 | } elsif ($rest =~ s/^\\(?:[\\\"\`]|\$\$)//) { |
3240 | } elsif ($rest =~ s/^\$\$\{([0-9A-Za-z_]+)\}// | | 3247 | } elsif ($rest =~ s/^\$\$\{([0-9A-Za-z_]+)\}// |
3241 | || $rest =~ s/^\$\$([0-9A-Z_a-z]+|[!#?\@]|\$\$)//) { | | 3248 | || $rest =~ s/^\$\$([0-9A-Z_a-z]+|[!#?\@]|\$\$)//) { |
3242 | my ($shvarname) = ($1); | | 3249 | my ($shvarname) = ($1); |
3243 | $opt_debug_shell and $line->log_debug("[checkline_mk_shellword] Found double-quoted variable ${shvarname}."); | | 3250 | $opt_debug_shell and $line->log_debug("[checkline_mk_shellword] Found double-quoted variable ${shvarname}."); |
3244 | } elsif ($rest =~ s/^\$\$//) { | | 3251 | } elsif ($rest =~ s/^\$\$//) { |
3245 | $line->log_warning("Unquoted \$ or strange shell variable found."); | | 3252 | $line->log_warning("Unquoted \$ or strange shell variable found."); |
3246 | } elsif ($rest =~ s/^\\(.)//) { | | 3253 | } elsif ($rest =~ s/^\\(.)//) { |
3247 | my ($char) = ($1); | | 3254 | my ($char) = ($1); |
3248 | $line->log_warning("Please use \"\\\\${char}\" instead of \"\\${char}\"."); | | 3255 | $line->log_warning("Please use \"\\\\${char}\" instead of \"\\${char}\"."); |
3249 | $line->explain_warning( | | 3256 | $line->explain_warning( |
3250 | "Although the current code may work, it is not good style to rely on", | | 3257 | "Although the current code may work, it is not good style to rely on", |
3251 | "the shell passing \"\\${char}\" exactly as is, and not discarding the", | | 3258 | "the shell passing \"\\${char}\" exactly as is, and not discarding the", |
3252 | "backslash. Alternatively you can use single quotes instead of double", | | 3259 | "backslash. Alternatively you can use single quotes instead of double", |
3253 | "quotes."); | | 3260 | "quotes."); |
3254 | } else { | | 3261 | } else { |
3255 | last; | | 3262 | last; |
3256 | } | | 3263 | } |
3257 | | | 3264 | |
3258 | } else { | | 3265 | } else { |
3259 | last; | | 3266 | last; |
3260 | } | | 3267 | } |
3261 | } | | 3268 | } |
3262 | if ($rest !~ m"^\s*$") { | | 3269 | if ($rest !~ m"^\s*$") { |
3263 | $line->log_error("Internal pkglint error: " . statename->[$state] . ": rest=${rest}"); | | 3270 | $line->log_error("Internal pkglint error: " . statename->[$state] . ": rest=${rest}"); |
3264 | } | | 3271 | } |
3265 | } | | 3272 | } |
3266 | | | 3273 | |
3267 | # Some shell commands should not be used in the install phase. | | 3274 | # Some shell commands should not be used in the install phase. |
3268 | # | | 3275 | # |
3269 | sub checkline_mk_shellcmd_use($$) { | | 3276 | sub checkline_mk_shellcmd_use($$) { |
3270 | my ($line, $shellcmd) = @_; | | 3277 | my ($line, $shellcmd) = @_; |
3271 | | | 3278 | |
3272 | use constant allowed_install_commands => array_to_hash(qw( | | 3279 | use constant allowed_install_commands => array_to_hash(qw( |
3273 | ${INSTALL} | | 3280 | ${INSTALL} |
3274 | ${INSTALL_DATA} ${INSTALL_DATA_DIR} | | 3281 | ${INSTALL_DATA} ${INSTALL_DATA_DIR} |
3275 | ${INSTALL_LIB} ${INSTALL_LIB_DIR} | | 3282 | ${INSTALL_LIB} ${INSTALL_LIB_DIR} |
3276 | ${INSTALL_MAN} ${INSTALL_MAN_DIR} | | 3283 | ${INSTALL_MAN} ${INSTALL_MAN_DIR} |
3277 | ${INSTALL_PROGRAM} ${INSTALL_PROGRAM_DIR} | | 3284 | ${INSTALL_PROGRAM} ${INSTALL_PROGRAM_DIR} |
3278 | ${INSTALL_SCRIPT} | | 3285 | ${INSTALL_SCRIPT} |
3279 | ${LIBTOOL} | | 3286 | ${LIBTOOL} |
3280 | ${LN} | | 3287 | ${LN} |
3281 | ${PAX} | | 3288 | ${PAX} |
3282 | )); | | 3289 | )); |
3283 | use constant discouraged_install_commands => array_to_hash(qw( | | 3290 | use constant discouraged_install_commands => array_to_hash(qw( |
3284 | sed ${SED} | | 3291 | sed ${SED} |
3285 | tr ${TR} | | 3292 | tr ${TR} |
3286 | )); | | 3293 | )); |
3287 | | | 3294 | |
3288 | if (defined($mkctx_target) && $mkctx_target =~ m"^(?:pre|do|post)-install") { | | 3295 | if (defined($mkctx_target) && $mkctx_target =~ m"^(?:pre|do|post)-install") { |
3289 | | | 3296 | |
3290 | if (exists(allowed_install_commands->{$shellcmd})) { | | 3297 | if (exists(allowed_install_commands->{$shellcmd})) { |
3291 | # Fine. | | 3298 | # Fine. |
3292 | | | 3299 | |
3293 | } elsif (exists(discouraged_install_commands->{$shellcmd})) { | | 3300 | } elsif (exists(discouraged_install_commands->{$shellcmd})) { |
3294 | $line->log_warning("The shell command \"${shellcmd}\" should not be used in the install phase."); | | 3301 | $line->log_warning("The shell command \"${shellcmd}\" should not be used in the install phase."); |
3295 | $line->explain_warning( | | 3302 | $line->explain_warning( |
3296 | "In the install phase, the only thing that should be done is to install", | | 3303 | "In the install phase, the only thing that should be done is to install", |
3297 | "the prepared files to their final location. The file's contents should", | | 3304 | "the prepared files to their final location. The file's contents should", |
3298 | "not be changed anymore."); | | 3305 | "not be changed anymore."); |
3299 | | | 3306 | |
3300 | } elsif ($shellcmd eq "\${CP}") { | | 3307 | } elsif ($shellcmd eq "\${CP}") { |
3301 | $line->log_warning("\${CP} should not be used to install files."); | | 3308 | $line->log_warning("\${CP} should not be used to install files."); |
3302 | $line->explain_warning( | | 3309 | $line->explain_warning( |
3303 | "The \${CP} command is highly platform dependent and cannot overwrite", | | 3310 | "The \${CP} command is highly platform dependent and cannot overwrite", |
3304 | "files that don't have write permission. Please use \${PAX} instead.", | | 3311 | "files that don't have write permission. Please use \${PAX} instead.", |
3305 | "", | | 3312 | "", |
3306 | "For example, instead of", | | 3313 | "For example, instead of", |
3307 | "\t\${CP} -R \${WRKSRC}/* \${PREFIX}/foodir", | | 3314 | "\t\${CP} -R \${WRKSRC}/* \${PREFIX}/foodir", |
3308 | "you should use", | | 3315 | "you should use", |
3309 | "\tcd \${WRKSRC} && \${PAX} -wr * \${PREFIX}/foodir"); | | 3316 | "\tcd \${WRKSRC} && \${PAX} -wr * \${PREFIX}/foodir"); |
3310 | | | 3317 | |
3311 | } else { | | 3318 | } else { |
3312 | $opt_debug_misc and $line->log_debug("May \"${shellcmd}\" be used in the install phase?"); | | 3319 | $opt_debug_misc and $line->log_debug("May \"${shellcmd}\" be used in the install phase?"); |
3313 | } | | 3320 | } |
3314 | } | | 3321 | } |
3315 | } | | 3322 | } |
3316 | | | 3323 | |
3317 | sub checkline_mk_shelltext($$) { | | 3324 | sub checkline_mk_shelltext($$) { |
3318 | my ($line, $text) = @_; | | 3325 | my ($line, $text) = @_; |
3319 | my ($vartools, $state, $rest, $set_e_mode); | | 3326 | my ($vartools, $state, $rest, $set_e_mode); |
3320 | | | 3327 | |
3321 | $opt_debug_trace and $line->log_debug("checkline_mk_shelltext(\"$text\")"); | | 3328 | $opt_debug_trace and $line->log_debug("checkline_mk_shelltext(\"$text\")"); |
3322 | | | 3329 | |
3323 | # Note: SCST is the abbreviation for [S]hell [C]ommand [ST]ate. | | 3330 | # Note: SCST is the abbreviation for [S]hell [C]ommand [ST]ate. |
3324 | use constant scst => qw( | | 3331 | use constant scst => qw( |
3325 | START CONT | | 3332 | START CONT |
3326 | INSTALL INSTALL_D | | 3333 | INSTALL INSTALL_D |
3327 | MKDIR | | 3334 | MKDIR |
3328 | PAX PAX_S | | 3335 | PAX PAX_S |
3329 | SED SED_E | | 3336 | SED SED_E |
3330 | SET SET_CONT | | 3337 | SET SET_CONT |
3331 | COND COND_CONT | | 3338 | COND COND_CONT |
3332 | CASE CASE_IN CASE_LABEL CASE_LABEL_CONT CASE_PAREN | | 3339 | CASE CASE_IN CASE_LABEL CASE_LABEL_CONT CASE_PAREN |
3333 | FOR FOR_IN FOR_CONT | | 3340 | FOR FOR_IN FOR_CONT |
3334 | ECHO | | 3341 | ECHO |
3335 | INSTALL_DIR INSTALL_DIR2 | | 3342 | INSTALL_DIR INSTALL_DIR2 |
3336 | ); | | 3343 | ); |
3337 | use enum (":SCST_", scst); | | 3344 | use enum (":SCST_", scst); |
3338 | use constant scst_statename => [ map { $_ = "SCST_$_"; } scst ]; | | 3345 | use constant scst_statename => [ map { $_ = "SCST_$_"; } scst ]; |
3339 | | | 3346 | |
3340 | use constant forbidden_commands => array_to_hash(qw( | | 3347 | use constant forbidden_commands => array_to_hash(qw( |
3341 | ktrace | | 3348 | ktrace |
3342 | mktexlsr | | 3349 | mktexlsr |
3343 | strace | | 3350 | strace |
3344 | texconfig truss | | 3351 | texconfig truss |
3345 | )); | | 3352 | )); |
3346 | | | 3353 | |
3347 | if ($text =~ m"\$\{SED\}" && $text =~ m"\$\{MV\}") { | | 3354 | if ($text =~ m"\$\{SED\}" && $text =~ m"\$\{MV\}") { |
3348 | $line->log_note("Please use the SUBST framework instead of \${SED} and \${MV}."); | | 3355 | $line->log_note("Please use the SUBST framework instead of \${SED} and \${MV}."); |
3349 | $line->explain_note( | | 3356 | $line->explain_note( |
3350 | "When converting things, pay attention to \"#\" characters. In shell", | | 3357 | "When converting things, pay attention to \"#\" characters. In shell", |
3351 | "commands make(1) does not interpret them as comment character, but", | | 3358 | "commands make(1) does not interpret them as comment character, but", |
3352 | "in other lines it does. Therefore, instead of the shell command", | | 3359 | "in other lines it does. Therefore, instead of the shell command", |
3353 | "", | | 3360 | "", |
3354 | "\tsed -e 's,#define foo,,'", | | 3361 | "\tsed -e 's,#define foo,,'", |
3355 | "", | | 3362 | "", |
3356 | "you need to write", | | 3363 | "you need to write", |
3357 | "", | | 3364 | "", |
3358 | "\tSUBST_SED.foo+=\t's,\\#define foo,,'"); | | 3365 | "\tSUBST_SED.foo+=\t's,\\#define foo,,'"); |
3359 | } | | 3366 | } |
3360 | | | 3367 | |
3361 | if ($text =~ m"^\@*-(.*(MKDIR|INSTALL.*-d|INSTALL_.*_DIR).*)") { | | 3368 | if ($text =~ m"^\@*-(.*(MKDIR|INSTALL.*-d|INSTALL_.*_DIR).*)") { |
3362 | my ($mkdir_cmd) = ($1); | | 3369 | my ($mkdir_cmd) = ($1); |
3363 | | | 3370 | |
3364 | $line->log_note("You don't need to use \"-\" before ${mkdir_cmd}."); | | 3371 | $line->log_note("You don't need to use \"-\" before ${mkdir_cmd}."); |
3365 | } | | 3372 | } |
3366 | | | 3373 | |
3367 | $vartools = get_vartool_names(); | | 3374 | $vartools = get_vartool_names(); |
3368 | $rest = $text; | | 3375 | $rest = $text; |
3369 | | | 3376 | |
3370 | use constant hidden_shell_commands => array_to_hash(qw( | | 3377 | use constant hidden_shell_commands => array_to_hash(qw( |
3371 | ${DELAYED_ERROR_MSG} ${DELAYED_WARNING_MSG} | | 3378 | ${DELAYED_ERROR_MSG} ${DELAYED_WARNING_MSG} |
3372 | ${DO_NADA} | | 3379 | ${DO_NADA} |
3373 | ${ECHO} ${ECHO_MSG} ${ECHO_N} ${ERROR_CAT} ${ERROR_MSG} | | 3380 | ${ECHO} ${ECHO_MSG} ${ECHO_N} ${ERROR_CAT} ${ERROR_MSG} |
3374 | ${FAIL_MSG} | | 3381 | ${FAIL_MSG} |
3375 | ${PHASE_MSG} ${PRINTF} | | 3382 | ${PHASE_MSG} ${PRINTF} |
3376 | ${SHCOMMENT} ${STEP_MSG} | | 3383 | ${SHCOMMENT} ${STEP_MSG} |
3377 | ${WARNING_CAT} ${WARNING_MSG} | | 3384 | ${WARNING_CAT} ${WARNING_MSG} |
3378 | )); | | 3385 | )); |
3379 | | | 3386 | |
3380 | $set_e_mode = false; | | 3387 | $set_e_mode = false; |
3381 | | | 3388 | |
3382 | if ($rest =~ s/^\s*([-@]*)(\$\{_PKG_SILENT\}\$\{_PKG_DEBUG\}|\$\{RUN\}|)//) { | | 3389 | if ($rest =~ s/^\s*([-@]*)(\$\{_PKG_SILENT\}\$\{_PKG_DEBUG\}|\$\{RUN\}|)//) { |
3383 | my ($hidden, $macro) = ($1, $2); | | 3390 | my ($hidden, $macro) = ($1, $2); |
3384 | | | 3391 | |
3385 | if ($hidden !~ m"\@") { | | 3392 | if ($hidden !~ m"\@") { |
3386 | # Nothing is hidden at all. | | 3393 | # Nothing is hidden at all. |
3387 | | | 3394 | |
3388 | } elsif (defined($mkctx_target) && $mkctx_target =~ m"^(?:show-.*|.*-message)$") { | | 3395 | } elsif (defined($mkctx_target) && $mkctx_target =~ m"^(?:show-.*|.*-message)$") { |
3389 | # In some targets commands may be hidden. | | 3396 | # In some targets commands may be hidden. |
3390 | | | 3397 | |
3391 | } elsif ($rest =~ m"^#") { | | 3398 | } elsif ($rest =~ m"^#") { |
3392 | # Shell comments may be hidden, as they have no side effects | | 3399 | # Shell comments may be hidden, as they have no side effects |
3393 | | | 3400 | |
3394 | } elsif ($rest =~ $regex_shellword) { | | 3401 | } elsif ($rest =~ $regex_shellword) { |
3395 | my ($cmd) = ($1); | | 3402 | my ($cmd) = ($1); |
3396 | | | 3403 | |
3397 | if (!exists(hidden_shell_commands->{$cmd})) { | | 3404 | if (!exists(hidden_shell_commands->{$cmd})) { |
3398 | $line->log_warning("The shell command \"${cmd}\" should not be hidden."); | | 3405 | $line->log_warning("The shell command \"${cmd}\" should not be hidden."); |
3399 | $line->explain_warning( | | 3406 | $line->explain_warning( |
3400 | "Hidden shell commands do not appear on the terminal or in the log file", | | 3407 | "Hidden shell commands do not appear on the terminal or in the log file", |
3401 | "when they are executed. When they fail, the error message cannot be", | | 3408 | "when they are executed. When they fail, the error message cannot be", |
3402 | "assigned to the command, which is very difficult to debug."); | | 3409 | "assigned to the command, which is very difficult to debug."); |
3403 | } | | 3410 | } |
3404 | } | | 3411 | } |
3405 | | | 3412 | |
3406 | if ($hidden =~ m"-") { | | 3413 | if ($hidden =~ m"-") { |
3407 | $line->log_warning("The use of a leading \"-\" to suppress errors is deprecated."); | | 3414 | $line->log_warning("The use of a leading \"-\" to suppress errors is deprecated."); |
3408 | $line->explain_warning( | | 3415 | $line->explain_warning( |
3409 | "If you really want to ignore any errors from this command (including", | | 3416 | "If you really want to ignore any errors from this command (including", |
3410 | "all errors you never thought of), append \"|| \${TRUE}\" to the", | | 3417 | "all errors you never thought of), append \"|| \${TRUE}\" to the", |
3411 | "command."); | | 3418 | "command."); |
3412 | } | | 3419 | } |
3413 | | | 3420 | |
3414 | if ($macro eq "\${RUN}") { | | 3421 | if ($macro eq "\${RUN}") { |
3415 | $set_e_mode = true; | | 3422 | $set_e_mode = true; |
3416 | } | | 3423 | } |
3417 | } | | 3424 | } |
3418 | | | 3425 | |
3419 | $state = SCST_START; | | 3426 | $state = SCST_START; |
3420 | while ($rest =~ s/^$regex_shellword//) { | | 3427 | while ($rest =~ s/^$regex_shellword//) { |
3421 | my ($shellword) = ($1); | | 3428 | my ($shellword) = ($1); |
3422 | | | 3429 | |
3423 | $opt_debug_shell and $line->log_debug(scst_statename->[$state] . ": ${shellword}"); | | 3430 | $opt_debug_shell and $line->log_debug(scst_statename->[$state] . ": ${shellword}"); |
3424 | | | 3431 | |
3425 | checkline_mk_shellword($line, $shellword, !( | | 3432 | checkline_mk_shellword($line, $shellword, !( |
3426 | $state == SCST_CASE | | 3433 | $state == SCST_CASE |
3427 | || $state == SCST_FOR_CONT | | 3434 | || $state == SCST_FOR_CONT |
3428 | || $state == SCST_SET_CONT | | 3435 | || $state == SCST_SET_CONT |
3429 | || ($state == SCST_START && $shellword =~ regex_sh_varassign))); | | 3436 | || ($state == SCST_START && $shellword =~ regex_sh_varassign))); |
3430 | | | 3437 | |
3431 | # | | 3438 | # |
3432 | # Actions associated with the current state | | 3439 | # Actions associated with the current state |
3433 | # and the symbol on the "input tape". | | 3440 | # and the symbol on the "input tape". |
3434 | # | | 3441 | # |
3435 | | | 3442 | |
3436 | if ($state == SCST_START || $state == SCST_COND) { | | 3443 | if ($state == SCST_START || $state == SCST_COND) { |
3437 | my ($type); | | 3444 | my ($type); |
3438 | | | 3445 | |
3439 | if ($shellword eq "\${RUN}") { | | 3446 | if ($shellword eq "\${RUN}") { |
3440 | # Just skip this one. | | 3447 | # Just skip this one. |
3441 | | | 3448 | |
3442 | } elsif (exists(forbidden_commands->{basename($shellword)})) { | | 3449 | } elsif (exists(forbidden_commands->{basename($shellword)})) { |
3443 | $line->log_error("${shellword} must not be used in Makefiles."); | | 3450 | $line->log_error("${shellword} must not be used in Makefiles."); |
3444 | $line->explain_error( | | 3451 | $line->explain_error( |
3445 | "This command must appear in INSTALL scripts, not in the package", | | 3452 | "This command must appear in INSTALL scripts, not in the package", |
3446 | "Makefile, so that the package also works if it is installed as a binary", | | 3453 | "Makefile, so that the package also works if it is installed as a binary", |
3447 | "package via pkg_add."); | | 3454 | "package via pkg_add."); |
3448 | | | 3455 | |
3449 | } elsif (exists(get_tool_names()->{$shellword})) { | | 3456 | } elsif (exists(get_tool_names()->{$shellword})) { |
3450 | if (!exists($mkctx_tools->{$shellword}) && !exists($mkctx_tools->{"g$shellword"})) { | | 3457 | if (!exists($mkctx_tools->{$shellword}) && !exists($mkctx_tools->{"g$shellword"})) { |
3451 | $line->log_warning("The \"${shellword}\" tool is used but not added to USE_TOOLS."); | | 3458 | $line->log_warning("The \"${shellword}\" tool is used but not added to USE_TOOLS."); |
3452 | } | | 3459 | } |
3453 | | | 3460 | |
3454 | if (exists(get_required_vartools()->{$shellword})) { | | 3461 | if (exists(get_required_vartools()->{$shellword})) { |
3455 | $line->log_warning("Please use \"\${" . get_vartool_names()->{$shellword} . "}\" instead of \"${shellword}\"."); | | 3462 | $line->log_warning("Please use \"\${" . get_vartool_names()->{$shellword} . "}\" instead of \"${shellword}\"."); |
3456 | } | | 3463 | } |
3457 | | | 3464 | |
3458 | checkline_mk_shellcmd_use($line, $shellword); | | 3465 | checkline_mk_shellcmd_use($line, $shellword); |
3459 | | | 3466 | |
3460 | } elsif ($shellword =~ m"^\$\{([\w_]+)\}$" && exists(get_varname_to_toolname()->{$1})) { | | 3467 | } elsif ($shellword =~ m"^\$\{([\w_]+)\}$" && exists(get_varname_to_toolname()->{$1})) { |
3461 | my ($vartool) = ($1); | | 3468 | my ($vartool) = ($1); |
3462 | my $plain_tool = get_varname_to_toolname()->{$vartool}; | | 3469 | my $plain_tool = get_varname_to_toolname()->{$vartool}; |
3463 | | | 3470 | |
3464 | if (!exists($mkctx_tools->{$plain_tool})) { | | 3471 | if (!exists($mkctx_tools->{$plain_tool})) { |
3465 | $line->log_warning("The \"${plain_tool}\" tool is used but not added to USE_TOOLS."); | | 3472 | $line->log_warning("The \"${plain_tool}\" tool is used but not added to USE_TOOLS."); |
3466 | } | | 3473 | } |
3467 | | | 3474 | |
3468 | # Deactivated to allow package developers to write | | 3475 | # Deactivated to allow package developers to write |
3469 | # consistent code that uses ${TOOL} in all places. | | 3476 | # consistent code that uses ${TOOL} in all places. |
3470 | if (false && defined($mkctx_target) && $mkctx_target =~ m"^(?:pre|do|post)-(?:extract|patch|wrapper|configure|build|install|package|clean)$") { | | 3477 | if (false && defined($mkctx_target) && $mkctx_target =~ m"^(?:pre|do|post)-(?:extract|patch|wrapper|configure|build|install|package|clean)$") { |
3471 | if (!exists(get_required_vartool_varnames()->{$vartool})) { | | 3478 | if (!exists(get_required_vartool_varnames()->{$vartool})) { |
3472 | $opt_warn_extra and $line->log_note("You can write \"${plain_tool}\" instead of \"${shellword}\"."); | | 3479 | $opt_warn_extra and $line->log_note("You can write \"${plain_tool}\" instead of \"${shellword}\"."); |
3473 | $opt_warn_extra and $line->explain_note( | | 3480 | $opt_warn_extra and $line->explain_note( |
3474 | "The wrapper framework from pkgsrc takes care that a sufficiently", | | 3481 | "The wrapper framework from pkgsrc takes care that a sufficiently", |
3475 | "capable implementation of that tool will be selected.", | | 3482 | "capable implementation of that tool will be selected.", |
3476 | "", | | 3483 | "", |
3477 | "Calling the commands by their plain name instead of the macros is", | | 3484 | "Calling the commands by their plain name instead of the macros is", |
3478 | "only available in the {pre,do,post}-* targets. For all other targets,", | | 3485 | "only available in the {pre,do,post}-* targets. For all other targets,", |
3479 | "you should still use the macros."); | | 3486 | "you should still use the macros."); |
3480 | } | | 3487 | } |
3481 | } | | 3488 | } |
3482 | | | 3489 | |
3483 | checkline_mk_shellcmd_use($line, $shellword); | | 3490 | checkline_mk_shellcmd_use($line, $shellword); |
3484 | | | 3491 | |
3485 | } elsif ($shellword =~ m"^\$\{([\w_]+)\}$" && defined($type = get_variable_type($line, $1)) && $type->basic_type eq "ShellCommand") { | | 3492 | } elsif ($shellword =~ m"^\$\{([\w_]+)\}$" && defined($type = get_variable_type($line, $1)) && $type->basic_type eq "ShellCommand") { |
3486 | checkline_mk_shellcmd_use($line, $shellword); | | 3493 | checkline_mk_shellcmd_use($line, $shellword); |
3487 | | | 3494 | |
3488 | } elsif ($shellword =~ m"^\$\{(\w+)\}$" && defined($pkgctx_vardef) && exists($pkgctx_vardef->{$1})) { | | 3495 | } elsif ($shellword =~ m"^\$\{(\w+)\}$" && defined($pkgctx_vardef) && exists($pkgctx_vardef->{$1})) { |
3489 | # When the package author has explicitly | | 3496 | # When the package author has explicitly |
3490 | # defined a command variable, assume it | | 3497 | # defined a command variable, assume it |
3491 | # to be valid. | | 3498 | # to be valid. |
3492 | | | 3499 | |
3493 | } elsif ($shellword =~ m"^(?:\(|\)|:|;|;;|&&|\|\||\{|\}|break|case|cd|continue|do|done|elif|else|esac|eval|exec|exit|export|fi|for|if|read|set|shift|then|umask|unset|while)$") { | | 3500 | } elsif ($shellword =~ m"^(?:\(|\)|:|;|;;|&&|\|\||\{|\}|break|case|cd|continue|do|done|elif|else|esac|eval|exec|exit|export|fi|for|if|read|set|shift|then|umask|unset|while)$") { |
3494 | # Shell builtins are fine. | | 3501 | # Shell builtins are fine. |
3495 | | | 3502 | |
3496 | } elsif ($shellword =~ m"^[\w_]+=.*$") { | | 3503 | } elsif ($shellword =~ m"^[\w_]+=.*$") { |
3497 | # Variable assignment. | | 3504 | # Variable assignment. |
3498 | | | 3505 | |
3499 | } elsif ($shellword =~ m"^\./.*$") { | | 3506 | } elsif ($shellword =~ m"^\./.*$") { |
3500 | # All commands from the current directory are fine. | | 3507 | # All commands from the current directory are fine. |
3501 | | | 3508 | |
3502 | } elsif ($shellword =~ m"^#") { | | 3509 | } elsif ($shellword =~ m"^#") { |
3503 | my $semicolon = ($shellword =~ m";"); | | 3510 | my $semicolon = ($shellword =~ m";"); |
3504 | my $multiline = ($line->lines =~ m"--"); | | 3511 | my $multiline = ($line->lines =~ m"--"); |
3505 | | | 3512 | |
3506 | if ($semicolon) { | | 3513 | if ($semicolon) { |
3507 | $line->log_warning("A shell comment should not contain semicolons."); | | 3514 | $line->log_warning("A shell comment should not contain semicolons."); |
3508 | } | | 3515 | } |
3509 | if ($multiline) { | | 3516 | if ($multiline) { |
3510 | $line->log_warning("A shell comment does not stop at the end of line."); | | 3517 | $line->log_warning("A shell comment does not stop at the end of line."); |
3511 | } | | 3518 | } |
3512 | | | 3519 | |
3513 | if ($semicolon || $multiline) { | | 3520 | if ($semicolon || $multiline) { |
3514 | $line->explain_warning( | | 3521 | $line->explain_warning( |
3515 | "When you split a shell command into multiple lines that are continued", | | 3522 | "When you split a shell command into multiple lines that are continued", |
3516 | "with a backslash, they will nevertheless be converted to a single line", | | 3523 | "with a backslash, they will nevertheless be converted to a single line", |
3517 | "before the shell sees them. That means that even if it _looks_ like that", | | 3524 | "before the shell sees them. That means that even if it _looks_ like that", |
3518 | "the comment only spans one line in the Makefile, in fact it spans until", | | 3525 | "the comment only spans one line in the Makefile, in fact it spans until", |
3519 | "the end of the whole shell command. To insert a comment into shell code,", | | 3526 | "the end of the whole shell command. To insert a comment into shell code,", |
3520 | "you can pass it as an argument to the \${SHCOMMENT} macro, which expands", | | 3527 | "you can pass it as an argument to the \${SHCOMMENT} macro, which expands", |
3521 | "to a command doing nothing. Note that any special characters are", | | 3528 | "to a command doing nothing. Note that any special characters are", |
3522 | "nevertheless interpreted by the shell."); | | 3529 | "nevertheless interpreted by the shell."); |
3523 | } | | 3530 | } |
3524 | | | 3531 | |
3525 | } else { | | 3532 | } else { |
3526 | $opt_warn_extra and $line->log_warning("Unknown shell command \"${shellword}\"."); | | 3533 | $opt_warn_extra and $line->log_warning("Unknown shell command \"${shellword}\"."); |
3527 | $opt_warn_extra and $line->explain_warning( | | 3534 | $opt_warn_extra and $line->explain_warning( |
3528 | "If you want your package to be portable to all platforms that pkgsrc", | | 3535 | "If you want your package to be portable to all platforms that pkgsrc", |
3529 | "supports, you should only use shell commands that are covered by the", | | 3536 | "supports, you should only use shell commands that are covered by the", |
3530 | "tools framework."); | | 3537 | "tools framework."); |
3531 | | | 3538 | |
3532 | } | | 3539 | } |
3533 | } | | 3540 | } |
3534 | | | 3541 | |
3535 | if ($state == SCST_COND && $shellword eq "cd") { | | 3542 | if ($state == SCST_COND && $shellword eq "cd") { |
3536 | $line->log_error("The Solaris /bin/sh cannot handle \"cd\" inside conditionals."); | | 3543 | $line->log_error("The Solaris /bin/sh cannot handle \"cd\" inside conditionals."); |
3537 | $line->explain_error( | | 3544 | $line->explain_error( |
3538 | "When the Solaris shell is in \"set -e\" mode and \"cd\" fails, the", | | 3545 | "When the Solaris shell is in \"set -e\" mode and \"cd\" fails, the", |
3539 | "shell will exit, no matter if it is protected by an \"if\" or the", | | 3546 | "shell will exit, no matter if it is protected by an \"if\" or the", |
3540 | "\"||\" operator."); | | 3547 | "\"||\" operator."); |
3541 | } | | 3548 | } |
3542 | | | 3549 | |
3543 | if (($state != SCST_PAX_S && $state != SCST_SED_E && $state != SCST_CASE_LABEL)) { | | 3550 | if (($state != SCST_PAX_S && $state != SCST_SED_E && $state != SCST_CASE_LABEL)) { |
3544 | checkline_mk_absolute_pathname($line, $shellword); | | 3551 | checkline_mk_absolute_pathname($line, $shellword); |
3545 | } | | 3552 | } |
3546 | | | 3553 | |
3547 | if (($state == SCST_INSTALL_D || $state == SCST_MKDIR) && $shellword =~ m"^(?:\$\{DESTDIR\})?\$\{PREFIX(?:|:Q)\}/") { | | 3554 | if (($state == SCST_INSTALL_D || $state == SCST_MKDIR) && $shellword =~ m"^(?:\$\{DESTDIR\})?\$\{PREFIX(?:|:Q)\}/") { |
3548 | $line->log_warning("Please use AUTO_MKDIRS instead of " | | 3555 | $line->log_warning("Please use AUTO_MKDIRS instead of " |
3549 | . (($state == SCST_MKDIR) ? "\${MKDIR}" : "\${INSTALL} -d") | | 3556 | . (($state == SCST_MKDIR) ? "\${MKDIR}" : "\${INSTALL} -d") |
3550 | . "."); | | 3557 | . "."); |
3551 | $line->explain_warning( | | 3558 | $line->explain_warning( |
3552 | "Setting AUTO_MKDIRS=yes automatically creates all directories that are", | | 3559 | "Setting AUTO_MKDIRS=yes automatically creates all directories that are", |
3553 | "mentioned in the PLIST. If you need additional directories, specify", | | 3560 | "mentioned in the PLIST. If you need additional directories, specify", |
3554 | "them in INSTALLATION_DIRS, which is a list of directories relative to", | | 3561 | "them in INSTALLATION_DIRS, which is a list of directories relative to", |
3555 | "\${PREFIX}."); | | 3562 | "\${PREFIX}."); |
3556 | } | | 3563 | } |
3557 | | | 3564 | |
3558 | if (($state == SCST_INSTALL_DIR || $state == SCST_INSTALL_DIR2) && $shellword !~ regex_mk_shellvaruse && $shellword =~ m"^(?:\${DESTDIR\})?\$\{PREFIX(?:|:Q)\}/(.*)") { | | 3565 | if (($state == SCST_INSTALL_DIR || $state == SCST_INSTALL_DIR2) && $shellword !~ regex_mk_shellvaruse && $shellword =~ m"^(?:\${DESTDIR\})?\$\{PREFIX(?:|:Q)\}/(.*)") { |
3559 | my ($dirname) = ($1); | | 3566 | my ($dirname) = ($1); |
3560 | | | 3567 | |
3561 | $line->log_note("You can use AUTO_MKDIRS=yes or INSTALLATION_DIRS+= ${dirname} instead of this command."); | | 3568 | $line->log_note("You can use AUTO_MKDIRS=yes or INSTALLATION_DIRS+= ${dirname} instead of this command."); |
3562 | $line->explain_note( | | 3569 | $line->explain_note( |
3563 | "This saves you some typing. You also don't have to think about which of", | | 3570 | "This saves you some typing. You also don't have to think about which of", |
3564 | "the many INSTALL_*_DIR macros is appropriate, since INSTALLATION_DIRS", | | 3571 | "the many INSTALL_*_DIR macros is appropriate, since INSTALLATION_DIRS", |
3565 | "takes care of that.", | | 3572 | "takes care of that.", |
3566 | "", | | 3573 | "", |
3567 | "Note that you should only do this if the package creates _all_", | | 3574 | "Note that you should only do this if the package creates _all_", |
3568 | "directories it needs before trying to install files into them.", | | 3575 | "directories it needs before trying to install files into them.", |
3569 | "", | | 3576 | "", |
3570 | "Many packages include a list of all needed directories in their PLIST", | | 3577 | "Many packages include a list of all needed directories in their PLIST", |
3571 | "file. In that case, you can just set AUTO_MKDIRS=yes and be done."); | | 3578 | "file. In that case, you can just set AUTO_MKDIRS=yes and be done."); |
3572 | } | | 3579 | } |
3573 | | | 3580 | |
3574 | if ($state == SCST_INSTALL_DIR2 && $shellword =~ m"^\$") { | | 3581 | if ($state == SCST_INSTALL_DIR2 && $shellword =~ m"^\$") { |
3575 | $line->log_warning("The INSTALL_*_DIR commands can only handle one directory at a time."); | | 3582 | $line->log_warning("The INSTALL_*_DIR commands can only handle one directory at a time."); |
3576 | $line->explain_warning( | | 3583 | $line->explain_warning( |
3577 | "Many implementations of install(1) can handle more, but pkgsrc aims at", | | 3584 | "Many implementations of install(1) can handle more, but pkgsrc aims at", |
3578 | "maximum portability."); | | 3585 | "maximum portability."); |
3579 | } | | 3586 | } |
3580 | | | 3587 | |
3581 | if ($state == SCST_PAX && $shellword eq "-pe") { | | 3588 | if ($state == SCST_PAX && $shellword eq "-pe") { |
3582 | $line->log_warning("Please use the -pp option to pax(1) instead of -pe."); | | 3589 | $line->log_warning("Please use the -pp option to pax(1) instead of -pe."); |
3583 | $line->explain_warning( | | 3590 | $line->explain_warning( |
3584 | "The -pe option tells pax to preserve the ownership of the files, which", | | 3591 | "The -pe option tells pax to preserve the ownership of the files, which", |
3585 | "means that the installed files will belong to the user that has built", | | 3592 | "means that the installed files will belong to the user that has built", |
3586 | "the package. That's a Bad Thing."); | | 3593 | "the package. That's a Bad Thing."); |
3587 | } | | 3594 | } |
3588 | | | 3595 | |
3589 | if ($state == SCST_PAX_S || $state == SCST_SED_E) { | | 3596 | if ($state == SCST_PAX_S || $state == SCST_SED_E) { |
3590 | if (false && $shellword !~ m"^[\"\'].*[\"\']$") { | | 3597 | if (false && $shellword !~ m"^[\"\'].*[\"\']$") { |
3591 | $line->log_warning("Substitution commands like \"${shellword}\" should always be quoted."); | | 3598 | $line->log_warning("Substitution commands like \"${shellword}\" should always be quoted."); |
3592 | $line->explain_warning( | | 3599 | $line->explain_warning( |
3593 | "Usually these substitution commands contain characters like '*' or", | | 3600 | "Usually these substitution commands contain characters like '*' or", |
3594 | "other shell metacharacters that might lead to lookup of matching", | | 3601 | "other shell metacharacters that might lead to lookup of matching", |
3595 | "filenames and then expand to more than one word."); | | 3602 | "filenames and then expand to more than one word."); |
3596 | } | | 3603 | } |
3597 | } | | 3604 | } |
3598 | | | 3605 | |
3599 | if ($state == SCST_ECHO && $shellword eq "-n") { | | 3606 | if ($state == SCST_ECHO && $shellword eq "-n") { |
3600 | $line->log_warning("Please use \${ECHO_N} instead of \"echo -n\"."); | | 3607 | $line->log_warning("Please use \${ECHO_N} instead of \"echo -n\"."); |
3601 | } | | 3608 | } |
3602 | | | 3609 | |
3603 | if ($opt_warn_extra && $state != SCST_CASE_LABEL_CONT && $shellword eq "|") { | | 3610 | if ($opt_warn_extra && $state != SCST_CASE_LABEL_CONT && $shellword eq "|") { |
3604 | $line->log_warning("The exitcode of the left-hand-side command of the pipe operator is ignored."); | | 3611 | $line->log_warning("The exitcode of the left-hand-side command of the pipe operator is ignored."); |
3605 | $line->explain_warning( | | 3612 | $line->explain_warning( |
3606 | "If you need to detect the failure of the left-hand-side command, use", | | 3613 | "If you need to detect the failure of the left-hand-side command, use", |
3607 | "temporary files to save the output of the command."); | | 3614 | "temporary files to save the output of the command."); |
3608 | } | | 3615 | } |
3609 | | | 3616 | |
3610 | if ($opt_warn_extra && $shellword eq ";" && $state != SCST_COND_CONT && $state != SCST_FOR_CONT && !$set_e_mode) { | | 3617 | if ($opt_warn_extra && $shellword eq ";" && $state != SCST_COND_CONT && $state != SCST_FOR_CONT && !$set_e_mode) { |
3611 | $line->log_warning("Please switch to \"set -e\" mode before using a semicolon to separate commands."); | | 3618 | $line->log_warning("Please switch to \"set -e\" mode before using a semicolon to separate commands."); |
3612 | $line->explain_warning( | | 3619 | $line->explain_warning( |
3613 | "Older versions of the NetBSD make(1) had run the shell commands using", | | 3620 | "Older versions of the NetBSD make(1) had run the shell commands using", |
3614 | "the \"-e\" option of /bin/sh. In 2004, this behavior has been changed to", | | 3621 | "the \"-e\" option of /bin/sh. In 2004, this behavior has been changed to", |
3615 | "follow the POSIX conventions, which is to not use the \"-e\" option.", | | 3622 | "follow the POSIX conventions, which is to not use the \"-e\" option.", |
3616 | "The consequence of this change is that shell programs don't terminate", | | 3623 | "The consequence of this change is that shell programs don't terminate", |
3617 | "as soon as an error occurs, but try to continue with the next command.", | | 3624 | "as soon as an error occurs, but try to continue with the next command.", |
3618 | "Imagine what would happen for these commands:", | | 3625 | "Imagine what would happen for these commands:", |
3619 | " cd \"\$HOME\"; cd /nonexistent; rm -rf *", | | 3626 | " cd \"\$HOME\"; cd /nonexistent; rm -rf *", |
3620 | "To fix this warning, either insert \"set -e\" at the beginning of this", | | 3627 | "To fix this warning, either insert \"set -e\" at the beginning of this", |
3621 | "line or use the \"&&\" operator instead of the semicolon."); | | 3628 | "line or use the \"&&\" operator instead of the semicolon."); |
3622 | } | | 3629 | } |
3623 | | | 3630 | |
3624 | # | | 3631 | # |
3625 | # State transition. | | 3632 | # State transition. |
3626 | # | | 3633 | # |
3627 | | | 3634 | |
3628 | if ($state == SCST_SET && $shellword =~ m"^-.*e") { | | 3635 | if ($state == SCST_SET && $shellword =~ m"^-.*e") { |
3629 | $set_e_mode = true; | | 3636 | $set_e_mode = true; |
3630 | } | | 3637 | } |
3631 | if ($state == SCST_START && $shellword eq "\${RUN}") { | | 3638 | if ($state == SCST_START && $shellword eq "\${RUN}") { |
3632 | $set_e_mode = true; | | 3639 | $set_e_mode = true; |
3633 | } | | 3640 | } |
3634 | | | 3641 | |
3635 | $state = ($shellword eq ";;") ? SCST_CASE_LABEL | | 3642 | $state = ($shellword eq ";;") ? SCST_CASE_LABEL |
3636 | # Note: The order of the following two lines is important. | | 3643 | # Note: The order of the following two lines is important. |
3637 | : ($state == SCST_CASE_LABEL_CONT && $shellword eq "|") ? SCST_CASE_LABEL | | 3644 | : ($state == SCST_CASE_LABEL_CONT && $shellword eq "|") ? SCST_CASE_LABEL |
3638 | : ($shellword =~ m"^[;&\|]+$") ? SCST_START | | 3645 | : ($shellword =~ m"^[;&\|]+$") ? SCST_START |
3639 | : ($state == SCST_START) ? ( | | 3646 | : ($state == SCST_START) ? ( |
3640 | ($shellword eq "\${INSTALL}") ? SCST_INSTALL | | 3647 | ($shellword eq "\${INSTALL}") ? SCST_INSTALL |
3641 | : ($shellword eq "\${MKDIR}") ? SCST_MKDIR | | 3648 | : ($shellword eq "\${MKDIR}") ? SCST_MKDIR |
3642 | : ($shellword eq "\${PAX}") ? SCST_PAX | | 3649 | : ($shellword eq "\${PAX}") ? SCST_PAX |
3643 | : ($shellword eq "\${SED}") ? SCST_SED | | 3650 | : ($shellword eq "\${SED}") ? SCST_SED |
3644 | : ($shellword eq "\${ECHO}") ? SCST_ECHO | | 3651 | : ($shellword eq "\${ECHO}") ? SCST_ECHO |
3645 | : ($shellword eq "\${RUN}") ? SCST_START | | 3652 | : ($shellword eq "\${RUN}") ? SCST_START |
3646 | : ($shellword eq "echo") ? SCST_ECHO | | 3653 | : ($shellword eq "echo") ? SCST_ECHO |
3647 | : ($shellword eq "set") ? SCST_SET | | 3654 | : ($shellword eq "set") ? SCST_SET |
3648 | : ($shellword =~ m"^(?:if|elif|while)$") ? SCST_COND | | 3655 | : ($shellword =~ m"^(?:if|elif|while)$") ? SCST_COND |
3649 | : ($shellword =~ m"^(?:then|else|do)$") ? SCST_START | | 3656 | : ($shellword =~ m"^(?:then|else|do)$") ? SCST_START |
3650 | : ($shellword eq "case") ? SCST_CASE | | 3657 | : ($shellword eq "case") ? SCST_CASE |
3651 | : ($shellword eq "for") ? SCST_FOR | | 3658 | : ($shellword eq "for") ? SCST_FOR |
3652 | : ($shellword eq "(") ? SCST_START | | 3659 | : ($shellword eq "(") ? SCST_START |
3653 | : ($shellword =~ m"^\$\{INSTALL_[A-Z]+_DIR\}$") ? SCST_INSTALL_DIR | | 3660 | : ($shellword =~ m"^\$\{INSTALL_[A-Z]+_DIR\}$") ? SCST_INSTALL_DIR |
3654 | : ($shellword =~ regex_sh_varassign) ? SCST_START | | 3661 | : ($shellword =~ regex_sh_varassign) ? SCST_START |
3655 | : SCST_CONT) | | 3662 | : SCST_CONT) |
3656 | : ($state == SCST_MKDIR) ? SCST_MKDIR | | 3663 | : ($state == SCST_MKDIR) ? SCST_MKDIR |
3657 | : ($state == SCST_INSTALL && $shellword eq "-d") ? SCST_INSTALL_D | | 3664 | : ($state == SCST_INSTALL && $shellword eq "-d") ? SCST_INSTALL_D |
3658 | : ($state == SCST_INSTALL || $state == SCST_INSTALL_D) ? ( | | 3665 | : ($state == SCST_INSTALL || $state == SCST_INSTALL_D) ? ( |
3659 | ($shellword =~ m"^-[ogm]$") ? SCST_CONT | | 3666 | ($shellword =~ m"^-[ogm]$") ? SCST_CONT |
3660 | : $state) | | 3667 | : $state) |
3661 | : ($state == SCST_INSTALL_DIR) ? ( | | 3668 | : ($state == SCST_INSTALL_DIR) ? ( |
3662 | ($shellword =~ m"^-") ? SCST_CONT | | 3669 | ($shellword =~ m"^-") ? SCST_CONT |
3663 | : ($shellword =~ m"^\$") ? SCST_INSTALL_DIR2 | | 3670 | : ($shellword =~ m"^\$") ? SCST_INSTALL_DIR2 |
3664 | : $state) | | 3671 | : $state) |
3665 | : ($state == SCST_INSTALL_DIR2) ? $state | | 3672 | : ($state == SCST_INSTALL_DIR2) ? $state |
3666 | : ($state == SCST_PAX) ? ( | | 3673 | : ($state == SCST_PAX) ? ( |
3667 | ($shellword eq "-s") ? SCST_PAX_S | | 3674 | ($shellword eq "-s") ? SCST_PAX_S |
3668 | : ($shellword =~ m"^-") ? SCST_PAX | | 3675 | : ($shellword =~ m"^-") ? SCST_PAX |
3669 | : SCST_CONT) | | 3676 | : SCST_CONT) |
3670 | : ($state == SCST_PAX_S) ? SCST_PAX | | 3677 | : ($state == SCST_PAX_S) ? SCST_PAX |
3671 | : ($state == SCST_SED) ? ( | | 3678 | : ($state == SCST_SED) ? ( |
3672 | ($shellword eq "-e") ? SCST_SED_E | | 3679 | ($shellword eq "-e") ? SCST_SED_E |
3673 | : ($shellword =~ m"^-") ? SCST_SED | | 3680 | : ($shellword =~ m"^-") ? SCST_SED |
3674 | : SCST_CONT) | | 3681 | : SCST_CONT) |
3675 | : ($state == SCST_SED_E) ? SCST_SED | | 3682 | : ($state == SCST_SED_E) ? SCST_SED |
3676 | : ($state == SCST_SET) ? SCST_SET_CONT | | 3683 | : ($state == SCST_SET) ? SCST_SET_CONT |
3677 | : ($state == SCST_SET_CONT) ? SCST_SET_CONT | | 3684 | : ($state == SCST_SET_CONT) ? SCST_SET_CONT |
3678 | : ($state == SCST_CASE) ? SCST_CASE_IN | | 3685 | : ($state == SCST_CASE) ? SCST_CASE_IN |
3679 | : ($state == SCST_CASE_IN && $shellword eq "in") ? SCST_CASE_LABEL | | 3686 | : ($state == SCST_CASE_IN && $shellword eq "in") ? SCST_CASE_LABEL |
3680 | : ($state == SCST_CASE_LABEL && $shellword eq "esac") ? SCST_CONT | | 3687 | : ($state == SCST_CASE_LABEL && $shellword eq "esac") ? SCST_CONT |
3681 | : ($state == SCST_CASE_LABEL) ? SCST_CASE_LABEL_CONT | | 3688 | : ($state == SCST_CASE_LABEL) ? SCST_CASE_LABEL_CONT |
3682 | : ($state == SCST_CASE_LABEL_CONT && $shellword eq ")") ? SCST_START | | 3689 | : ($state == SCST_CASE_LABEL_CONT && $shellword eq ")") ? SCST_START |
3683 | : ($state == SCST_CONT) ? SCST_CONT | | 3690 | : ($state == SCST_CONT) ? SCST_CONT |
3684 | : ($state == SCST_COND) ? SCST_COND_CONT | | 3691 | : ($state == SCST_COND) ? SCST_COND_CONT |
3685 | : ($state == SCST_COND_CONT) ? SCST_COND_CONT | | 3692 | : ($state == SCST_COND_CONT) ? SCST_COND_CONT |
3686 | : ($state == SCST_FOR) ? SCST_FOR_IN | | 3693 | : ($state == SCST_FOR) ? SCST_FOR_IN |
3687 | : ($state == SCST_FOR_IN && $shellword eq "in") ? SCST_FOR_CONT | | 3694 | : ($state == SCST_FOR_IN && $shellword eq "in") ? SCST_FOR_CONT |
3688 | : ($state == SCST_FOR_CONT) ? SCST_FOR_CONT | | 3695 | : ($state == SCST_FOR_CONT) ? SCST_FOR_CONT |
3689 | : ($state == SCST_ECHO) ? SCST_CONT | | 3696 | : ($state == SCST_ECHO) ? SCST_CONT |
3690 | : do { | | 3697 | : do { |
3691 | $line->log_warning("[" . scst_statename->[$state] . " ${shellword}] Keeping the current state."); | | 3698 | $line->log_warning("[" . scst_statename->[$state] . " ${shellword}] Keeping the current state."); |
3692 | $state; | | 3699 | $state; |
3693 | }; | | 3700 | }; |
3694 | } | | 3701 | } |
3695 | | | 3702 | |
3696 | if ($rest !~ m"^\s*$") { | | 3703 | if ($rest !~ m"^\s*$") { |
3697 | $line->log_error("Internal pkglint error: " . scst_statename->[$state] . ": rest=${rest}"); | | 3704 | $line->log_error("Internal pkglint error: " . scst_statename->[$state] . ": rest=${rest}"); |
3698 | } | | 3705 | } |
3699 | } | | 3706 | } |
3700 | | | 3707 | |
3701 | sub checkline_mk_shellcmd($$) { | | 3708 | sub checkline_mk_shellcmd($$) { |
3702 | my ($line, $shellcmd) = @_; | | 3709 | my ($line, $shellcmd) = @_; |
3703 | | | 3710 | |
3704 | checkline_mk_text($line, $shellcmd); | | 3711 | checkline_mk_text($line, $shellcmd); |
3705 | checkline_mk_shelltext($line, $shellcmd); | | 3712 | checkline_mk_shelltext($line, $shellcmd); |
3706 | } | | 3713 | } |
3707 | | | 3714 | |
3708 | sub expand_permission($) { | | 3715 | sub expand_permission($) { |
3709 | my ($perm) = @_; | | 3716 | my ($perm) = @_; |
3710 | my %fullperm = ( "a" => "append", "d" => "default", "p" => "preprocess", "s" => "set", "u" => "runtime", "?" => "unknown" ); | | 3717 | my %fullperm = ( "a" => "append", "d" => "default", "p" => "preprocess", "s" => "set", "u" => "runtime", "?" => "unknown" ); |
3711 | my $result = join(", ", map { $fullperm{$_} } split //, $perm); | | 3718 | my $result = join(", ", map { $fullperm{$_} } split //, $perm); |
3712 | $result =~ s/, $//g; | | 3719 | $result =~ s/, $//g; |
3713 | | | 3720 | |
3714 | return $result; | | 3721 | return $result; |
3715 | } | | 3722 | } |
3716 | | | 3723 | |
3717 | sub checkline_mk_vardef($$$) { | | 3724 | sub checkline_mk_vardef($$$) { |
3718 | my ($line, $varname, $op) = @_; | | 3725 | my ($line, $varname, $op) = @_; |
3719 | | | 3726 | |
3720 | $opt_debug_trace and $line->log_debug("checkline_mk_vardef(${varname}, ${op})"); | | 3727 | $opt_debug_trace and $line->log_debug("checkline_mk_vardef(${varname}, ${op})"); |
3721 | | | 3728 | |
3722 | # If we are checking a whole package, add it to the package-wide | | 3729 | # If we are checking a whole package, add it to the package-wide |
3723 | # list of defined variables. | | 3730 | # list of defined variables. |
3724 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{$varname})) { | | 3731 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{$varname})) { |
3725 | $pkgctx_vardef->{$varname} = $line; | | 3732 | $pkgctx_vardef->{$varname} = $line; |
3726 | } | | 3733 | } |
3727 | | | 3734 | |
3728 | # Add it to the file-wide list of defined variables. | | 3735 | # Add it to the file-wide list of defined variables. |
3729 | if (!exists($mkctx_vardef->{$varname})) { | | 3736 | if (!exists($mkctx_vardef->{$varname})) { |
3730 | $mkctx_vardef->{$varname} = $line; | | 3737 | $mkctx_vardef->{$varname} = $line; |
3731 | } | | 3738 | } |
3732 | | | 3739 | |
3733 | return unless $opt_warn_perm; | | 3740 | return unless $opt_warn_perm; |
3734 | | | 3741 | |
3735 | my $perms = get_variable_perms($line, $varname); | | 3742 | my $perms = get_variable_perms($line, $varname); |
3736 | my $needed = { "=" => "s", "!=" => "s", "?=" => "d", "+=" => "a", ":=" => "s" }->{$op}; | | 3743 | my $needed = { "=" => "s", "!=" => "s", "?=" => "d", "+=" => "a", ":=" => "s" }->{$op}; |
3737 | if (index($perms, $needed) == -1) { | | 3744 | if (index($perms, $needed) == -1) { |
3738 | $line->log_warning("Permission [" . expand_permission($needed) . "] requested for ${varname}, but only [" . expand_permission($perms) . "] is allowed."); | | 3745 | $line->log_warning("Permission [" . expand_permission($needed) . "] requested for ${varname}, but only [" . expand_permission($perms) . "] is allowed."); |
3739 | $line->explain_warning( | | 3746 | $line->explain_warning( |
3740 | "The available permissions are:", | | 3747 | "The available permissions are:", |
3741 | "\tappend\t\tappend something using +=", | | 3748 | "\tappend\t\tappend something using +=", |
3742 | "\tdefault\t\tset a default value using ?=", | | 3749 | "\tdefault\t\tset a default value using ?=", |
3743 | "\tpreprocess\tuse a variable during preprocessing", | | 3750 | "\tpreprocess\tuse a variable during preprocessing", |
3744 | "\truntime\t\tuse a variable at runtime", | | 3751 | "\truntime\t\tuse a variable at runtime", |
3745 | "\tset\t\tset a variable using :=, =, !=", | | 3752 | "\tset\t\tset a variable using :=, =, !=", |
3746 | "", | | 3753 | "", |
3747 | "A \"?\" means that it is not yet clear which permissions are allowed", | | 3754 | "A \"?\" means that it is not yet clear which permissions are allowed", |
3748 | "and which aren't."); | | 3755 | "and which aren't."); |
3749 | } | | 3756 | } |
3750 | } | | 3757 | } |
3751 | | | 3758 | |
3752 | # @param $op | | 3759 | # @param $op |
3753 | # The operator that is used for reading or writing to the variable. | | 3760 | # The operator that is used for reading or writing to the variable. |
3754 | # One of: "=", "+=", ":=", "!=", "?=", "use", "pp-use", "". | | 3761 | # One of: "=", "+=", ":=", "!=", "?=", "use", "pp-use", "". |
3755 | # For some variables (like BuildlinkDepth or BuildlinkPackages), the | | 3762 | # For some variables (like BuildlinkDepth or BuildlinkPackages), the |
3756 | # operator influences the valid values. | | 3763 | # operator influences the valid values. |
3757 | # @param $comment | | 3764 | # @param $comment |
3758 | # In assignments, a part of the line may be commented out. If there | | 3765 | # In assignments, a part of the line may be commented out. If there |
3759 | # is no comment, pass C<undef>. | | 3766 | # is no comment, pass C<undef>. |
3760 | # | | 3767 | # |
3761 | sub checkline_mk_vartype_basic($$$$$$$$); | | 3768 | sub checkline_mk_vartype_basic($$$$$$$$); |
3762 | sub checkline_mk_vartype_basic($$$$$$$$) { | | 3769 | sub checkline_mk_vartype_basic($$$$$$$$) { |
3763 | my ($line, $varname, $type, $op, $value, $comment, $list_context, $is_guessed) = @_; | | 3770 | my ($line, $varname, $type, $op, $value, $comment, $list_context, $is_guessed) = @_; |
3764 | my ($value_novar); | | 3771 | my ($value_novar); |
3765 | | | 3772 | |
3766 | $opt_debug_trace and $line->log_debug(sprintf("checkline_mk_vartype_basic(%s, %s, %s, %s, %s, %s, %s)", | | 3773 | $opt_debug_trace and $line->log_debug(sprintf("checkline_mk_vartype_basic(%s, %s, %s, %s, %s, %s, %s)", |
3767 | $varname, $type, $op, $value, defined($comment) ? $comment : "<undef>", $list_context, $is_guessed)); | | 3774 | $varname, $type, $op, $value, defined($comment) ? $comment : "<undef>", $list_context, $is_guessed)); |
3768 | | | 3775 | |
3769 | $value_novar = $value; | | 3776 | $value_novar = $value; |
3770 | while ($value_novar =~ s/\$\{([^{}]*)\}//g) { | | 3777 | while ($value_novar =~ s/\$\{([^{}]*)\}//g) { |
3771 | my ($varuse) = ($1); | | 3778 | my ($varuse) = ($1); |
3772 | if (!$list_context && $varuse =~ m":Q$") { | | 3779 | if (!$list_context && $varuse =~ m":Q$") { |
3773 | $line->log_warning("The :Q operator should only be used in lists and shell commands."); | | 3780 | $line->log_warning("The :Q operator should only be used in lists and shell commands."); |
3774 | } | | 3781 | } |
3775 | } | | 3782 | } |
3776 | | | 3783 | |
3777 | my %type_dispatch = ( | | 3784 | my %type_dispatch = ( |
3778 | AwkCommand => sub { | | 3785 | AwkCommand => sub { |
3779 | $opt_debug_unchecked and $line->log_debug("Unchecked AWK command: ${value}"); | | 3786 | $opt_debug_unchecked and $line->log_debug("Unchecked AWK command: ${value}"); |
3780 | }, | | 3787 | }, |
3781 | | | 3788 | |
3782 | BrokenIn => sub { | | 3789 | BrokenIn => sub { |
3783 | if ($value ne $value_novar) { | | 3790 | if ($value ne $value_novar) { |
3784 | $line->log_error("${varname} must not refer to other variables."); | | 3791 | $line->log_error("${varname} must not refer to other variables."); |
3785 | | | 3792 | |
3786 | } elsif ($value =~ m"^pkgsrc-(\d\d\d\d)Q(\d)$") { | | 3793 | } elsif ($value =~ m"^pkgsrc-(\d\d\d\d)Q(\d)$") { |
3787 | my ($year, $quarter) = ($1, $2); | | 3794 | my ($year, $quarter) = ($1, $2); |
3788 | | | 3795 | |
3789 | # Fine. | | 3796 | # Fine. |
3790 | | | 3797 | |
3791 | } else { | | 3798 | } else { |
3792 | $line->log_warning("Invalid value \"${value}\" for ${varname}."); | | 3799 | $line->log_warning("Invalid value \"${value}\" for ${varname}."); |
3793 | } | | 3800 | } |
3794 | $line->log_note("Please remove this line if the package builds for you."); | | 3801 | $line->log_note("Please remove this line if the package builds for you."); |
3795 | }, | | 3802 | }, |
3796 | | | 3803 | |
3797 | BuildlinkDepmethod => sub { | | 3804 | BuildlinkDepmethod => sub { |
3798 | # Note: this cannot be replaced with { build full } because | | 3805 | # Note: this cannot be replaced with { build full } because |
3799 | # enumerations may not contain references to other variables. | | 3806 | # enumerations may not contain references to other variables. |
3800 | if ($value ne $value_novar) { | | 3807 | if ($value ne $value_novar) { |
3801 | # No checks yet. | | 3808 | # No checks yet. |
3802 | } elsif ($value ne "build" && $value ne "full") { | | 3809 | } elsif ($value ne "build" && $value ne "full") { |
3803 | $line->log_warning("Invalid dependency method \"${value}\". Valid methods are \"build\" or \"full\"."); | | 3810 | $line->log_warning("Invalid dependency method \"${value}\". Valid methods are \"build\" or \"full\"."); |
3804 | } | | 3811 | } |
3805 | }, | | 3812 | }, |
3806 | | | 3813 | |
3807 | BuildlinkDepth => sub { | | 3814 | BuildlinkDepth => sub { |
3808 | if (!($op eq "use" && $value eq "+") | | 3815 | if (!($op eq "use" && $value eq "+") |
3809 | && $value ne "\${BUILDLINK_DEPTH}+" | | 3816 | && $value ne "\${BUILDLINK_DEPTH}+" |
3810 | && $value ne "\${BUILDLINK_DEPTH:S/+\$//}") { | | 3817 | && $value ne "\${BUILDLINK_DEPTH:S/+\$//}") { |
3811 | $line->log_warning("Invalid value for ${varname}."); | | 3818 | $line->log_warning("Invalid value for ${varname}."); |
3812 | } | | 3819 | } |
3813 | }, | | 3820 | }, |
3814 | | | 3821 | |
3815 | BuildlinkPackages => sub { | | 3822 | BuildlinkPackages => sub { |
3816 | my $re_del = qr"\$\{BUILDLINK_PACKAGES:N(?:[+\-.0-9A-Z_a-z]|\$\{[^\}]+\})+\}"; | | 3823 | my $re_del = qr"\$\{BUILDLINK_PACKAGES:N(?:[+\-.0-9A-Z_a-z]|\$\{[^\}]+\})+\}"; |
3817 | my $re_add = qr"(?:[+\-.0-9A-Z_a-z]|\$\{[^\}]+\})+"; | | 3824 | my $re_add = qr"(?:[+\-.0-9A-Z_a-z]|\$\{[^\}]+\})+"; |
3818 | | | 3825 | |
3819 | if (($op eq ":=" && $value =~ m"^${re_del}$") || | | 3826 | if (($op eq ":=" && $value =~ m"^${re_del}$") || |
3820 | ($op eq ":=" && $value =~ m"^${re_del}\s+${re_add}$") || | | 3827 | ($op eq ":=" && $value =~ m"^${re_del}\s+${re_add}$") || |
3821 | ($op eq "+=" && $value =~ m"^${re_add}$")) { | | 3828 | ($op eq "+=" && $value =~ m"^${re_add}$")) { |
3822 | # Fine. | | 3829 | # Fine. |
3823 | | | 3830 | |
3824 | } else { | | 3831 | } else { |
3825 | $line->log_warning("Invalid value for ${varname}."); | | 3832 | $line->log_warning("Invalid value for ${varname}."); |
3826 | } | | 3833 | } |
3827 | }, | | 3834 | }, |
3828 | | | 3835 | |
3829 | Category => sub { | | 3836 | Category => sub { |
3830 | my $allowed_categories = join("|", qw( | | 3837 | my $allowed_categories = join("|", qw( |
3831 | archivers audio | | 3838 | archivers audio |
3832 | benchmarks biology | | 3839 | benchmarks biology |
3833 | cad chat chinese comms converters cross crosspkgtools | | 3840 | cad chat chinese comms converters cross crosspkgtools |
3834 | databases devel | | 3841 | databases devel |
3835 | editors emulators | | 3842 | editors emulators |
3836 | filesystems finance fonts | | 3843 | filesystems finance fonts |
3837 | games geography gnome gnustep graphics | | 3844 | games geography gnome gnustep graphics |
3838 | ham | | 3845 | ham |
3839 | inputmethod | | 3846 | inputmethod |
3840 | japanese java | | 3847 | japanese java |
3841 | kde korean | | 3848 | kde korean |
3842 | lang linux local | | 3849 | lang linux local |
3843 | mail math mbone meta-pkgs misc multimedia | | 3850 | mail math mbone meta-pkgs misc multimedia |
3844 | net news | | 3851 | net news |
3845 | packages parallel perl5 pkgtools plan9 print python | | 3852 | packages parallel perl5 pkgtools plan9 print python |
3846 | ruby | | 3853 | ruby |
3847 | scm security shells sysutils | | 3854 | scm security shells sysutils |
3848 | tcl textproc time tk | | 3855 | tcl textproc time tk |
3849 | windowmaker wm www | | 3856 | windowmaker wm www |
3850 | x11 xmms | | 3857 | x11 xmms |
3851 | )); | | 3858 | )); |
3852 | if ($value !~ m"^(?:${allowed_categories})$") { | | 3859 | if ($value !~ m"^(?:${allowed_categories})$") { |
3853 | $line->log_error("Invalid category \"${value}\"."); | | 3860 | $line->log_error("Invalid category \"${value}\"."); |
3854 | } | | 3861 | } |
3855 | }, | | 3862 | }, |
3856 | | | 3863 | |
3857 | CFlag => sub { | | 3864 | CFlag => sub { |
3858 | if ($value =~ m"^-D([0-9A-Z_a-z]+)=(.*)") { | | 3865 | if ($value =~ m"^-D([0-9A-Z_a-z]+)=(.*)") { |
3859 | my ($macname, $macval) = ($1, $2); | | 3866 | my ($macname, $macval) = ($1, $2); |
3860 | | | 3867 | |
3861 | # No checks needed, since the macro definitions | | 3868 | # No checks needed, since the macro definitions |
3862 | # are usually directory names, which don't need | | 3869 | # are usually directory names, which don't need |
3863 | # any quoting. | | 3870 | # any quoting. |
3864 | | | 3871 | |
3865 | } elsif ($value =~ m"^-[DU]([0-9A-Z_a-z]+)") { | | 3872 | } elsif ($value =~ m"^-[DU]([0-9A-Z_a-z]+)") { |
3866 | my ($macname) = ($1); | | 3873 | my ($macname) = ($1); |
3867 | | | 3874 | |
3868 | $opt_debug_unchecked and $line->log_debug("Unchecked macro ${macname} in ${varname}."); | | 3875 | $opt_debug_unchecked and $line->log_debug("Unchecked macro ${macname} in ${varname}."); |
3869 | | | 3876 | |
3870 | } elsif ($value =~ m"^-I(.*)") { | | 3877 | } elsif ($value =~ m"^-I(.*)") { |
3871 | my ($dirname) = ($1); | | 3878 | my ($dirname) = ($1); |
3872 | | | 3879 | |
3873 | $opt_debug_unchecked and $line->log_debug("Unchecked directory ${dirname} in ${varname}."); | | 3880 | $opt_debug_unchecked and $line->log_debug("Unchecked directory ${dirname} in ${varname}."); |
3874 | | | 3881 | |
3875 | } elsif ($value eq "-c99") { | | 3882 | } elsif ($value eq "-c99") { |
3876 | # Only works on IRIX, but is usually enclosed with | | 3883 | # Only works on IRIX, but is usually enclosed with |
3877 | # the proper preprocessor conditional. | | 3884 | # the proper preprocessor conditional. |
3878 | | | 3885 | |
3879 | } elsif ($value =~ m"^-[OWfgm]") { | | 3886 | } elsif ($value =~ m"^-[OWfgm]") { |
3880 | $opt_debug_unchecked and $line->log_debug("Unchecked compiler flag ${value} in ${varname}."); | | 3887 | $opt_debug_unchecked and $line->log_debug("Unchecked compiler flag ${value} in ${varname}."); |
3881 | | | 3888 | |
3882 | } elsif ($value =~ m"^-.*") { | | 3889 | } elsif ($value =~ m"^-.*") { |
3883 | $line->log_warning("Unknown compiler flag \"${value}\"."); | | 3890 | $line->log_warning("Unknown compiler flag \"${value}\"."); |
3884 | | | 3891 | |
3885 | } elsif ($value =~ regex_unresolved) { | | 3892 | } elsif ($value =~ regex_unresolved) { |
3886 | $opt_debug_unchecked and $line->log_debug("Unchecked CFLAG: ${value}"); | | 3893 | $opt_debug_unchecked and $line->log_debug("Unchecked CFLAG: ${value}"); |
3887 | | | 3894 | |
3888 | } else { | | 3895 | } else { |
3889 | $line->log_warning("Compiler flag \"${value}\" does not start with a dash."); | | 3896 | $line->log_warning("Compiler flag \"${value}\" does not start with a dash."); |
3890 | } | | 3897 | } |
3891 | }, | | 3898 | }, |
3892 | | | 3899 | |
3893 | Comment => sub { | | 3900 | Comment => sub { |
3894 | if ($value eq "SHORT_DESCRIPTION_OF_THE_PACKAGE") { | | 3901 | if ($value eq "SHORT_DESCRIPTION_OF_THE_PACKAGE") { |
3895 | $line->log_error("COMMENT must be set."); | | 3902 | $line->log_error("COMMENT must be set."); |
3896 | } | | 3903 | } |
3897 | if ($value =~ m"^(a|an)\s+"i) { | | 3904 | if ($value =~ m"^(a|an)\s+"i) { |
3898 | $line->log_warning("COMMENT should not begin with '$1'."); | | 3905 | $line->log_warning("COMMENT should not begin with '$1'."); |
3899 | } | | 3906 | } |
3900 | if ($value =~ m"^[a-z]") { | | 3907 | if ($value =~ m"^[a-z]") { |
3901 | $line->log_warning("COMMENT should start with a capital letter."); | | 3908 | $line->log_warning("COMMENT should start with a capital letter."); |
3902 | } | | 3909 | } |
3903 | if ($value =~ m"\.$") { | | 3910 | if ($value =~ m"\.$") { |
3904 | $line->log_warning("COMMENT should not end with a period."); | | 3911 | $line->log_warning("COMMENT should not end with a period."); |
3905 | } | | 3912 | } |
3906 | if (length($value) > 70) { | | 3913 | if (length($value) > 70) { |
3907 | $line->log_warning("COMMENT should not be longer than 70 characters."); | | 3914 | $line->log_warning("COMMENT should not be longer than 70 characters."); |
3908 | } | | 3915 | } |
3909 | }, | | 3916 | }, |
3910 | | | 3917 | |
3911 | Dependency => sub { | | 3918 | Dependency => sub { |
3912 | if ($value =~ m"^(${regex_pkgbase})(<|=|>|<=|>=|!=)(${regex_pkgversion})$") { | | 3919 | if ($value =~ m"^(${regex_pkgbase})(<|=|>|<=|>=|!=)(${regex_pkgversion})$") { |
3913 | my ($depbase, $depop, $depversion) = ($1, $2, $3); | | 3920 | my ($depbase, $depop, $depversion) = ($1, $2, $3); |
3914 | | | 3921 | |
3915 | } elsif ($value =~ m"^(${regex_pkgbase})-(?:\[(.*)\]\*|(\d+(?:\.\d+)*(?:\.\*)?)(\{,nb\*\}|\*|)|(.*))?$") { | | 3922 | } elsif ($value =~ m"^(${regex_pkgbase})-(?:\[(.*)\]\*|(\d+(?:\.\d+)*(?:\.\*)?)(\{,nb\*\}|\*|)|(.*))?$") { |
3916 | my ($depbase, $bracket, $version, $version_wildcard, $other) = ($1, $2, $3, $4, $5); | | 3923 | my ($depbase, $bracket, $version, $version_wildcard, $other) = ($1, $2, $3, $4, $5); |
3917 | | | 3924 | |
3918 | if (defined($bracket)) { | | 3925 | if (defined($bracket)) { |
3919 | if ($bracket ne "0-9") { | | 3926 | if ($bracket ne "0-9") { |
3920 | $line->log_warning("Only [0-9]* is allowed in the numeric part of a dependency."); | | 3927 | $line->log_warning("Only [0-9]* is allowed in the numeric part of a dependency."); |
3921 | } | | 3928 | } |
3922 | | | 3929 | |
3923 | } elsif (defined($version) && defined($version_wildcard) && $version_wildcard ne "") { | | 3930 | } elsif (defined($version) && defined($version_wildcard) && $version_wildcard ne "") { |
3924 | # Great. | | 3931 | # Great. |
3925 | | | 3932 | |
3926 | } elsif (defined($version)) { | | 3933 | } elsif (defined($version)) { |
3927 | $line->log_warning("Please append {,nb*} to the version number of this dependency."); | | 3934 | $line->log_warning("Please append {,nb*} to the version number of this dependency."); |
3928 | $line->explain_warning( | | 3935 | $line->explain_warning( |
3929 | "Usually, a dependency should stay valid when the PKGREVISION is", | | 3936 | "Usually, a dependency should stay valid when the PKGREVISION is", |
3930 | "increased, since those changes are most often editorial. In the", | | 3937 | "increased, since those changes are most often editorial. In the", |
3931 | "current form, the dependency only matches if the PKGREVISION is", | | 3938 | "current form, the dependency only matches if the PKGREVISION is", |
3932 | "undefined."); | | 3939 | "undefined."); |
3933 | | | 3940 | |
3934 | } elsif ($other eq "*") { | | 3941 | } elsif ($other eq "*") { |
3935 | $line->log_warning("Please use ${depbase}-[0-9]* instead of ${depbase}-*."); | | 3942 | $line->log_warning("Please use ${depbase}-[0-9]* instead of ${depbase}-*."); |
3936 | $line->explain_warning( | | 3943 | $line->explain_warning( |
3937 | "If you use a * alone, the package specification may match other", | | 3944 | "If you use a * alone, the package specification may match other", |
3938 | "packages that have the same prefix, but a longer name. For example,", | | 3945 | "packages that have the same prefix, but a longer name. For example,", |
3939 | "foo-* matches foo-1.2, but also foo-client-1.2 and foo-server-1.2."); | | 3946 | "foo-* matches foo-1.2, but also foo-client-1.2 and foo-server-1.2."); |
3940 | | | 3947 | |
3941 | } else { | | 3948 | } else { |
3942 | $line->log_warning("Unknown dependency pattern \"${value}\"."); | | 3949 | $line->log_warning("Unknown dependency pattern \"${value}\"."); |
3943 | } | | 3950 | } |
3944 | | | 3951 | |
3945 | } elsif ($value =~ m"\{") { | | 3952 | } elsif ($value =~ m"\{") { |
3946 | # Dependency patterns containing alternatives | | 3953 | # Dependency patterns containing alternatives |
3947 | # are just too hard to check. | | 3954 | # are just too hard to check. |
3948 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern: ${value}"); | | 3955 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency pattern: ${value}"); |
3949 | | | 3956 | |
3950 | } elsif ($value ne $value_novar) { | | 3957 | } elsif ($value ne $value_novar) { |
3951 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency: ${value}"); | | 3958 | $opt_debug_unchecked and $line->log_debug("Unchecked dependency: ${value}"); |
3952 | | | 3959 | |
3953 | } else { | | 3960 | } else { |
3954 | $line->log_warning("Unknown dependency format: ${value}"); | | 3961 | $line->log_warning("Unknown dependency format: ${value}"); |
3955 | $line->explain_warning( | | 3962 | $line->explain_warning( |
3956 | "Typical dependencies have the form \"package>=2.5\", \"package-[0-9]*\"", | | 3963 | "Typical dependencies have the form \"package>=2.5\", \"package-[0-9]*\"", |
3957 | "or \"package-3.141\"."); | | 3964 | "or \"package-3.141\"."); |
3958 | } | | 3965 | } |
3959 | }, | | 3966 | }, |
3960 | | | 3967 | |
3961 | DependencyWithPath => sub { | | 3968 | DependencyWithPath => sub { |
3962 | if ($value =~ regex_unresolved) { | | 3969 | if ($value =~ regex_unresolved) { |
3963 | # don't even try to check anything | | 3970 | # don't even try to check anything |
3964 | } elsif ($value =~ m"(.*):(\.\./\.\./([^/]+)/([^/]+))$") { | | 3971 | } elsif ($value =~ m"(.*):(\.\./\.\./([^/]+)/([^/]+))$") { |
3965 | my ($pattern, $relpath, $cat, $pkg) = ($1, $2, $3, $4); | | 3972 | my ($pattern, $relpath, $cat, $pkg) = ($1, $2, $3, $4); |
3966 | | | 3973 | |
3967 | checkline_relative_pkgdir($line, $relpath); | | 3974 | checkline_relative_pkgdir($line, $relpath); |
3968 | | | 3975 | |
3969 | if ($pkg eq "msgfmt" || $pkg eq "gettext") { | | 3976 | if ($pkg eq "msgfmt" || $pkg eq "gettext") { |
3970 | $line->log_warning("Please use USE_TOOLS+=msgfmt instead of this dependency."); | | 3977 | $line->log_warning("Please use USE_TOOLS+=msgfmt instead of this dependency."); |
3971 | | | 3978 | |
3972 | } elsif ($pkg =~ m"^perl\d+") { | | 3979 | } elsif ($pkg =~ m"^perl\d+") { |
3973 | $line->log_warning("Please use USE_TOOLS+=perl:run instead of this dependency."); | | 3980 | $line->log_warning("Please use USE_TOOLS+=perl:run instead of this dependency."); |
3974 | | | 3981 | |
3975 | } elsif ($pkg eq "gmake") { | | 3982 | } elsif ($pkg eq "gmake") { |
3976 | $line->log_warning("Please use USE_TOOLS+=gmake instead of this dependency."); | | 3983 | $line->log_warning("Please use USE_TOOLS+=gmake instead of this dependency."); |
3977 | | | 3984 | |
3978 | } | | 3985 | } |
3979 | | | 3986 | |
3980 | if ($pattern =~ regex_dependency_gt) { | | 3987 | if ($pattern =~ regex_dependency_gt) { |
3981 | # ($abi_pkg, $abi_version) = ($1, $2); | | 3988 | # ($abi_pkg, $abi_version) = ($1, $2); |
3982 | } elsif ($pattern =~ regex_dependency_wildcard) { | | 3989 | } elsif ($pattern =~ regex_dependency_wildcard) { |
3983 | # ($abi_pkg) = ($1); | | 3990 | # ($abi_pkg) = ($1); |
3984 | } else { | | 3991 | } else { |
3985 | $line->log_warning("Unknown dependency pattern \"${pattern}\"."); | | 3992 | $line->log_warning("Unknown dependency pattern \"${pattern}\"."); |
3986 | } | | 3993 | } |
3987 | | | 3994 | |
3988 | } elsif ($value =~ m":\.\./[^/]+$") { | | 3995 | } elsif ($value =~ m":\.\./[^/]+$") { |
3989 | $line->log_warning("Dependencies should have the form \"../../category/package\"."); | | 3996 | $line->log_warning("Dependencies should have the form \"../../category/package\"."); |
3990 | $line->explain_warning(expl_relative_dirs); | | 3997 | $line->explain_warning(expl_relative_dirs); |
3991 | | | 3998 | |
3992 | } else { | | 3999 | } else { |
3993 | $line->log_warning("Unknown dependency format."); | | 4000 | $line->log_warning("Unknown dependency format."); |
3994 | $line->explain_warning( | | 4001 | $line->explain_warning( |
3995 | "Examples for valid dependencies are:", | | 4002 | "Examples for valid dependencies are:", |
3996 | " package-[0-9]*:../../category/package", | | 4003 | " package-[0-9]*:../../category/package", |
3997 | " package>=3.41:../../category/package", | | 4004 | " package>=3.41:../../category/package", |
3998 | " package-2.718:../../category/package"); | | 4005 | " package-2.718:../../category/package"); |
3999 | } | | 4006 | } |
4000 | }, | | 4007 | }, |
4001 | | | 4008 | |
4002 | DistSuffix => sub { | | 4009 | DistSuffix => sub { |
4003 | if ($value eq ".tar.gz") { | | 4010 | if ($value eq ".tar.gz") { |
4004 | $line->log_note("${varname} is \".tar.gz\" by default, so this definition may be redundant."); | | 4011 | $line->log_note("${varname} is \".tar.gz\" by default, so this definition may be redundant."); |
4005 | } | | 4012 | } |
4006 | }, | | 4013 | }, |
4007 | | | 4014 | |
4008 | EmulPlatform => sub { | | 4015 | EmulPlatform => sub { |
4009 | if ($value =~ m"^(\w+)-(\w+)$") { | | 4016 | if ($value =~ m"^(\w+)-(\w+)$") { |
4010 | my ($opsys, $arch) = ($1, $2); | | 4017 | my ($opsys, $arch) = ($1, $2); |
4011 | | | 4018 | |
4012 | if ($opsys !~ m"^(?:bsdos|cygwin|darwin|dragonfly|freebsd|haiku|hpux|interix|irix|linux|netbsd|openbsd|osf1|sunos)$") { | | 4019 | if ($opsys !~ m"^(?:bsdos|cygwin|darwin|dragonfly|freebsd|haiku|hpux|interix|irix|linux|netbsd|openbsd|osf1|sunos)$") { |
4013 | $line->log_warning("Unknown operating system: ${opsys}"); | | 4020 | $line->log_warning("Unknown operating system: ${opsys}"); |
4014 | } | | 4021 | } |
4015 | # no check for $os_version | | 4022 | # no check for $os_version |
4016 | if ($arch !~ m"^(?:i386|alpha|amd64|arc|arm|arm32|cobalt|convex|dreamcast|hpcmips|hpcsh|hppa|ia64|m68k|m88k|mips|mips64|mipsel|mipseb|mipsn32|ns32k|pc532|pmax|powerpc|rs6000|s390|sparc|sparc64|vax|x86_64)$") { | | 4023 | if ($arch !~ m"^(?:i386|alpha|amd64|arc|arm|arm32|cobalt|convex|dreamcast|hpcmips|hpcsh|hppa|ia64|m68k|m88k|mips|mips64|mipsel|mipseb|mipsn32|ns32k|pc532|pmax|powerpc|rs6000|s390|sparc|sparc64|vax|x86_64)$") { |
4017 | $line->log_warning("Unknown hardware architecture: ${arch}"); | | 4024 | $line->log_warning("Unknown hardware architecture: ${arch}"); |
4018 | } | | 4025 | } |
4019 | | | 4026 | |
4020 | } else { | | 4027 | } else { |
4021 | $line->log_warning("\"${value}\" is not a valid emulation platform."); | | 4028 | $line->log_warning("\"${value}\" is not a valid emulation platform."); |
4022 | $line->explain_warning( | | 4029 | $line->explain_warning( |
4023 | "An emulation platform has the form <OPSYS>-<MACHINE_ARCH>.", | | 4030 | "An emulation platform has the form <OPSYS>-<MACHINE_ARCH>.", |
4024 | "OPSYS is the lower-case name of the operating system, and MACHINE_ARCH", | | 4031 | "OPSYS is the lower-case name of the operating system, and MACHINE_ARCH", |
4025 | "is the hardware architecture.", | | 4032 | "is the hardware architecture.", |
4026 | "", | | 4033 | "", |
4027 | "Examples: linux-i386, irix-mipsel."); | | 4034 | "Examples: linux-i386, irix-mipsel."); |
4028 | } | | 4035 | } |
4029 | }, | | 4036 | }, |
4030 | | | 4037 | |
4031 | | | 4038 | |
4032 | | | 4039 | |
4033 | Filename => sub { | | 4040 | Filename => sub { |
4034 | if ($value_novar =~ m"/") { | | 4041 | if ($value_novar =~ m"/") { |
4035 | $line->log_warning("A filename should not contain a slash."); | | 4042 | $line->log_warning("A filename should not contain a slash."); |
4036 | | | 4043 | |
4037 | } elsif ($value_novar !~ m"^[-0-9\@A-Za-z.,_~+%]*$") { | | 4044 | } elsif ($value_novar !~ m"^[-0-9\@A-Za-z.,_~+%]*$") { |
4038 | $line->log_warning("\"${value}\" is not a valid filename."); | | 4045 | $line->log_warning("\"${value}\" is not a valid filename."); |
4039 | } | | 4046 | } |
4040 | }, | | 4047 | }, |
4041 | | | 4048 | |
4042 | Filemask => sub { | | 4049 | Filemask => sub { |
4043 | if ($value_novar !~ m"^[-0-9A-Za-z._~+%*?]*$") { | | 4050 | if ($value_novar !~ m"^[-0-9A-Za-z._~+%*?]*$") { |
4044 | $line->log_warning("\"${value}\" is not a valid filename mask."); | | 4051 | $line->log_warning("\"${value}\" is not a valid filename mask."); |
4045 | } | | 4052 | } |
4046 | }, | | 4053 | }, |
4047 | | | 4054 | |
4048 | FileMode => sub { | | 4055 | FileMode => sub { |
4049 | if ($value ne "" && $value_novar eq "") { | | 4056 | if ($value ne "" && $value_novar eq "") { |
4050 | # Fine. | | 4057 | # Fine. |
4051 | } elsif ($value =~ m"^[0-7]{3,4}") { | | 4058 | } elsif ($value =~ m"^[0-7]{3,4}") { |
4052 | # Fine. | | 4059 | # Fine. |
4053 | } else { | | 4060 | } else { |
4054 | $line->log_warning("Invalid file mode ${value}."); | | 4061 | $line->log_warning("Invalid file mode ${value}."); |
4055 | } | | 4062 | } |
4056 | }, | | 4063 | }, |
4057 | | | 4064 | |
4058 | Identifier => sub { | | 4065 | Identifier => sub { |
4059 | if ($value ne $value_novar) { | | 4066 | if ($value ne $value_novar) { |
4060 | #$line->log_warning("Identifiers should be given directly."); | | 4067 | #$line->log_warning("Identifiers should be given directly."); |
4061 | } | | 4068 | } |
4062 | if ($value_novar =~ m"^[+\-.0-9A-Z_a-z]+$") { | | 4069 | if ($value_novar =~ m"^[+\-.0-9A-Z_a-z]+$") { |
4063 | # Fine. | | 4070 | # Fine. |
4064 | } elsif ($value ne "" && $value_novar eq "") { | | 4071 | } elsif ($value ne "" && $value_novar eq "") { |
4065 | # Don't warn here. | | 4072 | # Don't warn here. |
4066 | } else { | | 4073 | } else { |
4067 | $line->log_warning("Invalid identifier \"${value}\"."); | | 4074 | $line->log_warning("Invalid identifier \"${value}\"."); |
4068 | } | | 4075 | } |
4069 | }, | | 4076 | }, |
4070 | | | 4077 | |
4071 | Integer => sub { | | 4078 | Integer => sub { |
4072 | if ($value !~ m"^\d+$") { | | 4079 | if ($value !~ m"^\d+$") { |
4073 | $line->log_warning("${varname} must be a valid integer."); | | 4080 | $line->log_warning("${varname} must be a valid integer."); |
4074 | } | | 4081 | } |
4075 | }, | | 4082 | }, |
4076 | | | 4083 | |
4077 | LdFlag => sub { | | 4084 | LdFlag => sub { |
4078 | if ($value =~ m"^-L(.*)") { | | 4085 | if ($value =~ m"^-L(.*)") { |
4079 | my ($dirname) = ($1); | | 4086 | my ($dirname) = ($1); |
4080 | | | 4087 | |
4081 | $opt_debug_unchecked and $line->log_debug("Unchecked directory ${dirname} in ${varname}."); | | 4088 | $opt_debug_unchecked and $line->log_debug("Unchecked directory ${dirname} in ${varname}."); |
4082 | | | 4089 | |
4083 | } elsif ($value =~ m"^-l(.*)") { | | 4090 | } elsif ($value =~ m"^-l(.*)") { |
4084 | my ($libname) = ($1); | | 4091 | my ($libname) = ($1); |
4085 | | | 4092 | |
4086 | $opt_debug_unchecked and $line->log_debug("Unchecked library name ${libname} in ${varname}."); | | 4093 | $opt_debug_unchecked and $line->log_debug("Unchecked library name ${libname} in ${varname}."); |
4087 | | | 4094 | |
4088 | } elsif ($value =~ m"^(?:-static)$") { | | 4095 | } elsif ($value =~ m"^(?:-static)$") { |
4089 | # Assume that the wrapper framework catches these. | | 4096 | # Assume that the wrapper framework catches these. |
4090 | | | 4097 | |
4091 | } elsif ($value =~ m"^(-Wl,(?:-R|-rpath|--rpath))") { | | 4098 | } elsif ($value =~ m"^(-Wl,(?:-R|-rpath|--rpath))") { |
4092 | my ($rpath_flag) = ($1); | | 4099 | my ($rpath_flag) = ($1); |
4093 | $line->log_warning("Please use \${COMPILER_RPATH_FLAG} instead of ${rpath_flag}."); | | 4100 | $line->log_warning("Please use \${COMPILER_RPATH_FLAG} instead of ${rpath_flag}."); |
4094 | | | 4101 | |
4095 | } elsif ($value =~ m"^-.*") { | | 4102 | } elsif ($value =~ m"^-.*") { |
4096 | $line->log_warning("Unknown linker flag \"${value}\"."); | | 4103 | $line->log_warning("Unknown linker flag \"${value}\"."); |
4097 | | | 4104 | |
4098 | } elsif ($value =~ regex_unresolved) { | | 4105 | } elsif ($value =~ regex_unresolved) { |
4099 | $opt_debug_unchecked and $line->log_debug("Unchecked LDFLAG: ${value}"); | | 4106 | $opt_debug_unchecked and $line->log_debug("Unchecked LDFLAG: ${value}"); |
4100 | | | 4107 | |
4101 | } else { | | 4108 | } else { |
4102 | $line->log_warning("Linker flag \"${value}\" does not start with a dash."); | | 4109 | $line->log_warning("Linker flag \"${value}\" does not start with a dash."); |
4103 | } | | 4110 | } |
4104 | }, | | 4111 | }, |
4105 | | | 4112 | |
4106 | License => sub { | | 4113 | License => sub { |
4107 | | | 4114 | |
4108 | use constant deprecated_licenses => array_to_hash(qw( | | 4115 | use constant deprecated_licenses => array_to_hash(qw( |
4109 | fee-based-commercial-use | | 4116 | fee-based-commercial-use |
4110 | no-commercial-use no-profit no-redistribution | | 4117 | no-commercial-use no-profit no-redistribution |
4111 | shareware | | 4118 | shareware |
4112 | )); | | 4119 | )); |
4113 | | | 4120 | |
4114 | my $licenses = parse_licenses($value); | | 4121 | my $licenses = parse_licenses($value); |
4115 | foreach my $license (@$licenses) { | | 4122 | foreach my $license (@$licenses) { |
4116 | my $license_file = "${cwd_pkgsrcdir}/licenses/${license}"; | | 4123 | my $license_file = "${cwd_pkgsrcdir}/licenses/${license}"; |
4117 | if (defined($pkgctx_vardef) && exists($pkgctx_vardef->{"LICENSE_FILE"})) { | | 4124 | if (defined($pkgctx_vardef) && exists($pkgctx_vardef->{"LICENSE_FILE"})) { |
4118 | my $license_file_line = $pkgctx_vardef->{"LICENSE_FILE"}; | | 4125 | my $license_file_line = $pkgctx_vardef->{"LICENSE_FILE"}; |
4119 | | | 4126 | |
4120 | $license_file = "${current_dir}/" . resolve_relative_path($license_file_line->get("value"), false); | | 4127 | $license_file = "${current_dir}/" . resolve_relative_path($license_file_line->get("value"), false); |
4121 | } | | 4128 | } |
4122 | if (!-f $license_file) { | | 4129 | if (!-f $license_file) { |
4123 | $line->log_warning("License file ".normalize_pathname($license_file)." does not exist."); | | 4130 | $line->log_warning("License file ".normalize_pathname($license_file)." does not exist."); |
4124 | } | | 4131 | } |
4125 | | | 4132 | |
4126 | if (exists(deprecated_licenses->{$license})) { | | 4133 | if (exists(deprecated_licenses->{$license})) { |
4127 | $line->log_warning("License ${license} is deprecated."); | | 4134 | $line->log_warning("License ${license} is deprecated."); |
4128 | } | | 4135 | } |
4129 | } | | 4136 | } |
4130 | }, | | 4137 | }, |
4131 | | | 4138 | |
4132 | Mail_Address => sub { | | 4139 | Mail_Address => sub { |
4133 | if ($value =~ m"^([+\-.0-9A-Z_a-z]+)\@([-\w\d.]+)$") { | | 4140 | if ($value =~ m"^([+\-.0-9A-Z_a-z]+)\@([-\w\d.]+)$") { |
4134 | my ($localpart, $domain) = ($1, $2); | | 4141 | my ($localpart, $domain) = ($1, $2); |
4135 | if ($domain =~ m"^NetBSD.org"i && $domain ne "NetBSD.org") { | | 4142 | if ($domain =~ m"^NetBSD.org"i && $domain ne "NetBSD.org") { |
4136 | $line->log_warning("Please write NetBSD.org instead of ${domain}."); | | 4143 | $line->log_warning("Please write NetBSD.org instead of ${domain}."); |
4137 | } | | 4144 | } |
4138 | if ("${localpart}\@${domain}" =~ m"^(tech-pkg|packages)\@NetBSD\.org$"i) { | | 4145 | if ("${localpart}\@${domain}" =~ m"^(tech-pkg|packages)\@NetBSD\.org$"i) { |
4139 | $line->log_warning("${localpart}\@${domain} is deprecated. Use pkgsrc-users\@NetBSD.org instead."); | | 4146 | $line->log_warning("${localpart}\@${domain} is deprecated. Use pkgsrc-users\@NetBSD.org instead."); |
4140 | } | | 4147 | } |
4141 | | | 4148 | |
4142 | } else { | | 4149 | } else { |
4143 | $line->log_warning("\"${value}\" is not a valid mail address."); | | 4150 | $line->log_warning("\"${value}\" is not a valid mail address."); |
4144 | } | | 4151 | } |
4145 | }, | | 4152 | }, |
4146 | | | 4153 | |
4147 | Message => sub { | | 4154 | Message => sub { |
4148 | if ($value =~ m"^[\"'].*[\"']$") { | | 4155 | if ($value =~ m"^[\"'].*[\"']$") { |
4149 | $line->log_warning("${varname} should not be quoted."); | | 4156 | $line->log_warning("${varname} should not be quoted."); |
4150 | $line->explain_warning( | | 4157 | $line->explain_warning( |
4151 | "The quoting is only needed for variables which are interpreted as", | | 4158 | "The quoting is only needed for variables which are interpreted as", |
4152 | "multiple words (or, generally speaking, a list of something). A single", | | 4159 | "multiple words (or, generally speaking, a list of something). A single", |
4153 | "text message does not belong to this class, since it is only printed", | | 4160 | "text message does not belong to this class, since it is only printed", |
4154 | "as a whole.", | | 4161 | "as a whole.", |
4155 | "", | | 4162 | "", |
4156 | "On the other hand, PKG_FAIL_REASON is a _list_ of text messages, so in", | | 4163 | "On the other hand, PKG_FAIL_REASON is a _list_ of text messages, so in", |
4157 | "that case, the quoting has to be done."); | | 4164 | "that case, the quoting has to be done."); |
4158 | } | | 4165 | } |
4159 | }, | | 4166 | }, |
4160 | | | 4167 | |
4161 | Option => sub { | | 4168 | Option => sub { |
4162 | if ($value ne $value_novar) { | | 4169 | if ($value ne $value_novar) { |
4163 | $opt_debug_unchecked and $line->log_debug("Unchecked option name \"${value}\"."); | | 4170 | $opt_debug_unchecked and $line->log_debug("Unchecked option name \"${value}\"."); |
4164 | | | 4171 | |
4165 | } elsif ($value_novar =~ m"^-?([a-z][-0-9a-z\+]*)$") { | | 4172 | } elsif ($value_novar =~ m"^-?([a-z][-0-9a-z\+]*)$") { |
4166 | my ($optname) = ($1); | | 4173 | my ($optname) = ($1); |
4167 | | | 4174 | |
4168 | if (!exists(get_pkg_options()->{$optname})) { | | 4175 | if (!exists(get_pkg_options()->{$optname})) { |
4169 | $line->log_warning("Unknown option \"${value}\"."); | | 4176 | $line->log_warning("Unknown option \"${value}\"."); |
4170 | $line->explain_warning( | | 4177 | $line->explain_warning( |
4171 | "This option is not documented in the mk/defaults/options.description", | | 4178 | "This option is not documented in the mk/defaults/options.description", |
4172 | "file. If this is not a typo, please think of a brief but precise", | | 4179 | "file. If this is not a typo, please think of a brief but precise", |
4173 | "description and either update that file yourself or ask on the", | | 4180 | "description and either update that file yourself or ask on the", |
4174 | "tech-pkg\@NetBSD.org mailing list."); | | 4181 | "tech-pkg\@NetBSD.org mailing list."); |
4175 | } | | 4182 | } |
4176 | | | 4183 | |
4177 | } elsif ($value_novar =~ m"^-?([a-z][-0-9a-z_\+]*)$") { | | 4184 | } elsif ($value_novar =~ m"^-?([a-z][-0-9a-z_\+]*)$") { |
4178 | my ($optname) = ($1); | | 4185 | my ($optname) = ($1); |
4179 | | | 4186 | |
4180 | $line->log_warning("Use of the underscore character in option names is deprecated."); | | 4187 | $line->log_warning("Use of the underscore character in option names is deprecated."); |
4181 | | | 4188 | |
4182 | } else { | | 4189 | } else { |
4183 | $line->log_error("\"${value}\" is not a valid option name."); | | 4190 | $line->log_error("\"${value}\" is not a valid option name."); |
4184 | } | | 4191 | } |
4185 | }, | | 4192 | }, |
4186 | | | 4193 | |
4187 | Pathlist => sub { | | 4194 | Pathlist => sub { |
4188 | | | 4195 | |
4189 | if ($value !~ m":" && $is_guessed) { | | 4196 | if ($value !~ m":" && $is_guessed) { |
4190 | checkline_mk_vartype_basic($line, $varname, "Pathname", $op, $value, $comment, $list_context, $is_guessed); | | 4197 | checkline_mk_vartype_basic($line, $varname, "Pathname", $op, $value, $comment, $list_context, $is_guessed); |
4191 | | | 4198 | |
4192 | } else { | | 4199 | } else { |
4193 | | | 4200 | |
4194 | # XXX: The splitting will fail if $value contains any | | 4201 | # XXX: The splitting will fail if $value contains any |
4195 | # variables with modifiers, for example :Q or :S/././. | | 4202 | # variables with modifiers, for example :Q or :S/././. |
4196 | foreach my $p (split(qr":", $value)) { | | 4203 | foreach my $p (split(qr":", $value)) { |
4197 | my $p_novar = remove_variables($p); | | 4204 | my $p_novar = remove_variables($p); |
4198 | | | 4205 | |
4199 | if ($p_novar !~ m"^[-0-9A-Za-z._~+%/]*$") { | | 4206 | if ($p_novar !~ m"^[-0-9A-Za-z._~+%/]*$") { |
4200 | $line->log_warning("\"${p}\" is not a valid pathname."); | | 4207 | $line->log_warning("\"${p}\" is not a valid pathname."); |
4201 | } | | 4208 | } |
4202 | | | 4209 | |
4203 | if ($p !~ m"^[\$/]") { | | 4210 | if ($p !~ m"^[\$/]") { |
4204 | $line->log_warning("All components of ${varname} (in this case \"${p}\") should be an absolute path."); | | 4211 | $line->log_warning("All components of ${varname} (in this case \"${p}\") should be an absolute path."); |
4205 | } | | 4212 | } |
4206 | } | | 4213 | } |
4207 | } | | 4214 | } |
4208 | }, | | 4215 | }, |
4209 | | | 4216 | |
4210 | Pathmask => sub { | | 4217 | Pathmask => sub { |
4211 | if ($value_novar !~ m"^[#\-0-9A-Za-z._~+%*?/\[\]]*$") { | | 4218 | if ($value_novar !~ m"^[#\-0-9A-Za-z._~+%*?/\[\]]*$") { |
4212 | $line->log_warning("\"${value}\" is not a valid pathname mask."); | | 4219 | $line->log_warning("\"${value}\" is not a valid pathname mask."); |
4213 | } | | 4220 | } |
4214 | checkline_mk_absolute_pathname($line, $value); | | 4221 | checkline_mk_absolute_pathname($line, $value); |
4215 | }, | | 4222 | }, |
4216 | | | 4223 | |
4217 | Pathname => sub { | | 4224 | Pathname => sub { |
4218 | if ($value_novar !~ m"^[#\-0-9A-Za-z._~+%/]*$") { | | 4225 | if ($value_novar !~ m"^[#\-0-9A-Za-z._~+%/]*$") { |
4219 | $line->log_warning("\"${value}\" is not a valid pathname."); | | 4226 | $line->log_warning("\"${value}\" is not a valid pathname."); |
4220 | } | | 4227 | } |
4221 | checkline_mk_absolute_pathname($line, $value); | | 4228 | checkline_mk_absolute_pathname($line, $value); |
4222 | }, | | 4229 | }, |
4223 | | | 4230 | |
4224 | Perl5Packlist => sub { | | 4231 | Perl5Packlist => sub { |
4225 | if ($value ne $value_novar) { | | 4232 | if ($value ne $value_novar) { |
4226 | $line->log_warning("${varname} should not depend on other variables."); | | 4233 | $line->log_warning("${varname} should not depend on other variables."); |
4227 | } | | 4234 | } |
4228 | }, | | 4235 | }, |
4229 | | | 4236 | |
4230 | PkgName => sub { | | 4237 | PkgName => sub { |
4231 | if ($value eq $value_novar && $value !~ regex_pkgname) { | | 4238 | if ($value eq $value_novar && $value !~ regex_pkgname) { |
4232 | $line->log_warning("\"${value}\" is not a valid package name. A valid package name has the form packagename-version, where version consists only of digits, letters and dots."); | | 4239 | $line->log_warning("\"${value}\" is not a valid package name. A valid package name has the form packagename-version, where version consists only of digits, letters and dots."); |
4233 | } | | 4240 | } |
4234 | }, | | 4241 | }, |
4235 | | | 4242 | |
4236 | PkgPath => sub { | | 4243 | PkgPath => sub { |
4237 | checkline_relative_pkgdir($line, "$cur_pkgsrcdir/$value"); | | 4244 | checkline_relative_pkgdir($line, "$cur_pkgsrcdir/$value"); |
4238 | }, | | 4245 | }, |
4239 | | | 4246 | |
4240 | PkgOptionsVar => sub { | | 4247 | PkgOptionsVar => sub { |
4241 | checkline_mk_vartype_basic($line, $varname, "Varname", $op, $value, $comment, false, $is_guessed); | | 4248 | checkline_mk_vartype_basic($line, $varname, "Varname", $op, $value, $comment, false, $is_guessed); |
4242 | if ($value =~ m"\$\{PKGBASE[:\}]") { | | 4249 | if ($value =~ m"\$\{PKGBASE[:\}]") { |
4243 | $line->log_error("PKGBASE must not be used in PKG_OPTIONS_VAR."); | | 4250 | $line->log_error("PKGBASE must not be used in PKG_OPTIONS_VAR."); |
4244 | $line->explain_error( | | 4251 | $line->explain_error( |
4245 | "PKGBASE is defined in bsd.pkg.mk, which is included as the", | | 4252 | "PKGBASE is defined in bsd.pkg.mk, which is included as the", |
4246 | "very last file, but PKG_OPTIONS_VAR is evaluated earlier.", | | 4253 | "very last file, but PKG_OPTIONS_VAR is evaluated earlier.", |
4247 | "Use \${PKGNAME:C/-[0-9].*//} instead."); | | 4254 | "Use \${PKGNAME:C/-[0-9].*//} instead."); |
4248 | } | | 4255 | } |
4249 | }, | | 4256 | }, |
4250 | | | 4257 | |
4251 | PkgRevision => sub { | | 4258 | PkgRevision => sub { |
4252 | if ($value !~ m"^[1-9]\d*$") { | | 4259 | if ($value !~ m"^[1-9]\d*$") { |
4253 | $line->log_warning("${varname} must be a positive integer number."); | | 4260 | $line->log_warning("${varname} must be a positive integer number."); |
4254 | } | | 4261 | } |
4255 | if ($line->fname !~ m"(?:^|/)Makefile$") { | | 4262 | if ($line->fname !~ m"(?:^|/)Makefile$") { |
4256 | $line->log_error("${varname} only makes sense directly in the package Makefile."); | | 4263 | $line->log_error("${varname} only makes sense directly in the package Makefile."); |
4257 | $line->explain_error( | | 4264 | $line->explain_error( |
4258 | "Usually, different packages using the same Makefile.common have", | | 4265 | "Usually, different packages using the same Makefile.common have", |
4259 | "different dependencies and will be bumped at different times (e.g. for", | | 4266 | "different dependencies and will be bumped at different times (e.g. for", |
4260 | "shlib major bumps) and thus the PKGREVISIONs must be in the separate", | | 4267 | "shlib major bumps) and thus the PKGREVISIONs must be in the separate", |
4261 | "Makefiles. There is no practical way of having this information in a", | | 4268 | "Makefiles. There is no practical way of having this information in a", |
4262 | "commonly used Makefile."); | | 4269 | "commonly used Makefile."); |
4263 | } | | 4270 | } |
4264 | }, | | 4271 | }, |
4265 | | | 4272 | |
4266 | PlatformTriple => sub { | | 4273 | PlatformTriple => sub { |
4267 | my $part = qr"(?:\[[^\]]+\]|[^-\[])+"; | | 4274 | my $part = qr"(?:\[[^\]]+\]|[^-\[])+"; |
4268 | if ($value =~ m"^(${part})-(${part})-(${part})$") { | | 4275 | if ($value =~ m"^(${part})-(${part})-(${part})$") { |
4269 | my ($opsys, $os_version, $arch) = ($1, $2, $3); | | 4276 | my ($opsys, $os_version, $arch) = ($1, $2, $3); |
4270 | | | 4277 | |
4271 | if ($opsys !~ m"^(?:\*|BSDOS|Cygwin|Darwin|DragonFly|FreeBSD|Haiku|HPUX|Interix|IRIX|Linux|NetBSD|OpenBSD|OSF1|SunOS)$") { | | 4278 | if ($opsys !~ m"^(?:\*|BSDOS|Cygwin|Darwin|DragonFly|FreeBSD|Haiku|HPUX|Interix|IRIX|Linux|NetBSD|OpenBSD|OSF1|SunOS)$") { |
4272 | $line->log_warning("Unknown operating system: ${opsys}"); | | 4279 | $line->log_warning("Unknown operating system: ${opsys}"); |
4273 | } | | 4280 | } |
4274 | # no check for $os_version | | 4281 | # no check for $os_version |
4275 | if ($arch !~ m"^(?:\*|i386|alpha|amd64|arc|arm|arm32|cobalt|convex|dreamcast|hpcmips|hpcsh|hppa|ia64|m68k|m88k|mips|mips64|mipsel|mipseb|mipsn32|ns32k|pc532|pmax|powerpc|rs6000|s390|sparc|sparc64|vax|x86_64)$") { | | 4282 | if ($arch !~ m"^(?:\*|i386|alpha|amd64|arc|arm|arm32|cobalt|convex|dreamcast|hpcmips|hpcsh|hppa|ia64|m68k|m88k|mips|mips64|mipsel|mipseb|mipsn32|ns32k|pc532|pmax|powerpc|rs6000|s390|sparc|sparc64|vax|x86_64)$") { |
4276 | $line->log_warning("Unknown hardware architecture: ${arch}"); | | 4283 | $line->log_warning("Unknown hardware architecture: ${arch}"); |
4277 | } | | 4284 | } |
4278 | | | 4285 | |
4279 | } else { | | 4286 | } else { |
4280 | $line->log_warning("\"${value}\" is not a valid platform triple."); | | 4287 | $line->log_warning("\"${value}\" is not a valid platform triple."); |
4281 | $line->explain_warning( | | 4288 | $line->explain_warning( |
4282 | "A platform triple has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.", | | 4289 | "A platform triple has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.", |
4283 | "Each of these components may be a shell globbing expression.", | | 4290 | "Each of these components may be a shell globbing expression.", |
4284 | "Examples: NetBSD-*-i386, *-*-*, Linux-*-*."); | | 4291 | "Examples: NetBSD-*-i386, *-*-*, Linux-*-*."); |
4285 | } | | 4292 | } |
4286 | }, | | 4293 | }, |
4287 | | | 4294 | |
4288 | PrefixPathname => sub { | | 4295 | PrefixPathname => sub { |
4289 | if ($value =~ m"^man/(.*)") { | | 4296 | if ($value =~ m"^man/(.*)") { |
4290 | my ($mansubdir) = ($1); | | 4297 | my ($mansubdir) = ($1); |
4291 | | | 4298 | |
4292 | $line->log_warning("Please use \"\${PKGMANDIR}/${mansubdir}\" instead of \"${value}\"."); | | 4299 | $line->log_warning("Please use \"\${PKGMANDIR}/${mansubdir}\" instead of \"${value}\"."); |
4293 | } | | 4300 | } |
4294 | }, | | 4301 | }, |
4295 | | | 4302 | |
4296 | RelativePkgDir => sub { | | 4303 | RelativePkgDir => sub { |
4297 | checkline_relative_pkgdir($line, $value); | | 4304 | checkline_relative_pkgdir($line, $value); |
4298 | }, | | 4305 | }, |
4299 | | | 4306 | |
4300 | RelativePkgPath => sub { | | 4307 | RelativePkgPath => sub { |
4301 | checkline_relative_path($line, $value, true); | | 4308 | checkline_relative_path($line, $value, true); |
4302 | }, | | 4309 | }, |
4303 | | | 4310 | |
4304 | Restricted => sub { | | 4311 | Restricted => sub { |
4305 | if ($value ne "\${RESTRICTED}") { | | 4312 | if ($value ne "\${RESTRICTED}") { |
4306 | $line->log_warning("The only valid value for ${varname} is \${RESTRICTED}."); | | 4313 | $line->log_warning("The only valid value for ${varname} is \${RESTRICTED}."); |
4307 | $line->explain_warning( | | 4314 | $line->explain_warning( |
4308 | "These variables are used to control which files may be mirrored on FTP", | | 4315 | "These variables are used to control which files may be mirrored on FTP", |
4309 | "servers or CD-ROM collections. They are not intended to mark packages", | | 4316 | "servers or CD-ROM collections. They are not intended to mark packages", |
4310 | "whose only MASTER_SITES are on ftp.NetBSD.org."); | | 4317 | "whose only MASTER_SITES are on ftp.NetBSD.org."); |
4311 | } | | 4318 | } |
4312 | }, | | 4319 | }, |
4313 | | | 4320 | |
4314 | SVR4PkgName => sub { | | 4321 | SVR4PkgName => sub { |
4315 | if ($value =~ regex_unresolved) { | | 4322 | if ($value =~ regex_unresolved) { |
4316 | $line->log_error("SVR4_PKGNAME must not contain references to other variables."); | | 4323 | $line->log_error("SVR4_PKGNAME must not contain references to other variables."); |
4317 | } elsif (length($value) > 5) { | | 4324 | } elsif (length($value) > 5) { |
4318 | $line->log_error("SVR4_PKGNAME must not be longer than 5 characters."); | | 4325 | $line->log_error("SVR4_PKGNAME must not be longer than 5 characters."); |
4319 | } | | 4326 | } |
4320 | }, | | 4327 | }, |
4321 | | | 4328 | |
4322 | SedCommand => sub { | | 4329 | SedCommand => sub { |
4323 | }, | | 4330 | }, |
4324 | | | 4331 | |
4325 | SedCommands => sub { | | 4332 | SedCommands => sub { |
4326 | my $words = shell_split($value); | | 4333 | my $words = shell_split($value); |
4327 | if (!$words) { | | 4334 | if (!$words) { |
4328 | $line->log_error("Invalid shell words in sed commands."); | | 4335 | $line->log_error("Invalid shell words in sed commands."); |
4329 | $line->explain_error( | | 4336 | $line->explain_error( |
4330 | "If your sed commands have embedded \"#\" characters, you need to escape", | | 4337 | "If your sed commands have embedded \"#\" characters, you need to escape", |
4331 | "them with a backslash, otherwise make(1) will interpret them as a", | | 4338 | "them with a backslash, otherwise make(1) will interpret them as a", |
4332 | "comment, no matter if they occur in single or double quotes or", | | 4339 | "comment, no matter if they occur in single or double quotes or", |
4333 | "whatever."); | | 4340 | "whatever."); |
4334 | | | 4341 | |
4335 | } else { | | 4342 | } else { |
4336 | my $nwords = scalar(@{$words}); | | 4343 | my $nwords = scalar(@{$words}); |
4337 | my $ncommands = 0; | | 4344 | my $ncommands = 0; |
4338 | | | 4345 | |
4339 | for (my $i = 0; $i < $nwords; $i++) { | | 4346 | for (my $i = 0; $i < $nwords; $i++) { |
4340 | my $word = $words->[$i]; | | 4347 | my $word = $words->[$i]; |
4341 | checkline_mk_shellword($line, $word, true); | | 4348 | checkline_mk_shellword($line, $word, true); |
4342 | | | 4349 | |
4343 | if ($word eq "-e") { | | 4350 | if ($word eq "-e") { |
4344 | if ($i + 1 < $nwords) { | | 4351 | if ($i + 1 < $nwords) { |
4345 | # Check the real sed command here. | | 4352 | # Check the real sed command here. |
4346 | $i++; | | 4353 | $i++; |
4347 | $ncommands++; | | 4354 | $ncommands++; |
4348 | if ($ncommands > 1) { | | 4355 | if ($ncommands > 1) { |
4349 | $line->log_warning("Each sed command should appear in an assignment of its own."); | | 4356 | $line->log_warning("Each sed command should appear in an assignment of its own."); |
4350 | $line->explain_warning( | | 4357 | $line->explain_warning( |
4351 | "For example, instead of", | | 4358 | "For example, instead of", |
4352 | " SUBST_SED.foo+= -e s,command1,, -e s,command2,,", | | 4359 | " SUBST_SED.foo+= -e s,command1,, -e s,command2,,", |
4353 | "use", | | 4360 | "use", |
4354 | " SUBST_SED.foo+= -e s,command1,,", | | 4361 | " SUBST_SED.foo+= -e s,command1,,", |
4355 | " SUBST_SED.foo+= -e s,command2,,", | | 4362 | " SUBST_SED.foo+= -e s,command2,,", |
4356 | "", | | 4363 | "", |
4357 | "This way, short sed commands cannot be hidden at the end of a line."); | | 4364 | "This way, short sed commands cannot be hidden at the end of a line."); |
4358 | } | | 4365 | } |
4359 | checkline_mk_shellword($line, $words->[$i - 1], true); | | 4366 | checkline_mk_shellword($line, $words->[$i - 1], true); |
4360 | checkline_mk_shellword($line, $words->[$i], true); | | 4367 | checkline_mk_shellword($line, $words->[$i], true); |
4361 | checkline_mk_vartype_basic($line, $varname, "SedCommand", $op, $words->[$i], $comment, $list_context, $is_guessed); | | 4368 | checkline_mk_vartype_basic($line, $varname, "SedCommand", $op, $words->[$i], $comment, $list_context, $is_guessed); |
4362 | } else { | | 4369 | } else { |
4363 | $line->log_error("The -e option to sed requires an argument."); | | 4370 | $line->log_error("The -e option to sed requires an argument."); |
4364 | } | | 4371 | } |
4365 | } elsif ($word eq "-E") { | | 4372 | } elsif ($word eq "-E") { |
4366 | # Switch to extended regular expressions mode. | | 4373 | # Switch to extended regular expressions mode. |
4367 | | | 4374 | |
4368 | } elsif ($word eq "-n") { | | 4375 | } elsif ($word eq "-n") { |
4369 | # Don't print lines per default. | | 4376 | # Don't print lines per default. |
4370 | | | 4377 | |
4371 | } elsif ($i == 0 && $word =~ m"^([\"']?)(?:\d*|/.*/)s(.).*\2g?\1$") { | | 4378 | } elsif ($i == 0 && $word =~ m"^([\"']?)(?:\d*|/.*/)s(.).*\2g?\1$") { |
4372 | $line->log_warning("Please always use \"-e\" in sed commands, even if there is only one substitution."); | | 4379 | $line->log_warning("Please always use \"-e\" in sed commands, even if there is only one substitution."); |
4373 | | | 4380 | |
4374 | } else { | | 4381 | } else { |
4375 | $line->log_warning("Unknown sed command ${word}."); | | 4382 | $line->log_warning("Unknown sed command ${word}."); |
4376 | } | | 4383 | } |
4377 | } | | 4384 | } |
4378 | } | | 4385 | } |
4379 | }, | | 4386 | }, |
4380 | | | 4387 | |
4381 | ShellCommand => sub { | | 4388 | ShellCommand => sub { |
4382 | checkline_mk_shelltext($line, $value); | | 4389 | checkline_mk_shelltext($line, $value); |
4383 | }, | | 4390 | }, |
4384 | | | 4391 | |
4385 | ShellWord => sub { | | 4392 | ShellWord => sub { |
4386 | if (!$list_context) { | | 4393 | if (!$list_context) { |
4387 | checkline_mk_shellword($line, $value, true); | | 4394 | checkline_mk_shellword($line, $value, true); |
4388 | } | | 4395 | } |
4389 | }, | | 4396 | }, |
4390 | | | 4397 | |
4391 | Stage => sub { | | 4398 | Stage => sub { |
4392 | if ($value !~ m"^(?:pre|do|post)-(?:extract|patch|configure|build|install)$") { | | 4399 | if ($value !~ m"^(?:pre|do|post)-(?:extract|patch|configure|build|install)$") { |
4393 | $line->log_warning("Invalid stage name. Use one of {pre,do,post}-{extract,patch,configure,build,install}."); | | 4400 | $line->log_warning("Invalid stage name. Use one of {pre,do,post}-{extract,patch,configure,build,install}."); |
4394 | } | | 4401 | } |
4395 | }, | | 4402 | }, |
4396 | | | 4403 | |
4397 | String => sub { | | 4404 | String => sub { |
4398 | # No further checks possible. | | 4405 | # No further checks possible. |
4399 | }, | | 4406 | }, |
4400 | | | 4407 | |
4401 | Tool => sub { | | 4408 | Tool => sub { |
4402 | if ($value =~ m"^([-\w]+|\[)(?::(\w+))?$") { | | 4409 | if ($varname eq "TOOLS_NOOP" && $op eq "+=") { |
| | | 4410 | # no warning for package-defined tool definitions |
| | | 4411 | |
| | | 4412 | } elsif ($value =~ m"^([-\w]+|\[)(?::(\w+))?$") { |
4403 | my ($toolname, $tooldep) = ($1, $2); | | 4413 | my ($toolname, $tooldep) = ($1, $2); |
4404 | if (!exists(get_tool_names()->{$toolname})) { | | 4414 | if (!exists(get_tool_names()->{$toolname})) { |
4405 | $line->log_error("Unknown tool \"${toolname}\"."); | | 4415 | $line->log_error("Unknown tool \"${toolname}\"."); |
4406 | } | | 4416 | } |
4407 | if (defined($tooldep) && $tooldep !~ m"^(?:bootstrap|build|pkgsrc|run)$") { | | 4417 | if (defined($tooldep) && $tooldep !~ m"^(?:bootstrap|build|pkgsrc|run)$") { |
4408 | $line->log_error("Unknown tool dependency \"${tooldep}\". Use one of \"build\", \"pkgsrc\" or \"run\"."); | | 4418 | $line->log_error("Unknown tool dependency \"${tooldep}\". Use one of \"build\", \"pkgsrc\" or \"run\"."); |
4409 | } | | 4419 | } |
4410 | } else { | | 4420 | } else { |
4411 | $line->log_error("Invalid tool syntax: \"${value}\"."); | | 4421 | $line->log_error("Invalid tool syntax: \"${value}\"."); |
4412 | } | | 4422 | } |
4413 | }, | | 4423 | }, |
4414 | | | 4424 | |
4415 | Unchecked => sub { | | 4425 | Unchecked => sub { |
4416 | # Do nothing, as the name says. | | 4426 | # Do nothing, as the name says. |
4417 | }, | | 4427 | }, |
4418 | | | 4428 | |
4419 | URL => sub { | | 4429 | URL => sub { |
4420 | if ($value eq "" && defined($comment) && $comment =~ m"^#") { | | 4430 | if ($value eq "" && defined($comment) && $comment =~ m"^#") { |
4421 | # Ok | | 4431 | # Ok |
4422 | | | 4432 | |
4423 | } elsif ($value =~ m"\$\{(MASTER_SITE_[^:]*).*:=(.*)\}$") { | | 4433 | } elsif ($value =~ m"\$\{(MASTER_SITE_[^:]*).*:=(.*)\}$") { |
4424 | my ($name, $subdir) = ($1, $2); | | 4434 | my ($name, $subdir) = ($1, $2); |
4425 | | | 4435 | |
4426 | if (!exists(get_dist_sites_names()->{$name})) { | | 4436 | if (!exists(get_dist_sites_names()->{$name})) { |
4427 | $line->log_error("${name} does not exist."); | | 4437 | $line->log_error("${name} does not exist."); |
4428 | } | | 4438 | } |
4429 | if ($subdir !~ m"/$") { | | 4439 | if ($subdir !~ m"/$") { |
4430 | $line->log_error("The subdirectory in ${name} must end with a slash."); | | 4440 | $line->log_error("The subdirectory in ${name} must end with a slash."); |
4431 | } | | 4441 | } |
4432 | | | 4442 | |
4433 | } elsif ($value =~ regex_unresolved) { | | 4443 | } elsif ($value =~ regex_unresolved) { |
4434 | # No further checks | | 4444 | # No further checks |
4435 | | | 4445 | |
4436 | } elsif ($value =~ m"^(https?|ftp|gopher)://([-0-9A-Za-z.]+)(?::(\d+))?/([-%&+,./0-9:=?\@A-Z_a-z~]|#)*$") { | | 4446 | } elsif ($value =~ m"^(https?|ftp|gopher)://([-0-9A-Za-z.]+)(?::(\d+))?/([-%&+,./0-9:=?\@A-Z_a-z~]|#)*$") { |
4437 | my ($proto, $host, $port, $path) = ($1, $2, $3, $4); | | 4447 | my ($proto, $host, $port, $path) = ($1, $2, $3, $4); |
4438 | my $sites = get_dist_sites(); | | 4448 | my $sites = get_dist_sites(); |
4439 | | | 4449 | |
4440 | if ($host =~ m"\.NetBSD\.org$"i && $host !~ m"\.NetBSD\.org$") { | | 4450 | if ($host =~ m"\.NetBSD\.org$"i && $host !~ m"\.NetBSD\.org$") { |
4441 | $line->log_warning("Please write NetBSD.org instead of ${host}."); | | 4451 | $line->log_warning("Please write NetBSD.org instead of ${host}."); |
4442 | } | | 4452 | } |
4443 | | | 4453 | |
4444 | foreach my $site (keys(%{$sites})) { | | 4454 | foreach my $site (keys(%{$sites})) { |
4445 | if (index($value, $site) == 0) { | | 4455 | if (index($value, $site) == 0) { |
4446 | my $subdir = substr($value, length($site)); | | 4456 | my $subdir = substr($value, length($site)); |
4447 | $line->log_warning(sprintf("Please use \${%s:=%s} instead of \"%s\".", $sites->{$site}, $subdir, $value)); | | 4457 | $line->log_warning(sprintf("Please use \${%s:=%s} instead of \"%s\".", $sites->{$site}, $subdir, $value)); |
4448 | last; | | 4458 | last; |
4449 | } | | 4459 | } |
4450 | } | | 4460 | } |
4451 | | | 4461 | |
4452 | } elsif ($value =~ m"^([0-9A-Za-z]+)://([^/]+)(.*)$") { | | 4462 | } elsif ($value =~ m"^([0-9A-Za-z]+)://([^/]+)(.*)$") { |
4453 | my ($scheme, $host, $abs_path) = ($1, $2, $3); | | 4463 | my ($scheme, $host, $abs_path) = ($1, $2, $3); |
4454 | | | 4464 | |
4455 | if ($scheme ne "ftp" && $scheme ne "http" && $scheme ne "gopher") { | | 4465 | if ($scheme ne "ftp" && $scheme ne "http" && $scheme ne "gopher") { |
4456 | $line->log_warning("\"${value}\" is not a valid URL. Only http, ftp and gopher URLs are allowed here."); | | 4466 | $line->log_warning("\"${value}\" is not a valid URL. Only http, ftp and gopher URLs are allowed here."); |
4457 | | | 4467 | |
4458 | } elsif ($abs_path eq "") { | | 4468 | } elsif ($abs_path eq "") { |
4459 | $line->log_note("For consistency, please add a trailing slash to \"${value}\"."); | | 4469 | $line->log_note("For consistency, please add a trailing slash to \"${value}\"."); |
4460 | | | 4470 | |
4461 | } else { | | 4471 | } else { |
4462 | $line->log_warning("\"${value}\" is not a valid URL."); | | 4472 | $line->log_warning("\"${value}\" is not a valid URL."); |
4463 | } | | 4473 | } |
4464 | | | 4474 | |
4465 | } else { | | 4475 | } else { |
4466 | $line->log_warning("\"${value}\" is not a valid URL."); | | 4476 | $line->log_warning("\"${value}\" is not a valid URL."); |
4467 | } | | 4477 | } |
4468 | }, | | 4478 | }, |
4469 | | | 4479 | |
4470 | UserGroupName => sub { | | 4480 | UserGroupName => sub { |
4471 | if ($value ne $value_novar) { | | 4481 | if ($value ne $value_novar) { |
4472 | # No checks for now. | | 4482 | # No checks for now. |
4473 | } elsif ($value !~ m"^[0-9_a-z]+$") { | | 4483 | } elsif ($value !~ m"^[0-9_a-z]+$") { |
4474 | $line->log_warning("Invalid user or group name \"${value}\"."); | | 4484 | $line->log_warning("Invalid user or group name \"${value}\"."); |
4475 | } | | 4485 | } |
4476 | }, | | 4486 | }, |
4477 | | | 4487 | |
4478 | Varname => sub { | | 4488 | Varname => sub { |
4479 | if ($value ne "" && $value_novar eq "") { | | 4489 | if ($value ne "" && $value_novar eq "") { |
4480 | # The value of another variable | | 4490 | # The value of another variable |
4481 | | | 4491 | |
4482 | } elsif ($value_novar !~ m"^[A-Z_][0-9A-Z_]*(?:[.].*)?$") { | | 4492 | } elsif ($value_novar !~ m"^[A-Z_][0-9A-Z_]*(?:[.].*)?$") { |
4483 | $line->log_warning("\"${value}\" is not a valid variable name."); | | 4493 | $line->log_warning("\"${value}\" is not a valid variable name."); |
4484 | } | | 4494 | } |
4485 | }, | | 4495 | }, |
4486 | | | 4496 | |
4487 | Version => sub { | | 4497 | Version => sub { |
4488 | if ($value !~ m"^([\d.])+$") { | | 4498 | if ($value !~ m"^([\d.])+$") { |
4489 | $line->log_warning("Invalid version number \"${value}\"."); | | 4499 | $line->log_warning("Invalid version number \"${value}\"."); |
4490 | } | | 4500 | } |
4491 | }, | | 4501 | }, |
4492 | | | 4502 | |
4493 | WrapperReorder => sub { | | 4503 | WrapperReorder => sub { |
4494 | if ($value =~ m"^reorder:l:([\w\-]+):([\w\-]+)$") { | | 4504 | if ($value =~ m"^reorder:l:([\w\-]+):([\w\-]+)$") { |
4495 | my ($lib1, $lib2) = ($1, $2); | | 4505 | my ($lib1, $lib2) = ($1, $2); |
4496 | # Fine. | | 4506 | # Fine. |
4497 | } else { | | 4507 | } else { |
4498 | $line->log_warning("Unknown wrapper reorder command \"${value}\"."); | | 4508 | $line->log_warning("Unknown wrapper reorder command \"${value}\"."); |
4499 | } | | 4509 | } |
4500 | }, | | 4510 | }, |
4501 | | | 4511 | |
4502 | WrapperTransform => sub { | | 4512 | WrapperTransform => sub { |
4503 | if ($value =~ m"^rm:(?:-[DILOUWflm].*|-std=.*)$") { | | 4513 | if ($value =~ m"^rm:(?:-[DILOUWflm].*|-std=.*)$") { |
4504 | # Fine. | | 4514 | # Fine. |
4505 | | | 4515 | |
4506 | } elsif ($value =~ m"^l:([^:]+):(.+)$") { | | 4516 | } elsif ($value =~ m"^l:([^:]+):(.+)$") { |
4507 | my ($lib, $replacement_libs) = ($1, $2); | | 4517 | my ($lib, $replacement_libs) = ($1, $2); |
4508 | # Fine. | | 4518 | # Fine. |
4509 | | | 4519 | |
4510 | } elsif ($value =~ m"^'?(?:opt|rename|rm-optarg|rmdir):.*$") { | | 4520 | } elsif ($value =~ m"^'?(?:opt|rename|rm-optarg|rmdir):.*$") { |
4511 | # FIXME: This is cheated. | | 4521 | # FIXME: This is cheated. |
4512 | # Fine. | | 4522 | # Fine. |
4513 | | | 4523 | |
4514 | } elsif ($value eq "-e" || $value =~ m"^\"?'?s[|:,]") { | | 4524 | } elsif ($value eq "-e" || $value =~ m"^\"?'?s[|:,]") { |
4515 | # FIXME: This is cheated. | | 4525 | # FIXME: This is cheated. |
4516 | # Fine. | | 4526 | # Fine. |
4517 | | | 4527 | |
4518 | } else { | | 4528 | } else { |
4519 | $line->log_warning("Unknown wrapper transform command \"${value}\"."); | | 4529 | $line->log_warning("Unknown wrapper transform command \"${value}\"."); |
4520 | } | | 4530 | } |
4521 | }, | | 4531 | }, |
4522 | | | 4532 | |
4523 | WrkdirSubdirectory => sub { | | 4533 | WrkdirSubdirectory => sub { |
4524 | checkline_mk_vartype_basic($line, $varname, "Pathname", $op, $value, $comment, $list_context, $is_guessed); | | 4534 | checkline_mk_vartype_basic($line, $varname, "Pathname", $op, $value, $comment, $list_context, $is_guessed); |
4525 | if ($value eq "\${WRKDIR}") { | | 4535 | if ($value eq "\${WRKDIR}") { |
4526 | # Fine. | | 4536 | # Fine. |
4527 | } else { | | 4537 | } else { |
4528 | $opt_debug_unchecked and $line->log_debug("Unchecked subdirectory \"${value}\" of \${WRKDIR}."); | | 4538 | $opt_debug_unchecked and $line->log_debug("Unchecked subdirectory \"${value}\" of \${WRKDIR}."); |
4529 | } | | 4539 | } |
4530 | }, | | 4540 | }, |
4531 | | | 4541 | |
4532 | WrksrcSubdirectory => sub { | | 4542 | WrksrcSubdirectory => sub { |
4533 | if ($value =~ m"^(\$\{WRKSRC\})(?:/(.*))?") { | | 4543 | if ($value =~ m"^(\$\{WRKSRC\})(?:/(.*))?") { |
4534 | my ($prefix, $rest) = ($1, $2); | | 4544 | my ($prefix, $rest) = ($1, $2); |
4535 | $line->log_note("You can use \"" . (defined($rest) ? $rest : ".") . "\" instead of \"${value}\"."); | | 4545 | $line->log_note("You can use \"" . (defined($rest) ? $rest : ".") . "\" instead of \"${value}\"."); |
4536 | | | 4546 | |
4537 | } elsif ($value ne "" && $value_novar eq "") { | | 4547 | } elsif ($value ne "" && $value_novar eq "") { |
4538 | # The value of another variable | | 4548 | # The value of another variable |
4539 | | | 4549 | |
4540 | } elsif ($value_novar !~ m"^(?:\.|[0-9A-Za-z_\@][-0-9A-Za-z_\@./+]*)$") { | | 4550 | } elsif ($value_novar !~ m"^(?:\.|[0-9A-Za-z_\@][-0-9A-Za-z_\@./+]*)$") { |
4541 | $line->log_warning("\"${value}\" is not a valid subdirectory of \${WRKSRC}."); | | 4551 | $line->log_warning("\"${value}\" is not a valid subdirectory of \${WRKSRC}."); |
4542 | } | | 4552 | } |
4543 | }, | | 4553 | }, |
4544 | | | 4554 | |
4545 | Yes => sub { | | 4555 | Yes => sub { |
4546 | if ($value !~ m"^(?:YES|yes)(?:\s+#.*)?$") { | | 4556 | if ($value !~ m"^(?:YES|yes)(?:\s+#.*)?$") { |
4547 | $line->log_warning("${varname} should be set to YES or yes."); | | 4557 | $line->log_warning("${varname} should be set to YES or yes."); |
4548 | $line->explain_warning( | | 4558 | $line->explain_warning( |
4549 | "This variable means \"yes\" if it is defined, and \"no\" if it is", | | 4559 | "This variable means \"yes\" if it is defined, and \"no\" if it is", |
4550 | "undefined. Even when it has the value \"no\", this means \"yes\".", | | 4560 | "undefined. Even when it has the value \"no\", this means \"yes\".", |
4551 | "Therefore when it is defined, its value should correspond to its", | | 4561 | "Therefore when it is defined, its value should correspond to its", |
4552 | "meaning."); | | 4562 | "meaning."); |
4553 | } | | 4563 | } |
4554 | }, | | 4564 | }, |
4555 | | | 4565 | |
4556 | YesNo => sub { | | 4566 | YesNo => sub { |
4557 | if ($value !~ m"^(?:YES|yes|NO|no)(?:\s+#.*)?$") { | | 4567 | if ($value !~ m"^(?:YES|yes|NO|no)(?:\s+#.*)?$") { |
4558 | $line->log_warning("${varname} should be set to YES, yes, NO, or no."); | | 4568 | $line->log_warning("${varname} should be set to YES, yes, NO, or no."); |
4559 | } | | 4569 | } |
4560 | }, | | 4570 | }, |
4561 | | | 4571 | |
4562 | YesNo_Indirectly => sub { | | 4572 | YesNo_Indirectly => sub { |
4563 | if ($value_novar ne "" && $value !~ m"^(?:YES|yes|NO|no)(?:\s+#.*)?$") { | | 4573 | if ($value_novar ne "" && $value !~ m"^(?:YES|yes|NO|no)(?:\s+#.*)?$") { |
4564 | $line->log_warning("${varname} should be set to YES, yes, NO, or no."); | | 4574 | $line->log_warning("${varname} should be set to YES, yes, NO, or no."); |
4565 | } | | 4575 | } |
4566 | }, | | 4576 | }, |
4567 | ); | | 4577 | ); |
4568 | | | 4578 | |
4569 | if (ref($type) eq "HASH") { | | 4579 | if (ref($type) eq "HASH") { |
4570 | if (!exists($type->{$value})) { | | 4580 | if (!exists($type->{$value})) { |
4571 | $line->log_warning("\"${value}\" is not valid for ${varname}. Use one of { ".join(" ", sort(keys(%{$type})))." } instead."); | | 4581 | $line->log_warning("\"${value}\" is not valid for ${varname}. Use one of { ".join(" ", sort(keys(%{$type})))." } instead."); |
4572 | } | | 4582 | } |
4573 | | | 4583 | |
4574 | } elsif (defined $type_dispatch{$type}) { | | 4584 | } elsif (defined $type_dispatch{$type}) { |
4575 | $type_dispatch{$type}->(); | | 4585 | $type_dispatch{$type}->(); |
4576 | | | 4586 | |
4577 | } else { | | 4587 | } else { |
4578 | $line->log_fatal("Type ${type} unknown."); | | 4588 | $line->log_fatal("Type ${type} unknown."); |
4579 | } | | 4589 | } |
4580 | } | | 4590 | } |
4581 | | | 4591 | |
4582 | # Checks whether the list of version numbers that are given as the | | 4592 | # Checks whether the list of version numbers that are given as the |
4583 | # C<value> of the variable C<varname> are in decreasing order. | | 4593 | # C<value> of the variable C<varname> are in decreasing order. |
4584 | sub checkline_decreasing_order($$$) { | | 4594 | sub checkline_decreasing_order($$$) { |
4585 | my ($line, $varname, $value) = @_; | | 4595 | my ($line, $varname, $value) = @_; |
4586 | | | 4596 | |
4587 | my @pyver = split(qr"\s+", $value); | | 4597 | my @pyver = split(qr"\s+", $value); |
4588 | if (!@pyver) { | | 4598 | if (!@pyver) { |
4589 | $line->log_error("There must be at least one value for ${varname}."); | | 4599 | $line->log_error("There must be at least one value for ${varname}."); |
4590 | return; | | 4600 | return; |
4591 | } | | 4601 | } |
4592 | | | 4602 | |
4593 | my $ver = shift(@pyver); | | 4603 | my $ver = shift(@pyver); |
4594 | if ($ver !~ m"^\d+$") { | | 4604 | if ($ver !~ m"^\d+$") { |
4595 | $line->log_error("All values for ${varname} must be numeric."); | | 4605 | $line->log_error("All values for ${varname} must be numeric."); |
4596 | return; | | 4606 | return; |
4597 | } | | 4607 | } |
4598 | | | 4608 | |
4599 | while (@pyver) { | | 4609 | while (@pyver) { |
4600 | my $nextver = shift(@pyver); | | 4610 | my $nextver = shift(@pyver); |
4601 | if ($nextver !~ m"^\d+$") { | | 4611 | if ($nextver !~ m"^\d+$") { |
4602 | $line->log_error("All values for ${varname} must be numeric."); | | 4612 | $line->log_error("All values for ${varname} must be numeric."); |
4603 | return; | | 4613 | return; |
4604 | } | | 4614 | } |
4605 | | | 4615 | |
4606 | if ($nextver >= $ver) { | | 4616 | if ($nextver >= $ver) { |
4607 | $line->log_warning("The values for ${varname} should be in decreasing order."); | | 4617 | $line->log_warning("The values for ${varname} should be in decreasing order."); |
4608 | $line->explain_warning( | | 4618 | $line->explain_warning( |
4609 | "If they aren't, it may be possible that needless versions of packages", | | 4619 | "If they aren't, it may be possible that needless versions of packages", |
4610 | "are installed."); | | 4620 | "are installed."); |
4611 | } | | 4621 | } |
4612 | $ver = $nextver; | | 4622 | $ver = $nextver; |
4613 | } | | 4623 | } |
4614 | } | | 4624 | } |
4615 | | | 4625 | |
4616 | sub checkline_mk_vartype($$$$$) { | | 4626 | sub checkline_mk_vartype($$$$$) { |
4617 | my ($line, $varname, $op, $value, $comment) = @_; | | 4627 | my ($line, $varname, $op, $value, $comment) = @_; |
4618 | | | 4628 | |
4619 | return unless $opt_warn_types; | | 4629 | return unless $opt_warn_types; |
4620 | | | 4630 | |
4621 | my $vartypes = get_vartypes_map(); | | 4631 | my $vartypes = get_vartypes_map(); |
4622 | my $varbase = varname_base($varname); | | 4632 | my $varbase = varname_base($varname); |
4623 | my $varcanon = varname_canon($varname); | | 4633 | my $varcanon = varname_canon($varname); |
4624 | | | 4634 | |
4625 | my $type = get_variable_type($line, $varname); | | 4635 | my $type = get_variable_type($line, $varname); |
4626 | | | 4636 | |
4627 | if ($op eq "+=") { | | 4637 | if ($op eq "+=") { |
4628 | if (defined($type)) { | | 4638 | if (defined($type)) { |
4629 | if (!$type->may_use_plus_eq()) { | | 4639 | if (!$type->may_use_plus_eq()) { |
4630 | $line->log_warning("The \"+=\" operator should only be used with lists."); | | 4640 | $line->log_warning("The \"+=\" operator should only be used with lists."); |
4631 | } | | 4641 | } |
4632 | } elsif ($varbase !~ m"^_" && $varbase !~ get_regex_plurals()) { | | 4642 | } elsif ($varbase !~ m"^_" && $varbase !~ get_regex_plurals()) { |
4633 | $line->log_warning("As ${varname} is modified using \"+=\", its name should indicate plural."); | | 4643 | $line->log_warning("As ${varname} is modified using \"+=\", its name should indicate plural."); |
4634 | } | | 4644 | } |
4635 | } | | 4645 | } |
4636 | | | 4646 | |
4637 | if (!defined($type)) { | | 4647 | if (!defined($type)) { |
4638 | # Cannot check anything if the type is not known. | | 4648 | # Cannot check anything if the type is not known. |
4639 | $opt_debug_unchecked and $line->log_debug("Unchecked variable assignment for ${varname}."); | | 4649 | $opt_debug_unchecked and $line->log_debug("Unchecked variable assignment for ${varname}."); |
4640 | | | 4650 | |
4641 | } elsif ($op eq "!=") { | | 4651 | } elsif ($op eq "!=") { |
4642 | $opt_debug_misc and $line->log_debug("Use of !=: ${value}"); | | 4652 | $opt_debug_misc and $line->log_debug("Use of !=: ${value}"); |
4643 | | | 4653 | |
4644 | } elsif ($type->kind_of_list != LK_NONE) { | | 4654 | } elsif ($type->kind_of_list != LK_NONE) { |
4645 | my (@words, $rest); | | 4655 | my (@words, $rest); |
4646 | | | 4656 | |
4647 | if ($type->kind_of_list == LK_INTERNAL) { | | 4657 | if ($type->kind_of_list == LK_INTERNAL) { |
4648 | @words = split(qr"\s+", $value); | | 4658 | @words = split(qr"\s+", $value); |
4649 | $rest = ""; | | 4659 | $rest = ""; |
4650 | } else { | | 4660 | } else { |
4651 | @words = (); | | 4661 | @words = (); |
4652 | $rest = $value; | | 4662 | $rest = $value; |
4653 | while ($rest =~ s/^$regex_shellword//) { | | 4663 | while ($rest =~ s/^$regex_shellword//) { |
4654 | my ($word) = ($1); | | 4664 | my ($word) = ($1); |
4655 | last if ($word =~ m"^#"); | | 4665 | last if ($word =~ m"^#"); |
4656 | push(@words, $1); | | 4666 | push(@words, $1); |
4657 | } | | 4667 | } |
4658 | } | | 4668 | } |
4659 | | | 4669 | |
4660 | foreach my $word (@words) { | | 4670 | foreach my $word (@words) { |
4661 | checkline_mk_vartype_basic($line, $varname, $type->basic_type, $op, $word, $comment, true, $type->is_guessed); | | 4671 | checkline_mk_vartype_basic($line, $varname, $type->basic_type, $op, $word, $comment, true, $type->is_guessed); |
4662 | if ($type->kind_of_list != LK_INTERNAL) { | | 4672 | if ($type->kind_of_list != LK_INTERNAL) { |
4663 | checkline_mk_shellword($line, $word, true); | | 4673 | checkline_mk_shellword($line, $word, true); |
4664 | } | | 4674 | } |
4665 | } | | 4675 | } |
4666 | | | 4676 | |
4667 | if ($rest !~ m"^\s*$") { | | 4677 | if ($rest !~ m"^\s*$") { |
4668 | $line->log_error("Internal pkglint error: rest=${rest}"); | | 4678 | $line->log_error("Internal pkglint error: rest=${rest}"); |
4669 | } | | 4679 | } |
4670 | | | 4680 | |
4671 | } else { | | 4681 | } else { |
4672 | checkline_mk_vartype_basic($line, $varname, $type->basic_type, $op, $value, $comment, $type->is_practically_a_list(), $type->is_guessed); | | 4682 | checkline_mk_vartype_basic($line, $varname, $type->basic_type, $op, $value, $comment, $type->is_practically_a_list(), $type->is_guessed); |
4673 | } | | 4683 | } |
4674 | } | | 4684 | } |
4675 | | | 4685 | |
4676 | sub checkline_mk_varassign($$$$$) { | | 4686 | sub checkline_mk_varassign($$$$$) { |
4677 | my ($line, $varname, $op, $value, $comment) = @_; | | 4687 | my ($line, $varname, $op, $value, $comment) = @_; |
4678 | my ($used_vars); | | 4688 | my ($used_vars); |
4679 | my $varbase = varname_base($varname); | | 4689 | my $varbase = varname_base($varname); |
4680 | my $varcanon = varname_canon($varname); | | 4690 | my $varcanon = varname_canon($varname); |
4681 | | | 4691 | |
4682 | $opt_debug_trace and $line->log_debug("checkline_mk_varassign($varname, $op, $value)"); | | 4692 | $opt_debug_trace and $line->log_debug("checkline_mk_varassign($varname, $op, $value)"); |
4683 | | | 4693 | |
4684 | checkline_mk_vardef($line, $varname, $op); | | 4694 | checkline_mk_vardef($line, $varname, $op); |
4685 | | | 4695 | |
4686 | if ($op eq "?=" && defined($seen_bsd_prefs_mk) && !$seen_bsd_prefs_mk) { | | 4696 | if ($op eq "?=" && defined($seen_bsd_prefs_mk) && !$seen_bsd_prefs_mk) { |
4687 | if ($varbase eq "BUILDLINK_PKGSRCDIR" | | 4697 | if ($varbase eq "BUILDLINK_PKGSRCDIR" |
4688 | || $varbase eq "BUILDLINK_DEPMETHOD" | | 4698 | || $varbase eq "BUILDLINK_DEPMETHOD" |
4689 | || $varbase eq "BUILDLINK_ABI_DEPENDS") { | | 4699 | || $varbase eq "BUILDLINK_ABI_DEPENDS") { |
4690 | # FIXME: What about these ones? They occur quite often. | | 4700 | # FIXME: What about these ones? They occur quite often. |
4691 | } else { | | 4701 | } else { |
4692 | $opt_warn_extra and $line->log_warning("Please include \"../../mk/bsd.prefs.mk\" before using \"?=\"."); | | 4702 | $opt_warn_extra and $line->log_warning("Please include \"../../mk/bsd.prefs.mk\" before using \"?=\"."); |
4693 | $opt_warn_extra and $line->explain_warning( | | 4703 | $opt_warn_extra and $line->explain_warning( |
4694 | "The ?= operator is used to provide a default value to a variable. In", | | 4704 | "The ?= operator is used to provide a default value to a variable. In", |
4695 | "pkgsrc, many variables can be set by the pkgsrc user in the mk.conf", | | 4705 | "pkgsrc, many variables can be set by the pkgsrc user in the mk.conf", |
4696 | "file. This file must be included explicitly. If a ?= operator appears", | | 4706 | "file. This file must be included explicitly. If a ?= operator appears", |
4697 | "before mk.conf has been included, it will not care about the user's", | | 4707 | "before mk.conf has been included, it will not care about the user's", |
4698 | "preferences, which can result in unexpected behavior. The easiest way", | | 4708 | "preferences, which can result in unexpected behavior. The easiest way", |
4699 | "to include the mk.conf file is by including the bsd.prefs.mk file,", | | 4709 | "to include the mk.conf file is by including the bsd.prefs.mk file,", |
4700 | "which will take care of everything."); | | 4710 | "which will take care of everything."); |
4701 | } | | 4711 | } |
4702 | } | | 4712 | } |
4703 | | | 4713 | |
4704 | checkline_mk_text($line, $value); | | 4714 | checkline_mk_text($line, $value); |
4705 | checkline_mk_vartype($line, $varname, $op, $value, $comment); | | 4715 | checkline_mk_vartype($line, $varname, $op, $value, $comment); |
4706 | | | 4716 | |
4707 | # If the variable is not used and is untyped, it may be a | | 4717 | # If the variable is not used and is untyped, it may be a |
4708 | # spelling mistake. | | 4718 | # spelling mistake. |
4709 | if ($op eq ":=" && $varname eq lc($varname)) { | | 4719 | if ($op eq ":=" && $varname eq lc($varname)) { |
4710 | $opt_debug_unchecked and $line->log_debug("${varname} might be unused unless it is an argument to a procedure file."); | | 4720 | $opt_debug_unchecked and $line->log_debug("${varname} might be unused unless it is an argument to a procedure file."); |
4711 | # TODO: check $varname against the list of "procedure files". | | 4721 | # TODO: check $varname against the list of "procedure files". |
4712 | | | 4722 | |
4713 | } elsif (!var_is_used($varname)) { | | 4723 | } elsif (!var_is_used($varname)) { |
4714 | my $vartypes = get_vartypes_map(); | | 4724 | my $vartypes = get_vartypes_map(); |
4715 | my $deprecated = get_deprecated_map(); | | 4725 | my $deprecated = get_deprecated_map(); |
4716 | | | 4726 | |
4717 | if (exists($vartypes->{$varname}) || exists($vartypes->{$varcanon})) { | | 4727 | if (exists($vartypes->{$varname}) || exists($vartypes->{$varcanon})) { |
4718 | # Ok | | 4728 | # Ok |
4719 | } elsif (exists($deprecated->{$varname}) || exists($deprecated->{$varcanon})) { | | 4729 | } elsif (exists($deprecated->{$varname}) || exists($deprecated->{$varcanon})) { |
4720 | # Ok | | 4730 | # Ok |
4721 | } else { | | 4731 | } else { |
4722 | $line->log_warning("${varname} is defined but not used. Spelling mistake?"); | | 4732 | $line->log_warning("${varname} is defined but not used. Spelling mistake?"); |
4723 | } | | 4733 | } |
4724 | } | | 4734 | } |
4725 | | | 4735 | |
4726 | if ($value =~ m"/etc/rc\.d") { | | 4736 | if ($value =~ m"/etc/rc\.d") { |
4727 | $line->log_warning("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to \${RCD_SCRIPTS_EXAMPLEDIR}."); | | 4737 | $line->log_warning("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to \${RCD_SCRIPTS_EXAMPLEDIR}."); |
4728 | } | | 4738 | } |
4729 | | | 4739 | |
4730 | if (!$is_internal && $varname =~ m"^_") { | | 4740 | if (!$is_internal && $varname =~ m"^_") { |
4731 | $line->log_warning("Variable names starting with an underscore are reserved for internal pkgsrc use."); | | 4741 | $line->log_warning("Variable names starting with an underscore are reserved for internal pkgsrc use."); |
4732 | } | | 4742 | } |
4733 | | | 4743 | |
4734 | if ($varname eq "PERL5_PACKLIST" && defined($effective_pkgbase) && $effective_pkgbase =~ m"^p5-(.*)") { | | 4744 | if ($varname eq "PERL5_PACKLIST" && defined($effective_pkgbase) && $effective_pkgbase =~ m"^p5-(.*)") { |
4735 | my ($guess) = ($1); | | 4745 | my ($guess) = ($1); |
4736 | $guess =~ s/-/\//g; | | 4746 | $guess =~ s/-/\//g; |
4737 | $guess = "auto/${guess}/.packlist"; | | 4747 | $guess = "auto/${guess}/.packlist"; |
4738 | | | 4748 | |
4739 | my ($ucvalue, $ucguess) = (uc($value), uc($guess)); | | 4749 | my ($ucvalue, $ucguess) = (uc($value), uc($guess)); |
4740 | if ($ucvalue ne $ucguess && $ucvalue ne "\${PERL5_SITEARCH\}/${ucguess}") { | | 4750 | if ($ucvalue ne $ucguess && $ucvalue ne "\${PERL5_SITEARCH\}/${ucguess}") { |
4741 | $line->log_warning("Unusual value for PERL5_PACKLIST -- \"${guess}\" expected."); | | 4751 | $line->log_warning("Unusual value for PERL5_PACKLIST -- \"${guess}\" expected."); |
4742 | } | | 4752 | } |
4743 | } | | 4753 | } |
4744 | | | 4754 | |
4745 | if ($varname eq "CONFIGURE_ARGS" && $value =~ m"=\$\{PREFIX\}/share/kde") { | | 4755 | if ($varname eq "CONFIGURE_ARGS" && $value =~ m"=\$\{PREFIX\}/share/kde") { |
4746 | $line->log_note("Please .include \"../../meta-pkgs/kde3/kde3.mk\" instead of this line."); | | 4756 | $line->log_note("Please .include \"../../meta-pkgs/kde3/kde3.mk\" instead of this line."); |
4747 | $line->explain_note( | | 4757 | $line->explain_note( |
4748 | "That file probably does many things automatically and consistently that", | | 4758 | "That file probably does many things automatically and consistently that", |
4749 | "this package also does. When using kde3.mk, you can probably also leave", | | 4759 | "this package also does. When using kde3.mk, you can probably also leave", |
4750 | "out some explicit dependencies."); | | 4760 | "out some explicit dependencies."); |
4751 | } | | 4761 | } |
4752 | | | 4762 | |
4753 | if ($varname eq "EVAL_PREFIX" && $value =~ m"^([\w_]+)=") { | | 4763 | if ($varname eq "EVAL_PREFIX" && $value =~ m"^([\w_]+)=") { |
4754 | my ($eval_varname) = ($1); | | 4764 | my ($eval_varname) = ($1); |
4755 | | | 4765 | |
4756 | # The variables mentioned in EVAL_PREFIX will later be | | 4766 | # The variables mentioned in EVAL_PREFIX will later be |
4757 | # defined by find-prefix.mk. Therefore, they are marked | | 4767 | # defined by find-prefix.mk. Therefore, they are marked |
4758 | # as known in the current file. | | 4768 | # as known in the current file. |
4759 | $mkctx_vardef->{$eval_varname} = $line; | | 4769 | $mkctx_vardef->{$eval_varname} = $line; |
4760 | } | | 4770 | } |
4761 | | | 4771 | |
4762 | if ($varname eq "PYTHON_VERSIONS_ACCEPTED") { | | 4772 | if ($varname eq "PYTHON_VERSIONS_ACCEPTED") { |
4763 | checkline_decreasing_order($line, $varname, $value); | | 4773 | checkline_decreasing_order($line, $varname, $value); |
4764 | } | | 4774 | } |
4765 | | | 4775 | |
4766 | if (defined($comment) && $comment eq "# defined" && $varname !~ m".*(?:_MK|_COMMON)$") { | | 4776 | if (defined($comment) && $comment eq "# defined" && $varname !~ m".*(?:_MK|_COMMON)$") { |
4767 | $line->log_note("Please use \"# empty\", \"# none\" or \"yes\" instead of \"# defined\"."); | | 4777 | $line->log_note("Please use \"# empty\", \"# none\" or \"yes\" instead of \"# defined\"."); |
4768 | $line->explain_note( | | 4778 | $line->explain_note( |
4769 | "The value #defined says something about the state of the variable, but", | | 4779 | "The value #defined says something about the state of the variable, but", |
4770 | "not what that _means_. In some cases a variable that is defined means", | | 4780 | "not what that _means_. In some cases a variable that is defined means", |
4771 | "\"yes\", in other cases it is an empty list (which is also only the", | | 4781 | "\"yes\", in other cases it is an empty list (which is also only the", |
4772 | "state of the variable), whose meaning could be described with \"none\".", | | 4782 | "state of the variable), whose meaning could be described with \"none\".", |
4773 | "It is this meaning that should be described."); | | 4783 | "It is this meaning that should be described."); |
4774 | } | | 4784 | } |
4775 | | | 4785 | |
4776 | if ($value =~ m"\$\{(PKGNAME|PKGVERSION)[:\}]") { | | 4786 | if ($value =~ m"\$\{(PKGNAME|PKGVERSION)[:\}]") { |
4777 | my ($pkgvarname) = ($1); | | 4787 | my ($pkgvarname) = ($1); |
4778 | if ($varname =~ m"^PKG_.*_REASON$") { | | 4788 | if ($varname =~ m"^PKG_.*_REASON$") { |
4779 | # ok | | 4789 | # ok |
4780 | } elsif ($varname =~ m"^(?:DIST_SUBDIR|WRKSRC)$") { | | 4790 | } elsif ($varname =~ m"^(?:DIST_SUBDIR|WRKSRC)$") { |
4781 | $line->log_warning("${pkgvarname} should not be used in ${varname}, as it sometimes includes the PKGREVISION. Please use ${pkgvarname}_NOREV instead."); | | 4791 | $line->log_warning("${pkgvarname} should not be used in ${varname}, as it sometimes includes the PKGREVISION. Please use ${pkgvarname}_NOREV instead."); |
4782 | } else { | | 4792 | } else { |
4783 | $opt_debug_misc and $line->log_debug("Use of PKGNAME in ${varname}."); | | 4793 | $opt_debug_misc and $line->log_debug("Use of PKGNAME in ${varname}."); |
4784 | } | | 4794 | } |
4785 | } | | 4795 | } |
4786 | | | 4796 | |
4787 | if (exists(get_deprecated_map()->{$varname})) { | | 4797 | if (exists(get_deprecated_map()->{$varname})) { |
4788 | $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varname}); | | 4798 | $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varname}); |
4789 | } elsif (exists(get_deprecated_map()->{$varcanon})) { | | 4799 | } elsif (exists(get_deprecated_map()->{$varcanon})) { |
4790 | $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varcanon}); | | 4800 | $line->log_warning("Definition of ${varname} is deprecated. ".get_deprecated_map()->{$varcanon}); |
4791 | } | | 4801 | } |
4792 | | | 4802 | |
4793 | if ($varname =~ m"^SITES_") { | | 4803 | if ($varname =~ m"^SITES_") { |
4794 | $line->log_warning("SITES_* is deprecated. Please use SITES.* instead."); | | 4804 | $line->log_warning("SITES_* is deprecated. Please use SITES.* instead."); |
4795 | } | | 4805 | } |
4796 | | | 4806 | |
4797 | if ($value =~ m"^[^=]\@comment") { | | 4807 | if ($value =~ m"^[^=]\@comment") { |
4798 | $line->log_warning("Please don't use \@comment in ${varname}."); | | 4808 | $line->log_warning("Please don't use \@comment in ${varname}."); |
4799 | $line->explain_warning( | | 4809 | $line->explain_warning( |
4800 | "Here you are defining a variable containing \@comment. As this value", | | 4810 | "Here you are defining a variable containing \@comment. As this value", |
4801 | "typically includes a space as the last character you probably also used", | | 4811 | "typically includes a space as the last character you probably also used", |
4802 | "quotes around the variable. This can lead to confusion when adding this", | | 4812 | "quotes around the variable. This can lead to confusion when adding this", |
4803 | "variable to PLIST_SUBST, as all other variables are quoted using the :Q", | | 4813 | "variable to PLIST_SUBST, as all other variables are quoted using the :Q", |
4804 | "operator when they are appended. As it is hard to check whether a", | | 4814 | "operator when they are appended. As it is hard to check whether a", |
4805 | "variable that is appended to PLIST_SUBST is already quoted or not, you", | | 4815 | "variable that is appended to PLIST_SUBST is already quoted or not, you", |
4806 | "should not have pre-quoted variables at all. To solve this, you should", | | 4816 | "should not have pre-quoted variables at all. To solve this, you should", |
4807 | "directly use PLIST_SUBST+= ${varname}=${value} or use any other", | | 4817 | "directly use PLIST_SUBST+= ${varname}=${value} or use any other", |
4808 | "variable for collecting the list of PLIST substitutions and later", | | 4818 | "variable for collecting the list of PLIST substitutions and later", |
4809 | "append that variable with PLIST_SUBST+= \${MY_PLIST_SUBST}."); | | 4819 | "append that variable with PLIST_SUBST+= \${MY_PLIST_SUBST}."); |
4810 | } | | 4820 | } |
4811 | | | 4821 | |
4812 | # Mark the variable as PLIST condition. This is later used in | | 4822 | # Mark the variable as PLIST condition. This is later used in |
4813 | # checkfile_PLIST. | | 4823 | # checkfile_PLIST. |
4814 | if (defined($pkgctx_plist_subst_cond) && $value =~ m"(.+)=.*\@comment.*") { | | 4824 | if (defined($pkgctx_plist_subst_cond) && $value =~ m"(.+)=.*\@comment.*") { |
4815 | $pkgctx_plist_subst_cond->{$1}++; | | 4825 | $pkgctx_plist_subst_cond->{$1}++; |
4816 | } | | 4826 | } |
4817 | | | 4827 | |
4818 | use constant op_to_use_time => { | | 4828 | use constant op_to_use_time => { |
4819 | ":=" => VUC_TIME_LOAD, | | 4829 | ":=" => VUC_TIME_LOAD, |
4820 | "!=" => VUC_TIME_LOAD, | | 4830 | "!=" => VUC_TIME_LOAD, |
4821 | "=" => VUC_TIME_RUN, | | 4831 | "=" => VUC_TIME_RUN, |
4822 | "+=" => VUC_TIME_RUN, | | 4832 | "+=" => VUC_TIME_RUN, |
4823 | "?=" => VUC_TIME_RUN | | 4833 | "?=" => VUC_TIME_RUN |
4824 | }; | | 4834 | }; |
4825 | | | 4835 | |
4826 | $used_vars = extract_used_variables($line, $value); | | 4836 | $used_vars = extract_used_variables($line, $value); |
4827 | my $vuc = PkgLint::VarUseContext->new( | | 4837 | my $vuc = PkgLint::VarUseContext->new( |
4828 | op_to_use_time->{$op}, | | 4838 | op_to_use_time->{$op}, |
4829 | get_variable_type($line, $varname), | | 4839 | get_variable_type($line, $varname), |
4830 | VUC_SHELLWORD_UNKNOWN, # XXX: maybe PLAIN? | | 4840 | VUC_SHELLWORD_UNKNOWN, # XXX: maybe PLAIN? |
4831 | VUC_EXTENT_UNKNOWN | | 4841 | VUC_EXTENT_UNKNOWN |
4832 | ); | | 4842 | ); |
4833 | foreach my $used_var (@{$used_vars}) { | | 4843 | foreach my $used_var (@{$used_vars}) { |
4834 | checkline_mk_varuse($line, $used_var, "", $vuc); | | 4844 | checkline_mk_varuse($line, $used_var, "", $vuc); |
4835 | } | | 4845 | } |
4836 | } | | 4846 | } |
4837 | | | 4847 | |
4838 | # The bmake parser is way too sloppy about syntax, so we need to check | | 4848 | # The bmake parser is way too sloppy about syntax, so we need to check |
4839 | # that here. | | 4849 | # that here. |
4840 | # | | 4850 | # |
4841 | sub checkline_mk_cond($$) { | | 4851 | sub checkline_mk_cond($$) { |
4842 | my ($line, $cond) = @_; | | 4852 | my ($line, $cond) = @_; |
4843 | my ($op, $varname, $match, $value); | | 4853 | my ($op, $varname, $match, $value); |
4844 | | | 4854 | |
4845 | $opt_debug_trace and $line->log_debug("checkline_mk_cond($cond)"); | | 4855 | $opt_debug_trace and $line->log_debug("checkline_mk_cond($cond)"); |
4846 | my $tree = parse_mk_cond($line, $cond); | | 4856 | my $tree = parse_mk_cond($line, $cond); |
4847 | if (tree_match($tree, ["not", ["empty", ["match", \$varname, \$match]]])) { | | 4857 | if (tree_match($tree, ["not", ["empty", ["match", \$varname, \$match]]])) { |
4848 | #$line->log_note("tree_match: varname=$varname, match=$match"); | | 4858 | #$line->log_note("tree_match: varname=$varname, match=$match"); |
4849 | | | 4859 | |
4850 | my $type = get_variable_type($line, $varname); | | 4860 | my $type = get_variable_type($line, $varname); |
4851 | my $btype = defined($type) ? $type->basic_type : undef; | | 4861 | my $btype = defined($type) ? $type->basic_type : undef; |
4852 | if (defined($btype) && ref($type->basic_type) eq "HASH") { | | 4862 | if (defined($btype) && ref($type->basic_type) eq "HASH") { |
4853 | if ($match !~ m"[\$\[*]" && !exists($btype->{$match})) { | | 4863 | if ($match !~ m"[\$\[*]" && !exists($btype->{$match})) { |
4854 | $line->log_warning("Invalid :M value \"$match\". Only { " . join(" ", sort keys %$btype) . " } are allowed."); | | 4864 | $line->log_warning("Invalid :M value \"$match\". Only { " . join(" ", sort keys %$btype) . " } are allowed."); |
4855 | } | | 4865 | } |
4856 | } | | 4866 | } |
4857 | | | 4867 | |
4858 | # Currently disabled because the valid options can also be defined in PKG_OPTIONS_GROUP.*. | | 4868 | # Currently disabled because the valid options can also be defined in PKG_OPTIONS_GROUP.*. |
4859 | # Additionally, all these variables may have multiple assigments (+=). | | 4869 | # Additionally, all these variables may have multiple assigments (+=). |
4860 | if (false && $varname eq "PKG_OPTIONS" && defined($pkgctx_vardef) && exists($pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"})) { | | 4870 | if (false && $varname eq "PKG_OPTIONS" && defined($pkgctx_vardef) && exists($pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"})) { |
4861 | my $options = $pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"}->get("value"); | | 4871 | my $options = $pkgctx_vardef->{"PKG_SUPPORTED_OPTIONS"}->get("value"); |
4862 | | | 4872 | |
4863 | if ($match !~ m"[\$\[*]" && index(" $options ", " $match ") == -1) { | | 4873 | if ($match !~ m"[\$\[*]" && index(" $options ", " $match ") == -1) { |
4864 | $line->log_warning("Invalid option \"$match\". Only { $options } are allowed."); | | 4874 | $line->log_warning("Invalid option \"$match\". Only { $options } are allowed."); |
4865 | } | | 4875 | } |
4866 | } | | 4876 | } |
4867 | | | 4877 | |
4868 | # TODO: PKG_BUILD_OPTIONS. That requires loading the | | 4878 | # TODO: PKG_BUILD_OPTIONS. That requires loading the |
4869 | # complete package definitition for the package "pkgbase" | | 4879 | # complete package definitition for the package "pkgbase" |
4870 | # or some other database. If we could confine all option | | 4880 | # or some other database. If we could confine all option |
4871 | # definitions to options.mk, this would become easier. | | 4881 | # definitions to options.mk, this would become easier. |
4872 | | | 4882 | |
4873 | } elsif (tree_match($tree, [\$op, ["var", \$varname], ["string", \$value]])) { | | 4883 | } elsif (tree_match($tree, [\$op, ["var", \$varname], ["string", \$value]])) { |
4874 | checkline_mk_vartype($line, $varname, "use", $value, undef); | | 4884 | checkline_mk_vartype($line, $varname, "use", $value, undef); |
4875 | | | 4885 | |
4876 | } | | 4886 | } |
4877 | # XXX: When adding new cases, be careful that the variables may have | | 4887 | # XXX: When adding new cases, be careful that the variables may have |
4878 | # been partially initialized by previous calls to tree_match. | | 4888 | # been partially initialized by previous calls to tree_match. |
4879 | # XXX: Maybe it is better to clear these references at the beginning | | 4889 | # XXX: Maybe it is better to clear these references at the beginning |
4880 | # of tree_match. | | 4890 | # of tree_match. |
4881 | } | | 4891 | } |
4882 | | | 4892 | |
4883 | # | | 4893 | # |
4884 | # Procedures to check an array of lines. | | 4894 | # Procedures to check an array of lines. |
4885 | # | | 4895 | # |
4886 | | | 4896 | |
4887 | sub checklines_trailing_empty_lines($) { | | 4897 | sub checklines_trailing_empty_lines($) { |
4888 | my ($lines) = @_; | | 4898 | my ($lines) = @_; |
4889 | my ($last, $max); | | 4899 | my ($last, $max); |
4890 | | | 4900 | |
4891 | $max = $#{$lines} + 1; | | 4901 | $max = $#{$lines} + 1; |
4892 | for ($last = $max; $last > 1 && $lines->[$last - 1]->text eq ""; ) { | | 4902 | for ($last = $max; $last > 1 && $lines->[$last - 1]->text eq ""; ) { |
4893 | $last--; | | 4903 | $last--; |
4894 | } | | 4904 | } |
4895 | if ($last != $max) { | | 4905 | if ($last != $max) { |
4896 | $lines->[$last]->log_note("Trailing empty lines."); | | 4906 | $lines->[$last]->log_note("Trailing empty lines."); |
4897 | } | | 4907 | } |
4898 | } | | 4908 | } |
4899 | | | 4909 | |
4900 | sub checklines_package_Makefile_varorder($) { | | 4910 | sub checklines_package_Makefile_varorder($) { |
4901 | my ($lines) = @_; | | 4911 | my ($lines) = @_; |
4902 | | | 4912 | |
4903 | return unless $opt_warn_varorder; | | 4913 | return unless $opt_warn_varorder; |
4904 | | | 4914 | |
4905 | use enum qw(once optional many); | | 4915 | use enum qw(once optional many); |
4906 | my (@sections) = ( | | 4916 | my (@sections) = ( |
4907 | [ "Initial comments", once, | | 4917 | [ "Initial comments", once, |
4908 | [ | | 4918 | [ |
4909 | ] | | 4919 | ] |
4910 | ], | | 4920 | ], |
4911 | [ "Unsorted stuff, part 1", once, | | 4921 | [ "Unsorted stuff, part 1", once, |
4912 | [ | | 4922 | [ |
4913 | [ "DISTNAME", once ], | | 4923 | [ "DISTNAME", once ], |
4914 | [ "PKGNAME", optional ], | | 4924 | [ "PKGNAME", optional ], |
4915 | [ "PKGREVISION", optional ], | | 4925 | [ "PKGREVISION", optional ], |
4916 | [ "SVR4_PKGNAME", optional ], | | 4926 | [ "SVR4_PKGNAME", optional ], |
4917 | [ "CATEGORIES", once ], | | 4927 | [ "CATEGORIES", once ], |
4918 | [ "MASTER_SITES", optional ], | | 4928 | [ "MASTER_SITES", optional ], |
4919 | [ "DIST_SUBDIR", optional ], | | 4929 | [ "DIST_SUBDIR", optional ], |
4920 | [ "EXTRACT_SUFX", optional ], | | 4930 | [ "EXTRACT_SUFX", optional ], |
4921 | [ "DISTFILES", many ], | | 4931 | [ "DISTFILES", many ], |
4922 | [ "SITES.*", many ], | | 4932 | [ "SITES.*", many ], |
4923 | ] | | 4933 | ] |
4924 | ], | | 4934 | ], |
4925 | [ "Distribution patches", optional, | | 4935 | [ "Distribution patches", optional, |
4926 | [ | | 4936 | [ |
4927 | [ "PATCH_SITES", optional ], # or once? | | 4937 | [ "PATCH_SITES", optional ], # or once? |
4928 | [ "PATCH_SITE_SUBDIR", optional ], | | 4938 | [ "PATCH_SITE_SUBDIR", optional ], |
4929 | [ "PATCHFILES", optional ], # or once? | | 4939 | [ "PATCHFILES", optional ], # or once? |
4930 | [ "PATCH_DIST_ARGS", optional ], | | 4940 | [ "PATCH_DIST_ARGS", optional ], |
4931 | [ "PATCH_DIST_STRIP", optional ], | | 4941 | [ "PATCH_DIST_STRIP", optional ], |
4932 | [ "PATCH_DIST_CAT", optional ], | | 4942 | [ "PATCH_DIST_CAT", optional ], |
4933 | ] | | 4943 | ] |
4934 | ], | | 4944 | ], |
4935 | [ "Unsorted stuff, part 2", once, | | 4945 | [ "Unsorted stuff, part 2", once, |
4936 | [ | | 4946 | [ |
4937 | [ "MAINTAINER", optional ], | | 4947 | [ "MAINTAINER", optional ], |
4938 | [ "OWNER", optional ], | | 4948 | [ "OWNER", optional ], |
4939 | [ "HOMEPAGE", optional ], | | 4949 | [ "HOMEPAGE", optional ], |
4940 | [ "COMMENT", once ], | | 4950 | [ "COMMENT", once ], |
4941 | [ "LICENSE", once ], | | 4951 | [ "LICENSE", once ], |
4942 | ] | | 4952 | ] |
4943 | ], | | 4953 | ], |
4944 | [ "Legal issues", optional, | | 4954 | [ "Legal issues", optional, |
4945 | [ | | 4955 | [ |
4946 | [ "LICENSE_FILE", optional ], | | 4956 | [ "LICENSE_FILE", optional ], |
4947 | [ "RESTRICTED", optional ], | | 4957 | [ "RESTRICTED", optional ], |
4948 | [ "NO_BIN_ON_CDROM", optional ], | | 4958 | [ "NO_BIN_ON_CDROM", optional ], |
4949 | [ "NO_BIN_ON_FTP", optional ], | | 4959 | [ "NO_BIN_ON_FTP", optional ], |
4950 | [ "NO_SRC_ON_CDROM", optional ], | | 4960 | [ "NO_SRC_ON_CDROM", optional ], |
4951 | [ "NO_SRC_ON_FTP", optional ], | | 4961 | [ "NO_SRC_ON_FTP", optional ], |
4952 | ] | | 4962 | ] |
4953 | ], | | 4963 | ], |
4954 | [ "Technical restrictions", optional, | | 4964 | [ "Technical restrictions", optional, |
4955 | [ | | 4965 | [ |
4956 | [ "NOT_FOR_PLATFORM", many ], | | 4966 | [ "NOT_FOR_PLATFORM", many ], |
4957 | [ "ONLY_FOR_PLATFORM", many ], | | 4967 | [ "ONLY_FOR_PLATFORM", many ], |
4958 | [ "NOT_FOR_COMPILER", many ], | | 4968 | [ "NOT_FOR_COMPILER", many ], |
4959 | [ "ONLY_FOR_COMPILER", many ], | | 4969 | [ "ONLY_FOR_COMPILER", many ], |
4960 | [ "NOT_FOR_UNPRIVILEGED", optional ], | | 4970 | [ "NOT_FOR_UNPRIVILEGED", optional ], |
4961 | [ "ONLY_FOR_UNPRIVILEGED", optional ], | | 4971 | [ "ONLY_FOR_UNPRIVILEGED", optional ], |
4962 | ] | | 4972 | ] |
4963 | ], | | 4973 | ], |
4964 | [ "Dependencies", optional, | | 4974 | [ "Dependencies", optional, |
4965 | [ | | 4975 | [ |
4966 | [ "BUILD_DEPENDS", many ], | | 4976 | [ "BUILD_DEPENDS", many ], |
4967 | [ "DEPENDS", many ], | | 4977 | [ "DEPENDS", many ], |
4968 | ] | | 4978 | ] |
4969 | ] | | 4979 | ] |
4970 | ); | | 4980 | ); |
4971 | | | 4981 | |
4972 | if (!defined($seen_Makefile_common) || $seen_Makefile_common) { | | 4982 | if (!defined($seen_Makefile_common) || $seen_Makefile_common) { |
4973 | return; | | 4983 | return; |
4974 | } | | 4984 | } |
4975 | | | 4985 | |
4976 | my ($lineno, $sectindex, $varindex) = (0, -1, 0); | | 4986 | my ($lineno, $sectindex, $varindex) = (0, -1, 0); |
4977 | my ($next_section, $vars, $below, $below_what) = (true, undef, {}, undef); | | 4987 | my ($next_section, $vars, $below, $below_what) = (true, undef, {}, undef); |
4978 | | | 4988 | |
4979 | # If the current section is optional but contains non-optional | | 4989 | # If the current section is optional but contains non-optional |
4980 | # fields, the complete section may be skipped as long as there | | 4990 | # fields, the complete section may be skipped as long as there |
4981 | # has not been a non-optional variable. | | 4991 | # has not been a non-optional variable. |
4982 | my $may_skip_section = false; | | 4992 | my $may_skip_section = false; |
4983 | | | 4993 | |
4984 | # In each iteration, one of the following becomes true: | | 4994 | # In each iteration, one of the following becomes true: |
4985 | # - new.lineno > old.lineno | | 4995 | # - new.lineno > old.lineno |
4986 | # - new.sectindex > old.sectindex | | 4996 | # - new.sectindex > old.sectindex |
4987 | # - new.sectindex == old.sectindex && new.varindex > old.varindex | | 4997 | # - new.sectindex == old.sectindex && new.varindex > old.varindex |
4988 | # - new.next_section == true && old.next_section == false | | 4998 | # - new.next_section == true && old.next_section == false |
4989 | while ($lineno <= $#{$lines}) { | | 4999 | while ($lineno <= $#{$lines}) { |
4990 | my $line = $lines->[$lineno]; | | 5000 | my $line = $lines->[$lineno]; |
4991 | my $text = $line->text; | | 5001 | my $text = $line->text; |
4992 | | | 5002 | |
4993 | $opt_debug_misc and $line->log_debug("[varorder] section ${sectindex} variable ${varindex}."); | | 5003 | $opt_debug_misc and $line->log_debug("[varorder] section ${sectindex} variable ${varindex}."); |
4994 | | | 5004 | |
4995 | if ($next_section) { | | 5005 | if ($next_section) { |
4996 | $next_section = false; | | 5006 | $next_section = false; |
4997 | $sectindex++; | | 5007 | $sectindex++; |
4998 | last if ($sectindex > $#sections); | | 5008 | last if ($sectindex > $#sections); |
4999 | $vars = $sections[$sectindex]->[2]; | | 5009 | $vars = $sections[$sectindex]->[2]; |
5000 | $may_skip_section = ($sections[$sectindex]->[1] == optional); | | 5010 | $may_skip_section = ($sections[$sectindex]->[1] == optional); |
5001 | $varindex = 0; | | 5011 | $varindex = 0; |
5002 | } | | 5012 | } |
5003 | | | 5013 | |
5004 | if ($text =~ m"^#") { | | 5014 | if ($text =~ m"^#") { |
5005 | $lineno++; | | 5015 | $lineno++; |
5006 | | | 5016 | |
5007 | } elsif ($line->has("varcanon")) { | | 5017 | } elsif ($line->has("varcanon")) { |
5008 | my $varcanon = $line->get("varcanon"); | | 5018 | my $varcanon = $line->get("varcanon"); |
5009 | | | 5019 | |
5010 | if (exists($below->{$varcanon})) { | | 5020 | if (exists($below->{$varcanon})) { |
5011 | if (defined($below->{$varcanon})) { | | 5021 | if (defined($below->{$varcanon})) { |
5012 | $line->log_warning("${varcanon} appears too late. Please put it below $below->{$varcanon}."); | | 5022 | $line->log_warning("${varcanon} appears too late. Please put it below $below->{$varcanon}."); |
5013 | } else { | | 5023 | } else { |
5014 | $line->log_warning("${varcanon} appears too late. It should be the very first definition."); | | 5024 | $line->log_warning("${varcanon} appears too late. It should be the very first definition."); |
5015 | } | | 5025 | } |
5016 | $lineno++; | | 5026 | $lineno++; |
5017 | next; | | 5027 | next; |
5018 | } | | 5028 | } |
5019 | | | 5029 | |
5020 | while ($varindex <= $#{$vars} && $varcanon ne $vars->[$varindex]->[0] && ($vars->[$varindex]->[1] != once || $may_skip_section)) { | | 5030 | while ($varindex <= $#{$vars} && $varcanon ne $vars->[$varindex]->[0] && ($vars->[$varindex]->[1] != once || $may_skip_section)) { |
5021 | if ($vars->[$varindex]->[1] == once) { | | 5031 | if ($vars->[$varindex]->[1] == once) { |
5022 | $may_skip_section = false; | | 5032 | $may_skip_section = false; |
5023 | } | | 5033 | } |
5024 | $below->{$vars->[$varindex]->[0]} = $below_what; | | 5034 | $below->{$vars->[$varindex]->[0]} = $below_what; |
5025 | $varindex++; | | 5035 | $varindex++; |
5026 | } | | 5036 | } |
5027 | if ($varindex > $#{$vars}) { | | 5037 | if ($varindex > $#{$vars}) { |
5028 | if ($sections[$sectindex]->[1] != optional) { | | 5038 | if ($sections[$sectindex]->[1] != optional) { |
5029 | $line->log_warning("Empty line expected."); | | 5039 | $line->log_warning("Empty line expected."); |
5030 | } | | 5040 | } |
5031 | $next_section = true; | | 5041 | $next_section = true; |
5032 | | | 5042 | |
5033 | } elsif ($varcanon ne $vars->[$varindex]->[0]) { | | 5043 | } elsif ($varcanon ne $vars->[$varindex]->[0]) { |
5034 | $line->log_warning("Expected " . $vars->[$varindex]->[0] . ", but found " . $varcanon . "."); | | 5044 | $line->log_warning("Expected " . $vars->[$varindex]->[0] . ", but found " . $varcanon . "."); |
5035 | $lineno++; | | 5045 | $lineno++; |
5036 | | | 5046 | |
5037 | } else { | | 5047 | } else { |
5038 | if ($vars->[$varindex]->[1] != many) { | | 5048 | if ($vars->[$varindex]->[1] != many) { |
5039 | $below->{$vars->[$varindex]->[0]} = $below_what; | | 5049 | $below->{$vars->[$varindex]->[0]} = $below_what; |
5040 | $varindex++; | | 5050 | $varindex++; |
5041 | } | | 5051 | } |
5042 | $lineno++; | | 5052 | $lineno++; |
5043 | } | | 5053 | } |
5044 | $below_what = $varcanon; | | 5054 | $below_what = $varcanon; |
5045 | | | 5055 | |
5046 | } else { | | 5056 | } else { |
5047 | while ($varindex <= $#{$vars}) { | | 5057 | while ($varindex <= $#{$vars}) { |
5048 | if ($vars->[$varindex]->[1] == once && !$may_skip_section) { | | 5058 | if ($vars->[$varindex]->[1] == once && !$may_skip_section) { |
5049 | $line->log_warning($vars->[$varindex]->[0] . " should be set here."); | | 5059 | $line->log_warning($vars->[$varindex]->[0] . " should be set here."); |
5050 | } | | 5060 | } |
5051 | $below->{$vars->[$varindex]->[0]} = $below_what; | | 5061 | $below->{$vars->[$varindex]->[0]} = $below_what; |
5052 | $varindex++; | | 5062 | $varindex++; |
5053 | } | | 5063 | } |
5054 | $next_section = true; | | 5064 | $next_section = true; |
5055 | if ($text eq "") { | | 5065 | if ($text eq "") { |
5056 | $below_what = "the previous empty line"; | | 5066 | $below_what = "the previous empty line"; |
5057 | $lineno++; | | 5067 | $lineno++; |
5058 | } | | 5068 | } |
5059 | } | | 5069 | } |
5060 | } | | 5070 | } |
5061 | } | | 5071 | } |
5062 | | | 5072 | |
5063 | sub checklines_mk($) { | | 5073 | sub checklines_mk($) { |
5064 | my ($lines) = @_; | | 5074 | my ($lines) = @_; |
5065 | my ($allowed_targets) = ({}); | | 5075 | my ($allowed_targets) = ({}); |
5066 | my ($substcontext) = PkgLint::SubstContext->new(); | | 5076 | my ($substcontext) = PkgLint::SubstContext->new(); |
5067 | | | 5077 | |
5068 | assert(@{$lines} != 0, "checklines_mk may only be called with non-empty lines."); | | 5078 | assert(@{$lines} != 0, "checklines_mk may only be called with non-empty lines."); |
5069 | $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_mk()"); | | 5079 | $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_mk()"); |
5070 | | | 5080 | |
5071 | # Define global variables for the Makefile context. | | 5081 | # Define global variables for the Makefile context. |
5072 | $mkctx_indentations = [0]; | | 5082 | $mkctx_indentations = [0]; |
5073 | $mkctx_target = undef; | | 5083 | $mkctx_target = undef; |
5074 | $mkctx_for_variables = {}; | | 5084 | $mkctx_for_variables = {}; |
5075 | $mkctx_vardef = {}; | | 5085 | $mkctx_vardef = {}; |
5076 | $mkctx_build_defs = {}; | | 5086 | $mkctx_build_defs = {}; |
5077 | $mkctx_plist_vars = {}; | | 5087 | $mkctx_plist_vars = {}; |
5078 | $mkctx_tools = {%{get_predefined_tool_names()}}; | | 5088 | $mkctx_tools = {%{get_predefined_tool_names()}}; |
5079 | $mkctx_varuse = {}; | | 5089 | $mkctx_varuse = {}; |
5080 | | | 5090 | |
5081 | determine_used_variables($lines); | | 5091 | determine_used_variables($lines); |
5082 | | | 5092 | |
5083 | foreach my $prefix (qw(pre do post)) { | | 5093 | foreach my $prefix (qw(pre do post)) { |
5084 | foreach my $action (qw(fetch extract patch tools wrapper configure build test install package clean)) { | | 5094 | foreach my $action (qw(fetch extract patch tools wrapper configure build test install package clean)) { |
5085 | $allowed_targets->{"${prefix}-${action}"} = true; | | 5095 | $allowed_targets->{"${prefix}-${action}"} = true; |
5086 | } | | 5096 | } |
5087 | } | | 5097 | } |
5088 | | | 5098 | |
5089 | # | | 5099 | # |
5090 | # In the first pass, all additions to BUILD_DEFS and USE_TOOLS | | 5100 | # In the first pass, all additions to BUILD_DEFS and USE_TOOLS |
5091 | # are collected to make the order of the definitions irrelevant. | | 5101 | # are collected to make the order of the definitions irrelevant. |
5092 | # | | 5102 | # |
5093 | | | 5103 | |
5094 | foreach my $line (@{$lines}) { | | 5104 | foreach my $line (@{$lines}) { |
5095 | next unless $line->has("is_varassign"); | | 5105 | next unless $line->has("is_varassign"); |
5096 | my $varcanon = $line->get("varcanon"); | | 5106 | my $varcanon = $line->get("varcanon"); |
5097 | | | 5107 | |
5098 | if ($varcanon eq "BUILD_DEFS" || $varcanon eq "PKG_GROUPS_VARS" || $varcanon eq "PKG_USERS_VARS") { | | 5108 | if ($varcanon eq "BUILD_DEFS" || $varcanon eq "PKG_GROUPS_VARS" || $varcanon eq "PKG_USERS_VARS") { |
5099 | foreach my $varname (split(qr"\s+", $line->get("value"))) { | | 5109 | foreach my $varname (split(qr"\s+", $line->get("value"))) { |
5100 | $mkctx_build_defs->{$varname} = true; | | 5110 | $mkctx_build_defs->{$varname} = true; |
5101 | $opt_debug_misc and $line->log_debug("${varname} is added to BUILD_DEFS."); | | 5111 | $opt_debug_misc and $line->log_debug("${varname} is added to BUILD_DEFS."); |
5102 | } | | 5112 | } |
5103 | | | 5113 | |
5104 | } elsif ($varcanon eq "PLIST_VARS") { | | 5114 | } elsif ($varcanon eq "PLIST_VARS") { |
5105 | foreach my $id (split(qr"\s+", $line->get("value"))) { | | 5115 | foreach my $id (split(qr"\s+", $line->get("value"))) { |
5106 | $mkctx_plist_vars->{"PLIST.$id"} = true; | | 5116 | $mkctx_plist_vars->{"PLIST.$id"} = true; |
5107 | $opt_debug_misc and $line->log_debug("PLIST.${id} is added to PLIST_VARS."); | | 5117 | $opt_debug_misc and $line->log_debug("PLIST.${id} is added to PLIST_VARS."); |
5108 | use_var($line, "PLIST.$id"); | | 5118 | use_var($line, "PLIST.$id"); |
5109 | } | | 5119 | } |
5110 | | | 5120 | |
5111 | } elsif ($varcanon eq "USE_TOOLS") { | | 5121 | } elsif ($varcanon eq "USE_TOOLS") { |
5112 | foreach my $tool (split(qr"\s+", $line->get("value"))) { | | 5122 | foreach my $tool (split(qr"\s+", $line->get("value"))) { |
5113 | $mkctx_tools->{$tool} = true; | | 5123 | $mkctx_tools->{$tool} = true; |
5114 | $opt_debug_misc and $line->log_debug("${tool} is added to USE_TOOLS."); | | 5124 | $opt_debug_misc and $line->log_debug("${tool} is added to USE_TOOLS."); |
5115 | } | | 5125 | } |
5116 | | | 5126 | |
5117 | } elsif ($varcanon eq "SUBST_VARS.*") { | | 5127 | } elsif ($varcanon eq "SUBST_VARS.*") { |
5118 | foreach my $svar (split(/\s+/, $line->get("value"))) { | | 5128 | foreach my $svar (split(/\s+/, $line->get("value"))) { |
5119 | use_var($svar, varname_canon($svar)); | | 5129 | use_var($svar, varname_canon($svar)); |
5120 | $opt_debug_misc and $line->log_debug("varuse $svar"); | | 5130 | $opt_debug_misc and $line->log_debug("varuse $svar"); |
5121 | } | | 5131 | } |
5122 | | | 5132 | |
5123 | } elsif ($varcanon eq "OPSYSVARS") { | | 5133 | } elsif ($varcanon eq "OPSYSVARS") { |
5124 | foreach my $osvar (split(/\s+/, $line->get("value"))) { | | 5134 | foreach my $osvar (split(/\s+/, $line->get("value"))) { |
5125 | use_var($line, "$osvar.*"); | | 5135 | use_var($line, "$osvar.*"); |
5126 | def_var($line, $osvar); | | 5136 | def_var($line, $osvar); |
5127 | } | | 5137 | } |
5128 | } | | 5138 | } |
5129 | } | | 5139 | } |
5130 | | | 5140 | |
5131 | # | | 5141 | # |
5132 | # In the second pass, all "normal" checks are done. | | 5142 | # In the second pass, all "normal" checks are done. |
5133 | # | | 5143 | # |
5134 | | | 5144 | |
5135 | if (0 <= $#{$lines}) { | | 5145 | if (0 <= $#{$lines}) { |
5136 | checkline_rcsid_regex($lines->[0], qr"^#\s+", "# "); | | 5146 | checkline_rcsid_regex($lines->[0], qr"^#\s+", "# "); |
5137 | } | | 5147 | } |
5138 | | | 5148 | |
5139 | foreach my $line (@{$lines}) { | | 5149 | foreach my $line (@{$lines}) { |
5140 | my $text = $line->text; | | 5150 | my $text = $line->text; |
5141 | | | 5151 | |
5142 | checkline_trailing_whitespace($line); | | 5152 | checkline_trailing_whitespace($line); |
5143 | checkline_spellcheck($line); | | 5153 | checkline_spellcheck($line); |
5144 | | | 5154 | |
5145 | if ($line->has("is_empty")) { | | 5155 | if ($line->has("is_empty")) { |
5146 | $substcontext->check_end($line); | | 5156 | $substcontext->check_end($line); |
5147 | | | 5157 | |
5148 | } elsif ($line->has("is_comment")) { | | 5158 | } elsif ($line->has("is_comment")) { |
5149 | # No further checks. | | 5159 | # No further checks. |
5150 | | | 5160 | |
5151 | } elsif ($text =~ regex_varassign) { | | 5161 | } elsif ($text =~ regex_varassign) { |
5152 | my ($varname, $op, undef, $comment) = ($1, $2, $3, $4); | | 5162 | my ($varname, $op, undef, $comment) = ($1, $2, $3, $4); |
5153 | my $space1 = substr($text, $+[1], $-[2] - $+[1]); | | 5163 | my $space1 = substr($text, $+[1], $-[2] - $+[1]); |
5154 | my $align = substr($text, $+[2], $-[3] - $+[2]); | | 5164 | my $align = substr($text, $+[2], $-[3] - $+[2]); |
5155 | my $value = $line->get("value"); | | 5165 | my $value = $line->get("value"); |
5156 | | | 5166 | |
5157 | if ($align !~ m"^(\t*|[ ])$") { | | 5167 | if ($align !~ m"^(\t*|[ ])$") { |
5158 | $opt_warn_space && $line->log_note("Alignment of variable values should be done with tabs, not spaces."); | | 5168 | $opt_warn_space && $line->log_note("Alignment of variable values should be done with tabs, not spaces."); |
5159 | my $prefix = "${varname}${space1}${op}"; | | 5169 | my $prefix = "${varname}${space1}${op}"; |
5160 | my $aligned_len = tablen("${prefix}${align}"); | | 5170 | my $aligned_len = tablen("${prefix}${align}"); |
5161 | if ($aligned_len % 8 == 0) { | | 5171 | if ($aligned_len % 8 == 0) { |
5162 | my $tabalign = ("\t" x (($aligned_len - tablen($prefix) + 7) / 8)); | | 5172 | my $tabalign = ("\t" x (($aligned_len - tablen($prefix) + 7) / 8)); |
5163 | $line->replace("${prefix}${align}", "${prefix}${tabalign}"); | | 5173 | $line->replace("${prefix}${align}", "${prefix}${tabalign}"); |
5164 | } | | 5174 | } |
5165 | } | | 5175 | } |
5166 | checkline_mk_varassign($line, $varname, $op, $value, $comment); | | 5176 | checkline_mk_varassign($line, $varname, $op, $value, $comment); |
5167 | $substcontext->check_varassign($line, $varname, $op, $value); | | 5177 | $substcontext->check_varassign($line, $varname, $op, $value); |
5168 | | | 5178 | |
5169 | } elsif ($text =~ regex_mk_shellcmd) { | | 5179 | } elsif ($text =~ regex_mk_shellcmd) { |
5170 | my ($shellcmd) = ($1); | | 5180 | my ($shellcmd) = ($1); |
5171 | checkline_mk_shellcmd($line, $shellcmd); | | 5181 | checkline_mk_shellcmd($line, $shellcmd); |
5172 | | | 5182 | |
5173 | } elsif ($text =~ regex_mk_include) { | | 5183 | } elsif ($text =~ regex_mk_include) { |
5174 | my ($include, $includefile) = ($1, $2); | | 5184 | my ($include, $includefile) = ($1, $2); |
5175 | | | 5185 | |
5176 | $opt_debug_include and $line->log_debug("includefile=${includefile}"); | | 5186 | $opt_debug_include and $line->log_debug("includefile=${includefile}"); |
5177 | checkline_relative_path($line, $includefile, $include eq "include"); | | 5187 | checkline_relative_path($line, $includefile, $include eq "include"); |
5178 | | | 5188 | |
5179 | if ($includefile =~ m"../Makefile$") { | | 5189 | if ($includefile =~ m"../Makefile$") { |
5180 | $line->log_error("Other Makefiles must not be included directly."); | | 5190 | $line->log_error("Other Makefiles must not be included directly."); |
5181 | $line->explain_warning( | | 5191 | $line->explain_warning( |
5182 | "If you want to include portions of another Makefile, extract", | | 5192 | "If you want to include portions of another Makefile, extract", |
5183 | "the common parts and put them into a Makefile.common. After", | | 5193 | "the common parts and put them into a Makefile.common. After", |
5184 | "that, both this one and the other package should include the", | | 5194 | "that, both this one and the other package should include the", |
5185 | "Makefile.common."); | | 5195 | "Makefile.common."); |
5186 | } | | 5196 | } |
5187 | | | 5197 | |
5188 | if ($includefile eq "../../mk/bsd.prefs.mk") { | | 5198 | if ($includefile eq "../../mk/bsd.prefs.mk") { |
5189 | if ($line->fname =~ m"buildlink3\.mk$") { | | 5199 | if ($line->fname =~ m"buildlink3\.mk$") { |
5190 | $line->log_note("For efficiency reasons, please include bsd.fast.prefs.mk instead of bsd.prefs.mk."); | | 5200 | $line->log_note("For efficiency reasons, please include bsd.fast.prefs.mk instead of bsd.prefs.mk."); |
5191 | } | | 5201 | } |
5192 | $seen_bsd_prefs_mk = true; | | 5202 | $seen_bsd_prefs_mk = true; |
5193 | } elsif ($includefile eq "../../mk/bsd.fast.prefs.mk") { | | 5203 | } elsif ($includefile eq "../../mk/bsd.fast.prefs.mk") { |
5194 | $seen_bsd_prefs_mk = true; | | 5204 | $seen_bsd_prefs_mk = true; |
5195 | } | | 5205 | } |
5196 | | | 5206 | |
5197 | if ($includefile =~ m"/x11-links/buildlink3\.mk$") { | | 5207 | if ($includefile =~ m"/x11-links/buildlink3\.mk$") { |
5198 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead."); | | 5208 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead."); |
5199 | } | | 5209 | } |
5200 | if ($includefile =~ m"/giflib/buildlink3\.mk$") { | | 5210 | if ($includefile =~ m"/giflib/buildlink3\.mk$") { |
5201 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/giflib.buildlink3.mk\" instead."); | | 5211 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/giflib.buildlink3.mk\" instead."); |
5202 | } | | 5212 | } |
5203 | if ($includefile =~ m"/jpeg/buildlink3\.mk$") { | | 5213 | if ($includefile =~ m"/jpeg/buildlink3\.mk$") { |
5204 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/jpeg.buildlink3.mk\" instead."); | | 5214 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/jpeg.buildlink3.mk\" instead."); |
5205 | } | | 5215 | } |
5206 | if ($includefile =~ m"/libungif/buildlink3\.mk$") { | | 5216 | if ($includefile =~ m"/libungif/buildlink3\.mk$") { |
5207 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/giflib.buildlink3.mk\" instead."); | | 5217 | $line->log_error("${includefile} must not be included directly. Include \"../../mk/giflib.buildlink3.mk\" instead."); |
5208 | } | | 5218 | } |
5209 | if ($includefile =~ m"/intltool/buildlink3\.mk$") { | | 5219 | if ($includefile =~ m"/intltool/buildlink3\.mk$") { |
5210 | $line->log_warning("Please say \"USE_TOOLS+= intltool\" instead of this line."); | | 5220 | $line->log_warning("Please say \"USE_TOOLS+= intltool\" instead of this line."); |
5211 | } | | 5221 | } |
5212 | if ($includefile =~ m"(.*)/builtin\.mk$") { | | 5222 | if ($includefile =~ m"(.*)/builtin\.mk$") { |
5213 | my ($dir) = ($1); | | 5223 | my ($dir) = ($1); |
5214 | $line->log_error("${includefile} must not be included directly. Include \"${dir}/buildlink3.mk\" instead."); | | 5224 | $line->log_error("${includefile} must not be included directly. Include \"${dir}/buildlink3.mk\" instead."); |
5215 | } | | 5225 | } |
5216 | | | 5226 | |
5217 | } elsif ($text =~ regex_mk_sysinclude) { | | 5227 | } elsif ($text =~ regex_mk_sysinclude) { |
5218 | my ($includefile, $comment) = ($1, $2); | | 5228 | my ($includefile, $comment) = ($1, $2); |
5219 | | | 5229 | |
5220 | # No further action. | | 5230 | # No further action. |
5221 | | | 5231 | |
5222 | } elsif ($text =~ regex_mk_cond) { | | 5232 | } elsif ($text =~ regex_mk_cond) { |
5223 | my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4); | | 5233 | my ($indent, $directive, $args, $comment) = ($1, $2, $3, $4); |
5224 | | | 5234 | |
5225 | use constant regex_directives_with_args => qr"^(?:if|ifdef|ifndef|elif|for|undef)$"; | | 5235 | use constant regex_directives_with_args => qr"^(?:if|ifdef|ifndef|elif|for|undef)$"; |
5226 | | | 5236 | |
5227 | if ($directive =~ m"^(?:endif|endfor|elif|else)$") { | | 5237 | if ($directive =~ m"^(?:endif|endfor|elif|else)$") { |
5228 | if ($#{$mkctx_indentations} >= 1) { | | 5238 | if ($#{$mkctx_indentations} >= 1) { |
5229 | pop(@{$mkctx_indentations}); | | 5239 | pop(@{$mkctx_indentations}); |
5230 | } else { | | 5240 | } else { |
5231 | $line->log_error("Unmatched .${directive}."); | | 5241 | $line->log_error("Unmatched .${directive}."); |
5232 | } | | 5242 | } |
5233 | } | | 5243 | } |
5234 | | | 5244 | |
5235 | # Check the indentation | | 5245 | # Check the indentation |
5236 | if ($indent ne " " x $mkctx_indentations->[-1]) { | | 5246 | if ($indent ne " " x $mkctx_indentations->[-1]) { |
5237 | $opt_warn_space and $line->log_note("This directive should be indented by ".$mkctx_indentations->[-1]." spaces."); | | 5247 | $opt_warn_space and $line->log_note("This directive should be indented by ".$mkctx_indentations->[-1]." spaces."); |
5238 | } | | 5248 | } |
5239 | | | 5249 | |
5240 | if ($directive eq "if" && $args =~ m"^!defined\([\w]+_MK\)$") { | | 5250 | if ($directive eq "if" && $args =~ m"^!defined\([\w]+_MK\)$") { |
5241 | push(@{$mkctx_indentations}, $mkctx_indentations->[-1]); | | 5251 | push(@{$mkctx_indentations}, $mkctx_indentations->[-1]); |
5242 | | | 5252 | |
5243 | } elsif ($directive =~ m"^(?:if|ifdef|ifndef|for|elif|else)$") { | | 5253 | } elsif ($directive =~ m"^(?:if|ifdef|ifndef|for|elif|else)$") { |
5244 | push(@{$mkctx_indentations}, $mkctx_indentations->[-1] + 2); | | 5254 | push(@{$mkctx_indentations}, $mkctx_indentations->[-1] + 2); |
5245 | } | | 5255 | } |
5246 | | | 5256 | |
5247 | if ($directive =~ regex_directives_with_args && !defined($args)) { | | 5257 | if ($directive =~ regex_directives_with_args && !defined($args)) { |
5248 | $line->log_error("\".${directive}\" must be given some arguments."); | | 5258 | $line->log_error("\".${directive}\" must be given some arguments."); |
5249 | | | 5259 | |
5250 | } elsif ($directive !~ regex_directives_with_args && defined($args)) { | | 5260 | } elsif ($directive !~ regex_directives_with_args && defined($args)) { |
5251 | $line->log_error("\".${directive}\" does not take arguments."); | | 5261 | $line->log_error("\".${directive}\" does not take arguments."); |
5252 | | | 5262 | |
5253 | if ($directive eq "else") { | | 5263 | if ($directive eq "else") { |
5254 | $line->log_note("If you meant \"else if\", use \".elif\"."); | | 5264 | $line->log_note("If you meant \"else if\", use \".elif\"."); |
5255 | } | | 5265 | } |
5256 | | | 5266 | |
5257 | } elsif ($directive eq "if" || $directive eq "elif") { | | 5267 | } elsif ($directive eq "if" || $directive eq "elif") { |
5258 | checkline_mk_cond($line, $args); | | 5268 | checkline_mk_cond($line, $args); |
5259 | | | 5269 | |
5260 | } elsif ($directive eq "ifdef" || $directive eq "ifndef") { | | 5270 | } elsif ($directive eq "ifdef" || $directive eq "ifndef") { |
5261 | if ($args =~ m"\s") { | | 5271 | if ($args =~ m"\s") { |
5262 | $line->log_error("The \".${directive}\" directive can only handle _one_ argument."); | | 5272 | $line->log_error("The \".${directive}\" directive can only handle _one_ argument."); |
5263 | } else { | | 5273 | } else { |
5264 | $line->log_warning("The \".${directive}\" directive is deprecated. Please use \".if " | | 5274 | $line->log_warning("The \".${directive}\" directive is deprecated. Please use \".if " |
5265 | . (($directive eq "ifdef" ? "" : "!")) | | 5275 | . (($directive eq "ifdef" ? "" : "!")) |
5266 | . "defined(${args})\" instead."); | | 5276 | . "defined(${args})\" instead."); |
5267 | } | | 5277 | } |
5268 | | | 5278 | |
5269 | } elsif ($directive eq "for") { | | 5279 | } elsif ($directive eq "for") { |
5270 | if ($args =~ m"^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$") { | | 5280 | if ($args =~ m"^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$") { |
5271 | my ($vars, $values) = ($1, $2); | | 5281 | my ($vars, $values) = ($1, $2); |
5272 | | | 5282 | |
5273 | foreach my $var (split(qr"\s+", $vars)) { | | 5283 | foreach my $var (split(qr"\s+", $vars)) { |
5274 | if (!$is_internal && $var =~ m"^_") { | | 5284 | if (!$is_internal && $var =~ m"^_") { |
5275 | $line->log_warning("Variable names starting with an underscore are reserved for internal pkgsrc use."); | | 5285 | $line->log_warning("Variable names starting with an underscore are reserved for internal pkgsrc use."); |
5276 | } | | 5286 | } |
5277 | | | 5287 | |
5278 | if ($var =~ m"^[_a-z][_a-z0-9]*$") { | | 5288 | if ($var =~ m"^[_a-z][_a-z0-9]*$") { |
5279 | # Fine. | | 5289 | # Fine. |
5280 | } elsif ($var =~ m"[A-Z]") { | | 5290 | } elsif ($var =~ m"[A-Z]") { |
5281 | $line->log_warning(".for variable names should not contain uppercase letters."); | | 5291 | $line->log_warning(".for variable names should not contain uppercase letters."); |
5282 | } else { | | 5292 | } else { |
5283 | $line->log_error("Invalid variable name \"${var}\"."); | | 5293 | $line->log_error("Invalid variable name \"${var}\"."); |
5284 | } | | 5294 | } |
5285 | | | 5295 | |
5286 | $mkctx_for_variables->{$var} = true; | | 5296 | $mkctx_for_variables->{$var} = true; |
5287 | } | | 5297 | } |
5288 | | | 5298 | |
5289 | # Check if any of the value's types is not guessed. | | 5299 | # Check if any of the value's types is not guessed. |
5290 | my $guessed = true; | | 5300 | my $guessed = true; |
5291 | foreach my $value (split(qr"\s+", $values)) { # XXX: too simple | | 5301 | foreach my $value (split(qr"\s+", $values)) { # XXX: too simple |
5292 | if ($value =~ m"^\$\{(.*)\}") { | | 5302 | if ($value =~ m"^\$\{(.*)\}") { |
5293 | my $type = get_variable_type($line, $1); | | 5303 | my $type = get_variable_type($line, $1); |
5294 | if (defined($type) && !$type->is_guessed()) { | | 5304 | if (defined($type) && !$type->is_guessed()) { |
5295 | $guessed = false; | | 5305 | $guessed = false; |
5296 | } | | 5306 | } |
5297 | } | | 5307 | } |
5298 | } | | 5308 | } |
5299 | | | 5309 | |
5300 | my $for_loop_type = PkgLint::Type->new( | | 5310 | my $for_loop_type = PkgLint::Type->new( |
5301 | LK_INTERNAL, | | 5311 | LK_INTERNAL, |
5302 | "Unchecked", | | 5312 | "Unchecked", |
5303 | [[qr".*", "pu"]], | | 5313 | [[qr".*", "pu"]], |
5304 | $guessed | | 5314 | $guessed |
5305 | ); | | 5315 | ); |
5306 | my $for_loop_context = PkgLint::VarUseContext->new( | | 5316 | my $for_loop_context = PkgLint::VarUseContext->new( |
5307 | VUC_TIME_LOAD, | | 5317 | VUC_TIME_LOAD, |
5308 | $for_loop_type, | | 5318 | $for_loop_type, |
5309 | VUC_SHELLWORD_FOR, | | 5319 | VUC_SHELLWORD_FOR, |
5310 | VUC_EXTENT_WORD | | 5320 | VUC_EXTENT_WORD |
5311 | ); | | 5321 | ); |
5312 | foreach my $var (@{extract_used_variables($line, $values)}) { | | 5322 | foreach my $var (@{extract_used_variables($line, $values)}) { |
5313 | checkline_mk_varuse($line, $var, "", $for_loop_context); | | 5323 | checkline_mk_varuse($line, $var, "", $for_loop_context); |
5314 | } | | 5324 | } |
5315 | | | 5325 | |
5316 | } | | 5326 | } |
5317 | | | 5327 | |
5318 | } elsif ($directive eq "undef" && defined($args)) { | | 5328 | } elsif ($directive eq "undef" && defined($args)) { |
5319 | foreach my $var (split(qr"\s+", $args)) { | | 5329 | foreach my $var (split(qr"\s+", $args)) { |
5320 | if (exists($mkctx_for_variables->{$var})) { | | 5330 | if (exists($mkctx_for_variables->{$var})) { |
5321 | $line->log_note("Using \".undef\" after a \".for\" loop is unnecessary."); | | 5331 | $line->log_note("Using \".undef\" after a \".for\" loop is unnecessary."); |
5322 | } | | 5332 | } |
5323 | } | | 5333 | } |
5324 | } | | 5334 | } |
5325 | | | 5335 | |
5326 | } elsif ($text =~ regex_mk_dependency) { | | 5336 | } elsif ($text =~ regex_mk_dependency) { |
5327 | my ($targets, $whitespace, $dependencies, $comment) = ($1, $2, $3, $4); | | 5337 | my ($targets, $whitespace, $dependencies, $comment) = ($1, $2, $3, $4); |
5328 | | | 5338 | |
5329 | $opt_debug_misc and $line->log_debug("targets=${targets}, dependencies=${dependencies}"); | | 5339 | $opt_debug_misc and $line->log_debug("targets=${targets}, dependencies=${dependencies}"); |
5330 | $mkctx_target = $targets; | | 5340 | $mkctx_target = $targets; |
5331 | | | 5341 | |
5332 | foreach my $source (split(/\s+/, $dependencies)) { | | 5342 | foreach my $source (split(/\s+/, $dependencies)) { |
5333 | if ($source eq ".PHONY") { | | 5343 | if ($source eq ".PHONY") { |
5334 | foreach my $target (split(/\s+/, $targets)) { | | 5344 | foreach my $target (split(/\s+/, $targets)) { |
5335 | $allowed_targets->{$target} = true; | | 5345 | $allowed_targets->{$target} = true; |
5336 | } | | 5346 | } |
5337 | } | | 5347 | } |
5338 | } | | 5348 | } |
5339 | | | 5349 | |
5340 | foreach my $target (split(/\s+/, $targets)) { | | 5350 | foreach my $target (split(/\s+/, $targets)) { |
5341 | if ($target eq ".PHONY") { | | 5351 | if ($target eq ".PHONY") { |
5342 | foreach my $dep (split(qr"\s+", $dependencies)) { | | 5352 | foreach my $dep (split(qr"\s+", $dependencies)) { |
5343 | $allowed_targets->{$dep} = true; | | 5353 | $allowed_targets->{$dep} = true; |
5344 | } | | 5354 | } |
5345 | | | 5355 | |
5346 | } elsif ($target eq ".ORDER") { | | 5356 | } elsif ($target eq ".ORDER") { |
5347 | # TODO: Check for spelling mistakes. | | 5357 | # TODO: Check for spelling mistakes. |
5348 | | | 5358 | |
5349 | } elsif (!exists($allowed_targets->{$target})) { | | 5359 | } elsif (!exists($allowed_targets->{$target})) { |
5350 | $line->log_warning("Unusual target \"${target}\"."); | | 5360 | $line->log_warning("Unusual target \"${target}\"."); |
5351 | $line->explain_warning( | | 5361 | $line->explain_warning( |
5352 | "If you really want to define your own targets, you can \"declare\"", | | 5362 | "If you really want to define your own targets, you can \"declare\"", |
5353 | "them by inserting a \".PHONY: my-target\" line before this line. This", | | 5363 | "them by inserting a \".PHONY: my-target\" line before this line. This", |
5354 | "will tell make(1) to not interpret this target's name as a filename."); | | 5364 | "will tell make(1) to not interpret this target's name as a filename."); |
5355 | } | | 5365 | } |
5356 | } | | 5366 | } |
5357 | | | 5367 | |
5358 | } elsif ($text =~ m"^\.\s*(\S*)") { | | 5368 | } elsif ($text =~ m"^\.\s*(\S*)") { |
5359 | my ($directive) = ($1); | | 5369 | my ($directive) = ($1); |
5360 | | | 5370 | |
5361 | $line->log_error("Unknown directive \".${directive}\"."); | | 5371 | $line->log_error("Unknown directive \".${directive}\"."); |
5362 | | | 5372 | |
5363 | } elsif ($text =~ m"^ ") { | | 5373 | } elsif ($text =~ m"^ ") { |
5364 | $line->log_warning("Makefile lines should not start with space characters."); | | 5374 | $line->log_warning("Makefile lines should not start with space characters."); |
5365 | $line->explain_warning( | | 5375 | $line->explain_warning( |
5366 | "If you want this line to contain a shell program, use a tab", | | 5376 | "If you want this line to contain a shell program, use a tab", |
5367 | "character for indentation. Otherwise please remove the leading", | | 5377 | "character for indentation. Otherwise please remove the leading", |
5368 | "white-space."); | | 5378 | "white-space."); |
5369 | | | 5379 | |
5370 | } else { | | 5380 | } else { |
5371 | $line->log_error("[Internal] Unknown line format: $text"); | | 5381 | $line->log_error("[Internal] Unknown line format: $text"); |
5372 | } | | 5382 | } |
5373 | } | | 5383 | } |
5374 | if (@{$lines} > 0) { | | 5384 | if (@{$lines} > 0) { |
5375 | $substcontext->check_end($lines->[-1]); | | 5385 | $substcontext->check_end($lines->[-1]); |
5376 | } | | 5386 | } |
5377 | | | 5387 | |
5378 | checklines_trailing_empty_lines($lines); | | 5388 | checklines_trailing_empty_lines($lines); |
5379 | | | 5389 | |
5380 | if ($#{$mkctx_indentations} != 0) { | | 5390 | if ($#{$mkctx_indentations} != 0) { |
5381 | $lines->[-1]->log_error("Directive indentation is not 0, but ".$mkctx_indentations->[-1]." at EOF."); | | 5391 | $lines->[-1]->log_error("Directive indentation is not 0, but ".$mkctx_indentations->[-1]." at EOF."); |
5382 | } | | 5392 | } |
5383 | | | 5393 | |
5384 | # Clean up global variables. | | 5394 | # Clean up global variables. |
5385 | $mkctx_for_variables = undef; | | 5395 | $mkctx_for_variables = undef; |
5386 | $mkctx_indentations = undef; | | 5396 | $mkctx_indentations = undef; |
5387 | $mkctx_target = undef; | | 5397 | $mkctx_target = undef; |
5388 | $mkctx_vardef = undef; | | 5398 | $mkctx_vardef = undef; |
5389 | $mkctx_build_defs = undef; | | 5399 | $mkctx_build_defs = undef; |
5390 | $mkctx_plist_vars = undef; | | 5400 | $mkctx_plist_vars = undef; |
5391 | $mkctx_tools = undef; | | 5401 | $mkctx_tools = undef; |
5392 | $mkctx_varuse = undef; | | 5402 | $mkctx_varuse = undef; |
5393 | } | | 5403 | } |
5394 | | | 5404 | |
5395 | sub checklines_buildlink3_inclusion($) { | | 5405 | sub checklines_buildlink3_inclusion($) { |
5396 | my ($lines) = @_; | | 5406 | my ($lines) = @_; |
5397 | my ($included_files); | | 5407 | my ($included_files); |
5398 | | | 5408 | |
5399 | assert(@{$lines} != 0, "The lines array must be non-empty."); | | 5409 | assert(@{$lines} != 0, "The lines array must be non-empty."); |
5400 | $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_buildlink3_inclusion()"); | | 5410 | $opt_debug_trace and log_debug($lines->[0]->fname, NO_LINES, "checklines_buildlink3_inclusion()"); |
5401 | | | 5411 | |
| @@ -5935,1615 +5945,1618 @@ sub checkfile_distinfo($) { | | | @@ -5935,1615 +5945,1618 @@ sub checkfile_distinfo($) { |
5935 | $line->log_error("The ${alg} checksum for ${chksum_fname} differs ..."); | | 5945 | $line->log_error("The ${alg} checksum for ${chksum_fname} differs ..."); |
5936 | $other->[0]->log_error("... from this one."); | | 5946 | $other->[0]->log_error("... from this one."); |
5937 | } | | 5947 | } |
5938 | } else { | | 5948 | } else { |
5939 | $ipc_distinfo->{$alg}->{$chksum_fname} = [$line, $sum]; | | 5949 | $ipc_distinfo->{$alg}->{$chksum_fname} = [$line, $sum]; |
5940 | } | | 5950 | } |
5941 | } | | 5951 | } |
5942 | | | 5952 | |
5943 | if ($alg eq "MD5") { | | 5953 | if ($alg eq "MD5") { |
5944 | $line->log_error("MD5 checksums are obsolete."); | | 5954 | $line->log_error("MD5 checksums are obsolete."); |
5945 | $line->explain_error( | | 5955 | $line->explain_error( |
5946 | "Run \"".conf_make." makedistinfo\" to regenerate the distinfo file."); | | 5956 | "Run \"".conf_make." makedistinfo\" to regenerate the distinfo file."); |
5947 | next; | | 5957 | next; |
5948 | } | | 5958 | } |
5949 | | | 5959 | |
5950 | if ($state == DIS_SHA1) { | | 5960 | if ($state == DIS_SHA1) { |
5951 | if ($alg eq "SHA1") { | | 5961 | if ($alg eq "SHA1") { |
5952 | $state = ($is_patch ? DIS_start : DIS_RMD160); | | 5962 | $state = ($is_patch ? DIS_start : DIS_RMD160); |
5953 | $current_fname = $chksum_fname; | | 5963 | $current_fname = $chksum_fname; |
5954 | } else { | | 5964 | } else { |
5955 | $line->log_warning("Expected an SHA1 checksum."); | | 5965 | $line->log_warning("Expected an SHA1 checksum."); |
5956 | } | | 5966 | } |
5957 | | | 5967 | |
5958 | } elsif ($state == DIS_RMD160) { | | 5968 | } elsif ($state == DIS_RMD160) { |
5959 | $state = DIS_start; | | 5969 | $state = DIS_start; |
5960 | if ($alg eq "RMD160") { | | 5970 | if ($alg eq "RMD160") { |
5961 | if ($chksum_fname eq $current_fname) { | | 5971 | if ($chksum_fname eq $current_fname) { |
5962 | $state = DIS_Size; | | 5972 | $state = DIS_Size; |
5963 | } else { | | 5973 | } else { |
5964 | $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not for ${chksum_fname}."); | | 5974 | $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not for ${chksum_fname}."); |
5965 | } | | 5975 | } |
5966 | } else { | | 5976 | } else { |
5967 | if ($chksum_fname eq $current_fname) { | | 5977 | if ($chksum_fname eq $current_fname) { |
5968 | # This is an error because this really should be fixed. | | 5978 | # This is an error because this really should be fixed. |
5969 | $line->log_error("Expected an RMD160 checksum, not ${alg} for ${chksum_fname}."); | | 5979 | $line->log_error("Expected an RMD160 checksum, not ${alg} for ${chksum_fname}."); |
5970 | } else { | | 5980 | } else { |
5971 | $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); | | 5981 | $line->log_warning("Expected an RMD160 checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); |
5972 | } | | 5982 | } |
5973 | } | | 5983 | } |
5974 | | | 5984 | |
5975 | } elsif ($state == DIS_Size) { | | 5985 | } elsif ($state == DIS_Size) { |
5976 | $state = DIS_start; | | 5986 | $state = DIS_start; |
5977 | if ($alg eq "Size") { | | 5987 | if ($alg eq "Size") { |
5978 | if ($chksum_fname ne $current_fname) { | | 5988 | if ($chksum_fname ne $current_fname) { |
5979 | $line->log_warning("Expected a Size checksum for ${current_fname}, not for ${chksum_fname}."); | | 5989 | $line->log_warning("Expected a Size checksum for ${current_fname}, not for ${chksum_fname}."); |
5980 | } | | 5990 | } |
5981 | } else { | | 5991 | } else { |
5982 | if ($chksum_fname eq $current_fname) { | | 5992 | if ($chksum_fname eq $current_fname) { |
5983 | $line->log_warning("Expected a Size checksum, not ${alg} for ${chksum_fname}."); | | 5993 | $line->log_warning("Expected a Size checksum, not ${alg} for ${chksum_fname}."); |
5984 | } else { | | 5994 | } else { |
5985 | $line->log_warning("Expected a Size checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); | | 5995 | $line->log_warning("Expected a Size checksum for ${current_fname}, not ${alg} for ${chksum_fname}."); |
5986 | } | | 5996 | } |
5987 | } | | 5997 | } |
5988 | } | | 5998 | } |
5989 | | | 5999 | |
5990 | if ($is_patch && defined($patches_dir) && !(defined($distinfo_file) && $distinfo_file eq "./../../lang/php5/distinfo")) { | | 6000 | if ($is_patch && defined($patches_dir) && !(defined($distinfo_file) && $distinfo_file eq "./../../lang/php5/distinfo")) { |
5991 | my $fname = "${current_dir}/${patches_dir}/${chksum_fname}"; | | 6001 | my $fname = "${current_dir}/${patches_dir}/${chksum_fname}"; |
5992 | if ($di_is_committed && !is_committed($fname)) { | | 6002 | if ($di_is_committed && !is_committed($fname)) { |
5993 | $line->log_warning("${patches_dir}/${chksum_fname} is registered in distinfo but not added to CVS."); | | 6003 | $line->log_warning("${patches_dir}/${chksum_fname} is registered in distinfo but not added to CVS."); |
5994 | } | | 6004 | } |
5995 | | | 6005 | |
5996 | if (open(PATCH, "<", $fname)) { | | 6006 | if (open(PATCH, "<", $fname)) { |
5997 | my $data = ""; | | 6007 | my $data = ""; |
5998 | foreach my $patchline (<PATCH>) { | | 6008 | foreach my $patchline (<PATCH>) { |
5999 | $data .= $patchline unless $patchline =~ m"\$[N]etBSD"; | | 6009 | $data .= $patchline unless $patchline =~ m"\$[N]etBSD"; |
6000 | } | | 6010 | } |
6001 | close(PATCH); | | 6011 | close(PATCH); |
6002 | my $chksum = Digest::SHA1::sha1_hex($data); | | 6012 | my $chksum = Digest::SHA1::sha1_hex($data); |
6003 | if ($sum ne $chksum) { | | 6013 | if ($sum ne $chksum) { |
6004 | $line->log_error("${alg} checksum of ${chksum_fname} differs (expected ${sum}, got ${chksum}). Rerun '".conf_make." makepatchsum'."); | | 6014 | $line->log_error("${alg} checksum of ${chksum_fname} differs (expected ${sum}, got ${chksum}). Rerun '".conf_make." makepatchsum'."); |
6005 | } | | 6015 | } |
6006 | } elsif (true) { | | 6016 | } elsif (true) { |
6007 | $line->log_warning("${chksum_fname} does not exist."); | | 6017 | $line->log_warning("${chksum_fname} does not exist."); |
6008 | $line->explain_warning( | | 6018 | $line->explain_warning( |
6009 | "All patches that are mentioned in a distinfo file should actually exist.", | | 6019 | "All patches that are mentioned in a distinfo file should actually exist.", |
6010 | "What's the use of a checksum if there is no file to check?"); | | 6020 | "What's the use of a checksum if there is no file to check?"); |
6011 | } | | 6021 | } |
6012 | } | | 6022 | } |
6013 | $in_distinfo{$chksum_fname} = true; | | 6023 | $in_distinfo{$chksum_fname} = true; |
6014 | } | | 6024 | } |
6015 | checklines_trailing_empty_lines($lines); | | 6025 | checklines_trailing_empty_lines($lines); |
6016 | | | 6026 | |
6017 | if (defined($patches_dir)) { | | 6027 | if (defined($patches_dir)) { |
6018 | foreach my $patch (<${current_dir}/${patches_dir}/patch-*>) { | | 6028 | foreach my $patch (<${current_dir}/${patches_dir}/patch-*>) { |
6019 | $patch = basename($patch); | | 6029 | $patch = basename($patch); |
6020 | if (!exists($in_distinfo{$patch})) { | | 6030 | if (!exists($in_distinfo{$patch})) { |
6021 | log_error($fname, NO_LINE_NUMBER, "$patch is not recorded. Rerun '".conf_make." makepatchsum'."); | | 6031 | log_error($fname, NO_LINE_NUMBER, "$patch is not recorded. Rerun '".conf_make." makepatchsum'."); |
6022 | } | | 6032 | } |
6023 | } | | 6033 | } |
6024 | } | | 6034 | } |
6025 | } | | 6035 | } |
6026 | | | 6036 | |
6027 | sub checkfile_extra($) { | | 6037 | sub checkfile_extra($) { |
6028 | my ($fname) = @_; | | 6038 | my ($fname) = @_; |
6029 | my ($lines); | | 6039 | my ($lines); |
6030 | | | 6040 | |
6031 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_extra()"); | | 6041 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_extra()"); |
6032 | | | 6042 | |
6033 | $lines = load_file($fname); | | 6043 | $lines = load_file($fname); |
6034 | if (!$lines) { | | 6044 | if (!$lines) { |
6035 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); | | 6045 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); |
6036 | return; | | 6046 | return; |
6037 | } | | 6047 | } |
6038 | checklines_trailing_empty_lines($lines); | | 6048 | checklines_trailing_empty_lines($lines); |
6039 | checkperms($fname); | | 6049 | checkperms($fname); |
6040 | } | | 6050 | } |
6041 | | | 6051 | |
6042 | sub checkfile_INSTALL($) { | | 6052 | sub checkfile_INSTALL($) { |
6043 | my ($fname) = @_; | | 6053 | my ($fname) = @_; |
6044 | my ($lines); | | 6054 | my ($lines); |
6045 | | | 6055 | |
6046 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); | | 6056 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_INSTALL()"); |
6047 | | | 6057 | |
6048 | checkperms($fname); | | 6058 | checkperms($fname); |
6049 | if (!($lines = load_file($fname))) { | | 6059 | if (!($lines = load_file($fname))) { |
6050 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6060 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6051 | return; | | 6061 | return; |
6052 | } | | 6062 | } |
6053 | } | | 6063 | } |
6054 | | | 6064 | |
6055 | sub checkfile_MESSAGE($) { | | 6065 | sub checkfile_MESSAGE($) { |
6056 | my ($fname) = @_; | | 6066 | my ($fname) = @_; |
6057 | my ($lines); | | 6067 | my ($lines); |
6058 | | | 6068 | |
6059 | my @explanation = ( | | 6069 | my @explanation = ( |
6060 | "A MESSAGE file should consist of a header line, having 75 \"=\"", | | 6070 | "A MESSAGE file should consist of a header line, having 75 \"=\"", |
6061 | "characters, followed by a line containing only the RCS Id, then an", | | 6071 | "characters, followed by a line containing only the RCS Id, then an", |
6062 | "empty line, your text and finally the footer line, which is the", | | 6072 | "empty line, your text and finally the footer line, which is the", |
6063 | "same as the header line."); | | 6073 | "same as the header line."); |
6064 | | | 6074 | |
6065 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); | | 6075 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_MESSAGE()"); |
6066 | | | 6076 | |
6067 | checkperms($fname); | | 6077 | checkperms($fname); |
6068 | if (!($lines = load_file($fname))) { | | 6078 | if (!($lines = load_file($fname))) { |
6069 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6079 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6070 | return; | | 6080 | return; |
6071 | } | | 6081 | } |
6072 | | | 6082 | |
6073 | if (@{$lines} < 3) { | | 6083 | if (@{$lines} < 3) { |
6074 | log_warning($fname, NO_LINE_NUMBER, "File too short."); | | 6084 | log_warning($fname, NO_LINE_NUMBER, "File too short."); |
6075 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6085 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6076 | return; | | 6086 | return; |
6077 | } | | 6087 | } |
6078 | if ($lines->[0]->text ne "=" x 75) { | | 6088 | if ($lines->[0]->text ne "=" x 75) { |
6079 | $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); | | 6089 | $lines->[0]->log_warning("Expected a line of exactly 75 \"=\" characters."); |
6080 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6090 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6081 | } | | 6091 | } |
6082 | checkline_rcsid($lines->[1], ""); | | 6092 | checkline_rcsid($lines->[1], ""); |
6083 | foreach my $line (@{$lines}) { | | 6093 | foreach my $line (@{$lines}) { |
6084 | checkline_length($line, 80); | | 6094 | checkline_length($line, 80); |
6085 | checkline_trailing_whitespace($line); | | 6095 | checkline_trailing_whitespace($line); |
6086 | checkline_valid_characters($line, regex_validchars); | | 6096 | checkline_valid_characters($line, regex_validchars); |
6087 | checkline_spellcheck($line); | | 6097 | checkline_spellcheck($line); |
6088 | } | | 6098 | } |
6089 | if ($lines->[-1]->text ne "=" x 75) { | | 6099 | if ($lines->[-1]->text ne "=" x 75) { |
6090 | $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); | | 6100 | $lines->[-1]->log_warning("Expected a line of exactly 75 \"=\" characters."); |
6091 | explain_warning($fname, NO_LINE_NUMBER, @explanation); | | 6101 | explain_warning($fname, NO_LINE_NUMBER, @explanation); |
6092 | } | | 6102 | } |
6093 | checklines_trailing_empty_lines($lines); | | 6103 | checklines_trailing_empty_lines($lines); |
6094 | } | | 6104 | } |
6095 | | | 6105 | |
6096 | sub checkfile_mk($) { | | 6106 | sub checkfile_mk($) { |
6097 | my ($fname) = @_; | | 6107 | my ($fname) = @_; |
6098 | my ($lines); | | 6108 | my ($lines); |
6099 | | | 6109 | |
6100 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); | | 6110 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_mk()"); |
6101 | | | 6111 | |
6102 | checkperms($fname); | | 6112 | checkperms($fname); |
6103 | if (!($lines = load_lines($fname, true))) { | | 6113 | if (!($lines = load_lines($fname, true))) { |
6104 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6114 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6105 | return; | | 6115 | return; |
6106 | } | | 6116 | } |
6107 | | | 6117 | |
6108 | parselines_mk($lines); | | 6118 | parselines_mk($lines); |
6109 | checklines_mk($lines); | | 6119 | checklines_mk($lines); |
6110 | autofix($lines); | | 6120 | autofix($lines); |
6111 | } | | 6121 | } |
6112 | | | 6122 | |
6113 | sub checkfile_package_Makefile($$) { | | 6123 | sub checkfile_package_Makefile($$) { |
6114 | my ($fname, $lines) = @_; | | 6124 | my ($fname, $lines) = @_; |
6115 | | | 6125 | |
6116 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); | | 6126 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_package_Makefile(..., ...)"); |
6117 | | | 6127 | |
6118 | checkperms($fname); | | 6128 | checkperms($fname); |
6119 | | | 6129 | |
6120 | if (!exists($pkgctx_vardef->{"PLIST_SRC"}) | | 6130 | if (!exists($pkgctx_vardef->{"PLIST_SRC"}) |
6121 | && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) | | 6131 | && !exists($pkgctx_vardef->{"GENERATE_PLIST"}) |
6122 | && !exists($pkgctx_vardef->{"META_PACKAGE"}) | | 6132 | && !exists($pkgctx_vardef->{"META_PACKAGE"}) |
6123 | && defined($pkgdir) | | 6133 | && defined($pkgdir) |
6124 | && !-f "${current_dir}/$pkgdir/PLIST" | | 6134 | && !-f "${current_dir}/$pkgdir/PLIST" |
6125 | && !-f "${current_dir}/$pkgdir/PLIST.common") { | | 6135 | && !-f "${current_dir}/$pkgdir/PLIST.common") { |
6126 | log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); | | 6136 | log_warning($fname, NO_LINE_NUMBER, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?"); |
6127 | } | | 6137 | } |
6128 | | | 6138 | |
6129 | if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { | | 6139 | if ((exists($pkgctx_vardef->{"NO_CHECKSUM"}) || $pkgctx_vardef->{"META_PACKAGE"}) && is_emptydir("${current_dir}/${patchdir}")) { |
6130 | if (-f "${current_dir}/${distinfo_file}") { | | 6140 | if (-f "${current_dir}/${distinfo_file}") { |
6131 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); | | 6141 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set."); |
6132 | } | | 6142 | } |
6133 | } else { | | 6143 | } else { |
6134 | if (!-f "${current_dir}/${distinfo_file}") { | | 6144 | if (!-f "${current_dir}/${distinfo_file}") { |
6135 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); | | 6145 | log_warning("${current_dir}/${distinfo_file}", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makesum'."); |
6136 | } | | 6146 | } |
6137 | } | | 6147 | } |
6138 | | | 6148 | |
6139 | if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { | | 6149 | if (exists($pkgctx_vardef->{"REPLACE_PERL"}) && exists($pkgctx_vardef->{"NO_CONFIGURE"})) { |
6140 | $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); | | 6150 | $pkgctx_vardef->{"REPLACE_PERL"}->log_warning("REPLACE_PERL is ignored when ..."); |
6141 | $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); | | 6151 | $pkgctx_vardef->{"NO_CONFIGURE"}->log_warning("... NO_CONFIGURE is set."); |
6142 | } | | 6152 | } |
6143 | | | 6153 | |
6144 | if (!exists($pkgctx_vardef->{"LICENSE"})) { | | 6154 | if (!exists($pkgctx_vardef->{"LICENSE"})) { |
6145 | log_error($fname, NO_LINE_NUMBER, "Each package must define its LICENSE."); | | 6155 | log_error($fname, NO_LINE_NUMBER, "Each package must define its LICENSE."); |
6146 | } | | 6156 | } |
6147 | | | 6157 | |
6148 | if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { | | 6158 | if (exists($pkgctx_vardef->{"GNU_CONFIGURE"}) && exists($pkgctx_vardef->{"USE_LANGUAGES"})) { |
6149 | my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; | | 6159 | my $languages_line = $pkgctx_vardef->{"USE_LANGUAGES"}; |
6150 | my $value = $languages_line->get("value"); | | 6160 | my $value = $languages_line->get("value"); |
6151 | | | 6161 | |
6152 | if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { | | 6162 | if ($languages_line->has("comment") && $languages_line->get("comment") =~ m"\b(?:c|empty|none)\b"i) { |
6153 | # Don't emit a warning, since the comment | | 6163 | # Don't emit a warning, since the comment |
6154 | # probably contains a statement that C is | | 6164 | # probably contains a statement that C is |
6155 | # really not needed. | | 6165 | # really not needed. |
6156 | | | 6166 | |
6157 | } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { | | 6167 | } elsif ($value !~ m"(?:^|\s+)(?:c|c99|objc)(?:\s+|$)") { |
6158 | $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); | | 6168 | $pkgctx_vardef->{"GNU_CONFIGURE"}->log_warning("GNU_CONFIGURE almost always needs a C compiler, ..."); |
6159 | $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); | | 6169 | $languages_line->log_warning("... but \"c\" is not added to USE_LANGUAGES."); |
6160 | } | | 6170 | } |
6161 | } | | 6171 | } |
6162 | | | 6172 | |
6163 | my $distname_line = $pkgctx_vardef->{"DISTNAME"}; | | 6173 | my $distname_line = $pkgctx_vardef->{"DISTNAME"}; |
6164 | my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; | | 6174 | my $pkgname_line = $pkgctx_vardef->{"PKGNAME"}; |
6165 | | | 6175 | |
6166 | my $distname = defined($distname_line) ? $distname_line->get("value") : undef; | | 6176 | my $distname = defined($distname_line) ? $distname_line->get("value") : undef; |
6167 | my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; | | 6177 | my $pkgname = defined($pkgname_line) ? $pkgname_line->get("value") : undef; |
6168 | my $nbpart = get_nbpart(); | | 6178 | my $nbpart = get_nbpart(); |
6169 | | | 6179 | |
6170 | # Let's do some tricks to get the proper value of the package | | 6180 | # Let's do some tricks to get the proper value of the package |
6171 | # name more often. | | 6181 | # name more often. |
6172 | if (defined($distname) && defined($pkgname)) { | | 6182 | if (defined($distname) && defined($pkgname)) { |
6173 | $pkgname =~ s/\$\{DISTNAME\}/$distname/; | | 6183 | $pkgname =~ s/\$\{DISTNAME\}/$distname/; |
6174 | | | 6184 | |
6175 | if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { | | 6185 | if ($pkgname =~ m"^(.*)\$\{DISTNAME:S(.)([^:]*)\2([^:]*)\2(g?)\}(.*)$") { |
6176 | my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); | | 6186 | my ($before, $separator, $old, $new, $mod, $after) = ($1, $2, $3, $4, $5, $6); |
6177 | my $newname = $distname; | | 6187 | my $newname = $distname; |
6178 | $old = quotemeta($old); | | 6188 | $old = quotemeta($old); |
6179 | $old =~ s/^\\\^/^/; | | 6189 | $old =~ s/^\\\^/^/; |
6180 | $old =~ s/\\\$$/\$/; | | 6190 | $old =~ s/\\\$$/\$/; |
6181 | if ($mod eq "g") { | | 6191 | if ($mod eq "g") { |
6182 | $newname =~ s/$old/$new/g; | | 6192 | $newname =~ s/$old/$new/g; |
6183 | } else { | | 6193 | } else { |
6184 | $newname =~ s/$old/$new/; | | 6194 | $newname =~ s/$old/$new/; |
6185 | } | | 6195 | } |
6186 | $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); | | 6196 | $opt_debug_misc and $pkgname_line->log_debug("old pkgname=$pkgname"); |
6187 | $pkgname = $before . $newname . $after; | | 6197 | $pkgname = $before . $newname . $after; |
6188 | $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); | | 6198 | $opt_debug_misc and $pkgname_line->log_debug("new pkgname=$pkgname"); |
6189 | } | | 6199 | } |
6190 | } | | 6200 | } |
6191 | | | 6201 | |
6192 | if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { | | 6202 | if (defined($pkgname) && defined($distname) && $pkgname eq $distname) { |
6193 | $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); | | 6203 | $pkgname_line->log_note("PKGNAME is \${DISTNAME} by default. You probably don't need to define PKGNAME."); |
6194 | } | | 6204 | } |
6195 | | | 6205 | |
6196 | if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { | | 6206 | if (!defined($pkgname) && defined($distname) && $distname !~ regex_unresolved && $distname !~ regex_pkgname) { |
6197 | $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); | | 6207 | $distname_line->log_warning("As DISTNAME is not a valid package name, please define the PKGNAME explicitly."); |
6198 | } | | 6208 | } |
6199 | | | 6209 | |
6200 | ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) | | 6210 | ($effective_pkgname, $effective_pkgname_line, $effective_pkgbase, $effective_pkgversion) |
6201 | = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) | | 6211 | = (defined($pkgname) && $pkgname !~ regex_unresolved && $pkgname =~ regex_pkgname) ? ($pkgname.$nbpart, $pkgname_line, $1, $2) |
6202 | : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) | | 6212 | : (defined($distname) && $distname !~ regex_unresolved && $distname =~ regex_pkgname) ? ($distname.$nbpart, $distname_line, $1, $2) |
6203 | : (undef, undef, undef, undef); | | 6213 | : (undef, undef, undef, undef); |
6204 | if (defined($effective_pkgname_line)) { | | 6214 | if (defined($effective_pkgname_line)) { |
6205 | $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); | | 6215 | $opt_debug_misc and $effective_pkgname_line->log_debug("Effective name=${effective_pkgname} base=${effective_pkgbase} version=${effective_pkgversion}."); |
6206 | # XXX: too many false positives | | 6216 | # XXX: too many false positives |
6207 | if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) { | | 6217 | if (false && $pkgpath =~ m"/([^/]+)$" && $effective_pkgbase ne $1) { |
6208 | $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1)."); | | 6218 | $effective_pkgname_line->log_warning("Mismatch between PKGNAME ($effective_pkgname) and package directory ($1)."); |
6209 | } | | 6219 | } |
6210 | } | | 6220 | } |
6211 | | | 6221 | |
6212 | checkpackage_possible_downgrade(); | | 6222 | checkpackage_possible_downgrade(); |
6213 | | | 6223 | |
6214 | if (!exists($pkgctx_vardef->{"COMMENT"})) { | | 6224 | if (!exists($pkgctx_vardef->{"COMMENT"})) { |
6215 | log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); | | 6225 | log_warning($fname, NO_LINE_NUMBER, "No COMMENT given."); |
6216 | } | | 6226 | } |
6217 | | | 6227 | |
6218 | if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { | | 6228 | if (exists($pkgctx_vardef->{"USE_IMAKE"}) && exists($pkgctx_vardef->{"USE_X11"})) { |
6219 | $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); | | 6229 | $pkgctx_vardef->{"USE_IMAKE"}->log_note("USE_IMAKE makes ..."); |
6220 | $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); | | 6230 | $pkgctx_vardef->{"USE_X11"}->log_note("... USE_X11 superfluous."); |
6221 | } | | 6231 | } |
6222 | | | 6232 | |
6223 | if (defined($effective_pkgbase)) { | | 6233 | if (defined($effective_pkgbase)) { |
6224 | | | 6234 | |
6225 | foreach my $suggested_update (@{get_suggested_package_updates()}) { | | 6235 | foreach my $suggested_update (@{get_suggested_package_updates()}) { |
6226 | my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; | | 6236 | my ($line, $suggbase, $suggver, $suggcomm) = @{$suggested_update}; |
6227 | my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); | | 6237 | my $comment = (defined($suggcomm) ? " (${suggcomm})" : ""); |
6228 | | | 6238 | |
6229 | next unless $effective_pkgbase eq $suggbase; | | 6239 | next unless $effective_pkgbase eq $suggbase; |
6230 | | | 6240 | |
6231 | if (dewey_cmp($effective_pkgversion, "<", $suggver)) { | | 6241 | if (dewey_cmp($effective_pkgversion, "<", $suggver)) { |
6232 | $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); | | 6242 | $effective_pkgname_line->log_warning("This package should be updated to ${suggver}${comment}."); |
6233 | $effective_pkgname_line->explain_warning( | | 6243 | $effective_pkgname_line->explain_warning( |
6234 | "The wishlist for package updates in doc/TODO mentions that a newer", | | 6244 | "The wishlist for package updates in doc/TODO mentions that a newer", |
6235 | "version of this package is available."); | | 6245 | "version of this package is available."); |
6236 | } | | 6246 | } |
6237 | if (dewey_cmp($effective_pkgversion, "==", $suggver)) { | | 6247 | if (dewey_cmp($effective_pkgversion, "==", $suggver)) { |
6238 | $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); | | 6248 | $effective_pkgname_line->log_note("The update request to ${suggver} from doc/TODO${comment} has been done."); |
6239 | } | | 6249 | } |
6240 | if (dewey_cmp($effective_pkgversion, ">", $suggver)) { | | 6250 | if (dewey_cmp($effective_pkgversion, ">", $suggver)) { |
6241 | $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); | | 6251 | $effective_pkgname_line->log_note("This package is newer than the update request to ${suggver}${comment}."); |
6242 | } | | 6252 | } |
6243 | } | | 6253 | } |
6244 | } | | 6254 | } |
6245 | | | 6255 | |
6246 | checklines_mk($lines); | | 6256 | checklines_mk($lines); |
6247 | checklines_package_Makefile_varorder($lines); | | 6257 | checklines_package_Makefile_varorder($lines); |
6248 | autofix($lines); | | 6258 | autofix($lines); |
6249 | } | | 6259 | } |
6250 | | | 6260 | |
6251 | sub checkfile_patch($) { | | 6261 | sub checkfile_patch($) { |
6252 | my ($fname) = @_; | | 6262 | my ($fname) = @_; |
6253 | my ($lines); | | 6263 | my ($lines); |
6254 | my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); | | 6264 | my ($state, $redostate, $nextstate, $dellines, $addlines, $hunks); |
6255 | my ($seen_comment, $current_fname, $current_ftype, $patched_files); | | 6265 | my ($seen_comment, $current_fname, $current_ftype, $patched_files); |
6256 | my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); | | 6266 | my ($leading_context_lines, $trailing_context_lines, $context_scanning_leading); |
6257 | | | 6267 | |
6258 | # Abbreviations used: | | 6268 | # Abbreviations used: |
6259 | # style: [c] = context diff, [u] = unified diff | | 6269 | # style: [c] = context diff, [u] = unified diff |
6260 | # scope: [f] = file, [h] = hunk, [l] = line | | 6270 | # scope: [f] = file, [h] = hunk, [l] = line |
6261 | # action: [d] = delete, [m] = modify, [a] = add, [c] = context | | 6271 | # action: [d] = delete, [m] = modify, [a] = add, [c] = context |
6262 | use constant re_patch_rcsid => qr"^\$.*\$$"; | | 6272 | use constant re_patch_rcsid => qr"^\$.*\$$"; |
6263 | use constant re_patch_text => qr"^(.+)$"; | | 6273 | use constant re_patch_text => qr"^(.+)$"; |
6264 | use constant re_patch_empty => qr"^$"; | | 6274 | use constant re_patch_empty => qr"^$"; |
6265 | use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; | | 6275 | use constant re_patch_cfd => qr"^\*\*\*\s(\S+)(.*)$"; |
6266 | use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; | | 6276 | use constant re_patch_cfa => qr"^---\s(\S+)(.*)$"; |
6267 | use constant re_patch_ch => qr"^\*{15}(.*)$"; | | 6277 | use constant re_patch_ch => qr"^\*{15}(.*)$"; |
6268 | use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; | | 6278 | use constant re_patch_chd => qr"^\*{3}\s(\d+)(?:,(\d+))?\s\*{4}$"; |
6269 | use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; | | 6279 | use constant re_patch_cha => qr"^-{3}\s(\d+)(?:,(\d+))?\s-{4}$"; |
6270 | use constant re_patch_cld => qr"^(?:-\s(.*))?$"; | | 6280 | use constant re_patch_cld => qr"^(?:-\s(.*))?$"; |
6271 | use constant re_patch_clm => qr"^(?:!\s(.*))?$"; | | 6281 | use constant re_patch_clm => qr"^(?:!\s(.*))?$"; |
6272 | use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; | | 6282 | use constant re_patch_cla => qr"^(?:\+\s(.*))?$"; |
6273 | use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; | | 6283 | use constant re_patch_clc => qr"^(?:\s\s(.*))?$"; |
6274 | use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; | | 6284 | use constant re_patch_ufd => qr"^---\s(\S+)(?:\s+(.*))?$"; |
6275 | use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; | | 6285 | use constant re_patch_ufa => qr"^\+{3}\s(\S+)(?:\s+(.*))?$"; |
6276 | use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; | | 6286 | use constant re_patch_uh => qr"^\@\@\s-(?:(\d+),)?(\d+)\s\+(?:(\d+),)?(\d+)\s\@\@(.*)$"; |
6277 | use constant re_patch_uld => qr"^-(.*)$"; | | 6287 | use constant re_patch_uld => qr"^-(.*)$"; |
6278 | use constant re_patch_ula => qr"^\+(.*)$"; | | 6288 | use constant re_patch_ula => qr"^\+(.*)$"; |
6279 | use constant re_patch_ulc => qr"^\s(.*)$"; | | 6289 | use constant re_patch_ulc => qr"^\s(.*)$"; |
6280 | use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; | | 6290 | use constant re_patch_ulnonl => qr"^\\ No newline at end of file$"; |
6281 | | | 6291 | |
6282 | use enum qw(:PST_ | | 6292 | use enum qw(:PST_ |
6283 | START CENTER TEXT | | 6293 | START CENTER TEXT |
6284 | CFA CH CHD CLD0 CLD CLA0 CLA | | 6294 | CFA CH CHD CLD0 CLD CLA0 CLA |
6285 | UFA UH UL | | 6295 | UFA UH UL |
6286 | ); | | 6296 | ); |
6287 | | | 6297 | |
6288 | my @comment_explanation = ( | | 6298 | my @comment_explanation = ( |
6289 | "Each patch must document why it is necessary. If it has been applied", | | 6299 | "Each patch must document why it is necessary. If it has been applied", |
6290 | "because of a security issue, a reference to the CVE should be mentioned", | | 6300 | "because of a security issue, a reference to the CVE should be mentioned", |
6291 | "as well.", | | 6301 | "as well.", |
6292 | "", | | 6302 | "", |
6293 | "Since it is our goal to have as few patches as possible, all patches", | | 6303 | "Since it is our goal to have as few patches as possible, all patches", |
6294 | "should be sent to the upstream maintainers of the package. After you", | | 6304 | "should be sent to the upstream maintainers of the package. After you", |
6295 | "have done so, you should add a reference to the bug report containing", | | 6305 | "have done so, you should add a reference to the bug report containing", |
6296 | "the patch."); | | 6306 | "the patch."); |
6297 | | | 6307 | |
6298 | my ($line, $m); | | 6308 | my ($line, $m); |
6299 | | | 6309 | |
6300 | my $check_text = sub($) { | | 6310 | my $check_text = sub($) { |
6301 | my ($text) = @_; | | 6311 | my ($text) = @_; |
6302 | | | 6312 | |
6303 | if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { | | 6313 | if ($text =~ m"(\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|$opt_rcsidstring)(?::[^\$]*)?\$)") { |
6304 | my ($tag) = ($2); | | 6314 | my ($tag) = ($2); |
6305 | | | 6315 | |
6306 | if ($text =~ re_patch_uh) { | | 6316 | if ($text =~ re_patch_uh) { |
6307 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); | | 6317 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it."); |
6308 | $line->set_text($1); | | 6318 | $line->set_text($1); |
6309 | } else { | | 6319 | } else { |
6310 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); | | 6320 | $line->log_warning("Found RCS tag \"\$${tag}\$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\"."); |
6311 | } | | 6321 | } |
6312 | } | | 6322 | } |
6313 | }; | | 6323 | }; |
6314 | | | 6324 | |
6315 | my $check_contents = sub() { | | 6325 | my $check_contents = sub() { |
6316 | | | 6326 | |
6317 | if ($m->has(1)) { | | 6327 | if ($m->has(1)) { |
6318 | $check_text->($m->text(1)); | | 6328 | $check_text->($m->text(1)); |
6319 | } | | 6329 | } |
6320 | }; | | 6330 | }; |
6321 | | | 6331 | |
6322 | my $check_added_contents = sub() { | | 6332 | my $check_added_contents = sub() { |
6323 | my $text; | | 6333 | my $text; |
6324 | | | 6334 | |
6325 | return unless $m->has(1); | | 6335 | return unless $m->has(1); |
6326 | $text = $m->text(1); | | 6336 | $text = $m->text(1); |
6327 | checkline_cpp_macro_names($line, $text); | | 6337 | checkline_cpp_macro_names($line, $text); |
6328 | checkline_spellcheck($line); | | 6338 | checkline_spellcheck($line); |
6329 | | | 6339 | |
6330 | # XXX: This check is not as accurate as the similar one in | | 6340 | # XXX: This check is not as accurate as the similar one in |
6331 | # checkline_mk_shelltext(). | | 6341 | # checkline_mk_shelltext(). |
6332 | if (defined($current_fname)) { | | 6342 | if (defined($current_fname)) { |
6333 | if ($current_ftype eq "shell" || $current_ftype eq "make") { | | 6343 | if ($current_ftype eq "shell" || $current_ftype eq "make") { |
6334 | my ($mm, $rest) = match_all($text, $regex_shellword); | | 6344 | my ($mm, $rest) = match_all($text, $regex_shellword); |
6335 | | | 6345 | |
6336 | foreach my $m (@{$mm}) { | | 6346 | foreach my $m (@{$mm}) { |
6337 | my $shellword = $m->text(1); | | 6347 | my $shellword = $m->text(1); |
6338 | | | 6348 | |
6339 | if ($shellword =~ m"^#") { | | 6349 | if ($shellword =~ m"^#") { |
6340 | last; | | 6350 | last; |
6341 | } | | 6351 | } |
6342 | checkline_mk_absolute_pathname($line, $shellword); | | 6352 | checkline_mk_absolute_pathname($line, $shellword); |
6343 | } | | 6353 | } |
6344 | | | 6354 | |
6345 | } elsif ($current_ftype eq "source") { | | 6355 | } elsif ($current_ftype eq "source") { |
6346 | checkline_source_absolute_pathname($line, $text); | | 6356 | checkline_source_absolute_pathname($line, $text); |
6347 | | | 6357 | |
6348 | } elsif ($current_ftype eq "configure") { | | 6358 | } elsif ($current_ftype eq "configure") { |
6349 | if ($text =~ m": Avoid regenerating within pkgsrc$") { | | 6359 | if ($text =~ m": Avoid regenerating within pkgsrc$") { |
6350 | $line->log_error("This code must not be included in patches."); | | 6360 | $line->log_error("This code must not be included in patches."); |
6351 | $line->explain_error( | | 6361 | $line->explain_error( |
6352 | "It is generated automatically by pkgsrc after the patch phase.", | | 6362 | "It is generated automatically by pkgsrc after the patch phase.", |
6353 | "", | | 6363 | "", |
6354 | "For more details, look for \"configure-scripts-override\" in", | | 6364 | "For more details, look for \"configure-scripts-override\" in", |
6355 | "mk/configure/gnu-configure.mk."); | | 6365 | "mk/configure/gnu-configure.mk."); |
6356 | } | | 6366 | } |
6357 | | | 6367 | |
6358 | } elsif ($current_ftype eq "ignore") { | | 6368 | } elsif ($current_ftype eq "ignore") { |
6359 | # Ignore it. | | 6369 | # Ignore it. |
6360 | | | 6370 | |
6361 | } else { | | 6371 | } else { |
6362 | checkline_other_absolute_pathname($line, $text); | | 6372 | checkline_other_absolute_pathname($line, $text); |
6363 | } | | 6373 | } |
6364 | } | | 6374 | } |
6365 | }; | | 6375 | }; |
6366 | | | 6376 | |
6367 | my $check_hunk_end = sub($$$) { | | 6377 | my $check_hunk_end = sub($$$) { |
6368 | my ($deldelta, $adddelta, $newstate) = @_; | | 6378 | my ($deldelta, $adddelta, $newstate) = @_; |
6369 | | | 6379 | |
6370 | if ($deldelta > 0 && $dellines == 0) { | | 6380 | if ($deldelta > 0 && $dellines == 0) { |
6371 | $redostate = $newstate; | | 6381 | $redostate = $newstate; |
6372 | if (defined($addlines) && $addlines > 0) { | | 6382 | if (defined($addlines) && $addlines > 0) { |
6373 | $line->log_error("Expected ${addlines} more lines to be added."); | | 6383 | $line->log_error("Expected ${addlines} more lines to be added."); |
6374 | } | | 6384 | } |
6375 | } elsif ($adddelta > 0 && $addlines == 0) { | | 6385 | } elsif ($adddelta > 0 && $addlines == 0) { |
6376 | $redostate = $newstate; | | 6386 | $redostate = $newstate; |
6377 | if (defined($dellines) && $dellines > 0) { | | 6387 | if (defined($dellines) && $dellines > 0) { |
6378 | $line->log_error("Expected ${dellines} more lines to be deleted."); | | 6388 | $line->log_error("Expected ${dellines} more lines to be deleted."); |
6379 | } | | 6389 | } |
6380 | } else { | | 6390 | } else { |
6381 | if (defined($context_scanning_leading)) { | | 6391 | if (defined($context_scanning_leading)) { |
6382 | if ($deldelta != 0 && $adddelta != 0) { | | 6392 | if ($deldelta != 0 && $adddelta != 0) { |
6383 | if ($context_scanning_leading) { | | 6393 | if ($context_scanning_leading) { |
6384 | $leading_context_lines++; | | 6394 | $leading_context_lines++; |
6385 | } else { | | 6395 | } else { |
6386 | $trailing_context_lines++; | | 6396 | $trailing_context_lines++; |
6387 | } | | 6397 | } |
6388 | } else { | | 6398 | } else { |
6389 | if ($context_scanning_leading) { | | 6399 | if ($context_scanning_leading) { |
6390 | $context_scanning_leading = false; | | 6400 | $context_scanning_leading = false; |
6391 | } else { | | 6401 | } else { |
6392 | $trailing_context_lines = 0; | | 6402 | $trailing_context_lines = 0; |
6393 | } | | 6403 | } |
6394 | } | | 6404 | } |
6395 | } | | 6405 | } |
6396 | | | 6406 | |
6397 | if ($deldelta != 0) { | | 6407 | if ($deldelta != 0) { |
6398 | $dellines -= $deldelta; | | 6408 | $dellines -= $deldelta; |
6399 | } | | 6409 | } |
6400 | if ($adddelta != 0) { | | 6410 | if ($adddelta != 0) { |
6401 | $addlines -= $adddelta; | | 6411 | $addlines -= $adddelta; |
6402 | } | | 6412 | } |
6403 | if (!((defined($dellines) && $dellines > 0) || | | 6413 | if (!((defined($dellines) && $dellines > 0) || |
6404 | (defined($addlines) && $addlines > 0))) { | | 6414 | (defined($addlines) && $addlines > 0))) { |
6405 | if (defined($context_scanning_leading)) { | | 6415 | if (defined($context_scanning_leading)) { |
6406 | if ($leading_context_lines != $trailing_context_lines) { | | 6416 | if ($leading_context_lines != $trailing_context_lines) { |
6407 | $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."); | | 6417 | $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."); |
6408 | } | | 6418 | } |
6409 | } | | 6419 | } |
6410 | $nextstate = $newstate; | | 6420 | $nextstate = $newstate; |
6411 | } | | 6421 | } |
6412 | } | | 6422 | } |
6413 | }; | | 6423 | }; |
6414 | | | 6424 | |
6415 | # @param deldelta | | 6425 | # @param deldelta |
6416 | # The number of lines that are deleted from the patched file. | | 6426 | # The number of lines that are deleted from the patched file. |
6417 | # @param adddelta | | 6427 | # @param adddelta |
6418 | # The number of lines that are added to the patched file. | | 6428 | # The number of lines that are added to the patched file. |
6419 | # @param newstate | | 6429 | # @param newstate |
6420 | # The follow-up state when this line is the last line to be | | 6430 | # The follow-up state when this line is the last line to be |
6421 | # added in this hunk of the patch. | | 6431 | # added in this hunk of the patch. |
6422 | # | | 6432 | # |
6423 | my $check_hunk_line = sub($$$) { | | 6433 | my $check_hunk_line = sub($$$) { |
6424 | my ($deldelta, $adddelta, $newstate) = @_; | | 6434 | my ($deldelta, $adddelta, $newstate) = @_; |
6425 | | | 6435 | |
6426 | $check_contents->(); | | 6436 | $check_contents->(); |
6427 | $check_hunk_end->($deldelta, $adddelta, $newstate); | | 6437 | $check_hunk_end->($deldelta, $adddelta, $newstate); |
6428 | | | 6438 | |
6429 | # If -Wextra is given, the context lines are checked for | | 6439 | # If -Wextra is given, the context lines are checked for |
6430 | # absolute paths and similar things. If it is not given, | | 6440 | # absolute paths and similar things. If it is not given, |
6431 | # only those lines that really add something to the patched | | 6441 | # only those lines that really add something to the patched |
6432 | # file are checked. | | 6442 | # file are checked. |
6433 | if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) { | | 6443 | if ($adddelta != 0 && ($deldelta == 0 || $opt_warn_extra)) { |
6434 | $check_added_contents->(); | | 6444 | $check_added_contents->(); |
6435 | } | | 6445 | } |
6436 | }; | | 6446 | }; |
6437 | | | 6447 | |
6438 | my $transitions = | | 6448 | my $transitions = |
6439 | # [ from state, regex, to state, action ] | | 6449 | # [ from state, regex, to state, action ] |
6440 | [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { | | 6450 | [ [PST_START, re_patch_rcsid, PST_CENTER, sub() { |
6441 | checkline_rcsid($line, ""); | | 6451 | checkline_rcsid($line, ""); |
6442 | }], [PST_START, undef, PST_CENTER, sub() { | | 6452 | }], [PST_START, undef, PST_CENTER, sub() { |
6443 | checkline_rcsid($line, ""); | | 6453 | checkline_rcsid($line, ""); |
6444 | }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { | | 6454 | }], [PST_CENTER, re_patch_empty, PST_TEXT, sub() { |
6445 | # | | 6455 | # |
6446 | }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { | | 6456 | }], [PST_TEXT, re_patch_cfd, PST_CFA, sub() { |
6447 | if (!$seen_comment) { | | 6457 | if (!$seen_comment) { |
6448 | $line->log_error("Comment expected."); | | 6458 | $line->log_error("Comment expected."); |
6449 | $line->explain_error(@comment_explanation); | | 6459 | $line->explain_error(@comment_explanation); |
6450 | } | | 6460 | } |
6451 | $line->log_warning("Please use unified diffs (diff -u) for patches."); | | 6461 | $line->log_warning("Please use unified diffs (diff -u) for patches."); |
6452 | }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { | | 6462 | }], [PST_TEXT, re_patch_ufd, PST_UFA, sub() { |
6453 | if (!$seen_comment) { | | 6463 | if (!$seen_comment) { |
6454 | $line->log_error("Comment expected."); | | 6464 | $line->log_error("Comment expected."); |
6455 | $line->explain_error(@comment_explanation); | | 6465 | $line->explain_error(@comment_explanation); |
6456 | } | | 6466 | } |
6457 | }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { | | 6467 | }], [PST_TEXT, re_patch_text, PST_TEXT, sub() { |
6458 | $seen_comment = true; | | 6468 | $seen_comment = true; |
6459 | }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { | | 6469 | }], [PST_TEXT, re_patch_empty, PST_TEXT, sub() { |
6460 | # | | 6470 | # |
6461 | }], [PST_TEXT, undef, PST_TEXT, sub() { | | 6471 | }], [PST_TEXT, undef, PST_TEXT, sub() { |
6462 | # | | 6472 | # |
6463 | }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { | | 6473 | }], [PST_CENTER, re_patch_cfd, PST_CFA, sub() { |
6464 | if ($seen_comment) { | | 6474 | if ($seen_comment) { |
6465 | $opt_warn_space and $line->log_note("Empty line expected."); | | 6475 | $opt_warn_space and $line->log_note("Empty line expected."); |
6466 | } else { | | 6476 | } else { |
6467 | $line->log_error("Comment expected."); | | 6477 | $line->log_error("Comment expected."); |
6468 | $line->explain_error(@comment_explanation); | | 6478 | $line->explain_error(@comment_explanation); |
6469 | } | | 6479 | } |
6470 | $line->log_warning("Please use unified diffs (diff -u) for patches."); | | 6480 | $line->log_warning("Please use unified diffs (diff -u) for patches."); |
6471 | }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { | | 6481 | }], [PST_CENTER, re_patch_ufd, PST_UFA, sub() { |
6472 | if ($seen_comment) { | | 6482 | if ($seen_comment) { |
6473 | $opt_warn_space and $line->log_note("Empty line expected."); | | 6483 | $opt_warn_space and $line->log_note("Empty line expected."); |
6474 | } else { | | 6484 | } else { |
6475 | $line->log_error("Comment expected."); | | 6485 | $line->log_error("Comment expected."); |
6476 | $line->explain_error(@comment_explanation); | | 6486 | $line->explain_error(@comment_explanation); |
6477 | } | | 6487 | } |
6478 | }], [PST_CENTER, undef, PST_TEXT, sub() { | | 6488 | }], [PST_CENTER, undef, PST_TEXT, sub() { |
6479 | $opt_warn_space and $line->log_note("Empty line expected."); | | 6489 | $opt_warn_space and $line->log_note("Empty line expected."); |
6480 | }], [PST_CFA, re_patch_cfa, PST_CH, sub() { | | 6490 | }], [PST_CFA, re_patch_cfa, PST_CH, sub() { |
6481 | $current_fname = $m->text(1); | | 6491 | $current_fname = $m->text(1); |
6482 | $current_ftype = get_filetype($line, $current_fname); | | 6492 | $current_ftype = get_filetype($line, $current_fname); |
6483 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); | | 6493 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); |
6484 | $patched_files++; | | 6494 | $patched_files++; |
6485 | $hunks = 0; | | 6495 | $hunks = 0; |
6486 | }], [PST_CH, re_patch_ch, PST_CHD, sub() { | | 6496 | }], [PST_CH, re_patch_ch, PST_CHD, sub() { |
6487 | $hunks++; | | 6497 | $hunks++; |
6488 | }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { | | 6498 | }], [PST_CHD, re_patch_chd, PST_CLD0, sub() { |
6489 | $dellines = ($m->has(2)) | | 6499 | $dellines = ($m->has(2)) |
6490 | ? (1 + $m->text(2) - $m->text(1)) | | 6500 | ? (1 + $m->text(2) - $m->text(1)) |
6491 | : ($m->text(1)); | | 6501 | : ($m->text(1)); |
6492 | }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { | | 6502 | }], [PST_CLD0, re_patch_clc, PST_CLD, sub() { |
6493 | $check_hunk_line->(1, 0, PST_CLD0); | | 6503 | $check_hunk_line->(1, 0, PST_CLD0); |
6494 | }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { | | 6504 | }], [PST_CLD0, re_patch_cld, PST_CLD, sub() { |
6495 | $check_hunk_line->(1, 0, PST_CLD0); | | 6505 | $check_hunk_line->(1, 0, PST_CLD0); |
6496 | }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { | | 6506 | }], [PST_CLD0, re_patch_clm, PST_CLD, sub() { |
6497 | $check_hunk_line->(1, 0, PST_CLD0); | | 6507 | $check_hunk_line->(1, 0, PST_CLD0); |
6498 | }], [PST_CLD, re_patch_clc, PST_CLD, sub() { | | 6508 | }], [PST_CLD, re_patch_clc, PST_CLD, sub() { |
6499 | $check_hunk_line->(1, 0, PST_CLD0); | | 6509 | $check_hunk_line->(1, 0, PST_CLD0); |
6500 | }], [PST_CLD, re_patch_cld, PST_CLD, sub() { | | 6510 | }], [PST_CLD, re_patch_cld, PST_CLD, sub() { |
6501 | $check_hunk_line->(1, 0, PST_CLD0); | | 6511 | $check_hunk_line->(1, 0, PST_CLD0); |
6502 | }], [PST_CLD, re_patch_clm, PST_CLD, sub() { | | 6512 | }], [PST_CLD, re_patch_clm, PST_CLD, sub() { |
6503 | $check_hunk_line->(1, 0, PST_CLD0); | | 6513 | $check_hunk_line->(1, 0, PST_CLD0); |
6504 | }], [PST_CLD, undef, PST_CLD0, sub() { | | 6514 | }], [PST_CLD, undef, PST_CLD0, sub() { |
6505 | if ($dellines != 0) { | | 6515 | if ($dellines != 0) { |
6506 | $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); | | 6516 | $line->log_warning("Invalid number of deleted lines (${dellines} missing)."); |
6507 | } | | 6517 | } |
6508 | }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { | | 6518 | }], [PST_CLD0, re_patch_cha, PST_CLA0, sub() { |
6509 | $dellines = undef; | | 6519 | $dellines = undef; |
6510 | $addlines = ($m->has(2)) | | 6520 | $addlines = ($m->has(2)) |
6511 | ? (1 + $m->text(2) - $m->text(1)) | | 6521 | ? (1 + $m->text(2) - $m->text(1)) |
6512 | : ($m->text(1)); | | 6522 | : ($m->text(1)); |
6513 | }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { | | 6523 | }], [PST_CLA0, re_patch_clc, PST_CLA, sub() { |
6514 | $check_hunk_line->(0, 1, PST_CH); | | 6524 | $check_hunk_line->(0, 1, PST_CH); |
6515 | }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { | | 6525 | }], [PST_CLA0, re_patch_clm, PST_CLA, sub() { |
6516 | $check_hunk_line->(0, 1, PST_CH); | | 6526 | $check_hunk_line->(0, 1, PST_CH); |
6517 | }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { | | 6527 | }], [PST_CLA0, re_patch_cla, PST_CLA, sub() { |
6518 | $check_hunk_line->(0, 1, PST_CH); | | 6528 | $check_hunk_line->(0, 1, PST_CH); |
6519 | }], [PST_CLA, re_patch_clc, PST_CLA, sub() { | | 6529 | }], [PST_CLA, re_patch_clc, PST_CLA, sub() { |
6520 | $check_hunk_line->(0, 1, PST_CH); | | 6530 | $check_hunk_line->(0, 1, PST_CH); |
6521 | }], [PST_CLA, re_patch_clm, PST_CLA, sub() { | | 6531 | }], [PST_CLA, re_patch_clm, PST_CLA, sub() { |
6522 | $check_hunk_line->(0, 1, PST_CH); | | 6532 | $check_hunk_line->(0, 1, PST_CH); |
6523 | }], [PST_CLA, re_patch_cla, PST_CLA, sub() { | | 6533 | }], [PST_CLA, re_patch_cla, PST_CLA, sub() { |
6524 | $check_hunk_line->(0, 1, PST_CH); | | 6534 | $check_hunk_line->(0, 1, PST_CH); |
6525 | }], [PST_CLA, undef, PST_CLA0, sub() { | | 6535 | }], [PST_CLA, undef, PST_CLA0, sub() { |
6526 | if ($addlines != 0) { | | 6536 | if ($addlines != 0) { |
6527 | $line->log_warning("Invalid number of added lines (${addlines} missing)."); | | 6537 | $line->log_warning("Invalid number of added lines (${addlines} missing)."); |
6528 | } | | 6538 | } |
6529 | }], [PST_CLA0, undef, PST_CH, sub() { | | 6539 | }], [PST_CLA0, undef, PST_CH, sub() { |
6530 | # | | 6540 | # |
6531 | }], [PST_CH, undef, PST_TEXT, sub() { | | 6541 | }], [PST_CH, undef, PST_TEXT, sub() { |
6532 | # | | 6542 | # |
6533 | }], [PST_UFA, re_patch_ufa, PST_UH, sub() { | | 6543 | }], [PST_UFA, re_patch_ufa, PST_UH, sub() { |
6534 | $current_fname = $m->text(1); | | 6544 | $current_fname = $m->text(1); |
6535 | $current_ftype = get_filetype($line, $current_fname); | | 6545 | $current_ftype = get_filetype($line, $current_fname); |
6536 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); | | 6546 | $opt_debug_patches and $line->log_debug("fname=$current_fname ftype=$current_ftype"); |
6537 | $patched_files++; | | 6547 | $patched_files++; |
6538 | $hunks = 0; | | 6548 | $hunks = 0; |
6539 | }], [PST_UH, re_patch_uh, PST_UL, sub() { | | 6549 | }], [PST_UH, re_patch_uh, PST_UL, sub() { |
6540 | $dellines = ($m->has(1) ? $m->text(2) : 1); | | 6550 | $dellines = ($m->has(1) ? $m->text(2) : 1); |
6541 | $addlines = ($m->has(3) ? $m->text(4) : 1); | | 6551 | $addlines = ($m->has(3) ? $m->text(4) : 1); |
6542 | $check_text->($line->text); | | 6552 | $check_text->($line->text); |
6543 | if ($line->text =~ m"\r$") { | | 6553 | if ($line->text =~ m"\r$") { |
6544 | $line->log_error("The hunk header must not end with a CR character."); | | 6554 | $line->log_error("The hunk header must not end with a CR character."); |
6545 | $line->explain_error( | | 6555 | $line->explain_error( |
6546 | "The MacOS X patch utility cannot handle these."); | | 6556 | "The MacOS X patch utility cannot handle these."); |
6547 | } | | 6557 | } |
6548 | $hunks++; | | 6558 | $hunks++; |
6549 | $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); | | 6559 | $context_scanning_leading = (($m->has(1) && $m->text(1) ne "1") ? true : undef); |
6550 | $leading_context_lines = 0; | | 6560 | $leading_context_lines = 0; |
6551 | $trailing_context_lines = 0; | | 6561 | $trailing_context_lines = 0; |
6552 | }], [PST_UL, re_patch_uld, PST_UL, sub() { | | 6562 | }], [PST_UL, re_patch_uld, PST_UL, sub() { |
6553 | $check_hunk_line->(1, 0, PST_UH); | | 6563 | $check_hunk_line->(1, 0, PST_UH); |
6554 | }], [PST_UL, re_patch_ula, PST_UL, sub() { | | 6564 | }], [PST_UL, re_patch_ula, PST_UL, sub() { |
6555 | $check_hunk_line->(0, 1, PST_UH); | | 6565 | $check_hunk_line->(0, 1, PST_UH); |
6556 | }], [PST_UL, re_patch_ulc, PST_UL, sub() { | | 6566 | }], [PST_UL, re_patch_ulc, PST_UL, sub() { |
6557 | $check_hunk_line->(1, 1, PST_UH); | | 6567 | $check_hunk_line->(1, 1, PST_UH); |
6558 | }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { | | 6568 | }], [PST_UL, re_patch_ulnonl, PST_UL, sub() { |
6559 | # | | 6569 | # |
6560 | }], [PST_UL, re_patch_empty, PST_UL, sub() { | | 6570 | }], [PST_UL, re_patch_empty, PST_UL, sub() { |
6561 | $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); | | 6571 | $opt_warn_space and $line->log_note("Leading white-space missing in hunk."); |
6562 | $check_hunk_line->(1, 1, PST_UH); | | 6572 | $check_hunk_line->(1, 1, PST_UH); |
6563 | }], [PST_UL, undef, PST_UH, sub() { | | 6573 | }], [PST_UL, undef, PST_UH, sub() { |
6564 | if ($dellines != 0 || $addlines != 0) { | | 6574 | if ($dellines != 0 || $addlines != 0) { |
6565 | $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); | | 6575 | $line->log_warning("Unexpected end of hunk (-${dellines},+${addlines} expected)."); |
6566 | } | | 6576 | } |
6567 | }], [PST_UH, undef, PST_TEXT, sub() { | | 6577 | }], [PST_UH, undef, PST_TEXT, sub() { |
6568 | ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); | | 6578 | ($hunks != 0) || $line->log_warning("No hunks for file ${current_fname}."); |
6569 | }]]; | | 6579 | }]]; |
6570 | | | 6580 | |
6571 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); | | 6581 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_patch()"); |
6572 | | | 6582 | |
6573 | checkperms($fname); | | 6583 | checkperms($fname); |
6574 | if (!($lines = load_lines($fname, false))) { | | 6584 | if (!($lines = load_lines($fname, false))) { |
6575 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); | | 6585 | log_error($fname, NO_LINE_NUMBER, "Could not be read."); |
6576 | return; | | 6586 | return; |
6577 | } | | 6587 | } |
6578 | if (@{$lines} == 0) { | | 6588 | if (@{$lines} == 0) { |
6579 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); | | 6589 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); |
6580 | return; | | 6590 | return; |
6581 | } | | 6591 | } |
6582 | | | 6592 | |
6583 | $state = PST_START; | | 6593 | $state = PST_START; |
6584 | $dellines = undef; | | 6594 | $dellines = undef; |
6585 | $addlines = undef; | | 6595 | $addlines = undef; |
6586 | $patched_files = 0; | | 6596 | $patched_files = 0; |
6587 | $seen_comment = false; | | 6597 | $seen_comment = false; |
6588 | $current_fname = undef; | | 6598 | $current_fname = undef; |
6589 | $current_ftype = undef; | | 6599 | $current_ftype = undef; |
6590 | $hunks = undef; | | 6600 | $hunks = undef; |
6591 | | | 6601 | |
6592 | for (my $lineno = 0; $lineno <= $#{$lines}; ) { | | 6602 | for (my $lineno = 0; $lineno <= $#{$lines}; ) { |
6593 | $line = $lines->[$lineno]; | | 6603 | $line = $lines->[$lineno]; |
6594 | my $text = $line->text; | | 6604 | my $text = $line->text; |
6595 | | | 6605 | |
6596 | $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); | | 6606 | $opt_debug_patches and $line->log_debug("[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."] $text"); |
6597 | | | 6607 | |
6598 | my $found = false; | | 6608 | my $found = false; |
6599 | foreach my $t (@{$transitions}) { | | 6609 | foreach my $t (@{$transitions}) { |
6600 | if ($state == $t->[0]) { | | 6610 | if ($state == $t->[0]) { |
6601 | if (!defined($t->[1])) { | | 6611 | if (!defined($t->[1])) { |
6602 | $m = undef; | | 6612 | $m = undef; |
6603 | } elsif ($text =~ $t->[1]) { | | 6613 | } elsif ($text =~ $t->[1]) { |
6604 | $opt_debug_patches and $line->log_debug($t->[1]); | | 6614 | $opt_debug_patches and $line->log_debug($t->[1]); |
6605 | $m = PkgLint::SimpleMatch->new($text, \@-, \@+); | | 6615 | $m = PkgLint::SimpleMatch->new($text, \@-, \@+); |
6606 | } else { | | 6616 | } else { |
6607 | next; | | 6617 | next; |
6608 | } | | 6618 | } |
6609 | $redostate = undef; | | 6619 | $redostate = undef; |
6610 | $nextstate = $t->[2]; | | 6620 | $nextstate = $t->[2]; |
6611 | $t->[3]->(); | | 6621 | $t->[3]->(); |
6612 | if (defined($redostate)) { | | 6622 | if (defined($redostate)) { |
6613 | $state = $redostate; | | 6623 | $state = $redostate; |
6614 | } else { | | 6624 | } else { |
6615 | $state = $nextstate; | | 6625 | $state = $nextstate; |
6616 | if (defined($t->[1])) { | | 6626 | if (defined($t->[1])) { |
6617 | $lineno++; | | 6627 | $lineno++; |
6618 | } | | 6628 | } |
6619 | } | | 6629 | } |
6620 | $found = true; | | 6630 | $found = true; |
6621 | last; | | 6631 | last; |
6622 | } | | 6632 | } |
6623 | } | | 6633 | } |
6624 | | | 6634 | |
6625 | if (!$found) { | | 6635 | if (!$found) { |
6626 | $line->log_error("Parse error: state=${state}"); | | 6636 | $line->log_error("Parse error: state=${state}"); |
6627 | $state = PST_TEXT; | | 6637 | $state = PST_TEXT; |
6628 | $lineno++; | | 6638 | $lineno++; |
6629 | } | | 6639 | } |
6630 | } | | 6640 | } |
6631 | | | 6641 | |
6632 | while ($state != PST_TEXT) { | | 6642 | while ($state != PST_TEXT) { |
6633 | $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); | | 6643 | $opt_debug_patches and log_debug($fname, "EOF", "[${state} ${patched_files}/".($hunks||0)."/-".($dellines||0)."+".($addlines||0)."]"); |
6634 | | | 6644 | |
6635 | my $found = false; | | 6645 | my $found = false; |
6636 | foreach my $t (@{$transitions}) { | | 6646 | foreach my $t (@{$transitions}) { |
6637 | if ($state == $t->[0] && !defined($t->[1])) { | | 6647 | if ($state == $t->[0] && !defined($t->[1])) { |
6638 | my $newstate; | | 6648 | my $newstate; |
6639 | | | 6649 | |
6640 | $m = undef; | | 6650 | $m = undef; |
6641 | $redostate = undef; | | 6651 | $redostate = undef; |
6642 | $nextstate = $t->[2]; | | 6652 | $nextstate = $t->[2]; |
6643 | $t->[3]->(); | | 6653 | $t->[3]->(); |
6644 | $newstate = (defined($redostate)) ? $redostate : $nextstate; | | 6654 | $newstate = (defined($redostate)) ? $redostate : $nextstate; |
6645 | if ($newstate == $state) { | | 6655 | if ($newstate == $state) { |
6646 | log_fatal($fname, "EOF", "Internal error in the patch transition table."); | | 6656 | log_fatal($fname, "EOF", "Internal error in the patch transition table."); |
6647 | } | | 6657 | } |
6648 | $state = $newstate; | | 6658 | $state = $newstate; |
6649 | $found = true; | | 6659 | $found = true; |
6650 | last; | | 6660 | last; |
6651 | } | | 6661 | } |
6652 | } | | 6662 | } |
6653 | | | 6663 | |
6654 | if (!$found) { | | 6664 | if (!$found) { |
6655 | log_error($fname, "EOF", "Parse error: state=${state}"); | | 6665 | log_error($fname, "EOF", "Parse error: state=${state}"); |
6656 | $state = PST_TEXT; | | 6666 | $state = PST_TEXT; |
6657 | } | | 6667 | } |
6658 | } | | 6668 | } |
6659 | | | 6669 | |
6660 | if ($patched_files > 1) { | | 6670 | if ($patched_files > 1) { |
6661 | log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); | | 6671 | log_warning($fname, NO_LINE_NUMBER, "Contains patches for $patched_files files, should be only one."); |
6662 | | | 6672 | |
6663 | } elsif ($patched_files == 0) { | | 6673 | } elsif ($patched_files == 0) { |
6664 | log_error($fname, NO_LINE_NUMBER, "Contains no patch."); | | 6674 | log_error($fname, NO_LINE_NUMBER, "Contains no patch."); |
6665 | } | | 6675 | } |
6666 | | | 6676 | |
6667 | checklines_trailing_empty_lines($lines); | | 6677 | checklines_trailing_empty_lines($lines); |
6668 | } | | 6678 | } |
6669 | | | 6679 | |
6670 | sub checkfile_PLIST($) { | | 6680 | sub checkfile_PLIST($) { |
6671 | my ($fname) = @_; | | 6681 | my ($fname) = @_; |
6672 | my ($lines, $last_file_seen); | | 6682 | my ($lines, $last_file_seen); |
6673 | | | 6683 | |
6674 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); | | 6684 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile_PLIST()"); |
6675 | | | 6685 | |
6676 | checkperms($fname); | | 6686 | checkperms($fname); |
6677 | if (!($lines = load_file($fname))) { | | 6687 | if (!($lines = load_file($fname))) { |
6678 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 6688 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
6679 | return; | | 6689 | return; |
6680 | } | | 6690 | } |
6681 | if (@{$lines} == 0) { | | 6691 | if (@{$lines} == 0) { |
6682 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); | | 6692 | log_error($fname, NO_LINE_NUMBER, "Must not be empty."); |
6683 | return; | | 6693 | return; |
6684 | } | | 6694 | } |
6685 | checkline_rcsid($lines->[0], "\@comment "); | | 6695 | checkline_rcsid($lines->[0], "\@comment "); |
6686 | | | 6696 | |
6687 | if (@$lines == 1) { | | 6697 | if (@$lines == 1) { |
6688 | $lines->[0]->log_warning("PLIST files shouldn't be empty."); | | 6698 | $lines->[0]->log_warning("PLIST files shouldn't be empty."); |
6689 | $lines->[0]->explain_warning( | | 6699 | $lines->[0]->explain_warning( |
6690 | "One reason for empty PLISTs is that this is a newly created package", | | 6700 | "One reason for empty PLISTs is that this is a newly created package", |
6691 | "and that the author didn't run \"bmake print-PLIST\" after installing", | | 6701 | "and that the author didn't run \"bmake print-PLIST\" after installing", |
6692 | "the files.", | | 6702 | "the files.", |
6693 | "", | | 6703 | "", |
6694 | "Another reason, common for Perl packages, is that the final PLIST is", | | 6704 | "Another reason, common for Perl packages, is that the final PLIST is", |
6695 | "automatically generated. Since the source PLIST is not used at all,", | | 6705 | "automatically generated. Since the source PLIST is not used at all,", |
6696 | "you can remove it.", | | 6706 | "you can remove it.", |
6697 | "", | | 6707 | "", |
6698 | "Meta packages also don't need a PLIST file."); | | 6708 | "Meta packages also don't need a PLIST file."); |
6699 | } | | 6709 | } |
6700 | | | 6710 | |
6701 | # Get the list of all files from the PLIST. | | 6711 | # Get the list of all files from the PLIST. |
6702 | my $all_files = {}; | | 6712 | my $all_files = {}; |
6703 | my $all_dirs = {}; | | 6713 | my $all_dirs = {}; |
6704 | my $extra_lines = []; | | 6714 | my $extra_lines = []; |
6705 | if (basename($fname) eq "PLIST.common_end") { | | 6715 | if (basename($fname) eq "PLIST.common_end") { |
6706 | my $common_lines = load_file(dirname($fname) . "/PLIST.common"); | | 6716 | my $common_lines = load_file(dirname($fname) . "/PLIST.common"); |
6707 | if ($common_lines) { | | 6717 | if ($common_lines) { |
6708 | $extra_lines = $common_lines; | | 6718 | $extra_lines = $common_lines; |
6709 | } | | 6719 | } |
6710 | } | | 6720 | } |
6711 | | | 6721 | |
6712 | foreach my $line (@{$extra_lines}, @{$lines}) { | | 6722 | foreach my $line (@{$extra_lines}, @{$lines}) { |
6713 | my $text = $line->text; | | 6723 | my $text = $line->text; |
6714 | | | 6724 | |
6715 | if ($text =~ m"\$\{([\w_]+)\}(.*)") { | | 6725 | if ($text =~ m"\$\{([\w_]+)\}(.*)") { |
6716 | if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { | | 6726 | if (defined($pkgctx_plist_subst_cond) && exists($pkgctx_plist_subst_cond->{$1})) { |
6717 | $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); | | 6727 | $opt_debug_misc and $line->log_debug("Removed PLIST_SUBST conditional $1."); |
6718 | $text = $2; | | 6728 | $text = $2; |
6719 | } | | 6729 | } |
6720 | } | | 6730 | } |
6721 | | | 6731 | |
6722 | if ($text =~ m"^[\w\$]") { | | 6732 | if ($text =~ m"^[\w\$]") { |
6723 | $all_files->{$text} = $line; | | 6733 | $all_files->{$text} = $line; |
6724 | my $dir = $text; | | 6734 | my $dir = $text; |
6725 | while ($dir =~ s,/[^/]+$,,) { | | 6735 | while ($dir =~ s,/[^/]+$,,) { |
6726 | $all_dirs->{$dir} = $line; | | 6736 | $all_dirs->{$dir} = $line; |
6727 | } | | 6737 | } |
6728 | } | | 6738 | } |
6729 | if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { | | 6739 | if ($text =~ m"^\@exec \$\{MKDIR\} %D/(.*)$") { |
6730 | my $dir = $1; | | 6740 | my $dir = $1; |
6731 | do { | | 6741 | do { |
6732 | $all_dirs->{$dir} = $line; | | 6742 | $all_dirs->{$dir} = $line; |
6733 | } while ($dir =~ s,/[^/]+$,,); | | 6743 | } while ($dir =~ s,/[^/]+$,,); |
6734 | } | | 6744 | } |
6735 | } | | 6745 | } |
6736 | | | 6746 | |
6737 | foreach my $line (@{$lines}) { | | 6747 | foreach my $line (@{$lines}) { |
6738 | my $text = $line->text; | | 6748 | my $text = $line->text; |
6739 | | | 6749 | |
6740 | if ($text =~ /\s$/) { | | 6750 | if ($text =~ /\s$/) { |
6741 | $line->log_error("pkgsrc does not support filenames ending in white-space."); | | 6751 | $line->log_error("pkgsrc does not support filenames ending in white-space."); |
6742 | $line->explain_error( | | 6752 | $line->explain_error( |
6743 | "Each character in the PLIST is relevant, even trailing white-space."); | | 6753 | "Each character in the PLIST is relevant, even trailing white-space."); |
6744 | } | | 6754 | } |
6745 | | | 6755 | |
6746 | # @foo directives. | | 6756 | # @foo directives. |
6747 | if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { | | 6757 | if ($text =~ /^(?:\$\{[\w_]+\})?\@([a-z-]+)\s+(.*)/) { |
6748 | my ($cmd, $arg) = ($1, $2); | | 6758 | my ($cmd, $arg) = ($1, $2); |
6749 | | | 6759 | |
6750 | if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { | | 6760 | if ($cmd eq "unexec" && $arg =~ m"^(rmdir|\$\{RMDIR\} \%D/)(.*)") { |
6751 | my ($rmdir, $rest) = ($1, $2); | | 6761 | my ($rmdir, $rest) = ($1, $2); |
6752 | if ($rest !~ m"(?:true|\$\{TRUE\})") { | | 6762 | if ($rest !~ m"(?:true|\$\{TRUE\})") { |
6753 | $line->log_warning("Please remove this line. It is no longer necessary."); | | 6763 | $line->log_warning("Please remove this line. It is no longer necessary."); |
6754 | } | | 6764 | } |
6755 | | | 6765 | |
6756 | } elsif (($cmd eq "exec" || $cmd eq "unexec")) { | | 6766 | } elsif (($cmd eq "exec" || $cmd eq "unexec")) { |
6757 | if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { | | 6767 | if ($arg =~ /(?:install-info|\$\{INSTALL_INFO\})/) { |
6758 | $line->log_warning("\@exec/unexec install-info is deprecated."); | | 6768 | $line->log_warning("\@exec/unexec install-info is deprecated."); |
6759 | | | 6769 | |
6760 | } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { | | 6770 | } elsif ($arg =~ /ldconfig/ && $arg !~ m"/usr/bin/true") { |
6761 | $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); | | 6771 | $line->log_error("ldconfig must be used with \"||/usr/bin/true\"."); |
6762 | } | | 6772 | } |
6763 | | | 6773 | |
6764 | } elsif ($cmd eq "comment") { | | 6774 | } elsif ($cmd eq "comment") { |
6765 | # nothing to do | | 6775 | # nothing to do |
6766 | | | 6776 | |
6767 | } elsif ($cmd eq "dirrm") { | | 6777 | } elsif ($cmd eq "dirrm") { |
6768 | $line->log_warning("\@dirrm is obsolete. Please remove this line."); | | 6778 | $line->log_warning("\@dirrm is obsolete. Please remove this line."); |
6769 | $line->explain_warning( | | 6779 | $line->explain_warning( |
6770 | "Directories are removed automatically when they are empty.", | | 6780 | "Directories are removed automatically when they are empty.", |
6771 | "When a package needs an empty directory, it can use the \@pkgdir", | | 6781 | "When a package needs an empty directory, it can use the \@pkgdir", |
6772 | "command in the PLIST"); | | 6782 | "command in the PLIST"); |
6773 | } elsif ($cmd eq "imake-man") { | | 6783 | } elsif ($cmd eq "imake-man") { |
6774 | my (@args) = split(/\s+/, $arg); | | 6784 | my (@args) = split(/\s+/, $arg); |
6775 | if (@args != 3) { | | 6785 | if (@args != 3) { |
6776 | $line->log_warning("Invalid number of arguments for imake-man."); | | 6786 | $line->log_warning("Invalid number of arguments for imake-man."); |
6777 | } else { | | 6787 | } else { |
6778 | if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { | | 6788 | if ($args[2] eq "\${IMAKE_MANNEWSUFFIX}") { |
6779 | warn_about_PLIST_imake_mannewsuffix($line); | | 6789 | warn_about_PLIST_imake_mannewsuffix($line); |
6780 | } | | 6790 | } |
6781 | } | | 6791 | } |
6782 | | | 6792 | |
6783 | } elsif ($cmd eq "pkgdir") { | | 6793 | } elsif ($cmd eq "pkgdir") { |
6784 | # TODO: What can we check here? | | 6794 | # TODO: What can we check here? |
6785 | | | 6795 | |
6786 | } else { | | 6796 | } else { |
6787 | $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); | | 6797 | $line->log_warning("Unknown PLIST directive \"\@$cmd\"."); |
6788 | } | | 6798 | } |
6789 | | | 6799 | |
6790 | # Pathnames. | | 6800 | # Pathnames. |
6791 | } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { | | 6801 | } elsif ($text =~ m"^([A-Za-z0-9\$].*)/([^/]+)$") { |
6792 | my ($dirname, $basename) = ($1, $2); | | 6802 | my ($dirname, $basename) = ($1, $2); |
6793 | | | 6803 | |
6794 | if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { | | 6804 | if ($opt_warn_plist_sort && $text =~ m"^\w" && $text !~ regex_unresolved) { |
6795 | if (defined($last_file_seen)) { | | 6805 | if (defined($last_file_seen)) { |
6796 | if ($last_file_seen gt $text) { | | 6806 | if ($last_file_seen gt $text) { |
6797 | $line->log_warning("${text} should be sorted before ${last_file_seen}."); | | 6807 | $line->log_warning("${text} should be sorted before ${last_file_seen}."); |
6798 | $line->explain_warning( | | 6808 | $line->explain_warning( |
6799 | "For aesthetic reasons, the files in the PLIST should be sorted", | | 6809 | "For aesthetic reasons, the files in the PLIST should be sorted", |
6800 | "alphabetically."); | | 6810 | "alphabetically."); |
6801 | } elsif ($last_file_seen eq $text) { | | 6811 | } elsif ($last_file_seen eq $text) { |
6802 | $line->log_warning("Duplicate filename."); | | 6812 | $line->log_warning("Duplicate filename."); |
6803 | } | | 6813 | } |
6804 | } | | 6814 | } |
6805 | $last_file_seen = $text; | | 6815 | $last_file_seen = $text; |
6806 | } | | 6816 | } |
6807 | | | 6817 | |
6808 | if ($basename =~ m"\$\{IMAKE_MANNEWSUFFIX\}") { | | 6818 | if ($basename =~ m"\$\{IMAKE_MANNEWSUFFIX\}") { |
6809 | warn_about_PLIST_imake_mannewsuffix($line); | | 6819 | warn_about_PLIST_imake_mannewsuffix($line); |
6810 | } | | 6820 | } |
6811 | | | 6821 | |
6812 | if ($dirname =~ m"^bin/") { | | 6822 | if ($dirname =~ m"^bin/") { |
6813 | $line->log_warning("The bin/ directory should not have subdirectories."); | | 6823 | $line->log_warning("The bin/ directory should not have subdirectories."); |
6814 | | | 6824 | |
6815 | } elsif ($dirname eq "bin") { | | 6825 | } elsif ($dirname eq "bin") { |
6816 | | | 6826 | |
6817 | if (exists($all_files->{"man/man1/${basename}.1"})) { | | 6827 | if (exists($all_files->{"man/man1/${basename}.1"})) { |
6818 | # Fine. | | 6828 | # Fine. |
6819 | } elsif (exists($all_files->{"man/man6/${basename}.6"})) { | | 6829 | } elsif (exists($all_files->{"man/man6/${basename}.6"})) { |
6820 | # Fine. | | 6830 | # Fine. |
6821 | } elsif (exists($all_files->{"\${IMAKE_MAN_DIR}/${basename}.\${IMAKE_MANNEWSUFFIX}"})) { | | 6831 | } elsif (exists($all_files->{"\${IMAKE_MAN_DIR}/${basename}.\${IMAKE_MANNEWSUFFIX}"})) { |
6822 | # Fine. | | 6832 | # Fine. |
6823 | } else { | | 6833 | } else { |
6824 | $opt_warn_extra and $line->log_warning("Manual page missing for bin/${basename}."); | | 6834 | $opt_warn_extra and $line->log_warning("Manual page missing for bin/${basename}."); |
6825 | $opt_warn_extra and $line->explain_warning( | | 6835 | $opt_warn_extra and $line->explain_warning( |
6826 | "All programs that can be run directly by the user should have a manual", | | 6836 | "All programs that can be run directly by the user should have a manual", |
6827 | "page for quick reference. The programs in the bin/ directory should have", | | 6837 | "page for quick reference. The programs in the bin/ directory should have", |
6828 | "corresponding manual pages in section 1 (filename program.1), not in", | | 6838 | "corresponding manual pages in section 1 (filename program.1), not in", |
6829 | "section 8."); | | 6839 | "section 8."); |
6830 | } | | 6840 | } |
6831 | | | 6841 | |
6832 | } elsif ($text =~ m"^doc/") { | | 6842 | } elsif ($text =~ m"^doc/") { |
6833 | $line->log_error("Documentation must be installed under share/doc, not doc."); | | 6843 | $line->log_error("Documentation must be installed under share/doc, not doc."); |
6834 | | | 6844 | |
6835 | } elsif ($text =~ m"^etc/rc\.d/") { | | 6845 | } elsif ($text =~ m"^etc/rc\.d/") { |
6836 | $line->log_error("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework."); | | 6846 | $line->log_error("RCD_SCRIPTS must not be registered in the PLIST. Please use the RCD_SCRIPTS framework."); |
6837 | | | 6847 | |
6838 | } elsif ($text =~ m"^etc/") { | | 6848 | } elsif ($text =~ m"^etc/") { |
6839 | my $f = "mk/pkginstall/bsd.pkginstall.mk"; | | 6849 | my $f = "mk/pkginstall/bsd.pkginstall.mk"; |
6840 | | | 6850 | |
6841 | assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file."); | | 6851 | assert(-f "${cwd_pkgsrcdir}/${f}", "${cwd_pkgsrcdir}/${f} is not a regular file."); |
6842 | $line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}."); | | 6852 | $line->log_error("Configuration files must not be registered in the PLIST. Please use the CONF_FILES framework, which is described in ${f}."); |
6843 | | | 6853 | |
6844 | } elsif ($text =~ m"^include/.*\.(?:h|hpp)$") { | | 6854 | } elsif ($text =~ m"^include/.*\.(?:h|hpp)$") { |
6845 | # Fine. | | 6855 | # Fine. |
6846 | | | 6856 | |
6847 | } elsif ($text eq "info/dir") { | | 6857 | } elsif ($text eq "info/dir") { |
6848 | $line->log_error("\"info/dir\" must not be listed. Use install-info to add/remove an entry."); | | 6858 | $line->log_error("\"info/dir\" must not be listed. Use install-info to add/remove an entry."); |
6849 | | | 6859 | |
6850 | } elsif ($text =~ m"^info/.+$") { | | 6860 | } elsif ($text =~ m"^info/.+$") { |
6851 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"INFO_FILES"})) { | | 6861 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"INFO_FILES"})) { |
6852 | $line->log_warning("Packages that install info files should set INFO_FILES."); | | 6862 | $line->log_warning("Packages that install info files should set INFO_FILES."); |
6853 | } | | 6863 | } |
6854 | | | 6864 | |
6855 | } elsif (defined($effective_pkgbase) && $text =~ m"^lib/\Q${effective_pkgbase}\E/") { | | 6865 | } elsif (defined($effective_pkgbase) && $text =~ m"^lib/\Q${effective_pkgbase}\E/") { |
6856 | # Fine. | | 6866 | # Fine. |
6857 | | | 6867 | |
6858 | } elsif ($text =~ m"^lib/locale/") { | | 6868 | } elsif ($text =~ m"^lib/locale/") { |
6859 | $line->log_error("\"lib/locale\" must not be listed. Use \${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead."); | | 6869 | $line->log_error("\"lib/locale\" must not be listed. Use \${PKGLOCALEDIR}/locale and set USE_PKGLOCALEDIR instead."); |
6860 | | | 6870 | |
6861 | } elsif ($text =~ m"^(lib/(?:.*/)*)([^/]+)\.(so|a|la)$") { | | 6871 | } elsif ($text =~ m"^(lib/(?:.*/)*)([^/]+)\.(so|a|la)$") { |
6862 | my ($dir, $lib, $ext) = ($1, $2, $3); | | 6872 | my ($dir, $lib, $ext) = ($1, $2, $3); |
6863 | | | 6873 | |
6864 | if ($dir eq "lib/" && $lib !~ m"^lib") { | | 6874 | if ($dir eq "lib/" && $lib !~ m"^lib") { |
6865 | $opt_warn_extra and $line->log_warning("Library filename does not start with \"lib\"."); | | 6875 | $opt_warn_extra and $line->log_warning("Library filename does not start with \"lib\"."); |
6866 | } | | 6876 | } |
6867 | if ($ext eq "la") { | | 6877 | if ($ext eq "la") { |
6868 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_LIBTOOL"})) { | | 6878 | if (defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_LIBTOOL"})) { |
6869 | $line->log_warning("Packages that install libtool libraries should define USE_LIBTOOL."); | | 6879 | $line->log_warning("Packages that install libtool libraries should define USE_LIBTOOL."); |
6870 | } | | 6880 | } |
6871 | } | | 6881 | } |
6872 | | | 6882 | |
6873 | } elsif ($text =~ m"^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$") { | | 6883 | } elsif ($text =~ m"^man/(cat|man)(\w+)/(.*?)\.(\w+)(\.gz)?$") { |
6874 | my ($cat_or_man, $section, $manpage, $ext, $gz) = ($1, $2, $3, $4, $5); | | 6884 | my ($cat_or_man, $section, $manpage, $ext, $gz) = ($1, $2, $3, $4, $5); |
6875 | | | 6885 | |
6876 | if ($section !~ m"^[\dln]$") { | | 6886 | if ($section !~ m"^[\dln]$") { |
6877 | $line->log_warning("Unknown section \"${section}\" for manual page."); | | 6887 | $line->log_warning("Unknown section \"${section}\" for manual page."); |
6878 | } | | 6888 | } |
6879 | | | 6889 | |
6880 | if ($cat_or_man eq "cat" && !exists($all_files->{"man/man${section}/${manpage}.${section}"})) { | | 6890 | if ($cat_or_man eq "cat" && !exists($all_files->{"man/man${section}/${manpage}.${section}"})) { |
6881 | $line->log_warning("Preformatted manual page without unformatted one."); | | 6891 | $line->log_warning("Preformatted manual page without unformatted one."); |
6882 | } | | 6892 | } |
6883 | | | 6893 | |
6884 | if ($cat_or_man eq "cat") { | | 6894 | if ($cat_or_man eq "cat") { |
6885 | if ($ext ne "0") { | | 6895 | if ($ext ne "0") { |
6886 | $line->log_warning("Preformatted manual pages should end in \".0\"."); | | 6896 | $line->log_warning("Preformatted manual pages should end in \".0\"."); |
6887 | } | | 6897 | } |
6888 | } else { | | 6898 | } else { |
6889 | if ($section ne $ext) { | | 6899 | if ($section ne $ext) { |
6890 | $line->log_warning("Mismatch between the section (${section}) and extension (${ext}) of the manual page."); | | 6900 | $line->log_warning("Mismatch between the section (${section}) and extension (${ext}) of the manual page."); |
6891 | } | | 6901 | } |
6892 | } | | 6902 | } |
6893 | | | 6903 | |
6894 | if (defined($gz)) { | | 6904 | if (defined($gz)) { |
6895 | $line->log_note("The .gz extension is unnecessary for manual pages."); | | 6905 | $line->log_note("The .gz extension is unnecessary for manual pages."); |
6896 | $line->explain_note( | | 6906 | $line->explain_note( |
6897 | "Whether the manual pages are installed in compressed form or not is", | | 6907 | "Whether the manual pages are installed in compressed form or not is", |
6898 | "configured by the pkgsrc user. Compression and decompression takes place", | | 6908 | "configured by the pkgsrc user. Compression and decompression takes place", |
6899 | "automatically, no matter if the .gz extension is mentioned in the PLIST", | | 6909 | "automatically, no matter if the .gz extension is mentioned in the PLIST", |
6900 | "or not."); | | 6910 | "or not."); |
6901 | } | | 6911 | } |
6902 | | | 6912 | |
6903 | } elsif ($text =~ m"^man/cat") { | | 6913 | } elsif ($text =~ m"^man/cat") { |
6904 | $line->log_warning("Invalid filename \"${text}\" for preformatted manual page."); | | 6914 | $line->log_warning("Invalid filename \"${text}\" for preformatted manual page."); |
6905 | | | 6915 | |
6906 | } elsif ($text =~ m"^man/man") { | | 6916 | } elsif ($text =~ m"^man/man") { |
6907 | $line->log_warning("Invalid filename \"${text}\" for unformatted manual page."); | | 6917 | $line->log_warning("Invalid filename \"${text}\" for unformatted manual page."); |
6908 | | | 6918 | |
6909 | } elsif ($text =~ m"^sbin/(.*)") { | | 6919 | } elsif ($text =~ m"^sbin/(.*)") { |
6910 | my ($binname) = ($1); | | 6920 | my ($binname) = ($1); |
6911 | | | 6921 | |
6912 | if (!exists($all_files->{"man/man8/${binname}.8"})) { | | 6922 | if (!exists($all_files->{"man/man8/${binname}.8"})) { |
6913 | $opt_warn_extra and $line->log_warning("Manual page missing for sbin/${binname}."); | | 6923 | $opt_warn_extra and $line->log_warning("Manual page missing for sbin/${binname}."); |
6914 | $opt_warn_extra and $line->explain_warning( | | 6924 | $opt_warn_extra and $line->explain_warning( |
6915 | "All programs that can be run directly by the user should have a manual", | | 6925 | "All programs that can be run directly by the user should have a manual", |
6916 | "page for quick reference. The programs in the sbin/ directory should have", | | 6926 | "page for quick reference. The programs in the sbin/ directory should have", |
6917 | "corresponding manual pages in section 8 (filename program.8), not in", | | 6927 | "corresponding manual pages in section 8 (filename program.8), not in", |
6918 | "section 1."); | | 6928 | "section 1."); |
6919 | } | | 6929 | } |
6920 | | | 6930 | |
6921 | } elsif ($text =~ m"^share/applications/.*\.desktop$") { | | 6931 | } elsif ($text =~ m"^share/applications/.*\.desktop$") { |
6922 | my $f = "../../sysutils/desktop-file-utils/desktopdb.mk"; | | 6932 | my $f = "../../sysutils/desktop-file-utils/desktopdb.mk"; |
6923 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { | | 6933 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { |
6924 | $line->log_warning("Packages that install a .desktop entry may .include \"$f\"."); | | 6934 | $line->log_warning("Packages that install a .desktop entry may .include \"$f\"."); |
6925 | $line->explain_warning( | | 6935 | $line->explain_warning( |
6926 | "If *.desktop files contain MimeType keys, global MIME Type registory DB", | | 6936 | "If *.desktop files contain MimeType keys, global MIME Type registory DB", |
6927 | "must be updated by desktop-file-utils.", | | 6937 | "must be updated by desktop-file-utils.", |
6928 | "Otherwise, this warning is harmless."); | | 6938 | "Otherwise, this warning is harmless."); |
6929 | } | | 6939 | } |
6930 | | | 6940 | |
6931 | } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor(?:$|/)") { | | 6941 | } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor(?:$|/)") { |
6932 | my $f = "../../graphics/hicolor-icon-theme/buildlink3.mk"; | | 6942 | my $f = "../../graphics/hicolor-icon-theme/buildlink3.mk"; |
6933 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { | | 6943 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { |
6934 | $line->log_error("Please .include \"$f\""); | | 6944 | $line->log_error("Please .include \"$f\" in the Makefile"); |
6935 | $line->explain_error( | | 6945 | $line->explain_error( |
6936 | "If hicolor icon themes are installed, icon theme cache must be maintained."); | | 6946 | "If hicolor icon themes are installed, icon theme cache must be", |
| | | 6947 | "maintained. The hicolor-icon-theme package takes care of that."); |
6937 | } | | 6948 | } |
6938 | | | 6949 | |
6939 | } elsif ($pkgpath ne "graphics/gnome-icon-theme" && $text =~ m"^share/icons/gnome(?:$|/)") { | | 6950 | } elsif ($pkgpath ne "graphics/gnome-icon-theme" && $text =~ m"^share/icons/gnome(?:$|/)") { |
6940 | my $f = "../../graphics/gnome-icon-theme/buildlink3.mk"; | | 6951 | my $f = "../../graphics/gnome-icon-theme/buildlink3.mk"; |
6941 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { | | 6952 | if (defined($pkgctx_included) && !exists($pkgctx_included->{$f})) { |
6942 | $line->log_error("Please .include \"$f\""); | | 6953 | $line->log_error("Please .include \"$f\""); |
6943 | $line->explain_error( | | 6954 | $line->explain_error( |
6944 | "If Gnome icon themes are installed, icon theme cache must be maintained."); | | 6955 | "If Gnome icon themes are installed, icon theme cache must be maintained."); |
6945 | } | | 6956 | } |
6946 | } elsif ($dirname eq "share/aclocal" && $basename =~ m"\.m4$") { | | 6957 | } elsif ($dirname eq "share/aclocal" && $basename =~ m"\.m4$") { |
6947 | # Fine. | | 6958 | # Fine. |
6948 | | | 6959 | |
6949 | } elsif ($text =~ m"^share/doc/html/") { | | 6960 | } elsif ($text =~ m"^share/doc/html/") { |
6950 | $opt_warn_plist_depr and $line->log_warning("Use of \"share/doc/html\" is deprecated. Use \"share/doc/\${PKGBASE}\" instead."); | | 6961 | $opt_warn_plist_depr and $line->log_warning("Use of \"share/doc/html\" is deprecated. Use \"share/doc/\${PKGBASE}\" instead."); |
6951 | | | 6962 | |
6952 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/doc/\Q${effective_pkgbase}\E/") { | | 6963 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/doc/\Q${effective_pkgbase}\E/") { |
6953 | # Fine. | | 6964 | # Fine. |
6954 | | | 6965 | |
6955 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/examples/\Q${effective_pkgbase}\E/") { | | 6966 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/examples/\Q${effective_pkgbase}\E/") { |
6956 | # Fine. | | 6967 | # Fine. |
6957 | | | 6968 | |
6958 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/\Q${effective_pkgbase}\E/") { | | 6969 | } elsif (defined($effective_pkgbase) && $text =~ m"^share/\Q${effective_pkgbase}\E/") { |
6959 | # Fine. | | 6970 | # Fine. |
6960 | | | 6971 | |
6961 | } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor/icon-theme\.cache") { | | 6972 | } elsif ($pkgpath ne "graphics/hicolor-icon-theme" && $text =~ m"^share/icons/hicolor/icon-theme\.cache") { |
6962 | $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line."); | | 6973 | $line->log_error("Please .include \"../../graphics/hicolor-icon-theme/buildlink3.mk\" and remove this line."); |
6963 | | | 6974 | |
6964 | } elsif ($text =~ m"^share/info/") { | | 6975 | } elsif ($text =~ m"^share/info/") { |
6965 | $line->log_warning("Info pages should be installed into info/, not share/info/."); | | 6976 | $line->log_warning("Info pages should be installed into info/, not share/info/."); |
6966 | $line->explain_warning( | | 6977 | $line->explain_warning( |
6967 | "To fix this, you should add INFO_FILES=yes to the package Makefile."); | | 6978 | "To fix this, you should add INFO_FILES=yes to the package Makefile."); |
6968 | | | 6979 | |
6969 | } elsif ($text =~ m"^share/locale/[\w\@_]+/LC_MESSAGES/[^/]+\.mo$") { | | 6980 | } elsif ($text =~ m"^share/locale/[\w\@_]+/LC_MESSAGES/[^/]+\.mo$") { |
6970 | # Fine. | | 6981 | # Fine. |
6971 | | | 6982 | |
6972 | } elsif ($text =~ m"^share/man/") { | | 6983 | } elsif ($text =~ m"^share/man/") { |
6973 | $line->log_warning("Man pages should be installed into man/, not share/man/."); | | 6984 | $line->log_warning("Man pages should be installed into man/, not share/man/."); |
6974 | | | 6985 | |
6975 | } else { | | 6986 | } else { |
6976 | $opt_debug_unchecked and $line->log_debug("Unchecked pathname \"${text}\"."); | | 6987 | $opt_debug_unchecked and $line->log_debug("Unchecked pathname \"${text}\"."); |
6977 | } | | 6988 | } |
6978 | | | 6989 | |
6979 | if ($text =~ /\${PKGLOCALEDIR}/ && defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_PKGLOCALEDIR"})) { | | 6990 | if ($text =~ /\${PKGLOCALEDIR}/ && defined($pkgctx_vardef) && !exists($pkgctx_vardef->{"USE_PKGLOCALEDIR"})) { |
6980 | $line->log_warning("PLIST contains \${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found."); | | 6991 | $line->log_warning("PLIST contains \${PKGLOCALEDIR}, but USE_PKGLOCALEDIR was not found."); |
6981 | } | | 6992 | } |
6982 | | | 6993 | |
6983 | if ($text =~ m"/CVS/") { | | 6994 | if ($text =~ m"/CVS/") { |
6984 | $line->log_warning("CVS files should not be in the PLIST."); | | 6995 | $line->log_warning("CVS files should not be in the PLIST."); |
6985 | } | | 6996 | } |
6986 | if ($text =~ m"\.orig$") { | | 6997 | if ($text =~ m"\.orig$") { |
6987 | $line->log_warning(".orig files should not be in the PLIST."); | | 6998 | $line->log_warning(".orig files should not be in the PLIST."); |
6988 | } | | 6999 | } |
6989 | if ($text =~ m"/perllocal\.pod$") { | | 7000 | if ($text =~ m"/perllocal\.pod$") { |
6990 | $line->log_warning("perllocal.pod files should not be in the PLIST."); | | 7001 | $line->log_warning("perllocal.pod files should not be in the PLIST."); |
6991 | $line->explain_warning( | | 7002 | $line->explain_warning( |
6992 | "This file is handled automatically by the INSTALL/DEINSTALL scripts,", | | 7003 | "This file is handled automatically by the INSTALL/DEINSTALL scripts,", |
6993 | "since its contents changes frequently."); | | 7004 | "since its contents changes frequently."); |
6994 | } | | 7005 | } |
6995 | | | 7006 | |
6996 | if ($text =~ m"^(.*)(\.a|\.so[0-9.]*)$") { | | 7007 | if ($text =~ m"^(.*)(\.a|\.so[0-9.]*)$") { |
6997 | my ($basename, $ext) = ($1, $2); | | 7008 | my ($basename, $ext) = ($1, $2); |
6998 | | | 7009 | |
6999 | if (exists($all_files->{"${basename}.la"})) { | | 7010 | if (exists($all_files->{"${basename}.la"})) { |
7000 | $line->log_warning("Redundant library found. The libtool library is in line " . $all_files->{"${basename}.la"}->lines . "."); | | 7011 | $line->log_warning("Redundant library found. The libtool library is in line " . $all_files->{"${basename}.la"}->lines . "."); |
7001 | } | | 7012 | } |
7002 | } | | 7013 | } |
7003 | | | 7014 | |
7004 | } elsif ($text =~ m"^\$\{[\w_]+\}$") { | | 7015 | } elsif ($text =~ m"^\$\{[\w_]+\}$") { |
7005 | # A variable on its own line. | | 7016 | # A variable on its own line. |
7006 | | | 7017 | |
7007 | } else { | | 7018 | } else { |
7008 | $line->log_error("Unknown line type."); | | 7019 | $line->log_error("Unknown line type."); |
7009 | } | | 7020 | } |
7010 | } | | 7021 | } |
7011 | checklines_trailing_empty_lines($lines); | | 7022 | checklines_trailing_empty_lines($lines); |
7012 | autofix($lines); | | 7023 | autofix($lines); |
7013 | } | | 7024 | } |
7014 | | | 7025 | |
7015 | sub checkfile($) { | | 7026 | sub checkfile($) { |
7016 | my ($fname) = @_; | | 7027 | my ($fname) = @_; |
7017 | my ($st, $basename); | | 7028 | my ($st, $basename); |
7018 | | | 7029 | |
7019 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile()"); | | 7030 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkfile()"); |
7020 | | | 7031 | |
7021 | $basename = basename($fname); | | 7032 | $basename = basename($fname); |
7022 | if ($basename =~ m"^(?:work.*|.*~|.*\.orig|.*\.rej)$") { | | 7033 | if ($basename =~ m"^(?:work.*|.*~|.*\.orig|.*\.rej)$") { |
7023 | if ($opt_import) { | | 7034 | if ($opt_import) { |
7024 | log_error($fname, NO_LINE_NUMBER, "Must be cleaned up before committing the package."); | | 7035 | log_error($fname, NO_LINE_NUMBER, "Must be cleaned up before committing the package."); |
7025 | } | | 7036 | } |
7026 | return; | | 7037 | return; |
7027 | } | | 7038 | } |
7028 | | | 7039 | |
7029 | if (!($st = lstat($fname))) { | | 7040 | if (!($st = lstat($fname))) { |
7030 | log_error($fname, NO_LINE_NUMBER, "$!"); | | 7041 | log_error($fname, NO_LINE_NUMBER, "$!"); |
7031 | return; | | 7042 | return; |
7032 | } | | 7043 | } |
7033 | if (S_ISDIR($st->mode)) { | | 7044 | if (S_ISDIR($st->mode)) { |
7034 | if ($basename eq "files" || $basename eq "patches" || $basename eq "CVS") { | | 7045 | if ($basename eq "files" || $basename eq "patches" || $basename eq "CVS") { |
7035 | # Ok | | 7046 | # Ok |
7036 | | | 7047 | |
7037 | } elsif (!is_emptydir($fname)) { | | 7048 | } elsif (!is_emptydir($fname)) { |
7038 | log_warning($fname, NO_LINE_NUMBER, "Unknown directory name."); | | 7049 | log_warning($fname, NO_LINE_NUMBER, "Unknown directory name."); |
7039 | } | | 7050 | } |
7040 | | | 7051 | |
7041 | } elsif (S_ISLNK($st->mode)) { | | 7052 | } elsif (S_ISLNK($st->mode)) { |
7042 | if ($basename !~ m"^work") { | | 7053 | if ($basename !~ m"^work") { |
7043 | log_warning($fname, NO_LINE_NUMBER, "Unknown symlink name."); | | 7054 | log_warning($fname, NO_LINE_NUMBER, "Unknown symlink name."); |
7044 | } | | 7055 | } |
7045 | | | 7056 | |
7046 | } elsif (!S_ISREG($st->mode)) { | | 7057 | } elsif (!S_ISREG($st->mode)) { |
7047 | log_error($fname, NO_LINE_NUMBER, "Only files and directories are allowed in pkgsrc."); | | 7058 | log_error($fname, NO_LINE_NUMBER, "Only files and directories are allowed in pkgsrc."); |
7048 | | | 7059 | |
7049 | } elsif ($basename eq "ALTERNATIVES") { | | 7060 | } elsif ($basename eq "ALTERNATIVES") { |
7050 | $opt_check_ALTERNATIVES and checkfile_ALTERNATIVES($fname); | | 7061 | $opt_check_ALTERNATIVES and checkfile_ALTERNATIVES($fname); |
7051 | | | 7062 | |
7052 | } elsif ($basename eq "buildlink3.mk") { | | 7063 | } elsif ($basename eq "buildlink3.mk") { |
7053 | $opt_check_bl3 and checkfile_buildlink3_mk($fname); | | 7064 | $opt_check_bl3 and checkfile_buildlink3_mk($fname); |
7054 | | | 7065 | |
7055 | } elsif ($basename =~ m"^DESCR") { | | 7066 | } elsif ($basename =~ m"^DESCR") { |
7056 | $opt_check_DESCR and checkfile_DESCR($fname); | | 7067 | $opt_check_DESCR and checkfile_DESCR($fname); |
7057 | | | 7068 | |
7058 | } elsif ($basename =~ m"^distinfo") { | | 7069 | } elsif ($basename =~ m"^distinfo") { |
7059 | $opt_check_distinfo and checkfile_distinfo($fname); | | 7070 | $opt_check_distinfo and checkfile_distinfo($fname); |
7060 | | | 7071 | |
7061 | } elsif ($basename eq "DEINSTALL" || $basename eq "INSTALL") { | | 7072 | } elsif ($basename eq "DEINSTALL" || $basename eq "INSTALL") { |
7062 | $opt_check_INSTALL and checkfile_INSTALL($fname); | | 7073 | $opt_check_INSTALL and checkfile_INSTALL($fname); |
7063 | | | 7074 | |
7064 | } elsif ($basename =~ m"^MESSAGE") { | | 7075 | } elsif ($basename =~ m"^MESSAGE") { |
7065 | $opt_check_MESSAGE and checkfile_MESSAGE($fname); | | 7076 | $opt_check_MESSAGE and checkfile_MESSAGE($fname); |
7066 | | | 7077 | |
7067 | } elsif ($basename =~ m"^patch-[-A-Za-z0-9_\.~]*$") { | | 7078 | } elsif ($basename =~ m"^patch-[-A-Za-z0-9_\.~]*$") { |
7068 | $opt_check_patches and checkfile_patch($fname); | | 7079 | $opt_check_patches and checkfile_patch($fname); |
7069 | | | 7080 | |
7070 | } elsif ($fname =~ m"(?:^|/)patches/manual-[^/]*$") { | | 7081 | } elsif ($fname =~ m"(?:^|/)patches/manual-[^/]*$") { |
7071 | $opt_debug_unchecked and log_debug($fname, NO_LINE_NUMBER, "Unchecked file \"${fname}\"."); | | 7082 | $opt_debug_unchecked and log_debug($fname, NO_LINE_NUMBER, "Unchecked file \"${fname}\"."); |
7072 | | | 7083 | |
7073 | } elsif ($fname =~ m"(?:^|/)patches/[^/]*$") { | | 7084 | } elsif ($fname =~ m"(?:^|/)patches/[^/]*$") { |
7074 | log_warning($fname, NO_LINE_NUMBER, "Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only."); | | 7085 | log_warning($fname, NO_LINE_NUMBER, "Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only."); |
7075 | | | 7086 | |
7076 | } elsif ($basename =~ m"^(?:.*\.mk|Makefile.*)$" and not $fname =~ m,files/, and not $fname =~ m,patches/,) { | | 7087 | } elsif ($basename =~ m"^(?:.*\.mk|Makefile.*)$" and not $fname =~ m,files/, and not $fname =~ m,patches/,) { |
7077 | $opt_check_mk and checkfile_mk($fname); | | 7088 | $opt_check_mk and checkfile_mk($fname); |
7078 | | | 7089 | |
7079 | } elsif ($basename =~ m"^PLIST") { | | 7090 | } elsif ($basename =~ m"^PLIST") { |
7080 | $opt_check_PLIST and checkfile_PLIST($fname); | | 7091 | $opt_check_PLIST and checkfile_PLIST($fname); |
7081 | | | 7092 | |
7082 | } elsif ($basename eq "TODO" || $basename eq "README") { | | 7093 | } elsif ($basename eq "TODO" || $basename eq "README") { |
7083 | # Ok | | 7094 | # Ok |
7084 | | | 7095 | |
7085 | } elsif ($basename =~ m"^CHANGES-.*") { | | 7096 | } elsif ($basename =~ m"^CHANGES-.*") { |
7086 | load_doc_CHANGES($fname); | | 7097 | load_doc_CHANGES($fname); |
7087 | | | 7098 | |
7088 | } elsif (!-T $fname) { | | 7099 | } elsif (!-T $fname) { |
7089 | log_warning($fname, NO_LINE_NUMBER, "Unexpectedly found a binary file."); | | 7100 | log_warning($fname, NO_LINE_NUMBER, "Unexpectedly found a binary file."); |
7090 | | | 7101 | |
7091 | } else { | | 7102 | } else { |
7092 | log_warning($fname, NO_LINE_NUMBER, "Unexpected file found."); | | 7103 | log_warning($fname, NO_LINE_NUMBER, "Unexpected file found."); |
7093 | $opt_check_extra and checkfile_extra($fname); | | 7104 | $opt_check_extra and checkfile_extra($fname); |
7094 | } | | 7105 | } |
7095 | } | | 7106 | } |
7096 | | | 7107 | |
7097 | sub my_split($$) { | | 7108 | sub my_split($$) { |
7098 | my ($delimiter, $s) = @_; | | 7109 | my ($delimiter, $s) = @_; |
7099 | my ($pos, $next, @result); | | 7110 | my ($pos, $next, @result); |
7100 | | | 7111 | |
7101 | $pos = 0; | | 7112 | $pos = 0; |
7102 | for ($pos = 0; $pos != -1; $pos = $next) { | | 7113 | for ($pos = 0; $pos != -1; $pos = $next) { |
7103 | $next = index($s, $delimiter, $pos); | | 7114 | $next = index($s, $delimiter, $pos); |
7104 | push @result, (($next == -1) ? substr($s, $pos) : substr($s, $pos, $next - $pos)); | | 7115 | push @result, (($next == -1) ? substr($s, $pos) : substr($s, $pos, $next - $pos)); |
7105 | if ($next != -1) { | | 7116 | if ($next != -1) { |
7106 | $next += length($delimiter); | | 7117 | $next += length($delimiter); |
7107 | } | | 7118 | } |
7108 | } | | 7119 | } |
7109 | return @result; | | 7120 | return @result; |
7110 | } | | 7121 | } |
7111 | | | 7122 | |
7112 | # Checks that the files in the directory are in sync with CVS's status. | | 7123 | # Checks that the files in the directory are in sync with CVS's status. |
7113 | # | | 7124 | # |
7114 | sub checkdir_CVS($) { | | 7125 | sub checkdir_CVS($) { |
7115 | my ($fname) = @_; | | 7126 | my ($fname) = @_; |
7116 | | | 7127 | |
7117 | my $cvs_entries = load_file("$fname/CVS/Entries"); | | 7128 | my $cvs_entries = load_file("$fname/CVS/Entries"); |
7118 | my $cvs_entries_log = load_file("$fname/CVS/Entries.Log"); | | 7129 | my $cvs_entries_log = load_file("$fname/CVS/Entries.Log"); |
7119 | return unless $cvs_entries; | | 7130 | return unless $cvs_entries; |
7120 | | | 7131 | |
7121 | foreach my $line (@$cvs_entries) { | | 7132 | foreach my $line (@$cvs_entries) { |
7122 | my ($type, $fname, $mtime, $date, $keyword_mode, $tag, $undef) = my_split("/", $line->text); | | 7133 | my ($type, $fname, $mtime, $date, $keyword_mode, $tag, $undef) = my_split("/", $line->text); |
7123 | next if ($type eq "D" && !defined($fname)); | | 7134 | next if ($type eq "D" && !defined($fname)); |
7124 | assert($type eq "" || $type eq "D", "Unknown line format: " . $line->text); | | 7135 | assert($type eq "" || $type eq "D", "Unknown line format: " . $line->text); |
7125 | assert(defined($tag), "Unknown line format: " . $line->text); | | 7136 | assert(defined($tag), "Unknown line format: " . $line->text); |
7126 | assert(defined($keyword_mode), "Unknown line format: " . $line->text); | | 7137 | assert(defined($keyword_mode), "Unknown line format: " . $line->text); |
7127 | assert(!defined($undef), "Unknown line format: " . $line->text); | | 7138 | assert(!defined($undef), "Unknown line format: " . $line->text); |
7128 | } | | 7139 | } |
7129 | } | | 7140 | } |
7130 | | | 7141 | |
7131 | # | | 7142 | # |
7132 | # Procedures to check a directory including the files in it. | | 7143 | # Procedures to check a directory including the files in it. |
7133 | # | | 7144 | # |
7134 | | | 7145 | |
7135 | sub checkdir_root() { | | 7146 | sub checkdir_root() { |
7136 | my ($fname) = "${current_dir}/Makefile"; | | 7147 | my ($fname) = "${current_dir}/Makefile"; |
7137 | my ($lines, $prev_subdir, @subdirs); | | 7148 | my ($lines, $prev_subdir, @subdirs); |
7138 | | | 7149 | |
7139 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_root()"); | | 7150 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_root()"); |
7140 | | | 7151 | |
7141 | if (!($lines = load_lines($fname, true))) { | | 7152 | if (!($lines = load_lines($fname, true))) { |
7142 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 7153 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
7143 | return; | | 7154 | return; |
7144 | } | | 7155 | } |
7145 | | | 7156 | |
7146 | parselines_mk($lines); | | 7157 | parselines_mk($lines); |
7147 | if (0 <= $#{$lines}) { | | 7158 | if (0 <= $#{$lines}) { |
7148 | checkline_rcsid_regex($lines->[0], qr"#\s+", "# "); | | 7159 | checkline_rcsid_regex($lines->[0], qr"#\s+", "# "); |
7149 | } | | 7160 | } |
7150 | | | 7161 | |
7151 | foreach my $line (@{$lines}) { | | 7162 | foreach my $line (@{$lines}) { |
7152 | if ($line->text =~ m"^(#?)SUBDIR\s*\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { | | 7163 | if ($line->text =~ m"^(#?)SUBDIR\s*\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { |
7153 | my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); | | 7164 | my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); |
7154 | | | 7165 | |
7155 | if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { | | 7166 | if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { |
7156 | $line->log_warning("${subdir} commented out without giving a reason."); | | 7167 | $line->log_warning("${subdir} commented out without giving a reason."); |
7157 | } | | 7168 | } |
7158 | | | 7169 | |
7159 | if ($indentation ne "\t") { | | 7170 | if ($indentation ne "\t") { |
7160 | $line->log_warning("Indentation should be a single tab character."); | | 7171 | $line->log_warning("Indentation should be a single tab character."); |
7161 | } | | 7172 | } |
7162 | | | 7173 | |
7163 | if ($subdir =~ m"\$" || !-f "${current_dir}/${subdir}/Makefile") { | | 7174 | if ($subdir =~ m"\$" || !-f "${current_dir}/${subdir}/Makefile") { |
7164 | next; | | 7175 | next; |
7165 | } | | 7176 | } |
7166 | | | 7177 | |
7167 | if (defined($prev_subdir) && $subdir eq $prev_subdir) { | | 7178 | if (!defined($prev_subdir) || $subdir gt $prev_subdir) { |
| | | 7179 | # correctly ordered |
| | | 7180 | } elsif ($subdir eq $prev_subdir) { |
7168 | $line->log_error("${subdir} must only appear once."); | | 7181 | $line->log_error("${subdir} must only appear once."); |
7169 | } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) { | | 7182 | } elsif ($prev_subdir eq "x11" && $subdir eq "archivers") { |
7170 | $line->log_warning("${subdir} should come before ${prev_subdir}."); | | 7183 | # ignore that one, since it is documented in the top-level Makefile |
7171 | } else { | | 7184 | } else { |
7172 | # correctly ordered | | 7185 | $line->log_warning("${subdir} should come before ${prev_subdir}."); |
7173 | } | | 7186 | } |
7174 | | | 7187 | |
7175 | $prev_subdir = $subdir; | | 7188 | $prev_subdir = $subdir; |
7176 | | | 7189 | |
7177 | if ($comment_flag eq "") { | | 7190 | if ($comment_flag eq "") { |
7178 | push(@subdirs, "${current_dir}/${subdir}"); | | 7191 | push(@subdirs, "${current_dir}/${subdir}"); |
7179 | } | | 7192 | } |
7180 | } | | 7193 | } |
7181 | } | | 7194 | } |
7182 | | | 7195 | |
7183 | checklines_mk($lines); | | 7196 | checklines_mk($lines); |
7184 | | | 7197 | |
7185 | if ($opt_recursive) { | | 7198 | if ($opt_recursive) { |
7186 | push(@todo_items, @subdirs); | | 7199 | push(@todo_items, @subdirs); |
7187 | } | | 7200 | } |
7188 | } | | 7201 | } |
7189 | | | 7202 | |
7190 | sub checkdir_category() { | | 7203 | sub checkdir_category() { |
7191 | my $fname = "${current_dir}/Makefile"; | | 7204 | my $fname = "${current_dir}/Makefile"; |
7192 | my ($lines, $lineno); | | 7205 | my ($lines, $lineno); |
7193 | | | 7206 | |
7194 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_category()"); | | 7207 | $opt_debug_trace and log_debug($fname, NO_LINES, "checkdir_category()"); |
7195 | | | 7208 | |
7196 | if (!($lines = load_lines($fname, true))) { | | 7209 | if (!($lines = load_lines($fname, true))) { |
7197 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); | | 7210 | log_error($fname, NO_LINE_NUMBER, "Cannot be read."); |
7198 | return; | | 7211 | return; |
7199 | } | | 7212 | } |
7200 | parselines_mk($lines); | | 7213 | parselines_mk($lines); |
7201 | | | 7214 | |
7202 | $lineno = 0; | | 7215 | $lineno = 0; |
7203 | | | 7216 | |
7204 | # The first line must contain the RCS Id | | 7217 | # The first line must contain the RCS Id |
7205 | if ($lineno <= $#{$lines} && checkline_rcsid_regex($lines->[$lineno], qr"#\s+", "# ")) { | | 7218 | if ($lineno <= $#{$lines} && checkline_rcsid_regex($lines->[$lineno], qr"#\s+", "# ")) { |
7206 | $lineno++; | | 7219 | $lineno++; |
7207 | } | | 7220 | } |
7208 | | | 7221 | |
7209 | # Then, arbitrary comments may follow | | 7222 | # Then, arbitrary comments may follow |
7210 | while ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^#") { | | 7223 | while ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^#") { |
7211 | $lineno++; | | 7224 | $lineno++; |
7212 | } | | 7225 | } |
7213 | | | 7226 | |
7214 | # Then we need an empty line | | 7227 | # Then we need an empty line |
7215 | expect_empty_line($lines, \$lineno); | | 7228 | expect_empty_line($lines, \$lineno); |
7216 | | | 7229 | |
7217 | # Then comes the COMMENT line | | 7230 | # Then comes the COMMENT line |
7218 | if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^COMMENT=\t*(.*)") { | | 7231 | if ($lineno <= $#{$lines} && $lines->[$lineno]->text =~ m"^COMMENT=\t*(.*)") { |
7219 | my ($comment) = ($1); | | 7232 | my ($comment) = ($1); |
7220 | | | 7233 | |
7221 | checkline_valid_characters_in_variable($lines->[$lineno], qr"[-\040'(),/0-9A-Za-z]"); | | 7234 | checkline_valid_characters_in_variable($lines->[$lineno], qr"[-\040'(),/0-9A-Za-z]"); |
7222 | $lineno++; | | 7235 | $lineno++; |
7223 | } else { | | 7236 | } else { |
7224 | $lines->[$lineno]->log_error("COMMENT= line expected."); | | 7237 | $lines->[$lineno]->log_error("COMMENT= line expected."); |
7225 | } | | 7238 | } |
7226 | | | 7239 | |
7227 | # Then we need an empty line | | 7240 | # Then we need an empty line |
7228 | expect_empty_line($lines, \$lineno); | | 7241 | expect_empty_line($lines, \$lineno); |
7229 | | | 7242 | |
7230 | # And now to the most complicated part of the category Makefiles, | | 7243 | # And now to the most complicated part of the category Makefiles, |
7231 | # the (hopefully) sorted list of SUBDIRs. The first step is to | | 7244 | # the (hopefully) sorted list of SUBDIRs. The first step is to |
7232 | # collect the SUBDIRs in the Makefile and in the file system. | | 7245 | # collect the SUBDIRs in the Makefile and in the file system. |
7233 | | | 7246 | |
7234 | my (@f_subdirs, @m_subdirs); | | 7247 | my (@f_subdirs, @m_subdirs); |
7235 | | | 7248 | |
7236 | @f_subdirs = sort(get_subdirs($current_dir)); | | 7249 | @f_subdirs = sort(get_subdirs($current_dir)); |
7237 | | | 7250 | |
7238 | my $prev_subdir = undef; | | 7251 | my $prev_subdir = undef; |
7239 | while ($lineno <= $#{$lines}) { | | 7252 | while ($lineno <= $#{$lines}) { |
7240 | my $line = $lines->[$lineno]; | | 7253 | my $line = $lines->[$lineno]; |
7241 | | | 7254 | |
7242 | if ($line->text =~ m"^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { | | 7255 | if ($line->text =~ m"^(#?)SUBDIR\+=(\s*)(\S+)\s*(?:#\s*(.*?)\s*|)$") { |
7243 | my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); | | 7256 | my ($comment_flag, $indentation, $subdir, $comment) = ($1, $2, $3, $4); |
7244 | | | 7257 | |
7245 | if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { | | 7258 | if ($comment_flag eq "#" && (!defined($comment) || $comment eq "")) { |
7246 | $line->log_warning("${subdir} commented out without giving a reason."); | | 7259 | $line->log_warning("${subdir} commented out without giving a reason."); |
7247 | } | | 7260 | } |
7248 | | | 7261 | |
7249 | if ($indentation ne "\t") { | | 7262 | if ($indentation ne "\t") { |
7250 | $line->log_warning("Indentation should be a single tab character."); | | 7263 | $line->log_warning("Indentation should be a single tab character."); |
7251 | } | | 7264 | } |
7252 | | | 7265 | |
7253 | if (defined($prev_subdir) && $subdir eq $prev_subdir) { | | 7266 | if (defined($prev_subdir) && $subdir eq $prev_subdir) { |
7254 | $line->log_error("${subdir} must only appear once."); | | 7267 | $line->log_error("${subdir} must only appear once."); |
7255 | } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) { | | 7268 | } elsif (defined($prev_subdir) && $subdir lt $prev_subdir) { |
7256 | $line->log_warning("${subdir} should come before ${prev_subdir}."); | | 7269 | $line->log_warning("${subdir} should come before ${prev_subdir}."); |
7257 | } else { | | 7270 | } else { |
7258 | # correctly ordered | | 7271 | # correctly ordered |
7259 | } | | 7272 | } |
7260 | | | 7273 | |
7261 | push(@m_subdirs, [$subdir, $line, $comment_flag ? false : true]); | | 7274 | push(@m_subdirs, [$subdir, $line, $comment_flag ? false : true]); |
7262 | $prev_subdir = $subdir; | | 7275 | $prev_subdir = $subdir; |
7263 | $lineno++; | | 7276 | $lineno++; |
7264 | | | 7277 | |
7265 | } else { | | 7278 | } else { |
7266 | if ($line->text ne "") { | | 7279 | if ($line->text ne "") { |
7267 | $line->log_error("SUBDIR+= line or empty line expected."); | | 7280 | $line->log_error("SUBDIR+= line or empty line expected."); |
7268 | } | | 7281 | } |
7269 | last; | | 7282 | last; |
7270 | } | | 7283 | } |
7271 | } | | 7284 | } |
7272 | | | 7285 | |
7273 | # To prevent unnecessary warnings about subdirectories that are | | 7286 | # To prevent unnecessary warnings about subdirectories that are |
7274 | # in one list, but not in the other, we generate the sets of | | 7287 | # in one list, but not in the other, we generate the sets of |
7275 | # subdirs of each list. | | 7288 | # subdirs of each list. |
7276 | my (%f_check, %m_check); | | 7289 | my (%f_check, %m_check); |
7277 | foreach my $f (@f_subdirs) { $f_check{$f} = true; } | | 7290 | foreach my $f (@f_subdirs) { $f_check{$f} = true; } |
7278 | foreach my $m (@m_subdirs) { $m_check{$m->[0]} = true; } | | 7291 | foreach my $m (@m_subdirs) { $m_check{$m->[0]} = true; } |
7279 | | | 7292 | |
7280 | my ($f_index, $f_atend, $f_neednext, $f_current) = (0, false, true, undef, undef); | | 7293 | my ($f_index, $f_atend, $f_neednext, $f_current) = (0, false, true, undef, undef); |
7281 | my ($m_index, $m_atend, $m_neednext, $m_current) = (0, false, true, undef, undef); | | 7294 | my ($m_index, $m_atend, $m_neednext, $m_current) = (0, false, true, undef, undef); |
7282 | my ($line, $m_recurse); | | 7295 | my ($line, $m_recurse); |
7283 | my (@subdirs); | | 7296 | my (@subdirs); |
7284 | | | 7297 | |
7285 | while (!($m_atend && $f_atend)) { | | 7298 | while (!($m_atend && $f_atend)) { |
7286 | | | 7299 | |
7287 | if (!$m_atend && $m_neednext) { | | 7300 | if (!$m_atend && $m_neednext) { |
7288 | $m_neednext = false; | | 7301 | $m_neednext = false; |
7289 | if ($m_index > $#m_subdirs) { | | 7302 | if ($m_index > $#m_subdirs) { |
7290 | $m_atend = true; | | 7303 | $m_atend = true; |
7291 | $line = $lines->[$lineno]; | | 7304 | $line = $lines->[$lineno]; |
7292 | next; | | 7305 | next; |
7293 | } else { | | 7306 | } else { |
7294 | $m_current = $m_subdirs[$m_index]->[0]; | | 7307 | $m_current = $m_subdirs[$m_index]->[0]; |
7295 | $line = $m_subdirs[$m_index]->[1]; | | 7308 | $line = $m_subdirs[$m_index]->[1]; |
7296 | $m_recurse = $m_subdirs[$m_index]->[2]; | | 7309 | $m_recurse = $m_subdirs[$m_index]->[2]; |
7297 | $m_index++; | | 7310 | $m_index++; |
7298 | } | | 7311 | } |
7299 | } | | 7312 | } |
7300 | | | 7313 | |
7301 | if (!$f_atend && $f_neednext) { | | 7314 | if (!$f_atend && $f_neednext) { |
7302 | $f_neednext = false; | | 7315 | $f_neednext = false; |
7303 | if ($f_index > $#f_subdirs) { | | 7316 | if ($f_index > $#f_subdirs) { |
7304 | $f_atend = true; | | 7317 | $f_atend = true; |
7305 | next; | | 7318 | next; |
7306 | } else { | | 7319 | } else { |
7307 | $f_current = $f_subdirs[$f_index++]; | | 7320 | $f_current = $f_subdirs[$f_index++]; |
7308 | } | | 7321 | } |
7309 | } | | 7322 | } |
7310 | | | 7323 | |
7311 | if (!$f_atend && ($m_atend || $f_current lt $m_current)) { | | 7324 | if (!$f_atend && ($m_atend || $f_current lt $m_current)) { |
7312 | if (!exists($m_check{$f_current})) { | | 7325 | if (!exists($m_check{$f_current})) { |
7313 | $line->log_error("${f_current} exists in the file system, but not in the Makefile."); | | 7326 | $line->log_error("${f_current} exists in the file system, but not in the Makefile."); |
7314 | $line->append_before("SUBDIR+=\t${f_current}"); | | 7327 | $line->append_before("SUBDIR+=\t${f_current}"); |
7315 | } | | 7328 | } |
7316 | $f_neednext = true; | | 7329 | $f_neednext = true; |
7317 | | | 7330 | |
7318 | } elsif (!$m_atend && ($f_atend || $m_current lt $f_current)) { | | 7331 | } elsif (!$m_atend && ($f_atend || $m_current lt $f_current)) { |
7319 | if (!exists($f_check{$m_current})) { | | 7332 | if (!exists($f_check{$m_current})) { |
7320 | $line->log_error("${m_current} exists in the Makefile, but not in the file system."); | | 7333 | $line->log_error("${m_current} exists in the Makefile, but not in the file system."); |
7321 | $line->delete(); | | 7334 | $line->delete(); |
7322 | } | | 7335 | } |
7323 | $m_neednext = true; | | 7336 | $m_neednext = true; |
7324 | | | 7337 | |
7325 | } else { # $f_current eq $m_current | | 7338 | } else { # $f_current eq $m_current |
7326 | $f_neednext = true; | | 7339 | $f_neednext = true; |
7327 | $m_neednext = true; | | 7340 | $m_neednext = true; |
7328 | if ($m_recurse) { | | 7341 | if ($m_recurse) { |
7329 | push(@subdirs, "${current_dir}/${m_current}"); | | 7342 | push(@subdirs, "${current_dir}/${m_current}"); |
7330 | } | | 7343 | } |
7331 | } | | 7344 | } |
7332 | } | | 7345 | } |
7333 | | | 7346 | |
7334 | # the wip category Makefile may have its own targets for generating | | 7347 | # the wip category Makefile may have its own targets for generating |
7335 | # indexes and READMEs. Just skip them. | | 7348 | # indexes and READMEs. Just skip them. |
7336 | if ($is_wip) { | | 7349 | if ($is_wip) { |
7337 | while ($lineno <= $#{$lines} - 2) { | | 7350 | while ($lineno <= $#{$lines} - 2) { |
7338 | $lineno++; | | 7351 | $lineno++; |
7339 | } | | 7352 | } |
7340 | } | | 7353 | } |
7341 | | | 7354 | |
7342 | expect_empty_line($lines, \$lineno); | | 7355 | expect_empty_line($lines, \$lineno); |
7343 | | | 7356 | |
7344 | # And, last but not least, the .include line | | 7357 | # And, last but not least, the .include line |
7345 | my $final_line = ".include \"../mk/bsd.pkg.subdir.mk\""; | | 7358 | my $final_line = ".include \"../mk/bsd.pkg.subdir.mk\""; |
7346 | expect($lines, \$lineno, qr"\Q$final_line\E") | | 7359 | expect($lines, \$lineno, qr"\Q$final_line\E") |
7347 | || expect_text($lines, \$lineno, ".include \"../mk/misc/category.mk\""); | | 7360 | || expect_text($lines, \$lineno, ".include \"../mk/misc/category.mk\""); |
7348 | | | 7361 | |
7349 | if ($lineno <= $#{$lines}) { | | 7362 | if ($lineno <= $#{$lines}) { |
7350 | $lines->[$lineno]->log_error("The file should end here."); | | 7363 | $lines->[$lineno]->log_error("The file should end here."); |
7351 | } | | 7364 | } |
7352 | | | 7365 | |
7353 | checklines_mk($lines); | | 7366 | checklines_mk($lines); |
7354 | | | 7367 | |
7355 | autofix($lines); | | 7368 | autofix($lines); |
7356 | | | 7369 | |
7357 | if ($opt_recursive) { | | 7370 | if ($opt_recursive) { |
7358 | unshift(@todo_items, @subdirs); | | 7371 | unshift(@todo_items, @subdirs); |
7359 | } | | 7372 | } |
7360 | } | | 7373 | } |
7361 | | | 7374 | |
7362 | sub checkdir_package() { | | 7375 | sub checkdir_package() { |
7363 | my ($lines, $have_distinfo, $have_patches); | | 7376 | my ($lines, $have_distinfo, $have_patches); |
7364 | | | 7377 | |
7365 | # Initialize global variables | | 7378 | # Initialize global variables |
7366 | $pkgdir = undef; | | 7379 | $pkgdir = undef; |
7367 | $filesdir = "files"; | | 7380 | $filesdir = "files"; |
7368 | $patchdir = "patches"; | | 7381 | $patchdir = "patches"; |
7369 | $distinfo_file = "distinfo"; | | 7382 | $distinfo_file = "distinfo"; |
7370 | $effective_pkgname = undef; | | 7383 | $effective_pkgname = undef; |
7371 | $effective_pkgbase = undef; | | 7384 | $effective_pkgbase = undef; |
7372 | $effective_pkgversion = undef; | | 7385 | $effective_pkgversion = undef; |
7373 | $effective_pkgname_line = undef; | | 7386 | $effective_pkgname_line = undef; |
7374 | $seen_bsd_prefs_mk = false; | | 7387 | $seen_bsd_prefs_mk = false; |
7375 | $pkgctx_vardef = {%{get_userdefined_variables()}}; | | 7388 | $pkgctx_vardef = {%{get_userdefined_variables()}}; |
7376 | $pkgctx_varuse = {}; | | 7389 | $pkgctx_varuse = {}; |
7377 | $pkgctx_bl3 = {}; | | 7390 | $pkgctx_bl3 = {}; |
7378 | $pkgctx_plist_subst_cond = {}; | | 7391 | $pkgctx_plist_subst_cond = {}; |
7379 | $pkgctx_included = {}; | | 7392 | $pkgctx_included = {}; |
7380 | $seen_Makefile_common = false; | | 7393 | $seen_Makefile_common = false; |
7381 | | | 7394 | |
7382 | # we need to handle the Makefile first to get some variables | | 7395 | # we need to handle the Makefile first to get some variables |
7383 | if (!load_package_Makefile("${current_dir}/Makefile", \$lines)) { | | 7396 | if (!load_package_Makefile("${current_dir}/Makefile", \$lines)) { |
7384 | log_error("${current_dir}/Makefile", NO_LINE_NUMBER, "Cannot be read."); | | 7397 | log_error("${current_dir}/Makefile", NO_LINE_NUMBER, "Cannot be read."); |
7385 | goto cleanup; | | 7398 | goto cleanup; |
7386 | } | | 7399 | } |
7387 | | | 7400 | |
7388 | my @files = <${current_dir}/*>; | | 7401 | my @files = <${current_dir}/*>; |
7389 | if ($pkgdir ne ".") { | | 7402 | if ($pkgdir ne ".") { |
7390 | push(@files, <${current_dir}/${pkgdir}/*>); | | 7403 | push(@files, <${current_dir}/${pkgdir}/*>); |
7391 | } | | 7404 | } |
7392 | if ($opt_check_extra) { | | 7405 | if ($opt_check_extra) { |
7393 | push(@files, <${current_dir}/${filesdir}/*>); | | 7406 | push(@files, <${current_dir}/${filesdir}/*>); |
7394 | } | | 7407 | } |
7395 | push(@files, <${current_dir}/${patchdir}/*>); | | 7408 | push(@files, <${current_dir}/${patchdir}/*>); |
7396 | if ($distinfo_file !~ m"^(?:\./)?distinfo$") { | | 7409 | if ($distinfo_file !~ m"^(?:\./)?distinfo$") { |
7397 | push(@files, "${current_dir}/${distinfo_file}"); | | 7410 | push(@files, "${current_dir}/${distinfo_file}"); |
7398 | } | | 7411 | } |
7399 | $have_distinfo = false; | | 7412 | $have_distinfo = false; |
7400 | $have_patches = false; | | 7413 | $have_patches = false; |
7401 | | | 7414 | |
7402 | # Determine the used variables before checking any of the | | 7415 | # Determine the used variables before checking any of the |
7403 | # Makefile fragments. | | 7416 | # Makefile fragments. |
7404 | foreach my $fname (@files) { | | 7417 | foreach my $fname (@files) { |
7405 | if (($fname =~ m"^((?:.*/)?Makefile\..*|.*\.mk)$") | | 7418 | if (($fname =~ m"^((?:.*/)?Makefile\..*|.*\.mk)$") |
7406 | && (not $fname =~ m"patch-") | | 7419 | && (not $fname =~ m"patch-") |
7407 | && (not $fname =~ m"${pkgdir}/") | | 7420 | && (not $fname =~ m"${pkgdir}/") |
7408 | && (not $fname =~ m"${filesdir}/") | | 7421 | && (not $fname =~ m"${filesdir}/") |
7409 | && (defined(my $lines = load_lines($fname, true)))) { | | 7422 | && (defined(my $lines = load_lines($fname, true)))) { |
7410 | parselines_mk($lines); | | 7423 | parselines_mk($lines); |
7411 | determine_used_variables($lines); | | 7424 | determine_used_variables($lines); |
7412 | } | | 7425 | } |
7413 | } | | 7426 | } |
7414 | | | 7427 | |
7415 | foreach my $fname (@files) { | | 7428 | foreach my $fname (@files) { |
7416 | if ($fname eq "${current_dir}/Makefile") { | | 7429 | if ($fname eq "${current_dir}/Makefile") { |
7417 | $opt_check_Makefile and checkfile_package_Makefile($fname, $lines); | | 7430 | $opt_check_Makefile and checkfile_package_Makefile($fname, $lines); |
7418 | } else { | | 7431 | } else { |
7419 | checkfile($fname); | | 7432 | checkfile($fname); |
7420 | } | | 7433 | } |
7421 | if ($fname =~ m"/patches/patch-*$") { | | 7434 | if ($fname =~ m"/patches/patch-*$") { |
7422 | $have_patches = true; | | 7435 | $have_patches = true; |
7423 | } elsif ($fname =~ m"/distinfo$") { | | 7436 | } elsif ($fname =~ m"/distinfo$") { |
7424 | $have_distinfo = true; | | 7437 | $have_distinfo = true; |
7425 | } | | 7438 | } |
7426 | } | | 7439 | } |
7427 | | | 7440 | |
7428 | if ($opt_check_distinfo && $opt_check_patches) { | | 7441 | if ($opt_check_distinfo && $opt_check_patches) { |
7429 | if ($have_patches && ! $have_distinfo) { | | 7442 | if ($have_patches && ! $have_distinfo) { |
7430 | log_warning("${current_dir}/$distinfo_file", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makepatchsum'."); | | 7443 | log_warning("${current_dir}/$distinfo_file", NO_LINE_NUMBER, "File not found. Please run '".conf_make." makepatchsum'."); |
7431 | } | | 7444 | } |
7432 | } | | 7445 | } |
7433 | | | 7446 | |
7434 | if (!is_emptydir("${current_dir}/scripts")) { | | 7447 | if (!is_emptydir("${current_dir}/scripts")) { |
7435 | 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."); | | 7448 | 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."); |
7436 | } | | 7449 | } |
7437 | | | 7450 | |
7438 | cleanup: | | 7451 | cleanup: |
7439 | # Clean up global variables. | | 7452 | # Clean up global variables. |
7440 | $pkgdir = undef; | | 7453 | $pkgdir = undef; |
7441 | $filesdir = undef; | | 7454 | $filesdir = undef; |
7442 | $patchdir = undef; | | 7455 | $patchdir = undef; |
7443 | $distinfo_file = undef; | | 7456 | $distinfo_file = undef; |
7444 | $effective_pkgname = undef; | | 7457 | $effective_pkgname = undef; |
7445 | $effective_pkgbase = undef; | | 7458 | $effective_pkgbase = undef; |
7446 | $effective_pkgversion = undef; | | 7459 | $effective_pkgversion = undef; |
7447 | $effective_pkgname_line = undef; | | 7460 | $effective_pkgname_line = undef; |
7448 | $seen_bsd_prefs_mk = undef; | | 7461 | $seen_bsd_prefs_mk = undef; |
7449 | $pkgctx_vardef = undef; | | 7462 | $pkgctx_vardef = undef; |
7450 | $pkgctx_varuse = undef; | | 7463 | $pkgctx_varuse = undef; |
7451 | $pkgctx_bl3 = undef; | | 7464 | $pkgctx_bl3 = undef; |
7452 | $pkgctx_plist_subst_cond = undef; | | 7465 | $pkgctx_plist_subst_cond = undef; |
7453 | $pkgctx_included = undef; | | 7466 | $pkgctx_included = undef; |
7454 | $seen_Makefile_common = undef; | | 7467 | $seen_Makefile_common = undef; |
7455 | } | | 7468 | } |
7456 | | | 7469 | |
7457 | # | | 7470 | # |
7458 | # Selecting the proper checking procedures for a directory entry. | | 7471 | # Selecting the proper checking procedures for a directory entry. |
7459 | # | | 7472 | # |
7460 | | | 7473 | |
7461 | sub checkitem($) { | | 7474 | sub checkitem($) { |
7462 | my ($item) = @_; | | 7475 | my ($item) = @_; |
7463 | my ($st, $is_dir, $is_reg); | | 7476 | my ($st, $is_dir, $is_reg); |
7464 | | | 7477 | |
7465 | if (!($st = lstat($item))) { | | 7478 | if (!($st = lstat($item))) { |
7466 | log_error($item, NO_LINE_NUMBER, "Does not exist."); | | 7479 | log_error($item, NO_LINE_NUMBER, "Does not exist."); |
7467 | return; | | 7480 | return; |
7468 | } | | 7481 | } |
7469 | | | 7482 | |
7470 | $is_dir = S_ISDIR($st->mode); | | 7483 | $is_dir = S_ISDIR($st->mode); |
7471 | $is_reg = S_ISREG($st->mode); | | 7484 | $is_reg = S_ISREG($st->mode); |
7472 | if (!$is_reg && !$is_dir) { | | 7485 | if (!$is_reg && !$is_dir) { |
7473 | log_error($item, NO_LINE_NUMBER, "Must be a file or directory."); | | 7486 | log_error($item, NO_LINE_NUMBER, "Must be a file or directory."); |
7474 | return; | | 7487 | return; |
7475 | } | | 7488 | } |
7476 | | | 7489 | |
7477 | $current_dir = $is_dir ? $item : dirname($item); | | 7490 | $current_dir = $is_dir ? $item : dirname($item); |
7478 | my $abs_current_dir = Cwd::abs_path($current_dir); | | 7491 | my $abs_current_dir = Cwd::abs_path($current_dir); |
7479 | $is_wip = !$opt_import && ($abs_current_dir =~ m"/wip(?:/|$)"); | | 7492 | $is_wip = !$opt_import && ($abs_current_dir =~ m"/wip(?:/|$)"); |
7480 | $is_internal = ($abs_current_dir =~ m"/mk(?:/|$)"); | | 7493 | $is_internal = ($abs_current_dir =~ m"/mk(?:/|$)"); |
7481 | | | 7494 | |
7482 | # Determine the root directory of pkgsrc. By only overwriting | | 7495 | # Determine the root directory of pkgsrc. By only overwriting |
7483 | # the global variable $cwd_pkgsrcdir when we are checking inside | | 7496 | # the global variable $cwd_pkgsrcdir when we are checking inside |
7484 | # a pkgsrc tree, the user can specify a tree with the | | 7497 | # a pkgsrc tree, the user can specify a tree with the |
7485 | # --pkgsrcdir option and then check files (but not directories) | | 7498 | # --pkgsrcdir option and then check files (but not directories) |
7486 | # outside of any pkgsrc tree. | | 7499 | # outside of any pkgsrc tree. |
7487 | $cur_pkgsrcdir = undef; | | 7500 | $cur_pkgsrcdir = undef; |
7488 | $pkgpath = undef; | | 7501 | $pkgpath = undef; |
7489 | foreach my $d (".", "..", "../..", "../../..") { | | 7502 | foreach my $d (".", "..", "../..", "../../..") { |
7490 | if (-f "${current_dir}/${d}/mk/bsd.pkg.mk") { | | 7503 | if (-f "${current_dir}/${d}/mk/bsd.pkg.mk") { |
7491 | $cur_pkgsrcdir = $d; | | 7504 | $cur_pkgsrcdir = $d; |
7492 | $pkgpath = relative_path("${current_dir}/${d}", $current_dir); | | 7505 | $pkgpath = relative_path("${current_dir}/${d}", $current_dir); |
7493 | } | | 7506 | } |
7494 | } | | 7507 | } |
7495 | if (!defined($cwd_pkgsrcdir) && defined($cur_pkgsrcdir)) { | | 7508 | if (!defined($cwd_pkgsrcdir) && defined($cur_pkgsrcdir)) { |
7496 | $cwd_pkgsrcdir = "${current_dir}/${cur_pkgsrcdir}"; | | 7509 | $cwd_pkgsrcdir = "${current_dir}/${cur_pkgsrcdir}"; |
7497 | } | | 7510 | } |
7498 | | | 7511 | |
7499 | if (!defined($cwd_pkgsrcdir)) { | | 7512 | if (!defined($cwd_pkgsrcdir)) { |
7500 | log_error($item, NO_LINE_NUMBER, "Cannot determine the pkgsrc root directory."); | | 7513 | log_error($item, NO_LINE_NUMBER, "Cannot determine the pkgsrc root directory."); |
7501 | return; | | 7514 | return; |
7502 | } | | 7515 | } |
7503 | | | 7516 | |
7504 | check_pkglint_version(); # (needs $cwd_pkgsrcdir) | | 7517 | check_pkglint_version(); # (needs $cwd_pkgsrcdir) |
7505 | | | 7518 | |
7506 | return if $is_dir && is_emptydir($item); | | 7519 | return if $is_dir && is_emptydir($item); |
7507 | | | 7520 | |
7508 | if ($is_dir) { | | 7521 | if ($is_dir) { |
7509 | checkdir_CVS($item); | | 7522 | checkdir_CVS($item); |
7510 | } | | 7523 | } |
7511 | | | 7524 | |
7512 | if ($is_reg) { | | 7525 | if ($is_reg) { |
7513 | checkfile($item); | | 7526 | checkfile($item); |
7514 | | | 7527 | |
7515 | } elsif (!defined($cur_pkgsrcdir)) { | | 7528 | } elsif (!defined($cur_pkgsrcdir)) { |
7516 | log_error($item, NO_LINES, "Cannot check directories outside a pkgsrc tree."); | | 7529 | log_error($item, NO_LINES, "Cannot check directories outside a pkgsrc tree."); |
7517 | | | 7530 | |
7518 | } elsif ($cur_pkgsrcdir eq "../..") { | | 7531 | } elsif ($cur_pkgsrcdir eq "../..") { |
7519 | checkdir_package(); | | 7532 | checkdir_package(); |
7520 | | | 7533 | |
7521 | } elsif ($cur_pkgsrcdir eq "..") { | | 7534 | } elsif ($cur_pkgsrcdir eq "..") { |
7522 | checkdir_category(); | | 7535 | checkdir_category(); |
7523 | | | 7536 | |
7524 | } elsif ($cur_pkgsrcdir eq ".") { | | 7537 | } elsif ($cur_pkgsrcdir eq ".") { |
7525 | checkdir_root(); | | 7538 | checkdir_root(); |
7526 | | | 7539 | |
7527 | } else { | | 7540 | } else { |
7528 | log_error($item, NO_LINE_NUMBER, "Don't know how to check this directory."); | | 7541 | log_error($item, NO_LINE_NUMBER, "Don't know how to check this directory."); |
7529 | } | | 7542 | } |
7530 | } | | 7543 | } |
7531 | | | 7544 | |
7532 | # | | 7545 | # |
7533 | # The main program | | 7546 | # The main program |
7534 | # | | 7547 | # |
7535 | | | 7548 | |
7536 | sub main() { | | 7549 | sub main() { |
7537 | | | 7550 | |
7538 | $| = true; | | 7551 | $| = true; |
7539 | parse_command_line(); | | 7552 | parse_command_line(); |
7540 | | | 7553 | |
7541 | @todo_items = (@ARGV != 0) ? @ARGV : ("."); | | 7554 | @todo_items = (@ARGV != 0) ? @ARGV : ("."); |
7542 | while (@todo_items != 0) { | | 7555 | while (@todo_items != 0) { |
7543 | checkitem(shift(@todo_items)); | | 7556 | checkitem(shift(@todo_items)); |
7544 | } | | 7557 | } |
7545 | | | 7558 | |
7546 | PkgLint::Logging::print_summary_and_exit($opt_quiet); | | 7559 | PkgLint::Logging::print_summary_and_exit($opt_quiet); |
7547 | } | | 7560 | } |
7548 | | | 7561 | |
7549 | main() unless caller(); | | 7562 | main() unless caller(); |