1 // Copyright 2023 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.
8 "cmd/go/internal/modload"
18 var ErrNotGoDebug = errors.New("not //go:debug line")
20 func ParseGoDebug(text string) (key, value string, err error) {
21 if !strings.HasPrefix(text, "//go:debug") {
22 return "", "", ErrNotGoDebug
24 i := strings.IndexAny(text, " \t")
26 if strings.TrimSpace(text) == "//go:debug" {
27 return "", "", fmt.Errorf("missing key=value")
29 return "", "", ErrNotGoDebug
31 k, v, ok := strings.Cut(strings.TrimSpace(text[i:]), "=")
33 return "", "", fmt.Errorf("missing key=value")
35 if strings.ContainsAny(k, " \t") {
36 return "", "", fmt.Errorf("key contains space")
38 if strings.ContainsAny(v, " \t") {
39 return "", "", fmt.Errorf("value contains space")
41 if strings.ContainsAny(k, ",") {
42 return "", "", fmt.Errorf("key contains comma")
44 if strings.ContainsAny(v, ",") {
45 return "", "", fmt.Errorf("value contains comma")
48 for _, info := range godebugs.All {
53 return "", "", fmt.Errorf("unknown //go:debug setting %q", k)
56 // defaultGODEBUG returns the default GODEBUG setting for the main package p.
57 // When building a test binary, directives, testDirectives, and xtestDirectives
58 // list additional directives from the package under test.
59 func defaultGODEBUG(p *Package, directives, testDirectives, xtestDirectives []build.Directive) string {
63 goVersion := modload.MainModules.GoVersion()
64 if modload.RootMode == modload.NoRoot && p.Module != nil {
65 // This is go install pkg@version or go run pkg@version.
66 // Use the Go version from the package.
67 // If there isn't one, then
68 goVersion = p.Module.GoVersion
74 m := godebugForGoVersion(goVersion)
75 for _, list := range [][]build.Directive{p.Internal.Build.Directives, directives, testDirectives, xtestDirectives} {
76 for _, d := range list {
77 k, v, err := ParseGoDebug(d.Text)
82 m = make(map[string]string)
89 keys = append(keys, k)
93 for _, k := range keys {
104 func godebugForGoVersion(v string) map[string]string {
105 if strings.Count(v, ".") >= 2 {
106 i := strings.Index(v, ".")
107 j := i + 1 + strings.Index(v[i+1:], ".")
111 if !strings.HasPrefix(v, "1.") {
114 n, err := strconv.Atoi(v[len("1."):])
119 def := make(map[string]string)
120 for _, info := range godebugs.All {
121 if n < info.Changed {
122 def[info.Name] = info.Old