]> Cypherpunks.ru repositories - gostls13.git/blob - src/go/build/build.go
[dev.boringcrypto] all: merge master (2f0da6d) into dev.boringcrypto
[gostls13.git] / src / go / build / build.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package build
6
7 import (
8         "bytes"
9         "errors"
10         "fmt"
11         "go/ast"
12         "go/doc"
13         "go/token"
14         exec "internal/execabs"
15         "internal/goroot"
16         "internal/goversion"
17         "io"
18         "io/fs"
19         "io/ioutil"
20         "os"
21         pathpkg "path"
22         "path/filepath"
23         "runtime"
24         "sort"
25         "strconv"
26         "strings"
27         "unicode"
28         "unicode/utf8"
29 )
30
31 // A Context specifies the supporting context for a build.
32 type Context struct {
33         GOARCH string // target architecture
34         GOOS   string // target operating system
35         GOROOT string // Go root
36         GOPATH string // Go path
37
38         // Dir is the caller's working directory, or the empty string to use
39         // the current directory of the running process. In module mode, this is used
40         // to locate the main module.
41         //
42         // If Dir is non-empty, directories passed to Import and ImportDir must
43         // be absolute.
44         Dir string
45
46         CgoEnabled  bool   // whether cgo files are included
47         UseAllFiles bool   // use files regardless of +build lines, file names
48         Compiler    string // compiler to assume when computing target paths
49
50         // The build and release tags specify build constraints
51         // that should be considered satisfied when processing +build lines.
52         // Clients creating a new context may customize BuildTags, which
53         // defaults to empty, but it is usually an error to customize ReleaseTags,
54         // which defaults to the list of Go releases the current release is compatible with.
55         // BuildTags is not set for the Default build Context.
56         // In addition to the BuildTags and ReleaseTags, build constraints
57         // consider the values of GOARCH and GOOS as satisfied tags.
58         // The last element in ReleaseTags is assumed to be the current release.
59         BuildTags   []string
60         ReleaseTags []string
61
62         // The install suffix specifies a suffix to use in the name of the installation
63         // directory. By default it is empty, but custom builds that need to keep
64         // their outputs separate can set InstallSuffix to do so. For example, when
65         // using the race detector, the go command uses InstallSuffix = "race", so
66         // that on a Linux/386 system, packages are written to a directory named
67         // "linux_386_race" instead of the usual "linux_386".
68         InstallSuffix string
69
70         // By default, Import uses the operating system's file system calls
71         // to read directories and files. To read from other sources,
72         // callers can set the following functions. They all have default
73         // behaviors that use the local file system, so clients need only set
74         // the functions whose behaviors they wish to change.
75
76         // JoinPath joins the sequence of path fragments into a single path.
77         // If JoinPath is nil, Import uses filepath.Join.
78         JoinPath func(elem ...string) string
79
80         // SplitPathList splits the path list into a slice of individual paths.
81         // If SplitPathList is nil, Import uses filepath.SplitList.
82         SplitPathList func(list string) []string
83
84         // IsAbsPath reports whether path is an absolute path.
85         // If IsAbsPath is nil, Import uses filepath.IsAbs.
86         IsAbsPath func(path string) bool
87
88         // IsDir reports whether the path names a directory.
89         // If IsDir is nil, Import calls os.Stat and uses the result's IsDir method.
90         IsDir func(path string) bool
91
92         // HasSubdir reports whether dir is lexically a subdirectory of
93         // root, perhaps multiple levels below. It does not try to check
94         // whether dir exists.
95         // If so, HasSubdir sets rel to a slash-separated path that
96         // can be joined to root to produce a path equivalent to dir.
97         // If HasSubdir is nil, Import uses an implementation built on
98         // filepath.EvalSymlinks.
99         HasSubdir func(root, dir string) (rel string, ok bool)
100
101         // ReadDir returns a slice of fs.FileInfo, sorted by Name,
102         // describing the content of the named directory.
103         // If ReadDir is nil, Import uses ioutil.ReadDir.
104         ReadDir func(dir string) ([]fs.FileInfo, error)
105
106         // OpenFile opens a file (not a directory) for reading.
107         // If OpenFile is nil, Import uses os.Open.
108         OpenFile func(path string) (io.ReadCloser, error)
109 }
110
111 // joinPath calls ctxt.JoinPath (if not nil) or else filepath.Join.
112 func (ctxt *Context) joinPath(elem ...string) string {
113         if f := ctxt.JoinPath; f != nil {
114                 return f(elem...)
115         }
116         return filepath.Join(elem...)
117 }
118
119 // splitPathList calls ctxt.SplitPathList (if not nil) or else filepath.SplitList.
120 func (ctxt *Context) splitPathList(s string) []string {
121         if f := ctxt.SplitPathList; f != nil {
122                 return f(s)
123         }
124         return filepath.SplitList(s)
125 }
126
127 // isAbsPath calls ctxt.IsAbsPath (if not nil) or else filepath.IsAbs.
128 func (ctxt *Context) isAbsPath(path string) bool {
129         if f := ctxt.IsAbsPath; f != nil {
130                 return f(path)
131         }
132         return filepath.IsAbs(path)
133 }
134
135 // isDir calls ctxt.IsDir (if not nil) or else uses os.Stat.
136 func (ctxt *Context) isDir(path string) bool {
137         if f := ctxt.IsDir; f != nil {
138                 return f(path)
139         }
140         fi, err := os.Stat(path)
141         return err == nil && fi.IsDir()
142 }
143
144 // hasSubdir calls ctxt.HasSubdir (if not nil) or else uses
145 // the local file system to answer the question.
146 func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) {
147         if f := ctxt.HasSubdir; f != nil {
148                 return f(root, dir)
149         }
150
151         // Try using paths we received.
152         if rel, ok = hasSubdir(root, dir); ok {
153                 return
154         }
155
156         // Try expanding symlinks and comparing
157         // expanded against unexpanded and
158         // expanded against expanded.
159         rootSym, _ := filepath.EvalSymlinks(root)
160         dirSym, _ := filepath.EvalSymlinks(dir)
161
162         if rel, ok = hasSubdir(rootSym, dir); ok {
163                 return
164         }
165         if rel, ok = hasSubdir(root, dirSym); ok {
166                 return
167         }
168         return hasSubdir(rootSym, dirSym)
169 }
170
171 // hasSubdir reports if dir is within root by performing lexical analysis only.
172 func hasSubdir(root, dir string) (rel string, ok bool) {
173         const sep = string(filepath.Separator)
174         root = filepath.Clean(root)
175         if !strings.HasSuffix(root, sep) {
176                 root += sep
177         }
178         dir = filepath.Clean(dir)
179         if !strings.HasPrefix(dir, root) {
180                 return "", false
181         }
182         return filepath.ToSlash(dir[len(root):]), true
183 }
184
185 // readDir calls ctxt.ReadDir (if not nil) or else ioutil.ReadDir.
186 func (ctxt *Context) readDir(path string) ([]fs.FileInfo, error) {
187         if f := ctxt.ReadDir; f != nil {
188                 return f(path)
189         }
190         return ioutil.ReadDir(path)
191 }
192
193 // openFile calls ctxt.OpenFile (if not nil) or else os.Open.
194 func (ctxt *Context) openFile(path string) (io.ReadCloser, error) {
195         if fn := ctxt.OpenFile; fn != nil {
196                 return fn(path)
197         }
198
199         f, err := os.Open(path)
200         if err != nil {
201                 return nil, err // nil interface
202         }
203         return f, nil
204 }
205
206 // isFile determines whether path is a file by trying to open it.
207 // It reuses openFile instead of adding another function to the
208 // list in Context.
209 func (ctxt *Context) isFile(path string) bool {
210         f, err := ctxt.openFile(path)
211         if err != nil {
212                 return false
213         }
214         f.Close()
215         return true
216 }
217
218 // gopath returns the list of Go path directories.
219 func (ctxt *Context) gopath() []string {
220         var all []string
221         for _, p := range ctxt.splitPathList(ctxt.GOPATH) {
222                 if p == "" || p == ctxt.GOROOT {
223                         // Empty paths are uninteresting.
224                         // If the path is the GOROOT, ignore it.
225                         // People sometimes set GOPATH=$GOROOT.
226                         // Do not get confused by this common mistake.
227                         continue
228                 }
229                 if strings.HasPrefix(p, "~") {
230                         // Path segments starting with ~ on Unix are almost always
231                         // users who have incorrectly quoted ~ while setting GOPATH,
232                         // preventing it from expanding to $HOME.
233                         // The situation is made more confusing by the fact that
234                         // bash allows quoted ~ in $PATH (most shells do not).
235                         // Do not get confused by this, and do not try to use the path.
236                         // It does not exist, and printing errors about it confuses
237                         // those users even more, because they think "sure ~ exists!".
238                         // The go command diagnoses this situation and prints a
239                         // useful error.
240                         // On Windows, ~ is used in short names, such as c:\progra~1
241                         // for c:\program files.
242                         continue
243                 }
244                 all = append(all, p)
245         }
246         return all
247 }
248
249 // SrcDirs returns a list of package source root directories.
250 // It draws from the current Go root and Go path but omits directories
251 // that do not exist.
252 func (ctxt *Context) SrcDirs() []string {
253         var all []string
254         if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" {
255                 dir := ctxt.joinPath(ctxt.GOROOT, "src")
256                 if ctxt.isDir(dir) {
257                         all = append(all, dir)
258                 }
259         }
260         for _, p := range ctxt.gopath() {
261                 dir := ctxt.joinPath(p, "src")
262                 if ctxt.isDir(dir) {
263                         all = append(all, dir)
264                 }
265         }
266         return all
267 }
268
269 // Default is the default Context for builds.
270 // It uses the GOARCH, GOOS, GOROOT, and GOPATH environment variables
271 // if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
272 var Default Context = defaultContext()
273
274 func defaultGOPATH() string {
275         env := "HOME"
276         if runtime.GOOS == "windows" {
277                 env = "USERPROFILE"
278         } else if runtime.GOOS == "plan9" {
279                 env = "home"
280         }
281         if home := os.Getenv(env); home != "" {
282                 def := filepath.Join(home, "go")
283                 if filepath.Clean(def) == filepath.Clean(runtime.GOROOT()) {
284                         // Don't set the default GOPATH to GOROOT,
285                         // as that will trigger warnings from the go tool.
286                         return ""
287                 }
288                 return def
289         }
290         return ""
291 }
292
293 var defaultReleaseTags []string
294
295 func defaultContext() Context {
296         var c Context
297
298         c.GOARCH = envOr("GOARCH", runtime.GOARCH)
299         c.GOOS = envOr("GOOS", runtime.GOOS)
300         c.GOROOT = pathpkg.Clean(runtime.GOROOT())
301         c.GOPATH = envOr("GOPATH", defaultGOPATH())
302         c.Compiler = runtime.Compiler
303
304         // Each major Go release in the Go 1.x series adds a new
305         // "go1.x" release tag. That is, the go1.x tag is present in
306         // all releases >= Go 1.x. Code that requires Go 1.x or later
307         // should say "+build go1.x", and code that should only be
308         // built before Go 1.x (perhaps it is the stub to use in that
309         // case) should say "+build !go1.x".
310         // The last element in ReleaseTags is the current release.
311         for i := 1; i <= goversion.Version; i++ {
312                 c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i))
313         }
314
315         defaultReleaseTags = append([]string{}, c.ReleaseTags...) // our own private copy
316
317         env := os.Getenv("CGO_ENABLED")
318         if env == "" {
319                 env = defaultCGO_ENABLED
320         }
321         switch env {
322         case "1":
323                 c.CgoEnabled = true
324         case "0":
325                 c.CgoEnabled = false
326         default:
327                 // cgo must be explicitly enabled for cross compilation builds
328                 if runtime.GOARCH == c.GOARCH && runtime.GOOS == c.GOOS {
329                         c.CgoEnabled = cgoEnabled[c.GOOS+"/"+c.GOARCH]
330                         break
331                 }
332                 c.CgoEnabled = false
333         }
334
335         return c
336 }
337
338 func envOr(name, def string) string {
339         s := os.Getenv(name)
340         if s == "" {
341                 return def
342         }
343         return s
344 }
345
346 // An ImportMode controls the behavior of the Import method.
347 type ImportMode uint
348
349 const (
350         // If FindOnly is set, Import stops after locating the directory
351         // that should contain the sources for a package. It does not
352         // read any files in the directory.
353         FindOnly ImportMode = 1 << iota
354
355         // If AllowBinary is set, Import can be satisfied by a compiled
356         // package object without corresponding sources.
357         //
358         // Deprecated:
359         // The supported way to create a compiled-only package is to
360         // write source code containing a //go:binary-only-package comment at
361         // the top of the file. Such a package will be recognized
362         // regardless of this flag setting (because it has source code)
363         // and will have BinaryOnly set to true in the returned Package.
364         AllowBinary
365
366         // If ImportComment is set, parse import comments on package statements.
367         // Import returns an error if it finds a comment it cannot understand
368         // or finds conflicting comments in multiple source files.
369         // See golang.org/s/go14customimport for more information.
370         ImportComment
371
372         // By default, Import searches vendor directories
373         // that apply in the given source directory before searching
374         // the GOROOT and GOPATH roots.
375         // If an Import finds and returns a package using a vendor
376         // directory, the resulting ImportPath is the complete path
377         // to the package, including the path elements leading up
378         // to and including "vendor".
379         // For example, if Import("y", "x/subdir", 0) finds
380         // "x/vendor/y", the returned package's ImportPath is "x/vendor/y",
381         // not plain "y".
382         // See golang.org/s/go15vendor for more information.
383         //
384         // Setting IgnoreVendor ignores vendor directories.
385         //
386         // In contrast to the package's ImportPath,
387         // the returned package's Imports, TestImports, and XTestImports
388         // are always the exact import paths from the source files:
389         // Import makes no attempt to resolve or check those paths.
390         IgnoreVendor
391 )
392
393 // A Package describes the Go package found in a directory.
394 type Package struct {
395         Dir           string   // directory containing package sources
396         Name          string   // package name
397         ImportComment string   // path in import comment on package statement
398         Doc           string   // documentation synopsis
399         ImportPath    string   // import path of package ("" if unknown)
400         Root          string   // root of Go tree where this package lives
401         SrcRoot       string   // package source root directory ("" if unknown)
402         PkgRoot       string   // package install root directory ("" if unknown)
403         PkgTargetRoot string   // architecture dependent install root directory ("" if unknown)
404         BinDir        string   // command install directory ("" if unknown)
405         Goroot        bool     // package found in Go root
406         PkgObj        string   // installed .a file
407         AllTags       []string // tags that can influence file selection in this directory
408         ConflictDir   string   // this directory shadows Dir in $GOPATH
409         BinaryOnly    bool     // cannot be rebuilt from source (has //go:binary-only-package comment)
410
411         // Source files
412         GoFiles           []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
413         CgoFiles          []string // .go source files that import "C"
414         IgnoredGoFiles    []string // .go source files ignored for this build (including ignored _test.go files)
415         InvalidGoFiles    []string // .go source files with detected problems (parse error, wrong package name, and so on)
416         IgnoredOtherFiles []string // non-.go source files ignored for this build
417         CFiles            []string // .c source files
418         CXXFiles          []string // .cc, .cpp and .cxx source files
419         MFiles            []string // .m (Objective-C) source files
420         HFiles            []string // .h, .hh, .hpp and .hxx source files
421         FFiles            []string // .f, .F, .for and .f90 Fortran source files
422         SFiles            []string // .s source files
423         SwigFiles         []string // .swig files
424         SwigCXXFiles      []string // .swigcxx files
425         SysoFiles         []string // .syso system object files to add to archive
426
427         // Cgo directives
428         CgoCFLAGS    []string // Cgo CFLAGS directives
429         CgoCPPFLAGS  []string // Cgo CPPFLAGS directives
430         CgoCXXFLAGS  []string // Cgo CXXFLAGS directives
431         CgoFFLAGS    []string // Cgo FFLAGS directives
432         CgoLDFLAGS   []string // Cgo LDFLAGS directives
433         CgoPkgConfig []string // Cgo pkg-config directives
434
435         // Test information
436         TestGoFiles  []string // _test.go files in package
437         XTestGoFiles []string // _test.go files outside package
438
439         // Dependency information
440         Imports        []string                    // import paths from GoFiles, CgoFiles
441         ImportPos      map[string][]token.Position // line information for Imports
442         TestImports    []string                    // import paths from TestGoFiles
443         TestImportPos  map[string][]token.Position // line information for TestImports
444         XTestImports   []string                    // import paths from XTestGoFiles
445         XTestImportPos map[string][]token.Position // line information for XTestImports
446
447         // //go:embed patterns found in Go source files
448         // For example, if a source file says
449         //      //go:embed a* b.c
450         // then the list will contain those two strings as separate entries.
451         // (See package embed for more details about //go:embed.)
452         EmbedPatterns        []string                    // patterns from GoFiles, CgoFiles
453         EmbedPatternPos      map[string][]token.Position // line information for EmbedPatterns
454         TestEmbedPatterns    []string                    // patterns from TestGoFiles
455         TestEmbedPatternPos  map[string][]token.Position // line information for TestEmbedPatterns
456         XTestEmbedPatterns   []string                    // patterns from XTestGoFiles
457         XTestEmbedPatternPos map[string][]token.Position // line information for XTestEmbedPatternPos
458 }
459
460 // IsCommand reports whether the package is considered a
461 // command to be installed (not just a library).
462 // Packages named "main" are treated as commands.
463 func (p *Package) IsCommand() bool {
464         return p.Name == "main"
465 }
466
467 // ImportDir is like Import but processes the Go package found in
468 // the named directory.
469 func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
470         return ctxt.Import(".", dir, mode)
471 }
472
473 // NoGoError is the error used by Import to describe a directory
474 // containing no buildable Go source files. (It may still contain
475 // test files, files hidden by build tags, and so on.)
476 type NoGoError struct {
477         Dir string
478 }
479
480 func (e *NoGoError) Error() string {
481         return "no buildable Go source files in " + e.Dir
482 }
483
484 // MultiplePackageError describes a directory containing
485 // multiple buildable Go source files for multiple packages.
486 type MultiplePackageError struct {
487         Dir      string   // directory containing files
488         Packages []string // package names found
489         Files    []string // corresponding files: Files[i] declares package Packages[i]
490 }
491
492 func (e *MultiplePackageError) Error() string {
493         // Error string limited to two entries for compatibility.
494         return fmt.Sprintf("found packages %s (%s) and %s (%s) in %s", e.Packages[0], e.Files[0], e.Packages[1], e.Files[1], e.Dir)
495 }
496
497 func nameExt(name string) string {
498         i := strings.LastIndex(name, ".")
499         if i < 0 {
500                 return ""
501         }
502         return name[i:]
503 }
504
505 // Import returns details about the Go package named by the import path,
506 // interpreting local import paths relative to the srcDir directory.
507 // If the path is a local import path naming a package that can be imported
508 // using a standard import path, the returned package will set p.ImportPath
509 // to that path.
510 //
511 // In the directory containing the package, .go, .c, .h, and .s files are
512 // considered part of the package except for:
513 //
514 //      - .go files in package documentation
515 //      - files starting with _ or . (likely editor temporary files)
516 //      - files with build constraints not satisfied by the context
517 //
518 // If an error occurs, Import returns a non-nil error and a non-nil
519 // *Package containing partial information.
520 //
521 func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) {
522         p := &Package{
523                 ImportPath: path,
524         }
525         if path == "" {
526                 return p, fmt.Errorf("import %q: invalid import path", path)
527         }
528
529         var pkgtargetroot string
530         var pkga string
531         var pkgerr error
532         suffix := ""
533         if ctxt.InstallSuffix != "" {
534                 suffix = "_" + ctxt.InstallSuffix
535         }
536         switch ctxt.Compiler {
537         case "gccgo":
538                 pkgtargetroot = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix
539         case "gc":
540                 pkgtargetroot = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix
541         default:
542                 // Save error for end of function.
543                 pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
544         }
545         setPkga := func() {
546                 switch ctxt.Compiler {
547                 case "gccgo":
548                         dir, elem := pathpkg.Split(p.ImportPath)
549                         pkga = pkgtargetroot + "/" + dir + "lib" + elem + ".a"
550                 case "gc":
551                         pkga = pkgtargetroot + "/" + p.ImportPath + ".a"
552                 }
553         }
554         setPkga()
555
556         binaryOnly := false
557         if IsLocalImport(path) {
558                 pkga = "" // local imports have no installed path
559                 if srcDir == "" {
560                         return p, fmt.Errorf("import %q: import relative to unknown directory", path)
561                 }
562                 if !ctxt.isAbsPath(path) {
563                         p.Dir = ctxt.joinPath(srcDir, path)
564                 }
565                 // p.Dir directory may or may not exist. Gather partial information first, check if it exists later.
566                 // Determine canonical import path, if any.
567                 // Exclude results where the import path would include /testdata/.
568                 inTestdata := func(sub string) bool {
569                         return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || strings.HasPrefix(sub, "testdata/") || sub == "testdata"
570                 }
571                 if ctxt.GOROOT != "" {
572                         root := ctxt.joinPath(ctxt.GOROOT, "src")
573                         if sub, ok := ctxt.hasSubdir(root, p.Dir); ok && !inTestdata(sub) {
574                                 p.Goroot = true
575                                 p.ImportPath = sub
576                                 p.Root = ctxt.GOROOT
577                                 setPkga() // p.ImportPath changed
578                                 goto Found
579                         }
580                 }
581                 all := ctxt.gopath()
582                 for i, root := range all {
583                         rootsrc := ctxt.joinPath(root, "src")
584                         if sub, ok := ctxt.hasSubdir(rootsrc, p.Dir); ok && !inTestdata(sub) {
585                                 // We found a potential import path for dir,
586                                 // but check that using it wouldn't find something
587                                 // else first.
588                                 if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" {
589                                         if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) {
590                                                 p.ConflictDir = dir
591                                                 goto Found
592                                         }
593                                 }
594                                 for _, earlyRoot := range all[:i] {
595                                         if dir := ctxt.joinPath(earlyRoot, "src", sub); ctxt.isDir(dir) {
596                                                 p.ConflictDir = dir
597                                                 goto Found
598                                         }
599                                 }
600
601                                 // sub would not name some other directory instead of this one.
602                                 // Record it.
603                                 p.ImportPath = sub
604                                 p.Root = root
605                                 setPkga() // p.ImportPath changed
606                                 goto Found
607                         }
608                 }
609                 // It's okay that we didn't find a root containing dir.
610                 // Keep going with the information we have.
611         } else {
612                 if strings.HasPrefix(path, "/") {
613                         return p, fmt.Errorf("import %q: cannot import absolute path", path)
614                 }
615
616                 if err := ctxt.importGo(p, path, srcDir, mode); err == nil {
617                         goto Found
618                 } else if err != errNoModules {
619                         return p, err
620                 }
621
622                 gopath := ctxt.gopath() // needed twice below; avoid computing many times
623
624                 // tried records the location of unsuccessful package lookups
625                 var tried struct {
626                         vendor []string
627                         goroot string
628                         gopath []string
629                 }
630
631                 // Vendor directories get first chance to satisfy import.
632                 if mode&IgnoreVendor == 0 && srcDir != "" {
633                         searchVendor := func(root string, isGoroot bool) bool {
634                                 sub, ok := ctxt.hasSubdir(root, srcDir)
635                                 if !ok || !strings.HasPrefix(sub, "src/") || strings.Contains(sub, "/testdata/") {
636                                         return false
637                                 }
638                                 for {
639                                         vendor := ctxt.joinPath(root, sub, "vendor")
640                                         if ctxt.isDir(vendor) {
641                                                 dir := ctxt.joinPath(vendor, path)
642                                                 if ctxt.isDir(dir) && hasGoFiles(ctxt, dir) {
643                                                         p.Dir = dir
644                                                         p.ImportPath = strings.TrimPrefix(pathpkg.Join(sub, "vendor", path), "src/")
645                                                         p.Goroot = isGoroot
646                                                         p.Root = root
647                                                         setPkga() // p.ImportPath changed
648                                                         return true
649                                                 }
650                                                 tried.vendor = append(tried.vendor, dir)
651                                         }
652                                         i := strings.LastIndex(sub, "/")
653                                         if i < 0 {
654                                                 break
655                                         }
656                                         sub = sub[:i]
657                                 }
658                                 return false
659                         }
660                         if ctxt.Compiler != "gccgo" && searchVendor(ctxt.GOROOT, true) {
661                                 goto Found
662                         }
663                         for _, root := range gopath {
664                                 if searchVendor(root, false) {
665                                         goto Found
666                                 }
667                         }
668                 }
669
670                 // Determine directory from import path.
671                 if ctxt.GOROOT != "" {
672                         // If the package path starts with "vendor/", only search GOROOT before
673                         // GOPATH if the importer is also within GOROOT. That way, if the user has
674                         // vendored in a package that is subsequently included in the standard
675                         // distribution, they'll continue to pick up their own vendored copy.
676                         gorootFirst := srcDir == "" || !strings.HasPrefix(path, "vendor/")
677                         if !gorootFirst {
678                                 _, gorootFirst = ctxt.hasSubdir(ctxt.GOROOT, srcDir)
679                         }
680                         if gorootFirst {
681                                 dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
682                                 if ctxt.Compiler != "gccgo" {
683                                         isDir := ctxt.isDir(dir)
684                                         binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
685                                         if isDir || binaryOnly {
686                                                 p.Dir = dir
687                                                 p.Goroot = true
688                                                 p.Root = ctxt.GOROOT
689                                                 goto Found
690                                         }
691                                 }
692                                 tried.goroot = dir
693                         }
694                 }
695                 if ctxt.Compiler == "gccgo" && goroot.IsStandardPackage(ctxt.GOROOT, ctxt.Compiler, path) {
696                         p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path)
697                         p.Goroot = true
698                         p.Root = ctxt.GOROOT
699                         goto Found
700                 }
701                 for _, root := range gopath {
702                         dir := ctxt.joinPath(root, "src", path)
703                         isDir := ctxt.isDir(dir)
704                         binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(root, pkga))
705                         if isDir || binaryOnly {
706                                 p.Dir = dir
707                                 p.Root = root
708                                 goto Found
709                         }
710                         tried.gopath = append(tried.gopath, dir)
711                 }
712
713                 // If we tried GOPATH first due to a "vendor/" prefix, fall back to GOPATH.
714                 // That way, the user can still get useful results from 'go list' for
715                 // standard-vendored paths passed on the command line.
716                 if ctxt.GOROOT != "" && tried.goroot == "" {
717                         dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
718                         if ctxt.Compiler != "gccgo" {
719                                 isDir := ctxt.isDir(dir)
720                                 binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga))
721                                 if isDir || binaryOnly {
722                                         p.Dir = dir
723                                         p.Goroot = true
724                                         p.Root = ctxt.GOROOT
725                                         goto Found
726                                 }
727                         }
728                         tried.goroot = dir
729                 }
730
731                 // package was not found
732                 var paths []string
733                 format := "\t%s (vendor tree)"
734                 for _, dir := range tried.vendor {
735                         paths = append(paths, fmt.Sprintf(format, dir))
736                         format = "\t%s"
737                 }
738                 if tried.goroot != "" {
739                         paths = append(paths, fmt.Sprintf("\t%s (from $GOROOT)", tried.goroot))
740                 } else {
741                         paths = append(paths, "\t($GOROOT not set)")
742                 }
743                 format = "\t%s (from $GOPATH)"
744                 for _, dir := range tried.gopath {
745                         paths = append(paths, fmt.Sprintf(format, dir))
746                         format = "\t%s"
747                 }
748                 if len(tried.gopath) == 0 {
749                         paths = append(paths, "\t($GOPATH not set. For more details see: 'go help gopath')")
750                 }
751                 return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n"))
752         }
753
754 Found:
755         if p.Root != "" {
756                 p.SrcRoot = ctxt.joinPath(p.Root, "src")
757                 p.PkgRoot = ctxt.joinPath(p.Root, "pkg")
758                 p.BinDir = ctxt.joinPath(p.Root, "bin")
759                 if pkga != "" {
760                         p.PkgTargetRoot = ctxt.joinPath(p.Root, pkgtargetroot)
761                         p.PkgObj = ctxt.joinPath(p.Root, pkga)
762                 }
763         }
764
765         // If it's a local import path, by the time we get here, we still haven't checked
766         // that p.Dir directory exists. This is the right time to do that check.
767         // We can't do it earlier, because we want to gather partial information for the
768         // non-nil *Package returned when an error occurs.
769         // We need to do this before we return early on FindOnly flag.
770         if IsLocalImport(path) && !ctxt.isDir(p.Dir) {
771                 if ctxt.Compiler == "gccgo" && p.Goroot {
772                         // gccgo has no sources for GOROOT packages.
773                         return p, nil
774                 }
775
776                 // package was not found
777                 return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir)
778         }
779
780         if mode&FindOnly != 0 {
781                 return p, pkgerr
782         }
783         if binaryOnly && (mode&AllowBinary) != 0 {
784                 return p, pkgerr
785         }
786
787         if ctxt.Compiler == "gccgo" && p.Goroot {
788                 // gccgo has no sources for GOROOT packages.
789                 return p, nil
790         }
791
792         dirs, err := ctxt.readDir(p.Dir)
793         if err != nil {
794                 return p, err
795         }
796
797         var badGoError error
798         var Sfiles []string // files with ".S"(capital S)/.sx(capital s equivalent for case insensitive filesystems)
799         var firstFile, firstCommentFile string
800         embedPos := make(map[string][]token.Position)
801         testEmbedPos := make(map[string][]token.Position)
802         xTestEmbedPos := make(map[string][]token.Position)
803         importPos := make(map[string][]token.Position)
804         testImportPos := make(map[string][]token.Position)
805         xTestImportPos := make(map[string][]token.Position)
806         allTags := make(map[string]bool)
807         fset := token.NewFileSet()
808         for _, d := range dirs {
809                 if d.IsDir() {
810                         continue
811                 }
812                 if d.Mode()&fs.ModeSymlink != 0 {
813                         if ctxt.isDir(ctxt.joinPath(p.Dir, d.Name())) {
814                                 // Symlinks to directories are not source files.
815                                 continue
816                         }
817                 }
818
819                 name := d.Name()
820                 ext := nameExt(name)
821
822                 badFile := func(err error) {
823                         if badGoError == nil {
824                                 badGoError = err
825                         }
826                         p.InvalidGoFiles = append(p.InvalidGoFiles, name)
827                 }
828
829                 info, err := ctxt.matchFile(p.Dir, name, allTags, &p.BinaryOnly, fset)
830                 if err != nil {
831                         badFile(err)
832                         continue
833                 }
834                 if info == nil {
835                         if strings.HasPrefix(name, "_") || strings.HasPrefix(name, ".") {
836                                 // not due to build constraints - don't report
837                         } else if ext == ".go" {
838                                 p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
839                         } else if fileListForExt(p, ext) != nil {
840                                 p.IgnoredOtherFiles = append(p.IgnoredOtherFiles, name)
841                         }
842                         continue
843                 }
844                 data, filename := info.header, info.name
845
846                 // Going to save the file. For non-Go files, can stop here.
847                 switch ext {
848                 case ".go":
849                         // keep going
850                 case ".S", ".sx":
851                         // special case for cgo, handled at end
852                         Sfiles = append(Sfiles, name)
853                         continue
854                 default:
855                         if list := fileListForExt(p, ext); list != nil {
856                                 *list = append(*list, name)
857                         }
858                         continue
859                 }
860
861                 if info.parseErr != nil {
862                         badFile(info.parseErr)
863                         continue
864                 }
865                 pf := info.parsed
866
867                 pkg := pf.Name.Name
868                 if pkg == "documentation" {
869                         p.IgnoredGoFiles = append(p.IgnoredGoFiles, name)
870                         continue
871                 }
872
873                 isTest := strings.HasSuffix(name, "_test.go")
874                 isXTest := false
875                 if isTest && strings.HasSuffix(pkg, "_test") {
876                         isXTest = true
877                         pkg = pkg[:len(pkg)-len("_test")]
878                 }
879
880                 if p.Name == "" {
881                         p.Name = pkg
882                         firstFile = name
883                 } else if pkg != p.Name {
884                         badFile(&MultiplePackageError{
885                                 Dir:      p.Dir,
886                                 Packages: []string{p.Name, pkg},
887                                 Files:    []string{firstFile, name},
888                         })
889                         p.InvalidGoFiles = append(p.InvalidGoFiles, name)
890                 }
891                 // Grab the first package comment as docs, provided it is not from a test file.
892                 if pf.Doc != nil && p.Doc == "" && !isTest && !isXTest {
893                         p.Doc = doc.Synopsis(pf.Doc.Text())
894                 }
895
896                 if mode&ImportComment != 0 {
897                         qcom, line := findImportComment(data)
898                         if line != 0 {
899                                 com, err := strconv.Unquote(qcom)
900                                 if err != nil {
901                                         badFile(fmt.Errorf("%s:%d: cannot parse import comment", filename, line))
902                                 } else if p.ImportComment == "" {
903                                         p.ImportComment = com
904                                         firstCommentFile = name
905                                 } else if p.ImportComment != com {
906                                         badFile(fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir))
907                                 }
908                         }
909                 }
910
911                 // Record imports and information about cgo.
912                 isCgo := false
913                 for _, imp := range info.imports {
914                         if imp.path == "C" {
915                                 if isTest {
916                                         badFile(fmt.Errorf("use of cgo in test %s not supported", filename))
917                                         continue
918                                 }
919                                 isCgo = true
920                                 if imp.doc != nil {
921                                         if err := ctxt.saveCgo(filename, p, imp.doc); err != nil {
922                                                 badFile(err)
923                                         }
924                                 }
925                         }
926                 }
927
928                 var fileList *[]string
929                 var importMap, embedMap map[string][]token.Position
930                 switch {
931                 case isCgo:
932                         allTags["cgo"] = true
933                         if ctxt.CgoEnabled {
934                                 fileList = &p.CgoFiles
935                                 importMap = importPos
936                                 embedMap = embedPos
937                         } else {
938                                 // Ignore imports and embeds from cgo files if cgo is disabled.
939                                 fileList = &p.IgnoredGoFiles
940                         }
941                 case isXTest:
942                         fileList = &p.XTestGoFiles
943                         importMap = xTestImportPos
944                         embedMap = xTestEmbedPos
945                 case isTest:
946                         fileList = &p.TestGoFiles
947                         importMap = testImportPos
948                         embedMap = testEmbedPos
949                 default:
950                         fileList = &p.GoFiles
951                         importMap = importPos
952                         embedMap = embedPos
953                 }
954                 *fileList = append(*fileList, name)
955                 if importMap != nil {
956                         for _, imp := range info.imports {
957                                 importMap[imp.path] = append(importMap[imp.path], fset.Position(imp.pos))
958                         }
959                 }
960                 if embedMap != nil {
961                         for _, emb := range info.embeds {
962                                 embedMap[emb.pattern] = append(embedMap[emb.pattern], emb.pos)
963                         }
964                 }
965         }
966
967         for tag := range allTags {
968                 p.AllTags = append(p.AllTags, tag)
969         }
970         sort.Strings(p.AllTags)
971
972         p.EmbedPatterns, p.EmbedPatternPos = cleanDecls(embedPos)
973         p.TestEmbedPatterns, p.TestEmbedPatternPos = cleanDecls(testEmbedPos)
974         p.XTestEmbedPatterns, p.XTestEmbedPatternPos = cleanDecls(xTestEmbedPos)
975
976         p.Imports, p.ImportPos = cleanDecls(importPos)
977         p.TestImports, p.TestImportPos = cleanDecls(testImportPos)
978         p.XTestImports, p.XTestImportPos = cleanDecls(xTestImportPos)
979
980         // add the .S/.sx files only if we are using cgo
981         // (which means gcc will compile them).
982         // The standard assemblers expect .s files.
983         if len(p.CgoFiles) > 0 {
984                 p.SFiles = append(p.SFiles, Sfiles...)
985                 sort.Strings(p.SFiles)
986         } else {
987                 p.IgnoredOtherFiles = append(p.IgnoredOtherFiles, Sfiles...)
988                 sort.Strings(p.IgnoredOtherFiles)
989         }
990
991         if badGoError != nil {
992                 return p, badGoError
993         }
994         if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
995                 return p, &NoGoError{p.Dir}
996         }
997         return p, pkgerr
998 }
999
1000 func fileListForExt(p *Package, ext string) *[]string {
1001         switch ext {
1002         case ".c":
1003                 return &p.CFiles
1004         case ".cc", ".cpp", ".cxx":
1005                 return &p.CXXFiles
1006         case ".m":
1007                 return &p.MFiles
1008         case ".h", ".hh", ".hpp", ".hxx":
1009                 return &p.HFiles
1010         case ".f", ".F", ".for", ".f90":
1011                 return &p.FFiles
1012         case ".s", ".S", ".sx":
1013                 return &p.SFiles
1014         case ".swig":
1015                 return &p.SwigFiles
1016         case ".swigcxx":
1017                 return &p.SwigCXXFiles
1018         case ".syso":
1019                 return &p.SysoFiles
1020         }
1021         return nil
1022 }
1023
1024 func uniq(list []string) []string {
1025         if list == nil {
1026                 return nil
1027         }
1028         out := make([]string, len(list))
1029         copy(out, list)
1030         sort.Strings(out)
1031         uniq := out[:0]
1032         for _, x := range out {
1033                 if len(uniq) == 0 || uniq[len(uniq)-1] != x {
1034                         uniq = append(uniq, x)
1035                 }
1036         }
1037         return uniq
1038 }
1039
1040 var errNoModules = errors.New("not using modules")
1041
1042 // importGo checks whether it can use the go command to find the directory for path.
1043 // If using the go command is not appropriate, importGo returns errNoModules.
1044 // Otherwise, importGo tries using the go command and reports whether that succeeded.
1045 // Using the go command lets build.Import and build.Context.Import find code
1046 // in Go modules. In the long term we want tools to use go/packages (currently golang.org/x/tools/go/packages),
1047 // which will also use the go command.
1048 // Invoking the go command here is not very efficient in that it computes information
1049 // about the requested package and all dependencies and then only reports about the requested package.
1050 // Then we reinvoke it for every dependency. But this is still better than not working at all.
1051 // See golang.org/issue/26504.
1052 func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) error {
1053         // To invoke the go command,
1054         // we must not being doing special things like AllowBinary or IgnoreVendor,
1055         // and all the file system callbacks must be nil (we're meant to use the local file system).
1056         if mode&AllowBinary != 0 || mode&IgnoreVendor != 0 ||
1057                 ctxt.JoinPath != nil || ctxt.SplitPathList != nil || ctxt.IsAbsPath != nil || ctxt.IsDir != nil || ctxt.HasSubdir != nil || ctxt.ReadDir != nil || ctxt.OpenFile != nil || !equal(ctxt.ReleaseTags, defaultReleaseTags) {
1058                 return errNoModules
1059         }
1060
1061         // Predict whether module aware mode is enabled by checking the value of
1062         // GO111MODULE and looking for a go.mod file in the source directory or
1063         // one of its parents. Running 'go env GOMOD' in the source directory would
1064         // give a canonical answer, but we'd prefer not to execute another command.
1065         go111Module := os.Getenv("GO111MODULE")
1066         switch go111Module {
1067         case "off":
1068                 return errNoModules
1069         default: // "", "on", "auto", anything else
1070                 // Maybe use modules.
1071         }
1072
1073         if srcDir != "" {
1074                 var absSrcDir string
1075                 if filepath.IsAbs(srcDir) {
1076                         absSrcDir = srcDir
1077                 } else if ctxt.Dir != "" {
1078                         return fmt.Errorf("go/build: Dir is non-empty, so relative srcDir is not allowed: %v", srcDir)
1079                 } else {
1080                         // Find the absolute source directory. hasSubdir does not handle
1081                         // relative paths (and can't because the callbacks don't support this).
1082                         var err error
1083                         absSrcDir, err = filepath.Abs(srcDir)
1084                         if err != nil {
1085                                 return errNoModules
1086                         }
1087                 }
1088
1089                 // If the source directory is in GOROOT, then the in-process code works fine
1090                 // and we should keep using it. Moreover, the 'go list' approach below doesn't
1091                 // take standard-library vendoring into account and will fail.
1092                 if _, ok := ctxt.hasSubdir(filepath.Join(ctxt.GOROOT, "src"), absSrcDir); ok {
1093                         return errNoModules
1094                 }
1095         }
1096
1097         // For efficiency, if path is a standard library package, let the usual lookup code handle it.
1098         if ctxt.GOROOT != "" {
1099                 dir := ctxt.joinPath(ctxt.GOROOT, "src", path)
1100                 if ctxt.isDir(dir) {
1101                         return errNoModules
1102                 }
1103         }
1104
1105         // If GO111MODULE=auto, look to see if there is a go.mod.
1106         // Since go1.13, it doesn't matter if we're inside GOPATH.
1107         if go111Module == "auto" {
1108                 var (
1109                         parent string
1110                         err    error
1111                 )
1112                 if ctxt.Dir == "" {
1113                         parent, err = os.Getwd()
1114                         if err != nil {
1115                                 // A nonexistent working directory can't be in a module.
1116                                 return errNoModules
1117                         }
1118                 } else {
1119                         parent, err = filepath.Abs(ctxt.Dir)
1120                         if err != nil {
1121                                 // If the caller passed a bogus Dir explicitly, that's materially
1122                                 // different from not having modules enabled.
1123                                 return err
1124                         }
1125                 }
1126                 for {
1127                         if f, err := ctxt.openFile(ctxt.joinPath(parent, "go.mod")); err == nil {
1128                                 buf := make([]byte, 100)
1129                                 _, err := f.Read(buf)
1130                                 f.Close()
1131                                 if err == nil || err == io.EOF {
1132                                         // go.mod exists and is readable (is a file, not a directory).
1133                                         break
1134                                 }
1135                         }
1136                         d := filepath.Dir(parent)
1137                         if len(d) >= len(parent) {
1138                                 return errNoModules // reached top of file system, no go.mod
1139                         }
1140                         parent = d
1141                 }
1142         }
1143
1144         cmd := exec.Command("go", "list", "-e", "-compiler="+ctxt.Compiler, "-tags="+strings.Join(ctxt.BuildTags, ","), "-installsuffix="+ctxt.InstallSuffix, "-f={{.Dir}}\n{{.ImportPath}}\n{{.Root}}\n{{.Goroot}}\n{{if .Error}}{{.Error}}{{end}}\n", "--", path)
1145
1146         if ctxt.Dir != "" {
1147                 cmd.Dir = ctxt.Dir
1148         }
1149
1150         var stdout, stderr strings.Builder
1151         cmd.Stdout = &stdout
1152         cmd.Stderr = &stderr
1153
1154         cgo := "0"
1155         if ctxt.CgoEnabled {
1156                 cgo = "1"
1157         }
1158         cmd.Env = append(os.Environ(),
1159                 "GOOS="+ctxt.GOOS,
1160                 "GOARCH="+ctxt.GOARCH,
1161                 "GOROOT="+ctxt.GOROOT,
1162                 "GOPATH="+ctxt.GOPATH,
1163                 "CGO_ENABLED="+cgo,
1164         )
1165
1166         if err := cmd.Run(); err != nil {
1167                 return fmt.Errorf("go/build: go list %s: %v\n%s\n", path, err, stderr.String())
1168         }
1169
1170         f := strings.SplitN(stdout.String(), "\n", 5)
1171         if len(f) != 5 {
1172                 return fmt.Errorf("go/build: importGo %s: unexpected output:\n%s\n", path, stdout.String())
1173         }
1174         dir := f[0]
1175         errStr := strings.TrimSpace(f[4])
1176         if errStr != "" && dir == "" {
1177                 // If 'go list' could not locate the package (dir is empty),
1178                 // return the same error that 'go list' reported.
1179                 return errors.New(errStr)
1180         }
1181
1182         // If 'go list' did locate the package, ignore the error.
1183         // It was probably related to loading source files, and we'll
1184         // encounter it ourselves shortly if the FindOnly flag isn't set.
1185         p.Dir = dir
1186         p.ImportPath = f[1]
1187         p.Root = f[2]
1188         p.Goroot = f[3] == "true"
1189         return nil
1190 }
1191
1192 func equal(x, y []string) bool {
1193         if len(x) != len(y) {
1194                 return false
1195         }
1196         for i, xi := range x {
1197                 if xi != y[i] {
1198                         return false
1199                 }
1200         }
1201         return true
1202 }
1203
1204 // hasGoFiles reports whether dir contains any files with names ending in .go.
1205 // For a vendor check we must exclude directories that contain no .go files.
1206 // Otherwise it is not possible to vendor just a/b/c and still import the
1207 // non-vendored a/b. See golang.org/issue/13832.
1208 func hasGoFiles(ctxt *Context, dir string) bool {
1209         ents, _ := ctxt.readDir(dir)
1210         for _, ent := range ents {
1211                 if !ent.IsDir() && strings.HasSuffix(ent.Name(), ".go") {
1212                         return true
1213                 }
1214         }
1215         return false
1216 }
1217
1218 func findImportComment(data []byte) (s string, line int) {
1219         // expect keyword package
1220         word, data := parseWord(data)
1221         if string(word) != "package" {
1222                 return "", 0
1223         }
1224
1225         // expect package name
1226         _, data = parseWord(data)
1227
1228         // now ready for import comment, a // or /* */ comment
1229         // beginning and ending on the current line.
1230         for len(data) > 0 && (data[0] == ' ' || data[0] == '\t' || data[0] == '\r') {
1231                 data = data[1:]
1232         }
1233
1234         var comment []byte
1235         switch {
1236         case bytes.HasPrefix(data, slashSlash):
1237                 i := bytes.Index(data, newline)
1238                 if i < 0 {
1239                         i = len(data)
1240                 }
1241                 comment = data[2:i]
1242         case bytes.HasPrefix(data, slashStar):
1243                 data = data[2:]
1244                 i := bytes.Index(data, starSlash)
1245                 if i < 0 {
1246                         // malformed comment
1247                         return "", 0
1248                 }
1249                 comment = data[:i]
1250                 if bytes.Contains(comment, newline) {
1251                         return "", 0
1252                 }
1253         }
1254         comment = bytes.TrimSpace(comment)
1255
1256         // split comment into `import`, `"pkg"`
1257         word, arg := parseWord(comment)
1258         if string(word) != "import" {
1259                 return "", 0
1260         }
1261
1262         line = 1 + bytes.Count(data[:cap(data)-cap(arg)], newline)
1263         return strings.TrimSpace(string(arg)), line
1264 }
1265
1266 var (
1267         slashSlash = []byte("//")
1268         slashStar  = []byte("/*")
1269         starSlash  = []byte("*/")
1270         newline    = []byte("\n")
1271 )
1272
1273 // skipSpaceOrComment returns data with any leading spaces or comments removed.
1274 func skipSpaceOrComment(data []byte) []byte {
1275         for len(data) > 0 {
1276                 switch data[0] {
1277                 case ' ', '\t', '\r', '\n':
1278                         data = data[1:]
1279                         continue
1280                 case '/':
1281                         if bytes.HasPrefix(data, slashSlash) {
1282                                 i := bytes.Index(data, newline)
1283                                 if i < 0 {
1284                                         return nil
1285                                 }
1286                                 data = data[i+1:]
1287                                 continue
1288                         }
1289                         if bytes.HasPrefix(data, slashStar) {
1290                                 data = data[2:]
1291                                 i := bytes.Index(data, starSlash)
1292                                 if i < 0 {
1293                                         return nil
1294                                 }
1295                                 data = data[i+2:]
1296                                 continue
1297                         }
1298                 }
1299                 break
1300         }
1301         return data
1302 }
1303
1304 // parseWord skips any leading spaces or comments in data
1305 // and then parses the beginning of data as an identifier or keyword,
1306 // returning that word and what remains after the word.
1307 func parseWord(data []byte) (word, rest []byte) {
1308         data = skipSpaceOrComment(data)
1309
1310         // Parse past leading word characters.
1311         rest = data
1312         for {
1313                 r, size := utf8.DecodeRune(rest)
1314                 if unicode.IsLetter(r) || '0' <= r && r <= '9' || r == '_' {
1315                         rest = rest[size:]
1316                         continue
1317                 }
1318                 break
1319         }
1320
1321         word = data[:len(data)-len(rest)]
1322         if len(word) == 0 {
1323                 return nil, nil
1324         }
1325
1326         return word, rest
1327 }
1328
1329 // MatchFile reports whether the file with the given name in the given directory
1330 // matches the context and would be included in a Package created by ImportDir
1331 // of that directory.
1332 //
1333 // MatchFile considers the name of the file and may use ctxt.OpenFile to
1334 // read some or all of the file's content.
1335 func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) {
1336         info, err := ctxt.matchFile(dir, name, nil, nil, nil)
1337         return info != nil, err
1338 }
1339
1340 var dummyPkg Package
1341
1342 // fileInfo records information learned about a file included in a build.
1343 type fileInfo struct {
1344         name     string // full name including dir
1345         header   []byte
1346         fset     *token.FileSet
1347         parsed   *ast.File
1348         parseErr error
1349         imports  []fileImport
1350         embeds   []fileEmbed
1351         embedErr error
1352 }
1353
1354 type fileImport struct {
1355         path string
1356         pos  token.Pos
1357         doc  *ast.CommentGroup
1358 }
1359
1360 type fileEmbed struct {
1361         pattern string
1362         pos     token.Position
1363 }
1364
1365 // matchFile determines whether the file with the given name in the given directory
1366 // should be included in the package being constructed.
1367 // If the file should be included, matchFile returns a non-nil *fileInfo (and a nil error).
1368 // Non-nil errors are reserved for unexpected problems.
1369 //
1370 // If name denotes a Go program, matchFile reads until the end of the
1371 // imports and returns that section of the file in the fileInfo's header field,
1372 // even though it only considers text until the first non-comment
1373 // for +build lines.
1374 //
1375 // If allTags is non-nil, matchFile records any encountered build tag
1376 // by setting allTags[tag] = true.
1377 func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binaryOnly *bool, fset *token.FileSet) (*fileInfo, error) {
1378         if strings.HasPrefix(name, "_") ||
1379                 strings.HasPrefix(name, ".") {
1380                 return nil, nil
1381         }
1382
1383         i := strings.LastIndex(name, ".")
1384         if i < 0 {
1385                 i = len(name)
1386         }
1387         ext := name[i:]
1388
1389         if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles {
1390                 return nil, nil
1391         }
1392
1393         if ext != ".go" && fileListForExt(&dummyPkg, ext) == nil {
1394                 // skip
1395                 return nil, nil
1396         }
1397
1398         info := &fileInfo{name: ctxt.joinPath(dir, name), fset: fset}
1399         if ext == ".syso" {
1400                 // binary, no reading
1401                 return info, nil
1402         }
1403
1404         f, err := ctxt.openFile(info.name)
1405         if err != nil {
1406                 return nil, err
1407         }
1408
1409         if strings.HasSuffix(name, ".go") {
1410                 err = readGoInfo(f, info)
1411                 if strings.HasSuffix(name, "_test.go") {
1412                         binaryOnly = nil // ignore //go:binary-only-package comments in _test.go files
1413                 }
1414         } else {
1415                 binaryOnly = nil // ignore //go:binary-only-package comments in non-Go sources
1416                 info.header, err = readComments(f)
1417         }
1418         f.Close()
1419         if err != nil {
1420                 return nil, fmt.Errorf("read %s: %v", info.name, err)
1421         }
1422
1423         // Look for +build comments to accept or reject the file.
1424         ok, sawBinaryOnly, err := ctxt.shouldBuild(info.header, allTags)
1425         if err != nil {
1426                 return nil, err
1427         }
1428         if !ok && !ctxt.UseAllFiles {
1429                 return nil, nil
1430         }
1431
1432         if binaryOnly != nil && sawBinaryOnly {
1433                 *binaryOnly = true
1434         }
1435
1436         return info, nil
1437 }
1438
1439 func cleanDecls(m map[string][]token.Position) ([]string, map[string][]token.Position) {
1440         all := make([]string, 0, len(m))
1441         for path := range m {
1442                 all = append(all, path)
1443         }
1444         sort.Strings(all)
1445         return all, m
1446 }
1447
1448 // Import is shorthand for Default.Import.
1449 func Import(path, srcDir string, mode ImportMode) (*Package, error) {
1450         return Default.Import(path, srcDir, mode)
1451 }
1452
1453 // ImportDir is shorthand for Default.ImportDir.
1454 func ImportDir(dir string, mode ImportMode) (*Package, error) {
1455         return Default.ImportDir(dir, mode)
1456 }
1457
1458 var (
1459         bSlashSlash = []byte(slashSlash)
1460         bStarSlash  = []byte(starSlash)
1461         bSlashStar  = []byte(slashStar)
1462
1463         goBuildComment = []byte("//go:build")
1464
1465         errGoBuildWithoutBuild = errors.New("//go:build comment without // +build comment")
1466         errMultipleGoBuild     = errors.New("multiple //go:build comments") // unused in Go 1.(N-1)
1467 )
1468
1469 func isGoBuildComment(line []byte) bool {
1470         if !bytes.HasPrefix(line, goBuildComment) {
1471                 return false
1472         }
1473         line = bytes.TrimSpace(line)
1474         rest := line[len(goBuildComment):]
1475         return len(rest) == 0 || len(bytes.TrimSpace(rest)) < len(rest)
1476 }
1477
1478 // Special comment denoting a binary-only package.
1479 // See https://golang.org/design/2775-binary-only-packages
1480 // for more about the design of binary-only packages.
1481 var binaryOnlyComment = []byte("//go:binary-only-package")
1482
1483 // shouldBuild reports whether it is okay to use this file,
1484 // The rule is that in the file's leading run of // comments
1485 // and blank lines, which must be followed by a blank line
1486 // (to avoid including a Go package clause doc comment),
1487 // lines beginning with '// +build' are taken as build directives.
1488 //
1489 // The file is accepted only if each such line lists something
1490 // matching the file. For example:
1491 //
1492 //      // +build windows linux
1493 //
1494 // marks the file as applicable only on Windows and Linux.
1495 //
1496 // For each build tag it consults, shouldBuild sets allTags[tag] = true.
1497 //
1498 // shouldBuild reports whether the file should be built
1499 // and whether a //go:binary-only-package comment was found.
1500 func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) (shouldBuild, binaryOnly bool, err error) {
1501
1502         // Pass 1. Identify leading run of // comments and blank lines,
1503         // which must be followed by a blank line.
1504         // Also identify any //go:build comments.
1505         content, goBuild, sawBinaryOnly, err := parseFileHeader(content)
1506         if err != nil {
1507                 return false, false, err
1508         }
1509
1510         // Pass 2.  Process each +build line in the run.
1511         p := content
1512         shouldBuild = true
1513         sawBuild := false
1514         for len(p) > 0 {
1515                 line := p
1516                 if i := bytes.IndexByte(line, '\n'); i >= 0 {
1517                         line, p = line[:i], p[i+1:]
1518                 } else {
1519                         p = p[len(p):]
1520                 }
1521                 line = bytes.TrimSpace(line)
1522                 if !bytes.HasPrefix(line, bSlashSlash) {
1523                         continue
1524                 }
1525                 line = bytes.TrimSpace(line[len(bSlashSlash):])
1526                 if len(line) > 0 && line[0] == '+' {
1527                         // Looks like a comment +line.
1528                         f := strings.Fields(string(line))
1529                         if f[0] == "+build" {
1530                                 sawBuild = true
1531                                 ok := false
1532                                 for _, tok := range f[1:] {
1533                                         if ctxt.match(tok, allTags) {
1534                                                 ok = true
1535                                         }
1536                                 }
1537                                 if !ok {
1538                                         shouldBuild = false
1539                                 }
1540                         }
1541                 }
1542         }
1543
1544         if goBuild != nil && !sawBuild {
1545                 return false, false, errGoBuildWithoutBuild
1546         }
1547
1548         return shouldBuild, sawBinaryOnly, nil
1549 }
1550
1551 func parseFileHeader(content []byte) (trimmed, goBuild []byte, sawBinaryOnly bool, err error) {
1552         end := 0
1553         p := content
1554         ended := false       // found non-blank, non-// line, so stopped accepting // +build lines
1555         inSlashStar := false // in /* */ comment
1556
1557 Lines:
1558         for len(p) > 0 {
1559                 line := p
1560                 if i := bytes.IndexByte(line, '\n'); i >= 0 {
1561                         line, p = line[:i], p[i+1:]
1562                 } else {
1563                         p = p[len(p):]
1564                 }
1565                 line = bytes.TrimSpace(line)
1566                 if len(line) == 0 && !ended { // Blank line
1567                         // Remember position of most recent blank line.
1568                         // When we find the first non-blank, non-// line,
1569                         // this "end" position marks the latest file position
1570                         // where a // +build line can appear.
1571                         // (It must appear _before_ a blank line before the non-blank, non-// line.
1572                         // Yes, that's confusing, which is part of why we moved to //go:build lines.)
1573                         // Note that ended==false here means that inSlashStar==false,
1574                         // since seeing a /* would have set ended==true.
1575                         end = len(content) - len(p)
1576                         continue Lines
1577                 }
1578                 if !bytes.HasPrefix(line, slashSlash) { // Not comment line
1579                         ended = true
1580                 }
1581
1582                 if !inSlashStar && isGoBuildComment(line) {
1583                         if false && goBuild != nil { // enabled in Go 1.N
1584                                 return nil, nil, false, errMultipleGoBuild
1585                         }
1586                         goBuild = line
1587                 }
1588                 if !inSlashStar && bytes.Equal(line, binaryOnlyComment) {
1589                         sawBinaryOnly = true
1590                 }
1591
1592         Comments:
1593                 for len(line) > 0 {
1594                         if inSlashStar {
1595                                 if i := bytes.Index(line, starSlash); i >= 0 {
1596                                         inSlashStar = false
1597                                         line = bytes.TrimSpace(line[i+len(starSlash):])
1598                                         continue Comments
1599                                 }
1600                                 continue Lines
1601                         }
1602                         if bytes.HasPrefix(line, bSlashSlash) {
1603                                 continue Lines
1604                         }
1605                         if bytes.HasPrefix(line, bSlashStar) {
1606                                 inSlashStar = true
1607                                 line = bytes.TrimSpace(line[len(bSlashStar):])
1608                                 continue Comments
1609                         }
1610                         // Found non-comment text.
1611                         break Lines
1612                 }
1613         }
1614
1615         return content[:end], goBuild, sawBinaryOnly, nil
1616 }
1617
1618 // saveCgo saves the information from the #cgo lines in the import "C" comment.
1619 // These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives
1620 // that affect the way cgo's C code is built.
1621 func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) error {
1622         text := cg.Text()
1623         for _, line := range strings.Split(text, "\n") {
1624                 orig := line
1625
1626                 // Line is
1627                 //      #cgo [GOOS/GOARCH...] LDFLAGS: stuff
1628                 //
1629                 line = strings.TrimSpace(line)
1630                 if len(line) < 5 || line[:4] != "#cgo" || (line[4] != ' ' && line[4] != '\t') {
1631                         continue
1632                 }
1633
1634                 // Split at colon.
1635                 line = strings.TrimSpace(line[4:])
1636                 i := strings.Index(line, ":")
1637                 if i < 0 {
1638                         return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
1639                 }
1640                 line, argstr := line[:i], line[i+1:]
1641
1642                 // Parse GOOS/GOARCH stuff.
1643                 f := strings.Fields(line)
1644                 if len(f) < 1 {
1645                         return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
1646                 }
1647
1648                 cond, verb := f[:len(f)-1], f[len(f)-1]
1649                 if len(cond) > 0 {
1650                         ok := false
1651                         for _, c := range cond {
1652                                 if ctxt.match(c, nil) {
1653                                         ok = true
1654                                         break
1655                                 }
1656                         }
1657                         if !ok {
1658                                 continue
1659                         }
1660                 }
1661
1662                 args, err := splitQuoted(argstr)
1663                 if err != nil {
1664                         return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
1665                 }
1666                 var ok bool
1667                 for i, arg := range args {
1668                         if arg, ok = expandSrcDir(arg, di.Dir); !ok {
1669                                 return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
1670                         }
1671                         args[i] = arg
1672                 }
1673
1674                 switch verb {
1675                 case "CFLAGS", "CPPFLAGS", "CXXFLAGS", "FFLAGS", "LDFLAGS":
1676                         // Change relative paths to absolute.
1677                         ctxt.makePathsAbsolute(args, di.Dir)
1678                 }
1679
1680                 switch verb {
1681                 case "CFLAGS":
1682                         di.CgoCFLAGS = append(di.CgoCFLAGS, args...)
1683                 case "CPPFLAGS":
1684                         di.CgoCPPFLAGS = append(di.CgoCPPFLAGS, args...)
1685                 case "CXXFLAGS":
1686                         di.CgoCXXFLAGS = append(di.CgoCXXFLAGS, args...)
1687                 case "FFLAGS":
1688                         di.CgoFFLAGS = append(di.CgoFFLAGS, args...)
1689                 case "LDFLAGS":
1690                         di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...)
1691                 case "pkg-config":
1692                         di.CgoPkgConfig = append(di.CgoPkgConfig, args...)
1693                 default:
1694                         return fmt.Errorf("%s: invalid #cgo verb: %s", filename, orig)
1695                 }
1696         }
1697         return nil
1698 }
1699
1700 // expandSrcDir expands any occurrence of ${SRCDIR}, making sure
1701 // the result is safe for the shell.
1702 func expandSrcDir(str string, srcdir string) (string, bool) {
1703         // "\" delimited paths cause safeCgoName to fail
1704         // so convert native paths with a different delimiter
1705         // to "/" before starting (eg: on windows).
1706         srcdir = filepath.ToSlash(srcdir)
1707
1708         chunks := strings.Split(str, "${SRCDIR}")
1709         if len(chunks) < 2 {
1710                 return str, safeCgoName(str)
1711         }
1712         ok := true
1713         for _, chunk := range chunks {
1714                 ok = ok && (chunk == "" || safeCgoName(chunk))
1715         }
1716         ok = ok && (srcdir == "" || safeCgoName(srcdir))
1717         res := strings.Join(chunks, srcdir)
1718         return res, ok && res != ""
1719 }
1720
1721 // makePathsAbsolute looks for compiler options that take paths and
1722 // makes them absolute. We do this because through the 1.8 release we
1723 // ran the compiler in the package directory, so any relative -I or -L
1724 // options would be relative to that directory. In 1.9 we changed to
1725 // running the compiler in the build directory, to get consistent
1726 // build results (issue #19964). To keep builds working, we change any
1727 // relative -I or -L options to be absolute.
1728 //
1729 // Using filepath.IsAbs and filepath.Join here means the results will be
1730 // different on different systems, but that's OK: -I and -L options are
1731 // inherently system-dependent.
1732 func (ctxt *Context) makePathsAbsolute(args []string, srcDir string) {
1733         nextPath := false
1734         for i, arg := range args {
1735                 if nextPath {
1736                         if !filepath.IsAbs(arg) {
1737                                 args[i] = filepath.Join(srcDir, arg)
1738                         }
1739                         nextPath = false
1740                 } else if strings.HasPrefix(arg, "-I") || strings.HasPrefix(arg, "-L") {
1741                         if len(arg) == 2 {
1742                                 nextPath = true
1743                         } else {
1744                                 if !filepath.IsAbs(arg[2:]) {
1745                                         args[i] = arg[:2] + filepath.Join(srcDir, arg[2:])
1746                                 }
1747                         }
1748                 }
1749         }
1750 }
1751
1752 // NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN.
1753 // We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay.
1754 // See golang.org/issue/6038.
1755 // The @ is for OS X. See golang.org/issue/13720.
1756 // The % is for Jenkins. See golang.org/issue/16959.
1757 // The ! is because module paths may use them. See golang.org/issue/26716.
1758 // The ~ and ^ are for sr.ht. See golang.org/issue/32260.
1759 const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@%! ~^"
1760
1761 func safeCgoName(s string) bool {
1762         if s == "" {
1763                 return false
1764         }
1765         for i := 0; i < len(s); i++ {
1766                 if c := s[i]; c < utf8.RuneSelf && strings.IndexByte(safeString, c) < 0 {
1767                         return false
1768                 }
1769         }
1770         return true
1771 }
1772
1773 // splitQuoted splits the string s around each instance of one or more consecutive
1774 // white space characters while taking into account quotes and escaping, and
1775 // returns an array of substrings of s or an empty list if s contains only white space.
1776 // Single quotes and double quotes are recognized to prevent splitting within the
1777 // quoted region, and are removed from the resulting substrings. If a quote in s
1778 // isn't closed err will be set and r will have the unclosed argument as the
1779 // last element. The backslash is used for escaping.
1780 //
1781 // For example, the following string:
1782 //
1783 //     a b:"c d" 'e''f'  "g\""
1784 //
1785 // Would be parsed as:
1786 //
1787 //     []string{"a", "b:c d", "ef", `g"`}
1788 //
1789 func splitQuoted(s string) (r []string, err error) {
1790         var args []string
1791         arg := make([]rune, len(s))
1792         escaped := false
1793         quoted := false
1794         quote := '\x00'
1795         i := 0
1796         for _, rune := range s {
1797                 switch {
1798                 case escaped:
1799                         escaped = false
1800                 case rune == '\\':
1801                         escaped = true
1802                         continue
1803                 case quote != '\x00':
1804                         if rune == quote {
1805                                 quote = '\x00'
1806                                 continue
1807                         }
1808                 case rune == '"' || rune == '\'':
1809                         quoted = true
1810                         quote = rune
1811                         continue
1812                 case unicode.IsSpace(rune):
1813                         if quoted || i > 0 {
1814                                 quoted = false
1815                                 args = append(args, string(arg[:i]))
1816                                 i = 0
1817                         }
1818                         continue
1819                 }
1820                 arg[i] = rune
1821                 i++
1822         }
1823         if quoted || i > 0 {
1824                 args = append(args, string(arg[:i]))
1825         }
1826         if quote != 0 {
1827                 err = errors.New("unclosed quote")
1828         } else if escaped {
1829                 err = errors.New("unfinished escaping")
1830         }
1831         return args, err
1832 }
1833
1834 // match reports whether the name is one of:
1835 //
1836 //      $GOOS
1837 //      $GOARCH
1838 //      cgo (if cgo is enabled)
1839 //      !cgo (if cgo is disabled)
1840 //      boringcrypto
1841 //      ctxt.Compiler
1842 //      !ctxt.Compiler
1843 //      tag (if tag is listed in ctxt.BuildTags or ctxt.ReleaseTags)
1844 //      !tag (if tag is not listed in ctxt.BuildTags or ctxt.ReleaseTags)
1845 //      a comma-separated list of any of these
1846 //
1847 func (ctxt *Context) match(name string, allTags map[string]bool) bool {
1848         if name == "" {
1849                 if allTags != nil {
1850                         allTags[name] = true
1851                 }
1852                 return false
1853         }
1854         if i := strings.Index(name, ","); i >= 0 {
1855                 // comma-separated list
1856                 ok1 := ctxt.match(name[:i], allTags)
1857                 ok2 := ctxt.match(name[i+1:], allTags)
1858                 return ok1 && ok2
1859         }
1860         if strings.HasPrefix(name, "!!") { // bad syntax, reject always
1861                 return false
1862         }
1863         if strings.HasPrefix(name, "!") { // negation
1864                 return len(name) > 1 && !ctxt.match(name[1:], allTags)
1865         }
1866
1867         if allTags != nil {
1868                 allTags[name] = true
1869         }
1870
1871         // Tags must be letters, digits, underscores or dots.
1872         // Unlike in Go identifiers, all digits are fine (e.g., "386").
1873         for _, c := range name {
1874                 if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
1875                         return false
1876                 }
1877         }
1878
1879         // special tags
1880         if ctxt.CgoEnabled && name == "cgo" {
1881                 return true
1882         }
1883         if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler {
1884                 return true
1885         }
1886         if ctxt.GOOS == "android" && name == "linux" {
1887                 return true
1888         }
1889         if ctxt.GOOS == "illumos" && name == "solaris" {
1890                 return true
1891         }
1892         if ctxt.GOOS == "ios" && name == "darwin" {
1893                 return true
1894         }
1895         // Let applications know that the Go+BoringCrypto toolchain is in use.
1896         if name == "boringcrypto" {
1897                 return true
1898         }
1899
1900         // other tags
1901         for _, tag := range ctxt.BuildTags {
1902                 if tag == name {
1903                         return true
1904                 }
1905         }
1906         for _, tag := range ctxt.ReleaseTags {
1907                 if tag == name {
1908                         return true
1909                 }
1910         }
1911
1912         return false
1913 }
1914
1915 // goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
1916 // suffix which does not match the current system.
1917 // The recognized name formats are:
1918 //
1919 //     name_$(GOOS).*
1920 //     name_$(GOARCH).*
1921 //     name_$(GOOS)_$(GOARCH).*
1922 //     name_$(GOOS)_test.*
1923 //     name_$(GOARCH)_test.*
1924 //     name_$(GOOS)_$(GOARCH)_test.*
1925 //
1926 // Exceptions:
1927 // if GOOS=android, then files with GOOS=linux are also matched.
1928 // if GOOS=illumos, then files with GOOS=solaris are also matched.
1929 // if GOOS=ios, then files with GOOS=darwin are also matched.
1930 func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
1931         if dot := strings.Index(name, "."); dot != -1 {
1932                 name = name[:dot]
1933         }
1934
1935         // Before Go 1.4, a file called "linux.go" would be equivalent to having a
1936         // build tag "linux" in that file. For Go 1.4 and beyond, we require this
1937         // auto-tagging to apply only to files with a non-empty prefix, so
1938         // "foo_linux.go" is tagged but "linux.go" is not. This allows new operating
1939         // systems, such as android, to arrive without breaking existing code with
1940         // innocuous source code in "android.go". The easiest fix: cut everything
1941         // in the name before the initial _.
1942         i := strings.Index(name, "_")
1943         if i < 0 {
1944                 return true
1945         }
1946         name = name[i:] // ignore everything before first _
1947
1948         l := strings.Split(name, "_")
1949         if n := len(l); n > 0 && l[n-1] == "test" {
1950                 l = l[:n-1]
1951         }
1952         n := len(l)
1953         if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
1954                 return ctxt.match(l[n-1], allTags) && ctxt.match(l[n-2], allTags)
1955         }
1956         if n >= 1 && (knownOS[l[n-1]] || knownArch[l[n-1]]) {
1957                 return ctxt.match(l[n-1], allTags)
1958         }
1959         return true
1960 }
1961
1962 var knownOS = make(map[string]bool)
1963 var knownArch = make(map[string]bool)
1964
1965 func init() {
1966         for _, v := range strings.Fields(goosList) {
1967                 knownOS[v] = true
1968         }
1969         for _, v := range strings.Fields(goarchList) {
1970                 knownArch[v] = true
1971         }
1972 }
1973
1974 // ToolDir is the directory containing build tools.
1975 var ToolDir = getToolDir()
1976
1977 // IsLocalImport reports whether the import path is
1978 // a local import path, like ".", "..", "./foo", or "../foo".
1979 func IsLocalImport(path string) bool {
1980         return path == "." || path == ".." ||
1981                 strings.HasPrefix(path, "./") || strings.HasPrefix(path, "../")
1982 }
1983
1984 // ArchChar returns "?" and an error.
1985 // In earlier versions of Go, the returned string was used to derive
1986 // the compiler and linker tool names, the default object file suffix,
1987 // and the default linker output name. As of Go 1.5, those strings
1988 // no longer vary by architecture; they are compile, link, .o, and a.out, respectively.
1989 func ArchChar(goarch string) (string, error) {
1990         return "?", errors.New("architecture letter no longer used")
1991 }