1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
package main
// VarUseContext defines the context in which a variable is defined
// or used. Whether that is allowed depends on:
//
// * The variable’s data type, as defined in vardefs.go.
// * Whether the variable is accessed at loading time (when the
// Makefiles are parsed) or at run time (when the shell commands are
// run). Especially at load time, there are several points of time
// (e.g. the bsd.pkg.mk file is loaded at the very end, therefore
// the variables that are defined there cannot be used at load time.)
// * When used on the right-hand side of an assigment, the variable can
// represent a list of words, a single word or even only part of a
// word. This distinction decides upon the correct use of the :Q
// operator.
// * When used in shell commands, the variable can appear inside single
// quotes, double quotes, backticks or some combination thereof. This
// also influences whether the variable is correctly used.
// * When used in preprocessing statements like .if or .for, the other
// operands of that statement should fit to the variable and are
// checked against the variable type. For example, comparing OPSYS to
// x86_64 doesn’t make sense.
type VarUseContext struct {
time vucTime
vartype *Vartype
shellword vucShellword
extent vucExtent
}
type vucTime int
const (
VUC_TIME_UNKNOWN vucTime = iota
VUC_TIME_LOAD // During loading, not all variables are available yet.
VUC_TIME_RUN // All files have been read, especially bsd.pkg.mk.
)
type vucShellword int
const (
VUC_SHW_UNKNOWN vucShellword = iota
VUC_SHW_PLAIN // Example: echo LOCALBASE=${LOCALBASE}
VUC_SHW_DQUOT // Example: echo "The version is ${PKGVERSION}."
VUC_SHW_SQUOT // Example: echo 'The version is ${PKGVERSION}.'
VUC_SHW_BACKT // Example: echo \`sed 1q ${WRKSRC}/README\`
VUC_SHW_FOR // Example: for f in ${EXAMPLE_FILES}
)
type vucExtent int
const (
VUC_EXTENT_UNKNOWN vucExtent = iota
VUC_EXT_WORD // Example: echo ${LOCALBASE}
VUC_EXT_WORDPART // Example: echo LOCALBASE=${LOCALBASE}
)
func (self *VarUseContext) String() string {
typename := "no-type"
if self.vartype != nil {
typename = self.vartype.String()
}
return sprintf("(%s %s %s %s)",
[]string{"unknown", "load-time", "run-time"}[self.time],
typename,
[]string{"unknown", "plain", "dquot", "squot", "backt", "for"}[self.shellword],
[]string{"unknown", "word", "word-part"}[self.extent])
}
|