Sun Jan 31 17:18:54 2016 UTC ()
Updated pkglint to 5.3.5

Changes since 5.3.4:

* Added parser for Makefile conditionals
* Variables that are matched using the :M modifier are checked whether
  the matched value is sensible
* Reworded and explained warning for variable ordering in packages
* Fixed bug in Tree.String
* Fixed a few variable types


(rillig)
diff -r1.480 -r1.481 pkgsrc/pkgtools/pkglint/Makefile
diff -r1.83 -r1.84 pkgsrc/pkgtools/pkglint/TODO
diff -r1.7 -r1.8 pkgsrc/pkgtools/pkglint/files/globaldata.go
diff -r1.8 -r1.9 pkgsrc/pkgtools/pkglint/files/mkline.go
diff -r1.9 -r1.10 pkgsrc/pkgtools/pkglint/files/mkline_test.go
diff -r1.3 -r1.4 pkgsrc/pkgtools/pkglint/files/mklines.go
diff -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/package.go
diff -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/package_test.go
diff -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/util.go
diff -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/parser.go
diff -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/parser_test.go
diff -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/tree.go
diff -r1.1 -r1.2 pkgsrc/pkgtools/pkglint/files/tree_test.go
diff -r1.4 -r1.5 pkgsrc/pkgtools/pkglint/files/vardefs.go
diff -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/vartypecheck.go
diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go

cvs diff -r1.480 -r1.481 pkgsrc/pkgtools/pkglint/Makefile (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/Makefile 2016/01/27 21:55:50 1.480
+++ pkgsrc/pkgtools/pkglint/Makefile 2016/01/31 17:18:54 1.481
@@ -1,16 +1,16 @@ @@ -1,16 +1,16 @@
1# $NetBSD: Makefile,v 1.480 2016/01/27 21:55:50 rillig Exp $ 1# $NetBSD: Makefile,v 1.481 2016/01/31 17:18:54 rillig Exp $
2 2
3PKGNAME= pkglint-5.3.4 3PKGNAME= pkglint-5.3.5
4DISTFILES= # none 4DISTFILES= # none
5CATEGORIES= pkgtools 5CATEGORIES= pkgtools
6 6
7OWNER= rillig@NetBSD.org 7OWNER= rillig@NetBSD.org
8HOMEPAGE= http://www.NetBSD.org/docs/pkgsrc/ 8HOMEPAGE= http://www.NetBSD.org/docs/pkgsrc/
9COMMENT= Verifier for NetBSD packages 9COMMENT= Verifier for NetBSD packages
10LICENSE= 2-clause-bsd 10LICENSE= 2-clause-bsd
11CONFLICTS+= pkglint4-[0-9]* 11CONFLICTS+= pkglint4-[0-9]*
12 12
13WRKSRC= ${WRKDIR}/netbsd.org/pkglint 13WRKSRC= ${WRKDIR}/netbsd.org/pkglint
14NO_CHECKSUM= yes 14NO_CHECKSUM= yes
15USE_LANGUAGES= # none 15USE_LANGUAGES= # none
16USE_TOOLS+= pax 16USE_TOOLS+= pax

cvs diff -r1.83 -r1.84 pkgsrc/pkgtools/pkglint/Attic/TODO (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/Attic/TODO 2015/11/25 13:29:07 1.83
+++ pkgsrc/pkgtools/pkglint/Attic/TODO 2016/01/31 17:18:54 1.84
@@ -1,31 +1,28 @@ @@ -1,31 +1,28 @@
1$NetBSD: TODO,v 1.83 2015/11/25 13:29:07 rillig Exp $ 1$NetBSD: TODO,v 1.84 2016/01/31 17:18:54 rillig Exp $
2 2
3Please add your own entries at the bottom of this file. If possible, 3Please add your own entries at the bottom of this file. If possible,
4include the name of an example package where a warning should occur. 4include the name of an example package where a warning should occur.
5 5
6* warn about the use of ${WRKDIR:=...}, as this construct should only 6* warn about the use of ${WRKDIR:=...}, as this construct should only
7 be used with lists. 7 be used with lists.
8* Add checks for binary packages. See Debian/lintian for ideas. 
9* Of the user-defined variables, some may be used at load-time and some 8* Of the user-defined variables, some may be used at load-time and some
10 don't. Find out how pkglint can distinguish them. 9 don't. Find out how pkglint can distinguish them.
11* Make sure that no variable is modified at load-time after it has been 10* Make sure that no variable is modified at load-time after it has been
12 used once. This should at least flag BUILD_DEFS in bsd.pkg.mk. 11 used once. This should at least flag BUILD_DEFS in bsd.pkg.mk.
13* ${MACHINE_ARCH}-${LOWER_OPSYS}elf in PLISTs etc. is a NetBSD config.guess 12* ${MACHINE_ARCH}-${LOWER_OPSYS}elf in PLISTs etc. is a NetBSD config.guess
14 problem ==> use of ${APPEND_ELF} 13 problem ==> use of ${APPEND_ELF}
15* Packages including lang/python/extension.mk must follow the Python version 14* Packages including lang/python/extension.mk must follow the Python version
16 scheme. Enforcing PYPKGPREFIX for those is most likely a good idea. 15 scheme. Enforcing PYPKGPREFIX for those is most likely a good idea.
17* Check for parallel files/dirs whose names differ only in case. 16* Check for parallel files/dirs whose names differ only in case.
18* If a dependency depends on an option (in options.mk), it should also 17* If a dependency depends on an option (in options.mk), it should also
19 depend on the same option in the buildlink3.mk file. 18 depend on the same option in the buildlink3.mk file.
20* Complain about ${PKGSRC_COMPILER} == "sunpro", which should be 19* Complain about ${PKGSRC_COMPILER} == "sunpro", which should be
21 !empty(PKGSRC_COMPILER:Msunpro). 20 !empty(PKGSRC_COMPILER:Msunpro).
22* If USE_TOOLS has autoconf213, and the package does stuff like 
23 cd ${WRKSRC} && autoconf, then an incorrect warning is issued. 
24* don't complain about "procedure calls", like for pkg-build-options in 21* don't complain about "procedure calls", like for pkg-build-options in
25 the various buildlink3.mk files. 22 the various buildlink3.mk files.
26* if package A conflicts with B, then B should also conflict with A. 23* if package A conflicts with B, then B should also conflict with A.
27* When pkglint runs on a case-insensitive filesystem, it should still 24* When pkglint runs on a case-insensitive filesystem, it should still
28 point out problems that only occur on case-sensitive filesystems. For 25 point out problems that only occur on case-sensitive filesystems. For
29 example, devel/p5-Net-LDAP and devel/p5-Net-ldap should be considered 26 example, devel/p5-Net-LDAP and devel/p5-Net-ldap should be considered
30 different paths. 27 different paths.
31* Warn about using REPLACE_PYTHON without including application.mk. 28* Warn about using REPLACE_PYTHON without including application.mk.

cvs diff -r1.7 -r1.8 pkgsrc/pkgtools/pkglint/files/Attic/globaldata.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/globaldata.go 2016/01/24 02:03:28 1.7
+++ pkgsrc/pkgtools/pkglint/files/Attic/globaldata.go 2016/01/31 17:18:54 1.8
@@ -522,15 +522,18 @@ func (gd *GlobalData) loadDeprecatedVars @@ -522,15 +522,18 @@ func (gd *GlobalData) loadDeprecatedVars
522 "NO_MTREE": "You can just remove it.", 522 "NO_MTREE": "You can just remove it.",
523 523
524 // July 2012 524 // July 2012
525 "SETGIDGAME": "Use USE_GAMESGROUP instead.", 525 "SETGIDGAME": "Use USE_GAMESGROUP instead.",
526 "GAMEGRP": "Use GAMES_GROUP instead.", 526 "GAMEGRP": "Use GAMES_GROUP instead.",
527 "GAMEOWN": "Use GAMES_USER instead.", 527 "GAMEOWN": "Use GAMES_USER instead.",
528 528
529 // July 2013 529 // July 2013
530 "USE_GNU_READLINE": "Include \"../../devel/readline/buildlink3.mk\" instead.", 530 "USE_GNU_READLINE": "Include \"../../devel/readline/buildlink3.mk\" instead.",
531 531
532 // October 2014 532 // October 2014
533 "SVR4_PKGNAME": "Just remove it.", 533 "SVR4_PKGNAME": "Just remove it.",
534 "PKG_INSTALLATION_TYPES": "Just remove it.", 534 "PKG_INSTALLATION_TYPES": "Just remove it.",
 535
 536 // January 2016
 537 "SUBST_POSTCMD.*": "Has been removed, as it seemed unused.",
535 } 538 }
536} 539}

cvs diff -r1.8 -r1.9 pkgsrc/pkgtools/pkglint/files/Attic/mkline.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkline.go 2016/01/24 02:03:28 1.8
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkline.go 2016/01/31 17:18:54 1.9
@@ -801,52 +801,57 @@ func (mkline *MkLine) CheckText(text str @@ -801,52 +801,57 @@ func (mkline *MkLine) CheckText(text str
801 varbase, varext := m[1], m[2] 801 varbase, varext := m[1], m[2]
802 varname := varbase + varext 802 varname := varbase + varext
803 varcanon := varnameCanon(varname) 803 varcanon := varnameCanon(varname)
804 instead := G.globalData.Deprecated[varname] 804 instead := G.globalData.Deprecated[varname]
805 if instead == "" { 805 if instead == "" {
806 instead = G.globalData.Deprecated[varcanon] 806 instead = G.globalData.Deprecated[varcanon]
807 } 807 }
808 if instead != "" { 808 if instead != "" {
809 mkline.Warn2("Use of %q is deprecated. %s", varname, instead) 809 mkline.Warn2("Use of %q is deprecated. %s", varname, instead)
810 } 810 }
811 } 811 }
812} 812}
813 813
814func (mkline *MkLine) CheckIf() { 814func (mkline *MkLine) CheckCond() {
815 if G.opts.DebugTrace { 815 if G.opts.DebugTrace {
816 defer tracecall0()() 816 defer tracecall0()()
817 } 817 }
818 818
819 tree := mkline.parseMkCond(mkline.Args()) 819 p := NewParser(mkline.Args())
 820 cond := p.MkCond()
 821 if !p.EOF() {
 822 mkline.Warn1("Invalid conditional %q.", mkline.Args())
 823 return
 824 }
820 825
821 { 826 cond.Visit("empty", func(node *Tree) {
822 var pvarname, ppattern *string 827 varuse := node.args[0].(MkVarUse)
823 if tree.Match(NewTree("not", NewTree("empty", NewTree("match", &pvarname, &ppattern)))) { 828 varname := varuse.varname
824 vartype := mkline.getVariableType(*pvarname) 829 for _, modifier := range varuse.modifiers {
825 if vartype != nil && vartype.checker.IsEnum() { 830 if modifier[0] == 'M' || modifier[0] == 'N' {
826 if !matches(*ppattern, `[\$\[*]`) && !vartype.checker.HasEnum(*ppattern) { 831 mkline.CheckVartype(varname, opUseMatch, modifier[1:], "")
827 mkline.Warn2("Invalid :M value %q. Only { %s } are allowed.", *ppattern, vartype.checker.AllowedEnums()) 
828 } 
829 } 832 }
830 return 
831 } 833 }
832 } 834 })
833 835
834 { 836 cond.Visit("compareVarStr", func(node *Tree) {
835 var pop, pvarname, pvalue *string 837 varuse := node.args[0].(MkVarUse)
836 if tree.Match(NewTree("compareVarStr", &pvarname, &pop, &pvalue)) { 838 varname := varuse.varname
837 mkline.CheckVartype(*pvarname, opUse, *pvalue, "") 839 varmods := varuse.modifiers
 840 value := node.args[2].(string)
 841 if len(varmods) == 0 || len(varmods) == 1 && matches(varmods[0], `^[MN]`) && value != "" {
 842 mkline.CheckVartype(varname, opUseMatch, value, "")
838 } 843 }
839 } 844 })
840} 845}
841 846
842func (mkline *MkLine) CheckValidCharactersInValue(reValid string) { 847func (mkline *MkLine) CheckValidCharactersInValue(reValid string) {
843 rest := regcomp(reValid).ReplaceAllString(mkline.Value(), "") 848 rest := regcomp(reValid).ReplaceAllString(mkline.Value(), "")
844 if rest != "" { 849 if rest != "" {
845 uni := "" 850 uni := ""
846 for _, c := range rest { 851 for _, c := range rest {
847 uni += fmt.Sprintf(" %U", c) 852 uni += fmt.Sprintf(" %U", c)
848 } 853 }
849 mkline.Warn2("%s contains invalid characters (%s).", mkline.Varname(), uni[1:]) 854 mkline.Warn2("%s contains invalid characters (%s).", mkline.Varname(), uni[1:])
850 } 855 }
851} 856}
852 857
@@ -940,57 +945,26 @@ func matchMkCond(text string) (m bool, i @@ -940,57 +945,26 @@ func matchMkCond(text string) (m bool, i
940 i++ 945 i++
941 } 946 }
942 for i > argsStart && (text[i-1] == ' ' || text[i-1] == '\t') { 947 for i > argsStart && (text[i-1] == ' ' || text[i-1] == '\t') {
943 i-- 948 i--
944 } 949 }
945 argsEnd := i 950 argsEnd := i
946 951
947 m = true 952 m = true
948 indent = text[indentStart:indentEnd] 953 indent = text[indentStart:indentEnd]
949 args = text[argsStart:argsEnd] 954 args = text[argsStart:argsEnd]
950 return 955 return
951} 956}
952 957
953func (mkline *MkLine) parseMkCond(cond string) *Tree { 
954 if G.opts.DebugTrace { 
955 defer tracecall1(cond)() 
956 } 
957 
958 const ( 
959 repartVarname = `[A-Z_][A-Z0-9_]*(?:\.[\w_+\-]+)?` 
960 reDefined = `^defined\((` + repartVarname + `)\)` 
961 reEmpty = `^empty\((` + repartVarname + `)\)` 
962 reEmptyMatch = `^empty\((` + repartVarname + `):M([^\$:{})]+)\)` 
963 reCompare = `^\$\{(` + repartVarname + `)\}\s+(==|!=)\s+"([^"\$\\]*)"` 
964 ) 
965 
966 if m, rest := replaceFirst(cond, `^!`, ""); m != nil { 
967 return NewTree("not", mkline.parseMkCond(rest)) 
968 } 
969 if m, rest := replaceFirst(cond, reDefined, ""); m != nil { 
970 return NewTree("defined", mkline.parseMkCond(rest)) 
971 } 
972 if m, _ := replaceFirst(cond, reEmpty, ""); m != nil { 
973 return NewTree("empty", m[1]) 
974 } 
975 if m, _ := replaceFirst(cond, reEmptyMatch, ""); m != nil { 
976 return NewTree("empty", NewTree("match", m[1], m[2])) 
977 } 
978 if m, _ := replaceFirst(cond, reCompare, ""); m != nil { 
979 return NewTree("compareVarStr", m[1], m[2], m[3]) 
980 } 
981 return NewTree("unknown", cond) 
982} 
983 
984type NeedsQuoting uint8 958type NeedsQuoting uint8
985 959
986const ( 960const (
987 nqNo NeedsQuoting = iota 961 nqNo NeedsQuoting = iota
988 nqYes 962 nqYes
989 nqDoesntMatter 963 nqDoesntMatter
990 nqDontKnow 964 nqDontKnow
991) 965)
992 966
993func (mkline *MkLine) variableNeedsQuoting(varname string, vuc *VarUseContext) (needsQuoting NeedsQuoting) { 967func (mkline *MkLine) variableNeedsQuoting(varname string, vuc *VarUseContext) (needsQuoting NeedsQuoting) {
994 if G.opts.DebugTrace { 968 if G.opts.DebugTrace {
995 defer tracecall(varname, *vuc, "=>", needsQuoting)() 969 defer tracecall(varname, *vuc, "=>", needsQuoting)()
996 } 970 }

cvs diff -r1.9 -r1.10 pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go 2016/01/27 21:55:51 1.9
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go 2016/01/31 17:18:54 1.10
@@ -295,59 +295,51 @@ func (s *Suite) TestMkLine_fields(c *che @@ -295,59 +295,51 @@ func (s *Suite) TestMkLine_fields(c *che
295 c.Check(s.Output(), equals, "WARN: test.mk:9: Space before colon in dependency line.\n") 295 c.Check(s.Output(), equals, "WARN: test.mk:9: Space before colon in dependency line.\n")
296} 296}
297 297
298func (s *Suite) TestMkLine_checkVarassign(c *check.C) { 298func (s *Suite) TestMkLine_checkVarassign(c *check.C) {
299 G.Pkg = NewPackage("graphics/gimp-fix-ca") 299 G.Pkg = NewPackage("graphics/gimp-fix-ca")
300 G.globalData.InitVartypes() 300 G.globalData.InitVartypes()
301 mkline := NewMkLine(NewLine("fname", 10, "MASTER_SITES=http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file=", nil)) 301 mkline := NewMkLine(NewLine("fname", 10, "MASTER_SITES=http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file=", nil))
302 302
303 mkline.CheckVarassign() 303 mkline.CheckVarassign()
304 304
305 c.Check(s.Output(), equals, "") 305 c.Check(s.Output(), equals, "")
306} 306}
307 307
308func (s *Suite) TestParseMkCond_NotEmptyMatch(c *check.C) { 
309 mkline := NewMkLine(NewLine("fname", 1, ".if !empty(USE_LIBTOOL:M[Yy][Ee][Ss])", nil)) 
310 
311 cond := mkline.parseMkCond(mkline.Args()) 
312 
313 c.Check(cond, check.DeepEquals, NewTree("not", NewTree("empty", NewTree("match", "USE_LIBTOOL", "[Yy][Ee][Ss]")))) 
314} 
315 
316func (s *Suite) TestParseMkCond_Compare(c *check.C) { 
317 mkline := NewMkLine(NewLine("fname", 1, ".if ${VARNAME} != \"Value\"", nil)) 
318 
319 cond := mkline.parseMkCond(mkline.Args()) 
320 
321 c.Check(cond, check.DeepEquals, NewTree("compareVarStr", "VARNAME", "!=", "Value")) 
322} 
323 
324func (s *Suite) TestChecklineMkCondition(c *check.C) { 308func (s *Suite) TestChecklineMkCondition(c *check.C) {
325 s.UseCommandLine(c, "-Wtypes") 309 s.UseCommandLine(c, "-Wtypes")
326 G.globalData.InitVartypes() 310 G.globalData.InitVartypes()
327 311
328 NewMkLine(NewLine("fname", 1, ".if !empty(PKGSRC_COMPILER:Mmycc)", nil)).CheckIf() 312 NewMkLine(NewLine("fname", 1, ".if !empty(PKGSRC_COMPILER:Mmycc)", nil)).CheckCond()
329 313
330 c.Check(s.Stdout(), equals, "WARN: fname:1: Invalid :M value \"mycc\". "+ 314 c.Check(s.Stdout(), equals, "WARN: fname:1: The pattern \"mycc\" cannot match any of "+
331 "Only { ccache ccc clang distcc f2c gcc hp icc ido gcc mipspro "+ 315 "{ ccache ccc clang distcc f2c gcc hp icc ido "+
332 "mipspro-ucode pcc sunpro xlc } are allowed.\n") 316 "gcc mipspro mipspro-ucode pcc sunpro xlc } for PKGSRC_COMPILER.\n")
333 317
334 NewMkLine(NewLine("fname", 1, ".elif ${A} != ${B}", nil)).CheckIf() 318 NewMkLine(NewLine("fname", 1, ".elif ${A} != ${B}", nil)).CheckCond()
335 319
336 c.Check(s.Stdout(), equals, "") // Unknown condition types are silently ignored 320 c.Check(s.Stdout(), equals, "")
337 321
338 NewMkLine(NewLine("fname", 1, ".if ${HOMEPAGE} == \"mailto:someone@example.org\"", nil)).CheckIf() 322 NewMkLine(NewLine("fname", 1, ".if ${HOMEPAGE} == \"mailto:someone@example.org\"", nil)).CheckCond()
339 323
340 c.Check(s.Output(), equals, "WARN: fname:1: \"mailto:someone@example.org\" is not a valid URL.\n") 324 c.Check(s.Output(), equals, "WARN: fname:1: \"mailto:someone@example.org\" is not a valid URL.\n")
 325
 326 NewMkLine(NewLine("fname", 1, ".if !empty(PKGSRC_RUN_TEST:M[Y][eE][sS])", nil)).CheckCond()
 327
 328 c.Check(s.Output(), equals, "WARN: fname:1: PKGSRC_RUN_TEST should be matched against \"[yY][eE][sS]\" or \"[nN][oO]\", not \"[Y][eE][sS]\".\n")
 329
 330 NewMkLine(NewLine("fname", 1, ".if !empty(IS_BUILTIN.Xfixes:M[yY][eE][sS])", nil)).CheckCond()
 331
 332 c.Check(s.Output(), equals, "")
341} 333}
342 334
343func (s *Suite) TestMkLine_variableNeedsQuoting(c *check.C) { 335func (s *Suite) TestMkLine_variableNeedsQuoting(c *check.C) {
344 mkline := NewMkLine(NewLine("fname", 1, "PKGNAME := ${UNKNOWN}", nil)) 336 mkline := NewMkLine(NewLine("fname", 1, "PKGNAME := ${UNKNOWN}", nil))
345 G.globalData.InitVartypes() 337 G.globalData.InitVartypes()
346 pkgnameType := G.globalData.vartypes["PKGNAME"] 338 pkgnameType := G.globalData.vartypes["PKGNAME"]
347 339
348 vuc := &VarUseContext{pkgnameType, vucTimeParse, vucQuotUnknown, vucExtentUnknown} 340 vuc := &VarUseContext{pkgnameType, vucTimeParse, vucQuotUnknown, vucExtentUnknown}
349 nq := mkline.variableNeedsQuoting("UNKNOWN", vuc) 341 nq := mkline.variableNeedsQuoting("UNKNOWN", vuc)
350 342
351 c.Check(nq, equals, nqDontKnow) 343 c.Check(nq, equals, nqDontKnow)
352} 344}
353 345
@@ -433,27 +425,27 @@ func (s *Suite) TestMkLine_CheckVarusePe @@ -433,27 +425,27 @@ func (s *Suite) TestMkLine_CheckVarusePe
433 "COMMENT=\t${GAMES_USER}", 425 "COMMENT=\t${GAMES_USER}",
434 "COMMENT:=\t${PKGBASE}", 426 "COMMENT:=\t${PKGBASE}",
435 "PYPKGPREFIX=${PKGBASE}") 427 "PYPKGPREFIX=${PKGBASE}")
436 G.globalData.UserDefinedVars = map[string]*MkLine{ 428 G.globalData.UserDefinedVars = map[string]*MkLine{
437 "GAMES_USER": mklines.mklines[0], 429 "GAMES_USER": mklines.mklines[0],
438 } 430 }
439 431
440 mklines.Check() 432 mklines.Check()
441 433
442 c.Check(s.Output(), equals, ""+ 434 c.Check(s.Output(), equals, ""+
443 "WARN: options.mk:2: The user-defined variable GAMES_USER is used but not added to BUILD_DEFS.\n"+ 435 "WARN: options.mk:2: The user-defined variable GAMES_USER is used but not added to BUILD_DEFS.\n"+
444 "WARN: options.mk:3: PKGBASE should not be evaluated at load time.\n"+ 436 "WARN: options.mk:3: PKGBASE should not be evaluated at load time.\n"+
445 "WARN: options.mk:4: The variable PYPKGPREFIX may not be set in this file; it would be ok in pyversion.mk.\n"+ 437 "WARN: options.mk:4: The variable PYPKGPREFIX may not be set in this file; it would be ok in pyversion.mk.\n"+
446 "WARN: options.mk:4: \"${PKGBASE}\" is not valid for PYPKGPREFIX. Use one of { py27 py33 py34 } instead.\n"+ 438 "WARN: options.mk:4: \"${PKGBASE}\" is not valid for PYPKGPREFIX. Use one of { py27 py33 py34 py35 } instead.\n"+
447 "WARN: options.mk:4: PKGBASE should not be evaluated indirectly at load time.\n"+ 439 "WARN: options.mk:4: PKGBASE should not be evaluated indirectly at load time.\n"+
448 "NOTE: options.mk:4: This variable value should be aligned to column 17.\n") 440 "NOTE: options.mk:4: This variable value should be aligned to column 17.\n")
449} 441}
450 442
451func (s *Suite) TestMkLine_WarnVaruseLocalbase(c *check.C) { 443func (s *Suite) TestMkLine_WarnVaruseLocalbase(c *check.C) {
452 mkline := NewMkLine(NewLine("options.mk", 56, "PKGNAME=${LOCALBASE}", nil)) 444 mkline := NewMkLine(NewLine("options.mk", 56, "PKGNAME=${LOCALBASE}", nil))
453 445
454 mkline.WarnVaruseLocalbase() 446 mkline.WarnVaruseLocalbase()
455 447
456 c.Check(s.Output(), equals, "WARN: options.mk:56: The LOCALBASE variable should not be used by packages.\n") 448 c.Check(s.Output(), equals, "WARN: options.mk:56: The LOCALBASE variable should not be used by packages.\n")
457} 449}
458 450
459func (s *Suite) TestMkLine_Misc(c *check.C) { 451func (s *Suite) TestMkLine_Misc(c *check.C) {

cvs diff -r1.3 -r1.4 pkgsrc/pkgtools/pkglint/files/Attic/mklines.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mklines.go 2016/01/26 21:10:42 1.3
+++ pkgsrc/pkgtools/pkglint/files/Attic/mklines.go 2016/01/31 17:18:54 1.4
@@ -32,33 +32,33 @@ func NewMkLines(lines []*Line) *MkLines  @@ -32,33 +32,33 @@ func NewMkLines(lines []*Line) *MkLines
32 return &MkLines{ 32 return &MkLines{
33 mklines, 33 mklines,
34 lines, 34 lines,
35 make(map[string]bool), 35 make(map[string]bool),
36 make([]int, 1), 36 make([]int, 1),
37 "", 37 "",
38 make(map[string]*MkLine), 38 make(map[string]*MkLine),
39 make(map[string]*MkLine), 39 make(map[string]*MkLine),
40 make(map[string]bool), 40 make(map[string]bool),
41 make(map[string]bool), 41 make(map[string]bool),
42 tools} 42 tools}
43} 43}
44 44
45func (mklines *MkLines) IndentDepth() int { 45func (mklines *MkLines) indentDepth() int {
46 return mklines.indentation[len(mklines.indentation)-1] 46 return mklines.indentation[len(mklines.indentation)-1]
47} 47}
48func (mklines *MkLines) PopIndent() { 48func (mklines *MkLines) popIndent() {
49 mklines.indentation = mklines.indentation[:len(mklines.indentation)-1] 49 mklines.indentation = mklines.indentation[:len(mklines.indentation)-1]
50} 50}
51func (mklines *MkLines) PushIndent(indent int) { 51func (mklines *MkLines) pushIndent(indent int) {
52 mklines.indentation = append(mklines.indentation, indent) 52 mklines.indentation = append(mklines.indentation, indent)
53} 53}
54 54
55func (mklines *MkLines) DefineVar(mkline *MkLine, varname string) { 55func (mklines *MkLines) DefineVar(mkline *MkLine, varname string) {
56 if mklines.vardef[varname] == nil { 56 if mklines.vardef[varname] == nil {
57 mklines.vardef[varname] = mkline 57 mklines.vardef[varname] = mkline
58 } 58 }
59 varcanon := varnameCanon(varname) 59 varcanon := varnameCanon(varname)
60 if mklines.vardef[varcanon] == nil { 60 if mklines.vardef[varcanon] == nil {
61 mklines.vardef[varcanon] = mkline 61 mklines.vardef[varcanon] = mkline
62 } 62 }
63} 63}
64 64
@@ -78,45 +78,45 @@ func (mklines *MkLines) VarValue(varname @@ -78,45 +78,45 @@ func (mklines *MkLines) VarValue(varname
78 } 78 }
79 return "", false 79 return "", false
80} 80}
81 81
82func (mklines *MkLines) Check() { 82func (mklines *MkLines) Check() {
83 if G.opts.DebugTrace { 83 if G.opts.DebugTrace {
84 defer tracecall1(mklines.lines[0].Fname)() 84 defer tracecall1(mklines.lines[0].Fname)()
85 } 85 }
86 86
87 G.Mk = mklines 87 G.Mk = mklines
88 defer func() { G.Mk = nil }() 88 defer func() { G.Mk = nil }()
89 89
90 allowedTargets := make(map[string]bool) 90 allowedTargets := make(map[string]bool)
91 prefixes := splitOnSpace("pre do post") 91 prefixes := [...]string{"pre", "do", "post"}
92 actions := splitOnSpace("fetch extract patch tools wrapper configure build test install package clean") 92 actions := [...]string{"fetch", "extract", "patch", "tools", "wrapper", "configure", "build", "test", "install", "package", "clean"}
93 for _, prefix := range prefixes { 93 for _, prefix := range prefixes {
94 for _, action := range actions { 94 for _, action := range actions {
95 allowedTargets[prefix+"-"+action] = true 95 allowedTargets[prefix+"-"+action] = true
96 } 96 }
97 } 97 }
98 98
99 // In the first pass, all additions to BUILD_DEFS and USE_TOOLS 99 // In the first pass, all additions to BUILD_DEFS and USE_TOOLS
100 // are collected to make the order of the definitions irrelevant. 100 // are collected to make the order of the definitions irrelevant.
101 mklines.DetermineUsedVariables() 101 mklines.DetermineUsedVariables()
102 mklines.determineDefinedVariables() 102 mklines.determineDefinedVariables()
103 103
104 // In the second pass, the actual checks are done. 104 // In the second pass, the actual checks are done.
105 105
106 mklines.lines[0].CheckRcsid(`#\s+`, "# ") 106 mklines.lines[0].CheckRcsid(`#\s+`, "# ")
107 107
108 substcontext := new(SubstContext) 108 var substcontext SubstContext
109 varalign := new(VaralignBlock) 109 var varalign VaralignBlock
110 for _, mkline := range mklines.mklines { 110 for _, mkline := range mklines.mklines {
111 mkline.Line.CheckTrailingWhitespace() 111 mkline.Line.CheckTrailingWhitespace()
112 mkline.Line.CheckValidCharacters(`[\t -~]`) 112 mkline.Line.CheckValidCharacters(`[\t -~]`)
113 varalign.Check(mkline) 113 varalign.Check(mkline)
114 114
115 switch { 115 switch {
116 case mkline.IsEmpty(): 116 case mkline.IsEmpty():
117 substcontext.Finish(mkline) 117 substcontext.Finish(mkline)
118 118
119 case mkline.IsVarassign(): 119 case mkline.IsVarassign():
120 mklines.target = "" 120 mklines.target = ""
121 mkline.CheckVarassign() 121 mkline.CheckVarassign()
122 substcontext.Varassign(mkline) 122 substcontext.Varassign(mkline)
@@ -133,28 +133,28 @@ func (mklines *MkLines) Check() { @@ -133,28 +133,28 @@ func (mklines *MkLines) Check() {
133 case mkline.IsCond(): 133 case mkline.IsCond():
134 mklines.checklineCond(mkline) 134 mklines.checklineCond(mkline)
135 135
136 case mkline.IsDependency(): 136 case mkline.IsDependency():
137 mklines.checklineDependencyRule(mkline, mkline.Targets(), mkline.Sources(), allowedTargets) 137 mklines.checklineDependencyRule(mkline, mkline.Targets(), mkline.Sources(), allowedTargets)
138 } 138 }
139 } 139 }
140 lastMkline := mklines.mklines[len(mklines.mklines)-1] 140 lastMkline := mklines.mklines[len(mklines.mklines)-1]
141 substcontext.Finish(lastMkline) 141 substcontext.Finish(lastMkline)
142 varalign.Finish() 142 varalign.Finish()
143 143
144 ChecklinesTrailingEmptyLines(mklines.lines) 144 ChecklinesTrailingEmptyLines(mklines.lines)
145 145
146 if len(mklines.indentation) != 1 && mklines.IndentDepth() != 0 { 146 if len(mklines.indentation) != 1 && mklines.indentDepth() != 0 {
147 lastMkline.Line.Errorf("Directive indentation is not 0, but %d.", mklines.IndentDepth()) 147 lastMkline.Line.Errorf("Directive indentation is not 0, but %d.", mklines.indentDepth())
148 } 148 }
149 149
150 SaveAutofixChanges(mklines.lines) 150 SaveAutofixChanges(mklines.lines)
151} 151}
152 152
153func (mklines *MkLines) determineDefinedVariables() { 153func (mklines *MkLines) determineDefinedVariables() {
154 for _, mkline := range mklines.mklines { 154 for _, mkline := range mklines.mklines {
155 if !mkline.IsVarassign() { 155 if !mkline.IsVarassign() {
156 continue 156 continue
157 } 157 }
158 158
159 varcanon := mkline.Varcanon() 159 varcanon := mkline.Varcanon()
160 switch varcanon { 160 switch varcanon {
@@ -213,59 +213,59 @@ func (mklines *MkLines) DetermineUsedVar @@ -213,59 +213,59 @@ func (mklines *MkLines) DetermineUsedVar
213 varnames := mkline.determineUsedVariables() 213 varnames := mkline.determineUsedVariables()
214 for _, varname := range varnames { 214 for _, varname := range varnames {
215 mklines.UseVar(mkline, varname) 215 mklines.UseVar(mkline, varname)
216 } 216 }
217 } 217 }
218} 218}
219 219
220func (mklines *MkLines) checklineCond(mkline *MkLine) { 220func (mklines *MkLines) checklineCond(mkline *MkLine) {
221 indent, directive, args := mkline.Indent(), mkline.Directive(), mkline.Args() 221 indent, directive, args := mkline.Indent(), mkline.Directive(), mkline.Args()
222 222
223 switch directive { 223 switch directive {
224 case "endif", "endfor", "elif", "else": 224 case "endif", "endfor", "elif", "else":
225 if len(mklines.indentation) > 1 { 225 if len(mklines.indentation) > 1 {
226 mklines.PopIndent() 226 mklines.popIndent()
227 } else { 227 } else {
228 mkline.Error1("Unmatched .%s.", directive) 228 mkline.Error1("Unmatched .%s.", directive)
229 } 229 }
230 } 230 }
231 231
232 // Check the indentation 232 // Check the indentation
233 if expected := strings.Repeat(" ", mklines.IndentDepth()); indent != expected { 233 if expected := strings.Repeat(" ", mklines.indentDepth()); indent != expected {
234 if G.opts.WarnSpace && !mkline.Line.AutofixReplace("."+indent, "."+expected) { 234 if G.opts.WarnSpace && !mkline.Line.AutofixReplace("."+indent, "."+expected) {
235 mkline.Line.Notef("This directive should be indented by %d spaces.", mklines.IndentDepth()) 235 mkline.Line.Notef("This directive should be indented by %d spaces.", mklines.indentDepth())
236 } 236 }
237 } 237 }
238 238
239 if directive == "if" && matches(args, `^!defined\([\w]+_MK\)$`) { 239 if directive == "if" && matches(args, `^!defined\([\w]+_MK\)$`) {
240 mklines.PushIndent(mklines.IndentDepth()) 240 mklines.pushIndent(mklines.indentDepth())
241 241
242 } else if matches(directive, `^(?:if|ifdef|ifndef|for|elif|else)$`) { 242 } else if matches(directive, `^(?:if|ifdef|ifndef|for|elif|else)$`) {
243 mklines.PushIndent(mklines.IndentDepth() + 2) 243 mklines.pushIndent(mklines.indentDepth() + 2)
244 } 244 }
245 245
246 reDirectivesWithArgs := `^(?:if|ifdef|ifndef|elif|for|undef)$` 246 reDirectivesWithArgs := `^(?:if|ifdef|ifndef|elif|for|undef)$`
247 if matches(directive, reDirectivesWithArgs) && args == "" { 247 if matches(directive, reDirectivesWithArgs) && args == "" {
248 mkline.Error1("\".%s\" requires arguments.", directive) 248 mkline.Error1("\".%s\" requires arguments.", directive)
249 249
250 } else if !matches(directive, reDirectivesWithArgs) && args != "" { 250 } else if !matches(directive, reDirectivesWithArgs) && args != "" {
251 mkline.Error1("\".%s\" does not take arguments.", directive) 251 mkline.Error1("\".%s\" does not take arguments.", directive)
252 252
253 if directive == "else" { 253 if directive == "else" {
254 mkline.Note0("If you meant \"else if\", use \".elif\".") 254 mkline.Note0("If you meant \"else if\", use \".elif\".")
255 } 255 }
256 256
257 } else if directive == "if" || directive == "elif" { 257 } else if directive == "if" || directive == "elif" {
258 mkline.CheckIf() 258 mkline.CheckCond()
259 259
260 } else if directive == "ifdef" || directive == "ifndef" { 260 } else if directive == "ifdef" || directive == "ifndef" {
261 if matches(args, `\s`) { 261 if matches(args, `\s`) {
262 mkline.Error1("The \".%s\" directive can only handle _one_ argument.", directive) 262 mkline.Error1("The \".%s\" directive can only handle _one_ argument.", directive)
263 } else { 263 } else {
264 mkline.Line.Warnf("The \".%s\" directive is deprecated. Please use \".if %sdefined(%s)\" instead.", 264 mkline.Line.Warnf("The \".%s\" directive is deprecated. Please use \".if %sdefined(%s)\" instead.",
265 directive, ifelseStr(directive == "ifdef", "", "!"), args) 265 directive, ifelseStr(directive == "ifdef", "", "!"), args)
266 } 266 }
267 267
268 } else if directive == "for" { 268 } else if directive == "for" {
269 if m, vars, values := match2(args, `^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$`); m { 269 if m, vars, values := match2(args, `^(\S+(?:\s*\S+)*?)\s+in\s+(.*)$`); m {
270 for _, forvar := range splitOnSpace(vars) { 270 for _, forvar := range splitOnSpace(vars) {
271 if !G.Infrastructure && hasPrefix(forvar, "_") { 271 if !G.Infrastructure && hasPrefix(forvar, "_") {

cvs diff -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/Attic/package.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/package.go 2016/01/27 21:55:51 1.5
+++ pkgsrc/pkgtools/pkglint/files/Attic/package.go 2016/01/31 17:18:54 1.6
@@ -673,27 +673,30 @@ func (pkg *Package) ChecklinesPackageMak @@ -673,27 +673,30 @@ func (pkg *Package) ChecklinesPackageMak
673 673
674 default: 674 default:
675 if vars[varindex].count != many { 675 if vars[varindex].count != many {
676 below[vars[varindex].varname] = belowWhat 676 below[vars[varindex].varname] = belowWhat
677 varindex++ 677 varindex++
678 } 678 }
679 lineno++ 679 lineno++
680 } 680 }
681 belowWhat = varcanon 681 belowWhat = varcanon
682 682
683 default: 683 default:
684 for varindex < len(vars) { 684 for varindex < len(vars) {
685 if vars[varindex].count == once && !maySkipSection { 685 if vars[varindex].count == once && !maySkipSection {
686 line.Warn1("%s should be set here.", vars[varindex].varname) 686 line.Warn1("The canonical position for the required variable %s is here.", vars[varindex].varname)
 687 Explain(
 688 "See doc/Makefile-example or the pkgsrc guide, section",
 689 "\"Package components\", subsection \"Makefile\" for more information.")
687 } 690 }
688 below[vars[varindex].varname] = belowWhat 691 below[vars[varindex].varname] = belowWhat
689 varindex++ 692 varindex++
690 } 693 }
691 nextSection = true 694 nextSection = true
692 if text == "" { 695 if text == "" {
693 belowWhat = "the previous empty line" 696 belowWhat = "the previous empty line"
694 lineno++ 697 lineno++
695 } 698 }
696 } 699 }
697 } 700 }
698} 701}
699 702

cvs diff -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/Attic/package_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/package_test.go 2016/01/27 21:55:51 1.5
+++ pkgsrc/pkgtools/pkglint/files/Attic/package_test.go 2016/01/31 17:18:54 1.6
@@ -29,28 +29,28 @@ func (s *Suite) TestChecklinesPackageMak @@ -29,28 +29,28 @@ func (s *Suite) TestChecklinesPackageMak
29 "CATEGORIES=x11")) 29 "CATEGORIES=x11"))
30 30
31 c.Check(s.Output(), equals, "") 31 c.Check(s.Output(), equals, "")
32 32
33 pkg.ChecklinesPackageMakefileVarorder(s.NewMkLines("Makefile", 33 pkg.ChecklinesPackageMakefileVarorder(s.NewMkLines("Makefile",
34 "# $"+"NetBSD$", 34 "# $"+"NetBSD$",
35 "", 35 "",
36 "DISTNAME=9term", 36 "DISTNAME=9term",
37 "CATEGORIES=x11", 37 "CATEGORIES=x11",
38 "", 38 "",
39 ".include \"../../mk/bsd.pkg.mk\"")) 39 ".include \"../../mk/bsd.pkg.mk\""))
40 40
41 c.Check(s.Output(), equals, ""+ 41 c.Check(s.Output(), equals, ""+
42 "WARN: Makefile:6: COMMENT should be set here.\n"+ 42 "WARN: Makefile:6: The canonical position for the required variable COMMENT is here.\n"+
43 "WARN: Makefile:6: LICENSE should be set here.\n") 43 "WARN: Makefile:6: The canonical position for the required variable LICENSE is here.\n")
44} 44}
45 45
46func (s *Suite) TestGetNbpart(c *check.C) { 46func (s *Suite) TestGetNbpart(c *check.C) {
47 pkg := NewPackage("category/pkgbase") 47 pkg := NewPackage("category/pkgbase")
48 pkg.vardef["PKGREVISION"] = NewMkLine(NewLine("Makefile", 1, "PKGREVISION=14", nil)) 48 pkg.vardef["PKGREVISION"] = NewMkLine(NewLine("Makefile", 1, "PKGREVISION=14", nil))
49 49
50 c.Check(pkg.getNbpart(), equals, "nb14") 50 c.Check(pkg.getNbpart(), equals, "nb14")
51 51
52 pkg.vardef["PKGREVISION"] = NewMkLine(NewLine("Makefile", 1, "PKGREVISION=asdf", nil)) 52 pkg.vardef["PKGREVISION"] = NewMkLine(NewLine("Makefile", 1, "PKGREVISION=asdf", nil))
53 53
54 c.Check(pkg.getNbpart(), equals, "") 54 c.Check(pkg.getNbpart(), equals, "")
55} 55}
56 56

cvs diff -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/Attic/util.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/util.go 2016/01/12 01:02:49 1.5
+++ pkgsrc/pkgtools/pkglint/files/Attic/util.go 2016/01/31 17:18:54 1.6
@@ -347,26 +347,29 @@ func (pr *PrefixReplacer) PeekByte() int @@ -347,26 +347,29 @@ func (pr *PrefixReplacer) PeekByte() int
347 } 347 }
348 return int(rest[0]) 348 return int(rest[0])
349} 349}
350 350
351func (pr *PrefixReplacer) Mark() string { 351func (pr *PrefixReplacer) Mark() string {
352 return pr.rest 352 return pr.rest
353} 353}
354func (pr *PrefixReplacer) Reset(mark string) { 354func (pr *PrefixReplacer) Reset(mark string) {
355 pr.rest = mark 355 pr.rest = mark
356} 356}
357func (pr *PrefixReplacer) Skip(n int) { 357func (pr *PrefixReplacer) Skip(n int) {
358 pr.rest = pr.rest[n:] 358 pr.rest = pr.rest[n:]
359} 359}
 360func (pr *PrefixReplacer) SkipSpace() {
 361 pr.rest = strings.TrimLeft(pr.rest, " \t")
 362}
360func (pr *PrefixReplacer) Since(mark string) string { 363func (pr *PrefixReplacer) Since(mark string) string {
361 return mark[:len(mark)-len(pr.rest)] 364 return mark[:len(mark)-len(pr.rest)]
362} 365}
363func (pr *PrefixReplacer) AdvanceRest() string { 366func (pr *PrefixReplacer) AdvanceRest() string {
364 rest := pr.rest 367 rest := pr.rest
365 pr.rest = "" 368 pr.rest = ""
366 return rest 369 return rest
367} 370}
368 371
369func (pr *PrefixReplacer) verifyBits(bits0x00, bits0x20, bits0x40, bits0x60 uint32, re string) { 372func (pr *PrefixReplacer) verifyBits(bits0x00, bits0x20, bits0x40, bits0x60 uint32, re string) {
370 if G.TestingData.VerifiedBits[re] { 373 if G.TestingData.VerifiedBits[re] {
371 return 374 return
372 } 375 }

cvs diff -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/Attic/parser.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/parser.go 2016/01/27 21:55:51 1.2
+++ pkgsrc/pkgtools/pkglint/files/Attic/parser.go 2016/01/31 17:18:54 1.3
@@ -270,13 +270,146 @@ func (p *Parser) VarUseModifiers(closing @@ -270,13 +270,146 @@ func (p *Parser) VarUseModifiers(closing
270 } 270 }
271 } 271 }
272 272
273 repl.Reset(modifierMark) 273 repl.Reset(modifierMark)
274 for p.VarUse() != nil || repl.AdvanceRegexp(`^([^:$`+closing+`]|\$\$)+`) { 274 for p.VarUse() != nil || repl.AdvanceRegexp(`^([^:$`+closing+`]|\$\$)+`) {
275 } 275 }
276 if suffixSubst := repl.Since(modifierMark); contains(suffixSubst, "=") { 276 if suffixSubst := repl.Since(modifierMark); contains(suffixSubst, "=") {
277 modifiers = append(modifiers, suffixSubst) 277 modifiers = append(modifiers, suffixSubst)
278 continue 278 continue
279 } 279 }
280 } 280 }
281 return modifiers 281 return modifiers
282} 282}
 283
 284func (p *Parser) MkCond() *Tree {
 285 return p.mkCondOr()
 286}
 287
 288func (p *Parser) mkCondOr() *Tree {
 289 and := p.mkCondAnd()
 290 if and == nil {
 291 return nil
 292 }
 293
 294 ands := append([]interface{}(nil), and)
 295 for {
 296 mark := p.repl.Mark()
 297 if !p.repl.AdvanceRegexp(`^\s*\|\|\s*`) {
 298 break
 299 }
 300 next := p.mkCondAnd()
 301 if next == nil {
 302 p.repl.Reset(mark)
 303 break
 304 }
 305 ands = append(ands, next)
 306 }
 307 if len(ands) == 1 {
 308 return and
 309 }
 310 return NewTree("or", ands...)
 311}
 312
 313func (p *Parser) mkCondAnd() *Tree {
 314 atom := p.mkCondAtom()
 315 if atom == nil {
 316 return nil
 317 }
 318
 319 atoms := append([]interface{}(nil), atom)
 320 for {
 321 mark := p.repl.Mark()
 322 if !p.repl.AdvanceRegexp(`^\s*&&\s*`) {
 323 break
 324 }
 325 next := p.mkCondAtom()
 326 if next == nil {
 327 p.repl.Reset(mark)
 328 break
 329 }
 330 atoms = append(atoms, next)
 331 }
 332 if len(atoms) == 1 {
 333 return atom
 334 }
 335 return NewTree("and", atoms...)
 336}
 337
 338func (p *Parser) mkCondAtom() *Tree {
 339 if G.opts.DebugTrace {
 340 defer tracecall1(p.Rest())()
 341 }
 342
 343 repl := p.repl
 344 mark := repl.Mark()
 345 repl.SkipSpace()
 346 switch {
 347 case repl.AdvanceStr("!"):
 348 cond := p.mkCondAtom()
 349 if cond != nil {
 350 return NewTree("not", cond)
 351 }
 352 case repl.AdvanceStr("("):
 353 cond := p.MkCond()
 354 if cond != nil {
 355 repl.SkipSpace()
 356 if repl.AdvanceStr(")") {
 357 return cond
 358 }
 359 }
 360 case repl.AdvanceRegexp(`^defined\s*\(`):
 361 if varname := p.Varname(); varname != "" {
 362 if repl.AdvanceStr(")") {
 363 return NewTree("defined", varname)
 364 }
 365 }
 366 case repl.AdvanceRegexp(`^empty\s*\(`):
 367 if varname := p.Varname(); varname != "" {
 368 modifiers := p.VarUseModifiers(")")
 369 if repl.AdvanceStr(")") {
 370 return NewTree("empty", MkVarUse{varname, modifiers})
 371 }
 372 }
 373 case repl.AdvanceRegexp(`^(commands|exists|make|target)\s*\(`):
 374 funcname := repl.m[1]
 375 argMark := repl.Mark()
 376 for p.VarUse() != nil || repl.AdvanceRegexp(`^[^$)]+`) {
 377 }
 378 arg := repl.Since(argMark)
 379 if repl.AdvanceStr(")") {
 380 return NewTree(funcname, arg)
 381 }
 382 default:
 383 lhs := p.VarUse()
 384 mark := repl.Mark()
 385 if lhs == nil && repl.AdvanceStr("\"") {
 386 if quotedLhs := p.VarUse(); quotedLhs != nil && repl.AdvanceStr("\"") {
 387 lhs = quotedLhs
 388 } else {
 389 repl.Reset(mark)
 390 }
 391 }
 392 if lhs != nil {
 393 if repl.AdvanceRegexp(`^\s*(<|<=|==|!=|>=|>)\s*(\d+(?:\.\d+)?)`) {
 394 return NewTree("compareVarNum", *lhs, repl.m[1], repl.m[2])
 395 }
 396 if repl.AdvanceRegexp(`^\s*(<|<=|==|!=|>=|>)\s*`) {
 397 op := repl.m[1]
 398 if (op == "!=" || op == "==") && repl.AdvanceRegexp(`^"([^"\$\\]*)"`) {
 399 return NewTree("compareVarStr", *lhs, op, repl.m[1])
 400 } else if repl.AdvanceRegexp(`^\w+`) {
 401 return NewTree("compareVarStr", *lhs, op, repl.m[0])
 402 } else if rhs := p.VarUse(); rhs != nil {
 403 return NewTree("compareVarVar", *lhs, op, *rhs)
 404 }
 405 } else {
 406 return NewTree("not", NewTree("empty", *lhs)) // See devel/bmake/files/cond.c:/\* For \.if \$/
 407 }
 408 }
 409 if repl.AdvanceRegexp(`^\d+(?:\.\d+)?`) {
 410 return NewTree("literalNum", repl.m[0])
 411 }
 412 }
 413 repl.Reset(mark)
 414 return nil
 415}

cvs diff -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/Attic/parser_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/parser_test.go 2016/01/27 21:55:51 1.2
+++ pkgsrc/pkgtools/pkglint/files/Attic/parser_test.go 2016/01/31 17:18:54 1.3
@@ -128,13 +128,90 @@ func (s *Suite) TestParser_MkTokens(c *c @@ -128,13 +128,90 @@ func (s *Suite) TestParser_MkTokens(c *c
128 token("${${XKBBASE}/xkbcomp:L:Q}", varuse("${XKBBASE}/xkbcomp", "L", "Q")) 128 token("${${XKBBASE}/xkbcomp:L:Q}", varuse("${XKBBASE}/xkbcomp", "L", "Q"))
129 token("${${PKGBASE} ${PKGVERSION}:L}", varuse("${PKGBASE} ${PKGVERSION}", "L")) 129 token("${${PKGBASE} ${PKGVERSION}:L}", varuse("${PKGBASE} ${PKGVERSION}", "L"))
130 token("${empty(CFLAGS):?:-cflags ${CFLAGS:Q}}", varuse("empty(CFLAGS)", "?:-cflags ${CFLAGS:Q}")) 130 token("${empty(CFLAGS):?:-cflags ${CFLAGS:Q}}", varuse("empty(CFLAGS)", "?:-cflags ${CFLAGS:Q}"))
131 token("${${${PKG_INFO} -E ${d} || echo:L:sh}:L:C/[^[0-9]]*/ /g:[1..3]:ts.}", 131 token("${${${PKG_INFO} -E ${d} || echo:L:sh}:L:C/[^[0-9]]*/ /g:[1..3]:ts.}",
132 varuse("${${PKG_INFO} -E ${d} || echo:L:sh}", "L", "C/[^[0-9]]*/ /g", "[1..3]", "ts.")) 132 varuse("${${PKG_INFO} -E ${d} || echo:L:sh}", "L", "C/[^[0-9]]*/ /g", "[1..3]", "ts."))
133 token("${VAR:S/-//S/.//}", varuse("VAR", "S/-//", "S/.//")) // For :S and :C, the colon can be left out. 133 token("${VAR:S/-//S/.//}", varuse("VAR", "S/-//", "S/.//")) // For :S and :C, the colon can be left out.
134 token("${VAR:ts}", varuse("VAR", "ts")) // The separator character can be left out. 134 token("${VAR:ts}", varuse("VAR", "ts")) // The separator character can be left out.
135 token("${VAR:ts\\000012}", varuse("VAR", "ts\\000012")) // The separator character can be a long octal number. 135 token("${VAR:ts\\000012}", varuse("VAR", "ts\\000012")) // The separator character can be a long octal number.
136 token("${VAR:ts\\124}", varuse("VAR", "ts\\124")) // Or even decimal. 136 token("${VAR:ts\\124}", varuse("VAR", "ts\\124")) // Or even decimal.
137 137
138 parse("${VAR)", nil, "${VAR)") // Opening brace, closing parenthesis 138 parse("${VAR)", nil, "${VAR)") // Opening brace, closing parenthesis
139 parse("$(VAR}", nil, "$(VAR}") // Opening parenthesis, closing brace 139 parse("$(VAR}", nil, "$(VAR}") // Opening parenthesis, closing brace
140} 140}
 141
 142func (s *Suite) TestParser_MkCond_Basics(c *check.C) {
 143 condrest := func(input string, expectedTree *Tree, expectedRest string) {
 144 p := NewParser(input)
 145 actualTree := p.MkCond()
 146 c.Check(actualTree, deepEquals, expectedTree)
 147 c.Check(p.Rest(), equals, expectedRest)
 148 }
 149 cond := func(input string, expectedTree *Tree) {
 150 condrest(input, expectedTree, "")
 151 }
 152 literal := func(literal string) MkToken {
 153 return MkToken{literal: literal}
 154 }
 155 varuse := func(varname string, modifiers ...string) MkVarUse {
 156 return MkVarUse{varname: varname, modifiers: modifiers}
 157 }
 158 _, _ = literal, varuse
 159
 160 cond("${OPSYS:MNetBSD}",
 161 NewTree("not", NewTree("empty", varuse("OPSYS", "MNetBSD"))))
 162 cond("defined(VARNAME)",
 163 NewTree("defined", "VARNAME"))
 164 cond("empty(VARNAME)",
 165 NewTree("empty", varuse("VARNAME")))
 166 cond("!empty(VARNAME)",
 167 NewTree("not", NewTree("empty", varuse("VARNAME"))))
 168 cond("!empty(VARNAME:M[yY][eE][sS])",
 169 NewTree("not", NewTree("empty", varuse("VARNAME", "M[yY][eE][sS]"))))
 170 cond("${VARNAME} != \"Value\"",
 171 NewTree("compareVarStr", varuse("VARNAME"), "!=", "Value"))
 172 cond("${VARNAME:Mi386} != \"Value\"",
 173 NewTree("compareVarStr", varuse("VARNAME", "Mi386"), "!=", "Value"))
 174 cond("${VARNAME} != Value",
 175 NewTree("compareVarStr", varuse("VARNAME"), "!=", "Value"))
 176 cond("\"${VARNAME}\" != Value",
 177 NewTree("compareVarStr", varuse("VARNAME"), "!=", "Value"))
 178 cond("(defined(VARNAME))",
 179 NewTree("defined", "VARNAME"))
 180 cond("exists(/etc/hosts)",
 181 NewTree("exists", "/etc/hosts"))
 182 cond("exists(${PREFIX}/var)",
 183 NewTree("exists", "${PREFIX}/var"))
 184 cond("${OPSYS} == \"NetBSD\" || ${OPSYS} == \"OpenBSD\"",
 185 NewTree("or",
 186 NewTree("compareVarStr", varuse("OPSYS"), "==", "NetBSD"),
 187 NewTree("compareVarStr", varuse("OPSYS"), "==", "OpenBSD")))
 188 cond("${OPSYS} == \"NetBSD\" && ${MACHINE_ARCH} == \"i386\"",
 189 NewTree("and",
 190 NewTree("compareVarStr", varuse("OPSYS"), "==", "NetBSD"),
 191 NewTree("compareVarStr", varuse("MACHINE_ARCH"), "==", "i386")))
 192 cond("defined(A) && defined(B) || defined(C) && defined(D)",
 193 NewTree("or",
 194 NewTree("and",
 195 NewTree("defined", "A"),
 196 NewTree("defined", "B")),
 197 NewTree("and",
 198 NewTree("defined", "C"),
 199 NewTree("defined", "D"))))
 200
 201 // Exotic cases
 202 cond("0",
 203 NewTree("literalNum", "0"))
 204 cond("! ( defined(A) && empty(VARNAME) )",
 205 NewTree("not", NewTree("and", NewTree("defined", "A"), NewTree("empty", varuse("VARNAME")))))
 206 cond("${REQD_MAJOR} > ${MAJOR}",
 207 NewTree("compareVarVar", varuse("REQD_MAJOR"), ">", varuse("MAJOR")))
 208 cond("${OS_VERSION} >= 6.5",
 209 NewTree("compareVarNum", varuse("OS_VERSION"), ">=", "6.5"))
 210 cond("${OS_VERSION} == 5.3",
 211 NewTree("compareVarNum", varuse("OS_VERSION"), "==", "5.3"))
 212
 213 // Errors
 214 condrest("!empty(PKG_OPTIONS:Msndfile) || defined(PKG_OPTIONS:Msamplerate)",
 215 NewTree("not", NewTree("empty", varuse("PKG_OPTIONS", "Msndfile"))),
 216 " || defined(PKG_OPTIONS:Msamplerate)")
 217}

cvs diff -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/Attic/tree.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/tree.go 2016/01/12 01:02:49 1.2
+++ pkgsrc/pkgtools/pkglint/files/Attic/tree.go 2016/01/31 17:18:54 1.3
@@ -3,69 +3,39 @@ package main @@ -3,69 +3,39 @@ package main
3import ( 3import (
4 "fmt" 4 "fmt"
5) 5)
6 6
7type Tree struct { 7type Tree struct {
8 name string 8 name string
9 args []interface{} 9 args []interface{}
10} 10}
11 11
12func NewTree(name string, args ...interface{}) *Tree { 12func NewTree(name string, args ...interface{}) *Tree {
13 return &Tree{name, args} 13 return &Tree{name, args}
14} 14}
15 15
16// Checks whether this tree matches the given pattern, and if so, 
17// copies the corresponding nodes from the tree to the pattern. 
18// If the match is partially successful, some or all of the variables 
19// may have been copied or not. 
20func (t *Tree) Match(pattern *Tree) bool { 
21 if G.opts.DebugTrace { 
22 defer tracecall(t, pattern)() 
23 } 
24 if t.name != pattern.name || len(t.args) != len(pattern.args) { 
25 return false 
26 } 
27 
28 for i, targ := range t.args { 
29 parg := pattern.args[i] 
30 switch parg := parg.(type) { 
31 case *Tree: 
32 if targ, ok := targ.(*Tree); ok { 
33 if !targ.Match(parg) { 
34 return false 
35 } 
36 } else { 
37 return false 
38 } 
39 case **string: 
40 if targ, ok := targ.(string); ok { 
41 if *parg == nil { 
42 *parg = &targ 
43 } else if **parg != targ { 
44 return false 
45 } 
46 } else { 
47 return false 
48 } 
49 default: 
50 return false 
51 } 
52 } 
53 return true 
54} 
55 
56func (t *Tree) String() string { 16func (t *Tree) String() string {
57 s := "(" + t.name 17 s := "(" + t.name
58 for _, arg := range t.args { 18 for _, arg := range t.args {
59 if arg, ok := arg.(*Tree); ok { 19 if arg, ok := arg.(*Tree); ok {
60 s += " " + (*arg).String() 20 s += " " + (*arg).String()
61 continue 21 continue
62 } 22 }
63 if arg, ok := arg.(string); ok { 23 if arg, ok := arg.(string); ok {
64 s += fmt.Sprintf(" %q", arg) 24 s += fmt.Sprintf(" %q", arg)
65 continue 25 continue
66 } else { 
67 s += fmt.Sprintf(" %v", arg) 
68 } 26 }
 27 s += fmt.Sprintf(" %v", arg)
69 } 28 }
70 return s + ")" 29 return s + ")"
71} 30}
 31
 32func (t *Tree) Visit(nodename string, action func(t *Tree)) {
 33 if t.name == nodename {
 34 action(t)
 35 }
 36 for _, arg := range t.args {
 37 if child, ok := arg.(*Tree); ok {
 38 child.Visit(nodename, action)
 39 }
 40 }
 41}

cvs diff -r1.1 -r1.2 pkgsrc/pkgtools/pkglint/files/Attic/tree_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/tree_test.go 2015/11/25 13:29:07 1.1
+++ pkgsrc/pkgtools/pkglint/files/Attic/tree_test.go 2016/01/31 17:18:54 1.2
@@ -1,28 +1,9 @@ @@ -1,28 +1,9 @@
1package main 1package main
2 2
3import ( 3import (
4 check "gopkg.in/check.v1" 4 check "gopkg.in/check.v1"
5) 5)
6 6
7func (s *Suite) TestTreeMatch_successful(c *check.C) { 
8 var varname *string 
9 pattern := NewTree("not", NewTree("empty", &varname)) 
10 tree := NewTree("not", NewTree("empty", "VARNAME")) 
11 
12 c.Check(tree.Match(pattern), equals, true) 
13 c.Assert(varname, check.Not(equals), nil) 
14 c.Check(*varname, equals, "VARNAME") 
15} 
16 
17func (s *Suite) TestTreeMatch_fails(c *check.C) { 
18 var varname *string 
19 pattern := NewTree("not", NewTree("empty", &varname)) 
20 tree := NewTree("not", NewTree("full", "VARNAME")) 
21 
22 c.Check(tree.Match(pattern), equals, false) 
23 c.Check(varname, equals, (*string)(nil)) 
24} 
25 
26func (s *Suite) TestTreeString(c *check.C) { 7func (s *Suite) TestTreeString(c *check.C) {
27 c.Check(NewTree("not", NewTree("empty", "varname")).String(), equals, "(not (empty \"varname\"))") 8 c.Check(NewTree("not", NewTree("empty", "varname")).String(), equals, "(not (empty \"varname\"))")
28} 9}

cvs diff -r1.4 -r1.5 pkgsrc/pkgtools/pkglint/files/Attic/vardefs.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/vardefs.go 2016/01/12 01:02:49 1.4
+++ pkgsrc/pkgtools/pkglint/files/Attic/vardefs.go 2016/01/31 17:18:54 1.5
@@ -19,27 +19,27 @@ import ( @@ -19,27 +19,27 @@ import (
19func (gd *GlobalData) InitVartypes() { 19func (gd *GlobalData) InitVartypes() {
20 usr("ALLOW_VULNERABLE_PACKAGES", lkNone, CheckvarYes) 20 usr("ALLOW_VULNERABLE_PACKAGES", lkNone, CheckvarYes)
21 usr("MANINSTALL", lkShell, enum("maninstall catinstall")) 21 usr("MANINSTALL", lkShell, enum("maninstall catinstall"))
22 usr("MANZ", lkNone, CheckvarYes) 22 usr("MANZ", lkNone, CheckvarYes)
23 usr("GZIP", lkShell, CheckvarShellWord) 23 usr("GZIP", lkShell, CheckvarShellWord)
24 usr("MKCRYPTO", lkNone, CheckvarYesNo) 24 usr("MKCRYPTO", lkNone, CheckvarYesNo)
25 usr("OBJHOSTNAME", lkNone, CheckvarYes) 25 usr("OBJHOSTNAME", lkNone, CheckvarYes)
26 usr("OBJMACHINE", lkNone, CheckvarYes) 26 usr("OBJMACHINE", lkNone, CheckvarYes)
27 usr("PKG_SUFX", lkNone, CheckvarFilename) 27 usr("PKG_SUFX", lkNone, CheckvarFilename)
28 usr("PKGSRC_LOCKTYPE", lkNone, enum("none sleep once")) 28 usr("PKGSRC_LOCKTYPE", lkNone, enum("none sleep once"))
29 usr("PKGSRC_SLEEPSECS", lkNone, CheckvarInteger) 29 usr("PKGSRC_SLEEPSECS", lkNone, CheckvarInteger)
30 usr("USETBL", lkNone, CheckvarYes) 30 usr("USETBL", lkNone, CheckvarYes)
31 usr("ABI", lkNone, enum("32 64")) 31 usr("ABI", lkNone, enum("32 64"))
32 usr("PKG_DEVELOPER", lkNone, CheckvarYes) 32 usr("PKG_DEVELOPER", lkNone, CheckvarYesNo)
33 usr("USE_ABI_DEPENDS", lkNone, CheckvarYesNo) 33 usr("USE_ABI_DEPENDS", lkNone, CheckvarYesNo)
34 usr("PKG_REGISTER_SHELLS", lkNone, enum("YES NO")) 34 usr("PKG_REGISTER_SHELLS", lkNone, enum("YES NO"))
35 usr("PKGSRC_COMPILER", lkShell, enum("ccache ccc clang distcc f2c gcc hp icc ido gcc mipspro mipspro-ucode pcc sunpro xlc")) 35 usr("PKGSRC_COMPILER", lkShell, enum("ccache ccc clang distcc f2c gcc hp icc ido gcc mipspro mipspro-ucode pcc sunpro xlc"))
36 usr("PKGSRC_MESSAGE_RECIPIENTS", lkShell, CheckvarMailAddress) 36 usr("PKGSRC_MESSAGE_RECIPIENTS", lkShell, CheckvarMailAddress)
37 usr("PKGSRC_SHOW_BUILD_DEFS", lkNone, CheckvarYesNo) 37 usr("PKGSRC_SHOW_BUILD_DEFS", lkNone, CheckvarYesNo)
38 usr("PKGSRC_SHOW_PATCH_ERRORMSG", lkNone, CheckvarYesNo) 38 usr("PKGSRC_SHOW_PATCH_ERRORMSG", lkNone, CheckvarYesNo)
39 usr("PKGSRC_RUN_TEST", lkNone, CheckvarYesNo) 39 usr("PKGSRC_RUN_TEST", lkNone, CheckvarYesNo)
40 usr("PREFER_PKGSRC", lkShell, CheckvarIdentifier) 40 usr("PREFER_PKGSRC", lkShell, CheckvarIdentifier)
41 usr("PREFER_NATIVE", lkShell, CheckvarIdentifier) 41 usr("PREFER_NATIVE", lkShell, CheckvarIdentifier)
42 usr("PREFER_NATIVE_PTHREADS", lkNone, CheckvarYesNo) 42 usr("PREFER_NATIVE_PTHREADS", lkNone, CheckvarYesNo)
43 usr("LOCALBASE", lkNone, CheckvarPathname) 43 usr("LOCALBASE", lkNone, CheckvarPathname)
44 usr("CROSSBASE", lkNone, CheckvarPathname) 44 usr("CROSSBASE", lkNone, CheckvarPathname)
45 usr("VARBASE", lkNone, CheckvarPathname) 45 usr("VARBASE", lkNone, CheckvarPathname)
@@ -260,31 +260,31 @@ func (gd *GlobalData) InitVartypes() { @@ -260,31 +260,31 @@ func (gd *GlobalData) InitVartypes() {
260 sys("EMACS_LISPPREFIX", lkNone, CheckvarPathname) 260 sys("EMACS_LISPPREFIX", lkNone, CheckvarPathname)
261 acl("EMACS_MODULES", lkShell, CheckvarIdentifier, "Makefile, Makefile.common: set, append") 261 acl("EMACS_MODULES", lkShell, CheckvarIdentifier, "Makefile, Makefile.common: set, append")
262 sys("EMACS_PKGNAME_PREFIX", lkNone, CheckvarIdentifier) // Or the empty string. 262 sys("EMACS_PKGNAME_PREFIX", lkNone, CheckvarIdentifier) // Or the empty string.
263 sys("EMACS_TYPE", lkNone, enum("emacs xemacs")) 263 sys("EMACS_TYPE", lkNone, enum("emacs xemacs"))
264 acl("EMACS_USE_LEIM", lkNone, CheckvarYes, "") 264 acl("EMACS_USE_LEIM", lkNone, CheckvarYes, "")
265 acl("EMACS_VERSIONS_ACCEPTED", lkShell, enum("emacs25 emacs24 emacs24nox emacs23 emacs23nox emacs22 emacs22nox emacs21 emacs21nox emacs20 xemacs215 xemacs215nox xemacs214 xemacs214nox"), "Makefile: set") 265 acl("EMACS_VERSIONS_ACCEPTED", lkShell, enum("emacs25 emacs24 emacs24nox emacs23 emacs23nox emacs22 emacs22nox emacs21 emacs21nox emacs20 xemacs215 xemacs215nox xemacs214 xemacs214nox"), "Makefile: set")
266 sys("EMACS_VERSION_MAJOR", lkNone, CheckvarInteger) 266 sys("EMACS_VERSION_MAJOR", lkNone, CheckvarInteger)
267 sys("EMACS_VERSION_MINOR", lkNone, CheckvarInteger) 267 sys("EMACS_VERSION_MINOR", lkNone, CheckvarInteger)
268 acl("EMACS_VERSION_REQD", lkShell, enum("emacs24 emacs24nox emacs23 emacs23nox emacs22 emacs22nox emacs21 emacs21nox emacs20 xemacs215 xemacs214"), "Makefile: set, append") 268 acl("EMACS_VERSION_REQD", lkShell, enum("emacs24 emacs24nox emacs23 emacs23nox emacs22 emacs22nox emacs21 emacs21nox emacs20 xemacs215 xemacs214"), "Makefile: set, append")
269 sys("EMULDIR", lkNone, CheckvarPathname) 269 sys("EMULDIR", lkNone, CheckvarPathname)
270 sys("EMULSUBDIR", lkNone, CheckvarPathname) 270 sys("EMULSUBDIR", lkNone, CheckvarPathname)
271 sys("OPSYS_EMULDIR", lkNone, CheckvarPathname) 271 sys("OPSYS_EMULDIR", lkNone, CheckvarPathname)
272 sys("EMULSUBDIRSLASH", lkNone, CheckvarPathname) 272 sys("EMULSUBDIRSLASH", lkNone, CheckvarPathname)
273 sys("EMUL_ARCH", lkNone, enum("i386 none x86_64")) 273 sys("EMUL_ARCH", lkNone, enum("arm i386 m68k none ns32k sparc vax x86_64"))
274 sys("EMUL_DISTRO", lkNone, CheckvarIdentifier) 274 sys("EMUL_DISTRO", lkNone, CheckvarIdentifier)
275 sys("EMUL_IS_NATIVE", lkNone, CheckvarYes) 275 sys("EMUL_IS_NATIVE", lkNone, CheckvarYes)
276 pkg("EMUL_MODULES.*", lkShell, CheckvarIdentifier) 276 pkg("EMUL_MODULES.*", lkShell, CheckvarIdentifier)
277 sys("EMUL_OPSYS", lkNone, enum("freebsd hpux irix linux osf1 solaris sunos none")) 277 sys("EMUL_OPSYS", lkNone, enum("darwin freebsd hpux irix linux osf1 solaris sunos none"))
278 pkg("EMUL_PKG_FMT", lkNone, enum("plain rpm")) 278 pkg("EMUL_PKG_FMT", lkNone, enum("plain rpm"))
279 usr("EMUL_PLATFORM", lkNone, CheckvarEmulPlatform) 279 usr("EMUL_PLATFORM", lkNone, CheckvarEmulPlatform)
280 pkg("EMUL_PLATFORMS", lkShell, CheckvarEmulPlatform) 280 pkg("EMUL_PLATFORMS", lkShell, CheckvarEmulPlatform)
281 usr("EMUL_PREFER", lkShell, CheckvarEmulPlatform) 281 usr("EMUL_PREFER", lkShell, CheckvarEmulPlatform)
282 pkg("EMUL_REQD", lkSpace, CheckvarDependency) 282 pkg("EMUL_REQD", lkSpace, CheckvarDependency)
283 usr("EMUL_TYPE.*", lkNone, enum("native builtin suse suse-9.1 suse-9.x suse-10.0 suse-10.x")) 283 usr("EMUL_TYPE.*", lkNone, enum("native builtin suse suse-9.1 suse-9.x suse-10.0 suse-10.x"))
284 sys("ERROR_CAT", lkNone, CheckvarShellCommand) 284 sys("ERROR_CAT", lkNone, CheckvarShellCommand)
285 sys("ERROR_MSG", lkNone, CheckvarShellCommand) 285 sys("ERROR_MSG", lkNone, CheckvarShellCommand)
286 acl("EVAL_PREFIX", lkSpace, CheckvarShellWord, "Makefile, Makefile.common: append") // XXX: Combining ShellWord with lkSpace looks weird. 286 acl("EVAL_PREFIX", lkSpace, CheckvarShellWord, "Makefile, Makefile.common: append") // XXX: Combining ShellWord with lkSpace looks weird.
287 sys("EXPORT_SYMBOLS_LDFLAGS", lkShell, CheckvarLdFlag) 287 sys("EXPORT_SYMBOLS_LDFLAGS", lkShell, CheckvarLdFlag)
288 sys("EXTRACT_CMD", lkNone, CheckvarShellCommand) 288 sys("EXTRACT_CMD", lkNone, CheckvarShellCommand)
289 pkg("EXTRACT_DIR", lkNone, CheckvarPathname) 289 pkg("EXTRACT_DIR", lkNone, CheckvarPathname)
290 pkglist("EXTRACT_ELEMENTS", lkShell, CheckvarPathmask) 290 pkglist("EXTRACT_ELEMENTS", lkShell, CheckvarPathmask)
@@ -527,27 +527,27 @@ func (gd *GlobalData) InitVartypes() { @@ -527,27 +527,27 @@ func (gd *GlobalData) InitVartypes() {
527 cmdline("PKG_DEBUG_LEVEL", lkNone, CheckvarInteger) 527 cmdline("PKG_DEBUG_LEVEL", lkNone, CheckvarInteger)
528 usr("PKG_DEFAULT_OPTIONS", lkShell, CheckvarOption) 528 usr("PKG_DEFAULT_OPTIONS", lkShell, CheckvarOption)
529 sys("PKG_DELETE", lkNone, CheckvarShellCommand) 529 sys("PKG_DELETE", lkNone, CheckvarShellCommand)
530 acl("PKG_DESTDIR_SUPPORT", lkShell, enum("destdir user-destdir"), "Makefile, Makefile.common: set") 530 acl("PKG_DESTDIR_SUPPORT", lkShell, enum("destdir user-destdir"), "Makefile, Makefile.common: set")
531 pkglist("PKG_FAIL_REASON", lkShell, CheckvarShellWord) 531 pkglist("PKG_FAIL_REASON", lkShell, CheckvarShellWord)
532 acl("PKG_GECOS.*", lkNone, CheckvarMessage, "Makefile: set") 532 acl("PKG_GECOS.*", lkNone, CheckvarMessage, "Makefile: set")
533 acl("PKG_GID.*", lkNone, CheckvarInteger, "Makefile: set") 533 acl("PKG_GID.*", lkNone, CheckvarInteger, "Makefile: set")
534 acl("PKG_GROUPS", lkShell, CheckvarShellWord, "Makefile: set, append") 534 acl("PKG_GROUPS", lkShell, CheckvarShellWord, "Makefile: set, append")
535 pkglist("PKG_GROUPS_VARS", lkShell, CheckvarVarname) 535 pkglist("PKG_GROUPS_VARS", lkShell, CheckvarVarname)
536 acl("PKG_HOME.*", lkNone, CheckvarPathname, "Makefile: set") 536 acl("PKG_HOME.*", lkNone, CheckvarPathname, "Makefile: set")
537 acl("PKG_HACKS", lkShell, CheckvarIdentifier, "hacks.mk: append") 537 acl("PKG_HACKS", lkShell, CheckvarIdentifier, "hacks.mk: append")
538 sys("PKG_INFO", lkNone, CheckvarShellCommand) 538 sys("PKG_INFO", lkNone, CheckvarShellCommand)
539 sys("PKG_JAVA_HOME", lkNone, CheckvarPathname) 539 sys("PKG_JAVA_HOME", lkNone, CheckvarPathname)
540 jvms := enum("blackdown-jdk13 jdk jdk14 kaffe run-jdk13 sun-jdk14 sun-jdk15 sun-jdk6 openjdk7 openjdk7-bin sun-jdk7") 540 jvms := enum("blackdown-jdk13 jdk jdk14 kaffe run-jdk13 sun-jdk14 sun-jdk15 sun-jdk6 openjdk7 openjdk7-bin sun-jdk7 openjdk8 oracle-jdk8")
541 sys("PKG_JVM", lkNone, jvms) 541 sys("PKG_JVM", lkNone, jvms)
542 acl("PKG_JVMS_ACCEPTED", lkShell, jvms, "Makefile: set; Makefile.common: default, set") 542 acl("PKG_JVMS_ACCEPTED", lkShell, jvms, "Makefile: set; Makefile.common: default, set")
543 usr("PKG_JVM_DEFAULT", lkNone, jvms) 543 usr("PKG_JVM_DEFAULT", lkNone, jvms)
544 acl("PKG_LEGACY_OPTIONS", lkShell, CheckvarOption, "") 544 acl("PKG_LEGACY_OPTIONS", lkShell, CheckvarOption, "")
545 acl("PKG_LIBTOOL", lkNone, CheckvarPathname, "Makefile: set") 545 acl("PKG_LIBTOOL", lkNone, CheckvarPathname, "Makefile: set")
546 acl("PKG_OPTIONS", lkSpace, CheckvarOption, "bsd.options.mk: set; *: use-loadtime, use") 546 acl("PKG_OPTIONS", lkSpace, CheckvarOption, "bsd.options.mk: set; *: use-loadtime, use")
547 usr("PKG_OPTIONS.*", lkSpace, CheckvarOption) 547 usr("PKG_OPTIONS.*", lkSpace, CheckvarOption)
548 acl("PKG_OPTIONS_DEPRECATED_WARNINGS", lkShell, CheckvarShellWord, "") 548 acl("PKG_OPTIONS_DEPRECATED_WARNINGS", lkShell, CheckvarShellWord, "")
549 acl("PKG_OPTIONS_GROUP.*", lkSpace, CheckvarOption, "options.mk: set; Makefile: set") 549 acl("PKG_OPTIONS_GROUP.*", lkSpace, CheckvarOption, "options.mk: set; Makefile: set")
550 acl("PKG_OPTIONS_LEGACY_OPTS", lkSpace, CheckvarUnchecked, "Makefile, Makefile.common: append; options.mk: append") 550 acl("PKG_OPTIONS_LEGACY_OPTS", lkSpace, CheckvarUnchecked, "Makefile, Makefile.common: append; options.mk: append")
551 acl("PKG_OPTIONS_LEGACY_VARS", lkSpace, CheckvarUnchecked, "Makefile, Makefile.common: append; options.mk: append") 551 acl("PKG_OPTIONS_LEGACY_VARS", lkSpace, CheckvarUnchecked, "Makefile, Makefile.common: append; options.mk: append")
552 acl("PKG_OPTIONS_NONEMPTY_SETS", lkSpace, CheckvarIdentifier, "") 552 acl("PKG_OPTIONS_NONEMPTY_SETS", lkSpace, CheckvarIdentifier, "")
553 acl("PKG_OPTIONS_OPTIONAL_GROUPS", lkSpace, CheckvarIdentifier, "options.mk: set, append") 553 acl("PKG_OPTIONS_OPTIONAL_GROUPS", lkSpace, CheckvarIdentifier, "options.mk: set, append")
@@ -577,27 +577,27 @@ func (gd *GlobalData) InitVartypes() { @@ -577,27 +577,27 @@ func (gd *GlobalData) InitVartypes() {
577 acl("PLIST_TYPE", lkNone, enum("dynamic static"), "") 577 acl("PLIST_TYPE", lkNone, enum("dynamic static"), "")
578 acl("PREPEND_PATH", lkShell, CheckvarPathname, "") 578 acl("PREPEND_PATH", lkShell, CheckvarPathname, "")
579 acl("PREFIX", lkNone, CheckvarPathname, "*: use") 579 acl("PREFIX", lkNone, CheckvarPathname, "*: use")
580 acl("PREV_PKGPATH", lkNone, CheckvarPathname, "*: use") // doesn't exist any longer 580 acl("PREV_PKGPATH", lkNone, CheckvarPathname, "*: use") // doesn't exist any longer
581 acl("PRINT_PLIST_AWK", lkNone, CheckvarAwkCommand, "*: append") 581 acl("PRINT_PLIST_AWK", lkNone, CheckvarAwkCommand, "*: append")
582 acl("PRIVILEGED_STAGES", lkShell, enum("install package clean"), "") 582 acl("PRIVILEGED_STAGES", lkShell, enum("install package clean"), "")
583 acl("PTHREAD_AUTO_VARS", lkNone, CheckvarYesNo, "Makefile: set") 583 acl("PTHREAD_AUTO_VARS", lkNone, CheckvarYesNo, "Makefile: set")
584 sys("PTHREAD_CFLAGS", lkShell, CheckvarCFlag) 584 sys("PTHREAD_CFLAGS", lkShell, CheckvarCFlag)
585 sys("PTHREAD_LDFLAGS", lkShell, CheckvarLdFlag) 585 sys("PTHREAD_LDFLAGS", lkShell, CheckvarLdFlag)
586 sys("PTHREAD_LIBS", lkShell, CheckvarLdFlag) 586 sys("PTHREAD_LIBS", lkShell, CheckvarLdFlag)
587 acl("PTHREAD_OPTS", lkShell, enum("native optional require"), "Makefile: set, append; Makefile.common: append; buildlink3.mk: append") 587 acl("PTHREAD_OPTS", lkShell, enum("native optional require"), "Makefile: set, append; Makefile.common: append; buildlink3.mk: append")
588 sys("PTHREAD_TYPE", lkNone, CheckvarIdentifier) // Or "native" or "none". 588 sys("PTHREAD_TYPE", lkNone, CheckvarIdentifier) // Or "native" or "none".
589 pkg("PY_PATCHPLIST", lkNone, CheckvarYes) 589 pkg("PY_PATCHPLIST", lkNone, CheckvarYes)
590 acl("PYPKGPREFIX", lkNone, enum("py27 py33 py34"), "pyversion.mk: set; *: use-loadtime, use") 590 acl("PYPKGPREFIX", lkNone, enum("py27 py33 py34 py35"), "pyversion.mk: set; *: use-loadtime, use")
591 pkg("PYTHON_FOR_BUILD_ONLY", lkNone, CheckvarYes) 591 pkg("PYTHON_FOR_BUILD_ONLY", lkNone, CheckvarYes)
592 pkglist("REPLACE_PYTHON", lkShell, CheckvarPathmask) 592 pkglist("REPLACE_PYTHON", lkShell, CheckvarPathmask)
593 pkg("PYTHON_VERSIONS_ACCEPTED", lkShell, CheckvarVersion) 593 pkg("PYTHON_VERSIONS_ACCEPTED", lkShell, CheckvarVersion)
594 pkg("PYTHON_VERSIONS_INCOMPATIBLE", lkShell, CheckvarVersion) 594 pkg("PYTHON_VERSIONS_INCOMPATIBLE", lkShell, CheckvarVersion)
595 usr("PYTHON_VERSION_DEFAULT", lkNone, CheckvarVersion) 595 usr("PYTHON_VERSION_DEFAULT", lkNone, CheckvarVersion)
596 usr("PYTHON_VERSION_REQD", lkNone, CheckvarVersion) 596 usr("PYTHON_VERSION_REQD", lkNone, CheckvarVersion)
597 pkglist("PYTHON_VERSIONED_DEPENDENCIES", lkShell, CheckvarPythonDependency) 597 pkglist("PYTHON_VERSIONED_DEPENDENCIES", lkShell, CheckvarPythonDependency)
598 sys("RANLIB", lkNone, CheckvarShellCommand) 598 sys("RANLIB", lkNone, CheckvarShellCommand)
599 pkglist("RCD_SCRIPTS", lkShell, CheckvarFilename) 599 pkglist("RCD_SCRIPTS", lkShell, CheckvarFilename)
600 acl("RCD_SCRIPT_SRC.*", lkShell, CheckvarPathname, "Makefile: set") 600 acl("RCD_SCRIPT_SRC.*", lkShell, CheckvarPathname, "Makefile: set")
601 acl("REPLACE.*", lkNone, CheckvarString, "Makefile: set") 601 acl("REPLACE.*", lkNone, CheckvarString, "Makefile: set")
602 pkglist("REPLACE_AWK", lkShell, CheckvarPathmask) 602 pkglist("REPLACE_AWK", lkShell, CheckvarPathmask)
603 pkglist("REPLACE_BASH", lkShell, CheckvarPathmask) 603 pkglist("REPLACE_BASH", lkShell, CheckvarPathmask)
@@ -660,26 +660,27 @@ func (gd *GlobalData) InitVartypes() { @@ -660,26 +660,27 @@ func (gd *GlobalData) InitVartypes() {
660 sys("TOOLS_PATH.*", lkNone, CheckvarPathname) 660 sys("TOOLS_PATH.*", lkNone, CheckvarPathname)
661 sys("TOOLS_PLATFORM.*", lkNone, CheckvarShellCommand) 661 sys("TOOLS_PLATFORM.*", lkNone, CheckvarShellCommand)
662 sys("TOUCH_FLAGS", lkShell, CheckvarShellWord) 662 sys("TOUCH_FLAGS", lkShell, CheckvarShellWord)
663 pkglist("UAC_REQD_EXECS", lkShell, CheckvarPrefixPathname) 663 pkglist("UAC_REQD_EXECS", lkShell, CheckvarPrefixPathname)
664 acl("UNLIMIT_RESOURCES", lkShell, enum("datasize stacksize memorysize"), "Makefile: set, append; Makefile.common: append") 664 acl("UNLIMIT_RESOURCES", lkShell, enum("datasize stacksize memorysize"), "Makefile: set, append; Makefile.common: append")
665 usr("UNPRIVILEGED_USER", lkNone, CheckvarUserGroupName) 665 usr("UNPRIVILEGED_USER", lkNone, CheckvarUserGroupName)
666 usr("UNPRIVILEGED_GROUP", lkNone, CheckvarUserGroupName) 666 usr("UNPRIVILEGED_GROUP", lkNone, CheckvarUserGroupName)
667 pkglist("UNWRAP_FILES", lkShell, CheckvarPathmask) 667 pkglist("UNWRAP_FILES", lkShell, CheckvarPathmask)
668 usr("UPDATE_TARGET", lkShell, CheckvarIdentifier) 668 usr("UPDATE_TARGET", lkShell, CheckvarIdentifier)
669 pkg("USE_BSD_MAKEFILE", lkNone, CheckvarYes) 669 pkg("USE_BSD_MAKEFILE", lkNone, CheckvarYes)
670 acl("USE_BUILTIN.*", lkNone, CheckvarYesNoIndirectly, "builtin.mk: set") 670 acl("USE_BUILTIN.*", lkNone, CheckvarYesNoIndirectly, "builtin.mk: set")
671 pkg("USE_CMAKE", lkNone, CheckvarYes) 671 pkg("USE_CMAKE", lkNone, CheckvarYes)
672 acl("USE_CROSSBASE", lkNone, CheckvarYes, "Makefile: set") 672 acl("USE_CROSSBASE", lkNone, CheckvarYes, "Makefile: set")
 673 usr("USE_DESTDIR", lkNone, CheckvarYes)
673 pkg("USE_FEATURES", lkShell, CheckvarIdentifier) 674 pkg("USE_FEATURES", lkShell, CheckvarIdentifier)
674 pkg("USE_GCC_RUNTIME", lkNone, CheckvarYesNo) 675 pkg("USE_GCC_RUNTIME", lkNone, CheckvarYesNo)
675 pkg("USE_GNU_CONFIGURE_HOST", lkNone, CheckvarYesNo) 676 pkg("USE_GNU_CONFIGURE_HOST", lkNone, CheckvarYesNo)
676 acl("USE_GNU_ICONV", lkNone, CheckvarYes, "Makefile, Makefile.common: set; options.mk: set") 677 acl("USE_GNU_ICONV", lkNone, CheckvarYes, "Makefile, Makefile.common: set; options.mk: set")
677 acl("USE_IMAKE", lkNone, CheckvarYes, "Makefile: set") 678 acl("USE_IMAKE", lkNone, CheckvarYes, "Makefile: set")
678 pkg("USE_JAVA", lkNone, enum("run yes build")) 679 pkg("USE_JAVA", lkNone, enum("run yes build"))
679 pkg("USE_JAVA2", lkNone, enum("YES yes no 1.4 1.5 6 7 8")) 680 pkg("USE_JAVA2", lkNone, enum("YES yes no 1.4 1.5 6 7 8"))
680 acl("USE_LANGUAGES", lkShell, enum("ada c c99 c++ fortran fortran77 java objc"), "Makefile, Makefile.common, options.mk: set") 681 acl("USE_LANGUAGES", lkShell, enum("ada c c99 c++ fortran fortran77 java objc"), "Makefile, Makefile.common, options.mk: set")
681 pkg("USE_LIBTOOL", lkNone, CheckvarYes) 682 pkg("USE_LIBTOOL", lkNone, CheckvarYes)
682 pkg("USE_MAKEINFO", lkNone, CheckvarYes) 683 pkg("USE_MAKEINFO", lkNone, CheckvarYes)
683 pkg("USE_MSGFMT_PLURALS", lkNone, CheckvarYes) 684 pkg("USE_MSGFMT_PLURALS", lkNone, CheckvarYes)
684 pkg("USE_NCURSES", lkNone, CheckvarYes) 685 pkg("USE_NCURSES", lkNone, CheckvarYes)
685 pkg("USE_OLD_DES_API", lkNone, CheckvarYesNo) 686 pkg("USE_OLD_DES_API", lkNone, CheckvarYesNo)
@@ -695,29 +696,46 @@ func (gd *GlobalData) InitVartypes() { @@ -695,29 +696,46 @@ func (gd *GlobalData) InitVartypes() {
695 sys("WRKDIR", lkNone, CheckvarPathname) 696 sys("WRKDIR", lkNone, CheckvarPathname)
696 pkg("WRKSRC", lkNone, CheckvarWrkdirSubdirectory) 697 pkg("WRKSRC", lkNone, CheckvarWrkdirSubdirectory)
697 sys("X11_PKGSRCDIR.*", lkNone, CheckvarPathname) 698 sys("X11_PKGSRCDIR.*", lkNone, CheckvarPathname)
698 usr("XAW_TYPE", lkNone, enum("3d neXtaw standard xpm")) 699 usr("XAW_TYPE", lkNone, enum("3d neXtaw standard xpm"))
699 acl("XMKMF_FLAGS", lkShell, CheckvarShellWord, "") 700 acl("XMKMF_FLAGS", lkShell, CheckvarShellWord, "")
700} 701}
701 702
702func enum(values string) *VarChecker { 703func enum(values string) *VarChecker {
703 vmap := make(map[string]bool) 704 vmap := make(map[string]bool)
704 for _, value := range splitOnSpace(values) { 705 for _, value := range splitOnSpace(values) {
705 vmap[value] = true 706 vmap[value] = true
706 } 707 }
707 name := "enum: " + values + " " // See IsEnum 708 name := "enum: " + values + " " // See IsEnum
708 return &VarChecker{name, func(ctx *VartypeCheck) { 709 return &VarChecker{name, func(cv *VartypeCheck) {
709 if !vmap[ctx.value] { 710 if cv.op == opUseMatch {
710 ctx.line.Warnf("%q is not valid for %s. Use one of { %s } instead.", ctx.value, ctx.varname, values) 711 if !vmap[cv.value] && cv.value == cv.valueNovar {
 712 canMatch := false
 713 for value := range vmap {
 714 if ok, err := path.Match(cv.value, value); err != nil {
 715 cv.line.Warnf("Invalid match pattern %q.", cv.value)
 716 } else if ok {
 717 canMatch = true
 718 }
 719 }
 720 if !canMatch {
 721 cv.line.Warnf("The pattern %q cannot match any of { %s } for %s.", cv.value, values, cv.varname)
 722 }
 723 }
 724 return
 725 }
 726
 727 if !vmap[cv.value] {
 728 cv.line.Warnf("%q is not valid for %s. Use one of { %s } instead.", cv.value, cv.varname, values)
711 } 729 }
712 }} 730 }}
713} 731}
714 732
715func acl(varname string, kindOfList KindOfList, checker *VarChecker, aclentries string) { 733func acl(varname string, kindOfList KindOfList, checker *VarChecker, aclentries string) {
716 m := mustMatch(varname, `^([A-Z_.][A-Z0-9_]*)(|\*|\.\*)$`) 734 m := mustMatch(varname, `^([A-Z_.][A-Z0-9_]*)(|\*|\.\*)$`)
717 varbase, varparam := m[1], m[2] 735 varbase, varparam := m[1], m[2]
718 736
719 vtype := &Vartype{kindOfList, checker, parseAclEntries(varname, aclentries), false} 737 vtype := &Vartype{kindOfList, checker, parseAclEntries(varname, aclentries), false}
720 738
721 if G.globalData.vartypes == nil { 739 if G.globalData.vartypes == nil {
722 G.globalData.vartypes = make(map[string]*Vartype) 740 G.globalData.vartypes = make(map[string]*Vartype)
723 } 741 }

cvs diff -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck.go 2016/01/12 01:07:37 1.10
+++ pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck.go 2016/01/31 17:18:54 1.11
@@ -15,48 +15,49 @@ type VartypeCheck struct { @@ -15,48 +15,49 @@ type VartypeCheck struct {
15 comment string 15 comment string
16 listContext bool 16 listContext bool
17 guessed bool // Whether the type definition is guessed (based on the variable name) or explicitly defined (see vardefs.go). 17 guessed bool // Whether the type definition is guessed (based on the variable name) or explicitly defined (see vardefs.go).
18} 18}
19 19
20type MkOperator uint8 20type MkOperator uint8
21 21
22const ( 22const (
23 opAssign MkOperator = iota // = 23 opAssign MkOperator = iota // =
24 opAssignShell // != 24 opAssignShell // !=
25 opAssignEval // := 25 opAssignEval // :=
26 opAssignAppend // += 26 opAssignAppend // +=
27 opAssignDefault // ?= 27 opAssignDefault // ?=
28 opUseLoadtime 28 opUse //
29 opUse 29 opUseLoadtime //
 30 opUseMatch // Used in the :M operator
30) 31)
31 32
32func NewMkOperator(op string) MkOperator { 33func NewMkOperator(op string) MkOperator {
33 switch op { 34 switch op {
34 case "=": 35 case "=":
35 return opAssign 36 return opAssign
36 case "!=": 37 case "!=":
37 return opAssignShell 38 return opAssignShell
38 case ":=": 39 case ":=":
39 return opAssignEval 40 return opAssignEval
40 case "+=": 41 case "+=":
41 return opAssignAppend 42 return opAssignAppend
42 case "?=": 43 case "?=":
43 return opAssignDefault 44 return opAssignDefault
44 } 45 }
45 return opAssign 46 return opAssign
46} 47}
47 48
48func (op MkOperator) String() string { 49func (op MkOperator) String() string {
49 return [...]string{"=", "!=", ":=", "+=", "?=", "use", "use-loadtime"}[op] 50 return [...]string{"=", "!=", ":=", "+=", "?=", "use", "use-loadtime", "use-match"}[op]
50} 51}
51 52
52func (cv *VartypeCheck) AwkCommand() { 53func (cv *VartypeCheck) AwkCommand() {
53 if G.opts.DebugUnchecked { 54 if G.opts.DebugUnchecked {
54 cv.line.Debug1("Unchecked AWK command: %q", cv.value) 55 cv.line.Debug1("Unchecked AWK command: %q", cv.value)
55 } 56 }
56} 57}
57 58
58func (cv *VartypeCheck) BasicRegularExpression() { 59func (cv *VartypeCheck) BasicRegularExpression() {
59 if G.opts.DebugUnchecked { 60 if G.opts.DebugUnchecked {
60 cv.line.Debug1("Unchecked basic regular expression: %q", cv.value) 61 cv.line.Debug1("Unchecked basic regular expression: %q", cv.value)
61 } 62 }
62} 63}
@@ -81,26 +82,29 @@ func (cv *VartypeCheck) Category() { @@ -81,26 +82,29 @@ func (cv *VartypeCheck) Category() {
81 "packages", "perl5", "plan9", "python", 82 "packages", "perl5", "plan9", "python",
82 "ruby", 83 "ruby",
83 "scm", 84 "scm",
84 "tcl", "tk", 85 "tcl", "tk",
85 "windowmaker", 86 "windowmaker",
86 "xmms": 87 "xmms":
87 default: 88 default:
88 cv.line.Error1("Invalid category %q.", cv.value) 89 cv.line.Error1("Invalid category %q.", cv.value)
89 } 90 }
90} 91}
91 92
92// A single option to the C/C++ compiler. 93// A single option to the C/C++ compiler.
93func (cv *VartypeCheck) CFlag() { 94func (cv *VartypeCheck) CFlag() {
 95 if cv.op == opUseMatch {
 96 return
 97 }
94 cflag := cv.value 98 cflag := cv.value
95 switch { 99 switch {
96 case matches(cflag, `^-[DILOUWfgm]`), 100 case matches(cflag, `^-[DILOUWfgm]`),
97 hasPrefix(cflag, "-std="), 101 hasPrefix(cflag, "-std="),
98 cflag == "-c99", 102 cflag == "-c99",
99 cflag == "-c", 103 cflag == "-c",
100 cflag == "-no-integrated-as", 104 cflag == "-no-integrated-as",
101 cflag == "-pthread", 105 cflag == "-pthread",
102 hasPrefix(cflag, "`") && hasSuffix(cflag, "`"), 106 hasPrefix(cflag, "`") && hasSuffix(cflag, "`"),
103 containsVarRef(cflag): 107 containsVarRef(cflag):
104 return 108 return
105 case hasPrefix(cflag, "-"): 109 case hasPrefix(cflag, "-"):
106 cv.line.Warn1("Unknown compiler flag %q.", cflag) 110 cv.line.Warn1("Unknown compiler flag %q.", cflag)
@@ -281,71 +285,85 @@ func (cv *VartypeCheck) FetchURL() { @@ -281,71 +285,85 @@ func (cv *VartypeCheck) FetchURL() {
281 if !G.globalData.MasterSiteVars[name] { 285 if !G.globalData.MasterSiteVars[name] {
282 cv.line.Error1("%s does not exist.", name) 286 cv.line.Error1("%s does not exist.", name)
283 } 287 }
284 if !hasSuffix(subdir, "/") { 288 if !hasSuffix(subdir, "/") {
285 cv.line.Error1("The subdirectory in %s must end with a slash.", name) 289 cv.line.Error1("The subdirectory in %s must end with a slash.", name)
286 } 290 }
287 } 291 }
288} 292}
289 293
290// See Pathname 294// See Pathname
291// See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_169 295// See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_169
292func (cv *VartypeCheck) Filename() { 296func (cv *VartypeCheck) Filename() {
293 switch { 297 switch {
 298 case cv.op == opUseMatch:
 299 break
294 case contains(cv.valueNovar, "/"): 300 case contains(cv.valueNovar, "/"):
295 cv.line.Warn0("A filename should not contain a slash.") 301 cv.line.Warn0("A filename should not contain a slash.")
296 case !matches(cv.valueNovar, `^[-0-9@A-Za-z.,_~+%]*$`): 302 case !matches(cv.valueNovar, `^[-0-9@A-Za-z.,_~+%]*$`):
297 cv.line.Warn1("%q is not a valid filename.", cv.value) 303 cv.line.Warn1("%q is not a valid filename.", cv.value)
298 } 304 }
299} 305}
300 306
301func (cv *VartypeCheck) Filemask() { 307func (cv *VartypeCheck) Filemask() {
 308 if cv.op == opUseMatch {
 309 return
 310 }
302 if !matches(cv.valueNovar, `^[-0-9A-Za-z._~+%*?]*$`) { 311 if !matches(cv.valueNovar, `^[-0-9A-Za-z._~+%*?]*$`) {
303 cv.line.Warn1("%q is not a valid filename mask.", cv.value) 312 cv.line.Warn1("%q is not a valid filename mask.", cv.value)
304 } 313 }
305} 314}
306 315
307func (cv *VartypeCheck) FileMode() { 316func (cv *VartypeCheck) FileMode() {
308 switch { 317 switch {
309 case cv.value != "" && cv.valueNovar == "": 318 case cv.value != "" && cv.valueNovar == "":
310 // Fine. 319 // Fine.
311 case matches(cv.value, `^[0-7]{3,4}`): 320 case matches(cv.value, `^[0-7]{3,4}`):
312 // Fine. 321 // Fine.
313 default: 322 default:
314 cv.line.Warn1("Invalid file mode %q.", cv.value) 323 cv.line.Warn1("Invalid file mode %q.", cv.value)
315 } 324 }
316} 325}
317 326
318func (cv *VartypeCheck) Identifier() { 327func (cv *VartypeCheck) Identifier() {
 328 if cv.op == opUseMatch {
 329 if cv.value == cv.valueNovar && !matches(cv.value, `^[\w*?]`) {
 330 cv.line.Warn2("Invalid identifier pattern %q for %s.", cv.value, cv.varname)
 331 }
 332 return
 333 }
319 if cv.value != cv.valueNovar { 334 if cv.value != cv.valueNovar {
320 //line.logWarning("Identifiers should be given directly.") 335 //line.logWarning("Identifiers should be given directly.")
321 } 336 }
322 switch { 337 switch {
323 case matches(cv.valueNovar, `^[+\-.0-9A-Z_a-z]+$`): 338 case matches(cv.valueNovar, `^[+\-.0-9A-Z_a-z]+$`):
324 // Fine. 339 // Fine.
325 case cv.value != "" && cv.valueNovar == "": 340 case cv.value != "" && cv.valueNovar == "":
326 // Don't warn here. 341 // Don't warn here.
327 default: 342 default:
328 cv.line.Warn1("Invalid identifier %q.", cv.value) 343 cv.line.Warn1("Invalid identifier %q.", cv.value)
329 } 344 }
330} 345}
331 346
332func (cv *VartypeCheck) Integer() { 347func (cv *VartypeCheck) Integer() {
333 if !matches(cv.value, `^\d+$`) { 348 if !matches(cv.value, `^\d+$`) {
334 cv.line.Warn1("Invalid integer %q.", cv.value) 349 cv.line.Warn1("Invalid integer %q.", cv.value)
335 } 350 }
336} 351}
337 352
338func (cv *VartypeCheck) LdFlag() { 353func (cv *VartypeCheck) LdFlag() {
 354 if cv.op == opUseMatch {
 355 return
 356 }
339 ldflag := cv.value 357 ldflag := cv.value
340 if m, rpathFlag := match1(ldflag, `^(-Wl,(?:-R|-rpath|--rpath))`); m { 358 if m, rpathFlag := match1(ldflag, `^(-Wl,(?:-R|-rpath|--rpath))`); m {
341 cv.line.Warn1("Please use \"${COMPILER_RPATH_FLAG}\" instead of %q.", rpathFlag) 359 cv.line.Warn1("Please use \"${COMPILER_RPATH_FLAG}\" instead of %q.", rpathFlag)
342 return 360 return
343 } 361 }
344 362
345 switch { 363 switch {
346 case hasPrefix(ldflag, "-L"), 364 case hasPrefix(ldflag, "-L"),
347 hasPrefix(ldflag, "-l"), 365 hasPrefix(ldflag, "-l"),
348 ldflag == "-pthread", 366 ldflag == "-pthread",
349 ldflag == "-static", 367 ldflag == "-static",
350 hasPrefix(ldflag, "-static-"), 368 hasPrefix(ldflag, "-static-"),
351 hasPrefix(ldflag, "-Wl,-"), 369 hasPrefix(ldflag, "-Wl,-"),
@@ -442,49 +460,55 @@ func (cv *VartypeCheck) Pathlist() { @@ -442,49 +460,55 @@ func (cv *VartypeCheck) Pathlist() {
442 if !matches(path, `^[-0-9A-Za-z._~+%/]*$`) { 460 if !matches(path, `^[-0-9A-Za-z._~+%/]*$`) {
443 cv.line.Warn1("%q is not a valid pathname.", path) 461 cv.line.Warn1("%q is not a valid pathname.", path)
444 } 462 }
445 463
446 if !hasPrefix(path, "/") { 464 if !hasPrefix(path, "/") {
447 cv.line.Warn2("All components of %s (in this case %q) should be absolute paths.", cv.varname, path) 465 cv.line.Warn2("All components of %s (in this case %q) should be absolute paths.", cv.varname, path)
448 } 466 }
449 } 467 }
450} 468}
451 469
452// Shell globbing including slashes. 470// Shell globbing including slashes.
453// See Filemask 471// See Filemask
454func (cv *VartypeCheck) Pathmask() { 472func (cv *VartypeCheck) Pathmask() {
 473 if cv.op == opUseMatch {
 474 return
 475 }
455 if !matches(cv.valueNovar, `^[#\-0-9A-Za-z._~+%*?/\[\]]*`) { 476 if !matches(cv.valueNovar, `^[#\-0-9A-Za-z._~+%*?/\[\]]*`) {
456 cv.line.Warn1("%q is not a valid pathname mask.", cv.value) 477 cv.line.Warn1("%q is not a valid pathname mask.", cv.value)
457 } 478 }
458 cv.line.CheckAbsolutePathname(cv.value) 479 cv.line.CheckAbsolutePathname(cv.value)
459} 480}
460 481
461// Like Filename, but including slashes 482// Like Filename, but including slashes
462// See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_266 483// See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_266
463func (cv *VartypeCheck) Pathname() { 484func (cv *VartypeCheck) Pathname() {
 485 if cv.op == opUseMatch {
 486 return
 487 }
464 if !matches(cv.valueNovar, `^[#\-0-9A-Za-z._~+%/]*$`) { 488 if !matches(cv.valueNovar, `^[#\-0-9A-Za-z._~+%/]*$`) {
465 cv.line.Warn1("%q is not a valid pathname.", cv.value) 489 cv.line.Warn1("%q is not a valid pathname.", cv.value)
466 } 490 }
467 cv.line.CheckAbsolutePathname(cv.value) 491 cv.line.CheckAbsolutePathname(cv.value)
468} 492}
469 493
470func (cv *VartypeCheck) Perl5Packlist() { 494func (cv *VartypeCheck) Perl5Packlist() {
471 if cv.value != cv.valueNovar { 495 if cv.value != cv.valueNovar {
472 cv.line.Warn1("%s should not depend on other variables.", cv.varname) 496 cv.line.Warn1("%s should not depend on other variables.", cv.varname)
473 } 497 }
474} 498}
475 499
476func (cv *VartypeCheck) PkgName() { 500func (cv *VartypeCheck) PkgName() {
477 if cv.value == cv.valueNovar && !matches(cv.value, rePkgname) { 501 if cv.op != opUseMatch && cv.value == cv.valueNovar && !matches(cv.value, rePkgname) {
478 cv.line.Warn1("%q is not a valid package name. A valid package name has the form packagename-version, where version consists only of digits, letters and dots.", cv.value) 502 cv.line.Warn1("%q is not a valid package name. A valid package name has the form packagename-version, where version consists only of digits, letters and dots.", cv.value)
479 } 503 }
480} 504}
481 505
482func (cv *VartypeCheck) PkgOptionsVar() { 506func (cv *VartypeCheck) PkgOptionsVar() {
483 cv.mkline.CheckVartypePrimitive(cv.varname, CheckvarVarname, cv.op, cv.value, cv.comment, false, cv.guessed) 507 cv.mkline.CheckVartypePrimitive(cv.varname, CheckvarVarname, cv.op, cv.value, cv.comment, false, cv.guessed)
484 if matches(cv.value, `\$\{PKGBASE[:\}]`) { 508 if matches(cv.value, `\$\{PKGBASE[:\}]`) {
485 cv.line.Error0("PKGBASE must not be used in PKG_OPTIONS_VAR.") 509 cv.line.Error0("PKGBASE must not be used in PKG_OPTIONS_VAR.")
486 Explain3( 510 Explain3(
487 "PKGBASE is defined in bsd.pkg.mk, which is included as the", 511 "PKGBASE is defined in bsd.pkg.mk, which is included as the",
488 "very last file, but PKG_OPTIONS_VAR is evaluated earlier.", 512 "very last file, but PKG_OPTIONS_VAR is evaluated earlier.",
489 "Use ${PKGNAME:C/-[0-9].*//} instead.") 513 "Use ${PKGNAME:C/-[0-9].*//} instead.")
490 } 514 }
@@ -632,26 +656,29 @@ func (cv *VartypeCheck) SedCommands() { @@ -632,26 +656,29 @@ func (cv *VartypeCheck) SedCommands() {
632 case token == "-n": 656 case token == "-n":
633 // Don't print lines per default. 657 // Don't print lines per default.
634 658
635 case i == 0 && matches(token, `^(["']?)(?:\d*|/.*/)s.+["']?$`): 659 case i == 0 && matches(token, `^(["']?)(?:\d*|/.*/)s.+["']?$`):
636 line.Note0("Please always use \"-e\" in sed commands, even if there is only one substitution.") 660 line.Note0("Please always use \"-e\" in sed commands, even if there is only one substitution.")
637 661
638 default: 662 default:
639 line.Warn1("Unknown sed command %q.", token) 663 line.Warn1("Unknown sed command %q.", token)
640 } 664 }
641 } 665 }
642} 666}
643 667
644func (cv *VartypeCheck) ShellCommand() { 668func (cv *VartypeCheck) ShellCommand() {
 669 if cv.op == opUseMatch {
 670 return
 671 }
645 setE := true 672 setE := true
646 NewShellLine(cv.mkline).CheckShellCommand(cv.value, &setE) 673 NewShellLine(cv.mkline).CheckShellCommand(cv.value, &setE)
647} 674}
648 675
649// Zero or more shell commands, each terminated with a semicolon. 676// Zero or more shell commands, each terminated with a semicolon.
650func (cv *VartypeCheck) ShellCommands() { 677func (cv *VartypeCheck) ShellCommands() {
651 NewShellLine(cv.mkline).CheckShellCommands(cv.value) 678 NewShellLine(cv.mkline).CheckShellCommands(cv.value)
652} 679}
653 680
654func (cv *VartypeCheck) ShellWord() { 681func (cv *VartypeCheck) ShellWord() {
655 if !cv.listContext { 682 if !cv.listContext {
656 NewShellLine(cv.mkline).CheckToken(cv.value, true) 683 NewShellLine(cv.mkline).CheckToken(cv.value, true)
657 } 684 }
@@ -670,27 +697,27 @@ func (cv *VartypeCheck) String() { @@ -670,27 +697,27 @@ func (cv *VartypeCheck) String() {
670func (cv *VartypeCheck) Tool() { 697func (cv *VartypeCheck) Tool() {
671 if cv.varname == "TOOLS_NOOP" && cv.op == opAssignAppend { 698 if cv.varname == "TOOLS_NOOP" && cv.op == opAssignAppend {
672 // no warning for package-defined tool definitions 699 // no warning for package-defined tool definitions
673 700
674 } else if m, toolname, tooldep := match2(cv.value, `^([-\w]+|\[)(?::(\w+))?$`); m { 701 } else if m, toolname, tooldep := match2(cv.value, `^([-\w]+|\[)(?::(\w+))?$`); m {
675 if !G.globalData.Tools[toolname] { 702 if !G.globalData.Tools[toolname] {
676 cv.line.Error1("Unknown tool %q.", toolname) 703 cv.line.Error1("Unknown tool %q.", toolname)
677 } 704 }
678 switch tooldep { 705 switch tooldep {
679 case "", "bootstrap", "build", "pkgsrc", "run": 706 case "", "bootstrap", "build", "pkgsrc", "run":
680 default: 707 default:
681 cv.line.Error1("Unknown tool dependency %q. Use one of \"build\", \"pkgsrc\" or \"run\".", tooldep) 708 cv.line.Error1("Unknown tool dependency %q. Use one of \"build\", \"pkgsrc\" or \"run\".", tooldep)
682 } 709 }
683 } else { 710 } else if cv.op != opUseMatch {
684 cv.line.Error1("Invalid tool syntax: %q.", cv.value) 711 cv.line.Error1("Invalid tool syntax: %q.", cv.value)
685 } 712 }
686} 713}
687 714
688func (cv *VartypeCheck) Unchecked() { 715func (cv *VartypeCheck) Unchecked() {
689 // Do nothing, as the name says. 716 // Do nothing, as the name says.
690} 717}
691 718
692func (cv *VartypeCheck) URL() { 719func (cv *VartypeCheck) URL() {
693 line, value := cv.line, cv.value 720 line, value := cv.line, cv.value
694 721
695 if value == "" && hasPrefix(cv.comment, "#") { 722 if value == "" && hasPrefix(cv.comment, "#") {
696 // Ok 723 // Ok
@@ -731,27 +758,31 @@ func (cv *VartypeCheck) Varname() { @@ -731,27 +758,31 @@ func (cv *VartypeCheck) Varname() {
731 cv.line.Warn1("%q is not a valid variable name.", cv.value) 758 cv.line.Warn1("%q is not a valid variable name.", cv.value)
732 Explain( 759 Explain(
733 "Variable names are restricted to only uppercase letters and the", 760 "Variable names are restricted to only uppercase letters and the",
734 "underscore in the basename, and arbitrary characters in the", 761 "underscore in the basename, and arbitrary characters in the",
735 "parameterized part, following the dot.", 762 "parameterized part, following the dot.",
736 "", 763 "",
737 "Examples:", 764 "Examples:",
738 "\t* PKGNAME", 765 "\t* PKGNAME",
739 "\t* PKG_OPTIONS.gnuchess") 766 "\t* PKG_OPTIONS.gnuchess")
740 } 767 }
741} 768}
742 769
743func (cv *VartypeCheck) Version() { 770func (cv *VartypeCheck) Version() {
744 if !matches(cv.value, `^([\d.])+$`) { 771 if cv.op == opUseMatch {
 772 if !matches(cv.value, `^[\d?\[][\w\-.*?\[\]]+$`) {
 773 cv.line.Warn1("Invalid version number pattern %q.", cv.value)
 774 }
 775 } else if cv.value == cv.valueNovar && !matches(cv.value, `^\d[\w.]+$`) {
745 cv.line.Warn1("Invalid version number %q.", cv.value) 776 cv.line.Warn1("Invalid version number %q.", cv.value)
746 } 777 }
747} 778}
748 779
749func (cv *VartypeCheck) WrapperReorder() { 780func (cv *VartypeCheck) WrapperReorder() {
750 if !matches(cv.value, `^reorder:l:([\w\-]+):([\w\-]+)$`) { 781 if !matches(cv.value, `^reorder:l:([\w\-]+):([\w\-]+)$`) {
751 cv.line.Warn1("Unknown wrapper reorder command %q.", cv.value) 782 cv.line.Warn1("Unknown wrapper reorder command %q.", cv.value)
752 } 783 }
753} 784}
754 785
755func (cv *VartypeCheck) WrapperTransform() { 786func (cv *VartypeCheck) WrapperTransform() {
756 cmd := cv.value 787 cmd := cv.value
757 if hasPrefix(cmd, "rm:-") || 788 if hasPrefix(cmd, "rm:-") ||
@@ -776,41 +807,57 @@ func (cv *VartypeCheck) WrksrcSubdirecto @@ -776,41 +807,57 @@ func (cv *VartypeCheck) WrksrcSubdirecto
776 } 807 }
777 cv.line.Note2("You can use %q instead of %q.", rest, cv.value) 808 cv.line.Note2("You can use %q instead of %q.", rest, cv.value)
778 Explain1( 809 Explain1(
779 "These directories are interpreted relative to ${WRKSRC}.") 810 "These directories are interpreted relative to ${WRKSRC}.")
780 811
781 } else if cv.value != "" && cv.valueNovar == "" { 812 } else if cv.value != "" && cv.valueNovar == "" {
782 // The value of another variable 813 // The value of another variable
783 814
784 } else if !matches(cv.valueNovar, `^(?:\.|[0-9A-Za-z_@][-0-9A-Za-z_@./+]*)$`) { 815 } else if !matches(cv.valueNovar, `^(?:\.|[0-9A-Za-z_@][-0-9A-Za-z_@./+]*)$`) {
785 cv.line.Warn1("%q is not a valid subdirectory of ${WRKSRC}.", cv.value) 816 cv.line.Warn1("%q is not a valid subdirectory of ${WRKSRC}.", cv.value)
786 } 817 }
787} 818}
788 819
789// Used for variables that are checked using `.if defined(VAR)`. 
790func (cv *VartypeCheck) Yes() { 820func (cv *VartypeCheck) Yes() {
791 if !matches(cv.value, `^(?:YES|yes)(?:\s+#.*)?$`) { 821 switch cv.op {
792 cv.line.Warn1("%s should be set to YES or yes.", cv.varname) 822 case opUseMatch:
793 Explain4( 823 cv.line.Warn1("%s should only be used in a \".if defined(...)\" conditional.", cv.varname)
794 "This variable means \"yes\" if it is defined, and \"no\" if it is", 824 Explain(
795 "undefined. Even when it has the value \"no\", this means \"yes\".", 825 "This variable can have only two values: defined or undefined.",
796 "Therefore when it is defined, its value should correspond to its", 826 "When it is defined, it means \"yes\", even when its value is",
797 "meaning.") 827 "\"no\" or the empty string.",
 828 "",
 829 "Therefore, it should not be checked by comparing its value",
 830 "but using \".if defined(VARNAME)\" alone.")
 831
 832 default:
 833 if !matches(cv.value, `^(?:YES|yes)(?:\s+#.*)?$`) {
 834 cv.line.Warn1("%s should be set to YES or yes.", cv.varname)
 835 Explain4(
 836 "This variable means \"yes\" if it is defined, and \"no\" if it is",
 837 "undefined. Even when it has the value \"no\", this means \"yes\".",
 838 "Therefore when it is defined, its value should correspond to its",
 839 "meaning.")
 840 }
798 } 841 }
799} 842}
800 843
801// The type YesNo is used for variables that are checked using 
802// .if defined(VAR) && !empty(VAR:M[Yy][Ee][Ss]) 
803// 
804func (cv *VartypeCheck) YesNo() { 844func (cv *VartypeCheck) YesNo() {
805 if !matches(cv.value, `^(?:YES|yes|NO|no)(?:\s+#.*)?$`) { 845 if cv.op == opUseMatch {
 846 switch cv.value {
 847 case "[yY][eE][sS]":
 848 case "[Yy][Ee][Ss]":
 849 case "[nN][oO]":
 850 case "[Nn][Oo]":
 851 default:
 852 cv.line.Warnf("%s should be matched against %q or %q, not %q.", cv.varname, "[yY][eE][sS]", "[nN][oO]", cv.value)
 853 }
 854 } else if !matches(cv.value, `^(?:YES|yes|NO|no)(?:\s+#.*)?$`) {
806 cv.line.Warn1("%s should be set to YES, yes, NO, or no.", cv.varname) 855 cv.line.Warn1("%s should be set to YES, yes, NO, or no.", cv.varname)
807 } 856 }
808} 857}
809 858
810// Like YesNo, but the value may be produced by a shell command using the 
811// != operator. 
812func (cv *VartypeCheck) YesNoIndirectly() { 859func (cv *VartypeCheck) YesNoIndirectly() {
813 if cv.valueNovar != "" && !matches(cv.value, `^(?:YES|yes|NO|no)(?:\s+#.*)?$`) { 860 if cv.valueNovar != "" {
814 cv.line.Warn1("%s should be set to YES, yes, NO, or no.", cv.varname) 861 cv.YesNo()
815 } 862 }
816} 863}

cvs diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck_test.go 2016/01/27 21:55:51 1.6
+++ pkgsrc/pkgtools/pkglint/files/Attic/vartypecheck_test.go 2016/01/31 17:18:54 1.7
@@ -1,16 +1,18 @@ @@ -1,16 +1,18 @@
1package main 1package main
2 2
3import ( 3import (
 4 "fmt"
 5
4 check "gopkg.in/check.v1" 6 check "gopkg.in/check.v1"
5) 7)
6 8
7func (s *Suite) TestVartypeCheck_AwkCommand(c *check.C) { 9func (s *Suite) TestVartypeCheck_AwkCommand(c *check.C) {
8 s.UseCommandLine(c, "-Dunchecked") 10 s.UseCommandLine(c, "-Dunchecked")
9 runVartypeChecks("PLIST_AWK", opAssignAppend, (*VartypeCheck).AwkCommand, 11 runVartypeChecks("PLIST_AWK", opAssignAppend, (*VartypeCheck).AwkCommand,
10 "{print $0}", 12 "{print $0}",
11 "{print $$0}") 13 "{print $$0}")
12 14
13 c.Check(s.Output(), equals, ""+ 15 c.Check(s.Output(), equals, ""+
14 "ERROR: fname:1: Invalid Makefile syntax at \"$0}\".\n"+ 16 "ERROR: fname:1: Invalid Makefile syntax at \"$0}\".\n"+
15 "DEBUG: fname:1: Unchecked AWK command: \"{print $0}\"\n"+ 17 "DEBUG: fname:1: Unchecked AWK command: \"{print $0}\"\n"+
16 "DEBUG: fname:2: Unchecked AWK command: \"{print $$0}\"\n") 18 "DEBUG: fname:2: Unchecked AWK command: \"{print $$0}\"\n")
@@ -159,26 +161,36 @@ func (s *Suite) TestVartypeCheck_DistSuf @@ -159,26 +161,36 @@ func (s *Suite) TestVartypeCheck_DistSuf
159 161
160func (s *Suite) TestVartypeCheck_EmulPlatform(c *check.C) { 162func (s *Suite) TestVartypeCheck_EmulPlatform(c *check.C) {
161 runVartypeChecks("EMUL_PLATFORM", opAssign, (*VartypeCheck).EmulPlatform, 163 runVartypeChecks("EMUL_PLATFORM", opAssign, (*VartypeCheck).EmulPlatform,
162 "linux-i386", 164 "linux-i386",
163 "nextbsd-8087", 165 "nextbsd-8087",
164 "${LINUX}") 166 "${LINUX}")
165 167
166 c.Check(s.Output(), equals, ""+ 168 c.Check(s.Output(), equals, ""+
167 "WARN: fname:2: Unknown operating system: nextbsd\n"+ 169 "WARN: fname:2: Unknown operating system: nextbsd\n"+
168 "WARN: fname:2: Unknown hardware architecture: 8087\n"+ 170 "WARN: fname:2: Unknown hardware architecture: 8087\n"+
169 "WARN: fname:3: \"${LINUX}\" is not a valid emulation platform.\n") 171 "WARN: fname:3: \"${LINUX}\" is not a valid emulation platform.\n")
170} 172}
171 173
 174func (s *Suite) TestVartypeCheck_Enum(c *check.C) {
 175 runVartypeMatchChecks("JDK", enum("jdk1 jdk2 jdk4").checker,
 176 "*",
 177 "jdk*",
 178 "sun-jdk*",
 179 "${JDKNAME}")
 180
 181 c.Check(s.Output(), equals, "WARN: fname:3: The pattern \"sun-jdk*\" cannot match any of { jdk1 jdk2 jdk4 } for JDK.\n")
 182}
 183
172func (s *Suite) TestVartypeCheck_FetchURL(c *check.C) { 184func (s *Suite) TestVartypeCheck_FetchURL(c *check.C) {
173 G.globalData.MasterSiteUrls = map[string]string{ 185 G.globalData.MasterSiteUrls = map[string]string{
174 "https://github.com/": "MASTER_SITE_GITHUB", 186 "https://github.com/": "MASTER_SITE_GITHUB",
175 "http://ftp.gnu.org/pub/gnu/": "MASTER_SITE_GNU", 187 "http://ftp.gnu.org/pub/gnu/": "MASTER_SITE_GNU",
176 } 188 }
177 G.globalData.MasterSiteVars = map[string]bool{ 189 G.globalData.MasterSiteVars = map[string]bool{
178 "MASTER_SITE_GITHUB": true, 190 "MASTER_SITE_GITHUB": true,
179 "MASTER_SITE_GNU": true, 191 "MASTER_SITE_GNU": true,
180 } 192 }
181 193
182 runVartypeChecks("MASTER_SITES", opAssign, (*VartypeCheck).FetchURL, 194 runVartypeChecks("MASTER_SITES", opAssign, (*VartypeCheck).FetchURL,
183 "https://github.com/example/project/", 195 "https://github.com/example/project/",
184 "http://ftp.gnu.org/pub/gnu/bison", // Missing a slash at the end 196 "http://ftp.gnu.org/pub/gnu/bison", // Missing a slash at the end
@@ -353,55 +365,78 @@ func (s *Suite) TestVartypeCheck_Varname @@ -353,55 +365,78 @@ func (s *Suite) TestVartypeCheck_Varname
353 365
354 c.Check(s.Output(), equals, "WARN: fname:2: \"VarBase\" is not a valid variable name.\n") 366 c.Check(s.Output(), equals, "WARN: fname:2: \"VarBase\" is not a valid variable name.\n")
355} 367}
356 368
357func (s *Suite) TestVartypeCheck_Yes(c *check.C) { 369func (s *Suite) TestVartypeCheck_Yes(c *check.C) {
358 runVartypeChecks("APACHE_MODULE", opAssign, (*VartypeCheck).Yes, 370 runVartypeChecks("APACHE_MODULE", opAssign, (*VartypeCheck).Yes,
359 "yes", 371 "yes",
360 "no", 372 "no",
361 "${YESVAR}") 373 "${YESVAR}")
362 374
363 c.Check(s.Output(), equals, ""+ 375 c.Check(s.Output(), equals, ""+
364 "WARN: fname:2: APACHE_MODULE should be set to YES or yes.\n"+ 376 "WARN: fname:2: APACHE_MODULE should be set to YES or yes.\n"+
365 "WARN: fname:3: APACHE_MODULE should be set to YES or yes.\n") 377 "WARN: fname:3: APACHE_MODULE should be set to YES or yes.\n")
 378
 379 runVartypeMatchChecks("PKG_DEVELOPER", (*VartypeCheck).Yes,
 380 "yes",
 381 "no",
 382 "${YESVAR}")
 383
 384 c.Check(s.Output(), equals, ""+
 385 "WARN: fname:1: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n"+
 386 "WARN: fname:2: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n"+
 387 "WARN: fname:3: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n")
366} 388}
367 389
368func (s *Suite) TestVartypeCheck_YesNo(c *check.C) { 390func (s *Suite) TestVartypeCheck_YesNo(c *check.C) {
369 runVartypeChecks("GNU_CONFIGURE", opAssign, (*VartypeCheck).YesNo, 391 runVartypeChecks("GNU_CONFIGURE", opAssign, (*VartypeCheck).YesNo,
370 "yes", 392 "yes",
371 "no", 393 "no",
372 "ja", 394 "ja",
373 "${YESVAR}") 395 "${YESVAR}")
374 396
375 c.Check(s.Output(), equals, ""+ 397 c.Check(s.Output(), equals, ""+
376 "WARN: fname:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n"+ 398 "WARN: fname:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n"+
377 "WARN: fname:4: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n") 399 "WARN: fname:4: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n")
378} 400}
379 401
380func (s *Suite) TestVartypeCheck_YesNoIndirectly(c *check.C) { 402func (s *Suite) TestVartypeCheck_YesNoIndirectly(c *check.C) {
381 runVartypeChecks("GNU_CONFIGURE", opAssign, (*VartypeCheck).YesNoIndirectly, 403 runVartypeChecks("GNU_CONFIGURE", opAssign, (*VartypeCheck).YesNoIndirectly,
382 "yes", 404 "yes",
383 "no", 405 "no",
384 "ja", 406 "ja",
385 "${YESVAR}") 407 "${YESVAR}")
386 408
387 c.Check(s.Output(), equals, ""+ 409 c.Check(s.Output(), equals, ""+
388 "WARN: fname:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n") 410 "WARN: fname:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n")
389} 411}
390 412
391func runVartypeChecks(varname string, op MkOperator, checker func(*VartypeCheck), values ...string) { 413func runVartypeChecks(varname string, op MkOperator, checker func(*VartypeCheck), values ...string) {
 414 if !contains(op.String(), "=") {
 415 panic("runVartypeChecks needs an assignment operator")
 416 }
392 for i, value := range values { 417 for i, value := range values {
393 mkline := NewMkLine(NewLine("fname", i+1, varname+op.String()+value, nil)) 418 mkline := NewMkLine(NewLine("fname", i+1, varname+op.String()+value, nil))
394 valueNovar := mkline.withoutMakeVariables(mkline.Value(), true) 419 valueNovar := mkline.withoutMakeVariables(mkline.Value(), true)
395 vc := &VartypeCheck{mkline, mkline.Line, mkline.Varname(), mkline.Op(), mkline.Value(), valueNovar, "", true, false} 420 vc := &VartypeCheck{mkline, mkline.Line, mkline.Varname(), mkline.Op(), mkline.Value(), valueNovar, "", true, false}
396 checker(vc) 421 checker(vc)
397 } 422 }
398} 423}
399 424
 425func runVartypeMatchChecks(varname string, checker func(*VartypeCheck), values ...string) {
 426 for i, value := range values {
 427 text := fmt.Sprintf(".if ${%s:M%s} == \"\"", varname, value)
 428 mkline := NewMkLine(NewLine("fname", i+1, text, nil))
 429 valueNovar := mkline.withoutMakeVariables(value, true)
 430 vc := &VartypeCheck{mkline, mkline.Line, varname, opUseMatch, value, valueNovar, "", true, false}
 431 checker(vc)
 432 }
 433}
 434
400func runVartypeChecksFname(fname, varname string, op MkOperator, checker func(*VartypeCheck), values ...string) { 435func runVartypeChecksFname(fname, varname string, op MkOperator, checker func(*VartypeCheck), values ...string) {
401 for i, value := range values { 436 for i, value := range values {
402 mkline := NewMkLine(NewLine(fname, i+1, varname+op.String()+value, nil)) 437 mkline := NewMkLine(NewLine(fname, i+1, varname+op.String()+value, nil))
403 valueNovar := mkline.withoutMakeVariables(value, true) 438 valueNovar := mkline.withoutMakeVariables(value, true)
404 vc := &VartypeCheck{mkline, mkline.Line, varname, op, value, valueNovar, "", true, false} 439 vc := &VartypeCheck{mkline, mkline.Line, varname, op, value, valueNovar, "", true, false}
405 checker(vc) 440 checker(vc)
406 } 441 }
407} 442}