portlint.pl 101 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426
  1. #! /usr/bin/perl -w
  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$
  20. # $MCom$
  21. #
  22. use strict;
  23. use warnings;
  24. use Getopt::Std;
  25. use File::Find;
  26. use IPC::Open2;
  27. use POSIX qw(strftime);
  28. sub perror($$$$);
  29. our ($opt_a, $opt_A, $opt_b, $opt_C, $opt_c, $opt_g, $opt_h, $opt_m, $opt_t, $opt_v, $opt_M, $opt_N, $opt_B, $opt_V, @ALLOWED_FULL_PATHS, @MASTERSITES_WHITELIST);
  30. my ($err, $warn);
  31. my ($extrafile, $parenwarn, $committer, $verbose, $usetabs, $newport,
  32. $grouperrs, $checkmfiles);
  33. my $contblank;
  34. my $portdir;
  35. my $makeenv = "";
  36. my @errlst = ();
  37. my %errcache = ();
  38. $err = $warn = 0;
  39. $extrafile = $parenwarn = $committer = $verbose = $usetabs = $newport = 0;
  40. $checkmfiles = 0;
  41. $contblank = 1;
  42. $portdir = '.';
  43. @ALLOWED_FULL_PATHS = qw(/boot/loader.conf /compat/ /dev/null /etc/inetd.conf);
  44. @MASTERSITES_WHITELIST = qw(googlecode.com nodeload.github.com);
  45. # version variables
  46. my $major = 2;
  47. my $minor = 14;
  48. my $micro = 2;
  49. sub l { '[{(]'; }
  50. sub r { '[)}]'; }
  51. sub s { '[ \t]'; }
  52. my $l = &l;
  53. my $r = &r;
  54. my $s = &s;
  55. # default setting - for FreeBSD
  56. my $portsdir = '/usr/ports';
  57. my $rcsidstr = 'FreeBSD';
  58. my $multiplist = 0;
  59. my $ldconfigwithtrue = 0;
  60. my $rcsidinplist = 0;
  61. my $mancompress = 1;
  62. my $manstrict = 0;
  63. my $newxdef = 1;
  64. my $automan = 1;
  65. my $autoinfo = 1;
  66. my $manchapters = '123456789ln';
  67. my $localbase = '/usr/local';
  68. my $numpitems = 6;
  69. my %lang_pref = qw(
  70. arabic ar
  71. chinese zh
  72. french fr
  73. german de
  74. hebrew iw
  75. hungarian hu
  76. japanese ja
  77. korean ko
  78. polish pl
  79. portuguese pt
  80. russian ru
  81. ukrainian uk
  82. vietnamese vi
  83. );
  84. my @lang_cat = keys %lang_pref;
  85. my @lang_short = values %lang_pref;
  86. my $re_lang_short = '(' . join('|', @lang_short) . ')-';
  87. my ($prog) = ($0 =~ /([^\/]+)$/);
  88. sub usage {
  89. print STDERR <<EOF;
  90. usage: $prog [-AabCcghmvtN] [-M ENV] [-B#] [port_directory]
  91. -a additional check for scripts/* and pkg-*
  92. -A turn on all additional checks (equivalent to -abcmNt)
  93. -b warn \$(VARIABLE)
  94. -c committer mode (implies -m)
  95. -C pedantic committer mode (equivalent to -abcmt)
  96. -g group errors together to avoid duplication (disabled if -v is specified)
  97. -h show summary of command line options
  98. -v verbose mode
  99. -t nit pick about use of spaces
  100. -m check \${PORTSDIR}/MOVED, UIDs, and GIDs files
  101. -N writing a new port
  102. -V print the version and exit
  103. -M ENV set make variables to ENV (ex. PORTSDIR=/usr/ports.work)
  104. -B# allow # contiguous blank lines (default: $contblank line)
  105. EOF
  106. exit 0;
  107. }
  108. sub version {
  109. print "$prog version $major.$minor.$micro\n";
  110. exit $major;
  111. }
  112. getopts('AabCcghmtvB:M:NV');
  113. &usage if $opt_h;
  114. &version if $opt_V;
  115. $extrafile = 1 if $opt_a || $opt_A || $opt_C;
  116. $parenwarn = 1 if $opt_b || $opt_A || $opt_C;
  117. $committer = 1 if $opt_c || $opt_A || $opt_C;
  118. $verbose = 1 if $opt_v;
  119. $grouperrs = 1 if $opt_g && !$opt_v;
  120. $checkmfiles = 1 if $opt_m || $opt_c || $opt_A || $opt_C;
  121. $newport = 1 if $opt_N || $opt_A;
  122. $usetabs = 1 if $opt_t || $opt_A || $opt_C;
  123. $contblank = $opt_B if $opt_B;
  124. $makeenv = $opt_M if $opt_M;
  125. $portdir = $ARGV[0] ? $ARGV[0] : '.';
  126. # OS dependent configs
  127. # os portsdir rcsid mplist ldcfg plist-rcsid mancompresss strict localbase newxdef automan autoinfo
  128. my @osdep = split(/\n/, <<EOF);
  129. FreeBSD /usr/ports FreeBSD 0 0 0 1 0 /usr/local 1 1 1
  130. NetBSD /usr/pkgsrc NetBSD 1 1 1 0 1 /usr/pkg 0 0 0
  131. EOF
  132. my $osname = `uname -s`;
  133. $osname =~ s/\n$//;
  134. foreach my $i (@osdep) {
  135. if ($i =~ /^$osname\t(.*)/) {
  136. print "OK: found OS config for $osname.\n" if ($verbose);
  137. ($portsdir, $rcsidstr, $multiplist, $ldconfigwithtrue,
  138. $rcsidinplist, $mancompress, $manstrict, $localbase,
  139. $newxdef, $automan, $autoinfo)
  140. = split(/\t+/, $1);
  141. last;
  142. }
  143. }
  144. # The PORTSDIR environment variable overrides our defaults.
  145. $portsdir = $ENV{PORTSDIR} if ( defined $ENV{'PORTSDIR'} );
  146. $ENV{'PL_SVN_IGNORE'} //= '';
  147. my $mfile_moved = "${portsdir}/MOVED";
  148. my $mfile_uids = "${portsdir}/UIDs";
  149. my $mfile_gids = "${portsdir}/GIDs";
  150. if ($verbose) {
  151. print "OK: config: portsdir: \"$portsdir\" ".
  152. "rcsidstr: \"$rcsidstr\" ".
  153. "multiplist: $multiplist ".
  154. "ldconfigwithtrue: $ldconfigwithtrue ".
  155. "rcsidinplist: $rcsidinplist ".
  156. "mancompress: $mancompress ".
  157. "manstrict: $manstrict ".
  158. "localbase: $localbase ".
  159. "\n";
  160. }
  161. #
  162. # just for safety.
  163. #
  164. if (! -d $portdir) {
  165. print STDERR "FATAL: invalid directory $portdir specified.\n";
  166. exit 1;
  167. }
  168. chdir "$portdir" || die "$portdir: $!";
  169. # get make vars
  170. my @varlist = qw(
  171. PORTNAME PORTVERSION PORTREVISION PORTEPOCH PKGNAME PKGNAMEPREFIX
  172. PKGNAMESUFFIX DISTVERSIONPREFIX DISTVERSION DISTVERSIONSUFFIX
  173. DISTNAME DISTFILES CATEGORIES MASTERDIR MAINTAINER MASTER_SITES
  174. WRKDIR WRKSRC NO_WRKSUBDIR SCRIPTDIR FILESDIR
  175. PKGDIR COMMENT DESCR PLIST PKGCATEGORY PKGINSTALL PKGDEINSTALL
  176. PKGREQ PKGMESSAGE DISTINFO_FILE .CURDIR USE_LDCONFIG USE_AUTOTOOLS
  177. USE_GNOME INDEXFILE PKGORIGIN CONFLICTS PKG_VERSION PKGINSTALLVER
  178. PLIST_FILES OPTIONS OPTIONS_DEFINE INSTALLS_OMF USE_GETTEXT USE_RC_SUBR
  179. DIST_SUBDIR ALLFILES IGNOREFILES CHECKSUM_ALGORITHMS INSTALLS_ICONS
  180. GNU_CONFIGURE CONFIGURE_ARGS MASTER_SITE_SUBDIR LICENSE LICENSE_COMB
  181. );
  182. my $cmd = join(' -V ', "make $makeenv MASTER_SITE_BACKUP=''", @varlist);
  183. my %makevar;
  184. my $i = 0;
  185. for (split(/\n/, `$cmd`)) {
  186. print "OK: makevar: $varlist[$i] = $_\n" if ($verbose);
  187. $makevar{$varlist[$i]} = $_;
  188. $i++;
  189. }
  190. #
  191. # variables for global checks.
  192. #
  193. my $sharedocused = 0;
  194. my %plistmanall = ();
  195. my %plistmangz = ();
  196. my %plistman = ();
  197. my %manlangs = ();
  198. my %predefined = ();
  199. # historical, no longer in FreeBSD's bsd.sites.mk
  200. foreach my $i (split(/\n/, <<EOF)) {
  201. GNU ftp://prep.ai.mit.edu/pub/gnu/%SUBDIR%/
  202. GNU ftp://wuarchive.wustl.edu/systems/gnu/%SUBDIR%/
  203. GNU ftp://ftp.ecrc.net/pub/gnu/%SUBDIR%/
  204. PERL_CPAN ftp://ftp.cdrom.com/pub/perl/CPAN/modules/by-module/%SUBDIR%/
  205. SUNSITE ftp://sunsite.unc.edu/pub/Linux/%SUBDIR%/
  206. SUNSITE ftp://ftp.funet.fi/pub/mirrors/sunsite.unc.edu/pub/Linux/%SUBDIR%/
  207. SUNSITE ftp://ftp.infomagic.com/pub/mirrors/linux/sunsite/%SUBDIR%/
  208. TEX_CTAN ftp://ftp.cdrom.com/pub/tex/ctan/%SUBDIR%/
  209. TEX_CTAN ftp://ftp.tex.ac.uk/public/ctan/tex-archive/%SUBDIR%/
  210. GNOME ftp://ftp.cybertrails.com/pub/gnome/%SUBDIR%/
  211. AFTERSTEP ftp://ftp.alpha1.net/pub/mirrors/ftp.afterstep.org/%SUBDIR%/
  212. AFTERSTEP ftp://casper.yz.yamagata-u.ac.jp/pub/X11/apps/afterstep/%SUBDIR%/
  213. WINDOWMAKER ftp://ftp.io.com/pub/%SUBDIR%/
  214. EOF
  215. my ($j, $k) = split(/\t+/, $i);
  216. $predefined{$k} = $j;
  217. }
  218. # Read bsd.sites.mk
  219. my $sites_mk = "$portsdir/Mk/bsd.sites.mk";
  220. open(MK, $sites_mk) || die "$sites_mk: $!";
  221. my @site_groups = grep($_ = /^MASTER_SITE_(\w+)/ && $1, <MK>);
  222. close(MK);
  223. $cmd = join(' -V MASTER_SITE_', "make $makeenv ", @site_groups);
  224. $i = 0;
  225. open2(\*IN, \*OUT, $cmd);
  226. close(OUT);
  227. while (<IN>) {
  228. my $g = $site_groups[$i];
  229. for my $s (split()) {
  230. $predefined{$s} = $g;
  231. }
  232. $i++;
  233. }
  234. close(IN);
  235. #
  236. # check for files.
  237. #
  238. my @checker = ($makevar{DESCR}, 'Makefile', $makevar{DISTINFO_FILE});
  239. my %checker = (
  240. $makevar{DESCR} => \&checkdescr,
  241. 'Makefile' => \&checkmakefile,
  242. $makevar{DISTINFO_FILE} => \&checkdistinfo
  243. );
  244. if ($extrafile) {
  245. my @files = (
  246. <$makevar{SCRIPTDIR}/*>,
  247. @makevar{qw(DESCR PLIST PKGINSTALL PKGDEINSTALL PKGREQ PKGMESSAGE)}
  248. );
  249. foreach my $i (@files) {
  250. next if (! -T $i);
  251. next if (defined $checker{$i});
  252. if ($i =~ /\bpkg-plist$/
  253. || ($multiplist && $i =~ /\bpkg-plist/)) {
  254. unshift(@checker, $i);
  255. $checker{$i} = \&checkplist;
  256. } else {
  257. push(@checker, $i);
  258. $checker{$i} = \&checkpathname;
  259. }
  260. }
  261. }
  262. if ($checkmfiles) {
  263. foreach my $i ($mfile_moved, $mfile_uids, $mfile_gids) {
  264. next if (! -T $i);
  265. next if (defined $checker{$i});
  266. push(@checker, $i);
  267. $checker{$i} = \&checkmfile;
  268. }
  269. }
  270. foreach my $i (<$makevar{FILESDIR}/patch-*>) {
  271. next if (! -T $i);
  272. next if (defined $checker{$i});
  273. push(@checker, $i);
  274. $checker{$i} = \&checkpatch;
  275. }
  276. foreach my $i (@checker) {
  277. print "OK: checking $i.\n" if ($verbose);
  278. if (! -f "$i") {
  279. &perror("FATAL", "", -1, "no $i in \"$portdir\".") unless $i eq $makevar{DISTINFO_FILE} && $makevar{DISTFILES} eq "";
  280. } else {
  281. my $proc = $checker{$i};
  282. &$proc($i) || &perror("", "", -1, "Cannot open the file $i\n");
  283. if ($proc ne \&checkpatch) {
  284. &checklastline($i)
  285. || &perror("", "", -1, "Cannot open the file $i\n");
  286. }
  287. }
  288. }
  289. # Check to make sure there is no pkg-comment file anymore.
  290. if (-f 'pkg-comment') {
  291. &perror("FATAL", "", -1, "Use of pkg-comment is obsolete. Use the COMMENT macro within the port's Makefile instead.");
  292. }
  293. if ($committer) {
  294. sub find_proc {
  295. return if /^\.\.?$/;
  296. (my $fullname = $File::Find::name) =~ s#^\./##;
  297. print "OK: checking the file name of $fullname.\n" if ($verbose);
  298. if ($fullname eq 'work') {
  299. &perror("FATAL", $fullname, -1, "be sure to cleanup the working directory ".
  300. "before committing the port.");
  301. $File::Find::prune = 1;
  302. } elsif (-l) {
  303. &perror("WARN", $fullname, -1, "this is a symlink. ".
  304. "Please remove it.");
  305. } elsif (-z) {
  306. &perror("FATAL", $fullname, -1, "empty file and should be removed. ".
  307. "If it still needs to be there, put a dummy comment ".
  308. "to state that the file is intentionally left empty.");
  309. } elsif (-d && scalar(my @x = <$_/{*,.?*}>) <= 1) {
  310. &perror("FATAL", $fullname, -1, "empty directory should be removed.");
  311. } elsif (/^\./) {
  312. &perror("WARN", $fullname, -1, "dotfiles are not preferred. ".
  313. "If this file is a dotfile to be installed as an example, ".
  314. "consider importing it as \"dot$_\".");
  315. } elsif (/[^-.a-zA-Z0-9_\+]/) {
  316. &perror("WARN", $fullname, -1, "only use characters ".
  317. "[-_.a-zA-Z0-9+] for patch or script names.");
  318. } elsif (/\.(orig|rej|bak)$/ || /~$/ || /^\#/) {
  319. &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
  320. "backup files before committing the port.");
  321. } elsif (/(^|\.)core$/) {
  322. &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
  323. "core files before committing the port.");
  324. } elsif (/README.html/) {
  325. &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
  326. "README.html files before committing the port.");
  327. } elsif ($_ eq '.svn' && -d) {
  328. &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
  329. "Subversion files before committing the port.");
  330. $File::Find::prune = 1;
  331. } elsif ($_ eq 'CVS' && -d) {
  332. if ($newport) {
  333. &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
  334. "CVS directories before importing the new port.");
  335. }
  336. $File::Find::prune = 1;
  337. } elsif (-f) {
  338. my $fullpath = $makevar{'.CURDIR'}.'/'.$fullname;
  339. my $result = `svn status $fullpath`;
  340. chomp $result;
  341. if (substr($result, 0, 1) eq '?') {
  342. &perror("FATAL", "", -1, "$fullname not under SVN.")
  343. unless (eval { /$ENV{'PL_SVN_IGNORE'}/, 1 } &&
  344. /$ENV{'PL_SVN_IGNORE'}/);
  345. }
  346. }
  347. }
  348. find(\&find_proc, '.');
  349. # Check for ports that may break INDEX
  350. my $indexerr = `env LOCALBASE=/nonexistentlocal make $makeenv describe 2>&1 >/dev/null`;
  351. chomp $indexerr;
  352. $indexerr =~ tr/\n/ /s;
  353. &perror("FATAL", "", -1, "breaks INDEX ($indexerr).")
  354. if ($indexerr);
  355. }
  356. if ($err || $warn) {
  357. my($errtext, $warntext) = ("error", "warning");
  358. $errtext .= "s" unless ($err == 1);
  359. $warntext .= "s" unless ($warn == 1);
  360. if ($grouperrs) {
  361. foreach my $msg (@errlst) {
  362. my $lines;
  363. if ($errcache{$msg} && scalar(@{$errcache{$msg}})) {
  364. $lines = "[" . (join(",", @{$errcache{$msg}})) . "]: ";
  365. } else {
  366. $lines = "";
  367. }
  368. $msg =~ s/%%LINES%%/$lines/;
  369. print $msg, "\n";
  370. }
  371. }
  372. printf("%d fatal %s and %d %s found.\n", $err, $errtext, $warn, $warntext);
  373. } else {
  374. print "looks fine.\n";
  375. }
  376. exit $err;
  377. #
  378. # distinfo
  379. #
  380. sub checkdistinfo {
  381. my($file) = @_;
  382. my($dist_subdir) = $makevar{DIST_SUBDIR};
  383. my(@allfiles) = split (/\s+/, $makevar{ALLFILES});
  384. my %ignorefiles = ();
  385. my %algorithms = ();
  386. my %records = ();
  387. foreach my $i (split (/\s+/, $makevar{IGNOREFILES})) {
  388. $ignorefiles{$i} = 1;
  389. }
  390. foreach my $i (split (/\s+/, uc ($makevar{CHECKSUM_ALGORITHMS}))) {
  391. $algorithms{$i} = 1;
  392. }
  393. if (scalar (%ignorefiles)) {
  394. &perror("WARN", "", -1, "Found IGNOREFILES. It is not recomended.");
  395. }
  396. open(IN, "< $file") || return 0;
  397. while (<IN>) {
  398. if (/^\s*$/) {
  399. &perror("FATAL", $file, $., "found blank line.");
  400. }
  401. m/(\S+)\s+\((\S+)\)\s+=\s+(\S+)/;
  402. if ($1 ne "" && $2 ne "" && $3 ne "") {
  403. my ($tag, $path, $value) = ($1, $2, $3);
  404. $records{$path}{$tag} = $value;
  405. if (!$algorithms{$tag} && $tag ne "SIZE") {
  406. &perror("FATAL", $file, $., "unsupported checksum algorithm ".
  407. "found: $tag.");
  408. }
  409. } else {
  410. &perror("FATAL", $file, $., "line format error.");
  411. }
  412. }
  413. close(IN);
  414. # For all files check SIZE and checksums
  415. foreach my $f (@allfiles) {
  416. # Remove hindering chars from DISTNAME
  417. $f =~ s/['\\]//g;
  418. my $path = $f;
  419. $path = "$dist_subdir/$f" if $dist_subdir;
  420. if (!defined($records{$path}{SIZE}) && !$ignorefiles{$f}) {
  421. &perror("FATAL", $file, -1, "has no SIZE record for $path.");
  422. }
  423. my $n = 0;
  424. foreach my $alg (keys %algorithms) {
  425. $n++ if exists($records{$path}{$alg});
  426. }
  427. if ($n == 0) {
  428. &perror("FATAL", $file, -1, "no checksum record for $path.");
  429. }
  430. if ($n < scalar(keys %algorithms)) {
  431. &perror("WARN", $file, -1, "no checksum records for all ".
  432. "supported algorithms (".join(" ",keys %algorithms).") for ".
  433. "$path.");
  434. }
  435. }
  436. return 1;
  437. }
  438. #
  439. # pkg-descr
  440. #
  441. sub checkdescr {
  442. my($file) = @_;
  443. my(%maxchars) = ($makevar{DESCR}, 80);
  444. my(%maxlines) = ($makevar{DESCR}, 24);
  445. my(%errmsg) = ($makevar{DESCR}, "exceeds $maxlines{$makevar{DESCR}} ".
  446. "lines, make it shorter if possible.");
  447. my($longlines, $linecnt, $tmp) = (0, 0, "");
  448. open(IN, "< $file") || return 0;
  449. while (<IN>) {
  450. $tmp .= $_;
  451. chomp || &perror("WARN", $file, -1, "lines should terminate with a ".
  452. "newline (i.e. '\\n').");
  453. if (/ $/) {
  454. &perror("WARN", $file, -1, "lines should not contain carriage ".
  455. "returns. Strip all carriage returns (e.g. run dos2unix) ".
  456. "in $file.");
  457. }
  458. if (/^WWW:(\s+)(\S*)/) {
  459. my $wwwurl = $2;
  460. if ($1 ne ' ') {
  461. &perror("WARN", $file, -1, "use WWW: with a single space, ".
  462. "then $wwwurl");
  463. }
  464. if ($wwwurl !~ m|^https?://|) {
  465. &perror("WARN", $file, -1, "WWW URL, $wwwurl should begin ".
  466. "with \"http://\" or \"https://\".");
  467. }
  468. if ($wwwurl =~ m|^http://search.cpan.org/~|) {
  469. &perror("WARN", $file, -1, "consider changing WWW URL to ".
  470. "http://search.cpan.org/dist/$makevar{PORTNAME}");
  471. }
  472. }
  473. $linecnt++;
  474. $longlines++ if ($maxchars{$file} < length);
  475. }
  476. if ($linecnt > $maxlines{$file}) {
  477. &perror("WARN", $file, -1, "$errmsg{$file}".
  478. "(currently $linecnt lines)");
  479. } else {
  480. print "OK: $file: has $linecnt lines.\n" if ($verbose);
  481. }
  482. if ($longlines > 0) {
  483. &perror("WARN", $file, -1, "includes lines that exceed $maxchars{$file} ".
  484. "characters.");
  485. }
  486. if ($tmp =~ /[\033\200-\377]/) {
  487. &perror("WARN", $file, -1, "includes iso-8859-1, or ".
  488. "other local characters. files should be in ".
  489. "plain 7-bit ASCII");
  490. }
  491. if ($file =~ /\bpkg-descr/ && $tmp =~ m,http://,) {
  492. my $has_url = 0;
  493. my $has_www = 0;
  494. my $cpan_url = 0;
  495. my $has_endslash = 0;
  496. foreach my $line (grep($_ =~ "http://", split(/\n+/, $tmp))) {
  497. $has_url = 1;
  498. if ($line =~ m,WWW:[ \t]+http://,) {
  499. $has_www = 1;
  500. if ($line =~ m,search.cpan.org,) {
  501. $cpan_url = 1;
  502. if ($line =~ m,/$,) {
  503. $has_endslash = 1;
  504. }
  505. }
  506. }
  507. }
  508. if (!$has_url) {
  509. &perror("WARN", $file, -1, "add \"WWW: UR:\" for this port if possible");
  510. }
  511. if ($cpan_url && !$has_endslash) {
  512. &perror("WARN", $file, -1, "end WWW CPAN URL with a \"/\"");
  513. }
  514. if ($has_url && ! $has_www) {
  515. &perror("FATAL", $file, -1, "contains a URL but no \"WWW:\"");
  516. }
  517. }
  518. close(IN);
  519. }
  520. #
  521. # pkg-plist
  522. #
  523. sub checkplist {
  524. my($file) = @_;
  525. my($curdir) = ($localbase);
  526. my($inforemoveseen, $infoinstallseen, $infoseen) = (0, 0, 0);
  527. my($infobeforeremove, $infoafterinstall) = (0, 0);
  528. my($infooverwrite) = (0);
  529. my($rcsidseen) = (0);
  530. my(@exec_info) = ();
  531. my(@unexec_info) = ();
  532. my(@infofile) = ();
  533. my $seen_dirrm_docsdir = 0;
  534. my $seen_special = 0;
  535. my $item_count = 0;
  536. # Variables that are allowed to be out-of-sync in the XXXDIR check.
  537. # E.g., %%PORTDOCS%%%%RUBY_MODDOCDIR%% will be OK because there is
  538. # no %%PORTRUBY_MODDOC%% substitution.
  539. my %check_xxxdir_ok = (
  540. "DOCS" => "DOCS",
  541. "EXAMPLES" => "EXAMPLES",
  542. "DATA" => "DATA",
  543. "RUBY_DOC" => "DOCS",
  544. "RUBY_EXAMPLES" => "EXAMPLES",
  545. "RUBY_MODDOC" => "DOCS",
  546. "RUBY_MODEXAMPLES" => "EXAMPLES",
  547. );
  548. open(IN, "< $file") || return 0;
  549. while (<IN>) {
  550. $item_count++;
  551. if ($_ =~ /[ \t]+\n?$/) {
  552. &perror("WARN", $file, $., "whitespace before end ".
  553. "of line.");
  554. }
  555. # make it easier to handle.
  556. $_ =~ s/\s+$//;
  557. $_ =~ s/\n$//;
  558. if ($_ =~ /\.DS_Store/) {
  559. &perror("WARN", $file, $., ".DS_Store meta data files must not ".
  560. "be installed.");
  561. }
  562. if ($osname eq 'NetBSD' && $_ =~ /<\$ARCH>/) {
  563. &perror("WARN", $file, $., "use of <\$ARCH> deprecated, ".
  564. "use \${MACHINE_ARCH} instead.");
  565. }
  566. if (m'lib/perl5/site_perl/%%PERL_VER%%') {
  567. &perror("WARN", $file, $., "use \%\%SITE_PERL\%\% ".
  568. "instead of lib/perl5/site_perl/\%\%PERL_VER\%\%.");
  569. }
  570. if ($osname ne 'NetBSD' && m'([\w\d]+-portbld-freebsd\d+\.\d+)') {
  571. &perror("WARN", $file, $., "possible direct use of the ".
  572. "CONFIGURE_TARGET value ($1). Consider using the plist ".
  573. "substitution %%CONFIGURE_TARGET%% instead.");
  574. }
  575. $seen_special++ if /[\%\@]/;
  576. $seen_dirrm_docsdir++ if /^(\%\%PORTDOCS\%\%)?\@dirrm\s+\%\%DOCSDIR\%\%/ || /^(\%\%PORTDOCS\%\%)?\@unexec\s+(\/bin\/)?rmdir\s+\%D\/\%\%DOCSDIR\%\%\s+2\>\s*\/dev\/null\s+\|\|\s+(\/usr\/bin\/)?true/;
  577. if ($_ =~ /^\@/) {
  578. if ($_ =~ /^\@(cwd|cd)[ \t]+(\S+)/) {
  579. $curdir = $2;
  580. } elsif ($_ =~ /^\@unexec[ \t]+rm[ \t]/) {
  581. if ($_ !~ /%[DB]/) {
  582. &perror("WARN", $file, $., "use \"%D\" or \"%B\" to ".
  583. "specify prefix.");
  584. }
  585. if ($_ !~ /true$/ && $_ !~ /rm -f/) {
  586. &perror("WARN", $file, $., "add \"2>&1 ".
  587. ">/dev/null || true\" ".
  588. "to \"\@unexec rm\".");
  589. }
  590. } elsif ($_ =~ /^\@unexec[ \t]+rmdir/) {
  591. if ($_ !~ /%[DB]/) {
  592. &perror("WARN", $file, $., "use \"%D\" or \"%B\" to ".
  593. "specify prefix.");
  594. }
  595. &perror("WARN", $file, $., "use \"\@dirrmtry\" ".
  596. "instead of \"\@unexec rmdir\".");
  597. } elsif (!$autoinfo && $_ =~ /^\@exec[ \t]+install-info\s+(.+)\s+(.+)$/) {
  598. $infoinstallseen = $.;
  599. push(@exec_info, $1);
  600. } elsif (!$autoinfo && $_ =~ /^\@unexec[ \t]+install-info[ \t]+--delete\s+(.+)\s+(.+)$/) {
  601. $inforemoveseen = $.;
  602. push(@unexec_info, $1);
  603. } elsif ($autoinfo && $_ =~ /^\@unexec[ \t]+install-info[ \t]+--delete\s+(.+)\s+(.+)$/) {
  604. &perror("WARN", $file, $., "\@unexec install-info is deprecated in favor of adding info files into the Makefile using the INFO macro.");
  605. } elsif ($_ =~ /^\@(exec|unexec)/) {
  606. if (/ldconfig/) {
  607. if ($ldconfigwithtrue
  608. && !/\/usr\/bin\/true/) {
  609. &perror("FATAL", $file, $., "ldconfig ".
  610. "must be used with ".
  611. "\"||/usr/bin/true\".");
  612. }
  613. &perror("WARN", $file, $., "possible ".
  614. "direct use of ldconfig ".
  615. "in PLIST found. use ".
  616. "USE_LDCONFIG instead.");
  617. }
  618. if (/scrollkeeper/) {
  619. &perror("WARN", $file, $., "possible ".
  620. "direct use of scrollkeeper commands ".
  621. "in PLIST found. Use ".
  622. "INSTALLS_OMF instead ".
  623. "(see http://www.FreeBSD.org/gnome/docs/porting.html ".
  624. "for more details).");
  625. }
  626. } elsif ($_ =~ /^\@(comment)/) {
  627. $rcsidseen++ if (/\$$rcsidstr[:\$]/);
  628. } elsif ($_ =~ /^\@(owner|group|mode)\s/) {
  629. &perror("WARN", $file, $., "\@$1 should not be needed");
  630. } elsif ($_ =~ m!^\@(dirrm|dirrmtry)\s+/!) {
  631. &perror("WARN", $file, $., "Using \@$1 with absolute path ".
  632. "will not work as you expected in most cases. Use ".
  633. "pkg-deinstall or \@unexec rmdir ... if you want to ".
  634. "remove a directory such as /var/\${PORTNAME}");
  635. } elsif ($_ =~ /^\@(dirrm|option|stopdaemon|rmtry)/) {
  636. ; # no check made
  637. } elsif ($_ eq "\@cwd") {
  638. ; # @cwd by itself means change directory back to the original
  639. # PREFIX.
  640. } else {
  641. &perror("WARN", $file, $.,
  642. "unknown pkg-plist directive \"$_\"");
  643. }
  644. next;
  645. }
  646. if ($_ =~ /^\//) {
  647. &perror("FATAL", $file, $., "use of full pathname ".
  648. "disallowed.");
  649. }
  650. if ($_ =~ /charset\.alias$/ || $_ =~ /locale\.alias$/) {
  651. &perror("WARN", $file, $., "installing charset.alias or locale.alias, ".
  652. "please add USE_GETTEXT=yes and use libintl from devel/gettext ".
  653. "instead of from outdated bundled one if possible. ".
  654. "See http://www.freebsd.org/cgi/query-pr.cgi?pr=ports/71531 ".
  655. "for more details.");
  656. }
  657. if ($_ =~ /\%gconf.*\.xml/ || $_ =~ /gconf.*\.schemas?/) {
  658. &perror("FATAL", $file, $., "explicitly listing \%gconf key files ".
  659. "or GConf schema files in the plist is not supported. ".
  660. "Use GCONF_SCHEMAS in the Makefile instead. ".
  661. "See http://www.FreeBSD.org/gnome/docs/porting.html ".
  662. "for more details.");
  663. }
  664. if ($_ =~ m|lib/pkgconfig/[^\/]+.pc$|) {
  665. &perror("FATAL", $file, $., "installing pkg-config files into ".
  666. "lib/pkgconfig. All pkg-config files must be installed ".
  667. "into libdata/pkgconfig for them to be found by pkg-config.");
  668. }
  669. if ($_ =~ m|lib[^\/]+\.so(\.\d+)?$| &&
  670. $makevar{USE_LDCONFIG} eq '') {
  671. &perror("WARN", $file, $., "installing shared libraries, ".
  672. "please define USE_LDCONFIG as appropriate");
  673. }
  674. if ($_ =~ m|^share/icons/.*/| &&
  675. $makevar{INSTALLS_ICONS} eq '') {
  676. &perror("WARN", $file, $., "installing icons, ".
  677. "please define INSTALLS_ICONS as appropriate");
  678. }
  679. if ($_ =~ m|\.omf$| && $makevar{INSTALLS_OMF} eq '') {
  680. &perror("WARN", $file, $., "installing OMF files, ".
  681. "please define INSTALLS_OMF (see the FreeBSD GNOME ".
  682. "porting guide at ".
  683. "http://www.FreeBSD.org/gnome/docs/porting.html ".
  684. "for more details)");
  685. }
  686. if ($_ =~ m|\.mo$| && $makevar{USE_GETTEXT} eq '') {
  687. &perror("WARN", $file, $., "installing gettext translation files, ".
  688. "please define USE_GETTEXT as appropriate");
  689. }
  690. if ($_ =~ m|\.core$| && $_ !~ /^\@/) {
  691. &perror("WARN", $file, $., "this port installs a file which ends ".
  692. "in \".core\". This file may be deleted if ".
  693. "daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ".
  694. "If possible, install this file with a different name.");
  695. }
  696. if ($_ =~ m|/a\.out$| && $_ !~ /^\@/) {
  697. &perror("WARN", $file, $., "this port installs a file named ".
  698. "\"a.out\". This file may be deleted if ".
  699. "daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ".
  700. "If possible, install this file with a different name.");
  701. }
  702. if ($autoinfo && $_ =~ /\.info$/) {
  703. &perror("WARN", $file, $., "enumerating info files in the plist is deprecated in favor of adding info files into the Makefile using the INFO macro.");
  704. }
  705. if ($autoinfo && $_ =~ /\.info-\d+$/) {
  706. &perror("FATAL", $file, $., "numbered info files are obsolete and not portable; add info files using the INFO macro in the Makefile.");
  707. }
  708. if (!$autoinfo) {
  709. if ($_ =~ /^info\/.*info(-[0-9]+)?$/) {
  710. $infoseen = $.;
  711. $infoafterinstall++ if ($infoinstallseen);
  712. $infobeforeremove++ if (!$inforemoveseen);
  713. push(@infofile, $_);
  714. }
  715. if ($_ =~ /^info\/dir$/) {
  716. &perror("FATAL", $file, $., "\"info/dir\" should not be listed.".
  717. "Use install-info to add/remove ".
  718. "an entry.");
  719. $infooverwrite++;
  720. }
  721. }
  722. if ($_ =~ /^(\%\%PORTDOCS\%\%)?share\/doc\//) {
  723. &perror("WARN", $file, $., "If and only if your port is ".
  724. "DOCSDIR-safe (that is, a user can override DOCSDIR ".
  725. "when building this port and the port will still work ".
  726. "correctly) consider using DOCSDIR macro; if you are ".
  727. "unsure if this this port is DOCSDIR-safe, then ignore ".
  728. "this warning");
  729. $sharedocused++;
  730. } elsif ($_ =~ /^(\%\%PORTDOCS\%\%)?\%\%DOCSDIR\%\%/) {
  731. $sharedocused++;
  732. }
  733. if ($_ =~ /^share\/examples\//) {
  734. &perror("WARN", $file, $., "If and only if your port is ".
  735. "EXAMPLESDIR-safe (that is, a user can override EXAMPLESDIR ".
  736. "when building this port and the port will still work ".
  737. "correctly) consider using EXAMPLESDIR macro; if you are ".
  738. "unsure if this port is EXAMPLESDIR-safe, then ignore this ".
  739. "warning");
  740. }
  741. {
  742. my $tmpportname = quotemeta($makevar{PORTNAME});
  743. if ($_ =~ /^share\/$tmpportname\//) {
  744. &perror("WARN", $file, $., "If and only if your port is ".
  745. "DATADIR-safe (that is, a user can override DATADIR when ".
  746. "building this port and the port will still work ".
  747. "correctly) consider using DATADIR macro; if you are ".
  748. "unsure if this port is DATADIR-safe, then ignore this ".
  749. "warning");
  750. }
  751. }
  752. if ($_ =~ m{^%%PORT(\w+)%%(.*?)%%(\w+)DIR%%(.*)$} and $1 ne $3) {
  753. &perror("WARN", $file, $., "Do not mix %%PORT$1%% with %%$3DIR%%. ".
  754. "Use '%%PORT$check_xxxdir_ok{$3}%%$2%%$3DIR%%$4' instead and update Makefile ".
  755. "accordingly.") unless (defined($check_xxxdir_ok{$3}) and
  756. $check_xxxdir_ok{$3} eq $1);
  757. }
  758. if ($_ =~ m#man/([^/]+/)?man([$manchapters])/([^\.]+\.[$manchapters])(\.gz)?$#) {
  759. if (!$4) {
  760. $plistman{$2} .= ' ' . $3;
  761. if ($mancompress) {
  762. &perror("FATAL", $file, $.,
  763. "unpacked man file $3 ".
  764. "listed. must be gzipped.");
  765. }
  766. } else {
  767. $plistmangz{$2} .= ' ' . $3;
  768. if (!$mancompress) {
  769. &perror("FATAL", $file, $.,
  770. "gzipped man file $3$4 ".
  771. "listed. unpacked one should ".
  772. "be installed.");
  773. }
  774. }
  775. $plistmanall{$2} .= ' ' . $3;
  776. if ($1) {
  777. $manlangs{substr($1, 0, length($1) - 1)}++;
  778. }
  779. }
  780. if ($curdir !~ m#^$localbase#
  781. && $curdir !~ m#^/usr/X11R6#) {
  782. &perror("WARN", $file, $., "installing to ".
  783. "directory $curdir discouraged. ".
  784. "could you please avoid it?");
  785. }
  786. if ("$curdir/$_" =~ m#^$localbase/share/doc#) {
  787. print "OK: $file [$.]: seen installation to share/doc. ".
  788. "($curdir/$_)\n" if ($verbose);
  789. $sharedocused++;
  790. }
  791. }
  792. if (!$seen_special && $item_count < $numpitems) {
  793. &perror("WARN", $file, -1, "There are only $item_count items in the plist. Consider using PLIST_FILES instead of pkg-plist when installing less than $numpitems items.");
  794. }
  795. if ($sharedocused && !$seen_dirrm_docsdir) {
  796. &perror("WARN", $file, -1, "Both ``\%\%PORTDOCS\%\%\@dirrm \%\%DOCSDIR\%\%'' and ``\%\%PORTDOCS\%\%\@unexec \%D/\%\%DOCSDIR\%\% 2>/dev/null || true'' are missing. At least one should be used.");
  797. }
  798. if (!$autoinfo) {
  799. # check that every infofile has an exec install-info and unexec install-info
  800. my $exec_install = join(" ", @exec_info);
  801. $exec_install .= ' ';
  802. my $unexec_install = join(" ", @unexec_info);
  803. $unexec_install .= ' ';
  804. foreach my $if (@infofile) {
  805. next if ($if =~ m/info-/);
  806. if ($exec_install !~ m/\%D\/\Q$if\E/) {
  807. &perror("FATAL", $file, -1, "you need an '\@exec install-info \%D/$if \%D/info/dir' line");
  808. }
  809. if ($unexec_install !~ m/\%D\/$if/) {
  810. &perror("FATAL", $file, -1, "you need an '\@unexec install-info --delete \%D/$if \%D/info/dir' line");
  811. }
  812. }
  813. }
  814. if ($rcsidinplist && !$rcsidseen) {
  815. &perror("FATAL", $file, -1, "RCS tag \"\$$rcsidstr\$\" must be present ".
  816. "as \@comment.")
  817. }
  818. if (((!$autoinfo && !$infoseen) || $autoinfo)) {
  819. close(IN);
  820. return 1;
  821. }
  822. if (!$autoinfo && $infoseen) {
  823. if (!$infoinstallseen) {
  824. if ($infooverwrite) {
  825. &perror("FATAL", $file, -1, "install-info must be used to ".
  826. "add/delete entries into \"info/dir\".");
  827. }
  828. &perror("FATAL", $file, -1, "\"\@exec install-info \%D/... \%D/info/dir\" must be placed ".
  829. "after all the info files.");
  830. } elsif ($infoafterinstall) {
  831. &perror("FATAL", $file, $infoinstallseen, "move ".
  832. "\"\@exec install-info\" line to make ".
  833. "sure that it is placed after all the info files.");
  834. }
  835. if (!$inforemoveseen) {
  836. &perror("FATAL", $file, -1, "\"\@unexec install-info --delete \%D/... \%D/info/dir\" must ".
  837. "be placed before any of the info files listed.");
  838. } elsif ($infobeforeremove) {
  839. &perror("FATAL", $file, $inforemoveseen, "move ".
  840. "\"\@exec install-info --delete\" ".
  841. "line to make sure ".
  842. "that it is placed before any of the info files. ");
  843. }
  844. }
  845. close(IN);
  846. }
  847. #
  848. # ${PORTSDIR}/MOVED, UIDs, GIDs files
  849. #
  850. sub checkmfile {
  851. my ($file) = @_;
  852. my $line = 0;
  853. my $format;
  854. my @entries;
  855. my @sorted;
  856. my $dosort;
  857. if ($file =~ m/MOVED$/) {
  858. $format = '^[^|]*\|[^|]*\|[^|]*\|[^|]*$';
  859. $dosort = 0;
  860. } elsif ($file =~ m/UIDs$/) {
  861. $format = '^[^:]+:\*:[0-9]+:[0-9]+:[^:]*:0:0:[^:]+:[^:]+:[^:]+$';
  862. $dosort = 1;
  863. } elsif ($file =~ m/GIDs$/) {
  864. $format = '^[^:]+:\*:[0-9]+:[^:]*$';
  865. $dosort = 1;
  866. } else {
  867. &perror("FATAL", $file, -1, "Internal error. ".
  868. "Invalid name for mfiles.");
  869. }
  870. open(IN, "<$file") || return 0;
  871. while (<IN>) {
  872. chomp;
  873. $line++;
  874. next if (m,^\s*#,);
  875. if (!m,${format},) {
  876. &perror("FATAL", $file, -1,
  877. "malformed line at ".
  878. "${line}.\n => $_");
  879. } else {
  880. push @entries, "$line:$_";
  881. next;
  882. }
  883. }
  884. if ($dosort) {
  885. my $errline;
  886. @sorted = sort {(split /:/, $a)[3] <=> (split /:/, $b)[3] } @entries;
  887. for (my $n = 0; $n < @entries; $n++) {
  888. if (!defined($sorted[$n]) or
  889. $entries[$n] ne $sorted[$n]) {
  890. ($line, $errline) = ($entries[$n] =~ m/([0-9]+):(.*)/);
  891. &perror("WARN", $file, -1,
  892. "malformed sorting order at " .
  893. "${line}.\n => $errline");
  894. }
  895. }
  896. }
  897. close(IN);
  898. }
  899. #
  900. # misc files
  901. #
  902. sub checkpathname {
  903. my($file) = @_;
  904. my($whole);
  905. open(IN, "< $file") || return 0;
  906. $whole = '';
  907. while (<IN>) {
  908. $whole .= $_;
  909. }
  910. &abspathname($whole, $file);
  911. close(IN);
  912. }
  913. sub checklastline {
  914. my($file) = @_;
  915. my($whole);
  916. open(IN, "< $file") || return 0;
  917. $whole = '';
  918. while (<IN>) {
  919. $whole .= $_;
  920. }
  921. if ($whole !~ /\n$/) {
  922. &perror("FATAL", $file, -1, "the last line has to be ".
  923. "terminated by \\n.");
  924. }
  925. if ($whole =~ /\n([ \t]*\n)+$/) {
  926. &perror("WARN", $file, -1, "seems to have unnecessary blank lines ".
  927. "at the last part.");
  928. }
  929. close(IN);
  930. }
  931. sub checkpatch {
  932. my($file) = @_;
  933. my($whole);
  934. if (-z "$file") {
  935. &perror("FATAL", $file, -1, "has no content. should be removed ".
  936. "from repository.");
  937. return;
  938. }
  939. open(IN, "< $file") || return 0;
  940. $whole = '';
  941. while (<IN>) {
  942. $whole .= $_;
  943. }
  944. if ($committer && $whole =~ /\$([A-Z][A-Za-z0-9]+)(:[^\n]+)?\$/) {
  945. my $lineno = &linenumber($`);
  946. &perror("WARN", $file, $lineno, "includes possible RCS tag \"\$$1\$\". ".
  947. "use binary mode (-ko) on commit/import.") unless
  948. $1 eq $rcsidstr;
  949. }
  950. if ($committer && $whole =~ /\wjavavm\w/) {
  951. my $lineno = &linenumber($`);
  952. &perror("WARN", $file, $lineno, "since javavmwrapper 2.0, the ".
  953. "``javavm'' command to invoke a JVM is deprecated. Use ".
  954. "``java'' instead");
  955. }
  956. if ($whole =~ / /) {
  957. my $lineno = &linenumber($`);
  958. &perror("WARN", $file, $lineno, "patch contains ^M characters. ".
  959. "Consider defining USE_DOS2UNIX to remove DOS line endings ".
  960. "from source files.");
  961. }
  962. close(IN);
  963. }
  964. sub check_depends_syntax {
  965. my $tmp = shift;
  966. my $file = shift;
  967. my (%seen_depends, $j);
  968. $ENV{'PORTSDIR'} //= $portsdir;
  969. foreach my $i (grep(/^(PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS[?+]?=/, split(/\n/, $tmp))) {
  970. $i =~ s/^((PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS)[?+]?=[ \t]*//;
  971. $j = $1;
  972. $seen_depends{$j}++;
  973. if ($j ne 'DEPENDS' &&
  974. $i =~ /^\${([A-Z_]+DEPENDS)}\s*$/ &&
  975. $seen_depends{$1} &&
  976. $j ne $1)
  977. {
  978. print "OK: $j refers to $1, skipping checks.\n"
  979. if ($verbose);
  980. next;
  981. }
  982. print "OK: checking ports listed in $j.\n"
  983. if ($verbose);
  984. foreach my $k (split(/\s+/, $i)) {
  985. if ($k =~ /^#/) {
  986. last;
  987. }
  988. if ($k =~ /^\$\{(\w+)\}$/) {
  989. $k = `make -V $1`;
  990. chomp $k;
  991. }
  992. my @l = split(':', $k);
  993. print "OK: checking dependency value for $j.\n"
  994. if ($verbose);
  995. if ($k =~ /\${((PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS)}/) {
  996. &perror("WARN", $file, -1, "do not set $j to $k. ".
  997. "Instead, explicity list out required $j dependencies.");
  998. }
  999. if (($j ne 'DEPENDS'
  1000. && scalar(@l) != 2 && scalar(@l) != 3)) {
  1001. &perror("WARN", $file, -1, "wrong dependency value ".
  1002. "for $j. $j requires ".
  1003. "2 or 3 ".
  1004. "colon-separated tuples.");
  1005. next;
  1006. }
  1007. my %m = ();
  1008. $m{'dep'} = $l[0];
  1009. $m{'dir'} = $l[1];
  1010. $m{'tgt'} = $l[2];
  1011. print "OK: dep=\"$m{'dep'}\", ".
  1012. "dir=\"$m{'dir'}\", tgt=\"$m{'tgt'}\"\n"
  1013. if ($verbose);
  1014. # check USE_PERL5
  1015. if ($m{'dep'} =~ /^perl5(\.\d+)?$/) {
  1016. &perror("WARN", $file, -1, "dependency to perl5 ".
  1017. "listed in $j. consider using ".
  1018. "USE_PERL5.");
  1019. }
  1020. # check USE_ICONV
  1021. if ($m{'dep'} =~ /^(iconv\.\d+)$/) {
  1022. &perror("WARN", $file, -1, "dependency to $1 ".
  1023. "listed in $j. consider using ".
  1024. "USE_ICONV.");
  1025. }
  1026. # check USE_GETTEXT
  1027. if ($m{'dep'} =~ /^(intl\.\d+)$/) {
  1028. &perror("WARN", $file, -1, "dependency to $1 ".
  1029. "listed in $j. consider using ".
  1030. "USE_GETTEXT.");
  1031. }
  1032. # check USE_GMAKE
  1033. if ($m{'dep'} =~ /^(gmake|\${GMAKE})$/) {
  1034. &perror("WARN", $file, -1, "dependency to $1 ".
  1035. "listed in $j. consider using ".
  1036. "USE_GMAKE.");
  1037. }
  1038. # check USE_QT
  1039. if ($m{'dep'} =~ /^(qt\d)+$/) {
  1040. &perror("WARN", $file, -1, "dependency to $1 ".
  1041. "listed in $j. consider using ".
  1042. "USE_QT.");
  1043. }
  1044. # check LIBLTDL
  1045. if ($m{'dep'} =~ /^(ltdl\.\d)+$/) {
  1046. &perror("WARN", $file, -1, "dependency to $1 ".
  1047. "listed in $j. consider using ".
  1048. "USE_LIBLTDL.");
  1049. }
  1050. # check CDRTOOLS
  1051. if ($m{'dir'} =~ /(cdrtools|cdrtools-cjk)$/) {
  1052. &perror("WARN", $file, -1, "dependency to $1 ".
  1053. "listed in $j. consider using ".
  1054. "USE_CDRTOOLS.");
  1055. }
  1056. # check GHOSTSCRIPT
  1057. if ($m{'dep'} eq "gs") {
  1058. &perror("WARN", $file, -1, "dependency to gs ".
  1059. "listed in $j. consider using ".
  1060. "USE_GHOSTSCRIPT(_BUILD|_RUN).");
  1061. }
  1062. # check JAVALIBDIR
  1063. if ($m{'dep'} =~ m|share/java/classes|) {
  1064. &perror("FATAL", $file, -1, "you should use \${JAVALIBDIR} ".
  1065. "in BUILD_DEPENDS/RUN_DEPENDS to define ".
  1066. "dependencies on JAR files installed in ".
  1067. "\${JAVAJARDIR}");
  1068. }
  1069. # check backslash in LIB_DEPENDS
  1070. if ($osname eq 'NetBSD' && $j eq 'LIB_DEPENDS'
  1071. && $m{'dep'} =~ /\\\\./) {
  1072. &perror("WARN", $file, -1, "use of backslashes in ".
  1073. "$j is deprecated.");
  1074. }
  1075. # check for PREFIX
  1076. if ($m{'dep'} =~ /\${PREFIX}/) {
  1077. &perror("FATAL", $file, -1, "\${PREFIX} must not be ".
  1078. "contained in *_DEPENDS. ".
  1079. "use \${LOCALBASE} instead.");
  1080. }
  1081. # Check for direct dependency on apache.
  1082. if ($m{'dep'} =~ /\/www\/apache\d*\//) {
  1083. &perror("FATAL", $file, -1, "do not depend on any apache ".
  1084. "port in *_DEPENDS directly. ".
  1085. "Instead use USE_APACHE=VERSION, where VERSION can be ".
  1086. "found in \${PORTSDIR}/Mk/bsd.apache.mk.");
  1087. }
  1088. # Check for over-specific shared library dependencies
  1089. if ($j eq 'LIB_DEPENDS' && $m{'dep'} =~ m/(\.\d+$)/) {
  1090. &perror("WARN", $file, -1, "$j don't specify the " .
  1091. "ABI version number $1 in $m{'dep'} unless it is " .
  1092. "really necessary.");
  1093. }
  1094. # check port dir existence
  1095. $k = $m{'dir'};
  1096. $k =~ s/\${PORTSDIR}/$ENV{'PORTSDIR'}/;
  1097. $k =~ s/\$[\({]PORTSDIR[\)}]/$ENV{'PORTSDIR'}/;
  1098. if (! -d $k) {
  1099. &perror("WARN", $file, -1, "no port directory $k ".
  1100. "found, even though it is ".
  1101. "listed in $j.");
  1102. } else {
  1103. print "OK: port directory $k found.\n"
  1104. if ($verbose);
  1105. }
  1106. }
  1107. }
  1108. }
  1109. #
  1110. # Makefile
  1111. #
  1112. sub checkmakefile {
  1113. my($file) = @_;
  1114. my($rawwhole, $whole, $idx, @sections);
  1115. my($i, $j, $k, $l);
  1116. my @cat = ();
  1117. my $has_lang_cat = 0;
  1118. my $port_lang = '';
  1119. my $tmp;
  1120. my $bogusdistfiles = 0;
  1121. my @varnames = ();
  1122. my($portname, $portversion, $distfiles, $distversionprefix, $distversion, $distversionsuffix, $distname, $extractsufx) = ('') x 8;
  1123. my $masterport = 0;
  1124. my $slaveport = 0;
  1125. my $use_gnome_hack = 0;
  1126. my $use_java = 0;
  1127. my $use_ant = 0;
  1128. my($realwrksrc, $wrksrc, $nowrksubdir) = ('', '', '');
  1129. my(@mman, @pman);
  1130. my(@mopt, @oopt);
  1131. my(@nmopt, @noopt);
  1132. my($pkg_version, $versiondir, $versionfile) = ('', '', '');
  1133. my $useindex = 0;
  1134. my %deprecated = ();
  1135. my @deplist = ();
  1136. my %autocmdnames = ();
  1137. my $pre_mk_line = 0;
  1138. my $options_mk_line = 0;
  1139. my $docsused = 0;
  1140. my $nlsused = 0;
  1141. my $newoptused = 0;
  1142. open(IN, "< $file") || return 0;
  1143. $rawwhole = '';
  1144. $tmp = 0;
  1145. while (<IN>) {
  1146. if ($_ =~ /[ \t]+\n?$/) {
  1147. &perror("WARN", $file, $., "whitespace before ".
  1148. "end of line.");
  1149. }
  1150. if ($_ =~ /^ /) { # 8 spaces here!
  1151. &perror("WARN", $file, $., "use tab (not space) to make ".
  1152. "indentation");
  1153. }
  1154. if ($usetabs) {
  1155. if (m/^[A-Za-z0-9_-]+.?= /) {
  1156. if (m/[?+]=/) {
  1157. &perror("WARN", $file, $., "use a tab (not space) after a ".
  1158. "variable name");
  1159. } else {
  1160. &perror("FATAL", $file, $., "use a tab (not space) after a ".
  1161. "variable name");
  1162. }
  1163. }
  1164. }
  1165. #
  1166. # I'm still not very convinced, for using this kind of magical word.
  1167. # 1. This kind of items are not important for Makefile;
  1168. # portlint should not require any additional rule to Makefile.
  1169. # portlint should simply implement items that are declared in Handbook.
  1170. # 2. If we have LINTSKIP, we can't stop people using LINTSKIP too much.
  1171. # IMHO it is better to warn the user and let the user think twice,
  1172. # than let the user escape from portlint.
  1173. # Uncomment this part if you are willing to use these magical words.
  1174. # Thu Jun 26 11:37:56 JST 1997
  1175. # -- itojun
  1176. #
  1177. # if ($_ =~ /^# LINTSKIP\n?$/) {
  1178. # print "OK: skipping from line $. in $file.\n"
  1179. # if ($verbose);
  1180. # $tmp = 1;
  1181. # next;
  1182. # }
  1183. # if ($_ =~ /^# LINTAGAIN\n?$/) {
  1184. # print "OK: check start again from line $. in $file.\n"
  1185. # if ($verbose);
  1186. # $tmp = 0;
  1187. # next;
  1188. # }
  1189. # if ($_ =~ /# LINTIGNORE/) {
  1190. # print "OK: ignoring line $. in $file.\n" if ($verbose);
  1191. # next;
  1192. # }
  1193. # next if ($tmp);
  1194. $rawwhole .= $_;
  1195. }
  1196. close(IN);
  1197. #
  1198. # whole file: blank lines.
  1199. #
  1200. $whole = "\n" . $rawwhole;
  1201. study $whole;
  1202. print "OK: checking contiguous blank lines in $file.\n"
  1203. if ($verbose);
  1204. $i = "\n" x ($contblank + 2);
  1205. if ($whole =~ /$i/) {
  1206. my $lineno = &linenumber($`);
  1207. &perror("FATAL", $file, $lineno, "contiguous blank lines ".
  1208. "(> $contblank lines) found.");
  1209. }
  1210. #
  1211. # whole file: header
  1212. #
  1213. my @lines = split("\n", $whole);
  1214. print "OK: checking header in $file.\n" if ($verbose);
  1215. if ($lines[1] =~ /^# (?:New )?[Pp]orts collection [mM]akefile/) {
  1216. &perror("FATAL", $file, 1, "old style headers found.");
  1217. } elsif ($lines[1] =~ /^# Created by: \S/) {
  1218. if ($lines[2] !~ /^# \$$rcsidstr[:\$]/) {
  1219. &perror("FATAL", $file, 2, "header should be ".
  1220. "followed by \$$rcsidstr\$.");
  1221. } elsif ($lines[3] !~ /^$/) {
  1222. #&perror("FATAL", $file, 3, "do not add extra ".
  1223. # "empty comments after header.");
  1224. }
  1225. } elsif ($lines[1] !~ /^# \$$rcsidstr[:\$]/ or $lines[2] !~ /^$/) {
  1226. &perror("FATAL", $file, 1, "incorrect header; ".
  1227. "use Created by: with a single space, then \$$rcsidstr\$.");
  1228. }
  1229. #
  1230. # whole file: $(VARIABLE)
  1231. #
  1232. if ($parenwarn) {
  1233. print "OK: checking for \$(VARIABLE).\n" if ($verbose);
  1234. if ($whole =~ /\$\([\w\d]+\)/) {
  1235. my $lineno = &linenumber($`);
  1236. &perror("WARN", $file, $lineno, "use \${VARIABLE}, instead of ".
  1237. "\$(VARIABLE).");
  1238. }
  1239. }
  1240. #
  1241. # whole file: empty(${VARIABLE})
  1242. #
  1243. if ($parenwarn) {
  1244. print "OK: checking for empty(\${VARIABLE}).\n" if ($verbose);
  1245. if ($whole =~ /empty\(\${[\w\d]+/) {
  1246. my $lineno = &linenumber($`);
  1247. &perror("WARN", $file, $lineno, "use empty(VARIABLE), instead of ".
  1248. "empty(\${VARIABLE}).");
  1249. }
  1250. }
  1251. #
  1252. # whole file: use of !=
  1253. #
  1254. print "OK: checking for use of !=.\n" if ($verbose);
  1255. if ($whole =~ /^[\w\d_]+\!=/m) {
  1256. my $lineno = &linenumber($`);
  1257. &perror("WARN", $file, $lineno, "use of != in assignments is almost ".
  1258. "never a good thing to do. Try to avoid using them. See ".
  1259. "http://lists.freebsd.org/pipermail/freebsd-ports/2008-July/049777.html ".
  1260. "for some helpful hints on what to do instead.");
  1261. }
  1262. #
  1263. # whole file: use of .elseif
  1264. #
  1265. print "OK: checking for use of .elseif.\n" if ($verbose);
  1266. if ($whole =~ /^\.\s*else\s*if/m) {
  1267. my $lineno = &linenumber($`);
  1268. &perror("FATAL", $file, $lineno, "use of .elseif (or .else if) is not
  1269. supported in all versions of FreeBSD. Use .elif instead.");
  1270. }
  1271. #
  1272. # whole file: PLIST_FILES and PLIST_DIRS
  1273. #
  1274. print "OK: checking PLIST_FILES and PLIST_DIRS.\n" if ($verbose);
  1275. if ($whole =~ /\nPLIST_FILES.?=/ || $whole =~ /\nPLIST_DIRS.?=/) {
  1276. if (-f 'pkg-plist') {
  1277. my $lineno = &linenumber($`);
  1278. &perror("WARN", $file, $lineno, "You may remove pkg-plist ".
  1279. "if you use PLIST_FILES and/or PLIST_DIRS.");
  1280. }
  1281. my @plist_files = split(/\s+/, $makevar{PLIST_FILES});
  1282. foreach my $plist_file (@plist_files) {
  1283. if ($plist_file =~ m|lib[^\/]+\.so(\.\d+)?$| &&
  1284. $makevar{USE_LDCONFIG} eq '') {
  1285. &perror("WARN", "", -1, "PLIST_FILES: installing shared libraries, ".
  1286. "please define USE_LDCONFIG as appropriate");
  1287. }
  1288. if ($plist_file =~ m|\.omf$| && $makevar{INSTALLS_OMF} eq '') {
  1289. &perror("WARN", "", -1, "PLIST_FILES: installing OMF files, ".
  1290. "please define INSTALLS_OMF (see the FreeBSD GNOME ".
  1291. "porting guide at ".
  1292. "http://www.FreeBSD.org/gnome/docs/porting.html ".
  1293. "for more details)");
  1294. }
  1295. if ($plist_file =~ m|\.core$| && $plist_file !~ /^\@/) {
  1296. &perror("WARN", "", -1, "this port installs a file which ".
  1297. "ends in \".core\". This file may be deleted if ".
  1298. "daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ".
  1299. "If possible, install this file with a different name.");
  1300. }
  1301. }
  1302. }
  1303. #
  1304. # whole file: USE_* and others variables used too late
  1305. #
  1306. my @options_early = qw(
  1307. OPTIONS
  1308. OPTIONS_DEFAULT
  1309. OPTIONS_DEFINE
  1310. OPTIONS_EXCLUDE
  1311. OPTIONS_GROUP.*?
  1312. OPTIONS_MULTI.*?
  1313. OPTIONS_RADIO.*?
  1314. OPTIONS_SINGLE.*?
  1315. );
  1316. pos($whole) = 0;
  1317. if ($whole =~ /^\.include\s+<bsd\.port\.pre\.mk>$/gm) {
  1318. # Remember position
  1319. $pre_mk_line = &linenumber($`) + 1;
  1320. print "OK: checking for USE_* used too late.\n" if ($verbose);
  1321. my @use_early = qw(
  1322. BZIP2
  1323. GNUSTEP
  1324. IMAKE
  1325. KDE(?:BASE|LIBS)_VER
  1326. (?:LIB)?RUBY
  1327. LINUX_PREFIX
  1328. OPENSSL
  1329. PYTHON
  1330. QT2?
  1331. QT_VER
  1332. X_PREFIX
  1333. ZIP
  1334. );
  1335. my @other_early = qw(
  1336. EMACS_PORT_NAME
  1337. );
  1338. my $earlypattern = join('|', 'USE_(?:'.join('|', @use_early).')',
  1339. @other_early, @options_early);
  1340. while ($whole =~ /^($earlypattern)[+?:!]?=/gmo) {
  1341. my $lineno = &linenumber($`);
  1342. &perror("FATAL", $file, $lineno, "$1 is set after ".
  1343. "including bsd.port.pre.mk.");
  1344. }
  1345. }
  1346. #
  1347. # whole file: check OPTIONS
  1348. #
  1349. print "OK: checking OPTIONS.\n" if ($verbose);
  1350. pos($whole) = 0;
  1351. if ($whole =~ /^\.include\s+<bsd\.port\.options\.mk>$/gm) {
  1352. # Remember position
  1353. $options_mk_line = &linenumber($`) + 1;
  1354. }
  1355. pos($whole) = 0;
  1356. if ($whole =~ /^\.include\s+<bsd\.port\.options\.mk>$/gm) {
  1357. my $earlypattern = join('|', @options_early);
  1358. while ($whole =~ /^($earlypattern)[+?]?=/gmo) {
  1359. my $lineno = &linenumber($`);
  1360. &perror("FATAL", $file, $lineno, "$1 is set after ".
  1361. "including bsd.port.options.mk.");
  1362. }
  1363. }
  1364. pos($whole) = 0;
  1365. if ($whole =~ /\nOPTIONS_DEFINE[+?]?=/) {
  1366. $newoptused++;
  1367. }
  1368. @oopt = ($makevar{OPTIONS} =~ /(\w+)\s+\".*?\"\s+\w+/sg);
  1369. @noopt = split(/\s+/, $makevar{OPTIONS_DEFINE});
  1370. if (scalar(@oopt) && $newoptused) {
  1371. &perror("FATAL", $file, -1, "Both old and new OPTIONS are found. ".
  1372. "Remove one or another.");
  1373. }
  1374. if (scalar(@oopt)) {
  1375. &perror("WARN", $file, -1, "Use of OPTIONS is obsolete. Use the ".
  1376. "new options framework.");
  1377. }
  1378. pos($whole) = 0;
  1379. while ($whole =~ /\(?\s*WITH(?:OUT)?_(\w+)\s*\)?/mg) {
  1380. push @mopt, $1;
  1381. my $lineno = &linenumber($`) + 1;
  1382. &perror("FATAL", $file, $lineno, "option WITH(OUT)_$1 is used before ".
  1383. "including bsd.port.pre.mk or bsd.port.options.mk.")
  1384. if (scalar(@oopt) && $lineno < $pre_mk_line &&
  1385. $lineno < $options_mk_line);
  1386. }
  1387. foreach my $i (@oopt) {
  1388. if (!grep(/^$i$/, @mopt)) {
  1389. &perror("WARN", $file, -1, "$i is listed in OPTIONS, ".
  1390. "but neither WITH_$i nor WITHOUT_$i appears.");
  1391. }
  1392. }
  1393. if ($newoptused) {
  1394. pos($whole) = 0;
  1395. while ($whole =~ /PORT_OPTIONS:M(\w+)/mg) {
  1396. push @nmopt, $1;
  1397. my $lineno = &linenumber($`) + 1;
  1398. &perror("FATAL", $file, $lineno, "option $1 is used before ".
  1399. "including bsd.port.pre.mk or bsd.port.options.mk.")
  1400. if ($newoptused && $lineno < $pre_mk_line &&
  1401. $lineno < $options_mk_line);
  1402. }
  1403. foreach my $i (@noopt) {
  1404. if (!grep(/^$i$/, @nmopt)) {
  1405. &perror("WARN", $file, -1, "$i is listed in OPTIONS_DEFINE, ".
  1406. "but no PORT_OPTIONS:M$i appears.");
  1407. }
  1408. }
  1409. }
  1410. foreach my $i (@mopt) {
  1411. next if ($i eq 'NLS'); # skip WITHOUT_NLS
  1412. if (!grep(/^$i$/, @oopt)) {
  1413. # XXX: disable temporarily.
  1414. # OPTIONS is still "in flux"
  1415. #&perror("WARN: $file: WITH_$i or WITHOUT_$i appears, ".
  1416. # "consider using OPTIONS macro.");
  1417. }
  1418. }
  1419. #
  1420. # whole file: USE_* as a user-settable option
  1421. #
  1422. print "OK: checking for USE_* as a user-settable option.\n" if ($verbose);
  1423. while ($whole =~ /\n\s*\.\s*(?:el)?if[^\n]*?\b(\w*USE_)(\w+)(?![^\n]*\n#?\.error)/g) {
  1424. my $lineno = &linenumber($`);
  1425. &perror("WARN", $file, $lineno, "is $1$2 a user-settable option? ".
  1426. "Consider using WITH_$2 instead.")
  1427. if ($1.$2 ne 'USE_GCC');
  1428. }
  1429. #
  1430. # whole file: NO_CHECKSUM
  1431. #
  1432. # XXX Don't compress newlines since it messes up line number calculation.
  1433. #$whole =~ s/\n#[^\n]*/\n/g;
  1434. #$whole =~ s/\n\n+/\n/g;
  1435. print "OK: checking NO_CHECKSUM.\n" if ($verbose);
  1436. if ($whole =~ /\nNO_CHECKSUM/) {
  1437. my $lineno = &linenumber($`);
  1438. &perror("FATAL", $file, $lineno, "NO_CHECKSUM is a user ".
  1439. "variable and is not to be set in a port's Makefile.");
  1440. }
  1441. #
  1442. # whole file: USE_SIZE
  1443. #
  1444. print "OK: checking USE_SIZE.\n" if ($verbose);
  1445. if ($whole =~ /\nUSE_SIZE/) {
  1446. my $lineno = &linenumber($`);
  1447. &perror("WARN", $file, $lineno, "use of USE_SIZE is no longer ".
  1448. "required.");
  1449. }
  1450. #
  1451. # whole file: MACHINE_ARCH
  1452. #
  1453. print "OK: checking MACHINE_ARCH.\n" if ($verbose);
  1454. if ($whole =~ /\nMACHINE_ARCH/) {
  1455. my $lineno = &linenumber($`);
  1456. &perror("FATAL", $file, $lineno, "MACHINE_ARCH should never be ".
  1457. "overridden.");
  1458. }
  1459. #
  1460. # whole file: DEPRECATED
  1461. #
  1462. print "OK: checking DEPRECATED.\n" if ($verbose);
  1463. if ($whole =~ /\nDEPRECATED[+?]?=[ \t]*"/ &&
  1464. $whole !~ /\nDEPRECATED[+?]?=[ \t]*"\$\{BROKEN\}"/) {
  1465. my $lineno = &linenumber($`);
  1466. &perror("WARN", $file, $lineno, "DEPRECATED messages should not ".
  1467. "be quoted unless they are exactly \"\${BROKEN}\".");
  1468. }
  1469. if ($whole =~ /\nDEPRECATED[+?]?=[^"]*\$\{BROKEN\}/) {
  1470. my $lineno = &linenumber($`);
  1471. &perror("WARN", $file, $lineno, "\"\${BROKEN}\" must be quoted ".
  1472. "when it is the source of DEPRECATED.");
  1473. }
  1474. #
  1475. # whole file: BROKEN et al.
  1476. #
  1477. my ($var);
  1478. foreach $var (qw(IGNORE BROKEN COMMENT FORBIDDEN MANUAL_PACKAGE_BUILD NO_CDROM NO_PACKAGE RESTRICTED)) {
  1479. print "OK: checking ${var}.\n" if ($verbose);
  1480. if ($whole =~ /\n${var}[+?]?=[ \t]+"/) {
  1481. my $lineno = &linenumber($`);
  1482. &perror("WARN", $file, $lineno, "${var} messages should not ".
  1483. "be quoted.");
  1484. }
  1485. }
  1486. if ($whole =~ /\nIGNORE[+?]?=[ \t]+[^a-z \t]/ ||
  1487. $whole =~ /^IGNORE[+?]?=[ \t]+.*\.$/m) {
  1488. my $lineno = &linenumber($`);
  1489. &perror("WARN", $file, $lineno, "IGNORE messages should begin ".
  1490. "with a lowercase letter and end without a period.");
  1491. }
  1492. #
  1493. # whole file: PKGNAME
  1494. #
  1495. print "OK: checking PKGNAME.\n" if ($verbose);
  1496. if ($whole =~ /\nPKGNAME.?=/) {
  1497. my $lineno = &linenumber($`);
  1498. &perror("FATAL", $file, $lineno, "PKGNAME is obsoleted by PORTNAME, ".
  1499. "PORTVERSION, PKGNAMEPREFIX and PKGNAMESUFFIX.");
  1500. }
  1501. #
  1502. # whole file: USE_REINPLACE
  1503. #
  1504. print "OK: checking for USE_REINPLACE.\n" if ($verbose);
  1505. if ($whole =~ /\nUSE_REINPLACE.?=/) {
  1506. my $lineno = &linenumber($`);
  1507. &perror("WARN", $file, $lineno, "USE_REINPLACE is now obsolete. ".
  1508. "You can safely use REINPLACE_CMD without it.");
  1509. }
  1510. #
  1511. # whole file: MAKE_JOBS_[UN]SAFE
  1512. #
  1513. print "OK: checking for MAKE_JOBS_SAFE in combination with NO_BUILD.\n" if ($verbose);
  1514. if ($whole =~ /\n(MAKE_JOBS_(UN)?SAFE).?=/) {
  1515. my $matched = $1;
  1516. if ($whole =~ /\nNO_BUILD.?=/) {
  1517. my $lineno = &linenumber($`);
  1518. &perror("WARN", $file, $lineno, "$matched should not ".
  1519. "be used in combination with NO_BUILD. You ".
  1520. "should remove $matched from your Makefile.");
  1521. }
  1522. }
  1523. #
  1524. # whole file: USE_GETOPT_LONG
  1525. #
  1526. print "OK: checking for USE_GETOPT_LONG.\n" if ($verbose);
  1527. if ($whole =~ /\nUSE_GETOPT_LONG.?=/) {
  1528. my $lineno = &linenumber($`);
  1529. &perror("WARN", $file, $lineno, "USE_GETOPT_LONG is now obsolete. ".
  1530. "You can safely remove this macro from your Makefile.");
  1531. }
  1532. #
  1533. # whole file: USE_GNOME=pkgconfig
  1534. #
  1535. print "OK: checking for USE_GNOME=pkgconfig.\n" if ($verbose);
  1536. if ($makevar{USE_GNOME} =~ /pkgconfig/) {
  1537. &perror("WARN", $file, -1, "USE_GNOME=pkgconfig is now obsolete. ".
  1538. "Use USE_PKGCONFIG instead.");
  1539. }
  1540. #
  1541. # whole file: EXPIRATION_DATE
  1542. #
  1543. print "OK: checking for valid EXPIRATION_DATE.\n" if ($verbose);
  1544. my $edate;
  1545. if (($edate) = ($whole =~ m/\nEXPIRATION_DATE\??=[ \t]*([^\n]*)\n/)) {
  1546. my $lineno = &linenumber($`);
  1547. if ($edate ne strftime("%Y-%m-%d", 0, 0, 0,
  1548. substr($edate, 8, 2),
  1549. substr($edate, 5, 2) - 1,
  1550. substr($edate, 0, 4) - 1900)) {
  1551. &perror("FATAL", $file, $lineno, "EXPIRATION_DATE ($edate) is ".
  1552. "either not in YYYY-MM-DD format or it is not a valid ".
  1553. "date.");
  1554. }
  1555. }
  1556. #
  1557. # whole file: IS_INTERACTIVE/NOPORTDOCS|PORT_OPTIONS:MDOCS
  1558. #
  1559. print "OK: checking IS_INTERACTIVE.\n" if ($verbose);
  1560. if ($whole =~ /\nIS_INTERACTIVE/) {
  1561. if ($whole !~ /defined\((BATCH|FOR_CDROM)\)/) {
  1562. my $lineno = &linenumber($`);
  1563. &perror("WARN", $file, $lineno, "use of IS_INTERACTIVE ".
  1564. "discouraged. provide batch mode by using BATCH and/or ".
  1565. "FOR_CDROM.");
  1566. }
  1567. }
  1568. print "OK: checking for use of PORT_OPTIONS:MDOCS.\n" if ($verbose);
  1569. if ($sharedocused && $whole =~ /PORT_OPTIONS:MDOCS/) {
  1570. $docsused++;
  1571. }
  1572. print "OK: checking for use of NOPORTDOCS.\n" if ($verbose);
  1573. if ($whole =~ /NOPORTSDOC/) {
  1574. my $lineno = &linenumber($`);
  1575. &perror("WARN", $file, $lineno, "NOPORTSDOC found. Do you ".
  1576. "mean NOPORTDOCS?");
  1577. }
  1578. if ($sharedocused && $whole !~ /defined\s*\(?NOPORTDOCS\)?/
  1579. && $whole !~ /def\s*\(?NOPORTDOCS\)?/) {
  1580. if ($docsused == 0 && $whole !~ m#(\$[\{\(]PREFIX[\}\)]|$localbase)/share/doc#) {
  1581. &perror("WARN", $file, -1, "use \".if !defined(NOPORTDOCS)\" to wrap ".
  1582. "installation of files into $localbase/share/doc.");
  1583. }
  1584. } else {
  1585. $docsused++;
  1586. }
  1587. if ($docsused > 1) {
  1588. &perror("FATAL", $file, -1, "Both NOPORTDOCS and PORT_OPTIONS:MDOCS are found. ".
  1589. "Remove one or another.");
  1590. }
  1591. print "OK: checking for use of NOPORTDOCS.\n" if ($verbose);
  1592. if ($whole =~ /NOPORTDOCS/) {
  1593. my $lineno = &linenumber($`);
  1594. &perror("WARN", $file, $lineno, "NOPORTDOCS found. Consider ".
  1595. "using PORT_OPTIONS:MDOCS");
  1596. }
  1597. #
  1598. # whole file: check for USE_GETTEXT
  1599. #
  1600. print "OK: checking for USE_GETTEXT without PORT_OPTIONS:MNLS.\n" if ($verbose);
  1601. if ($whole =~ /\nUSE_GETTEXT/ && $whole =~ /PORT_OPTIONS:MNLS/) {
  1602. $nlsused++;
  1603. }
  1604. print "OK: checking for USE_GETTEXT without WITHOUT_NLS.\n" if ($verbose);
  1605. if ($whole =~ /\nUSE_GETTEXT/ && $whole !~ /def(?:ined)?\s*\(?WITHOUT_NLS\)?/) {
  1606. if ($nlsused == 0) {
  1607. &perror("WARN", $file, -1, "Consider adding support for a WITHOUT_NLS ".
  1608. "knob to conditionally disable gettext support.");
  1609. }
  1610. } else {
  1611. $nlsused++;
  1612. }
  1613. if ($nlsused > 1) {
  1614. &perror("FATAL", $file, -1, "Both WITHOUT_NLS and PORT_OPTIONS:MNLS are found. ".
  1615. "Remove one or another.");
  1616. }
  1617. #
  1618. # whole file: check for deprecated commands
  1619. #
  1620. print "OK: checking for deprecated macros.\n" if $verbose;
  1621. %deprecated = (
  1622. USE_MESA => 'USE_GL',
  1623. USE_RCORDER => 'USE_RC_SUBR',
  1624. INSTALLS_SHLIB => 'USE_LDCONFIG',
  1625. APACHE_COMPAT => 'USE_APACHE',
  1626. USE_XPM => 'USE_X11=xpm',
  1627. );
  1628. @deplist = (\%deprecated);
  1629. for my $dlst (@deplist) {
  1630. my $hurl = $dlst->{'__HELP__'};
  1631. foreach my $depmacro (keys %{$dlst}) {
  1632. if ($whole =~ /\n($depmacro)[+?:!]?=/) {
  1633. my $derror = "$depmacro is ".
  1634. "deprecated, use $dlst->{$1} instead";
  1635. if (defined($hurl)) {
  1636. $derror .= " (see $hurl for more details)";
  1637. }
  1638. &perror("FATAL", $file, -1, $derror);
  1639. }
  1640. }
  1641. }
  1642. #
  1643. # whole file: DOS line endings
  1644. #
  1645. print "OK: checking for DOS line ending removal.\n" if ($verbose);
  1646. if ($whole =~ / / || $whole =~ /:cntrl:/) {
  1647. my $lineno = &linenumber($`);
  1648. &perror("WARN", $file, $lineno, "Possible manual removal of DOS ".
  1649. "line endings found. Consider defining USE_DOS2UNIX instead.");
  1650. }
  1651. #
  1652. # whole file: direct use of command names
  1653. #
  1654. my %cmdnames = ();
  1655. print "OK: checking direct use of command names.\n" if ($verbose);
  1656. foreach my $i (qw(
  1657. awk basename brandelf cat chmod chown cp cpio dialog dirname egrep expr
  1658. false file find gmake grep gzcat ldconfig ln md5 mkdir mv objcopy paste patch
  1659. pax perl printf rm rmdir pkg_add pkg_delete pkg_info pkg_version
  1660. ruby sed sh sort sysctl touch tr which xargs xmkmf
  1661. )) {
  1662. $cmdnames{$i} = "\$\{\U$i\E\}";
  1663. }
  1664. $cmdnames{'echo'} = '${ECHO_CMD} or ${ECHO_MSG}';
  1665. $cmdnames{'env'} = '${SETENV}';
  1666. $cmdnames{'gunzip'} = '${GUNZIP_CMD}';
  1667. $cmdnames{'gzip'} = '${GZIP_CMD}';
  1668. $cmdnames{'install'} = '${INSTALL_foobaa}';
  1669. $cmdnames{'python'} = '${PYTHON_CMD}';
  1670. $cmdnames{'strip'} = '${STRIP_CMD}';
  1671. $cmdnames{'unzip'} = '${UNZIP_CMD}';
  1672. $cmdnames{'pkg_create'} = '${PKG_CMD}';
  1673. foreach my $i (qw(aclocal autoconf autoheader automake autoreconf autoupdate autoscan ifnames libtool libtoolize)) {
  1674. $autocmdnames{$i} = "\$\{" . ( ( $i !~ /auto|aclocal|libtool/ ) ? "AUTO" : "" ) . "\U$i\E\}";
  1675. }
  1676. #
  1677. # ignore parameter string to echo command.
  1678. # note that we leave the command as is, since we need to check the
  1679. # use of echo itself.
  1680. $j = $whole;
  1681. $j =~ s/([ \t][\@\-]{0,2})(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+(?:"(?:\\'|\\"|[^"])*"|'(?:\\'|\\"|[^'])*')[ \t]*;?(\n?)/$1$2;$3/g; #"
  1682. # ignore variables names in .for loops, but not what's at the end
  1683. # of the for loop
  1684. $j =~ s/(\.for +)([^ ]*)( .*)/$1$3/;
  1685. foreach my $i (keys %cmdnames) {
  1686. # XXX This is a hack. Really, we should break $j up into individual
  1687. # lines, and go through each one.
  1688. while ($j =~ /^(.*$i.*)$/gm) {
  1689. my $curline = $1;
  1690. my $lineno = &linenumber($`);
  1691. if ($curline =~ /(?:^|\s)[\@\-]{0,2}$i(?:$|\s)/
  1692. && $curline !~ /^[A-Z]+_TARGET[?+]?=[^\n]+$i/m
  1693. && $curline !~ /^IGNORE(.)?=[^\n]+$i/m
  1694. && $curline !~ /^BROKEN(.)?=[^\n]+$i/m
  1695. && $curline !~ /^RESTRICTED(.)?=[^\n]+$i/m
  1696. && $curline !~ /^NO_PACKAGE(.)?=[^\n]+$i/m
  1697. && $curline !~ /^NO_CDROM(.)?=[^\n]+$i/m
  1698. && $curline !~ /^MAINTAINER(.)?=[^\n]+$i/m
  1699. && $curline !~ /^CATEGORIES(.)?=[^\n]+$i/m
  1700. && $curline !~ /^WX_COMPS(.)?=[^\n]+$i/m
  1701. && $curline !~ /^\s*#.+$/m
  1702. && $curline !~ /\-\-$i/m
  1703. && $curline !~ /^COMMENT(.)?=[^\n]+$i/m) {
  1704. &perror("WARN", $file, $lineno, "possible direct use of ".
  1705. "command \"$i\" found. use ".
  1706. "$cmdnames{$i} instead.");
  1707. }
  1708. }
  1709. }
  1710. foreach my $i (keys %autocmdnames) {
  1711. # XXX Same hack as above.
  1712. while ($j =~ /^(.*($i\d*).*)$/gm) {
  1713. my $lm = $1;
  1714. my $sm = $2;
  1715. my $lineno = &linenumber($`);
  1716. if ($lm =~ /(^|\s+)[\@\-]{0,2}($i\d*)\b/
  1717. && $lm !~ /^[A-Z]+_TARGET[?+]?=[^\n]+($i\d*)/m
  1718. && $lm !~ /^IGNORE(.)?=[^\n]+($i\d*)/m
  1719. && $lm !~ /^BROKEN(.)?=[^\n]+($i\d*)/m
  1720. && $lm !~ /^RESTRICTED(.)?=[^\n]+($i\d*)/m
  1721. && $lm !~ /^NO_PACKAGE(.)?=[^\n]+($i\d*)/m
  1722. && $lm !~ /^NO_CDROM(.)?=[^\n]+($i\d*)/m
  1723. && $lm !~ /^MAINTAINER(.)?=[^\n]+($i\d*)/m
  1724. && $lm !~ /^CATEGORIES(.)?=[^\n]+($i\d*)/m
  1725. && $lm !~ /^USE_AUTOTOOLS(.)?=[^\n]+($i\d*)/m
  1726. && $lm !~ /^\s*#.+$/m
  1727. && $lm !~ /^COMMENT(.)?=[^\n]+($i\d*)/m) {
  1728. &perror("WARN", $file, $lineno, "possible direct use of ".
  1729. "command \"$sm\" found. Use $autocmdnames{$i} ".
  1730. "instead and set according USE_AUTOTOOLS=<tool> macro");
  1731. }
  1732. }
  1733. }
  1734. #
  1735. # whole file: check for use of paths that have macro replacements
  1736. #
  1737. my %pathnames = ();
  1738. print "OK: checking for paths that have macro replacements.\n"
  1739. if ($verbose);
  1740. $pathnames{'${PREFIX}/share/java/classes'} = 'JAVADIR';
  1741. $pathnames{'${PREFIX}/share/java'} = 'JAVASHAREDIR';
  1742. foreach my $i (keys %pathnames) {
  1743. my $lineno = &linenumber($`);
  1744. if ($j =~ m|$i|gm) {
  1745. &perror("FATAL", $file, $lineno, "you should use ".
  1746. "$pathnames{$i} rather than $i");
  1747. }
  1748. }
  1749. #
  1750. # whole file: ldconfig must come with "true" command
  1751. #
  1752. print "OK: checking that ldconfig is properly checked.\n"
  1753. if ($verbose);
  1754. if ($ldconfigwithtrue
  1755. && $j =~ /(ldconfig|\$[{(]LDCONFIG[)}])/
  1756. && $j !~ /(\/usr\/bin\/true|\$[{(]TRUE[)}])/) {
  1757. my $lineno = &linenumber($`);
  1758. &perror("FATAL", $file, $lineno, "ldconfig must be used with ".
  1759. "\"||\${TRUE}\".");
  1760. }
  1761. #
  1762. # whole file: ${GZIP_CMD} -9 (or any other number)
  1763. #
  1764. print "OK: checking for compression arguments passed to \${GZIP_CMD}.\n"
  1765. if ($verbose);
  1766. if ($j =~ /\${GZIP_CMD}\s+-(\w+(\s+-)?)*(\d)/) {
  1767. my $lineno = &linenumber($`);
  1768. &perror("WARN", $file, $lineno, "possible use of \"\${GZIP_CMD} -$3\" ".
  1769. "found. \${GZIP_CMD} includes \"-\${GZIP}\" which ".
  1770. "sets the compression level.");
  1771. }
  1772. #
  1773. # whole file: ${MKDIR} -p
  1774. #
  1775. print "OK: checking for \${MKDIR} -p.\n"
  1776. if ($verbose);
  1777. if ($j =~ /\${MKDIR}\s+-p/) {
  1778. my $lineno = &linenumber($`);
  1779. &perror("WARN", $file, $lineno, "possible use of \"\${MKDIR} -p\" ".
  1780. "found. \${MKDIR} includes ".
  1781. "\"-p\" by default.");
  1782. }
  1783. #
  1784. # check for use of ${FIND} ... ${XARGS} ${RM}
  1785. #
  1786. print "OK: checking for instances of \${FIND} ... \${XARGS} \${RM}.\n"
  1787. if ($verbose);
  1788. if ($j =~ /\$\{FIND\}.*\|.*\$\{XARGS\}.*\$\{RM\}/) {
  1789. my $lineno = &linenumber($`);
  1790. &perror("WARN", $file, $lineno, "possible use of ".
  1791. "\"\${FIND} ... \${XARGS} \${RM}\" when ".
  1792. "\"\${FIND} ... -delete\" will work.");
  1793. }
  1794. #
  1795. # whole file: ${MACHINE_ARCH}
  1796. #
  1797. print "OK: checking for instances of \${MACHINE_ARCH} being test.\n"
  1798. if ($verbose);
  1799. if ($j =~ /\${MACHINE_ARCH}\s*[!=]=/) {
  1800. my $lineno = &linenumber($`);
  1801. &perror("FATAL", $file, $lineno, "MACHINE_ARCH should never be tested ".
  1802. "directly; use ARCH instead.");
  1803. }
  1804. #
  1805. # whole file: full path name
  1806. #
  1807. &abspathname($whole, $file);
  1808. #
  1809. # whole file: SITE_PERL
  1810. #
  1811. print "OK: checking SITE_PERL.\n" if ($verbose);
  1812. if ($whole =~ /\nSITE_PERL[?:]?=/) {
  1813. my $lineno = &linenumber($`);
  1814. &perror("FATAL", $file, $lineno, "use of SITE_PERL discouraged. ".
  1815. "it is set in bsd.port.mk.");
  1816. }
  1817. #
  1818. # whole file: ${LOCALBASE}/lib/perl5/site_perl/${PERL_VER}
  1819. #
  1820. if ($j =~ m'\${(?:LOCALBASE|PREFIX)}/lib/perl5/site_perl/\${PERL_VER}') {
  1821. my $lineno = &linenumber($`);
  1822. &perror("WARN", $file, $lineno, "possible use of \"\${LOCALBASE}/lib/perl5/site_perl/\${PERL_VER}\" ".
  1823. "found. use \"\${SITE_PERL}\" instead.");
  1824. }
  1825. #
  1826. # whole file: USE_GNOME check
  1827. #
  1828. if ($whole =~ /^USE_GNOME[?:]?=\s*(.*)$/m) {
  1829. if ($1 =~ /gnomehack/) {
  1830. $use_gnome_hack = 1;
  1831. }
  1832. }
  1833. #
  1834. # whole file: USE_GCC checks
  1835. #
  1836. if ($whole =~ /^USE_GCC[?:]?=\s*(.*)$/m) {
  1837. my $lineno = &linenumber($`);
  1838. my $gcc_val = $1;
  1839. if ($gcc_val eq 'any' || $gcc_val eq 'yes') {
  1840. # Just accept these two.
  1841. } elsif ($gcc_val =~ /3\.[234]\+/) {
  1842. &perror("WARN", $file, $lineno, "USE_GCC=3.2+, USE_GCC=3.3+, ".
  1843. "and USE_GCC=3.4+ are noops on all currently (and future) ".
  1844. "supported versions of FreeBSD. Do not use them.");
  1845. } elsif ($gcc_val eq "4.1+") {
  1846. &perror("WARN", $file, $lineno, "USE_GCC=4.2+ is recommended ".
  1847. "over USE_GCC=4.1+ since the former is the system compiler ".
  1848. "for FreeBSD 7.X.");
  1849. } elsif ($gcc_val !~ /\+/ && $gcc_val ne 'any') {
  1850. &perror("WARN", $file, $lineno, "Setting a specific version for ".
  1851. "USE_GCC should only be done as a last resort. Unless you ".
  1852. "have confirmed this port does not build with later ".
  1853. "versions of GCC, please use USE_GCC=$gcc_val+.");
  1854. }
  1855. }
  1856. #
  1857. # whole file: USE_JAVA check
  1858. #
  1859. if ($whole =~ /^USE_JAVA[?:]?=\s*(.*)$/m) {
  1860. $use_java = 1;
  1861. }
  1862. #
  1863. # whole file: USE_ANT check
  1864. #
  1865. if ($whole =~ /^USE_ANT[?:]?=\s*(.*)$/m) {
  1866. $use_ant = 1;
  1867. }
  1868. #
  1869. # whole file: USE_JAVA not defined, but other Java components are requested
  1870. #
  1871. if (!$use_java && ($use_ant || $whole =~ /^JAVA_VERSION[?:]?=\s*(.*)$/m ||
  1872. $whole =~ /^JAVA_OS[?:]?=\s*(.*)$/m ||
  1873. $whole =~ /^JAVA_VENDOR[?:]?=\s*(.*)$/m ||
  1874. $whole =~ /^JAVA_RUN[?:]?=\s*(.*)$/m ||
  1875. $whole =~ /^JAVA_BUILD[?:]?=\s*(.*)$/m)) {
  1876. &perror("FATAL", $file, -1, "the port uses Java features, but USE_JAVA ".
  1877. "is not defined");
  1878. }
  1879. #
  1880. # whole file: check for USE_ANT and USE_GMAKE both defined
  1881. #
  1882. if ($use_ant && $whole =~ /^USE_GMAKE[?:]?=\s*(.*)$/m) {
  1883. &perror("WARN", $file, -1, "a port shall not define both USE_ANT ".
  1884. "and USE_GMAKE");
  1885. }
  1886. #
  1887. # whole file: check for USE_APACHE=yes
  1888. #
  1889. if ($whole =~ /^USE_APACHE[?:]?=\s*(yes)$/m) {
  1890. &perror("FATAL", $file, -1, "Use USE_APACHE=VERSION ".
  1891. "(where version can be found in \${PORTSDIR}/Mk/bsd.apache.mk) ".
  1892. "instead of yes");
  1893. }
  1894. #
  1895. # whole file: check for WITH_APACHE\d+
  1896. #
  1897. if ($whole =~ /WITH_APACHE\d+/) {
  1898. &perror("FATAL", $file, -1, "Use WITH_APACHE=yes and .if ".
  1899. "\${APACHE_VERSION} [==|<|>] 13|20|22|24");
  1900. }
  1901. #
  1902. # whole file: check for JAVA_BUILD and NO_BUILD
  1903. #
  1904. if ($whole =~ /^NO_BUILD[?:]?=\s*(.*)$/m &&
  1905. $whole =~ /^JAVA_BUILD[?:]?=\s*(.*)$/m) {
  1906. &perror("FATAL", $file, -1, "JAVA_BUILD and NO_BUILD cannot be set ".
  1907. "at the same time");
  1908. }
  1909. #
  1910. # whole file: check for reassignment of ECHO_MSG
  1911. #
  1912. if ($whole =~ /^ECHO_MSG[?:]?=\s*(.*)$/m) {
  1913. &perror("FATAL", $file, -1, "Re-assigning ECHO_MSG can break ".
  1914. "``make readme''. Consider using \${PRINTF} directly instead ".
  1915. "for custom message output.");
  1916. }
  1917. #
  1918. # whole file: check for --build, --mandir, and --infodir
  1919. # when GNU_CONFIGURE
  1920. #
  1921. if (exists $makevar{GNU_CONFIGURE} &&
  1922. $makevar{GNU_CONFIGURE} ne '' &&
  1923. $makevar{CONFIGURE_ARGS} =~ /--(build|(man|info)dir)/) {
  1924. &perror("WARN", $file, -1, "--build, --mandir, and --infodir ".
  1925. "are not needed in CONFIGURE_ARGS as they are already set in ".
  1926. "bsd.port.mk.");
  1927. }
  1928. #
  1929. # whole file: CONFIGURE_ENV
  1930. #
  1931. if ($whole =~ /\nCONFIGURE_ENV[?:+]?=\s*([^\\\n]+(\\\n[^\\\n]+)*)/) {
  1932. my $configure_env = $1;
  1933. my $cflags = undef;
  1934. my $cxxflags = undef;
  1935. if ($configure_env =~ /\bCFLAGS="([^"]+)"/ ||
  1936. $configure_env =~ /\bCFLAGS='([^']+)'/ ||
  1937. $configure_env =~ /\bCFLAGS=(\S+)/) {
  1938. $cflags = $1;
  1939. }
  1940. if ($configure_env =~ /\bCXXFLAGS="([^"]+)"/ ||
  1941. $configure_env =~ /\bCXXFLAGS='([^']+)'/ ||
  1942. $configure_env =~ /\bCXXFLAGS=(\S+)/) {
  1943. $cxxflags = $1;
  1944. }
  1945. if (defined($cflags) || defined($cxxflags)) {
  1946. &perror("WARN", $file, -1, "CFLAGS/CXXFLAGS are not needed in ".
  1947. "CONFIGURE_ENV as they are already added there in bsd.port.mk.");
  1948. }
  1949. if ($makevar{GNU_CONFIGURE} ne '') {
  1950. if ((defined($cflags) && $cflags =~ /-I/) ||
  1951. (defined($cxxflags) && $cxxflags =~ /-I/)) {
  1952. &perror("WARN", $file, -1, "Consider passing include paths ".
  1953. "to configure via the CPPFLAGS macro ".
  1954. "(i.e. CPPFLAGS+=-I...)");
  1955. }
  1956. }
  1957. if (defined($cflags) && $cflags !~ /\$\{CFLAGS/) {
  1958. &perror("FATAL", $file, -1, "CFLAGS are clobbered in ".
  1959. "CONFIGURE_ENV. Alter CFLAGS in the Makefile with ".
  1960. "CFLAGS+=... instead");
  1961. }
  1962. if (defined($cxxflags) && $cflags !~ /\$\{CXXFLAGS/) {
  1963. &perror("FATAL", $file, -1, "CXXFLAGS are clobbered in ".
  1964. "CONFIGURE_ENV. Alter CXXFLAGS in the Makefile with ".
  1965. "CXXFLAGS+=... instead");
  1966. }
  1967. if ($configure_env =~ /(FC)=/ ||
  1968. $configure_env =~ /(F77)=/ ||
  1969. $configure_env =~ /(FFLAGS)=/) {
  1970. &perror("FATAL", $file, -1, "$1 is already ".
  1971. "passed in CONFIGURE_ENV via bsd.gcc.mk. If you need to ".
  1972. "override the default value, alter $1 in the Makefile ".
  1973. "instead with $1=...");
  1974. }
  1975. if ($configure_env =~ /(\bCPPFLAGS)=/) {
  1976. &perror("FATAL", $file, -1, "$1 is already ".
  1977. "passed in CONFIGURE_ENV via bsd.port.mk. If you need to ".
  1978. "override the default value, alter $1 in the Makefile ".
  1979. "instead with $1+=...");
  1980. }
  1981. if ($configure_env =~ /(\bLDFLAGS)=/) {
  1982. &perror("FATAL", $file, -1, "$1 is already passed in ".
  1983. "CONFIGURE_ENV via bsd.port.mk. If you need to ".
  1984. "override the default value, alter $1 in the Makefile ".
  1985. "instead with $1+=...");
  1986. }
  1987. }
  1988. #
  1989. # whole file: *FLAGS
  1990. #
  1991. foreach my $f (qw(CFLAGS CXXFLAGS CPPFLAGS LDFLAGS)) {
  1992. if ($whole =~ /^$f=/m) {
  1993. &perror("WARN", $file, -1, "$f is overridden in the Makefile ".
  1994. "clobbering a value possibly set by a user. Consider ".
  1995. "using $f+=... if you want to add or $f:=\${$f:C/...//} ".
  1996. "if you want to remove specific flags");
  1997. }
  1998. }
  1999. #
  2000. # whole file: MAKE_ENV
  2001. #
  2002. if ($whole =~ /\nMAKE_ENV[?:+]?=\s*([^\\\n]+(\\\n[^\\\n]+)*)/) {
  2003. my $make_env = $1;
  2004. if ($make_env =~ /(CPPFLAGS)=/) {
  2005. &perror("FATAL", $file, -1, "$1 is already ".
  2006. "passed in MAKE_ENV via bsd.port.mk. If you need to ".
  2007. "override the default value, alter $1 in the Makefile ".
  2008. "instead with $1=...");
  2009. }
  2010. }
  2011. #
  2012. # slave port check
  2013. #
  2014. my $masterdir = $makevar{MASTERDIR};
  2015. if ($masterdir ne '' && $masterdir ne $makevar{'.CURDIR'}) {
  2016. $slaveport = 1;
  2017. print "OK: slave port detected, checking for inclusion of $masterdir/Makefile.\n"
  2018. if ($verbose);
  2019. if ($whole =~ /^\.\s*include\s*[<"]bsd\.port(?:\.post)?\.mk[">]/m) {
  2020. &perror("FATAL", $file, -1, "supposedly non-slave port with".
  2021. " .CURDIR != MASTERDIR");
  2022. } elsif ($whole =~ /^\.\s*include\s*[<"]bsd\.port\.pre\.mk[">]/m) {
  2023. &perror("FATAL", $file, -1, "slave ports may not include".
  2024. " bsd.port.pre.mk");
  2025. }
  2026. if ($whole !~ /\n\.include\s+"\$\{MASTERDIR\}\/Makefile"\s*$/s) {
  2027. &perror("FATAL", $file, -1, "the last line of a slave port's Makefile has to be".
  2028. ' .include "${MASTERDIR}/Makefile"');
  2029. }
  2030. print "OK: checking master port in $masterdir.\n" if ($verbose);
  2031. if (! -e "$masterdir/Makefile") {
  2032. &perror("WARN", "", -1, "unable to locate master port in $masterdir");
  2033. }
  2034. if ($whole !~ /^MASTERDIR=\s*\$\{\.CURDIR\}(?:\/\.\.){1,2}(?:\/[\w\@.+-]+){1,2}\s*$/m) {
  2035. &perror("WARN", $file, -1, "slave ports must define MASTERDIR=".
  2036. '${.CURDIR}/..(/../<category>)/<port>');
  2037. }
  2038. } else {
  2039. #$slaveport = 0;
  2040. print "OK: non-slave port detected, checking for anything after bsd.port(.post).mk.\n"
  2041. if ($verbose);
  2042. if ($whole !~ /\n\.include\s+<bsd\.port(?:\.post)?\.mk>\s*$/s) {
  2043. &perror("FATAL", $file, -1, "the last line of Makefile has to be".
  2044. ' .include <bsd.port(.post).mk>');
  2045. }
  2046. if ($whole =~ /^MASTERDIR\s*[+?:!]?\s*=/m) {
  2047. &perror("WARN", $file, -1, "non-slave ports may not define MASTERDIR");
  2048. }
  2049. }
  2050. #
  2051. # break the makefile into sections.
  2052. #
  2053. $tmp = $rawwhole;
  2054. # keep comment, blank line, comment in the same section
  2055. $tmp =~ s/(#.*\n)\n+(#.*)/$1$2/g;
  2056. $tmp =~ s/\\\n\n/\n/g;
  2057. @sections = split(/\n\n+/, $tmp);
  2058. for ($i = 0; $i <= $#sections; $i++) {
  2059. if ($sections[$i] !~ /\n$/) {
  2060. $sections[$i] .= "\n";
  2061. }
  2062. }
  2063. $idx = 0;
  2064. #
  2065. # section 1: comment lines.
  2066. #
  2067. print "OK: checking comment section of $file.\n" if ($verbose);
  2068. my @linestocheck = split("\n", <<EOF);
  2069. Whom
  2070. Date [cC]reated
  2071. EOF
  2072. if ($osname eq 'NetBSD') {
  2073. unshift(@linestocheck, '(New )?[pP](ackage|ort)s [cC]ollection [mM]akefile [fF]or');
  2074. }
  2075. $tmp = $sections[$idx++];
  2076. $tmp = "\n" . $tmp; # to make the begin-of-line check easier
  2077. if ($tmp =~ /\n[^#]/) {
  2078. &perror("FATAL", $file, -1, "non-comment line in comment section.");
  2079. }
  2080. if ($osname eq 'NetBSD') {
  2081. foreach my $i (@linestocheck) {
  2082. $j = $i;
  2083. $j =~ s/\(.*\)\?//g;
  2084. $j =~ s/\[(.)[^\]]*\]/$1/g;
  2085. if ($tmp !~ /# $i:[ \t]+\S+/) {
  2086. &perror("FATAL", $file, -1, "no \"$j\" line in comment section.");
  2087. } else {
  2088. print "OK: \"$j\" seen in $file.\n" if ($verbose);
  2089. }
  2090. }
  2091. }
  2092. if ($tmp =~ m/Version [rR]equired/) {
  2093. &perror("WARN", $file, -1, "Version required is no longer needed in the comment section.");
  2094. }
  2095. my $tmp2 = "";
  2096. for (split(/\n/, $tmp)) {
  2097. $tmp2 .= $_ if (m/\$$rcsidstr/);
  2098. }
  2099. if ($tmp2 !~ /#(\s+)\$$rcsidstr([^\$]*)\$$/) {
  2100. &perror("FATAL", $file, -1, "no \$$rcsidstr\$ line in comment ".
  2101. "section.");
  2102. } else {
  2103. print "OK: \$$rcsidstr\$ seen in $file.\n" if ($verbose);
  2104. if ($1 ne ' ') {
  2105. &perror("WARN", $file, -1, "please use single whitespace ".
  2106. "right before \$$rcsidstr\$ tag.");
  2107. }
  2108. if ($2 ne '') {
  2109. if ($verbose || $newport) { # XXX
  2110. &perror("WARN", $file, -1,
  2111. ($newport ? 'for new port, '
  2112. : 'is it a new port? if so, ').
  2113. "make \$$rcsidstr\$ tag in comment ".
  2114. "section empty, to make SVN happy.");
  2115. }
  2116. }
  2117. }
  2118. #
  2119. # for the rest of the checks, comment lines are not important.
  2120. #
  2121. for ($i = 0; $i < scalar(@sections); $i++) {
  2122. $sections[$i] = "\n" . $sections[$i];
  2123. $sections[$i] =~ s/\n#[^\n]*//g;
  2124. $sections[$i] =~ s/\n\n+/\n/g;
  2125. $sections[$i] =~ s/\\\n/ /g;
  2126. $sections[$i] =~ s/^\n//;
  2127. }
  2128. #
  2129. # section 2: PORTNAME/PORTVERSION/...
  2130. #
  2131. print "OK: checking first section of $file (PORTNAME/...).\n"
  2132. if ($verbose);
  2133. $tmp = $sections[$idx++];
  2134. # check the order of items.
  2135. &checkorder('PORTNAME', $tmp, $file, qw(
  2136. PORTNAME PORTVERSION DISTVERSIONPREFIX DISTVERSION DISTVERSIONSUFFIX
  2137. PORTREVISION PORTEPOCH CATEGORIES MASTER_SITES MASTER_SITE_SUBDIR
  2138. PROJECTHOST PKGNAMEPREFIX PKGNAMESUFFIX DISTNAME EXTRACT_SUFX DISTFILES
  2139. DIST_SUBDIR EXTRACT_ONLY
  2140. ));
  2141. # check the items that has to be there.
  2142. $tmp = "\n" . $tmp;
  2143. print "OK: checking PORTNAME/PORTVERSION/DISTVERSION.\n" if ($verbose);
  2144. if ($tmp !~ /\nPORTNAME(.)?=/) {
  2145. &perror("FATAL", $file, -1, "PORTNAME has to be there.") unless ($slaveport && $makevar{PORTNAME} ne '');
  2146. } elsif (defined $1 && $1 ne '') {
  2147. &perror("WARN", $file, -1, "unless this is a master port, PORTNAME has to be set by \"=\", ".
  2148. "not by \"$1=\".") unless ($masterport);
  2149. }
  2150. if ($tmp !~ /\n(PORTVERSION|DISTVERSION)(.)?=/) {
  2151. &perror("FATAL", $file, -1, "PORTVERSION or DISTVERSION has to be there.") unless (($makevar{PORTVERSION} ne '' || $makevar{DISTVERSION} ne ''));
  2152. if (!$slaveport && ($makevar{PORTVERSION} ne '' || $makevar{DISTVERSION} ne '')) {
  2153. &perror("WARN", $file, -1, "PORTVERSION/DISTVERSION is set externally to this port's Makefile, but this port is not configured as a slave port.");
  2154. }
  2155. } elsif (defined $2 && $2 ne '') {
  2156. &perror("WARN", $file, -1, "unless this is a master port, PORTVERSION has to be set by \"=\", ".
  2157. "not by \"$2=\".") unless ($masterport);
  2158. }
  2159. if ($tmp =~ /\nPORTVERSION.?=/ && $tmp =~ /\nDISTVERSION.?=/) {
  2160. &perror("FATAL", $file, -1, "either PORTVERSION or DISTVERSION must be ".
  2161. "specified, not both.");
  2162. }
  2163. if ($newport) {
  2164. print "OK: checking for existence of PORTREVISION in new port.\n"
  2165. if ($verbose);
  2166. if ($tmp =~ /^PORTREVISION(.)?=/m) {
  2167. &perror("WARN", $file, -1, "new ports should not set PORTREVISION.");
  2168. }
  2169. } elsif (!$slaveport) {
  2170. print "OK: checking for PORTREVISION=0.\n" if ($verbose);
  2171. if ($tmp =~ /^PORTREVISION=\s*0/m) {
  2172. &perror("WARN", $file, -1, "Setting PORTREVISION to 0 is not ".
  2173. "necessary.");
  2174. }
  2175. }
  2176. if ($newport) {
  2177. print "OK: checking for existence of PORTEPOCH in new port.\n"
  2178. if ($verbose);
  2179. if ($tmp =~ /^PORTEPOCH(.)?=/m) {
  2180. &perror("WARN", $file, -1, "new ports should not set PORTEPOCH.");
  2181. }
  2182. }
  2183. print "OK: checking CATEGORIES.\n" if ($verbose);
  2184. if ($tmp !~ /\nCATEGORIES(.)?=/) {
  2185. &perror("FATAL", $file, -1, "CATEGORIES has to be there.") unless ($makevar{CATEGORIES} ne '');
  2186. if (!$slaveport && $makevar{CATEGORIES} ne '') {
  2187. &perror("WARN", $file, -1, "CATEGORIES is set externally to this port's Makefile, but this port is not configured as a slave port.");
  2188. }
  2189. } elsif (defined $1 && ($i = $1) ne '' && $i =~ /[^?+]/) {
  2190. &perror("WARN", $file, -1, "unless this is a master port, CATEGORIES should be set by \"=\", \"?=\", or \"+=\", ".
  2191. "not by \"$i=\".") unless ($masterport);
  2192. }
  2193. @cat = split(/\s+/, $makevar{CATEGORIES});
  2194. if (@cat == 0) {
  2195. &perror("FATAL", $file, -1, "CATEGORIES left blank. set it to \"misc\"".
  2196. " if nothing seems apropriate.");
  2197. } else {
  2198. my %seencat = ();
  2199. foreach my $cat (@cat) {
  2200. if ($seencat{$cat}) {
  2201. &perror("WARN", $file, -1, "Duplicate category, $cat specified".
  2202. " in CATEGORIES.");
  2203. } else {
  2204. $seencat{$cat} = 1;
  2205. }
  2206. }
  2207. }
  2208. if ($use_java && !grep /^java$/, @cat) {
  2209. &perror("WARN", $file, -1, "the port uses Java but is not part of the ".
  2210. "``java'' category");
  2211. }
  2212. if (scalar(@cat) == 1 && $cat[0] eq "java") {
  2213. &perror("FATAL", $file, -1, "the ``java'' category shall not be the only ".
  2214. "one for a port");
  2215. }
  2216. if ($newport && scalar(@cat) > 0 && $cat[0] eq "java") {
  2217. &perror("WARN", $file, -1, "save for ports directly related to the Java ".
  2218. "language, porters are encouraged not to use ``java'' as ".
  2219. "the main category for a port");
  2220. }
  2221. if ($committer && $makevar{'.CURDIR'} =~ m'${portsdir}/([^/]+)/[^/]+/?$') {
  2222. if ($cat[0] ne $1 && $makevar{PKGCATEGORY} ne $1 ) {
  2223. &perror("FATAL", $file, -1, "category \"$1\" must be listed first");
  2224. }
  2225. }
  2226. #MICHAEL: can these three lang cat checks be combined?
  2227. # skip the first category specification if it's a language specific one.
  2228. if (grep($_ eq $cat[0], @lang_cat)) {
  2229. $has_lang_cat = 1;
  2230. $port_lang = $lang_pref{$cat[0]};
  2231. shift @cat;
  2232. }
  2233. # skip further if more language specific ones follow.
  2234. if (@cat && grep($_ eq $cat[0], @lang_cat)) {
  2235. &perror("WARN", $file, -1, "multiple language specific categories detected. ".
  2236. "are you sure?");
  2237. do {
  2238. shift @cat;
  2239. } while (@cat && grep($_ eq $cat[0], @lang_cat));
  2240. }
  2241. # check x11 in CATEGORIES
  2242. if ($newxdef) {
  2243. #MICHAEL: I don't understand this line
  2244. if (2 <= @cat && $cat[1] eq "x11") {
  2245. &perror("WARN", $file, -1, "only specific kind of apps should ".
  2246. "specify \"x11\" in CATEGORIES. ".
  2247. "Do you mean just USE_XORG? ".
  2248. "Then remove \"x11\" from CATEGORIES.");
  2249. }
  2250. }
  2251. if (2 <= @cat) {
  2252. # skip the first one that we know is _not_ language specific.
  2253. shift @cat;
  2254. # any language specific one after non language specific ones?
  2255. foreach my $cat (@cat) {
  2256. if (grep($_ eq $cat, @lang_cat)) {
  2257. $has_lang_cat = 1;
  2258. $port_lang = $lang_pref{$cat};
  2259. &perror("WARN", $file, -1, "when you specify multiple categories, ".
  2260. "language specific category should come first.");
  2261. }
  2262. }
  2263. }
  2264. # check number of MASTER_SITES
  2265. if ($makevar{MASTER_SITES} ne '' &&
  2266. ! grep {$makevar{MASTER_SITES} =~ m|$_|} @MASTERSITES_WHITELIST) {
  2267. my @sites = split(/\s+/, $makevar{MASTER_SITES});
  2268. if (scalar(@sites) == 1) {
  2269. &perror("WARN", $file, -1, "only one MASTER_SITE configured. ".
  2270. "Consider adding additional mirrors.");
  2271. }
  2272. }
  2273. # check the URL
  2274. if (($tmp =~ /\nMASTER_SITES[+?]?=[ \t]*([^\n]*)\n/
  2275. && $1 !~ /^[ \t]*$/) || ($makevar{MASTER_SITES} ne '')) {
  2276. print "OK: seen MASTER_SITES, sanity checking URLs.\n"
  2277. if ($verbose);
  2278. my @sites = split(/\s+/, $1 // '');
  2279. my $skipnext = 0;
  2280. foreach my $i (@sites) {
  2281. if ($skipnext) {
  2282. $skipnext = 0;
  2283. next;
  2284. }
  2285. $skipnext++ if ($i =~ /^#/);
  2286. if ($i =~ m#^\w+://#) {
  2287. &urlcheck($i, $file);
  2288. unless (&is_predefined($i, $file)) {
  2289. print "OK: URL \"$i\" ok.\n"
  2290. if ($verbose);
  2291. }
  2292. } else {
  2293. print "OK: non-URL \"$i\" ok.\n"
  2294. if ($verbose);
  2295. }
  2296. }
  2297. } else {
  2298. &perror("WARN", $file, -1, "no MASTER_SITES found. is it ok?");
  2299. }
  2300. # check DISTFILES and related items.
  2301. $distfiles = $1 if ($tmp =~ /\nDISTFILES[+?]?=[ \t]*([^\n]+)\n/);
  2302. #$portname = $1 if ($tmp =~ /\nPORTNAME[+?]?=[ \t]*([^\n]+)\n/);
  2303. #$portversion = $1 if ($tmp =~ /\nPORTVERSION[+?]?=[ \t]*([^\n]+)\n/);
  2304. $portname = $makevar{PORTNAME};
  2305. $portversion = $makevar{PORTVERSION};
  2306. $distversionprefix = $makevar{DISTVERSIONPREFIX};
  2307. $distversion = $makevar{DISTVERSION};
  2308. $distversionsuffix = $makevar{DISTVERSIONSUFFIX};
  2309. $distname = $1 if ($tmp =~ /\nDISTNAME[+?]?=[ \t]*([^\n]+)\n/);
  2310. $extractsufx = $1 if ($tmp =~ /\nEXTRACT_SUFX[+?]?=[ \t]*([^\n]+)\n/);
  2311. # check bogus EXTRACT_SUFX.
  2312. if ($extractsufx ne '') {
  2313. print "OK: seen EXTRACT_SUFX, checking value.\n" if ($verbose);
  2314. if ($distfiles ne '') {
  2315. &perror("WARN", $file, -1, "no need to define EXTRACT_SUFX if ".
  2316. "DISTFILES is defined.");
  2317. }
  2318. if ($extractsufx eq '.tar.gz') {
  2319. &perror("WARN", $file, -1, "EXTRACT_SUFX is \".tar.gz.\" ".
  2320. "by default. you don't need to specify it.");
  2321. }
  2322. if ($extractsufx eq '.tar.bz2') {
  2323. &perror("WARN", $file, -1, "EXTRACT_SUFX is \".tar.bz2.\" ".
  2324. "You should use USE_BZIP2 instead.");
  2325. }
  2326. if ($extractsufx eq '.zip') {
  2327. &perror("WARN", $file, -1, "EXTRACT_SUFX is \".zip\" ".
  2328. "You should use USE_ZIP instead.");
  2329. }
  2330. } else {
  2331. print "OK: no EXTRACT_SUFX seen, using default value.\n"
  2332. if ($verbose);
  2333. $extractsufx = '.tar.gz';
  2334. }
  2335. print "OK: sanity checking PORTNAME/PORTVERSION/DISTVERSIONPREFIX/DISTVERSION/DISTVERSIONSUFFIX.\n" if ($verbose);
  2336. if ($distname ne '') {
  2337. my $exp_distname = $makevar{DISTNAME};
  2338. if ($exp_distname eq "$portname-$portversion") {
  2339. &perror("WARN", $file, -1, "DISTNAME is \${PORTNAME}-\${PORTVERSION} by ".
  2340. "default, you don't need to define DISTNAME.");
  2341. } else {
  2342. if ($exp_distname eq "$portname-$distversionprefix$distversion$distversionsuffix") {
  2343. &perror("WARN", $file, -1, "DISTNAME is \${PORTNAME}-\${DISTVERSIONPREFIX}\${DISTVERSION}\${DISTVERSIONSUFFIX} by ".
  2344. "default, you don't need to define DISTNAME.");
  2345. }
  2346. }
  2347. if ($distname =~ /PORTREVISION/) {
  2348. &perror("FATAL", $file, -1, "DISTNAME contains a reference to ".
  2349. "PORTREVISION. You should only be using PORTVERSION");
  2350. }
  2351. if ($distname =~ /PORTEPOCH/) {
  2352. &perror("FATAL", $file, -1, "DISTNAME contains a reference to ".
  2353. "PORTEPOCH. You should only be using PORTVERSION");
  2354. }
  2355. }
  2356. if ($portname =~ /^$re_lang_short/) {
  2357. &perror("FATAL", $file, -1, "language prefix is automatically".
  2358. " set by PKGNAMEPREFIX.".
  2359. " you must remove it from PORTNAME.");
  2360. }
  2361. if ($portname =~ /([|<>=! ])/) {
  2362. &perror("FATAL", $file, -1, "PORTNAME contains the illegal character \"$1\".".
  2363. " You should modify \"$portname\".");
  2364. } elsif ($portname =~ /\$[\{\(].+[\}\)]/) {
  2365. &perror("WARN", $file, -1, "using variable in PORTNAME.".
  2366. " consider using PKGNAMEPREFIX and/or PKGNAMESUFFIX.");
  2367. } elsif ($portname =~ /([^\w._@+-])/) {
  2368. &perror("WARN", $file, -1, "using \"$1\" in PORTNAME.".
  2369. " You should modify \"$portname\".");
  2370. } elsif ($portname =~ /-/ && $distname ne '') {
  2371. &perror("WARN", $file, -1, "using hyphen in PORTNAME.".
  2372. " consider using PKGNAMEPREFIX and/or PKGNAMESUFFIX.");
  2373. }
  2374. if ($portversion eq '' && $distversion eq '') {
  2375. &perror("FATAL", $file, -1, "either PORTVERSION or DISTVERSION must be specified");
  2376. }
  2377. if ($portversion =~ /^pl[0-9]*$/
  2378. || $portversion =~ /^[0-9]*[A-Za-z]?[0-9]*(\.[0-9]*[A-Za-z]?[0-9+]*)*$/) {
  2379. print "OK: PORTVERSION \"$portversion\" looks fine.\n" if ($verbose);
  2380. } elsif ($portversion =~ /^[^\-]*\$[{\(].+[\)}][^\-]*$/) {
  2381. &perror("WARN", $file, -1, "using variable, \"$portversion\", as version ".
  2382. "number");
  2383. } elsif ($portversion =~ /([-,_<>=! #*])/) {
  2384. &perror("FATAL", $file, -1, "PORTVERSION must not contain \"$1\". ".
  2385. "You should modify \"$portversion\".");
  2386. } else {
  2387. &perror("FATAL", $file, -1, "PORTVERSION looks illegal. ".
  2388. "You should modify \"$portversion\".");
  2389. }
  2390. $pkg_version = $makevar{PKG_VERSION};
  2391. if ($makevar{CONFLICTS}) {
  2392. print "OK: checking CONFLICTS.\n" if ($verbose);
  2393. foreach my $conflict (split ' ', $makevar{CONFLICTS}) {
  2394. my $selfconflict;
  2395. if ($makevar{PKGINSTALLVER} ne "" &&
  2396. $makevar{PKGINSTALLVER} >= 20040125) {
  2397. $selfconflict = !system($pkg_version, '-T',
  2398. $makevar{PKGNAME}, $conflict);
  2399. } else {
  2400. my $conflictre = $conflict;
  2401. $conflictre =~ s/[.+]/\\$&/g;
  2402. $conflictre =~ s/\*/.*/g;
  2403. $conflictre =~ s/\?/./g;
  2404. $conflictre =~ s/\[!/[^/g;
  2405. $selfconflict = ($makevar{PKGNAME} =~ /^$conflictre$/);
  2406. }
  2407. if ($conflict !~ /(?:[<>=]|[]?*]$)/) {
  2408. &perror("WARN", "", -1, "Conflict \"$conflict\" specified too narrow. ".
  2409. "You should end it with a wildcard (-[0-9]*).");
  2410. } elsif ($conflict !~ /[<>=-][^-]*[0-9][^-]*$/) {
  2411. &perror("WARN", "", -1, "Conflict \"$conflict\" specified too broad. ".
  2412. "You should end it with a version number fragment (-[0-9]*).");
  2413. }
  2414. if ($selfconflict) {
  2415. &perror("FATAL", "", -1, "Package conflicts with itself. ".
  2416. "You should remove \"$conflict\" from CONFLICTS.");
  2417. }
  2418. }
  2419. }
  2420. $versiondir = $ENV{VERSIONDIR} // '/var/db/chkversion';
  2421. $versionfile = "$versiondir/VERSIONS";
  2422. $useindex = !-r "$versionfile";
  2423. $versionfile = "$portsdir/$makevar{INDEXFILE}"
  2424. if $useindex;
  2425. if (-r "$versionfile") {
  2426. print "OK: checking if PORTVERSION is going backwards.\n" if ($verbose);
  2427. open VERSIONS, "<$versionfile";
  2428. while (<VERSIONS>) {
  2429. my($origin, $version) = ('', '');
  2430. chomp;
  2431. next if /^(#|$)/;
  2432. if ($useindex) {
  2433. ($version, $origin) = split /\|/;
  2434. $origin =~ s,^.*/([^/]+/[^/]+)/?$,$1,;
  2435. } else {
  2436. ($origin, $version) = split;
  2437. }
  2438. if ($origin eq $makevar{PKGORIGIN}) {
  2439. my $newversion = $makevar{PKGNAME};
  2440. my $oldversion = $version;
  2441. my $result = '';
  2442. $newversion =~ s/^.*-//;
  2443. $oldversion =~ s/^.*-//;
  2444. $result = `$pkg_version -t '$newversion' '$oldversion'`;
  2445. chomp $result;
  2446. if ($result eq '<') {
  2447. &perror("FATAL", $file, -1, "$makevar{PKGNAME} < $version. ".
  2448. "Choose another PORTVERSION or bump PORTEPOCH.");
  2449. # $backwards{$origin} = "$pkgname{$origin} < $version";
  2450. }
  2451. last;
  2452. }
  2453. }
  2454. close VERSIONS;
  2455. }
  2456. # if DISTFILES have only single item, it is better to avoid DISTFILES
  2457. # and to use combination of DISTNAME and EXTRACT_SUFX.
  2458. # example:
  2459. # DISTFILES=package-1.0.tgz
  2460. # should be
  2461. # DISTNAME= package-1.0
  2462. # EXTRACT_SUFX= .tgz
  2463. if ($distfiles =~ /^\S+$/ && $distfiles !~ /:[^\/:]+$/) {
  2464. $bogusdistfiles++;
  2465. print "OK: seen DISTFILES with single item, checking value.\n"
  2466. if ($verbose);
  2467. &perror("WARN", $file, -1, "use of DISTFILES with single file ".
  2468. "discouraged. distribution filename should be set by ".
  2469. "DISTNAME and EXTRACT_SUFX.");
  2470. if ($distfiles eq (($distname ne '') ? $distname : "$portname-$portversion") . $extractsufx) {
  2471. &perror("WARN", $file, -1, "definition of DISTFILES not necessary. ".
  2472. "DISTFILES is \${DISTNAME}/\${EXTRACT_SUFX} ".
  2473. "by default.");
  2474. }
  2475. # display advice only in certain cases.
  2476. #MICHAEL: will this work with multiple distfiles in this list? what about
  2477. # doing the same sort of thing for DISTNAME, is it needed?
  2478. if ($distfiles =~ /^\Q$i\E([\-.].+)$/) {
  2479. &perror("WARN", $file, -1, "how about \"EXTRACT_SUFX=$1\"".
  2480. ", instead of DISTFILES?");
  2481. }
  2482. }
  2483. # additional checks for committer.
  2484. if ($committer && $has_lang_cat) {
  2485. &perror("WARN", $file, -1, "be sure to include language code ".
  2486. "\"$port_lang-\" ".
  2487. "in the module alias name.");
  2488. }
  2489. if ($committer) {
  2490. if (opendir(DIR, ".")) {
  2491. my @tgz = grep(/\.tgz$/, readdir(DIR));
  2492. closedir(DIR);
  2493. if (@tgz) {
  2494. my $tgz = (2 <= @tgz)
  2495. ? '{' . join(',', @tgz) . '}'
  2496. : $tgz[0];
  2497. &perror("WARN", "", -1, "be sure to remove $portdir/$tgz ".
  2498. "before committing the port.");
  2499. }
  2500. }
  2501. }
  2502. push(@varnames, qw(
  2503. PORTNAME PORTVERSION PORTREVISION PORTEPOCH CATEGORIES MASTER_SITES
  2504. PKGNAMEPREFIX PKGNAMESUFFIX DISTNAME EXTRACT_SUFX
  2505. DISTFILES EXTRACT_ONLY
  2506. ));
  2507. #
  2508. # section 3: PATCH_SITES/PATCHFILES(optional)
  2509. #
  2510. print "OK: checking second section of $file (PATCH*: optional).\n"
  2511. if ($verbose);
  2512. $tmp = $sections[$idx];
  2513. if ($tmp =~ /(PATCH_SITES|PATCH_SITE_SUBDIR|PATCHFILES|PATCH_DIST_STRIP)/) {
  2514. &checkearlier($file, $tmp, @varnames);
  2515. if ($tmp =~ /PATCH_SITES[?+]?=[^\n]+\n/) {
  2516. print "OK: seen PATCH_SITES.\n" if ($verbose);
  2517. $tmp =~ s/PATCH_SITES[?+]?=[^\n]+\n//;
  2518. }
  2519. if ($tmp =~ /PATCH_SITE_SUBDIR[?+]?=[^\n]+\n/) {
  2520. print "OK: seen PATCH_SITE_SUBDIR.\n" if ($verbose);
  2521. $tmp =~ s/PATCH_SITE_SUBDIR[?+]?=[^\n]+\n//;
  2522. }
  2523. if ($tmp =~ /PATCHFILES[?+]?=[^\n]+\n/) {
  2524. print "OK: seen PATCHFILES.\n" if ($verbose);
  2525. $tmp =~ s/PATCHFILES[?+]?=[^\n]+\n//;
  2526. }
  2527. if ($tmp =~ /PATCH_DIST_STRIP[?+]?=[^\n]+\n/) {
  2528. print "OK: seen PATCH_DIST_STRIP.\n" if ($verbose);
  2529. $tmp =~ s/PATCH_DIST_STRIP[?+]?=[^\n]+\n//;
  2530. }
  2531. &checkextra($tmp, 'PATCH_SITES', $file);
  2532. $idx++;
  2533. }
  2534. push(@varnames, qw(
  2535. PATCH_SITES PATCHFILES PATCH_DIST_STRIP
  2536. ));
  2537. #
  2538. # section 4: MAINTAINER
  2539. #
  2540. print "OK: checking third section of $file (MAINTAINER).\n"
  2541. if ($verbose);
  2542. $tmp = $sections[$idx];
  2543. &checkearlier($file, $tmp, @varnames);
  2544. &checkorder('MAINTAINER', $tmp, $file, qw(
  2545. MAINTAINER COMMENT
  2546. ));
  2547. $tmp = "\n" . $tmp;
  2548. if ($tmp =~ /\nMAINTAINER(\?)?=([^\n]+)/) {
  2549. my $addr = $2;
  2550. if (defined $1 && $1 ne '') {
  2551. &perror("WARN", $file, -1, "unless this is a master port, ".
  2552. "MAINTAINER has to be set by \"=\", ".
  2553. "not by \"$1=\".") unless ($masterport);
  2554. }
  2555. $addr =~ s/^\s*//;
  2556. $addr =~ s/\s*$//;
  2557. if ($addr =~ /[\s,<>()]/) {
  2558. &perror("FATAL", $file, -1, "MAINTAINER should be a single address without comment.");
  2559. }
  2560. if ($addr !~ /^[^\@]+\@[\w\d\-\.]+$/) {
  2561. &perror("FATAL", $file, -1, "MAINTAINER address, $addr, does not appear to be a valid email address.");
  2562. }
  2563. if ($newport && $addr =~ /ports\@freebsd.org/i) {
  2564. &perror("WARN", $file, -1, "new ports should not be maintained by ".
  2565. "ports\@FreeBSD.org.");
  2566. }
  2567. $tmp =~ s/\nMAINTAINER\??=[^\n]+//;
  2568. } elsif ($whole !~ /\nMAINTAINER[?]?=/) {
  2569. &perror("FATAL", $file, -1, "no MAINTAINER listed.") unless ($makevar{MAINTAINER} ne '');
  2570. if (!$slaveport && $makevar{MAINTAINER} ne '') {
  2571. &perror("WARN", $file, -1, "MAINTAINER is set externally to this port's Makefile, but this port is not configured as a slave port.");
  2572. }
  2573. }
  2574. $tmp =~ s/\n\n+/\n/g;
  2575. # check COMMENT
  2576. if ($tmp !~ /\nCOMMENT(.)?=/) {
  2577. &perror("FATAL", $file, -1, "COMMENT has to be there.") unless ($makevar{COMMENT} ne '');
  2578. if (!$slaveport && $makevar{COMMENT} ne '') {
  2579. &perror("WARN", $file, -1, "COMMENT is set externally to this port's Makefile, but this port is not configured as a slave port.");
  2580. }
  2581. } elsif (defined $1 && $1 ne '') {
  2582. &perror("WARN", $file, -1, "unless this is a master port, COMMENT has to be set by \"=\", ".
  2583. "not by \"$1=\".") unless ($masterport);
  2584. } else { # check for correctness
  2585. if (($makevar{COMMENT} !~ /^["\[0-9A-Z]/) || ($makevar{COMMENT} =~ m/\.$/)) { #"
  2586. &perror("WARN", $file, -1, "COMMENT should begin with a capital, and end without a period");
  2587. } elsif (length($makevar{COMMENT}) > 70) {
  2588. &perror("WARN", $file, -1, "COMMENT exceeds 70 characters limit.");
  2589. }
  2590. }
  2591. $idx++;
  2592. push(@varnames, qw(
  2593. MAINTAINER COMMENT
  2594. ));
  2595. #
  2596. # section 5: LICENSE
  2597. #
  2598. print "OK: checking fourth section of $file (LICENSE).\n"
  2599. if ($verbose);
  2600. $tmp = $sections[$idx];
  2601. if ($makevar{LICENSE}) {
  2602. &checkorder('LICENSE', $tmp, $file, qw(
  2603. LICENSE LICENSE_COMB LICENSE_GROUPS(_\w+)? LICENSE_NAME(_\w+)?
  2604. LICENSE_TEXT(_\w+)? LICENSE_FILE(_\w+)? LICENSE_PERMS(_\w+)?
  2605. LICENSE_DISTFILES(_\w+)?
  2606. ));
  2607. # check LICENSE
  2608. if ($makevar{LICENSE} && $makevar{LICENSE} ne '') {
  2609. my $comb = $makevar{LICENSE_COMB} // 'single';
  2610. my @tokens = split(/ /, $makevar{LICENSE});
  2611. if ($comb eq 'single' && scalar(@tokens) > 1) {
  2612. &perror("FATAL", $file, -1, "LICENSE contains multiple licenses but LICENSE_COMB is not set to 'dual' or 'multi'");
  2613. }
  2614. }
  2615. # check value of LICENSE_COMB
  2616. if ($makevar{LICENSE_COMB} && $makevar{LICENSE_COMB} !~ /^(single|dual|multi$)/) {
  2617. &perror("FATAL", $file, -1, "LICENSE_COMB contains invalid value '$1' - must be one of 'single', 'dual', 'multi'");
  2618. }
  2619. $idx++;
  2620. push(@varnames, qw(
  2621. LICENSE LICENSE_COMB LICENSE_GROUPS LICENSE_NAME
  2622. LICENSE_TEXT LICENSE_FILE LICENSE_PERMS
  2623. ));
  2624. }
  2625. #
  2626. # section 6: *_DEPENDS (may not be there)
  2627. #
  2628. print "OK: checking fifth section of $file (*_DEPENDS).\n"
  2629. if ($verbose);
  2630. $tmp = $sections[$idx];
  2631. # Check for direct assignment of BUILD_DEPENDS to RUN_DEPENDS.
  2632. if ($tmp =~ /\nRUN_DEPENDS=[ \t]*\${BUILD_DEPENDS}/) {
  2633. &perror("FATAL", $file, -1, "RUN_DEPENDS should not be set to ".
  2634. "\${BUILD_DEPENDS} as \${BUILD_DEPENDS} includes other ".
  2635. "implicit dependencies. Instead, copy the explicit dependencies ".
  2636. "from BUILD_DEPENDS to RUN_DEPENDS. See ".
  2637. "http://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/makefile-depend.html#AEN2154 ".
  2638. "for more details.");
  2639. }
  2640. # NOTE: EXEC_DEPENDS is obsolete, so it should not be listed.
  2641. @linestocheck = qw(
  2642. EXTRACT_DEPENDS LIB_DEPENDS PATCH_DEPENDS BUILD_DEPENDS RUN_DEPENDS
  2643. TEST_DEPENDS FETCH_DEPENDS DEPENDS_TARGET
  2644. );
  2645. if ($tmp =~ /^(PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)DEPENDS/m) {
  2646. &checkearlier($file, $tmp, @varnames);
  2647. check_depends_syntax($tmp, $file);
  2648. foreach my $i (@linestocheck) {
  2649. $tmp =~ s/$i[?+:]?=[^\n]+\n//g;
  2650. }
  2651. &checkextra($tmp, '*_DEPENDS', $file);
  2652. $idx++;
  2653. }
  2654. push(@varnames, @linestocheck);
  2655. &checkearlier($file, $tmp, @varnames);
  2656. #
  2657. # Makefile 7: check the rest of file
  2658. #
  2659. print "OK: checking the rest of the $file.\n" if ($verbose);
  2660. $tmp = join("\n\n", @sections[$idx .. scalar(@sections)-1]);
  2661. $tmp = "\n" . $tmp; # to make the begin-of-line check easier
  2662. &checkearlier($file, $tmp, @varnames);
  2663. # Check depends that might be specified based on the WITH_/WITHOUT_
  2664. # arguments and other external variables.
  2665. check_depends_syntax($tmp, $file);
  2666. # check WRKSRC/NO_WRKSUBDIR
  2667. #
  2668. # do not use DISTFILES/DISTNAME to control over WRKSRC.
  2669. # DISTNAME is for controlling distribution filename.
  2670. # example:
  2671. # DISTNAME= package
  2672. # DISTFILES=package-1.0.tgz
  2673. # should be
  2674. # DISTNAME= package-1.0
  2675. # EXTRACT_SUFX=.tgz
  2676. # WRKSRC= ${WRKDIR}/package
  2677. #
  2678. print "OK: checking WRKSRC.\n" if ($verbose);
  2679. $wrksrc = $nowrksubdir = '';
  2680. $wrksrc = $1 if ($tmp =~ /\nWRKSRC[+?]?=[ \t]*([^\n]*)\n/);
  2681. $nowrksubdir = $1 if ($tmp =~ /\nNO_WRKSUBDIR[+?]?=[ \t]*([^\n]*)\n/);
  2682. if ($nowrksubdir eq '') {
  2683. $realwrksrc = $wrksrc ? "$wrksrc/$distname"
  2684. : "\${WRKDIR}/$distname";
  2685. } else {
  2686. $realwrksrc = $wrksrc ? $wrksrc : '${WRKDIR}';
  2687. }
  2688. print "OK: WRKSRC seems to be $realwrksrc.\n" if ($verbose);
  2689. if ($nowrksubdir eq '') {
  2690. print "OK: no NO_WRKSUBDIR, checking value of WRKSRC.\n"
  2691. if ($verbose);
  2692. if ($wrksrc eq 'work' || $wrksrc =~ /^$[\{\(]WRKDIR[\}\)]/) {
  2693. &perror("WARN", $file, -1, "WRKSRC is set to meaningless value ".
  2694. "\"$1\".".
  2695. ($nowrksubdir eq ''
  2696. ? " use \"NO_WRKSUBDIR=yes\" instead."
  2697. : ""));
  2698. }
  2699. if ($bogusdistfiles) {
  2700. if ($distname ne '' && $wrksrc eq '') {
  2701. &perror("WARN", $file, -1, "do not use DISTFILES and DISTNAME ".
  2702. "to control WRKSRC. how about ".
  2703. "\"WRKSRC=\${WRKDIR}/$distname\"?");
  2704. } else {
  2705. &perror("WARN", $file, -1, "DISTFILES/DISTNAME affects WRKSRC. ".
  2706. "take caution when changing them.");
  2707. }
  2708. }
  2709. } else {
  2710. print "OK: seen NO_WRKSUBDIR, checking value of WRKSRC.\n"
  2711. if ($verbose);
  2712. if ($wrksrc eq 'work' || $wrksrc =~ /^$[\{\(]WRKDIR[\}\)]/) {
  2713. &perror("WARN", $file, -1, "definition of WRKSRC not necessary. ".
  2714. "WRKSRC is \${WRKDIR} by default.");
  2715. }
  2716. }
  2717. # check RESTRICTED/NO_CDROM/NO_PACKAGE
  2718. print "OK: checking RESTRICTED/NO_CDROM/NO_PACKAGE.\n" if ($verbose);
  2719. if ($committer && $tmp =~ /\n(RESTRICTED|NO_CDROM|NO_PACKAGE)[+?]?=/) {
  2720. &perror("WARN", $file, -1, "\"$1\" found. do not forget to update ".
  2721. "ports/LEGAL.");
  2722. }
  2723. # check NO_CONFIGURE/NO_PATCH
  2724. print "OK: checking NO_CONFIGURE/NO_PATCH.\n" if ($verbose);
  2725. if ($tmp =~ /\n(NO_CONFIGURE|NO_PATCH)[+?]?=/) {
  2726. &perror("FATAL", $file, -1, "\"$1\" was obsoleted. remove this.");
  2727. }
  2728. # check MAN[1-9LN]
  2729. print "OK: checking MAN[0-9LN].\n" if ($verbose);
  2730. foreach my $i (keys %plistmanall) {
  2731. print "OK: pkg-plist MAN$i=$plistmanall{$i}\n" if ($verbose);
  2732. }
  2733. if ($tmp =~ /PERL_CONFIGURE=\s*/
  2734. && $tmp =~ /^MAN3PREFIX=\s*\${PREFIX}\/lib\/perl5\/\${PERL_VERSION}/) {
  2735. &perror("WARN", $file, -1, "MAN3PREFIX is ".
  2736. "\"\${PREFIX}/lib/perl5/\${PERL_VERSION}\" ".
  2737. "when PERL_CONFIGURE is set. You do not need to specify it.");
  2738. }
  2739. foreach my $i (split(//, $manchapters)) {
  2740. if ($tmp =~ /^MAN\U$i\E=\s*([^\n]*)\n/) {
  2741. print "OK: Makefile MAN\U$i\E=$1\n" if ($verbose);
  2742. }
  2743. }
  2744. foreach my $i (split(//, $manchapters)) {
  2745. next if ($i eq '');
  2746. my @mansecs = grep(/^MAN\U$i\E=\s*(.*)/, split(/\n/, $tmp));
  2747. if (scalar @mansecs > 1) {
  2748. &perror("FATAL", $file, -1, "duplicate MAN$i macro. ".
  2749. "Only the last MAN$i macro will be processed. Use ".
  2750. "MAN$i+=... instead to append man pages.");
  2751. }
  2752. if ($tmp =~ /^MAN\U$i\E=\s*([^\n]*)\n/) {
  2753. @mman = grep($_ !~ /^\s*$/, split(/\s+/, $1));
  2754. @pman = grep($_ !~ /^\s*$/,
  2755. split(/\s+/, $plistmanall{$i} // ''));
  2756. foreach my $j (@mman) {
  2757. print "OK: checking $j (Makefile)\n"
  2758. if ($verbose);
  2759. if ($automan && grep($_ eq $j, @pman)) {
  2760. &perror("FATAL", $file, -1, "duplicated manpage ".
  2761. "entry $j: content of ".
  2762. "MAN\U$i\E will be automatically ".
  2763. "added to pkg-plist.");
  2764. } elsif (!$automan && !grep($_ eq $j, @pman)) {
  2765. &perror("WARN", $file, -1, "manpage $j ".
  2766. "MAN\U$i\E but not in pkg-plist.");
  2767. }
  2768. }
  2769. foreach my $j (@pman) {
  2770. print "OK: checking $j (pkg-plist)\n" if ($verbose);
  2771. if (!grep($_ eq $j, @mman)) {
  2772. &perror("WARN", $file, -1, "manpage $j in pkg-plist ".
  2773. "but not in MAN\U$i\E.");
  2774. }
  2775. }
  2776. } else {
  2777. if ($plistmanall{$i}) {
  2778. if ($manstrict) {
  2779. &perror("FATAL", $file, -1, "manpage for chapter ".
  2780. "$i must be listed in ".
  2781. "MAN\U$i\E. ");
  2782. } else {
  2783. &perror("WARN", $file, -1, "manpage for chapter ".
  2784. "$i should be listed in ".
  2785. "MAN\U$i\E, ".
  2786. "even if compression is ".
  2787. "not necessary.");
  2788. }
  2789. }
  2790. if ($mancompress && $plistman{$i}) {
  2791. &perror("WARN", $file, -1, "MAN\U$i\E will help you ".
  2792. "compressing manual page in chapter ".
  2793. "\"$i\".");
  2794. } elsif (!$mancompress && $plistmangz{$i}) {
  2795. &perror("WARN", $file, -1, "MAN\U$i\E will help you ".
  2796. "uncompressing manual page in chapter ".
  2797. "\"$i\".");
  2798. }
  2799. }
  2800. }
  2801. if ($tmp !~ /MANLANG/ && scalar(keys %manlangs)) {
  2802. $i = (keys %manlangs)[0];
  2803. &perror("WARN", $file, -1, "how about using MANLANG for ".
  2804. "designating manual language, such as \"$i\"?");
  2805. }
  2806. # check INFO
  2807. print "OK: checking INFO.\n" if ($verbose);
  2808. if ($autoinfo && $tmp =~ /\nINFO=\s*([^\n]*)\n/) {
  2809. my @minfo = grep($_ !~ /^\s*$/, split(/\s+/, $1));
  2810. if ($tmp =~ /[\/|\s]install-info\s/) {
  2811. &perror("FATAL", $file, -1, "install-info is automatically run ".
  2812. "when INFO is defined.");
  2813. }
  2814. foreach $i (@minfo) {
  2815. if ($i =~ /\.info(-\d+)?$/) {
  2816. &perror("FATAL", $file, -1, "do not include the .info extension ".
  2817. "on files listed in the INFO macro.");
  2818. }
  2819. }
  2820. } elsif ($autoinfo && $tmp =~ /[\/|\s]install-info\s/) {
  2821. &perror("WARN", $file, -1, "do not call install-info directly. Use the ".
  2822. "INFO macro instead.");
  2823. }
  2824. # check for HAS_CONFIGURE or GNU_CONFIGURE
  2825. if ($tmp =~ /\nGNU_CONFIGURE[?+]?=/
  2826. && $tmp =~ /\n(HAS_CONFIGURE)[?+]?=/) {
  2827. &perror("WARN", $file, -1, "since you already have GNU_CONFIGURE, ".
  2828. "you do not need $1.");
  2829. }
  2830. # check direct use of important make targets.
  2831. if ($tmp =~ /\n(fetch|extract|patch|configure|build|install):/) {
  2832. &perror("FATAL", $file, -1, "direct redefinition of make target \"$1\" ".
  2833. "discouraged. redefine \"do-$1\" instead.");
  2834. }
  2835. # check for incorrect use of the pre-everything target.
  2836. if ($tmp =~ /\npre-everything:[^:]/) {
  2837. &perror("FATAL", $file, -1, "use pre-everything:: instead of pre-everything:");
  2838. }
  2839. if ($tmp =~ /^pre-patch:/m && $use_gnome_hack) {
  2840. &perror("FATAL", $file, -1, "pre-patch target overwrites gnomehack component. ".
  2841. "use post-patch instead.");
  2842. }
  2843. if ($tmp =~ /^do-build:/m && $use_ant) {
  2844. &perror("WARN", $file, -1, "USE_ANT is intended only for ports that ".
  2845. "build with Ant. It is recommended not to override the default ".
  2846. "'do-build:' target when defining USE_ANT");
  2847. }
  2848. #
  2849. # check for deprecated use of USE_RC_SUBR, and current syntax
  2850. #
  2851. if ($tmp =~ /\nUSE_RC_SUBR=([\s]*)(.*)/) {
  2852. my $subr_value = $makevar{USE_RC_SUBR};
  2853. if ($subr_value eq '') {
  2854. $subr_value = $2;
  2855. }
  2856. if (($subr_value =~ /^yes$/i) ||
  2857. ($subr_value =~ /^true$/i) ||
  2858. ($subr_value =~ /^1$/)) {
  2859. &perror("FATAL", $file, -1, "The value of the USE_RC_SUBR variable ".
  2860. "should be the name of the intended rc.d script, and there ".
  2861. "should be a corresponding file in the files/ directory.");
  2862. } else {
  2863. foreach my $i (split(/\s/, $subr_value)) {
  2864. my $mvar;
  2865. if ($i =~ /\$\{([^}]+)\}/) {
  2866. $mvar = $1;
  2867. if (defined($makevar{$mvar})) {
  2868. $i = $makevar{$mvar};
  2869. } else {
  2870. $i = &getMakevar($mvar);
  2871. }
  2872. }
  2873. if ($i ne '' && ! -f "files/$i.in") {
  2874. &perror("FATAL", $file, -1, "$i listed in USE_RC_SUBR, ".
  2875. "but files/$i.in is missing.");
  2876. } elsif ($i eq '' && $mvar ne '') {
  2877. &perror("WARN", $file, -1, "possible undefined make variable ".
  2878. "$mvar used as the value for USE_RC_SUBR.");
  2879. }
  2880. }
  2881. }
  2882. }
  2883. 1;
  2884. }
  2885. sub perror($$$$) {
  2886. my($type, $file, $line, $msg) = @_;
  2887. if ($type eq 'FATAL') {
  2888. $err++;
  2889. } else {
  2890. $warn++;
  2891. }
  2892. if ($grouperrs) {
  2893. $msg = '%%LINES%%' . $msg;
  2894. if ($file ne "") {
  2895. $msg = $file . ": " . $msg;
  2896. }
  2897. $msg = $type . ": " . $msg;
  2898. if (!$errcache{$msg}) {
  2899. push @errlst, $msg;
  2900. }
  2901. if ($line > -1) {
  2902. push @{$errcache{$msg}}, $line;
  2903. }
  2904. } else {
  2905. if ($line > -1) {
  2906. $msg = "[$line]: " . $msg;
  2907. }
  2908. if ($file ne "") {
  2909. $msg = $file . ": " . $msg;
  2910. }
  2911. $msg = $type . ": " . $msg;
  2912. print $msg . "\n";
  2913. }
  2914. }
  2915. sub checkextra {
  2916. my($str, $section, $file) = @_;
  2917. $str = "\n" . $str if ($str !~ /^\n/);
  2918. $str =~ s/\n#[^\n]*/\n/g;
  2919. $str =~ s/\n\.[^\n]+/\n/g;
  2920. $str =~ s/\n\n+/\n/g;
  2921. $str =~ s/^\s+//;
  2922. $str =~ s/\s+$//;
  2923. return if ($str eq '');
  2924. if ($str =~ /^([\w\d]+)/) {
  2925. &perror("WARN", $file, -1, "extra item placed in the ".
  2926. "$section section, ".
  2927. "for example, \"$1\".");
  2928. } else {
  2929. &perror("WARN", $file, -1, "extra item placed in the ".
  2930. "$section section.");
  2931. }
  2932. }
  2933. sub checkorder {
  2934. my($section, $str, $file, @order) = @_;
  2935. my(@items, $i, $j, $k, $invalidorder);
  2936. print "OK: checking the order of $section section.\n" if ($verbose);
  2937. @items = ();
  2938. foreach my $i (split("\n", $str)) {
  2939. $i =~ s/[+?]?=.*$//;
  2940. push(@items, $i);
  2941. }
  2942. @items = reverse(@items);
  2943. $j = -1;
  2944. $invalidorder = 0;
  2945. while (scalar(@items)) {
  2946. $i = pop(@items);
  2947. $k = 0;
  2948. while ($k < scalar(@order) && $order[$k] ne $i) {
  2949. if (defined $order[$k] &&
  2950. $order[$k] =~ /[\.\*\+\?\{\}\[\]\^\$\|]/ &&
  2951. $i =~ /$order[$k]/) {
  2952. last;
  2953. }
  2954. $k++;
  2955. }
  2956. if (defined $order[$k] && $order[$k] =~ /[\.\*\+\?\{\}\[\]\^\$\|]/ &&
  2957. $i =~ /$order[$k]/) {
  2958. if ($k < $j) {
  2959. &perror("FATAL", $file, -1, "$i appears out-of-order.");
  2960. $invalidorder++;
  2961. } else {
  2962. print "OK: seen $i, in order.\n" if ($verbose);
  2963. }
  2964. $j = $k;
  2965. } elsif (defined $order[$k] && $order[$k] eq $i) {
  2966. if ($k < $j) {
  2967. &perror("FATAL", $file, -1, "$i appears out-of-order.");
  2968. $invalidorder++;
  2969. } else {
  2970. print "OK: seen $i, in order.\n" if ($verbose);
  2971. }
  2972. $j = $k;
  2973. # This if condition tests for .if, .else (in all forms),
  2974. # .for and .endfor and .include
  2975. } elsif ($i !~ m/^\.(if|el|endif|for|endfor|include)/) {
  2976. &perror("FATAL", $file, -1, "extra item \"$i\" placed in the ".
  2977. "$section section.");
  2978. }
  2979. }
  2980. if ($invalidorder) {
  2981. &perror("FATAL", $file, -1, "order must be " . join('/', @order) . '.');
  2982. } else {
  2983. print "OK: $section section is ordered properly.\n"
  2984. if ($verbose);
  2985. }
  2986. }
  2987. sub checkearlier {
  2988. my($file, $str, @varnames) = @_;
  2989. my($i);
  2990. print "OK: checking items that has to appear earlier.\n" if ($verbose);
  2991. foreach my $i (@varnames) {
  2992. if ($str =~ /\n$i\??=/) {
  2993. &perror("WARN", $file, -1, "\"$i\" has to appear earlier.");
  2994. }
  2995. }
  2996. }
  2997. sub linenumber {
  2998. my $text = shift;
  2999. my @lines;
  3000. @lines = split /\n/, $text;
  3001. return scalar(@lines);
  3002. }
  3003. sub abspathname {
  3004. my($str, $file) = @_;
  3005. my($s, $i, %cmdnames);
  3006. my($pre);
  3007. # trim all trailing backslash and newline
  3008. $str =~ s/\\\n\s*/ /g;
  3009. # ignore parameter string to reinplace command
  3010. $str =~ s/([ \t][\@-]?(?:sed|\$[\{\(]SED[\}\)]|\$[\{\(]REINPLACE_CMD[\}\)]))((?:\s+\-\w+)*\s+(?:"(?:\\"|[^"\n])*"|'(?:\\'|[^'\n])*'))+(.*)/$1$3/g; #'
  3011. # ignore parameter string to echo command
  3012. # XXX: This next pattern crashes Perl 5.8.7.
  3013. #$str =~ s/[ \t][\@-]?(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+("(\\'|\\"|[^"])*"|'(\\'|\\"|[^"])*')[ \t]*[;\n]//; #'
  3014. $str =~ s/[ \t][\@-]?(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+.*(;|$)//m; #'
  3015. print "OK: checking direct use of full pathnames in $file.\n"
  3016. if ($verbose);
  3017. foreach my $s (split(/\n+/, $str)) {
  3018. $i = '';
  3019. $s =~ s/#.*$//;
  3020. if ($s =~ /(^|[ \t\@'"-])(\/[\w\d])/) { #'
  3021. # suspected pathnames are recorded.
  3022. $i = $2 . $';
  3023. $pre = $` . $1;
  3024. if ($pre =~ /MASTER_SITE_SUBDIR/) {
  3025. # MASTER_SITE_SUBDIR lines are ok.
  3026. $i = '';
  3027. }
  3028. }
  3029. if ($i ne '' && ! grep {$i =~ m|^$_|} @ALLOWED_FULL_PATHS) {
  3030. $i =~ s/\s.*$//;
  3031. $i =~ s/['"].*$//; #'
  3032. $i = substr($i, 0, 20) . '...' if (20 < length($i));
  3033. &perror("WARN", $file, -1, "possible use of absolute pathname ".
  3034. "\"$i\".");
  3035. }
  3036. }
  3037. print "OK: checking direct use of pathnames, phase 1.\n" if ($verbose);
  3038. %cmdnames = split(/\n|\t+/, <<EOF);
  3039. /usr/opt \${PORTSDIR} instead
  3040. $portsdir \${PORTSDIR} instead
  3041. $localbase \${PREFIX} or \${LOCALBASE}, as appropriate
  3042. EOF
  3043. foreach my $i (keys %cmdnames) {
  3044. if ($str =~ /$i/) {
  3045. &perror("WARN", $file, -1, "possible direct use of \"$&\" ".
  3046. "found. if so, use $cmdnames{$i}.");
  3047. }
  3048. }
  3049. print "OK: checking direct use of pathnames, phase 2.\n" if ($verbose);
  3050. %cmdnames = split(/\n|\t+/, <<EOF);
  3051. distfiles \${DISTDIR} instead
  3052. pkg \${PKGDIR} instead
  3053. files \${FILESDIR} instead
  3054. scripts \${SCRIPTDIR} instead
  3055. patches \${PATCHDIR} instead
  3056. work \${WRKDIR} instead
  3057. EOF
  3058. foreach my $i (keys %cmdnames) {
  3059. if ($str =~ /(\.\/|\$[\{\(]\.CURDIR[\}\)]\/|[ \t])(\b$i)\//) {
  3060. &perror("WARN", $file, -1, "possible direct use of \"$i\" ".
  3061. "found. if so, use $cmdnames{$i}.");
  3062. }
  3063. }
  3064. }
  3065. sub get_makevar {
  3066. my($mvar) = @_;
  3067. my($cmd, $result);
  3068. $cmd = join(' -V ', "make $makeenv MASTER_SITE_BACKUP=''", $mvar);
  3069. $result = `$cmd`;
  3070. return chomp $result;
  3071. }
  3072. sub is_predefined {
  3073. my($url, $file) = @_;
  3074. my($site, $site_re);
  3075. my $subdir_re = quotemeta quotemeta '/%SUBDIR%/';
  3076. for my $site (keys %predefined) {
  3077. $site_re = quotemeta $site;
  3078. $site_re =~ s,$subdir_re,/(.*)/,;
  3079. if ($url =~ /$site_re/) {
  3080. &perror("WARN", $file, -1, "how about using ".
  3081. "\"\${MASTER_SITE_$predefined{$site}}\" with ".
  3082. "\"MASTER_SITE_SUBDIR=$1\", instead of \"$url\"?");
  3083. return &TRUE;
  3084. }
  3085. }
  3086. undef;
  3087. }
  3088. sub urlcheck {
  3089. my ($url, $file) = @_;
  3090. if ($url !~ m#^\w+://#) {
  3091. &perror("WARN", $file, -1, "\"$url\" doesn't appear to be a URL to me.");
  3092. }
  3093. if ($url !~ m#/(:[^/:]+)?$#) {
  3094. &perror("FATAL", $file, -1, "URL \"$url\" should ".
  3095. "end with \"/\" or a group name (e.g. :something).");
  3096. }
  3097. if ($url =~ m#://[^/]*:/#) {
  3098. &perror("FATAL", $file, -1, "URL \"$url\" contains ".
  3099. "extra \":\".");
  3100. }
  3101. if ($osname eq 'FreeBSD' && $url =~ m#(www\.freebsd\.org)/~.+/#i) {
  3102. &perror("WARN", $file, -1, "URL \"$url\", ".
  3103. "$1 should be ".
  3104. "people.FreeBSD.org");
  3105. }
  3106. }
  3107. sub TRUE {1;}
  3108. # Local variables:
  3109. # tab-width: 4
  3110. # End: