Updated pkglint to 5.4.4. Changes since 5.4.3: * Improved detection for undocumented patches from Git * Added warning about unnecessary space after variable names * Lots of internal housekeepingdiff -r1.488 -r1.489 pkgsrc/pkgtools/pkglint/Makefile
(rillig)
@@ -1,16 +1,16 @@ | @@ -1,16 +1,16 @@ | |||
1 | # $NetBSD: Makefile,v 1.488 2016/07/07 12:09:26 rillig Exp $ | 1 | # $NetBSD: Makefile,v 1.489 2016/07/09 09:43:48 rillig Exp $ | |
2 | 2 | |||
3 | PKGNAME= pkglint-5.4.3 | 3 | PKGNAME= pkglint-5.4.4 | |
4 | DISTFILES= # none | 4 | DISTFILES= # none | |
5 | CATEGORIES= pkgtools | 5 | CATEGORIES= pkgtools | |
6 | 6 | |||
7 | OWNER= rillig@NetBSD.org | 7 | OWNER= rillig@NetBSD.org | |
8 | HOMEPAGE= http://www.NetBSD.org/docs/pkgsrc/ | 8 | HOMEPAGE= http://www.NetBSD.org/docs/pkgsrc/ | |
9 | COMMENT= Verifier for NetBSD packages | 9 | COMMENT= Verifier for NetBSD packages | |
10 | LICENSE= 2-clause-bsd | 10 | LICENSE= 2-clause-bsd | |
11 | CONFLICTS+= pkglint4-[0-9]* | 11 | CONFLICTS+= pkglint4-[0-9]* | |
12 | 12 | |||
13 | WRKSRC= ${WRKDIR}/netbsd.org/pkglint | 13 | WRKSRC= ${WRKDIR}/netbsd.org/pkglint | |
14 | NO_CHECKSUM= yes | 14 | NO_CHECKSUM= yes | |
15 | USE_LANGUAGES= # none | 15 | USE_LANGUAGES= # none | |
16 | USE_TOOLS+= pax | 16 | USE_TOOLS+= pax |
@@ -1,20 +1,20 @@ | @@ -1,20 +1,20 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestChecklinesBuildlink3(c *check.C) { | 7 | func (s *Suite) Test_ChecklinesBuildlink3Mk(c *check.C) { | |
8 | G.globalData.InitVartypes() | 8 | G.globalData.InitVartypes() | |
9 | mklines := s.NewMkLines("buildlink3.mk", | 9 | mklines := s.NewMkLines("buildlink3.mk", | |
10 | "# $"+"NetBSD$", | 10 | "# $"+"NetBSD$", | |
11 | "# XXX This file was created automatically using createbuildlink-@PKGVERSION@", | 11 | "# XXX This file was created automatically using createbuildlink-@PKGVERSION@", | |
12 | "", | 12 | "", | |
13 | "BUILDLINK_TREE+= Xbae", | 13 | "BUILDLINK_TREE+= Xbae", | |
14 | "", | 14 | "", | |
15 | "BUILDLINK_DEPMETHOD.Xbae?=\tfull", | 15 | "BUILDLINK_DEPMETHOD.Xbae?=\tfull", | |
16 | ".if !defined(XBAE_BUILDLINK3_MK)", | 16 | ".if !defined(XBAE_BUILDLINK3_MK)", | |
17 | "XBAE_BUILDLINK3_MK:=", | 17 | "XBAE_BUILDLINK3_MK:=", | |
18 | "", | 18 | "", | |
19 | "BUILDLINK_API_DEPENDS.Xbae+= Xbae>=4.8.4", | 19 | "BUILDLINK_API_DEPENDS.Xbae+= Xbae>=4.8.4", | |
20 | "BUILDLINK_ABI_DEPENDS.Xbae+= Xbae>=4.51.01nb2", | 20 | "BUILDLINK_ABI_DEPENDS.Xbae+= Xbae>=4.51.01nb2", | |
@@ -27,245 +27,245 @@ func (s *Suite) TestChecklinesBuildlink3 | @@ -27,245 +27,245 @@ func (s *Suite) TestChecklinesBuildlink3 | |||
27 | 27 | |||
28 | ChecklinesBuildlink3Mk(mklines) | 28 | ChecklinesBuildlink3Mk(mklines) | |
29 | 29 | |||
30 | c.Check(s.Output(), equals, ""+ | 30 | c.Check(s.Output(), equals, ""+ | |
31 | "ERROR: buildlink3.mk:12: \"/x11/Xbae\" does not exist.\n"+ | 31 | "ERROR: buildlink3.mk:12: \"/x11/Xbae\" does not exist.\n"+ | |
32 | "ERROR: buildlink3.mk:12: There is no package in \"x11/Xbae\".\n"+ | 32 | "ERROR: buildlink3.mk:12: There is no package in \"x11/Xbae\".\n"+ | |
33 | "ERROR: buildlink3.mk:14: \"/mk/motif.buildlink3.mk\" does not exist.\n"+ | 33 | "ERROR: buildlink3.mk:14: \"/mk/motif.buildlink3.mk\" does not exist.\n"+ | |
34 | "ERROR: buildlink3.mk:2: This comment indicates unfinished work (url2pkg).\n") | 34 | "ERROR: buildlink3.mk:2: This comment indicates unfinished work (url2pkg).\n") | |
35 | } | 35 | } | |
36 | 36 | |||
37 | // Before version 5.3, pkglint wrongly warned here. | 37 | // Before version 5.3, pkglint wrongly warned here. | |
38 | // The mk/haskell.mk file takes care of constructing the correct PKGNAME, | 38 | // The mk/haskell.mk file takes care of constructing the correct PKGNAME, | |
39 | // but pkglint had not looked at that file. | 39 | // but pkglint had not looked at that file. | |
40 | func (s *Suite) TestChecklinesBuildlink3_NameMismatch(c *check.C) { | 40 | func (s *Suite) Test_ChecklinesBuildlink3Mk_name_mismatch(c *check.C) { | |
41 | G.globalData.InitVartypes() | 41 | G.globalData.InitVartypes() | |
42 | G.Pkg = NewPackage("x11/hs-X11") | 42 | G.Pkg = NewPackage("x11/hs-X11") | |
43 | G.Pkg.EffectivePkgbase = "X11" | 43 | G.Pkg.EffectivePkgbase = "X11" | |
44 | G.Pkg.EffectivePkgnameLine = NewMkLine(NewLine("Makefile", 3, "DISTNAME=\tX11-1.0", nil)) | 44 | G.Pkg.EffectivePkgnameLine = NewMkLine(NewLine("Makefile", 3, "DISTNAME=\tX11-1.0", nil)) | |
45 | mklines := s.NewMkLines("buildlink3.mk", | 45 | mklines := s.NewMkLines("buildlink3.mk", | |
46 | "# $"+"NetBSD$", | 46 | "# $"+"NetBSD$", | |
47 | "", | 47 | "", | |
48 | "BUILDLINK_TREE+=\ths-X11", | 48 | "BUILDLINK_TREE+=\ths-X11", | |
49 | "", | 49 | "", | |
50 | ".if !defined(HS_X11_BUILDLINK3_MK)", | 50 | ".if !defined(HS_X11_BUILDLINK3_MK)", | |
51 | "HS_X11_BUILDLINK3_MK:=", | 51 | "HS_X11_BUILDLINK3_MK:=", | |
52 | "", | 52 | "", | |
53 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | 53 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | |
54 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11>=1.6.1.2nb2", | 54 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11>=1.6.1.2nb2", | |
55 | "", | 55 | "", | |
56 | ".endif\t# HS_X11_BUILDLINK3_MK", | 56 | ".endif\t# HS_X11_BUILDLINK3_MK", | |
57 | "", | 57 | "", | |
58 | "BUILDLINK_TREE+=\t-hs-X11") | 58 | "BUILDLINK_TREE+=\t-hs-X11") | |
59 | 59 | |||
60 | ChecklinesBuildlink3Mk(mklines) | 60 | ChecklinesBuildlink3Mk(mklines) | |
61 | 61 | |||
62 | c.Check(s.Output(), equals, "ERROR: buildlink3.mk:3: Package name mismatch between \"hs-X11\" in this file and \"X11\" from Makefile:3.\n") | 62 | c.Check(s.Output(), equals, "ERROR: buildlink3.mk:3: Package name mismatch between \"hs-X11\" in this file and \"X11\" from Makefile:3.\n") | |
63 | } | 63 | } | |
64 | 64 | |||
65 | func (s *Suite) TestChecklinesBuildlink3_NameMismatchMultipleInclusion(c *check.C) { | 65 | func (s *Suite) Test_ChecklinesBuildlink3Mk_name_mismatch_multiple_inclusion(c *check.C) { | |
66 | G.globalData.InitVartypes() | 66 | G.globalData.InitVartypes() | |
67 | mklines := s.NewMkLines("buildlink3.mk", | 67 | mklines := s.NewMkLines("buildlink3.mk", | |
68 | "# $"+"NetBSD$", | 68 | "# $"+"NetBSD$", | |
69 | "", | 69 | "", | |
70 | "BUILDLINK_TREE+=\tpkgbase1", | 70 | "BUILDLINK_TREE+=\tpkgbase1", | |
71 | "", | 71 | "", | |
72 | ".if !defined(PKGBASE2_BUILDLINK3_MK)", | 72 | ".if !defined(PKGBASE2_BUILDLINK3_MK)", | |
73 | "PKGBASE2_BUILDLINK3_MK:=", | 73 | "PKGBASE2_BUILDLINK3_MK:=", | |
74 | "", | 74 | "", | |
75 | ".endif", | 75 | ".endif", | |
76 | "", | 76 | "", | |
77 | "BUILDLINK_TREE+=\t-pkgbase1") | 77 | "BUILDLINK_TREE+=\t-pkgbase1") | |
78 | 78 | |||
79 | ChecklinesBuildlink3Mk(mklines) | 79 | ChecklinesBuildlink3Mk(mklines) | |
80 | 80 | |||
81 | c.Check(s.Output(), equals, ""+ | 81 | c.Check(s.Output(), equals, ""+ | |
82 | "ERROR: buildlink3.mk:5: Package name mismatch between multiple-inclusion guard \"PKGBASE2\" (expected \"PKGBASE1\") and package name \"pkgbase1\" (from line 3).\n"+ | 82 | "ERROR: buildlink3.mk:5: Package name mismatch between multiple-inclusion guard \"PKGBASE2\" (expected \"PKGBASE1\") and package name \"pkgbase1\" (from line 3).\n"+ | |
83 | "WARN: buildlink3.mk:9: Definition of BUILDLINK_API_DEPENDS is missing.\n") | 83 | "WARN: buildlink3.mk:9: Definition of BUILDLINK_API_DEPENDS is missing.\n") | |
84 | } | 84 | } | |
85 | 85 | |||
86 | func (s *Suite) TestChecklinesBuildlink3_NameMismatchAbiApi(c *check.C) { | 86 | func (s *Suite) Test_ChecklinesBuildlink3Mk_name_mismatch_abi_api(c *check.C) { | |
87 | G.globalData.InitVartypes() | 87 | G.globalData.InitVartypes() | |
88 | mklines := s.NewMkLines("buildlink3.mk", | 88 | mklines := s.NewMkLines("buildlink3.mk", | |
89 | "# $"+"NetBSD$", | 89 | "# $"+"NetBSD$", | |
90 | "", | 90 | "", | |
91 | "BUILDLINK_TREE+=\ths-X11", | 91 | "BUILDLINK_TREE+=\ths-X11", | |
92 | "", | 92 | "", | |
93 | ".if !defined(HS_X11_BUILDLINK3_MK)", | 93 | ".if !defined(HS_X11_BUILDLINK3_MK)", | |
94 | "HS_X11_BUILDLINK3_MK:=", | 94 | "HS_X11_BUILDLINK3_MK:=", | |
95 | "", | 95 | "", | |
96 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | 96 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | |
97 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X12>=1.6.1.2nb2", | 97 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X12>=1.6.1.2nb2", | |
98 | "", | 98 | "", | |
99 | ".endif\t# HS_X11_BUILDLINK3_MK", | 99 | ".endif\t# HS_X11_BUILDLINK3_MK", | |
100 | "", | 100 | "", | |
101 | "BUILDLINK_TREE+=\t-hs-X11") | 101 | "BUILDLINK_TREE+=\t-hs-X11") | |
102 | 102 | |||
103 | ChecklinesBuildlink3Mk(mklines) | 103 | ChecklinesBuildlink3Mk(mklines) | |
104 | 104 | |||
105 | c.Check(s.Output(), equals, "WARN: buildlink3.mk:9: Package name mismatch between ABI \"hs-X12\" and API \"hs-X11\" (from line 8).\n") | 105 | c.Check(s.Output(), equals, "WARN: buildlink3.mk:9: Package name mismatch between ABI \"hs-X12\" and API \"hs-X11\" (from line 8).\n") | |
106 | } | 106 | } | |
107 | 107 | |||
108 | func (s *Suite) TestChecklinesBuildlink3_AbiApiVersions(c *check.C) { | 108 | func (s *Suite) Test_ChecklinesBuildlink3Mk_abi_api_versions(c *check.C) { | |
109 | G.globalData.InitVartypes() | 109 | G.globalData.InitVartypes() | |
110 | mklines := s.NewMkLines("buildlink3.mk", | 110 | mklines := s.NewMkLines("buildlink3.mk", | |
111 | "# $"+"NetBSD$", | 111 | "# $"+"NetBSD$", | |
112 | "", | 112 | "", | |
113 | "BUILDLINK_TREE+=\ths-X11", | 113 | "BUILDLINK_TREE+=\ths-X11", | |
114 | "", | 114 | "", | |
115 | ".if !defined(HS_X11_BUILDLINK3_MK)", | 115 | ".if !defined(HS_X11_BUILDLINK3_MK)", | |
116 | "HS_X11_BUILDLINK3_MK:=", | 116 | "HS_X11_BUILDLINK3_MK:=", | |
117 | "", | 117 | "", | |
118 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | 118 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | |
119 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11>=1.6.0", | 119 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11>=1.6.0", | |
120 | "", | 120 | "", | |
121 | ".endif\t# HS_X11_BUILDLINK3_MK", | 121 | ".endif\t# HS_X11_BUILDLINK3_MK", | |
122 | "", | 122 | "", | |
123 | "BUILDLINK_TREE+=\t-hs-X11") | 123 | "BUILDLINK_TREE+=\t-hs-X11") | |
124 | 124 | |||
125 | ChecklinesBuildlink3Mk(mklines) | 125 | ChecklinesBuildlink3Mk(mklines) | |
126 | 126 | |||
127 | c.Check(s.Output(), equals, ""+ | 127 | c.Check(s.Output(), equals, ""+ | |
128 | "WARN: buildlink3.mk:9: ABI version \"1.6.0\" should be at least API version \"1.6.1\" (see line 8).\n") | 128 | "WARN: buildlink3.mk:9: ABI version \"1.6.0\" should be at least API version \"1.6.1\" (see line 8).\n") | |
129 | } | 129 | } | |
130 | 130 | |||
131 | func (s *Suite) TestChecklinesBuildlink3_NoBuildlinkTreeAtBeginning(c *check.C) { | 131 | func (s *Suite) Test_ChecklinesBuildlink3Mk_no_BUILDLINK_TREE_at_beginning(c *check.C) { | |
132 | G.globalData.InitVartypes() | 132 | G.globalData.InitVartypes() | |
133 | mklines := s.NewMkLines("buildlink3.mk", | 133 | mklines := s.NewMkLines("buildlink3.mk", | |
134 | "# $"+"NetBSD$", | 134 | "# $"+"NetBSD$", | |
135 | "", | 135 | "", | |
136 | ".if !defined(HS_X11_BUILDLINK3_MK)", | 136 | ".if !defined(HS_X11_BUILDLINK3_MK)", | |
137 | "HS_X11_BUILDLINK3_MK:=", | 137 | "HS_X11_BUILDLINK3_MK:=", | |
138 | "", | 138 | "", | |
139 | "BUILDLINK_DEPMETHOD.hs-X11?=\tfull", | 139 | "BUILDLINK_DEPMETHOD.hs-X11?=\tfull", | |
140 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | 140 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | |
141 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11>=1.6.1.2nb2", | 141 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11>=1.6.1.2nb2", | |
142 | "", | 142 | "", | |
143 | ".endif\t# HS_X11_BUILDLINK3_MK", | 143 | ".endif\t# HS_X11_BUILDLINK3_MK", | |
144 | "", | 144 | "", | |
145 | "BUILDLINK_TREE+=\t-hs-X11") | 145 | "BUILDLINK_TREE+=\t-hs-X11") | |
146 | 146 | |||
147 | ChecklinesBuildlink3Mk(mklines) | 147 | ChecklinesBuildlink3Mk(mklines) | |
148 | 148 | |||
149 | c.Check(s.Output(), equals, "WARN: buildlink3.mk:3: Expected a BUILDLINK_TREE line.\n") | 149 | c.Check(s.Output(), equals, "WARN: buildlink3.mk:3: Expected a BUILDLINK_TREE line.\n") | |
150 | } | 150 | } | |
151 | 151 | |||
152 | func (s *Suite) TestChecklinesBuildlink3_NoBuildlinkTreeAtEnd(c *check.C) { | 152 | func (s *Suite) Test_ChecklinesBuildlink3Mk_no_BUILDLINK_TREE_at_end(c *check.C) { | |
153 | G.globalData.InitVartypes() | 153 | G.globalData.InitVartypes() | |
154 | mklines := s.NewMkLines("buildlink3.mk", | 154 | mklines := s.NewMkLines("buildlink3.mk", | |
155 | "# $"+"NetBSD$", | 155 | "# $"+"NetBSD$", | |
156 | "", | 156 | "", | |
157 | "BUILDLINK_DEPMETHOD.hs-X11?=\tfull", | 157 | "BUILDLINK_DEPMETHOD.hs-X11?=\tfull", | |
158 | "", | 158 | "", | |
159 | "BUILDLINK_TREE+=\ths-X11", | 159 | "BUILDLINK_TREE+=\ths-X11", | |
160 | "", | 160 | "", | |
161 | ".if !defined(HS_X11_BUILDLINK3_MK)", | 161 | ".if !defined(HS_X11_BUILDLINK3_MK)", | |
162 | "HS_X11_BUILDLINK3_MK:=", | 162 | "HS_X11_BUILDLINK3_MK:=", | |
163 | "", | 163 | "", | |
164 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | 164 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11>=1.6.1", | |
165 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11>=1.6.1.2nb2", | 165 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11>=1.6.1.2nb2", | |
166 | "", | 166 | "", | |
167 | ".endif\t# HS_X11_BUILDLINK3_MK", | 167 | ".endif\t# HS_X11_BUILDLINK3_MK", | |
168 | "", | 168 | "", | |
169 | "# needless comment", | 169 | "# needless comment", | |
170 | "BUILDLINK_TREE+=\t-hs-X11") | 170 | "BUILDLINK_TREE+=\t-hs-X11") | |
171 | 171 | |||
172 | ChecklinesBuildlink3Mk(mklines) | 172 | ChecklinesBuildlink3Mk(mklines) | |
173 | 173 | |||
174 | c.Check(s.Output(), equals, ""+ | 174 | c.Check(s.Output(), equals, ""+ | |
175 | "WARN: buildlink3.mk:3: This line belongs inside the .ifdef block.\n"+ | 175 | "WARN: buildlink3.mk:3: This line belongs inside the .ifdef block.\n"+ | |
176 | "WARN: buildlink3.mk:15: This line should contain the following text: BUILDLINK_TREE+=\t-hs-X11\n") | 176 | "WARN: buildlink3.mk:15: This line should contain the following text: BUILDLINK_TREE+=\t-hs-X11\n") | |
177 | } | 177 | } | |
178 | 178 | |||
179 | func (s *Suite) TestChecklinesBuildlink3_MultipleInclusionWrong(c *check.C) { | 179 | func (s *Suite) Test_ChecklinesBuildlink3Mk_multiple_inclusion_wrong(c *check.C) { | |
180 | G.globalData.InitVartypes() | 180 | G.globalData.InitVartypes() | |
181 | mklines := s.NewMkLines("buildlink3.mk", | 181 | mklines := s.NewMkLines("buildlink3.mk", | |
182 | "# $"+"NetBSD$", | 182 | "# $"+"NetBSD$", | |
183 | "", | 183 | "", | |
184 | "BUILDLINK_TREE+=\ths-X11", | 184 | "BUILDLINK_TREE+=\ths-X11", | |
185 | "", | 185 | "", | |
186 | ".if !defined(HS_X11_BUILDLINK3_MK)", | 186 | ".if !defined(HS_X11_BUILDLINK3_MK)", | |
187 | "UNRELATED_BUILDLINK3_MK:=") | 187 | "UNRELATED_BUILDLINK3_MK:=") | |
188 | 188 | |||
189 | ChecklinesBuildlink3Mk(mklines) | 189 | ChecklinesBuildlink3Mk(mklines) | |
190 | 190 | |||
191 | c.Check(s.Output(), equals, ""+ | 191 | c.Check(s.Output(), equals, ""+ | |
192 | "WARN: buildlink3.mk:6: UNRELATED_BUILDLINK3_MK is defined but not used. Spelling mistake?\n"+ | 192 | "WARN: buildlink3.mk:6: UNRELATED_BUILDLINK3_MK is defined but not used. Spelling mistake?\n"+ | |
193 | "WARN: buildlink3.mk:6: This line should contain the following text: HS_X11_BUILDLINK3_MK:=\n") | 193 | "WARN: buildlink3.mk:6: This line should contain the following text: HS_X11_BUILDLINK3_MK:=\n") | |
194 | } | 194 | } | |
195 | 195 | |||
196 | func (s *Suite) TestChecklinesBuildlink3_EndIfMissing(c *check.C) { | 196 | func (s *Suite) Test_ChecklinesBuildlink3Mk_missing_endif(c *check.C) { | |
197 | G.globalData.InitVartypes() | 197 | G.globalData.InitVartypes() | |
198 | mklines := s.NewMkLines("buildlink3.mk", | 198 | mklines := s.NewMkLines("buildlink3.mk", | |
199 | "# $"+"NetBSD$", | 199 | "# $"+"NetBSD$", | |
200 | "", | 200 | "", | |
201 | "BUILDLINK_TREE+=\tpkgbase1", | 201 | "BUILDLINK_TREE+=\tpkgbase1", | |
202 | "", | 202 | "", | |
203 | ".if !defined(PKGBASE1_BUILDLINK3_MK)", | 203 | ".if !defined(PKGBASE1_BUILDLINK3_MK)", | |
204 | "PKGBASE1_BUILDLINK3_MK:=") | 204 | "PKGBASE1_BUILDLINK3_MK:=") | |
205 | 205 | |||
206 | ChecklinesBuildlink3Mk(mklines) | 206 | ChecklinesBuildlink3Mk(mklines) | |
207 | 207 | |||
208 | c.Check(s.Output(), equals, "WARN: buildlink3.mk:EOF: Expected .endif\n") | 208 | c.Check(s.Output(), equals, "WARN: buildlink3.mk:EOF: Expected .endif\n") | |
209 | } | 209 | } | |
210 | 210 | |||
211 | func (s *Suite) TestChecklinesBuildlink3_UnknownDependencyPatterns(c *check.C) { | 211 | func (s *Suite) Test_ChecklinesBuildlink3Mk_unknown_dependency_patterns(c *check.C) { | |
212 | G.globalData.InitVartypes() | 212 | G.globalData.InitVartypes() | |
213 | mklines := s.NewMkLines("buildlink3.mk", | 213 | mklines := s.NewMkLines("buildlink3.mk", | |
214 | "# $"+"NetBSD$", | 214 | "# $"+"NetBSD$", | |
215 | "", | 215 | "", | |
216 | "BUILDLINK_TREE+= hs-X11", | 216 | "BUILDLINK_TREE+= hs-X11", | |
217 | "", | 217 | "", | |
218 | ".if !defined(HS_X11_BUILDLINK3_MK)", | 218 | ".if !defined(HS_X11_BUILDLINK3_MK)", | |
219 | "HS_X11_BUILDLINK3_MK:=", | 219 | "HS_X11_BUILDLINK3_MK:=", | |
220 | "", | 220 | "", | |
221 | "BUILDLINK_DEPMETHOD.hs-X11?=\tfull", | 221 | "BUILDLINK_DEPMETHOD.hs-X11?=\tfull", | |
222 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11!=1.6.1", | 222 | "BUILDLINK_API_DEPENDS.hs-X11+=\ths-X11!=1.6.1", | |
223 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11!=1.6.1.2nb2", | 223 | "BUILDLINK_ABI_DEPENDS.hs-X11+=\ths-X11!=1.6.1.2nb2", | |
224 | "", | 224 | "", | |
225 | ".endif\t# HS_X11_BUILDLINK3_MK", | 225 | ".endif\t# HS_X11_BUILDLINK3_MK", | |
226 | "", | 226 | "", | |
227 | "BUILDLINK_TREE+=\t-hs-X11") | 227 | "BUILDLINK_TREE+=\t-hs-X11") | |
228 | 228 | |||
229 | ChecklinesBuildlink3Mk(mklines) | 229 | ChecklinesBuildlink3Mk(mklines) | |
230 | 230 | |||
231 | c.Check(s.Output(), equals, ""+ | 231 | c.Check(s.Output(), equals, ""+ | |
232 | "WARN: buildlink3.mk:9: Unknown dependency pattern \"hs-X11!=1.6.1\".\n"+ | 232 | "WARN: buildlink3.mk:9: Unknown dependency pattern \"hs-X11!=1.6.1\".\n"+ | |
233 | "WARN: buildlink3.mk:10: Unknown dependency pattern \"hs-X11!=1.6.1.2nb2\".\n") | 233 | "WARN: buildlink3.mk:10: Unknown dependency pattern \"hs-X11!=1.6.1.2nb2\".\n") | |
234 | } | 234 | } | |
235 | 235 | |||
236 | func (s *Suite) TestChecklinesBuildlink3_PkgbaseWithVariable(c *check.C) { | 236 | func (s *Suite) Test_ChecklinesBuildlink3Mk_PKGBASE_with_variable(c *check.C) { | |
237 | G.globalData.InitVartypes() | 237 | G.globalData.InitVartypes() | |
238 | mklines := s.NewMkLines("buildlink3.mk", | 238 | mklines := s.NewMkLines("buildlink3.mk", | |
239 | "# $"+"NetBSD$", | 239 | "# $"+"NetBSD$", | |
240 | "", | 240 | "", | |
241 | "BUILDLINK_TREE+=\t${PYPKGPREFIX}-wxWidgets", | 241 | "BUILDLINK_TREE+=\t${PYPKGPREFIX}-wxWidgets", | |
242 | "", | 242 | "", | |
243 | ".if !defined(PY_WXWIDGETS_BUILDLINK3_MK)", | 243 | ".if !defined(PY_WXWIDGETS_BUILDLINK3_MK)", | |
244 | "PY_WXWIDGETS_BUILDLINK3_MK:=", | 244 | "PY_WXWIDGETS_BUILDLINK3_MK:=", | |
245 | "", | 245 | "", | |
246 | "BUILDLINK_API_DEPENDS.${PYPKGPREFIX}-wxWidgets+=\t${PYPKGPREFIX}-wxWidgets>=2.6.1.0", | 246 | "BUILDLINK_API_DEPENDS.${PYPKGPREFIX}-wxWidgets+=\t${PYPKGPREFIX}-wxWidgets>=2.6.1.0", | |
247 | "BUILDLINK_ABI_DEPENDS.${PYPKGPREFIX}-wxWidgets+=\t${PYPKGPREFIX}-wxWidgets>=2.8.10.1nb26", | 247 | "BUILDLINK_ABI_DEPENDS.${PYPKGPREFIX}-wxWidgets+=\t${PYPKGPREFIX}-wxWidgets>=2.8.10.1nb26", | |
248 | "", | 248 | "", | |
249 | ".endif", | 249 | ".endif", | |
250 | "", | 250 | "", | |
251 | "BUILDLINK_TREE+=\t-${PYPKGPREFIX}-wxWidgets") | 251 | "BUILDLINK_TREE+=\t-${PYPKGPREFIX}-wxWidgets") | |
252 | 252 | |||
253 | ChecklinesBuildlink3Mk(mklines) | 253 | ChecklinesBuildlink3Mk(mklines) | |
254 | 254 | |||
255 | c.Check(s.Output(), equals, "WARN: buildlink3.mk:3: Please use \"py\" instead of \"${PYPKGPREFIX}\".\n") | 255 | c.Check(s.Output(), equals, "WARN: buildlink3.mk:3: Please use \"py\" instead of \"${PYPKGPREFIX}\".\n") | |
256 | } | 256 | } | |
257 | 257 | |||
258 | func (s *Suite) TestChecklinesBuildlink3_PkgbaseWithUnknownVariable(c *check.C) { | 258 | func (s *Suite) Test_ChecklinesBuildlink3Mk_PKGBASE_with_unknown_variable(c *check.C) { | |
259 | G.globalData.InitVartypes() | 259 | G.globalData.InitVartypes() | |
260 | mklines := s.NewMkLines("buildlink3.mk", | 260 | mklines := s.NewMkLines("buildlink3.mk", | |
261 | "# $"+"NetBSD$", | 261 | "# $"+"NetBSD$", | |
262 | "", | 262 | "", | |
263 | "BUILDLINK_TREE+=\t${LICENSE}-wxWidgets", | 263 | "BUILDLINK_TREE+=\t${LICENSE}-wxWidgets", | |
264 | "", | 264 | "", | |
265 | ".if !defined(LICENSE_BUILDLINK3_MK)", | 265 | ".if !defined(LICENSE_BUILDLINK3_MK)", | |
266 | "LICENSE_BUILDLINK3_MK:=", | 266 | "LICENSE_BUILDLINK3_MK:=", | |
267 | "", | 267 | "", | |
268 | "BUILDLINK_API_DEPENDS.${LICENSE}-wxWidgets+=\t${PYPKGPREFIX}-wxWidgets>=2.6.1.0", | 268 | "BUILDLINK_API_DEPENDS.${LICENSE}-wxWidgets+=\t${PYPKGPREFIX}-wxWidgets>=2.6.1.0", | |
269 | "BUILDLINK_ABI_DEPENDS.${LICENSE}-wxWidgets+=\t${PYPKGPREFIX}-wxWidgets>=2.8.10.1nb26", | 269 | "BUILDLINK_ABI_DEPENDS.${LICENSE}-wxWidgets+=\t${PYPKGPREFIX}-wxWidgets>=2.8.10.1nb26", | |
270 | "", | 270 | "", | |
271 | ".endif", | 271 | ".endif", |
@@ -27,29 +27,29 @@ func (exp *Expecter) EOF() bool { | @@ -27,29 +27,29 @@ func (exp *Expecter) EOF() bool { | |||
27 | return !(exp.index < len(exp.lines)) | 27 | return !(exp.index < len(exp.lines)) | |
28 | } | 28 | } | |
29 | 29 | |||
30 | func (exp *Expecter) Advance() bool { | 30 | func (exp *Expecter) Advance() bool { | |
31 | exp.index++ | 31 | exp.index++ | |
32 | exp.m = nil | 32 | exp.m = nil | |
33 | return true | 33 | return true | |
34 | } | 34 | } | |
35 | 35 | |||
36 | func (exp *Expecter) StepBack() { | 36 | func (exp *Expecter) StepBack() { | |
37 | exp.index-- | 37 | exp.index-- | |
38 | } | 38 | } | |
39 | 39 | |||
40 | func (exp *Expecter) AdvanceIfMatches(re string) bool { | 40 | func (exp *Expecter) AdvanceIfMatches(re RegexPattern) bool { | |
41 | if G.opts.Debug { | 41 | if G.opts.Debug { | |
42 | defer tracecall2(exp.CurrentLine().Text, re)() | 42 | defer tracecall(exp.CurrentLine().Text, re)() | |
43 | } | 43 | } | |
44 | 44 | |||
45 | if !exp.EOF() { | 45 | if !exp.EOF() { | |
46 | if m := match(exp.lines[exp.index].Text, re); m != nil { | 46 | if m := match(exp.lines[exp.index].Text, re); m != nil { | |
47 | exp.index++ | 47 | exp.index++ | |
48 | exp.m = m | 48 | exp.m = m | |
49 | return true | 49 | return true | |
50 | } | 50 | } | |
51 | } | 51 | } | |
52 | return false | 52 | return false | |
53 | } | 53 | } | |
54 | 54 | |||
55 | func (exp *Expecter) AdvanceIfPrefix(prefix string) bool { | 55 | func (exp *Expecter) AdvanceIfPrefix(prefix string) bool { |
@@ -1,88 +1,88 @@ | @@ -1,88 +1,88 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestMkopSubst_middle(c *check.C) { | 7 | func (s *Suite) Test_MkopSubst__middle(c *check.C) { | |
8 | c.Check(mkopSubst("pkgname", false, "kgna", false, "ri", ""), equals, "prime") | 8 | c.Check(mkopSubst("pkgname", false, "kgna", false, "ri", ""), equals, "prime") | |
9 | c.Check(mkopSubst("pkgname", false, "pkgname", false, "replacement", ""), equals, "replacement") | 9 | c.Check(mkopSubst("pkgname", false, "pkgname", false, "replacement", ""), equals, "replacement") | |
10 | } | 10 | } | |
11 | 11 | |||
12 | func (s *Suite) TestMkopSubst_left(c *check.C) { | 12 | func (s *Suite) Test_MkopSubst__left(c *check.C) { | |
13 | c.Check(mkopSubst("pkgname", true, "kgna", false, "ri", ""), equals, "pkgname") | 13 | c.Check(mkopSubst("pkgname", true, "kgna", false, "ri", ""), equals, "pkgname") | |
14 | c.Check(mkopSubst("pkgname", true, "pkgname", false, "replacement", ""), equals, "replacement") | 14 | c.Check(mkopSubst("pkgname", true, "pkgname", false, "replacement", ""), equals, "replacement") | |
15 | } | 15 | } | |
16 | 16 | |||
17 | func (s *Suite) TestMkopSubst_right(c *check.C) { | 17 | func (s *Suite) Test_MkopSubst__right(c *check.C) { | |
18 | c.Check(mkopSubst("pkgname", false, "kgna", true, "ri", ""), equals, "pkgname") | 18 | c.Check(mkopSubst("pkgname", false, "kgna", true, "ri", ""), equals, "pkgname") | |
19 | c.Check(mkopSubst("pkgname", false, "pkgname", true, "replacement", ""), equals, "replacement") | 19 | c.Check(mkopSubst("pkgname", false, "pkgname", true, "replacement", ""), equals, "replacement") | |
20 | } | 20 | } | |
21 | 21 | |||
22 | func (s *Suite) TestMkopSubst_leftRight(c *check.C) { | 22 | func (s *Suite) Test_MkopSubst__leftRight(c *check.C) { | |
23 | c.Check(mkopSubst("pkgname", true, "kgna", true, "ri", ""), equals, "pkgname") | 23 | c.Check(mkopSubst("pkgname", true, "kgna", true, "ri", ""), equals, "pkgname") | |
24 | c.Check(mkopSubst("pkgname", false, "pkgname", false, "replacement", ""), equals, "replacement") | 24 | c.Check(mkopSubst("pkgname", false, "pkgname", false, "replacement", ""), equals, "replacement") | |
25 | } | 25 | } | |
26 | 26 | |||
27 | func (s *Suite) TestMkopSubst_gflag(c *check.C) { | 27 | func (s *Suite) Test_MkopSubst__gflag(c *check.C) { | |
28 | c.Check(mkopSubst("aaaaa", false, "a", false, "b", "g"), equals, "bbbbb") | 28 | c.Check(mkopSubst("aaaaa", false, "a", false, "b", "g"), equals, "bbbbb") | |
29 | c.Check(mkopSubst("aaaaa", true, "a", false, "b", "g"), equals, "baaaa") | 29 | c.Check(mkopSubst("aaaaa", true, "a", false, "b", "g"), equals, "baaaa") | |
30 | c.Check(mkopSubst("aaaaa", false, "a", true, "b", "g"), equals, "aaaab") | 30 | c.Check(mkopSubst("aaaaa", false, "a", true, "b", "g"), equals, "aaaab") | |
31 | c.Check(mkopSubst("aaaaa", true, "a", true, "b", "g"), equals, "aaaaa") | 31 | c.Check(mkopSubst("aaaaa", true, "a", true, "b", "g"), equals, "aaaaa") | |
32 | } | 32 | } | |
33 | 33 | |||
34 | func (s *Suite) TestReplaceFirst(c *check.C) { | 34 | func (s *Suite) Test_replaceFirst(c *check.C) { | |
35 | m, rest := replaceFirst("a+b+c+d", `(\w)(.)(\w)`, "X") | 35 | m, rest := replaceFirst("a+b+c+d", `(\w)(.)(\w)`, "X") | |
36 | 36 | |||
37 | c.Assert(m, check.NotNil) | 37 | c.Assert(m, check.NotNil) | |
38 | c.Check(m, check.DeepEquals, []string{"a+b", "a", "+", "b"}) | 38 | c.Check(m, check.DeepEquals, []string{"a+b", "a", "+", "b"}) | |
39 | c.Check(rest, equals, "X+c+d") | 39 | c.Check(rest, equals, "X+c+d") | |
40 | } | 40 | } | |
41 | 41 | |||
42 | func (s *Suite) TestTabLength(c *check.C) { | 42 | func (s *Suite) Test_tabLength(c *check.C) { | |
43 | c.Check(tabLength("12345"), equals, 5) | 43 | c.Check(tabLength("12345"), equals, 5) | |
44 | c.Check(tabLength("\t"), equals, 8) | 44 | c.Check(tabLength("\t"), equals, 8) | |
45 | c.Check(tabLength("123\t"), equals, 8) | 45 | c.Check(tabLength("123\t"), equals, 8) | |
46 | c.Check(tabLength("1234567\t"), equals, 8) | 46 | c.Check(tabLength("1234567\t"), equals, 8) | |
47 | c.Check(tabLength("12345678\t"), equals, 16) | 47 | c.Check(tabLength("12345678\t"), equals, 16) | |
48 | } | 48 | } | |
49 | 49 | |||
50 | func (s *Suite) TestCleanpath(c *check.C) { | 50 | func (s *Suite) Test_cleanpath(c *check.C) { | |
51 | c.Check(cleanpath("simple/path"), equals, "simple/path") | 51 | c.Check(cleanpath("simple/path"), equals, "simple/path") | |
52 | c.Check(cleanpath("/absolute/path"), equals, "/absolute/path") | 52 | c.Check(cleanpath("/absolute/path"), equals, "/absolute/path") | |
53 | c.Check(cleanpath("./././."), equals, ".") | 53 | c.Check(cleanpath("./././."), equals, ".") | |
54 | c.Check(cleanpath("./././"), equals, ".") | 54 | c.Check(cleanpath("./././"), equals, ".") | |
55 | c.Check(cleanpath("dir/../dir/../dir/../dir/subdir/../../Makefile"), equals, "dir/../dir/../dir/../Makefile") | 55 | c.Check(cleanpath("dir/../dir/../dir/../dir/subdir/../../Makefile"), equals, "dir/../dir/../dir/../Makefile") | |
56 | c.Check(cleanpath("dir/multi/././/file"), equals, "dir/multi/file") | 56 | c.Check(cleanpath("dir/multi/././/file"), equals, "dir/multi/file") | |
57 | c.Check(cleanpath("111/222/../../333/444/../../555/666/../../777/888/9"), equals, "111/222/../../777/888/9") | 57 | c.Check(cleanpath("111/222/../../333/444/../../555/666/../../777/888/9"), equals, "111/222/../../777/888/9") | |
58 | c.Check(cleanpath("cat/pkg.v1/../../cat/pkg.v2/Makefile"), equals, "cat/pkg.v1/../../cat/pkg.v2/Makefile") | 58 | c.Check(cleanpath("cat/pkg.v1/../../cat/pkg.v2/Makefile"), equals, "cat/pkg.v1/../../cat/pkg.v2/Makefile") | |
59 | c.Check(cleanpath("dir/"), equals, "dir") | 59 | c.Check(cleanpath("dir/"), equals, "dir") | |
60 | } | 60 | } | |
61 | 61 | |||
62 | func (s *Suite) TestIsEmptyDirAndGetSubdirs(c *check.C) { | 62 | func (s *Suite) Test_isEmptyDir_and_getSubdirs(c *check.C) { | |
63 | s.CreateTmpFile(c, "CVS/Entries", "dummy\n") | 63 | s.CreateTmpFile(c, "CVS/Entries", "dummy\n") | |
64 | 64 | |||
65 | c.Check(isEmptyDir(s.tmpdir), equals, true) | 65 | c.Check(isEmptyDir(s.tmpdir), equals, true) | |
66 | c.Check(getSubdirs(s.tmpdir), check.DeepEquals, []string(nil)) | 66 | c.Check(getSubdirs(s.tmpdir), check.DeepEquals, []string(nil)) | |
67 | 67 | |||
68 | s.CreateTmpFile(c, "somedir/file", "") | 68 | s.CreateTmpFile(c, "somedir/file", "") | |
69 | 69 | |||
70 | c.Check(isEmptyDir(s.tmpdir), equals, false) | 70 | c.Check(isEmptyDir(s.tmpdir), equals, false) | |
71 | c.Check(getSubdirs(s.tmpdir), check.DeepEquals, []string{"somedir"}) | 71 | c.Check(getSubdirs(s.tmpdir), check.DeepEquals, []string{"somedir"}) | |
72 | 72 | |||
73 | if nodir := s.tmpdir + "/nonexistent"; true { | 73 | if nodir := s.tmpdir + "/nonexistent"; true { | |
74 | c.Check(isEmptyDir(nodir), equals, true) // Counts as empty. | 74 | c.Check(isEmptyDir(nodir), equals, true) // Counts as empty. | |
75 | defer s.ExpectFatalError(func() { | 75 | defer s.ExpectFatalError(func() { | |
76 | c.Check(s.Output(), check.Matches, `FATAL: (.+): Cannot be read: open (.+): (.+)\n`) | 76 | c.Check(s.Output(), check.Matches, `FATAL: (.+): Cannot be read: open (.+): (.+)\n`) | |
77 | }) | 77 | }) | |
78 | c.Check(getSubdirs(nodir), check.DeepEquals, []string(nil)) | 78 | c.Check(getSubdirs(nodir), check.DeepEquals, []string(nil)) | |
79 | c.FailNow() | 79 | c.FailNow() | |
80 | } | 80 | } | |
81 | } | 81 | } | |
82 | 82 | |||
83 | func (s *Suite) TestPrefixReplacer_Since(c *check.C) { | 83 | func (s *Suite) Test_PrefixReplacer_Since(c *check.C) { | |
84 | repl := NewPrefixReplacer("hello, world") | 84 | repl := NewPrefixReplacer("hello, world") | |
85 | mark := repl.Mark() | 85 | mark := repl.Mark() | |
86 | repl.AdvanceRegexp(`^\w+`) | 86 | repl.AdvanceRegexp(`^\w+`) | |
87 | c.Check(repl.Since(mark), equals, "hello") | 87 | c.Check(repl.Since(mark), equals, "hello") | |
88 | } | 88 | } |
@@ -1,20 +1,20 @@ | @@ -1,20 +1,20 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestCheckdirCategory_TotallyBroken(c *check.C) { | 7 | func (s *Suite) Test_CheckdirCategory_totally_broken(c *check.C) { | |
8 | G.globalData.InitVartypes() | 8 | G.globalData.InitVartypes() | |
9 | s.CreateTmpFile(c, "archivers/Makefile", ""+ | 9 | s.CreateTmpFile(c, "archivers/Makefile", ""+ | |
10 | "# $\n"+ | 10 | "# $\n"+ | |
11 | "SUBDIR+=pkg1\n"+ | 11 | "SUBDIR+=pkg1\n"+ | |
12 | "SUBDIR+=\u0020aaaaa\n"+ | 12 | "SUBDIR+=\u0020aaaaa\n"+ | |
13 | "SUBDIR-=unknown #doesn’t work\n"+ | 13 | "SUBDIR-=unknown #doesn’t work\n"+ | |
14 | "\n"+ | 14 | "\n"+ | |
15 | ".include \"../mk/category.mk\"\n") | 15 | ".include \"../mk/category.mk\"\n") | |
16 | 16 | |||
17 | G.CurrentDir = s.tmpdir + "/archivers" | 17 | G.CurrentDir = s.tmpdir + "/archivers" | |
18 | CheckdirCategory() | 18 | CheckdirCategory() | |
19 | 19 | |||
20 | c.Check(s.Output(), equals, ""+ | 20 | c.Check(s.Output(), equals, ""+ | |
@@ -23,27 +23,27 @@ func (s *Suite) TestCheckdirCategory_Tot | @@ -23,27 +23,27 @@ func (s *Suite) TestCheckdirCategory_Tot | |||
23 | "WARN: ~/archivers/Makefile:4: SUBDIR- is defined but not used. Spelling mistake?\n"+ | 23 | "WARN: ~/archivers/Makefile:4: SUBDIR- is defined but not used. Spelling mistake?\n"+ | |
24 | "ERROR: ~/archivers/Makefile:6: \"../mk/category.mk\" does not exist.\n"+ | 24 | "ERROR: ~/archivers/Makefile:6: \"../mk/category.mk\" does not exist.\n"+ | |
25 | "ERROR: ~/archivers/Makefile:2: COMMENT= line expected.\n"+ | 25 | "ERROR: ~/archivers/Makefile:2: COMMENT= line expected.\n"+ | |
26 | "WARN: ~/archivers/Makefile:2: Indentation should be a single tab character.\n"+ | 26 | "WARN: ~/archivers/Makefile:2: Indentation should be a single tab character.\n"+ | |
27 | "WARN: ~/archivers/Makefile:3: Indentation should be a single tab character.\n"+ | 27 | "WARN: ~/archivers/Makefile:3: Indentation should be a single tab character.\n"+ | |
28 | "WARN: ~/archivers/Makefile:3: \"aaaaa\" should come before \"pkg1\".\n"+ | 28 | "WARN: ~/archivers/Makefile:3: \"aaaaa\" should come before \"pkg1\".\n"+ | |
29 | "ERROR: ~/archivers/Makefile:4: SUBDIR+= line or empty line expected.\n"+ | 29 | "ERROR: ~/archivers/Makefile:4: SUBDIR+= line or empty line expected.\n"+ | |
30 | "ERROR: ~/archivers/Makefile:2: \"pkg1\" exists in the Makefile, but not in the file system.\n"+ | 30 | "ERROR: ~/archivers/Makefile:2: \"pkg1\" exists in the Makefile, but not in the file system.\n"+ | |
31 | "ERROR: ~/archivers/Makefile:3: \"aaaaa\" exists in the Makefile, but not in the file system.\n"+ | 31 | "ERROR: ~/archivers/Makefile:3: \"aaaaa\" exists in the Makefile, but not in the file system.\n"+ | |
32 | "WARN: ~/archivers/Makefile:4: This line should contain the following text: .include \"../mk/misc/category.mk\"\n"+ | 32 | "WARN: ~/archivers/Makefile:4: This line should contain the following text: .include \"../mk/misc/category.mk\"\n"+ | |
33 | "ERROR: ~/archivers/Makefile:4: The file should end here.\n") | 33 | "ERROR: ~/archivers/Makefile:4: The file should end here.\n") | |
34 | } | 34 | } | |
35 | 35 | |||
36 | func (s *Suite) TestCheckdirCategory_InvalidComment(c *check.C) { | 36 | func (s *Suite) Test_CheckdirCategory_invalid_comment(c *check.C) { | |
37 | G.globalData.InitVartypes() | 37 | G.globalData.InitVartypes() | |
38 | s.CreateTmpFile(c, "archivers/Makefile", ""+ | 38 | s.CreateTmpFile(c, "archivers/Makefile", ""+ | |
39 | "# $"+"NetBSD$\n"+ | 39 | "# $"+"NetBSD$\n"+ | |
40 | "COMMENT=\t\\Make $$$$ fast\"\n"+ | 40 | "COMMENT=\t\\Make $$$$ fast\"\n"+ | |
41 | "\n"+ | 41 | "\n"+ | |
42 | "SUBDIR+=\tpackage\n"+ | 42 | "SUBDIR+=\tpackage\n"+ | |
43 | "\n"+ | 43 | "\n"+ | |
44 | ".include \"../mk/misc/category.mk\"\n") | 44 | ".include \"../mk/misc/category.mk\"\n") | |
45 | s.CreateTmpFile(c, "archivers/package/Makefile", "# dummy\n") | 45 | s.CreateTmpFile(c, "archivers/package/Makefile", "# dummy\n") | |
46 | s.CreateTmpFile(c, "mk/misc/category.mk", "# dummy\n") | 46 | s.CreateTmpFile(c, "mk/misc/category.mk", "# dummy\n") | |
47 | G.CurrentDir = s.tmpdir + "/archivers" | 47 | G.CurrentDir = s.tmpdir + "/archivers" | |
48 | G.CurPkgsrcdir = ".." | 48 | G.CurPkgsrcdir = ".." | |
49 | 49 |
@@ -1,28 +1,28 @@ | @@ -1,28 +1,28 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestCheckDirent_outside(c *check.C) { | 7 | func (s *Suite) Test_CheckDirent_outside(c *check.C) { | |
8 | s.CreateTmpFile(c, "empty", "") | 8 | s.CreateTmpFile(c, "empty", "") | |
9 | 9 | |||
10 | CheckDirent(s.tmpdir) | 10 | CheckDirent(s.tmpdir) | |
11 | 11 | |||
12 | c.Check(s.Output(), equals, "ERROR: ~: Cannot determine the pkgsrc root directory for \"~\".\n") | 12 | c.Check(s.Output(), equals, "ERROR: ~: Cannot determine the pkgsrc root directory for \"~\".\n") | |
13 | } | 13 | } | |
14 | 14 | |||
15 | func (s *Suite) TestCheckDirent(c *check.C) { | 15 | func (s *Suite) Test_CheckDirent(c *check.C) { | |
16 | s.CreateTmpFile(c, "mk/bsd.pkg.mk", "") | 16 | s.CreateTmpFile(c, "mk/bsd.pkg.mk", "") | |
17 | s.CreateTmpFile(c, "category/package/Makefile", "") | 17 | s.CreateTmpFile(c, "category/package/Makefile", "") | |
18 | s.CreateTmpFile(c, "category/Makefile", "") | 18 | s.CreateTmpFile(c, "category/Makefile", "") | |
19 | s.CreateTmpFile(c, "Makefile", "") | 19 | s.CreateTmpFile(c, "Makefile", "") | |
20 | G.globalData.Pkgsrcdir = s.tmpdir | 20 | G.globalData.Pkgsrcdir = s.tmpdir | |
21 | 21 | |||
22 | CheckDirent(s.tmpdir) | 22 | CheckDirent(s.tmpdir) | |
23 | 23 | |||
24 | c.Check(s.Output(), equals, "ERROR: ~/Makefile: Must not be empty.\n") | 24 | c.Check(s.Output(), equals, "ERROR: ~/Makefile: Must not be empty.\n") | |
25 | 25 | |||
26 | CheckDirent(s.tmpdir + "/category") | 26 | CheckDirent(s.tmpdir + "/category") | |
27 | 27 | |||
28 | c.Check(s.Output(), equals, "ERROR: ~/category/Makefile: Must not be empty.\n") | 28 | c.Check(s.Output(), equals, "ERROR: ~/category/Makefile: Must not be empty.\n") |
@@ -1,40 +1,40 @@ | @@ -1,40 +1,40 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | "os" | 4 | "os" | |
5 | 5 | |||
6 | check "gopkg.in/check.v1" | 6 | check "gopkg.in/check.v1" | |
7 | ) | 7 | ) | |
8 | 8 | |||
9 | func (s *Suite) TestMainHelp(c *check.C) { | 9 | func (s *Suite) Test_Pkglint_Main_help(c *check.C) { | |
10 | exitcode := new(Pkglint).Main("pkglint", "-h") | 10 | exitcode := new(Pkglint).Main("pkglint", "-h") | |
11 | 11 | |||
12 | c.Check(exitcode, equals, 0) | 12 | c.Check(exitcode, equals, 0) | |
13 | c.Check(s.Output(), check.Matches, `^\Qusage: pkglint [options] dir...\E\n(?s).+`) | 13 | c.Check(s.Output(), check.Matches, `^\Qusage: pkglint [options] dir...\E\n(?s).+`) | |
14 | } | 14 | } | |
15 | 15 | |||
16 | func (s *Suite) TestMainVersion(c *check.C) { | 16 | func (s *Suite) Test_Pkglint_Main_version(c *check.C) { | |
17 | exitcode := new(Pkglint).Main("pkglint", "--version") | 17 | exitcode := new(Pkglint).Main("pkglint", "--version") | |
18 | 18 | |||
19 | c.Check(exitcode, equals, 0) | 19 | c.Check(exitcode, equals, 0) | |
20 | c.Check(s.Output(), equals, confVersion+"\n") | 20 | c.Check(s.Output(), equals, confVersion+"\n") | |
21 | } | 21 | } | |
22 | 22 | |||
23 | func (s *Suite) TestMainNoArgs(c *check.C) { | 23 | func (s *Suite) Test_Pkglint_Main_no_args(c *check.C) { | |
24 | exitcode := new(Pkglint).Main("pkglint") | 24 | exitcode := new(Pkglint).Main("pkglint") | |
25 | 25 | |||
26 | c.Check(exitcode, equals, 1) | 26 | c.Check(exitcode, equals, 1) | |
27 | c.Check(s.Stderr(), equals, "FATAL: \".\" is not inside a pkgsrc tree.\n") | 27 | c.Check(s.Stderr(), equals, "FATAL: \".\" is not inside a pkgsrc tree.\n") | |
28 | } | 28 | } | |
29 | 29 | |||
30 | // go test -c -covermode count | 30 | // go test -c -covermode count | |
31 | // pkgsrcdir=... | 31 | // pkgsrcdir=... | |
32 | // env PKGLINT_TESTCMDLINE="$pkgsrcdir -r" ./pkglint.test -test.coverprofile pkglint.cov -check.f TestRunPkglint | 32 | // env PKGLINT_TESTCMDLINE="$pkgsrcdir -r" ./pkglint.test -test.coverprofile pkglint.cov -check.f TestRunPkglint | |
33 | // go tool cover -html=pkglint.cov -o coverage.html | 33 | // go tool cover -html=pkglint.cov -o coverage.html | |
34 | func (s *Suite) TestRunPkglint(c *check.C) { | 34 | func (s *Suite) Test_Pkglint_coverage(c *check.C) { | |
35 | cmdline := os.Getenv("PKGLINT_TESTCMDLINE") | 35 | cmdline := os.Getenv("PKGLINT_TESTCMDLINE") | |
36 | if cmdline != "" { | 36 | if cmdline != "" { | |
37 | G.logOut, G.logErr, G.debugOut = os.Stdout, os.Stderr, os.Stdout | 37 | G.logOut, G.logErr, G.debugOut = os.Stdout, os.Stderr, os.Stdout | |
38 | new(Pkglint).Main(append([]string{"pkglint"}, splitOnSpace(cmdline)...)...) | 38 | new(Pkglint).Main(append([]string{"pkglint"}, splitOnSpace(cmdline)...)...) | |
39 | } | 39 | } | |
40 | } | 40 | } |
@@ -57,27 +57,27 @@ func (p *MkParser) VarUse() *MkVarUse { | @@ -57,27 +57,27 @@ func (p *MkParser) VarUse() *MkVarUse { | |||
57 | 57 | |||
58 | varnameMark := repl.Mark() | 58 | varnameMark := repl.Mark() | |
59 | varname := p.Varname() | 59 | varname := p.Varname() | |
60 | if varname != "" { | 60 | if varname != "" { | |
61 | if usingRoundParen && p.EmitWarnings { | 61 | if usingRoundParen && p.EmitWarnings { | |
62 | p.Line.Warn1("Please use curly braces {} instead of round parentheses () for %s.", varname) | 62 | p.Line.Warn1("Please use curly braces {} instead of round parentheses () for %s.", varname) | |
63 | } | 63 | } | |
64 | modifiers := p.VarUseModifiers(varname, closing) | 64 | modifiers := p.VarUseModifiers(varname, closing) | |
65 | if repl.AdvanceStr(closing) { | 65 | if repl.AdvanceStr(closing) { | |
66 | return &MkVarUse{varname, modifiers} | 66 | return &MkVarUse{varname, modifiers} | |
67 | } | 67 | } | |
68 | } | 68 | } | |
69 | 69 | |||
70 | for p.VarUse() != nil || repl.AdvanceRegexp(`^([^$:`+closing+`]|\$\$)+`) { | 70 | for p.VarUse() != nil || repl.AdvanceRegexp(RegexPattern(`^([^$:`+closing+`]|\$\$)+`)) { | |
71 | } | 71 | } | |
72 | rest := p.Rest() | 72 | rest := p.Rest() | |
73 | if hasPrefix(rest, ":L") || hasPrefix(rest, ":?") { | 73 | if hasPrefix(rest, ":L") || hasPrefix(rest, ":?") { | |
74 | varexpr := repl.Since(varnameMark) | 74 | varexpr := repl.Since(varnameMark) | |
75 | modifiers := p.VarUseModifiers(varexpr, closing) | 75 | modifiers := p.VarUseModifiers(varexpr, closing) | |
76 | if repl.AdvanceStr(closing) { | 76 | if repl.AdvanceStr(closing) { | |
77 | return &MkVarUse{varexpr, modifiers} | 77 | return &MkVarUse{varexpr, modifiers} | |
78 | } | 78 | } | |
79 | } | 79 | } | |
80 | repl.Reset(mark) | 80 | repl.Reset(mark) | |
81 | } | 81 | } | |
82 | 82 | |||
83 | if repl.AdvanceStr("$@") { | 83 | if repl.AdvanceStr("$@") { | |
@@ -116,85 +116,85 @@ func (p *MkParser) VarUseModifiers(varna | @@ -116,85 +116,85 @@ func (p *MkParser) VarUseModifiers(varna | |||
116 | if len(rest) >= 2 && (rest[1] == closing[0] || rest[1] == ':') { | 116 | if len(rest) >= 2 && (rest[1] == closing[0] || rest[1] == ':') { | |
117 | repl.Skip(1) | 117 | repl.Skip(1) | |
118 | } else if len(rest) >= 1 && (rest[0] == closing[0] || rest[0] == ':') { | 118 | } else if len(rest) >= 1 && (rest[0] == closing[0] || rest[0] == ':') { | |
119 | } else if repl.AdvanceRegexp(`^\\\d+`) { | 119 | } else if repl.AdvanceRegexp(`^\\\d+`) { | |
120 | } else { | 120 | } else { | |
121 | break | 121 | break | |
122 | } | 122 | } | |
123 | modifiers = append(modifiers, repl.Since(modifierMark)) | 123 | modifiers = append(modifiers, repl.Since(modifierMark)) | |
124 | continue | 124 | continue | |
125 | } | 125 | } | |
126 | 126 | |||
127 | case '=', 'D', 'M', 'N', 'U': | 127 | case '=', 'D', 'M', 'N', 'U': | |
128 | if repl.AdvanceRegexp(`^[=DMNU]`) { | 128 | if repl.AdvanceRegexp(`^[=DMNU]`) { | |
129 | for p.VarUse() != nil || repl.AdvanceRegexp(`^([^$:`+closing+`]|\$\$)+`) { | 129 | for p.VarUse() != nil || repl.AdvanceRegexp(RegexPattern(`^([^$:`+closing+`]|\$\$)+`)) { | |
130 | } | 130 | } | |
131 | modifiers = append(modifiers, repl.Since(modifierMark)) | 131 | modifiers = append(modifiers, repl.Since(modifierMark)) | |
132 | continue | 132 | continue | |
133 | } | 133 | } | |
134 | 134 | |||
135 | case 'C', 'S': | 135 | case 'C', 'S': | |
136 | if repl.AdvanceRegexp(`^[CS]([%,/:;@^|])`) { | 136 | if repl.AdvanceRegexp(`^[CS]([%,/:;@^|])`) { | |
137 | separator := repl.m[1] | 137 | separator := repl.m[1] | |
138 | repl.AdvanceStr("^") | 138 | repl.AdvanceStr("^") | |
139 | re := `^([^\` + separator + `$` + closing + `\\]|\$\$|\\.)+` | 139 | re := RegexPattern(`^([^\` + separator + `$` + closing + `\\]|\$\$|\\.)+`) | |
140 | for p.VarUse() != nil || repl.AdvanceRegexp(re) { | 140 | for p.VarUse() != nil || repl.AdvanceRegexp(re) { | |
141 | } | 141 | } | |
142 | repl.AdvanceStr("$") | 142 | repl.AdvanceStr("$") | |
143 | if repl.AdvanceStr(separator) { | 143 | if repl.AdvanceStr(separator) { | |
144 | for p.VarUse() != nil || repl.AdvanceRegexp(re) { | 144 | for p.VarUse() != nil || repl.AdvanceRegexp(re) { | |
145 | } | 145 | } | |
146 | if repl.AdvanceStr(separator) { | 146 | if repl.AdvanceStr(separator) { | |
147 | repl.AdvanceRegexp(`^[1gW]`) | 147 | repl.AdvanceRegexp(`^[1gW]`) | |
148 | modifiers = append(modifiers, repl.Since(modifierMark)) | 148 | modifiers = append(modifiers, repl.Since(modifierMark)) | |
149 | mayOmitColon = true | 149 | mayOmitColon = true | |
150 | continue | 150 | continue | |
151 | } | 151 | } | |
152 | } | 152 | } | |
153 | } | 153 | } | |
154 | 154 | |||
155 | case '@': | 155 | case '@': | |
156 | if repl.AdvanceRegexp(`^@([\w.]+)@`) { | 156 | if repl.AdvanceRegexp(`^@([\w.]+)@`) { | |
157 | loopvar := repl.m[1] | 157 | loopvar := repl.m[1] | |
158 | for p.VarUse() != nil || repl.AdvanceRegexp(`^([^$:@`+closing+`\\]|\$\$|\\.)+`) { | 158 | for p.VarUse() != nil || repl.AdvanceRegexp(RegexPattern(`^([^$:@`+closing+`\\]|\$\$|\\.)+`)) { | |
159 | } | 159 | } | |
160 | if !repl.AdvanceStr("@") && p.EmitWarnings { | 160 | if !repl.AdvanceStr("@") && p.EmitWarnings { | |
161 | p.Line.Warn2("Modifier ${%s:@%s@...@} is missing the final \"@\".", varname, loopvar) | 161 | p.Line.Warn2("Modifier ${%s:@%s@...@} is missing the final \"@\".", varname, loopvar) | |
162 | } | 162 | } | |
163 | modifiers = append(modifiers, repl.Since(modifierMark)) | 163 | modifiers = append(modifiers, repl.Since(modifierMark)) | |
164 | continue | 164 | continue | |
165 | } | 165 | } | |
166 | 166 | |||
167 | case '[': | 167 | case '[': | |
168 | if repl.AdvanceRegexp(`^\[[-.\d]+\]`) { | 168 | if repl.AdvanceRegexp(`^\[[-.\d]+\]`) { | |
169 | modifiers = append(modifiers, repl.Since(modifierMark)) | 169 | modifiers = append(modifiers, repl.Since(modifierMark)) | |
170 | continue | 170 | continue | |
171 | } | 171 | } | |
172 | 172 | |||
173 | case '?': | 173 | case '?': | |
174 | repl.AdvanceStr("?") | 174 | repl.AdvanceStr("?") | |
175 | re := `^([^$:` + closing + `]|\$\$)+` | 175 | re := RegexPattern(`^([^$:` + closing + `]|\$\$)+`) | |
176 | for p.VarUse() != nil || repl.AdvanceRegexp(re) { | 176 | for p.VarUse() != nil || repl.AdvanceRegexp(re) { | |
177 | } | 177 | } | |
178 | if repl.AdvanceStr(":") { | 178 | if repl.AdvanceStr(":") { | |
179 | for p.VarUse() != nil || repl.AdvanceRegexp(re) { | 179 | for p.VarUse() != nil || repl.AdvanceRegexp(re) { | |
180 | } | 180 | } | |
181 | modifiers = append(modifiers, repl.Since(modifierMark)) | 181 | modifiers = append(modifiers, repl.Since(modifierMark)) | |
182 | continue | 182 | continue | |
183 | } | 183 | } | |
184 | } | 184 | } | |
185 | 185 | |||
186 | repl.Reset(modifierMark) | 186 | repl.Reset(modifierMark) | |
187 | for p.VarUse() != nil || repl.AdvanceRegexp(`^([^:$`+closing+`]|\$\$)+`) { | 187 | for p.VarUse() != nil || repl.AdvanceRegexp(RegexPattern(`^([^:$`+closing+`]|\$\$)+`)) { | |
188 | } | 188 | } | |
189 | if suffixSubst := repl.Since(modifierMark); contains(suffixSubst, "=") { | 189 | if suffixSubst := repl.Since(modifierMark); contains(suffixSubst, "=") { | |
190 | modifiers = append(modifiers, suffixSubst) | 190 | modifiers = append(modifiers, suffixSubst) | |
191 | continue | 191 | continue | |
192 | } | 192 | } | |
193 | } | 193 | } | |
194 | return modifiers | 194 | return modifiers | |
195 | } | 195 | } | |
196 | 196 | |||
197 | func (p *MkParser) MkCond() *Tree { | 197 | func (p *MkParser) MkCond() *Tree { | |
198 | return p.mkCondOr() | 198 | return p.mkCondOr() | |
199 | } | 199 | } | |
200 | 200 |
@@ -134,27 +134,27 @@ type StrCommand struct { | @@ -134,27 +134,27 @@ type StrCommand struct { | |||
134 | Name string | 134 | Name string | |
135 | Args []string | 135 | Args []string | |
136 | } | 136 | } | |
137 | 137 | |||
138 | func (c *StrCommand) HasOption(opt string) bool { | 138 | func (c *StrCommand) HasOption(opt string) bool { | |
139 | for _, arg := range c.Args { | 139 | for _, arg := range c.Args { | |
140 | if arg == opt { | 140 | if arg == opt { | |
141 | return true | 141 | return true | |
142 | } | 142 | } | |
143 | } | 143 | } | |
144 | return false | 144 | return false | |
145 | } | 145 | } | |
146 | 146 | |||
147 | func (c *StrCommand) AnyArgMatches(pattern string) bool { | 147 | func (c *StrCommand) AnyArgMatches(pattern RegexPattern) bool { | |
148 | for _, arg := range c.Args { | 148 | for _, arg := range c.Args { | |
149 | if matches(arg, pattern) { | 149 | if matches(arg, pattern) { | |
150 | return true | 150 | return true | |
151 | } | 151 | } | |
152 | } | 152 | } | |
153 | return false | 153 | return false | |
154 | } | 154 | } | |
155 | 155 | |||
156 | func (c *StrCommand) String() string { | 156 | func (c *StrCommand) String() string { | |
157 | return fmt.Sprintf("%v %v %v", c.Assignments, c.Name, c.Args) | 157 | return fmt.Sprintf("%v %v %v", c.Assignments, c.Name, c.Args) | |
158 | } | 158 | } | |
159 | 159 | |||
160 | type MkShRedirection struct { | 160 | type MkShRedirection struct { |
@@ -48,57 +48,40 @@ func (p *ShTokenizer) ShAtom(quoting ShQ | @@ -48,57 +48,40 @@ func (p *ShTokenizer) ShAtom(quoting ShQ | |||
48 | atom = p.shAtomDquotBacktDquot() | 48 | atom = p.shAtomDquotBacktDquot() | |
49 | case shqDquotBacktSquot: | 49 | case shqDquotBacktSquot: | |
50 | atom = p.shAtomDquotBacktSquot() | 50 | atom = p.shAtomDquotBacktSquot() | |
51 | } | 51 | } | |
52 | 52 | |||
53 | if atom == nil { | 53 | if atom == nil { | |
54 | repl.Reset(mark) | 54 | repl.Reset(mark) | |
55 | p.parser.Line.Warnf("Pkglint parse error in ShTokenizer.ShAtom at %q (quoting=%s)", repl.rest, quoting) | 55 | p.parser.Line.Warnf("Pkglint parse error in ShTokenizer.ShAtom at %q (quoting=%s)", repl.rest, quoting) | |
56 | } | 56 | } | |
57 | return atom | 57 | return atom | |
58 | } | 58 | } | |
59 | 59 | |||
60 | func (p *ShTokenizer) shAtomPlain() *ShAtom { | 60 | func (p *ShTokenizer) shAtomPlain() *ShAtom { | |
61 | q := shqPlain | 61 | const q = shqPlain | |
62 | if op := p.shOperator(q); op != nil { | |||
63 | return op | |||
64 | } | |||
62 | repl := p.parser.repl | 65 | repl := p.parser.repl | |
63 | switch { | 66 | switch { | |
64 | case repl.AdvanceHspace(): | 67 | case repl.AdvanceHspace(): | |
65 | return &ShAtom{shtSpace, repl.s, q, nil} | 68 | return &ShAtom{shtSpace, repl.s, q, nil} | |
66 | case repl.AdvanceStr("\n"): | |||
67 | return &ShAtom{shtNewline, repl.s, q, nil} | |||
68 | case repl.AdvanceStr(";;"): | |||
69 | return &ShAtom{shtCaseSeparator, repl.s, q, nil} | |||
70 | case repl.AdvanceStr(";"): | |||
71 | return &ShAtom{shtSemicolon, repl.s, q, nil} | |||
72 | case repl.AdvanceStr("("): | |||
73 | return &ShAtom{shtParenOpen, repl.s, q, nil} | |||
74 | case repl.AdvanceStr(")"): | |||
75 | return &ShAtom{shtParenClose, repl.s, q, nil} | |||
76 | case repl.AdvanceStr("||"): | |||
77 | return &ShAtom{shtOr, repl.s, q, nil} | |||
78 | case repl.AdvanceStr("&&"): | |||
79 | return &ShAtom{shtAnd, repl.s, q, nil} | |||
80 | case repl.AdvanceStr("|"): | |||
81 | return &ShAtom{shtPipe, repl.s, q, nil} | |||
82 | case repl.AdvanceStr("&"): | |||
83 | return &ShAtom{shtBackground, repl.s, q, nil} | |||
84 | case repl.AdvanceStr("\""): | 69 | case repl.AdvanceStr("\""): | |
85 | return &ShAtom{shtWord, repl.s, shqDquot, nil} | 70 | return &ShAtom{shtWord, repl.s, shqDquot, nil} | |
86 | case repl.AdvanceStr("'"): | 71 | case repl.AdvanceStr("'"): | |
87 | return &ShAtom{shtWord, repl.s, shqSquot, nil} | 72 | return &ShAtom{shtWord, repl.s, shqSquot, nil} | |
88 | case repl.AdvanceStr("`"): | 73 | case repl.AdvanceStr("`"): | |
89 | return &ShAtom{shtWord, repl.s, shqBackt, nil} | 74 | return &ShAtom{shtWord, repl.s, shqBackt, nil} | |
90 | case repl.AdvanceRegexp(`^\d*(?:<<-|<<|<&|<>|>>|>&|>\||<|>)`): | |||
91 | return &ShAtom{shtRedirect, repl.m[0], q, nil} | |||
92 | case repl.AdvanceRegexp(`^#.*`): | 75 | case repl.AdvanceRegexp(`^#.*`): | |
93 | return &ShAtom{shtComment, repl.m[0], q, nil} | 76 | return &ShAtom{shtComment, repl.m[0], q, nil} | |
94 | case repl.AdvanceStr("$$("): | 77 | case repl.AdvanceStr("$$("): | |
95 | return &ShAtom{shtSubshell, repl.s, q, nil} | 78 | return &ShAtom{shtSubshell, repl.s, q, nil} | |
96 | case repl.AdvanceRegexp(`^(?:[!#%*+,\-./0-9:=?@A-Z\[\]^_a-z{}~]+|\\[^$]|` + reShDollar + `)+`): | 79 | case repl.AdvanceRegexp(`^(?:[!#%*+,\-./0-9:=?@A-Z\[\]^_a-z{}~]+|\\[^$]|` + reShDollar + `)+`): | |
97 | return &ShAtom{shtWord, repl.m[0], q, nil} | 80 | return &ShAtom{shtWord, repl.m[0], q, nil} | |
98 | } | 81 | } | |
99 | return nil | 82 | return nil | |
100 | } | 83 | } | |
101 | 84 | |||
102 | func (p *ShTokenizer) shAtomDquot() *ShAtom { | 85 | func (p *ShTokenizer) shAtomDquot() *ShAtom { | |
103 | repl := p.parser.repl | 86 | repl := p.parser.repl | |
104 | switch { | 87 | switch { | |
@@ -115,132 +98,91 @@ func (p *ShTokenizer) shAtomDquot() *ShA | @@ -115,132 +98,91 @@ func (p *ShTokenizer) shAtomDquot() *ShA | |||
115 | func (p *ShTokenizer) shAtomSquot() *ShAtom { | 98 | func (p *ShTokenizer) shAtomSquot() *ShAtom { | |
116 | repl := p.parser.repl | 99 | repl := p.parser.repl | |
117 | switch { | 100 | switch { | |
118 | case repl.AdvanceStr("'"): | 101 | case repl.AdvanceStr("'"): | |
119 | return &ShAtom{shtWord, repl.s, shqPlain, nil} | 102 | return &ShAtom{shtWord, repl.s, shqPlain, nil} | |
120 | case repl.AdvanceRegexp(`^([\t !"#%&()*+,\-./0-9:;<=>?@A-Z\[\\\]^_` + "`" + `a-z{|}~]+|\$\$)+`): | 103 | case repl.AdvanceRegexp(`^([\t !"#%&()*+,\-./0-9:;<=>?@A-Z\[\\\]^_` + "`" + `a-z{|}~]+|\$\$)+`): | |
121 | return &ShAtom{shtWord, repl.m[0], shqSquot, nil} | 104 | return &ShAtom{shtWord, repl.m[0], shqSquot, nil} | |
122 | } | 105 | } | |
123 | return nil | 106 | return nil | |
124 | } | 107 | } | |
125 | 108 | |||
126 | func (p *ShTokenizer) shAtomBackt() *ShAtom { | 109 | func (p *ShTokenizer) shAtomBackt() *ShAtom { | |
127 | const q = shqBackt | 110 | const q = shqBackt | |
111 | if op := p.shOperator(q); op != nil { | |||
112 | return op | |||
113 | } | |||
128 | repl := p.parser.repl | 114 | repl := p.parser.repl | |
129 | switch { | 115 | switch { | |
130 | case repl.AdvanceStr("\""): | 116 | case repl.AdvanceStr("\""): | |
131 | return &ShAtom{shtWord, repl.s, shqBacktDquot, nil} | 117 | return &ShAtom{shtWord, repl.s, shqBacktDquot, nil} | |
132 | case repl.AdvanceStr("`"): | 118 | case repl.AdvanceStr("`"): | |
133 | return &ShAtom{shtWord, repl.s, shqPlain, nil} | 119 | return &ShAtom{shtWord, repl.s, shqPlain, nil} | |
134 | case repl.AdvanceStr("'"): | 120 | case repl.AdvanceStr("'"): | |
135 | return &ShAtom{shtWord, repl.s, shqBacktSquot, nil} | 121 | return &ShAtom{shtWord, repl.s, shqBacktSquot, nil} | |
136 | case repl.AdvanceHspace(): | 122 | case repl.AdvanceHspace(): | |
137 | return &ShAtom{shtSpace, repl.s, q, nil} | 123 | return &ShAtom{shtSpace, repl.s, q, nil} | |
138 | case repl.AdvanceStr(";;"): | |||
139 | return &ShAtom{shtCaseSeparator, repl.s, q, nil} | |||
140 | case repl.AdvanceStr(";"): | |||
141 | return &ShAtom{shtSemicolon, repl.s, q, nil} | |||
142 | case repl.AdvanceStr("("): | |||
143 | return &ShAtom{shtParenOpen, repl.s, q, nil} | |||
144 | case repl.AdvanceStr(")"): | |||
145 | return &ShAtom{shtParenClose, repl.s, q, nil} | |||
146 | case repl.AdvanceStr("||"): | |||
147 | return &ShAtom{shtOr, repl.s, q, nil} | |||
148 | case repl.AdvanceStr("&&"): | |||
149 | return &ShAtom{shtAnd, repl.s, q, nil} | |||
150 | case repl.AdvanceStr("|"): | |||
151 | return &ShAtom{shtPipe, repl.s, q, nil} | |||
152 | case repl.AdvanceStr("&"): | |||
153 | return &ShAtom{shtBackground, repl.s, q, nil} | |||
154 | case repl.AdvanceRegexp(`^(?:<|<<|>|>>|>&)`): | |||
155 | return &ShAtom{shtRedirect, repl.s, q, nil} | |||
156 | case repl.AdvanceRegexp("^#[^`]*"): | 124 | case repl.AdvanceRegexp("^#[^`]*"): | |
157 | return &ShAtom{shtComment, repl.s, q, nil} | 125 | return &ShAtom{shtComment, repl.s, q, nil} | |
158 | case repl.AdvanceRegexp(`^(?:[!#%*+,\-./0-9:=?@A-Z\[\]_a-z~]+|\\[^$]|` + reShDollar + `)+`): | 126 | case repl.AdvanceRegexp(`^(?:[!#%*+,\-./0-9:=?@A-Z\[\]_a-z~]+|\\[^$]|` + reShDollar + `)+`): | |
159 | return &ShAtom{shtWord, repl.s, q, nil} | 127 | return &ShAtom{shtWord, repl.s, q, nil} | |
160 | } | 128 | } | |
161 | return nil | 129 | return nil | |
162 | } | 130 | } | |
163 | 131 | |||
164 | func (p *ShTokenizer) shAtomSub() *ShAtom { | 132 | func (p *ShTokenizer) shAtomSub() *ShAtom { | |
165 | const q = shqSubsh | 133 | const q = shqSubsh | |
134 | if op := p.shOperator(q); op != nil { | |||
135 | return op | |||
136 | } | |||
166 | repl := p.parser.repl | 137 | repl := p.parser.repl | |
167 | mark := repl.Mark() | 138 | mark := repl.Mark() | |
168 | atom := func(typ ShAtomType) *ShAtom { | 139 | atom := func(typ ShAtomType) *ShAtom { | |
169 | return NewShAtom(typ, repl.Since(mark), shqSubsh) | 140 | return NewShAtom(typ, repl.Since(mark), shqSubsh) | |
170 | } | 141 | } | |
171 | switch { | 142 | switch { | |
172 | case repl.AdvanceHspace(): | 143 | case repl.AdvanceHspace(): | |
173 | return atom(shtSpace) | 144 | return atom(shtSpace) | |
174 | case repl.AdvanceStr(";;"): | |||
175 | return atom(shtCaseSeparator) | |||
176 | case repl.AdvanceStr(";"): | |||
177 | return atom(shtSemicolon) | |||
178 | case repl.AdvanceStr("||"): | |||
179 | return atom(shtOr) | |||
180 | case repl.AdvanceStr("&&"): | |||
181 | return atom(shtAnd) | |||
182 | case repl.AdvanceStr("|"): | |||
183 | return atom(shtPipe) | |||
184 | case repl.AdvanceStr("&"): | |||
185 | return atom(shtBackground) | |||
186 | case repl.AdvanceStr("\""): | 145 | case repl.AdvanceStr("\""): | |
187 | //return &ShAtom{shtWord, repl.s, shqDquot, nil} | 146 | //return &ShAtom{shtWord, repl.s, shqDquot, nil} | |
188 | case repl.AdvanceStr("'"): | 147 | case repl.AdvanceStr("'"): | |
189 | return &ShAtom{shtWord, repl.s, shqSubshSquot, nil} | 148 | return &ShAtom{shtWord, repl.s, shqSubshSquot, nil} | |
190 | case repl.AdvanceStr("`"): | 149 | case repl.AdvanceStr("`"): | |
191 | //return &ShAtom{shtWord, repl.s, shqBackt, nil} | 150 | //return &ShAtom{shtWord, repl.s, shqBackt, nil} | |
192 | case repl.AdvanceRegexp(`^\d*(?:<<-|<<|<&|<>|>>|>&|>\||<|>)`): | |||
193 | return &ShAtom{shtRedirect, repl.m[0], q, nil} | |||
194 | case repl.AdvanceRegexp(`^#.*`): | 151 | case repl.AdvanceRegexp(`^#.*`): | |
195 | return &ShAtom{shtComment, repl.m[0], q, nil} | 152 | return &ShAtom{shtComment, repl.m[0], q, nil} | |
196 | case repl.AdvanceStr(")"): | 153 | case repl.AdvanceStr(")"): | |
197 | return NewShAtom(shtWord, repl.s, shqPlain) | 154 | return NewShAtom(shtWord, repl.s, shqPlain) | |
198 | case repl.AdvanceRegexp(`^(?:[!#%*+,\-./0-9:=?@A-Z\[\]^_a-z{}~]+|\\[^$]|` + reShDollar + `)+`): | 155 | case repl.AdvanceRegexp(`^(?:[!#%*+,\-./0-9:=?@A-Z\[\]^_a-z{}~]+|\\[^$]|` + reShDollar + `)+`): | |
199 | return &ShAtom{shtWord, repl.m[0], q, nil} | 156 | return &ShAtom{shtWord, repl.m[0], q, nil} | |
200 | } | 157 | } | |
201 | return nil | 158 | return nil | |
202 | } | 159 | } | |
203 | 160 | |||
204 | func (p *ShTokenizer) shAtomDquotBackt() *ShAtom { | 161 | func (p *ShTokenizer) shAtomDquotBackt() *ShAtom { | |
205 | const q = shqDquotBackt | 162 | const q = shqDquotBackt | |
163 | if op := p.shOperator(q); op != nil { | |||
164 | return op | |||
165 | } | |||
206 | repl := p.parser.repl | 166 | repl := p.parser.repl | |
207 | switch { | 167 | switch { | |
208 | case repl.AdvanceStr("`"): | 168 | case repl.AdvanceStr("`"): | |
209 | return &ShAtom{shtWord, repl.s, shqDquot, nil} | 169 | return &ShAtom{shtWord, repl.s, shqDquot, nil} | |
210 | case repl.AdvanceStr("\""): | 170 | case repl.AdvanceStr("\""): | |
211 | return &ShAtom{shtWord, repl.s, shqDquotBacktDquot, nil} | 171 | return &ShAtom{shtWord, repl.s, shqDquotBacktDquot, nil} | |
212 | case repl.AdvanceStr("'"): | 172 | case repl.AdvanceStr("'"): | |
213 | return &ShAtom{shtWord, repl.s, shqDquotBacktSquot, nil} | 173 | return &ShAtom{shtWord, repl.s, shqDquotBacktSquot, nil} | |
214 | case repl.AdvanceRegexp("^#[^`]*"): | 174 | case repl.AdvanceRegexp("^#[^`]*"): | |
215 | return &ShAtom{shtComment, repl.s, q, nil} | 175 | return &ShAtom{shtComment, repl.s, q, nil} | |
216 | case repl.AdvanceStr(";;"): | |||
217 | return &ShAtom{shtCaseSeparator, repl.s, q, nil} | |||
218 | case repl.AdvanceStr(";"): | |||
219 | return &ShAtom{shtSemicolon, repl.s, q, nil} | |||
220 | case repl.AdvanceStr("("): | |||
221 | return &ShAtom{shtParenOpen, repl.s, q, nil} | |||
222 | case repl.AdvanceStr(")"): | |||
223 | return &ShAtom{shtParenClose, repl.s, q, nil} | |||
224 | case repl.AdvanceStr("||"): | |||
225 | return &ShAtom{shtOr, repl.s, q, nil} | |||
226 | case repl.AdvanceStr("&&"): | |||
227 | return &ShAtom{shtAnd, repl.s, q, nil} | |||
228 | case repl.AdvanceStr("|"): | |||
229 | return &ShAtom{shtPipe, repl.s, q, nil} | |||
230 | case repl.AdvanceStr("&"): | |||
231 | return &ShAtom{shtBackground, repl.s, q, nil} | |||
232 | case repl.AdvanceRegexp(`^(?:<|<<|>|>>|>&)`): | |||
233 | return &ShAtom{shtRedirect, repl.s, q, nil} | |||
234 | case repl.AdvanceRegexp(`^(?:[!#%*+,\-./0-9:=?@A-Z\[\]_a-z~]+|\\[^$]|` + reShDollar + `)+`): | 176 | case repl.AdvanceRegexp(`^(?:[!#%*+,\-./0-9:=?@A-Z\[\]_a-z~]+|\\[^$]|` + reShDollar + `)+`): | |
235 | return &ShAtom{shtWord, repl.s, q, nil} | 177 | return &ShAtom{shtWord, repl.s, q, nil} | |
236 | case repl.AdvanceHspace(): | 178 | case repl.AdvanceHspace(): | |
237 | return &ShAtom{shtSpace, repl.s, q, nil} | 179 | return &ShAtom{shtSpace, repl.s, q, nil} | |
238 | } | 180 | } | |
239 | return nil | 181 | return nil | |
240 | } | 182 | } | |
241 | 183 | |||
242 | func (p *ShTokenizer) shAtomBacktDquot() *ShAtom { | 184 | func (p *ShTokenizer) shAtomBacktDquot() *ShAtom { | |
243 | repl := p.parser.repl | 185 | repl := p.parser.repl | |
244 | switch { | 186 | switch { | |
245 | case repl.AdvanceStr("\""): | 187 | case repl.AdvanceStr("\""): | |
246 | return &ShAtom{shtWord, repl.s, shqBackt, nil} | 188 | return &ShAtom{shtWord, repl.s, shqBackt, nil} | |
@@ -287,26 +229,45 @@ func (p *ShTokenizer) shAtomDquotBacktDq | @@ -287,26 +229,45 @@ func (p *ShTokenizer) shAtomDquotBacktDq | |||
287 | } | 229 | } | |
288 | 230 | |||
289 | func (p *ShTokenizer) shAtomDquotBacktSquot() *ShAtom { | 231 | func (p *ShTokenizer) shAtomDquotBacktSquot() *ShAtom { | |
290 | repl := p.parser.repl | 232 | repl := p.parser.repl | |
291 | switch { | 233 | switch { | |
292 | case repl.AdvanceStr("'"): | 234 | case repl.AdvanceStr("'"): | |
293 | return &ShAtom{shtWord, repl.s, shqDquotBackt, nil} | 235 | return &ShAtom{shtWord, repl.s, shqDquotBackt, nil} | |
294 | case repl.AdvanceRegexp(`^(?:[\t !"#%()*+,\-./0-9:;<=>?@A-Z\[\]^_a-z{|}~]+|\\[^$]|\\\$\$|\$\$)+`): | 236 | case repl.AdvanceRegexp(`^(?:[\t !"#%()*+,\-./0-9:;<=>?@A-Z\[\]^_a-z{|}~]+|\\[^$]|\\\$\$|\$\$)+`): | |
295 | return &ShAtom{shtWord, repl.m[0], shqDquotBacktSquot, nil} | 237 | return &ShAtom{shtWord, repl.m[0], shqDquotBacktSquot, nil} | |
296 | } | 238 | } | |
297 | return nil | 239 | return nil | |
298 | } | 240 | } | |
299 | 241 | |||
242 | func (p *ShTokenizer) shOperator(q ShQuoting) *ShAtom { | |||
243 | repl := p.parser.repl | |||
244 | switch { | |||
245 | case repl.AdvanceStr("||"), | |||
246 | repl.AdvanceStr("&&"), | |||
247 | repl.AdvanceStr(";;"), | |||
248 | repl.AdvanceStr("\n"), | |||
249 | repl.AdvanceStr(";"), | |||
250 | repl.AdvanceStr("("), | |||
251 | repl.AdvanceStr(")"), | |||
252 | repl.AdvanceStr("|"), | |||
253 | repl.AdvanceStr("&"): | |||
254 | return &ShAtom{shtOperator, repl.s, q, nil} | |||
255 | case repl.AdvanceRegexp(`^\d*(?:<<-|<<|<&|<>|>>|>&|>\||<|>)`): | |||
256 | return &ShAtom{shtOperator, repl.m[0], q, nil} | |||
257 | } | |||
258 | return nil | |||
259 | } | |||
260 | ||||
300 | func (p *ShTokenizer) ShAtoms() []*ShAtom { | 261 | func (p *ShTokenizer) ShAtoms() []*ShAtom { | |
301 | var atoms []*ShAtom | 262 | var atoms []*ShAtom | |
302 | q := shqPlain | 263 | q := shqPlain | |
303 | for { | 264 | for { | |
304 | atom := p.ShAtom(q) | 265 | atom := p.ShAtom(q) | |
305 | if atom == nil { | 266 | if atom == nil { | |
306 | return atoms | 267 | return atoms | |
307 | } | 268 | } | |
308 | atoms = append(atoms, atom) | 269 | atoms = append(atoms, atom) | |
309 | q = atom.Quoting | 270 | q = atom.Quoting | |
310 | } | 271 | } | |
311 | } | 272 | } | |
312 | 273 |
@@ -1,71 +1,71 @@ | @@ -1,71 +1,71 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | // @Beta | |||
8 | func (s *Suite) Test_ShTokenizer_ShAtom(c *check.C) { | 7 | func (s *Suite) Test_ShTokenizer_ShAtom(c *check.C) { | |
9 | checkRest := func(s string, expected ...*ShAtom) string { | 8 | checkRest := func(s string, expected ...*ShAtom) string { | |
10 | p := NewShTokenizer(dummyLine, s, false) | 9 | p := NewShTokenizer(dummyLine, s, false) | |
11 | q := shqPlain | 10 | q := shqPlain | |
12 | for _, exp := range expected { | 11 | for _, exp := range expected { | |
13 | c.Check(p.ShAtom(q), deepEquals, exp) | 12 | c.Check(p.ShAtom(q), deepEquals, exp) | |
14 | q = exp.Quoting | 13 | q = exp.Quoting | |
15 | } | 14 | } | |
16 | return p.Rest() | 15 | return p.Rest() | |
17 | } | 16 | } | |
18 | check := func(str string, expected ...*ShAtom) { | 17 | check := func(str string, expected ...*ShAtom) { | |
19 | rest := checkRest(str, expected...) | 18 | rest := checkRest(str, expected...) | |
20 | c.Check(rest, equals, "") | 19 | c.Check(rest, equals, "") | |
21 | c.Check(s.Output(), equals, "") | 20 | c.Check(s.Output(), equals, "") | |
22 | } | 21 | } | |
23 | 22 | |||
24 | token := func(typ ShAtomType, text string, quoting ShQuoting) *ShAtom { | 23 | token := func(typ ShAtomType, text string, quoting ShQuoting) *ShAtom { | |
25 | return &ShAtom{typ, text, quoting, nil} | 24 | return &ShAtom{typ, text, quoting, nil} | |
26 | } | 25 | } | |
27 | word := func(s string) *ShAtom { return token(shtWord, s, shqPlain) } | 26 | word := func(s string) *ShAtom { return token(shtWord, s, shqPlain) } | |
28 | dquot := func(s string) *ShAtom { return token(shtWord, s, shqDquot) } | 27 | dquot := func(s string) *ShAtom { return token(shtWord, s, shqDquot) } | |
29 | squot := func(s string) *ShAtom { return token(shtWord, s, shqSquot) } | 28 | squot := func(s string) *ShAtom { return token(shtWord, s, shqSquot) } | |
30 | backt := func(s string) *ShAtom { return token(shtWord, s, shqBackt) } | 29 | backt := func(s string) *ShAtom { return token(shtWord, s, shqBackt) } | |
30 | operator := func(s string) *ShAtom { return token(shtOperator, s, shqPlain) } | |||
31 | varuse := func(varname string, modifiers ...string) *ShAtom { | 31 | varuse := func(varname string, modifiers ...string) *ShAtom { | |
32 | text := "${" + varname | 32 | text := "${" + varname | |
33 | for _, modifier := range modifiers { | 33 | for _, modifier := range modifiers { | |
34 | text += ":" + modifier | 34 | text += ":" + modifier | |
35 | } | 35 | } | |
36 | text += "}" | 36 | text += "}" | |
37 | varuse := &MkVarUse{varname: varname, modifiers: modifiers} | 37 | varuse := &MkVarUse{varname: varname, modifiers: modifiers} | |
38 | return &ShAtom{shtVaruse, text, shqPlain, varuse} | 38 | return &ShAtom{shtVaruse, text, shqPlain, varuse} | |
39 | } | 39 | } | |
40 | q := func(q ShQuoting, token *ShAtom) *ShAtom { | 40 | q := func(q ShQuoting, token *ShAtom) *ShAtom { | |
41 | return &ShAtom{token.Type, token.MkText, q, token.Data} | 41 | return &ShAtom{token.Type, token.MkText, q, token.Data} | |
42 | } | 42 | } | |
43 | whitespace := func(s string) *ShAtom { return token(shtSpace, s, shqPlain) } | 43 | whitespace := func(s string) *ShAtom { return token(shtSpace, s, shqPlain) } | |
44 | space := token(shtSpace, " ", shqPlain) | 44 | space := token(shtSpace, " ", shqPlain) | |
45 | semicolon := token(shtSemicolon, ";", shqPlain) | 45 | semicolon := operator(";") | |
46 | pipe := token(shtPipe, "|", shqPlain) | 46 | pipe := operator("|") | |
47 | 47 | |||
48 | check("" /* none */) | 48 | check("" /* none */) | |
49 | 49 | |||
50 | check("$$var", | 50 | check("$$var", | |
51 | word("$$var")) | 51 | word("$$var")) | |
52 | 52 | |||
53 | check("$$var$$var", | 53 | check("$$var$$var", | |
54 | word("$$var$$var")) | 54 | word("$$var$$var")) | |
55 | 55 | |||
56 | check("$$var;;", | 56 | check("$$var;;", | |
57 | word("$$var"), | 57 | word("$$var"), | |
58 | token(shtCaseSeparator, ";;", shqPlain)) | 58 | operator(";;")) | |
59 | 59 | |||
60 | check("'single-quoted'", | 60 | check("'single-quoted'", | |
61 | q(shqSquot, word("'")), | 61 | q(shqSquot, word("'")), | |
62 | q(shqSquot, word("single-quoted")), | 62 | q(shqSquot, word("single-quoted")), | |
63 | q(shqPlain, word("'"))) | 63 | q(shqPlain, word("'"))) | |
64 | 64 | |||
65 | rest := checkRest("\"" /* none */) | 65 | rest := checkRest("\"" /* none */) | |
66 | c.Check(rest, equals, "\"") | 66 | c.Check(rest, equals, "\"") | |
67 | 67 | |||
68 | check("$${file%.c}.o", | 68 | check("$${file%.c}.o", | |
69 | word("$${file%.c}.o")) | 69 | word("$${file%.c}.o")) | |
70 | 70 | |||
71 | check("hello", | 71 | check("hello", | |
@@ -106,47 +106,47 @@ func (s *Suite) Test_ShTokenizer_ShAtom( | @@ -106,47 +106,47 @@ func (s *Suite) Test_ShTokenizer_ShAtom( | |||
106 | word("cd"), | 106 | word("cd"), | |
107 | space, | 107 | space, | |
108 | varuse("WRKSRC"), | 108 | varuse("WRKSRC"), | |
109 | word("/doc/man/man3"), | 109 | word("/doc/man/man3"), | |
110 | semicolon, | 110 | semicolon, | |
111 | space, | 111 | space, | |
112 | word("PAGES="), | 112 | word("PAGES="), | |
113 | dquot("\""), | 113 | dquot("\""), | |
114 | q(shqDquotBackt, word("`")), | 114 | q(shqDquotBackt, word("`")), | |
115 | q(shqDquotBackt, word("ls")), | 115 | q(shqDquotBackt, word("ls")), | |
116 | q(shqDquotBackt, space), | 116 | q(shqDquotBackt, space), | |
117 | q(shqDquotBackt, word("-1")), | 117 | q(shqDquotBackt, word("-1")), | |
118 | q(shqDquotBackt, space), | 118 | q(shqDquotBackt, space), | |
119 | token(shtPipe, "|", shqDquotBackt), | 119 | q(shqDquotBackt, operator("|")), | |
120 | q(shqDquotBackt, space), | 120 | q(shqDquotBackt, space), | |
121 | q(shqDquotBackt, varuse("SED")), | 121 | q(shqDquotBackt, varuse("SED")), | |
122 | q(shqDquotBackt, space), | 122 | q(shqDquotBackt, space), | |
123 | q(shqDquotBackt, word("-e")), | 123 | q(shqDquotBackt, word("-e")), | |
124 | q(shqDquotBackt, space), | 124 | q(shqDquotBackt, space), | |
125 | q(shqDquotBacktSquot, word("'")), | 125 | q(shqDquotBacktSquot, word("'")), | |
126 | q(shqDquotBacktSquot, word("s,3qt$$,3,")), | 126 | q(shqDquotBacktSquot, word("s,3qt$$,3,")), | |
127 | q(shqDquotBackt, word("'")), | 127 | q(shqDquotBackt, word("'")), | |
128 | q(shqDquot, word("`")), | 128 | q(shqDquot, word("`")), | |
129 | q(shqPlain, word("\"")), | 129 | q(shqPlain, word("\"")), | |
130 | semicolon) | 130 | semicolon) | |
131 | 131 | |||
132 | check("ls -1 | ${SED} -e 's,3qt$$,3,'", | 132 | check("ls -1 | ${SED} -e 's,3qt$$,3,'", | |
133 | word("ls"), space, word("-1"), space, | 133 | word("ls"), space, word("-1"), space, | |
134 | pipe, space, | 134 | pipe, space, | |
135 | varuse("SED"), space, word("-e"), space, | 135 | varuse("SED"), space, word("-e"), space, | |
136 | squot("'"), squot("s,3qt$$,3,"), word("'")) | 136 | squot("'"), squot("s,3qt$$,3,"), word("'")) | |
137 | 137 | |||
138 | check("(for PAGE in $$PAGES; do ", | 138 | check("(for PAGE in $$PAGES; do ", | |
139 | &ShAtom{shtParenOpen, "(", shqPlain, nil}, | 139 | &ShAtom{shtOperator, "(", shqPlain, nil}, | |
140 | word("for"), | 140 | word("for"), | |
141 | space, | 141 | space, | |
142 | word("PAGE"), | 142 | word("PAGE"), | |
143 | space, | 143 | space, | |
144 | word("in"), | 144 | word("in"), | |
145 | space, | 145 | space, | |
146 | word("$$PAGES"), | 146 | word("$$PAGES"), | |
147 | semicolon, | 147 | semicolon, | |
148 | space, | 148 | space, | |
149 | word("do"), | 149 | word("do"), | |
150 | space) | 150 | space) | |
151 | 151 | |||
152 | check(" ${ECHO} installing ${DESTDIR}${QTPREFIX}/man/man3/$${PAGE}; ", | 152 | check(" ${ECHO} installing ${DESTDIR}${QTPREFIX}/man/man3/$${PAGE}; ", | |
@@ -202,27 +202,27 @@ func (s *Suite) Test_ShTokenizer_ShAtom( | @@ -202,27 +202,27 @@ func (s *Suite) Test_ShTokenizer_ShAtom( | |||
202 | word("`")) | 202 | word("`")) | |
203 | 203 | |||
204 | check("\"`'echo;echo'`\"", | 204 | check("\"`'echo;echo'`\"", | |
205 | q(shqDquot, word("\"")), | 205 | q(shqDquot, word("\"")), | |
206 | q(shqDquotBackt, word("`")), | 206 | q(shqDquotBackt, word("`")), | |
207 | q(shqDquotBacktSquot, word("'")), | 207 | q(shqDquotBacktSquot, word("'")), | |
208 | q(shqDquotBacktSquot, word("echo;echo")), | 208 | q(shqDquotBacktSquot, word("echo;echo")), | |
209 | q(shqDquotBackt, word("'")), | 209 | q(shqDquotBackt, word("'")), | |
210 | q(shqDquot, word("`")), | 210 | q(shqDquot, word("`")), | |
211 | q(shqPlain, word("\""))) | 211 | q(shqPlain, word("\""))) | |
212 | 212 | |||
213 | check("cat<file", | 213 | check("cat<file", | |
214 | word("cat"), | 214 | word("cat"), | |
215 | token(shtRedirect, "<", shqPlain), | 215 | operator("<"), | |
216 | word("file")) | 216 | word("file")) | |
217 | 217 | |||
218 | check("-e \"s,\\$$sysconfdir/jabberd,\\$$sysconfdir,g\"", | 218 | check("-e \"s,\\$$sysconfdir/jabberd,\\$$sysconfdir,g\"", | |
219 | word("-e"), | 219 | word("-e"), | |
220 | space, | 220 | space, | |
221 | dquot("\""), | 221 | dquot("\""), | |
222 | dquot("s,\\$$sysconfdir/jabberd,\\$$sysconfdir,g"), | 222 | dquot("s,\\$$sysconfdir/jabberd,\\$$sysconfdir,g"), | |
223 | word("\"")) | 223 | word("\"")) | |
224 | 224 | |||
225 | check("echo $$,$$/", | 225 | check("echo $$,$$/", | |
226 | word("echo"), | 226 | word("echo"), | |
227 | space, | 227 | space, | |
228 | word("$$,$$/")) | 228 | word("$$,$$/")) | |
@@ -233,35 +233,35 @@ func (s *Suite) Test_ShTokenizer_ShAtom( | @@ -233,35 +233,35 @@ func (s *Suite) Test_ShTokenizer_ShAtom( | |||
233 | word("\\Make"), | 233 | word("\\Make"), | |
234 | space, | 234 | space, | |
235 | word("$$$$"), | 235 | word("$$$$"), | |
236 | space, | 236 | space, | |
237 | word("fast")) | 237 | word("fast")) | |
238 | c.Check(rest, equals, "\"") | 238 | c.Check(rest, equals, "\"") | |
239 | 239 | |||
240 | check("var=`echo;echo|echo&echo||echo&&echo>echo`", | 240 | check("var=`echo;echo|echo&echo||echo&&echo>echo`", | |
241 | q(shqPlain, word("var=")), | 241 | q(shqPlain, word("var=")), | |
242 | q(shqBackt, word("`")), | 242 | q(shqBackt, word("`")), | |
243 | q(shqBackt, word("echo")), | 243 | q(shqBackt, word("echo")), | |
244 | q(shqBackt, semicolon), | 244 | q(shqBackt, semicolon), | |
245 | q(shqBackt, word("echo")), | 245 | q(shqBackt, word("echo")), | |
246 | q(shqBackt, token(shtPipe, "|", shqBackt)), | 246 | q(shqBackt, operator("|")), | |
247 | q(shqBackt, word("echo")), | 247 | q(shqBackt, word("echo")), | |
248 | q(shqBackt, token(shtBackground, "&", shqBackt)), | 248 | q(shqBackt, operator("&")), | |
249 | q(shqBackt, word("echo")), | 249 | q(shqBackt, word("echo")), | |
250 | q(shqBackt, token(shtOr, "||", shqBackt)), | 250 | q(shqBackt, operator("||")), | |
251 | q(shqBackt, word("echo")), | 251 | q(shqBackt, word("echo")), | |
252 | q(shqBackt, token(shtAnd, "&&", shqBackt)), | 252 | q(shqBackt, operator("&&")), | |
253 | q(shqBackt, word("echo")), | 253 | q(shqBackt, word("echo")), | |
254 | q(shqBackt, token(shtRedirect, ">", shqBackt)), | 254 | q(shqBackt, operator(">")), | |
255 | q(shqBackt, word("echo")), | 255 | q(shqBackt, word("echo")), | |
256 | q(shqPlain, word("`"))) | 256 | q(shqPlain, word("`"))) | |
257 | 257 | |||
258 | check("# comment", | 258 | check("# comment", | |
259 | token(shtComment, "# comment", shqPlain)) | 259 | token(shtComment, "# comment", shqPlain)) | |
260 | check("no#comment", | 260 | check("no#comment", | |
261 | word("no#comment")) | 261 | word("no#comment")) | |
262 | check("`# comment`continue", | 262 | check("`# comment`continue", | |
263 | token(shtWord, "`", shqBackt), | 263 | token(shtWord, "`", shqBackt), | |
264 | token(shtComment, "# comment", shqBackt), | 264 | token(shtComment, "# comment", shqBackt), | |
265 | token(shtWord, "`", shqPlain), | 265 | token(shtWord, "`", shqPlain), | |
266 | token(shtWord, "continue", shqPlain)) | 266 | token(shtWord, "continue", shqPlain)) | |
267 | check("`no#comment`continue", | 267 | check("`no#comment`continue", | |
@@ -311,27 +311,27 @@ func (s *Suite) Test_ShTokenizer_ShAtom( | @@ -311,27 +311,27 @@ func (s *Suite) Test_ShTokenizer_ShAtom( | |||
311 | token(shtWord, ")", shqPlain)) | 311 | token(shtWord, ")", shqPlain)) | |
312 | 312 | |||
313 | check("$$(cat 'file')", | 313 | check("$$(cat 'file')", | |
314 | token(shtWord, "$$(", shqSubsh), | 314 | token(shtWord, "$$(", shqSubsh), | |
315 | token(shtWord, "cat", shqSubsh), | 315 | token(shtWord, "cat", shqSubsh), | |
316 | token(shtSpace, " ", shqSubsh), | 316 | token(shtSpace, " ", shqSubsh), | |
317 | token(shtWord, "'", shqSubshSquot), | 317 | token(shtWord, "'", shqSubshSquot), | |
318 | token(shtWord, "file", shqSubshSquot), | 318 | token(shtWord, "file", shqSubshSquot), | |
319 | token(shtWord, "'", shqSubsh), | 319 | token(shtWord, "'", shqSubsh), | |
320 | token(shtWord, ")", shqPlain)) | 320 | token(shtWord, ")", shqPlain)) | |
321 | } | 321 | } | |
322 | } | 322 | } | |
323 | 323 | |||
324 | func (s *Suite) Test_Shtokenizer_ShAtom_Quoting(c *check.C) { | 324 | func (s *Suite) Test_Shtokenizer_ShAtom__quoting(c *check.C) { | |
325 | checkQuotingChange := func(input, expectedOutput string) { | 325 | checkQuotingChange := func(input, expectedOutput string) { | |
326 | p := NewShTokenizer(dummyLine, input, false) | 326 | p := NewShTokenizer(dummyLine, input, false) | |
327 | q := shqPlain | 327 | q := shqPlain | |
328 | result := "" | 328 | result := "" | |
329 | for { | 329 | for { | |
330 | token := p.ShAtom(q) | 330 | token := p.ShAtom(q) | |
331 | if token == nil { | 331 | if token == nil { | |
332 | break | 332 | break | |
333 | } | 333 | } | |
334 | result += token.MkText | 334 | result += token.MkText | |
335 | if token.Quoting != q { | 335 | if token.Quoting != q { | |
336 | q = token.Quoting | 336 | q = token.Quoting | |
337 | result += "[" + q.String() + "]" | 337 | result += "[" + q.String() + "]" | |
@@ -379,62 +379,62 @@ func (s *Suite) Test_ShTokenizer_ShToken | @@ -379,62 +379,62 @@ func (s *Suite) Test_ShTokenizer_ShToken | |||
379 | NewShAtom(shtSpace, " ", shqBackt), | 379 | NewShAtom(shtSpace, " ", shqBackt), | |
380 | NewShAtom(shtWord, "file", shqBackt), | 380 | NewShAtom(shtWord, "file", shqBackt), | |
381 | NewShAtom(shtWord, "`", shqPlain))) | 381 | NewShAtom(shtWord, "`", shqPlain))) | |
382 | 382 | |||
383 | check("PAGES=\"`ls -1 | ${SED} -e 's,3qt$$,3,'`\"", | 383 | check("PAGES=\"`ls -1 | ${SED} -e 's,3qt$$,3,'`\"", | |
384 | NewShToken("PAGES=\"`ls -1 | ${SED} -e 's,3qt$$,3,'`\"", | 384 | NewShToken("PAGES=\"`ls -1 | ${SED} -e 's,3qt$$,3,'`\"", | |
385 | NewShAtom(shtWord, "PAGES=", shqPlain), | 385 | NewShAtom(shtWord, "PAGES=", shqPlain), | |
386 | NewShAtom(shtWord, "\"", shqDquot), | 386 | NewShAtom(shtWord, "\"", shqDquot), | |
387 | NewShAtom(shtWord, "`", shqDquotBackt), | 387 | NewShAtom(shtWord, "`", shqDquotBackt), | |
388 | NewShAtom(shtWord, "ls", shqDquotBackt), | 388 | NewShAtom(shtWord, "ls", shqDquotBackt), | |
389 | NewShAtom(shtSpace, " ", shqDquotBackt), | 389 | NewShAtom(shtSpace, " ", shqDquotBackt), | |
390 | NewShAtom(shtWord, "-1", shqDquotBackt), | 390 | NewShAtom(shtWord, "-1", shqDquotBackt), | |
391 | NewShAtom(shtSpace, " ", shqDquotBackt), | 391 | NewShAtom(shtSpace, " ", shqDquotBackt), | |
392 | NewShAtom(shtPipe, "|", shqDquotBackt), | 392 | NewShAtom(shtOperator, "|", shqDquotBackt), | |
393 | NewShAtom(shtSpace, " ", shqDquotBackt), | 393 | NewShAtom(shtSpace, " ", shqDquotBackt), | |
394 | NewShAtomVaruse("${SED}", shqDquotBackt, "SED"), | 394 | NewShAtomVaruse("${SED}", shqDquotBackt, "SED"), | |
395 | NewShAtom(shtSpace, " ", shqDquotBackt), | 395 | NewShAtom(shtSpace, " ", shqDquotBackt), | |
396 | NewShAtom(shtWord, "-e", shqDquotBackt), | 396 | NewShAtom(shtWord, "-e", shqDquotBackt), | |
397 | NewShAtom(shtSpace, " ", shqDquotBackt), | 397 | NewShAtom(shtSpace, " ", shqDquotBackt), | |
398 | NewShAtom(shtWord, "'", shqDquotBacktSquot), | 398 | NewShAtom(shtWord, "'", shqDquotBacktSquot), | |
399 | NewShAtom(shtWord, "s,3qt$$,3,", shqDquotBacktSquot), | 399 | NewShAtom(shtWord, "s,3qt$$,3,", shqDquotBacktSquot), | |
400 | NewShAtom(shtWord, "'", shqDquotBackt), | 400 | NewShAtom(shtWord, "'", shqDquotBackt), | |
401 | NewShAtom(shtWord, "`", shqDquot), | 401 | NewShAtom(shtWord, "`", shqDquot), | |
402 | NewShAtom(shtWord, "\"", shqPlain))) | 402 | NewShAtom(shtWord, "\"", shqPlain))) | |
403 | 403 | |||
404 | check("echo hello, world", | 404 | check("echo hello, world", | |
405 | NewShToken("echo", | 405 | NewShToken("echo", | |
406 | NewShAtom(shtWord, "echo", shqPlain)), | 406 | NewShAtom(shtWord, "echo", shqPlain)), | |
407 | NewShToken("hello,", | 407 | NewShToken("hello,", | |
408 | NewShAtom(shtWord, "hello,", shqPlain)), | 408 | NewShAtom(shtWord, "hello,", shqPlain)), | |
409 | NewShToken("world", | 409 | NewShToken("world", | |
410 | NewShAtom(shtWord, "world", shqPlain))) | 410 | NewShAtom(shtWord, "world", shqPlain))) | |
411 | 411 | |||
412 | check("if cond1; then action1; elif cond2; then action2; else action3; fi", | 412 | check("if cond1; then action1; elif cond2; then action2; else action3; fi", | |
413 | NewShToken("if", NewShAtom(shtWord, "if", shqPlain)), | 413 | NewShToken("if", NewShAtom(shtWord, "if", shqPlain)), | |
414 | NewShToken("cond1", NewShAtom(shtWord, "cond1", shqPlain)), | 414 | NewShToken("cond1", NewShAtom(shtWord, "cond1", shqPlain)), | |
415 | NewShToken(";", NewShAtom(shtSemicolon, ";", shqPlain)), | 415 | NewShToken(";", NewShAtom(shtOperator, ";", shqPlain)), | |
416 | NewShToken("then", NewShAtom(shtWord, "then", shqPlain)), | 416 | NewShToken("then", NewShAtom(shtWord, "then", shqPlain)), | |
417 | NewShToken("action1", NewShAtom(shtWord, "action1", shqPlain)), | 417 | NewShToken("action1", NewShAtom(shtWord, "action1", shqPlain)), | |
418 | NewShToken(";", NewShAtom(shtSemicolon, ";", shqPlain)), | 418 | NewShToken(";", NewShAtom(shtOperator, ";", shqPlain)), | |
419 | NewShToken("elif", NewShAtom(shtWord, "elif", shqPlain)), | 419 | NewShToken("elif", NewShAtom(shtWord, "elif", shqPlain)), | |
420 | NewShToken("cond2", NewShAtom(shtWord, "cond2", shqPlain)), | 420 | NewShToken("cond2", NewShAtom(shtWord, "cond2", shqPlain)), | |
421 | NewShToken(";", NewShAtom(shtSemicolon, ";", shqPlain)), | 421 | NewShToken(";", NewShAtom(shtOperator, ";", shqPlain)), | |
422 | NewShToken("then", NewShAtom(shtWord, "then", shqPlain)), | 422 | NewShToken("then", NewShAtom(shtWord, "then", shqPlain)), | |
423 | NewShToken("action2", NewShAtom(shtWord, "action2", shqPlain)), | 423 | NewShToken("action2", NewShAtom(shtWord, "action2", shqPlain)), | |
424 | NewShToken(";", NewShAtom(shtSemicolon, ";", shqPlain)), | 424 | NewShToken(";", NewShAtom(shtOperator, ";", shqPlain)), | |
425 | NewShToken("else", NewShAtom(shtWord, "else", shqPlain)), | 425 | NewShToken("else", NewShAtom(shtWord, "else", shqPlain)), | |
426 | NewShToken("action3", NewShAtom(shtWord, "action3", shqPlain)), | 426 | NewShToken("action3", NewShAtom(shtWord, "action3", shqPlain)), | |
427 | NewShToken(";", NewShAtom(shtSemicolon, ";", shqPlain)), | 427 | NewShToken(";", NewShAtom(shtOperator, ";", shqPlain)), | |
428 | NewShToken("fi", NewShAtom(shtWord, "fi", shqPlain))) | 428 | NewShToken("fi", NewShAtom(shtWord, "fi", shqPlain))) | |
429 | 429 | |||
430 | check("PATH=/nonexistent env PATH=${PATH:Q} true", | 430 | check("PATH=/nonexistent env PATH=${PATH:Q} true", | |
431 | NewShToken("PATH=/nonexistent", NewShAtom(shtWord, "PATH=/nonexistent", shqPlain)), | 431 | NewShToken("PATH=/nonexistent", NewShAtom(shtWord, "PATH=/nonexistent", shqPlain)), | |
432 | NewShToken("env", NewShAtom(shtWord, "env", shqPlain)), | 432 | NewShToken("env", NewShAtom(shtWord, "env", shqPlain)), | |
433 | NewShToken("PATH=${PATH:Q}", | 433 | NewShToken("PATH=${PATH:Q}", | |
434 | NewShAtom(shtWord, "PATH=", shqPlain), | 434 | NewShAtom(shtWord, "PATH=", shqPlain), | |
435 | NewShAtomVaruse("${PATH:Q}", shqPlain, "PATH", "Q")), | 435 | NewShAtomVaruse("${PATH:Q}", shqPlain, "PATH", "Q")), | |
436 | NewShToken("true", NewShAtom(shtWord, "true", shqPlain))) | 436 | NewShToken("true", NewShAtom(shtWord, "true", shqPlain))) | |
437 | 437 | |||
438 | if false { // Don’t know how to tokenize this correctly. | 438 | if false { // Don’t know how to tokenize this correctly. | |
439 | check("id=$$(${AWK} '{print}' < ${WRKSRC}/idfile)", | 439 | check("id=$$(${AWK} '{print}' < ${WRKSRC}/idfile)", | |
440 | NewShToken("id=$$(${AWK} '{print}' < ${WRKSRC}/idfile)", | 440 | NewShToken("id=$$(${AWK} '{print}' < ${WRKSRC}/idfile)", | |
@@ -442,19 +442,19 @@ func (s *Suite) Test_ShTokenizer_ShToken | @@ -442,19 +442,19 @@ func (s *Suite) Test_ShTokenizer_ShToken | |||
442 | NewShAtom(shtWord, "$$(", shqPlain), | 442 | NewShAtom(shtWord, "$$(", shqPlain), | |
443 | NewShAtomVaruse("${AWK}", shqPlain, "AWK"))) | 443 | NewShAtomVaruse("${AWK}", shqPlain, "AWK"))) | |
444 | } | 444 | } | |
445 | check("id=`${AWK} '{print}' < ${WRKSRC}/idfile`", | 445 | check("id=`${AWK} '{print}' < ${WRKSRC}/idfile`", | |
446 | NewShToken("id=`${AWK} '{print}' < ${WRKSRC}/idfile`", | 446 | NewShToken("id=`${AWK} '{print}' < ${WRKSRC}/idfile`", | |
447 | NewShAtom(shtWord, "id=", shqPlain), | 447 | NewShAtom(shtWord, "id=", shqPlain), | |
448 | NewShAtom(shtWord, "`", shqBackt), | 448 | NewShAtom(shtWord, "`", shqBackt), | |
449 | NewShAtomVaruse("${AWK}", shqBackt, "AWK"), | 449 | NewShAtomVaruse("${AWK}", shqBackt, "AWK"), | |
450 | NewShAtom(shtSpace, " ", shqBackt), | 450 | NewShAtom(shtSpace, " ", shqBackt), | |
451 | NewShAtom(shtWord, "'", shqBacktSquot), | 451 | NewShAtom(shtWord, "'", shqBacktSquot), | |
452 | NewShAtom(shtWord, "{print}", shqBacktSquot), | 452 | NewShAtom(shtWord, "{print}", shqBacktSquot), | |
453 | NewShAtom(shtWord, "'", shqBackt), | 453 | NewShAtom(shtWord, "'", shqBackt), | |
454 | NewShAtom(shtSpace, " ", shqBackt), | 454 | NewShAtom(shtSpace, " ", shqBackt), | |
455 | NewShAtom(shtRedirect, "<", shqBackt), | 455 | NewShAtom(shtOperator, "<", shqBackt), | |
456 | NewShAtom(shtSpace, " ", shqBackt), | 456 | NewShAtom(shtSpace, " ", shqBackt), | |
457 | NewShAtomVaruse("${WRKSRC}", shqBackt, "WRKSRC"), | 457 | NewShAtomVaruse("${WRKSRC}", shqBackt, "WRKSRC"), | |
458 | NewShAtom(shtWord, "/idfile", shqBackt), | 458 | NewShAtom(shtWord, "/idfile", shqBackt), | |
459 | NewShAtom(shtWord, "`", shqPlain))) | 459 | NewShAtom(shtWord, "`", shqPlain))) | |
460 | } | 460 | } |
@@ -1,68 +1,46 @@ | @@ -1,68 +1,46 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | "fmt" | 4 | "fmt" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | //go:generate go tool yacc -o shellyacc.go -v shellyacc.log -p shyy shell.y | 7 | //go:generate go tool yacc -o shellyacc.go -v shellyacc.log -p shyy shell.y | |
8 | 8 | |||
9 | type ShAtomType uint8 | 9 | type ShAtomType uint8 | |
10 | 10 | |||
11 | const ( | 11 | const ( | |
12 | shtSpace ShAtomType = iota | 12 | shtSpace ShAtomType = iota | |
13 | shtVaruse // ${PREFIX} | 13 | shtVaruse // ${PREFIX} | |
14 | shtWord // | 14 | shtWord // | |
15 | shtSemicolon // ; | 15 | shtOperator | |
16 | shtCaseSeparator // ;; | 16 | shtComment // # ... | |
17 | shtParenOpen // ( | 17 | shtSubshell // $$( | |
18 | shtParenClose // ) | |||
19 | shtPipe // | | |||
20 | shtBackground // & | |||
21 | shtOr // || | |||
22 | shtAnd // && | |||
23 | shtRedirect // >, <, >> | |||
24 | shtComment // # ... | |||
25 | shtSubshell // $$( | |||
26 | shtNewline // \n | |||
27 | ) | 18 | ) | |
28 | 19 | |||
29 | func (t ShAtomType) String() string { | 20 | func (t ShAtomType) String() string { | |
30 | return [...]string{ | 21 | return [...]string{ | |
31 | "space", | 22 | "space", | |
32 | "varuse", | 23 | "varuse", | |
33 | "word", | 24 | "word", | |
34 | "semicolon", | 25 | "operator", | |
35 | "caseSeparator", | |||
36 | "parenOpen", "parenClose", | |||
37 | "pipe", "background", | |||
38 | "or", "and", | |||
39 | "redirect", | |||
40 | "comment", | 26 | "comment", | |
41 | "newline", | 27 | "subshell", | |
42 | }[t] | 28 | }[t] | |
43 | } | 29 | } | |
44 | 30 | |||
45 | func (t ShAtomType) IsWord() bool { | 31 | func (t ShAtomType) IsWord() bool { | |
46 | switch t { | 32 | switch t { | |
47 | case shtVaruse, shtWord, shtRedirect: | 33 | case shtVaruse, shtWord: | |
48 | return true | |||
49 | } | |||
50 | return false | |||
51 | } | |||
52 | ||||
53 | func (t ShAtomType) IsCommandDelimiter() bool { | |||
54 | switch t { | |||
55 | case shtSemicolon, shtNewline, shtPipe, shtBackground, shtAnd, shtOr, shtCaseSeparator: | |||
56 | return true | 34 | return true | |
57 | } | 35 | } | |
58 | return false | 36 | return false | |
59 | } | 37 | } | |
60 | 38 | |||
61 | // @Beta | 39 | // @Beta | |
62 | type ShAtom struct { | 40 | type ShAtom struct { | |
63 | Type ShAtomType | 41 | Type ShAtomType | |
64 | MkText string | 42 | MkText string | |
65 | Quoting ShQuoting | 43 | Quoting ShQuoting | |
66 | Data interface{} | 44 | Data interface{} | |
67 | } | 45 | } | |
68 | 46 |
@@ -1,9 +1,9 @@ | @@ -1,9 +1,9 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestTreeString(c *check.C) { | 7 | func (s *Suite) Test_Tree_String(c *check.C) { | |
8 | 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\"))") | |
9 | } | 9 | } |
@@ -1,48 +1,44 @@ | @@ -1,48 +1,44 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestVartypeEffectivePermissions(c *check.C) { | 7 | func (s *Suite) Test_Vartype_EffectivePermissions(c *check.C) { | |
8 | G.globalData.InitVartypes() | 8 | G.globalData.InitVartypes() | |
9 | 9 | |||
10 | { | 10 | if t := G.globalData.vartypes["PREFIX"]; c.Check(t, check.NotNil) { | |
11 | t := G.globalData.vartypes["PREFIX"] | |||
12 | ||||
13 | c.Check(t.checker.name, equals, "Pathname") | 11 | c.Check(t.checker.name, equals, "Pathname") | |
14 | c.Check(t.aclEntries, check.DeepEquals, []AclEntry{{glob: "*", permissions: aclpUse}}) | 12 | c.Check(t.aclEntries, check.DeepEquals, []AclEntry{{glob: "*", permissions: aclpUse}}) | |
15 | c.Check(t.EffectivePermissions("Makefile"), equals, aclpUse) | 13 | c.Check(t.EffectivePermissions("Makefile"), equals, aclpUse) | |
16 | } | 14 | } | |
17 | 15 | |||
18 | { | 16 | if t := G.globalData.vartypes["EXTRACT_OPTS"]; c.Check(t, check.NotNil) { | |
19 | t := G.globalData.vartypes["EXTRACT_OPTS"] | |||
20 | ||||
21 | c.Check(t.checker.name, equals, "ShellWord") | 17 | c.Check(t.checker.name, equals, "ShellWord") | |
22 | c.Check(t.EffectivePermissions("Makefile"), equals, aclpAppend|aclpSet) | 18 | c.Check(t.EffectivePermissions("Makefile"), equals, aclpAppend|aclpSet) | |
23 | c.Check(t.EffectivePermissions("../Makefile"), equals, aclpAppend|aclpSet) | 19 | c.Check(t.EffectivePermissions("../Makefile"), equals, aclpAppend|aclpSet) | |
24 | c.Check(t.EffectivePermissions("options.mk"), equals, aclpUnknown) | 20 | c.Check(t.EffectivePermissions("options.mk"), equals, aclpUnknown) | |
25 | } | 21 | } | |
26 | } | 22 | } | |
27 | 23 | |||
28 | func (s *Suite) TestVarCheckerHasEnum(c *check.C) { | 24 | func (s *Suite) Test_VarChecker_HasEnum(c *check.C) { | |
29 | vc := enum("catinstall middle maninstall") | 25 | vc := enum("catinstall middle maninstall") | |
30 | 26 | |||
31 | c.Check(vc.HasEnum("catinstall"), equals, true) | 27 | c.Check(vc.HasEnum("catinstall"), equals, true) | |
32 | c.Check(vc.HasEnum("middle"), equals, true) | 28 | c.Check(vc.HasEnum("middle"), equals, true) | |
33 | c.Check(vc.HasEnum("maninstall"), equals, true) | 29 | c.Check(vc.HasEnum("maninstall"), equals, true) | |
34 | } | 30 | } | |
35 | 31 | |||
36 | func (s *Suite) TestAclPermissions_contains(c *check.C) { | 32 | func (s *Suite) Test_AclPermissions_Contains(c *check.C) { | |
37 | perms := aclpAllRuntime | 33 | perms := aclpAllRuntime | |
38 | 34 | |||
39 | c.Check(perms.Contains(aclpAllRuntime), equals, true) | 35 | c.Check(perms.Contains(aclpAllRuntime), equals, true) | |
40 | c.Check(perms.Contains(aclpUse), equals, true) | 36 | c.Check(perms.Contains(aclpUse), equals, true) | |
41 | c.Check(perms.Contains(aclpUseLoadtime), equals, false) | 37 | c.Check(perms.Contains(aclpUseLoadtime), equals, false) | |
42 | } | 38 | } | |
43 | 39 | |||
44 | func (s *Suite) TestAclPermissions_String(c *check.C) { | 40 | func (s *Suite) Test_AclPermissions_String(c *check.C) { | |
45 | c.Check(AclPermissions(0).String(), equals, "none") | 41 | c.Check(AclPermissions(0).String(), equals, "none") | |
46 | c.Check(aclpAll.String(), equals, "set, set-default, append, use-loadtime, use") | 42 | c.Check(aclpAll.String(), equals, "set, set-default, append, use-loadtime, use") | |
47 | c.Check(aclpUnknown.String(), equals, "unknown") | 43 | c.Check(aclpUnknown.String(), equals, "unknown") | |
48 | } | 44 | } |
@@ -1,99 +1,99 @@ | @@ -1,99 +1,99 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestChecklinesDistinfo(c *check.C) { | 7 | func (s *Suite) Test_ChecklinesDistinfo(c *check.C) { | |
8 | s.CreateTmpFile(c, "patches/patch-aa", ""+ | 8 | s.CreateTmpFile(c, "patches/patch-aa", ""+ | |
9 | "$"+"NetBSD$ line is ignored\n"+ | 9 | "$"+"NetBSD$ line is ignored\n"+ | |
10 | "patch contents\n") | 10 | "patch contents\n") | |
11 | s.CreateTmpFile(c, "patches/patch-ab", ""+ | 11 | s.CreateTmpFile(c, "patches/patch-ab", ""+ | |
12 | "patch contents\n") | 12 | "patch contents\n") | |
13 | G.CurrentDir = s.tmpdir | 13 | G.CurrentDir = s.tmpdir | |
14 | 14 | |||
15 | ChecklinesDistinfo(s.NewLines("distinfo", | 15 | ChecklinesDistinfo(s.NewLines("distinfo", | |
16 | "should be the RCS ID", | 16 | "should be the RCS ID", | |
17 | "should be empty", | 17 | "should be empty", | |
18 | "MD5 (distfile.tar.gz) = 12345678901234567890123456789012", | 18 | "MD5 (distfile.tar.gz) = 12345678901234567890123456789012", | |
19 | "SHA1 (distfile.tar.gz) = 1234567890123456789012345678901234567890", | 19 | "SHA1 (distfile.tar.gz) = 1234567890123456789012345678901234567890", | |
20 | "SHA1 (patch-aa) = 6b98dd609f85a9eb9c4c1e4e7055a6aaa62b7cc7", | 20 | "SHA1 (patch-aa) = 6b98dd609f85a9eb9c4c1e4e7055a6aaa62b7cc7", | |
21 | "SHA1 (patch-ab) = 6b98dd609f85a9eb9c4c1e4e7055a6aaa62b7cc7", | 21 | "SHA1 (patch-ab) = 6b98dd609f85a9eb9c4c1e4e7055a6aaa62b7cc7", | |
22 | "SHA1 (patch-nonexistent) = 1234")) | 22 | "SHA1 (patch-nonexistent) = 1234")) | |
23 | 23 | |||
24 | c.Check(s.Output(), equals, ""+ | 24 | c.Check(s.Output(), equals, ""+ | |
25 | "ERROR: distinfo:1: Expected \"$"+"NetBSD$\".\n"+ | 25 | "ERROR: distinfo:1: Expected \"$"+"NetBSD$\".\n"+ | |
26 | "NOTE: distinfo:2: Empty line expected.\n"+ | 26 | "NOTE: distinfo:2: Empty line expected.\n"+ | |
27 | "ERROR: distinfo:5: Expected SHA1, RMD160, SHA512, Size checksums for \"distfile.tar.gz\", got MD5, SHA1.\n"+ | 27 | "ERROR: distinfo:5: Expected SHA1, RMD160, SHA512, Size checksums for \"distfile.tar.gz\", got MD5, SHA1.\n"+ | |
28 | "WARN: distinfo:7: Patch file \"patch-nonexistent\" does not exist in directory \"patches\".\n") | 28 | "WARN: distinfo:7: Patch file \"patch-nonexistent\" does not exist in directory \"patches\".\n") | |
29 | } | 29 | } | |
30 | 30 | |||
31 | func (s *Suite) TestChecklinesDistinfo_GlobalHashMismatch(c *check.C) { | 31 | func (s *Suite) Test_ChecklinesDistinfo_global_hash_mismatch(c *check.C) { | |
32 | otherLine := NewLine("other/distinfo", 7, "dummy", nil) | 32 | otherLine := NewLine("other/distinfo", 7, "dummy", nil) | |
33 | G.Hash = make(map[string]*Hash) | 33 | G.Hash = make(map[string]*Hash) | |
34 | G.Hash["SHA512:pkgname-1.0.tar.gz"] = &Hash{"asdfasdf", otherLine} | 34 | G.Hash["SHA512:pkgname-1.0.tar.gz"] = &Hash{"asdfasdf", otherLine} | |
35 | 35 | |||
36 | ChecklinesDistinfo(s.NewLines("distinfo", | 36 | ChecklinesDistinfo(s.NewLines("distinfo", | |
37 | "$"+"NetBSD$", | 37 | "$"+"NetBSD$", | |
38 | "", | 38 | "", | |
39 | "SHA512 (pkgname-1.0.tar.gz) = 12341234")) | 39 | "SHA512 (pkgname-1.0.tar.gz) = 12341234")) | |
40 | 40 | |||
41 | c.Check(s.Output(), equals, ""+ | 41 | c.Check(s.Output(), equals, ""+ | |
42 | "ERROR: distinfo:3: The hash SHA512 for pkgname-1.0.tar.gz is 12341234, which differs from asdfasdf in other/distinfo:7.\n"+ | 42 | "ERROR: distinfo:3: The hash SHA512 for pkgname-1.0.tar.gz is 12341234, which differs from asdfasdf in other/distinfo:7.\n"+ | |
43 | "ERROR: distinfo:EOF: Expected SHA1, RMD160, SHA512, Size checksums for \"pkgname-1.0.tar.gz\", got SHA512.\n") | 43 | "ERROR: distinfo:EOF: Expected SHA1, RMD160, SHA512, Size checksums for \"pkgname-1.0.tar.gz\", got SHA512.\n") | |
44 | } | 44 | } | |
45 | 45 | |||
46 | func (s *Suite) TestChecklinesDistinfo_UncommittedPatch(c *check.C) { | 46 | func (s *Suite) Test_ChecklinesDistinfo_uncommitted_patch(c *check.C) { | |
47 | s.CreateTmpFile(c, "patches/patch-aa", ""+ | 47 | s.CreateTmpFile(c, "patches/patch-aa", ""+ | |
48 | "$"+"NetBSD$\n"+ | 48 | "$"+"NetBSD$\n"+ | |
49 | "\n"+ | 49 | "\n"+ | |
50 | "--- oldfile\n"+ | 50 | "--- oldfile\n"+ | |
51 | "+++ newfile\n"+ | 51 | "+++ newfile\n"+ | |
52 | "@@ -1,1 +1,1 @@\n"+ | 52 | "@@ -1,1 +1,1 @@\n"+ | |
53 | "-old\n"+ | 53 | "-old\n"+ | |
54 | "+new\n") | 54 | "+new\n") | |
55 | s.CreateTmpFile(c, "CVS/Entries", | 55 | s.CreateTmpFile(c, "CVS/Entries", | |
56 | "/distinfo/...\n") | 56 | "/distinfo/...\n") | |
57 | G.CurrentDir = s.tmpdir | 57 | G.CurrentDir = s.tmpdir | |
58 | 58 | |||
59 | ChecklinesDistinfo(s.NewLines(s.tmpdir+"/distinfo", | 59 | ChecklinesDistinfo(s.NewLines(s.tmpdir+"/distinfo", | |
60 | "$"+"NetBSD$", | 60 | "$"+"NetBSD$", | |
61 | "", | 61 | "", | |
62 | "SHA1 (patch-aa) = 5ad1fb9b3c328fff5caa1a23e8f330e707dd50c0")) | 62 | "SHA1 (patch-aa) = 5ad1fb9b3c328fff5caa1a23e8f330e707dd50c0")) | |
63 | 63 | |||
64 | c.Check(s.Output(), equals, ""+ | 64 | c.Check(s.Output(), equals, ""+ | |
65 | "WARN: ~/distinfo:3: patches/patch-aa is registered in distinfo but not added to CVS.\n") | 65 | "WARN: ~/distinfo:3: patches/patch-aa is registered in distinfo but not added to CVS.\n") | |
66 | } | 66 | } | |
67 | 67 | |||
68 | func (s *Suite) TestChecklinesDistinfo_UnrecordedPatches(c *check.C) { | 68 | func (s *Suite) Test_ChecklinesDistinfo_unrecorded_patches(c *check.C) { | |
69 | s.CreateTmpFile(c, "patches/CVS/Entries", "") | 69 | s.CreateTmpFile(c, "patches/CVS/Entries", "") | |
70 | s.CreateTmpFile(c, "patches/patch-aa", "") | 70 | s.CreateTmpFile(c, "patches/patch-aa", "") | |
71 | s.CreateTmpFile(c, "patches/patch-src-Makefile", "") | 71 | s.CreateTmpFile(c, "patches/patch-src-Makefile", "") | |
72 | G.CurrentDir = s.tmpdir | 72 | G.CurrentDir = s.tmpdir | |
73 | 73 | |||
74 | ChecklinesDistinfo(s.NewLines(s.tmpdir+"/distinfo", | 74 | ChecklinesDistinfo(s.NewLines(s.tmpdir+"/distinfo", | |
75 | "$"+"NetBSD$", | 75 | "$"+"NetBSD$", | |
76 | "", | 76 | "", | |
77 | "SHA1 (distfile.tar.gz) = ...", | 77 | "SHA1 (distfile.tar.gz) = ...", | |
78 | "RMD160 (distfile.tar.gz) = ...", | 78 | "RMD160 (distfile.tar.gz) = ...", | |
79 | "SHA512 (distfile.tar.gz) = ...", | 79 | "SHA512 (distfile.tar.gz) = ...", | |
80 | "Size (distfile.tar.gz) = 1024 bytes")) | 80 | "Size (distfile.tar.gz) = 1024 bytes")) | |
81 | 81 | |||
82 | c.Check(s.Output(), equals, ""+ | 82 | c.Check(s.Output(), equals, ""+ | |
83 | "ERROR: ~/distinfo: patch \"patches/patch-aa\" is not recorded. Run \""+confMake+" makepatchsum\".\n"+ | 83 | "ERROR: ~/distinfo: patch \"patches/patch-aa\" is not recorded. Run \""+confMake+" makepatchsum\".\n"+ | |
84 | "ERROR: ~/distinfo: patch \"patches/patch-src-Makefile\" is not recorded. Run \""+confMake+" makepatchsum\".\n") | 84 | "ERROR: ~/distinfo: patch \"patches/patch-src-Makefile\" is not recorded. Run \""+confMake+" makepatchsum\".\n") | |
85 | } | 85 | } | |
86 | 86 | |||
87 | func (s *Suite) TestChecklinesDistinfo_ManualPatches(c *check.C) { | 87 | func (s *Suite) Test_ChecklinesDistinfo_manual_patches(c *check.C) { | |
88 | s.CreateTmpFile(c, "patches/manual-libtool.m4", | 88 | s.CreateTmpFile(c, "patches/manual-libtool.m4", | |
89 | "") | 89 | "") | |
90 | G.CurrentDir = s.tmpdir | 90 | G.CurrentDir = s.tmpdir | |
91 | 91 | |||
92 | ChecklinesDistinfo(s.NewLines(s.tmpdir+"/distinfo", | 92 | ChecklinesDistinfo(s.NewLines(s.tmpdir+"/distinfo", | |
93 | "$"+"NetBSD$", | 93 | "$"+"NetBSD$", | |
94 | "", | 94 | "", | |
95 | "SHA1 (patch-aa) = ...")) | 95 | "SHA1 (patch-aa) = ...")) | |
96 | 96 | |||
97 | c.Check(s.Output(), equals, ""+ | 97 | c.Check(s.Output(), equals, ""+ | |
98 | "WARN: ~/distinfo:3: Patch file \"patch-aa\" does not exist in directory \"patches\".\n") | 98 | "WARN: ~/distinfo:3: Patch file \"patch-aa\" does not exist in directory \"patches\".\n") | |
99 | } | 99 | } |
@@ -1,92 +1,92 @@ | @@ -1,92 +1,92 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestConvertToLogicalLines_nocont(c *check.C) { | 7 | func (s *Suite) Test_convertToLogicalLines_no_continuation(c *check.C) { | |
8 | rawText := "" + | 8 | rawText := "" + | |
9 | "first line\n" + | 9 | "first line\n" + | |
10 | "second line\n" | 10 | "second line\n" | |
11 | 11 | |||
12 | lines := convertToLogicalLines("fname_nocont", rawText, false) | 12 | lines := convertToLogicalLines("fname_nocont", rawText, false) | |
13 | 13 | |||
14 | c.Check(lines, check.HasLen, 2) | 14 | c.Check(lines, check.HasLen, 2) | |
15 | c.Check(lines[0].String(), equals, "fname_nocont:1: first line") | 15 | c.Check(lines[0].String(), equals, "fname_nocont:1: first line") | |
16 | c.Check(lines[1].String(), equals, "fname_nocont:2: second line") | 16 | c.Check(lines[1].String(), equals, "fname_nocont:2: second line") | |
17 | } | 17 | } | |
18 | 18 | |||
19 | func (s *Suite) TestConvertToLogicalLines_cont(c *check.C) { | 19 | func (s *Suite) Test_convertToLogicalLines_continuation(c *check.C) { | |
20 | rawText := "" + | 20 | rawText := "" + | |
21 | "first line \\\n" + | 21 | "first line \\\n" + | |
22 | "second line\n" + | 22 | "second line\n" + | |
23 | "third\n" | 23 | "third\n" | |
24 | 24 | |||
25 | lines := convertToLogicalLines("fname_cont", rawText, true) | 25 | lines := convertToLogicalLines("fname_cont", rawText, true) | |
26 | 26 | |||
27 | c.Check(lines, check.HasLen, 2) | 27 | c.Check(lines, check.HasLen, 2) | |
28 | c.Check(lines[0].String(), equals, "fname_cont:1--2: first line second line") | 28 | c.Check(lines[0].String(), equals, "fname_cont:1--2: first line second line") | |
29 | c.Check(lines[1].String(), equals, "fname_cont:3: third") | 29 | c.Check(lines[1].String(), equals, "fname_cont:3: third") | |
30 | } | 30 | } | |
31 | 31 | |||
32 | func (s *Suite) TestConvertToLogicalLines_contInLastLine(c *check.C) { | 32 | func (s *Suite) Test_convertToLogicalLines_continuationInLastLine(c *check.C) { | |
33 | rawText := "" + | 33 | rawText := "" + | |
34 | "last line\\" | 34 | "last line\\" | |
35 | 35 | |||
36 | lines := convertToLogicalLines("fname_contlast", rawText, true) | 36 | lines := convertToLogicalLines("fname_contlast", rawText, true) | |
37 | 37 | |||
38 | c.Check(lines, check.HasLen, 1) | 38 | c.Check(lines, check.HasLen, 1) | |
39 | c.Check(lines[0].String(), equals, "fname_contlast:1: last line\\") | 39 | c.Check(lines[0].String(), equals, "fname_contlast:1: last line\\") | |
40 | c.Check(s.Stdout(), equals, "ERROR: fname_contlast:EOF: File must end with a newline.\n") | 40 | c.Check(s.Stdout(), equals, "ERROR: fname_contlast:EOF: File must end with a newline.\n") | |
41 | } | 41 | } | |
42 | 42 | |||
43 | func (s *Suite) TestSplitRawLine(c *check.C) { | 43 | func (s *Suite) Test_splitRawLine(c *check.C) { | |
44 | leadingWhitespace, text, trailingWhitespace, continuation := splitRawLine("\n") | 44 | leadingWhitespace, text, trailingWhitespace, continuation := splitRawLine("\n") | |
45 | 45 | |||
46 | c.Check(leadingWhitespace, equals, "") | 46 | c.Check(leadingWhitespace, equals, "") | |
47 | c.Check(text, equals, "") | 47 | c.Check(text, equals, "") | |
48 | c.Check(trailingWhitespace, equals, "") | 48 | c.Check(trailingWhitespace, equals, "") | |
49 | c.Check(continuation, equals, "") | 49 | c.Check(continuation, equals, "") | |
50 | 50 | |||
51 | leadingWhitespace, text, trailingWhitespace, continuation = splitRawLine("\tword \\\n") | 51 | leadingWhitespace, text, trailingWhitespace, continuation = splitRawLine("\tword \\\n") | |
52 | 52 | |||
53 | c.Check(leadingWhitespace, equals, "\t") | 53 | c.Check(leadingWhitespace, equals, "\t") | |
54 | c.Check(text, equals, "word") | 54 | c.Check(text, equals, "word") | |
55 | c.Check(trailingWhitespace, equals, " ") | 55 | c.Check(trailingWhitespace, equals, " ") | |
56 | c.Check(continuation, equals, "\\") | 56 | c.Check(continuation, equals, "\\") | |
57 | } | 57 | } | |
58 | 58 | |||
59 | func (s *Suite) TestAutofix_show(c *check.C) { | 59 | func (s *Suite) Test_show_autofix(c *check.C) { | |
60 | s.UseCommandLine(c, "--show-autofix") | 60 | s.UseCommandLine(c, "--show-autofix") | |
61 | fname := s.CreateTmpFile(c, "Makefile", ""+ | 61 | fname := s.CreateTmpFile(c, "Makefile", ""+ | |
62 | "line1\n"+ | 62 | "line1\n"+ | |
63 | "line2\n"+ | 63 | "line2\n"+ | |
64 | "line3\n") | 64 | "line3\n") | |
65 | lines := LoadExistingLines(fname, true) | 65 | lines := LoadExistingLines(fname, true) | |
66 | 66 | |||
67 | if !lines[1].AutofixReplaceRegexp(`.`, "X") { | 67 | if !lines[1].AutofixReplaceRegexp(`.`, "X") { | |
68 | lines[1].Warn0("Something's wrong here.") // Prints the autofix NOTE afterwards | 68 | lines[1].Warn0("Something's wrong here.") // Prints the autofix NOTE afterwards | |
69 | } | 69 | } | |
70 | SaveAutofixChanges(lines) | 70 | SaveAutofixChanges(lines) | |
71 | 71 | |||
72 | c.Check(lines[1].raw[0].textnl, equals, "XXXXX\n") | 72 | c.Check(lines[1].raw[0].textnl, equals, "XXXXX\n") | |
73 | c.Check(s.LoadTmpFile(c, "Makefile"), equals, "line1\nline2\nline3\n") | 73 | c.Check(s.LoadTmpFile(c, "Makefile"), equals, "line1\nline2\nline3\n") | |
74 | c.Check(s.Output(), equals, ""+ | 74 | c.Check(s.Output(), equals, ""+ | |
75 | "WARN: ~/Makefile:2: Something's wrong here.\n"+ | 75 | "WARN: ~/Makefile:2: Something's wrong here.\n"+ | |
76 | "AUTOFIX: ~/Makefile:2: Replacing regular expression \".\" with \"X\".\n") | 76 | "AUTOFIX: ~/Makefile:2: Replacing regular expression \".\" with \"X\".\n") | |
77 | } | 77 | } | |
78 | 78 | |||
79 | func (s *Suite) TestAutofix_fix(c *check.C) { | 79 | func (s *Suite) Test_autofix(c *check.C) { | |
80 | s.UseCommandLine(c, "--autofix") | 80 | s.UseCommandLine(c, "--autofix") | |
81 | fname := s.CreateTmpFile(c, "Makefile", ""+ | 81 | fname := s.CreateTmpFile(c, "Makefile", ""+ | |
82 | "line1\n"+ | 82 | "line1\n"+ | |
83 | "line2\n"+ | 83 | "line2\n"+ | |
84 | "line3\n") | 84 | "line3\n") | |
85 | lines := LoadExistingLines(fname, true) | 85 | lines := LoadExistingLines(fname, true) | |
86 | 86 | |||
87 | if !lines[1].AutofixReplaceRegexp(`.`, "X") { | 87 | if !lines[1].AutofixReplaceRegexp(`.`, "X") { | |
88 | lines[1].Warn0("Something's wrong here.") // Prints the autofix NOTE afterwards | 88 | lines[1].Warn0("Something's wrong here.") // Prints the autofix NOTE afterwards | |
89 | } | 89 | } | |
90 | SaveAutofixChanges(lines) | 90 | SaveAutofixChanges(lines) | |
91 | 91 | |||
92 | c.Check(s.LoadTmpFile(c, "Makefile"), equals, "line1\nXXXXX\nline3\n") | 92 | c.Check(s.LoadTmpFile(c, "Makefile"), equals, "line1\nXXXXX\nline3\n") |
@@ -1,46 +1,46 @@ | @@ -1,46 +1,46 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestGlobalDataVartypes(c *check.C) { | 7 | func (s *Suite) Test_GlobalData_InitVartypes(c *check.C) { | |
8 | G.globalData.InitVartypes() | 8 | G.globalData.InitVartypes() | |
9 | 9 | |||
10 | c.Check(G.globalData.vartypes["BSD_MAKE_ENV"].checker.name, equals, "ShellWord") | 10 | c.Check(G.globalData.vartypes["BSD_MAKE_ENV"].checker.name, equals, "ShellWord") | |
11 | c.Check(G.globalData.vartypes["USE_BUILTIN.*"].checker.name, equals, "YesNoIndirectly") | 11 | c.Check(G.globalData.vartypes["USE_BUILTIN.*"].checker.name, equals, "YesNoIndirectly") | |
12 | } | 12 | } | |
13 | 13 | |||
14 | func (s *Suite) TestParselinesSuggestedUpdates(c *check.C) { | 14 | func (s *Suite) Test_parselinesSuggestedUpdates(c *check.C) { | |
15 | lines := s.NewLines("doc/TODO", | 15 | lines := s.NewLines("doc/TODO", | |
16 | "", | 16 | "", | |
17 | "Suggested package updates", | 17 | "Suggested package updates", | |
18 | "==============", | 18 | "==============", | |
19 | "For Perl updates \u2026", | 19 | "For Perl updates \u2026", | |
20 | "", | 20 | "", | |
21 | "\t"+"o CSP-0.34", | 21 | "\t"+"o CSP-0.34", | |
22 | "\t"+"o freeciv-client-2.5.0 (urgent)", | 22 | "\t"+"o freeciv-client-2.5.0 (urgent)", | |
23 | "", | 23 | "", | |
24 | "\t"+"o ignored-0.0") | 24 | "\t"+"o ignored-0.0") | |
25 | 25 | |||
26 | todo := parselinesSuggestedUpdates(lines) | 26 | todo := parselinesSuggestedUpdates(lines) | |
27 | 27 | |||
28 | c.Check(todo, check.DeepEquals, []SuggestedUpdate{ | 28 | c.Check(todo, check.DeepEquals, []SuggestedUpdate{ | |
29 | {lines[5], "CSP", "0.34", ""}, | 29 | {lines[5], "CSP", "0.34", ""}, | |
30 | {lines[6], "freeciv-client", "2.5.0", "(urgent)"}}) | 30 | {lines[6], "freeciv-client", "2.5.0", "(urgent)"}}) | |
31 | } | 31 | } | |
32 | 32 | |||
33 | func (s *Suite) TestGlobalData_LoadTools(c *check.C) { | 33 | func (s *Suite) Test_GlobalData_loadTools(c *check.C) { | |
34 | s.CreateTmpFileLines(c, "mk/tools/bsd.tools.mk", | 34 | s.CreateTmpFileLines(c, "mk/tools/bsd.tools.mk", | |
35 | ".include \"flex.mk\"", | 35 | ".include \"flex.mk\"", | |
36 | ".include \"gettext.mk\"") | 36 | ".include \"gettext.mk\"") | |
37 | s.CreateTmpFileLines(c, "mk/tools/defaults.mk", | 37 | s.CreateTmpFileLines(c, "mk/tools/defaults.mk", | |
38 | "_TOOLS_VARNAME.chown=CHOWN", | 38 | "_TOOLS_VARNAME.chown=CHOWN", | |
39 | "_TOOLS_VARNAME.gawk=AWK", | 39 | "_TOOLS_VARNAME.gawk=AWK", | |
40 | "_TOOLS_VARNAME.mv=MV", | 40 | "_TOOLS_VARNAME.mv=MV", | |
41 | "_TOOLS_VARNAME.pwd=PWD") | 41 | "_TOOLS_VARNAME.pwd=PWD") | |
42 | s.CreateTmpFileLines(c, "mk/tools/flex.mk", | 42 | s.CreateTmpFileLines(c, "mk/tools/flex.mk", | |
43 | "# empty") | 43 | "# empty") | |
44 | s.CreateTmpFileLines(c, "mk/tools/gettext.mk", | 44 | s.CreateTmpFileLines(c, "mk/tools/gettext.mk", | |
45 | "USE_TOOLS+=msgfmt", | 45 | "USE_TOOLS+=msgfmt", | |
46 | "TOOLS_CREATE+=msgfmt") | 46 | "TOOLS_CREATE+=msgfmt") | |
@@ -64,43 +64,43 @@ func (s *Suite) TestGlobalData_LoadTools | @@ -64,43 +64,43 @@ func (s *Suite) TestGlobalData_LoadTools | |||
64 | "TRACE: 1 tool &{Name:chown Varname:CHOWN MustUseVarForm:false Predefined:false UsableAtLoadtime:false}\n"+ | 64 | "TRACE: 1 tool &{Name:chown Varname:CHOWN MustUseVarForm:false Predefined:false UsableAtLoadtime:false}\n"+ | |
65 | "TRACE: 1 tool &{Name:echo Varname:ECHO MustUseVarForm:true Predefined:true UsableAtLoadtime:true}\n"+ | 65 | "TRACE: 1 tool &{Name:echo Varname:ECHO MustUseVarForm:true Predefined:true UsableAtLoadtime:true}\n"+ | |
66 | "TRACE: 1 tool &{Name:echo -n Varname:ECHO_N MustUseVarForm:true Predefined:true UsableAtLoadtime:true}\n"+ | 66 | "TRACE: 1 tool &{Name:echo -n Varname:ECHO_N MustUseVarForm:true Predefined:true UsableAtLoadtime:true}\n"+ | |
67 | "TRACE: 1 tool &{Name:false Varname:FALSE MustUseVarForm:true Predefined:true UsableAtLoadtime:false}\n"+ | 67 | "TRACE: 1 tool &{Name:false Varname:FALSE MustUseVarForm:true Predefined:true UsableAtLoadtime:false}\n"+ | |
68 | "TRACE: 1 tool &{Name:gawk Varname:AWK MustUseVarForm:false Predefined:false UsableAtLoadtime:false}\n"+ | 68 | "TRACE: 1 tool &{Name:gawk Varname:AWK MustUseVarForm:false Predefined:false UsableAtLoadtime:false}\n"+ | |
69 | "TRACE: 1 tool &{Name:msgfmt Varname: MustUseVarForm:false Predefined:false UsableAtLoadtime:false}\n"+ | 69 | "TRACE: 1 tool &{Name:msgfmt Varname: MustUseVarForm:false Predefined:false UsableAtLoadtime:false}\n"+ | |
70 | "TRACE: 1 tool &{Name:mv Varname:MV MustUseVarForm:false Predefined:true UsableAtLoadtime:false}\n"+ | 70 | "TRACE: 1 tool &{Name:mv Varname:MV MustUseVarForm:false Predefined:true UsableAtLoadtime:false}\n"+ | |
71 | "TRACE: 1 tool &{Name:pwd Varname:PWD MustUseVarForm:false Predefined:true UsableAtLoadtime:true}\n"+ | 71 | "TRACE: 1 tool &{Name:pwd Varname:PWD MustUseVarForm:false Predefined:true UsableAtLoadtime:true}\n"+ | |
72 | "TRACE: 1 tool &{Name:test Varname:TEST MustUseVarForm:true Predefined:true UsableAtLoadtime:true}\n"+ | 72 | "TRACE: 1 tool &{Name:test Varname:TEST MustUseVarForm:true Predefined:true UsableAtLoadtime:true}\n"+ | |
73 | "TRACE: 1 tool &{Name:true Varname:TRUE MustUseVarForm:true Predefined:true UsableAtLoadtime:true}\n"+ | 73 | "TRACE: 1 tool &{Name:true Varname:TRUE MustUseVarForm:true Predefined:true UsableAtLoadtime:true}\n"+ | |
74 | "TRACE: - (*ToolRegistry).Trace()\n") | 74 | "TRACE: - (*ToolRegistry).Trace()\n") | |
75 | } | 75 | } | |
76 | 76 | |||
77 | func (s *Suite) TestGlobalData_loadDocChanges(c *check.C) { | 77 | func (s *Suite) Test_GlobalData_loadDocChangesFromFile(c *check.C) { | |
78 | s.CreateTmpFile(c, "doc/CHANGES-2015", ""+ | 78 | s.CreateTmpFile(c, "doc/CHANGES-2015", ""+ | |
79 | "\tAdded category/package version 1.0 [author1 2015-01-01]\n"+ | 79 | "\tAdded category/package version 1.0 [author1 2015-01-01]\n"+ | |
80 | "\tUpdated category/package to 1.5 [author2 2015-01-02]\n"+ | 80 | "\tUpdated category/package to 1.5 [author2 2015-01-02]\n"+ | |
81 | "\tRenamed category/package to category/pkg [author3 2015-01-03]\n"+ | 81 | "\tRenamed category/package to category/pkg [author3 2015-01-03]\n"+ | |
82 | "\tMoved category/package to other/package [author4 2015-01-04]\n"+ | 82 | "\tMoved category/package to other/package [author4 2015-01-04]\n"+ | |
83 | "\tRemoved category/package [author5 2015-01-05]\n"+ | 83 | "\tRemoved category/package [author5 2015-01-05]\n"+ | |
84 | "\tRemoved category/package successor category/package2 [author6 2015-01-06]\n"+ | 84 | "\tRemoved category/package successor category/package2 [author6 2015-01-06]\n"+ | |
85 | "\tDowngraded category/package to 1.2 [author7 2015-01-07]\n") | 85 | "\tDowngraded category/package to 1.2 [author7 2015-01-07]\n") | |
86 | 86 | |||
87 | changes := G.globalData.loadDocChangesFromFile(s.tmpdir + "/doc/CHANGES-2015") | 87 | changes := G.globalData.loadDocChangesFromFile(s.tmpdir + "/doc/CHANGES-2015") | |
88 | 88 | |||
89 | c.Assert(len(changes), equals, 7) | 89 | c.Assert(len(changes), equals, 7) | |
90 | c.Check(*changes[0], equals, Change{changes[0].Line, "Added", "category/package", "1.0", "author1", "2015-01-01"}) | 90 | c.Check(*changes[0], equals, Change{changes[0].Line, "Added", "category/package", "1.0", "author1", "2015-01-01"}) | |
91 | c.Check(*changes[1], equals, Change{changes[1].Line, "Updated", "category/package", "1.5", "author2", "2015-01-02"}) | 91 | c.Check(*changes[1], equals, Change{changes[1].Line, "Updated", "category/package", "1.5", "author2", "2015-01-02"}) | |
92 | c.Check(*changes[2], equals, Change{changes[2].Line, "Renamed", "category/package", "", "author3", "2015-01-03"}) | 92 | c.Check(*changes[2], equals, Change{changes[2].Line, "Renamed", "category/package", "", "author3", "2015-01-03"}) | |
93 | c.Check(*changes[3], equals, Change{changes[3].Line, "Moved", "category/package", "", "author4", "2015-01-04"}) | 93 | c.Check(*changes[3], equals, Change{changes[3].Line, "Moved", "category/package", "", "author4", "2015-01-04"}) | |
94 | c.Check(*changes[4], equals, Change{changes[4].Line, "Removed", "category/package", "", "author5", "2015-01-05"}) | 94 | c.Check(*changes[4], equals, Change{changes[4].Line, "Removed", "category/package", "", "author5", "2015-01-05"}) | |
95 | c.Check(*changes[5], equals, Change{changes[5].Line, "Removed", "category/package", "", "author6", "2015-01-06"}) | 95 | c.Check(*changes[5], equals, Change{changes[5].Line, "Removed", "category/package", "", "author6", "2015-01-06"}) | |
96 | c.Check(*changes[6], equals, Change{changes[6].Line, "Downgraded", "category/package", "1.2", "author7", "2015-01-07"}) | 96 | c.Check(*changes[6], equals, Change{changes[6].Line, "Downgraded", "category/package", "1.2", "author7", "2015-01-07"}) | |
97 | } | 97 | } | |
98 | 98 | |||
99 | func (s *Suite) TestGlobalData_deprecated(c *check.C) { | 99 | func (s *Suite) Test_GlobalData_deprecated(c *check.C) { | |
100 | G.globalData.loadDeprecatedVars() | 100 | G.globalData.loadDeprecatedVars() | |
101 | 101 | |||
102 | line := NewLine("Makefile", 5, "USE_PERL5=\tyes", nil) | 102 | line := NewLine("Makefile", 5, "USE_PERL5=\tyes", nil) | |
103 | NewMkLine(line).checkVarassign() | 103 | NewMkLine(line).checkVarassign() | |
104 | 104 | |||
105 | c.Check(s.Output(), equals, "WARN: Makefile:5: Definition of USE_PERL5 is deprecated. Use USE_TOOLS+=perl or USE_TOOLS+=perl:run instead.\n") | 105 | c.Check(s.Output(), equals, "WARN: Makefile:5: Definition of USE_PERL5 is deprecated. Use USE_TOOLS+=perl or USE_TOOLS+=perl:run instead.\n") | |
106 | } | 106 | } |
@@ -1,20 +1,20 @@ | @@ -1,20 +1,20 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestLineModify(c *check.C) { | 7 | func (s *Suite) Test_Line_modifications(c *check.C) { | |
8 | s.UseCommandLine(c, "--show-autofix") | 8 | s.UseCommandLine(c, "--show-autofix") | |
9 | 9 | |||
10 | line := NewLine("fname", 1, "dummy", s.NewRawLines(1, "original\n")) | 10 | line := NewLine("fname", 1, "dummy", s.NewRawLines(1, "original\n")) | |
11 | 11 | |||
12 | c.Check(line.changed, equals, false) | 12 | c.Check(line.changed, equals, false) | |
13 | c.Check(line.raw, check.DeepEquals, s.NewRawLines(1, "original\n")) | 13 | c.Check(line.raw, check.DeepEquals, s.NewRawLines(1, "original\n")) | |
14 | 14 | |||
15 | line.AutofixReplaceRegexp(`(.)(.*)(.)`, "$3$2$1") | 15 | line.AutofixReplaceRegexp(`(.)(.*)(.)`, "$3$2$1") | |
16 | 16 | |||
17 | c.Check(line.changed, equals, true) | 17 | c.Check(line.changed, equals, true) | |
18 | c.Check(line.raw, check.DeepEquals, s.NewRawLines(1, "original\n", "lriginao\n")) | 18 | c.Check(line.raw, check.DeepEquals, s.NewRawLines(1, "original\n", "lriginao\n")) | |
19 | 19 | |||
20 | line.changed = false | 20 | line.changed = false | |
@@ -43,81 +43,99 @@ func (s *Suite) TestLineModify(c *check. | @@ -43,81 +43,99 @@ func (s *Suite) TestLineModify(c *check. | |||
43 | "between middle and after\n", | 43 | "between middle and after\n", | |
44 | "after\n"}) | 44 | "after\n"}) | |
45 | 45 | |||
46 | line.AutofixDelete() | 46 | line.AutofixDelete() | |
47 | 47 | |||
48 | c.Check(line.modifiedLines(), check.DeepEquals, []string{ | 48 | c.Check(line.modifiedLines(), check.DeepEquals, []string{ | |
49 | "before\n", | 49 | "before\n", | |
50 | "between before and middle\n", | 50 | "between before and middle\n", | |
51 | "", | 51 | "", | |
52 | "between middle and after\n", | 52 | "between middle and after\n", | |
53 | "after\n"}) | 53 | "after\n"}) | |
54 | } | 54 | } | |
55 | 55 | |||
56 | func (s *Suite) TestLine_CheckAbsolutePathname(c *check.C) { | 56 | func (s *Suite) Test_Line_CheckAbsolutePathname(c *check.C) { | |
57 | line := NewLine("Makefile", 1, "# dummy", nil) | 57 | line := NewLine("Makefile", 1, "# dummy", nil) | |
58 | 58 | |||
59 | line.CheckAbsolutePathname("bindir=/bin") | 59 | line.CheckAbsolutePathname("bindir=/bin") | |
60 | line.CheckAbsolutePathname("bindir=/../lib") | 60 | line.CheckAbsolutePathname("bindir=/../lib") | |
61 | 61 | |||
62 | c.Check(s.Output(), equals, "WARN: Makefile:1: Found absolute pathname: /bin\n") | 62 | c.Check(s.Output(), equals, "WARN: Makefile:1: Found absolute pathname: /bin\n") | |
63 | } | 63 | } | |
64 | 64 | |||
65 | func (s *Suite) TestShowAutofix_replace(c *check.C) { | 65 | func (s *Suite) Test_Line_show_autofix_AutofixReplace(c *check.C) { | |
66 | s.UseCommandLine(c, "--show-autofix", "--source") | 66 | s.UseCommandLine(c, "--show-autofix", "--source") | |
67 | line := NewLineMulti("Makefile", 27, 29, "# old", s.NewRawLines( | 67 | line := NewLineMulti("Makefile", 27, 29, "# old", s.NewRawLines( | |
68 | 27, "before\n", | 68 | 27, "before\n", | |
69 | 28, "The old song\n", | 69 | 28, "The old song\n", | |
70 | 29, "after\n")) | 70 | 29, "after\n")) | |
71 | 71 | |||
72 | if !line.AutofixReplace("old", "new") { | 72 | if !line.AutofixReplace("old", "new") { | |
73 | line.Warn0("Using \"old\" is deprecated.") | 73 | line.Warn0("Using \"old\" is deprecated.") | |
74 | } | 74 | } | |
75 | 75 | |||
76 | c.Check(s.Output(), equals, ""+ | 76 | c.Check(s.Output(), equals, ""+ | |
77 | "\n"+ | 77 | "\n"+ | |
78 | "> before\n"+ | 78 | "> before\n"+ | |
79 | "- The old song\n"+ | 79 | "- The old song\n"+ | |
80 | "+ The new song\n"+ | 80 | "+ The new song\n"+ | |
81 | "> after\n"+ | 81 | "> after\n"+ | |
82 | "WARN: Makefile:27--29: Using \"old\" is deprecated.\n"+ | 82 | "WARN: Makefile:27--29: Using \"old\" is deprecated.\n"+ | |
83 | "AUTOFIX: Makefile:27--29: Replacing \"old\" with \"new\".\n") | 83 | "AUTOFIX: Makefile:27--29: Replacing \"old\" with \"new\".\n") | |
84 | } | 84 | } | |
85 | 85 | |||
86 | func (s *Suite) TestShowAutofix_insert(c *check.C) { | 86 | func (s *Suite) Test_Line_show_autofix_AutofixInsertBefore(c *check.C) { | |
87 | s.UseCommandLine(c, "--show-autofix", "--source") | 87 | s.UseCommandLine(c, "--show-autofix", "--source") | |
88 | line := NewLine("Makefile", 30, "original", s.NewRawLines(30, "original\n")) | 88 | line := NewLine("Makefile", 30, "original", s.NewRawLines(30, "original\n")) | |
89 | 89 | |||
90 | if !line.AutofixInsertBefore("inserted") { | 90 | if !line.AutofixInsertBefore("inserted") { | |
91 | line.Warn0("Dummy") | 91 | line.Warn0("Dummy") | |
92 | } | 92 | } | |
93 | 93 | |||
94 | c.Check(s.Output(), equals, ""+ | 94 | c.Check(s.Output(), equals, ""+ | |
95 | "\n"+ | 95 | "\n"+ | |
96 | "+ inserted\n"+ | 96 | "+ inserted\n"+ | |
97 | "> original\n"+ | 97 | "> original\n"+ | |
98 | "WARN: Makefile:30: Dummy\n"+ | 98 | "WARN: Makefile:30: Dummy\n"+ | |
99 | "AUTOFIX: Makefile:30: Inserting a line \"inserted\" before this line.\n") | 99 | "AUTOFIX: Makefile:30: Inserting a line \"inserted\" before this line.\n") | |
100 | } | 100 | } | |
101 | 101 | |||
102 | func (s *Suite) TestShowAutofix_delete(c *check.C) { | 102 | func (s *Suite) Test_Line_show_autofix_AutofixDelete(c *check.C) { | |
103 | s.UseCommandLine(c, "--show-autofix", "--source") | 103 | s.UseCommandLine(c, "--show-autofix", "--source") | |
104 | line := NewLine("Makefile", 30, "to be deleted", s.NewRawLines(30, "to be deleted\n")) | 104 | line := NewLine("Makefile", 30, "to be deleted", s.NewRawLines(30, "to be deleted\n")) | |
105 | 105 | |||
106 | if !line.AutofixDelete() { | 106 | if !line.AutofixDelete() { | |
107 | line.Warn0("Dummy") | 107 | line.Warn0("Dummy") | |
108 | } | 108 | } | |
109 | 109 | |||
110 | c.Check(s.Output(), equals, ""+ | 110 | c.Check(s.Output(), equals, ""+ | |
111 | "\n"+ | 111 | "\n"+ | |
112 | "- to be deleted\n"+ | 112 | "- to be deleted\n"+ | |
113 | "WARN: Makefile:30: Dummy\n"+ | 113 | "WARN: Makefile:30: Dummy\n"+ | |
114 | "AUTOFIX: Makefile:30: Deleting this line.\n") | 114 | "AUTOFIX: Makefile:30: Deleting this line.\n") | |
115 | } | 115 | } | |
116 | 116 | |||
117 | func (s *Suite) TestLine_CheckTrailingWhitespace(c *check.C) { | 117 | func (s *Suite) Test_Line_CheckTrailingWhitespace(c *check.C) { | |
118 | line := NewLine("Makefile", 32, "The line must go on ", nil) | 118 | line := NewLine("Makefile", 32, "The line must go on ", nil) | |
119 | 119 | |||
120 | line.CheckTrailingWhitespace() | 120 | line.CheckTrailingWhitespace() | |
121 | 121 | |||
122 | c.Check(s.Output(), equals, "NOTE: Makefile:32: Trailing white-space.\n") | 122 | c.Check(s.Output(), equals, "NOTE: Makefile:32: Trailing white-space.\n") | |
123 | } | 123 | } | |
124 | ||||
125 | func (s *Suite) Test_Line_CheckRcsid(c *check.C) { | |||
126 | lines := s.NewLines("fname", | |||
127 | "$"+"NetBSD: dummy $", | |||
128 | "$"+"NetBSD$", | |||
129 | "$"+"Id: dummy $", | |||
130 | "$"+"Id$", | |||
131 | "$"+"FreeBSD$") | |||
132 | ||||
133 | for _, line := range lines { | |||
134 | line.CheckRcsid(``, "") | |||
135 | } | |||
136 | ||||
137 | c.Check(s.Output(), equals, ""+ | |||
138 | "ERROR: fname:3: Expected \"$"+"NetBSD$\".\n"+ | |||
139 | "ERROR: fname:4: Expected \"$"+"NetBSD$\".\n"+ | |||
140 | "ERROR: fname:5: Expected \"$"+"NetBSD$\".\n") | |||
141 | } |
@@ -1,35 +1,35 @@ | @@ -1,35 +1,35 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestParser_PkgbasePattern(c *check.C) { | 7 | func (s *Suite) Test_Parser_PkgbasePattern(c *check.C) { | |
8 | checkRest := func(pattern, expected, rest string) { | 8 | checkRest := func(pattern, expected, rest string) { | |
9 | parser := NewParser(dummyLine, pattern, false) | 9 | parser := NewParser(dummyLine, pattern, false) | |
10 | actual := parser.PkgbasePattern() | 10 | actual := parser.PkgbasePattern() | |
11 | c.Check(actual, equals, expected) | 11 | c.Check(actual, equals, expected) | |
12 | c.Check(parser.Rest(), equals, rest) | 12 | c.Check(parser.Rest(), equals, rest) | |
13 | } | 13 | } | |
14 | 14 | |||
15 | checkRest("fltk", "fltk", "") | 15 | checkRest("fltk", "fltk", "") | |
16 | checkRest("fltk|", "fltk", "|") | 16 | checkRest("fltk|", "fltk", "|") | |
17 | checkRest("boost-build-1.59.*", "boost-build", "-1.59.*") | 17 | checkRest("boost-build-1.59.*", "boost-build", "-1.59.*") | |
18 | checkRest("${PHP_PKG_PREFIX}-pdo-5.*", "${PHP_PKG_PREFIX}-pdo", "-5.*") | 18 | checkRest("${PHP_PKG_PREFIX}-pdo-5.*", "${PHP_PKG_PREFIX}-pdo", "-5.*") | |
19 | checkRest("${PYPKGPREFIX}-metakit-[0-9]*", "${PYPKGPREFIX}-metakit", "-[0-9]*") | 19 | checkRest("${PYPKGPREFIX}-metakit-[0-9]*", "${PYPKGPREFIX}-metakit", "-[0-9]*") | |
20 | } | 20 | } | |
21 | 21 | |||
22 | func (s *Suite) TestParser_Dependency(c *check.C) { | 22 | func (s *Suite) Test_Parser_Dependency(c *check.C) { | |
23 | 23 | |||
24 | checkRest := func(pattern string, expected DependencyPattern, rest string) { | 24 | checkRest := func(pattern string, expected DependencyPattern, rest string) { | |
25 | parser := NewParser(dummyLine, pattern, false) | 25 | parser := NewParser(dummyLine, pattern, false) | |
26 | dp := parser.Dependency() | 26 | dp := parser.Dependency() | |
27 | if c.Check(dp, check.NotNil) { | 27 | if c.Check(dp, check.NotNil) { | |
28 | c.Check(*dp, equals, expected) | 28 | c.Check(*dp, equals, expected) | |
29 | c.Check(parser.Rest(), equals, rest) | 29 | c.Check(parser.Rest(), equals, rest) | |
30 | } | 30 | } | |
31 | } | 31 | } | |
32 | check := func(pattern string, expected DependencyPattern) { | 32 | check := func(pattern string, expected DependencyPattern) { | |
33 | checkRest(pattern, expected, "") | 33 | checkRest(pattern, expected, "") | |
34 | } | 34 | } | |
35 | 35 | |||
@@ -40,36 +40,13 @@ func (s *Suite) TestParser_Dependency(c | @@ -40,36 +40,13 @@ func (s *Suite) TestParser_Dependency(c | |||
40 | check("boost-build-1.59.*", DependencyPattern{"boost-build", "", "", "", "", "1.59.*"}) | 40 | check("boost-build-1.59.*", DependencyPattern{"boost-build", "", "", "", "", "1.59.*"}) | |
41 | check("${_EMACS_REQD}", DependencyPattern{"${_EMACS_REQD}", "", "", "", "", ""}) | 41 | check("${_EMACS_REQD}", DependencyPattern{"${_EMACS_REQD}", "", "", "", "", ""}) | |
42 | check("{gcc46,gcc46-libs}>=4.6.0", DependencyPattern{"{gcc46,gcc46-libs}", ">=", "4.6.0", "", "", ""}) | 42 | check("{gcc46,gcc46-libs}>=4.6.0", DependencyPattern{"{gcc46,gcc46-libs}", ">=", "4.6.0", "", "", ""}) | |
43 | check("perl5-*", DependencyPattern{"perl5", "", "", "", "", "*"}) | 43 | check("perl5-*", DependencyPattern{"perl5", "", "", "", "", "*"}) | |
44 | check("verilog{,-current}-[0-9]*", DependencyPattern{"verilog{,-current}", "", "", "", "", "[0-9]*"}) | 44 | check("verilog{,-current}-[0-9]*", DependencyPattern{"verilog{,-current}", "", "", "", "", "[0-9]*"}) | |
45 | check("mpg123{,-esound,-nas}>=0.59.18", DependencyPattern{"mpg123{,-esound,-nas}", ">=", "0.59.18", "", "", ""}) | 45 | check("mpg123{,-esound,-nas}>=0.59.18", DependencyPattern{"mpg123{,-esound,-nas}", ">=", "0.59.18", "", "", ""}) | |
46 | check("mysql*-{client,server}-[0-9]*", DependencyPattern{"mysql*-{client,server}", "", "", "", "", "[0-9]*"}) | 46 | check("mysql*-{client,server}-[0-9]*", DependencyPattern{"mysql*-{client,server}", "", "", "", "", "[0-9]*"}) | |
47 | check("postgresql8[0-35-9]-${module}-[0-9]*", DependencyPattern{"postgresql8[0-35-9]-${module}", "", "", "", "", "[0-9]*"}) | 47 | check("postgresql8[0-35-9]-${module}-[0-9]*", DependencyPattern{"postgresql8[0-35-9]-${module}", "", "", "", "", "[0-9]*"}) | |
48 | check("ncurses-${NC_VERS}{,nb*}", DependencyPattern{"ncurses", "", "", "", "", "${NC_VERS}{,nb*}"}) | 48 | check("ncurses-${NC_VERS}{,nb*}", DependencyPattern{"ncurses", "", "", "", "", "${NC_VERS}{,nb*}"}) | |
49 | check("xulrunner10>=${MOZ_BRANCH}${MOZ_BRANCH_MINOR}", DependencyPattern{"xulrunner10", ">=", "${MOZ_BRANCH}${MOZ_BRANCH_MINOR}", "", "", ""}) | 49 | check("xulrunner10>=${MOZ_BRANCH}${MOZ_BRANCH_MINOR}", DependencyPattern{"xulrunner10", ">=", "${MOZ_BRANCH}${MOZ_BRANCH_MINOR}", "", "", ""}) | |
50 | checkRest("gnome-control-center>=2.20.1{,nb*}", DependencyPattern{"gnome-control-center", ">=", "2.20.1", "", "", ""}, "{,nb*}") | 50 | checkRest("gnome-control-center>=2.20.1{,nb*}", DependencyPattern{"gnome-control-center", ">=", "2.20.1", "", "", ""}, "{,nb*}") | |
51 | // "{ssh{,6}-[0-9]*,openssh-[0-9]*}" is not representable using the current data structure | 51 | // "{ssh{,6}-[0-9]*,openssh-[0-9]*}" is not representable using the current data structure | |
52 | } | 52 | } | |
53 | ||||
54 | // @Beta | |||
55 | func (s *Suite) Test_Parser_ShAst(c *check.C) { | |||
56 | f := func(args ...interface{}) interface{} { return nil } | |||
57 | Commands := f | |||
58 | Command := f | |||
59 | Arg := f | |||
60 | Varuse := f | |||
61 | Varassign := f | |||
62 | Subshell := f | |||
63 | Pipe := f | |||
64 | ||||
65 | _ = "cd ${WRKSRC}/doc/man/man3; PAGES=\"`ls -1 | ${SED} -e 's,3qt$$,3,'`\";" | |||
66 | ||||
67 | Commands( | |||
68 | Command("cd", | |||
69 | Arg(Varuse("WRKSRC"), "/doc/man/man3")), | |||
70 | Varassign("PAGES", Subshell( | |||
71 | Pipe( | |||
72 | Command("ls", "-1"), | |||
73 | Command(Varuse("SED"), "-e", "s,3qt$,3,"))))) | |||
74 | ||||
75 | } |
@@ -1,42 +1,42 @@ | @@ -1,42 +1,42 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | "io/ioutil" | 5 | "io/ioutil" | |
6 | ) | 6 | ) | |
7 | 7 | |||
8 | func (s *Suite) TestChecklinesPatch_WithComment(c *check.C) { | 8 | func (s *Suite) Test_ChecklinesPatch__with_comment(c *check.C) { | |
9 | s.UseCommandLine(c, "-Wall") | 9 | s.UseCommandLine(c, "-Wall") | |
10 | lines := s.NewLines("patch-WithComment", | 10 | lines := s.NewLines("patch-WithComment", | |
11 | "$"+"NetBSD$", | 11 | "$"+"NetBSD$", | |
12 | "", | 12 | "", | |
13 | "Text", | 13 | "Text", | |
14 | "Text", | 14 | "Text", | |
15 | "", | 15 | "", | |
16 | "--- file.orig", | 16 | "--- file.orig", | |
17 | "+++ file", | 17 | "+++ file", | |
18 | "@@ -5,3 +5,3 @@", | 18 | "@@ -5,3 +5,3 @@", | |
19 | " context before", | 19 | " context before", | |
20 | "-old line", | 20 | "-old line", | |
21 | "+old line", | 21 | "+old line", | |
22 | " context after") | 22 | " context after") | |
23 | 23 | |||
24 | ChecklinesPatch(lines) | 24 | ChecklinesPatch(lines) | |
25 | 25 | |||
26 | c.Check(s.Output(), equals, "") | 26 | c.Check(s.Output(), equals, "") | |
27 | } | 27 | } | |
28 | 28 | |||
29 | func (s *Suite) TestChecklinesPatch_WithoutEmptyLine(c *check.C) { | 29 | func (s *Suite) Test_ChecklinesPatch__without_empty_line(c *check.C) { | |
30 | fname := s.CreateTmpFile(c, "patch-WithoutEmptyLines", "dummy") | 30 | fname := s.CreateTmpFile(c, "patch-WithoutEmptyLines", "dummy") | |
31 | s.UseCommandLine(c, "-Wall", "--autofix") | 31 | s.UseCommandLine(c, "-Wall", "--autofix") | |
32 | lines := s.NewLines(fname, | 32 | lines := s.NewLines(fname, | |
33 | "$"+"NetBSD$", | 33 | "$"+"NetBSD$", | |
34 | "Text", | 34 | "Text", | |
35 | "--- file.orig", | 35 | "--- file.orig", | |
36 | "+++ file", | 36 | "+++ file", | |
37 | "@@ -5,3 +5,3 @@", | 37 | "@@ -5,3 +5,3 @@", | |
38 | " context before", | 38 | " context before", | |
39 | "-old line", | 39 | "-old line", | |
40 | "+old line", | 40 | "+old line", | |
41 | " context after") | 41 | " context after") | |
42 | 42 | |||
@@ -53,187 +53,207 @@ func (s *Suite) TestChecklinesPatch_With | @@ -53,187 +53,207 @@ func (s *Suite) TestChecklinesPatch_With | |||
53 | "$"+"NetBSD$\n"+ | 53 | "$"+"NetBSD$\n"+ | |
54 | "\n"+ | 54 | "\n"+ | |
55 | "Text\n"+ | 55 | "Text\n"+ | |
56 | "\n"+ | 56 | "\n"+ | |
57 | "--- file.orig\n"+ | 57 | "--- file.orig\n"+ | |
58 | "+++ file\n"+ | 58 | "+++ file\n"+ | |
59 | "@@ -5,3 +5,3 @@\n"+ | 59 | "@@ -5,3 +5,3 @@\n"+ | |
60 | " context before\n"+ | 60 | " context before\n"+ | |
61 | "-old line\n"+ | 61 | "-old line\n"+ | |
62 | "+old line\n"+ | 62 | "+old line\n"+ | |
63 | " context after\n") | 63 | " context after\n") | |
64 | } | 64 | } | |
65 | 65 | |||
66 | func (s *Suite) TestChecklinesPatch_WithoutComment(c *check.C) { | 66 | func (s *Suite) Test_ChecklinesPatch__without_comment(c *check.C) { | |
67 | s.UseCommandLine(c, "-Wall") | 67 | s.UseCommandLine(c, "-Wall") | |
68 | lines := s.NewLines("patch-WithoutComment", | 68 | lines := s.NewLines("patch-WithoutComment", | |
69 | "$"+"NetBSD$", | 69 | "$"+"NetBSD$", | |
70 | "", | 70 | "", | |
71 | "--- file.orig", | 71 | "--- file.orig", | |
72 | "+++ file", | 72 | "+++ file", | |
73 | "@@ -5,3 +5,3 @@", | 73 | "@@ -5,3 +5,3 @@", | |
74 | " context before", | 74 | " context before", | |
75 | "-old line", | 75 | "-old line", | |
76 | "+old line", | 76 | "+old line", | |
77 | " context after") | 77 | " context after") | |
78 | 78 | |||
79 | ChecklinesPatch(lines) | 79 | ChecklinesPatch(lines) | |
80 | 80 | |||
81 | c.Check(s.Output(), equals, "ERROR: patch-WithoutComment:3: Each patch must be documented.\n") | 81 | c.Check(s.Output(), equals, "ERROR: patch-WithoutComment:3: Each patch must be documented.\n") | |
82 | } | 82 | } | |
83 | 83 | |||
84 | func (s *Suite) TestChecklineOtherAbsolutePathname(c *check.C) { | 84 | func (s *Suite) Test_ChecklinesPatch__git_without_comment(c *check.C) { | |
85 | s.UseCommandLine(c, "-Wall") | |||
86 | lines := s.NewLines("patch-aa", | |||
87 | "$"+"NetBSD$", | |||
88 | "", | |||
89 | "diff --git a/aa b/aa", | |||
90 | "index 1234567..1234567 100644", | |||
91 | "--- a/aa", | |||
92 | "+++ b/aa", | |||
93 | "@@ -1,1 +1,1 @@", | |||
94 | "-old", | |||
95 | "+new") | |||
96 | ||||
97 | ChecklinesPatch(lines) | |||
98 | ||||
99 | c.Check(s.Output(), equals, "ERROR: patch-aa:5: Each patch must be documented.\n") | |||
100 | } | |||
101 | ||||
102 | func (s *Suite) Test_checklineOtherAbsolutePathname(c *check.C) { | |||
85 | line := NewLine("patch-ag", 1, "+$install -s -c ./bin/rosegarden ${DESTDIR}$BINDIR", nil) | 103 | line := NewLine("patch-ag", 1, "+$install -s -c ./bin/rosegarden ${DESTDIR}$BINDIR", nil) | |
86 | 104 | |||
87 | checklineOtherAbsolutePathname(line, line.Text) | 105 | checklineOtherAbsolutePathname(line, line.Text) | |
88 | 106 | |||
89 | c.Check(s.Output(), equals, "") | 107 | c.Check(s.Output(), equals, "") | |
90 | } | 108 | } | |
91 | 109 | |||
92 | func (s *Suite) TestChecklinesPatch_ErrorCode(c *check.C) { | 110 | func (s *Suite) Test_ChecklinesPatch__error_code(c *check.C) { | |
93 | s.UseCommandLine(c, "-Wall") | 111 | s.UseCommandLine(c, "-Wall") | |
94 | lines := s.NewLines("patch-ErrorCode", | 112 | lines := s.NewLines("patch-ErrorCode", | |
95 | "$"+"NetBSD$", | 113 | "$"+"NetBSD$", | |
96 | "", | 114 | "", | |
97 | "*** Error code 1", // Looks like a context diff, but isn’t. | 115 | "*** Error code 1", // Looks like a context diff, but isn’t. | |
98 | "", | 116 | "", | |
99 | "--- file.orig", | 117 | "--- file.orig", | |
100 | "+++ file", | 118 | "+++ file", | |
101 | "@@ -5,3 +5,3 @@", | 119 | "@@ -5,3 +5,3 @@", | |
102 | " context before", | 120 | " context before", | |
103 | "-old line", | 121 | "-old line", | |
104 | "+old line", | 122 | "+old line", | |
105 | " context after") | 123 | " context after") | |
106 | 124 | |||
107 | ChecklinesPatch(lines) | 125 | ChecklinesPatch(lines) | |
108 | 126 | |||
109 | c.Check(s.Output(), equals, "") | 127 | c.Check(s.Output(), equals, "") | |
110 | } | 128 | } | |
111 | 129 | |||
112 | func (s *Suite) TestChecklinesPatch_WrongOrder(c *check.C) { | 130 | func (s *Suite) Test_ChecklinesPatch__wrong_header_order(c *check.C) { | |
113 | s.UseCommandLine(c, "-Wall") | 131 | s.UseCommandLine(c, "-Wall") | |
114 | lines := s.NewLines("patch-WrongOrder", | 132 | lines := s.NewLines("patch-WrongOrder", | |
115 | "$"+"NetBSD$", | 133 | "$"+"NetBSD$", | |
116 | "", | 134 | "", | |
117 | "Text", | 135 | "Text", | |
118 | "Text", | 136 | "Text", | |
119 | "", | 137 | "", | |
120 | "+++ file", // Wrong | 138 | "+++ file", // Wrong | |
121 | "--- file.orig", // Wrong | 139 | "--- file.orig", // Wrong | |
122 | "@@ -5,3 +5,3 @@", | 140 | "@@ -5,3 +5,3 @@", | |
123 | " context before", | 141 | " context before", | |
124 | "-old line", | 142 | "-old line", | |
125 | "+old line", | 143 | "+old line", | |
126 | " context after") | 144 | " context after") | |
127 | 145 | |||
128 | ChecklinesPatch(lines) | 146 | ChecklinesPatch(lines) | |
129 | 147 | |||
130 | c.Check(s.Output(), equals, "WARN: patch-WrongOrder:7: Unified diff headers should be first ---, then +++.\n") | 148 | c.Check(s.Output(), equals, "WARN: patch-WrongOrder:7: Unified diff headers should be first ---, then +++.\n") | |
131 | } | 149 | } | |
132 | 150 | |||
133 | func (s *Suite) TestChecklinesPatch_ContextDiff(c *check.C) { | 151 | func (s *Suite) Test_ChecklinesPatch__context_diff(c *check.C) { | |
134 | s.UseCommandLine(c, "-Wall") | 152 | s.UseCommandLine(c, "-Wall") | |
135 | lines := s.NewLines("patch-ctx", | 153 | lines := s.NewLines("patch-ctx", | |
136 | "$"+"NetBSD$", | 154 | "$"+"NetBSD$", | |
137 | "", | 155 | "", | |
138 | "diff -cr history.c.orig history.c", | 156 | "diff -cr history.c.orig history.c", | |
139 | "*** history.c.orig", | 157 | "*** history.c.orig", | |
140 | "--- history.c") | 158 | "--- history.c") | |
141 | 159 | |||
142 | ChecklinesPatch(lines) | 160 | ChecklinesPatch(lines) | |
143 | 161 | |||
144 | c.Check(s.Output(), equals, ""+ | 162 | c.Check(s.Output(), equals, ""+ | |
145 | "ERROR: patch-ctx:4: Each patch must be documented.\n"+ | 163 | "ERROR: patch-ctx:4: Each patch must be documented.\n"+ | |
146 | "WARN: patch-ctx:4: Please use unified diffs (diff -u) for patches.\n") | 164 | "WARN: patch-ctx:4: Please use unified diffs (diff -u) for patches.\n") | |
147 | } | 165 | } | |
148 | 166 | |||
149 | func (s *Suite) TestChecklinesPatch_NoPatch(c *check.C) { | 167 | func (s *Suite) Test_ChecklinesPatch__no_patch(c *check.C) { | |
150 | lines := s.NewLines("patch-aa", | 168 | lines := s.NewLines("patch-aa", | |
151 | "$"+"NetBSD$", | 169 | "$"+"NetBSD$", | |
152 | "", | 170 | "", | |
153 | "-- oldfile", | 171 | "-- oldfile", | |
154 | "++ newfile") | 172 | "++ newfile") | |
155 | 173 | |||
156 | ChecklinesPatch(lines) | 174 | ChecklinesPatch(lines) | |
157 | 175 | |||
158 | c.Check(s.Output(), equals, "ERROR: patch-aa: Contains no patch.\n") | 176 | c.Check(s.Output(), equals, "ERROR: patch-aa: Contains no patch.\n") | |
159 | } | 177 | } | |
160 | 178 | |||
161 | func (s *Suite) TestChecklinesPatch_TwoPatches(c *check.C) { | 179 | func (s *Suite) Test_ChecklinesPatch__two_patched_files(c *check.C) { | |
162 | lines := s.NewLines("patch-aa", | 180 | lines := s.NewLines("patch-aa", | |
163 | "$"+"NetBSD$", | 181 | "$"+"NetBSD$", | |
164 | "", | 182 | "", | |
165 | "--- oldfile", | 183 | "--- oldfile", | |
166 | "+++ newfile", | 184 | "+++ newfile", | |
167 | "@@ -1 +1 @@", | 185 | "@@ -1 +1 @@", | |
168 | "-old", | 186 | "-old", | |
169 | "+new", | 187 | "+new", | |
170 | "--- oldfile2", | 188 | "--- oldfile2", | |
171 | "+++ newfile2", | 189 | "+++ newfile2", | |
172 | "@@ -1 +1 @@", | 190 | "@@ -1 +1 @@", | |
173 | "-old", | 191 | "-old", | |
174 | "+new") | 192 | "+new") | |
175 | 193 | |||
176 | ChecklinesPatch(lines) | 194 | ChecklinesPatch(lines) | |
177 | 195 | |||
178 | c.Check(s.Output(), equals, ""+ | 196 | c.Check(s.Output(), equals, ""+ | |
179 | "ERROR: patch-aa:3: Each patch must be documented.\n"+ | 197 | "ERROR: patch-aa:3: Each patch must be documented.\n"+ | |
180 | "WARN: patch-aa: Contains patches for 2 files, should be only one.\n") | 198 | "WARN: patch-aa: Contains patches for 2 files, should be only one.\n") | |
181 | } | 199 | } | |
182 | 200 | |||
183 | func (s *Suite) TestChecklinesPatch_PatchlikeDocumentation(c *check.C) { | 201 | func (s *Suite) Test_ChecklinesPatch__documentation_that_looks_like_patch_lines(c *check.C) { | |
184 | lines := s.NewLines("patch-aa", | 202 | lines := s.NewLines("patch-aa", | |
185 | "$"+"NetBSD$", | 203 | "$"+"NetBSD$", | |
186 | "", | 204 | "", | |
187 | "--- oldfile", | 205 | "--- oldfile", | |
188 | "", | 206 | "", | |
189 | "+++ newfile", | 207 | "+++ newfile", | |
190 | "", | 208 | "", | |
191 | "*** oldOrNewFile") | 209 | "*** oldOrNewFile") | |
192 | 210 | |||
193 | ChecklinesPatch(lines) | 211 | ChecklinesPatch(lines) | |
194 | 212 | |||
195 | c.Check(s.Output(), equals, "ERROR: patch-aa: Contains no patch.\n") | 213 | c.Check(s.Output(), equals, "ERROR: patch-aa: Contains no patch.\n") | |
196 | } | 214 | } | |
197 | 215 | |||
198 | func (s *Suite) TestChecklinesPatch_OnlyUnifiedHeader(c *check.C) { | 216 | func (s *Suite) Test_ChecklinesPatch__only_unified_header_but_no_content(c *check.C) { | |
199 | lines := s.NewLines("patch-unified", | 217 | lines := s.NewLines("patch-unified", | |
200 | "$"+"NetBSD$", | 218 | "$"+"NetBSD$", | |
201 | "", | 219 | "", | |
202 | "Documentation for the patch", | 220 | "Documentation for the patch", | |
203 | "", | 221 | "", | |
204 | "--- file.orig", | 222 | "--- file.orig", | |
205 | "+++ file") | 223 | "+++ file") | |
206 | 224 | |||
207 | ChecklinesPatch(lines) | 225 | ChecklinesPatch(lines) | |
208 | 226 | |||
209 | c.Check(s.Output(), equals, "ERROR: patch-unified:EOF: No patch hunks for \"file\".\n") | 227 | c.Check(s.Output(), equals, "ERROR: patch-unified:EOF: No patch hunks for \"file\".\n") | |
210 | } | 228 | } | |
211 | 229 | |||
212 | func (s *Suite) TestChecklinesPatch_OnlyContextHeader(c *check.C) { | 230 | func (s *Suite) Test_ChecklinesPatch__only_context_header_but_no_content(c *check.C) { | |
213 | lines := s.NewLines("patch-context", | 231 | lines := s.NewLines("patch-context", | |
214 | "$"+"NetBSD$", | 232 | "$"+"NetBSD$", | |
215 | "", | 233 | "", | |
216 | "Documentation for the patch", | 234 | "Documentation for the patch", | |
217 | "", | 235 | "", | |
218 | "*** file.orig", | 236 | "*** file.orig", | |
219 | "--- file") | 237 | "--- file") | |
220 | 238 | |||
221 | ChecklinesPatch(lines) | 239 | ChecklinesPatch(lines) | |
222 | 240 | |||
241 | // Context diffs are deprecated, therefore it is not worth | |||
242 | // adding extra code for checking them thoroughly. | |||
223 | c.Check(s.Output(), equals, "WARN: patch-context:5: Please use unified diffs (diff -u) for patches.\n") | 243 | c.Check(s.Output(), equals, "WARN: patch-context:5: Please use unified diffs (diff -u) for patches.\n") | |
224 | } | 244 | } | |
225 | 245 | |||
226 | func (s *Suite) TestChecklinesPatch_Makefile(c *check.C) { | 246 | func (s *Suite) Test_ChecklinesPatch__Makefile_with_absolute_pathnames(c *check.C) { | |
227 | lines := s.NewLines("patch-unified", | 247 | lines := s.NewLines("patch-unified", | |
228 | "$"+"NetBSD$", | 248 | "$"+"NetBSD$", | |
229 | "", | 249 | "", | |
230 | "Documentation for the patch", | 250 | "Documentation for the patch", | |
231 | "", | 251 | "", | |
232 | "--- Makefile.orig", | 252 | "--- Makefile.orig", | |
233 | "+++ Makefile", | 253 | "+++ Makefile", | |
234 | "@@ -1,3 +1,7 @@", | 254 | "@@ -1,3 +1,7 @@", | |
235 | " \t/bin/cp context before", | 255 | " \t/bin/cp context before", | |
236 | "-\t/bin/cp deleted", | 256 | "-\t/bin/cp deleted", | |
237 | "+\t/bin/cp added", | 257 | "+\t/bin/cp added", | |
238 | "+#\t/bin/cp added comment", | 258 | "+#\t/bin/cp added comment", | |
239 | "+# added comment", | 259 | "+# added comment", | |
@@ -248,89 +268,89 @@ func (s *Suite) TestChecklinesPatch_Make | @@ -248,89 +268,89 @@ func (s *Suite) TestChecklinesPatch_Make | |||
248 | "WARN: patch-unified:13: Found absolute pathname: /bin/cp\n") | 268 | "WARN: patch-unified:13: Found absolute pathname: /bin/cp\n") | |
249 | 269 | |||
250 | G.opts.WarnExtra = true | 270 | G.opts.WarnExtra = true | |
251 | 271 | |||
252 | ChecklinesPatch(lines) | 272 | ChecklinesPatch(lines) | |
253 | 273 | |||
254 | c.Check(s.Output(), equals, ""+ | 274 | c.Check(s.Output(), equals, ""+ | |
255 | "WARN: patch-unified:8: Found absolute pathname: /bin/cp\n"+ | 275 | "WARN: patch-unified:8: Found absolute pathname: /bin/cp\n"+ | |
256 | "WARN: patch-unified:10: Found absolute pathname: /bin/cp\n"+ | 276 | "WARN: patch-unified:10: Found absolute pathname: /bin/cp\n"+ | |
257 | "WARN: patch-unified:13: Found absolute pathname: /bin/cp\n"+ | 277 | "WARN: patch-unified:13: Found absolute pathname: /bin/cp\n"+ | |
258 | "WARN: patch-unified:15: Found absolute pathname: /bin/cp\n") | 278 | "WARN: patch-unified:15: Found absolute pathname: /bin/cp\n") | |
259 | } | 279 | } | |
260 | 280 | |||
261 | func (s *Suite) TestChecklinesPatch_NoNewline_withFollowingText(c *check.C) { | 281 | func (s *Suite) Test_ChecklinesPatch__no_newline_with_text_following(c *check.C) { | |
262 | lines := s.NewLines("patch-aa", | 282 | lines := s.NewLines("patch-aa", | |
263 | "$"+"NetBSD$", | 283 | "$"+"NetBSD$", | |
264 | "", | 284 | "", | |
265 | "comment", | 285 | "comment", | |
266 | "", | 286 | "", | |
267 | "--- oldfile", | 287 | "--- oldfile", | |
268 | "+++ newfile", | 288 | "+++ newfile", | |
269 | "@@ -1 +1 @@", | 289 | "@@ -1 +1 @@", | |
270 | "-old", | 290 | "-old", | |
271 | "\\ No newline at end of file", | 291 | "\\ No newline at end of file", | |
272 | "+new", | 292 | "+new", | |
273 | "\\ No newline at end of file", | 293 | "\\ No newline at end of file", | |
274 | "last line (a comment)") | 294 | "last line (a comment)") | |
275 | 295 | |||
276 | ChecklinesPatch(lines) | 296 | ChecklinesPatch(lines) | |
277 | 297 | |||
278 | c.Check(s.Output(), equals, "WARN: patch-aa:12: Empty line or end of file expected.\n") | 298 | c.Check(s.Output(), equals, "WARN: patch-aa:12: Empty line or end of file expected.\n") | |
279 | } | 299 | } | |
280 | 300 | |||
281 | func (s *Suite) TestChecklinesPatch_NoNewline(c *check.C) { | 301 | func (s *Suite) Test_ChecklinesPatch__no_newline(c *check.C) { | |
282 | lines := s.NewLines("patch-aa", | 302 | lines := s.NewLines("patch-aa", | |
283 | "$"+"NetBSD$", | 303 | "$"+"NetBSD$", | |
284 | "", | 304 | "", | |
285 | "comment", | 305 | "comment", | |
286 | "", | 306 | "", | |
287 | "--- oldfile", | 307 | "--- oldfile", | |
288 | "+++ newfile", | 308 | "+++ newfile", | |
289 | "@@ -1 +1 @@", | 309 | "@@ -1 +1 @@", | |
290 | "-old", | 310 | "-old", | |
291 | "\\ No newline at end of file", | 311 | "\\ No newline at end of file", | |
292 | "+new", | 312 | "+new", | |
293 | "\\ No newline at end of file") | 313 | "\\ No newline at end of file") | |
294 | 314 | |||
295 | ChecklinesPatch(lines) | 315 | ChecklinesPatch(lines) | |
296 | 316 | |||
297 | c.Check(s.Output(), equals, "") | 317 | c.Check(s.Output(), equals, "") | |
298 | } | 318 | } | |
299 | 319 | |||
300 | func (s *Suite) TestChecklinesPatch_ShortAtEof(c *check.C) { | 320 | func (s *Suite) Test_ChecklinesPatch__empty_lines_left_out_at_eof(c *check.C) { | |
301 | lines := s.NewLines("patch-aa", | 321 | lines := s.NewLines("patch-aa", | |
302 | "$"+"NetBSD$", | 322 | "$"+"NetBSD$", | |
303 | "", | 323 | "", | |
304 | "comment", | 324 | "comment", | |
305 | "", | 325 | "", | |
306 | "--- oldfile", | 326 | "--- oldfile", | |
307 | "+++ newfile", | 327 | "+++ newfile", | |
308 | "@@ -1,7 +1,6 @@", | 328 | "@@ -1,7 +1,6 @@", | |
309 | " 1", | 329 | " 1", | |
310 | " 2", | 330 | " 2", | |
311 | " 3", | 331 | " 3", | |
312 | "-4", | 332 | "-4", | |
313 | " 5", | 333 | " 5", | |
314 | " 6") // Line 7 was empty, therefore omitted | 334 | " 6") // Line 7 was empty, therefore omitted | |
315 | 335 | |||
316 | ChecklinesPatch(lines) | 336 | ChecklinesPatch(lines) | |
317 | 337 | |||
318 | c.Check(s.Output(), equals, "") | 338 | c.Check(s.Output(), equals, "") | |
319 | } | 339 | } | |
320 | 340 | |||
321 | // In some context lines, the leading space character is missing. | 341 | // In some context lines, the leading space character is missing. | |
322 | // Since this is no problem for patch(1), pkglint also doesn’t complain. | 342 | // Since this is no problem for patch(1), pkglint also doesn’t complain. | |
323 | func (s *Suite) TestChecklinesPatch_AddTab(c *check.C) { | 343 | func (s *Suite) Test_ChecklinesPatch__context_lines_with_tab_instead_of_space(c *check.C) { | |
324 | lines := s.NewLines("patch-aa", | 344 | lines := s.NewLines("patch-aa", | |
325 | "$"+"NetBSD$", | 345 | "$"+"NetBSD$", | |
326 | "", | 346 | "", | |
327 | "comment", | 347 | "comment", | |
328 | "", | 348 | "", | |
329 | "--- oldfile", | 349 | "--- oldfile", | |
330 | "+++ newfile", | 350 | "+++ newfile", | |
331 | "@@ -1,3 +1,3 @@", | 351 | "@@ -1,3 +1,3 @@", | |
332 | "\tcontext", | 352 | "\tcontext", | |
333 | "-old", | 353 | "-old", | |
334 | "+new", | 354 | "+new", | |
335 | "\tcontext") | 355 | "\tcontext") | |
336 | 356 |
@@ -1,82 +1,82 @@ | @@ -1,82 +1,82 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestSubstContext_Incomplete(c *check.C) { | 7 | func (s *Suite) Test_SubstContext__incomplete(c *check.C) { | |
8 | G.opts.WarnExtra = true | 8 | G.opts.WarnExtra = true | |
9 | ctx := new(SubstContext) | 9 | ctx := new(SubstContext) | |
10 | 10 | |||
11 | ctx.Varassign(newSubstLine(10, "PKGNAME=pkgname-1.0")) | 11 | ctx.Varassign(newSubstLine(10, "PKGNAME=pkgname-1.0")) | |
12 | 12 | |||
13 | c.Check(ctx.id, equals, "") | 13 | c.Check(ctx.id, equals, "") | |
14 | 14 | |||
15 | ctx.Varassign(newSubstLine(11, "SUBST_CLASSES+=interp")) | 15 | ctx.Varassign(newSubstLine(11, "SUBST_CLASSES+=interp")) | |
16 | 16 | |||
17 | c.Check(ctx.id, equals, "interp") | 17 | c.Check(ctx.id, equals, "interp") | |
18 | 18 | |||
19 | ctx.Varassign(newSubstLine(12, "SUBST_FILES.interp=Makefile")) | 19 | ctx.Varassign(newSubstLine(12, "SUBST_FILES.interp=Makefile")) | |
20 | 20 | |||
21 | c.Check(ctx.IsComplete(), equals, false) | 21 | c.Check(ctx.IsComplete(), equals, false) | |
22 | 22 | |||
23 | ctx.Varassign(newSubstLine(13, "SUBST_SED.interp=s,@PREFIX@,${PREFIX},g")) | 23 | ctx.Varassign(newSubstLine(13, "SUBST_SED.interp=s,@PREFIX@,${PREFIX},g")) | |
24 | 24 | |||
25 | c.Check(ctx.IsComplete(), equals, false) | 25 | c.Check(ctx.IsComplete(), equals, false) | |
26 | 26 | |||
27 | ctx.Finish(newSubstLine(14, "")) | 27 | ctx.Finish(newSubstLine(14, "")) | |
28 | 28 | |||
29 | c.Check(s.Output(), equals, "WARN: Makefile:14: Incomplete SUBST block: SUBST_STAGE.interp missing.\n") | 29 | c.Check(s.Output(), equals, "WARN: Makefile:14: Incomplete SUBST block: SUBST_STAGE.interp missing.\n") | |
30 | } | 30 | } | |
31 | 31 | |||
32 | func (s *Suite) TestSubstContext_Complete(c *check.C) { | 32 | func (s *Suite) Test_SubstContext__complete(c *check.C) { | |
33 | G.opts.WarnExtra = true | 33 | G.opts.WarnExtra = true | |
34 | ctx := new(SubstContext) | 34 | ctx := new(SubstContext) | |
35 | 35 | |||
36 | ctx.Varassign(newSubstLine(10, "PKGNAME=pkgname-1.0")) | 36 | ctx.Varassign(newSubstLine(10, "PKGNAME=pkgname-1.0")) | |
37 | ctx.Varassign(newSubstLine(11, "SUBST_CLASSES+=p")) | 37 | ctx.Varassign(newSubstLine(11, "SUBST_CLASSES+=p")) | |
38 | ctx.Varassign(newSubstLine(12, "SUBST_FILES.p=Makefile")) | 38 | ctx.Varassign(newSubstLine(12, "SUBST_FILES.p=Makefile")) | |
39 | ctx.Varassign(newSubstLine(13, "SUBST_SED.p=s,@PREFIX@,${PREFIX},g")) | 39 | ctx.Varassign(newSubstLine(13, "SUBST_SED.p=s,@PREFIX@,${PREFIX},g")) | |
40 | 40 | |||
41 | c.Check(ctx.IsComplete(), equals, false) | 41 | c.Check(ctx.IsComplete(), equals, false) | |
42 | 42 | |||
43 | ctx.Varassign(newSubstLine(14, "SUBST_STAGE.p=post-configure")) | 43 | ctx.Varassign(newSubstLine(14, "SUBST_STAGE.p=post-configure")) | |
44 | 44 | |||
45 | c.Check(ctx.IsComplete(), equals, true) | 45 | c.Check(ctx.IsComplete(), equals, true) | |
46 | 46 | |||
47 | ctx.Finish(newSubstLine(15, "")) | 47 | ctx.Finish(newSubstLine(15, "")) | |
48 | 48 | |||
49 | c.Check(s.Output(), equals, "") | 49 | c.Check(s.Output(), equals, "") | |
50 | } | 50 | } | |
51 | 51 | |||
52 | func (s *Suite) Test_SubstContext_OPSYSVARS(c *check.C) { | 52 | func (s *Suite) Test_SubstContext__OPSYSVARS(c *check.C) { | |
53 | G.opts.WarnExtra = true | 53 | G.opts.WarnExtra = true | |
54 | ctx := new(SubstContext) | 54 | ctx := new(SubstContext) | |
55 | 55 | |||
56 | ctx.Varassign(newSubstLine(11, "SUBST_CLASSES.SunOS+=prefix")) | 56 | ctx.Varassign(newSubstLine(11, "SUBST_CLASSES.SunOS+=prefix")) | |
57 | ctx.Varassign(newSubstLine(12, "SUBST_CLASSES.NetBSD+=prefix")) | 57 | ctx.Varassign(newSubstLine(12, "SUBST_CLASSES.NetBSD+=prefix")) | |
58 | ctx.Varassign(newSubstLine(13, "SUBST_FILES.prefix=Makefile")) | 58 | ctx.Varassign(newSubstLine(13, "SUBST_FILES.prefix=Makefile")) | |
59 | ctx.Varassign(newSubstLine(14, "SUBST_SED.prefix=s,@PREFIX@,${PREFIX},g")) | 59 | ctx.Varassign(newSubstLine(14, "SUBST_SED.prefix=s,@PREFIX@,${PREFIX},g")) | |
60 | ctx.Varassign(newSubstLine(15, "SUBST_STAGE.prefix=post-configure")) | 60 | ctx.Varassign(newSubstLine(15, "SUBST_STAGE.prefix=post-configure")) | |
61 | 61 | |||
62 | c.Check(ctx.IsComplete(), equals, true) | 62 | c.Check(ctx.IsComplete(), equals, true) | |
63 | 63 | |||
64 | ctx.Finish(newSubstLine(15, "")) | 64 | ctx.Finish(newSubstLine(15, "")) | |
65 | 65 | |||
66 | c.Check(s.Output(), equals, "") | 66 | c.Check(s.Output(), equals, "") | |
67 | } | 67 | } | |
68 | 68 | |||
69 | func (s *Suite) TestSubstContext_NoClass(c *check.C) { | 69 | func (s *Suite) Test_SubstContext__no_class(c *check.C) { | |
70 | s.UseCommandLine(c, "-Wextra") | 70 | s.UseCommandLine(c, "-Wextra") | |
71 | ctx := new(SubstContext) | 71 | ctx := new(SubstContext) | |
72 | 72 | |||
73 | ctx.Varassign(newSubstLine(10, "UNRELATED=anything")) | 73 | ctx.Varassign(newSubstLine(10, "UNRELATED=anything")) | |
74 | ctx.Varassign(newSubstLine(11, "SUBST_FILES.repl+=Makefile.in")) | 74 | ctx.Varassign(newSubstLine(11, "SUBST_FILES.repl+=Makefile.in")) | |
75 | ctx.Varassign(newSubstLine(12, "SUBST_SED.repl+=-e s,from,to,g")) | 75 | ctx.Varassign(newSubstLine(12, "SUBST_SED.repl+=-e s,from,to,g")) | |
76 | ctx.Finish(newSubstLine(13, "")) | 76 | ctx.Finish(newSubstLine(13, "")) | |
77 | 77 | |||
78 | c.Check(s.Output(), equals, ""+ | 78 | c.Check(s.Output(), equals, ""+ | |
79 | "WARN: Makefile:11: SUBST_CLASSES should come before the definition of \"SUBST_FILES.repl\".\n"+ | 79 | "WARN: Makefile:11: SUBST_CLASSES should come before the definition of \"SUBST_FILES.repl\".\n"+ | |
80 | "WARN: Makefile:13: Incomplete SUBST block: SUBST_STAGE.repl missing.\n") | 80 | "WARN: Makefile:13: Incomplete SUBST block: SUBST_STAGE.repl missing.\n") | |
81 | } | 81 | } | |
82 | 82 |
@@ -1,91 +1,91 @@ | @@ -1,91 +1,91 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestGetopt_Short(c *check.C) { | 7 | func (s *Suite) Test_Options_Parse_short(c *check.C) { | |
8 | opts := NewOptions() | 8 | opts := NewOptions() | |
9 | var help bool | 9 | var help bool | |
10 | opts.AddFlagVar('h', "help", &help, false, "prints a help page") | 10 | opts.AddFlagVar('h', "help", &help, false, "prints a help page") | |
11 | 11 | |||
12 | args, err := opts.Parse([]string{"progname", "-h"}) | 12 | args, err := opts.Parse([]string{"progname", "-h"}) | |
13 | 13 | |||
14 | c.Assert(err, check.IsNil) | 14 | c.Assert(err, check.IsNil) | |
15 | c.Check(args, check.IsNil) | 15 | c.Check(args, check.IsNil) | |
16 | c.Check(help, equals, true) | 16 | c.Check(help, equals, true) | |
17 | } | 17 | } | |
18 | 18 | |||
19 | func (s *Suite) TestGetopt_UnknownShort(c *check.C) { | 19 | func (s *Suite) Test_Options_Parse_unknown_short(c *check.C) { | |
20 | opts := NewOptions() | 20 | opts := NewOptions() | |
21 | 21 | |||
22 | _, err := opts.Parse([]string{"progname", "-z"}) | 22 | _, err := opts.Parse([]string{"progname", "-z"}) | |
23 | 23 | |||
24 | c.Check(err.Error(), equals, "progname: unknown option: -z") | 24 | c.Check(err.Error(), equals, "progname: unknown option: -z") | |
25 | } | 25 | } | |
26 | 26 | |||
27 | func (s *Suite) TestGetopt_UnknownLong(c *check.C) { | 27 | func (s *Suite) Test_Options_Parse_unknown_long(c *check.C) { | |
28 | opts := NewOptions() | 28 | opts := NewOptions() | |
29 | 29 | |||
30 | _, err := opts.Parse([]string{"progname", "--unknown-long"}) | 30 | _, err := opts.Parse([]string{"progname", "--unknown-long"}) | |
31 | 31 | |||
32 | c.Check(err.Error(), equals, "progname: unknown option: --unknown-long") | 32 | c.Check(err.Error(), equals, "progname: unknown option: --unknown-long") | |
33 | } | 33 | } | |
34 | 34 | |||
35 | func (s *Suite) TestGetopt_UnknownFlagInGroup(c *check.C) { | 35 | func (s *Suite) Test_Options_Parse_unknown_flag_in_group(c *check.C) { | |
36 | opts := NewOptions() | 36 | opts := NewOptions() | |
37 | opts.AddFlagGroup('W', "warnings", "", "") | 37 | opts.AddFlagGroup('W', "warnings", "", "") | |
38 | 38 | |||
39 | _, err := opts.Parse([]string{"progname", "-Wall", "-Werror"}) | 39 | _, err := opts.Parse([]string{"progname", "-Wall", "-Werror"}) | |
40 | 40 | |||
41 | c.Check(err.Error(), equals, "progname: unknown option: -Werror") | 41 | c.Check(err.Error(), equals, "progname: unknown option: -Werror") | |
42 | 42 | |||
43 | _, err = opts.Parse([]string{"progname", "--warnings=all", "--warnings=no-error"}) | 43 | _, err = opts.Parse([]string{"progname", "--warnings=all", "--warnings=no-error"}) | |
44 | 44 | |||
45 | c.Check(err.Error(), equals, "progname: unknown option: --warnings=no-error") | 45 | c.Check(err.Error(), equals, "progname: unknown option: --warnings=no-error") | |
46 | 46 | |||
47 | _, err = opts.Parse([]string{"progname", "-W"}) | 47 | _, err = opts.Parse([]string{"progname", "-W"}) | |
48 | 48 | |||
49 | c.Check(err.Error(), equals, "progname: option requires an argument: -W") | 49 | c.Check(err.Error(), equals, "progname: option requires an argument: -W") | |
50 | } | 50 | } | |
51 | 51 | |||
52 | func (s *Suite) TestGetopt_AbbreviatedLong(c *check.C) { | 52 | func (s *Suite) Test_Options_Parse_abbreviated_long(c *check.C) { | |
53 | opts := NewOptions() | 53 | opts := NewOptions() | |
54 | var longFlag, longerFlag bool | 54 | var longFlag, longerFlag bool | |
55 | opts.AddFlagVar('?', "long", &longFlag, false, "") | 55 | opts.AddFlagVar('?', "long", &longFlag, false, "") | |
56 | opts.AddFlagVar('?', "longer", &longerFlag, false, "") | 56 | opts.AddFlagVar('?', "longer", &longerFlag, false, "") | |
57 | 57 | |||
58 | _, err := opts.Parse([]string{"progname", "--lo"}) | 58 | _, err := opts.Parse([]string{"progname", "--lo"}) | |
59 | 59 | |||
60 | c.Check(err.Error(), equals, "progname: ambiguous option: --lo could mean --long or --longer") | 60 | c.Check(err.Error(), equals, "progname: ambiguous option: --lo could mean --long or --longer") | |
61 | 61 | |||
62 | args, err := opts.Parse([]string{"progname", "--long"}) | 62 | args, err := opts.Parse([]string{"progname", "--long"}) | |
63 | 63 | |||
64 | c.Assert(err, check.IsNil) | 64 | c.Assert(err, check.IsNil) | |
65 | c.Check(args, check.IsNil) | 65 | c.Check(args, check.IsNil) | |
66 | c.Check(longFlag, equals, true) | 66 | c.Check(longFlag, equals, true) | |
67 | c.Check(longerFlag, equals, false) | 67 | c.Check(longerFlag, equals, false) | |
68 | 68 | |||
69 | longFlag = false | 69 | longFlag = false | |
70 | args, err = opts.Parse([]string{"progname", "--longe"}) | 70 | args, err = opts.Parse([]string{"progname", "--longe"}) | |
71 | 71 | |||
72 | c.Assert(err, check.IsNil) | 72 | c.Assert(err, check.IsNil) | |
73 | c.Check(args, check.IsNil) | 73 | c.Check(args, check.IsNil) | |
74 | c.Check(longFlag, equals, false) | 74 | c.Check(longFlag, equals, false) | |
75 | c.Check(longerFlag, equals, true) | 75 | c.Check(longerFlag, equals, true) | |
76 | } | 76 | } | |
77 | 77 | |||
78 | func (s *Suite) TestGetopt_MixedArgsAndOptions(c *check.C) { | 78 | func (s *Suite) Test_Options_Parse_mixed_args_and_options(c *check.C) { | |
79 | opts := NewOptions() | 79 | opts := NewOptions() | |
80 | var aflag, bflag bool | 80 | var aflag, bflag bool | |
81 | opts.AddFlagVar('a', "aflag", &aflag, false, "") | 81 | opts.AddFlagVar('a', "aflag", &aflag, false, "") | |
82 | opts.AddFlagVar('b', "bflag", &bflag, false, "") | 82 | opts.AddFlagVar('b', "bflag", &bflag, false, "") | |
83 | 83 | |||
84 | args, err := opts.Parse([]string{"progname", "-a", "arg1", "-b", "arg2"}) | 84 | args, err := opts.Parse([]string{"progname", "-a", "arg1", "-b", "arg2"}) | |
85 | 85 | |||
86 | c.Assert(err, check.IsNil) | 86 | c.Assert(err, check.IsNil) | |
87 | c.Check(args, check.DeepEquals, []string{"arg1", "arg2"}) | 87 | c.Check(args, check.DeepEquals, []string{"arg1", "arg2"}) | |
88 | c.Check(aflag, equals, true) | 88 | c.Check(aflag, equals, true) | |
89 | c.Check(bflag, equals, true) | 89 | c.Check(bflag, equals, true) | |
90 | 90 | |||
91 | aflag = false | 91 | aflag = false |
@@ -1,25 +1,25 @@ | @@ -1,25 +1,25 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestParseLicenses(c *check.C) { | 7 | func (s *Suite) Test_parseLicenses(c *check.C) { | |
8 | c.Check(parseLicenses("gnu-gpl-v2"), check.DeepEquals, []string{"gnu-gpl-v2"}) | 8 | c.Check(parseLicenses("gnu-gpl-v2"), check.DeepEquals, []string{"gnu-gpl-v2"}) | |
9 | c.Check(parseLicenses("AND artistic"), check.DeepEquals, []string{"artistic"}) | 9 | c.Check(parseLicenses("AND artistic"), check.DeepEquals, []string{"artistic"}) | |
10 | } | 10 | } | |
11 | 11 | |||
12 | func (s *Suite) TestChecklineLicense(c *check.C) { | 12 | func (s *Suite) Test_checklineLicense(c *check.C) { | |
13 | s.CreateTmpFile(c, "licenses/gnu-gpl-v2", "Most software \u2026") | 13 | s.CreateTmpFile(c, "licenses/gnu-gpl-v2", "Most software \u2026") | |
14 | mkline := NewMkLine(NewLine("Makefile", 7, "LICENSE=dummy", nil)) | 14 | mkline := NewMkLine(NewLine("Makefile", 7, "LICENSE=dummy", nil)) | |
15 | G.globalData.Pkgsrcdir = s.tmpdir | 15 | G.globalData.Pkgsrcdir = s.tmpdir | |
16 | G.CurrentDir = s.tmpdir | 16 | G.CurrentDir = s.tmpdir | |
17 | 17 | |||
18 | checklineLicense(mkline, "gpl-v2") | 18 | checklineLicense(mkline, "gpl-v2") | |
19 | 19 | |||
20 | c.Check(s.Output(), equals, "WARN: Makefile:7: License file ~/licenses/gpl-v2 does not exist.\n") | 20 | c.Check(s.Output(), equals, "WARN: Makefile:7: License file ~/licenses/gpl-v2 does not exist.\n") | |
21 | 21 | |||
22 | checklineLicense(mkline, "no-profit shareware") | 22 | checklineLicense(mkline, "no-profit shareware") | |
23 | 23 | |||
24 | c.Check(s.Output(), equals, ""+ | 24 | c.Check(s.Output(), equals, ""+ | |
25 | "WARN: Makefile:7: License file ~/licenses/no-profit does not exist.\n"+ | 25 | "WARN: Makefile:7: License file ~/licenses/no-profit does not exist.\n"+ |
@@ -1,20 +1,20 @@ | @@ -1,20 +1,20 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestCheckdirToplevel(c *check.C) { | 7 | func (s *Suite) Test_CheckdirToplevel(c *check.C) { | |
8 | s.CreateTmpFile(c, "Makefile", ""+ | 8 | s.CreateTmpFile(c, "Makefile", ""+ | |
9 | "# $"+"NetBSD$\n"+ | 9 | "# $"+"NetBSD$\n"+ | |
10 | "\n"+ | 10 | "\n"+ | |
11 | "SUBDIR+= x11\n"+ | 11 | "SUBDIR+= x11\n"+ | |
12 | "SUBDIR+=\tarchivers\n"+ | 12 | "SUBDIR+=\tarchivers\n"+ | |
13 | "SUBDIR+=\tccc\n"+ | 13 | "SUBDIR+=\tccc\n"+ | |
14 | "SUBDIR+=\tccc\n"+ | 14 | "SUBDIR+=\tccc\n"+ | |
15 | "#SUBDIR+=\tignoreme\n"+ | 15 | "#SUBDIR+=\tignoreme\n"+ | |
16 | "SUBDIR+=\tnonexisting\n"+ // This just doesn’t happen in practice. | 16 | "SUBDIR+=\tnonexisting\n"+ // This just doesn’t happen in practice. | |
17 | "SUBDIR+=\tbbb\n") | 17 | "SUBDIR+=\tbbb\n") | |
18 | s.CreateTmpFile(c, "archivers/Makefile", "") | 18 | s.CreateTmpFile(c, "archivers/Makefile", "") | |
19 | s.CreateTmpFile(c, "bbb/Makefile", "") | 19 | s.CreateTmpFile(c, "bbb/Makefile", "") | |
20 | s.CreateTmpFile(c, "ccc/Makefile", "") | 20 | s.CreateTmpFile(c, "ccc/Makefile", "") |
@@ -1,34 +1,34 @@ | @@ -1,34 +1,34 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestMkversion(c *check.C) { | 7 | func (s *Suite) Test_newVersion(c *check.C) { | |
8 | c.Check(newVersion("5.0"), check.DeepEquals, &version{[]int{5, 0, 0}, 0}) | 8 | c.Check(newVersion("5.0"), check.DeepEquals, &version{[]int{5, 0, 0}, 0}) | |
9 | c.Check(newVersion("5.0nb5"), check.DeepEquals, &version{[]int{5, 0, 0}, 5}) | 9 | c.Check(newVersion("5.0nb5"), check.DeepEquals, &version{[]int{5, 0, 0}, 5}) | |
10 | c.Check(newVersion("0.0.1-SNAPSHOT"), check.DeepEquals, &version{[]int{0, 0, 0, 0, 1, 19, 14, 1, 16, 19, 8, 15, 20}, 0}) | 10 | c.Check(newVersion("0.0.1-SNAPSHOT"), check.DeepEquals, &version{[]int{0, 0, 0, 0, 1, 19, 14, 1, 16, 19, 8, 15, 20}, 0}) | |
11 | c.Check(newVersion("1.0alpha3"), check.DeepEquals, &version{[]int{1, 0, 0, -3, 3}, 0}) | 11 | c.Check(newVersion("1.0alpha3"), check.DeepEquals, &version{[]int{1, 0, 0, -3, 3}, 0}) | |
12 | c.Check(newVersion("2.5beta"), check.DeepEquals, &version{[]int{2, 0, 5, -2}, 0}) | 12 | c.Check(newVersion("2.5beta"), check.DeepEquals, &version{[]int{2, 0, 5, -2}, 0}) | |
13 | c.Check(newVersion("20151110"), check.DeepEquals, &version{[]int{20151110}, 0}) | 13 | c.Check(newVersion("20151110"), check.DeepEquals, &version{[]int{20151110}, 0}) | |
14 | c.Check(newVersion("0"), check.DeepEquals, &version{[]int{0}, 0}) | 14 | c.Check(newVersion("0"), check.DeepEquals, &version{[]int{0}, 0}) | |
15 | c.Check(newVersion("nb1"), check.DeepEquals, &version{nil, 1}) | 15 | c.Check(newVersion("nb1"), check.DeepEquals, &version{nil, 1}) | |
16 | c.Check(newVersion("1.0.1a"), deepEquals, &version{[]int{1, 0, 0, 0, 1, 1}, 0}) | 16 | c.Check(newVersion("1.0.1a"), deepEquals, &version{[]int{1, 0, 0, 0, 1, 1}, 0}) | |
17 | c.Check(newVersion("1.0.1z"), deepEquals, &version{[]int{1, 0, 0, 0, 1, 26}, 0}) | 17 | c.Check(newVersion("1.0.1z"), deepEquals, &version{[]int{1, 0, 0, 0, 1, 26}, 0}) | |
18 | c.Check(newVersion("0pre20160620"), deepEquals, &version{[]int{0, -1, 20160620}, 0}) | 18 | c.Check(newVersion("0pre20160620"), deepEquals, &version{[]int{0, -1, 20160620}, 0}) | |
19 | } | 19 | } | |
20 | 20 | |||
21 | func (s *Suite) TestPkgverCmp(c *check.C) { | 21 | func (s *Suite) Test_pkgverCmp(c *check.C) { | |
22 | var versions = [][]string{ | 22 | var versions = [][]string{ | |
23 | {"0pre20160620"}, | 23 | {"0pre20160620"}, | |
24 | {"0"}, | 24 | {"0"}, | |
25 | {"nb1"}, | 25 | {"nb1"}, | |
26 | {"0.0.1-SNAPSHOT"}, | 26 | {"0.0.1-SNAPSHOT"}, | |
27 | {"1.0alpha"}, | 27 | {"1.0alpha"}, | |
28 | {"1.0alpha3"}, | 28 | {"1.0alpha3"}, | |
29 | {"1", "1.0", "1.0.0"}, | 29 | {"1", "1.0", "1.0.0"}, | |
30 | {"1.0nb1"}, | 30 | {"1.0nb1"}, | |
31 | {"1.0nb2"}, | 31 | {"1.0nb2"}, | |
32 | {"1.0.1a"}, | 32 | {"1.0.1a"}, | |
33 | {"1.0.1z"}, | 33 | {"1.0.1z"}, | |
34 | {"2.0pre", "2.0rc"}, | 34 | {"2.0pre", "2.0rc"}, |
@@ -60,27 +60,27 @@ func (gd *GlobalData) Initialize() { | @@ -60,27 +60,27 @@ func (gd *GlobalData) Initialize() { | |||
60 | gd.loadSuggestedUpdates() | 60 | gd.loadSuggestedUpdates() | |
61 | gd.loadUserDefinedVars() | 61 | gd.loadUserDefinedVars() | |
62 | gd.loadTools() | 62 | gd.loadTools() | |
63 | gd.loadDeprecatedVars() | 63 | gd.loadDeprecatedVars() | |
64 | } | 64 | } | |
65 | 65 | |||
66 | func (gd *GlobalData) loadDistSites() { | 66 | func (gd *GlobalData) loadDistSites() { | |
67 | fname := gd.Pkgsrcdir + "/mk/fetch/sites.mk" | 67 | fname := gd.Pkgsrcdir + "/mk/fetch/sites.mk" | |
68 | lines := LoadExistingLines(fname, true) | 68 | lines := LoadExistingLines(fname, true) | |
69 | 69 | |||
70 | name2url := make(map[string]string) | 70 | name2url := make(map[string]string) | |
71 | url2name := make(map[string]string) | 71 | url2name := make(map[string]string) | |
72 | for _, line := range lines { | 72 | for _, line := range lines { | |
73 | if m, varname, _, _, urls, _ := MatchVarassign(line.Text); m { | 73 | if m, varname, _, _, _, urls, _ := MatchVarassign(line.Text); m { | |
74 | if hasPrefix(varname, "MASTER_SITE_") && varname != "MASTER_SITE_BACKUP" { | 74 | if hasPrefix(varname, "MASTER_SITE_") && varname != "MASTER_SITE_BACKUP" { | |
75 | for _, url := range splitOnSpace(urls) { | 75 | for _, url := range splitOnSpace(urls) { | |
76 | if matches(url, `^(?:http://|https://|ftp://)`) { | 76 | if matches(url, `^(?:http://|https://|ftp://)`) { | |
77 | if name2url[varname] == "" { | 77 | if name2url[varname] == "" { | |
78 | name2url[varname] = url | 78 | name2url[varname] = url | |
79 | } | 79 | } | |
80 | url2name[url] = varname | 80 | url2name[url] = varname | |
81 | } | 81 | } | |
82 | } | 82 | } | |
83 | } | 83 | } | |
84 | } | 84 | } | |
85 | } | 85 | } | |
86 | 86 | |||
@@ -128,27 +128,27 @@ func (gd *GlobalData) loadTools() { | @@ -128,27 +128,27 @@ func (gd *GlobalData) loadTools() { | |||
128 | reg := NewToolRegistry() | 128 | reg := NewToolRegistry() | |
129 | reg.RegisterTool(&Tool{"echo", "ECHO", true, true, true}) | 129 | reg.RegisterTool(&Tool{"echo", "ECHO", true, true, true}) | |
130 | reg.RegisterTool(&Tool{"echo -n", "ECHO_N", true, true, true}) | 130 | reg.RegisterTool(&Tool{"echo -n", "ECHO_N", true, true, true}) | |
131 | reg.RegisterTool(&Tool{"false", "FALSE", true /*why?*/, true, false}) | 131 | reg.RegisterTool(&Tool{"false", "FALSE", true /*why?*/, true, false}) | |
132 | reg.RegisterTool(&Tool{"test", "TEST", true, true, true}) | 132 | reg.RegisterTool(&Tool{"test", "TEST", true, true, true}) | |
133 | reg.RegisterTool(&Tool{"true", "TRUE", true /*why?*/, true, true}) | 133 | reg.RegisterTool(&Tool{"true", "TRUE", true /*why?*/, true, true}) | |
134 | 134 | |||
135 | systemBuildDefs := make(map[string]bool) | 135 | systemBuildDefs := make(map[string]bool) | |
136 | 136 | |||
137 | for _, basename := range toolFiles { | 137 | for _, basename := range toolFiles { | |
138 | fname := G.globalData.Pkgsrcdir + "/mk/tools/" + basename | 138 | fname := G.globalData.Pkgsrcdir + "/mk/tools/" + basename | |
139 | lines := LoadExistingLines(fname, true) | 139 | lines := LoadExistingLines(fname, true) | |
140 | for _, line := range lines { | 140 | for _, line := range lines { | |
141 | if m, varname, _, _, value, _ := MatchVarassign(line.Text); m { | 141 | if m, varname, _, _, _, value, _ := MatchVarassign(line.Text); m { | |
142 | if varname == "TOOLS_CREATE" && (value == "[" || matches(value, `^?[-\w.]+$`)) { | 142 | if varname == "TOOLS_CREATE" && (value == "[" || matches(value, `^?[-\w.]+$`)) { | |
143 | reg.Register(value) | 143 | reg.Register(value) | |
144 | 144 | |||
145 | } else if m, toolname := match1(varname, `^_TOOLS_VARNAME\.([-\w.]+|\[)$`); m { | 145 | } else if m, toolname := match1(varname, `^_TOOLS_VARNAME\.([-\w.]+|\[)$`); m { | |
146 | reg.RegisterVarname(toolname, value) | 146 | reg.RegisterVarname(toolname, value) | |
147 | 147 | |||
148 | } else if m, toolname := match1(varname, `^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$`); m { | 148 | } else if m, toolname := match1(varname, `^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$`); m { | |
149 | reg.Register(toolname) | 149 | reg.Register(toolname) | |
150 | 150 | |||
151 | } else if m, toolname := match1(varname, `_TOOLS\.(.*)`); m { | 151 | } else if m, toolname := match1(varname, `_TOOLS\.(.*)`); m { | |
152 | reg.Register(toolname) | 152 | reg.Register(toolname) | |
153 | for _, tool := range splitOnSpace(value) { | 153 | for _, tool := range splitOnSpace(value) { | |
154 | reg.Register(tool) | 154 | reg.Register(tool) | |
@@ -156,27 +156,27 @@ func (gd *GlobalData) loadTools() { | @@ -156,27 +156,27 @@ func (gd *GlobalData) loadTools() { | |||
156 | } | 156 | } | |
157 | } | 157 | } | |
158 | } | 158 | } | |
159 | } | 159 | } | |
160 | 160 | |||
161 | for _, basename := range []string{"bsd.prefs.mk", "bsd.pkg.mk"} { | 161 | for _, basename := range []string{"bsd.prefs.mk", "bsd.pkg.mk"} { | |
162 | fname := G.globalData.Pkgsrcdir + "/mk/" + basename | 162 | fname := G.globalData.Pkgsrcdir + "/mk/" + basename | |
163 | condDepth := 0 | 163 | condDepth := 0 | |
164 | 164 | |||
165 | lines := LoadExistingLines(fname, true) | 165 | lines := LoadExistingLines(fname, true) | |
166 | for _, line := range lines { | 166 | for _, line := range lines { | |
167 | text := line.Text | 167 | text := line.Text | |
168 | 168 | |||
169 | if m, varname, _, _, value, _ := MatchVarassign(text); m { | 169 | if m, varname, _, _, _, value, _ := MatchVarassign(text); m { | |
170 | if varname == "USE_TOOLS" { | 170 | if varname == "USE_TOOLS" { | |
171 | if G.opts.Debug { | 171 | if G.opts.Debug { | |
172 | traceStep("[condDepth=%d] %s", condDepth, value) | 172 | traceStep("[condDepth=%d] %s", condDepth, value) | |
173 | } | 173 | } | |
174 | if condDepth == 0 || condDepth == 1 && basename == "bsd.prefs.mk" { | 174 | if condDepth == 0 || condDepth == 1 && basename == "bsd.prefs.mk" { | |
175 | for _, toolname := range splitOnSpace(value) { | 175 | for _, toolname := range splitOnSpace(value) { | |
176 | if !containsVarRef(toolname) { | 176 | if !containsVarRef(toolname) { | |
177 | for _, tool := range []*Tool{reg.Register(toolname), reg.Register("TOOLS_" + toolname)} { | 177 | for _, tool := range []*Tool{reg.Register(toolname), reg.Register("TOOLS_" + toolname)} { | |
178 | tool.Predefined = true | 178 | tool.Predefined = true | |
179 | if basename == "bsd.prefs.mk" { | 179 | if basename == "bsd.prefs.mk" { | |
180 | tool.UsableAtLoadtime = true | 180 | tool.UsableAtLoadtime = true | |
181 | } | 181 | } | |
182 | } | 182 | } |
@@ -141,41 +141,41 @@ func (gd *GlobalData) InitVartypes() { | @@ -141,41 +141,41 @@ func (gd *GlobalData) InitVartypes() { | |||
141 | bl3list("BUILDLINK_LDFLAGS.*", lkShell, CheckvarLdFlag) | 141 | bl3list("BUILDLINK_LDFLAGS.*", lkShell, CheckvarLdFlag) | |
142 | acl("BUILDLINK_LIBDIRS.*", lkShell, CheckvarPathname, "buildlink3.mk, builtin.mk: append; Makefile, Makefile.common, *.mk: use") | 142 | acl("BUILDLINK_LIBDIRS.*", lkShell, CheckvarPathname, "buildlink3.mk, builtin.mk: append; Makefile, Makefile.common, *.mk: use") | |
143 | acl("BUILDLINK_LIBS.*", lkShell, CheckvarLdFlag, "buildlink3.mk: append") | 143 | acl("BUILDLINK_LIBS.*", lkShell, CheckvarLdFlag, "buildlink3.mk: append") | |
144 | acl("BUILDLINK_PASSTHRU_DIRS", lkShell, CheckvarPathname, "Makefile, Makefile.common, buildlink3.mk, hacks.mk: append") | 144 | acl("BUILDLINK_PASSTHRU_DIRS", lkShell, CheckvarPathname, "Makefile, Makefile.common, buildlink3.mk, hacks.mk: append") | |
145 | acl("BUILDLINK_PASSTHRU_RPATHDIRS", lkShell, CheckvarPathname, "Makefile, Makefile.common, buildlink3.mk, hacks.mk: append") | 145 | acl("BUILDLINK_PASSTHRU_RPATHDIRS", lkShell, CheckvarPathname, "Makefile, Makefile.common, buildlink3.mk, hacks.mk: append") | |
146 | acl("BUILDLINK_PKGSRCDIR.*", lkNone, CheckvarRelativePkgDir, "buildlink3.mk: default, use-loadtime") | 146 | acl("BUILDLINK_PKGSRCDIR.*", lkNone, CheckvarRelativePkgDir, "buildlink3.mk: default, use-loadtime") | |
147 | acl("BUILDLINK_PREFIX.*", lkNone, CheckvarPathname, "builtin.mk: set, use; Makefile, Makefile.common, *.mk: use") | 147 | acl("BUILDLINK_PREFIX.*", lkNone, CheckvarPathname, "builtin.mk: set, use; Makefile, Makefile.common, *.mk: use") | |
148 | acl("BUILDLINK_RPATHDIRS.*", lkShell, CheckvarPathname, "buildlink3.mk: append") | 148 | acl("BUILDLINK_RPATHDIRS.*", lkShell, CheckvarPathname, "buildlink3.mk: append") | |
149 | acl("BUILDLINK_TARGETS", lkShell, CheckvarIdentifier, "") | 149 | acl("BUILDLINK_TARGETS", lkShell, CheckvarIdentifier, "") | |
150 | acl("BUILDLINK_FNAME_TRANSFORM.*", lkNone, CheckvarSedCommands, "Makefile, buildlink3.mk, builtin.mk, hacks.mk: append") | 150 | acl("BUILDLINK_FNAME_TRANSFORM.*", lkNone, CheckvarSedCommands, "Makefile, buildlink3.mk, builtin.mk, hacks.mk: append") | |
151 | acl("BUILDLINK_TRANSFORM", lkShell, CheckvarWrapperTransform, "*: append") | 151 | acl("BUILDLINK_TRANSFORM", lkShell, CheckvarWrapperTransform, "*: append") | |
152 | acl("BUILDLINK_TRANSFORM.*", lkShell, CheckvarWrapperTransform, "*: append") | 152 | acl("BUILDLINK_TRANSFORM.*", lkShell, CheckvarWrapperTransform, "*: append") | |
153 | acl("BUILDLINK_TREE", lkShell, CheckvarIdentifier, "buildlink3.mk: append") | 153 | acl("BUILDLINK_TREE", lkShell, CheckvarIdentifier, "buildlink3.mk: append") | |
154 | acl("BUILD_DEFS", lkShell, CheckvarVarname, "Makefile, Makefile.common, options.mk: append") | 154 | acl("BUILD_DEFS", lkShell, CheckvarVariableName, "Makefile, Makefile.common, options.mk: append") | |
155 | acl("BUILD_DEPENDS", lkSpace, CheckvarDependencyWithPath, "Makefile, Makefile.common, *.mk: append") | 155 | acl("BUILD_DEPENDS", lkSpace, CheckvarDependencyWithPath, "Makefile, Makefile.common, *.mk: append") | |
156 | pkglist("BUILD_DIRS", lkShell, CheckvarWrksrcSubdirectory) | 156 | pkglist("BUILD_DIRS", lkShell, CheckvarWrksrcSubdirectory) | |
157 | pkglist("BUILD_ENV", lkShell, CheckvarShellWord) | 157 | pkglist("BUILD_ENV", lkShell, CheckvarShellWord) | |
158 | sys("BUILD_MAKE_CMD", lkNone, CheckvarShellCommand) | 158 | sys("BUILD_MAKE_CMD", lkNone, CheckvarShellCommand) | |
159 | pkglist("BUILD_MAKE_FLAGS", lkShell, CheckvarShellWord) | 159 | pkglist("BUILD_MAKE_FLAGS", lkShell, CheckvarShellWord) | |
160 | pkglist("BUILD_TARGET", lkShell, CheckvarIdentifier) | 160 | pkglist("BUILD_TARGET", lkShell, CheckvarIdentifier) | |
161 | pkglist("BUILD_TARGET.*", lkShell, CheckvarIdentifier) | 161 | pkglist("BUILD_TARGET.*", lkShell, CheckvarIdentifier) | |
162 | pkg("BUILD_USES_MSGFMT", lkNone, CheckvarYes) | 162 | pkg("BUILD_USES_MSGFMT", lkNone, CheckvarYes) | |
163 | acl("BUILTIN_PKG", lkNone, CheckvarIdentifier, "builtin.mk: set, use-loadtime, use") | 163 | acl("BUILTIN_PKG", lkNone, CheckvarIdentifier, "builtin.mk: set, use-loadtime, use") | |
164 | acl("BUILTIN_PKG.*", lkNone, CheckvarPkgName, "builtin.mk: set, use-loadtime, use") | 164 | acl("BUILTIN_PKG.*", lkNone, CheckvarPkgName, "builtin.mk: set, use-loadtime, use") | |
165 | acl("BUILTIN_FIND_FILES_VAR", lkShell, CheckvarVarname, "builtin.mk: set") | 165 | acl("BUILTIN_FIND_FILES_VAR", lkShell, CheckvarVariableName, "builtin.mk: set") | |
166 | acl("BUILTIN_FIND_FILES.*", lkShell, CheckvarPathname, "builtin.mk: set") | 166 | acl("BUILTIN_FIND_FILES.*", lkShell, CheckvarPathname, "builtin.mk: set") | |
167 | acl("BUILTIN_FIND_GREP.*", lkNone, CheckvarString, "builtin.mk: set") | 167 | acl("BUILTIN_FIND_GREP.*", lkNone, CheckvarString, "builtin.mk: set") | |
168 | acl("BUILTIN_FIND_HEADERS_VAR", lkShell, CheckvarVarname, "builtin.mk: set") | 168 | acl("BUILTIN_FIND_HEADERS_VAR", lkShell, CheckvarVariableName, "builtin.mk: set") | |
169 | acl("BUILTIN_FIND_HEADERS.*", lkShell, CheckvarPathname, "builtin.mk: set") | 169 | acl("BUILTIN_FIND_HEADERS.*", lkShell, CheckvarPathname, "builtin.mk: set") | |
170 | acl("BUILTIN_FIND_LIBS", lkShell, CheckvarPathname, "builtin.mk: set") | 170 | acl("BUILTIN_FIND_LIBS", lkShell, CheckvarPathname, "builtin.mk: set") | |
171 | acl("BUILTIN_IMAKE_CHECK", lkShell, CheckvarUnchecked, "builtin.mk: set") | 171 | acl("BUILTIN_IMAKE_CHECK", lkShell, CheckvarUnchecked, "builtin.mk: set") | |
172 | acl("BUILTIN_IMAKE_CHECK.*", lkNone, CheckvarYesNo, "") | 172 | acl("BUILTIN_IMAKE_CHECK.*", lkNone, CheckvarYesNo, "") | |
173 | sys("BUILTIN_X11_TYPE", lkNone, CheckvarUnchecked) | 173 | sys("BUILTIN_X11_TYPE", lkNone, CheckvarUnchecked) | |
174 | sys("BUILTIN_X11_VERSION", lkNone, CheckvarUnchecked) | 174 | sys("BUILTIN_X11_VERSION", lkNone, CheckvarUnchecked) | |
175 | acl("CATEGORIES", lkShell, CheckvarCategory, "Makefile: set, append; Makefile.common: set, default, append") | 175 | acl("CATEGORIES", lkShell, CheckvarCategory, "Makefile: set, append; Makefile.common: set, default, append") | |
176 | sys("CC_VERSION", lkNone, CheckvarMessage) | 176 | sys("CC_VERSION", lkNone, CheckvarMessage) | |
177 | sys("CC", lkNone, CheckvarShellCommand) | 177 | sys("CC", lkNone, CheckvarShellCommand) | |
178 | pkglist("CFLAGS", lkShell, CheckvarCFlag) // may also be changed by the user | 178 | pkglist("CFLAGS", lkShell, CheckvarCFlag) // may also be changed by the user | |
179 | pkglist("CFLAGS.*", lkShell, CheckvarCFlag) // may also be changed by the user | 179 | pkglist("CFLAGS.*", lkShell, CheckvarCFlag) // may also be changed by the user | |
180 | acl("CHECK_BUILTIN", lkNone, CheckvarYesNo, "builtin.mk: default; Makefile: set") | 180 | acl("CHECK_BUILTIN", lkNone, CheckvarYesNo, "builtin.mk: default; Makefile: set") | |
181 | acl("CHECK_BUILTIN.*", lkNone, CheckvarYesNo, "Makefile, options.mk, buildlink3.mk: set; builtin.mk: default; *: use-loadtime") | 181 | acl("CHECK_BUILTIN.*", lkNone, CheckvarYesNo, "Makefile, options.mk, buildlink3.mk: set; builtin.mk: default; *: use-loadtime") | |
@@ -222,27 +222,27 @@ func (gd *GlobalData) InitVartypes() { | @@ -222,27 +222,27 @@ func (gd *GlobalData) InitVartypes() { | |||
222 | acl("CRYPTO", lkNone, CheckvarYes, "Makefile: set") | 222 | acl("CRYPTO", lkNone, CheckvarYes, "Makefile: set") | |
223 | sys("CXX", lkNone, CheckvarShellCommand) | 223 | sys("CXX", lkNone, CheckvarShellCommand) | |
224 | pkglist("CXXFLAGS", lkShell, CheckvarCFlag) | 224 | pkglist("CXXFLAGS", lkShell, CheckvarCFlag) | |
225 | pkglist("CXXFLAGS.*", lkShell, CheckvarCFlag) | 225 | pkglist("CXXFLAGS.*", lkShell, CheckvarCFlag) | |
226 | acl("DEINSTALL_FILE", lkNone, CheckvarPathname, "Makefile: set") | 226 | acl("DEINSTALL_FILE", lkNone, CheckvarPathname, "Makefile: set") | |
227 | acl("DEINSTALL_SRC", lkShell, CheckvarPathname, "Makefile: set; Makefile.common: default, set") | 227 | acl("DEINSTALL_SRC", lkShell, CheckvarPathname, "Makefile: set; Makefile.common: default, set") | |
228 | acl("DEINSTALL_TEMPLATES", lkShell, CheckvarPathname, "Makefile: set, append; Makefile.common: set, default, append") | 228 | acl("DEINSTALL_TEMPLATES", lkShell, CheckvarPathname, "Makefile: set, append; Makefile.common: set, default, append") | |
229 | sys("DELAYED_ERROR_MSG", lkNone, CheckvarShellCommand) | 229 | sys("DELAYED_ERROR_MSG", lkNone, CheckvarShellCommand) | |
230 | sys("DELAYED_WARNING_MSG", lkNone, CheckvarShellCommand) | 230 | sys("DELAYED_WARNING_MSG", lkNone, CheckvarShellCommand) | |
231 | pkglist("DEPENDS", lkSpace, CheckvarDependencyWithPath) | 231 | pkglist("DEPENDS", lkSpace, CheckvarDependencyWithPath) | |
232 | usr("DEPENDS_TARGET", lkShell, CheckvarIdentifier) | 232 | usr("DEPENDS_TARGET", lkShell, CheckvarIdentifier) | |
233 | acl("DESCR_SRC", lkShell, CheckvarPathname, "Makefile: set, append; Makefile.common: default, set") | 233 | acl("DESCR_SRC", lkShell, CheckvarPathname, "Makefile: set, append; Makefile.common: default, set") | |
234 | sys("DESTDIR", lkNone, CheckvarPathname) | 234 | sys("DESTDIR", lkNone, CheckvarPathname) | |
235 | acl("DESTDIR_VARNAME", lkNone, CheckvarVarname, "Makefile, Makefile.common: set") | 235 | acl("DESTDIR_VARNAME", lkNone, CheckvarVariableName, "Makefile, Makefile.common: set") | |
236 | sys("DEVOSSAUDIO", lkNone, CheckvarPathname) | 236 | sys("DEVOSSAUDIO", lkNone, CheckvarPathname) | |
237 | sys("DEVOSSSOUND", lkNone, CheckvarPathname) | 237 | sys("DEVOSSSOUND", lkNone, CheckvarPathname) | |
238 | pkglist("DISTFILES", lkShell, CheckvarFilename) | 238 | pkglist("DISTFILES", lkShell, CheckvarFilename) | |
239 | pkg("DISTINFO_FILE", lkNone, CheckvarRelativePkgPath) | 239 | pkg("DISTINFO_FILE", lkNone, CheckvarRelativePkgPath) | |
240 | pkg("DISTNAME", lkNone, CheckvarFilename) | 240 | pkg("DISTNAME", lkNone, CheckvarFilename) | |
241 | pkg("DIST_SUBDIR", lkNone, CheckvarPathname) | 241 | pkg("DIST_SUBDIR", lkNone, CheckvarPathname) | |
242 | acl("DJB_BUILD_ARGS", lkShell, CheckvarShellWord, "") | 242 | acl("DJB_BUILD_ARGS", lkShell, CheckvarShellWord, "") | |
243 | acl("DJB_BUILD_TARGETS", lkShell, CheckvarIdentifier, "") | 243 | acl("DJB_BUILD_TARGETS", lkShell, CheckvarIdentifier, "") | |
244 | acl("DJB_CONFIG_CMDS", lkNone, CheckvarShellCommands, "options.mk: set") | 244 | acl("DJB_CONFIG_CMDS", lkNone, CheckvarShellCommands, "options.mk: set") | |
245 | acl("DJB_CONFIG_DIRS", lkShell, CheckvarWrksrcSubdirectory, "") | 245 | acl("DJB_CONFIG_DIRS", lkShell, CheckvarWrksrcSubdirectory, "") | |
246 | acl("DJB_CONFIG_HOME", lkNone, CheckvarFilename, "") | 246 | acl("DJB_CONFIG_HOME", lkNone, CheckvarFilename, "") | |
247 | acl("DJB_CONFIG_PREFIX", lkNone, CheckvarPathname, "") | 247 | acl("DJB_CONFIG_PREFIX", lkNone, CheckvarPathname, "") | |
248 | acl("DJB_INSTALL_TARGETS", lkShell, CheckvarIdentifier, "") | 248 | acl("DJB_INSTALL_TARGETS", lkShell, CheckvarIdentifier, "") | |
@@ -310,27 +310,27 @@ func (gd *GlobalData) InitVartypes() { | @@ -310,27 +310,27 @@ func (gd *GlobalData) InitVartypes() { | |||
310 | acl("EXTRACT_OPTS_ZOO", lkShell, CheckvarShellWord, "Makefile, Makefile.common: set, append") | 310 | acl("EXTRACT_OPTS_ZOO", lkShell, CheckvarShellWord, "Makefile, Makefile.common: set, append") | |
311 | pkg("EXTRACT_SUFX", lkNone, CheckvarDistSuffix) | 311 | pkg("EXTRACT_SUFX", lkNone, CheckvarDistSuffix) | |
312 | pkg("EXTRACT_USING", lkNone, enum("bsdtar gtar nbtar pax")) | 312 | pkg("EXTRACT_USING", lkNone, enum("bsdtar gtar nbtar pax")) | |
313 | sys("FAIL_MSG", lkNone, CheckvarShellCommand) | 313 | sys("FAIL_MSG", lkNone, CheckvarShellCommand) | |
314 | sys("FAMBASE", lkNone, CheckvarPathname) | 314 | sys("FAMBASE", lkNone, CheckvarPathname) | |
315 | pkg("FAM_ACCEPTED", lkShell, enum("fam gamin")) | 315 | pkg("FAM_ACCEPTED", lkShell, enum("fam gamin")) | |
316 | usr("FAM_DEFAULT", lkNone, enum("fam gamin")) | 316 | usr("FAM_DEFAULT", lkNone, enum("fam gamin")) | |
317 | sys("FAM_TYPE", lkNone, enum("fam gamin")) | 317 | sys("FAM_TYPE", lkNone, enum("fam gamin")) | |
318 | acl("FETCH_BEFORE_ARGS", lkShell, CheckvarShellWord, "Makefile: set, append") | 318 | acl("FETCH_BEFORE_ARGS", lkShell, CheckvarShellWord, "Makefile: set, append") | |
319 | pkglist("FETCH_MESSAGE", lkShell, CheckvarShellWord) | 319 | pkglist("FETCH_MESSAGE", lkShell, CheckvarShellWord) | |
320 | pkg("FILESDIR", lkNone, CheckvarRelativePkgPath) | 320 | pkg("FILESDIR", lkNone, CheckvarRelativePkgPath) | |
321 | pkglist("FILES_SUBST", lkShell, CheckvarShellWord) | 321 | pkglist("FILES_SUBST", lkShell, CheckvarShellWord) | |
322 | acl("FILES_SUBST_SED", lkShell, CheckvarShellWord, "") | 322 | acl("FILES_SUBST_SED", lkShell, CheckvarShellWord, "") | |
323 | pkglist("FIX_RPATH", lkShell, CheckvarVarname) | 323 | pkglist("FIX_RPATH", lkShell, CheckvarVariableName) | |
324 | pkglist("FLEX_REQD", lkShell, CheckvarVersion) | 324 | pkglist("FLEX_REQD", lkShell, CheckvarVersion) | |
325 | acl("FONTS_DIRS.*", lkShell, CheckvarPathname, "Makefile: set, append, use; Makefile.common: append, use") | 325 | acl("FONTS_DIRS.*", lkShell, CheckvarPathname, "Makefile: set, append, use; Makefile.common: append, use") | |
326 | sys("GAMEDATAMODE", lkNone, CheckvarFileMode) | 326 | sys("GAMEDATAMODE", lkNone, CheckvarFileMode) | |
327 | sys("GAMES_GROUP", lkNone, CheckvarUserGroupName) | 327 | sys("GAMES_GROUP", lkNone, CheckvarUserGroupName) | |
328 | sys("GAMEMODE", lkNone, CheckvarFileMode) | 328 | sys("GAMEMODE", lkNone, CheckvarFileMode) | |
329 | sys("GAMES_USER", lkNone, CheckvarUserGroupName) | 329 | sys("GAMES_USER", lkNone, CheckvarUserGroupName) | |
330 | pkglist("GCC_REQD", lkShell, CheckvarVersion) | 330 | pkglist("GCC_REQD", lkShell, CheckvarVersion) | |
331 | pkglist("GENERATE_PLIST", lkNone, CheckvarShellCommands) | 331 | pkglist("GENERATE_PLIST", lkNone, CheckvarShellCommands) | |
332 | pkg("GITHUB_PROJECT", lkNone, CheckvarIdentifier) | 332 | pkg("GITHUB_PROJECT", lkNone, CheckvarIdentifier) | |
333 | pkg("GITHUB_TAG", lkNone, CheckvarIdentifier) | 333 | pkg("GITHUB_TAG", lkNone, CheckvarIdentifier) | |
334 | pkg("GITHUB_RELEASE", lkNone, CheckvarFilename) | 334 | pkg("GITHUB_RELEASE", lkNone, CheckvarFilename) | |
335 | pkg("GITHUB_TYPE", lkNone, enum("tag release")) | 335 | pkg("GITHUB_TYPE", lkNone, enum("tag release")) | |
336 | acl("GNU_ARCH", lkNone, enum("mips"), "") | 336 | acl("GNU_ARCH", lkNone, enum("mips"), "") | |
@@ -400,27 +400,27 @@ func (gd *GlobalData) InitVartypes() { | @@ -400,27 +400,27 @@ func (gd *GlobalData) InitVartypes() { | |||
400 | acl("LICENCE", lkNone, CheckvarLicense, "Makefile, Makefile.common, options.mk: set") | 400 | acl("LICENCE", lkNone, CheckvarLicense, "Makefile, Makefile.common, options.mk: set") | |
401 | acl("LICENSE", lkNone, CheckvarLicense, "Makefile, Makefile.common, options.mk: set") | 401 | acl("LICENSE", lkNone, CheckvarLicense, "Makefile, Makefile.common, options.mk: set") | |
402 | pkg("LICENSE_FILE", lkNone, CheckvarPathname) | 402 | pkg("LICENSE_FILE", lkNone, CheckvarPathname) | |
403 | sys("LINKER_RPATH_FLAG", lkNone, CheckvarShellWord) | 403 | sys("LINKER_RPATH_FLAG", lkNone, CheckvarShellWord) | |
404 | sys("LOWER_OPSYS", lkNone, CheckvarIdentifier) | 404 | sys("LOWER_OPSYS", lkNone, CheckvarIdentifier) | |
405 | acl("LTCONFIG_OVERRIDE", lkShell, CheckvarPathmask, "Makefile: set, append; Makefile.common: append") | 405 | acl("LTCONFIG_OVERRIDE", lkShell, CheckvarPathmask, "Makefile: set, append; Makefile.common: append") | |
406 | sys("MACHINE_ARCH", lkNone, enumMachineArch) | 406 | sys("MACHINE_ARCH", lkNone, enumMachineArch) | |
407 | sys("MACHINE_GNU_ARCH", lkNone, enumMachineGnuArch) | 407 | sys("MACHINE_GNU_ARCH", lkNone, enumMachineGnuArch) | |
408 | sys("MACHINE_GNU_PLATFORM", lkNone, CheckvarMachineGnuPlatform) | 408 | sys("MACHINE_GNU_PLATFORM", lkNone, CheckvarMachineGnuPlatform) | |
409 | sys("MACHINE_PLATFORM", lkNone, CheckvarMachinePlatform) | 409 | sys("MACHINE_PLATFORM", lkNone, CheckvarMachinePlatform) | |
410 | acl("MAINTAINER", lkNone, CheckvarMailAddress, "Makefile: set; Makefile.common: default") | 410 | acl("MAINTAINER", lkNone, CheckvarMailAddress, "Makefile: set; Makefile.common: default") | |
411 | sys("MAKE", lkNone, CheckvarShellCommand) | 411 | sys("MAKE", lkNone, CheckvarShellCommand) | |
412 | pkglist("MAKEFLAGS", lkShell, CheckvarShellWord) | 412 | pkglist("MAKEFLAGS", lkShell, CheckvarShellWord) | |
413 | acl("MAKEVARS", lkShell, CheckvarVarname, "buildlink3.mk, builtin.mk, hacks.mk: append") | 413 | acl("MAKEVARS", lkShell, CheckvarVariableName, "buildlink3.mk, builtin.mk, hacks.mk: append") | |
414 | pkglist("MAKE_DIRS", lkShell, CheckvarPathname) | 414 | pkglist("MAKE_DIRS", lkShell, CheckvarPathname) | |
415 | pkglist("MAKE_DIRS_PERMS", lkShell, CheckvarPerms) | 415 | pkglist("MAKE_DIRS_PERMS", lkShell, CheckvarPerms) | |
416 | acl("MAKE_ENV", lkShell, CheckvarShellWord, "Makefile, Makefile.common: append, set, use; buildlink3.mk, builtin.mk: append; *.mk: append, use") | 416 | acl("MAKE_ENV", lkShell, CheckvarShellWord, "Makefile, Makefile.common: append, set, use; buildlink3.mk, builtin.mk: append; *.mk: append, use") | |
417 | acl("MAKE_ENV.*", lkShell, CheckvarShellWord, "Makefile, Makefile.common: append, set, use; buildlink3.mk, builtin.mk: append; *.mk: append, use") | 417 | acl("MAKE_ENV.*", lkShell, CheckvarShellWord, "Makefile, Makefile.common: append, set, use; buildlink3.mk, builtin.mk: append; *.mk: append, use") | |
418 | pkg("MAKE_FILE", lkNone, CheckvarPathname) | 418 | pkg("MAKE_FILE", lkNone, CheckvarPathname) | |
419 | pkglist("MAKE_FLAGS", lkShell, CheckvarShellWord) | 419 | pkglist("MAKE_FLAGS", lkShell, CheckvarShellWord) | |
420 | pkglist("MAKE_FLAGS.*", lkShell, CheckvarShellWord) | 420 | pkglist("MAKE_FLAGS.*", lkShell, CheckvarShellWord) | |
421 | usr("MAKE_JOBS", lkNone, CheckvarInteger) | 421 | usr("MAKE_JOBS", lkNone, CheckvarInteger) | |
422 | pkg("MAKE_JOBS_SAFE", lkNone, CheckvarYesNo) | 422 | pkg("MAKE_JOBS_SAFE", lkNone, CheckvarYesNo) | |
423 | pkg("MAKE_PROGRAM", lkNone, CheckvarShellCommand) | 423 | pkg("MAKE_PROGRAM", lkNone, CheckvarShellCommand) | |
424 | acl("MANCOMPRESSED", lkNone, CheckvarYesNo, "Makefile: set; Makefile.common: default, set") | 424 | acl("MANCOMPRESSED", lkNone, CheckvarYesNo, "Makefile: set; Makefile.common: default, set") | |
425 | acl("MANCOMPRESSED_IF_MANZ", lkNone, CheckvarYes, "Makefile: set; Makefile.common: default, set") | 425 | acl("MANCOMPRESSED_IF_MANZ", lkNone, CheckvarYes, "Makefile: set; Makefile.common: default, set") | |
426 | sys("MANGRP", lkNone, CheckvarUserGroupName) | 426 | sys("MANGRP", lkNone, CheckvarUserGroupName) | |
@@ -474,27 +474,27 @@ func (gd *GlobalData) InitVartypes() { | @@ -474,27 +474,27 @@ func (gd *GlobalData) InitVartypes() { | |||
474 | acl("NO_BUILD", lkNone, CheckvarYes, "Makefile, Makefile.common: set; Makefile.*: default, set") | 474 | acl("NO_BUILD", lkNone, CheckvarYes, "Makefile, Makefile.common: set; Makefile.*: default, set") | |
475 | pkg("NO_CHECKSUM", lkNone, CheckvarYes) | 475 | pkg("NO_CHECKSUM", lkNone, CheckvarYes) | |
476 | pkg("NO_CONFIGURE", lkNone, CheckvarYes) | 476 | pkg("NO_CONFIGURE", lkNone, CheckvarYes) | |
477 | acl("NO_EXPORT_CPP", lkNone, CheckvarYes, "Makefile: set") | 477 | acl("NO_EXPORT_CPP", lkNone, CheckvarYes, "Makefile: set") | |
478 | pkg("NO_EXTRACT", lkNone, CheckvarYes) | 478 | pkg("NO_EXTRACT", lkNone, CheckvarYes) | |
479 | pkg("NO_INSTALL_MANPAGES", lkNone, CheckvarYes) // only has an effect for Imake packages. | 479 | pkg("NO_INSTALL_MANPAGES", lkNone, CheckvarYes) // only has an effect for Imake packages. | |
480 | acl("NO_PKGTOOLS_REQD_CHECK", lkNone, CheckvarYes, "Makefile: set") | 480 | acl("NO_PKGTOOLS_REQD_CHECK", lkNone, CheckvarYes, "Makefile: set") | |
481 | acl("NO_SRC_ON_CDROM", lkNone, CheckvarRestricted, "Makefile, Makefile.common: set") | 481 | acl("NO_SRC_ON_CDROM", lkNone, CheckvarRestricted, "Makefile, Makefile.common: set") | |
482 | acl("NO_SRC_ON_FTP", lkNone, CheckvarRestricted, "Makefile, Makefile.common: set") | 482 | acl("NO_SRC_ON_FTP", lkNone, CheckvarRestricted, "Makefile, Makefile.common: set") | |
483 | pkglist("ONLY_FOR_COMPILER", lkShell, enum("ccc clang gcc hp icc ido mipspro mipspro-ucode pcc sunpro xlc")) | 483 | pkglist("ONLY_FOR_COMPILER", lkShell, enum("ccc clang gcc hp icc ido mipspro mipspro-ucode pcc sunpro xlc")) | |
484 | pkglist("ONLY_FOR_PLATFORM", lkSpace, CheckvarMachinePlatformPattern) | 484 | pkglist("ONLY_FOR_PLATFORM", lkSpace, CheckvarMachinePlatformPattern) | |
485 | pkg("ONLY_FOR_UNPRIVILEGED", lkNone, CheckvarYesNo) | 485 | pkg("ONLY_FOR_UNPRIVILEGED", lkNone, CheckvarYesNo) | |
486 | sys("OPSYS", lkNone, CheckvarIdentifier) | 486 | sys("OPSYS", lkNone, CheckvarIdentifier) | |
487 | acl("OPSYSVARS", lkShell, CheckvarVarname, "Makefile, Makefile.common: append") | 487 | acl("OPSYSVARS", lkShell, CheckvarVariableName, "Makefile, Makefile.common: append") | |
488 | acl("OSVERSION_SPECIFIC", lkNone, CheckvarYes, "Makefile, Makefile.common: set") | 488 | acl("OSVERSION_SPECIFIC", lkNone, CheckvarYes, "Makefile, Makefile.common: set") | |
489 | sys("OS_VERSION", lkNone, CheckvarVersion) | 489 | sys("OS_VERSION", lkNone, CheckvarVersion) | |
490 | pkg("OVERRIDE_DIRDEPTH*", lkNone, CheckvarInteger) | 490 | pkg("OVERRIDE_DIRDEPTH*", lkNone, CheckvarInteger) | |
491 | pkg("OVERRIDE_GNU_CONFIG_SCRIPTS", lkNone, CheckvarYes) | 491 | pkg("OVERRIDE_GNU_CONFIG_SCRIPTS", lkNone, CheckvarYes) | |
492 | acl("OWNER", lkNone, CheckvarMailAddress, "Makefile: set; Makefile.common: default") | 492 | acl("OWNER", lkNone, CheckvarMailAddress, "Makefile: set; Makefile.common: default") | |
493 | pkglist("OWN_DIRS", lkShell, CheckvarPathname) | 493 | pkglist("OWN_DIRS", lkShell, CheckvarPathname) | |
494 | pkglist("OWN_DIRS_PERMS", lkShell, CheckvarPerms) | 494 | pkglist("OWN_DIRS_PERMS", lkShell, CheckvarPerms) | |
495 | sys("PAMBASE", lkNone, CheckvarPathname) | 495 | sys("PAMBASE", lkNone, CheckvarPathname) | |
496 | usr("PAM_DEFAULT", lkNone, enum("linux-pam openpam solaris-pam")) | 496 | usr("PAM_DEFAULT", lkNone, enum("linux-pam openpam solaris-pam")) | |
497 | acl("PATCHDIR", lkNone, CheckvarRelativePkgPath, "Makefile: set; Makefile.common: default, set") | 497 | acl("PATCHDIR", lkNone, CheckvarRelativePkgPath, "Makefile: set; Makefile.common: default, set") | |
498 | pkglist("PATCHFILES", lkShell, CheckvarFilename) | 498 | pkglist("PATCHFILES", lkShell, CheckvarFilename) | |
499 | acl("PATCH_ARGS", lkShell, CheckvarShellWord, "") | 499 | acl("PATCH_ARGS", lkShell, CheckvarShellWord, "") | |
500 | acl("PATCH_DIST_ARGS", lkShell, CheckvarShellWord, "Makefile: set, append") | 500 | acl("PATCH_DIST_ARGS", lkShell, CheckvarShellWord, "Makefile: set, append") | |
@@ -538,27 +538,27 @@ func (gd *GlobalData) InitVartypes() { | @@ -538,27 +538,27 @@ func (gd *GlobalData) InitVartypes() { | |||
538 | // ^^ No, this is not the popular command from GNOME, but the setting | 538 | // ^^ No, this is not the popular command from GNOME, but the setting | |
539 | // whether the pkgsrc user wants configuration files automatically | 539 | // whether the pkgsrc user wants configuration files automatically | |
540 | // installed or not. | 540 | // installed or not. | |
541 | sys("PKG_CREATE", lkNone, CheckvarShellCommand) | 541 | sys("PKG_CREATE", lkNone, CheckvarShellCommand) | |
542 | sys("PKG_DBDIR", lkNone, CheckvarPathname) | 542 | sys("PKG_DBDIR", lkNone, CheckvarPathname) | |
543 | cmdline("PKG_DEBUG_LEVEL", lkNone, CheckvarInteger) | 543 | cmdline("PKG_DEBUG_LEVEL", lkNone, CheckvarInteger) | |
544 | usr("PKG_DEFAULT_OPTIONS", lkShell, CheckvarOption) | 544 | usr("PKG_DEFAULT_OPTIONS", lkShell, CheckvarOption) | |
545 | sys("PKG_DELETE", lkNone, CheckvarShellCommand) | 545 | sys("PKG_DELETE", lkNone, CheckvarShellCommand) | |
546 | acl("PKG_DESTDIR_SUPPORT", lkShell, enum("destdir user-destdir"), "Makefile, Makefile.common: set") | 546 | acl("PKG_DESTDIR_SUPPORT", lkShell, enum("destdir user-destdir"), "Makefile, Makefile.common: set") | |
547 | pkglist("PKG_FAIL_REASON", lkShell, CheckvarShellWord) | 547 | pkglist("PKG_FAIL_REASON", lkShell, CheckvarShellWord) | |
548 | acl("PKG_GECOS.*", lkNone, CheckvarMessage, "Makefile: set") | 548 | acl("PKG_GECOS.*", lkNone, CheckvarMessage, "Makefile: set") | |
549 | acl("PKG_GID.*", lkNone, CheckvarInteger, "Makefile: set") | 549 | acl("PKG_GID.*", lkNone, CheckvarInteger, "Makefile: set") | |
550 | acl("PKG_GROUPS", lkShell, CheckvarShellWord, "Makefile: set, append") | 550 | acl("PKG_GROUPS", lkShell, CheckvarShellWord, "Makefile: set, append") | |
551 | pkglist("PKG_GROUPS_VARS", lkShell, CheckvarVarname) | 551 | pkglist("PKG_GROUPS_VARS", lkShell, CheckvarVariableName) | |
552 | acl("PKG_HOME.*", lkNone, CheckvarPathname, "Makefile: set") | 552 | acl("PKG_HOME.*", lkNone, CheckvarPathname, "Makefile: set") | |
553 | acl("PKG_HACKS", lkShell, CheckvarIdentifier, "hacks.mk: append") | 553 | acl("PKG_HACKS", lkShell, CheckvarIdentifier, "hacks.mk: append") | |
554 | sys("PKG_INFO", lkNone, CheckvarShellCommand) | 554 | sys("PKG_INFO", lkNone, CheckvarShellCommand) | |
555 | sys("PKG_JAVA_HOME", lkNone, CheckvarPathname) | 555 | sys("PKG_JAVA_HOME", lkNone, CheckvarPathname) | |
556 | jvms := enum("openjdk8 oracle-jdk8 openjdk7 sun-jdk7 sun-jdk6 jdk16 jdk15 kaffe") // See mk/java-vm.mk:/_PKG_JVMS/ | 556 | jvms := enum("openjdk8 oracle-jdk8 openjdk7 sun-jdk7 sun-jdk6 jdk16 jdk15 kaffe") // See mk/java-vm.mk:/_PKG_JVMS/ | |
557 | sys("PKG_JVM", lkNone, jvms) | 557 | sys("PKG_JVM", lkNone, jvms) | |
558 | acl("PKG_JVMS_ACCEPTED", lkShell, jvms, "Makefile: set; Makefile.common: default, set") | 558 | acl("PKG_JVMS_ACCEPTED", lkShell, jvms, "Makefile: set; Makefile.common: default, set") | |
559 | usr("PKG_JVM_DEFAULT", lkNone, jvms) | 559 | usr("PKG_JVM_DEFAULT", lkNone, jvms) | |
560 | acl("PKG_LEGACY_OPTIONS", lkShell, CheckvarOption, "") | 560 | acl("PKG_LEGACY_OPTIONS", lkShell, CheckvarOption, "") | |
561 | acl("PKG_LIBTOOL", lkNone, CheckvarPathname, "Makefile: set") | 561 | acl("PKG_LIBTOOL", lkNone, CheckvarPathname, "Makefile: set") | |
562 | acl("PKG_OPTIONS", lkSpace, CheckvarOption, "bsd.options.mk: set; *: use-loadtime, use") | 562 | acl("PKG_OPTIONS", lkSpace, CheckvarOption, "bsd.options.mk: set; *: use-loadtime, use") | |
563 | usr("PKG_OPTIONS.*", lkSpace, CheckvarOption) | 563 | usr("PKG_OPTIONS.*", lkSpace, CheckvarOption) | |
564 | acl("PKG_OPTIONS_DEPRECATED_WARNINGS", lkShell, CheckvarShellWord, "") | 564 | acl("PKG_OPTIONS_DEPRECATED_WARNINGS", lkShell, CheckvarShellWord, "") | |
@@ -574,27 +574,27 @@ func (gd *GlobalData) InitVartypes() { | @@ -574,27 +574,27 @@ func (gd *GlobalData) InitVartypes() { | |||
574 | acl("PKG_SHELL", lkNone, CheckvarPathname, "Makefile, Makefile.common: set") | 574 | acl("PKG_SHELL", lkNone, CheckvarPathname, "Makefile, Makefile.common: set") | |
575 | acl("PKG_SHELL.*", lkNone, CheckvarPathname, "Makefile, Makefile.common: set") | 575 | acl("PKG_SHELL.*", lkNone, CheckvarPathname, "Makefile, Makefile.common: set") | |
576 | acl("PKG_SHLIBTOOL", lkNone, CheckvarPathname, "") | 576 | acl("PKG_SHLIBTOOL", lkNone, CheckvarPathname, "") | |
577 | pkglist("PKG_SKIP_REASON", lkShell, CheckvarShellWord) | 577 | pkglist("PKG_SKIP_REASON", lkShell, CheckvarShellWord) | |
578 | acl("PKG_SUGGESTED_OPTIONS", lkShell, CheckvarOption, "Makefile, Makefile.common, options.mk: set, append") | 578 | acl("PKG_SUGGESTED_OPTIONS", lkShell, CheckvarOption, "Makefile, Makefile.common, options.mk: set, append") | |
579 | acl("PKG_SUPPORTED_OPTIONS", lkShell, CheckvarOption, "Makefile: set, append; Makefile.common: set; options.mk: set, append, use") | 579 | acl("PKG_SUPPORTED_OPTIONS", lkShell, CheckvarOption, "Makefile: set, append; Makefile.common: set; options.mk: set, append, use") | |
580 | pkg("PKG_SYSCONFDIR*", lkNone, CheckvarPathname) | 580 | pkg("PKG_SYSCONFDIR*", lkNone, CheckvarPathname) | |
581 | pkglist("PKG_SYSCONFDIR_PERMS", lkShell, CheckvarPerms) | 581 | pkglist("PKG_SYSCONFDIR_PERMS", lkShell, CheckvarPerms) | |
582 | sys("PKG_SYSCONFBASEDIR", lkNone, CheckvarPathname) | 582 | sys("PKG_SYSCONFBASEDIR", lkNone, CheckvarPathname) | |
583 | pkg("PKG_SYSCONFSUBDIR", lkNone, CheckvarPathname) | 583 | pkg("PKG_SYSCONFSUBDIR", lkNone, CheckvarPathname) | |
584 | acl("PKG_SYSCONFVAR", lkNone, CheckvarIdentifier, "") // FIXME: name/type mismatch. | 584 | acl("PKG_SYSCONFVAR", lkNone, CheckvarIdentifier, "") // FIXME: name/type mismatch. | |
585 | acl("PKG_UID", lkNone, CheckvarInteger, "Makefile: set") | 585 | acl("PKG_UID", lkNone, CheckvarInteger, "Makefile: set") | |
586 | acl("PKG_USERS", lkShell, CheckvarShellWord, "Makefile: set, append") | 586 | acl("PKG_USERS", lkShell, CheckvarShellWord, "Makefile: set, append") | |
587 | pkg("PKG_USERS_VARS", lkShell, CheckvarVarname) | 587 | pkg("PKG_USERS_VARS", lkShell, CheckvarVariableName) | |
588 | acl("PKG_USE_KERBEROS", lkNone, CheckvarYes, "Makefile, Makefile.common: set") | 588 | acl("PKG_USE_KERBEROS", lkNone, CheckvarYes, "Makefile, Makefile.common: set") | |
589 | // PLIST.* has special handling code | 589 | // PLIST.* has special handling code | |
590 | pkglist("PLIST_VARS", lkShell, CheckvarIdentifier) | 590 | pkglist("PLIST_VARS", lkShell, CheckvarIdentifier) | |
591 | pkglist("PLIST_SRC", lkShell, CheckvarRelativePkgPath) | 591 | pkglist("PLIST_SRC", lkShell, CheckvarRelativePkgPath) | |
592 | pkglist("PLIST_SUBST", lkShell, CheckvarShellWord) | 592 | pkglist("PLIST_SUBST", lkShell, CheckvarShellWord) | |
593 | acl("PLIST_TYPE", lkNone, enum("dynamic static"), "") | 593 | acl("PLIST_TYPE", lkNone, enum("dynamic static"), "") | |
594 | acl("PREPEND_PATH", lkShell, CheckvarPathname, "") | 594 | acl("PREPEND_PATH", lkShell, CheckvarPathname, "") | |
595 | acl("PREFIX", lkNone, CheckvarPathname, "*: use") | 595 | acl("PREFIX", lkNone, CheckvarPathname, "*: use") | |
596 | acl("PREV_PKGPATH", lkNone, CheckvarPathname, "*: use") // doesn't exist any longer | 596 | acl("PREV_PKGPATH", lkNone, CheckvarPathname, "*: use") // doesn't exist any longer | |
597 | acl("PRINT_PLIST_AWK", lkNone, CheckvarAwkCommand, "*: append") | 597 | acl("PRINT_PLIST_AWK", lkNone, CheckvarAwkCommand, "*: append") | |
598 | acl("PRIVILEGED_STAGES", lkShell, enum("install package clean"), "") | 598 | acl("PRIVILEGED_STAGES", lkShell, enum("install package clean"), "") | |
599 | acl("PTHREAD_AUTO_VARS", lkNone, CheckvarYesNo, "Makefile: set") | 599 | acl("PTHREAD_AUTO_VARS", lkNone, CheckvarYesNo, "Makefile: set") | |
600 | sys("PTHREAD_CFLAGS", lkShell, CheckvarCFlag) | 600 | sys("PTHREAD_CFLAGS", lkShell, CheckvarCFlag) | |
@@ -648,27 +648,27 @@ func (gd *GlobalData) InitVartypes() { | @@ -648,27 +648,27 @@ func (gd *GlobalData) InitVartypes() { | |||
648 | acl("SHLIBTOOL", lkNone, CheckvarShellCommand, "Makefile: use") | 648 | acl("SHLIBTOOL", lkNone, CheckvarShellCommand, "Makefile: use") | |
649 | acl("SHLIBTOOL_OVERRIDE", lkShell, CheckvarPathmask, "Makefile: set, append; Makefile.common: append") | 649 | acl("SHLIBTOOL_OVERRIDE", lkShell, CheckvarPathmask, "Makefile: set, append; Makefile.common: append") | |
650 | acl("SITES.*", lkShell, CheckvarFetchURL, "Makefile, Makefile.common, options.mk: set, append, use") | 650 | acl("SITES.*", lkShell, CheckvarFetchURL, "Makefile, Makefile.common, options.mk: set, append, use") | |
651 | pkglist("SPECIAL_PERMS", lkShell, CheckvarPerms) | 651 | pkglist("SPECIAL_PERMS", lkShell, CheckvarPerms) | |
652 | sys("STEP_MSG", lkNone, CheckvarShellCommand) | 652 | sys("STEP_MSG", lkNone, CheckvarShellCommand) | |
653 | acl("SUBDIR", lkShell, CheckvarFilename, "Makefile: append; *:") | 653 | acl("SUBDIR", lkShell, CheckvarFilename, "Makefile: append; *:") | |
654 | acl("SUBST_CLASSES", lkShell, CheckvarIdentifier, "Makefile: set, append; *: append") | 654 | acl("SUBST_CLASSES", lkShell, CheckvarIdentifier, "Makefile: set, append; *: append") | |
655 | acl("SUBST_CLASSES.*", lkShell, CheckvarIdentifier, "Makefile: set, append; *: append") | 655 | acl("SUBST_CLASSES.*", lkShell, CheckvarIdentifier, "Makefile: set, append; *: append") | |
656 | acl("SUBST_FILES.*", lkShell, CheckvarPathmask, "Makefile, Makefile.*, *.mk: set, append") | 656 | acl("SUBST_FILES.*", lkShell, CheckvarPathmask, "Makefile, Makefile.*, *.mk: set, append") | |
657 | acl("SUBST_FILTER_CMD.*", lkNone, CheckvarShellCommand, "Makefile, Makefile.*, *.mk: set") | 657 | acl("SUBST_FILTER_CMD.*", lkNone, CheckvarShellCommand, "Makefile, Makefile.*, *.mk: set") | |
658 | acl("SUBST_MESSAGE.*", lkNone, CheckvarMessage, "Makefile, Makefile.*, *.mk: set") | 658 | acl("SUBST_MESSAGE.*", lkNone, CheckvarMessage, "Makefile, Makefile.*, *.mk: set") | |
659 | acl("SUBST_SED.*", lkNone, CheckvarSedCommands, "Makefile, Makefile.*, *.mk: set, append") | 659 | acl("SUBST_SED.*", lkNone, CheckvarSedCommands, "Makefile, Makefile.*, *.mk: set, append") | |
660 | pkg("SUBST_STAGE.*", lkNone, CheckvarStage) | 660 | pkg("SUBST_STAGE.*", lkNone, CheckvarStage) | |
661 | pkglist("SUBST_VARS.*", lkShell, CheckvarVarname) | 661 | pkglist("SUBST_VARS.*", lkShell, CheckvarVariableName) | |
662 | pkglist("SUPERSEDES", lkSpace, CheckvarDependency) | 662 | pkglist("SUPERSEDES", lkSpace, CheckvarDependency) | |
663 | pkglist("TEST_DIRS", lkShell, CheckvarWrksrcSubdirectory) | 663 | pkglist("TEST_DIRS", lkShell, CheckvarWrksrcSubdirectory) | |
664 | pkglist("TEST_ENV", lkShell, CheckvarShellWord) | 664 | pkglist("TEST_ENV", lkShell, CheckvarShellWord) | |
665 | acl("TEST_TARGET", lkShell, CheckvarIdentifier, "Makefile: set; Makefile.common: default, set; options.mk: set, append") | 665 | acl("TEST_TARGET", lkShell, CheckvarIdentifier, "Makefile: set; Makefile.common: default, set; options.mk: set, append") | |
666 | acl("TEX_ACCEPTED", lkShell, enum("teTeX1 teTeX2 teTeX3"), "Makefile, Makefile.common: set") | 666 | acl("TEX_ACCEPTED", lkShell, enum("teTeX1 teTeX2 teTeX3"), "Makefile, Makefile.common: set") | |
667 | acl("TEX_DEPMETHOD", lkNone, enum("build run"), "Makefile, Makefile.common: set") | 667 | acl("TEX_DEPMETHOD", lkNone, enum("build run"), "Makefile, Makefile.common: set") | |
668 | pkglist("TEXINFO_REQD", lkShell, CheckvarVersion) | 668 | pkglist("TEXINFO_REQD", lkShell, CheckvarVersion) | |
669 | acl("TOOL_DEPENDS", lkSpace, CheckvarDependencyWithPath, "Makefile, Makefile.common, *.mk: append") | 669 | acl("TOOL_DEPENDS", lkSpace, CheckvarDependencyWithPath, "Makefile, Makefile.common, *.mk: append") | |
670 | sys("TOOLS_ALIASES", lkShell, CheckvarFilename) | 670 | sys("TOOLS_ALIASES", lkShell, CheckvarFilename) | |
671 | sys("TOOLS_BROKEN", lkShell, CheckvarTool) | 671 | sys("TOOLS_BROKEN", lkShell, CheckvarTool) | |
672 | sys("TOOLS_CMD.*", lkNone, CheckvarPathname) | 672 | sys("TOOLS_CMD.*", lkNone, CheckvarPathname) | |
673 | sys("TOOLS_CREATE", lkShell, CheckvarTool) | 673 | sys("TOOLS_CREATE", lkShell, CheckvarTool) | |
674 | acl("TOOLS_DEPENDS.*", lkSpace, CheckvarDependencyWithPath, "buildlink3.mk:; Makefile, Makefile.*: set, default; *: use") | 674 | acl("TOOLS_DEPENDS.*", lkSpace, CheckvarDependencyWithPath, "buildlink3.mk:; Makefile, Makefile.*: set, default; *: use") | |
@@ -714,45 +714,45 @@ func (gd *GlobalData) InitVartypes() { | @@ -714,45 +714,45 @@ func (gd *GlobalData) InitVartypes() { | |||
714 | pkg("WRKSRC", lkNone, CheckvarWrkdirSubdirectory) | 714 | pkg("WRKSRC", lkNone, CheckvarWrkdirSubdirectory) | |
715 | sys("X11_PKGSRCDIR.*", lkNone, CheckvarPathname) | 715 | sys("X11_PKGSRCDIR.*", lkNone, CheckvarPathname) | |
716 | usr("XAW_TYPE", lkNone, enum("3d neXtaw standard xpm")) | 716 | usr("XAW_TYPE", lkNone, enum("3d neXtaw standard xpm")) | |
717 | acl("XMKMF_FLAGS", lkShell, CheckvarShellWord, "") | 717 | acl("XMKMF_FLAGS", lkShell, CheckvarShellWord, "") | |
718 | } | 718 | } | |
719 | 719 | |||
720 | func enum(values string) *VarChecker { | 720 | func enum(values string) *VarChecker { | |
721 | vmap := make(map[string]bool) | 721 | vmap := make(map[string]bool) | |
722 | for _, value := range splitOnSpace(values) { | 722 | for _, value := range splitOnSpace(values) { | |
723 | vmap[value] = true | 723 | vmap[value] = true | |
724 | } | 724 | } | |
725 | name := "enum: " + values + " " // See IsEnum | 725 | name := "enum: " + values + " " // See IsEnum | |
726 | return &VarChecker{name, func(cv *VartypeCheck) { | 726 | return &VarChecker{name, func(cv *VartypeCheck) { | |
727 | if cv.op == opUseMatch { | 727 | if cv.Op == opUseMatch { | |
728 | if !vmap[cv.value] && cv.value == cv.valueNovar { | 728 | if !vmap[cv.Value] && cv.Value == cv.ValueNoVar { | |
729 | canMatch := false | 729 | canMatch := false | |
730 | for value := range vmap { | 730 | for value := range vmap { | |
731 | if ok, err := path.Match(cv.value, value); err != nil { | 731 | if ok, err := path.Match(cv.Value, value); err != nil { | |
732 | cv.line.Warnf("Invalid match pattern %q.", cv.value) | 732 | cv.Line.Warnf("Invalid match pattern %q.", cv.Value) | |
733 | } else if ok { | 733 | } else if ok { | |
734 | canMatch = true | 734 | canMatch = true | |
735 | } | 735 | } | |
736 | } | 736 | } | |
737 | if !canMatch { | 737 | if !canMatch { | |
738 | cv.line.Warnf("The pattern %q cannot match any of { %s } for %s.", cv.value, values, cv.varname) | 738 | cv.Line.Warnf("The pattern %q cannot match any of { %s } for %s.", cv.Value, values, cv.Varname) | |
739 | } | 739 | } | |
740 | } | 740 | } | |
741 | return | 741 | return | |
742 | } | 742 | } | |
743 | 743 | |||
744 | if cv.value == cv.valueNovar && !vmap[cv.value] { | 744 | if cv.Value == cv.ValueNoVar && !vmap[cv.Value] { | |
745 | cv.line.Warnf("%q is not valid for %s. Use one of { %s } instead.", cv.value, cv.varname, values) | 745 | cv.Line.Warnf("%q is not valid for %s. Use one of { %s } instead.", cv.Value, cv.Varname, values) | |
746 | } | 746 | } | |
747 | }} | 747 | }} | |
748 | } | 748 | } | |
749 | 749 | |||
750 | func acl(varname string, kindOfList KindOfList, checker *VarChecker, aclentries string) { | 750 | func acl(varname string, kindOfList KindOfList, checker *VarChecker, aclentries string) { | |
751 | m := mustMatch(varname, `^([A-Z_.][A-Z0-9_]*)(|\*|\.\*)$`) | 751 | m := mustMatch(varname, `^([A-Z_.][A-Z0-9_]*)(|\*|\.\*)$`) | |
752 | varbase, varparam := m[1], m[2] | 752 | varbase, varparam := m[1], m[2] | |
753 | 753 | |||
754 | vtype := &Vartype{kindOfList, checker, parseAclEntries(varname, aclentries), false} | 754 | vtype := &Vartype{kindOfList, checker, parseAclEntries(varname, aclentries), false} | |
755 | 755 | |||
756 | if G.globalData.vartypes == nil { | 756 | if G.globalData.vartypes == nil { | |
757 | G.globalData.vartypes = make(map[string]*Vartype) | 757 | G.globalData.vartypes = make(map[string]*Vartype) | |
758 | } | 758 | } |
@@ -1,93 +1,93 @@ | @@ -1,93 +1,93 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | "fmt" | 4 | "fmt" | |
5 | 5 | |||
6 | check "gopkg.in/check.v1" | 6 | check "gopkg.in/check.v1" | |
7 | ) | 7 | ) | |
8 | 8 | |||
9 | func (s *Suite) TestVartypeCheck_AwkCommand(c *check.C) { | 9 | func (s *Suite) Test_VartypeCheck_AwkCommand(c *check.C) { | |
10 | runVartypeChecks("PLIST_AWK", opAssignAppend, (*VartypeCheck).AwkCommand, | 10 | runVartypeChecks("PLIST_AWK", opAssignAppend, (*VartypeCheck).AwkCommand, | |
11 | "{print $0}", | 11 | "{print $0}", | |
12 | "{print $$0}") | 12 | "{print $$0}") | |
13 | 13 | |||
14 | c.Check(s.Output(), equals, "WARN: fname:1: $0 is ambiguous. Use ${0} if you mean a Makefile variable or $$0 if you mean a shell variable.\n") | 14 | c.Check(s.Output(), equals, "WARN: fname:1: $0 is ambiguous. Use ${0} if you mean a Makefile variable or $$0 if you mean a shell variable.\n") | |
15 | } | 15 | } | |
16 | 16 | |||
17 | func (s *Suite) TestVartypeCheck_BasicRegularExpression(c *check.C) { | 17 | func (s *Suite) Test_VartypeCheck_BasicRegularExpression(c *check.C) { | |
18 | runVartypeChecks("REPLACE_FILES.pl", opAssign, (*VartypeCheck).BasicRegularExpression, | 18 | runVartypeChecks("REPLACE_FILES.pl", opAssign, (*VartypeCheck).BasicRegularExpression, | |
19 | ".*\\.pl$", | 19 | ".*\\.pl$", | |
20 | ".*\\.pl$$") | 20 | ".*\\.pl$$") | |
21 | 21 | |||
22 | c.Check(s.Output(), equals, "WARN: fname:1: Pkglint parse error in MkLine.Tokenize at \"$\".\n") | 22 | c.Check(s.Output(), equals, "WARN: fname:1: Pkglint parse error in MkLine.Tokenize at \"$\".\n") | |
23 | } | 23 | } | |
24 | 24 | |||
25 | func (s *Suite) TestVartypeCheck_BuildlinkDepmethod(c *check.C) { | 25 | func (s *Suite) Test_VartypeCheck_BuildlinkDepmethod(c *check.C) { | |
26 | runVartypeChecks("BUILDLINK_DEPMETHOD.libc", opAssignDefault, (*VartypeCheck).BuildlinkDepmethod, | 26 | runVartypeChecks("BUILDLINK_DEPMETHOD.libc", opAssignDefault, (*VartypeCheck).BuildlinkDepmethod, | |
27 | "full", | 27 | "full", | |
28 | "unknown") | 28 | "unknown") | |
29 | 29 | |||
30 | c.Check(s.Output(), equals, "WARN: fname:2: Invalid dependency method \"unknown\". Valid methods are \"build\" or \"full\".\n") | 30 | c.Check(s.Output(), equals, "WARN: fname:2: Invalid dependency method \"unknown\". Valid methods are \"build\" or \"full\".\n") | |
31 | } | 31 | } | |
32 | 32 | |||
33 | func (s *Suite) TestVartypeCheck_Category(c *check.C) { | 33 | func (s *Suite) Test_VartypeCheck_Category(c *check.C) { | |
34 | s.CreateTmpFile(c, "filesyscategory/Makefile", "# empty\n") | 34 | s.CreateTmpFile(c, "filesyscategory/Makefile", "# empty\n") | |
35 | s.CreateTmpFile(c, "wip/Makefile", "# empty\n") | 35 | s.CreateTmpFile(c, "wip/Makefile", "# empty\n") | |
36 | G.CurrentDir = s.tmpdir | 36 | G.CurrentDir = s.tmpdir | |
37 | G.CurPkgsrcdir = "." | 37 | G.CurPkgsrcdir = "." | |
38 | 38 | |||
39 | runVartypeChecks("CATEGORIES", opAssign, (*VartypeCheck).Category, | 39 | runVartypeChecks("CATEGORIES", opAssign, (*VartypeCheck).Category, | |
40 | "chinese", | 40 | "chinese", | |
41 | "arabic", | 41 | "arabic", | |
42 | "filesyscategory", | 42 | "filesyscategory", | |
43 | "wip") | 43 | "wip") | |
44 | 44 | |||
45 | c.Check(s.Output(), equals, ""+ | 45 | c.Check(s.Output(), equals, ""+ | |
46 | "ERROR: fname:2: Invalid category \"arabic\".\n"+ | 46 | "ERROR: fname:2: Invalid category \"arabic\".\n"+ | |
47 | "ERROR: fname:4: Invalid category \"wip\".\n") | 47 | "ERROR: fname:4: Invalid category \"wip\".\n") | |
48 | } | 48 | } | |
49 | 49 | |||
50 | func (s *Suite) TestVartypeCheck_CFlag(c *check.C) { | 50 | func (s *Suite) Test_VartypeCheck_CFlag(c *check.C) { | |
51 | runVartypeChecks("CFLAGS", opAssignAppend, (*VartypeCheck).CFlag, | 51 | runVartypeChecks("CFLAGS", opAssignAppend, (*VartypeCheck).CFlag, | |
52 | "-Wall", | 52 | "-Wall", | |
53 | "/W3", | 53 | "/W3", | |
54 | "target:sparc64", | 54 | "target:sparc64", | |
55 | "-std=c99", | 55 | "-std=c99", | |
56 | "-XX:+PrintClassHistogramAfterFullGC", | 56 | "-XX:+PrintClassHistogramAfterFullGC", | |
57 | "`pkg-config pidgin --cflags`") | 57 | "`pkg-config pidgin --cflags`") | |
58 | 58 | |||
59 | c.Check(s.Output(), equals, ""+ | 59 | c.Check(s.Output(), equals, ""+ | |
60 | "WARN: fname:2: Compiler flag \"/W3\" should start with a hyphen.\n"+ | 60 | "WARN: fname:2: Compiler flag \"/W3\" should start with a hyphen.\n"+ | |
61 | "WARN: fname:3: Compiler flag \"target:sparc64\" should start with a hyphen.\n"+ | 61 | "WARN: fname:3: Compiler flag \"target:sparc64\" should start with a hyphen.\n"+ | |
62 | "WARN: fname:5: Unknown compiler flag \"-XX:+PrintClassHistogramAfterFullGC\".\n") | 62 | "WARN: fname:5: Unknown compiler flag \"-XX:+PrintClassHistogramAfterFullGC\".\n") | |
63 | } | 63 | } | |
64 | 64 | |||
65 | func (s *Suite) TestVartypeCheck_Comment(c *check.C) { | 65 | func (s *Suite) Test_VartypeCheck_Comment(c *check.C) { | |
66 | runVartypeChecks("COMMENT", opAssign, (*VartypeCheck).Comment, | 66 | runVartypeChecks("COMMENT", opAssign, (*VartypeCheck).Comment, | |
67 | "Versatile Programming Language", | 67 | "Versatile Programming Language", | |
68 | "TODO: Short description of the package", | 68 | "TODO: Short description of the package", | |
69 | "A great package.", | 69 | "A great package.", | |
70 | "some packages need a very very long comment to explain their basic usefulness") | 70 | "some packages need a very very long comment to explain their basic usefulness") | |
71 | 71 | |||
72 | c.Check(s.Output(), equals, ""+ | 72 | c.Check(s.Output(), equals, ""+ | |
73 | "ERROR: fname:2: COMMENT must be set.\n"+ | 73 | "ERROR: fname:2: COMMENT must be set.\n"+ | |
74 | "WARN: fname:3: COMMENT should not begin with \"A\".\n"+ | 74 | "WARN: fname:3: COMMENT should not begin with \"A\".\n"+ | |
75 | "WARN: fname:3: COMMENT should not end with a period.\n"+ | 75 | "WARN: fname:3: COMMENT should not end with a period.\n"+ | |
76 | "WARN: fname:4: COMMENT should start with a capital letter.\n"+ | 76 | "WARN: fname:4: COMMENT should start with a capital letter.\n"+ | |
77 | "WARN: fname:4: COMMENT should not be longer than 70 characters.\n") | 77 | "WARN: fname:4: COMMENT should not be longer than 70 characters.\n") | |
78 | } | 78 | } | |
79 | 79 | |||
80 | func (s *Suite) TestVartypeCheck_Dependency(c *check.C) { | 80 | func (s *Suite) Test_VartypeCheck_Dependency(c *check.C) { | |
81 | runVartypeChecks("CONFLICTS", opAssignAppend, (*VartypeCheck).Dependency, | 81 | runVartypeChecks("CONFLICTS", opAssignAppend, (*VartypeCheck).Dependency, | |
82 | "Perl", | 82 | "Perl", | |
83 | "perl5>=5.22", | 83 | "perl5>=5.22", | |
84 | "perl5-*", | 84 | "perl5-*", | |
85 | "perl5-5.22.*", | 85 | "perl5-5.22.*", | |
86 | "perl5-[5.10-5.22]*", | 86 | "perl5-[5.10-5.22]*", | |
87 | "py-docs", | 87 | "py-docs", | |
88 | "perl5-5.22.*{,nb*}", | 88 | "perl5-5.22.*{,nb*}", | |
89 | "libkipi>=0.1.5<4.0", | 89 | "libkipi>=0.1.5<4.0", | |
90 | "gtk2+>=2.16", | 90 | "gtk2+>=2.16", | |
91 | "perl-5.22", | 91 | "perl-5.22", | |
92 | "perl-5*", | 92 | "perl-5*", | |
93 | "gtksourceview-sharp-2.0-[0-9]*", | 93 | "gtksourceview-sharp-2.0-[0-9]*", | |
@@ -104,27 +104,27 @@ func (s *Suite) TestVartypeCheck_Depende | @@ -104,27 +104,27 @@ func (s *Suite) TestVartypeCheck_Depende | |||
104 | c.Check(s.Output(), equals, ""+ | 104 | c.Check(s.Output(), equals, ""+ | |
105 | "WARN: fname:1: Unknown dependency pattern \"Perl\".\n"+ | 105 | "WARN: fname:1: Unknown dependency pattern \"Perl\".\n"+ | |
106 | "WARN: fname:3: Please use \"perl5-[0-9]*\" instead of \"perl5-*\".\n"+ | 106 | "WARN: fname:3: Please use \"perl5-[0-9]*\" instead of \"perl5-*\".\n"+ | |
107 | "WARN: fname:5: Only [0-9]* is allowed in the numeric part of a dependency.\n"+ | 107 | "WARN: fname:5: Only [0-9]* is allowed in the numeric part of a dependency.\n"+ | |
108 | "WARN: fname:5: The version pattern \"[5.10-5.22]*\" should not contain a hyphen.\n"+ | 108 | "WARN: fname:5: The version pattern \"[5.10-5.22]*\" should not contain a hyphen.\n"+ | |
109 | "WARN: fname:6: Unknown dependency pattern \"py-docs\".\n"+ | 109 | "WARN: fname:6: Unknown dependency pattern \"py-docs\".\n"+ | |
110 | "WARN: fname:10: Please use \"5.22{,nb*}\" instead of \"5.22\" as the version pattern.\n"+ | 110 | "WARN: fname:10: Please use \"5.22{,nb*}\" instead of \"5.22\" as the version pattern.\n"+ | |
111 | "WARN: fname:11: Please use \"5.*\" instead of \"5*\" as the version pattern.\n"+ | 111 | "WARN: fname:11: Please use \"5.*\" instead of \"5*\" as the version pattern.\n"+ | |
112 | "WARN: fname:12: The version pattern \"2.0-[0-9]*\" should not contain a hyphen.\n"+ | 112 | "WARN: fname:12: The version pattern \"2.0-[0-9]*\" should not contain a hyphen.\n"+ | |
113 | "WARN: fname:20: The version pattern \"[0-9]*,openssh-[0-9]*}\" should not contain a hyphen.\n"+ // XXX | 113 | "WARN: fname:20: The version pattern \"[0-9]*,openssh-[0-9]*}\" should not contain a hyphen.\n"+ // XXX | |
114 | "WARN: fname:21: Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.\n") | 114 | "WARN: fname:21: Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.\n") | |
115 | } | 115 | } | |
116 | 116 | |||
117 | func (s *Suite) TestVartypeCheck_DependencyWithPath(c *check.C) { | 117 | func (s *Suite) Test_VartypeCheck_DependencyWithPath(c *check.C) { | |
118 | s.CreateTmpFile(c, "x11/alacarte/Makefile", "# empty\n") | 118 | s.CreateTmpFile(c, "x11/alacarte/Makefile", "# empty\n") | |
119 | s.CreateTmpFile(c, "category/package/Makefile", "# empty\n") | 119 | s.CreateTmpFile(c, "category/package/Makefile", "# empty\n") | |
120 | G.globalData.Pkgsrcdir = s.tmpdir | 120 | G.globalData.Pkgsrcdir = s.tmpdir | |
121 | G.CurrentDir = s.tmpdir + "/category/package" | 121 | G.CurrentDir = s.tmpdir + "/category/package" | |
122 | G.CurPkgsrcdir = "../.." | 122 | G.CurPkgsrcdir = "../.." | |
123 | 123 | |||
124 | runVartypeChecks("DEPENDS", opAssignAppend, (*VartypeCheck).DependencyWithPath, | 124 | runVartypeChecks("DEPENDS", opAssignAppend, (*VartypeCheck).DependencyWithPath, | |
125 | "Perl", | 125 | "Perl", | |
126 | "perl5>=5.22:../perl5", | 126 | "perl5>=5.22:../perl5", | |
127 | "perl5>=5.24:../../lang/perl5", | 127 | "perl5>=5.24:../../lang/perl5", | |
128 | "broken0.12.1:../../x11/alacarte", | 128 | "broken0.12.1:../../x11/alacarte", | |
129 | "broken[0-9]*:../../x11/alacarte", | 129 | "broken[0-9]*:../../x11/alacarte", | |
130 | "broken[0-9]*../../x11/alacarte", | 130 | "broken[0-9]*../../x11/alacarte", | |
@@ -141,57 +141,57 @@ func (s *Suite) TestVartypeCheck_Depende | @@ -141,57 +141,57 @@ func (s *Suite) TestVartypeCheck_Depende | |||
141 | "ERROR: fname:3: \"../../lang/perl5\" does not exist.\n"+ | 141 | "ERROR: fname:3: \"../../lang/perl5\" does not exist.\n"+ | |
142 | "ERROR: fname:3: There is no package in \"lang/perl5\".\n"+ | 142 | "ERROR: fname:3: There is no package in \"lang/perl5\".\n"+ | |
143 | "WARN: fname:3: Please use USE_TOOLS+=perl:run instead of this dependency.\n"+ | 143 | "WARN: fname:3: Please use USE_TOOLS+=perl:run instead of this dependency.\n"+ | |
144 | "WARN: fname:4: Unknown dependency pattern \"broken0.12.1\".\n"+ | 144 | "WARN: fname:4: Unknown dependency pattern \"broken0.12.1\".\n"+ | |
145 | "WARN: fname:5: Unknown dependency pattern \"broken[0-9]*\".\n"+ | 145 | "WARN: fname:5: Unknown dependency pattern \"broken[0-9]*\".\n"+ | |
146 | "WARN: fname:6: Unknown dependency pattern with path \"broken[0-9]*../../x11/alacarte\".\n"+ | 146 | "WARN: fname:6: Unknown dependency pattern with path \"broken[0-9]*../../x11/alacarte\".\n"+ | |
147 | "WARN: fname:7: Unknown dependency pattern \"broken>=\".\n"+ | 147 | "WARN: fname:7: Unknown dependency pattern \"broken>=\".\n"+ | |
148 | "WARN: fname:8: Unknown dependency pattern \"broken=0\".\n"+ | 148 | "WARN: fname:8: Unknown dependency pattern \"broken=0\".\n"+ | |
149 | "WARN: fname:9: Unknown dependency pattern \"broken=\".\n"+ | 149 | "WARN: fname:9: Unknown dependency pattern \"broken=\".\n"+ | |
150 | "WARN: fname:10: Unknown dependency pattern \"broken-\".\n"+ | 150 | "WARN: fname:10: Unknown dependency pattern \"broken-\".\n"+ | |
151 | "WARN: fname:11: Unknown dependency pattern \"broken>\".\n") | 151 | "WARN: fname:11: Unknown dependency pattern \"broken>\".\n") | |
152 | } | 152 | } | |
153 | 153 | |||
154 | func (s *Suite) TestVartypeCheck_DistSuffix(c *check.C) { | 154 | func (s *Suite) Test_VartypeCheck_DistSuffix(c *check.C) { | |
155 | runVartypeChecks("EXTRACT_SUFX", opAssign, (*VartypeCheck).DistSuffix, | 155 | runVartypeChecks("EXTRACT_SUFX", opAssign, (*VartypeCheck).DistSuffix, | |
156 | ".tar.gz", | 156 | ".tar.gz", | |
157 | ".tar.bz2") | 157 | ".tar.bz2") | |
158 | 158 | |||
159 | c.Check(s.Output(), equals, "NOTE: fname:1: EXTRACT_SUFX is \".tar.gz\" by default, so this definition may be redundant.\n") | 159 | c.Check(s.Output(), equals, "NOTE: fname:1: EXTRACT_SUFX is \".tar.gz\" by default, so this definition may be redundant.\n") | |
160 | } | 160 | } | |
161 | 161 | |||
162 | func (s *Suite) TestVartypeCheck_EmulPlatform(c *check.C) { | 162 | func (s *Suite) Test_VartypeCheck_EmulPlatform(c *check.C) { | |
163 | runVartypeChecks("EMUL_PLATFORM", opAssign, (*VartypeCheck).EmulPlatform, | 163 | runVartypeChecks("EMUL_PLATFORM", opAssign, (*VartypeCheck).EmulPlatform, | |
164 | "linux-i386", | 164 | "linux-i386", | |
165 | "nextbsd-8087", | 165 | "nextbsd-8087", | |
166 | "${LINUX}") | 166 | "${LINUX}") | |
167 | 167 | |||
168 | c.Check(s.Output(), equals, ""+ | 168 | c.Check(s.Output(), equals, ""+ | |
169 | "WARN: fname:2: \"nextbsd\" is not valid for the operating system part of EMUL_PLATFORM. Use one of { bitrig bsdos cygwin darwin dragonfly freebsd haiku hpux interix irix linux mirbsd netbsd openbsd osf1 solaris sunos } instead.\n"+ | 169 | "WARN: fname:2: \"nextbsd\" is not valid for the operating system part of EMUL_PLATFORM. Use one of { bitrig bsdos cygwin darwin dragonfly freebsd haiku hpux interix irix linux mirbsd netbsd openbsd osf1 solaris sunos } instead.\n"+ | |
170 | "WARN: fname:2: \"8087\" is not valid for the hardware architecture part of EMUL_PLATFORM. Use one of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } instead.\n"+ | 170 | "WARN: fname:2: \"8087\" is not valid for the hardware architecture part of EMUL_PLATFORM. Use one of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } instead.\n"+ | |
171 | "WARN: fname:3: \"${LINUX}\" is not a valid emulation platform.\n") | 171 | "WARN: fname:3: \"${LINUX}\" is not a valid emulation platform.\n") | |
172 | } | 172 | } | |
173 | 173 | |||
174 | func (s *Suite) TestVartypeCheck_Enum(c *check.C) { | 174 | func (s *Suite) Test_VartypeCheck_Enum(c *check.C) { | |
175 | runVartypeMatchChecks("JDK", enum("jdk1 jdk2 jdk4").checker, | 175 | runVartypeMatchChecks("JDK", enum("jdk1 jdk2 jdk4").checker, | |
176 | "*", | 176 | "*", | |
177 | "jdk*", | 177 | "jdk*", | |
178 | "sun-jdk*", | 178 | "sun-jdk*", | |
179 | "${JDKNAME}") | 179 | "${JDKNAME}") | |
180 | 180 | |||
181 | c.Check(s.Output(), equals, "WARN: fname:3: The pattern \"sun-jdk*\" cannot match any of { jdk1 jdk2 jdk4 } for JDK.\n") | 181 | c.Check(s.Output(), equals, "WARN: fname:3: The pattern \"sun-jdk*\" cannot match any of { jdk1 jdk2 jdk4 } for JDK.\n") | |
182 | } | 182 | } | |
183 | 183 | |||
184 | func (s *Suite) TestVartypeCheck_FetchURL(c *check.C) { | 184 | func (s *Suite) Test_VartypeCheck_FetchURL(c *check.C) { | |
185 | s.RegisterMasterSite("MASTER_SITE_GNU", "http://ftp.gnu.org/pub/gnu/") | 185 | s.RegisterMasterSite("MASTER_SITE_GNU", "http://ftp.gnu.org/pub/gnu/") | |
186 | s.RegisterMasterSite("MASTER_SITE_GITHUB", "https://github.com/") | 186 | s.RegisterMasterSite("MASTER_SITE_GITHUB", "https://github.com/") | |
187 | 187 | |||
188 | runVartypeChecks("MASTER_SITES", opAssign, (*VartypeCheck).FetchURL, | 188 | runVartypeChecks("MASTER_SITES", opAssign, (*VartypeCheck).FetchURL, | |
189 | "https://github.com/example/project/", | 189 | "https://github.com/example/project/", | |
190 | "http://ftp.gnu.org/pub/gnu/bison", // Missing a slash at the end | 190 | "http://ftp.gnu.org/pub/gnu/bison", // Missing a slash at the end | |
191 | "${MASTER_SITE_GNU:=bison}", | 191 | "${MASTER_SITE_GNU:=bison}", | |
192 | "${MASTER_SITE_INVALID:=subdir/}") | 192 | "${MASTER_SITE_INVALID:=subdir/}") | |
193 | 193 | |||
194 | c.Check(s.Output(), equals, ""+ | 194 | c.Check(s.Output(), equals, ""+ | |
195 | "WARN: fname:1: Please use ${MASTER_SITE_GITHUB:=example/} instead of \"https://github.com/example/project/\" and run \""+confMake+" help topic=github\" for further tips.\n"+ | 195 | "WARN: fname:1: Please use ${MASTER_SITE_GITHUB:=example/} instead of \"https://github.com/example/project/\" and run \""+confMake+" help topic=github\" for further tips.\n"+ | |
196 | "WARN: fname:2: Please use ${MASTER_SITE_GNU:=bison} instead of \"http://ftp.gnu.org/pub/gnu/bison\".\n"+ | 196 | "WARN: fname:2: Please use ${MASTER_SITE_GNU:=bison} instead of \"http://ftp.gnu.org/pub/gnu/bison\".\n"+ | |
197 | "ERROR: fname:3: The subdirectory in MASTER_SITE_GNU must end with a slash.\n"+ | 197 | "ERROR: fname:3: The subdirectory in MASTER_SITE_GNU must end with a slash.\n"+ | |
@@ -201,262 +201,262 @@ func (s *Suite) TestVartypeCheck_FetchUR | @@ -201,262 +201,262 @@ func (s *Suite) TestVartypeCheck_FetchUR | |||
201 | runVartypeChecks("MASTER_SITES", opAssign, (*VartypeCheck).FetchURL, | 201 | runVartypeChecks("MASTER_SITES", opAssign, (*VartypeCheck).FetchURL, | |
202 | "https://example.org/download.cgi?fname=fname&sha1=12341234") | 202 | "https://example.org/download.cgi?fname=fname&sha1=12341234") | |
203 | 203 | |||
204 | c.Check(s.Output(), equals, "") | 204 | c.Check(s.Output(), equals, "") | |
205 | 205 | |||
206 | runVartypeChecks("MASTER_SITES", opAssign, (*VartypeCheck).FetchURL, | 206 | runVartypeChecks("MASTER_SITES", opAssign, (*VartypeCheck).FetchURL, | |
207 | "http://example.org/distfiles/", | 207 | "http://example.org/distfiles/", | |
208 | "http://example.org/download?fname=distfile;version=1.0", | 208 | "http://example.org/download?fname=distfile;version=1.0", | |
209 | "http://example.org/download?fname=<distfile>;version=<version>") | 209 | "http://example.org/download?fname=<distfile>;version=<version>") | |
210 | 210 | |||
211 | c.Check(s.Output(), equals, "WARN: fname:3: \"http://example.org/download?fname=<distfile>;version=<version>\" is not a valid URL.\n") | 211 | c.Check(s.Output(), equals, "WARN: fname:3: \"http://example.org/download?fname=<distfile>;version=<version>\" is not a valid URL.\n") | |
212 | } | 212 | } | |
213 | 213 | |||
214 | func (s *Suite) TestVartypeCheck_Filename(c *check.C) { | 214 | func (s *Suite) Test_VartypeCheck_Filename(c *check.C) { | |
215 | runVartypeChecks("FNAME", opAssign, (*VartypeCheck).Filename, | 215 | runVartypeChecks("FNAME", opAssign, (*VartypeCheck).Filename, | |
216 | "Filename with spaces.docx", | 216 | "Filename with spaces.docx", | |
217 | "OS/2-manual.txt") | 217 | "OS/2-manual.txt") | |
218 | 218 | |||
219 | c.Check(s.Output(), equals, ""+ | 219 | c.Check(s.Output(), equals, ""+ | |
220 | "WARN: fname:1: \"Filename with spaces.docx\" is not a valid filename.\n"+ | 220 | "WARN: fname:1: \"Filename with spaces.docx\" is not a valid filename.\n"+ | |
221 | "WARN: fname:2: A filename should not contain a slash.\n") | 221 | "WARN: fname:2: A filename should not contain a slash.\n") | |
222 | } | 222 | } | |
223 | 223 | |||
224 | func (s *Suite) TestVartypeCheck_LdFlag(c *check.C) { | 224 | func (s *Suite) Test_VartypeCheck_LdFlag(c *check.C) { | |
225 | runVartypeChecks("LDFLAGS", opAssignAppend, (*VartypeCheck).LdFlag, | 225 | runVartypeChecks("LDFLAGS", opAssignAppend, (*VartypeCheck).LdFlag, | |
226 | "-lc", | 226 | "-lc", | |
227 | "-L/usr/lib64", | 227 | "-L/usr/lib64", | |
228 | "`pkg-config pidgin --ldflags`", | 228 | "`pkg-config pidgin --ldflags`", | |
229 | "-unknown") | 229 | "-unknown") | |
230 | 230 | |||
231 | c.Check(s.Output(), equals, "WARN: fname:4: Unknown linker flag \"-unknown\".\n") | 231 | c.Check(s.Output(), equals, "WARN: fname:4: Unknown linker flag \"-unknown\".\n") | |
232 | } | 232 | } | |
233 | 233 | |||
234 | func (s *Suite) TestVartypeCheck_MachineGnuPlatform(c *check.C) { | 234 | func (s *Suite) Test_VartypeCheck_MachineGnuPlatform(c *check.C) { | |
235 | runVartypeMatchChecks("MACHINE_GNU_PLATFORM", (*VartypeCheck).MachineGnuPlatform, | 235 | runVartypeMatchChecks("MACHINE_GNU_PLATFORM", (*VartypeCheck).MachineGnuPlatform, | |
236 | "x86_64-pc-cygwin", | 236 | "x86_64-pc-cygwin", | |
237 | "Cygwin-*-amd64") | 237 | "Cygwin-*-amd64") | |
238 | 238 | |||
239 | c.Check(s.Output(), equals, ""+ | 239 | c.Check(s.Output(), equals, ""+ | |
240 | "WARN: fname:2: The pattern \"Cygwin\" cannot match any of { aarch64 aarch64_be alpha amd64 arc arm armeb armv4 armv4eb armv6 armv6eb armv7 armv7eb cobalt convex dreamcast hpcmips hpcsh hppa hppa64 i386 i486 ia64 m5407 m68010 m68k m88k mips mips64 mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh shle sparc sparc64 vax x86_64 } for the hardware architecture part of MACHINE_GNU_PLATFORM.\n"+ | 240 | "WARN: fname:2: The pattern \"Cygwin\" cannot match any of { aarch64 aarch64_be alpha amd64 arc arm armeb armv4 armv4eb armv6 armv6eb armv7 armv7eb cobalt convex dreamcast hpcmips hpcsh hppa hppa64 i386 i486 ia64 m5407 m68010 m68k m88k mips mips64 mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh shle sparc sparc64 vax x86_64 } for the hardware architecture part of MACHINE_GNU_PLATFORM.\n"+ | |
241 | "WARN: fname:2: The pattern \"amd64\" cannot match any of { bitrig bsdos cygwin darwin dragonfly freebsd haiku hpux interix irix linux mirbsd netbsd openbsd osf1 solaris sunos } for the operating system part of MACHINE_GNU_PLATFORM.\n") | 241 | "WARN: fname:2: The pattern \"amd64\" cannot match any of { bitrig bsdos cygwin darwin dragonfly freebsd haiku hpux interix irix linux mirbsd netbsd openbsd osf1 solaris sunos } for the operating system part of MACHINE_GNU_PLATFORM.\n") | |
242 | } | 242 | } | |
243 | 243 | |||
244 | func (s *Suite) TestVartypeCheck_MailAddress(c *check.C) { | 244 | func (s *Suite) Test_VartypeCheck_MailAddress(c *check.C) { | |
245 | runVartypeChecks("MAINTAINER", opAssign, (*VartypeCheck).MailAddress, | 245 | runVartypeChecks("MAINTAINER", opAssign, (*VartypeCheck).MailAddress, | |
246 | "pkgsrc-users@netbsd.org") | 246 | "pkgsrc-users@netbsd.org") | |
247 | 247 | |||
248 | c.Check(s.Output(), equals, "WARN: fname:1: Please write \"NetBSD.org\" instead of \"netbsd.org\".\n") | 248 | c.Check(s.Output(), equals, "WARN: fname:1: Please write \"NetBSD.org\" instead of \"netbsd.org\".\n") | |
249 | } | 249 | } | |
250 | 250 | |||
251 | func (s *Suite) TestVartypeCheck_Message(c *check.C) { | 251 | func (s *Suite) Test_VartypeCheck_Message(c *check.C) { | |
252 | runVartypeChecks("SUBST_MESSAGE.id", opAssign, (*VartypeCheck).Message, | 252 | runVartypeChecks("SUBST_MESSAGE.id", opAssign, (*VartypeCheck).Message, | |
253 | "\"Correct paths\"", | 253 | "\"Correct paths\"", | |
254 | "Correct paths") | 254 | "Correct paths") | |
255 | 255 | |||
256 | c.Check(s.Output(), equals, "WARN: fname:1: SUBST_MESSAGE.id should not be quoted.\n") | 256 | c.Check(s.Output(), equals, "WARN: fname:1: SUBST_MESSAGE.id should not be quoted.\n") | |
257 | } | 257 | } | |
258 | 258 | |||
259 | func (s *Suite) TestVartypeCheck_Option(c *check.C) { | 259 | func (s *Suite) Test_VartypeCheck_Option(c *check.C) { | |
260 | G.globalData.PkgOptions = map[string]string{ | 260 | G.globalData.PkgOptions = map[string]string{ | |
261 | "documented": "Option description", | 261 | "documented": "Option description", | |
262 | "undocumented": "", | 262 | "undocumented": "", | |
263 | } | 263 | } | |
264 | 264 | |||
265 | runVartypeChecks("PKG_OPTIONS.pkgbase", opAssign, (*VartypeCheck).Option, | 265 | runVartypeChecks("PKG_OPTIONS.pkgbase", opAssign, (*VartypeCheck).Option, | |
266 | "documented", | 266 | "documented", | |
267 | "undocumented", | 267 | "undocumented", | |
268 | "unknown") | 268 | "unknown") | |
269 | 269 | |||
270 | c.Check(s.Output(), equals, "WARN: fname:3: Unknown option \"unknown\".\n") | 270 | c.Check(s.Output(), equals, "WARN: fname:3: Unknown option \"unknown\".\n") | |
271 | } | 271 | } | |
272 | 272 | |||
273 | func (s *Suite) TestVartypeCheck_Pathlist(c *check.C) { | 273 | func (s *Suite) Test_VartypeCheck_Pathlist(c *check.C) { | |
274 | runVartypeChecks("PATH", opAssign, (*VartypeCheck).Pathlist, | 274 | runVartypeChecks("PATH", opAssign, (*VartypeCheck).Pathlist, | |
275 | "/usr/bin:/usr/sbin:.:${LOCALBASE}/bin") | 275 | "/usr/bin:/usr/sbin:.:${LOCALBASE}/bin") | |
276 | 276 | |||
277 | c.Check(s.Output(), equals, "WARN: fname:1: All components of PATH (in this case \".\") should be absolute paths.\n") | 277 | c.Check(s.Output(), equals, "WARN: fname:1: All components of PATH (in this case \".\") should be absolute paths.\n") | |
278 | } | 278 | } | |
279 | 279 | |||
280 | func (s *Suite) Test_VartypeCheck_Perms(c *check.C) { | 280 | func (s *Suite) Test_VartypeCheck_Perms(c *check.C) { | |
281 | runVartypeChecks("CONF_FILES_PERMS", opAssignAppend, (*VartypeCheck).Perms, | 281 | runVartypeChecks("CONF_FILES_PERMS", opAssignAppend, (*VartypeCheck).Perms, | |
282 | "root", | 282 | "root", | |
283 | "${ROOT_USER}", | 283 | "${ROOT_USER}", | |
284 | "ROOT_USER", | 284 | "ROOT_USER", | |
285 | "${REAL_ROOT_USER}") | 285 | "${REAL_ROOT_USER}") | |
286 | 286 | |||
287 | c.Check(s.Output(), equals, "ERROR: fname:2: ROOT_USER must not be used in permission definitions. Use REAL_ROOT_USER instead.\n") | 287 | c.Check(s.Output(), equals, "ERROR: fname:2: ROOT_USER must not be used in permission definitions. Use REAL_ROOT_USER instead.\n") | |
288 | } | 288 | } | |
289 | 289 | |||
290 | func (s *Suite) TestVartypeCheck_PkgOptionsVar(c *check.C) { | 290 | func (s *Suite) Test_VartypeCheck_PkgOptionsVar(c *check.C) { | |
291 | runVartypeChecks("PKG_OPTIONS_VAR.screen", opAssign, (*VartypeCheck).PkgOptionsVar, | 291 | runVartypeChecks("PKG_OPTIONS_VAR.screen", opAssign, (*VartypeCheck).PkgOptionsVar, | |
292 | "PKG_OPTIONS.${PKGBASE}", | 292 | "PKG_OPTIONS.${PKGBASE}", | |
293 | "PKG_OPTIONS.anypkgbase") | 293 | "PKG_OPTIONS.anypkgbase") | |
294 | 294 | |||
295 | c.Check(s.Output(), equals, ""+ | 295 | c.Check(s.Output(), equals, ""+ | |
296 | "ERROR: fname:1: PKGBASE must not be used in PKG_OPTIONS_VAR.\n") | 296 | "ERROR: fname:1: PKGBASE must not be used in PKG_OPTIONS_VAR.\n") | |
297 | } | 297 | } | |
298 | 298 | |||
299 | func (s *Suite) TestVartypeCheck_PkgRevision(c *check.C) { | 299 | func (s *Suite) Test_VartypeCheck_PkgRevision(c *check.C) { | |
300 | runVartypeChecks("PKGREVISION", opAssign, (*VartypeCheck).PkgRevision, | 300 | runVartypeChecks("PKGREVISION", opAssign, (*VartypeCheck).PkgRevision, | |
301 | "3a") | 301 | "3a") | |
302 | 302 | |||
303 | c.Check(s.Output(), equals, ""+ | 303 | c.Check(s.Output(), equals, ""+ | |
304 | "WARN: fname:1: PKGREVISION must be a positive integer number.\n"+ | 304 | "WARN: fname:1: PKGREVISION must be a positive integer number.\n"+ | |
305 | "ERROR: fname:1: PKGREVISION only makes sense directly in the package Makefile.\n") | 305 | "ERROR: fname:1: PKGREVISION only makes sense directly in the package Makefile.\n") | |
306 | 306 | |||
307 | runVartypeChecksFname("Makefile", "PKGREVISION", opAssign, (*VartypeCheck).PkgRevision, | 307 | runVartypeChecksFname("Makefile", "PKGREVISION", opAssign, (*VartypeCheck).PkgRevision, | |
308 | "3") | 308 | "3") | |
309 | 309 | |||
310 | c.Check(s.Output(), equals, "") | 310 | c.Check(s.Output(), equals, "") | |
311 | } | 311 | } | |
312 | 312 | |||
313 | func (s *Suite) TestVartypeCheck_MachinePlatformPattern(c *check.C) { | 313 | func (s *Suite) Test_VartypeCheck_MachinePlatformPattern(c *check.C) { | |
314 | runVartypeMatchChecks("ONLY_FOR_PLATFORM", (*VartypeCheck).MachinePlatformPattern, | 314 | runVartypeMatchChecks("ONLY_FOR_PLATFORM", (*VartypeCheck).MachinePlatformPattern, | |
315 | "linux-i386", | 315 | "linux-i386", | |
316 | "nextbsd-5.0-8087", | 316 | "nextbsd-5.0-8087", | |
317 | "netbsd-7.0-l*", | 317 | "netbsd-7.0-l*", | |
318 | "NetBSD-1.6.2-i386", | 318 | "NetBSD-1.6.2-i386", | |
319 | "FreeBSD*", | 319 | "FreeBSD*", | |
320 | "FreeBSD-*", | 320 | "FreeBSD-*", | |
321 | "${LINUX}") | 321 | "${LINUX}") | |
322 | 322 | |||
323 | c.Check(s.Output(), equals, ""+ | 323 | c.Check(s.Output(), equals, ""+ | |
324 | "WARN: fname:1: \"linux-i386\" is not a valid platform pattern.\n"+ | 324 | "WARN: fname:1: \"linux-i386\" is not a valid platform pattern.\n"+ | |
325 | "WARN: fname:2: The pattern \"nextbsd\" cannot match any of { AIX BSDOS Bitrig Cygwin Darwin DragonFly FreeBSD FreeMiNT GNUkFreeBSD HPUX Haiku IRIX Interix Linux Minix MirBSD NetBSD OSF1 OpenBSD QNX SCO_SV SunOS UnixWare } for the operating system part of ONLY_FOR_PLATFORM.\n"+ | 325 | "WARN: fname:2: The pattern \"nextbsd\" cannot match any of { AIX BSDOS Bitrig Cygwin Darwin DragonFly FreeBSD FreeMiNT GNUkFreeBSD HPUX Haiku IRIX Interix Linux Minix MirBSD NetBSD OSF1 OpenBSD QNX SCO_SV SunOS UnixWare } for the operating system part of ONLY_FOR_PLATFORM.\n"+ | |
326 | "WARN: fname:2: The pattern \"8087\" cannot match any of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of ONLY_FOR_PLATFORM.\n"+ | 326 | "WARN: fname:2: The pattern \"8087\" cannot match any of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of ONLY_FOR_PLATFORM.\n"+ | |
327 | "WARN: fname:3: The pattern \"netbsd\" cannot match any of { AIX BSDOS Bitrig Cygwin Darwin DragonFly FreeBSD FreeMiNT GNUkFreeBSD HPUX Haiku IRIX Interix Linux Minix MirBSD NetBSD OSF1 OpenBSD QNX SCO_SV SunOS UnixWare } for the operating system part of ONLY_FOR_PLATFORM.\n"+ | 327 | "WARN: fname:3: The pattern \"netbsd\" cannot match any of { AIX BSDOS Bitrig Cygwin Darwin DragonFly FreeBSD FreeMiNT GNUkFreeBSD HPUX Haiku IRIX Interix Linux Minix MirBSD NetBSD OSF1 OpenBSD QNX SCO_SV SunOS UnixWare } for the operating system part of ONLY_FOR_PLATFORM.\n"+ | |
328 | "WARN: fname:3: The pattern \"l*\" cannot match any of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of ONLY_FOR_PLATFORM.\n"+ | 328 | "WARN: fname:3: The pattern \"l*\" cannot match any of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of ONLY_FOR_PLATFORM.\n"+ | |
329 | "WARN: fname:5: \"FreeBSD*\" is not a valid platform pattern.\n") | 329 | "WARN: fname:5: \"FreeBSD*\" is not a valid platform pattern.\n") | |
330 | } | 330 | } | |
331 | 331 | |||
332 | func (s *Suite) TestVartypeCheck_PythonDependency(c *check.C) { | 332 | func (s *Suite) Test_VartypeCheck_PythonDependency(c *check.C) { | |
333 | runVartypeChecks("PYTHON_VERSIONED_DEPENDENCIES", opAssign, (*VartypeCheck).PythonDependency, | 333 | runVartypeChecks("PYTHON_VERSIONED_DEPENDENCIES", opAssign, (*VartypeCheck).PythonDependency, | |
334 | "cairo", | 334 | "cairo", | |
335 | "${PYDEP}", | 335 | "${PYDEP}", | |
336 | "cairo,X") | 336 | "cairo,X") | |
337 | 337 | |||
338 | c.Check(s.Output(), equals, ""+ | 338 | c.Check(s.Output(), equals, ""+ | |
339 | "WARN: fname:2: Python dependencies should not contain variables.\n"+ | 339 | "WARN: fname:2: Python dependencies should not contain variables.\n"+ | |
340 | "WARN: fname:3: Invalid Python dependency \"cairo,X\".\n") | 340 | "WARN: fname:3: Invalid Python dependency \"cairo,X\".\n") | |
341 | } | 341 | } | |
342 | 342 | |||
343 | func (s *Suite) TestVartypeCheck_Restricted(c *check.C) { | 343 | func (s *Suite) Test_VartypeCheck_Restricted(c *check.C) { | |
344 | runVartypeChecks("NO_BIN_ON_CDROM", opAssign, (*VartypeCheck).Restricted, | 344 | runVartypeChecks("NO_BIN_ON_CDROM", opAssign, (*VartypeCheck).Restricted, | |
345 | "May only be distributed free of charge") | 345 | "May only be distributed free of charge") | |
346 | 346 | |||
347 | c.Check(s.Output(), equals, "WARN: fname:1: The only valid value for NO_BIN_ON_CDROM is ${RESTRICTED}.\n") | 347 | c.Check(s.Output(), equals, "WARN: fname:1: The only valid value for NO_BIN_ON_CDROM is ${RESTRICTED}.\n") | |
348 | } | 348 | } | |
349 | 349 | |||
350 | func (s *Suite) TestVartypeCheck_SedCommands(c *check.C) { | 350 | func (s *Suite) Test_VartypeCheck_SedCommands(c *check.C) { | |
351 | runVartypeChecks("SUBST_SED.dummy", opAssign, (*VartypeCheck).SedCommands, | 351 | runVartypeChecks("SUBST_SED.dummy", opAssign, (*VartypeCheck).SedCommands, | |
352 | "s,@COMPILER@,gcc,g", | 352 | "s,@COMPILER@,gcc,g", | |
353 | "-e s,a,b, -e a,b,c,", | 353 | "-e s,a,b, -e a,b,c,", | |
354 | "-e \"s,#,comment ,\"", | 354 | "-e \"s,#,comment ,\"", | |
355 | "-e \"s,\\#,comment ,\"") | 355 | "-e \"s,\\#,comment ,\"") | |
356 | 356 | |||
357 | c.Check(s.Output(), equals, ""+ | 357 | c.Check(s.Output(), equals, ""+ | |
358 | "NOTE: fname:1: Please always use \"-e\" in sed commands, even if there is only one substitution.\n"+ | 358 | "NOTE: fname:1: Please always use \"-e\" in sed commands, even if there is only one substitution.\n"+ | |
359 | "NOTE: fname:2: Each sed command should appear in an assignment of its own.\n") | 359 | "NOTE: fname:2: Each sed command should appear in an assignment of its own.\n") | |
360 | } | 360 | } | |
361 | 361 | |||
362 | func (s *Suite) TestVartypeCheck_ShellCommands(c *check.C) { | 362 | func (s *Suite) Test_VartypeCheck_ShellCommands(c *check.C) { | |
363 | runVartypeChecks("GENERATE_PLIST", opAssign, (*VartypeCheck).ShellCommands, | 363 | runVartypeChecks("GENERATE_PLIST", opAssign, (*VartypeCheck).ShellCommands, | |
364 | "echo bin/program", | 364 | "echo bin/program", | |
365 | "echo bin/program;") | 365 | "echo bin/program;") | |
366 | 366 | |||
367 | c.Check(s.Output(), equals, "WARN: fname:1: This shell command list should end with a semicolon.\n") | 367 | c.Check(s.Output(), equals, "WARN: fname:1: This shell command list should end with a semicolon.\n") | |
368 | } | 368 | } | |
369 | 369 | |||
370 | func (s *Suite) TestVartypeCheck_Stage(c *check.C) { | 370 | func (s *Suite) Test_VartypeCheck_Stage(c *check.C) { | |
371 | runVartypeChecks("SUBST_STAGE.dummy", opAssign, (*VartypeCheck).Stage, | 371 | runVartypeChecks("SUBST_STAGE.dummy", opAssign, (*VartypeCheck).Stage, | |
372 | "post-patch", | 372 | "post-patch", | |
373 | "post-modern", | 373 | "post-modern", | |
374 | "pre-test") | 374 | "pre-test") | |
375 | 375 | |||
376 | c.Check(s.Output(), equals, "WARN: fname:2: Invalid stage name \"post-modern\". Use one of {pre,do,post}-{extract,patch,configure,build,test,install}.\n") | 376 | c.Check(s.Output(), equals, "WARN: fname:2: Invalid stage name \"post-modern\". Use one of {pre,do,post}-{extract,patch,configure,build,test,install}.\n") | |
377 | } | 377 | } | |
378 | 378 | |||
379 | func (s *Suite) TestVartypeCheck_Varname(c *check.C) { | 379 | func (s *Suite) Test_VartypeCheck_VariableName(c *check.C) { | |
380 | runVartypeChecks("BUILD_DEFS", opAssign, (*VartypeCheck).Varname, | 380 | runVartypeChecks("BUILD_DEFS", opAssign, (*VartypeCheck).VariableName, | |
381 | "VARBASE", | 381 | "VARBASE", | |
382 | "VarBase", | 382 | "VarBase", | |
383 | "PKG_OPTIONS_VAR.pkgbase", | 383 | "PKG_OPTIONS_VAR.pkgbase", | |
384 | "${INDIRECT}") | 384 | "${INDIRECT}") | |
385 | 385 | |||
386 | c.Check(s.Output(), equals, "WARN: fname:2: \"VarBase\" is not a valid variable name.\n") | 386 | c.Check(s.Output(), equals, "WARN: fname:2: \"VarBase\" is not a valid variable name.\n") | |
387 | } | 387 | } | |
388 | 388 | |||
389 | func (s *Suite) TestVartypeCheck_Yes(c *check.C) { | 389 | func (s *Suite) Test_VartypeCheck_Yes(c *check.C) { | |
390 | runVartypeChecks("APACHE_MODULE", opAssign, (*VartypeCheck).Yes, | 390 | runVartypeChecks("APACHE_MODULE", opAssign, (*VartypeCheck).Yes, | |
391 | "yes", | 391 | "yes", | |
392 | "no", | 392 | "no", | |
393 | "${YESVAR}") | 393 | "${YESVAR}") | |
394 | 394 | |||
395 | c.Check(s.Output(), equals, ""+ | 395 | c.Check(s.Output(), equals, ""+ | |
396 | "WARN: fname:2: APACHE_MODULE should be set to YES or yes.\n"+ | 396 | "WARN: fname:2: APACHE_MODULE should be set to YES or yes.\n"+ | |
397 | "WARN: fname:3: APACHE_MODULE should be set to YES or yes.\n") | 397 | "WARN: fname:3: APACHE_MODULE should be set to YES or yes.\n") | |
398 | 398 | |||
399 | runVartypeMatchChecks("PKG_DEVELOPER", (*VartypeCheck).Yes, | 399 | runVartypeMatchChecks("PKG_DEVELOPER", (*VartypeCheck).Yes, | |
400 | "yes", | 400 | "yes", | |
401 | "no", | 401 | "no", | |
402 | "${YESVAR}") | 402 | "${YESVAR}") | |
403 | 403 | |||
404 | c.Check(s.Output(), equals, ""+ | 404 | c.Check(s.Output(), equals, ""+ | |
405 | "WARN: fname:1: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n"+ | 405 | "WARN: fname:1: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n"+ | |
406 | "WARN: fname:2: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n"+ | 406 | "WARN: fname:2: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n"+ | |
407 | "WARN: fname:3: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n") | 407 | "WARN: fname:3: PKG_DEVELOPER should only be used in a \".if defined(...)\" conditional.\n") | |
408 | } | 408 | } | |
409 | 409 | |||
410 | func (s *Suite) TestVartypeCheck_YesNo(c *check.C) { | 410 | func (s *Suite) Test_VartypeCheck_YesNo(c *check.C) { | |
411 | runVartypeChecks("GNU_CONFIGURE", opAssign, (*VartypeCheck).YesNo, | 411 | runVartypeChecks("GNU_CONFIGURE", opAssign, (*VartypeCheck).YesNo, | |
412 | "yes", | 412 | "yes", | |
413 | "no", | 413 | "no", | |
414 | "ja", | 414 | "ja", | |
415 | "${YESVAR}") | 415 | "${YESVAR}") | |
416 | 416 | |||
417 | c.Check(s.Output(), equals, ""+ | 417 | c.Check(s.Output(), equals, ""+ | |
418 | "WARN: fname:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n"+ | 418 | "WARN: fname:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n"+ | |
419 | "WARN: fname:4: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n") | 419 | "WARN: fname:4: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n") | |
420 | } | 420 | } | |
421 | 421 | |||
422 | func (s *Suite) TestVartypeCheck_YesNoIndirectly(c *check.C) { | 422 | func (s *Suite) Test_VartypeCheck_YesNoIndirectly(c *check.C) { | |
423 | runVartypeChecks("GNU_CONFIGURE", opAssign, (*VartypeCheck).YesNoIndirectly, | 423 | runVartypeChecks("GNU_CONFIGURE", opAssign, (*VartypeCheck).YesNoIndirectly, | |
424 | "yes", | 424 | "yes", | |
425 | "no", | 425 | "no", | |
426 | "ja", | 426 | "ja", | |
427 | "${YESVAR}") | 427 | "${YESVAR}") | |
428 | 428 | |||
429 | c.Check(s.Output(), equals, ""+ | 429 | c.Check(s.Output(), equals, ""+ | |
430 | "WARN: fname:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n") | 430 | "WARN: fname:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.\n") | |
431 | } | 431 | } | |
432 | 432 | |||
433 | func runVartypeChecks(varname string, op MkOperator, checker func(*VartypeCheck), values ...string) { | 433 | func runVartypeChecks(varname string, op MkOperator, checker func(*VartypeCheck), values ...string) { | |
434 | if !contains(op.String(), "=") { | 434 | if !contains(op.String(), "=") { | |
435 | panic("runVartypeChecks needs an assignment operator") | 435 | panic("runVartypeChecks needs an assignment operator") | |
436 | } | 436 | } | |
437 | for i, value := range values { | 437 | for i, value := range values { | |
438 | mkline := NewMkLine(NewLine("fname", i+1, varname+op.String()+value, nil)) | 438 | mkline := NewMkLine(NewLine("fname", i+1, varname+op.String()+value, nil)) | |
439 | valueNovar := mkline.withoutMakeVariables(mkline.Value(), true) | 439 | valueNovar := mkline.withoutMakeVariables(mkline.Value()) | |
440 | vc := &VartypeCheck{mkline, mkline.Line, mkline.Varname(), mkline.Op(), mkline.Value(), valueNovar, "", true, false} | 440 | vc := &VartypeCheck{mkline, mkline.Line, mkline.Varname(), mkline.Op(), mkline.Value(), valueNovar, "", false} | |
441 | checker(vc) | 441 | checker(vc) | |
442 | } | 442 | } | |
443 | } | 443 | } | |
444 | 444 | |||
445 | func runVartypeMatchChecks(varname string, checker func(*VartypeCheck), values ...string) { | 445 | func runVartypeMatchChecks(varname string, checker func(*VartypeCheck), values ...string) { | |
446 | for i, value := range values { | 446 | for i, value := range values { | |
447 | text := fmt.Sprintf(".if ${%s:M%s} == \"\"", varname, value) | 447 | text := fmt.Sprintf(".if ${%s:M%s} == \"\"", varname, value) | |
448 | mkline := NewMkLine(NewLine("fname", i+1, text, nil)) | 448 | mkline := NewMkLine(NewLine("fname", i+1, text, nil)) | |
449 | valueNovar := mkline.withoutMakeVariables(value, true) | 449 | valueNovar := mkline.withoutMakeVariables(value) | |
450 | vc := &VartypeCheck{mkline, mkline.Line, varname, opUseMatch, value, valueNovar, "", true, false} | 450 | vc := &VartypeCheck{mkline, mkline.Line, varname, opUseMatch, value, valueNovar, "", false} | |
451 | checker(vc) | 451 | checker(vc) | |
452 | } | 452 | } | |
453 | } | 453 | } | |
454 | 454 | |||
455 | func runVartypeChecksFname(fname, varname string, op MkOperator, checker func(*VartypeCheck), values ...string) { | 455 | func runVartypeChecksFname(fname, varname string, op MkOperator, checker func(*VartypeCheck), values ...string) { | |
456 | for i, value := range values { | 456 | for i, value := range values { | |
457 | mkline := NewMkLine(NewLine(fname, i+1, varname+op.String()+value, nil)) | 457 | mkline := NewMkLine(NewLine(fname, i+1, varname+op.String()+value, nil)) | |
458 | valueNovar := mkline.withoutMakeVariables(value, true) | 458 | valueNovar := mkline.withoutMakeVariables(value) | |
459 | vc := &VartypeCheck{mkline, mkline.Line, varname, op, value, valueNovar, "", true, false} | 459 | vc := &VartypeCheck{mkline, mkline.Line, varname, op, value, valueNovar, "", false} | |
460 | checker(vc) | 460 | checker(vc) | |
461 | } | 461 | } | |
462 | } | 462 | } |
@@ -30,36 +30,36 @@ type RawLine struct { | @@ -30,36 +30,36 @@ type RawLine struct { | |||
30 | func (rline *RawLine) String() string { | 30 | func (rline *RawLine) String() string { | |
31 | return strconv.Itoa(rline.Lineno) + ":" + rline.textnl | 31 | return strconv.Itoa(rline.Lineno) + ":" + rline.textnl | |
32 | } | 32 | } | |
33 | 33 | |||
34 | type Line struct { | 34 | type Line struct { | |
35 | Fname string | 35 | Fname string | |
36 | firstLine int32 // Zero means not applicable, -1 means EOF | 36 | firstLine int32 // Zero means not applicable, -1 means EOF | |
37 | lastLine int32 // Usually the same as firstLine, may differ in Makefiles | 37 | lastLine int32 // Usually the same as firstLine, may differ in Makefiles | |
38 | Text string | 38 | Text string | |
39 | raw []*RawLine | 39 | raw []*RawLine | |
40 | changed bool | 40 | changed bool | |
41 | before []string | 41 | before []string | |
42 | after []string | 42 | after []string | |
43 | autofixMessage *string | 43 | autofixMessage string | |
44 | } | 44 | } | |
45 | 45 | |||
46 | func NewLine(fname string, lineno int, text string, rawLines []*RawLine) *Line { | 46 | func NewLine(fname string, lineno int, text string, rawLines []*RawLine) *Line { | |
47 | return NewLineMulti(fname, lineno, lineno, text, rawLines) | 47 | return NewLineMulti(fname, lineno, lineno, text, rawLines) | |
48 | } | 48 | } | |
49 | 49 | |||
50 | // NewLineMulti is for logical Makefile lines that end with backslash. | 50 | // NewLineMulti is for logical Makefile lines that end with backslash. | |
51 | func NewLineMulti(fname string, firstLine, lastLine int, text string, rawLines []*RawLine) *Line { | 51 | func NewLineMulti(fname string, firstLine, lastLine int, text string, rawLines []*RawLine) *Line { | |
52 | return &Line{fname, int32(firstLine), int32(lastLine), text, rawLines, false, nil, nil, nil} | 52 | return &Line{fname, int32(firstLine), int32(lastLine), text, rawLines, false, nil, nil, ""} | |
53 | } | 53 | } | |
54 | 54 | |||
55 | // NewLineEOF creates a dummy line for logging, with the “line number” EOF. | 55 | // NewLineEOF creates a dummy line for logging, with the “line number” EOF. | |
56 | func NewLineEOF(fname string) *Line { | 56 | func NewLineEOF(fname string) *Line { | |
57 | return NewLineMulti(fname, -1, 0, "", nil) | 57 | return NewLineMulti(fname, -1, 0, "", nil) | |
58 | } | 58 | } | |
59 | 59 | |||
60 | // NewLineWhole creates a dummy line for logging messages that affect a file as a whole. | 60 | // NewLineWhole creates a dummy line for logging messages that affect a file as a whole. | |
61 | func NewLineWhole(fname string) *Line { | 61 | func NewLineWhole(fname string) *Line { | |
62 | return NewLine(fname, 0, "", nil) | 62 | return NewLine(fname, 0, "", nil) | |
63 | } | 63 | } | |
64 | 64 | |||
65 | func (line *Line) modifiedLines() []string { | 65 | func (line *Line) modifiedLines() []string { | |
@@ -147,29 +147,29 @@ func (line *Line) Notef(format string, a | @@ -147,29 +147,29 @@ func (line *Line) Notef(format string, a | |||
147 | line.printSource(G.logOut) | 147 | line.printSource(G.logOut) | |
148 | logs(llNote, line.Fname, line.linenos(), format, fmt.Sprintf(format, args...)) | 148 | logs(llNote, line.Fname, line.linenos(), format, fmt.Sprintf(format, args...)) | |
149 | line.logAutofix() | 149 | line.logAutofix() | |
150 | } | 150 | } | |
151 | func (line *Line) Note0(format string) { line.Notef(format) } | 151 | func (line *Line) Note0(format string) { line.Notef(format) } | |
152 | func (line *Line) Note1(format, arg1 string) { line.Notef(format, arg1) } | 152 | func (line *Line) Note1(format, arg1 string) { line.Notef(format, arg1) } | |
153 | func (line *Line) Note2(format, arg1, arg2 string) { line.Notef(format, arg1, arg2) } | 153 | func (line *Line) Note2(format, arg1, arg2 string) { line.Notef(format, arg1, arg2) } | |
154 | 154 | |||
155 | func (line *Line) String() string { | 155 | func (line *Line) String() string { | |
156 | return line.Fname + ":" + line.linenos() + ": " + line.Text | 156 | return line.Fname + ":" + line.linenos() + ": " + line.Text | |
157 | } | 157 | } | |
158 | 158 | |||
159 | func (line *Line) logAutofix() { | 159 | func (line *Line) logAutofix() { | |
160 | if line.autofixMessage != nil { | 160 | if line.autofixMessage != "" { | |
161 | logs(llAutofix, line.Fname, line.linenos(), "%s", *line.autofixMessage) | 161 | logs(llAutofix, line.Fname, line.linenos(), "%s", line.autofixMessage) | |
162 | line.autofixMessage = nil | 162 | line.autofixMessage = "" | |
163 | } | 163 | } | |
164 | } | 164 | } | |
165 | 165 | |||
166 | func (line *Line) AutofixInsertBefore(text string) bool { | 166 | func (line *Line) AutofixInsertBefore(text string) bool { | |
167 | if G.opts.PrintAutofix || G.opts.Autofix { | 167 | if G.opts.PrintAutofix || G.opts.Autofix { | |
168 | line.before = append(line.before, text+"\n") | 168 | line.before = append(line.before, text+"\n") | |
169 | } | 169 | } | |
170 | return line.RememberAutofix("Inserting a line %q before this line.", text) | 170 | return line.RememberAutofix("Inserting a line %q before this line.", text) | |
171 | } | 171 | } | |
172 | 172 | |||
173 | func (line *Line) AutofixInsertAfter(text string) bool { | 173 | func (line *Line) AutofixInsertAfter(text string) bool { | |
174 | if G.opts.PrintAutofix || G.opts.Autofix { | 174 | if G.opts.PrintAutofix || G.opts.Autofix { | |
175 | line.after = append(line.after, text+"\n") | 175 | line.after = append(line.after, text+"\n") | |
@@ -190,52 +190,51 @@ func (line *Line) AutofixReplace(from, t | @@ -190,52 +190,51 @@ func (line *Line) AutofixReplace(from, t | |||
190 | for _, rawLine := range line.raw { | 190 | for _, rawLine := range line.raw { | |
191 | if rawLine.Lineno != 0 { | 191 | if rawLine.Lineno != 0 { | |
192 | if replaced := strings.Replace(rawLine.textnl, from, to, 1); replaced != rawLine.textnl { | 192 | if replaced := strings.Replace(rawLine.textnl, from, to, 1); replaced != rawLine.textnl { | |
193 | if G.opts.PrintAutofix || G.opts.Autofix { | 193 | if G.opts.PrintAutofix || G.opts.Autofix { | |
194 | rawLine.textnl = replaced | 194 | rawLine.textnl = replaced | |
195 | } | 195 | } | |
196 | return line.RememberAutofix("Replacing %q with %q.", from, to) | 196 | return line.RememberAutofix("Replacing %q with %q.", from, to) | |
197 | } | 197 | } | |
198 | } | 198 | } | |
199 | } | 199 | } | |
200 | return false | 200 | return false | |
201 | } | 201 | } | |
202 | 202 | |||
203 | func (line *Line) AutofixReplaceRegexp(from, to string) bool { | 203 | func (line *Line) AutofixReplaceRegexp(from RegexPattern, to string) bool { | |
204 | for _, rawLine := range line.raw { | 204 | for _, rawLine := range line.raw { | |
205 | if rawLine.Lineno != 0 { | 205 | if rawLine.Lineno != 0 { | |
206 | if replaced := regcomp(from).ReplaceAllString(rawLine.textnl, to); replaced != rawLine.textnl { | 206 | if replaced := regcomp(from).ReplaceAllString(rawLine.textnl, to); replaced != rawLine.textnl { | |
207 | if G.opts.PrintAutofix || G.opts.Autofix { | 207 | if G.opts.PrintAutofix || G.opts.Autofix { | |
208 | rawLine.textnl = replaced | 208 | rawLine.textnl = replaced | |
209 | } | 209 | } | |
210 | return line.RememberAutofix("Replacing regular expression %q with %q.", from, to) | 210 | return line.RememberAutofix("Replacing regular expression %q with %q.", from, to) | |
211 | } | 211 | } | |
212 | } | 212 | } | |
213 | } | 213 | } | |
214 | return false | 214 | return false | |
215 | } | 215 | } | |
216 | 216 | |||
217 | func (line *Line) RememberAutofix(format string, args ...interface{}) (hasBeenFixed bool) { | 217 | func (line *Line) RememberAutofix(format string, args ...interface{}) (hasBeenFixed bool) { | |
218 | if line.firstLine < 1 { | 218 | if line.firstLine < 1 { | |
219 | return false | 219 | return false | |
220 | } | 220 | } | |
221 | line.changed = true | 221 | line.changed = true | |
222 | if G.opts.Autofix { | 222 | if G.opts.Autofix { | |
223 | logs(llAutofix, line.Fname, line.linenos(), format, fmt.Sprintf(format, args...)) | 223 | logs(llAutofix, line.Fname, line.linenos(), format, fmt.Sprintf(format, args...)) | |
224 | return true | 224 | return true | |
225 | } | 225 | } | |
226 | if G.opts.PrintAutofix { | 226 | if G.opts.PrintAutofix { | |
227 | msg := fmt.Sprintf(format, args...) | 227 | line.autofixMessage = fmt.Sprintf(format, args...) | |
228 | line.autofixMessage = &msg | |||
229 | } | 228 | } | |
230 | return false | 229 | return false | |
231 | } | 230 | } | |
232 | 231 | |||
233 | func (line *Line) CheckAbsolutePathname(text string) { | 232 | func (line *Line) CheckAbsolutePathname(text string) { | |
234 | if G.opts.Debug { | 233 | if G.opts.Debug { | |
235 | defer tracecall1(text)() | 234 | defer tracecall1(text)() | |
236 | } | 235 | } | |
237 | 236 | |||
238 | // In the GNU coding standards, DESTDIR is defined as a (usually | 237 | // In the GNU coding standards, DESTDIR is defined as a (usually | |
239 | // empty) prefix that can be used to install files to a different | 238 | // empty) prefix that can be used to install files to a different | |
240 | // location from what they have been built for. Therefore | 239 | // location from what they have been built for. Therefore | |
241 | // everything following it is considered an absolute pathname. | 240 | // everything following it is considered an absolute pathname. | |
@@ -249,51 +248,51 @@ func (line *Line) CheckAbsolutePathname( | @@ -249,51 +248,51 @@ func (line *Line) CheckAbsolutePathname( | |||
249 | } | 248 | } | |
250 | } | 249 | } | |
251 | 250 | |||
252 | func (line *Line) CheckLength(maxlength int) { | 251 | func (line *Line) CheckLength(maxlength int) { | |
253 | if len(line.Text) > maxlength { | 252 | if len(line.Text) > maxlength { | |
254 | line.Warnf("Line too long (should be no more than %d characters).", maxlength) | 253 | line.Warnf("Line too long (should be no more than %d characters).", maxlength) | |
255 | Explain3( | 254 | Explain3( | |
256 | "Back in the old time, terminals with 80x25 characters were common.", | 255 | "Back in the old time, terminals with 80x25 characters were common.", | |
257 | "And this is still the default size of many terminal emulators.", | 256 | "And this is still the default size of many terminal emulators.", | |
258 | "Moderately short lines also make reading easier.") | 257 | "Moderately short lines also make reading easier.") | |
259 | } | 258 | } | |
260 | } | 259 | } | |
261 | 260 | |||
262 | func (line *Line) CheckValidCharacters(reChar string) { | 261 | func (line *Line) CheckValidCharacters(reChar RegexPattern) { | |
263 | rest := regcomp(reChar).ReplaceAllString(line.Text, "") | 262 | rest := regcomp(reChar).ReplaceAllString(line.Text, "") | |
264 | if rest != "" { | 263 | if rest != "" { | |
265 | uni := "" | 264 | uni := "" | |
266 | for _, c := range rest { | 265 | for _, c := range rest { | |
267 | uni += fmt.Sprintf(" %U", c) | 266 | uni += fmt.Sprintf(" %U", c) | |
268 | } | 267 | } | |
269 | line.Warn1("Line contains invalid characters (%s).", uni[1:]) | 268 | line.Warn1("Line contains invalid characters (%s).", uni[1:]) | |
270 | } | 269 | } | |
271 | } | 270 | } | |
272 | 271 | |||
273 | func (line *Line) CheckTrailingWhitespace() { | 272 | func (line *Line) CheckTrailingWhitespace() { | |
274 | if hasSuffix(line.Text, " ") || hasSuffix(line.Text, "\t") { | 273 | if hasSuffix(line.Text, " ") || hasSuffix(line.Text, "\t") { | |
275 | if !line.AutofixReplaceRegexp(`\s+\n$`, "\n") { | 274 | if !line.AutofixReplaceRegexp(`\s+\n$`, "\n") { | |
276 | line.Note0("Trailing white-space.") | 275 | line.Note0("Trailing white-space.") | |
277 | Explain2( | 276 | Explain2( | |
278 | "When a line ends with some white-space, that space is in most cases", | 277 | "When a line ends with some white-space, that space is in most cases", | |
279 | "irrelevant and can be removed.") | 278 | "irrelevant and can be removed.") | |
280 | } | 279 | } | |
281 | } | 280 | } | |
282 | } | 281 | } | |
283 | 282 | |||
284 | func (line *Line) CheckRcsid(prefixRe, suggestedPrefix string) bool { | 283 | func (line *Line) CheckRcsid(prefixRe RegexPattern, suggestedPrefix string) bool { | |
285 | if G.opts.Debug { | 284 | if G.opts.Debug { | |
286 | defer tracecall2(prefixRe, suggestedPrefix)() | 285 | defer tracecall(prefixRe, suggestedPrefix)() | |
287 | } | 286 | } | |
288 | 287 | |||
289 | if matches(line.Text, `^`+prefixRe+`\$`+`NetBSD(?::[^\$]+)?\$$`) { | 288 | if matches(line.Text, `^`+prefixRe+`\$`+`NetBSD(?::[^\$]+)?\$$`) { | |
290 | return true | 289 | return true | |
291 | } | 290 | } | |
292 | 291 | |||
293 | if !line.AutofixInsertBefore(suggestedPrefix + "$" + "NetBSD$") { | 292 | if !line.AutofixInsertBefore(suggestedPrefix + "$" + "NetBSD$") { | |
294 | line.Error1("Expected %q.", suggestedPrefix+"$"+"NetBSD$") | 293 | line.Error1("Expected %q.", suggestedPrefix+"$"+"NetBSD$") | |
295 | Explain3( | 294 | Explain3( | |
296 | "Several files in pkgsrc must contain the CVS Id, so that their", | 295 | "Several files in pkgsrc must contain the CVS Id, so that their", | |
297 | "current version can be traced back later from a binary package.", | 296 | "current version can be traced back later from a binary package.", | |
298 | "This is to ensure reproducible builds, for example for finding bugs.") | 297 | "This is to ensure reproducible builds, for example for finding bugs.") | |
299 | } | 298 | } |
@@ -15,27 +15,27 @@ const ( | @@ -15,27 +15,27 @@ const ( | |||
15 | reShDollar = `\\\$\$|` + reShVaruse + `|\$\$[,\-/|]` | 15 | reShDollar = `\\\$\$|` + reShVaruse + `|\$\$[,\-/|]` | |
16 | ) | 16 | ) | |
17 | 17 | |||
18 | type ShellLine struct { | 18 | type ShellLine struct { | |
19 | line *Line | 19 | line *Line | |
20 | mkline *MkLine | 20 | mkline *MkLine | |
21 | } | 21 | } | |
22 | 22 | |||
23 | func NewShellLine(mkline *MkLine) *ShellLine { | 23 | func NewShellLine(mkline *MkLine) *ShellLine { | |
24 | return &ShellLine{mkline.Line, mkline} | 24 | return &ShellLine{mkline.Line, mkline} | |
25 | } | 25 | } | |
26 | 26 | |||
27 | var shellcommandsContextType = &Vartype{lkNone, CheckvarShellCommands, []AclEntry{{"*", aclpAllRuntime}}, false} | 27 | var shellcommandsContextType = &Vartype{lkNone, CheckvarShellCommands, []AclEntry{{"*", aclpAllRuntime}}, false} | |
28 | var shellwordVuc = &VarUseContext{shellcommandsContextType, vucTimeUnknown, vucQuotPlain, vucExtentWord} | 28 | var shellwordVuc = &VarUseContext{shellcommandsContextType, vucTimeUnknown, vucQuotPlain, false} | |
29 | 29 | |||
30 | func (shline *ShellLine) CheckWord(token string, checkQuoting bool) { | 30 | func (shline *ShellLine) CheckWord(token string, checkQuoting bool) { | |
31 | if G.opts.Debug { | 31 | if G.opts.Debug { | |
32 | defer tracecall(token, checkQuoting)() | 32 | defer tracecall(token, checkQuoting)() | |
33 | } | 33 | } | |
34 | 34 | |||
35 | if token == "" || hasPrefix(token, "#") { | 35 | if token == "" || hasPrefix(token, "#") { | |
36 | return | 36 | return | |
37 | } | 37 | } | |
38 | 38 | |||
39 | line := shline.line | 39 | line := shline.line | |
40 | 40 | |||
41 | p := NewMkParser(line, token, false) | 41 | p := NewMkParser(line, token, false) | |
@@ -197,27 +197,27 @@ func (shline *ShellLine) checkVaruseToke | @@ -197,27 +197,27 @@ func (shline *ShellLine) checkVaruseToke | |||
197 | case quoting == shqBackt: | 197 | case quoting == shqBackt: | |
198 | // Don't check anything here, to avoid false positives for tool names. | 198 | // Don't check anything here, to avoid false positives for tool names. | |
199 | case (quoting == shqSquot || quoting == shqDquot) && matches(varname, `^(?:.*DIR|.*FILE|.*PATH|.*_VAR|PREFIX|.*BASE|PKGNAME)$`): | 199 | case (quoting == shqSquot || quoting == shqDquot) && matches(varname, `^(?:.*DIR|.*FILE|.*PATH|.*_VAR|PREFIX|.*BASE|PKGNAME)$`): | |
200 | // This is ok if we don't allow these variables to have embedded [\$\\\"\'\`]. | 200 | // This is ok if we don't allow these variables to have embedded [\$\\\"\'\`]. | |
201 | case quoting == shqDquot && varuse.IsQ(): | 201 | case quoting == shqDquot && varuse.IsQ(): | |
202 | shline.line.Warn0("Please don't use the :Q operator in double quotes.") | 202 | shline.line.Warn0("Please don't use the :Q operator in double quotes.") | |
203 | Explain2( | 203 | Explain2( | |
204 | "Either remove the :Q or the double quotes. In most cases, it is", | 204 | "Either remove the :Q or the double quotes. In most cases, it is", | |
205 | "more appropriate to remove the double quotes.") | 205 | "more appropriate to remove the double quotes.") | |
206 | } | 206 | } | |
207 | 207 | |||
208 | if varname != "@" { | 208 | if varname != "@" { | |
209 | vucstate := quoting.ToVarUseContext() | 209 | vucstate := quoting.ToVarUseContext() | |
210 | vuc := &VarUseContext{shellcommandsContextType, vucTimeUnknown, vucstate, vucExtentWordpart} | 210 | vuc := &VarUseContext{shellcommandsContextType, vucTimeUnknown, vucstate, true} | |
211 | shline.mkline.CheckVaruse(varuse, vuc) | 211 | shline.mkline.CheckVaruse(varuse, vuc) | |
212 | } | 212 | } | |
213 | return true | 213 | return true | |
214 | } | 214 | } | |
215 | 215 | |||
216 | // Scan for the end of the backticks, checking for single backslashes | 216 | // Scan for the end of the backticks, checking for single backslashes | |
217 | // and removing one level of backslashes. Backslashes are only removed | 217 | // and removing one level of backslashes. Backslashes are only removed | |
218 | // before a dollar, a backslash or a backtick. | 218 | // before a dollar, a backslash or a backtick. | |
219 | // | 219 | // | |
220 | // See http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03 | 220 | // See http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_03 | |
221 | func (shline *ShellLine) unescapeBackticks(shellword string, repl *PrefixReplacer, quoting ShQuoting) (unescaped string, newQuoting ShQuoting) { | 221 | func (shline *ShellLine) unescapeBackticks(shellword string, repl *PrefixReplacer, quoting ShQuoting) (unescaped string, newQuoting ShQuoting) { | |
222 | if G.opts.Debug { | 222 | if G.opts.Debug { | |
223 | defer tracecall(shellword, quoting, "=>", ref(&unescaped))() | 223 | defer tracecall(shellword, quoting, "=>", ref(&unescaped))() |
@@ -1,119 +1,119 @@ | @@ -1,119 +1,119 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | "strings" | 4 | "strings" | |
5 | 5 | |||
6 | check "gopkg.in/check.v1" | 6 | check "gopkg.in/check.v1" | |
7 | ) | 7 | ) | |
8 | 8 | |||
9 | func (s *Suite) Test_SplitIntoShellTokens_LineContinuation(c *check.C) { | 9 | func (s *Suite) Test_splitIntoShellTokens__line_continuation(c *check.C) { | |
10 | words, rest := splitIntoShellTokens(dummyLine, "if true; then \\") | 10 | words, rest := splitIntoShellTokens(dummyLine, "if true; then \\") | |
11 | 11 | |||
12 | c.Check(words, check.DeepEquals, []string{"if", "true", ";", "then"}) | 12 | c.Check(words, check.DeepEquals, []string{"if", "true", ";", "then"}) | |
13 | c.Check(rest, equals, "\\") | 13 | c.Check(rest, equals, "\\") | |
14 | 14 | |||
15 | c.Check(s.Output(), equals, "WARN: Pkglint parse error in ShTokenizer.ShAtom at \"\\\\\" (quoting=plain)\n") | 15 | c.Check(s.Output(), equals, "WARN: Pkglint parse error in ShTokenizer.ShAtom at \"\\\\\" (quoting=plain)\n") | |
16 | } | 16 | } | |
17 | 17 | |||
18 | func (s *Suite) Test_SplitIntoShellTokens_DollarSlash(c *check.C) { | 18 | func (s *Suite) Test_splitIntoShellTokens__dollar_slash(c *check.C) { | |
19 | words, rest := splitIntoShellTokens(dummyLine, "pax -s /.*~$$//g") | 19 | words, rest := splitIntoShellTokens(dummyLine, "pax -s /.*~$$//g") | |
20 | 20 | |||
21 | c.Check(words, check.DeepEquals, []string{"pax", "-s", "/.*~$$//g"}) | 21 | c.Check(words, check.DeepEquals, []string{"pax", "-s", "/.*~$$//g"}) | |
22 | c.Check(rest, equals, "") | 22 | c.Check(rest, equals, "") | |
23 | } | 23 | } | |
24 | 24 | |||
25 | func (s *Suite) Test_SplitIntoShellTokens_DollarSubshell(c *check.C) { | 25 | func (s *Suite) Test_splitIntoShellTokens__dollar_subshell(c *check.C) { | |
26 | words, rest := splitIntoShellTokens(dummyLine, "id=$$(${AWK} '{print}' < ${WRKSRC}/idfile) && echo \"$$id\"") | 26 | words, rest := splitIntoShellTokens(dummyLine, "id=$$(${AWK} '{print}' < ${WRKSRC}/idfile) && echo \"$$id\"") | |
27 | 27 | |||
28 | c.Check(words, deepEquals, []string{"id=", "$$(", "${AWK}", "'{print}'", "<", "${WRKSRC}/idfile", ")", "&&", "echo", "\"$$id\""}) | 28 | c.Check(words, deepEquals, []string{"id=", "$$(", "${AWK}", "'{print}'", "<", "${WRKSRC}/idfile", ")", "&&", "echo", "\"$$id\""}) | |
29 | c.Check(rest, equals, "") | 29 | c.Check(rest, equals, "") | |
30 | } | 30 | } | |
31 | 31 | |||
32 | func (s *Suite) Test_SplitIntoShellTokens_Semicolons(c *check.C) { | 32 | func (s *Suite) Test_splitIntoShellTokens__semicolons(c *check.C) { | |
33 | words, rest := splitIntoShellTokens(dummyLine, "word1 word2;;;") | 33 | words, rest := splitIntoShellTokens(dummyLine, "word1 word2;;;") | |
34 | 34 | |||
35 | c.Check(words, deepEquals, []string{"word1", "word2", ";;", ";"}) | 35 | c.Check(words, deepEquals, []string{"word1", "word2", ";;", ";"}) | |
36 | c.Check(rest, equals, "") | 36 | c.Check(rest, equals, "") | |
37 | } | 37 | } | |
38 | 38 | |||
39 | func (s *Suite) Test_SplitIntoShellTokens_Whitespace(c *check.C) { | 39 | func (s *Suite) Test_splitIntoShellTokens__whitespace(c *check.C) { | |
40 | text := "\t${RUN} cd ${WRKSRC}&&(${ECHO} ${PERL5:Q};${ECHO})|${BASH} ./install" | 40 | text := "\t${RUN} cd ${WRKSRC}&&(${ECHO} ${PERL5:Q};${ECHO})|${BASH} ./install" | |
41 | words, rest := splitIntoShellTokens(dummyLine, text) | 41 | words, rest := splitIntoShellTokens(dummyLine, text) | |
42 | 42 | |||
43 | c.Check(words, deepEquals, []string{ | 43 | c.Check(words, deepEquals, []string{ | |
44 | "${RUN}", | 44 | "${RUN}", | |
45 | "cd", "${WRKSRC}", | 45 | "cd", "${WRKSRC}", | |
46 | "&&", "(", "${ECHO}", "${PERL5:Q}", ";", "${ECHO}", ")", | 46 | "&&", "(", "${ECHO}", "${PERL5:Q}", ";", "${ECHO}", ")", | |
47 | "|", "${BASH}", "./install"}) | 47 | "|", "${BASH}", "./install"}) | |
48 | c.Check(rest, equals, "") | 48 | c.Check(rest, equals, "") | |
49 | } | 49 | } | |
50 | 50 | |||
51 | func (s *Suite) Test_SplitIntoShellTokens_MkVarUse(c *check.C) { | 51 | func (s *Suite) Test_splitIntoShellTokens__varuse_with_embedded_space_and_other_vars(c *check.C) { | |
52 | varuseWord := "${GCONF_SCHEMAS:@.s.@${INSTALL_DATA} ${WRKSRC}/src/common/dbus/${.s.} ${DESTDIR}${GCONF_SCHEMAS_DIR}/@}" | 52 | varuseWord := "${GCONF_SCHEMAS:@.s.@${INSTALL_DATA} ${WRKSRC}/src/common/dbus/${.s.} ${DESTDIR}${GCONF_SCHEMAS_DIR}/@}" | |
53 | words, rest := splitIntoShellTokens(dummyLine, varuseWord) | 53 | words, rest := splitIntoShellTokens(dummyLine, varuseWord) | |
54 | 54 | |||
55 | c.Check(words, deepEquals, []string{varuseWord}) | 55 | c.Check(words, deepEquals, []string{varuseWord}) | |
56 | c.Check(rest, equals, "") | 56 | c.Check(rest, equals, "") | |
57 | } | 57 | } | |
58 | 58 | |||
59 | func (s *Suite) Test_SplitIntoMkWords_Semicolons(c *check.C) { | 59 | func (s *Suite) Test_splitIntoMkWords__semicolons(c *check.C) { | |
60 | words, rest := splitIntoMkWords(dummyLine, "word1 word2;;;") | 60 | words, rest := splitIntoMkWords(dummyLine, "word1 word2;;;") | |
61 | 61 | |||
62 | c.Check(words, deepEquals, []string{"word1", "word2;;;"}) | 62 | c.Check(words, deepEquals, []string{"word1", "word2;;;"}) | |
63 | c.Check(rest, equals, "") | 63 | c.Check(rest, equals, "") | |
64 | } | 64 | } | |
65 | 65 | |||
66 | func (s *Suite) Test_SplitIntoShellTokens_VaruseSpace(c *check.C) { | 66 | func (s *Suite) Test_splitIntoShellTokens__varuse_with_embedded_space(c *check.C) { | |
67 | words, rest := splitIntoShellTokens(dummyLine, "${VAR:S/ /_/g}") | 67 | words, rest := splitIntoShellTokens(dummyLine, "${VAR:S/ /_/g}") | |
68 | 68 | |||
69 | c.Check(words, deepEquals, []string{"${VAR:S/ /_/g}"}) | 69 | c.Check(words, deepEquals, []string{"${VAR:S/ /_/g}"}) | |
70 | c.Check(rest, equals, "") | 70 | c.Check(rest, equals, "") | |
71 | } | 71 | } | |
72 | 72 | |||
73 | func (s *Suite) Test_SplitIntoMkWords_VaruseSpace(c *check.C) { | 73 | func (s *Suite) Test_splitIntoMkWords__varuse_with_embedded_space(c *check.C) { | |
74 | words, rest := splitIntoMkWords(dummyLine, "${VAR:S/ /_/g}") | 74 | words, rest := splitIntoMkWords(dummyLine, "${VAR:S/ /_/g}") | |
75 | 75 | |||
76 | c.Check(words, deepEquals, []string{"${VAR:S/ /_/g}"}) | 76 | c.Check(words, deepEquals, []string{"${VAR:S/ /_/g}"}) | |
77 | c.Check(rest, equals, "") | 77 | c.Check(rest, equals, "") | |
78 | } | 78 | } | |
79 | 79 | |||
80 | func (s *Suite) Test_splitIntoShellTokens_Redirect(c *check.C) { | 80 | func (s *Suite) Test_splitIntoShellTokens__redirect(c *check.C) { | |
81 | words, rest := splitIntoShellTokens(dummyLine, "echo 1>output 2>>append 3>|clobber 4>&5 6<input >>append") | 81 | words, rest := splitIntoShellTokens(dummyLine, "echo 1>output 2>>append 3>|clobber 4>&5 6<input >>append") | |
82 | 82 | |||
83 | c.Check(words, deepEquals, []string{ | 83 | c.Check(words, deepEquals, []string{ | |
84 | "echo", | 84 | "echo", | |
85 | "1>", "output", | 85 | "1>", "output", | |
86 | "2>>", "append", | 86 | "2>>", "append", | |
87 | "3>|", "clobber", | 87 | "3>|", "clobber", | |
88 | "4>&", "5", | 88 | "4>&", "5", | |
89 | "6<", "input", | 89 | "6<", "input", | |
90 | ">>", "append"}) | 90 | ">>", "append"}) | |
91 | c.Check(rest, equals, "") | 91 | c.Check(rest, equals, "") | |
92 | 92 | |||
93 | words, rest = splitIntoShellTokens(dummyLine, "echo 1> output 2>> append 3>| clobber 4>& 5 6< input >> append") | 93 | words, rest = splitIntoShellTokens(dummyLine, "echo 1> output 2>> append 3>| clobber 4>& 5 6< input >> append") | |
94 | 94 | |||
95 | c.Check(words, deepEquals, []string{ | 95 | c.Check(words, deepEquals, []string{ | |
96 | "echo", | 96 | "echo", | |
97 | "1>", "output", | 97 | "1>", "output", | |
98 | "2>>", "append", | 98 | "2>>", "append", | |
99 | "3>|", "clobber", | 99 | "3>|", "clobber", | |
100 | "4>&", "5", | 100 | "4>&", "5", | |
101 | "6<", "input", | 101 | "6<", "input", | |
102 | ">>", "append"}) | 102 | ">>", "append"}) | |
103 | c.Check(rest, equals, "") | 103 | c.Check(rest, equals, "") | |
104 | } | 104 | } | |
105 | 105 | |||
106 | func (s *Suite) TestChecklineMkShellCommandLine(c *check.C) { | 106 | func (s *Suite) Test_ShellLine_CheckShellCommandLine(c *check.C) { | |
107 | s.UseCommandLine(c, "-Wall") | 107 | s.UseCommandLine(c, "-Wall") | |
108 | G.Mk = s.NewMkLines("fname", | 108 | G.Mk = s.NewMkLines("fname", | |
109 | "# dummy") | 109 | "# dummy") | |
110 | shline := NewShellLine(G.Mk.mklines[0]) | 110 | shline := NewShellLine(G.Mk.mklines[0]) | |
111 | 111 | |||
112 | shline.CheckShellCommandLine("@# Comment") | 112 | shline.CheckShellCommandLine("@# Comment") | |
113 | 113 | |||
114 | c.Check(s.Output(), equals, "") | 114 | c.Check(s.Output(), equals, "") | |
115 | 115 | |||
116 | shline.CheckShellCommandLine("uname=`uname`; echo $$uname; echo") | 116 | shline.CheckShellCommandLine("uname=`uname`; echo $$uname; echo") | |
117 | 117 | |||
118 | c.Check(s.Output(), equals, ""+ | 118 | c.Check(s.Output(), equals, ""+ | |
119 | "WARN: fname:1: Unknown shell command \"uname\".\n"+ | 119 | "WARN: fname:1: Unknown shell command \"uname\".\n"+ | |
@@ -219,98 +219,98 @@ func (s *Suite) TestChecklineMkShellComm | @@ -219,98 +219,98 @@ func (s *Suite) TestChecklineMkShellComm | |||
219 | 219 | |||
220 | shline.CheckShellCommandLine("${RUN} ${INSTALL_DATA_DIR} share/pkgbase ${PREFIX}/share/pkgbase") | 220 | shline.CheckShellCommandLine("${RUN} ${INSTALL_DATA_DIR} share/pkgbase ${PREFIX}/share/pkgbase") | |
221 | 221 | |||
222 | c.Check(s.Output(), equals, ""+ | 222 | c.Check(s.Output(), equals, ""+ | |
223 | "NOTE: fname:1: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= share/pkgbase\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | 223 | "NOTE: fname:1: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= share/pkgbase\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | |
224 | "WARN: fname:1: The INSTALL_*_DIR commands can only handle one directory at a time.\n") | 224 | "WARN: fname:1: The INSTALL_*_DIR commands can only handle one directory at a time.\n") | |
225 | 225 | |||
226 | // See PR 46570, item "1. It does not" | 226 | // See PR 46570, item "1. It does not" | |
227 | shline.CheckShellCommandLine("for x in 1 2 3; do echo \"$$x\" || exit 1; done") | 227 | shline.CheckShellCommandLine("for x in 1 2 3; do echo \"$$x\" || exit 1; done") | |
228 | 228 | |||
229 | c.Check(s.Output(), equals, "") // No warning about missing error checking. | 229 | c.Check(s.Output(), equals, "") // No warning about missing error checking. | |
230 | } | 230 | } | |
231 | 231 | |||
232 | func (s *Suite) TestShellLine_CheckShelltext_nofix(c *check.C) { | 232 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__nofix(c *check.C) { | |
233 | s.UseCommandLine(c, "-Wall") | 233 | s.UseCommandLine(c, "-Wall") | |
234 | G.globalData.InitVartypes() | 234 | G.globalData.InitVartypes() | |
235 | s.RegisterTool(&Tool{Name: "echo", Predefined: true}) | 235 | s.RegisterTool(&Tool{Name: "echo", Predefined: true}) | |
236 | G.Mk = s.NewMkLines("Makefile", | 236 | G.Mk = s.NewMkLines("Makefile", | |
237 | "\techo ${PKGNAME:Q}") | 237 | "\techo ${PKGNAME:Q}") | |
238 | shline := NewShellLine(G.Mk.mklines[0]) | 238 | shline := NewShellLine(G.Mk.mklines[0]) | |
239 | 239 | |||
240 | c.Check(shline.line.raw[0].textnl, equals, "\techo ${PKGNAME:Q}\n") | 240 | c.Check(shline.line.raw[0].textnl, equals, "\techo ${PKGNAME:Q}\n") | |
241 | c.Check(shline.line.raw[0].Lineno, equals, 1) | 241 | c.Check(shline.line.raw[0].Lineno, equals, 1) | |
242 | 242 | |||
243 | shline.CheckShellCommandLine("echo ${PKGNAME:Q}") | 243 | shline.CheckShellCommandLine("echo ${PKGNAME:Q}") | |
244 | 244 | |||
245 | c.Check(s.Output(), equals, ""+ | 245 | c.Check(s.Output(), equals, ""+ | |
246 | "NOTE: Makefile:1: The :Q operator isn't necessary for ${PKGNAME} here.\n") | 246 | "NOTE: Makefile:1: The :Q operator isn't necessary for ${PKGNAME} here.\n") | |
247 | } | 247 | } | |
248 | 248 | |||
249 | func (s *Suite) TestShellLine_CheckShelltext_showAutofix(c *check.C) { | 249 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__show_autofix(c *check.C) { | |
250 | s.UseCommandLine(c, "-Wall", "--show-autofix") | 250 | s.UseCommandLine(c, "-Wall", "--show-autofix") | |
251 | G.globalData.InitVartypes() | 251 | G.globalData.InitVartypes() | |
252 | s.RegisterTool(&Tool{Name: "echo", Predefined: true}) | 252 | s.RegisterTool(&Tool{Name: "echo", Predefined: true}) | |
253 | G.Mk = s.NewMkLines("Makefile", | 253 | G.Mk = s.NewMkLines("Makefile", | |
254 | "\techo ${PKGNAME:Q}") | 254 | "\techo ${PKGNAME:Q}") | |
255 | shline := NewShellLine(G.Mk.mklines[0]) | 255 | shline := NewShellLine(G.Mk.mklines[0]) | |
256 | 256 | |||
257 | shline.CheckShellCommandLine("echo ${PKGNAME:Q}") | 257 | shline.CheckShellCommandLine("echo ${PKGNAME:Q}") | |
258 | 258 | |||
259 | c.Check(s.Output(), equals, ""+ | 259 | c.Check(s.Output(), equals, ""+ | |
260 | "NOTE: Makefile:1: The :Q operator isn't necessary for ${PKGNAME} here.\n"+ | 260 | "NOTE: Makefile:1: The :Q operator isn't necessary for ${PKGNAME} here.\n"+ | |
261 | "AUTOFIX: Makefile:1: Replacing \"${PKGNAME:Q}\" with \"${PKGNAME}\".\n") | 261 | "AUTOFIX: Makefile:1: Replacing \"${PKGNAME:Q}\" with \"${PKGNAME}\".\n") | |
262 | } | 262 | } | |
263 | 263 | |||
264 | func (s *Suite) TestShellLine_CheckShelltext_autofix(c *check.C) { | 264 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__autofix(c *check.C) { | |
265 | s.UseCommandLine(c, "-Wall", "--autofix") | 265 | s.UseCommandLine(c, "-Wall", "--autofix") | |
266 | G.globalData.InitVartypes() | 266 | G.globalData.InitVartypes() | |
267 | s.RegisterTool(&Tool{Name: "echo", Predefined: true}) | 267 | s.RegisterTool(&Tool{Name: "echo", Predefined: true}) | |
268 | G.Mk = s.NewMkLines("Makefile", | 268 | G.Mk = s.NewMkLines("Makefile", | |
269 | "\techo ${PKGNAME:Q}") | 269 | "\techo ${PKGNAME:Q}") | |
270 | shline := NewShellLine(G.Mk.mklines[0]) | 270 | shline := NewShellLine(G.Mk.mklines[0]) | |
271 | 271 | |||
272 | shline.CheckShellCommandLine("echo ${PKGNAME:Q}") | 272 | shline.CheckShellCommandLine("echo ${PKGNAME:Q}") | |
273 | 273 | |||
274 | c.Check(s.Output(), equals, ""+ | 274 | c.Check(s.Output(), equals, ""+ | |
275 | "AUTOFIX: Makefile:1: Replacing \"${PKGNAME:Q}\" with \"${PKGNAME}\".\n") | 275 | "AUTOFIX: Makefile:1: Replacing \"${PKGNAME:Q}\" with \"${PKGNAME}\".\n") | |
276 | } | 276 | } | |
277 | 277 | |||
278 | func (s *Suite) TestShellLine_CheckShelltext_InternalError1(c *check.C) { | 278 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__implementation(c *check.C) { | |
279 | s.UseCommandLine(c, "-Wall") | 279 | s.UseCommandLine(c, "-Wall") | |
280 | G.globalData.InitVartypes() | 280 | G.globalData.InitVartypes() | |
281 | G.Mk = s.NewMkLines("fname", | 281 | G.Mk = s.NewMkLines("fname", | |
282 | "# dummy") | 282 | "# dummy") | |
283 | shline := NewShellLine(G.Mk.mklines[0]) | 283 | shline := NewShellLine(G.Mk.mklines[0]) | |
284 | 284 | |||
285 | // foobar="`echo \"foo bar\"`" | 285 | // foobar="`echo \"foo bar\"`" | |
286 | text := "foobar=\"`echo \\\"foo bar\\\"`\"" | 286 | text := "foobar=\"`echo \\\"foo bar\\\"`\"" | |
287 | 287 | |||
288 | tokens, rest := splitIntoShellTokens(dummyLine, text) | 288 | tokens, rest := splitIntoShellTokens(dummyLine, text) | |
289 | 289 | |||
290 | c.Check(tokens, deepEquals, []string{text}) | 290 | c.Check(tokens, deepEquals, []string{text}) | |
291 | c.Check(rest, equals, "") | 291 | c.Check(rest, equals, "") | |
292 | 292 | |||
293 | shline.CheckWord(text, false) | 293 | shline.CheckWord(text, false) | |
294 | 294 | |||
295 | c.Check(s.Output(), equals, "WARN: fname:1: Unknown shell command \"echo\".\n") | 295 | c.Check(s.Output(), equals, "WARN: fname:1: Unknown shell command \"echo\".\n") | |
296 | 296 | |||
297 | shline.CheckShellCommandLine(text) | 297 | shline.CheckShellCommandLine(text) | |
298 | 298 | |||
299 | c.Check(s.Output(), equals, ""+ // No parse errors | 299 | c.Check(s.Output(), equals, ""+ // No parse errors | |
300 | "WARN: fname:1: Unknown shell command \"echo\".\n") | 300 | "WARN: fname:1: Unknown shell command \"echo\".\n") | |
301 | } | 301 | } | |
302 | 302 | |||
303 | func (s *Suite) TestShellLine_CheckShelltext_DollarWithoutVariable(c *check.C) { | 303 | func (s *Suite) Test_ShellLine_CheckShelltext__dollar_without_variable(c *check.C) { | |
304 | G.globalData.InitVartypes() | 304 | G.globalData.InitVartypes() | |
305 | G.Mk = s.NewMkLines("fname", | 305 | G.Mk = s.NewMkLines("fname", | |
306 | "# dummy") | 306 | "# dummy") | |
307 | shline := NewShellLine(G.Mk.mklines[0]) | 307 | shline := NewShellLine(G.Mk.mklines[0]) | |
308 | s.RegisterTool(&Tool{Name: "pax", Varname: "PAX"}) | 308 | s.RegisterTool(&Tool{Name: "pax", Varname: "PAX"}) | |
309 | G.Mk.tools["pax"] = true | 309 | G.Mk.tools["pax"] = true | |
310 | 310 | |||
311 | shline.CheckShellCommandLine("pax -rwpp -s /.*~$$//g . ${DESTDIR}${PREFIX}") | 311 | shline.CheckShellCommandLine("pax -rwpp -s /.*~$$//g . ${DESTDIR}${PREFIX}") | |
312 | 312 | |||
313 | c.Check(s.Output(), equals, "") | 313 | c.Check(s.Output(), equals, "") | |
314 | } | 314 | } | |
315 | 315 | |||
316 | func (s *Suite) Test_ShellLine_CheckWord(c *check.C) { | 316 | func (s *Suite) Test_ShellLine_CheckWord(c *check.C) { | |
@@ -345,159 +345,159 @@ func (s *Suite) Test_ShellLine_CheckWord | @@ -345,159 +345,159 @@ func (s *Suite) Test_ShellLine_CheckWord | |||
345 | c.Check(s.Output(), equals, ""+ | 345 | c.Check(s.Output(), equals, ""+ | |
346 | "WARN: fname:1: DISTINFO_FILE may not be used in this file; it would be ok in Makefile, Makefile.*, *.mk.\n"+ | 346 | "WARN: fname:1: DISTINFO_FILE may not be used in this file; it would be ok in Makefile, Makefile.*, *.mk.\n"+ | |
347 | "NOTE: fname:1: The :Q operator isn't necessary for ${DISTINFO_FILE} here.\n") | 347 | "NOTE: fname:1: The :Q operator isn't necessary for ${DISTINFO_FILE} here.\n") | |
348 | 348 | |||
349 | shline.CheckWord("s,\\.,,", true) | 349 | shline.CheckWord("s,\\.,,", true) | |
350 | 350 | |||
351 | c.Check(s.Output(), equals, "") | 351 | c.Check(s.Output(), equals, "") | |
352 | 352 | |||
353 | shline.CheckWord("\"s,\\.,,\"", true) | 353 | shline.CheckWord("\"s,\\.,,\"", true) | |
354 | 354 | |||
355 | c.Check(s.Output(), equals, "") | 355 | c.Check(s.Output(), equals, "") | |
356 | } | 356 | } | |
357 | 357 | |||
358 | func (s *Suite) Test_ShellLine_CheckWord_DollarWithoutVariable(c *check.C) { | 358 | func (s *Suite) Test_ShellLine_CheckWord__dollar_without_variable(c *check.C) { | |
359 | shline := NewShellLine(NewMkLine(NewLine("fname", 1, "# dummy", nil))) | 359 | shline := NewShellLine(NewMkLine(NewLine("fname", 1, "# dummy", nil))) | |
360 | 360 | |||
361 | shline.CheckWord("/.*~$$//g", false) // Typical argument to pax(1). | 361 | shline.CheckWord("/.*~$$//g", false) // Typical argument to pax(1). | |
362 | 362 | |||
363 | c.Check(s.Output(), equals, "") | 363 | c.Check(s.Output(), equals, "") | |
364 | } | 364 | } | |
365 | 365 | |||
366 | func (s *Suite) TestShelltextContext_CheckCommandStart(c *check.C) { | 366 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__echo(c *check.C) { | |
367 | s.UseCommandLine(c, "-Wall") | 367 | s.UseCommandLine(c, "-Wall") | |
368 | s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", MustUseVarForm: true, Predefined: true}) | 368 | s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", MustUseVarForm: true, Predefined: true}) | |
369 | G.Mk = s.NewMkLines("fname", | 369 | G.Mk = s.NewMkLines("fname", | |
370 | "# dummy") | 370 | "# dummy") | |
371 | mkline := NewMkLine(NewLine("fname", 3, "# dummy", nil)) | 371 | mkline := NewMkLine(NewLine("fname", 3, "# dummy", nil)) | |
372 | 372 | |||
373 | mkline.checkText("echo \"hello, world\"") | 373 | mkline.checkText("echo \"hello, world\"") | |
374 | 374 | |||
375 | c.Check(s.Output(), equals, "") | 375 | c.Check(s.Output(), equals, "") | |
376 | 376 | |||
377 | NewShellLine(mkline).CheckShellCommandLine("echo \"hello, world\"") | 377 | NewShellLine(mkline).CheckShellCommandLine("echo \"hello, world\"") | |
378 | 378 | |||
379 | c.Check(s.Output(), equals, ""+ | 379 | c.Check(s.Output(), equals, ""+ | |
380 | "WARN: fname:3: Please use \"${ECHO}\" instead of \"echo\".\n") | 380 | "WARN: fname:3: Please use \"${ECHO}\" instead of \"echo\".\n") | |
381 | } | 381 | } | |
382 | 382 | |||
383 | func (s *Suite) TestShellLine_checklineMkShelltext(c *check.C) { | 383 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__shell_variables(c *check.C) { | |
384 | text := "\tfor f in *.pl; do ${SED} s,@PREFIX@,${PREFIX}, < $f > $f.tmp && ${MV} $f.tmp $f; done" | 384 | text := "\tfor f in *.pl; do ${SED} s,@PREFIX@,${PREFIX}, < $f > $f.tmp && ${MV} $f.tmp $f; done" | |
385 | 385 | |||
386 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 3, text, nil))) | 386 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 3, text, nil))) | |
387 | shline.CheckShellCommandLine(text) | 387 | shline.CheckShellCommandLine(text) | |
388 | 388 | |||
389 | c.Check(s.Output(), equals, ""+ | 389 | c.Check(s.Output(), equals, ""+ | |
390 | "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+ | 390 | "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+ | |
391 | "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+ | 391 | "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+ | |
392 | "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+ | 392 | "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+ | |
393 | "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+ | 393 | "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Makefile variable or $$f if you mean a shell variable.\n"+ | |
394 | "NOTE: Makefile:3: Please use the SUBST framework instead of ${SED} and ${MV}.\n") | 394 | "NOTE: Makefile:3: Please use the SUBST framework instead of ${SED} and ${MV}.\n") | |
395 | 395 | |||
396 | shline.CheckShellCommandLine("install -c manpage.1 ${PREFIX}/man/man1/manpage.1") | 396 | shline.CheckShellCommandLine("install -c manpage.1 ${PREFIX}/man/man1/manpage.1") | |
397 | 397 | |||
398 | c.Check(s.Output(), equals, "WARN: Makefile:3: Please use ${PKGMANDIR} instead of \"man\".\n") | 398 | c.Check(s.Output(), equals, "WARN: Makefile:3: Please use ${PKGMANDIR} instead of \"man\".\n") | |
399 | 399 | |||
400 | shline.CheckShellCommandLine("cp init-script ${PREFIX}/etc/rc.d/service") | 400 | shline.CheckShellCommandLine("cp init-script ${PREFIX}/etc/rc.d/service") | |
401 | 401 | |||
402 | c.Check(s.Output(), equals, "WARN: Makefile:3: Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.\n") | 402 | c.Check(s.Output(), equals, "WARN: Makefile:3: Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.\n") | |
403 | } | 403 | } | |
404 | 404 | |||
405 | func (s *Suite) TestShellLine_checkCommandUse(c *check.C) { | 405 | func (s *Suite) Test_ShellLine_checkCommandUse(c *check.C) { | |
406 | G.Mk = s.NewMkLines("fname", | 406 | G.Mk = s.NewMkLines("fname", | |
407 | "# dummy") | 407 | "# dummy") | |
408 | G.Mk.target = "do-install" | 408 | G.Mk.target = "do-install" | |
409 | 409 | |||
410 | shline := NewShellLine(NewMkLine(NewLine("fname", 1, "\tdummy", nil))) | 410 | shline := NewShellLine(NewMkLine(NewLine("fname", 1, "\tdummy", nil))) | |
411 | 411 | |||
412 | shline.checkCommandUse("sed") | 412 | shline.checkCommandUse("sed") | |
413 | 413 | |||
414 | c.Check(s.Output(), equals, "WARN: fname:1: The shell command \"sed\" should not be used in the install phase.\n") | 414 | c.Check(s.Output(), equals, "WARN: fname:1: The shell command \"sed\" should not be used in the install phase.\n") | |
415 | 415 | |||
416 | shline.checkCommandUse("cp") | 416 | shline.checkCommandUse("cp") | |
417 | 417 | |||
418 | c.Check(s.Output(), equals, "WARN: fname:1: ${CP} should not be used to install files.\n") | 418 | c.Check(s.Output(), equals, "WARN: fname:1: ${CP} should not be used to install files.\n") | |
419 | } | 419 | } | |
420 | 420 | |||
421 | func (s *Suite) TestSplitIntoMkWords(c *check.C) { | 421 | func (s *Suite) Test_splitIntoMkWords(c *check.C) { | |
422 | url := "http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file=" | 422 | url := "http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file=" | |
423 | 423 | |||
424 | words, rest := splitIntoShellTokens(dummyLine, url) // Doesn’t really make sense | 424 | words, rest := splitIntoShellTokens(dummyLine, url) // Doesn’t really make sense | |
425 | 425 | |||
426 | c.Check(words, check.DeepEquals, []string{"http://registry.gimp.org/file/fix-ca.c?action=download", "&", "id=9884", "&", "file="}) | 426 | c.Check(words, check.DeepEquals, []string{"http://registry.gimp.org/file/fix-ca.c?action=download", "&", "id=9884", "&", "file="}) | |
427 | c.Check(rest, equals, "") | 427 | c.Check(rest, equals, "") | |
428 | 428 | |||
429 | words, rest = splitIntoMkWords(dummyLine, url) | 429 | words, rest = splitIntoMkWords(dummyLine, url) | |
430 | 430 | |||
431 | c.Check(words, check.DeepEquals, []string{"http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file="}) | 431 | c.Check(words, check.DeepEquals, []string{"http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file="}) | |
432 | c.Check(rest, equals, "") | 432 | c.Check(rest, equals, "") | |
433 | 433 | |||
434 | words, rest = splitIntoMkWords(dummyLine, "a b \"c c c\" d;;d;; \"e\"''`` 'rest") | 434 | words, rest = splitIntoMkWords(dummyLine, "a b \"c c c\" d;;d;; \"e\"''`` 'rest") | |
435 | 435 | |||
436 | c.Check(words, check.DeepEquals, []string{"a", "b", "\"c c c\"", "d;;d;;", "\"e\"''``"}) | 436 | c.Check(words, check.DeepEquals, []string{"a", "b", "\"c c c\"", "d;;d;;", "\"e\"''``"}) | |
437 | c.Check(rest, equals, "'rest") | 437 | c.Check(rest, equals, "'rest") | |
438 | } | 438 | } | |
439 | 439 | |||
440 | func (s *Suite) TestShellLine_CheckShellCommandLine_SedMv(c *check.C) { | 440 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__sed_and_mv(c *check.C) { | |
441 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${SED} 's,#,// comment:,g' fname > fname.tmp; ${MV} fname.tmp fname", nil))) | 441 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${SED} 's,#,// comment:,g' fname > fname.tmp; ${MV} fname.tmp fname", nil))) | |
442 | 442 | |||
443 | shline.CheckShellCommandLine(shline.mkline.Shellcmd()) | 443 | shline.CheckShellCommandLine(shline.mkline.Shellcmd()) | |
444 | 444 | |||
445 | c.Check(s.Output(), equals, "NOTE: Makefile:85: Please use the SUBST framework instead of ${SED} and ${MV}.\n") | 445 | c.Check(s.Output(), equals, "NOTE: Makefile:85: Please use the SUBST framework instead of ${SED} and ${MV}.\n") | |
446 | } | 446 | } | |
447 | 447 | |||
448 | func (s *Suite) TestShellLine_CheckShellCommandLine_Subshell(c *check.C) { | 448 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__subshell(c *check.C) { | |
449 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} uname=$$(uname)", nil))) | 449 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} uname=$$(uname)", nil))) | |
450 | 450 | |||
451 | shline.CheckShellCommandLine(shline.mkline.Shellcmd()) | 451 | shline.CheckShellCommandLine(shline.mkline.Shellcmd()) | |
452 | 452 | |||
453 | c.Check(s.Output(), equals, "WARN: Makefile:85: Invoking subshells via $(...) is not portable enough.\n") | 453 | c.Check(s.Output(), equals, "WARN: Makefile:85: Invoking subshells via $(...) is not portable enough.\n") | |
454 | } | 454 | } | |
455 | 455 | |||
456 | func (s *Suite) TestShellLine_CheckShellCommandLine_InstallDirs(c *check.C) { | 456 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__install_dir(c *check.C) { | |
457 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${INSTALL_DATA_DIR} ${DESTDIR}${PREFIX}/dir1 ${DESTDIR}${PREFIX}/dir2", nil))) | 457 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${INSTALL_DATA_DIR} ${DESTDIR}${PREFIX}/dir1 ${DESTDIR}${PREFIX}/dir2", nil))) | |
458 | 458 | |||
459 | shline.CheckShellCommandLine(shline.mkline.Shellcmd()) | 459 | shline.CheckShellCommandLine(shline.mkline.Shellcmd()) | |
460 | 460 | |||
461 | c.Check(s.Output(), equals, ""+ | 461 | c.Check(s.Output(), equals, ""+ | |
462 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | 462 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | |
463 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | 463 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | |
464 | "WARN: Makefile:85: The INSTALL_*_DIR commands can only handle one directory at a time.\n") | 464 | "WARN: Makefile:85: The INSTALL_*_DIR commands can only handle one directory at a time.\n") | |
465 | 465 | |||
466 | shline.CheckShellCommandLine("${INSTALL_DATA_DIR} -d -m 0755 ${DESTDIR}${PREFIX}/share/examples/gdchart") | 466 | shline.CheckShellCommandLine("${INSTALL_DATA_DIR} -d -m 0755 ${DESTDIR}${PREFIX}/share/examples/gdchart") | |
467 | 467 | |||
468 | // No warning about multiple directories, since 0755 is an option, not an argument. | 468 | // No warning about multiple directories, since 0755 is an option, not an argument. | |
469 | c.Check(s.Output(), equals, ""+ | 469 | c.Check(s.Output(), equals, ""+ | |
470 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= share/examples/gdchart\" instead of \"${INSTALL_DATA_DIR}\".\n") | 470 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= share/examples/gdchart\" instead of \"${INSTALL_DATA_DIR}\".\n") | |
471 | 471 | |||
472 | shline.CheckShellCommandLine("${INSTALL_DATA_DIR} -d -m 0755 ${DESTDIR}${PREFIX}/dir1 ${PREFIX}/dir2") | 472 | shline.CheckShellCommandLine("${INSTALL_DATA_DIR} -d -m 0755 ${DESTDIR}${PREFIX}/dir1 ${PREFIX}/dir2") | |
473 | 473 | |||
474 | c.Check(s.Output(), equals, ""+ | 474 | c.Check(s.Output(), equals, ""+ | |
475 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | 475 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | |
476 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | 476 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL_DATA_DIR}\".\n"+ | |
477 | "WARN: Makefile:85: The INSTALL_*_DIR commands can only handle one directory at a time.\n") | 477 | "WARN: Makefile:85: The INSTALL_*_DIR commands can only handle one directory at a time.\n") | |
478 | } | 478 | } | |
479 | 479 | |||
480 | func (s *Suite) TestShellLine_CheckShellCommandLine_InstallD(c *check.C) { | 480 | func (s *Suite) Test_ShellLine_CheckShellCommandLine__install_option_d(c *check.C) { | |
481 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${INSTALL} -d ${DESTDIR}${PREFIX}/dir1 ${DESTDIR}${PREFIX}/dir2", nil))) | 481 | shline := NewShellLine(NewMkLine(NewLine("Makefile", 85, "\t${RUN} ${INSTALL} -d ${DESTDIR}${PREFIX}/dir1 ${DESTDIR}${PREFIX}/dir2", nil))) | |
482 | 482 | |||
483 | shline.CheckShellCommandLine(shline.mkline.Shellcmd()) | 483 | shline.CheckShellCommandLine(shline.mkline.Shellcmd()) | |
484 | 484 | |||
485 | c.Check(s.Output(), equals, ""+ | 485 | c.Check(s.Output(), equals, ""+ | |
486 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL} -d\".\n"+ | 486 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir1\" instead of \"${INSTALL} -d\".\n"+ | |
487 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL} -d\".\n") | 487 | "NOTE: Makefile:85: You can use AUTO_MKDIRS=yes or \"INSTALLATION_DIRS+= dir2\" instead of \"${INSTALL} -d\".\n") | |
488 | } | 488 | } | |
489 | 489 | |||
490 | func (s *Suite) TestShellLine_(c *check.C) { | 490 | func (s *Suite) Test_ShellLine__shell_comment_with_line_continuation(c *check.C) { | |
491 | tmpfile := s.CreateTmpFile(c, "Makefile", ""+ | 491 | tmpfile := s.CreateTmpFile(c, "Makefile", ""+ | |
492 | "# $"+"NetBSD$\n"+ | 492 | "# $"+"NetBSD$\n"+ | |
493 | "pre-install:\n"+ | 493 | "pre-install:\n"+ | |
494 | "\t"+"# comment\\\n"+ | 494 | "\t"+"# comment\\\n"+ | |
495 | "\t"+"echo \"hello\"\n") | 495 | "\t"+"echo \"hello\"\n") | |
496 | lines := LoadNonemptyLines(tmpfile, true) | 496 | lines := LoadNonemptyLines(tmpfile, true) | |
497 | 497 | |||
498 | NewMkLines(lines).Check() | 498 | NewMkLines(lines).Check() | |
499 | 499 | |||
500 | c.Check(s.Output(), equals, "WARN: ~/Makefile:3--4: A shell comment does not stop at the end of line.\n") | 500 | c.Check(s.Output(), equals, "WARN: ~/Makefile:3--4: A shell comment does not stop at the end of line.\n") | |
501 | } | 501 | } | |
502 | 502 | |||
503 | func (s *Suite) Test_ShQuote(c *check.C) { | 503 | func (s *Suite) Test_ShQuote(c *check.C) { | |
@@ -508,25 +508,25 @@ func (s *Suite) Test_ShQuote(c *check.C) | @@ -508,25 +508,25 @@ func (s *Suite) Test_ShQuote(c *check.C) | |||
508 | result += part + "[" + sq.q.String() + "]" | 508 | result += part + "[" + sq.q.String() + "]" | |
509 | } | 509 | } | |
510 | return | 510 | return | |
511 | } | 511 | } | |
512 | 512 | |||
513 | c.Check(traceQuoting("x\"x`x`x\"x'x\"x'"), equals, "[plain]\"[d]`[db]`[d]\"[plain]'[s]\"[s]'[plain]") | 513 | c.Check(traceQuoting("x\"x`x`x\"x'x\"x'"), equals, "[plain]\"[d]`[db]`[d]\"[plain]'[s]\"[s]'[plain]") | |
514 | c.Check(traceQuoting("x\"x`x'x'x`x\""), equals, "[plain]\"[d]`[db]'[dbs]'[db]`[d]\"[plain]") | 514 | c.Check(traceQuoting("x\"x`x'x'x`x\""), equals, "[plain]\"[d]`[db]'[dbs]'[db]`[d]\"[plain]") | |
515 | c.Check(traceQuoting("x\\\"x\\'x\\`x\\\\"), equals, "[plain]\\\"[plain]\\'[plain]\\`[plain]\\\\[plain]") | 515 | c.Check(traceQuoting("x\\\"x\\'x\\`x\\\\"), equals, "[plain]\\\"[plain]\\'[plain]\\`[plain]\\\\[plain]") | |
516 | c.Check(traceQuoting("x\"x\\\"x\\'x\\`x\\\\"), equals, "[plain]\"[d]\\\"[d]\\'[d]\\`[d]\\\\[d]") | 516 | c.Check(traceQuoting("x\"x\\\"x\\'x\\`x\\\\"), equals, "[plain]\"[d]\\\"[d]\\'[d]\\`[d]\\\\[d]") | |
517 | c.Check(traceQuoting("x'x\\\"x\\'x\\`x\\\\"), equals, "[plain]'[s]\\\"[s]\\'[plain]\\`[plain]\\\\[plain]") | 517 | c.Check(traceQuoting("x'x\\\"x\\'x\\`x\\\\"), equals, "[plain]'[s]\\\"[s]\\'[plain]\\`[plain]\\\\[plain]") | |
518 | c.Check(traceQuoting("x`x\\\"x\\'x\\`x\\\\"), equals, "[plain]`[b]\\\"[b]\\'[b]\\`[b]\\\\[b]") | 518 | c.Check(traceQuoting("x`x\\\"x\\'x\\`x\\\\"), equals, "[plain]`[b]\\\"[b]\\'[b]\\`[b]\\\\[b]") | |
519 | } | 519 | } | |
520 | 520 | |||
521 | func (s *Suite) Test_unescapeBackticks(c *check.C) { | 521 | func (s *Suite) Test_ShellLine_unescapeBackticks(c *check.C) { | |
522 | shline := NewShellLine(NewMkLine(dummyLine)) | 522 | shline := NewShellLine(NewMkLine(dummyLine)) | |
523 | // foobar="`echo \"foo bar\"`" | 523 | // foobar="`echo \"foo bar\"`" | |
524 | text := "foobar=\"`echo \\\"foo bar\\\"`\"" | 524 | text := "foobar=\"`echo \\\"foo bar\\\"`\"" | |
525 | repl := NewPrefixReplacer(text) | 525 | repl := NewPrefixReplacer(text) | |
526 | repl.AdvanceStr("foobar=\"`") | 526 | repl.AdvanceStr("foobar=\"`") | |
527 | 527 | |||
528 | backtCommand, newQuoting := shline.unescapeBackticks(text, repl, shqDquotBackt) | 528 | backtCommand, newQuoting := shline.unescapeBackticks(text, repl, shqDquotBackt) | |
529 | c.Check(backtCommand, equals, "echo \"foo bar\"") | 529 | c.Check(backtCommand, equals, "echo \"foo bar\"") | |
530 | c.Check(newQuoting, equals, shqDquot) | 530 | c.Check(newQuoting, equals, shqDquot) | |
531 | c.Check(repl.rest, equals, "\"") | 531 | c.Check(repl.rest, equals, "\"") | |
532 | } | 532 | } |
@@ -34,27 +34,40 @@ func (mkline *MkLine) Note2(format, arg1 | @@ -34,27 +34,40 @@ func (mkline *MkLine) Note2(format, arg1 | |||
34 | func NewMkLine(line *Line) (mkline *MkLine) { | 34 | func NewMkLine(line *Line) (mkline *MkLine) { | |
35 | mkline = &MkLine{Line: line} | 35 | mkline = &MkLine{Line: line} | |
36 | 36 | |||
37 | text := line.Text | 37 | text := line.Text | |
38 | 38 | |||
39 | if hasPrefix(text, " ") { | 39 | if hasPrefix(text, " ") { | |
40 | mkline.Warn0("Makefile lines should not start with space characters.") | 40 | mkline.Warn0("Makefile lines should not start with space characters.") | |
41 | Explain3( | 41 | Explain3( | |
42 | "If you want this line to contain a shell program, use a tab", | 42 | "If you want this line to contain a shell program, use a tab", | |
43 | "character for indentation. Otherwise please remove the leading", | 43 | "character for indentation. Otherwise please remove the leading", | |
44 | "white-space.") | 44 | "white-space.") | |
45 | } | 45 | } | |
46 | 46 | |||
47 | if m, varname, op, valueAlign, value, comment := MatchVarassign(text); m { | 47 | if m, varname, spaceAfterVarname, op, valueAlign, value, comment := MatchVarassign(text); m { | |
48 | if G.opts.WarnSpace && spaceAfterVarname != "" { | |||
49 | switch { | |||
50 | case hasSuffix(varname, "+") && op == "=": | |||
51 | break | |||
52 | case matches(varname, `^[a-z]`) && op == ":=": | |||
53 | break | |||
54 | default: | |||
55 | if !line.AutofixReplace(varname+spaceAfterVarname+op, varname+op) { | |||
56 | line.Warn1("Unnecessary space after variable name %q.", varname) | |||
57 | } | |||
58 | } | |||
59 | } | |||
60 | ||||
48 | value = strings.Replace(value, "\\#", "#", -1) | 61 | value = strings.Replace(value, "\\#", "#", -1) | |
49 | varparam := varnameParam(varname) | 62 | varparam := varnameParam(varname) | |
50 | 63 | |||
51 | mkline.xtype = 1 | 64 | mkline.xtype = 1 | |
52 | mkline.xs1 = varname | 65 | mkline.xs1 = varname | |
53 | mkline.xs2 = varnameCanon(varname) | 66 | mkline.xs2 = varnameCanon(varname) | |
54 | mkline.xs3 = varparam | 67 | mkline.xs3 = varparam | |
55 | mkline.xop = NewMkOperator(op) | 68 | mkline.xop = NewMkOperator(op) | |
56 | mkline.xvalign = valueAlign | 69 | mkline.xvalign = valueAlign | |
57 | mkline.xvalue = value | 70 | mkline.xvalue = value | |
58 | mkline.xcomment = comment | 71 | mkline.xcomment = comment | |
59 | mkline.Tokenize(value) | 72 | mkline.Tokenize(value) | |
60 | return | 73 | return | |
@@ -233,27 +246,27 @@ func (mkline *MkLine) checkCond(forVars | @@ -233,27 +246,27 @@ func (mkline *MkLine) checkCond(forVars | |||
233 | if expected := strings.Repeat(" ", indentation.Depth()); indent != expected { | 246 | if expected := strings.Repeat(" ", indentation.Depth()); indent != expected { | |
234 | if G.opts.WarnSpace && !mkline.Line.AutofixReplace("."+indent, "."+expected) { | 247 | if G.opts.WarnSpace && !mkline.Line.AutofixReplace("."+indent, "."+expected) { | |
235 | mkline.Line.Notef("This directive should be indented by %d spaces.", indentation.Depth()) | 248 | mkline.Line.Notef("This directive should be indented by %d spaces.", indentation.Depth()) | |
236 | } | 249 | } | |
237 | } | 250 | } | |
238 | 251 | |||
239 | if directive == "if" && matches(args, `^!defined\([\w]+_MK\)$`) { | 252 | if directive == "if" && matches(args, `^!defined\([\w]+_MK\)$`) { | |
240 | indentation.Push(indentation.Depth()) | 253 | indentation.Push(indentation.Depth()) | |
241 | 254 | |||
242 | } else if matches(directive, `^(?:if|ifdef|ifndef|for|elif|else)$`) { | 255 | } else if matches(directive, `^(?:if|ifdef|ifndef|for|elif|else)$`) { | |
243 | indentation.Push(indentation.Depth() + 2) | 256 | indentation.Push(indentation.Depth() + 2) | |
244 | } | 257 | } | |
245 | 258 | |||
246 | reDirectivesWithArgs := `^(?:if|ifdef|ifndef|elif|for|undef)$` | 259 | const reDirectivesWithArgs = `^(?:if|ifdef|ifndef|elif|for|undef)$` | |
247 | if matches(directive, reDirectivesWithArgs) && args == "" { | 260 | if matches(directive, reDirectivesWithArgs) && args == "" { | |
248 | mkline.Error1("\".%s\" requires arguments.", directive) | 261 | mkline.Error1("\".%s\" requires arguments.", directive) | |
249 | 262 | |||
250 | } else if !matches(directive, reDirectivesWithArgs) && args != "" { | 263 | } else if !matches(directive, reDirectivesWithArgs) && args != "" { | |
251 | mkline.Error1("\".%s\" does not take arguments.", directive) | 264 | mkline.Error1("\".%s\" does not take arguments.", directive) | |
252 | 265 | |||
253 | if directive == "else" { | 266 | if directive == "else" { | |
254 | mkline.Note0("If you meant \"else if\", use \".elif\".") | 267 | mkline.Note0("If you meant \"else if\", use \".elif\".") | |
255 | } | 268 | } | |
256 | 269 | |||
257 | } else if directive == "if" || directive == "elif" { | 270 | } else if directive == "if" || directive == "elif" { | |
258 | mkline.CheckCond() | 271 | mkline.CheckCond() | |
259 | 272 | |||
@@ -285,27 +298,27 @@ func (mkline *MkLine) checkCond(forVars | @@ -285,27 +298,27 @@ func (mkline *MkLine) checkCond(forVars | |||
285 | 298 | |||
286 | // Check if any of the value's types is not guessed. | 299 | // Check if any of the value's types is not guessed. | |
287 | guessed := true | 300 | guessed := true | |
288 | for _, value := range splitOnSpace(values) { | 301 | for _, value := range splitOnSpace(values) { | |
289 | if m, vname := match1(value, `^\$\{(.*)\}`); m { | 302 | if m, vname := match1(value, `^\$\{(.*)\}`); m { | |
290 | vartype := mkline.getVariableType(vname) | 303 | vartype := mkline.getVariableType(vname) | |
291 | if vartype != nil && !vartype.guessed { | 304 | if vartype != nil && !vartype.guessed { | |
292 | guessed = false | 305 | guessed = false | |
293 | } | 306 | } | |
294 | } | 307 | } | |
295 | } | 308 | } | |
296 | 309 | |||
297 | forLoopType := &Vartype{lkSpace, CheckvarUnchecked, []AclEntry{{"*", aclpAllRead}}, guessed} | 310 | forLoopType := &Vartype{lkSpace, CheckvarUnchecked, []AclEntry{{"*", aclpAllRead}}, guessed} | |
298 | forLoopContext := &VarUseContext{forLoopType, vucTimeParse, vucQuotFor, vucExtentWord} | 311 | forLoopContext := &VarUseContext{forLoopType, vucTimeParse, vucQuotFor, false} | |
299 | for _, forLoopVar := range mkline.extractUsedVariables(values) { | 312 | for _, forLoopVar := range mkline.extractUsedVariables(values) { | |
300 | mkline.CheckVaruse(&MkVarUse{forLoopVar, nil}, forLoopContext) | 313 | mkline.CheckVaruse(&MkVarUse{forLoopVar, nil}, forLoopContext) | |
301 | } | 314 | } | |
302 | } | 315 | } | |
303 | 316 | |||
304 | } else if directive == "undef" && args != "" { | 317 | } else if directive == "undef" && args != "" { | |
305 | for _, uvar := range splitOnSpace(args) { | 318 | for _, uvar := range splitOnSpace(args) { | |
306 | if forVars[uvar] { | 319 | if forVars[uvar] { | |
307 | mkline.Note0("Using \".undef\" after a \".for\" loop is unnecessary.") | 320 | mkline.Note0("Using \".undef\" after a \".for\" loop is unnecessary.") | |
308 | } | 321 | } | |
309 | } | 322 | } | |
310 | } | 323 | } | |
311 | } | 324 | } | |
@@ -630,27 +643,27 @@ func (mkline *MkLine) CheckVaruseShellwo | @@ -630,27 +643,27 @@ func (mkline *MkLine) CheckVaruseShellwo | |||
630 | needMstar := matches(varname, `^(?:.*_)?(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$`) && | 643 | needMstar := matches(varname, `^(?:.*_)?(?:CFLAGS||CPPFLAGS|CXXFLAGS|FFLAGS|LDFLAGS|LIBS)$`) && | |
631 | (G.Pkg == nil || G.Pkg.vardef["GNU_CONFIGURE"] != nil) | 644 | (G.Pkg == nil || G.Pkg.vardef["GNU_CONFIGURE"] != nil) | |
632 | 645 | |||
633 | strippedMod := mod | 646 | strippedMod := mod | |
634 | if m, stripped := match1(mod, `(.*?)(?::M\*)?(?::Q)?$`); m { | 647 | if m, stripped := match1(mod, `(.*?)(?::M\*)?(?::Q)?$`); m { | |
635 | strippedMod = stripped | 648 | strippedMod = stripped | |
636 | } | 649 | } | |
637 | 650 | |||
638 | if mod == ":M*:Q" && !needMstar { | 651 | if mod == ":M*:Q" && !needMstar { | |
639 | mkline.Line.Note0("The :M* modifier is not needed here.") | 652 | mkline.Line.Note0("The :M* modifier is not needed here.") | |
640 | 653 | |||
641 | } else if needsQuoting == nqYes { | 654 | } else if needsQuoting == nqYes { | |
642 | correctMod := strippedMod + ifelseStr(needMstar, ":M*:Q", ":Q") | 655 | correctMod := strippedMod + ifelseStr(needMstar, ":M*:Q", ":Q") | |
643 | if correctMod == mod+":Q" && vuc.extent == vucExtentWordpart && !vartype.IsShell() { | 656 | if correctMod == mod+":Q" && vuc.IsWordPart && !vartype.IsShell() { | |
644 | mkline.Line.Warnf("The list variable %s should not be embedded in a word.", varname) | 657 | mkline.Line.Warnf("The list variable %s should not be embedded in a word.", varname) | |
645 | Explain( | 658 | Explain( | |
646 | "When a list variable has multiple elements, this expression expands", | 659 | "When a list variable has multiple elements, this expression expands", | |
647 | "to something unexpected:", | 660 | "to something unexpected:", | |
648 | "", | 661 | "", | |
649 | "Example: ${MASTER_SITE_SOURCEFORGE}directory/ expands to", | 662 | "Example: ${MASTER_SITE_SOURCEFORGE}directory/ expands to", | |
650 | "", | 663 | "", | |
651 | "\thttps://mirror1.sf.net/ https://mirror2.sf.net/directory/", | 664 | "\thttps://mirror1.sf.net/ https://mirror2.sf.net/directory/", | |
652 | "", | 665 | "", | |
653 | "The first URL is missing the directory. To fix this, write", | 666 | "The first URL is missing the directory. To fix this, write", | |
654 | "\t${MASTER_SITE_SOURCEFORGE:=directory/}.", | 667 | "\t${MASTER_SITE_SOURCEFORGE:=directory/}.", | |
655 | "", | 668 | "", | |
656 | "Example: -l${LIBS} expands to", | 669 | "Example: -l${LIBS} expands to", | |
@@ -838,63 +851,53 @@ func (mkline *MkLine) checkVarassignVaru | @@ -838,63 +851,53 @@ func (mkline *MkLine) checkVarassignVaru | |||
838 | mkline.checkVarassignVaruseMk(vartype, time) | 851 | mkline.checkVarassignVaruseMk(vartype, time) | |
839 | } | 852 | } | |
840 | } | 853 | } | |
841 | 854 | |||
842 | func (mkline *MkLine) checkVarassignVaruseMk(vartype *Vartype, time vucTime) { | 855 | func (mkline *MkLine) checkVarassignVaruseMk(vartype *Vartype, time vucTime) { | |
843 | if G.opts.Debug { | 856 | if G.opts.Debug { | |
844 | defer tracecall(vartype, time)() | 857 | defer tracecall(vartype, time)() | |
845 | } | 858 | } | |
846 | tokens := NewMkParser(mkline.Line, mkline.Value(), false).MkTokens() | 859 | tokens := NewMkParser(mkline.Line, mkline.Value(), false).MkTokens() | |
847 | for i, token := range tokens { | 860 | for i, token := range tokens { | |
848 | if token.Varuse != nil { | 861 | if token.Varuse != nil { | |
849 | spaceLeft := i-1 < 0 || matches(tokens[i-1].Text, `\s$`) | 862 | spaceLeft := i-1 < 0 || matches(tokens[i-1].Text, `\s$`) | |
850 | spaceRight := i+1 >= len(tokens) || matches(tokens[i+1].Text, `^\s`) | 863 | spaceRight := i+1 >= len(tokens) || matches(tokens[i+1].Text, `^\s`) | |
851 | extent := vucExtentWordpart | 864 | isWordPart := !(spaceLeft && spaceRight) | |
852 | if spaceLeft && spaceRight { | 865 | vuc := &VarUseContext{vartype, time, vucQuotPlain, isWordPart} | |
853 | extent = vucExtentWord | |||
854 | } | |||
855 | ||||
856 | vuc := &VarUseContext{vartype, time, vucQuotPlain, extent} | |||
857 | mkline.CheckVaruse(token.Varuse, vuc) | 866 | mkline.CheckVaruse(token.Varuse, vuc) | |
858 | } | 867 | } | |
859 | } | 868 | } | |
860 | } | 869 | } | |
861 | 870 | |||
862 | func (mkline *MkLine) checkVarassignVaruseShell(vartype *Vartype, time vucTime) { | 871 | func (mkline *MkLine) checkVarassignVaruseShell(vartype *Vartype, time vucTime) { | |
863 | if G.opts.Debug { | 872 | if G.opts.Debug { | |
864 | defer tracecall(vartype, time)() | 873 | defer tracecall(vartype, time)() | |
865 | } | 874 | } | |
866 | 875 | |||
867 | extent := func(tokens []*ShAtom, i int) vucExtent { | 876 | isWordPart := func(tokens []*ShAtom, i int) bool { | |
868 | if i-1 >= 0 { | 877 | if i-1 >= 0 && tokens[i-1].Type.IsWord() { | |
869 | typ := tokens[i-1].Type | 878 | return true | |
870 | if typ != shtSpace && typ != shtSemicolon && typ != shtParenOpen && typ != shtParenClose { | |||
871 | return vucExtentWordpart | |||
872 | } | |||
873 | } | 879 | } | |
874 | if i+1 < len(tokens) { | 880 | if i+1 < len(tokens) && tokens[i+1].Type.IsWord() { | |
875 | typ := tokens[i+1].Type | 881 | return true | |
876 | if typ != shtSpace && typ != shtSemicolon && typ != shtParenOpen && typ != shtParenClose { | |||
877 | return vucExtentWordpart | |||
878 | } | |||
879 | } | 882 | } | |
880 | return vucExtentWord | 883 | return false | |
881 | } | 884 | } | |
882 | 885 | |||
883 | atoms := NewShTokenizer(mkline.Line, mkline.Value(), false).ShAtoms() | 886 | atoms := NewShTokenizer(mkline.Line, mkline.Value(), false).ShAtoms() | |
884 | for i, atom := range atoms { | 887 | for i, atom := range atoms { | |
885 | if atom.Type == shtVaruse { | 888 | if atom.Type == shtVaruse { | |
886 | extent := extent(atoms, i) | 889 | isWordPart := isWordPart(atoms, i) | |
887 | vuc := &VarUseContext{vartype, time, atom.Quoting.ToVarUseContext(), extent} | 890 | vuc := &VarUseContext{vartype, time, atom.Quoting.ToVarUseContext(), isWordPart} | |
888 | mkline.CheckVaruse(atom.Data.(*MkVarUse), vuc) | 891 | mkline.CheckVaruse(atom.Data.(*MkVarUse), vuc) | |
889 | } | 892 | } | |
890 | } | 893 | } | |
891 | } | 894 | } | |
892 | 895 | |||
893 | func (mkline *MkLine) checkVarassignSpecific() { | 896 | func (mkline *MkLine) checkVarassignSpecific() { | |
894 | varname := mkline.Varname() | 897 | varname := mkline.Varname() | |
895 | value := mkline.Value() | 898 | value := mkline.Value() | |
896 | 899 | |||
897 | if contains(value, "/etc/rc.d") { | 900 | if contains(value, "/etc/rc.d") { | |
898 | mkline.Warn0("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.") | 901 | mkline.Warn0("Please use the RCD_SCRIPTS mechanism to install rc.d scripts automatically to ${RCD_SCRIPTS_EXAMPLEDIR}.") | |
899 | } | 902 | } | |
900 | 903 | |||
@@ -1018,66 +1021,62 @@ func (mkline *MkLine) CheckVartype(varna | @@ -1018,66 +1021,62 @@ func (mkline *MkLine) CheckVartype(varna | |||
1018 | 1021 | |||
1019 | switch { | 1022 | switch { | |
1020 | case vartype == nil: | 1023 | case vartype == nil: | |
1021 | if G.opts.Debug { | 1024 | if G.opts.Debug { | |
1022 | traceStep1("Unchecked variable assignment for %s.", varname) | 1025 | traceStep1("Unchecked variable assignment for %s.", varname) | |
1023 | } | 1026 | } | |
1024 | 1027 | |||
1025 | case op == opAssignShell: | 1028 | case op == opAssignShell: | |
1026 | if G.opts.Debug { | 1029 | if G.opts.Debug { | |
1027 | traceStep1("Unchecked use of !=: %q", value) | 1030 | traceStep1("Unchecked use of !=: %q", value) | |
1028 | } | 1031 | } | |
1029 | 1032 | |||
1030 | case vartype.kindOfList == lkNone: | 1033 | case vartype.kindOfList == lkNone: | |
1031 | mkline.CheckVartypePrimitive(varname, vartype.checker, op, value, comment, vartype.IsConsideredList(), vartype.guessed) | 1034 | mkline.CheckVartypePrimitive(varname, vartype.checker, op, value, comment, vartype.guessed) | |
1032 | 1035 | |||
1033 | case value == "": | 1036 | case value == "": | |
1034 | break | 1037 | break | |
1035 | 1038 | |||
1036 | case vartype.kindOfList == lkSpace: | 1039 | case vartype.kindOfList == lkSpace: | |
1037 | for _, word := range splitOnSpace(value) { | 1040 | for _, word := range splitOnSpace(value) { | |
1038 | mkline.CheckVartypePrimitive(varname, vartype.checker, op, word, comment, true, vartype.guessed) | 1041 | mkline.CheckVartypePrimitive(varname, vartype.checker, op, word, comment, vartype.guessed) | |
1039 | } | 1042 | } | |
1040 | 1043 | |||
1041 | case vartype.kindOfList == lkShell: | 1044 | case vartype.kindOfList == lkShell: | |
1042 | words, _ := splitIntoMkWords(mkline.Line, value) | 1045 | words, _ := splitIntoMkWords(mkline.Line, value) | |
1043 | for _, word := range words { | 1046 | for _, word := range words { | |
1044 | mkline.CheckVartypePrimitive(varname, vartype.checker, op, word, comment, true, vartype.guessed) | 1047 | mkline.CheckVartypePrimitive(varname, vartype.checker, op, word, comment, vartype.guessed) | |
1045 | } | 1048 | } | |
1046 | } | 1049 | } | |
1047 | } | 1050 | } | |
1048 | 1051 | |||
1049 | // For some variables (like `BuildlinkDepth`), `op` influences the valid values. | 1052 | // For some variables (like `BuildlinkDepth`), `op` influences the valid values. | |
1050 | // The `comment` parameter comes from a variable assignment, when a part of the line is commented out. | 1053 | // The `comment` parameter comes from a variable assignment, when a part of the line is commented out. | |
1051 | func (mkline *MkLine) CheckVartypePrimitive(varname string, checker *VarChecker, op MkOperator, value, comment string, isList bool, guessed bool) { | 1054 | func (mkline *MkLine) CheckVartypePrimitive(varname string, checker *VarChecker, op MkOperator, value, comment string, guessed bool) { | |
1052 | if G.opts.Debug { | 1055 | if G.opts.Debug { | |
1053 | defer tracecall(varname, checker.name, op, value, comment, isList, guessed)() | 1056 | defer tracecall(varname, checker.name, op, value, comment, guessed)() | |
1054 | } | 1057 | } | |
1055 | 1058 | |||
1056 | valueNoVar := mkline.withoutMakeVariables(value, isList) | 1059 | valueNoVar := mkline.withoutMakeVariables(value) | |
1057 | ctx := &VartypeCheck{mkline, mkline.Line, varname, op, value, valueNoVar, comment, isList, guessed} | 1060 | ctx := &VartypeCheck{mkline, mkline.Line, varname, op, value, valueNoVar, comment, guessed} | |
1058 | checker.checker(ctx) | 1061 | checker.checker(ctx) | |
1059 | } | 1062 | } | |
1060 | 1063 | |||
1061 | func (mkline *MkLine) withoutMakeVariables(value string, qModifierAllowed bool) string { | 1064 | func (mkline *MkLine) withoutMakeVariables(value string) string { | |
1062 | valueNovar := value | 1065 | valueNovar := value | |
1063 | for { | 1066 | for { | |
1064 | var m []string | 1067 | var m []string | |
1065 | if m, valueNovar = replaceFirst(valueNovar, `\$\{([^{}]*)\}`, ""); m != nil { | 1068 | m, valueNovar = replaceFirst(valueNovar, `\$\{[^{}]*\}`, "") | |
1066 | varuse := m[1] | 1069 | if m == nil { | |
1067 | if !qModifierAllowed && hasSuffix(varuse, ":Q") { | |||
1068 | mkline.Warn0("The :Q operator should only be used in lists and shell commands.") | |||
1069 | } | |||
1070 | } else { | |||
1071 | return valueNovar | 1070 | return valueNovar | |
1072 | } | 1071 | } | |
1073 | } | 1072 | } | |
1074 | } | 1073 | } | |
1075 | 1074 | |||
1076 | func (mkline *MkLine) checkText(text string) { | 1075 | func (mkline *MkLine) checkText(text string) { | |
1077 | if G.opts.Debug { | 1076 | if G.opts.Debug { | |
1078 | defer tracecall1(text)() | 1077 | defer tracecall1(text)() | |
1079 | } | 1078 | } | |
1080 | 1079 | |||
1081 | if contains(text, "${WRKSRC}/..") { | 1080 | if contains(text, "${WRKSRC}/..") { | |
1082 | mkline.Warn0("Building the package should take place entirely inside ${WRKSRC}, not \"${WRKSRC}/..\".") | 1081 | mkline.Warn0("Building the package should take place entirely inside ${WRKSRC}, not \"${WRKSRC}/..\".") | |
1083 | Explain( | 1082 | Explain( | |
@@ -1188,27 +1187,27 @@ func (mkline *MkLine) rememberUsedVariab | @@ -1188,27 +1187,27 @@ func (mkline *MkLine) rememberUsedVariab | |||
1188 | } | 1187 | } | |
1189 | arg2varuse := func(node *Tree) { | 1188 | arg2varuse := func(node *Tree) { | |
1190 | varuse := node.args[2].(MkVarUse) | 1189 | varuse := node.args[2].(MkVarUse) | |
1191 | indentation.AddVar(varuse.varname) | 1190 | indentation.AddVar(varuse.varname) | |
1192 | } | 1191 | } | |
1193 | cond.Visit("defined", arg0varname) | 1192 | cond.Visit("defined", arg0varname) | |
1194 | cond.Visit("empty", arg0varuse) | 1193 | cond.Visit("empty", arg0varuse) | |
1195 | cond.Visit("compareVarNum", arg0varuse) | 1194 | cond.Visit("compareVarNum", arg0varuse) | |
1196 | cond.Visit("compareVarStr", arg0varuse) | 1195 | cond.Visit("compareVarStr", arg0varuse) | |
1197 | cond.Visit("compareVarVar", arg0varuse) | 1196 | cond.Visit("compareVarVar", arg0varuse) | |
1198 | cond.Visit("compareVarVar", arg2varuse) | 1197 | cond.Visit("compareVarVar", arg2varuse) | |
1199 | } | 1198 | } | |
1200 | 1199 | |||
1201 | func (mkline *MkLine) CheckValidCharactersInValue(reValid string) { | 1200 | func (mkline *MkLine) CheckValidCharactersInValue(reValid RegexPattern) { | |
1202 | rest := regcomp(reValid).ReplaceAllString(mkline.Value(), "") | 1201 | rest := regcomp(reValid).ReplaceAllString(mkline.Value(), "") | |
1203 | if rest != "" { | 1202 | if rest != "" { | |
1204 | uni := "" | 1203 | uni := "" | |
1205 | for _, c := range rest { | 1204 | for _, c := range rest { | |
1206 | uni += fmt.Sprintf(" %U", c) | 1205 | uni += fmt.Sprintf(" %U", c) | |
1207 | } | 1206 | } | |
1208 | mkline.Warn2("%s contains invalid characters (%s).", mkline.Varname(), uni[1:]) | 1207 | mkline.Warn2("%s contains invalid characters (%s).", mkline.Varname(), uni[1:]) | |
1209 | } | 1208 | } | |
1210 | } | 1209 | } | |
1211 | 1210 | |||
1212 | func (mkline *MkLine) explainRelativeDirs() { | 1211 | func (mkline *MkLine) explainRelativeDirs() { | |
1213 | Explain3( | 1212 | Explain3( | |
1214 | "Directories in the form \"../../category/package\" make it easier to", | 1213 | "Directories in the form \"../../category/package\" make it easier to", | |
@@ -1325,111 +1324,111 @@ func (nq NeedsQuoting) String() string { | @@ -1325,111 +1324,111 @@ func (nq NeedsQuoting) String() string { | |||
1325 | func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc *VarUseContext) (needsQuoting NeedsQuoting) { | 1324 | func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc *VarUseContext) (needsQuoting NeedsQuoting) { | |
1326 | if G.opts.Debug { | 1325 | if G.opts.Debug { | |
1327 | defer tracecall(varname, vartype, vuc, "=>", &needsQuoting)() | 1326 | defer tracecall(varname, vartype, vuc, "=>", &needsQuoting)() | |
1328 | } | 1327 | } | |
1329 | 1328 | |||
1330 | if vartype == nil || vuc.vartype == nil { | 1329 | if vartype == nil || vuc.vartype == nil { | |
1331 | return nqDontKnow | 1330 | return nqDontKnow | |
1332 | } | 1331 | } | |
1333 | 1332 | |||
1334 | if vartype.checker.IsEnum() || vartype.IsBasicSafe() { | 1333 | if vartype.checker.IsEnum() || vartype.IsBasicSafe() { | |
1335 | if vartype.kindOfList == lkNone { | 1334 | if vartype.kindOfList == lkNone { | |
1336 | return nqDoesntMatter | 1335 | return nqDoesntMatter | |
1337 | } | 1336 | } | |
1338 | if vartype.kindOfList == lkShell && vuc.extent != vucExtentWordpart { | 1337 | if vartype.kindOfList == lkShell && !vuc.IsWordPart { | |
1339 | return nqNo | 1338 | return nqNo | |
1340 | } | 1339 | } | |
1341 | } | 1340 | } | |
1342 | 1341 | |||
1343 | // In .for loops, the :Q operator is always misplaced, since | 1342 | // In .for loops, the :Q operator is always misplaced, since | |
1344 | // the items are broken up at white-space, not as shell words | 1343 | // the items are broken up at white-space, not as shell words | |
1345 | // like in all other parts of make(1). | 1344 | // like in all other parts of make(1). | |
1346 | if vuc.quoting == vucQuotFor { | 1345 | if vuc.quoting == vucQuotFor { | |
1347 | return nqNo | 1346 | return nqNo | |
1348 | } | 1347 | } | |
1349 | 1348 | |||
1350 | // Determine whether the context expects a list of shell words or not. | 1349 | // Determine whether the context expects a list of shell words or not. | |
1351 | wantList := vuc.vartype.IsConsideredList() | 1350 | wantList := vuc.vartype.IsConsideredList() | |
1352 | haveList := vartype.IsConsideredList() | 1351 | haveList := vartype.IsConsideredList() | |
1353 | if G.opts.Debug { | 1352 | if G.opts.Debug { | |
1354 | traceStep("wantList=%v, haveList=%v", wantList, haveList) | 1353 | traceStep("wantList=%v, haveList=%v", wantList, haveList) | |
1355 | } | 1354 | } | |
1356 | 1355 | |||
1357 | // A shell word may appear as part of a shell word, for example COMPILER_RPATH_FLAG. | 1356 | // A shell word may appear as part of a shell word, for example COMPILER_RPATH_FLAG. | |
1358 | if vuc.extent == vucExtentWordpart && vuc.quoting == vucQuotPlain { | 1357 | if vuc.IsWordPart && vuc.quoting == vucQuotPlain { | |
1359 | if vartype.kindOfList == lkNone && vartype.checker == CheckvarShellWord { | 1358 | if vartype.kindOfList == lkNone && vartype.checker == CheckvarShellWord { | |
1360 | return nqNo | 1359 | return nqNo | |
1361 | } | 1360 | } | |
1362 | } | 1361 | } | |
1363 | 1362 | |||
1364 | // Both of these can be correct, depending on the situation: | 1363 | // Both of these can be correct, depending on the situation: | |
1365 | // 1. echo ${PERL5:Q} | 1364 | // 1. echo ${PERL5:Q} | |
1366 | // 2. xargs ${PERL5} | 1365 | // 2. xargs ${PERL5} | |
1367 | if vuc.extent == vucExtentWord && vuc.quoting == vucQuotPlain { | 1366 | if !vuc.IsWordPart && vuc.quoting == vucQuotPlain { | |
1368 | if wantList && haveList { | 1367 | if wantList && haveList { | |
1369 | return nqDontKnow | 1368 | return nqDontKnow | |
1370 | } | 1369 | } | |
1371 | } | 1370 | } | |
1372 | 1371 | |||
1373 | // Assuming the tool definitions don't include very special characters, | 1372 | // Assuming the tool definitions don't include very special characters, | |
1374 | // so they can safely be used inside any quotes. | 1373 | // so they can safely be used inside any quotes. | |
1375 | if G.globalData.Tools.byVarname[varname] != nil { | 1374 | if G.globalData.Tools.byVarname[varname] != nil { | |
1376 | switch vuc.quoting { | 1375 | switch vuc.quoting { | |
1377 | case vucQuotPlain: | 1376 | case vucQuotPlain: | |
1378 | if vuc.extent != vucExtentWordpart { | 1377 | if !vuc.IsWordPart { | |
1379 | return nqNo | 1378 | return nqNo | |
1380 | } | 1379 | } | |
1381 | case vucQuotBackt: | 1380 | case vucQuotBackt: | |
1382 | return nqNo | 1381 | return nqNo | |
1383 | case vucQuotDquot, vucQuotSquot: | 1382 | case vucQuotDquot, vucQuotSquot: | |
1384 | return nqDoesntMatter | 1383 | return nqDoesntMatter | |
1385 | } | 1384 | } | |
1386 | } | 1385 | } | |
1387 | 1386 | |||
1388 | // Variables that appear as parts of shell words generally need | 1387 | // Variables that appear as parts of shell words generally need | |
1389 | // to be quoted. An exception is in the case of backticks, | 1388 | // to be quoted. An exception is in the case of backticks, | |
1390 | // because the whole backticks expression is parsed as a single | 1389 | // because the whole backticks expression is parsed as a single | |
1391 | // shell word by pkglint. | 1390 | // shell word by pkglint. | |
1392 | if vuc.extent == vucExtentWordpart && vuc.vartype != nil && vuc.vartype.IsShell() && vuc.quoting != vucQuotBackt { | 1391 | if vuc.IsWordPart && vuc.vartype != nil && vuc.vartype.IsShell() && vuc.quoting != vucQuotBackt { | |
1393 | return nqYes | 1392 | return nqYes | |
1394 | } | 1393 | } | |
1395 | 1394 | |||
1396 | // SUBST_MESSAGE.perl= Replacing in ${REPLACE_PERL} | 1395 | // SUBST_MESSAGE.perl= Replacing in ${REPLACE_PERL} | |
1397 | if vuc.vartype != nil && vuc.vartype.IsPlainString() { | 1396 | if vuc.vartype != nil && vuc.vartype.IsPlainString() { | |
1398 | return nqNo | 1397 | return nqNo | |
1399 | } | 1398 | } | |
1400 | 1399 | |||
1401 | // Assigning lists to lists does not require any quoting, though | 1400 | // Assigning lists to lists does not require any quoting, though | |
1402 | // there may be cases like "CONFIGURE_ARGS+= -libs ${LDFLAGS:Q}" | 1401 | // there may be cases like "CONFIGURE_ARGS+= -libs ${LDFLAGS:Q}" | |
1403 | // where quoting is necessary. | 1402 | // where quoting is necessary. | |
1404 | if wantList && haveList && vuc.extent != vucExtentWordpart { | 1403 | if wantList && haveList && !vuc.IsWordPart { | |
1405 | return nqDoesntMatter | 1404 | return nqDoesntMatter | |
1406 | } | 1405 | } | |
1407 | 1406 | |||
1408 | if wantList != haveList { | 1407 | if wantList != haveList { | |
1409 | if vuc.vartype != nil && vartype != nil { | 1408 | if vuc.vartype != nil && vartype != nil { | |
1410 | if vuc.vartype.checker == CheckvarFetchURL && vartype.checker == CheckvarHomepage { | 1409 | if vuc.vartype.checker == CheckvarFetchURL && vartype.checker == CheckvarHomepage { | |
1411 | return nqNo | 1410 | return nqNo | |
1412 | } | 1411 | } | |
1413 | if vuc.vartype.checker == CheckvarHomepage && vartype.checker == CheckvarFetchURL { | 1412 | if vuc.vartype.checker == CheckvarHomepage && vartype.checker == CheckvarFetchURL { | |
1414 | return nqNo // Just for HOMEPAGE=${MASTER_SITE_*:=subdir/}. | 1413 | return nqNo // Just for HOMEPAGE=${MASTER_SITE_*:=subdir/}. | |
1415 | } | 1414 | } | |
1416 | } | 1415 | } | |
1417 | return nqYes | 1416 | return nqYes | |
1418 | } | 1417 | } | |
1419 | 1418 | |||
1420 | // Bad: LDADD += -l${LIBS} | 1419 | // Bad: LDADD += -l${LIBS} | |
1421 | // Good: LDADD += ${LIBS:@lib@-l${lib} @} | 1420 | // Good: LDADD += ${LIBS:@lib@-l${lib} @} | |
1422 | if wantList && haveList && vuc.extent == vucExtentWordpart { | 1421 | if wantList && haveList && vuc.IsWordPart { | |
1423 | return nqYes | 1422 | return nqYes | |
1424 | } | 1423 | } | |
1425 | 1424 | |||
1426 | if G.opts.Debug { | 1425 | if G.opts.Debug { | |
1427 | traceStep1("Don't know whether :Q is needed for %q", varname) | 1426 | traceStep1("Don't know whether :Q is needed for %q", varname) | |
1428 | } | 1427 | } | |
1429 | return nqDontKnow | 1428 | return nqDontKnow | |
1430 | } | 1429 | } | |
1431 | 1430 | |||
1432 | // Returns the type of the variable (maybe guessed based on the variable name), | 1431 | // Returns the type of the variable (maybe guessed based on the variable name), | |
1433 | // or nil if the type cannot even be guessed. | 1432 | // or nil if the type cannot even be guessed. | |
1434 | func (mkline *MkLine) getVariableType(varname string) *Vartype { | 1433 | func (mkline *MkLine) getVariableType(varname string) *Vartype { | |
1435 | if G.opts.Debug { | 1434 | if G.opts.Debug { | |
@@ -1576,30 +1575,30 @@ func (mkline *MkLine) determineUsedVaria | @@ -1576,30 +1575,30 @@ func (mkline *MkLine) determineUsedVaria | |||
1576 | // VarUseContext defines the context in which a variable is defined | 1575 | // VarUseContext defines the context in which a variable is defined | |
1577 | // or used. Whether that is allowed depends on: | 1576 | // or used. Whether that is allowed depends on: | |
1578 | // | 1577 | // | |
1579 | // * The variable’s data type, as defined in vardefs.go. | 1578 | // * The variable’s data type, as defined in vardefs.go. | |
1580 | // * When used on the right-hand side of an assigment, the variable can | 1579 | // * When used on the right-hand side of an assigment, the variable can | |
1581 | // represent a list of words, a single word or even only part of a | 1580 | // represent a list of words, a single word or even only part of a | |
1582 | // word. This distinction decides upon the correct use of the :Q | 1581 | // word. This distinction decides upon the correct use of the :Q | |
1583 | // operator. | 1582 | // operator. | |
1584 | // * When used in preprocessing statements like .if or .for, the other | 1583 | // * When used in preprocessing statements like .if or .for, the other | |
1585 | // operands of that statement should fit to the variable and are | 1584 | // operands of that statement should fit to the variable and are | |
1586 | // checked against the variable type. For example, comparing OPSYS to | 1585 | // checked against the variable type. For example, comparing OPSYS to | |
1587 | // x86_64 doesn’t make sense. | 1586 | // x86_64 doesn’t make sense. | |
1588 | type VarUseContext struct { | 1587 | type VarUseContext struct { | |
1589 | vartype *Vartype | 1588 | vartype *Vartype | |
1590 | time vucTime | 1589 | time vucTime | |
1591 | quoting vucQuoting | 1590 | quoting vucQuoting | |
1592 | extent vucExtent | 1591 | IsWordPart bool // Example: echo ${LOCALBASE} LOCALBASE=${LOCALBASE} | |
1593 | } | 1592 | } | |
1594 | 1593 | |||
1595 | type vucTime uint8 | 1594 | type vucTime uint8 | |
1596 | 1595 | |||
1597 | const ( | 1596 | const ( | |
1598 | vucTimeUnknown vucTime = iota | 1597 | vucTimeUnknown vucTime = iota | |
1599 | 1598 | |||
1600 | // When Makefiles are loaded, the operators := and != are evaluated, | 1599 | // When Makefiles are loaded, the operators := and != are evaluated, | |
1601 | // as well as the conditionals .if, .elif and .for. | 1600 | // as well as the conditionals .if, .elif and .for. | |
1602 | // During loading, not all variables are available yet. | 1601 | // During loading, not all variables are available yet. | |
1603 | // Variable values are still subject to change, especially lists. | 1602 | // Variable values are still subject to change, especially lists. | |
1604 | vucTimeParse | 1603 | vucTimeParse | |
1605 | 1604 | |||
@@ -1623,41 +1622,32 @@ const ( | @@ -1623,41 +1622,32 @@ const ( | |||
1623 | 1622 | |||
1624 | // The .for loop in Makefiles. This is the only place where | 1623 | // The .for loop in Makefiles. This is the only place where | |
1625 | // variables are split on whitespace. Everywhere else (:Q, :M) | 1624 | // variables are split on whitespace. Everywhere else (:Q, :M) | |
1626 | // they are split like in the shell. | 1625 | // they are split like in the shell. | |
1627 | // | 1626 | // | |
1628 | // Example: .for f in ${EXAMPLE_FILES} | 1627 | // Example: .for f in ${EXAMPLE_FILES} | |
1629 | vucQuotFor | 1628 | vucQuotFor | |
1630 | ) | 1629 | ) | |
1631 | 1630 | |||
1632 | func (q vucQuoting) String() string { | 1631 | func (q vucQuoting) String() string { | |
1633 | return [...]string{"unknown", "plain", "dquot", "squot", "backt", "mk-for"}[q] | 1632 | return [...]string{"unknown", "plain", "dquot", "squot", "backt", "mk-for"}[q] | |
1634 | } | 1633 | } | |
1635 | 1634 | |||
1636 | type vucExtent uint8 | |||
1637 | ||||
1638 | const ( | |||
1639 | vucExtentWord vucExtent = iota // Example: echo ${LOCALBASE} | |||
1640 | vucExtentWordpart // Example: echo LOCALBASE=${LOCALBASE} | |||
1641 | ) | |||
1642 | ||||
1643 | func (e vucExtent) String() string { return [...]string{"word", "wordpart"}[e] } | |||
1644 | ||||
1645 | func (vuc *VarUseContext) String() string { | 1635 | func (vuc *VarUseContext) String() string { | |
1646 | typename := "no-type" | 1636 | typename := "no-type" | |
1647 | if vuc.vartype != nil { | 1637 | if vuc.vartype != nil { | |
1648 | typename = vuc.vartype.String() | 1638 | typename = vuc.vartype.String() | |
1649 | } | 1639 | } | |
1650 | return fmt.Sprintf("(%s time:%s quoting:%s extent:%s)", typename, vuc.time, vuc.quoting, vuc.extent) | 1640 | return fmt.Sprintf("(%s time:%s quoting:%s wordpart:%v)", typename, vuc.time, vuc.quoting, vuc.IsWordPart) | |
1651 | } | 1641 | } | |
1652 | 1642 | |||
1653 | type Indentation struct { | 1643 | type Indentation struct { | |
1654 | depth []int // Number of space characters; always a multiple of 2 | 1644 | depth []int // Number of space characters; always a multiple of 2 | |
1655 | conditionVars []map[string]bool // Variables on which the current path depends | 1645 | conditionVars []map[string]bool // Variables on which the current path depends | |
1656 | } | 1646 | } | |
1657 | 1647 | |||
1658 | func (ind *Indentation) Len() int { | 1648 | func (ind *Indentation) Len() int { | |
1659 | return len(ind.depth) | 1649 | return len(ind.depth) | |
1660 | } | 1650 | } | |
1661 | 1651 | |||
1662 | func (ind *Indentation) Depth() int { | 1652 | func (ind *Indentation) Depth() int { | |
1663 | return ind.depth[len(ind.depth)-1] | 1653 | return ind.depth[len(ind.depth)-1] |
@@ -1,65 +1,65 @@ | @@ -1,65 +1,65 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestChecklineMkVartype_SimpleType(c *check.C) { | 7 | func (s *Suite) Test_MkLine_CheckVartype_simple_type(c *check.C) { | |
8 | s.UseCommandLine(c, "-Wtypes") | 8 | s.UseCommandLine(c, "-Wtypes") | |
9 | G.globalData.InitVartypes() | 9 | G.globalData.InitVartypes() | |
10 | mkline := NewMkLine(NewLine("fname", 1, "COMMENT=\tA nice package", nil)) | 10 | mkline := NewMkLine(NewLine("fname", 1, "COMMENT=\tA nice package", nil)) | |
11 | 11 | |||
12 | vartype1 := G.globalData.vartypes["COMMENT"] | 12 | vartype1 := G.globalData.vartypes["COMMENT"] | |
13 | c.Assert(vartype1, check.NotNil) | 13 | c.Assert(vartype1, check.NotNil) | |
14 | c.Check(vartype1.guessed, equals, false) | 14 | c.Check(vartype1.guessed, equals, false) | |
15 | 15 | |||
16 | vartype := mkline.getVariableType("COMMENT") | 16 | vartype := mkline.getVariableType("COMMENT") | |
17 | 17 | |||
18 | c.Assert(vartype, check.NotNil) | 18 | c.Assert(vartype, check.NotNil) | |
19 | c.Check(vartype.checker.name, equals, "Comment") | 19 | c.Check(vartype.checker.name, equals, "Comment") | |
20 | c.Check(vartype.guessed, equals, false) | 20 | c.Check(vartype.guessed, equals, false) | |
21 | c.Check(vartype.kindOfList, equals, lkNone) | 21 | c.Check(vartype.kindOfList, equals, lkNone) | |
22 | 22 | |||
23 | mkline.CheckVartype("COMMENT", opAssign, "A nice package", "") | 23 | mkline.CheckVartype("COMMENT", opAssign, "A nice package", "") | |
24 | 24 | |||
25 | c.Check(s.Stdout(), equals, "WARN: fname:1: COMMENT should not begin with \"A\".\n") | 25 | c.Check(s.Stdout(), equals, "WARN: fname:1: COMMENT should not begin with \"A\".\n") | |
26 | } | 26 | } | |
27 | 27 | |||
28 | func (s *Suite) TestChecklineMkVartype(c *check.C) { | 28 | func (s *Suite) Test_MkLine_CheckVartype(c *check.C) { | |
29 | G.globalData.InitVartypes() | 29 | G.globalData.InitVartypes() | |
30 | mkline := NewMkLine(NewLine("fname", 1, "DISTNAME=gcc-${GCC_VERSION}", nil)) | 30 | mkline := NewMkLine(NewLine("fname", 1, "DISTNAME=gcc-${GCC_VERSION}", nil)) | |
31 | 31 | |||
32 | mkline.CheckVartype("DISTNAME", opAssign, "gcc-${GCC_VERSION}", "") | 32 | mkline.CheckVartype("DISTNAME", opAssign, "gcc-${GCC_VERSION}", "") | |
33 | } | 33 | } | |
34 | 34 | |||
35 | func (s *Suite) TestMkLine_CheckVaralign_Autofix(c *check.C) { | 35 | func (s *Suite) Test_VaralignBlock_Check_autofix(c *check.C) { | |
36 | s.UseCommandLine(c, "-Wspace", "-f") | 36 | s.UseCommandLine(c, "-Wspace", "-f") | |
37 | lines := s.NewLines("file.mk", | 37 | lines := s.NewLines("file.mk", | |
38 | "VAR= value", // Indentation 7, fixed to 8. | 38 | "VAR= value", // Indentation 7, fixed to 8. | |
39 | "", // | 39 | "", // | |
40 | "VAR= value", // Indentation 8, fixed to 8. | 40 | "VAR= value", // Indentation 8, fixed to 8. | |
41 | "", // | 41 | "", // | |
42 | "VAR= value", // Indentation 9, fixed to 8. | 42 | "VAR= value", // Indentation 9, fixed to 8. | |
43 | "", // | 43 | "", // | |
44 | "VAR= \tvalue", // Mixed indentation 8, fixed to 8. | 44 | "VAR= \tvalue", // Mixed indentation 8, fixed to 8. | |
45 | "", // | 45 | "", // | |
46 | "VAR= \tvalue", // Mixed indentation 8, fixed to 8. | 46 | "VAR= \tvalue", // Mixed indentation 8, fixed to 8. | |
47 | "", // | 47 | "", // | |
48 | "VAR= \tvalue", // Mixed indentation 16, fixed to 8. | 48 | "VAR= \tvalue", // Mixed indentation 16, fixed to 8. | |
49 | "", // | 49 | "", // | |
50 | "VAR=\tvalue") // Already aligned with tabs only, left unchanged. | 50 | "VAR=\tvalue") // Already aligned with tabs only, left unchanged. | |
51 | 51 | |||
52 | varalign := new(VaralignBlock) | 52 | varalign := &VaralignBlock{} | |
53 | for _, line := range lines { | 53 | for _, line := range lines { | |
54 | varalign.Check(NewMkLine(line)) | 54 | varalign.Check(NewMkLine(line)) | |
55 | } | 55 | } | |
56 | varalign.Finish() | 56 | varalign.Finish() | |
57 | 57 | |||
58 | c.Check(lines[0].changed, equals, true) | 58 | c.Check(lines[0].changed, equals, true) | |
59 | c.Check(lines[0].raw[0].String(), equals, "1:VAR=\tvalue\n") | 59 | c.Check(lines[0].raw[0].String(), equals, "1:VAR=\tvalue\n") | |
60 | c.Check(lines[2].changed, equals, true) | 60 | c.Check(lines[2].changed, equals, true) | |
61 | c.Check(lines[2].raw[0].String(), equals, "3:VAR=\tvalue\n") | 61 | c.Check(lines[2].raw[0].String(), equals, "3:VAR=\tvalue\n") | |
62 | c.Check(lines[4].changed, equals, true) | 62 | c.Check(lines[4].changed, equals, true) | |
63 | c.Check(lines[4].raw[0].String(), equals, "5:VAR=\tvalue\n") | 63 | c.Check(lines[4].raw[0].String(), equals, "5:VAR=\tvalue\n") | |
64 | c.Check(lines[6].changed, equals, true) | 64 | c.Check(lines[6].changed, equals, true) | |
65 | c.Check(lines[6].raw[0].String(), equals, "7:VAR=\tvalue\n") | 65 | c.Check(lines[6].raw[0].String(), equals, "7:VAR=\tvalue\n") | |
@@ -74,92 +74,93 @@ func (s *Suite) TestMkLine_CheckVaralign | @@ -74,92 +74,93 @@ func (s *Suite) TestMkLine_CheckVaralign | |||
74 | "AUTOFIX: file.mk:1: Replacing \"VAR= \" with \"VAR=\\t\".\n"+ | 74 | "AUTOFIX: file.mk:1: Replacing \"VAR= \" with \"VAR=\\t\".\n"+ | |
75 | "NOTE: file.mk:3: Variable values should be aligned with tabs, not spaces.\n"+ | 75 | "NOTE: file.mk:3: Variable values should be aligned with tabs, not spaces.\n"+ | |
76 | "AUTOFIX: file.mk:3: Replacing \"VAR= \" with \"VAR=\\t\".\n"+ | 76 | "AUTOFIX: file.mk:3: Replacing \"VAR= \" with \"VAR=\\t\".\n"+ | |
77 | "NOTE: file.mk:5: This variable value should be aligned with tabs, not spaces, to column 9.\n"+ | 77 | "NOTE: file.mk:5: This variable value should be aligned with tabs, not spaces, to column 9.\n"+ | |
78 | "AUTOFIX: file.mk:5: Replacing \"VAR= \" with \"VAR=\\t\".\n"+ | 78 | "AUTOFIX: file.mk:5: Replacing \"VAR= \" with \"VAR=\\t\".\n"+ | |
79 | "NOTE: file.mk:7: Variable values should be aligned with tabs, not spaces.\n"+ | 79 | "NOTE: file.mk:7: Variable values should be aligned with tabs, not spaces.\n"+ | |
80 | "AUTOFIX: file.mk:7: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n"+ | 80 | "AUTOFIX: file.mk:7: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n"+ | |
81 | "NOTE: file.mk:9: Variable values should be aligned with tabs, not spaces.\n"+ | 81 | "NOTE: file.mk:9: Variable values should be aligned with tabs, not spaces.\n"+ | |
82 | "AUTOFIX: file.mk:9: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n"+ | 82 | "AUTOFIX: file.mk:9: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n"+ | |
83 | "NOTE: file.mk:11: This variable value should be aligned with tabs, not spaces, to column 9.\n"+ | 83 | "NOTE: file.mk:11: This variable value should be aligned with tabs, not spaces, to column 9.\n"+ | |
84 | "AUTOFIX: file.mk:11: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n") | 84 | "AUTOFIX: file.mk:11: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n") | |
85 | } | 85 | } | |
86 | 86 | |||
87 | func (s *Suite) TestMkLine_CheckVaralign_ReduceIndentation(c *check.C) { | 87 | func (s *Suite) Test_VaralignBlock_Check_reduce_indentation(c *check.C) { | |
88 | s.UseCommandLine(c, "-Wspace") | 88 | s.UseCommandLine(c, "-Wspace") | |
89 | mklines := s.NewMkLines("file.mk", | 89 | mklines := s.NewMkLines("file.mk", | |
90 | "VAR= \tvalue", | 90 | "VAR= \tvalue", | |
91 | "VAR= \tvalue", | 91 | "VAR= \tvalue", | |
92 | "VAR=\t\t\t\tvalue", | 92 | "VAR=\t\t\t\tvalue", | |
93 | "", | 93 | "", | |
94 | "VAR=\t\t\tneedlessly", // Nothing to be fixed here, since it looks good. | 94 | "VAR=\t\t\tneedlessly", // Nothing to be fixed here, since it looks good. | |
95 | "VAR=\t\t\tdeep", | 95 | "VAR=\t\t\tdeep", | |
96 | "VAR=\t\t\tindentation") | 96 | "VAR=\t\t\tindentation") | |
97 | 97 | |||
98 | varalign := new(VaralignBlock) | 98 | varalign := new(VaralignBlock) | |
99 | for _, mkline := range mklines.mklines { | 99 | for _, mkline := range mklines.mklines { | |
100 | varalign.Check(mkline) | 100 | varalign.Check(mkline) | |
101 | } | 101 | } | |
102 | varalign.Finish() | 102 | varalign.Finish() | |
103 | 103 | |||
104 | c.Check(s.Output(), equals, ""+ | 104 | c.Check(s.Output(), equals, ""+ | |
105 | "NOTE: file.mk:1: Variable values should be aligned with tabs, not spaces.\n"+ | 105 | "NOTE: file.mk:1: Variable values should be aligned with tabs, not spaces.\n"+ | |
106 | "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 9.\n"+ | 106 | "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 9.\n"+ | |
107 | "NOTE: file.mk:3: This variable value should be aligned to column 9.\n") | 107 | "NOTE: file.mk:3: This variable value should be aligned to column 9.\n") | |
108 | } | 108 | } | |
109 | 109 | |||
110 | func (s *Suite) TestMkLine_CheckVaralign_LongestLineEmptyAlignment(c *check.C) { | 110 | func (s *Suite) Test_VaralignBlock_Check_longest_line_no_space(c *check.C) { | |
111 | s.UseCommandLine(c, "-Wspace") | 111 | s.UseCommandLine(c, "-Wspace") | |
112 | mklines := s.NewMkLines("file.mk", | 112 | mklines := s.NewMkLines("file.mk", | |
113 | "SUBST_CLASSES+= aaaaaaaa", | 113 | "SUBST_CLASSES+= aaaaaaaa", | |
114 | "SUBST_STAGE.aaaaaaaa= pre-configure", | 114 | "SUBST_STAGE.aaaaaaaa= pre-configure", | |
115 | "SUBST_FILES.aaaaaaaa= *.pl", | 115 | "SUBST_FILES.aaaaaaaa= *.pl", | |
116 | "SUBST_FILTER_CMD.aaaaaaaa=cat") | 116 | "SUBST_FILTER_CMD.aaaaaaaa=cat") | |
117 | 117 | |||
118 | varalign := new(VaralignBlock) | 118 | varalign := new(VaralignBlock) | |
119 | for _, mkline := range mklines.mklines { | 119 | for _, mkline := range mklines.mklines { | |
120 | varalign.Check(mkline) | 120 | varalign.Check(mkline) | |
121 | } | 121 | } | |
122 | varalign.Finish() | 122 | varalign.Finish() | |
123 | 123 | |||
124 | c.Check(s.Output(), equals, ""+ | 124 | c.Check(s.Output(), equals, ""+ | |
125 | "NOTE: file.mk:1: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | 125 | "NOTE: file.mk:1: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | |
126 | "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | 126 | "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | |
127 | "NOTE: file.mk:3: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | 127 | "NOTE: file.mk:3: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | |
128 | "NOTE: file.mk:4: This variable value should be aligned to column 33.\n") | 128 | "NOTE: file.mk:4: This variable value should be aligned to column 33.\n") | |
129 | } | 129 | } | |
130 | 130 | |||
131 | func (s *Suite) TestMkLine_CheckVaralign_OnlySpaces(c *check.C) { | 131 | func (s *Suite) Test_VaralignBlock_Check_only_spaces(c *check.C) { | |
132 | s.UseCommandLine(c, "-Wspace") | 132 | s.UseCommandLine(c, "-Wspace") | |
133 | mklines := s.NewMkLines("file.mk", | 133 | mklines := s.NewMkLines("file.mk", | |
134 | "SUBST_CLASSES+= aaaaaaaa", | 134 | "SUBST_CLASSES+= aaaaaaaa", | |
135 | "SUBST_STAGE.aaaaaaaa= pre-configure", | 135 | "SUBST_STAGE.aaaaaaaa= pre-configure", | |
136 | "SUBST_FILES.aaaaaaaa= *.pl", | 136 | "SUBST_FILES.aaaaaaaa= *.pl", | |
137 | "SUBST_FILTER_CMD.aaaaaaaa= cat") | 137 | "SUBST_FILTER_CMD.aaaaaaaa= cat") | |
138 | 138 | |||
139 | varalign := new(VaralignBlock) | 139 | varalign := new(VaralignBlock) | |
140 | for _, mkline := range mklines.mklines { | 140 | for _, mkline := range mklines.mklines { | |
141 | varalign.Check(mkline) | 141 | varalign.Check(mkline) | |
142 | } | 142 | } | |
143 | varalign.Finish() | 143 | varalign.Finish() | |
144 | 144 | |||
145 | c.Check(s.Output(), equals, ""+ | 145 | c.Check(s.Output(), equals, ""+ | |
146 | "NOTE: file.mk:1: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | 146 | "NOTE: file.mk:1: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | |
147 | "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | 147 | "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | |
148 | "NOTE: file.mk:3: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | 148 | "NOTE: file.mk:3: This variable value should be aligned with tabs, not spaces, to column 33.\n"+ | |
149 | "NOTE: file.mk:4: This variable value should be aligned with tabs, not spaces, to column 33.\n") | 149 | "NOTE: file.mk:4: This variable value should be aligned with tabs, not spaces, to column 33.\n") | |
150 | } | 150 | } | |
151 | 151 | |||
152 | func (s *Suite) TestMkLine_fields(c *check.C) { | 152 | func (s *Suite) Test_NewMkLine(c *check.C) { | |
153 | s.UseCommandLine(c, "-Wspace") | |||
153 | mklines := NewMkLines(s.NewLines("test.mk", | 154 | mklines := NewMkLines(s.NewLines("test.mk", | |
154 | "VARNAME.param?=value # varassign comment", | 155 | "VARNAME.param?=value # varassign comment", | |
155 | "\tshell command # shell comment", | 156 | "\tshell command # shell comment", | |
156 | "# whole line comment", | 157 | "# whole line comment", | |
157 | "", | 158 | "", | |
158 | ". if !empty(PKGNAME:M*-*) # cond comment", | 159 | ". if !empty(PKGNAME:M*-*) # cond comment", | |
159 | ".include \"../../mk/bsd.prefs.mk\" # include comment", | 160 | ".include \"../../mk/bsd.prefs.mk\" # include comment", | |
160 | ".include <subdir.mk> # sysinclude comment", | 161 | ".include <subdir.mk> # sysinclude comment", | |
161 | "target1 target2: source1 source2", | 162 | "target1 target2: source1 source2", | |
162 | "target : source", | 163 | "target : source", | |
163 | "VARNAME+=value")) | 164 | "VARNAME+=value")) | |
164 | ln := mklines.mklines | 165 | ln := mklines.mklines | |
165 | 166 | |||
@@ -198,37 +199,71 @@ func (s *Suite) TestMkLine_fields(c *che | @@ -198,37 +199,71 @@ func (s *Suite) TestMkLine_fields(c *che | |||
198 | c.Check(ln[7].IsDependency(), equals, true) | 199 | c.Check(ln[7].IsDependency(), equals, true) | |
199 | c.Check(ln[7].Targets(), equals, "target1 target2") | 200 | c.Check(ln[7].Targets(), equals, "target1 target2") | |
200 | c.Check(ln[7].Sources(), equals, "source1 source2") | 201 | c.Check(ln[7].Sources(), equals, "source1 source2") | |
201 | c.Check(ln[7].Comment(), equals, "") // Not needed | 202 | c.Check(ln[7].Comment(), equals, "") // Not needed | |
202 | 203 | |||
203 | c.Check(ln[9].IsVarassign(), equals, true) | 204 | c.Check(ln[9].IsVarassign(), equals, true) | |
204 | c.Check(ln[9].Varname(), equals, "VARNAME") | 205 | c.Check(ln[9].Varname(), equals, "VARNAME") | |
205 | c.Check(ln[9].Varcanon(), equals, "VARNAME") | 206 | c.Check(ln[9].Varcanon(), equals, "VARNAME") | |
206 | c.Check(ln[9].Varparam(), equals, "") | 207 | c.Check(ln[9].Varparam(), equals, "") | |
207 | 208 | |||
208 | c.Check(s.Output(), equals, "WARN: test.mk:9: Space before colon in dependency line.\n") | 209 | c.Check(s.Output(), equals, "WARN: test.mk:9: Space before colon in dependency line.\n") | |
209 | } | 210 | } | |
210 | 211 | |||
211 | func (s *Suite) TestMkLine_checkVarassign(c *check.C) { | 212 | func (s *Suite) Test_NewMkLine__autofix_space_after_varname(c *check.C) { | |
213 | s.UseCommandLine(c, "-Wspace") | |||
214 | fname := s.CreateTmpFileLines(c, "Makefile", | |||
215 | mkrcsid, | |||
216 | "VARNAME +=\t${VARNAME}", | |||
217 | "VARNAME+ =\t${VARNAME+}", | |||
218 | "VARNAME+ +=\t${VARNAME+}", | |||
219 | "pkgbase := pkglint") | |||
220 | ||||
221 | CheckfileMk(fname) | |||
222 | ||||
223 | c.Check(s.Output(), equals, ""+ | |||
224 | "WARN: ~/Makefile:2: Unnecessary space after variable name \"VARNAME\".\n"+ | |||
225 | "WARN: ~/Makefile:4: Unnecessary space after variable name \"VARNAME+\".\n") | |||
226 | ||||
227 | s.UseCommandLine(c, "-Wspace", "--autofix") | |||
228 | ||||
229 | CheckfileMk(fname) | |||
230 | ||||
231 | c.Check(s.Output(), equals, ""+ | |||
232 | "AUTOFIX: ~/Makefile:2: Replacing \"VARNAME +=\" with \"VARNAME+=\".\n"+ | |||
233 | "AUTOFIX: ~/Makefile:4: Replacing \"VARNAME+ +=\" with \"VARNAME++=\".\n"+ | |||
234 | "AUTOFIX: ~/Makefile: Has been auto-fixed. Please re-run pkglint.\n"+ | |||
235 | "AUTOFIX: ~/Makefile: Has been auto-fixed. Please re-run pkglint.\n") | |||
236 | c.Check(s.LoadTmpFile(c, "Makefile"), equals, ""+ | |||
237 | "# $NetBSD: mkline_test.go,v 1.14 2016/07/09 09:43:48 rillig Exp $\n"+ | |||
238 | "VARNAME+=\t${VARNAME}\n"+ | |||
239 | "VARNAME+ =\t${VARNAME+}\n"+ | |||
240 | "VARNAME++=\t${VARNAME+}\n"+ | |||
241 | "pkgbase := pkglint\n") | |||
242 | } | |||
243 | ||||
244 | // Pkglint once interpreted all lists as consisting of shell tokens, | |||
245 | // splitting this URL at the ampersands. | |||
246 | func (s *Suite) Test_MkLine_checkVarassign_URL_with_shell_special_characters(c *check.C) { | |||
212 | G.Pkg = NewPackage("graphics/gimp-fix-ca") | 247 | G.Pkg = NewPackage("graphics/gimp-fix-ca") | |
213 | G.globalData.InitVartypes() | 248 | G.globalData.InitVartypes() | |
214 | mkline := NewMkLine(NewLine("fname", 10, "MASTER_SITES=http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file=", nil)) | 249 | mkline := NewMkLine(NewLine("fname", 10, "MASTER_SITES=http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file=", nil)) | |
215 | 250 | |||
216 | mkline.checkVarassign() | 251 | mkline.checkVarassign() | |
217 | 252 | |||
218 | c.Check(s.Output(), equals, "") | 253 | c.Check(s.Output(), equals, "") | |
219 | } | 254 | } | |
220 | 255 | |||
221 | func (s *Suite) TestChecklineMkCondition(c *check.C) { | 256 | func (s *Suite) Test_MkLine_Check_conditions(c *check.C) { | |
222 | s.UseCommandLine(c, "-Wtypes") | 257 | s.UseCommandLine(c, "-Wtypes") | |
223 | G.globalData.InitVartypes() | 258 | G.globalData.InitVartypes() | |
224 | 259 | |||
225 | NewMkLine(NewLine("fname", 1, ".if !empty(PKGSRC_COMPILER:Mmycc)", nil)).CheckCond() | 260 | NewMkLine(NewLine("fname", 1, ".if !empty(PKGSRC_COMPILER:Mmycc)", nil)).CheckCond() | |
226 | 261 | |||
227 | c.Check(s.Stdout(), equals, "WARN: fname:1: The pattern \"mycc\" cannot match any of "+ | 262 | c.Check(s.Stdout(), equals, "WARN: fname:1: The pattern \"mycc\" cannot match any of "+ | |
228 | "{ ccache ccc clang distcc f2c gcc hp icc ido "+ | 263 | "{ ccache ccc clang distcc f2c gcc hp icc ido "+ | |
229 | "gcc mipspro mipspro-ucode pcc sunpro xlc } for PKGSRC_COMPILER.\n") | 264 | "gcc mipspro mipspro-ucode pcc sunpro xlc } for PKGSRC_COMPILER.\n") | |
230 | 265 | |||
231 | NewMkLine(NewLine("fname", 1, ".elif ${A} != ${B}", nil)).CheckCond() | 266 | NewMkLine(NewLine("fname", 1, ".elif ${A} != ${B}", nil)).CheckCond() | |
232 | 267 | |||
233 | c.Check(s.Stdout(), equals, "") | 268 | c.Check(s.Stdout(), equals, "") | |
234 | 269 | |||
@@ -253,425 +288,440 @@ func (s *Suite) TestChecklineMkCondition | @@ -253,425 +288,440 @@ func (s *Suite) TestChecklineMkCondition | |||
253 | c.Check(s.Output(), equals, "WARN: fname:1: \"x386\" is not valid for the hardware architecture part of EMUL_PLATFORM. Use one of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } instead.\n") | 288 | c.Check(s.Output(), equals, "WARN: fname:1: \"x386\" is not valid for the hardware architecture part of EMUL_PLATFORM. Use one of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } instead.\n") | |
254 | 289 | |||
255 | NewMkLine(NewLine("fname", 1, ".if ${EMUL_PLATFORM:Mlinux-x386}", nil)).CheckCond() | 290 | NewMkLine(NewLine("fname", 1, ".if ${EMUL_PLATFORM:Mlinux-x386}", nil)).CheckCond() | |
256 | 291 | |||
257 | c.Check(s.Output(), equals, "WARN: fname:1: The pattern \"x386\" cannot match any of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of EMUL_PLATFORM.\n") | 292 | c.Check(s.Output(), equals, "WARN: fname:1: The pattern \"x386\" cannot match any of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for the hardware architecture part of EMUL_PLATFORM.\n") | |
258 | 293 | |||
259 | NewMkLine(NewLine("fname", 98, ".if ${MACHINE_PLATFORM:MUnknownOS-*-*} || ${MACHINE_ARCH:Mx86}", nil)).CheckCond() | 294 | NewMkLine(NewLine("fname", 98, ".if ${MACHINE_PLATFORM:MUnknownOS-*-*} || ${MACHINE_ARCH:Mx86}", nil)).CheckCond() | |
260 | 295 | |||
261 | c.Check(s.Output(), equals, ""+ | 296 | c.Check(s.Output(), equals, ""+ | |
262 | "WARN: fname:98: The pattern \"UnknownOS\" cannot match any of { AIX BSDOS Bitrig Cygwin Darwin DragonFly FreeBSD FreeMiNT GNUkFreeBSD HPUX Haiku IRIX Interix Linux Minix MirBSD NetBSD OSF1 OpenBSD QNX SCO_SV SunOS UnixWare } for the operating system part of MACHINE_PLATFORM.\n"+ | 297 | "WARN: fname:98: The pattern \"UnknownOS\" cannot match any of { AIX BSDOS Bitrig Cygwin Darwin DragonFly FreeBSD FreeMiNT GNUkFreeBSD HPUX Haiku IRIX Interix Linux Minix MirBSD NetBSD OSF1 OpenBSD QNX SCO_SV SunOS UnixWare } for the operating system part of MACHINE_PLATFORM.\n"+ | |
263 | "WARN: fname:98: The pattern \"x86\" cannot match any of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for MACHINE_ARCH.\n") | 298 | "WARN: fname:98: The pattern \"x86\" cannot match any of { aarch64 aarch64eb alpha amd64 arc arm arm26 arm32 cobalt coldfire convex dreamcast earm earmeb earmhf earmhfeb earmv4 earmv4eb earmv5 earmv5eb earmv6 earmv6eb earmv6hf earmv6hfeb earmv7 earmv7eb earmv7hf earmv7hfeb evbarm hpcmips hpcsh hppa hppa64 i386 i586 i686 ia64 m68000 m68k m88k mips mips64 mips64eb mips64el mipseb mipsel mipsn32 mlrisc ns32k pc532 pmax powerpc powerpc64 rs6000 s390 sh3eb sh3el sparc sparc64 vax x86_64 } for MACHINE_ARCH.\n") | |
264 | } | 299 | } | |
265 | 300 | |||
266 | func (s *Suite) TestMkLine_variableNeedsQuoting_Varbase(c *check.C) { | 301 | func (s *Suite) Test_MkLine_getVariableType_varparam(c *check.C) { | |
267 | mkline := NewMkLine(NewLine("fname", 1, "# dummy", nil)) | 302 | mkline := NewMkLine(NewLine("fname", 1, "# dummy", nil)) | |
268 | G.globalData.InitVartypes() | 303 | G.globalData.InitVartypes() | |
269 | 304 | |||
270 | t1 := mkline.getVariableType("FONT_DIRS") | 305 | t1 := mkline.getVariableType("FONT_DIRS") | |
271 | 306 | |||
272 | c.Assert(t1, check.NotNil) | 307 | c.Assert(t1, check.NotNil) | |
273 | c.Check(t1.String(), equals, "ShellList of Pathmask") | 308 | c.Check(t1.String(), equals, "ShellList of Pathmask") | |
274 | 309 | |||
275 | t2 := mkline.getVariableType("FONT_DIRS.ttf") | 310 | t2 := mkline.getVariableType("FONT_DIRS.ttf") | |
276 | 311 | |||
277 | c.Assert(t2, check.NotNil) | 312 | c.Assert(t2, check.NotNil) | |
278 | c.Check(t2.String(), equals, "ShellList of Pathmask") | 313 | c.Check(t2.String(), equals, "ShellList of Pathmask") | |
279 | } | 314 | } | |
280 | 315 | |||
281 | func (s *Suite) TestVarUseContext_ToString(c *check.C) { | 316 | func (s *Suite) Test_VarUseContext_String(c *check.C) { | |
282 | G.globalData.InitVartypes() | 317 | G.globalData.InitVartypes() | |
283 | mkline := NewMkLine(NewLine("fname", 1, "# dummy", nil)) | 318 | mkline := NewMkLine(NewLine("fname", 1, "# dummy", nil)) | |
284 | vartype := mkline.getVariableType("PKGNAME") | 319 | vartype := mkline.getVariableType("PKGNAME") | |
285 | vuc := &VarUseContext{vartype, vucTimeUnknown, vucQuotBackt, vucExtentWord} | 320 | vuc := &VarUseContext{vartype, vucTimeUnknown, vucQuotBackt, false} | |
286 | 321 | |||
287 | c.Check(vuc.String(), equals, "(PkgName time:unknown quoting:backt extent:word)") | 322 | c.Check(vuc.String(), equals, "(PkgName time:unknown quoting:backt wordpart:false)") | |
288 | } | 323 | } | |
289 | 324 | |||
290 | func (s *Suite) TestMkLine_(c *check.C) { | 325 | func (s *Suite) Test_MkLine_checkVarassign(c *check.C) { | |
291 | G.globalData.InitVartypes() | 326 | G.globalData.InitVartypes() | |
292 | 327 | |||
293 | G.Mk = s.NewMkLines("Makefile", | 328 | G.Mk = s.NewMkLines("Makefile", | |
294 | "# $"+"NetBSD$", | 329 | "# $"+"NetBSD$", | |
295 | "ac_cv_libpari_libs+=\t-L${BUILDLINK_PREFIX.pari}/lib") // From math/clisp-pari/Makefile, rev. 1.8 | 330 | "ac_cv_libpari_libs+=\t-L${BUILDLINK_PREFIX.pari}/lib") // From math/clisp-pari/Makefile, rev. 1.8 | |
296 | 331 | |||
297 | G.Mk.mklines[1].checkVarassign() | 332 | G.Mk.mklines[1].checkVarassign() | |
298 | 333 | |||
299 | c.Check(s.Output(), equals, "WARN: Makefile:2: ac_cv_libpari_libs is defined but not used. Spelling mistake?\n") | 334 | c.Check(s.Output(), equals, "WARN: Makefile:2: ac_cv_libpari_libs is defined but not used. Spelling mistake?\n") | |
300 | } | 335 | } | |
301 | 336 | |||
302 | // In variable assignments, a plain '#' introduces a line comment, unless | 337 | // In variable assignments, a plain '#' introduces a line comment, unless | |
303 | // it is escaped by a backslash. In shell commands, on the other hand, it | 338 | // it is escaped by a backslash. In shell commands, on the other hand, it | |
304 | // is interpreted literally. | 339 | // is interpreted literally. | |
305 | func (s *Suite) TestParselineMk(c *check.C) { | 340 | func (s *Suite) Test_NewMkLine_numbersign(c *check.C) { | |
306 | line1 := NewMkLine(NewLine("fname", 1, "SED_CMD=\t's,\\#,hash,g'", nil)) | 341 | mklineVarassignEscaped := NewMkLine(NewLine("fname", 1, "SED_CMD=\t's,\\#,hash,g'", nil)) | |
307 | 342 | |||
308 | c.Check(line1.Varname(), equals, "SED_CMD") | 343 | c.Check(mklineVarassignEscaped.Varname(), equals, "SED_CMD") | |
309 | c.Check(line1.Value(), equals, "'s,#,hash,g'") | 344 | c.Check(mklineVarassignEscaped.Value(), equals, "'s,#,hash,g'") | |
310 | 345 | |||
311 | line2 := NewMkLine(NewLine("fname", 1, "\tsed -e 's,\\#,hash,g'", nil)) | 346 | mklineCommandEscaped := NewMkLine(NewLine("fname", 1, "\tsed -e 's,\\#,hash,g'", nil)) | |
312 | 347 | |||
313 | c.Check(line2.Shellcmd(), equals, "sed -e 's,\\#,hash,g'") | 348 | c.Check(mklineCommandEscaped.Shellcmd(), equals, "sed -e 's,\\#,hash,g'") | |
314 | 349 | |||
315 | // From shells/zsh/Makefile.common, rev. 1.78 | 350 | // From shells/zsh/Makefile.common, rev. 1.78 | |
316 | NewMkLine(NewLine("fname", 1, "\t# $ sha1 patches/patch-ac", nil)) | 351 | mklineCommandUnescaped := NewMkLine(NewLine("fname", 1, "\t# $ sha1 patches/patch-ac", nil)) | |
317 | 352 | |||
318 | c.Check(s.Output(), equals, "") | 353 | c.Check(mklineCommandUnescaped.Shellcmd(), equals, "# $ sha1 patches/patch-ac") | |
354 | c.Check(s.Output(), equals, "") // No warning about parsing the lonely dollar sign. | |||
355 | ||||
356 | mklineVarassignUnescaped := NewMkLine(NewLine("fname", 1, "SED_CMD=\t's,#,hash,'", nil)) | |||
357 | ||||
358 | c.Check(mklineVarassignUnescaped.Value(), equals, "'s,") | |||
319 | } | 359 | } | |
320 | 360 | |||
321 | func (s *Suite) TestMkLine_LeadingSpace(c *check.C) { | 361 | func (s *Suite) Test_NewMkLine_leading_space(c *check.C) { | |
322 | _ = NewMkLine(NewLine("rubyversion.mk", 427, " _RUBYVER=\t2.15", nil)) | 362 | _ = NewMkLine(NewLine("rubyversion.mk", 427, " _RUBYVER=\t2.15", nil)) | |
323 | 363 | |||
324 | c.Check(s.Output(), equals, "WARN: rubyversion.mk:427: Makefile lines should not start with space characters.\n") | 364 | c.Check(s.Output(), equals, "WARN: rubyversion.mk:427: Makefile lines should not start with space characters.\n") | |
325 | } | 365 | } | |
326 | 366 | |||
327 | func (s *Suite) TestMkLine_checkVarassignDefPermissions(c *check.C) { | 367 | func (s *Suite) Test_MkLine_checkVarassignDefPermissions(c *check.C) { | |
328 | s.UseCommandLine(c, "-Wall") | 368 | s.UseCommandLine(c, "-Wall") | |
329 | G.globalData.InitVartypes() | 369 | G.globalData.InitVartypes() | |
330 | mklines := s.NewMkLines("options.mk", | 370 | mkline := NewMkLine(NewLine("options.mk", 2, "PKG_DEVELOPER?=\tyes", nil)) | |
331 | "# $"+"NetBSD$", | |||
332 | "PKG_DEVELOPER?=\tyes", | |||
333 | "COMMENT=\t${PKG_DEVELOPER}") | |||
334 | 371 | |||
335 | mklines.Check() | 372 | mkline.checkVarassignDefPermissions() | |
336 | 373 | |||
337 | c.Check(s.Output(), equals, "WARN: options.mk:2: The variable PKG_DEVELOPER may not be given a default value by any package.\n") | 374 | c.Check(s.Output(), equals, "WARN: options.mk:2: The variable PKG_DEVELOPER may not be given a default value by any package.\n") | |
338 | } | 375 | } | |
339 | 376 | |||
340 | func (s *Suite) TestMkLine_CheckVarusePermissions(c *check.C) { | 377 | func (s *Suite) Test_MkLine_CheckVarusePermissions(c *check.C) { | |
341 | s.UseCommandLine(c, "-Wall") | 378 | s.UseCommandLine(c, "-Wall") | |
342 | G.globalData.InitVartypes() | 379 | G.globalData.InitVartypes() | |
343 | mklines := s.NewMkLines("options.mk", | 380 | mklines := s.NewMkLines("options.mk", | |
344 | "# $"+"NetBSD$", | 381 | "# $"+"NetBSD$", | |
345 | "COMMENT=\t${GAMES_USER}", | 382 | "COMMENT=\t${GAMES_USER}", | |
346 | "COMMENT:=\t${PKGBASE}", | 383 | "COMMENT:=\t${PKGBASE}", | |
347 | "PYPKGPREFIX=${PKGBASE}") | 384 | "PYPKGPREFIX=${PKGBASE}") | |
348 | G.globalData.UserDefinedVars = map[string]*MkLine{ | 385 | G.globalData.UserDefinedVars = map[string]*MkLine{ | |
349 | "GAMES_USER": mklines.mklines[0], | 386 | "GAMES_USER": mklines.mklines[0], | |
350 | } | 387 | } | |
351 | 388 | |||
352 | mklines.Check() | 389 | mklines.Check() | |
353 | 390 | |||
354 | c.Check(s.Output(), equals, ""+ | 391 | c.Check(s.Output(), equals, ""+ | |
355 | "WARN: options.mk:2: The user-defined variable GAMES_USER is used but not added to BUILD_DEFS.\n"+ | 392 | "WARN: options.mk:2: The user-defined variable GAMES_USER is used but not added to BUILD_DEFS.\n"+ | |
356 | "WARN: options.mk:3: PKGBASE should not be evaluated at load time.\n"+ | 393 | "WARN: options.mk:3: PKGBASE should not be evaluated at load time.\n"+ | |
357 | "WARN: options.mk:4: The variable PYPKGPREFIX may not be set in this file; it would be ok in pyversion.mk.\n"+ | 394 | "WARN: options.mk:4: The variable PYPKGPREFIX may not be set in this file; it would be ok in pyversion.mk.\n"+ | |
358 | "WARN: options.mk:4: PKGBASE should not be evaluated indirectly at load time.\n"+ | 395 | "WARN: options.mk:4: PKGBASE should not be evaluated indirectly at load time.\n"+ | |
359 | "NOTE: options.mk:4: This variable value should be aligned to column 17.\n") | 396 | "NOTE: options.mk:4: This variable value should be aligned to column 17.\n") | |
360 | } | 397 | } | |
361 | 398 | |||
362 | func (s *Suite) Test_MkLine_CheckVarusePermissions_LoadTime(c *check.C) { | 399 | func (s *Suite) Test_MkLine_CheckVarusePermissions__load_time(c *check.C) { | |
363 | s.UseCommandLine(c, "-Wall") | 400 | s.UseCommandLine(c, "-Wall") | |
364 | G.globalData.InitVartypes() | 401 | G.globalData.InitVartypes() | |
365 | mklines := s.NewMkLines("options.mk", | 402 | mklines := s.NewMkLines("options.mk", | |
366 | "# $"+"NetBSD$", | 403 | "# $"+"NetBSD$", | |
367 | "WRKSRC:=${.CURDIR}") | 404 | "WRKSRC:=${.CURDIR}") | |
368 | 405 | |||
369 | mklines.Check() | 406 | mklines.Check() | |
370 | 407 | |||
371 | c.Check(s.Output(), equals, "") // Don’t warn that “.CURDIR should not be evaluated at load time.” | 408 | c.Check(s.Output(), equals, "") // Don’t warn that “.CURDIR should not be evaluated at load time.” | |
372 | } | 409 | } | |
373 | 410 | |||
374 | func (s *Suite) TestMkLine_WarnVaruseLocalbase(c *check.C) { | 411 | func (s *Suite) Test_MkLine_WarnVaruseLocalbase(c *check.C) { | |
375 | mkline := NewMkLine(NewLine("options.mk", 56, "PKGNAME=${LOCALBASE}", nil)) | 412 | mkline := NewMkLine(NewLine("options.mk", 56, "PKGNAME=${LOCALBASE}", nil)) | |
376 | 413 | |||
377 | mkline.WarnVaruseLocalbase() | 414 | mkline.WarnVaruseLocalbase() | |
378 | 415 | |||
379 | c.Check(s.Output(), equals, "WARN: options.mk:56: The LOCALBASE variable should not be used by packages.\n") | 416 | c.Check(s.Output(), equals, "WARN: options.mk:56: The LOCALBASE variable should not be used by packages.\n") | |
380 | } | 417 | } | |
381 | 418 | |||
382 | func (s *Suite) TestMkLine_Misc(c *check.C) { | 419 | func (s *Suite) Test_MkLines_Check__extra(c *check.C) { | |
383 | s.UseCommandLine(c, "-Wextra") | 420 | s.UseCommandLine(c, "-Wextra") | |
384 | G.globalData.InitVartypes() | 421 | G.globalData.InitVartypes() | |
385 | G.Pkg = NewPackage("category/pkgbase") | 422 | G.Pkg = NewPackage("category/pkgbase") | |
386 | G.Mk = s.NewMkLines("options.mk", | 423 | G.Mk = s.NewMkLines("options.mk", | |
387 | "# $"+"NetBSD$", | 424 | "# $"+"NetBSD$", | |
388 | ".for word in ${PKG_FAIL_REASON}", | 425 | ".for word in ${PKG_FAIL_REASON}", | |
389 | "PYTHON_VERSIONS_ACCEPTED=\t27 35 30", | 426 | "PYTHON_VERSIONS_ACCEPTED=\t27 35 30", | |
390 | "CONFIGURE_ARGS+=\t--sharedir=${PREFIX}/share/kde", | 427 | "CONFIGURE_ARGS+=\t--sharedir=${PREFIX}/share/kde", | |
391 | "COMMENT=\t# defined", | 428 | "COMMENT=\t# defined", | |
392 | ".endfor", | 429 | ".endfor", | |
393 | "GAMES_USER?=pkggames", | 430 | "GAMES_USER?=pkggames", | |
394 | "PLIST_SUBST+= CONDITIONAL=${CONDITIONAL}", | 431 | "PLIST_SUBST+= CONDITIONAL=${CONDITIONAL}", | |
395 | "CONDITIONAL=\"@comment\"", | 432 | "CONDITIONAL=\"@comment\"", | |
396 | "BUILD_DIRS=\t${WRKSRC}/../build") | 433 | "BUILD_DIRS=\t${WRKSRC}/../build") | |
397 | 434 | |||
398 | G.Mk.Check() | 435 | G.Mk.Check() | |
399 | 436 | |||
400 | c.Check(s.Output(), equals, ""+ | 437 | c.Check(s.Output(), equals, ""+ | |
401 | "WARN: options.mk:3: The values for PYTHON_VERSIONS_ACCEPTED should be in decreasing order.\n"+ | 438 | "WARN: options.mk:3: The values for PYTHON_VERSIONS_ACCEPTED should be in decreasing order.\n"+ | |
402 | "NOTE: options.mk:4: Please .include \"../../meta-pkgs/kde3/kde3.mk\" instead of this line.\n"+ | 439 | "NOTE: options.mk:4: Please .include \"../../meta-pkgs/kde3/kde3.mk\" instead of this line.\n"+ | |
403 | "NOTE: options.mk:5: Please use \"# empty\", \"# none\" or \"yes\" instead of \"# defined\".\n"+ | 440 | "NOTE: options.mk:5: Please use \"# empty\", \"# none\" or \"yes\" instead of \"# defined\".\n"+ | |
404 | "WARN: options.mk:7: Please include \"../../mk/bsd.prefs.mk\" before using \"?=\".\n"+ | 441 | "WARN: options.mk:7: Please include \"../../mk/bsd.prefs.mk\" before using \"?=\".\n"+ | |
405 | "WARN: options.mk:10: Building the package should take place entirely inside ${WRKSRC}, not \"${WRKSRC}/..\".\n"+ | 442 | "WARN: options.mk:10: Building the package should take place entirely inside ${WRKSRC}, not \"${WRKSRC}/..\".\n"+ | |
406 | "NOTE: options.mk:10: You can use \"../build\" instead of \"${WRKSRC}/../build\".\n") | 443 | "NOTE: options.mk:10: You can use \"../build\" instead of \"${WRKSRC}/../build\".\n") | |
407 | } | 444 | } | |
408 | 445 | |||
409 | func (s *Suite) TestMkLine_CheckRelativePkgdir(c *check.C) { | 446 | func (s *Suite) Test_MkLine_CheckRelativePkgdir(c *check.C) { | |
410 | mkline := NewMkLine(NewLine("Makefile", 46, "# dummy", nil)) | 447 | mkline := NewMkLine(NewLine("Makefile", 46, "# dummy", nil)) | |
411 | 448 | |||
412 | mkline.CheckRelativePkgdir("../pkgbase") | 449 | mkline.CheckRelativePkgdir("../pkgbase") | |
413 | 450 | |||
414 | c.Check(s.Output(), equals, ""+ | 451 | c.Check(s.Output(), equals, ""+ | |
415 | "ERROR: Makefile:46: \"../pkgbase\" does not exist.\n"+ | 452 | "ERROR: Makefile:46: \"../pkgbase\" does not exist.\n"+ | |
416 | "WARN: Makefile:46: \"../pkgbase\" is not a valid relative package directory.\n") | 453 | "WARN: Makefile:46: \"../pkgbase\" is not a valid relative package directory.\n") | |
417 | } | 454 | } | |
418 | 455 | |||
419 | // PR pkg/46570, item 2 | 456 | // PR pkg/46570, item 2 | |
420 | func (s *Suite) TestMkLine_UnfinishedVaruse(c *check.C) { | 457 | func (s *Suite) Test_MkLine__unclosed_varuse(c *check.C) { | |
421 | mkline := NewMkLine(NewLine("Makefile", 93, "EGDIRS=${EGDIR/apparmor.d ${EGDIR/dbus-1/system.d ${EGDIR/pam.d", nil)) | 458 | mkline := NewMkLine(NewLine("Makefile", 93, "EGDIRS=${EGDIR/apparmor.d ${EGDIR/dbus-1/system.d ${EGDIR/pam.d", nil)) | |
422 | 459 | |||
423 | mkline.checkVarassign() | 460 | mkline.checkVarassign() | |
424 | 461 | |||
425 | c.Check(s.Output(), equals, ""+ | 462 | c.Check(s.Output(), equals, ""+ | |
426 | "WARN: Makefile:93: Pkglint parse error in MkLine.Tokenize at \"${EGDIR/apparmor.d ${EGDIR/dbus-1/system.d ${EGDIR/pam.d\".\n"+ | 463 | "WARN: Makefile:93: Pkglint parse error in MkLine.Tokenize at \"${EGDIR/apparmor.d ${EGDIR/dbus-1/system.d ${EGDIR/pam.d\".\n"+ | |
427 | "WARN: Makefile:93: Pkglint parse error in ShTokenizer.ShAtom at \"${EGDIR/apparmor.d ${EGDIR/dbus-1/system.d ${EGDIR/pam.d\" (quoting=plain)\n"+ | 464 | "WARN: Makefile:93: Pkglint parse error in ShTokenizer.ShAtom at \"${EGDIR/apparmor.d ${EGDIR/dbus-1/system.d ${EGDIR/pam.d\" (quoting=plain)\n"+ | |
428 | "WARN: Makefile:93: EGDIRS is defined but not used. Spelling mistake?\n") | 465 | "WARN: Makefile:93: EGDIRS is defined but not used. Spelling mistake?\n") | |
429 | } | 466 | } | |
430 | 467 | |||
431 | func (s *Suite) TestMkLine_variableNeedsQuoting_1(c *check.C) { | 468 | func (s *Suite) Test_MkLine_variableNeedsQuoting__unknown_rhs(c *check.C) { | |
432 | mkline := NewMkLine(NewLine("fname", 1, "PKGNAME := ${UNKNOWN}", nil)) | 469 | mkline := NewMkLine(NewLine("fname", 1, "PKGNAME := ${UNKNOWN}", nil)) | |
433 | G.globalData.InitVartypes() | 470 | G.globalData.InitVartypes() | |
434 | 471 | |||
435 | vuc := &VarUseContext{G.globalData.vartypes["PKGNAME"], vucTimeParse, vucQuotUnknown, vucExtentWord} | 472 | vuc := &VarUseContext{G.globalData.vartypes["PKGNAME"], vucTimeParse, vucQuotUnknown, false} | |
436 | nq := mkline.variableNeedsQuoting("UNKNOWN", nil, vuc) | 473 | nq := mkline.variableNeedsQuoting("UNKNOWN", nil, vuc) | |
437 | 474 | |||
438 | c.Check(nq, equals, nqDontKnow) | 475 | c.Check(nq, equals, nqDontKnow) | |
439 | } | 476 | } | |
440 | 477 | |||
441 | func (s *Suite) TestMkLine_variableNeedsQuoting_2(c *check.C) { | 478 | func (s *Suite) Test_MkLine_variableNeedsQuoting__append_URL_to_list_of_URLs(c *check.C) { | |
442 | s.UseCommandLine(c, "-Wall") | 479 | s.UseCommandLine(c, "-Wall") | |
443 | G.globalData.InitVartypes() | 480 | G.globalData.InitVartypes() | |
444 | s.RegisterMasterSite("MASTER_SITE_SOURCEFORGE", "http://downloads.sourceforge.net/sourceforge/") | 481 | s.RegisterMasterSite("MASTER_SITE_SOURCEFORGE", "http://downloads.sourceforge.net/sourceforge/") | |
445 | mkline := NewMkLine(NewLine("Makefile", 95, "MASTER_SITES=\t${HOMEPAGE}", nil)) | 482 | mkline := NewMkLine(NewLine("Makefile", 95, "MASTER_SITES=\t${HOMEPAGE}", nil)) | |
446 | 483 | |||
447 | vuc := &VarUseContext{G.globalData.vartypes["MASTER_SITES"], vucTimeRun, vucQuotPlain, vucExtentWord} | 484 | vuc := &VarUseContext{G.globalData.vartypes["MASTER_SITES"], vucTimeRun, vucQuotPlain, false} | |
448 | nq := mkline.variableNeedsQuoting("HOMEPAGE", G.globalData.vartypes["HOMEPAGE"], vuc) | 485 | nq := mkline.variableNeedsQuoting("HOMEPAGE", G.globalData.vartypes["HOMEPAGE"], vuc) | |
449 | 486 | |||
450 | c.Check(nq, equals, nqNo) | 487 | c.Check(nq, equals, nqNo) | |
451 | 488 | |||
452 | mkline.checkVarassign() | 489 | mkline.checkVarassign() | |
453 | 490 | |||
454 | c.Check(s.Output(), equals, "") // Up to pkglint 5.3.6, it warned about a missing :Q here, which was wrong. | 491 | c.Check(s.Output(), equals, "") // Up to pkglint 5.3.6, it warned about a missing :Q here, which was wrong. | |
455 | } | 492 | } | |
456 | 493 | |||
457 | // Assigning lists to lists is ok. | 494 | // Assigning lists to lists is ok. | |
458 | func (s *Suite) TestMkLine_variableNeedsQuoting_3(c *check.C) { | 495 | func (s *Suite) Test_MkLine_variableNeedsQuoting__append_list_to_list(c *check.C) { | |
459 | s.UseCommandLine(c, "-Wall") | 496 | s.UseCommandLine(c, "-Wall") | |
460 | G.globalData.InitVartypes() | 497 | G.globalData.InitVartypes() | |
461 | s.RegisterMasterSite("MASTER_SITE_SOURCEFORGE", "http://downloads.sourceforge.net/sourceforge/") | 498 | s.RegisterMasterSite("MASTER_SITE_SOURCEFORGE", "http://downloads.sourceforge.net/sourceforge/") | |
462 | mkline := NewMkLine(NewLine("Makefile", 96, "MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=squirrel-sql/}", nil)) | 499 | mkline := NewMkLine(NewLine("Makefile", 96, "MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=squirrel-sql/}", nil)) | |
463 | 500 | |||
464 | mkline.checkVarassign() | 501 | mkline.checkVarassign() | |
465 | 502 | |||
466 | c.Check(s.Output(), equals, "") | 503 | c.Check(s.Output(), equals, "") | |
467 | } | 504 | } | |
468 | 505 | |||
469 | func (s *Suite) TestMkLine_variableNeedsQuoting_4(c *check.C) { | 506 | func (s *Suite) Test_MkLine_variableNeedsQuoting__eval_shell(c *check.C) { | |
470 | s.UseCommandLine(c, "-Wall") | 507 | s.UseCommandLine(c, "-Wall") | |
471 | G.globalData.InitVartypes() | 508 | G.globalData.InitVartypes() | |
472 | mkline := NewMkLine(NewLine("builtin.mk", 3, "USE_BUILTIN.Xfixes!=\t${PKG_ADMIN} pmatch 'pkg-[0-9]*' ${BUILTIN_PKG.Xfixes:Q}", nil)) | 509 | mkline := NewMkLine(NewLine("builtin.mk", 3, "USE_BUILTIN.Xfixes!=\t${PKG_ADMIN} pmatch 'pkg-[0-9]*' ${BUILTIN_PKG.Xfixes:Q}", nil)) | |
473 | 510 | |||
474 | mkline.checkVarassign() | 511 | mkline.checkVarassign() | |
475 | 512 | |||
476 | c.Check(s.Output(), equals, ""+ | 513 | c.Check(s.Output(), equals, ""+ | |
477 | "WARN: builtin.mk:3: PKG_ADMIN should not be evaluated at load time.\n"+ | 514 | "WARN: builtin.mk:3: PKG_ADMIN should not be evaluated at load time.\n"+ | |
478 | "NOTE: builtin.mk:3: The :Q operator isn't necessary for ${BUILTIN_PKG.Xfixes} here.\n") | 515 | "NOTE: builtin.mk:3: The :Q operator isn't necessary for ${BUILTIN_PKG.Xfixes} here.\n") | |
479 | } | 516 | } | |
480 | 517 | |||
481 | func (s *Suite) TestMkLine_variableNeedsQuoting_5(c *check.C) { | 518 | func (s *Suite) Test_MkLine_variableNeedsQuoting__command_in_single_quotes(c *check.C) { | |
482 | s.UseCommandLine(c, "-Wall") | 519 | s.UseCommandLine(c, "-Wall") | |
483 | G.globalData.InitVartypes() | 520 | G.globalData.InitVartypes() | |
484 | mkline := NewMkLine(NewLine("Makefile", 3, "SUBST_SED.hpath=\t-e 's|^\\(INSTALL[\t:]*=\\).*|\\1${INSTALL}|'", nil)) | 521 | mkline := NewMkLine(NewLine("Makefile", 3, "SUBST_SED.hpath=\t-e 's|^\\(INSTALL[\t:]*=\\).*|\\1${INSTALL}|'", nil)) | |
485 | 522 | |||
486 | mkline.checkVarassign() | 523 | mkline.checkVarassign() | |
487 | 524 | |||
488 | c.Check(s.Output(), equals, "WARN: Makefile:3: Please use ${INSTALL:Q} instead of ${INSTALL} and make sure the variable appears outside of any quoting characters.\n") | 525 | c.Check(s.Output(), equals, "WARN: Makefile:3: Please use ${INSTALL:Q} instead of ${INSTALL} and make sure the variable appears outside of any quoting characters.\n") | |
489 | } | 526 | } | |
490 | 527 | |||
491 | func (s *Suite) TestMkLine_variableNeedsQuoting_6(c *check.C) { | 528 | func (s *Suite) Test_MkLine_variableNeedsQuoting__command_in_command(c *check.C) { | |
492 | s.UseCommandLine(c, "-Wall") | 529 | s.UseCommandLine(c, "-Wall") | |
493 | G.globalData.InitVartypes() | 530 | G.globalData.InitVartypes() | |
494 | s.RegisterTool(&Tool{Name: "find", Varname: "FIND", Predefined: true}) | 531 | s.RegisterTool(&Tool{Name: "find", Varname: "FIND", Predefined: true}) | |
495 | s.RegisterTool(&Tool{Name: "sort", Varname: "SORT", Predefined: true}) | 532 | s.RegisterTool(&Tool{Name: "sort", Varname: "SORT", Predefined: true}) | |
496 | G.Pkg = NewPackage("category/pkgbase") | 533 | G.Pkg = NewPackage("category/pkgbase") | |
497 | G.Mk = s.NewMkLines("Makefile", | 534 | G.Mk = s.NewMkLines("Makefile", | |
498 | "# $"+"NetBSD$", | 535 | "# $"+"NetBSD$", | |
499 | "GENERATE_PLIST= cd ${DESTDIR}${PREFIX}; ${FIND} * \\( -type f -or -type l \\) | ${SORT};") | 536 | "GENERATE_PLIST= cd ${DESTDIR}${PREFIX}; ${FIND} * \\( -type f -or -type l \\) | ${SORT};") | |
500 | 537 | |||
501 | G.Mk.determineDefinedVariables() | 538 | G.Mk.determineDefinedVariables() | |
502 | G.Mk.mklines[1].Check() | 539 | G.Mk.mklines[1].Check() | |
503 | 540 | |||
504 | c.Check(s.Output(), equals, ""+ | 541 | c.Check(s.Output(), equals, ""+ | |
505 | "WARN: Makefile:2: The exitcode of the left-hand-side command of the pipe operator is ignored.\n") | 542 | "WARN: Makefile:2: The exitcode of the left-hand-side command of the pipe operator is ignored.\n") | |
506 | } | 543 | } | |
507 | 544 | |||
508 | func (s *Suite) TestMkLine_variableNeedsQuoting_7(c *check.C) { | 545 | func (s *Suite) Test_MkLine_variableNeedsQuoting__word_as_part_of_word(c *check.C) { | |
509 | s.UseCommandLine(c, "-Wall") | 546 | s.UseCommandLine(c, "-Wall") | |
510 | G.globalData.InitVartypes() | 547 | G.globalData.InitVartypes() | |
511 | G.Mk = s.NewMkLines("Makefile", | 548 | G.Mk = s.NewMkLines("Makefile", | |
512 | "# $"+"NetBSD$", | 549 | "# $"+"NetBSD$", | |
513 | "EGDIR=\t${EGDIR}/${MACHINE_GNU_PLATFORM}") | 550 | "EGDIR=\t${EGDIR}/${MACHINE_GNU_PLATFORM}") | |
514 | 551 | |||
515 | G.Mk.mklines[1].Check() | 552 | G.Mk.mklines[1].Check() | |
516 | 553 | |||
517 | c.Check(s.Output(), equals, "") | 554 | c.Check(s.Output(), equals, "") | |
518 | } | 555 | } | |
519 | 556 | |||
557 | // As an argument to ${ECHO}, the :Q modifier should be used, but pkglint | |||
558 | // currently does not know all shell commands and how they handle their | |||
559 | // arguments. As an argument to xargs(1), the :Q modifier would be misplaced, | |||
560 | // therefore no warning is issued. | |||
561 | // | |||
520 | // Based on graphics/circos/Makefile. | 562 | // Based on graphics/circos/Makefile. | |
521 | func (s *Suite) TestMkLine_variableNeedsQuoting_8(c *check.C) { | 563 | func (s *Suite) Test_MkLine_variableNeedsQuoting__command_as_command_argument(c *check.C) { | |
522 | s.UseCommandLine(c, "-Wall") | 564 | s.UseCommandLine(c, "-Wall") | |
523 | s.RegisterTool(&Tool{Name: "perl", Varname: "PERL5", Predefined: true}) | 565 | s.RegisterTool(&Tool{Name: "perl", Varname: "PERL5", Predefined: true}) | |
524 | s.RegisterTool(&Tool{Name: "bash", Varname: "BASH", Predefined: true}) | 566 | s.RegisterTool(&Tool{Name: "bash", Varname: "BASH", Predefined: true}) | |
525 | G.globalData.InitVartypes() | 567 | G.globalData.InitVartypes() | |
526 | G.Mk = s.NewMkLines("Makefile", | 568 | G.Mk = s.NewMkLines("Makefile", | |
527 | "# $"+"NetBSD$", | 569 | "# $"+"NetBSD$", | |
528 | "\t${RUN} cd ${WRKSRC} && ( ${ECHO} ${PERL5:Q} ; ${ECHO} ) | ${BASH} ./install", | 570 | "\t${RUN} cd ${WRKSRC} && ( ${ECHO} ${PERL5:Q} ; ${ECHO} ) | ${BASH} ./install", | |
529 | "\t${RUN} cd ${WRKSRC} && ( ${ECHO} ${PERL5} ; ${ECHO} ) | ${BASH} ./install") | 571 | "\t${RUN} cd ${WRKSRC} && ( ${ECHO} ${PERL5} ; ${ECHO} ) | ${BASH} ./install") | |
530 | 572 | |||
531 | G.Mk.mklines[1].Check() | 573 | G.Mk.mklines[1].Check() | |
532 | G.Mk.mklines[2].Check() | 574 | G.Mk.mklines[2].Check() | |
533 | 575 | |||
534 | c.Check(s.Output(), equals, ""+ | 576 | c.Check(s.Output(), equals, ""+ | |
535 | "WARN: Makefile:2: The exitcode of the left-hand-side command of the pipe operator is ignored.\n"+ | 577 | "WARN: Makefile:2: The exitcode of the left-hand-side command of the pipe operator is ignored.\n"+ | |
536 | "WARN: Makefile:3: The exitcode of the left-hand-side command of the pipe operator is ignored.\n") | 578 | "WARN: Makefile:3: The exitcode of the left-hand-side command of the pipe operator is ignored.\n") | |
537 | } | 579 | } | |
538 | 580 | |||
539 | // Based on mail/mailfront/Makefile. | 581 | // Based on mail/mailfront/Makefile. | |
540 | func (s *Suite) TestMkLine_variableNeedsQuoting_9(c *check.C) { | 582 | func (s *Suite) Test_MkLine_variableNeedsQuoting__URL_as_part_of_word_in_list(c *check.C) { | |
541 | s.UseCommandLine(c, "-Wall") | 583 | s.UseCommandLine(c, "-Wall") | |
542 | G.globalData.InitVartypes() | 584 | G.globalData.InitVartypes() | |
543 | G.Mk = s.NewMkLines("Makefile", | 585 | G.Mk = s.NewMkLines("Makefile", | |
544 | "# $"+"NetBSD$", | 586 | "# $"+"NetBSD$", | |
545 | "MASTER_SITES=${HOMEPAGE}archive/") | 587 | "MASTER_SITES=${HOMEPAGE}archive/") | |
546 | 588 | |||
547 | G.Mk.mklines[1].Check() | 589 | G.Mk.mklines[1].Check() | |
548 | 590 | |||
549 | c.Check(s.Output(), equals, "") // Don’t suggest to use ${HOMEPAGE:Q}. | 591 | c.Check(s.Output(), equals, "") // Don’t suggest to use ${HOMEPAGE:Q}. | |
550 | } | 592 | } | |
551 | 593 | |||
594 | // Pkglint currently does not parse $$(subshell) commands very well. As | |||
595 | // a side effect, it sometimes issues wrong warnings about the :Q | |||
596 | // modifier. | |||
597 | // | |||
552 | // Based on www/firefox31/xpi.mk. | 598 | // Based on www/firefox31/xpi.mk. | |
553 | func (s *Suite) TestMkLine_variableNeedsQuoting_10(c *check.C) { | 599 | func (s *Suite) Test_MkLine_variableNeedsQuoting__command_in_subshell(c *check.C) { | |
554 | s.UseCommandLine(c, "-Wall") | 600 | s.UseCommandLine(c, "-Wall") | |
555 | G.globalData.InitVartypes() | 601 | G.globalData.InitVartypes() | |
556 | s.RegisterTool(&Tool{Name: "awk", Varname: "AWK", Predefined: true}) | 602 | s.RegisterTool(&Tool{Name: "awk", Varname: "AWK", Predefined: true}) | |
557 | s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", Predefined: true}) | 603 | s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", Predefined: true}) | |
558 | G.Mk = s.NewMkLines("xpi.mk", | 604 | G.Mk = s.NewMkLines("xpi.mk", | |
559 | "# $"+"NetBSD$", | 605 | "# $"+"NetBSD$", | |
560 | "\t id=$$(${AWK} '{print}' < ${WRKSRC}/idfile) && echo \"$$id\"", | 606 | "\t id=$$(${AWK} '{print}' < ${WRKSRC}/idfile) && echo \"$$id\"", | |
561 | "\t id=`${AWK} '{print}' < ${WRKSRC}/idfile` && echo \"$$id\"") | 607 | "\t id=`${AWK} '{print}' < ${WRKSRC}/idfile` && echo \"$$id\"") | |
562 | 608 | |||
563 | G.Mk.mklines[1].Check() | 609 | G.Mk.mklines[1].Check() | |
564 | G.Mk.mklines[2].Check() | 610 | G.Mk.mklines[2].Check() | |
565 | 611 | |||
566 | c.Check(s.Output(), equals, "WARN: xpi.mk:2: Invoking subshells via $(...) is not portable enough.\n") // Don’t suggest to use ${AWK:Q}. | 612 | c.Check(s.Output(), equals, "WARN: xpi.mk:2: Invoking subshells via $(...) is not portable enough.\n") // Don’t suggest to use ${AWK:Q}. | |
567 | } | 613 | } | |
568 | 614 | |||
569 | func (s *Suite) TestMkLine_variableNeedsQuoting_11(c *check.C) { | 615 | // LDFLAGS (and even more so CPPFLAGS and CFLAGS) may contain special | |
616 | // shell characters like quotes or backslashes. Therefore, quoting them | |||
617 | // correctly is more tricky than with other variables. | |||
618 | func (s *Suite) Test_MkLine_variableNeedsQuoting__LDFLAGS_in_single_quotes(c *check.C) { | |||
570 | s.UseCommandLine(c, "-Wall") | 619 | s.UseCommandLine(c, "-Wall") | |
571 | G.globalData.InitVartypes() | 620 | G.globalData.InitVartypes() | |
572 | G.Mk = s.NewMkLines("x11/mlterm/Makefile", | 621 | G.Mk = s.NewMkLines("x11/mlterm/Makefile", | |
573 | "# $"+"NetBSD$", | 622 | "# $"+"NetBSD$", | |
574 | "SUBST_SED.link=-e 's|(LIBTOOL_LINK).*(LIBS)|& ${LDFLAGS:M*:Q}|g'", | 623 | "SUBST_SED.link=-e 's|(LIBTOOL_LINK).*(LIBS)|& ${LDFLAGS:M*:Q}|g'", | |
575 | "SUBST_SED.link=-e 's|(LIBTOOL_LINK).*(LIBS)|& '${LDFLAGS:M*:Q}'|g'") | 624 | "SUBST_SED.link=-e 's|(LIBTOOL_LINK).*(LIBS)|& '${LDFLAGS:M*:Q}'|g'") | |
576 | 625 | |||
577 | G.Mk.mklines[1].Check() | 626 | G.Mk.mklines[1].Check() | |
578 | G.Mk.mklines[2].Check() | 627 | G.Mk.mklines[2].Check() | |
579 | 628 | |||
580 | c.Check(s.Output(), equals, "WARN: x11/mlterm/Makefile:2: Please move ${LDFLAGS:M*:Q} outside of any quoting characters.\n") | 629 | c.Check(s.Output(), equals, "WARN: x11/mlterm/Makefile:2: Please move ${LDFLAGS:M*:Q} outside of any quoting characters.\n") | |
581 | } | 630 | } | |
582 | 631 | |||
583 | func (s *Suite) TestMkLine_variableNeedsQuoting_12(c *check.C) { | 632 | func (s *Suite) Test_MkLines_Check__MASTER_SITE_in_HOMEPAGE(c *check.C) { | |
584 | s.UseCommandLine(c, "-Wall") | 633 | s.UseCommandLine(c, "-Wall") | |
585 | s.RegisterMasterSite("MASTER_SITE_GITHUB", "https://github.com/") | 634 | s.RegisterMasterSite("MASTER_SITE_GITHUB", "https://github.com/") | |
586 | G.globalData.InitVartypes() | 635 | G.globalData.InitVartypes() | |
587 | G.Mk = s.NewMkLines("devel/catch/Makefile", | 636 | G.Mk = s.NewMkLines("devel/catch/Makefile", | |
588 | "# $"+"NetBSD$", | 637 | "# $"+"NetBSD$", | |
589 | "HOMEPAGE=\t${MASTER_SITE_GITHUB:=philsquared/Catch/}", | 638 | "HOMEPAGE=\t${MASTER_SITE_GITHUB:=philsquared/Catch/}", | |
590 | "HOMEPAGE=\t${MASTER_SITE_GITHUB}", | 639 | "HOMEPAGE=\t${MASTER_SITE_GITHUB}", | |
591 | "HOMEPAGE=\t${MASTER_SITES}", | 640 | "HOMEPAGE=\t${MASTER_SITES}", | |
592 | "HOMEPAGE=\t${MASTER_SITES}${GITHUB_PROJECT}") | 641 | "HOMEPAGE=\t${MASTER_SITES}${GITHUB_PROJECT}") | |
593 | 642 | |||
594 | G.Mk.Check() | 643 | G.Mk.Check() | |
595 | 644 | |||
596 | c.Check(s.Output(), equals, ""+ | 645 | c.Check(s.Output(), equals, ""+ | |
597 | "WARN: devel/catch/Makefile:2: HOMEPAGE should not be defined in terms of MASTER_SITEs. Use https://github.com/philsquared/Catch/ directly.\n"+ | 646 | "WARN: devel/catch/Makefile:2: HOMEPAGE should not be defined in terms of MASTER_SITEs. Use https://github.com/philsquared/Catch/ directly.\n"+ | |
598 | "WARN: devel/catch/Makefile:3: HOMEPAGE should not be defined in terms of MASTER_SITEs. Use https://github.com/ directly.\n"+ | 647 | "WARN: devel/catch/Makefile:3: HOMEPAGE should not be defined in terms of MASTER_SITEs. Use https://github.com/ directly.\n"+ | |
599 | "WARN: devel/catch/Makefile:4: HOMEPAGE should not be defined in terms of MASTER_SITEs.\n"+ | 648 | "WARN: devel/catch/Makefile:4: HOMEPAGE should not be defined in terms of MASTER_SITEs.\n"+ | |
600 | "WARN: devel/catch/Makefile:5: HOMEPAGE should not be defined in terms of MASTER_SITEs.\n") | 649 | "WARN: devel/catch/Makefile:5: HOMEPAGE should not be defined in terms of MASTER_SITEs.\n") | |
601 | } | 650 | } | |
602 | 651 | |||
603 | func (s *Suite) TestMkLine_variableNeedsQuoting_13(c *check.C) { | 652 | func (s *Suite) Test_MkLine_variableNeedsQuoting__tool_in_quotes_in_subshell_in_shellwords(c *check.C) { | |
604 | s.UseCommandLine(c, "-Wall") | 653 | s.UseCommandLine(c, "-Wall") | |
605 | s.RegisterTool(&Tool{Varname: "SH", Predefined: true}) | 654 | s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", Predefined: true}) | |
655 | s.RegisterTool(&Tool{Name: "sh", Varname: "SH", Predefined: true}) | |||
606 | G.globalData.InitVartypes() | 656 | G.globalData.InitVartypes() | |
607 | G.Mk = s.NewMkLines("x11/labltk/Makefile", | 657 | G.Mk = s.NewMkLines("x11/labltk/Makefile", | |
608 | "# $"+"NetBSD$", | 658 | "# $"+"NetBSD$", | |
609 | "CONFIGURE_ARGS+=\t-tklibs \"`${SH} -c '${ECHO} $$TK_LD_FLAGS'`\"") | 659 | "CONFIGURE_ARGS+=\t-tklibs \"`${SH} -c '${ECHO} $$TK_LD_FLAGS'`\"") | |
610 | 660 | |||
611 | G.Mk.mklines[1].Check() | 661 | G.Mk.mklines[1].Check() | |
612 | 662 | |||
613 | c.Check(s.Output(), equals, "") // Don’t suggest ${ECHO:Q} here. | 663 | c.Check(s.Output(), equals, "") // Don’t suggest ${ECHO:Q} here. | |
614 | } | 664 | } | |
615 | 665 | |||
616 | func (s *Suite) TestMkLine_variableNeedsQuoting_14(c *check.C) { | 666 | func (s *Suite) Test_MkLine_variableNeedsQuoting__LDADD_in_BUILDLINK_TRANSFORM(c *check.C) { | |
617 | s.UseCommandLine(c, "-Wall") | 667 | s.UseCommandLine(c, "-Wall") | |
618 | G.globalData.InitVartypes() | 668 | G.globalData.InitVartypes() | |
619 | G.Mk = s.NewMkLines("x11/qt5-qtbase/Makefile.common", | 669 | G.Mk = s.NewMkLines("x11/qt5-qtbase/Makefile.common", | |
620 | "BUILDLINK_TRANSFORM+=opt:-ldl:${BUILDLINK_LDADD.dl:M*}") | 670 | "BUILDLINK_TRANSFORM+=opt:-ldl:${BUILDLINK_LDADD.dl:M*}") | |
621 | 671 | |||
622 | G.Mk.mklines[0].Check() | 672 | G.Mk.mklines[0].Check() | |
623 | 673 | |||
624 | // Note: The :M* modifier is not necessary, since this is not a GNU Configure package. | 674 | // Note: The :M* modifier is not necessary, since this is not a GNU Configure package. | |
625 | c.Check(s.Output(), equals, "WARN: x11/qt5-qtbase/Makefile.common:1: Please use ${BUILDLINK_LDADD.dl:Q} instead of ${BUILDLINK_LDADD.dl:M*}.\n") | 675 | c.Check(s.Output(), equals, "WARN: x11/qt5-qtbase/Makefile.common:1: Please use ${BUILDLINK_LDADD.dl:Q} instead of ${BUILDLINK_LDADD.dl:M*}.\n") | |
626 | } | 676 | } | |
627 | 677 | |||
628 | func (s *Suite) TestMkLine_variableNeedsQuoting_15(c *check.C) { | 678 | func (s *Suite) Test_MkLine_variableNeedsQuoting_command_in_message(c *check.C) { | |
629 | s.UseCommandLine(c, "-Wall") | 679 | s.UseCommandLine(c, "-Wall") | |
630 | G.globalData.InitVartypes() | 680 | G.globalData.InitVartypes() | |
631 | G.Mk = s.NewMkLines("benchmarks/iozone/Makefile", | 681 | G.Mk = s.NewMkLines("benchmarks/iozone/Makefile", | |
632 | "SUBST_MESSAGE.crlf=\tStripping EOL CR in ${REPLACE_PERL}") | 682 | "SUBST_MESSAGE.crlf=\tStripping EOL CR in ${REPLACE_PERL}") | |
633 | 683 | |||
634 | G.Mk.mklines[0].Check() | 684 | G.Mk.mklines[0].Check() | |
635 | 685 | |||
636 | c.Check(s.Output(), equals, "") // Don’t suggest ${REPLACE_PERL:Q}. | 686 | c.Check(s.Output(), equals, "") // Don’t suggest ${REPLACE_PERL:Q}. | |
637 | } | 687 | } | |
638 | 688 | |||
639 | func (s *Suite) TestMkLine_variableNeedsQuoting_16(c *check.C) { | 689 | func (s *Suite) Test_MkLine_variableNeedsQuoting_guessed_list_variable_in_quotes(c *check.C) { | |
640 | s.UseCommandLine(c, "-Wall") | 690 | s.UseCommandLine(c, "-Wall") | |
641 | G.globalData.InitVartypes() | 691 | G.globalData.InitVartypes() | |
642 | G.Mk = s.NewMkLines("audio/jack-rack/Makefile", | 692 | G.Mk = s.NewMkLines("audio/jack-rack/Makefile", | |
643 | "# $"+"NetBSD$", | 693 | "# $"+"NetBSD$", | |
644 | "LADSPA_PLUGIN_PATH?=\t${PREFIX}/lib/ladspa", | 694 | "LADSPA_PLUGIN_PATH?=\t${PREFIX}/lib/ladspa", | |
645 | "CPPFLAGS+=\t\t-DLADSPA_PATH=\"\\\"${LADSPA_PLUGIN_PATH}\\\"\"") | 695 | "CPPFLAGS+=\t\t-DLADSPA_PATH=\"\\\"${LADSPA_PLUGIN_PATH}\\\"\"") | |
646 | 696 | |||
647 | G.Mk.Check() | 697 | G.Mk.Check() | |
648 | 698 | |||
649 | c.Check(s.Output(), equals, "WARN: audio/jack-rack/Makefile:3: The list variable LADSPA_PLUGIN_PATH should not be embedded in a word.\n") | 699 | c.Check(s.Output(), equals, "WARN: audio/jack-rack/Makefile:3: The list variable LADSPA_PLUGIN_PATH should not be embedded in a word.\n") | |
650 | } | 700 | } | |
651 | 701 | |||
652 | func (s *Suite) TestMkLine_variableNeedsQuoting_17(c *check.C) { | 702 | func (s *Suite) Test_MkLine_variableNeedsQuoting_list_in_list(c *check.C) { | |
653 | s.UseCommandLine(c, "-Wall") | 703 | s.UseCommandLine(c, "-Wall") | |
654 | G.globalData.InitVartypes() | 704 | G.globalData.InitVartypes() | |
655 | G.Mk = s.NewMkLines("x11/eterm/Makefile", | 705 | G.Mk = s.NewMkLines("x11/eterm/Makefile", | |
656 | "# $"+"NetBSD$", | 706 | "# $"+"NetBSD$", | |
657 | "DISTFILES=\t${DEFAULT_DISTFILES} ${PIXMAP_FILES}") | 707 | "DISTFILES=\t${DEFAULT_DISTFILES} ${PIXMAP_FILES}") | |
658 | 708 | |||
659 | G.Mk.Check() | 709 | G.Mk.Check() | |
660 | 710 | |||
661 | c.Check(s.Output(), equals, "") // Don’t warn about missing :Q operators. | 711 | c.Check(s.Output(), equals, "") // Don’t warn about missing :Q operators. | |
662 | } | 712 | } | |
663 | 713 | |||
664 | func (s *Suite) TestMkLine_variableNeedsQuoting_18(c *check.C) { | 714 | func (s *Suite) Test_MkLine_variableNeedsQuoting_PKGNAME_and_URL_list_in_URL_list(c *check.C) { | |
665 | s.UseCommandLine(c, "-Wall") | 715 | s.UseCommandLine(c, "-Wall") | |
666 | s.RegisterMasterSite("MASTER_SITE_GNOME", "http://ftp.gnome.org/") | 716 | s.RegisterMasterSite("MASTER_SITE_GNOME", "http://ftp.gnome.org/") | |
667 | G.globalData.InitVartypes() | 717 | G.globalData.InitVartypes() | |
668 | G.Mk = s.NewMkLines("x11/gtk3/Makefile", | 718 | G.Mk = s.NewMkLines("x11/gtk3/Makefile", | |
669 | "# $"+"NetBSD$", | 719 | "# $"+"NetBSD$", | |
670 | "MASTER_SITES=\tftp://ftp.gtk.org/${PKGNAME}/ ${MASTER_SITE_GNOME:=subdir/}") | 720 | "MASTER_SITES=\tftp://ftp.gtk.org/${PKGNAME}/ ${MASTER_SITE_GNOME:=subdir/}") | |
671 | 721 | |||
672 | G.Mk.mklines[1].checkVarassignVaruse() | 722 | G.Mk.mklines[1].checkVarassignVaruse() | |
673 | 723 | |||
674 | c.Check(s.Output(), equals, "") // Don’t warn about missing :Q operators. | 724 | c.Check(s.Output(), equals, "") // Don’t warn about missing :Q operators. | |
675 | } | 725 | } | |
676 | 726 | |||
677 | func (s *Suite) Test_MkLine_variableNeedsQuoting_tool_in_CONFIGURE_ENV(c *check.C) { | 727 | func (s *Suite) Test_MkLine_variableNeedsQuoting_tool_in_CONFIGURE_ENV(c *check.C) { | |
@@ -693,119 +743,121 @@ func (s *Suite) Test_MkLine_variableNeed | @@ -693,119 +743,121 @@ func (s *Suite) Test_MkLine_variableNeed | |||
693 | } | 743 | } | |
694 | 744 | |||
695 | func (s *Suite) Test_MkLine_Varuse_Modifier_L(c *check.C) { | 745 | func (s *Suite) Test_MkLine_Varuse_Modifier_L(c *check.C) { | |
696 | s.UseCommandLine(c, "-Wall") | 746 | s.UseCommandLine(c, "-Wall") | |
697 | G.globalData.InitVartypes() | 747 | G.globalData.InitVartypes() | |
698 | G.Mk = s.NewMkLines("x11/xkeyboard-config/Makefile", | 748 | G.Mk = s.NewMkLines("x11/xkeyboard-config/Makefile", | |
699 | "FILES_SUBST+=XKBCOMP_SYMLINK=${${XKBBASE}/xkbcomp:L:Q}") | 749 | "FILES_SUBST+=XKBCOMP_SYMLINK=${${XKBBASE}/xkbcomp:L:Q}") | |
700 | 750 | |||
701 | G.Mk.mklines[0].Check() | 751 | G.Mk.mklines[0].Check() | |
702 | 752 | |||
703 | c.Check(s.Output(), equals, "") // Don’t warn that ${XKBBASE}/xkbcomp is used but not defined. | 753 | c.Check(s.Output(), equals, "") // Don’t warn that ${XKBBASE}/xkbcomp is used but not defined. | |
704 | } | 754 | } | |
705 | 755 | |||
706 | func (s *Suite) Test_MkLine_Cond_ShellCommand(c *check.C) { | 756 | func (s *Suite) Test_MkLine_CheckCond_comparison_with_shell_command(c *check.C) { | |
707 | s.UseCommandLine(c, "-Wall") | 757 | s.UseCommandLine(c, "-Wall") | |
708 | G.globalData.InitVartypes() | 758 | G.globalData.InitVartypes() | |
709 | G.Mk = s.NewMkLines("security/openssl/Makefile", | 759 | G.Mk = s.NewMkLines("security/openssl/Makefile", | |
710 | "# $"+"NetBSD$", | 760 | "# $"+"NetBSD$", | |
711 | ".if ${PKGSRC_COMPILER} == \"gcc\" && ${CC} == \"cc\"", | 761 | ".if ${PKGSRC_COMPILER} == \"gcc\" && ${CC} == \"cc\"", | |
712 | ".endif") | 762 | ".endif") | |
713 | 763 | |||
714 | G.Mk.Check() | 764 | G.Mk.Check() | |
715 | 765 | |||
716 | c.Check(s.Output(), equals, "") // Don’t warn about unknown shell command "cc". | 766 | c.Check(s.Output(), equals, "") // Don’t warn about unknown shell command "cc". | |
717 | } | 767 | } | |
718 | 768 | |||
719 | func (s *Suite) disabledTest_MkLine_Pkgmandir(c *check.C) { | 769 | func (s *Suite) disabled_Test_MkLine_Pkgmandir(c *check.C) { | |
720 | s.UseCommandLine(c, "-Wall") | 770 | s.UseCommandLine(c, "-Wall") | |
721 | G.globalData.InitVartypes() | 771 | G.globalData.InitVartypes() | |
722 | G.Mk = s.NewMkLines("chat/ircII/Makefile", | 772 | G.Mk = s.NewMkLines("chat/ircII/Makefile", | |
723 | "# $"+"NetBSD$", | 773 | "# $"+"NetBSD$", | |
724 | "CONFIGURE_ARGS+=--mandir=${DESTDIR}${PREFIX}/man", | 774 | "CONFIGURE_ARGS+=--mandir=${DESTDIR}${PREFIX}/man", | |
725 | "CONFIGURE_ARGS+=--mandir=${DESTDIR}${PREFIX}/${PKGMANDIR}") | 775 | "CONFIGURE_ARGS+=--mandir=${DESTDIR}${PREFIX}/${PKGMANDIR}") | |
726 | 776 | |||
727 | G.Mk.Check() | 777 | G.Mk.Check() | |
728 | 778 | |||
729 | c.Check(s.Output(), equals, "WARN: chat/ircII/Makefile:2: Please use ${PKGMANDIR} instead of \"man\".\n") | 779 | c.Check(s.Output(), equals, "WARN: chat/ircII/Makefile:2: Please use ${PKGMANDIR} instead of \"man\".\n") | |
730 | } | 780 | } | |
731 | 781 | |||
732 | func (s *Suite) Test_MkLine_Check_Cflags_Backticks(c *check.C) { | 782 | func (s *Suite) Test_MkLine_Check_CFLAGS_with_backticks(c *check.C) { | |
733 | s.UseCommandLine(c, "-Wall") | 783 | s.UseCommandLine(c, "-Wall") | |
734 | G.globalData.InitVartypes() | 784 | G.globalData.InitVartypes() | |
735 | G.Mk = s.NewMkLines("chat/pidgin-icb/Makefile", | 785 | G.Mk = s.NewMkLines("chat/pidgin-icb/Makefile", | |
736 | "# $"+"NetBSD$", | 786 | "# $"+"NetBSD$", | |
737 | "CFLAGS+=\t`pkg-config pidgin --cflags`") | 787 | "CFLAGS+=\t`pkg-config pidgin --cflags`") | |
738 | mkline := G.Mk.mklines[1] | 788 | mkline := G.Mk.mklines[1] | |
739 | 789 | |||
740 | words, rest := splitIntoMkWords(mkline.Line, mkline.Value()) | 790 | words, rest := splitIntoMkWords(mkline.Line, mkline.Value()) | |
741 | 791 | |||
742 | c.Check(words, deepEquals, []string{"`pkg-config pidgin --cflags`"}) | 792 | c.Check(words, deepEquals, []string{"`pkg-config pidgin --cflags`"}) | |
743 | c.Check(rest, equals, "") | 793 | c.Check(rest, equals, "") | |
744 | 794 | |||
745 | G.Mk.mklines[1].CheckVartype("CFLAGS", opAssignAppend, "`pkg-config pidgin --cflags`", "") | 795 | G.Mk.mklines[1].CheckVartype("CFLAGS", opAssignAppend, "`pkg-config pidgin --cflags`", "") | |
746 | 796 | |||
747 | c.Check(s.Output(), equals, "") // No warning about "`pkg-config" being an unknown CFlag. | 797 | c.Check(s.Output(), equals, "") // No warning about "`pkg-config" being an unknown CFlag. | |
748 | } | 798 | } | |
749 | 799 | |||
750 | func (s *Suite) Test_MkLine_MasterSites_WordPart(c *check.C) { | 800 | func (s *Suite) Test_MkLine_Check_VERSION_as_wordpart_in_MASTER_SITES(c *check.C) { | |
751 | s.UseCommandLine(c, "-Wall") | 801 | s.UseCommandLine(c, "-Wall") | |
752 | G.globalData.InitVartypes() | 802 | G.globalData.InitVartypes() | |
753 | mklines := s.NewMkLines("geography/viking/Makefile", | 803 | mklines := s.NewMkLines("geography/viking/Makefile", | |
754 | "# $"+"NetBSD$", | 804 | "# $"+"NetBSD$", | |
755 | "MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=viking/}${VERSION}/") | 805 | "MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=viking/}${VERSION}/") | |
756 | 806 | |||
757 | mklines.Check() | 807 | mklines.Check() | |
758 | 808 | |||
759 | c.Check(s.Output(), equals, "WARN: geography/viking/Makefile:2: "+ | 809 | c.Check(s.Output(), equals, "WARN: geography/viking/Makefile:2: "+ | |
760 | "The list variable MASTER_SITE_SOURCEFORGE should not be embedded in a word.\n") | 810 | "The list variable MASTER_SITE_SOURCEFORGE should not be embedded in a word.\n") | |
761 | } | 811 | } | |
762 | 812 | |||
763 | func (s *Suite) Test_MkLine_ShellCommand_WordPart(c *check.C) { | 813 | func (s *Suite) Test_MkLine_Check_shell_command_as_wordpart_in_ENV_list(c *check.C) { | |
764 | s.UseCommandLine(c, "-Wall") | 814 | s.UseCommandLine(c, "-Wall") | |
765 | G.globalData.InitVartypes() | 815 | G.globalData.InitVartypes() | |
766 | mklines := s.NewMkLines("x11/lablgtk1/Makefile", | 816 | mklines := s.NewMkLines("x11/lablgtk1/Makefile", | |
767 | "# $"+"NetBSD$", | 817 | "# $"+"NetBSD$", | |
768 | "CONFIGURE_ENV+=\tCC=${CC}") | 818 | "CONFIGURE_ENV+=\tCC=${CC}") | |
769 | 819 | |||
770 | mklines.Check() | 820 | mklines.Check() | |
771 | 821 | |||
772 | c.Check(s.Output(), equals, "WARN: x11/lablgtk1/Makefile:2: Please use ${CC:Q} instead of ${CC}.\n") | 822 | c.Check(s.Output(), equals, ""+ | |
823 | "WARN: x11/lablgtk1/Makefile:2: Please use ${CC:Q} instead of ${CC}.\n"+ | |||
824 | "WARN: x11/lablgtk1/Makefile:2: Please use ${CC:Q} instead of ${CC}.\n") | |||
773 | } | 825 | } | |
774 | 826 | |||
775 | func (s *Suite) Test_MkLine_shell_varuse_in_backt_dquot(c *check.C) { | 827 | func (s *Suite) Test_MkLine_shell_varuse_in_backt_dquot(c *check.C) { | |
776 | s.UseCommandLine(c, "-Wall") | 828 | s.UseCommandLine(c, "-Wall") | |
777 | G.globalData.InitVartypes() | 829 | G.globalData.InitVartypes() | |
778 | mklines := s.NewMkLines("x11/motif/Makefile", | 830 | mklines := s.NewMkLines("x11/motif/Makefile", | |
779 | "# $"+"NetBSD$", | 831 | "# $"+"NetBSD$", | |
780 | "post-patch:", | 832 | "post-patch:", | |
781 | "\tfiles=`${GREP} -l \".fB$${name}.fP(3)\" *.3`") | 833 | "\tfiles=`${GREP} -l \".fB$${name}.fP(3)\" *.3`") | |
782 | 834 | |||
783 | mklines.Check() | 835 | mklines.Check() | |
784 | 836 | |||
785 | c.Check(s.Output(), equals, "WARN: x11/motif/Makefile:3: Unknown shell command \"${GREP}\".\n") // No parse errors. | 837 | c.Check(s.Output(), equals, "WARN: x11/motif/Makefile:3: Unknown shell command \"${GREP}\".\n") // No parse errors. | |
786 | } | 838 | } | |
787 | 839 | |||
788 | // See PR 46570, Ctrl+F "3. In lang/perl5". | 840 | // See PR 46570, Ctrl+F "3. In lang/perl5". | |
789 | func (s *Suite) Test_MkLine_getVariableType(c *check.C) { | 841 | func (s *Suite) Test_MkLine_getVariableType(c *check.C) { | |
790 | mkline := NewMkLine(dummyLine) | 842 | mkline := NewMkLine(dummyLine) | |
791 | 843 | |||
792 | c.Check(mkline.getVariableType("_PERL5_PACKLIST_AWK_STRIP_DESTDIR"), check.IsNil) | 844 | c.Check(mkline.getVariableType("_PERL5_PACKLIST_AWK_STRIP_DESTDIR"), check.IsNil) | |
793 | c.Check(mkline.getVariableType("SOME_DIR").guessed, equals, true) | 845 | c.Check(mkline.getVariableType("SOME_DIR").guessed, equals, true) | |
794 | c.Check(mkline.getVariableType("SOMEDIR").guessed, equals, true) | 846 | c.Check(mkline.getVariableType("SOMEDIR").guessed, equals, true) | |
795 | } | 847 | } | |
796 | 848 | |||
797 | // See PR 46570, Ctrl+F "4. Shell quoting". | 849 | // See PR 46570, Ctrl+F "4. Shell quoting". | |
798 | // Pkglint is correct, since this definition for CPPFLAGS should be | 850 | // Pkglint is correct, since the shell sees this definition for | |
799 | // seen by the shell as three words, not one word. | 851 | // CPPFLAGS as three words, not one word. | |
800 | func (s *Suite) Test_MkLine_Cflags(c *check.C) { | 852 | func (s *Suite) Test_MkLine_CheckVartype_CFLAGS(c *check.C) { | |
801 | G.globalData.InitVartypes() | 853 | G.globalData.InitVartypes() | |
802 | mklines := s.NewMkLines("Makefile", | 854 | mklines := s.NewMkLines("Makefile", | |
803 | "# $"+"NetBSD$", | 855 | "# $"+"NetBSD$", | |
804 | "CPPFLAGS.SunOS+=\t-DPIPECOMMAND=\\\"/usr/sbin/sendmail -bs %s\\\"") | 856 | "CPPFLAGS.SunOS+=\t-DPIPECOMMAND=\\\"/usr/sbin/sendmail -bs %s\\\"") | |
805 | 857 | |||
806 | mklines.Check() | 858 | mklines.Check() | |
807 | 859 | |||
808 | c.Check(s.Output(), equals, ""+ | 860 | c.Check(s.Output(), equals, ""+ | |
809 | "WARN: Makefile:2: Unknown compiler flag \"-bs\".\n"+ | 861 | "WARN: Makefile:2: Unknown compiler flag \"-bs\".\n"+ | |
810 | "WARN: Makefile:2: Compiler flag \"%s\\\\\\\"\" should start with a hyphen.\n") | 862 | "WARN: Makefile:2: Compiler flag \"%s\\\\\\\"\" should start with a hyphen.\n") | |
811 | } | 863 | } |
@@ -293,26 +293,31 @@ func (va *VaralignBlock) Finish() { | @@ -293,26 +293,31 @@ func (va *VaralignBlock) Finish() { | |||
293 | func (va *VaralignBlock) fixalign(mkline *MkLine, prefix, oldalign string) { | 293 | func (va *VaralignBlock) fixalign(mkline *MkLine, prefix, oldalign string) { | |
294 | if mkline.Value() == "" && mkline.Comment() == "" { | 294 | if mkline.Value() == "" && mkline.Comment() == "" { | |
295 | return | 295 | return | |
296 | } | 296 | } | |
297 | 297 | |||
298 | hasSpace := contains(oldalign, " ") | 298 | hasSpace := contains(oldalign, " ") | |
299 | if hasSpace && | 299 | if hasSpace && | |
300 | va.maxTabWidth != 0 && | 300 | va.maxTabWidth != 0 && | |
301 | va.maxSpaceWidth > va.maxTabWidth && | 301 | va.maxSpaceWidth > va.maxTabWidth && | |
302 | tabLength(prefix+oldalign) == va.maxSpaceWidth { | 302 | tabLength(prefix+oldalign) == va.maxSpaceWidth { | |
303 | return | 303 | return | |
304 | } | 304 | } | |
305 | 305 | |||
306 | // Don’t warn about procedure parameters | |||
307 | if mkline.Op() == opAssignEval && matches(mkline.Varname(), `^[a-z]`) { | |||
308 | return | |||
309 | } | |||
310 | ||||
306 | goodWidth := va.maxTabWidth | 311 | goodWidth := va.maxTabWidth | |
307 | if goodWidth == 0 && va.differ { | 312 | if goodWidth == 0 && va.differ { | |
308 | goodWidth = va.maxSpaceWidth | 313 | goodWidth = va.maxSpaceWidth | |
309 | } | 314 | } | |
310 | minWidth := va.maxPrefixWidth + 1 | 315 | minWidth := va.maxPrefixWidth + 1 | |
311 | if goodWidth == 0 || minWidth < goodWidth && va.differ { | 316 | if goodWidth == 0 || minWidth < goodWidth && va.differ { | |
312 | goodWidth = minWidth | 317 | goodWidth = minWidth | |
313 | } | 318 | } | |
314 | goodWidth = (goodWidth + 7) & -8 | 319 | goodWidth = (goodWidth + 7) & -8 | |
315 | 320 | |||
316 | newalign := "" | 321 | newalign := "" | |
317 | for tabLength(prefix+newalign) < goodWidth { | 322 | for tabLength(prefix+newalign) < goodWidth { | |
318 | newalign += "\t" | 323 | newalign += "\t" |
@@ -1,22 +1,22 @@ | @@ -1,22 +1,22 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | const mkrcsid = "# $" + "NetBSD$" | 7 | const mkrcsid = "# $" + "NetBSD$" | |
8 | 8 | |||
9 | func (s *Suite) TestMkLines_AutofixConditionalIndentation(c *check.C) { | 9 | func (s *Suite) Test_MkLines_Check__autofix_conditional_indentation(c *check.C) { | |
10 | s.UseCommandLine(c, "--autofix", "-Wspace") | 10 | s.UseCommandLine(c, "--autofix", "-Wspace") | |
11 | tmpfile := s.CreateTmpFile(c, "fname.mk", "") | 11 | tmpfile := s.CreateTmpFile(c, "fname.mk", "") | |
12 | mklines := s.NewMkLines(tmpfile, | 12 | mklines := s.NewMkLines(tmpfile, | |
13 | "# $"+"NetBSD$", | 13 | "# $"+"NetBSD$", | |
14 | ".if defined(A)", | 14 | ".if defined(A)", | |
15 | ".for a in ${A}", | 15 | ".for a in ${A}", | |
16 | ".if defined(C)", | 16 | ".if defined(C)", | |
17 | ".endif", | 17 | ".endif", | |
18 | ".endfor", | 18 | ".endfor", | |
19 | ".endif") | 19 | ".endif") | |
20 | 20 | |||
21 | mklines.Check() | 21 | mklines.Check() | |
22 | 22 | |||
@@ -26,65 +26,65 @@ func (s *Suite) TestMkLines_AutofixCondi | @@ -26,65 +26,65 @@ func (s *Suite) TestMkLines_AutofixCondi | |||
26 | "AUTOFIX: ~/fname.mk:5: Replacing \".\" with \". \".\n"+ | 26 | "AUTOFIX: ~/fname.mk:5: Replacing \".\" with \". \".\n"+ | |
27 | "AUTOFIX: ~/fname.mk:6: Replacing \".\" with \". \".\n"+ | 27 | "AUTOFIX: ~/fname.mk:6: Replacing \".\" with \". \".\n"+ | |
28 | "AUTOFIX: ~/fname.mk: Has been auto-fixed. Please re-run pkglint.\n") | 28 | "AUTOFIX: ~/fname.mk: Has been auto-fixed. Please re-run pkglint.\n") | |
29 | c.Check(s.LoadTmpFile(c, "fname.mk"), equals, ""+ | 29 | c.Check(s.LoadTmpFile(c, "fname.mk"), equals, ""+ | |
30 | "# $"+"NetBSD$\n"+ | 30 | "# $"+"NetBSD$\n"+ | |
31 | ".if defined(A)\n"+ | 31 | ".if defined(A)\n"+ | |
32 | ". for a in ${A}\n"+ | 32 | ". for a in ${A}\n"+ | |
33 | ". if defined(C)\n"+ | 33 | ". if defined(C)\n"+ | |
34 | ". endif\n"+ | 34 | ". endif\n"+ | |
35 | ". endfor\n"+ | 35 | ". endfor\n"+ | |
36 | ".endif\n") | 36 | ".endif\n") | |
37 | } | 37 | } | |
38 | 38 | |||
39 | func (s *Suite) TestMkLines_UnusualTarget(c *check.C) { | 39 | func (s *Suite) Test_MkLines_Check__unusual_target(c *check.C) { | |
40 | mklines := s.NewMkLines("Makefile", | 40 | mklines := s.NewMkLines("Makefile", | |
41 | "# $"+"NetBSD$", | 41 | "# $"+"NetBSD$", | |
42 | "", | 42 | "", | |
43 | "echo: echo.c", | 43 | "echo: echo.c", | |
44 | "\tcc -o ${.TARGET} ${.IMPSRC}") | 44 | "\tcc -o ${.TARGET} ${.IMPSRC}") | |
45 | 45 | |||
46 | mklines.Check() | 46 | mklines.Check() | |
47 | 47 | |||
48 | c.Check(s.Output(), equals, "WARN: Makefile:3: Unusual target \"echo\".\n") | 48 | c.Check(s.Output(), equals, "WARN: Makefile:3: Unusual target \"echo\".\n") | |
49 | } | 49 | } | |
50 | 50 | |||
51 | func (s *Suite) TestMkLines_checklineInclude_Makefile(c *check.C) { | 51 | func (s *Suite) Test_MkLine_checklineInclude_Makefile(c *check.C) { | |
52 | mklines := s.NewMkLines("Makefile", | 52 | mkline := NewMkLine(NewLine("Makefile", 2, ".include \"../../other/package/Makefile\"", nil)) | |
53 | "# $"+"NetBSD$", | |||
54 | ".include \"../../other/package/Makefile\"") | |||
55 | 53 | |||
56 | mklines.Check() | 54 | mkline.checkInclude() | |
57 | 55 | |||
58 | c.Check(s.Output(), equals, ""+ | 56 | c.Check(s.Output(), equals, ""+ | |
59 | "ERROR: Makefile:2: \"/other/package/Makefile\" does not exist.\n"+ | 57 | "ERROR: Makefile:2: \"/other/package/Makefile\" does not exist.\n"+ | |
60 | "ERROR: Makefile:2: Other Makefiles must not be included directly.\n") | 58 | "ERROR: Makefile:2: Other Makefiles must not be included directly.\n") | |
61 | } | 59 | } | |
62 | 60 | |||
63 | func (s *Suite) TestMkLines_Quoting(c *check.C) { | 61 | func (s *Suite) Test_MkLines_quoting_LDFLAGS_for_GNU_configure(c *check.C) { | |
64 | s.UseCommandLine(c, "-Wall") | 62 | s.UseCommandLine(c, "-Wall") | |
65 | G.globalData.InitVartypes() | 63 | G.globalData.InitVartypes() | |
66 | G.Pkg = NewPackage("category/pkgbase") | 64 | G.Pkg = NewPackage("category/pkgbase") | |
67 | mklines := s.NewMkLines("Makefile", | 65 | mklines := s.NewMkLines("Makefile", | |
68 | "# $"+"NetBSD$", | 66 | "# $"+"NetBSD$", | |
69 | "GNU_CONFIGURE=\tyes", | 67 | "GNU_CONFIGURE=\tyes", | |
70 | "CONFIGURE_ENV+=\tX_LIBS=${X11_LDFLAGS:Q}") | 68 | "CONFIGURE_ENV+=\tX_LIBS=${X11_LDFLAGS:Q}") | |
71 | 69 | |||
72 | mklines.Check() | 70 | mklines.Check() | |
73 | 71 | |||
74 | c.Check(s.Output(), equals, "WARN: Makefile:3: Please use ${X11_LDFLAGS:M*:Q} instead of ${X11_LDFLAGS:Q}.\n") | 72 | c.Check(s.Output(), equals, ""+ | |
73 | "WARN: Makefile:3: Please use ${X11_LDFLAGS:M*:Q} instead of ${X11_LDFLAGS:Q}.\n"+ | |||
74 | "WARN: Makefile:3: Please use ${X11_LDFLAGS:M*:Q} instead of ${X11_LDFLAGS:Q}.\n") | |||
75 | } | 75 | } | |
76 | 76 | |||
77 | func (s *Suite) Test_MkLines_Varalign_Advanced(c *check.C) { | 77 | func (s *Suite) Test_MkLines__variable_alignment_advanced(c *check.C) { | |
78 | s.UseCommandLine(c, "-Wspace") | 78 | s.UseCommandLine(c, "-Wspace") | |
79 | fname := s.CreateTmpFileLines(c, "Makefile", | 79 | fname := s.CreateTmpFileLines(c, "Makefile", | |
80 | "# $"+"NetBSD$", | 80 | "# $"+"NetBSD$", | |
81 | "", | 81 | "", | |
82 | "VAR= \\", // In continuation lines, indenting with spaces is ok | 82 | "VAR= \\", // In continuation lines, indenting with spaces is ok | |
83 | "\tvalue", | 83 | "\tvalue", | |
84 | "", | 84 | "", | |
85 | "VAR= indented with one space", // Exactly one space is ok in general | 85 | "VAR= indented with one space", // Exactly one space is ok in general | |
86 | "VAR= indented with two spaces", // Two spaces are uncommon | 86 | "VAR= indented with two spaces", // Two spaces are uncommon | |
87 | "", | 87 | "", | |
88 | "BLOCK=\tindented with tab", | 88 | "BLOCK=\tindented with tab", | |
89 | "BLOCK_LONGVAR= indented with space", // This is ok, to prevent the block from being indented further | 89 | "BLOCK_LONGVAR= indented with space", // This is ok, to prevent the block from being indented further | |
90 | "", | 90 | "", | |
@@ -138,176 +138,251 @@ func (s *Suite) Test_MkLines_Varalign_Ad | @@ -138,176 +138,251 @@ func (s *Suite) Test_MkLines_Varalign_Ad | |||
138 | "\n"+ | 138 | "\n"+ | |
139 | "BLOCK=\t\tshort\n"+ | 139 | "BLOCK=\t\tshort\n"+ | |
140 | "BLOCK_LONGVAR=\tlong\n"+ | 140 | "BLOCK_LONGVAR=\tlong\n"+ | |
141 | "\n"+ | 141 | "\n"+ | |
142 | "GRP_A=\t\tavalue\n"+ | 142 | "GRP_A=\t\tavalue\n"+ | |
143 | "GRP_AA=\t\tvalue\n"+ | 143 | "GRP_AA=\t\tvalue\n"+ | |
144 | "GRP_AAA=\tvalue\n"+ | 144 | "GRP_AAA=\tvalue\n"+ | |
145 | "GRP_AAAA=\tvalue\n"+ | 145 | "GRP_AAAA=\tvalue\n"+ | |
146 | "\n"+ | 146 | "\n"+ | |
147 | "VAR=\t${VAR}${BLOCK}${BLOCK_LONGVAR} # suppress warnings about unused variables\n"+ | 147 | "VAR=\t${VAR}${BLOCK}${BLOCK_LONGVAR} # suppress warnings about unused variables\n"+ | |
148 | "VAR=\t${GRP_A}${GRP_AA}${GRP_AAA}${GRP_AAAA}\n") | 148 | "VAR=\t${GRP_A}${GRP_AA}${GRP_AAA}${GRP_AAAA}\n") | |
149 | } | 149 | } | |
150 | 150 | |||
151 | func (s *Suite) Test_MkLines_Varalign_Misc(c *check.C) { | 151 | func (s *Suite) Test_MkLines__variable_alignment_space_and_tab(c *check.C) { | |
152 | s.UseCommandLine(c, "-Wspace") | 152 | s.UseCommandLine(c, "-Wspace") | |
153 | mklines := s.NewMkLines("Makefile", | 153 | mklines := s.NewMkLines("Makefile", | |
154 | "# $"+"NetBSD$", | 154 | "# $"+"NetBSD$", | |
155 | "", | 155 | "", | |
156 | "VAR= space", | 156 | "VAR= space", | |
157 | "VAR=\ttab ${VAR}") | 157 | "VAR=\ttab ${VAR}") | |
158 | 158 | |||
159 | mklines.Check() | 159 | mklines.Check() | |
160 | 160 | |||
161 | c.Check(s.Output(), equals, "NOTE: Makefile:3: Variable values should be aligned with tabs, not spaces.\n") | 161 | c.Check(s.Output(), equals, "NOTE: Makefile:3: Variable values should be aligned with tabs, not spaces.\n") | |
162 | } | 162 | } | |
163 | 163 | |||
164 | func (s *Suite) Test_MkLines_ForLoop_Multivar(c *check.C) { | 164 | func (s *Suite) Test_MkLines__for_loop_multiple_variables(c *check.C) { | |
165 | s.UseCommandLine(c, "-Wall") | 165 | s.UseCommandLine(c, "-Wall") | |
166 | s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", Predefined: true}) | 166 | s.RegisterTool(&Tool{Name: "echo", Varname: "ECHO", Predefined: true}) | |
167 | s.RegisterTool(&Tool{Name: "find", Varname: "FIND", Predefined: true}) | 167 | s.RegisterTool(&Tool{Name: "find", Varname: "FIND", Predefined: true}) | |
168 | s.RegisterTool(&Tool{Name: "pax", Varname: "PAX", Predefined: true}) | 168 | s.RegisterTool(&Tool{Name: "pax", Varname: "PAX", Predefined: true}) | |
169 | mklines := s.NewMkLines("audio/squeezeboxserver/Makefile", | 169 | mklines := s.NewMkLines("audio/squeezeboxserver/Makefile", | |
170 | "# $"+"NetBSD$", | 170 | "# $"+"NetBSD$", | |
171 | "", | 171 | "", | |
172 | ".for _list_ _dir_ in ${SBS_COPY}", | 172 | ".for _list_ _dir_ in ${SBS_COPY}", | |
173 | "\tcd ${WRKSRC} && ${FIND} ${${_list_}} -type f ! -name '*.orig' 2>/dev/null "+ | 173 | "\tcd ${WRKSRC} && ${FIND} ${${_list_}} -type f ! -name '*.orig' 2>/dev/null "+ | |
174 | "| pax -rw -pm ${DESTDIR}${PREFIX}/${${_dir_}}", | 174 | "| pax -rw -pm ${DESTDIR}${PREFIX}/${${_dir_}}", | |
175 | ".endfor") | 175 | ".endfor") | |
176 | 176 | |||
177 | mklines.Check() | 177 | mklines.Check() | |
178 | 178 | |||
179 | c.Check(s.Output(), equals, ""+ | 179 | c.Check(s.Output(), equals, ""+ | |
180 | "WARN: audio/squeezeboxserver/Makefile:3: Variable names starting with an underscore (_list_) are reserved for internal pkgsrc use.\n"+ | 180 | "WARN: audio/squeezeboxserver/Makefile:3: Variable names starting with an underscore (_list_) are reserved for internal pkgsrc use.\n"+ | |
181 | "WARN: audio/squeezeboxserver/Makefile:3: Variable names starting with an underscore (_dir_) are reserved for internal pkgsrc use.\n"+ | 181 | "WARN: audio/squeezeboxserver/Makefile:3: Variable names starting with an underscore (_dir_) are reserved for internal pkgsrc use.\n"+ | |
182 | "WARN: audio/squeezeboxserver/Makefile:4: The exitcode of the left-hand-side command of the pipe operator is ignored.\n") | 182 | "WARN: audio/squeezeboxserver/Makefile:4: The exitcode of the left-hand-side command of the pipe operator is ignored.\n") | |
183 | } | 183 | } | |
184 | 184 | |||
185 | func (s *Suite) Test_MkLines_Cond_Compare_YesNo(c *check.C) { | 185 | func (s *Suite) Test_MkLines__comparing_YesNo_variable_to_string(c *check.C) { | |
186 | s.UseCommandLine(c, "-Wall") | 186 | s.UseCommandLine(c, "-Wall") | |
187 | G.globalData.InitVartypes() | 187 | G.globalData.InitVartypes() | |
188 | mklines := s.NewMkLines("databases/gdbm_compat/builtin.mk", | 188 | mklines := s.NewMkLines("databases/gdbm_compat/builtin.mk", | |
189 | "# $"+"NetBSD$", | 189 | "# $"+"NetBSD$", | |
190 | ".if ${USE_BUILTIN.gdbm} == \"no\"", | 190 | ".if ${USE_BUILTIN.gdbm} == \"no\"", | |
191 | ".endif") | 191 | ".endif") | |
192 | 192 | |||
193 | mklines.Check() | 193 | mklines.Check() | |
194 | 194 | |||
195 | c.Check(s.Output(), equals, "WARN: databases/gdbm_compat/builtin.mk:2: "+ | 195 | c.Check(s.Output(), equals, "WARN: databases/gdbm_compat/builtin.mk:2: "+ | |
196 | "USE_BUILTIN.gdbm should be matched against \"[yY][eE][sS]\" or \"[nN][oO]\", not compared with \"no\".\n") | 196 | "USE_BUILTIN.gdbm should be matched against \"[yY][eE][sS]\" or \"[nN][oO]\", not compared with \"no\".\n") | |
197 | } | 197 | } | |
198 | 198 | |||
199 | func (s *Suite) Test_MkLines_Varuse_sh_Modifier(c *check.C) { | 199 | func (s *Suite) Test_MkLines__varuse_sh_modifier(c *check.C) { | |
200 | s.UseCommandLine(c, "-Wall") | 200 | s.UseCommandLine(c, "-Wall") | |
201 | G.globalData.InitVartypes() | 201 | G.globalData.InitVartypes() | |
202 | mklines := s.NewMkLines("lang/qore/module.mk", | 202 | mklines := s.NewMkLines("lang/qore/module.mk", | |
203 | "# $"+"NetBSD$", | 203 | "# $"+"NetBSD$", | |
204 | "qore-version=\tqore --short-version | ${SED} -e s/-.*//", | 204 | "qore-version=\tqore --short-version | ${SED} -e s/-.*//", | |
205 | "PLIST_SUBST+=\tQORE_VERSION=\"${qore-version:sh}\"") | 205 | "PLIST_SUBST+=\tQORE_VERSION=\"${qore-version:sh}\"") | |
206 | 206 | |||
207 | vars2 := mklines.mklines[1].determineUsedVariables() | 207 | vars2 := mklines.mklines[1].determineUsedVariables() | |
208 | 208 | |||
209 | c.Check(vars2, deepEquals, []string{"SED"}) | 209 | c.Check(vars2, deepEquals, []string{"SED"}) | |
210 | 210 | |||
211 | vars3 := mklines.mklines[2].determineUsedVariables() | 211 | vars3 := mklines.mklines[2].determineUsedVariables() | |
212 | 212 | |||
213 | c.Check(vars3, deepEquals, []string{"qore-version"}) | 213 | c.Check(vars3, deepEquals, []string{"qore-version"}) | |
214 | 214 | |||
215 | mklines.Check() | 215 | mklines.Check() | |
216 | 216 | |||
217 | c.Check(s.Output(), equals, "") // No warnings about defined but not used or vice versa | 217 | c.Check(s.Output(), equals, "") // No warnings about defined but not used or vice versa | |
218 | } | 218 | } | |
219 | 219 | |||
220 | func (s *Suite) Test_MkLines_Varuse_parameterized(c *check.C) { | 220 | func (s *Suite) Test_MkLines__varuse_parameterized(c *check.C) { | |
221 | s.UseCommandLine(c, "-Wall") | 221 | s.UseCommandLine(c, "-Wall") | |
222 | G.globalData.InitVartypes() | 222 | G.globalData.InitVartypes() | |
223 | mklines := s.NewMkLines("converters/wv2/Makefile", | 223 | mklines := s.NewMkLines("converters/wv2/Makefile", | |
224 | "# $"+"NetBSD$", | 224 | "# $"+"NetBSD$", | |
225 | "CONFIGURE_ARGS+=\t\t${CONFIGURE_ARGS.${ICONV_TYPE}-iconv}", | 225 | "CONFIGURE_ARGS+=\t\t${CONFIGURE_ARGS.${ICONV_TYPE}-iconv}", | |
226 | "CONFIGURE_ARGS.gnu-iconv=\t--with-libiconv=${BUILDLINK_PREFIX.iconv}") | 226 | "CONFIGURE_ARGS.gnu-iconv=\t--with-libiconv=${BUILDLINK_PREFIX.iconv}") | |
227 | 227 | |||
228 | mklines.Check() | 228 | mklines.Check() | |
229 | 229 | |||
230 | c.Check(s.Output(), equals, "") // No warnings about defined but not used or vice versa | 230 | c.Check(s.Output(), equals, "") // No warnings about defined but not used or vice versa | |
231 | } | 231 | } | |
232 | 232 | |||
233 | func (s *Suite) Test_MkLines_LoopModifier(c *check.C) { | 233 | func (s *Suite) Test_MkLines__loop_modifier(c *check.C) { | |
234 | s.UseCommandLine(c, "-Wall") | 234 | s.UseCommandLine(c, "-Wall") | |
235 | G.globalData.InitVartypes() | 235 | G.globalData.InitVartypes() | |
236 | mklines := s.NewMkLines("chat/xchat/Makefile", | 236 | mklines := s.NewMkLines("chat/xchat/Makefile", | |
237 | "# $"+"NetBSD$", | 237 | "# $"+"NetBSD$", | |
238 | "GCONF_SCHEMAS=\tapps_xchat_url_handler.schemas", | 238 | "GCONF_SCHEMAS=\tapps_xchat_url_handler.schemas", | |
239 | "post-install:", | 239 | "post-install:", | |
240 | "\t${GCONF_SCHEMAS:@.s.@"+ | 240 | "\t${GCONF_SCHEMAS:@.s.@"+ | |
241 | "${INSTALL_DATA} ${WRKSRC}/src/common/dbus/${.s.} ${DESTDIR}${GCONF_SCHEMAS_DIR}/@}") | 241 | "${INSTALL_DATA} ${WRKSRC}/src/common/dbus/${.s.} ${DESTDIR}${GCONF_SCHEMAS_DIR}/@}") | |
242 | 242 | |||
243 | mklines.Check() | 243 | mklines.Check() | |
244 | 244 | |||
245 | c.Check(s.Output(), equals, ""+ // No warning about missing @ at the end | 245 | c.Check(s.Output(), equals, ""+ // No warning about missing @ at the end | |
246 | "WARN: chat/xchat/Makefile:4: Unknown shell command \"${GCONF_SCHEMAS:@.s.@"+ | 246 | "WARN: chat/xchat/Makefile:4: Unknown shell command \"${GCONF_SCHEMAS:@.s.@"+ | |
247 | "${INSTALL_DATA} ${WRKSRC}/src/common/dbus/${.s.} ${DESTDIR}${GCONF_SCHEMAS_DIR}/@}\".\n") | 247 | "${INSTALL_DATA} ${WRKSRC}/src/common/dbus/${.s.} ${DESTDIR}${GCONF_SCHEMAS_DIR}/@}\".\n") | |
248 | } | 248 | } | |
249 | 249 | |||
250 | func (s *Suite) Test_MkLines_Indentation_DependsOn(c *check.C) { | 250 | // PR 46570 | |
251 | func (s *Suite) Test_MkLines__PKG_SKIP_REASON_depending_on_OPSYS(c *check.C) { | |||
251 | G.globalData.InitVartypes() | 252 | G.globalData.InitVartypes() | |
252 | mklines := s.NewMkLines("Makefile", | 253 | mklines := s.NewMkLines("Makefile", | |
253 | "# $"+"NetBSD$", | 254 | "# $"+"NetBSD$", | |
254 | "PKG_SKIP_REASON+=\t\"Fails everywhere\"", | 255 | "PKG_SKIP_REASON+=\t\"Fails everywhere\"", | |
255 | ".if ${OPSYS} == \"Cygwin\"", | 256 | ".if ${OPSYS} == \"Cygwin\"", | |
256 | "PKG_SKIP_REASON+=\t\"Fails on Cygwin\"", | 257 | "PKG_SKIP_REASON+=\t\"Fails on Cygwin\"", | |
257 | ".endif") | 258 | ".endif") | |
258 | 259 | |||
259 | mklines.Check() | 260 | mklines.Check() | |
260 | 261 | |||
261 | c.Check(s.Output(), equals, "NOTE: Makefile:4: Consider defining NOT_FOR_PLATFORM instead of setting PKG_SKIP_REASON depending on ${OPSYS}.\n") | 262 | c.Check(s.Output(), equals, "NOTE: Makefile:4: Consider defining NOT_FOR_PLATFORM instead of setting PKG_SKIP_REASON depending on ${OPSYS}.\n") | |
262 | } | 263 | } | |
263 | 264 | |||
264 | // PR 46570, item "15. net/uucp/Makefile has a make loop" | 265 | // PR 46570, item "15. net/uucp/Makefile has a make loop" | |
265 | func (s *Suite) Test_MkLines_indirect_variables(c *check.C) { | 266 | func (s *Suite) Test_MkLines__indirect_variables(c *check.C) { | |
266 | s.UseCommandLine(c, "-Wall") | 267 | s.UseCommandLine(c, "-Wall") | |
267 | mklines := s.NewMkLines("net/uucp/Makefile", | 268 | mklines := s.NewMkLines("net/uucp/Makefile", | |
268 | "# $"+"NetBSD$", | 269 | "# $"+"NetBSD$", | |
269 | "", | 270 | "", | |
270 | "post-configure:", | 271 | "post-configure:", | |
271 | ".for var in MAIL_PROGRAM CMDPATH", | 272 | ".for var in MAIL_PROGRAM CMDPATH", | |
272 | "\t"+`${RUN} ${ECHO} "#define ${var} \""${UUCP_${var}}"\"`, | 273 | "\t"+`${RUN} ${ECHO} "#define ${var} \""${UUCP_${var}}"\"`, | |
273 | ".endfor") | 274 | ".endfor") | |
274 | 275 | |||
275 | mklines.Check() | 276 | mklines.Check() | |
276 | 277 | |||
277 | // No warning about UUCP_${var} being used but not defined. | 278 | // No warning about UUCP_${var} being used but not defined. | |
278 | c.Check(s.Output(), equals, ""+ | 279 | c.Check(s.Output(), equals, ""+ | |
279 | "WARN: net/uucp/Makefile:5: Unknown shell command \"${ECHO}\".\n") | 280 | "WARN: net/uucp/Makefile:5: Unknown shell command \"${ECHO}\".\n") | |
280 | } | 281 | } | |
281 | 282 | |||
282 | func (s *Suite) Test_MkLines_Check_list_variable_as_part_of_word(c *check.C) { | 283 | func (s *Suite) Test_MkLines_Check__list_variable_as_part_of_word(c *check.C) { | |
283 | s.UseCommandLine(c, "-Wall") | 284 | s.UseCommandLine(c, "-Wall") | |
284 | mklines := s.NewMkLines("converters/chef/Makefile", | 285 | mklines := s.NewMkLines("converters/chef/Makefile", | |
285 | mkrcsid, | 286 | mkrcsid, | |
286 | "\tcd ${WRKSRC} && tr '\\r' '\\n' < ${DISTDIR}/${DIST_SUBDIR}/${DISTFILES} > chef.l") | 287 | "\tcd ${WRKSRC} && tr '\\r' '\\n' < ${DISTDIR}/${DIST_SUBDIR}/${DISTFILES} > chef.l") | |
287 | 288 | |||
288 | mklines.Check() | 289 | mklines.Check() | |
289 | 290 | |||
290 | c.Check(s.Output(), equals, ""+ | 291 | c.Check(s.Output(), equals, ""+ | |
291 | "WARN: converters/chef/Makefile:2: Unknown shell command \"tr\".\n"+ | 292 | "WARN: converters/chef/Makefile:2: Unknown shell command \"tr\".\n"+ | |
292 | "WARN: converters/chef/Makefile:2: The list variable DISTFILES should not be embedded in a word.\n") | 293 | "WARN: converters/chef/Makefile:2: The list variable DISTFILES should not be embedded in a word.\n") | |
293 | } | 294 | } | |
294 | 295 | |||
295 | func (s *Suite) Test_MkLines_Check_absolute_pathname_depending_on_OPSYS(c *check.C) { | 296 | func (s *Suite) Test_MkLines_Check__absolute_pathname_depending_on_OPSYS(c *check.C) { | |
296 | s.UseCommandLine(c, "-Wall") | 297 | s.UseCommandLine(c, "-Wall") | |
297 | G.globalData.InitVartypes() | 298 | G.globalData.InitVartypes() | |
298 | mklines := s.NewMkLines("games/heretic2-demo/Makefile", | 299 | mklines := s.NewMkLines("games/heretic2-demo/Makefile", | |
299 | mkrcsid, | 300 | mkrcsid, | |
300 | ".if ${OPSYS} == \"DragonFly\"", | 301 | ".if ${OPSYS} == \"DragonFly\"", | |
301 | "TOOLS_PLATFORM.gtar=\t/usr/bin/bsdtar", | 302 | "TOOLS_PLATFORM.gtar=\t/usr/bin/bsdtar", | |
302 | ".endif", | 303 | ".endif", | |
303 | "TOOLS_PLATFORM.gtar=\t/usr/bin/bsdtar") | 304 | "TOOLS_PLATFORM.gtar=\t/usr/bin/bsdtar") | |
304 | 305 | |||
305 | mklines.Check() | 306 | mklines.Check() | |
306 | 307 | |||
307 | // No warning about an unknown shell command in line 3, | 308 | // No warning about an unknown shell command in line 3, | |
308 | // since that line depends on OPSYS. | 309 | // since that line depends on OPSYS. | |
309 | c.Check(s.Output(), equals, ""+ | 310 | c.Check(s.Output(), equals, ""+ | |
310 | "WARN: games/heretic2-demo/Makefile:3: The variable TOOLS_PLATFORM.gtar may not be set by any package.\n"+ | 311 | "WARN: games/heretic2-demo/Makefile:3: The variable TOOLS_PLATFORM.gtar may not be set by any package.\n"+ | |
311 | "WARN: games/heretic2-demo/Makefile:5: The variable TOOLS_PLATFORM.gtar may not be set by any package.\n"+ | 312 | "WARN: games/heretic2-demo/Makefile:5: The variable TOOLS_PLATFORM.gtar may not be set by any package.\n"+ | |
312 | "WARN: games/heretic2-demo/Makefile:5: Unknown shell command \"/usr/bin/bsdtar\".\n") | 313 | "WARN: games/heretic2-demo/Makefile:5: Unknown shell command \"/usr/bin/bsdtar\".\n") | |
313 | } | 314 | } | |
315 | ||||
316 | func (s *Suite) Test_MkLines_checkForUsedComment(c *check.C) { | |||
317 | s.UseCommandLine(c, "--show-autofix") | |||
318 | s.NewMkLines("Makefile.common", | |||
319 | "# $"+"NetBSD$", | |||
320 | "", | |||
321 | "# used by sysutils/mc", | |||
322 | ).checkForUsedComment("sysutils/mc") | |||
323 | ||||
324 | c.Check(s.Output(), equals, "") | |||
325 | ||||
326 | s.NewMkLines("Makefile.common").checkForUsedComment("category/package") | |||
327 | ||||
328 | c.Check(s.Output(), equals, "") | |||
329 | ||||
330 | s.NewMkLines("Makefile.common", | |||
331 | "# $"+"NetBSD$", | |||
332 | ).checkForUsedComment("category/package") | |||
333 | ||||
334 | c.Check(s.Output(), equals, "") | |||
335 | ||||
336 | s.NewMkLines("Makefile.common", | |||
337 | "# $"+"NetBSD$", | |||
338 | "", | |||
339 | ).checkForUsedComment("category/package") | |||
340 | ||||
341 | c.Check(s.Output(), equals, "") | |||
342 | ||||
343 | s.NewMkLines("Makefile.common", | |||
344 | "# $"+"NetBSD$", | |||
345 | "", | |||
346 | "VARNAME=\tvalue", | |||
347 | ).checkForUsedComment("category/package") | |||
348 | ||||
349 | c.Check(s.Output(), equals, ""+ | |||
350 | "WARN: Makefile.common:2: Please add a line \"# used by category/package\" here.\n"+ | |||
351 | "AUTOFIX: Makefile.common:2: Inserting a line \"# used by category/package\" before this line.\n") | |||
352 | ||||
353 | s.NewMkLines("Makefile.common", | |||
354 | "# $"+"NetBSD$", | |||
355 | "#", | |||
356 | "#", | |||
357 | ).checkForUsedComment("category/package") | |||
358 | ||||
359 | c.Check(s.Output(), equals, ""+ | |||
360 | "WARN: Makefile.common:3: Please add a line \"# used by category/package\" here.\n"+ | |||
361 | "AUTOFIX: Makefile.common:3: Inserting a line \"# used by category/package\" before this line.\n") | |||
362 | } | |||
363 | ||||
364 | func (s *Suite) Test_MkLines_DetermineUsedVariables__simple(c *check.C) { | |||
365 | mklines := s.NewMkLines("fname", | |||
366 | "\t${VAR}") | |||
367 | mkline := mklines.mklines[0] | |||
368 | G.Mk = mklines | |||
369 | ||||
370 | mklines.DetermineUsedVariables() | |||
371 | ||||
372 | c.Check(len(mklines.varuse), equals, 1) | |||
373 | c.Check(mklines.varuse["VAR"], equals, mkline) | |||
374 | } | |||
375 | ||||
376 | func (s *Suite) Test_MkLines_DetermineUsedVariables__nested(c *check.C) { | |||
377 | mklines := s.NewMkLines("fname", | |||
378 | "\t${outer.${inner}}") | |||
379 | mkline := mklines.mklines[0] | |||
380 | G.Mk = mklines | |||
381 | ||||
382 | mklines.DetermineUsedVariables() | |||
383 | ||||
384 | c.Check(len(mklines.varuse), equals, 3) | |||
385 | c.Check(mklines.varuse["inner"], equals, mkline) | |||
386 | c.Check(mklines.varuse["outer."], equals, mkline) | |||
387 | c.Check(mklines.varuse["outer.*"], equals, mkline) | |||
388 | } |
@@ -1,176 +1,115 @@ | @@ -1,176 +1,115 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | "strings" | 4 | "strings" | |
5 | 5 | |||
6 | check "gopkg.in/check.v1" | 6 | check "gopkg.in/check.v1" | |
7 | ) | 7 | ) | |
8 | 8 | |||
9 | func (s *Suite) TestDetermineUsedVariables_simple(c *check.C) { | 9 | func (s *Suite) Test_resolveVariableRefs__circular_reference(c *check.C) { | |
10 | mklines := s.NewMkLines("fname", | |||
11 | "\t${VAR}") | |||
12 | mkline := mklines.mklines[0] | |||
13 | G.Mk = mklines | |||
14 | ||||
15 | mklines.DetermineUsedVariables() | |||
16 | ||||
17 | c.Check(len(mklines.varuse), equals, 1) | |||
18 | c.Check(mklines.varuse["VAR"], equals, mkline) | |||
19 | } | |||
20 | ||||
21 | func (s *Suite) TestDetermineUsedVariables_nested(c *check.C) { | |||
22 | mklines := s.NewMkLines("fname", | |||
23 | "\t${outer.${inner}}") | |||
24 | mkline := mklines.mklines[0] | |||
25 | G.Mk = mklines | |||
26 | ||||
27 | mklines.DetermineUsedVariables() | |||
28 | ||||
29 | c.Check(len(mklines.varuse), equals, 3) | |||
30 | c.Check(mklines.varuse["inner"], equals, mkline) | |||
31 | c.Check(mklines.varuse["outer."], equals, mkline) | |||
32 | c.Check(mklines.varuse["outer.*"], equals, mkline) | |||
33 | } | |||
34 | ||||
35 | func (s *Suite) TestResolveVariableRefs_CircularReference(c *check.C) { | |||
36 | mkline := NewMkLine(NewLine("fname", 1, "GCC_VERSION=${GCC_VERSION}", nil)) | 10 | mkline := NewMkLine(NewLine("fname", 1, "GCC_VERSION=${GCC_VERSION}", nil)) | |
37 | G.Pkg = NewPackage(".") | 11 | G.Pkg = NewPackage(".") | |
38 | G.Pkg.vardef["GCC_VERSION"] = mkline | 12 | G.Pkg.vardef["GCC_VERSION"] = mkline | |
39 | 13 | |||
40 | resolved := resolveVariableRefs("gcc-${GCC_VERSION}") | 14 | resolved := resolveVariableRefs("gcc-${GCC_VERSION}") | |
41 | 15 | |||
42 | c.Check(resolved, equals, "gcc-${GCC_VERSION}") | 16 | c.Check(resolved, equals, "gcc-${GCC_VERSION}") | |
43 | } | 17 | } | |
44 | 18 | |||
45 | func (s *Suite) TestResolveVariableRefs_Multilevel(c *check.C) { | 19 | func (s *Suite) Test_resolveVariableRefs__multilevel(c *check.C) { | |
46 | mkline1 := NewMkLine(NewLine("fname", 10, "_=${SECOND}", nil)) | 20 | mkline1 := NewMkLine(NewLine("fname", 10, "_=${SECOND}", nil)) | |
47 | mkline2 := NewMkLine(NewLine("fname", 11, "_=${THIRD}", nil)) | 21 | mkline2 := NewMkLine(NewLine("fname", 11, "_=${THIRD}", nil)) | |
48 | mkline3 := NewMkLine(NewLine("fname", 12, "_=got it", nil)) | 22 | mkline3 := NewMkLine(NewLine("fname", 12, "_=got it", nil)) | |
49 | G.Pkg = NewPackage(".") | 23 | G.Pkg = NewPackage(".") | |
50 | defineVar(mkline1, "FIRST") | 24 | defineVar(mkline1, "FIRST") | |
51 | defineVar(mkline2, "SECOND") | 25 | defineVar(mkline2, "SECOND") | |
52 | defineVar(mkline3, "THIRD") | 26 | defineVar(mkline3, "THIRD") | |
53 | 27 | |||
54 | resolved := resolveVariableRefs("you ${FIRST}") | 28 | resolved := resolveVariableRefs("you ${FIRST}") | |
55 | 29 | |||
56 | c.Check(resolved, equals, "you got it") | 30 | c.Check(resolved, equals, "you got it") | |
57 | } | 31 | } | |
58 | 32 | |||
59 | func (s *Suite) TestResolveVariableRefs_SpecialChars(c *check.C) { | 33 | func (s *Suite) Test_resolveVariableRefs__special_chars(c *check.C) { | |
60 | mkline := NewMkLine(NewLine("fname", 10, "_=x11", nil)) | 34 | mkline := NewMkLine(NewLine("fname", 10, "_=x11", nil)) | |
61 | G.Pkg = NewPackage("category/pkg") | 35 | G.Pkg = NewPackage("category/pkg") | |
62 | G.Pkg.vardef["GST_PLUGINS0.10_TYPE"] = mkline | 36 | G.Pkg.vardef["GST_PLUGINS0.10_TYPE"] = mkline | |
63 | 37 | |||
64 | resolved := resolveVariableRefs("gst-plugins0.10-${GST_PLUGINS0.10_TYPE}/distinfo") | 38 | resolved := resolveVariableRefs("gst-plugins0.10-${GST_PLUGINS0.10_TYPE}/distinfo") | |
65 | 39 | |||
66 | c.Check(resolved, equals, "gst-plugins0.10-x11/distinfo") | 40 | c.Check(resolved, equals, "gst-plugins0.10-x11/distinfo") | |
67 | } | 41 | } | |
68 | 42 | |||
69 | func (s *Suite) TestChecklineRcsid(c *check.C) { | 43 | func (s *Suite) Test_MatchVarassign(c *check.C) { | |
70 | lines := s.NewLines("fname", | 44 | checkVarassign := func(text string, ck check.Checker, varname, spaceAfterVarname, op, align, value, comment string) { | |
71 | "$"+"NetBSD: dummy $", | |||
72 | "$"+"NetBSD$", | |||
73 | "$"+"Id: dummy $", | |||
74 | "$"+"Id$", | |||
75 | "$"+"FreeBSD$") | |||
76 | ||||
77 | for _, line := range lines { | |||
78 | line.CheckRcsid(``, "") | |||
79 | } | |||
80 | ||||
81 | c.Check(s.Output(), equals, ""+ | |||
82 | "ERROR: fname:3: Expected \"$"+"NetBSD$\".\n"+ | |||
83 | "ERROR: fname:4: Expected \"$"+"NetBSD$\".\n"+ | |||
84 | "ERROR: fname:5: Expected \"$"+"NetBSD$\".\n") | |||
85 | } | |||
86 | ||||
87 | func (s *Suite) TestMatchVarassign(c *check.C) { | |||
88 | checkVarassign := func(text string, ck check.Checker, varname, op, align, value, comment string) { | |||
89 | type va struct { | 45 | type va struct { | |
90 | varname, op, align, value, comment string | 46 | varname, spaceAfterVarname, op, align, value, comment string | |
91 | } | 47 | } | |
92 | expected := va{varname, op, align, value, comment} | 48 | expected := va{varname, spaceAfterVarname, op, align, value, comment} | |
93 | am, avarname, aop, aalign, avalue, acomment := MatchVarassign(text) | 49 | am, avarname, aspaceAfterVarname, aop, aalign, avalue, acomment := MatchVarassign(text) | |
94 | if !am { | 50 | if !am { | |
95 | c.Errorf("Text %q doesn’t match variable assignment", text) | 51 | c.Errorf("Text %q doesn’t match variable assignment", text) | |
96 | return | 52 | return | |
97 | } | 53 | } | |
98 | actual := va{avarname, aop, aalign, avalue, acomment} | 54 | actual := va{avarname, aspaceAfterVarname, aop, aalign, avalue, acomment} | |
99 | c.Check(actual, ck, expected) | 55 | c.Check(actual, ck, expected) | |
100 | } | 56 | } | |
101 | checkNotVarassign := func(text string) { | 57 | checkNotVarassign := func(text string) { | |
102 | m, _, _, _, _, _ := MatchVarassign(text) | 58 | m, _, _, _, _, _, _ := MatchVarassign(text) | |
103 | if m { | 59 | if m { | |
104 | c.Errorf("Text %q matches variable assignment, but shouldn’t.", text) | 60 | c.Errorf("Text %q matches variable assignment, but shouldn’t.", text) | |
105 | } | 61 | } | |
106 | } | 62 | } | |
107 | 63 | |||
108 | checkVarassign("C++=c11", equals, "C+", "+=", "C++=", "c11", "") | 64 | checkVarassign("C++=c11", equals, "C+", "", "+=", "C++=", "c11", "") | |
109 | checkVarassign("V=v", equals, "V", "=", "V=", "v", "") | 65 | checkVarassign("V=v", equals, "V", "", "=", "V=", "v", "") | |
110 | checkVarassign("VAR=#comment", equals, "VAR", "=", "VAR=", "", "#comment") | 66 | checkVarassign("VAR=#comment", equals, "VAR", "", "=", "VAR=", "", "#comment") | |
111 | checkVarassign("VAR=\\#comment", equals, "VAR", "=", "VAR=", "#comment", "") | 67 | checkVarassign("VAR=\\#comment", equals, "VAR", "", "=", "VAR=", "#comment", "") | |
112 | checkVarassign("VAR=\\\\\\##comment", equals, "VAR", "=", "VAR=", "\\\\#", "#comment") | 68 | checkVarassign("VAR=\\\\\\##comment", equals, "VAR", "", "=", "VAR=", "\\\\#", "#comment") | |
113 | checkVarassign("VAR=\\", equals, "VAR", "=", "VAR=", "\\", "") | 69 | checkVarassign("VAR=\\", equals, "VAR", "", "=", "VAR=", "\\", "") | |
114 | checkVarassign("VAR += value", equals, "VAR", "+=", "VAR += ", "value", "") | 70 | checkVarassign("VAR += value", equals, "VAR", " ", "+=", "VAR += ", "value", "") | |
115 | checkVarassign(" VAR=value", equals, "VAR", "=", " VAR=", "value", "") | 71 | checkVarassign(" VAR=value", equals, "VAR", "", "=", " VAR=", "value", "") | |
116 | checkNotVarassign("\tVAR=value") | 72 | checkNotVarassign("\tVAR=value") | |
117 | checkNotVarassign("?=value") | 73 | checkNotVarassign("?=value") | |
118 | checkNotVarassign("<=value") | 74 | checkNotVarassign("<=value") | |
119 | } | 75 | } | |
120 | 76 | |||
121 | func (s *Suite) TestPackage_LoadPackageMakefile(c *check.C) { | 77 | func (s *Suite) Test_ChecklinesDescr(c *check.C) { | |
122 | makefile := s.CreateTmpFile(c, "category/package/Makefile", ""+ | |||
123 | "# $"+"NetBSD$\n"+ | |||
124 | "\n"+ | |||
125 | "PKGNAME=pkgname-1.67\n"+ | |||
126 | "DISTNAME=distfile_1_67\n"+ | |||
127 | ".include \"../../category/package/Makefile\"\n") | |||
128 | pkg := NewPackage("category/package") | |||
129 | G.CurrentDir = s.tmpdir + "/category/package" | |||
130 | G.CurPkgsrcdir = "../.." | |||
131 | G.Pkg = pkg | |||
132 | ||||
133 | pkg.loadPackageMakefile(makefile) | |||
134 | ||||
135 | c.Check(s.Output(), equals, "") | |||
136 | } | |||
137 | ||||
138 | func (s *Suite) TestChecklinesDescr(c *check.C) { | |||
139 | lines := s.NewLines("DESCR", | 78 | lines := s.NewLines("DESCR", | |
140 | strings.Repeat("X", 90), | 79 | strings.Repeat("X", 90), | |
141 | "", "", "", "", "", "", "", "", "10", | 80 | "", "", "", "", "", "", "", "", "10", | |
142 | "Try ${PREFIX}", | 81 | "Try ${PREFIX}", | |
143 | "", "", "", "", "", "", "", "", "20", | 82 | "", "", "", "", "", "", "", "", "20", | |
144 | "", "", "", "", "", "", "", "", "", "30") | 83 | "", "", "", "", "", "", "", "", "", "30") | |
145 | 84 | |||
146 | ChecklinesDescr(lines) | 85 | ChecklinesDescr(lines) | |
147 | 86 | |||
148 | c.Check(s.Output(), equals, ""+ | 87 | c.Check(s.Output(), equals, ""+ | |
149 | "WARN: DESCR:1: Line too long (should be no more than 80 characters).\n"+ | 88 | "WARN: DESCR:1: Line too long (should be no more than 80 characters).\n"+ | |
150 | "NOTE: DESCR:11: Variables are not expanded in the DESCR file.\n"+ | 89 | "NOTE: DESCR:11: Variables are not expanded in the DESCR file.\n"+ | |
151 | "WARN: DESCR:25: File too long (should be no more than 24 lines).\n") | 90 | "WARN: DESCR:25: File too long (should be no more than 24 lines).\n") | |
152 | } | 91 | } | |
153 | 92 | |||
154 | func (s *Suite) TestChecklinesMessage_short(c *check.C) { | 93 | func (s *Suite) Test_ChecklinesMessage__short(c *check.C) { | |
155 | lines := s.NewLines("MESSAGE", | 94 | lines := s.NewLines("MESSAGE", | |
156 | "one line") | 95 | "one line") | |
157 | 96 | |||
158 | ChecklinesMessage(lines) | 97 | ChecklinesMessage(lines) | |
159 | 98 | |||
160 | c.Check(s.Output(), equals, "WARN: MESSAGE:1: File too short.\n") | 99 | c.Check(s.Output(), equals, "WARN: MESSAGE:1: File too short.\n") | |
161 | } | 100 | } | |
162 | 101 | |||
163 | func (s *Suite) TestChecklinesMessage_malformed(c *check.C) { | 102 | func (s *Suite) Test_ChecklinesMessage__malformed(c *check.C) { | |
164 | lines := s.NewLines("MESSAGE", | 103 | lines := s.NewLines("MESSAGE", | |
165 | "1", | 104 | "1", | |
166 | "2", | 105 | "2", | |
167 | "3", | 106 | "3", | |
168 | "4", | 107 | "4", | |
169 | "5") | 108 | "5") | |
170 | 109 | |||
171 | ChecklinesMessage(lines) | 110 | ChecklinesMessage(lines) | |
172 | 111 | |||
173 | c.Check(s.Output(), equals, ""+ | 112 | c.Check(s.Output(), equals, ""+ | |
174 | "WARN: MESSAGE:1: Expected a line of exactly 75 \"=\" characters.\n"+ | 113 | "WARN: MESSAGE:1: Expected a line of exactly 75 \"=\" characters.\n"+ | |
175 | "ERROR: MESSAGE:2: Expected \"$"+"NetBSD$\".\n"+ | 114 | "ERROR: MESSAGE:2: Expected \"$"+"NetBSD$\".\n"+ | |
176 | "WARN: MESSAGE:5: Expected a line of exactly 75 \"=\" characters.\n") | 115 | "WARN: MESSAGE:5: Expected a line of exactly 75 \"=\" characters.\n") |
@@ -1,20 +1,20 @@ | @@ -1,20 +1,20 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestChecklinesPlist(c *check.C) { | 7 | func (s *Suite) Test_ChecklinesPlist(c *check.C) { | |
8 | s.UseCommandLine(c, "-Wall") | 8 | s.UseCommandLine(c, "-Wall") | |
9 | G.Pkg = NewPackage("category/pkgbase") | 9 | G.Pkg = NewPackage("category/pkgbase") | |
10 | lines := s.NewLines("PLIST", | 10 | lines := s.NewLines("PLIST", | |
11 | "bin/i386/6c", | 11 | "bin/i386/6c", | |
12 | "bin/program", | 12 | "bin/program", | |
13 | "etc/my.cnf", | 13 | "etc/my.cnf", | |
14 | "etc/rc.d/service", | 14 | "etc/rc.d/service", | |
15 | "@exec ${MKDIR} include/pkgbase", | 15 | "@exec ${MKDIR} include/pkgbase", | |
16 | "info/dir", | 16 | "info/dir", | |
17 | "lib/c.so", | 17 | "lib/c.so", | |
18 | "lib/libc.so.6", | 18 | "lib/libc.so.6", | |
19 | "lib/libc.la", | 19 | "lib/libc.la", | |
20 | "${PLIST.man}man/cat3/strcpy.4", | 20 | "${PLIST.man}man/cat3/strcpy.4", | |
@@ -36,78 +36,78 @@ func (s *Suite) TestChecklinesPlist(c *c | @@ -36,78 +36,78 @@ func (s *Suite) TestChecklinesPlist(c *c | |||
36 | "ERROR: PLIST:6: \"info/dir\" must not be listed. Use install-info to add/remove an entry.\n"+ | 36 | "ERROR: PLIST:6: \"info/dir\" must not be listed. Use install-info to add/remove an entry.\n"+ | |
37 | "WARN: PLIST:7: Library filename \"c.so\" should start with \"lib\".\n"+ | 37 | "WARN: PLIST:7: Library filename \"c.so\" should start with \"lib\".\n"+ | |
38 | "WARN: PLIST:8: Redundant library found. The libtool library is in line 9.\n"+ | 38 | "WARN: PLIST:8: Redundant library found. The libtool library is in line 9.\n"+ | |
39 | "WARN: PLIST:9: \"lib/libc.la\" should be sorted before \"lib/libc.so.6\".\n"+ | 39 | "WARN: PLIST:9: \"lib/libc.la\" should be sorted before \"lib/libc.so.6\".\n"+ | |
40 | "WARN: PLIST:10: Preformatted manual page without unformatted one.\n"+ | 40 | "WARN: PLIST:10: Preformatted manual page without unformatted one.\n"+ | |
41 | "WARN: PLIST:10: Preformatted manual pages should end in \".0\".\n"+ | 41 | "WARN: PLIST:10: Preformatted manual pages should end in \".0\".\n"+ | |
42 | "WARN: PLIST:11: IMAKE_MANNEWSUFFIX is not meant to appear in PLISTs.\n"+ | 42 | "WARN: PLIST:11: IMAKE_MANNEWSUFFIX is not meant to appear in PLISTs.\n"+ | |
43 | "WARN: PLIST:12: Please remove this line. It is no longer necessary.\n"+ | 43 | "WARN: PLIST:12: Please remove this line. It is no longer necessary.\n"+ | |
44 | "WARN: PLIST:13: Manual page missing for sbin/clockctl.\n"+ | 44 | "WARN: PLIST:13: Manual page missing for sbin/clockctl.\n"+ | |
45 | "ERROR: PLIST:14: The package Makefile must include \"../../graphics/gnome-icon-theme/buildlink3.mk\".\n"+ | 45 | "ERROR: PLIST:14: The package Makefile must include \"../../graphics/gnome-icon-theme/buildlink3.mk\".\n"+ | |
46 | "ERROR: PLIST:16: Duplicate filename \"share/tzinfo\", already appeared in line 15.\n") | 46 | "ERROR: PLIST:16: Duplicate filename \"share/tzinfo\", already appeared in line 15.\n") | |
47 | } | 47 | } | |
48 | 48 | |||
49 | func (s *Suite) TestChecklinesPlist_empty(c *check.C) { | 49 | func (s *Suite) Test_ChecklinesPlist__empty(c *check.C) { | |
50 | lines := s.NewLines("PLIST", | 50 | lines := s.NewLines("PLIST", | |
51 | "@comment $"+"NetBSD$") | 51 | "@comment $"+"NetBSD$") | |
52 | 52 | |||
53 | ChecklinesPlist(lines) | 53 | ChecklinesPlist(lines) | |
54 | 54 | |||
55 | c.Check(s.Output(), equals, "WARN: PLIST:1: PLIST files shouldn't be empty.\n") | 55 | c.Check(s.Output(), equals, "WARN: PLIST:1: PLIST files shouldn't be empty.\n") | |
56 | } | 56 | } | |
57 | 57 | |||
58 | func (s *Suite) TestChecklinesPlist_commonEnd(c *check.C) { | 58 | func (s *Suite) Test_ChecklinesPlist__commonEnd(c *check.C) { | |
59 | s.CreateTmpFile(c, "PLIST.common", ""+ | 59 | s.CreateTmpFile(c, "PLIST.common", ""+ | |
60 | "@comment $"+"NetBSD$\n"+ | 60 | "@comment $"+"NetBSD$\n"+ | |
61 | "bin/common\n") | 61 | "bin/common\n") | |
62 | fname := s.CreateTmpFile(c, "PLIST.common_end", ""+ | 62 | fname := s.CreateTmpFile(c, "PLIST.common_end", ""+ | |
63 | "@comment $"+"NetBSD$\n"+ | 63 | "@comment $"+"NetBSD$\n"+ | |
64 | "sbin/common_end\n") | 64 | "sbin/common_end\n") | |
65 | 65 | |||
66 | ChecklinesPlist(LoadExistingLines(fname, false)) | 66 | ChecklinesPlist(LoadExistingLines(fname, false)) | |
67 | 67 | |||
68 | c.Check(s.Output(), equals, "") | 68 | c.Check(s.Output(), equals, "") | |
69 | } | 69 | } | |
70 | 70 | |||
71 | func (s *Suite) TestChecklinesPlist_conditional(c *check.C) { | 71 | func (s *Suite) Test_ChecklinesPlist__conditional(c *check.C) { | |
72 | G.Pkg = NewPackage("category/pkgbase") | 72 | G.Pkg = NewPackage("category/pkgbase") | |
73 | G.Pkg.plistSubstCond["PLIST.bincmds"] = true | 73 | G.Pkg.plistSubstCond["PLIST.bincmds"] = true | |
74 | lines := s.NewLines("PLIST", | 74 | lines := s.NewLines("PLIST", | |
75 | "@comment $"+"NetBSD$", | 75 | "@comment $"+"NetBSD$", | |
76 | "${PLIST.bincmds}bin/subdir/command") | 76 | "${PLIST.bincmds}bin/subdir/command") | |
77 | 77 | |||
78 | ChecklinesPlist(lines) | 78 | ChecklinesPlist(lines) | |
79 | 79 | |||
80 | c.Check(s.Output(), equals, "WARN: PLIST:2: The bin/ directory should not have subdirectories.\n") | 80 | c.Check(s.Output(), equals, "WARN: PLIST:2: The bin/ directory should not have subdirectories.\n") | |
81 | } | 81 | } | |
82 | 82 | |||
83 | func (s *Suite) TestChecklinesPlist_sorting(c *check.C) { | 83 | func (s *Suite) Test_ChecklinesPlist__sorting(c *check.C) { | |
84 | s.UseCommandLine(c, "-Wplist-sort") | 84 | s.UseCommandLine(c, "-Wplist-sort") | |
85 | lines := s.NewLines("PLIST", | 85 | lines := s.NewLines("PLIST", | |
86 | "@comment $"+"NetBSD$", | 86 | "@comment $"+"NetBSD$", | |
87 | "@comment Do not remove", | 87 | "@comment Do not remove", | |
88 | "sbin/i386/6c", | 88 | "sbin/i386/6c", | |
89 | "sbin/program", | 89 | "sbin/program", | |
90 | "bin/otherprogram", | 90 | "bin/otherprogram", | |
91 | "${PLIST.conditional}bin/cat") | 91 | "${PLIST.conditional}bin/cat") | |
92 | 92 | |||
93 | ChecklinesPlist(lines) | 93 | ChecklinesPlist(lines) | |
94 | 94 | |||
95 | c.Check(s.Output(), equals, ""+ | 95 | c.Check(s.Output(), equals, ""+ | |
96 | "WARN: PLIST:5: \"bin/otherprogram\" should be sorted before \"sbin/program\".\n"+ | 96 | "WARN: PLIST:5: \"bin/otherprogram\" should be sorted before \"sbin/program\".\n"+ | |
97 | "WARN: PLIST:6: \"bin/cat\" should be sorted before \"bin/otherprogram\".\n") | 97 | "WARN: PLIST:6: \"bin/cat\" should be sorted before \"bin/otherprogram\".\n") | |
98 | } | 98 | } | |
99 | 99 | |||
100 | func (s *Suite) TestPlistChecker_sort(c *check.C) { | 100 | func (s *Suite) Test_PlistLineSorter_Sort(c *check.C) { | |
101 | s.UseCommandLine(c, "--autofix") | 101 | s.UseCommandLine(c, "--autofix") | |
102 | tmpfile := s.CreateTmpFile(c, "PLIST", "dummy\n") | 102 | tmpfile := s.CreateTmpFile(c, "PLIST", "dummy\n") | |
103 | ck := &PlistChecker{nil, nil, ""} | 103 | ck := &PlistChecker{nil, nil, ""} | |
104 | lines := s.NewLines(tmpfile, | 104 | lines := s.NewLines(tmpfile, | |
105 | "@comment $"+"NetBSD$", | 105 | "@comment $"+"NetBSD$", | |
106 | "@comment Do not remove", | 106 | "@comment Do not remove", | |
107 | "A", | 107 | "A", | |
108 | "b", | 108 | "b", | |
109 | "CCC", | 109 | "CCC", | |
110 | "lib/${UNKNOWN}.la", | 110 | "lib/${UNKNOWN}.la", | |
111 | "C", | 111 | "C", | |
112 | "ddd", | 112 | "ddd", | |
113 | "@exec echo \"after ddd\"", | 113 | "@exec echo \"after ddd\"", | |
@@ -134,36 +134,36 @@ func (s *Suite) TestPlistChecker_sort(c | @@ -134,36 +134,36 @@ func (s *Suite) TestPlistChecker_sort(c | |||
134 | "lib/${UNKNOWN}.la\n"+ // Stays below the previous line | 134 | "lib/${UNKNOWN}.la\n"+ // Stays below the previous line | |
135 | "b\n"+ | 135 | "b\n"+ | |
136 | "${PLIST.one}bin/program\n"+ // Conditionals are ignored while sorting | 136 | "${PLIST.one}bin/program\n"+ // Conditionals are ignored while sorting | |
137 | "${PKGMANDIR}/man1/program.1\n"+ // Stays below the previous line | 137 | "${PKGMANDIR}/man1/program.1\n"+ // Stays below the previous line | |
138 | "${PLIST.two}bin/program2\n"+ | 138 | "${PLIST.two}bin/program2\n"+ | |
139 | "ddd\n"+ | 139 | "ddd\n"+ | |
140 | "@exec echo \"after ddd\"\n"+ // Stays below the previous line | 140 | "@exec echo \"after ddd\"\n"+ // Stays below the previous line | |
141 | "lib/after.la\n"+ | 141 | "lib/after.la\n"+ | |
142 | "@exec echo \"after lib/after.la\"\n"+ | 142 | "@exec echo \"after lib/after.la\"\n"+ | |
143 | "lib/before.la\n"+ | 143 | "lib/before.la\n"+ | |
144 | "sbin/program\n") | 144 | "sbin/program\n") | |
145 | } | 145 | } | |
146 | 146 | |||
147 | func (s *Suite) TestPlistChecker_checkpathShare_Desktop(c *check.C) { | 147 | func (s *Suite) Test_PlistChecker_checkpathShare_Desktop(c *check.C) { | |
148 | // Disabled due to PR 46570, item "10. It should stop". | 148 | // Disabled due to PR 46570, item "10. It should stop". | |
149 | return | 149 | return | |
150 | 150 | |||
151 | s.UseCommandLine(c, "-Wextra") | 151 | s.UseCommandLine(c, "-Wextra") | |
152 | G.Pkg = NewPackage("category/pkgpath") | 152 | G.Pkg = NewPackage("category/pkgpath") | |
153 | 153 | |||
154 | ChecklinesPlist(s.NewLines("PLIST", | 154 | ChecklinesPlist(s.NewLines("PLIST", | |
155 | "@comment $"+"NetBSD$", | 155 | "@comment $"+"NetBSD$", | |
156 | "share/applications/pkgbase.desktop")) | 156 | "share/applications/pkgbase.desktop")) | |
157 | 157 | |||
158 | c.Check(s.Output(), equals, "WARN: PLIST:2: Packages that install a .desktop entry should .include \"../../sysutils/desktop-file-utils/desktopdb.mk\".\n") | 158 | c.Check(s.Output(), equals, "WARN: PLIST:2: Packages that install a .desktop entry should .include \"../../sysutils/desktop-file-utils/desktopdb.mk\".\n") | |
159 | } | 159 | } | |
160 | 160 | |||
161 | func (s *Suite) TestPlistChecker_checkpathMan_gz(c *check.C) { | 161 | func (s *Suite) Test_PlistChecker_checkpathMan_gz(c *check.C) { | |
162 | G.Pkg = NewPackage("category/pkgbase") | 162 | G.Pkg = NewPackage("category/pkgbase") | |
163 | 163 | |||
164 | ChecklinesPlist(s.NewLines("PLIST", | 164 | ChecklinesPlist(s.NewLines("PLIST", | |
165 | "@comment $"+"NetBSD$", | 165 | "@comment $"+"NetBSD$", | |
166 | "man/man3/strerror.3.gz")) | 166 | "man/man3/strerror.3.gz")) | |
167 | 167 | |||
168 | c.Check(s.Output(), equals, "NOTE: PLIST:2: The .gz extension is unnecessary for manual pages.\n") | 168 | c.Check(s.Output(), equals, "NOTE: PLIST:2: The .gz extension is unnecessary for manual pages.\n") | |
169 | } | 169 | } |
@@ -1,153 +1,153 @@ | @@ -1,153 +1,153 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | type MkShWalker struct { | 3 | type MkShWalker struct { | |
4 | } | 4 | } | |
5 | 5 | |||
6 | func (w *MkShWalker) Walk(list *MkShList, callback func(node interface{})) { | 6 | func (w *MkShWalker) Walk(list *MkShList, callback func(node interface{})) { | |
7 | for element := range w.iterate(list) { | 7 | for element := range w.iterate(list) { | |
8 | callback(element) | 8 | callback(element) | |
9 | } | 9 | } | |
10 | } | 10 | } | |
11 | 11 | |||
12 | func (w *MkShWalker) iterate(list *MkShList) chan interface{} { | 12 | func (w *MkShWalker) iterate(list *MkShList) <-chan interface{} { | |
13 | elements := make(chan interface{}) | 13 | elements := make(chan interface{}) | |
14 | 14 | |||
15 | go func() { | 15 | go func() { | |
16 | w.walkList(list, elements) | 16 | w.walkList(list, elements) | |
17 | close(elements) | 17 | close(elements) | |
18 | }() | 18 | }() | |
19 | 19 | |||
20 | return elements | 20 | return elements | |
21 | } | 21 | } | |
22 | 22 | |||
23 | func (w *MkShWalker) walkList(list *MkShList, collector chan interface{}) { | 23 | func (w *MkShWalker) walkList(list *MkShList, collector chan<- interface{}) { | |
24 | collector <- list | 24 | collector <- list | |
25 | 25 | |||
26 | for _, andor := range list.AndOrs { | 26 | for _, andor := range list.AndOrs { | |
27 | w.walkAndOr(andor, collector) | 27 | w.walkAndOr(andor, collector) | |
28 | } | 28 | } | |
29 | } | 29 | } | |
30 | 30 | |||
31 | func (w *MkShWalker) walkAndOr(andor *MkShAndOr, collector chan interface{}) { | 31 | func (w *MkShWalker) walkAndOr(andor *MkShAndOr, collector chan<- interface{}) { | |
32 | collector <- andor | 32 | collector <- andor | |
33 | 33 | |||
34 | for _, pipeline := range andor.Pipes { | 34 | for _, pipeline := range andor.Pipes { | |
35 | w.walkPipeline(pipeline, collector) | 35 | w.walkPipeline(pipeline, collector) | |
36 | } | 36 | } | |
37 | } | 37 | } | |
38 | 38 | |||
39 | func (w *MkShWalker) walkPipeline(pipeline *MkShPipeline, collector chan interface{}) { | 39 | func (w *MkShWalker) walkPipeline(pipeline *MkShPipeline, collector chan<- interface{}) { | |
40 | collector <- pipeline | 40 | collector <- pipeline | |
41 | 41 | |||
42 | for _, command := range pipeline.Cmds { | 42 | for _, command := range pipeline.Cmds { | |
43 | w.walkCommand(command, collector) | 43 | w.walkCommand(command, collector) | |
44 | } | 44 | } | |
45 | } | 45 | } | |
46 | 46 | |||
47 | func (w *MkShWalker) walkCommand(command *MkShCommand, collector chan interface{}) { | 47 | func (w *MkShWalker) walkCommand(command *MkShCommand, collector chan<- interface{}) { | |
48 | collector <- command | 48 | collector <- command | |
49 | 49 | |||
50 | switch { | 50 | switch { | |
51 | case command.Simple != nil: | 51 | case command.Simple != nil: | |
52 | w.walkSimpleCommand(command.Simple, collector) | 52 | w.walkSimpleCommand(command.Simple, collector) | |
53 | case command.Compound != nil: | 53 | case command.Compound != nil: | |
54 | w.walkCompoundCommand(command.Compound, collector) | 54 | w.walkCompoundCommand(command.Compound, collector) | |
55 | w.walkRedirects(command.Redirects, collector) | 55 | w.walkRedirects(command.Redirects, collector) | |
56 | case command.FuncDef != nil: | 56 | case command.FuncDef != nil: | |
57 | w.walkFunctionDefinition(command.FuncDef, collector) | 57 | w.walkFunctionDefinition(command.FuncDef, collector) | |
58 | w.walkRedirects(command.Redirects, collector) | 58 | w.walkRedirects(command.Redirects, collector) | |
59 | } | 59 | } | |
60 | } | 60 | } | |
61 | 61 | |||
62 | func (w *MkShWalker) walkSimpleCommand(command *MkShSimpleCommand, collector chan interface{}) { | 62 | func (w *MkShWalker) walkSimpleCommand(command *MkShSimpleCommand, collector chan<- interface{}) { | |
63 | collector <- command | 63 | collector <- command | |
64 | 64 | |||
65 | w.walkWords(command.Assignments, collector) | 65 | w.walkWords(command.Assignments, collector) | |
66 | if command.Name != nil { | 66 | if command.Name != nil { | |
67 | w.walkWord(command.Name, collector) | 67 | w.walkWord(command.Name, collector) | |
68 | } | 68 | } | |
69 | w.walkWords(command.Args, collector) | 69 | w.walkWords(command.Args, collector) | |
70 | w.walkRedirects(command.Redirections, collector) | 70 | w.walkRedirects(command.Redirections, collector) | |
71 | } | 71 | } | |
72 | 72 | |||
73 | func (w *MkShWalker) walkCompoundCommand(command *MkShCompoundCommand, collector chan interface{}) { | 73 | func (w *MkShWalker) walkCompoundCommand(command *MkShCompoundCommand, collector chan<- interface{}) { | |
74 | collector <- command | 74 | collector <- command | |
75 | 75 | |||
76 | switch { | 76 | switch { | |
77 | case command.Brace != nil: | 77 | case command.Brace != nil: | |
78 | w.walkList(command.Brace, collector) | 78 | w.walkList(command.Brace, collector) | |
79 | case command.Case != nil: | 79 | case command.Case != nil: | |
80 | w.walkCase(command.Case, collector) | 80 | w.walkCase(command.Case, collector) | |
81 | case command.For != nil: | 81 | case command.For != nil: | |
82 | w.walkFor(command.For, collector) | 82 | w.walkFor(command.For, collector) | |
83 | case command.If != nil: | 83 | case command.If != nil: | |
84 | w.walkIf(command.If, collector) | 84 | w.walkIf(command.If, collector) | |
85 | case command.Loop != nil: | 85 | case command.Loop != nil: | |
86 | w.walkLoop(command.Loop, collector) | 86 | w.walkLoop(command.Loop, collector) | |
87 | case command.Subshell != nil: | 87 | case command.Subshell != nil: | |
88 | w.walkList(command.Subshell, collector) | 88 | w.walkList(command.Subshell, collector) | |
89 | } | 89 | } | |
90 | } | 90 | } | |
91 | 91 | |||
92 | func (w *MkShWalker) walkCase(caseClause *MkShCaseClause, collector chan interface{}) { | 92 | func (w *MkShWalker) walkCase(caseClause *MkShCaseClause, collector chan<- interface{}) { | |
93 | collector <- caseClause | 93 | collector <- caseClause | |
94 | 94 | |||
95 | w.walkWord(caseClause.Word, collector) | 95 | w.walkWord(caseClause.Word, collector) | |
96 | for _, caseItem := range caseClause.Cases { | 96 | for _, caseItem := range caseClause.Cases { | |
97 | collector <- caseItem | 97 | collector <- caseItem | |
98 | w.walkWords(caseItem.Patterns, collector) | 98 | w.walkWords(caseItem.Patterns, collector) | |
99 | w.walkList(caseItem.Action, collector) | 99 | w.walkList(caseItem.Action, collector) | |
100 | } | 100 | } | |
101 | } | 101 | } | |
102 | 102 | |||
103 | func (w *MkShWalker) walkFunctionDefinition(funcdef *MkShFunctionDefinition, collector chan interface{}) { | 103 | func (w *MkShWalker) walkFunctionDefinition(funcdef *MkShFunctionDefinition, collector chan<- interface{}) { | |
104 | collector <- funcdef | 104 | collector <- funcdef | |
105 | 105 | |||
106 | w.walkCompoundCommand(funcdef.Body, collector) | 106 | w.walkCompoundCommand(funcdef.Body, collector) | |
107 | } | 107 | } | |
108 | 108 | |||
109 | func (w *MkShWalker) walkIf(ifClause *MkShIfClause, collector chan interface{}) { | 109 | func (w *MkShWalker) walkIf(ifClause *MkShIfClause, collector chan<- interface{}) { | |
110 | collector <- ifClause | 110 | collector <- ifClause | |
111 | for i, cond := range ifClause.Conds { | 111 | for i, cond := range ifClause.Conds { | |
112 | w.walkList(cond, collector) | 112 | w.walkList(cond, collector) | |
113 | w.walkList(ifClause.Actions[i], collector) | 113 | w.walkList(ifClause.Actions[i], collector) | |
114 | } | 114 | } | |
115 | if ifClause.Else != nil { | 115 | if ifClause.Else != nil { | |
116 | w.walkList(ifClause.Else, collector) | 116 | w.walkList(ifClause.Else, collector) | |
117 | } | 117 | } | |
118 | } | 118 | } | |
119 | 119 | |||
120 | func (w *MkShWalker) walkLoop(loop *MkShLoopClause, collector chan interface{}) { | 120 | func (w *MkShWalker) walkLoop(loop *MkShLoopClause, collector chan<- interface{}) { | |
121 | collector <- loop | 121 | collector <- loop | |
122 | w.walkList(loop.Cond, collector) | 122 | w.walkList(loop.Cond, collector) | |
123 | w.walkList(loop.Action, collector) | 123 | w.walkList(loop.Action, collector) | |
124 | } | 124 | } | |
125 | 125 | |||
126 | func (w *MkShWalker) walkWords(words []*ShToken, collector chan interface{}) { | 126 | func (w *MkShWalker) walkWords(words []*ShToken, collector chan<- interface{}) { | |
127 | collector <- words | 127 | collector <- words | |
128 | 128 | |||
129 | for _, word := range words { | 129 | for _, word := range words { | |
130 | w.walkWord(word, collector) | 130 | w.walkWord(word, collector) | |
131 | } | 131 | } | |
132 | } | 132 | } | |
133 | 133 | |||
134 | func (w *MkShWalker) walkWord(word *ShToken, collector chan interface{}) { | 134 | func (w *MkShWalker) walkWord(word *ShToken, collector chan<- interface{}) { | |
135 | collector <- word | 135 | collector <- word | |
136 | } | 136 | } | |
137 | 137 | |||
138 | func (w *MkShWalker) walkRedirects(redirects []*MkShRedirection, collector chan interface{}) { | 138 | func (w *MkShWalker) walkRedirects(redirects []*MkShRedirection, collector chan<- interface{}) { | |
139 | collector <- redirects | 139 | collector <- redirects | |
140 | 140 | |||
141 | for _, redirect := range redirects { | 141 | for _, redirect := range redirects { | |
142 | collector <- redirect | 142 | collector <- redirect | |
143 | w.walkWord(redirect.Target, collector) | 143 | w.walkWord(redirect.Target, collector) | |
144 | } | 144 | } | |
145 | } | 145 | } | |
146 | 146 | |||
147 | func (w *MkShWalker) walkFor(forClause *MkShForClause, collector chan interface{}) { | 147 | func (w *MkShWalker) walkFor(forClause *MkShForClause, collector chan<- interface{}) { | |
148 | collector <- forClause | 148 | collector <- forClause | |
149 | 149 | |||
150 | collector <- forClause.Varname | 150 | collector <- forClause.Varname | |
151 | w.walkWords(forClause.Values, collector) | 151 | w.walkWords(forClause.Values, collector) | |
152 | w.walkList(forClause.Body, collector) | 152 | w.walkList(forClause.Body, collector) | |
153 | } | 153 | } |
@@ -483,27 +483,27 @@ func (pkg *Package) determineEffectivePk | @@ -483,27 +483,27 @@ func (pkg *Package) determineEffectivePk | |||
483 | pkg.EffectivePkgname, pkg.EffectivePkgbase, pkg.EffectivePkgversion) | 483 | pkg.EffectivePkgname, pkg.EffectivePkgbase, pkg.EffectivePkgversion) | |
484 | } | 484 | } | |
485 | } | 485 | } | |
486 | } | 486 | } | |
487 | 487 | |||
488 | func (pkg *Package) pkgnameFromDistname(pkgname, distname string) string { | 488 | func (pkg *Package) pkgnameFromDistname(pkgname, distname string) string { | |
489 | tokens := NewMkParser(dummyLine, pkgname, false).MkTokens() | 489 | tokens := NewMkParser(dummyLine, pkgname, false).MkTokens() | |
490 | 490 | |||
491 | subst := func(str, smod string) (result string) { | 491 | subst := func(str, smod string) (result string) { | |
492 | if G.opts.Debug { | 492 | if G.opts.Debug { | |
493 | defer tracecall(str, smod, ref(result))() | 493 | defer tracecall(str, smod, ref(result))() | |
494 | } | 494 | } | |
495 | qsep := regexp.QuoteMeta(smod[1:2]) | 495 | qsep := regexp.QuoteMeta(smod[1:2]) | |
496 | if m, left, from, right, to, flags := match5(smod, `^S`+qsep+`(\^?)([^:]*?)(\$?)`+qsep+`([^:]*)`+qsep+`([1g]*)$`); m { | 496 | if m, left, from, right, to, flags := match5(smod, RegexPattern(`^S`+qsep+`(\^?)([^:]*?)(\$?)`+qsep+`([^:]*)`+qsep+`([1g]*)$`)); m { | |
497 | result := mkopSubst(str, left != "", from, right != "", to, flags) | 497 | result := mkopSubst(str, left != "", from, right != "", to, flags) | |
498 | if G.opts.Debug { | 498 | if G.opts.Debug { | |
499 | traceStep("subst %q %q => %q", str, smod, result) | 499 | traceStep("subst %q %q => %q", str, smod, result) | |
500 | } | 500 | } | |
501 | return result | 501 | return result | |
502 | } | 502 | } | |
503 | return str | 503 | return str | |
504 | } | 504 | } | |
505 | 505 | |||
506 | result := "" | 506 | result := "" | |
507 | for _, token := range tokens { | 507 | for _, token := range tokens { | |
508 | if token.Varuse != nil && token.Varuse.varname == "DISTNAME" { | 508 | if token.Varuse != nil && token.Varuse.varname == "DISTNAME" { | |
509 | newDistname := distname | 509 | newDistname := distname |
@@ -66,27 +66,27 @@ func (ck *PatchChecker) Check() { | @@ -66,27 +66,27 @@ func (ck *PatchChecker) Check() { | |||
66 | } | 66 | } | |
67 | 67 | |||
68 | if ck.exp.AdvanceIfMatches(`^\*\*\*\s(\S+)(.*)$`) { | 68 | if ck.exp.AdvanceIfMatches(`^\*\*\*\s(\S+)(.*)$`) { | |
69 | if ck.exp.AdvanceIfMatches(`^---\s(\S+)(.*)$`) { | 69 | if ck.exp.AdvanceIfMatches(`^---\s(\S+)(.*)$`) { | |
70 | ck.checkBeginDiff(line, patchedFiles) | 70 | ck.checkBeginDiff(line, patchedFiles) | |
71 | line.Warn0("Please use unified diffs (diff -u) for patches.") | 71 | line.Warn0("Please use unified diffs (diff -u) for patches.") | |
72 | return | 72 | return | |
73 | } | 73 | } | |
74 | 74 | |||
75 | ck.exp.StepBack() | 75 | ck.exp.StepBack() | |
76 | } | 76 | } | |
77 | 77 | |||
78 | ck.exp.Advance() | 78 | ck.exp.Advance() | |
79 | ck.previousLineEmpty = line.Text == "" || hasPrefix(line.Text, "diff ") || hasPrefix(line.Text, "=============") | 79 | ck.previousLineEmpty = ck.isEmptyLine(line.Text) | |
80 | if !ck.previousLineEmpty { | 80 | if !ck.previousLineEmpty { | |
81 | ck.seenDocumentation = true | 81 | ck.seenDocumentation = true | |
82 | } | 82 | } | |
83 | } | 83 | } | |
84 | 84 | |||
85 | if patchedFiles > 1 { | 85 | if patchedFiles > 1 { | |
86 | NewLineWhole(ck.lines[0].Fname).Warnf("Contains patches for %d files, should be only one.", patchedFiles) | 86 | NewLineWhole(ck.lines[0].Fname).Warnf("Contains patches for %d files, should be only one.", patchedFiles) | |
87 | } else if patchedFiles == 0 { | 87 | } else if patchedFiles == 0 { | |
88 | NewLineWhole(ck.lines[0].Fname).Error0("Contains no patch.") | 88 | NewLineWhole(ck.lines[0].Fname).Error0("Contains no patch.") | |
89 | } | 89 | } | |
90 | 90 | |||
91 | ChecklinesTrailingEmptyLines(ck.lines) | 91 | ChecklinesTrailingEmptyLines(ck.lines) | |
92 | SaveAutofixChanges(ck.lines) | 92 | SaveAutofixChanges(ck.lines) | |
@@ -133,27 +133,27 @@ func (ck *PatchChecker) checkUnifiedDiff | @@ -133,27 +133,27 @@ func (ck *PatchChecker) checkUnifiedDiff | |||
133 | case hasPrefix(text, "\\"): | 133 | case hasPrefix(text, "\\"): | |
134 | // \ No newline at end of file | 134 | // \ No newline at end of file | |
135 | default: | 135 | default: | |
136 | line.Error0("Invalid line in unified patch hunk") | 136 | line.Error0("Invalid line in unified patch hunk") | |
137 | return | 137 | return | |
138 | } | 138 | } | |
139 | } | 139 | } | |
140 | } | 140 | } | |
141 | if !hasHunks { | 141 | if !hasHunks { | |
142 | ck.exp.CurrentLine().Error1("No patch hunks for %q.", patchedFile) | 142 | ck.exp.CurrentLine().Error1("No patch hunks for %q.", patchedFile) | |
143 | } | 143 | } | |
144 | if !ck.exp.EOF() { | 144 | if !ck.exp.EOF() { | |
145 | line := ck.exp.CurrentLine() | 145 | line := ck.exp.CurrentLine() | |
146 | if line.Text != "" && !matches(line.Text, rePatchUniFileDel) && !hasPrefix(line.Text, "Index:") && !hasPrefix(line.Text, "diff ") { | 146 | if !ck.isEmptyLine(line.Text) && !matches(line.Text, rePatchUniFileDel) { | |
147 | line.Warn0("Empty line or end of file expected.") | 147 | line.Warn0("Empty line or end of file expected.") | |
148 | Explain3( | 148 | Explain3( | |
149 | "This empty line makes the end of the patch clearly visible.", | 149 | "This empty line makes the end of the patch clearly visible.", | |
150 | "Otherwise the reader would have to count lines to see where", | 150 | "Otherwise the reader would have to count lines to see where", | |
151 | "the patch ends.") | 151 | "the patch ends.") | |
152 | } | 152 | } | |
153 | } | 153 | } | |
154 | } | 154 | } | |
155 | 155 | |||
156 | func (ck *PatchChecker) checkBeginDiff(line *Line, patchedFiles int) { | 156 | func (ck *PatchChecker) checkBeginDiff(line *Line, patchedFiles int) { | |
157 | if G.opts.Debug { | 157 | if G.opts.Debug { | |
158 | defer tracecall0()() | 158 | defer tracecall0()() | |
159 | } | 159 | } | |
@@ -239,26 +239,34 @@ func (ck *PatchChecker) checktextUniHunk | @@ -239,26 +239,34 @@ func (ck *PatchChecker) checktextUniHunk | |||
239 | func (ck *PatchChecker) checktextRcsid(text string) { | 239 | func (ck *PatchChecker) checktextRcsid(text string) { | |
240 | if strings.IndexByte(text, '$') == -1 { | 240 | if strings.IndexByte(text, '$') == -1 { | |
241 | return | 241 | return | |
242 | } | 242 | } | |
243 | if m, tagname := match1(text, `\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|NetBSD)(?::[^\$]*)?\$`); m { | 243 | if m, tagname := match1(text, `\$(Author|Date|Header|Id|Locker|Log|Name|RCSfile|Revision|Source|State|NetBSD)(?::[^\$]*)?\$`); m { | |
244 | if matches(text, rePatchUniHunk) { | 244 | if matches(text, rePatchUniHunk) { | |
245 | ck.exp.PreviousLine().Warn1("Found RCS tag \"$%s$\". Please remove it.", tagname) | 245 | ck.exp.PreviousLine().Warn1("Found RCS tag \"$%s$\". Please remove it.", tagname) | |
246 | } else { | 246 | } else { | |
247 | ck.exp.PreviousLine().Warn1("Found RCS tag \"$%s$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\".", tagname) | 247 | ck.exp.PreviousLine().Warn1("Found RCS tag \"$%s$\". Please remove it by reducing the number of context lines using pkgdiff or \"diff -U[210]\".", tagname) | |
248 | } | 248 | } | |
249 | } | 249 | } | |
250 | } | 250 | } | |
251 | 251 | |||
252 | func (ck *PatchChecker) isEmptyLine(text string) bool { | |||
253 | return text == "" || | |||
254 | hasPrefix(text, "index ") || | |||
255 | hasPrefix(text, "Index: ") || | |||
256 | hasPrefix(text, "diff ") || | |||
257 | hasPrefix(text, "=============") | |||
258 | } | |||
259 | ||||
252 | type FileType uint8 | 260 | type FileType uint8 | |
253 | 261 | |||
254 | const ( | 262 | const ( | |
255 | ftSource FileType = iota | 263 | ftSource FileType = iota | |
256 | ftShell | 264 | ftShell | |
257 | ftMakefile | 265 | ftMakefile | |
258 | ftText | 266 | ftText | |
259 | ftConfigure | 267 | ftConfigure | |
260 | ftIgnore | 268 | ftIgnore | |
261 | ftUnknown | 269 | ftUnknown | |
262 | ) | 270 | ) | |
263 | 271 | |||
264 | func (ft FileType) String() string { | 272 | func (ft FileType) String() string { |
@@ -296,27 +296,27 @@ func Checkfile(fname string) { | @@ -296,27 +296,27 @@ func Checkfile(fname string) { | |||
296 | } | 296 | } | |
297 | 297 | |||
298 | func ChecklinesTrailingEmptyLines(lines []*Line) { | 298 | func ChecklinesTrailingEmptyLines(lines []*Line) { | |
299 | max := len(lines) | 299 | max := len(lines) | |
300 | last := max | 300 | last := max | |
301 | for last > 1 && lines[last-1].Text == "" { | 301 | for last > 1 && lines[last-1].Text == "" { | |
302 | last-- | 302 | last-- | |
303 | } | 303 | } | |
304 | if last != max { | 304 | if last != max { | |
305 | lines[last].Note0("Trailing empty lines.") | 305 | lines[last].Note0("Trailing empty lines.") | |
306 | } | 306 | } | |
307 | } | 307 | } | |
308 | 308 | |||
309 | func MatchVarassign(text string) (m bool, varname, op, valueAlign, value, comment string) { | 309 | func MatchVarassign(text string) (m bool, varname, spaceAfterVarname, op, valueAlign, value, comment string) { | |
310 | i, n := 0, len(text) | 310 | i, n := 0, len(text) | |
311 | 311 | |||
312 | for i < n && text[i] == ' ' { | 312 | for i < n && text[i] == ' ' { | |
313 | i++ | 313 | i++ | |
314 | } | 314 | } | |
315 | 315 | |||
316 | varnameStart := i | 316 | varnameStart := i | |
317 | for ; i < n; i++ { | 317 | for ; i < n; i++ { | |
318 | b := text[i] | 318 | b := text[i] | |
319 | mask := uint(0) | 319 | mask := uint(0) | |
320 | switch b & 0xE0 { | 320 | switch b & 0xE0 { | |
321 | case 0x20: | 321 | case 0x20: | |
322 | mask = 0x03ff6c10 | 322 | mask = 0x03ff6c10 | |
@@ -369,26 +369,27 @@ func MatchVarassign(text string) (m bool | @@ -369,26 +369,27 @@ func MatchVarassign(text string) (m bool | |||
369 | if b == '#' && (i == valueStart || text[i-1] != '\\') { | 369 | if b == '#' && (i == valueStart || text[i-1] != '\\') { | |
370 | break | 370 | break | |
371 | } else if b != '\\' || i+1 >= n || text[i+1] != '#' { | 371 | } else if b != '\\' || i+1 >= n || text[i+1] != '#' { | |
372 | valuebuf[j] = b | 372 | valuebuf[j] = b | |
373 | j++ | 373 | j++ | |
374 | } | 374 | } | |
375 | } | 375 | } | |
376 | 376 | |||
377 | commentStart := i | 377 | commentStart := i | |
378 | commentEnd := n | 378 | commentEnd := n | |
379 | 379 | |||
380 | m = true | 380 | m = true | |
381 | varname = text[varnameStart:varnameEnd] | 381 | varname = text[varnameStart:varnameEnd] | |
382 | spaceAfterVarname = text[varnameEnd:opStart] | |||
382 | op = text[opStart:opEnd] | 383 | op = text[opStart:opEnd] | |
383 | valueAlign = text[0:valueStart] | 384 | valueAlign = text[0:valueStart] | |
384 | value = strings.TrimSpace(string(valuebuf[:j])) | 385 | value = strings.TrimSpace(string(valuebuf[:j])) | |
385 | comment = text[commentStart:commentEnd] | 386 | comment = text[commentStart:commentEnd] | |
386 | return | 387 | return | |
387 | } | 388 | } | |
388 | 389 | |||
389 | type DependencyPattern struct { | 390 | type DependencyPattern struct { | |
390 | pkgbase string // "freeciv-client", "{gcc48,gcc48-libs}", "${EMACS_REQD}" | 391 | pkgbase string // "freeciv-client", "{gcc48,gcc48-libs}", "${EMACS_REQD}" | |
391 | lowerOp string // ">=", ">" | 392 | lowerOp string // ">=", ">" | |
392 | lower string // "2.5.0", "${PYVER}" | 393 | lower string // "2.5.0", "${PYVER}" | |
393 | upperOp string // "<", "<=" | 394 | upperOp string // "<", "<=" | |
394 | upper string // "3.0", "${PYVER}" | 395 | upper string // "3.0", "${PYVER}" |
@@ -1,189 +1,141 @@ | @@ -1,189 +1,141 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | check "gopkg.in/check.v1" | 4 | check "gopkg.in/check.v1" | |
5 | ) | 5 | ) | |
6 | 6 | |||
7 | func (s *Suite) TestPkgnameFromDistname(c *check.C) { | 7 | func (s *Suite) Test_Package_pkgnameFromDistname(c *check.C) { | |
8 | pkg := NewPackage("dummy") | 8 | pkg := NewPackage("dummy") | |
9 | pkg.vardef["PKGNAME"] = NewMkLine(NewLine("Makefile", 5, "PKGNAME=dummy", nil)) | 9 | pkg.vardef["PKGNAME"] = NewMkLine(NewLine("Makefile", 5, "PKGNAME=dummy", nil)) | |
10 | 10 | |||
11 | c.Check(pkg.pkgnameFromDistname("pkgname-1.0", "whatever"), equals, "pkgname-1.0") | 11 | c.Check(pkg.pkgnameFromDistname("pkgname-1.0", "whatever"), equals, "pkgname-1.0") | |
12 | c.Check(pkg.pkgnameFromDistname("${DISTNAME}", "distname-1.0"), equals, "distname-1.0") | 12 | c.Check(pkg.pkgnameFromDistname("${DISTNAME}", "distname-1.0"), equals, "distname-1.0") | |
13 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S/dist/pkg/}", "distname-1.0"), equals, "pkgname-1.0") | 13 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S/dist/pkg/}", "distname-1.0"), equals, "pkgname-1.0") | |
14 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S|a|b|g}", "panama-0.13"), equals, "pbnbmb-0.13") | 14 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S|a|b|g}", "panama-0.13"), equals, "pbnbmb-0.13") | |
15 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S|^lib||}", "libncurses"), equals, "ncurses") | 15 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S|^lib||}", "libncurses"), equals, "ncurses") | |
16 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S|^lib||}", "mylib"), equals, "mylib") | 16 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S|^lib||}", "mylib"), equals, "mylib") | |
17 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:tl:S/-/./g:S/he/-/1}", "SaxonHE9-5-0-1J"), equals, "saxon-9.5.0.1j") | 17 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:tl:S/-/./g:S/he/-/1}", "SaxonHE9-5-0-1J"), equals, "saxon-9.5.0.1j") | |
18 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:C/beta/.0./}", "fspanel-0.8beta1"), equals, "${DISTNAME:C/beta/.0./}") | 18 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:C/beta/.0./}", "fspanel-0.8beta1"), equals, "${DISTNAME:C/beta/.0./}") | |
19 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S/-0$/.0/1}", "aspell-af-0.50-0"), equals, "aspell-af-0.50.0") | 19 | c.Check(pkg.pkgnameFromDistname("${DISTNAME:S/-0$/.0/1}", "aspell-af-0.50-0"), equals, "aspell-af-0.50.0") | |
20 | 20 | |||
21 | c.Check(s.Output(), equals, "") | 21 | c.Check(s.Output(), equals, "") | |
22 | } | 22 | } | |
23 | 23 | |||
24 | func (s *Suite) TestChecklinesPackageMakefileVarorder(c *check.C) { | 24 | func (s *Suite) Test_Package_ChecklinesPackageMakefileVarorder(c *check.C) { | |
25 | s.UseCommandLine(c, "-Worder") | 25 | s.UseCommandLine(c, "-Worder") | |
26 | pkg := NewPackage("x11/9term") | 26 | pkg := NewPackage("x11/9term") | |
27 | 27 | |||
28 | pkg.ChecklinesPackageMakefileVarorder(s.NewMkLines("Makefile", | 28 | pkg.ChecklinesPackageMakefileVarorder(s.NewMkLines("Makefile", | |
29 | "# $"+"NetBSD$", | 29 | "# $"+"NetBSD$", | |
30 | "", | 30 | "", | |
31 | "DISTNAME=9term", | 31 | "DISTNAME=9term", | |
32 | "CATEGORIES=x11")) | 32 | "CATEGORIES=x11")) | |
33 | 33 | |||
34 | c.Check(s.Output(), equals, "") | 34 | c.Check(s.Output(), equals, "") | |
35 | 35 | |||
36 | pkg.ChecklinesPackageMakefileVarorder(s.NewMkLines("Makefile", | 36 | pkg.ChecklinesPackageMakefileVarorder(s.NewMkLines("Makefile", | |
37 | "# $"+"NetBSD$", | 37 | "# $"+"NetBSD$", | |
38 | "", | 38 | "", | |
39 | "DISTNAME=9term", | 39 | "DISTNAME=9term", | |
40 | "CATEGORIES=x11", | 40 | "CATEGORIES=x11", | |
41 | "", | 41 | "", | |
42 | ".include \"../../mk/bsd.pkg.mk\"")) | 42 | ".include \"../../mk/bsd.pkg.mk\"")) | |
43 | 43 | |||
44 | c.Check(s.Output(), equals, ""+ | 44 | c.Check(s.Output(), equals, ""+ | |
45 | "WARN: Makefile:6: The canonical position for the required variable COMMENT is here.\n"+ | 45 | "WARN: Makefile:6: The canonical position for the required variable COMMENT is here.\n"+ | |
46 | "WARN: Makefile:6: The canonical position for the required variable LICENSE is here.\n") | 46 | "WARN: Makefile:6: The canonical position for the required variable LICENSE is here.\n") | |
47 | } | 47 | } | |
48 | 48 | |||
49 | func (s *Suite) TestGetNbpart(c *check.C) { | 49 | func (s *Suite) Test_Package_getNbpart(c *check.C) { | |
50 | pkg := NewPackage("category/pkgbase") | 50 | pkg := NewPackage("category/pkgbase") | |
51 | pkg.vardef["PKGREVISION"] = NewMkLine(NewLine("Makefile", 1, "PKGREVISION=14", nil)) | 51 | pkg.vardef["PKGREVISION"] = NewMkLine(NewLine("Makefile", 1, "PKGREVISION=14", nil)) | |
52 | 52 | |||
53 | c.Check(pkg.getNbpart(), equals, "nb14") | 53 | c.Check(pkg.getNbpart(), equals, "nb14") | |
54 | 54 | |||
55 | pkg.vardef["PKGREVISION"] = NewMkLine(NewLine("Makefile", 1, "PKGREVISION=asdf", nil)) | 55 | pkg.vardef["PKGREVISION"] = NewMkLine(NewLine("Makefile", 1, "PKGREVISION=asdf", nil)) | |
56 | 56 | |||
57 | c.Check(pkg.getNbpart(), equals, "") | 57 | c.Check(pkg.getNbpart(), equals, "") | |
58 | } | 58 | } | |
59 | 59 | |||
60 | func (s *Suite) TestMkLines_CheckForUsedComment(c *check.C) { | 60 | func (s *Suite) Test_Package_determineEffectivePkgVars__precedence(c *check.C) { | |
61 | s.UseCommandLine(c, "--show-autofix") | |||
62 | s.NewMkLines("Makefile.common", | |||
63 | "# $"+"NetBSD$", | |||
64 | "", | |||
65 | "# used by sysutils/mc", | |||
66 | ).checkForUsedComment("sysutils/mc") | |||
67 | ||||
68 | c.Check(s.Output(), equals, "") | |||
69 | ||||
70 | s.NewMkLines("Makefile.common").checkForUsedComment("category/package") | |||
71 | ||||
72 | c.Check(s.Output(), equals, "") | |||
73 | ||||
74 | s.NewMkLines("Makefile.common", | |||
75 | "# $"+"NetBSD$", | |||
76 | ).checkForUsedComment("category/package") | |||
77 | ||||
78 | c.Check(s.Output(), equals, "") | |||
79 | ||||
80 | s.NewMkLines("Makefile.common", | |||
81 | "# $"+"NetBSD$", | |||
82 | "", | |||
83 | ).checkForUsedComment("category/package") | |||
84 | ||||
85 | c.Check(s.Output(), equals, "") | |||
86 | ||||
87 | s.NewMkLines("Makefile.common", | |||
88 | "# $"+"NetBSD$", | |||
89 | "", | |||
90 | "VARNAME=\tvalue", | |||
91 | ).checkForUsedComment("category/package") | |||
92 | ||||
93 | c.Check(s.Output(), equals, ""+ | |||
94 | "WARN: Makefile.common:2: Please add a line \"# used by category/package\" here.\n"+ | |||
95 | "AUTOFIX: Makefile.common:2: Inserting a line \"# used by category/package\" before this line.\n") | |||
96 | ||||
97 | s.NewMkLines("Makefile.common", | |||
98 | "# $"+"NetBSD$", | |||
99 | "#", | |||
100 | "#", | |||
101 | ).checkForUsedComment("category/package") | |||
102 | ||||
103 | c.Check(s.Output(), equals, ""+ | |||
104 | "WARN: Makefile.common:3: Please add a line \"# used by category/package\" here.\n"+ | |||
105 | "AUTOFIX: Makefile.common:3: Inserting a line \"# used by category/package\" before this line.\n") | |||
106 | } | |||
107 | ||||
108 | func (s *Suite) TestPackage_DetermineEffectivePkgVars_Precedence(c *check.C) { | |||
109 | pkg := NewPackage("category/pkgbase") | 61 | pkg := NewPackage("category/pkgbase") | |
110 | pkgnameLine := NewMkLine(NewLine("Makefile", 3, "PKGNAME=pkgname-1.0", nil)) | 62 | pkgnameLine := NewMkLine(NewLine("Makefile", 3, "PKGNAME=pkgname-1.0", nil)) | |
111 | distnameLine := NewMkLine(NewLine("Makefile", 4, "DISTNAME=distname-1.0", nil)) | 63 | distnameLine := NewMkLine(NewLine("Makefile", 4, "DISTNAME=distname-1.0", nil)) | |
112 | pkgrevisionLine := NewMkLine(NewLine("Makefile", 5, "PKGREVISION=13", nil)) | 64 | pkgrevisionLine := NewMkLine(NewLine("Makefile", 5, "PKGREVISION=13", nil)) | |
113 | 65 | |||
114 | pkg.defineVar(pkgnameLine, pkgnameLine.Varname()) | 66 | pkg.defineVar(pkgnameLine, pkgnameLine.Varname()) | |
115 | pkg.defineVar(distnameLine, distnameLine.Varname()) | 67 | pkg.defineVar(distnameLine, distnameLine.Varname()) | |
116 | pkg.defineVar(pkgrevisionLine, pkgrevisionLine.Varname()) | 68 | pkg.defineVar(pkgrevisionLine, pkgrevisionLine.Varname()) | |
117 | 69 | |||
118 | pkg.determineEffectivePkgVars() | 70 | pkg.determineEffectivePkgVars() | |
119 | 71 | |||
120 | c.Check(pkg.EffectivePkgbase, equals, "pkgname") | 72 | c.Check(pkg.EffectivePkgbase, equals, "pkgname") | |
121 | c.Check(pkg.EffectivePkgname, equals, "pkgname-1.0nb13") | 73 | c.Check(pkg.EffectivePkgname, equals, "pkgname-1.0nb13") | |
122 | c.Check(pkg.EffectivePkgversion, equals, "1.0") | 74 | c.Check(pkg.EffectivePkgversion, equals, "1.0") | |
123 | } | 75 | } | |
124 | 76 | |||
125 | func (s *Suite) TestPackage_CheckPossibleDowngrade(c *check.C) { | 77 | func (s *Suite) Test_Package_checkPossibleDowngrade(c *check.C) { | |
126 | G.Pkg = NewPackage("category/pkgbase") | 78 | G.Pkg = NewPackage("category/pkgbase") | |
127 | G.CurPkgsrcdir = "../.." | 79 | G.CurPkgsrcdir = "../.." | |
128 | G.Pkg.EffectivePkgname = "package-1.0nb15" | 80 | G.Pkg.EffectivePkgname = "package-1.0nb15" | |
129 | G.Pkg.EffectivePkgnameLine = NewMkLine(NewLine("category/pkgbase/Makefile", 5, "PKGNAME=dummy", nil)) | 81 | G.Pkg.EffectivePkgnameLine = NewMkLine(NewLine("category/pkgbase/Makefile", 5, "PKGNAME=dummy", nil)) | |
130 | G.globalData.LastChange = map[string]*Change{ | 82 | G.globalData.LastChange = map[string]*Change{ | |
131 | "category/pkgbase": &Change{ | 83 | "category/pkgbase": &Change{ | |
132 | Action: "Updated", | 84 | Action: "Updated", | |
133 | Version: "1.8", | 85 | Version: "1.8", | |
134 | Line: NewLine("doc/CHANGES", 116, "dummy", nil), | 86 | Line: NewLine("doc/CHANGES", 116, "dummy", nil), | |
135 | }, | 87 | }, | |
136 | } | 88 | } | |
137 | 89 | |||
138 | G.Pkg.checkPossibleDowngrade() | 90 | G.Pkg.checkPossibleDowngrade() | |
139 | 91 | |||
140 | c.Check(s.Output(), equals, "WARN: category/pkgbase/Makefile:5: The package is being downgraded from 1.8 (see ../../doc/CHANGES:116) to 1.0nb15\n") | 92 | c.Check(s.Output(), equals, "WARN: category/pkgbase/Makefile:5: The package is being downgraded from 1.8 (see ../../doc/CHANGES:116) to 1.0nb15\n") | |
141 | 93 | |||
142 | G.globalData.LastChange["category/pkgbase"].Version = "1.0nb22" | 94 | G.globalData.LastChange["category/pkgbase"].Version = "1.0nb22" | |
143 | 95 | |||
144 | G.Pkg.checkPossibleDowngrade() | 96 | G.Pkg.checkPossibleDowngrade() | |
145 | 97 | |||
146 | c.Check(s.Output(), equals, "") | 98 | c.Check(s.Output(), equals, "") | |
147 | } | 99 | } | |
148 | 100 | |||
149 | func (s *Suite) TestCheckdirPackage(c *check.C) { | 101 | func (s *Suite) Test_checkdirPackage(c *check.C) { | |
150 | s.CreateTmpFile(c, "Makefile", ""+ | 102 | s.CreateTmpFile(c, "Makefile", ""+ | |
151 | "# $"+"NetBSD$\n") | 103 | "# $"+"NetBSD$\n") | |
152 | G.CurrentDir = s.tmpdir | 104 | G.CurrentDir = s.tmpdir | |
153 | 105 | |||
154 | checkdirPackage(s.tmpdir) | 106 | checkdirPackage(s.tmpdir) | |
155 | 107 | |||
156 | c.Check(s.Output(), equals, ""+ | 108 | c.Check(s.Output(), equals, ""+ | |
157 | "WARN: ~/Makefile: Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?\n"+ | 109 | "WARN: ~/Makefile: Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?\n"+ | |
158 | "WARN: ~/distinfo: File not found. Please run \"@BMAKE@ makesum\".\n"+ | 110 | "WARN: ~/distinfo: File not found. Please run \"@BMAKE@ makesum\".\n"+ | |
159 | "ERROR: ~/Makefile: Each package must define its LICENSE.\n"+ | 111 | "ERROR: ~/Makefile: Each package must define its LICENSE.\n"+ | |
160 | "WARN: ~/Makefile: No COMMENT given.\n") | 112 | "WARN: ~/Makefile: No COMMENT given.\n") | |
161 | } | 113 | } | |
162 | 114 | |||
163 | func (s *Suite) Test_Package_Meta_package_License(c *check.C) { | 115 | func (s *Suite) Test_checkdirPackage__meta_package_without_license(c *check.C) { | |
164 | s.CreateTmpFileLines(c, "Makefile", | 116 | s.CreateTmpFileLines(c, "Makefile", | |
165 | "# $"+"NetBSD$", | 117 | "# $"+"NetBSD$", | |
166 | "", | 118 | "", | |
167 | "META_PACKAGE=\tyes") | 119 | "META_PACKAGE=\tyes") | |
168 | G.CurrentDir = s.tmpdir | 120 | G.CurrentDir = s.tmpdir | |
169 | G.globalData.InitVartypes() | 121 | G.globalData.InitVartypes() | |
170 | 122 | |||
171 | checkdirPackage(s.tmpdir) | 123 | checkdirPackage(s.tmpdir) | |
172 | 124 | |||
173 | c.Check(s.Output(), equals, "WARN: ~/Makefile: No COMMENT given.\n") // No error about missing LICENSE. | 125 | c.Check(s.Output(), equals, "WARN: ~/Makefile: No COMMENT given.\n") // No error about missing LICENSE. | |
174 | } | 126 | } | |
175 | 127 | |||
176 | func (s *Suite) Test_Package_Varuse_LoadTime(c *check.C) { | 128 | func (s *Suite) Test_Package__varuse_at_load_time(c *check.C) { | |
177 | s.CreateTmpFileLines(c, "doc/CHANGES-2016", | 129 | s.CreateTmpFileLines(c, "doc/CHANGES-2016", | |
178 | "# dummy") | 130 | "# dummy") | |
179 | s.CreateTmpFileLines(c, "doc/TODO", | 131 | s.CreateTmpFileLines(c, "doc/TODO", | |
180 | "# dummy") | 132 | "# dummy") | |
181 | s.CreateTmpFileLines(c, "licenses/bsd-2", | 133 | s.CreateTmpFileLines(c, "licenses/bsd-2", | |
182 | "# dummy") | 134 | "# dummy") | |
183 | s.CreateTmpFileLines(c, "mk/fetch/sites.mk", | 135 | s.CreateTmpFileLines(c, "mk/fetch/sites.mk", | |
184 | "# dummy") | 136 | "# dummy") | |
185 | s.CreateTmpFileLines(c, "mk/bsd.pkg.mk", | 137 | s.CreateTmpFileLines(c, "mk/bsd.pkg.mk", | |
186 | "# dummy") | 138 | "# dummy") | |
187 | s.CreateTmpFileLines(c, "mk/defaults/options.description", | 139 | s.CreateTmpFileLines(c, "mk/defaults/options.description", | |
188 | "option Description") | 140 | "option Description") | |
189 | s.CreateTmpFileLines(c, "mk/defaults/mk.conf", | 141 | s.CreateTmpFileLines(c, "mk/defaults/mk.conf", | |
@@ -224,13 +176,30 @@ func (s *Suite) Test_Package_Varuse_Load | @@ -224,13 +176,30 @@ func (s *Suite) Test_Package_Varuse_Load | |||
224 | "", | 176 | "", | |
225 | ".include \"../../mk/bsd.pkg.mk\"") | 177 | ".include \"../../mk/bsd.pkg.mk\"") | |
226 | s.CreateTmpFileLines(c, "category/pkgbase/distinfo", | 178 | s.CreateTmpFileLines(c, "category/pkgbase/distinfo", | |
227 | "$"+"NetBSD$") | 179 | "$"+"NetBSD$") | |
228 | 180 | |||
229 | (&Pkglint{}).Main("pkglint", "-q", "-Wperm", s.tmpdir+"/category/pkgbase") | 181 | (&Pkglint{}).Main("pkglint", "-q", "-Wperm", s.tmpdir+"/category/pkgbase") | |
230 | 182 | |||
231 | c.Check(s.Output(), equals, ""+ | 183 | c.Check(s.Output(), equals, ""+ | |
232 | "WARN: ~/category/pkgbase/Makefile:8: To use the tool \"FALSE\" at load time, bsd.prefs.mk has to be included before.\n"+ | 184 | "WARN: ~/category/pkgbase/Makefile:8: To use the tool \"FALSE\" at load time, bsd.prefs.mk has to be included before.\n"+ | |
233 | "WARN: ~/category/pkgbase/Makefile:9: To use the tool \"NICE\" at load time, bsd.prefs.mk has to be included before.\n"+ | 185 | "WARN: ~/category/pkgbase/Makefile:9: To use the tool \"NICE\" at load time, bsd.prefs.mk has to be included before.\n"+ | |
234 | "WARN: ~/category/pkgbase/Makefile:10: To use the tool \"TRUE\" at load time, bsd.prefs.mk has to be included before.\n"+ | 186 | "WARN: ~/category/pkgbase/Makefile:10: To use the tool \"TRUE\" at load time, bsd.prefs.mk has to be included before.\n"+ | |
235 | "WARN: ~/category/pkgbase/Makefile:16: To use the tool \"NICE\" at load time, it has to be added to USE_TOOLS before including bsd.prefs.mk.\n") | 187 | "WARN: ~/category/pkgbase/Makefile:16: To use the tool \"NICE\" at load time, it has to be added to USE_TOOLS before including bsd.prefs.mk.\n") | |
236 | } | 188 | } | |
189 | ||||
190 | func (s *Suite) Test_Package_loadPackageMakefile(c *check.C) { | |||
191 | makefile := s.CreateTmpFile(c, "category/package/Makefile", ""+ | |||
192 | "# $"+"NetBSD$\n"+ | |||
193 | "\n"+ | |||
194 | "PKGNAME=pkgname-1.67\n"+ | |||
195 | "DISTNAME=distfile_1_67\n"+ | |||
196 | ".include \"../../category/package/Makefile\"\n") | |||
197 | pkg := NewPackage("category/package") | |||
198 | G.CurrentDir = s.tmpdir + "/category/package" | |||
199 | G.CurPkgsrcdir = "../.." | |||
200 | G.Pkg = pkg | |||
201 | ||||
202 | pkg.loadPackageMakefile(makefile) | |||
203 | ||||
204 | c.Check(s.Output(), equals, "") | |||
205 | } |
@@ -18,27 +18,27 @@ import ( | @@ -18,27 +18,27 @@ import ( | |||
18 | 18 | |||
19 | // Short names for commonly used functions. | 19 | // Short names for commonly used functions. | |
20 | func contains(s, substr string) bool { return strings.Contains(s, substr) } | 20 | func contains(s, substr string) bool { return strings.Contains(s, substr) } | |
21 | func hasPrefix(s, prefix string) bool { return strings.HasPrefix(s, prefix) } | 21 | func hasPrefix(s, prefix string) bool { return strings.HasPrefix(s, prefix) } | |
22 | func hasSuffix(s, suffix string) bool { return strings.HasSuffix(s, suffix) } | 22 | func hasSuffix(s, suffix string) bool { return strings.HasSuffix(s, suffix) } | |
23 | 23 | |||
24 | func ifelseStr(cond bool, a, b string) string { | 24 | func ifelseStr(cond bool, a, b string) string { | |
25 | if cond { | 25 | if cond { | |
26 | return a | 26 | return a | |
27 | } | 27 | } | |
28 | return b | 28 | return b | |
29 | } | 29 | } | |
30 | 30 | |||
31 | func mustMatch(s, re string) []string { | 31 | func mustMatch(s string, re RegexPattern) []string { | |
32 | if m := match(s, re); m != nil { | 32 | if m := match(s, re); m != nil { | |
33 | return m | 33 | return m | |
34 | } | 34 | } | |
35 | panic(fmt.Sprintf("mustMatch %q %q", s, re)) | 35 | panic(fmt.Sprintf("mustMatch %q %q", s, re)) | |
36 | } | 36 | } | |
37 | 37 | |||
38 | func isEmptyDir(fname string) bool { | 38 | func isEmptyDir(fname string) bool { | |
39 | dirents, err := ioutil.ReadDir(fname) | 39 | dirents, err := ioutil.ReadDir(fname) | |
40 | if err != nil || hasSuffix(fname, "/CVS") { | 40 | if err != nil || hasSuffix(fname, "/CVS") { | |
41 | return true | 41 | return true | |
42 | } | 42 | } | |
43 | for _, dirent := range dirents { | 43 | for _, dirent := range dirents { | |
44 | name := dirent.Name() | 44 | name := dirent.Name() | |
@@ -182,113 +182,115 @@ func splitOnSpace(s string) []string { | @@ -182,113 +182,115 @@ func splitOnSpace(s string) []string { | |||
182 | return regcomp(`\s+`).Split(s, -1) | 182 | return regcomp(`\s+`).Split(s, -1) | |
183 | } | 183 | } | |
184 | 184 | |||
185 | func fileExists(fname string) bool { | 185 | func fileExists(fname string) bool { | |
186 | st, err := os.Stat(fname) | 186 | st, err := os.Stat(fname) | |
187 | return err == nil && st.Mode().IsRegular() | 187 | return err == nil && st.Mode().IsRegular() | |
188 | } | 188 | } | |
189 | 189 | |||
190 | func dirExists(fname string) bool { | 190 | func dirExists(fname string) bool { | |
191 | st, err := os.Stat(fname) | 191 | st, err := os.Stat(fname) | |
192 | return err == nil && st.Mode().IsDir() | 192 | return err == nil && st.Mode().IsDir() | |
193 | } | 193 | } | |
194 | 194 | |||
195 | var res = make(map[string]*regexp.Regexp) | 195 | type RegexPattern string | |
196 | 196 | |||
197 | func regcomp(re string) *regexp.Regexp { | 197 | var res = make(map[RegexPattern]*regexp.Regexp) | |
198 | ||||
199 | func regcomp(re RegexPattern) *regexp.Regexp { | |||
198 | cre := res[re] | 200 | cre := res[re] | |
199 | if cre == nil { | 201 | if cre == nil { | |
200 | cre = regexp.MustCompile(re) | 202 | cre = regexp.MustCompile(string(re)) | |
201 | res[re] = cre | 203 | res[re] = cre | |
202 | } | 204 | } | |
203 | return cre | 205 | return cre | |
204 | } | 206 | } | |
205 | 207 | |||
206 | func match(s, re string) []string { | 208 | func match(s string, re RegexPattern) []string { | |
207 | if !G.opts.Profiling { | 209 | if !G.opts.Profiling { | |
208 | return regcomp(re).FindStringSubmatch(s) | 210 | return regcomp(re).FindStringSubmatch(s) | |
209 | } | 211 | } | |
210 | 212 | |||
211 | before := time.Now() | 213 | before := time.Now() | |
212 | immediatelyBefore := time.Now() | 214 | immediatelyBefore := time.Now() | |
213 | m := regcomp(re).FindStringSubmatch(s) | 215 | m := regcomp(re).FindStringSubmatch(s) | |
214 | after := time.Now() | 216 | after := time.Now() | |
215 | 217 | |||
216 | delay := immediatelyBefore.UnixNano() - before.UnixNano() | 218 | delay := immediatelyBefore.UnixNano() - before.UnixNano() | |
217 | timeTaken := after.UnixNano() - immediatelyBefore.UnixNano() - delay | 219 | timeTaken := after.UnixNano() - immediatelyBefore.UnixNano() - delay | |
218 | 220 | |||
219 | G.retime.Add(re, int(timeTaken)) | 221 | G.retime.Add(string(re), int(timeTaken)) | |
220 | if m != nil { | 222 | if m != nil { | |
221 | G.rematch.Add(re, 1) | 223 | G.rematch.Add(string(re), 1) | |
222 | } else { | 224 | } else { | |
223 | G.renomatch.Add(re, 1) | 225 | G.renomatch.Add(string(re), 1) | |
224 | } | 226 | } | |
225 | return m | 227 | return m | |
226 | } | 228 | } | |
227 | 229 | |||
228 | func matches(s, re string) bool { | 230 | func matches(s string, re RegexPattern) bool { | |
229 | matches := regcomp(re).MatchString(s) | 231 | matches := regcomp(re).MatchString(s) | |
230 | if G.opts.Profiling { | 232 | if G.opts.Profiling { | |
231 | if matches { | 233 | if matches { | |
232 | G.rematch.Add(re, 1) | 234 | G.rematch.Add(string(re), 1) | |
233 | } else { | 235 | } else { | |
234 | G.renomatch.Add(re, 1) | 236 | G.renomatch.Add(string(re), 1) | |
235 | } | 237 | } | |
236 | } | 238 | } | |
237 | return matches | 239 | return matches | |
238 | } | 240 | } | |
239 | 241 | |||
240 | func matchn(s, re string, n int) []string { | 242 | func matchn(s string, re RegexPattern, n int) []string { | |
241 | if m := match(s, re); m != nil { | 243 | if m := match(s, re); m != nil { | |
242 | if len(m) != 1+n { | 244 | if len(m) != 1+n { | |
243 | panic(fmt.Sprintf("expected match%d, got match%d for %q", len(m)-1, n, re)) | 245 | panic(fmt.Sprintf("expected match%d, got match%d for %q", len(m)-1, n, re)) | |
244 | } | 246 | } | |
245 | return m | 247 | return m | |
246 | } | 248 | } | |
247 | return nil | 249 | return nil | |
248 | } | 250 | } | |
249 | 251 | |||
250 | func match1(s, re string) (matched bool, m1 string) { | 252 | func match1(s string, re RegexPattern) (matched bool, m1 string) { | |
251 | if m := matchn(s, re, 1); m != nil { | 253 | if m := matchn(s, re, 1); m != nil { | |
252 | return true, m[1] | 254 | return true, m[1] | |
253 | } | 255 | } | |
254 | return | 256 | return | |
255 | } | 257 | } | |
256 | func match2(s, re string) (matched bool, m1, m2 string) { | 258 | func match2(s string, re RegexPattern) (matched bool, m1, m2 string) { | |
257 | if m := matchn(s, re, 2); m != nil { | 259 | if m := matchn(s, re, 2); m != nil { | |
258 | return true, m[1], m[2] | 260 | return true, m[1], m[2] | |
259 | } | 261 | } | |
260 | return | 262 | return | |
261 | } | 263 | } | |
262 | func match3(s, re string) (matched bool, m1, m2, m3 string) { | 264 | func match3(s string, re RegexPattern) (matched bool, m1, m2, m3 string) { | |
263 | if m := matchn(s, re, 3); m != nil { | 265 | if m := matchn(s, re, 3); m != nil { | |
264 | return true, m[1], m[2], m[3] | 266 | return true, m[1], m[2], m[3] | |
265 | } | 267 | } | |
266 | return | 268 | return | |
267 | } | 269 | } | |
268 | func match4(s, re string) (matched bool, m1, m2, m3, m4 string) { | 270 | func match4(s string, re RegexPattern) (matched bool, m1, m2, m3, m4 string) { | |
269 | if m := matchn(s, re, 4); m != nil { | 271 | if m := matchn(s, re, 4); m != nil { | |
270 | return true, m[1], m[2], m[3], m[4] | 272 | return true, m[1], m[2], m[3], m[4] | |
271 | } | 273 | } | |
272 | return | 274 | return | |
273 | } | 275 | } | |
274 | func match5(s, re string) (matched bool, m1, m2, m3, m4, m5 string) { | 276 | func match5(s string, re RegexPattern) (matched bool, m1, m2, m3, m4, m5 string) { | |
275 | if m := matchn(s, re, 5); m != nil { | 277 | if m := matchn(s, re, 5); m != nil { | |
276 | return true, m[1], m[2], m[3], m[4], m[5] | 278 | return true, m[1], m[2], m[3], m[4], m[5] | |
277 | } | 279 | } | |
278 | return | 280 | return | |
279 | } | 281 | } | |
280 | 282 | |||
281 | func replaceFirst(s, re, replacement string) ([]string, string) { | 283 | func replaceFirst(s string, re RegexPattern, replacement string) ([]string, string) { | |
282 | if G.opts.Debug { | 284 | if G.opts.Debug { | |
283 | defer tracecall(s, re, replacement)() | 285 | defer tracecall(s, re, replacement)() | |
284 | } | 286 | } | |
285 | 287 | |||
286 | if m := regcomp(re).FindStringSubmatchIndex(s); m != nil { | 288 | if m := regcomp(re).FindStringSubmatchIndex(s); m != nil { | |
287 | replaced := s[:m[0]] + replacement + s[m[1]:] | 289 | replaced := s[:m[0]] + replacement + s[m[1]:] | |
288 | mm := make([]string, len(m)/2) | 290 | mm := make([]string, len(m)/2) | |
289 | for i := 0; i < len(m); i += 2 { | 291 | for i := 0; i < len(m); i += 2 { | |
290 | mm[i/2] = s[negToZero(m[i]):negToZero(m[i+1])] | 292 | mm[i/2] = s[negToZero(m[i]):negToZero(m[i+1])] | |
291 | } | 293 | } | |
292 | return mm, replaced | 294 | return mm, replaced | |
293 | } | 295 | } | |
294 | return nil, s | 296 | return nil, s | |
@@ -337,30 +339,30 @@ func (pr *PrefixReplacer) AdvanceHspace( | @@ -337,30 +339,30 @@ func (pr *PrefixReplacer) AdvanceHspace( | |||
337 | i := 0 | 339 | i := 0 | |
338 | rest := pr.rest | 340 | rest := pr.rest | |
339 | for i < len(rest) && (rest[i] == ' ' || rest[i] == '\t') { | 341 | for i < len(rest) && (rest[i] == ' ' || rest[i] == '\t') { | |
340 | i++ | 342 | i++ | |
341 | } | 343 | } | |
342 | if i != 0 { | 344 | if i != 0 { | |
343 | pr.s = pr.rest[:i] | 345 | pr.s = pr.rest[:i] | |
344 | pr.rest = pr.rest[i:] | 346 | pr.rest = pr.rest[i:] | |
345 | return true | 347 | return true | |
346 | } | 348 | } | |
347 | return false | 349 | return false | |
348 | } | 350 | } | |
349 | 351 | |||
350 | func (pr *PrefixReplacer) AdvanceRegexp(re string) bool { | 352 | func (pr *PrefixReplacer) AdvanceRegexp(re RegexPattern) bool { | |
351 | pr.m = nil | 353 | pr.m = nil | |
352 | pr.s = "" | 354 | pr.s = "" | |
353 | if !hasPrefix(re, "^") { | 355 | if !hasPrefix(string(re), "^") { | |
354 | panic(fmt.Sprintf("PrefixReplacer.AdvanceRegexp: regular expression %q must have prefix %q.", re, "^")) | 356 | panic(fmt.Sprintf("PrefixReplacer.AdvanceRegexp: regular expression %q must have prefix %q.", re, "^")) | |
355 | } | 357 | } | |
356 | if G.Testing && matches("", re) { | 358 | if G.Testing && matches("", re) { | |
357 | panic(fmt.Sprintf("PrefixReplacer.AdvanceRegexp: the empty string must not match the regular expression %q.", re)) | 359 | panic(fmt.Sprintf("PrefixReplacer.AdvanceRegexp: the empty string must not match the regular expression %q.", re)) | |
358 | } | 360 | } | |
359 | if m := match(pr.rest, re); m != nil { | 361 | if m := match(pr.rest, re); m != nil { | |
360 | if G.opts.Debug { | 362 | if G.opts.Debug { | |
361 | traceStep("PrefixReplacer.AdvanceRegexp(%q, %q, %q)", pr.rest, re, m[0]) | 363 | traceStep("PrefixReplacer.AdvanceRegexp(%q, %q, %q)", pr.rest, re, m[0]) | |
362 | } | 364 | } | |
363 | pr.rest = pr.rest[len(m[0]):] | 365 | pr.rest = pr.rest[len(m[0]):] | |
364 | pr.m = m | 366 | pr.m = m | |
365 | pr.s = m[0] | 367 | pr.s = m[0] | |
366 | return true | 368 | return true | |
@@ -520,27 +522,27 @@ func ref(rv interface{}) Ref { | @@ -520,27 +522,27 @@ func ref(rv interface{}) Ref { | |||
520 | } | 522 | } | |
521 | 523 | |||
522 | func (r Ref) String() string { | 524 | func (r Ref) String() string { | |
523 | ptr := reflect.ValueOf(r.intf) | 525 | ptr := reflect.ValueOf(r.intf) | |
524 | ref := reflect.Indirect(ptr) | 526 | ref := reflect.Indirect(ptr) | |
525 | return fmt.Sprintf("%v", ref) | 527 | return fmt.Sprintf("%v", ref) | |
526 | } | 528 | } | |
527 | 529 | |||
528 | // Emulates make(1)’s :S substitution operator. | 530 | // Emulates make(1)’s :S substitution operator. | |
529 | func mkopSubst(s string, left bool, from string, right bool, to string, flags string) string { | 531 | func mkopSubst(s string, left bool, from string, right bool, to string, flags string) string { | |
530 | if G.opts.Debug { | 532 | if G.opts.Debug { | |
531 | defer tracecall(s, left, from, right, to, flags)() | 533 | defer tracecall(s, left, from, right, to, flags)() | |
532 | } | 534 | } | |
533 | re := ifelseStr(left, "^", "") + regexp.QuoteMeta(from) + ifelseStr(right, "$", "") | 535 | re := RegexPattern(ifelseStr(left, "^", "") + regexp.QuoteMeta(from) + ifelseStr(right, "$", "")) | |
534 | done := false | 536 | done := false | |
535 | gflag := contains(flags, "g") | 537 | gflag := contains(flags, "g") | |
536 | return regcomp(re).ReplaceAllStringFunc(s, func(match string) string { | 538 | return regcomp(re).ReplaceAllStringFunc(s, func(match string) string { | |
537 | if gflag || !done { | 539 | if gflag || !done { | |
538 | done = !gflag | 540 | done = !gflag | |
539 | return to | 541 | return to | |
540 | } | 542 | } | |
541 | return match | 543 | return match | |
542 | }) | 544 | }) | |
543 | } | 545 | } | |
544 | 546 | |||
545 | func relpath(from, to string) string { | 547 | func relpath(from, to string) string { | |
546 | absFrom, err1 := filepath.Abs(from) | 548 | absFrom, err1 := filepath.Abs(from) | |
@@ -577,27 +579,27 @@ func cleanpath(fname string) string { | @@ -577,27 +579,27 @@ func cleanpath(fname string) string { | |||
577 | } | 579 | } | |
578 | for contains(tmp, "//") { | 580 | for contains(tmp, "//") { | |
579 | tmp = strings.Replace(tmp, "//", "/", -1) | 581 | tmp = strings.Replace(tmp, "//", "/", -1) | |
580 | } | 582 | } | |
581 | tmp = reReplaceRepeatedly(tmp, `/[^.][^/]*/[^.][^/]*/\.\./\.\./`, "/") | 583 | tmp = reReplaceRepeatedly(tmp, `/[^.][^/]*/[^.][^/]*/\.\./\.\./`, "/") | |
582 | tmp = strings.TrimSuffix(tmp, "/") | 584 | tmp = strings.TrimSuffix(tmp, "/") | |
583 | return tmp | 585 | return tmp | |
584 | } | 586 | } | |
585 | 587 | |||
586 | func containsVarRef(s string) bool { | 588 | func containsVarRef(s string) bool { | |
587 | return contains(s, "${") | 589 | return contains(s, "${") | |
588 | } | 590 | } | |
589 | 591 | |||
590 | func reReplaceRepeatedly(from string, re string, to string) string { | 592 | func reReplaceRepeatedly(from string, re RegexPattern, to string) string { | |
591 | replaced := regcomp(re).ReplaceAllString(from, to) | 593 | replaced := regcomp(re).ReplaceAllString(from, to) | |
592 | if replaced != from { | 594 | if replaced != from { | |
593 | return reReplaceRepeatedly(replaced, re, to) | 595 | return reReplaceRepeatedly(replaced, re, to) | |
594 | } | 596 | } | |
595 | return replaced | 597 | return replaced | |
596 | } | 598 | } | |
597 | 599 | |||
598 | type Histogram struct { | 600 | type Histogram struct { | |
599 | histo map[string]int | 601 | histo map[string]int | |
600 | } | 602 | } | |
601 | 603 | |||
602 | func NewHistogram() *Histogram { | 604 | func NewHistogram() *Histogram { | |
603 | h := new(Histogram) | 605 | h := new(Histogram) |
@@ -247,27 +247,27 @@ var ( | @@ -247,27 +247,27 @@ var ( | |||
247 | CheckvarRelativePkgPath = &VarChecker{"RelativePkgPath", (*VartypeCheck).RelativePkgPath} | 247 | CheckvarRelativePkgPath = &VarChecker{"RelativePkgPath", (*VartypeCheck).RelativePkgPath} | |
248 | CheckvarRestricted = &VarChecker{"Restricted", (*VartypeCheck).Restricted} | 248 | CheckvarRestricted = &VarChecker{"Restricted", (*VartypeCheck).Restricted} | |
249 | CheckvarSedCommand = &VarChecker{"SedCommand", (*VartypeCheck).SedCommand} | 249 | CheckvarSedCommand = &VarChecker{"SedCommand", (*VartypeCheck).SedCommand} | |
250 | CheckvarSedCommands = &VarChecker{"SedCommands", nil} | 250 | CheckvarSedCommands = &VarChecker{"SedCommands", nil} | |
251 | CheckvarShellCommand = &VarChecker{"ShellCommand", nil} | 251 | CheckvarShellCommand = &VarChecker{"ShellCommand", nil} | |
252 | CheckvarShellCommands = &VarChecker{"ShellCommands", nil} | 252 | CheckvarShellCommands = &VarChecker{"ShellCommands", nil} | |
253 | CheckvarShellWord = &VarChecker{"ShellWord", nil} | 253 | CheckvarShellWord = &VarChecker{"ShellWord", nil} | |
254 | CheckvarStage = &VarChecker{"Stage", (*VartypeCheck).Stage} | 254 | CheckvarStage = &VarChecker{"Stage", (*VartypeCheck).Stage} | |
255 | CheckvarString = &VarChecker{"String", (*VartypeCheck).String} | 255 | CheckvarString = &VarChecker{"String", (*VartypeCheck).String} | |
256 | CheckvarTool = &VarChecker{"Tool", (*VartypeCheck).Tool} | 256 | CheckvarTool = &VarChecker{"Tool", (*VartypeCheck).Tool} | |
257 | CheckvarUnchecked = &VarChecker{"Unchecked", (*VartypeCheck).Unchecked} | 257 | CheckvarUnchecked = &VarChecker{"Unchecked", (*VartypeCheck).Unchecked} | |
258 | CheckvarURL = &VarChecker{"URL", (*VartypeCheck).URL} | 258 | CheckvarURL = &VarChecker{"URL", (*VartypeCheck).URL} | |
259 | CheckvarUserGroupName = &VarChecker{"UserGroupName", (*VartypeCheck).UserGroupName} | 259 | CheckvarUserGroupName = &VarChecker{"UserGroupName", (*VartypeCheck).UserGroupName} | |
260 | CheckvarVarname = &VarChecker{"Varname", (*VartypeCheck).Varname} | 260 | CheckvarVariableName = &VarChecker{"VariableName", (*VartypeCheck).VariableName} | |
261 | CheckvarVersion = &VarChecker{"Version", (*VartypeCheck).Version} | 261 | CheckvarVersion = &VarChecker{"Version", (*VartypeCheck).Version} | |
262 | CheckvarWrapperReorder = &VarChecker{"WrapperReorder", (*VartypeCheck).WrapperReorder} | 262 | CheckvarWrapperReorder = &VarChecker{"WrapperReorder", (*VartypeCheck).WrapperReorder} | |
263 | CheckvarWrapperTransform = &VarChecker{"WrapperTransform", (*VartypeCheck).WrapperTransform} | 263 | CheckvarWrapperTransform = &VarChecker{"WrapperTransform", (*VartypeCheck).WrapperTransform} | |
264 | CheckvarWrkdirSubdirectory = &VarChecker{"WrkdirSubdirectory", (*VartypeCheck).WrkdirSubdirectory} | 264 | CheckvarWrkdirSubdirectory = &VarChecker{"WrkdirSubdirectory", (*VartypeCheck).WrkdirSubdirectory} | |
265 | CheckvarWrksrcSubdirectory = &VarChecker{"WrksrcSubdirectory", (*VartypeCheck).WrksrcSubdirectory} | 265 | CheckvarWrksrcSubdirectory = &VarChecker{"WrksrcSubdirectory", (*VartypeCheck).WrksrcSubdirectory} | |
266 | CheckvarYes = &VarChecker{"Yes", (*VartypeCheck).Yes} | 266 | CheckvarYes = &VarChecker{"Yes", (*VartypeCheck).Yes} | |
267 | CheckvarYesNo = &VarChecker{"YesNo", (*VartypeCheck).YesNo} | 267 | CheckvarYesNo = &VarChecker{"YesNo", (*VartypeCheck).YesNo} | |
268 | CheckvarYesNoIndirectly = &VarChecker{"YesNoIndirectly", (*VartypeCheck).YesNoIndirectly} | 268 | CheckvarYesNoIndirectly = &VarChecker{"YesNoIndirectly", (*VartypeCheck).YesNoIndirectly} | |
269 | ) | 269 | ) | |
270 | 270 | |||
271 | func init() { // Necessary due to circular dependency | 271 | func init() { // Necessary due to circular dependency | |
272 | CheckvarSedCommands.checker = (*VartypeCheck).SedCommands | 272 | CheckvarSedCommands.checker = (*VartypeCheck).SedCommands | |
273 | CheckvarShellCommand.checker = (*VartypeCheck).ShellCommand | 273 | CheckvarShellCommand.checker = (*VartypeCheck).ShellCommand |
@@ -1,31 +1,30 @@ | @@ -1,31 +1,30 @@ | |||
1 | package main | 1 | package main | |
2 | 2 | |||
3 | import ( | 3 | import ( | |
4 | "path" | 4 | "path" | |
5 | "sort" | 5 | "sort" | |
6 | "strings" | 6 | "strings" | |
7 | ) | 7 | ) | |
8 | 8 | |||
9 | type VartypeCheck struct { | 9 | type VartypeCheck struct { | |
10 | mkline *MkLine | 10 | MkLine *MkLine | |
11 | line *Line | 11 | Line *Line | |
12 | varname string | 12 | Varname string | |
13 | op MkOperator | 13 | Op MkOperator | |
14 | value string | 14 | Value string | |
15 | valueNovar string | 15 | ValueNoVar string | |
16 | comment string | 16 | MkComment string | |
17 | listContext bool | 17 | Guessed bool // Whether the type definition is guessed (based on the variable name) or explicitly defined (see vardefs.go). | |
18 | guessed bool // Whether the type definition is guessed (based on the variable name) or explicitly defined (see vardefs.go). | |||
19 | } | 18 | } | |
20 | 19 | |||
21 | type MkOperator uint8 | 20 | type MkOperator uint8 | |
22 | 21 | |||
23 | const ( | 22 | const ( | |
24 | opAssign MkOperator = iota // = | 23 | opAssign MkOperator = iota // = | |
25 | opAssignShell // != | 24 | opAssignShell // != | |
26 | opAssignEval // := | 25 | opAssignEval // := | |
27 | opAssignAppend // += | 26 | opAssignAppend // += | |
28 | opAssignDefault // ?= | 27 | opAssignDefault // ?= | |
29 | opUse // | 28 | opUse // | |
30 | opUseMatch // Used in the :M operator | 29 | opUseMatch // Used in the :M operator | |
31 | ) | 30 | ) | |
@@ -99,110 +98,110 @@ func enumFromRe(re string) *VarChecker { | @@ -99,110 +98,110 @@ func enumFromRe(re string) *VarChecker { | |||
99 | } | 98 | } | |
100 | 99 | |||
101 | var ( | 100 | var ( | |
102 | enumMachineOpsys = enumFromRe(reMachineOpsys) | 101 | enumMachineOpsys = enumFromRe(reMachineOpsys) | |
103 | enumMachineArch = enumFromRe(reMachineArch) | 102 | enumMachineArch = enumFromRe(reMachineArch) | |
104 | enumMachineGnuArch = enumFromRe(reMachineGnuArch) | 103 | enumMachineGnuArch = enumFromRe(reMachineGnuArch) | |
105 | enumEmulOpsys = enumFromRe(reEmulOpsys) | 104 | enumEmulOpsys = enumFromRe(reEmulOpsys) | |
106 | enumEmulArch = enumFromRe(reEmulArch) | 105 | enumEmulArch = enumFromRe(reEmulArch) | |
107 | enumMachineGnuPlatformOpsys = enumEmulOpsys | 106 | enumMachineGnuPlatformOpsys = enumEmulOpsys | |
108 | ) | 107 | ) | |
109 | 108 | |||
110 | func (cv *VartypeCheck) AwkCommand() { | 109 | func (cv *VartypeCheck) AwkCommand() { | |
111 | if G.opts.Debug { | 110 | if G.opts.Debug { | |
112 | traceStep1("Unchecked AWK command: %q", cv.value) | 111 | traceStep1("Unchecked AWK command: %q", cv.Value) | |
113 | } | 112 | } | |
114 | } | 113 | } | |
115 | 114 | |||
116 | func (cv *VartypeCheck) BasicRegularExpression() { | 115 | func (cv *VartypeCheck) BasicRegularExpression() { | |
117 | if G.opts.Debug { | 116 | if G.opts.Debug { | |
118 | traceStep1("Unchecked basic regular expression: %q", cv.value) | 117 | traceStep1("Unchecked basic regular expression: %q", cv.Value) | |
119 | } | 118 | } | |
120 | } | 119 | } | |
121 | 120 | |||
122 | func (cv *VartypeCheck) BuildlinkDepmethod() { | 121 | func (cv *VartypeCheck) BuildlinkDepmethod() { | |
123 | if !containsVarRef(cv.value) && cv.value != "build" && cv.value != "full" { | 122 | if !containsVarRef(cv.Value) && cv.Value != "build" && cv.Value != "full" { | |
124 | cv.line.Warn1("Invalid dependency method %q. Valid methods are \"build\" or \"full\".", cv.value) | 123 | cv.Line.Warn1("Invalid dependency method %q. Valid methods are \"build\" or \"full\".", cv.Value) | |
125 | } | 124 | } | |
126 | } | 125 | } | |
127 | 126 | |||
128 | func (cv *VartypeCheck) Category() { | 127 | func (cv *VartypeCheck) Category() { | |
129 | if cv.value != "wip" && fileExists(G.CurrentDir+"/"+G.CurPkgsrcdir+"/"+cv.value+"/Makefile") { | 128 | if cv.Value != "wip" && fileExists(G.CurrentDir+"/"+G.CurPkgsrcdir+"/"+cv.Value+"/Makefile") { | |
130 | return | 129 | return | |
131 | } | 130 | } | |
132 | switch cv.value { | 131 | switch cv.Value { | |
133 | case | 132 | case | |
134 | "chinese", "crosspkgtools", | 133 | "chinese", "crosspkgtools", | |
135 | "gnome", "gnustep", | 134 | "gnome", "gnustep", | |
136 | "japanese", "java", | 135 | "japanese", "java", | |
137 | "kde", "korean", | 136 | "kde", "korean", | |
138 | "linux", "local", | 137 | "linux", "local", | |
139 | "packages", "perl5", "plan9", "python", | 138 | "packages", "perl5", "plan9", "python", | |
140 | "ruby", | 139 | "ruby", | |
141 | "scm", | 140 | "scm", | |
142 | "tcl", "tk", | 141 | "tcl", "tk", | |
143 | "windowmaker", | 142 | "windowmaker", | |
144 | "xmms": | 143 | "xmms": | |
145 | default: | 144 | default: | |
146 | cv.line.Error1("Invalid category %q.", cv.value) | 145 | cv.Line.Error1("Invalid category %q.", cv.Value) | |
147 | } | 146 | } | |
148 | } | 147 | } | |
149 | 148 | |||
150 | // A single option to the C/C++ compiler. | 149 | // A single option to the C/C++ compiler. | |
151 | func (cv *VartypeCheck) CFlag() { | 150 | func (cv *VartypeCheck) CFlag() { | |
152 | if cv.op == opUseMatch { | 151 | if cv.Op == opUseMatch { | |
153 | return | 152 | return | |
154 | } | 153 | } | |
155 | cflag := cv.value | 154 | cflag := cv.Value | |
156 | switch { | 155 | switch { | |
157 | case matches(cflag, `^-[DILOUWfgm]`), | 156 | case matches(cflag, `^-[DILOUWfgm]`), | |
158 | hasPrefix(cflag, "-std="), | 157 | hasPrefix(cflag, "-std="), | |
159 | cflag == "-c99", | 158 | cflag == "-c99", | |
160 | cflag == "-c", | 159 | cflag == "-c", | |
161 | cflag == "-no-integrated-as", | 160 | cflag == "-no-integrated-as", | |
162 | cflag == "-pthread", | 161 | cflag == "-pthread", | |
163 | hasPrefix(cflag, "`") && hasSuffix(cflag, "`"), | 162 | hasPrefix(cflag, "`") && hasSuffix(cflag, "`"), | |
164 | containsVarRef(cflag): | 163 | containsVarRef(cflag): | |
165 | return | 164 | return | |
166 | case hasPrefix(cflag, "-"): | 165 | case hasPrefix(cflag, "-"): | |
167 | cv.line.Warn1("Unknown compiler flag %q.", cflag) | 166 | cv.Line.Warn1("Unknown compiler flag %q.", cflag) | |
168 | default: | 167 | default: | |
169 | cv.line.Warn1("Compiler flag %q should start with a hyphen.", cflag) | 168 | cv.Line.Warn1("Compiler flag %q should start with a hyphen.", cflag) | |
170 | } | 169 | } | |
171 | } | 170 | } | |
172 | 171 | |||
173 | // The single-line description of the package. | 172 | // The single-line description of the package. | |
174 | func (cv *VartypeCheck) Comment() { | 173 | func (cv *VartypeCheck) Comment() { | |
175 | line, value := cv.line, cv.value | 174 | line, value := cv.Line, cv.Value | |
176 | 175 | |||
177 | if value == "TODO: Short description of the package" { // See pkgtools/url2pkg/files/url2pkg.pl, keyword "COMMENT". | 176 | if value == "TODO: Short description of the package" { // See pkgtools/url2pkg/files/url2pkg.pl, keyword "COMMENT". | |
178 | line.Error0("COMMENT must be set.") | 177 | line.Error0("COMMENT must be set.") | |
179 | } | 178 | } | |
180 | if m, first := match1(value, `^(?i)(a|an)\s`); m { | 179 | if m, first := match1(value, `^(?i)(a|an)\s`); m { | |
181 | line.Warn1("COMMENT should not begin with %q.", first) | 180 | line.Warn1("COMMENT should not begin with %q.", first) | |
182 | } | 181 | } | |
183 | if matches(value, `^[a-z]`) { | 182 | if matches(value, `^[a-z]`) { | |
184 | line.Warn0("COMMENT should start with a capital letter.") | 183 | line.Warn0("COMMENT should start with a capital letter.") | |
185 | } | 184 | } | |
186 | if hasSuffix(value, ".") { | 185 | if hasSuffix(value, ".") { | |
187 | line.Warn0("COMMENT should not end with a period.") | 186 | line.Warn0("COMMENT should not end with a period.") | |
188 | } | 187 | } | |
189 | if len(value) > 70 { | 188 | if len(value) > 70 { | |
190 | line.Warn0("COMMENT should not be longer than 70 characters.") | 189 | line.Warn0("COMMENT should not be longer than 70 characters.") | |
191 | } | 190 | } | |
192 | } | 191 | } | |
193 | 192 | |||
194 | func (cv *VartypeCheck) Dependency() { | 193 | func (cv *VartypeCheck) Dependency() { | |
195 | line, value := cv.line, cv.value | 194 | line, value := cv.Line, cv.Value | |
196 | 195 | |||
197 | parser := NewParser(line, value, false) | 196 | parser := NewParser(line, value, false) | |
198 | deppat := parser.Dependency() | 197 | deppat := parser.Dependency() | |
199 | if deppat != nil && deppat.wildcard == "" && (parser.Rest() == "{,nb*}" || parser.Rest() == "{,nb[0-9]*}") { | 198 | if deppat != nil && deppat.wildcard == "" && (parser.Rest() == "{,nb*}" || parser.Rest() == "{,nb[0-9]*}") { | |
200 | line.Warn0("Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.") | 199 | line.Warn0("Dependency patterns of the form pkgbase>=1.0 don't need the \"{,nb*}\" extension.") | |
201 | Explain4( | 200 | Explain4( | |
202 | "The \"{,nb*}\" extension is only necessary for dependencies of the", | 201 | "The \"{,nb*}\" extension is only necessary for dependencies of the", | |
203 | "form \"pkgbase-1.2\", since the pattern \"pkgbase-1.2\" doesn't match", | 202 | "form \"pkgbase-1.2\", since the pattern \"pkgbase-1.2\" doesn't match", | |
204 | "the version \"pkgbase-1.2nb5\". For dependency patterns using the", | 203 | "the version \"pkgbase-1.2nb5\". For dependency patterns using the", | |
205 | "comparison operators, this is not necessary.") | 204 | "comparison operators, this is not necessary.") | |
206 | 205 | |||
207 | } else if deppat == nil || !parser.EOF() { | 206 | } else if deppat == nil || !parser.EOF() { | |
208 | line.Warn1("Unknown dependency pattern %q.", value) | 207 | line.Warn1("Unknown dependency pattern %q.", value) | |
@@ -248,350 +247,346 @@ func (cv *VartypeCheck) Dependency() { | @@ -248,350 +247,346 @@ func (cv *VartypeCheck) Dependency() { | |||
248 | if nocclasses := regcomp(`\[[\d-]+\]`).ReplaceAllString(wildcard, ""); contains(nocclasses, "-") { | 247 | if nocclasses := regcomp(`\[[\d-]+\]`).ReplaceAllString(wildcard, ""); contains(nocclasses, "-") { | |
249 | line.Warn1("The version pattern %q should not contain a hyphen.", wildcard) | 248 | line.Warn1("The version pattern %q should not contain a hyphen.", wildcard) | |
250 | Explain( | 249 | Explain( | |
251 | "Pkgsrc interprets package names with version numbers like this:", | 250 | "Pkgsrc interprets package names with version numbers like this:", | |
252 | "", | 251 | "", | |
253 | "\t\"foo-2.0-2.1.x\" => pkgbase \"foo\", version \"2.0-2.1.x\"", | 252 | "\t\"foo-2.0-2.1.x\" => pkgbase \"foo\", version \"2.0-2.1.x\"", | |
254 | "", | 253 | "", | |
255 | "To make the \"2.0\" above part of the package basename, the hyphen", | 254 | "To make the \"2.0\" above part of the package basename, the hyphen", | |
256 | "must be omitted, so the full package name becomes \"foo2.0-2.1.x\".") | 255 | "must be omitted, so the full package name becomes \"foo2.0-2.1.x\".") | |
257 | } | 256 | } | |
258 | } | 257 | } | |
259 | 258 | |||
260 | func (cv *VartypeCheck) DependencyWithPath() { | 259 | func (cv *VartypeCheck) DependencyWithPath() { | |
261 | line, value := cv.line, cv.value | 260 | line, value := cv.Line, cv.Value | |
262 | if value != cv.valueNovar { | 261 | if value != cv.ValueNoVar { | |
263 | return // It's probably not worth checking this. | 262 | return // It's probably not worth checking this. | |
264 | } | 263 | } | |
265 | 264 | |||
266 | if m, pattern, relpath, pkg := match3(value, `(.*):(\.\./\.\./[^/]+/([^/]+))$`); m { | 265 | if m, pattern, relpath, pkg := match3(value, `(.*):(\.\./\.\./[^/]+/([^/]+))$`); m { | |
267 | cv.mkline.CheckRelativePkgdir(relpath) | 266 | cv.MkLine.CheckRelativePkgdir(relpath) | |
268 | 267 | |||
269 | switch pkg { | 268 | switch pkg { | |
270 | case "msgfmt", "gettext": | 269 | case "msgfmt", "gettext": | |
271 | line.Warn0("Please use USE_TOOLS+=msgfmt instead of this dependency.") | 270 | line.Warn0("Please use USE_TOOLS+=msgfmt instead of this dependency.") | |
272 | case "perl5": | 271 | case "perl5": | |
273 | line.Warn0("Please use USE_TOOLS+=perl:run instead of this dependency.") | 272 | line.Warn0("Please use USE_TOOLS+=perl:run instead of this dependency.") | |
274 | case "gmake": | 273 | case "gmake": | |
275 | line.Warn0("Please use USE_TOOLS+=gmake instead of this dependency.") | 274 | line.Warn0("Please use USE_TOOLS+=gmake instead of this dependency.") | |
276 | } | 275 | } | |
277 | 276 | |||
278 | cv.mkline.CheckVartypePrimitive(cv.varname, CheckvarDependency, cv.op, pattern, cv.comment, cv.listContext, cv.guessed) | 277 | cv.MkLine.CheckVartypePrimitive(cv.Varname, CheckvarDependency, cv.Op, pattern, cv.MkComment, cv.Guessed) | |
279 | return | 278 | return | |
280 | } | 279 | } | |
281 | 280 | |||
282 | if matches(value, `:\.\./[^/]+$`) { | 281 | if matches(value, `:\.\./[^/]+$`) { | |
283 | line.Warn0("Dependencies should have the form \"../../category/package\".") | 282 | line.Warn0("Dependencies should have the form \"../../category/package\".") | |
284 | cv.mkline.explainRelativeDirs() | 283 | cv.MkLine.explainRelativeDirs() | |
285 | return | 284 | return | |
286 | } | 285 | } | |
287 | 286 | |||
288 | line.Warn1("Unknown dependency pattern with path %q.", value) | 287 | line.Warn1("Unknown dependency pattern with path %q.", value) | |
289 | Explain4( | 288 | Explain4( | |
290 | "Examples for valid dependency patterns with path are:", | 289 | "Examples for valid dependency patterns with path are:", | |
291 | " package-[0-9]*:../../category/package", | 290 | " package-[0-9]*:../../category/package", | |
292 | " package>=3.41:../../category/package", | 291 | " package>=3.41:../../category/package", | |
293 | " package-2.718:../../category/package") | 292 | " package-2.718:../../category/package") | |
294 | } | 293 | } | |
295 | 294 | |||
296 | func (cv *VartypeCheck) DistSuffix() { | 295 | func (cv *VartypeCheck) DistSuffix() { | |
297 | if cv.value == ".tar.gz" { | 296 | if cv.Value == ".tar.gz" { | |
298 | cv.line.Note1("%s is \".tar.gz\" by default, so this definition may be redundant.", cv.varname) | 297 | cv.Line.Note1("%s is \".tar.gz\" by default, so this definition may be redundant.", cv.Varname) | |
299 | } | 298 | } | |
300 | } | 299 | } | |
301 | 300 | |||
302 | func (cv *VartypeCheck) EmulPlatform() { | 301 | func (cv *VartypeCheck) EmulPlatform() { | |
303 | const rePart = `(?:\[[^\]]+\]|[^-\[])+` | 302 | const rePart = `(?:\[[^\]]+\]|[^-\[])+` | |
304 | const rePair = `^(` + rePart + `)-(` + rePart + `)$` | 303 | const rePair = `^(` + rePart + `)-(` + rePart + `)$` | |
305 | if m, opsysPattern, archPattern := match2(cv.value, rePair); m { | 304 | if m, opsysPattern, archPattern := match2(cv.Value, rePair); m { | |
306 | opsysCv := &VartypeCheck{ | 305 | opsysCv := &VartypeCheck{ | |
307 | cv.mkline, | 306 | cv.MkLine, | |
308 | cv.line, | 307 | cv.Line, | |
309 | "the operating system part of " + cv.varname, | 308 | "the operating system part of " + cv.Varname, | |
310 | cv.op, | 309 | cv.Op, | |
311 | opsysPattern, | 310 | opsysPattern, | |
312 | opsysPattern, | 311 | opsysPattern, | |
313 | cv.comment, | 312 | cv.MkComment, | |
314 | cv.listContext, | 313 | cv.Guessed} | |
315 | cv.guessed} | |||
316 | enumEmulOpsys.checker(opsysCv) | 314 | enumEmulOpsys.checker(opsysCv) | |
317 | 315 | |||
318 | // no check for os_version | 316 | // no check for os_version | |
319 | 317 | |||
320 | archCv := &VartypeCheck{ | 318 | archCv := &VartypeCheck{ | |
321 | cv.mkline, | 319 | cv.MkLine, | |
322 | cv.line, | 320 | cv.Line, | |
323 | "the hardware architecture part of " + cv.varname, | 321 | "the hardware architecture part of " + cv.Varname, | |
324 | cv.op, | 322 | cv.Op, | |
325 | archPattern, | 323 | archPattern, | |
326 | archPattern, | 324 | archPattern, | |
327 | cv.comment, | 325 | cv.MkComment, | |
328 | cv.listContext, | 326 | cv.Guessed} | |
329 | cv.guessed} | |||
330 | enumEmulArch.checker(archCv) | 327 | enumEmulArch.checker(archCv) | |
331 | } else { | 328 | } else { | |
332 | cv.line.Warn1("%q is not a valid emulation platform.", cv.value) | 329 | cv.Line.Warn1("%q is not a valid emulation platform.", cv.Value) | |
333 | Explain( | 330 | Explain( | |
334 | "An emulation platform has the form <OPSYS>-<MACHINE_ARCH>.", | 331 | "An emulation platform has the form <OPSYS>-<MACHINE_ARCH>.", | |
335 | "OPSYS is the lower-case name of the operating system, and", | 332 | "OPSYS is the lower-case name of the operating system, and", | |
336 | "MACHINE_ARCH is the hardware architecture.", | 333 | "MACHINE_ARCH is the hardware architecture.", | |
337 | "", | 334 | "", | |
338 | "Examples:", | 335 | "Examples:", | |
339 | "* linux-i386", | 336 | "* linux-i386", | |
340 | "* irix-mipsel") | 337 | "* irix-mipsel") | |
341 | } | 338 | } | |
342 | } | 339 | } | |
343 | 340 | |||
344 | func (cv *VartypeCheck) FetchURL() { | 341 | func (cv *VartypeCheck) FetchURL() { | |
345 | cv.mkline.CheckVartypePrimitive(cv.varname, CheckvarURL, cv.op, cv.value, cv.comment, cv.listContext, cv.guessed) | 342 | cv.MkLine.CheckVartypePrimitive(cv.Varname, CheckvarURL, cv.Op, cv.Value, cv.MkComment, cv.Guessed) | |
346 | 343 | |||
347 | for siteURL, siteName := range G.globalData.MasterSiteURLToVar { | 344 | for siteURL, siteName := range G.globalData.MasterSiteURLToVar { | |
348 | if hasPrefix(cv.value, siteURL) { | 345 | if hasPrefix(cv.Value, siteURL) { | |
349 | subdir := cv.value[len(siteURL):] | 346 | subdir := cv.Value[len(siteURL):] | |
350 | if hasPrefix(cv.value, "https://github.com/") { | 347 | if hasPrefix(cv.Value, "https://github.com/") { | |
351 | subdir = strings.SplitAfter(subdir, "/")[0] | 348 | subdir = strings.SplitAfter(subdir, "/")[0] | |
352 | cv.line.Warnf("Please use ${%s:=%s} instead of %q and run \"%s help topic=github\" for further tips.", | 349 | cv.Line.Warnf("Please use ${%s:=%s} instead of %q and run \"%s help topic=github\" for further tips.", | |
353 | siteName, subdir, cv.value, confMake) | 350 | siteName, subdir, cv.Value, confMake) | |
354 | } else { | 351 | } else { | |
355 | cv.line.Warnf("Please use ${%s:=%s} instead of %q.", siteName, subdir, cv.value) | 352 | cv.Line.Warnf("Please use ${%s:=%s} instead of %q.", siteName, subdir, cv.Value) | |
356 | } | 353 | } | |
357 | return | 354 | return | |
358 | } | 355 | } | |
359 | } | 356 | } | |
360 | 357 | |||
361 | if m, name, subdir := match2(cv.value, `\$\{(MASTER_SITE_[^:]*).*:=(.*)\}$`); m { | 358 | if m, name, subdir := match2(cv.Value, `\$\{(MASTER_SITE_[^:]*).*:=(.*)\}$`); m { | |
362 | if G.globalData.MasterSiteVarToURL[name] == "" { | 359 | if G.globalData.MasterSiteVarToURL[name] == "" { | |
363 | cv.line.Error1("The site %s does not exist.", name) | 360 | cv.Line.Error1("The site %s does not exist.", name) | |
364 | } | 361 | } | |
365 | if !hasSuffix(subdir, "/") { | 362 | if !hasSuffix(subdir, "/") { | |
366 | cv.line.Error1("The subdirectory in %s must end with a slash.", name) | 363 | cv.Line.Error1("The subdirectory in %s must end with a slash.", name) | |
367 | } | 364 | } | |
368 | } | 365 | } | |
369 | } | 366 | } | |
370 | 367 | |||
371 | // See Pathname | 368 | // See Pathname | |
372 | // See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_169 | 369 | // See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_169 | |
373 | func (cv *VartypeCheck) Filename() { | 370 | func (cv *VartypeCheck) Filename() { | |
374 | switch { | 371 | switch { | |
375 | case cv.op == opUseMatch: | 372 | case cv.Op == opUseMatch: | |
376 | break | 373 | break | |
377 | case contains(cv.valueNovar, "/"): | 374 | case contains(cv.ValueNoVar, "/"): | |
378 | cv.line.Warn0("A filename should not contain a slash.") | 375 | cv.Line.Warn0("A filename should not contain a slash.") | |
379 | case !matches(cv.valueNovar, `^[-0-9@A-Za-z.,_~+%]*$`): | 376 | case !matches(cv.ValueNoVar, `^[-0-9@A-Za-z.,_~+%]*$`): | |
380 | cv.line.Warn1("%q is not a valid filename.", cv.value) | 377 | cv.Line.Warn1("%q is not a valid filename.", cv.Value) | |
381 | } | 378 | } | |
382 | } | 379 | } | |
383 | 380 | |||
384 | func (cv *VartypeCheck) Filemask() { | 381 | func (cv *VartypeCheck) Filemask() { | |
385 | if cv.op == opUseMatch { | 382 | if cv.Op == opUseMatch { | |
386 | return | 383 | return | |
387 | } | 384 | } | |
388 | if !matches(cv.valueNovar, `^[-0-9A-Za-z._~+%*?]*$`) { | 385 | if !matches(cv.ValueNoVar, `^[-0-9A-Za-z._~+%*?]*$`) { | |
389 | cv.line.Warn1("%q is not a valid filename mask.", cv.value) | 386 | cv.Line.Warn1("%q is not a valid filename mask.", cv.Value) | |
390 | } | 387 | } | |
391 | } | 388 | } | |
392 | 389 | |||
393 | func (cv *VartypeCheck) FileMode() { | 390 | func (cv *VartypeCheck) FileMode() { | |
394 | switch { | 391 | switch { | |
395 | case cv.value != "" && cv.valueNovar == "": | 392 | case cv.Value != "" && cv.ValueNoVar == "": | |
396 | // Fine. | 393 | // Fine. | |
397 | case matches(cv.value, `^[0-7]{3,4}`): | 394 | case matches(cv.Value, `^[0-7]{3,4}`): | |
398 | // Fine. | 395 | // Fine. | |
399 | default: | 396 | default: | |
400 | cv.line.Warn1("Invalid file mode %q.", cv.value) | 397 | cv.Line.Warn1("Invalid file mode %q.", cv.Value) | |
401 | } | 398 | } | |
402 | } | 399 | } | |
403 | 400 | |||
404 | func (cv *VartypeCheck) Homepage() { | 401 | func (cv *VartypeCheck) Homepage() { | |
405 | cv.mkline.CheckVartypePrimitive(cv.varname, CheckvarURL, cv.op, cv.value, cv.comment, cv.listContext, cv.guessed) | 402 | cv.MkLine.CheckVartypePrimitive(cv.Varname, CheckvarURL, cv.Op, cv.Value, cv.MkComment, cv.Guessed) | |
406 | 403 | |||
407 | if m, wrong, sitename, subdir := match3(cv.value, `^(\$\{(MASTER_SITE\w+)(?::=([\w\-/]+))?\})`); m { | 404 | if m, wrong, sitename, subdir := match3(cv.Value, `^(\$\{(MASTER_SITE\w+)(?::=([\w\-/]+))?\})`); m { | |
408 | baseURL := G.globalData.MasterSiteVarToURL[sitename] | 405 | baseURL := G.globalData.MasterSiteVarToURL[sitename] | |
409 | if sitename == "MASTER_SITES" && G.Pkg != nil { | 406 | if sitename == "MASTER_SITES" && G.Pkg != nil { | |
410 | masterSites, _ := G.Pkg.varValue("MASTER_SITES") | 407 | masterSites, _ := G.Pkg.varValue("MASTER_SITES") | |
411 | if !containsVarRef(masterSites) { | 408 | if !containsVarRef(masterSites) { | |
412 | baseURL = masterSites | 409 | baseURL = masterSites | |
413 | } | 410 | } | |
414 | } | 411 | } | |
415 | fixedURL := baseURL + subdir | 412 | fixedURL := baseURL + subdir | |
416 | explain := false | 413 | explain := false | |
417 | if baseURL != "" { | 414 | if baseURL != "" { | |
418 | if !cv.line.AutofixReplace(wrong, fixedURL) { | 415 | if !cv.Line.AutofixReplace(wrong, fixedURL) { | |
419 | cv.line.Warn1("HOMEPAGE should not be defined in terms of MASTER_SITEs. Use %s directly.", fixedURL) | 416 | cv.Line.Warn1("HOMEPAGE should not be defined in terms of MASTER_SITEs. Use %s directly.", fixedURL) | |
420 | explain = true | 417 | explain = true | |
421 | } | 418 | } | |
422 | } else { | 419 | } else { | |
423 | cv.line.Warn0("HOMEPAGE should not be defined in terms of MASTER_SITEs.") | 420 | cv.Line.Warn0("HOMEPAGE should not be defined in terms of MASTER_SITEs.") | |
424 | explain = true | 421 | explain = true | |
425 | } | 422 | } | |
426 | if explain { | 423 | if explain { | |
427 | Explain( | 424 | Explain( | |
428 | "The HOMEPAGE is a single URL, while MASTER_SITES is a list of URLs.", | 425 | "The HOMEPAGE is a single URL, while MASTER_SITES is a list of URLs.", | |
429 | "As long as this list has exactly one element, this works, but as", | 426 | "As long as this list has exactly one element, this works, but as", | |
430 | "soon as another site is added, the HOMEPAGE would not be a valid", | 427 | "soon as another site is added, the HOMEPAGE would not be a valid", | |
431 | "URL anymore.", | 428 | "URL anymore.", | |
432 | "", | 429 | "", | |
433 | "Defining MASTER_SITES=${HOMEPAGE} is ok, though.") | 430 | "Defining MASTER_SITES=${HOMEPAGE} is ok, though.") | |
434 | } | 431 | } | |
435 | } | 432 | } | |
436 | } | 433 | } | |
437 | 434 | |||
438 | func (cv *VartypeCheck) Identifier() { | 435 | func (cv *VartypeCheck) Identifier() { | |
439 | if cv.op == opUseMatch { | 436 | if cv.Op == opUseMatch { | |
440 | if cv.value == cv.valueNovar && !matches(cv.value, `^[\w*?]`) { | 437 | if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^[\w*?]`) { | |
441 | cv.line.Warn2("Invalid identifier pattern %q for %s.", cv.value, cv.varname) | 438 | cv.Line.Warn2("Invalid identifier pattern %q for %s.", cv.Value, cv.Varname) | |
442 | } | 439 | } | |
443 | return | 440 | return | |
444 | } | 441 | } | |
445 | if cv.value != cv.valueNovar { | 442 | if cv.Value != cv.ValueNoVar { | |
446 | //line.logWarning("Identifiers should be given directly.") | 443 | //line.logWarning("Identifiers should be given directly.") | |
447 | } | 444 | } | |
448 | switch { | 445 | switch { | |
449 | case matches(cv.valueNovar, `^[+\-.0-9A-Z_a-z]+$`): | 446 | case matches(cv.ValueNoVar, `^[+\-.0-9A-Z_a-z]+$`): | |
450 | // Fine. | 447 | // Fine. | |
451 | case cv.value != "" && cv.valueNovar == "": | 448 | case cv.Value != "" && cv.ValueNoVar == "": | |
452 | // Don't warn here. | 449 | // Don't warn here. | |
453 | default: | 450 | default: | |
454 | cv.line.Warn1("Invalid identifier %q.", cv.value) | 451 | cv.Line.Warn1("Invalid identifier %q.", cv.Value) | |
455 | } | 452 | } | |
456 | } | 453 | } | |
457 | 454 | |||
458 | func (cv *VartypeCheck) Integer() { | 455 | func (cv *VartypeCheck) Integer() { | |
459 | if !matches(cv.value, `^\d+$`) { | 456 | if !matches(cv.Value, `^\d+$`) { | |
460 | cv.line.Warn1("Invalid integer %q.", cv.value) | 457 | cv.Line.Warn1("Invalid integer %q.", cv.Value) | |
461 | } | 458 | } | |
462 | } | 459 | } | |
463 | 460 | |||
464 | func (cv *VartypeCheck) LdFlag() { | 461 | func (cv *VartypeCheck) LdFlag() { | |
465 | if cv.op == opUseMatch { | 462 | if cv.Op == opUseMatch { | |
466 | return | 463 | return | |
467 | } | 464 | } | |
468 | ldflag := cv.value | 465 | ldflag := cv.Value | |
469 | if m, rpathFlag := match1(ldflag, `^(-Wl,(?:-R|-rpath|--rpath))`); m { | 466 | if m, rpathFlag := match1(ldflag, `^(-Wl,(?:-R|-rpath|--rpath))`); m { | |
470 | cv.line.Warn1("Please use \"${COMPILER_RPATH_FLAG}\" instead of %q.", rpathFlag) | 467 | cv.Line.Warn1("Please use \"${COMPILER_RPATH_FLAG}\" instead of %q.", rpathFlag) | |
471 | return | 468 | return | |
472 | } | 469 | } | |
473 | 470 | |||
474 | switch { | 471 | switch { | |
475 | case hasPrefix(ldflag, "-L"), | 472 | case hasPrefix(ldflag, "-L"), | |
476 | hasPrefix(ldflag, "-l"), | 473 | hasPrefix(ldflag, "-l"), | |
477 | ldflag == "-pthread", | 474 | ldflag == "-pthread", | |
478 | ldflag == "-static", | 475 | ldflag == "-static", | |
479 | hasPrefix(ldflag, "-static-"), | 476 | hasPrefix(ldflag, "-static-"), | |
480 | hasPrefix(ldflag, "-Wl,-"), | 477 | hasPrefix(ldflag, "-Wl,-"), | |
481 | hasPrefix(ldflag, "`") && hasSuffix(ldflag, "`"), | 478 | hasPrefix(ldflag, "`") && hasSuffix(ldflag, "`"), | |
482 | ldflag != cv.valueNovar: | 479 | ldflag != cv.ValueNoVar: | |
483 | return | 480 | return | |
484 | case hasPrefix(ldflag, "-"): | 481 | case hasPrefix(ldflag, "-"): | |
485 | cv.line.Warn1("Unknown linker flag %q.", cv.value) | 482 | cv.Line.Warn1("Unknown linker flag %q.", cv.Value) | |
486 | default: | 483 | default: | |
487 | cv.line.Warn1("Linker flag %q should start with a hypen.", cv.value) | 484 | cv.Line.Warn1("Linker flag %q should start with a hypen.", cv.Value) | |
488 | } | 485 | } | |
489 | } | 486 | } | |
490 | 487 | |||
491 | func (cv *VartypeCheck) License() { | 488 | func (cv *VartypeCheck) License() { | |
492 | checklineLicense(cv.mkline, cv.value) | 489 | checklineLicense(cv.MkLine, cv.Value) | |
493 | } | 490 | } | |
494 | 491 | |||
495 | func (cv *VartypeCheck) MachineGnuPlatform() { | 492 | func (cv *VartypeCheck) MachineGnuPlatform() { | |
496 | if cv.value != cv.valueNovar { | 493 | if cv.Value != cv.ValueNoVar { | |
497 | return | 494 | return | |
498 | } | 495 | } | |
499 | 496 | |||
500 | const rePart = `(?:\[[^\]]+\]|[^-\[])+` | 497 | const rePart = `(?:\[[^\]]+\]|[^-\[])+` | |
501 | const rePair = `^(` + rePart + `)-(` + rePart + `)$` | 498 | const rePair = `^(` + rePart + `)-(` + rePart + `)$` | |
502 | const reTriple = `^(` + rePart + `)-(` + rePart + `)-(` + rePart + `)$` | 499 | const reTriple = `^(` + rePart + `)-(` + rePart + `)-(` + rePart + `)$` | |
503 | 500 | |||
504 | pattern := cv.value | 501 | pattern := cv.Value | |
505 | if matches(pattern, rePair) && hasSuffix(pattern, "*") { | 502 | if matches(pattern, rePair) && hasSuffix(pattern, "*") { | |
506 | pattern += "-*" | 503 | pattern += "-*" | |
507 | } | 504 | } | |
508 | 505 | |||
509 | if m, archPattern, vendorPattern, opsysPattern := match3(pattern, reTriple); m { | 506 | if m, archPattern, vendorPattern, opsysPattern := match3(pattern, reTriple); m { | |
510 | archCv := &VartypeCheck{ | 507 | archCv := &VartypeCheck{ | |
511 | cv.mkline, | 508 | cv.MkLine, | |
512 | cv.line, | 509 | cv.Line, | |
513 | "the hardware architecture part of " + cv.varname, | 510 | "the hardware architecture part of " + cv.Varname, | |
514 | opUseMatch, // Always allow patterns, since this is a PlatformPattern. | 511 | opUseMatch, // Always allow patterns, since this is a PlatformPattern. | |
515 | archPattern, | 512 | archPattern, | |
516 | archPattern, | 513 | archPattern, | |
517 | cv.comment, | 514 | cv.MkComment, | |
518 | cv.listContext, | 515 | cv.Guessed} | |
519 | cv.guessed} | |||
520 | enumMachineGnuArch.checker(archCv) | 516 | enumMachineGnuArch.checker(archCv) | |
521 | 517 | |||
522 | _ = vendorPattern | 518 | _ = vendorPattern | |
523 | 519 | |||
524 | opsysCv := &VartypeCheck{ | 520 | opsysCv := &VartypeCheck{ | |
525 | cv.mkline, | 521 | cv.MkLine, | |
526 | cv.line, | 522 | cv.Line, | |
527 | "the operating system part of " + cv.varname, | 523 | "the operating system part of " + cv.Varname, | |
528 | opUseMatch, // Always allow patterns, since this is a PlatformPattern. | 524 | opUseMatch, // Always allow patterns, since this is a PlatformPattern. | |
529 | opsysPattern, | 525 | opsysPattern, | |
530 | opsysPattern, | 526 | opsysPattern, | |
531 | cv.comment, | 527 | cv.MkComment, | |
532 | cv.listContext, | 528 | cv.Guessed} | |
533 | cv.guessed} | |||
534 | enumMachineGnuPlatformOpsys.checker(opsysCv) | 529 | enumMachineGnuPlatformOpsys.checker(opsysCv) | |
535 | 530 | |||
536 | } else { | 531 | } else { | |
537 | cv.line.Warn1("%q is not a valid platform pattern.", cv.value) | 532 | cv.Line.Warn1("%q is not a valid platform pattern.", cv.Value) | |
538 | Explain( | 533 | Explain( | |
539 | "A platform pattern has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.", | 534 | "A platform pattern has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.", | |
540 | "Each of these components may be a shell globbing expression.", | 535 | "Each of these components may be a shell globbing expression.", | |
541 | "", | 536 | "", | |
542 | "Examples:", | 537 | "Examples:", | |
543 | "* NetBSD-[456].*-i386", | 538 | "* NetBSD-[456].*-i386", | |
544 | "* *-*-*", | 539 | "* *-*-*", | |
545 | "* Linux-*-*") | 540 | "* Linux-*-*") | |
546 | } | 541 | } | |
547 | } | 542 | } | |
548 | 543 | |||
549 | func (cv *VartypeCheck) MailAddress() { | 544 | func (cv *VartypeCheck) MailAddress() { | |
550 | line, value := cv.line, cv.value | 545 | line, value := cv.Line, cv.Value | |
551 | 546 | |||
552 | if m, _, domain := match2(value, `^([+\-.0-9A-Z_a-z]+)@([-\w\d.]+)$`); m { | 547 | if m, _, domain := match2(value, `^([+\-.0-9A-Z_a-z]+)@([-\w\d.]+)$`); m { | |
553 | if strings.EqualFold(domain, "NetBSD.org") && domain != "NetBSD.org" { | 548 | if strings.EqualFold(domain, "NetBSD.org") && domain != "NetBSD.org" { | |
554 | line.Warn1("Please write \"NetBSD.org\" instead of %q.", domain) | 549 | line.Warn1("Please write \"NetBSD.org\" instead of %q.", domain) | |
555 | } | 550 | } | |
556 | if matches(value, `(?i)^(tech-pkg|packages)@NetBSD\.org$`) { | 551 | if matches(value, `(?i)^(tech-pkg|packages)@NetBSD\.org$`) { | |
557 | line.Error0("This mailing list address is obsolete. Use pkgsrc-users@NetBSD.org instead.") | 552 | line.Error0("This mailing list address is obsolete. Use pkgsrc-users@NetBSD.org instead.") | |
558 | } | 553 | } | |
559 | 554 | |||
560 | } else { | 555 | } else { | |
561 | line.Warn1("\"%s\" is not a valid mail address.", value) | 556 | line.Warn1("\"%s\" is not a valid mail address.", value) | |
562 | } | 557 | } | |
563 | } | 558 | } | |
564 | 559 | |||
565 | // See ${STEP_MSG}, ${PKG_FAIL_REASON} | 560 | // See ${STEP_MSG}, ${PKG_FAIL_REASON} | |
566 | func (cv *VartypeCheck) Message() { | 561 | func (cv *VartypeCheck) Message() { | |
567 | line, varname, value := cv.line, cv.varname, cv.value | 562 | line, varname, value := cv.Line, cv.Varname, cv.Value | |
568 | 563 | |||
569 | if matches(value, `^[\"'].*[\"']$`) { | 564 | if matches(value, `^[\"'].*[\"']$`) { | |
570 | line.Warn1("%s should not be quoted.", varname) | 565 | line.Warn1("%s should not be quoted.", varname) | |
571 | Explain( | 566 | Explain( | |
572 | "The quoting is only needed for variables which are interpreted as", | 567 | "The quoting is only needed for variables which are interpreted as", | |
573 | "multiple words (or, generally speaking, a list of something). A", | 568 | "multiple words (or, generally speaking, a list of something). A", | |
574 | "single text message does not belong to this class, since it is only", | 569 | "single text message does not belong to this class, since it is only", | |
575 | "printed as a whole.", | 570 | "printed as a whole.", | |
576 | "", | 571 | "", | |
577 | "On the other hand, PKG_FAIL_REASON is a _list_ of text messages, so", | 572 | "On the other hand, PKG_FAIL_REASON is a _list_ of text messages, so", | |
578 | "in that case, the quoting has to be done.") | 573 | "in that case, the quoting has to be done.") | |
579 | } | 574 | } | |
580 | } | 575 | } | |
581 | 576 | |||
582 | // A package option from options.mk | 577 | // A package option from options.mk | |
583 | func (cv *VartypeCheck) Option() { | 578 | func (cv *VartypeCheck) Option() { | |
584 | line, value, valueNovar := cv.line, cv.value, cv.valueNovar | 579 | line, value, valueNovar := cv.Line, cv.Value, cv.ValueNoVar | |
585 | 580 | |||
586 | if value != valueNovar { | 581 | if value != valueNovar { | |
587 | if G.opts.Debug { | 582 | if G.opts.Debug { | |
588 | traceStep1("Unchecked option name: %q", value) | 583 | traceStep1("Unchecked option name: %q", value) | |
589 | } | 584 | } | |
590 | return | 585 | return | |
591 | } | 586 | } | |
592 | 587 | |||
593 | if m, optname := match1(value, `^-?([a-z][-0-9a-z+]*)$`); m { | 588 | if m, optname := match1(value, `^-?([a-z][-0-9a-z+]*)$`); m { | |
594 | if _, found := G.globalData.PkgOptions[optname]; !found { // There’s a difference between empty and absent here. | 589 | if _, found := G.globalData.PkgOptions[optname]; !found { // There’s a difference between empty and absent here. | |
595 | line.Warn1("Unknown option \"%s\".", optname) | 590 | line.Warn1("Unknown option \"%s\".", optname) | |
596 | Explain4( | 591 | Explain4( | |
597 | "This option is not documented in the mk/defaults/options.description", | 592 | "This option is not documented in the mk/defaults/options.description", | |
@@ -602,232 +597,230 @@ func (cv *VartypeCheck) Option() { | @@ -602,232 +597,230 @@ func (cv *VartypeCheck) Option() { | |||
602 | return | 597 | return | |
603 | } | 598 | } | |
604 | 599 | |||
605 | if matches(value, `^-?([a-z][-0-9a-z_\+]*)$`) { | 600 | if matches(value, `^-?([a-z][-0-9a-z_\+]*)$`) { | |
606 | line.Warn0("Use of the underscore character in option names is deprecated.") | 601 | line.Warn0("Use of the underscore character in option names is deprecated.") | |
607 | return | 602 | return | |
608 | } | 603 | } | |
609 | 604 | |||
610 | line.Error1("Invalid option name %q. Option names must start with a lowercase letter and be all-lowercase.", value) | 605 | line.Error1("Invalid option name %q. Option names must start with a lowercase letter and be all-lowercase.", value) | |
611 | } | 606 | } | |
612 | 607 | |||
613 | // The PATH environment variable | 608 | // The PATH environment variable | |
614 | func (cv *VartypeCheck) Pathlist() { | 609 | func (cv *VartypeCheck) Pathlist() { | |
615 | if !contains(cv.value, ":") && cv.guessed { | 610 | if !contains(cv.Value, ":") && cv.Guessed { | |
616 | cv.mkline.CheckVartypePrimitive(cv.varname, CheckvarPathname, cv.op, cv.value, cv.comment, cv.listContext, cv.guessed) | 611 | cv.MkLine.CheckVartypePrimitive(cv.Varname, CheckvarPathname, cv.Op, cv.Value, cv.MkComment, cv.Guessed) | |
617 | return | 612 | return | |
618 | } | 613 | } | |
619 | 614 | |||
620 | for _, path := range strings.Split(cv.value, ":") { | 615 | for _, path := range strings.Split(cv.Value, ":") { | |
621 | if contains(path, "${") { | 616 | if contains(path, "${") { | |
622 | continue | 617 | continue | |
623 | } | 618 | } | |
624 | 619 | |||
625 | if !matches(path, `^[-0-9A-Za-z._~+%/]*$`) { | 620 | if !matches(path, `^[-0-9A-Za-z._~+%/]*$`) { | |
626 | cv.line.Warn1("%q is not a valid pathname.", path) | 621 | cv.Line.Warn1("%q is not a valid pathname.", path) | |
627 | } | 622 | } | |
628 | 623 | |||
629 | if !hasPrefix(path, "/") { | 624 | if !hasPrefix(path, "/") { | |
630 | cv.line.Warn2("All components of %s (in this case %q) should be absolute paths.", cv.varname, path) | 625 | cv.Line.Warn2("All components of %s (in this case %q) should be absolute paths.", cv.Varname, path) | |
631 | } | 626 | } | |
632 | } | 627 | } | |
633 | } | 628 | } | |
634 | 629 | |||
635 | // Shell globbing including slashes. | 630 | // Shell globbing including slashes. | |
636 | // See Filemask | 631 | // See Filemask | |
637 | func (cv *VartypeCheck) Pathmask() { | 632 | func (cv *VartypeCheck) Pathmask() { | |
638 | if cv.op == opUseMatch { | 633 | if cv.Op == opUseMatch { | |
639 | return | 634 | return | |
640 | } | 635 | } | |
641 | if !matches(cv.valueNovar, `^[#\-0-9A-Za-z._~+%*?/\[\]]*`) { | 636 | if !matches(cv.ValueNoVar, `^[#\-0-9A-Za-z._~+%*?/\[\]]*`) { | |
642 | cv.line.Warn1("%q is not a valid pathname mask.", cv.value) | 637 | cv.Line.Warn1("%q is not a valid pathname mask.", cv.Value) | |
643 | } | 638 | } | |
644 | cv.line.CheckAbsolutePathname(cv.value) | 639 | cv.Line.CheckAbsolutePathname(cv.Value) | |
645 | } | 640 | } | |
646 | 641 | |||
647 | // Like Filename, but including slashes | 642 | // Like Filename, but including slashes | |
648 | // See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_266 | 643 | // See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_266 | |
649 | func (cv *VartypeCheck) Pathname() { | 644 | func (cv *VartypeCheck) Pathname() { | |
650 | if cv.op == opUseMatch { | 645 | if cv.Op == opUseMatch { | |
651 | return | 646 | return | |
652 | } | 647 | } | |
653 | if !matches(cv.valueNovar, `^[#\-0-9A-Za-z._~+%/]*$`) { | 648 | if !matches(cv.ValueNoVar, `^[#\-0-9A-Za-z._~+%/]*$`) { | |
654 | cv.line.Warn1("%q is not a valid pathname.", cv.value) | 649 | cv.Line.Warn1("%q is not a valid pathname.", cv.Value) | |
655 | } | 650 | } | |
656 | cv.line.CheckAbsolutePathname(cv.value) | 651 | cv.Line.CheckAbsolutePathname(cv.Value) | |
657 | } | 652 | } | |
658 | 653 | |||
659 | func (cv *VartypeCheck) Perl5Packlist() { | 654 | func (cv *VartypeCheck) Perl5Packlist() { | |
660 | if cv.value != cv.valueNovar { | 655 | if cv.Value != cv.ValueNoVar { | |
661 | cv.line.Warn1("%s should not depend on other variables.", cv.varname) | 656 | cv.Line.Warn1("%s should not depend on other variables.", cv.Varname) | |
662 | } | 657 | } | |
663 | } | 658 | } | |
664 | 659 | |||
665 | func (cv *VartypeCheck) Perms() { | 660 | func (cv *VartypeCheck) Perms() { | |
666 | if cv.value == "${ROOT_USER}" || cv.value == "${ROOT_GROUP}" { | 661 | if cv.Value == "${ROOT_USER}" || cv.Value == "${ROOT_GROUP}" { | |
667 | valuename := cv.value[2 : len(cv.value)-1] | 662 | valuename := cv.Value[2 : len(cv.Value)-1] | |
668 | cv.line.Error1("%s must not be used in permission definitions. Use REAL_%[1]s instead.", valuename) | 663 | cv.Line.Error1("%s must not be used in permission definitions. Use REAL_%[1]s instead.", valuename) | |
669 | } | 664 | } | |
670 | } | 665 | } | |
671 | 666 | |||
672 | func (cv *VartypeCheck) PkgName() { | 667 | func (cv *VartypeCheck) PkgName() { | |
673 | if cv.op != opUseMatch && cv.value == cv.valueNovar && !matches(cv.value, rePkgname) { | 668 | if cv.Op != opUseMatch && cv.Value == cv.ValueNoVar && !matches(cv.Value, rePkgname) { | |
674 | 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) | 669 | 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) | |
675 | } | 670 | } | |
676 | } | 671 | } | |
677 | 672 | |||
678 | func (cv *VartypeCheck) PkgOptionsVar() { | 673 | func (cv *VartypeCheck) PkgOptionsVar() { | |
679 | cv.mkline.CheckVartypePrimitive(cv.varname, CheckvarVarname, cv.op, cv.value, cv.comment, false, cv.guessed) | 674 | cv.MkLine.CheckVartypePrimitive(cv.Varname, CheckvarVariableName, cv.Op, cv.Value, cv.MkComment, cv.Guessed) | |
680 | if matches(cv.value, `\$\{PKGBASE[:\}]`) { | 675 | if matches(cv.Value, `\$\{PKGBASE[:\}]`) { | |
681 | cv.line.Error0("PKGBASE must not be used in PKG_OPTIONS_VAR.") | 676 | cv.Line.Error0("PKGBASE must not be used in PKG_OPTIONS_VAR.") | |
682 | Explain3( | 677 | Explain3( | |
683 | "PKGBASE is defined in bsd.pkg.mk, which is included as the", | 678 | "PKGBASE is defined in bsd.pkg.mk, which is included as the", | |
684 | "very last file, but PKG_OPTIONS_VAR is evaluated earlier.", | 679 | "very last file, but PKG_OPTIONS_VAR is evaluated earlier.", | |
685 | "Use ${PKGNAME:C/-[0-9].*//} instead.") | 680 | "Use ${PKGNAME:C/-[0-9].*//} instead.") | |
686 | } | 681 | } | |
687 | 682 | |||
688 | // PR 46570, item "6. It should complain in PKG_OPTIONS_VAR is wrong" | 683 | // PR 46570, item "6. It should complain in PKG_OPTIONS_VAR is wrong" | |
689 | if !hasPrefix(cv.value, "PKG_OPTIONS.") { | 684 | if !hasPrefix(cv.Value, "PKG_OPTIONS.") { | |
690 | cv.line.Error2("PKG_OPTIONS_VAR must be of the form %q, not %q.", "PKG_OPTIONS.*", cv.value) | 685 | cv.Line.Error2("PKG_OPTIONS_VAR must be of the form %q, not %q.", "PKG_OPTIONS.*", cv.Value) | |
691 | } | 686 | } | |
692 | } | 687 | } | |
693 | 688 | |||
694 | // A directory name relative to the top-level pkgsrc directory. | 689 | // A directory name relative to the top-level pkgsrc directory. | |
695 | // Despite its name, it is more similar to RelativePkgDir than to RelativePkgPath. | 690 | // Despite its name, it is more similar to RelativePkgDir than to RelativePkgPath. | |
696 | func (cv *VartypeCheck) PkgPath() { | 691 | func (cv *VartypeCheck) PkgPath() { | |
697 | cv.mkline.CheckRelativePkgdir(G.CurPkgsrcdir + "/" + cv.value) | 692 | cv.MkLine.CheckRelativePkgdir(G.CurPkgsrcdir + "/" + cv.Value) | |
698 | } | 693 | } | |
699 | 694 | |||
700 | func (cv *VartypeCheck) PkgRevision() { | 695 | func (cv *VartypeCheck) PkgRevision() { | |
701 | if !matches(cv.value, `^[1-9]\d*$`) { | 696 | if !matches(cv.Value, `^[1-9]\d*$`) { | |
702 | cv.line.Warn1("%s must be a positive integer number.", cv.varname) | 697 | cv.Line.Warn1("%s must be a positive integer number.", cv.Varname) | |
703 | } | 698 | } | |
704 | if path.Base(cv.line.Fname) != "Makefile" { | 699 | if path.Base(cv.Line.Fname) != "Makefile" { | |
705 | cv.line.Error1("%s only makes sense directly in the package Makefile.", cv.varname) | 700 | cv.Line.Error1("%s only makes sense directly in the package Makefile.", cv.Varname) | |
706 | Explain( | 701 | Explain( | |
707 | "Usually, different packages using the same Makefile.common have", | 702 | "Usually, different packages using the same Makefile.common have", | |
708 | "different dependencies and will be bumped at different times (e.g.", | 703 | "different dependencies and will be bumped at different times (e.g.", | |
709 | "for shlib major bumps) and thus the PKGREVISIONs must be in the", | 704 | "for shlib major bumps) and thus the PKGREVISIONs must be in the", | |
710 | "separate Makefiles. There is no practical way of having this", | 705 | "separate Makefiles. There is no practical way of having this", | |
711 | "information in a commonly used Makefile.") | 706 | "information in a commonly used Makefile.") | |
712 | } | 707 | } | |
713 | } | 708 | } | |
714 | 709 | |||
715 | func (cv *VartypeCheck) MachinePlatform() { | 710 | func (cv *VartypeCheck) MachinePlatform() { | |
716 | cv.MachinePlatformPattern() | 711 | cv.MachinePlatformPattern() | |
717 | } | 712 | } | |
718 | 713 | |||
719 | func (cv *VartypeCheck) MachinePlatformPattern() { | 714 | func (cv *VartypeCheck) MachinePlatformPattern() { | |
720 | if cv.value != cv.valueNovar { | 715 | if cv.Value != cv.ValueNoVar { | |
721 | return | 716 | return | |
722 | } | 717 | } | |
723 | 718 | |||
724 | const rePart = `(?:\[[^\]]+\]|[^-\[])+` | 719 | const rePart = `(?:\[[^\]]+\]|[^-\[])+` | |
725 | const rePair = `^(` + rePart + `)-(` + rePart + `)$` | 720 | const rePair = `^(` + rePart + `)-(` + rePart + `)$` | |
726 | const reTriple = `^(` + rePart + `)-(` + rePart + `)-(` + rePart + `)$` | 721 | const reTriple = `^(` + rePart + `)-(` + rePart + `)-(` + rePart + `)$` | |
727 | 722 | |||
728 | pattern := cv.value | 723 | pattern := cv.Value | |
729 | if matches(pattern, rePair) && hasSuffix(pattern, "*") { | 724 | if matches(pattern, rePair) && hasSuffix(pattern, "*") { | |
730 | pattern += "-*" | 725 | pattern += "-*" | |
731 | } | 726 | } | |
732 | 727 | |||
733 | if m, opsysPattern, _, archPattern := match3(pattern, reTriple); m { | 728 | if m, opsysPattern, _, archPattern := match3(pattern, reTriple); m { | |
734 | opsysCv := &VartypeCheck{ | 729 | opsysCv := &VartypeCheck{ | |
735 | cv.mkline, | 730 | cv.MkLine, | |
736 | cv.line, | 731 | cv.Line, | |
737 | "the operating system part of " + cv.varname, | 732 | "the operating system part of " + cv.Varname, | |
738 | opUseMatch, // Always allow patterns, since this is a PlatformPattern. | 733 | opUseMatch, // Always allow patterns, since this is a PlatformPattern. | |
739 | opsysPattern, | 734 | opsysPattern, | |
740 | opsysPattern, | 735 | opsysPattern, | |
741 | cv.comment, | 736 | cv.MkComment, | |
742 | cv.listContext, | 737 | cv.Guessed} | |
743 | cv.guessed} | |||
744 | enumMachineOpsys.checker(opsysCv) | 738 | enumMachineOpsys.checker(opsysCv) | |
745 | 739 | |||
746 | // no check for os_version | 740 | // no check for os_version | |
747 | 741 | |||
748 | archCv := &VartypeCheck{ | 742 | archCv := &VartypeCheck{ | |
749 | cv.mkline, | 743 | cv.MkLine, | |
750 | cv.line, | 744 | cv.Line, | |
751 | "the hardware architecture part of " + cv.varname, | 745 | "the hardware architecture part of " + cv.Varname, | |
752 | opUseMatch, // Always allow patterns, since this is a PlatformPattern. | 746 | opUseMatch, // Always allow patterns, since this is a PlatformPattern. | |
753 | archPattern, | 747 | archPattern, | |
754 | archPattern, | 748 | archPattern, | |
755 | cv.comment, | 749 | cv.MkComment, | |
756 | cv.listContext, | 750 | cv.Guessed} | |
757 | cv.guessed} | |||
758 | enumMachineArch.checker(archCv) | 751 | enumMachineArch.checker(archCv) | |
759 | 752 | |||
760 | } else { | 753 | } else { | |
761 | cv.line.Warn1("%q is not a valid platform pattern.", cv.value) | 754 | cv.Line.Warn1("%q is not a valid platform pattern.", cv.Value) | |
762 | Explain( | 755 | Explain( | |
763 | "A platform pattern has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.", | 756 | "A platform pattern has the form <OPSYS>-<OS_VERSION>-<MACHINE_ARCH>.", | |
764 | "Each of these components may be a shell globbing expression.", | 757 | "Each of these components may be a shell globbing expression.", | |
765 | "", | 758 | "", | |
766 | "Examples:", | 759 | "Examples:", | |
767 | "* NetBSD-[456].*-i386", | 760 | "* NetBSD-[456].*-i386", | |
768 | "* *-*-*", | 761 | "* *-*-*", | |
769 | "* Linux-*-*") | 762 | "* Linux-*-*") | |
770 | } | 763 | } | |
771 | } | 764 | } | |
772 | 765 | |||
773 | // A pathname relative to ${PREFIX}. | 766 | // A pathname relative to ${PREFIX}. | |
774 | func (cv *VartypeCheck) PrefixPathname() { | 767 | func (cv *VartypeCheck) PrefixPathname() { | |
775 | if m, mansubdir := match1(cv.value, `^man/(.+)`); m { | 768 | if m, mansubdir := match1(cv.Value, `^man/(.+)`); m { | |
776 | cv.line.Warn2("Please use \"${PKGMANDIR}/%s\" instead of %q.", mansubdir, cv.value) | 769 | cv.Line.Warn2("Please use \"${PKGMANDIR}/%s\" instead of %q.", mansubdir, cv.Value) | |
777 | } | 770 | } | |
778 | } | 771 | } | |
779 | 772 | |||
780 | func (cv *VartypeCheck) PythonDependency() { | 773 | func (cv *VartypeCheck) PythonDependency() { | |
781 | if cv.value != cv.valueNovar { | 774 | if cv.Value != cv.ValueNoVar { | |
782 | cv.line.Warn0("Python dependencies should not contain variables.") | 775 | cv.Line.Warn0("Python dependencies should not contain variables.") | |
783 | } else if !matches(cv.valueNovar, `^[+\-.0-9A-Z_a-z]+(?:|:link|:build)$`) { | 776 | } else if !matches(cv.ValueNoVar, `^[+\-.0-9A-Z_a-z]+(?:|:link|:build)$`) { | |
784 | cv.line.Warn1("Invalid Python dependency %q.", cv.value) | 777 | cv.Line.Warn1("Invalid Python dependency %q.", cv.Value) | |
785 | Explain4( | 778 | Explain4( | |
786 | "Python dependencies must be an identifier for a package, as", | 779 | "Python dependencies must be an identifier for a package, as", | |
787 | "specified in lang/python/versioned_dependencies.mk. This", | 780 | "specified in lang/python/versioned_dependencies.mk. This", | |
788 | "identifier may be followed by :build for a build-time only", | 781 | "identifier may be followed by :build for a build-time only", | |
789 | "dependency, or by :link for a run-time only dependency.") | 782 | "dependency, or by :link for a run-time only dependency.") | |
790 | } | 783 | } | |
791 | } | 784 | } | |
792 | 785 | |||
793 | // Refers to a package directory, e.g. ../../category/pkgbase. | 786 | // Refers to a package directory, e.g. ../../category/pkgbase. | |
794 | func (cv *VartypeCheck) RelativePkgDir() { | 787 | func (cv *VartypeCheck) RelativePkgDir() { | |
795 | cv.mkline.CheckRelativePkgdir(cv.value) | 788 | cv.MkLine.CheckRelativePkgdir(cv.Value) | |
796 | } | 789 | } | |
797 | 790 | |||
798 | // Refers to a file or directory, e.g. ../../category/pkgbase, ../../category/pkgbase/Makefile. | 791 | // Refers to a file or directory, e.g. ../../category/pkgbase, ../../category/pkgbase/Makefile. | |
799 | func (cv *VartypeCheck) RelativePkgPath() { | 792 | func (cv *VartypeCheck) RelativePkgPath() { | |
800 | cv.mkline.CheckRelativePath(cv.value, true) | 793 | cv.MkLine.CheckRelativePath(cv.Value, true) | |
801 | } | 794 | } | |
802 | 795 | |||
803 | func (cv *VartypeCheck) Restricted() { | 796 | func (cv *VartypeCheck) Restricted() { | |
804 | if cv.value != "${RESTRICTED}" { | 797 | if cv.Value != "${RESTRICTED}" { | |
805 | cv.line.Warn1("The only valid value for %s is ${RESTRICTED}.", cv.varname) | 798 | cv.Line.Warn1("The only valid value for %s is ${RESTRICTED}.", cv.Varname) | |
806 | Explain3( | 799 | Explain3( | |
807 | "These variables are used to control which files may be mirrored on", | 800 | "These variables are used to control which files may be mirrored on", | |
808 | "FTP servers or CD-ROM collections. They are not intended to mark", | 801 | "FTP servers or CD-ROM collections. They are not intended to mark", | |
809 | "packages whose only MASTER_SITES are on ftp.NetBSD.org.") | 802 | "packages whose only MASTER_SITES are on ftp.NetBSD.org.") | |
810 | } | 803 | } | |
811 | } | 804 | } | |
812 | 805 | |||
813 | func (cv *VartypeCheck) SedCommand() { | 806 | func (cv *VartypeCheck) SedCommand() { | |
814 | } | 807 | } | |
815 | 808 | |||
816 | func (cv *VartypeCheck) SedCommands() { | 809 | func (cv *VartypeCheck) SedCommands() { | |
817 | line := cv.line | 810 | line := cv.Line | |
818 | mkline := cv.mkline | 811 | mkline := cv.MkLine | |
819 | 812 | |||
820 | tokens, rest := splitIntoShellTokens(line, cv.value) | 813 | tokens, rest := splitIntoShellTokens(line, cv.Value) | |
821 | if rest != "" { | 814 | if rest != "" { | |
822 | if strings.Contains(line.Text, "#") { | 815 | if strings.Contains(line.Text, "#") { | |
823 | line.Error1("Invalid shell words %q in sed commands.", rest) | 816 | line.Error1("Invalid shell words %q in sed commands.", rest) | |
824 | Explain4( | 817 | Explain4( | |
825 | "When sed commands have embedded \"#\" characters, they need to be", | 818 | "When sed commands have embedded \"#\" characters, they need to be", | |
826 | "escaped with a backslash, otherwise make(1) will interpret them as a", | 819 | "escaped with a backslash, otherwise make(1) will interpret them as a", | |
827 | "comment, no matter if they occur in single or double quotes or", | 820 | "comment, no matter if they occur in single or double quotes or", | |
828 | "whatever.") | 821 | "whatever.") | |
829 | } | 822 | } | |
830 | return | 823 | return | |
831 | } | 824 | } | |
832 | 825 | |||
833 | ntokens := len(tokens) | 826 | ntokens := len(tokens) | |
@@ -843,100 +836,98 @@ func (cv *VartypeCheck) SedCommands() { | @@ -843,100 +836,98 @@ func (cv *VartypeCheck) SedCommands() { | |||
843 | i++ | 836 | i++ | |
844 | ncommands++ | 837 | ncommands++ | |
845 | if ncommands > 1 { | 838 | if ncommands > 1 { | |
846 | line.Note0("Each sed command should appear in an assignment of its own.") | 839 | line.Note0("Each sed command should appear in an assignment of its own.") | |
847 | Explain( | 840 | Explain( | |
848 | "For example, instead of", | 841 | "For example, instead of", | |
849 | " SUBST_SED.foo+= -e s,command1,, -e s,command2,,", | 842 | " SUBST_SED.foo+= -e s,command1,, -e s,command2,,", | |
850 | "use", | 843 | "use", | |
851 | " SUBST_SED.foo+= -e s,command1,,", | 844 | " SUBST_SED.foo+= -e s,command1,,", | |
852 | " SUBST_SED.foo+= -e s,command2,,", | 845 | " SUBST_SED.foo+= -e s,command2,,", | |
853 | "", | 846 | "", | |
854 | "This way, short sed commands cannot be hidden at the end of a line.") | 847 | "This way, short sed commands cannot be hidden at the end of a line.") | |
855 | } | 848 | } | |
856 | mkline.CheckVartypePrimitive(cv.varname, CheckvarSedCommand, cv.op, tokens[i], cv.comment, cv.listContext, cv.guessed) | 849 | mkline.CheckVartypePrimitive(cv.Varname, CheckvarSedCommand, cv.Op, tokens[i], cv.MkComment, cv.Guessed) | |
857 | } else { | 850 | } else { | |
858 | line.Error0("The -e option to sed requires an argument.") | 851 | line.Error0("The -e option to sed requires an argument.") | |
859 | } | 852 | } | |
860 | case token == "-E": | 853 | case token == "-E": | |
861 | // Switch to extended regular expressions mode. | 854 | // Switch to extended regular expressions mode. | |
862 | 855 | |||
863 | case token == "-n": | 856 | case token == "-n": | |
864 | // Don't print lines per default. | 857 | // Don't print lines per default. | |
865 | 858 | |||
866 | case i == 0 && matches(token, `^(["']?)(?:\d*|/.*/)s.+["']?$`): | 859 | case i == 0 && matches(token, `^(["']?)(?:\d*|/.*/)s.+["']?$`): | |
867 | line.Note0("Please always use \"-e\" in sed commands, even if there is only one substitution.") | 860 | line.Note0("Please always use \"-e\" in sed commands, even if there is only one substitution.") | |
868 | 861 | |||
869 | default: | 862 | default: | |
870 | line.Warn1("Unknown sed command %q.", token) | 863 | line.Warn1("Unknown sed command %q.", token) | |
871 | } | 864 | } | |
872 | } | 865 | } | |
873 | } | 866 | } | |
874 | 867 | |||
875 | func (cv *VartypeCheck) ShellCommand() { | 868 | func (cv *VartypeCheck) ShellCommand() { | |
876 | if cv.op == opUseMatch || cv.op == opUse { | 869 | if cv.Op == opUseMatch || cv.Op == opUse { | |
877 | return | 870 | return | |
878 | } | 871 | } | |
879 | setE := true | 872 | setE := true | |
880 | NewShellLine(cv.mkline).CheckShellCommand(cv.value, &setE) | 873 | NewShellLine(cv.MkLine).CheckShellCommand(cv.Value, &setE) | |
881 | } | 874 | } | |
882 | 875 | |||
883 | // Zero or more shell commands, each terminated with a semicolon. | 876 | // Zero or more shell commands, each terminated with a semicolon. | |
884 | func (cv *VartypeCheck) ShellCommands() { | 877 | func (cv *VartypeCheck) ShellCommands() { | |
885 | NewShellLine(cv.mkline).CheckShellCommands(cv.value) | 878 | NewShellLine(cv.MkLine).CheckShellCommands(cv.Value) | |
886 | } | 879 | } | |
887 | 880 | |||
888 | func (cv *VartypeCheck) ShellWord() { | 881 | func (cv *VartypeCheck) ShellWord() { | |
889 | if !cv.listContext { | 882 | NewShellLine(cv.MkLine).CheckWord(cv.Value, true) | |
890 | NewShellLine(cv.mkline).CheckWord(cv.value, true) | |||
891 | } | |||
892 | } | 883 | } | |
893 | 884 | |||
894 | func (cv *VartypeCheck) Stage() { | 885 | func (cv *VartypeCheck) Stage() { | |
895 | if !matches(cv.value, `^(?:pre|do|post)-(?:extract|patch|configure|build|test|install)`) { | 886 | if !matches(cv.Value, `^(?:pre|do|post)-(?:extract|patch|configure|build|test|install)`) { | |
896 | cv.line.Warn1("Invalid stage name %q. Use one of {pre,do,post}-{extract,patch,configure,build,test,install}.", cv.value) | 887 | cv.Line.Warn1("Invalid stage name %q. Use one of {pre,do,post}-{extract,patch,configure,build,test,install}.", cv.Value) | |
897 | } | 888 | } | |
898 | } | 889 | } | |
899 | 890 | |||
900 | func (cv *VartypeCheck) String() { | 891 | func (cv *VartypeCheck) String() { | |
901 | // No further checks possible. | 892 | // No further checks possible. | |
902 | } | 893 | } | |
903 | 894 | |||
904 | func (cv *VartypeCheck) Tool() { | 895 | func (cv *VartypeCheck) Tool() { | |
905 | if cv.varname == "TOOLS_NOOP" && cv.op == opAssignAppend { | 896 | if cv.Varname == "TOOLS_NOOP" && cv.Op == opAssignAppend { | |
906 | // no warning for package-defined tool definitions | 897 | // no warning for package-defined tool definitions | |
907 | 898 | |||
908 | } else if m, toolname, tooldep := match2(cv.value, `^([-\w]+|\[)(?::(\w+))?$`); m { | 899 | } else if m, toolname, tooldep := match2(cv.Value, `^([-\w]+|\[)(?::(\w+))?$`); m { | |
909 | if G.globalData.Tools.byName[toolname] == nil { | 900 | if G.globalData.Tools.byName[toolname] == nil { | |
910 | cv.line.Error1("Unknown tool %q.", toolname) | 901 | cv.Line.Error1("Unknown tool %q.", toolname) | |
911 | } | 902 | } | |
912 | switch tooldep { | 903 | switch tooldep { | |
913 | case "", "bootstrap", "build", "pkgsrc", "run": | 904 | case "", "bootstrap", "build", "pkgsrc", "run": | |
914 | default: | 905 | default: | |
915 | cv.line.Error1("Unknown tool dependency %q. Use one of \"build\", \"pkgsrc\" or \"run\".", tooldep) | 906 | cv.Line.Error1("Unknown tool dependency %q. Use one of \"build\", \"pkgsrc\" or \"run\".", tooldep) | |
916 | } | 907 | } | |
917 | } else if cv.op != opUseMatch { | 908 | } else if cv.Op != opUseMatch { | |
918 | cv.line.Error1("Invalid tool syntax: %q.", cv.value) | 909 | cv.Line.Error1("Invalid tool syntax: %q.", cv.Value) | |
919 | } | 910 | } | |
920 | } | 911 | } | |
921 | 912 | |||
922 | func (cv *VartypeCheck) Unchecked() { | 913 | func (cv *VartypeCheck) Unchecked() { | |
923 | // Do nothing, as the name says. | 914 | // Do nothing, as the name says. | |
924 | } | 915 | } | |
925 | 916 | |||
926 | func (cv *VartypeCheck) URL() { | 917 | func (cv *VartypeCheck) URL() { | |
927 | line, value := cv.line, cv.value | 918 | line, value := cv.Line, cv.Value | |
928 | 919 | |||
929 | if value == "" && hasPrefix(cv.comment, "#") { | 920 | if value == "" && hasPrefix(cv.MkComment, "#") { | |
930 | // Ok | 921 | // Ok | |
931 | 922 | |||
932 | } else if containsVarRef(value) { | 923 | } else if containsVarRef(value) { | |
933 | // No further checks | 924 | // No further checks | |
934 | 925 | |||
935 | } else if m, _, host, _, _ := match4(value, `^(https?|ftp|gopher)://([-0-9A-Za-z.]+)(?::(\d+))?/([-%&+,./0-9:;=?@A-Z_a-z~]|#)*$`); m { | 926 | } else if m, _, host, _, _ := match4(value, `^(https?|ftp|gopher)://([-0-9A-Za-z.]+)(?::(\d+))?/([-%&+,./0-9:;=?@A-Z_a-z~]|#)*$`); m { | |
936 | if matches(host, `(?i)\.NetBSD\.org$`) && !matches(host, `\.NetBSD\.org$`) { | 927 | if matches(host, `(?i)\.NetBSD\.org$`) && !matches(host, `\.NetBSD\.org$`) { | |
937 | line.Warn1("Please write NetBSD.org instead of %s.", host) | 928 | line.Warn1("Please write NetBSD.org instead of %s.", host) | |
938 | } | 929 | } | |
939 | 930 | |||
940 | } else if m, scheme, _, absPath := match3(value, `^([0-9A-Za-z]+)://([^/]+)(.*)$`); m { | 931 | } else if m, scheme, _, absPath := match3(value, `^([0-9A-Za-z]+)://([^/]+)(.*)$`); m { | |
941 | switch { | 932 | switch { | |
942 | case scheme != "ftp" && scheme != "http" && scheme != "https" && scheme != "gopher": | 933 | case scheme != "ftp" && scheme != "http" && scheme != "https" && scheme != "gopher": | |
@@ -945,135 +936,135 @@ func (cv *VartypeCheck) URL() { | @@ -945,135 +936,135 @@ func (cv *VartypeCheck) URL() { | |||
945 | case absPath == "": | 936 | case absPath == "": | |
946 | line.Note1("For consistency, please add a trailing slash to %q.", value) | 937 | line.Note1("For consistency, please add a trailing slash to %q.", value) | |
947 | 938 | |||
948 | default: | 939 | default: | |
949 | line.Warn1("%q is not a valid URL.", value) | 940 | line.Warn1("%q is not a valid URL.", value) | |
950 | } | 941 | } | |
951 | 942 | |||
952 | } else { | 943 | } else { | |
953 | line.Warn1("%q is not a valid URL.", value) | 944 | line.Warn1("%q is not a valid URL.", value) | |
954 | } | 945 | } | |
955 | } | 946 | } | |
956 | 947 | |||
957 | func (cv *VartypeCheck) UserGroupName() { | 948 | func (cv *VartypeCheck) UserGroupName() { | |
958 | if cv.value == cv.valueNovar && !matches(cv.value, `^[0-9_a-z]+$`) { | 949 | if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^[0-9_a-z]+$`) { | |
959 | cv.line.Warn1("Invalid user or group name %q.", cv.value) | 950 | cv.Line.Warn1("Invalid user or group name %q.", cv.Value) | |
960 | } | 951 | } | |
961 | } | 952 | } | |
962 | 953 | |||
963 | func (cv *VartypeCheck) Varname() { | 954 | func (cv *VartypeCheck) VariableName() { | |
964 | if cv.value == cv.valueNovar && !matches(cv.value, `^[A-Z_][0-9A-Z_]*(?:[.].*)?$`) { | 955 | if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^[A-Z_][0-9A-Z_]*(?:[.].*)?$`) { | |
965 | cv.line.Warn1("%q is not a valid variable name.", cv.value) | 956 | cv.Line.Warn1("%q is not a valid variable name.", cv.Value) | |
966 | Explain( | 957 | Explain( | |
967 | "Variable names are restricted to only uppercase letters and the", | 958 | "Variable names are restricted to only uppercase letters and the", | |
968 | "underscore in the basename, and arbitrary characters in the", | 959 | "underscore in the basename, and arbitrary characters in the", | |
969 | "parameterized part, following the dot.", | 960 | "parameterized part, following the dot.", | |
970 | "", | 961 | "", | |
971 | "Examples:", | 962 | "Examples:", | |
972 | "\t* PKGNAME", | 963 | "\t* PKGNAME", | |
973 | "\t* PKG_OPTIONS.gnuchess") | 964 | "\t* PKG_OPTIONS.gnuchess") | |
974 | } | 965 | } | |
975 | } | 966 | } | |
976 | 967 | |||
977 | func (cv *VartypeCheck) Version() { | 968 | func (cv *VartypeCheck) Version() { | |
978 | if cv.op == opUseMatch { | 969 | if cv.Op == opUseMatch { | |
979 | if !matches(cv.value, `^[\d?\[][\w\-.*?\[\]]+$`) { | 970 | if !matches(cv.Value, `^[\d?\[][\w\-.*?\[\]]+$`) { | |
980 | cv.line.Warn1("Invalid version number pattern %q.", cv.value) | 971 | cv.Line.Warn1("Invalid version number pattern %q.", cv.Value) | |
981 | } | 972 | } | |
982 | } else if cv.value == cv.valueNovar && !matches(cv.value, `^\d[\w.]+$`) { | 973 | } else if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^\d[\w.]+$`) { | |
983 | cv.line.Warn1("Invalid version number %q.", cv.value) | 974 | cv.Line.Warn1("Invalid version number %q.", cv.Value) | |
984 | } | 975 | } | |
985 | } | 976 | } | |
986 | 977 | |||
987 | func (cv *VartypeCheck) WrapperReorder() { | 978 | func (cv *VartypeCheck) WrapperReorder() { | |
988 | if !matches(cv.value, `^reorder:l:([\w\-]+):([\w\-]+)$`) { | 979 | if !matches(cv.Value, `^reorder:l:([\w\-]+):([\w\-]+)$`) { | |
989 | cv.line.Warn1("Unknown wrapper reorder command %q.", cv.value) | 980 | cv.Line.Warn1("Unknown wrapper reorder command %q.", cv.Value) | |
990 | } | 981 | } | |
991 | } | 982 | } | |
992 | 983 | |||
993 | func (cv *VartypeCheck) WrapperTransform() { | 984 | func (cv *VartypeCheck) WrapperTransform() { | |
994 | cmd := cv.value | 985 | cmd := cv.Value | |
995 | if hasPrefix(cmd, "rm:-") || | 986 | if hasPrefix(cmd, "rm:-") || | |
996 | matches(cmd, `^(R|l|rpath):([^:]+):(.+)$`) || | 987 | matches(cmd, `^(R|l|rpath):([^:]+):(.+)$`) || | |
997 | matches(cmd, `^'?(opt|rename|rm-optarg|rmdir):.*$`) || | 988 | matches(cmd, `^'?(opt|rename|rm-optarg|rmdir):.*$`) || | |
998 | cmd == "-e" || | 989 | cmd == "-e" || | |
999 | matches(cmd, `^["']?s[|:,]`) { | 990 | matches(cmd, `^["']?s[|:,]`) { | |
1000 | return | 991 | return | |
1001 | } | 992 | } | |
1002 | cv.line.Warn1("Unknown wrapper transform command %q.", cmd) | 993 | cv.Line.Warn1("Unknown wrapper transform command %q.", cmd) | |
1003 | } | 994 | } | |
1004 | 995 | |||
1005 | func (cv *VartypeCheck) WrkdirSubdirectory() { | 996 | func (cv *VartypeCheck) WrkdirSubdirectory() { | |
1006 | cv.mkline.CheckVartypePrimitive(cv.varname, CheckvarPathname, cv.op, cv.value, cv.comment, cv.listContext, cv.guessed) | 997 | cv.MkLine.CheckVartypePrimitive(cv.Varname, CheckvarPathname, cv.Op, cv.Value, cv.MkComment, cv.Guessed) | |
1007 | } | 998 | } | |
1008 | 999 | |||
1009 | // A directory relative to ${WRKSRC}, for use in CONFIGURE_DIRS and similar variables. | 1000 | // A directory relative to ${WRKSRC}, for use in CONFIGURE_DIRS and similar variables. | |
1010 | func (cv *VartypeCheck) WrksrcSubdirectory() { | 1001 | func (cv *VartypeCheck) WrksrcSubdirectory() { | |
1011 | if m, _, rest := match2(cv.value, `^(\$\{WRKSRC\})(?:/(.*))?`); m { | 1002 | if m, _, rest := match2(cv.Value, `^(\$\{WRKSRC\})(?:/(.*))?`); m { | |
1012 | if rest == "" { | 1003 | if rest == "" { | |
1013 | rest = "." | 1004 | rest = "." | |
1014 | } | 1005 | } | |
1015 | cv.line.Note2("You can use %q instead of %q.", rest, cv.value) | 1006 | cv.Line.Note2("You can use %q instead of %q.", rest, cv.Value) | |
1016 | Explain1( | 1007 | Explain1( | |
1017 | "These directories are interpreted relative to ${WRKSRC}.") | 1008 | "These directories are interpreted relative to ${WRKSRC}.") | |
1018 | 1009 | |||
1019 | } else if cv.value != "" && cv.valueNovar == "" { | 1010 | } else if cv.Value != "" && cv.ValueNoVar == "" { | |
1020 | // The value of another variable | 1011 | // The value of another variable | |
1021 | 1012 | |||
1022 | } else if !matches(cv.valueNovar, `^(?:\.|[0-9A-Za-z_@][-0-9A-Za-z_@./+]*)$`) { | 1013 | } else if !matches(cv.ValueNoVar, `^(?:\.|[0-9A-Za-z_@][-0-9A-Za-z_@./+]*)$`) { | |
1023 | cv.line.Warn1("%q is not a valid subdirectory of ${WRKSRC}.", cv.value) | 1014 | cv.Line.Warn1("%q is not a valid subdirectory of ${WRKSRC}.", cv.Value) | |
1024 | } | 1015 | } | |
1025 | } | 1016 | } | |
1026 | 1017 | |||
1027 | func (cv *VartypeCheck) Yes() { | 1018 | func (cv *VartypeCheck) Yes() { | |
1028 | switch cv.op { | 1019 | switch cv.Op { | |
1029 | case opUseMatch: | 1020 | case opUseMatch: | |
1030 | cv.line.Warn1("%s should only be used in a \".if defined(...)\" conditional.", cv.varname) | 1021 | cv.Line.Warn1("%s should only be used in a \".if defined(...)\" conditional.", cv.Varname) | |
1031 | Explain( | 1022 | Explain( | |
1032 | "This variable can have only two values: defined or undefined.", | 1023 | "This variable can have only two values: defined or undefined.", | |
1033 | "When it is defined, it means \"yes\", even when its value is", | 1024 | "When it is defined, it means \"yes\", even when its value is", | |
1034 | "\"no\" or the empty string.", | 1025 | "\"no\" or the empty string.", | |
1035 | "", | 1026 | "", | |
1036 | "Therefore, it should not be checked by comparing its value", | 1027 | "Therefore, it should not be checked by comparing its value", | |
1037 | "but using \".if defined(VARNAME)\" alone.") | 1028 | "but using \".if defined(VARNAME)\" alone.") | |
1038 | 1029 | |||
1039 | default: | 1030 | default: | |
1040 | if !matches(cv.value, `^(?:YES|yes)(?:\s+#.*)?$`) { | 1031 | if !matches(cv.Value, `^(?:YES|yes)(?:\s+#.*)?$`) { | |
1041 | cv.line.Warn1("%s should be set to YES or yes.", cv.varname) | 1032 | cv.Line.Warn1("%s should be set to YES or yes.", cv.Varname) | |
1042 | Explain4( | 1033 | Explain4( | |
1043 | "This variable means \"yes\" if it is defined, and \"no\" if it is", | 1034 | "This variable means \"yes\" if it is defined, and \"no\" if it is", | |
1044 | "undefined. Even when it has the value \"no\", this means \"yes\".", | 1035 | "undefined. Even when it has the value \"no\", this means \"yes\".", | |
1045 | "Therefore when it is defined, its value should correspond to its", | 1036 | "Therefore when it is defined, its value should correspond to its", | |
1046 | "meaning.") | 1037 | "meaning.") | |
1047 | } | 1038 | } | |
1048 | } | 1039 | } | |
1049 | } | 1040 | } | |
1050 | 1041 | |||
1051 | func (cv *VartypeCheck) YesNo() { | 1042 | func (cv *VartypeCheck) YesNo() { | |
1052 | const ( | 1043 | const ( | |
1053 | yes1 = "[yY][eE][sS]" | 1044 | yes1 = "[yY][eE][sS]" | |
1054 | yes2 = "[Yy][Ee][Ss]" | 1045 | yes2 = "[Yy][Ee][Ss]" | |
1055 | no1 = "[nN][oO]" | 1046 | no1 = "[nN][oO]" | |
1056 | no2 = "[Nn][Oo]" | 1047 | no2 = "[Nn][Oo]" | |
1057 | ) | 1048 | ) | |
1058 | if cv.op == opUseMatch { | 1049 | if cv.Op == opUseMatch { | |
1059 | switch cv.value { | 1050 | switch cv.Value { | |
1060 | case yes1, yes2, no1, no2: | 1051 | case yes1, yes2, no1, no2: | |
1061 | default: | 1052 | default: | |
1062 | cv.line.Warnf("%s should be matched against %q or %q, not %q.", cv.varname, yes1, no1, cv.value) | 1053 | cv.Line.Warnf("%s should be matched against %q or %q, not %q.", cv.Varname, yes1, no1, cv.Value) | |
1063 | } | 1054 | } | |
1064 | } else if cv.op == opUse { | 1055 | } else if cv.Op == opUse { | |
1065 | cv.line.Warnf("%s should be matched against %q or %q, not compared with %q.", cv.varname, yes1, no1, cv.value) | 1056 | cv.Line.Warnf("%s should be matched against %q or %q, not compared with %q.", cv.Varname, yes1, no1, cv.Value) | |
1066 | Explain( | 1057 | Explain( | |
1067 | "The yes/no value can be written in either upper or lower case, and", | 1058 | "The yes/no value can be written in either upper or lower case, and", | |
1068 | "both forms are actually used. As long as this is the case, when", | 1059 | "both forms are actually used. As long as this is the case, when", | |
1069 | "checking the variable value, both must be accepted.") | 1060 | "checking the variable value, both must be accepted.") | |
1070 | } else if !matches(cv.value, `^(?:YES|yes|NO|no)(?:\s+#.*)?$`) { | 1061 | } else if !matches(cv.Value, `^(?:YES|yes|NO|no)(?:\s+#.*)?$`) { | |
1071 | cv.line.Warn1("%s should be set to YES, yes, NO, or no.", cv.varname) | 1062 | cv.Line.Warn1("%s should be set to YES, yes, NO, or no.", cv.Varname) | |
1072 | } | 1063 | } | |
1073 | } | 1064 | } | |
1074 | 1065 | |||
1075 | func (cv *VartypeCheck) YesNoIndirectly() { | 1066 | func (cv *VartypeCheck) YesNoIndirectly() { | |
1076 | if cv.valueNovar != "" { | 1067 | if cv.ValueNoVar != "" { | |
1077 | cv.YesNo() | 1068 | cv.YesNo() | |
1078 | } | 1069 | } | |
1079 | } | 1070 | } |