portlint.pl 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728
  1. #! /usr/bin/perl
  2. # ex:ts=4
  3. #
  4. # portlint - lint for port directory
  5. # implemented by:
  6. # Jun-ichiro itojun Hagino <itojun@itojun.org>
  7. # Yoshishige Arai <ryo2@on.rim.or.jp>
  8. #
  9. # Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>.
  10. # All rights reserved.
  11. # Freely redistributable. Absolutely no warranty.
  12. #
  13. # Please note that this perl code used to be able to handle (Open|Net|Free)BSD
  14. # bsd.port.mk. There are significant differences in those so you'll have
  15. # hard time upgrading this...
  16. # This code now mainly supports FreeBSD, but patches to update support for
  17. # OpenBSD and NetBSD will be accepted.
  18. #
  19. # $FreeBSD: ports/devel/portlint/src/portlint.pl,v 1.35 2003/03/07 17:00:43 petef Exp $
  20. # $Id$
  21. #
  22. use vars qw/ $opt_a $opt_b $opt_c $opt_h $opt_t $opt_v $opt_M $opt_N $opt_B $opt_V /;
  23. use Getopt::Std;
  24. use File::Find;
  25. use IPC::Open2;
  26. #use strict;
  27. my ($err, $warn);
  28. my ($extrafile, $parenwarn, $committer, $verbose, $usetabs, $newport);
  29. my $contblank;
  30. my $portdir;
  31. my $makeenv;
  32. $err = $warn = 0;
  33. $extrafile = $parenwarn = $committer = $verbose = $usetabs = $newport = 0;
  34. $contblank = 1;
  35. $portdir = '.';
  36. # version variables
  37. my $major = 2;
  38. my $minor = 3;
  39. sub l { '[{(]'; }
  40. sub r { '[)}]'; }
  41. sub s { '[ \t]'; }
  42. my $l = &l;
  43. my $r = &r;
  44. my $s = &s;
  45. # default setting - for FreeBSD
  46. my $portsdir = '/usr/ports';
  47. my $rcsidstr = 'FreeBSD';
  48. my $multiplist = 0;
  49. my $ldconfigwithtrue = 0;
  50. my $rcsidinplist = 0;
  51. my $mancompress = 1;
  52. my $manstrict = 0;
  53. my $newxdef = 1;
  54. my $automan = 1;
  55. my $manchapters = '123456789ln';
  56. my $localbase = '/usr/local';
  57. my %lang_pref = qw(
  58. chinese zh
  59. french fr
  60. german de
  61. hebrew iw
  62. hungarian hu
  63. japanese ja
  64. korean ko
  65. portuguese pt
  66. russian ru
  67. ukrainian uk
  68. vietnamese vi
  69. );
  70. my @lang_cat = keys %lang_pref;
  71. my @lang_pref = values %lang_pref;
  72. my $re_lang_pref = '(' . join('|', @lang_pref) . ')-';
  73. my ($prog) = ($0 =~ /([^\/]+)$/);
  74. sub usage {
  75. print STDERR <<EOF;
  76. usage: $prog [-abchvtN] [-M ENV] [-B#] [port_directory]
  77. -a additional check for scripts/* and pkg-*
  78. -b warn \$(VARIABLE)
  79. -c committer mode
  80. -h show summary of command line options
  81. -v verbose mode
  82. -t nit pick about use of spaces
  83. -N writing a new port
  84. -M ENV set make variables to ENV (ex. PORTSDIR=/usr/ports.work)
  85. -B# allow # contiguous blank lines (default: $contblank line)
  86. EOF
  87. exit 0;
  88. }
  89. sub version {
  90. print "$prog version $major.$minor\n";
  91. exit $major;
  92. }
  93. getopts('AabchtvB:M:NV');
  94. &usage if $opt_h;
  95. &version if $opt_V;
  96. $extrafile = 1 if $opt_a || $opt_A;
  97. $parenwarn = 1 if $opt_b || $opt_A;
  98. $committer = 1 if $opt_c || $opt_A;
  99. $verbose = 1 if $opt_v;
  100. $newport = 1 if $opt_N || $opt_A;
  101. $usetabs = 1 if $opt_t || $opt_A;
  102. $contblank = $opt_B if $opt_B;
  103. $makeenv = $opt_M;
  104. $portdir = $ARGV[0] ? $ARGV[0] : '.';
  105. # OS dependent configs
  106. # os portsdir rcsid mplist ldcfg plist-rcsid mancompresss strict localbase newxdef automan
  107. my @osdep = split(/\n/, <<EOF);
  108. FreeBSD /usr/ports FreeBSD 0 0 0 1 0 /usr/local 1 1
  109. NetBSD /usr/pkgsrc NetBSD 1 1 1 0 1 /usr/pkg 0 0
  110. EOF
  111. my $osname = `uname -s`;
  112. $osname =~ s/\n$//;
  113. foreach my $i (@osdep) {
  114. if ($i =~ /^$osname\t(.*)/) {
  115. print "OK: found OS config for $osname.\n" if ($verbose);
  116. ($portsdir, $rcsidstr, $multiplist, $ldconfigwithtrue,
  117. $rcsidinplist, $mancompress, $manstrict, $localbase,
  118. $newxdef, $automan)
  119. = split(/\t+/, $1);
  120. last;
  121. }
  122. }
  123. # The PORTSDIR environment variable overrides our defaults.
  124. $portsdir = $ENV{PORTSDIR} if ( defined $ENV{'PORTSDIR'} );
  125. if ($verbose) {
  126. print "OK: config: portsdir: \"$portsdir\" ".
  127. "rcsidstr: \"$rcsidstr\" ".
  128. "multiplist: $multiplist ".
  129. "ldconfigwithtrue: $ldconfigwithtrue ".
  130. "rcsidinplist: $rcsidinplist ".
  131. "mancompress: $mancompress ".
  132. "manstrict: $manstrict ".
  133. "localbase: $localbase ".
  134. "\n";
  135. }
  136. #
  137. # just for safety.
  138. #
  139. if (! -d $portdir) {
  140. print STDERR "FATAL: invalid directory $portdir specified.\n";
  141. exit 1;
  142. }
  143. chdir "$portdir" || die "$portdir: $!";
  144. # get make vars
  145. my @varlist = qw(
  146. PORTNAME PORTVERSION PORTREVISION PORTEPOCH PKGNAME PKGNAMEPREFIX
  147. PKGNAMESUFFIX DISTNAME DISTFILES CATEGORIES MASTERDIR MAINTAINER
  148. MASTER_SITES WRKDIR WRKSRC NO_WRKSUBDIR PATCHDIR SCRIPTDIR FILESDIR
  149. PKGDIR COMMENT DESCR PLIST PKGINSTALL PKGDEINSTALL PKGREQ PKGMESSAGE
  150. MD5_FILE .CURDIR INSTALLS_SHLIB
  151. );
  152. my $cmd = join(' -V ', "make $makeenv MASTER_SITE_BACKUP=''", @varlist);
  153. my %makevar;
  154. my $i = 0;
  155. for (split(/\n/, `$cmd`)) {
  156. print "OK: makevar: $varlist[$i] = $_\n" if ($verbose);
  157. $makevar{$varlist[$i]} = $_;
  158. $i++;
  159. }
  160. #
  161. # variables for global checks.
  162. #
  163. my $sharedocused = 0;
  164. my %plistmanall = ();
  165. my %plistmangz = ();
  166. my %plistman = ();
  167. my %manlangs = ();
  168. my %predefined = ();
  169. # historical, no longer in FreeBSD's bsd.sites.mk
  170. foreach my $i (split(/\n/, <<EOF)) {
  171. GNU ftp://prep.ai.mit.edu/pub/gnu/%SUBDIR%/
  172. GNU ftp://wuarchive.wustl.edu/systems/gnu/%SUBDIR%/
  173. GNU ftp://ftp.ecrc.net/pub/gnu/%SUBDIR%/
  174. PERL_CPAN ftp://ftp.cdrom.com/pub/perl/CPAN/modules/by-module/%SUBDIR%/
  175. SUNSITE ftp://sunsite.unc.edu/pub/Linux/%SUBDIR%/
  176. SUNSITE ftp://ftp.funet.fi/pub/mirrors/sunsite.unc.edu/pub/Linux/%SUBDIR%/
  177. SUNSITE ftp://ftp.infomagic.com/pub/mirrors/linux/sunsite/%SUBDIR%/
  178. TEX_CTAN ftp://ftp.cdrom.com/pub/tex/ctan/%SUBDIR%/
  179. TEX_CTAN ftp://ftp.tex.ac.uk/public/ctan/tex-archive/%SUBDIR%/
  180. GNOME ftp://ftp.cybertrails.com/pub/gnome/%SUBDIR%/
  181. AFTERSTEP ftp://ftp.alpha1.net/pub/mirrors/ftp.afterstep.org/%SUBDIR%/
  182. AFTERSTEP ftp://casper.yz.yamagata-u.ac.jp/pub/X11/apps/afterstep/%SUBDIR%/
  183. WINDOWMAKER ftp://ftp.io.com/pub/%SUBDIR%/
  184. EOF
  185. my ($j, $k) = split(/\t+/, $i);
  186. $predefined{$k} = $j;
  187. }
  188. # Read bsd.sites.mk
  189. $sites_mk = "$portsdir/Mk/bsd.sites.mk";
  190. open(MK, $sites_mk) || die "$sites_mk: $!";
  191. my @site_groups = grep($_ = /^MASTER_SITE_(\w+)/ && $1, <MK>);
  192. close(MK);
  193. my $cmd = join(' -V MASTER_SITE_', "make $makeenv -f - all", @site_groups);
  194. my $i = 0;
  195. open2(IN, OUT, $cmd);
  196. print OUT <<EOF;
  197. all:
  198. # do nothing
  199. .include "$sites_mk"
  200. EOF
  201. close(OUT);
  202. while (<IN>) {
  203. my $g = $site_groups[$i];
  204. for my $s (split()) {
  205. $predefined{$s} = $g;
  206. }
  207. $i++;
  208. }
  209. close(IN);
  210. #
  211. # check for files.
  212. #
  213. my @checker = ($makevar{DESCR}, 'Makefile', $makevar{MD5_FILE});
  214. my %checker = (
  215. $makevar{DESCR} => 'checkdescr',
  216. 'Makefile' => 'checkmakefile',
  217. $makevar{MD5_FILE} => 'TRUE'
  218. );
  219. if ($extrafile) {
  220. my @files = (
  221. <$makevar{SCRIPTDIR}/*>,
  222. @makevar{DESCR,PLIST,PKGINSTALL,PKGDEINSTALL,PKGREQ,PKGMESSAGE}
  223. );
  224. foreach my $i (@files) {
  225. next if (! -T $i);
  226. next if (defined $checker{$i});
  227. if ($i =~ /\bpkg-plist$/
  228. || ($multiplist && $i =~ /\bpkg-plist/)) {
  229. unshift(@checker, $i);
  230. $checker{$i} = 'checkplist';
  231. } else {
  232. push(@checker, $i);
  233. $checker{$i} = 'checkpathname';
  234. }
  235. }
  236. }
  237. foreach my $i (<$makevar{PATCHDIR}/patch-*>) {
  238. next if (! -T $i);
  239. next if (defined $checker{$i});
  240. push(@checker, $i);
  241. $checker{$i} = 'checkpatch';
  242. }
  243. foreach my $i (@checker) {
  244. print "OK: checking $i.\n";
  245. if (! -f "$i") {
  246. &perror("FATAL: no $i in \"$portdir\".") unless $i eq $makevar{MD5_FILE} && $makevar{DISTFILES} eq "";
  247. } else {
  248. my $proc = $checker{$i};
  249. &$proc($i) || &perror("Cannot open the file $i\n");
  250. if ($proc ne 'checkpatch') {
  251. &checklastline($i)
  252. || &perror("Cannot open the file $i\n");
  253. }
  254. }
  255. }
  256. if ($committer) {
  257. sub find_proc {
  258. return if /^\.\.?$/;
  259. (my $fullname = $File::Find::name) =~ s#^\./##;
  260. print "OK: checking the file name of $fullname.\n" if ($verbose);
  261. if ($fullname eq 'work') {
  262. &perror("FATAL: $fullname: be sure to cleanup the working directory ".
  263. "before committing the port.");
  264. $File::Find::prune = 1;
  265. } elsif (-l) {
  266. &perror("Warning: $fullname: this is a symlink. ".
  267. "CVS will ignore it.");
  268. } elsif (-z) {
  269. &perror("FATAL: $fullname: empty file and should be removed. ".
  270. "If it still needs to be there, put a dummy comment ".
  271. "to state that the file is intentionally left empty.");
  272. $problem = 1;
  273. } elsif (-d && scalar(@x = <$_/{*,.?*}>) <= 1) {
  274. &perror("FATAL: $fullname: empty directory should be removed.");
  275. } elsif (/^\./) {
  276. &perror("Warning: $fullname: dotfiles are not preferred. ".
  277. "If this file is a dotfile to be installed as an example, ".
  278. "consider importing it as \"dot$_\".");
  279. } elsif (/\.(orig|rej|bak)$/ || /~$/ || /^\#/) {
  280. &perror("FATAL: $fullname: for safety, be sure to cleanup ".
  281. "backup files before committing the port.");
  282. } elsif (/(^|\.)core$/) {
  283. &perror("FATAL: $fullname: for safety, be sure to cleanup ".
  284. "core files before committing the port.");
  285. } elsif ($_ eq 'CVS' && -d) {
  286. if ($newport) {
  287. &perror("FATAL: $fullname: for safety, be sure to cleanup ".
  288. "CVS directories before importing the new port.");
  289. }
  290. $File::Find::prune = 1;
  291. }
  292. }
  293. find(\&find_proc, '.');
  294. }
  295. if ($err || $warn) {
  296. print "$err fatal errors and $warn warnings found.\n"
  297. } else {
  298. print "looks fine.\n";
  299. }
  300. exit $err;
  301. #
  302. # pkg-descr
  303. #
  304. sub checkdescr {
  305. my($file) = @_;
  306. my(%maxchars) = ($makevar{DESCR}, 80);
  307. my(%maxlines) = ($makevar{DESCR}, 24);
  308. my(%errmsg) = ($makevar{DESCR}, "exceeds $maxlines{$makevar{DESCR}} ".
  309. "lines, make it shorter if possible.");
  310. my($longlines, $linecnt, $tmp) = (0, 0, "");
  311. open(IN, "< $file") || return 0;
  312. while (<IN>) {
  313. $tmp .= $_;
  314. chomp || &perror("WARN: $file should terminate in '\n'.");
  315. $linecnt++;
  316. $longlines++ if ($maxchars{$file} < length);
  317. }
  318. if ($linecnt > $maxlines{$file}) {
  319. &perror("WARN: $file $errmsg{$file}".
  320. "(currently $linecnt lines)");
  321. } else {
  322. print "OK: $file has $linecnt lines.\n" if ($verbose);
  323. }
  324. if ($longlines > 0) {
  325. &perror("WARN: $file includes lines that exceed $maxchars{$file} ".
  326. "characters.");
  327. }
  328. if ($tmp =~ /[\033\200-\377]/) {
  329. &perror("WARN: $file includes iso-8859-1, or ".
  330. "other local characters. $file should be ".
  331. "plain ascii file.");
  332. }
  333. if ($file =~ /\bpkg-descr/ && $tmp =~ m,http://,) {
  334. my $has_url = 0;
  335. my $has_www = 0;
  336. foreach my $line (grep($_ =~ "http://", split(/\n+/, $tmp))) {
  337. $has_url = 1;
  338. if ($line =~ m,WWW:[ \t]+http://,) {
  339. $has_www = 1;
  340. }
  341. }
  342. if ($has_url && ! $has_www) {
  343. &perror("FATAL: $file: contains a URL but no WWW:");
  344. }
  345. }
  346. close(IN);
  347. }
  348. #
  349. # pkg-plist
  350. #
  351. sub checkplist {
  352. my($file) = @_;
  353. my($curdir) = ($localbase);
  354. my($inforemoveseen, $infoinstallseen, $infoseen) = (0, 0, 0);
  355. my($infobeforeremove, $infoafterinstall) = (0, 0);
  356. my($infooverwrite) = (0);
  357. my($rcsidseen) = (0);
  358. my(@exec_info) = ();
  359. my(@unexec_info) = ();
  360. my(@infofile) = ();
  361. open(IN, "< $file") || return 0;
  362. while (<IN>) {
  363. if ($_ =~ /[ \t]+\n?$/) {
  364. &perror("WARN: $file $.: whitespace before end ".
  365. "of line.");
  366. }
  367. # make it easier to handle.
  368. $_ =~ s/\s+$//;
  369. $_ =~ s/\n$//;
  370. if ($osname eq 'NetBSD' && $_ =~ /<\$ARCH>/) {
  371. &perror("WARN: $file $.: use of <\$ARCH> deprecated, ".
  372. "use \${MACHINE_ARCH} instead.");
  373. }
  374. if ($_ =~ /^\@/) {
  375. if ($_ =~ /^\@(cwd|cd)[ \t]+(\S+)/) {
  376. $curdir = $2;
  377. } elsif ($_ =~ /^\@unexec[ \t]+rmdir/) {
  378. if ($_ !~ /true$/) {
  379. &perror("WARN: use \"\@dirrm\" ".
  380. "instead of \"\@unexec rmdir\".");
  381. }
  382. } elsif ($_ =~ /^\@exec[ \t]+install-info\s+(.+)\s+(.+)$/) {
  383. $infoinstallseen = $.;
  384. push(@exec_info, $1);
  385. } elsif ($_ =~ /^\@unexec[ \t]+install-info[ \t]+--delete\s+(.+)\s+(.+)$/) {
  386. $inforemoveseen = $.;
  387. push(@unexec_info, $1);
  388. } elsif ($_ =~ /^\@(exec|unexec)/) {
  389. if (/ldconfig/) {
  390. if ($ldconfigwithtrue
  391. && !/\/usr\/bin\/true/) {
  392. &perror("FATAL: $file $.: ldconfig ".
  393. "must be used with ".
  394. "\"||/usr/bin/true\".");
  395. }
  396. &perror("WARN: $file $.: possible ".
  397. "direct use of ldconfig ".
  398. "in PLIST found. use ".
  399. "INSTALLS_SHLIB instead.");
  400. }
  401. } elsif ($_ =~ /^\@(comment)/) {
  402. $rcsidseen++ if (/\$$rcsidstr[:\$]/);
  403. } elsif ($_ =~ /^\@(owner|group)\s/) {
  404. &perror("WARN: \@$1 should not be needed in pkg-plist");
  405. } elsif ($_ =~ /^\@(dirrm|option)/) {
  406. ; # no check made
  407. } else {
  408. &perror("WARN: $file $.: ".
  409. "unknown pkg-plist directive \"$_\"");
  410. }
  411. next;
  412. }
  413. if ($_ =~ /^\//) {
  414. &perror("FATAL: $file $.: use of full pathname ".
  415. "disallowed.");
  416. }
  417. if ($_ =~ /\.la$/) {
  418. &perror("WARN: $file $.: installing libtool archives, ".
  419. "please use USE_LIBTOOL in Makefile if possible");
  420. }
  421. if ($_ =~ /\.so(\.\d+)?$/ && $makevar{INSTALLS_SHLIB} eq '') {
  422. &perror("WARN: $file $.: installing shared libraries, ".
  423. "please define INSTALLS_SHLIB as appropriate");
  424. }
  425. if ($_ =~ /^info\/.*info(-[0-9]+)?$/) {
  426. $infoseen = $.;
  427. $infoafterinstall++ if ($infoinstallseen);
  428. $infobeforeremove++ if (!$inforemoveseen);
  429. push(@infofile, $_);
  430. }
  431. if ($_ =~ /^info\/dir$/) {
  432. &perror("FATAL: \"info/dir\" should not be listed in ".
  433. "$file. use install-info to add/remove ".
  434. "an entry.");
  435. $infooverwrite++;
  436. }
  437. if ($_ =~ m#man/([^/]+/)?man([$manchapters])/([^\.]+\.[$manchapters])(\.gz)?$#) {
  438. if ($4 eq '') {
  439. $plistman{$2} .= ' ' . $3;
  440. if ($mancompress) {
  441. &perror("FATAL: $file $.: ".
  442. "unpacked man file $3 ".
  443. "listed. must be gzipped.");
  444. }
  445. } else {
  446. $plistmangz{$2} .= ' ' . $3;
  447. if (!$mancompress) {
  448. &perror("FATAL: $file $.: ".
  449. "gzipped man file $3$4 ".
  450. "listed. unpacked one should ".
  451. "be installed.");
  452. }
  453. }
  454. $plistmanall{$2} .= ' ' . $3;
  455. if ($1 ne '') {
  456. $manlangs{substr($1, 0, length($1) - 1)}++;
  457. }
  458. }
  459. if ($curdir !~ m#^$localbase#
  460. && $curdir !~ m#^/usr/X11R6#) {
  461. &perror("WARN: $file $.: installing to ".
  462. "directory $curdir discouraged. ".
  463. "could you please avoid it?");
  464. }
  465. if ("$curdir/$_" =~ m#^$localbase/share/doc#) {
  466. print "OK: seen installation to share/doc in $file. ".
  467. "($curdir/$_)\n" if ($verbose);
  468. $sharedocused++;
  469. }
  470. }
  471. # check that every infofile has an exec install-info and unexec install-info
  472. my $exec_install = join(" ", @exec_info);
  473. $exec_install .= ' ';
  474. my $unexec_install = join(" ", @unexec_info);
  475. $unexec_install .= ' ';
  476. foreach my $if (@infofile) {
  477. next if ($if =~ m/info-/);
  478. if ($exec_install !~ m/\%D\/\Q$if\E/) {
  479. &perror("FATAL: you need an '\@exec install-info \%D/$if \%D/info/dir' line in your pkg-plist");
  480. }
  481. if ($unexec_install !~ m/\%D\/$if/) {
  482. &perror("FATAL: you need an '\@unexec install-info --delete \%D/$if \%D/info/dir' line in your pkg-plist");
  483. }
  484. }
  485. if ($rcsidinplist && !$rcsidseen) {
  486. &perror("FATAL: RCS tag \"\$$rcsidstr\$\" must be present ".
  487. "in $file as \@comment.")
  488. }
  489. if (!$infoseen) {
  490. close(IN);
  491. return 1;
  492. }
  493. if (!$infoinstallseen) {
  494. if ($infooverwrite) {
  495. &perror("FATAL: install-info must be used to ".
  496. "add/delete entries into \"info/dir\".");
  497. }
  498. &perror("FATAL: \"\@exec install-info \%D/... \%D/info/dir\" must be placed ".
  499. "after all the info files.");
  500. } elsif ($infoafterinstall) {
  501. &perror("FATAL: move \"\@exec install-info\" line to make ".
  502. "sure that it is placed after all the info files. ".
  503. "(currently on line $infoinstallseen in $file)");
  504. }
  505. if (!$inforemoveseen) {
  506. &perror("FATAL: \"\@unexec install-info --delete \%D/... \%D/info/dir\" must ".
  507. "be placed before any of the info files listed.");
  508. } elsif ($infobeforeremove) {
  509. &perror("FATAL: move \"\@exec install-info --delete\" ".
  510. "line to make sure ".
  511. "that it is placed before any of the info files. ".
  512. "(currently on line $inforemoveseen in $file)");
  513. }
  514. close(IN);
  515. }
  516. #
  517. # misc files
  518. #
  519. sub checkpathname {
  520. my($file) = @_;
  521. my($whole);
  522. open(IN, "< $file") || return 0;
  523. $whole = '';
  524. while (<IN>) {
  525. $whole .= $_;
  526. }
  527. &abspathname($whole, $file);
  528. close(IN);
  529. }
  530. sub checklastline {
  531. my($file) = @_;
  532. my($whole);
  533. open(IN, "< $file") || return 0;
  534. $whole = '';
  535. while (<IN>) {
  536. $whole .= $_;
  537. }
  538. if ($whole !~ /\n$/) {
  539. &perror("FATAL: the last line of $file has to be ".
  540. "terminated by \\n.");
  541. }
  542. if ($whole =~ /\n([ \t]*\n)+$/) {
  543. &perror("WARN: $file seems to have unnecessary blank lines ".
  544. "at the last part.");
  545. }
  546. close(IN);
  547. }
  548. sub checkpatch {
  549. my($file) = @_;
  550. my($whole);
  551. if (-z "$file") {
  552. &perror("FATAL: $file has no content. should be removed ".
  553. "from repository.");
  554. return;
  555. }
  556. open(IN, "< $file") || return 0;
  557. $whole = '';
  558. while (<IN>) {
  559. $whole .= $_;
  560. }
  561. if ($committer && $whole =~ /\$([A-Za-z0-9]+)[:\$]/) {
  562. &perror("WARN: $file includes possible RCS tag \"\$$1\$\". ".
  563. "use binary mode (-ko) on commit/import.") unless
  564. $1 eq $rcsidstr;
  565. }
  566. close(IN);
  567. }
  568. #
  569. # Makefile
  570. #
  571. sub checkmakefile {
  572. my($file) = @_;
  573. my($rawwhole, $whole, $idx, @sections);
  574. my($i, $j, $k, $l);
  575. my @cat = ();
  576. my $has_lang_cat = 0;
  577. my $lang_pref = '';
  578. my $tmp;
  579. my $bogusdistfiles = 0;
  580. my @varnames = ();
  581. my($portname, $portversion, $distfiles, $distname, $extractsufx) = ('', '', '', '', '');
  582. my $masterport = 0;
  583. my $slaveport = 0;
  584. my($realwrksrc, $wrksrc, $nowrksubdir) = ('', '', '');
  585. my(@mman, @pman);
  586. open(IN, "< $file") || return 0;
  587. $rawwhole = '';
  588. $tmp = 0;
  589. while (<IN>) {
  590. if ($_ =~ /[ \t]+\n?$/) {
  591. &perror("WARN: $file $.: whitespace before ".
  592. "end of line.");
  593. }
  594. if ($_ =~ /^ /) { # 8 spaces here!
  595. &perror("WARN: $file $.: use tab (not space) to make ".
  596. "indentation");
  597. }
  598. if ($usetabs) {
  599. if (m/^[A-Za-z0-9_-]+.?= /) {
  600. if (m/[?+]=/) {
  601. &perror("WARN: $file $.: use a tab (not space) after a ".
  602. "variable name");
  603. } else {
  604. &perror("FATAL: $file $.: use a tab (not space) after a ".
  605. "variable name");
  606. }
  607. }
  608. }
  609. #
  610. # I'm still not very convinced, for using this kind of magical word.
  611. # 1. This kind of items are not important for Makefile;
  612. # portlint should not require any additional rule to Makefile.
  613. # portlint should simply implement items that are declared in Handbook.
  614. # 2. If we have LINTSKIP, we can't stop people using LINTSKIP too much.
  615. # IMHO it is better to warn the user and let the user think twice,
  616. # than let the user escape from portlint.
  617. # Uncomment this part if you are willing to use these magical words.
  618. # Thu Jun 26 11:37:56 JST 1997
  619. # -- itojun
  620. #
  621. # if ($_ =~ /^# LINTSKIP\n?$/) {
  622. # print "OK: skipping from line $. in $file.\n"
  623. # if ($verbose);
  624. # $tmp = 1;
  625. # next;
  626. # }
  627. # if ($_ =~ /^# LINTAGAIN\n?$/) {
  628. # print "OK: check start again from line $. in $file.\n"
  629. # if ($verbose);
  630. # $tmp = 0;
  631. # next;
  632. # }
  633. # if ($_ =~ /# LINTIGNORE/) {
  634. # print "OK: ignoring line $. in $file.\n" if ($verbose);
  635. # next;
  636. # }
  637. # next if ($tmp);
  638. $rawwhole .= $_;
  639. }
  640. close(IN);
  641. #
  642. # whole file: blank lines.
  643. #
  644. $whole = "\n" . $rawwhole;
  645. print "OK: checking contiguous blank lines in $file.\n"
  646. if ($verbose);
  647. $i = "\n" x ($contblank + 2);
  648. if ($whole =~ /$i/) {
  649. my @linesbefore = split(/\n/, $`);
  650. &perror("FATAL: contiguous blank lines (> $contblank lines) found ".
  651. "in $file at line " . ($#linesbefore + 1) . ".");
  652. }
  653. #
  654. # whole file: $(VARIABLE)
  655. #
  656. if ($parenwarn) {
  657. print "OK: checking for \$(VARIABLE).\n" if ($verbose);
  658. if ($whole =~ /\$\([\w\d]+\)/) {
  659. &perror("WARN: use \${VARIABLE}, instead of ".
  660. "\$(VARIABLE).");
  661. }
  662. }
  663. #
  664. # whole file: NO_CHECKSUM
  665. #
  666. $whole =~ s/\n#[^\n]*/\n/g;
  667. $whole =~ s/\n\n+/\n/g;
  668. print "OK: checking NO_CHECKSUM.\n" if ($verbose);
  669. if ($whole =~ /\nNO_CHECKSUM/) {
  670. &perror("FATAL: use of NO_CHECKSUM discouraged. ".
  671. "it is intended to be a user variable.");
  672. }
  673. #
  674. # whole file: PKGNAME
  675. #
  676. print "OK: checking PKGNAME.\n" if ($verbose);
  677. if ($whole =~ /\nPKGNAME.?=/) {
  678. &perror("FATAL: PKGNAME is obsoleted by PORTNAME, ".
  679. "PORTVERSION, PKGNAMEPREFIX and PKGNAMESUFFIX.");
  680. }
  681. #
  682. # whole file: IS_INTERACTIVE/NOPORTDOCS
  683. #
  684. print "OK: checking IS_INTERACTIVE.\n" if ($verbose);
  685. if ($whole =~ /\nIS_INTERACTIVE/) {
  686. if ($whole !~ /defined\((BATCH|FOR_CDROM)\)/) {
  687. &perror("WARN: use of IS_INTERACTIVE discouraged. ".
  688. "provide batch mode by using BATCH and/or ".
  689. "FOR_CDROM.");
  690. }
  691. }
  692. print "OK: checking for use of NOPORTDOCS.\n" if ($verbose);
  693. if ($sharedocused && $whole !~ /defined\(NOPORTDOCS\)/
  694. && $whole !~ m#(\$[\{\(]PREFIX[\}\)]|$localbase)/share/doc#) {
  695. &perror("WARN: use \".if !defined(NOPORTDOCS)\" to wrap ".
  696. "installation of files into $localbase/share/doc.");
  697. }
  698. #
  699. # whole file: direct use of command names
  700. #
  701. my %cmdnames = ();
  702. print "OK: checking direct use of command names.\n" if ($verbose);
  703. foreach my $i (qw(
  704. awk basename cat chmod chown cp echo expr false gmake grep gzcat
  705. ldconfig ln md5 mkdir mv patch rm rmdir sed sh touch tr which xmkmf
  706. )) {
  707. $cmdnames{$i} = "\$\{\U$i\E\}";
  708. }
  709. $cmdnames{'env'} = '${SETENV}';
  710. $cmdnames{'gunzip'} = '${GUNZIP_CMD}';
  711. $cmdnames{'gzip'} = '${GZIP_CMD}';
  712. $cmdnames{'install'} = '${INSTALL_foobaa}';
  713. #
  714. # ignore parameter string to echo command.
  715. # note that we leave the command as is, since we need to check the
  716. # use of echo itself.
  717. $j = $whole;
  718. $j =~ s/([ \t][\@-]?)(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+("(\\'|\\"|[^"])*"|'(\\'|\\"|[^'])*')[ \t]*[;\n]/$1$2;/; #"
  719. foreach my $i (keys %cmdnames) {
  720. if ($j =~ /[ \t\/]$i[ \t\n;]/
  721. && $j !~ /\n[A-Z]+_TARGET[?+]?=[^\n]+$i/) {
  722. &perror("WARN: possible direct use of command \"$i\" ".
  723. "found. use $cmdnames{$i} instead.");
  724. }
  725. }
  726. #
  727. # whole file: ldconfig must come with "true" command
  728. #
  729. if ($ldconfigwithtrue
  730. && $j =~ /(ldconfig|\$[{(]LDCONFIG[)}])/
  731. && $j !~ /(\/usr\/bin\/true|\$[{(]TRUE[)}])/) {
  732. &perror("FATAL: ldconfig must be used with \"||\${TRUE}\".");
  733. }
  734. #
  735. # whole file: ${GZIP_CMD} -9 (or any other number)
  736. #
  737. if ($j =~ /\${GZIP_CMD}\s+-(\w+(\s+-)?)*(\d)/) {
  738. &perror("WARN: possible use of \"\${GZIP_CMD} -$3\" ".
  739. "found. \${GZIP_CMD} includes \"-\${GZIP}\" which ".
  740. "sets the compression level.");
  741. }
  742. #
  743. # whole file: ${MKDIR} -p
  744. #
  745. if ($j =~ /\${MKDIR}\s+-p/) {
  746. &perror("WARN: possible use of \"\${MKDIR} -p\" ".
  747. "found. \${MKDIR} includes \"-p\" by default.");
  748. }
  749. #
  750. # whole file: full path name
  751. #
  752. &abspathname($whole, $file);
  753. #
  754. # slave port check
  755. #
  756. my $masterdir = $makevar{MASTERDIR};
  757. if ($masterdir ne '' && $masterdir ne $makevar{'.CURDIR'}) {
  758. $slaveport = 1;
  759. print "OK: checking master port in $masterdir.\n" if ($verbose);
  760. if (! -e "$masterdir/Makefile") {
  761. &perror("WARN: unable to locate master port in $masterdir");
  762. }
  763. }
  764. #
  765. # break the makefile into sections.
  766. #
  767. $tmp = $rawwhole;
  768. # keep comment, blank line, comment in the same section
  769. $tmp =~ s/(#.*\n)\n+(#.*)/$1$2/g;
  770. @sections = split(/\n\n+/, $tmp);
  771. for ($i = 0; $i <= $#sections; $i++) {
  772. if ($sections[$i] !~ /\n$/) {
  773. $sections[$i] .= "\n";
  774. }
  775. }
  776. $idx = 0;
  777. #
  778. # section 1: comment lines.
  779. #
  780. print "OK: checking comment section of $file.\n" if ($verbose);
  781. my @linestocheck = split("\n", <<EOF);
  782. Whom
  783. Date [cC]reated
  784. EOF
  785. if ($osname eq 'NetBSD') {
  786. unshift(@linestocheck, '(New )?[pP](ackage|ort)s [cC]ollection [mM]akefile [fF]or');
  787. } else {
  788. unshift(@linestocheck, '(New )?[pP]orts [cC]ollection [mM]akefile [fF]or');
  789. }
  790. $tmp = $sections[$idx++];
  791. $tmp = "\n" . $tmp; # to make the begin-of-line check easier
  792. if ($tmp =~ /\n[^#]/) {
  793. &perror("FATAL: non-comment line in comment section of $file.");
  794. }
  795. foreach my $i (@linestocheck) {
  796. $j = $i;
  797. $j =~ s/\(.*\)\?//g;
  798. $j =~ s/\[(.)[^\]]*\]/$1/g;
  799. if ($tmp !~ /# $i:[ \t]+\S+/) {
  800. &perror("FATAL: no \"$j\" line in comment section of $file.");
  801. } else {
  802. print "OK: \"$j\" seen in $file.\n" if ($verbose);
  803. }
  804. }
  805. if ($tmp =~ m/Version [rR]equired/) {
  806. &perror("WARN: Version required is no longer needed in the comment section of $file.");
  807. }
  808. my $tmp2 = "";
  809. for (split(/\n/, $tmp)) {
  810. $tmp2 .= $_ if (m/\$$rcsidstr/);
  811. }
  812. if ($tmp2 !~ /#(\s+)\$$rcsidstr([^\$]*)\$$/) {
  813. &perror("FATAL: no \$$rcsidstr\$ line in $file comment ".
  814. "section.");
  815. } else {
  816. print "OK: \$$rcsidstr\$ seen in $file.\n" if ($verbose);
  817. if ($1 ne ' ') {
  818. &perror("WARN: please use single whitespace ".
  819. "right before \$$rcsidstr\$ tag.");
  820. }
  821. if ($2 ne '') {
  822. if ($verbose || $newport) { # XXX
  823. &perror("WARN: ".
  824. ($newport ? 'for new port, '
  825. : 'is it a new port? if so, ').
  826. "make \$$rcsidstr\$ tag in comment ".
  827. "section empty, to make CVS happy.");
  828. }
  829. }
  830. }
  831. #
  832. # for the rest of the checks, comment lines are not important.
  833. #
  834. for ($i = 0; $i < scalar(@sections); $i++) {
  835. $sections[$i] = "\n" . $sections[$i];
  836. $sections[$i] =~ s/\n#[^\n]*//g;
  837. $sections[$i] =~ s/\n\n+/\n/g;
  838. $sections[$i] =~ s/\\\n/ /g;
  839. $sections[$i] =~ s/^\n//;
  840. }
  841. #
  842. #
  843. # section 2: PORTNAME/PORTVERSION/...
  844. #
  845. print "OK: checking first section of $file (PORTNAME/...).\n"
  846. if ($verbose);
  847. $tmp = $sections[$idx++];
  848. # check the order of items.
  849. &checkorder('PORTNAME', $tmp, qw(
  850. PORTNAME PORTVERSION PORTREVISION PORTEPOCH CATEGORIES MASTER_SITES
  851. MASTER_SITE_SUBDIR PKGNAMEPREFIX PKGNAMESUFFIX DISTNAME EXTRACT_SUFX
  852. DISTFILES DIST_SUBDIR EXTRACT_ONLY
  853. ));
  854. # check the items that has to be there.
  855. $tmp = "\n" . $tmp;
  856. print "OK: checking PORTNAME/PORTVERSION.\n" if ($verbose);
  857. if ($tmp !~ /\nPORTNAME(.)?=/) {
  858. &perror("FATAL: PORTNAME has to be there.") unless ($slaveport && $makevar{PORTNAME} ne '');
  859. } elsif ($1 ne '') {
  860. &perror("WARN: unless this is a master port, PORTNAME has to be set by \"=\", ".
  861. "not by \"$1=\".") unless ($masterport);
  862. }
  863. if ($tmp !~ /\nPORTVERSION(.)?=/) {
  864. &perror("FATAL: PORTVERSION has to be there.") unless ($slaveport && $makevar{PORTVERSION} ne '');
  865. } elsif ($1 ne '') {
  866. &perror("WARN: unless this is a master port, PORTVERSION has to be set by \"=\", ".
  867. "not by \"$1=\".") unless ($masterport);
  868. }
  869. print "OK: checking CATEGORIES.\n" if ($verbose);
  870. if ($tmp !~ /\nCATEGORIES(.)?=/) {
  871. &perror("FATAL: CATEGORIES has to be there.") unless ($slaveport && $makevar{CATEGORIES} ne '');
  872. } elsif (($i = $1) ne '' && $i =~ /[^?+]/) {
  873. &perror("WARN: unless this is a master port, CATEGORIES should be set by \"=\", \"?=\", or \"+=\", ".
  874. "not by \"$i=\".") unless ($masterport);
  875. }
  876. @cat = split(/\s+/, $makevar{CATEGORIES});
  877. if (@cat == 0) {
  878. &perror("FATAL: CATEGORIES left blank. set it to \"misc\"".
  879. " if nothing seems apropriate.");
  880. }
  881. #MICHAEL: can these three lang cat checks be combined?
  882. # skip the first category specification if it's a language specific one.
  883. if (grep($_ eq $cat[0], @lang_cat)) {
  884. $has_lang_cat = 1;
  885. $lang_pref = $lang_pref{$cat[0]};
  886. shift @cat;
  887. }
  888. # skip further if more language specific ones follow.
  889. if (@cat && grep($_ eq $cat[0], @lang_cat)) {
  890. &perror("WARN: multiple language specific categories detected. ".
  891. "are you sure?");
  892. do {
  893. shift @cat;
  894. } while (@cat && grep($_ eq $cat[0], @lang_cat));
  895. }
  896. # check x11 in CATEGORIES
  897. if ($newxdef) {
  898. #MICHAEL: I don't understand this line
  899. if (2 <= @cat && $cat[1] eq "x11") {
  900. &perror("WARN: only specific kind of apps should ".
  901. "specify \"x11\" in CATEGORIES. ".
  902. "Do you mean just USE_XLIB? ".
  903. "Then remove \"x11\" from CATEGORIES.");
  904. }
  905. }
  906. if (2 <= @cat) {
  907. # skip the first one that we know is _not_ language specific.
  908. shift @cat;
  909. # any language specific one after non language specific ones?
  910. my $cat;
  911. if (grep(do { $cat = $_; grep($_ eq $cat, @cat) }, @lang_cat)) {
  912. $has_lang_cat = 1;
  913. $lang_pref = $lang_pref{$cat};
  914. &perror("WARN: when you specify multiple categories, ".
  915. "language specific category should come first.");
  916. }
  917. }
  918. # check the URL
  919. if (($tmp =~ /\nMASTER_SITES[+?]?=[ \t]*([^\n]*)\n/
  920. && $1 !~ /^[ \t]*$/) || ($makevar{MASTER_SITES} ne '')) {
  921. print "OK: seen MASTER_SITES, sanity checking URLs.\n"
  922. if ($verbose);
  923. my @sites = split(/\s+/, $1);
  924. foreach my $i (@sites) {
  925. if ($i =~ m#^\w+://#) {
  926. &urlcheck($i);
  927. unless (&is_predefined($i)) {
  928. print "OK: URL \"$i\" ok.\n"
  929. if ($verbose);
  930. }
  931. } else {
  932. print "OK: non-URL \"$i\" ok.\n"
  933. if ($verbose);
  934. }
  935. }
  936. } else {
  937. &perror("WARN: no MASTER_SITES found. is it ok?");
  938. }
  939. # check DISTFILES and related items.
  940. $distfiles = $1 if ($tmp =~ /\nDISTFILES[+?]?=[ \t]*([^\n]+)\n/);
  941. #$portname = $1 if ($tmp =~ /\nPORTNAME[+?]?=[ \t]*([^\n]+)\n/);
  942. #$portversion = $1 if ($tmp =~ /\nPORTVERSION[+?]?=[ \t]*([^\n]+)\n/);
  943. $portname = $makevar{PORTNAME};
  944. $portversion = $makevar{PORTVERSION};
  945. $distname = $1 if ($tmp =~ /\nDISTNAME[+?]?=[ \t]*([^\n]+)\n/);
  946. $extractsufx = $1 if ($tmp =~ /\nEXTRACT_SUFX[+?]?=[ \t]*([^\n]+)\n/);
  947. # check bogus EXTRACT_SUFX.
  948. if ($extractsufx ne '') {
  949. print "OK: seen EXTRACT_SUFX, checking value.\n" if ($verbose);
  950. if ($distfiles ne '') {
  951. &perror("WARN: no need to define EXTRACT_SUFX if ".
  952. "DISTFILES is defined.");
  953. }
  954. if ($extractsufx eq '.tar.gz') {
  955. &perror("WARN: EXTRACT_SUFX is \".tar.gz.\" ".
  956. "by default. you don't need to specify it.");
  957. }
  958. } else {
  959. print "OK: no EXTRACT_SUFX seen, using default value.\n"
  960. if ($verbose);
  961. $extractsufx = '.tar.gz';
  962. }
  963. print "OK: sanity checking PORTNAME/PORTVERSION.\n" if ($verbose);
  964. if ($distname ne '' && $distname eq "$portname-$portversion") {
  965. &perror("WARN: DISTNAME is \${PORTNAME}-\${PORTVERSION} by default, ".
  966. "you don't need to define DISTNAME.");
  967. }
  968. if ($portname =~ /^$re_lang_pref/) {
  969. &perror("FATAL: language prefix is automatically".
  970. " set by PKGNAMEPREFIX.".
  971. " you must remove it from PORTNAME.");
  972. }
  973. if ($portname =~ /\$[\{\(].+[\}\)]/) {
  974. &perror("WARN: using variable in PORTNAME.".
  975. " consider using PKGNAMEPREFIX and/or PKGNAMESUFFIX.");
  976. } elsif ($portname =~ /-/ && $distname ne '') {
  977. &perror("WARN: using hyphen in PORTNAME.".
  978. " consider using PKGNAMEPREFIX and/or PKGNAMESUFFIX.");
  979. }
  980. if ($portversion eq '') {
  981. &perror("FATAL: PORTVERSION must be specified");
  982. }
  983. if ($portversion =~ /^pl[0-9]*$/
  984. || $portversion =~ /^[0-9]*[A-Za-z]?[0-9]*(\.[0-9]*[A-Za-z]?[0-9]*)*$/) {
  985. print "OK: PORTVERSION \"$portversion\" looks fine.\n" if ($verbose);
  986. } elsif ($portversion =~ /^[^\-]*\$[{\(].+[\)}][^\-]*$/) {
  987. &perror("WARN: using variable, \"$portversion\", as version number");
  988. } elsif ($portversion =~ /-/) {
  989. &perror("FATAL: PORTVERSION should not contain a hyphen.".
  990. "should modify \"$portversion\".");
  991. } else {
  992. &perror("FATAL: PORTVERSION looks illegal. ".
  993. "should modify \"$portversion\".");
  994. }
  995. # if DISTFILES have only single item, it is better to avoid DISTFILES
  996. # and to use combination of DISTNAME and EXTRACT_SUFX.
  997. # example:
  998. # DISTFILES=package-1.0.tgz
  999. # should be
  1000. # DISTNAME= package-1.0
  1001. # EXTRACT_SUFX= .tgz
  1002. if ($distfiles =~ /^\S+$/) {
  1003. $bogusdistfiles++;
  1004. print "OK: seen DISTFILES with single item, checking value.\n"
  1005. if ($verbose);
  1006. &perror("WARN: use of DISTFILES with single file ".
  1007. "discouraged. distribution filename should be set by ".
  1008. "DISTNAME and EXTRACT_SUFX.");
  1009. if ($distfiles eq (($distname ne '') ? $distname : "$portname-$portversion") . $extractsufx) {
  1010. &perror("WARN: definition of DISTFILES not necessary. ".
  1011. "DISTFILES is \${DISTNAME}/\${EXTRACT_SUFX} ".
  1012. "by default.");
  1013. }
  1014. # display advice only in certain cases.
  1015. #MICHAEL: will this work with multiple distfiles in this list? what about
  1016. # doing the same sort of thing for DISTNAME, is it needed?
  1017. if ($distfiles =~ /^\Q$i\E([\-.].+)$/) {
  1018. &perror("WARN: how about \"EXTRACT_SUFX=$1\"".
  1019. ", instead of DISTFILES?");
  1020. }
  1021. }
  1022. # additional checks for committer.
  1023. if ($committer && $has_lang_cat) {
  1024. &perror("WARN: be sure to include language code \"$lang_pref-\" ".
  1025. "in the module alias name.");
  1026. }
  1027. if ($committer) {
  1028. if (opendir(DIR, ".")) {
  1029. my @tgz = grep(/\.tgz$/, readdir(DIR));
  1030. closedir(DIR);
  1031. if (@tgz) {
  1032. my $tgz = (2 <= @tgz)
  1033. ? '{' . join(',', @tgz) . '}'
  1034. : $tgz[0];
  1035. &perror("WARN: be sure to remove $portdir/$tgz ".
  1036. "before committing the port.");
  1037. }
  1038. }
  1039. }
  1040. push(@varnames, qw(
  1041. PORTNAME PORTVERSION PORTREVISION PORTEPOCH CATEGORIES MASTER_SITES
  1042. MASTER_SITE_SUBDIR PKGNAMEPREFIX PKGNAMESUFFIX DISTNAME EXTRACT_SUFX
  1043. DISTFILES EXTRACT_ONLY
  1044. ));
  1045. #
  1046. # section 3: PATCH_SITES/PATCHFILES(optional)
  1047. #
  1048. print "OK: checking second section of $file (PATCH*: optional).\n"
  1049. if ($verbose);
  1050. $tmp = $sections[$idx];
  1051. if ($tmp =~ /(PATCH_SITES|PATCH_SITE_SUBDIR|PATCHFILES|PATCH_DIST_STRIP)/) {
  1052. &checkearlier($file, $tmp, @varnames);
  1053. if ($tmp =~ /^PATCH_SITES=/) {
  1054. print "OK: seen PATCH_SITES.\n" if ($verbose);
  1055. $tmp =~ s/^[^\n]+\n//;
  1056. }
  1057. if ($tmp =~ /^PATCH_SITE_SUBDIR=/) {
  1058. print "OK: seen PATCH_SITE_SUBDIR.\n" if ($verbose);
  1059. $tmp =~ s/^[^\n]+\n//;
  1060. }
  1061. if ($tmp =~ /^PATCHFILES=/) {
  1062. print "OK: seen PATCHFILES.\n" if ($verbose);
  1063. $tmp =~ s/^[^\n]+\n//;
  1064. }
  1065. if ($tmp =~ /^PATCH_DIST_STRIP=/) {
  1066. print "OK: seen PATCH_DIST_STRIP.\n" if ($verbose);
  1067. $tmp =~ s/^[^\n]+\n//;
  1068. }
  1069. &checkextra($tmp, 'PATCH_SITES');
  1070. $idx++;
  1071. }
  1072. push(@varnames, qw(
  1073. PATCH_SITES PATCHFILES PATCH_DIST_STRIP
  1074. ));
  1075. #
  1076. # section 4: MAINTAINER
  1077. #
  1078. print "OK: checking third section of $file (MAINTAINER).\n"
  1079. if ($verbose);
  1080. $tmp = $sections[$idx++];
  1081. &checkearlier($file, $tmp, @varnames);
  1082. &checkorder('MAINTAINER', $tmp, qw(
  1083. MAINTAINER COMMENT
  1084. ));
  1085. $tmp = "\n" . $tmp;
  1086. if ($tmp =~ /\nMAINTAINER\??=([^\n]+)/) {
  1087. my $addr = $1;
  1088. $addr =~ s/^\s*//;
  1089. $addr =~ s/\s*$//;
  1090. if ($addr =~ /[\s,<>()]/) {
  1091. &perror("FATAL: MAINTAINER should be a single address without comment.");
  1092. }
  1093. $tmp =~ s/\nMAINTAINER\??=[^\n]+//;
  1094. } elsif ($whole !~ /\nMAINTAINER[?]?=/) {
  1095. &perror("FATAL: no MAINTAINER listed in $file.") unless ($slaveport && $makevar{MAINTAINER} ne '');
  1096. }
  1097. $tmp =~ s/\n\n+/\n/g;
  1098. # check COMMENT
  1099. if ($tmp !~ /\nCOMMENT(.)?=/) {
  1100. &perror("FATAL: COMMENT has to be there.") unless ($slaveport && $makevar{COMMENT} ne '');
  1101. } elsif ($1 ne '') {
  1102. &perror("WARN: unless this is a master port, COMMENT has to be set by \"=\", ".
  1103. "not by \"$1=\".") unless ($masterport);
  1104. } else { # check for correctness
  1105. if (($makevar{COMMENT} !~ /^["0-9A-Z]/) || ($makevar{COMMENT} =~ m/\.$/)) { #"
  1106. &perror("WARN: COMMENT should begin with a capital, and end without a period");
  1107. } elsif (length($makevar{COMMENT}) > 70) {
  1108. &perror("WARN: COMMENT exceeds 70 characters limit.");
  1109. }
  1110. }
  1111. push(@varnames, qw(
  1112. MAINTAINER COMMENT
  1113. ));
  1114. #
  1115. # section 5: *_DEPENDS (may not be there)
  1116. #
  1117. print "OK: checking fourth section of $file (*_DEPENDS).\n"
  1118. if ($verbose);
  1119. $tmp = $sections[$idx];
  1120. # NOTE: EXEC_DEPENDS is obsolete, so it should not be listed.
  1121. @linestocheck = qw(
  1122. LIB_DEPENDS BUILD_DEPENDS RUN_DEPENDS FETCH_DEPENDS DEPENDS DEPENDS_TARGET
  1123. );
  1124. if ($tmp =~ /(LIB_|BUILD_|RUN_|FETCH_)?DEPENDS/) {
  1125. &checkearlier($file, $tmp, @varnames);
  1126. my %seen_depends;
  1127. if (!defined $ENV{'PORTSDIR'}) {
  1128. $ENV{'PORTSDIR'} = $portsdir;
  1129. }
  1130. foreach my $i (grep(/^[A-Z_]*DEPENDS[?+]?=/, split(/\n/, $tmp))) {
  1131. $i =~ s/^([A-Z_]*DEPENDS)[?+]?=[ \t]*//;
  1132. $j = $1;
  1133. $seen_depends{$j}++;
  1134. if ($j ne 'DEPENDS' &&
  1135. $i =~ /^\${([A-Z_]+DEPENDS)}\s*$/ &&
  1136. $seen_depends{$1} &&
  1137. $j ne $1)
  1138. {
  1139. print "OK: $j refers to $1, skipping checks.\n"
  1140. if ($verbose);
  1141. next;
  1142. }
  1143. print "OK: checking ports listed in $j.\n"
  1144. if ($verbose);
  1145. foreach my $k (split(/\s+/, $i)) {
  1146. my @l = split(':', $k);
  1147. print "OK: checking dependency value for $j.\n"
  1148. if ($verbose);
  1149. if (($j eq 'DEPENDS'
  1150. && scalar(@l) != 1 && scalar(@l) != 2)
  1151. || ($j ne 'DEPENDS'
  1152. && scalar(@l) != 2 && scalar(@l) != 3)) {
  1153. &perror("WARN: wrong dependency value ".
  1154. "for $j. $j requires ".
  1155. ($j eq 'DEPENDS'
  1156. ? "1 or 2 "
  1157. : "2 or 3 ").
  1158. "colon-separated tuples.");
  1159. next;
  1160. }
  1161. my %m = ();
  1162. if ($j eq 'DEPENDS') {
  1163. $m{'dir'} = $l[0];
  1164. $m{'tgt'} = $l[1];
  1165. } else {
  1166. $m{'dep'} = $l[0];
  1167. $m{'dir'} = $l[1];
  1168. $m{'tgt'} = $l[2];
  1169. }
  1170. print "OK: dep=\"$m{'dep'}\", ".
  1171. "dir=\"$m{'dir'}\", tgt=\"$m{'tgt'}\"\n"
  1172. if ($verbose);
  1173. # check USE_PERL5
  1174. if ($m{'dep'} =~ /^perl5(\.\d+)?$/) {
  1175. &perror("WARN: dependency to perl5 ".
  1176. "listed in $j. consider using ".
  1177. "USE_PERL5.");
  1178. }
  1179. # check USE_GMAKE
  1180. if ($m{'dep'} =~ /^(gmake|\${GMAKE})$/) {
  1181. &perror("WARN: dependency to $1 ".
  1182. "listed in $j. consider using ".
  1183. "USE_GMAKE.");
  1184. }
  1185. # check USE_QT
  1186. if ($m{'dep'} =~ /^(qt\d)+$/) {
  1187. &perror("WARN: dependency to $1 ".
  1188. "listed in $j. consider using ".
  1189. "USE_QT.");
  1190. }
  1191. # check backslash in LIB_DEPENDS
  1192. if ($osname eq 'NetBSD' && $j eq 'LIB_DEPENDS'
  1193. && $m{'dep'} =~ /\\\\./) {
  1194. &perror("WARN: use of backslashes in ".
  1195. "$j is deprecated.");
  1196. }
  1197. # check for PREFIX
  1198. if ($m{'dep'} =~ /\${PREFIX}/) {
  1199. &perror("FATAL: \${PREFIX} must not be ".
  1200. "contained in *_DEPENDS. ".
  1201. "use \${LOCALBASE} or ".
  1202. "\${X11BASE} instead.");
  1203. }
  1204. # check port dir existence
  1205. $k = $m{'dir'};
  1206. $k =~ s/\${PORTSDIR}/$ENV{'PORTSDIR'}/;
  1207. $k =~ s/\$[\({]PORTSDIR[\)}]/$ENV{'PORTSDIR'}/;
  1208. if (! -d $k) {
  1209. &perror("WARN: no port directory $k ".
  1210. "found, even though it is ".
  1211. "listed in $j.");
  1212. } else {
  1213. print "OK: port directory $k found.\n"
  1214. if ($verbose);
  1215. }
  1216. }
  1217. }
  1218. foreach my $i (@linestocheck) {
  1219. $tmp =~ s/$i[?+]?=[^\n]+\n//g;
  1220. }
  1221. &checkextra($tmp, '*_DEPENDS');
  1222. $idx++;
  1223. }
  1224. push(@varnames, @linestocheck);
  1225. &checkearlier($file, $tmp, @varnames);
  1226. #
  1227. # Makefile 6: check the rest of file
  1228. #
  1229. print "OK: checking the rest of the $file.\n" if ($verbose);
  1230. $tmp = join("\n\n", @sections[$idx .. scalar(@sections)-1]);
  1231. $tmp = "\n" . $tmp; # to make the begin-of-line check easier
  1232. &checkearlier($file, $tmp, @varnames);
  1233. # check WRKSRC/NO_WRKSUBDIR
  1234. #
  1235. # do not use DISTFILES/DISTNAME to control over WRKSRC.
  1236. # DISTNAME is for controlling distribution filename.
  1237. # example:
  1238. # DISTNAME= package
  1239. # DISTFILES=package-1.0.tgz
  1240. # should be
  1241. # DISTNAME= package-1.0
  1242. # EXTRACT_SUFX=.tgz
  1243. # WRKSRC= ${WRKDIR}/package
  1244. #
  1245. print "OK: checking WRKSRC.\n" if ($verbose);
  1246. $wrksrc = $nowrksubdir = '';
  1247. $wrksrc = $1 if ($tmp =~ /\nWRKSRC[+?]?=[ \t]*([^\n]*)\n/);
  1248. $nowrksubdir = $1 if ($tmp =~ /\nNO_WRKSUBDIR[+?]?=[ \t]*([^\n]*)\n/);
  1249. if ($nowrksubdir eq '') {
  1250. $realwrksrc = $wrksrc ? "$wrksrc/$distname"
  1251. : "\${WRKDIR}/$distname";
  1252. } else {
  1253. $realwrksrc = $wrksrc ? $wrksrc : '${WRKDIR}';
  1254. }
  1255. print "OK: WRKSRC seems to be $realwrksrc.\n" if ($verbose);
  1256. if ($nowrksubdir eq '') {
  1257. print "OK: no NO_WRKSUBDIR, checking value of WRKSRC.\n"
  1258. if ($verbose);
  1259. if ($wrksrc eq 'work' || $wrksrc =~ /^$[\{\(]WRKDIR[\}\)]/) {
  1260. &perror("WARN: WRKSRC is set to meaningless value ".
  1261. "\"$1\".".
  1262. ($nowrksubdir eq ''
  1263. ? " use \"NO_WRKSUBDIR=yes\" instead."
  1264. : ""));
  1265. }
  1266. if ($bogusdistfiles) {
  1267. if ($distname ne '' && $wrksrc eq '') {
  1268. &perror("WARN: do not use DISTFILES and DISTNAME ".
  1269. "to control WRKSRC. how about ".
  1270. "\"WRKSRC=\${WRKDIR}/$distname\"?");
  1271. } else {
  1272. &perror("WARN: DISTFILES/DISTNAME affects WRKSRC. ".
  1273. "take caution when changing them.");
  1274. }
  1275. }
  1276. } else {
  1277. print "OK: seen NO_WRKSUBDIR, checking value of WRKSRC.\n"
  1278. if ($verbose);
  1279. if ($wrksrc eq 'work' || $wrksrc =~ /^$[\{\(]WRKDIR[\}\)]/) {
  1280. &perror("WARN: definition of WRKSRC not necessary. ".
  1281. "WRKSRC is \${WRKDIR} by default.");
  1282. }
  1283. }
  1284. # check RESTRICTED/NO_CDROM/NO_PACKAGE
  1285. print "OK: checking RESTRICTED/NO_CDROM/NO_PACKAGE.\n" if ($verbose);
  1286. if ($committer && $tmp =~ /\n(RESTRICTED|NO_CDROM|NO_PACKAGE)[+?]?=/) {
  1287. &perror("WARN: \"$1\" found. do not forget to update ".
  1288. "ports/LEGAL.");
  1289. }
  1290. # check NO_CONFIGURE/NO_PATCH
  1291. print "OK: checking NO_CONFIGURE/NO_PATCH.\n" if ($verbose);
  1292. if ($tmp =~ /\n(NO_CONFIGURE|NO_PATCH)[+?]?=/) {
  1293. &perror("FATAL: \"$1\" was obsoleted. remove this.");
  1294. }
  1295. # check MAN[1-9LN]
  1296. print "OK: checking MAN[0-9LN].\n" if ($verbose);
  1297. foreach my $i (keys %plistmanall) {
  1298. print "OK: pkg-plist MAN$i=$plistmanall{$i}\n" if ($verbose);
  1299. }
  1300. foreach my $i (split(//, $manchapters)) {
  1301. if ($tmp =~ /MAN\U$i\E=\s*([^\n]*)\n/) {
  1302. print "OK: Makefile MAN$i=$1\n" if ($verbose);
  1303. }
  1304. }
  1305. foreach my $i (split(//, $manchapters)) {
  1306. next if ($i eq '');
  1307. if ($tmp =~ /MAN\U$i\E=\s*([^\n]*)\n/) {
  1308. @mman = grep($_ !~ /^\s*$/, split(/\s+/, $1));
  1309. @pman = grep($_ !~ /^\s*$/,
  1310. split(/\s+/, $plistmanall{$i}));
  1311. foreach my $j (@mman) {
  1312. print "OK: checking $j (Makefile)\n"
  1313. if ($verbose);
  1314. if ($automan && grep($_ eq $j, @pman)) {
  1315. &perror("FATAL: duplicated manpage ".
  1316. "entry $j: content of ".
  1317. "MAN$i will be automatically ".
  1318. "added to pkg-plist.");
  1319. } elsif (!$automan && !grep($_ eq $j, @pman)) {
  1320. &perror("WARN: manpage $j in $file ".
  1321. "MAN$i but not in pkg-plist.");
  1322. }
  1323. }
  1324. foreach my $j (@pman) {
  1325. print "OK: checking $j (pkg-plist)\n" if ($verbose);
  1326. if (!grep($_ eq $j, @mman)) {
  1327. &perror("WARN: manpage $j in pkg-plist ".
  1328. "but not in $file MAN$i.");
  1329. }
  1330. }
  1331. } else {
  1332. if ($plistmanall{$i}) {
  1333. if ($manstrict) {
  1334. &perror("FATAL: manpage for chapter ".
  1335. "$i must be listed in ".
  1336. "$file MAN\U$i\E. ");
  1337. } else {
  1338. &perror("WARN: manpage for chapter ".
  1339. "$i should be listed in ".
  1340. "MAN\U$i\E, ".
  1341. "even if compression is ".
  1342. "not necessary.");
  1343. }
  1344. }
  1345. if ($mancompress && $plistman{$i}) {
  1346. &perror("WARN: MAN\U$i\E will help you ".
  1347. "compressing manual page in chapter ".
  1348. "\"$i\".");
  1349. } elsif (!$mancompress && $plistmangz{$i}) {
  1350. &perror("WARN: MAN\U$i\E will help you ".
  1351. "uncompressing manual page in chapter ".
  1352. "\"$i\".");
  1353. }
  1354. }
  1355. }
  1356. if ($tmp !~ /MANLANG/ && scalar(keys %manlangs)) {
  1357. $i = (keys %manlangs)[0];
  1358. &perror("WARN: how about using MANLANG for ".
  1359. "designating manual language, such as \"$i\"?");
  1360. }
  1361. # check USE_X11 and USE_IMAKE
  1362. if ($tmp =~ /\nUSE_IMAKE[?+]?=/
  1363. && $tmp =~ /\n(USE_X11)[?+]?=/) {
  1364. &perror("WARN: since you already have USE_IMAKE, ".
  1365. "you don't need $1.");
  1366. }
  1367. # check USE_X11 and USE_IMAKE
  1368. if ($newxdef && $tmp =~ /\nUSE_IMAKE[?+]?=/
  1369. && $tmp =~ /\n(USE_X_PREFIX)[?+]?=/) {
  1370. &perror("WARN: since you already have USE_IMAKE, ".
  1371. "you don't need $1.");
  1372. }
  1373. # check USE_X11 and USE_X_PREFIX
  1374. if ($newxdef && $tmp =~ /\nUSE_X11[?+]?=/
  1375. && $tmp !~ /\nUSE_X_PREFIX[?+]?=/) {
  1376. &perror("FATAL: meaning of USE_X11 is changed in Aug 1998. ".
  1377. "use USE_X_PREFIX instead.");
  1378. }
  1379. # check direct use of important make targets.
  1380. if ($tmp =~ /\n(fetch|extract|patch|configure|build|install):/) {
  1381. &perror("FATAL: direct redefinition of make target \"$1\" ".
  1382. "discouraged. redefine \"do-$1\" instead.");
  1383. }
  1384. # check for incorrect use of the pre-everything target.
  1385. if ($tmp =~ /\npre-everything:[^:]/) {
  1386. &perror("FATAL: use pre-everything:: instead of pre-everything:");
  1387. }
  1388. 1;
  1389. }
  1390. sub perror {
  1391. my(@msg) = @_;
  1392. if ($msg[0] =~ /^FATAL/) {
  1393. $err++;
  1394. } else {
  1395. $warn++;
  1396. }
  1397. print join("\n", @msg) . "\n";
  1398. }
  1399. sub checkextra {
  1400. my($str, $section) = @_;
  1401. $str = "\n" . $str if ($str !~ /^\n/);
  1402. $str =~ s/\n#[^\n]*/\n/g;
  1403. $str =~ s/\n\n+/\n/g;
  1404. $str =~ s/^\s+//;
  1405. $str =~ s/\s+$//;
  1406. return if ($str eq '');
  1407. if ($str =~ /^([\w\d]+)/) {
  1408. &perror("WARN: extra item placed in the ".
  1409. "$section section, ".
  1410. "for example, \"$1\".");
  1411. } else {
  1412. &perror("WARN: extra item placed in the ".
  1413. "$section section.");
  1414. }
  1415. }
  1416. sub checkorder {
  1417. my($section, $str, @order) = @_;
  1418. my(@items, $i, $j, $k, $invalidorder);
  1419. print "OK: checking the order of $section section.\n" if ($verbose);
  1420. @items = ();
  1421. foreach my $i (split("\n", $str)) {
  1422. $i =~ s/[+?]?=.*$//;
  1423. push(@items, $i);
  1424. }
  1425. @items = reverse(@items);
  1426. $j = -1;
  1427. $invalidorder = 0;
  1428. while (scalar(@items)) {
  1429. $i = pop(@items);
  1430. $k = 0;
  1431. while ($k < scalar(@order) && $order[$k] ne $i) {
  1432. $k++;
  1433. }
  1434. if ($order[$k] eq $i) {
  1435. if ($k < $j) {
  1436. &perror("FATAL: $i appears out-of-order.");
  1437. $invalidorder++;
  1438. } else {
  1439. print "OK: seen $i, in order.\n" if ($verbose);
  1440. }
  1441. $j = $k;
  1442. # This if condition tests for .if, .else (in all forms),
  1443. # .for and .endfor and .include
  1444. } elsif ($i !~ m/^\.(if|el|endif|for|endfor|include)/) {
  1445. &perror("FATAL: extra item \"$i\" placed in the ".
  1446. "$section section.");
  1447. }
  1448. }
  1449. if ($invalidorder) {
  1450. &perror("FATAL: order must be " . join('/', @order) . '.');
  1451. } else {
  1452. print "OK: $section section is ordered properly.\n"
  1453. if ($verbose);
  1454. }
  1455. }
  1456. sub checkearlier {
  1457. my($file, $str, @varnames) = @_;
  1458. my($i);
  1459. print "OK: checking items that has to appear earlier.\n" if ($verbose);
  1460. foreach my $i (@varnames) {
  1461. if ($str =~ /\n$i[?+]?=/) {
  1462. &perror("WARN: \"$i\" has to appear earlier in $file.");
  1463. }
  1464. }
  1465. }
  1466. sub abspathname {
  1467. my($str, $file) = @_;
  1468. my($s, $i, %cmdnames);
  1469. my($pre);
  1470. # ignore parameter string to echo command
  1471. $str =~ s/[ \t][\@-]?(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+("(\\'|\\"|[^"])*"|'(\\'|\\"|[^"])*')[ \t]*[;\n]//; #'
  1472. print "OK: checking direct use of full pathnames in $file.\n"
  1473. if ($verbose);
  1474. foreach my $s (split(/\n+/, $str)) {
  1475. $i = '';
  1476. if ($s =~ /(^|[ \t\@'"-])(\/[\w\d])/) { #'
  1477. # suspected pathnames are recorded.
  1478. $i = $2 . $';
  1479. $pre = $` . $1;
  1480. if ($pre =~ /MASTER_SITE_SUBDIR/) {
  1481. # MASTER_SITE_SUBDIR lines are ok.
  1482. $i = '';
  1483. }
  1484. }
  1485. if ($i ne '') {
  1486. $i =~ s/\s.*$//;
  1487. $i =~ s/['"].*$//; #'
  1488. $i = substr($i, 0, 20) . '...' if (20 < length($i));
  1489. &perror("WARN: possible use of absolute pathname ".
  1490. "\"$i\", in $file.") unless ($i =~ m,^/compat/,);
  1491. }
  1492. }
  1493. print "OK: checking direct use of pathnames, phase 1.\n" if ($verbose);
  1494. %cmdnames = split(/\n|\t+/, <<EOF);
  1495. /usr/opt \${PORTSDIR} instead
  1496. $portsdir \${PORTSDIR} instead
  1497. $localbase \${PREFIX} or \${LOCALBASE}, as appropriate
  1498. /usr/X11 \${PREFIX} or \${X11BASE}, as appropriate
  1499. EOF
  1500. foreach my $i (keys %cmdnames) {
  1501. if ($str =~ /$i/) {
  1502. &perror("WARN: possible direct use of \"$&\" ".
  1503. "found in $file. if so, use $cmdnames{$i}.");
  1504. }
  1505. }
  1506. print "OK: checking direct use of pathnames, phase 2.\n" if ($verbose);
  1507. %cmdnames = split(/\n|\t+/, <<EOF);
  1508. distfiles \${DISTDIR} instead
  1509. pkg \${PKGDIR} instead
  1510. files \${FILESDIR} instead
  1511. scripts \${SCRIPTDIR} instead
  1512. patches \${PATCHDIR} instead
  1513. work \${WRKDIR} instead
  1514. EOF
  1515. foreach my $i (keys %cmdnames) {
  1516. if ($str =~ /(\.\/|\$[\{\(]\.CURDIR[\}\)]\/|[ \t])(\b$i)\//) {
  1517. &perror("WARN: possible direct use of \"$i\" ".
  1518. "found in $file. if so, use $cmdnames{$i}.");
  1519. }
  1520. }
  1521. }
  1522. sub is_predefined {
  1523. my($url) = @_;
  1524. my($site, $site_re);
  1525. my $subdir_re = quotemeta quotemeta '/%SUBDIR%/';
  1526. for my $site (keys %predefined) {
  1527. $site_re = quotemeta $site;
  1528. $site_re =~ s,$subdir_re,/(.*)/,;
  1529. if ($url =~ /$site_re/) {
  1530. &perror("WARN: how about using ".
  1531. "\"\${MASTER_SITE_$predefined{$site}}\" with ".
  1532. "\"MASTER_SITE_SUBDIR=$1\", instead of \"$url\"?");
  1533. return &TRUE;
  1534. }
  1535. }
  1536. undef;
  1537. }
  1538. sub urlcheck {
  1539. my ($url) = @_;
  1540. if ($url !~ m#^\w+://#) {
  1541. &perror("WARN: \"$url\" doesn't appear to be a URL to me.");
  1542. }
  1543. if ($url !~ m#/$#) {
  1544. &perror("FATAL: URL \"$url\" should ".
  1545. "end with \"/\".");
  1546. }
  1547. if ($url =~ m#://[^/]*:/#) {
  1548. &perror("FATAL: URL \"$url\" contains ".
  1549. "extra \":\".");
  1550. }
  1551. if ($osname == 'FreeBSD' && $url =~ m#(www\.freebsd\.org)/~.+/#i) {
  1552. &perror("WARN: URL \"$url\", ".
  1553. "$1 should be ".
  1554. "people.FreeBSD.org");
  1555. }
  1556. }
  1557. sub TRUE {1;}
  1558. # Local variables:
  1559. # tab-width: 4
  1560. # End: