1
2
3
4
5 package load
6
7 import (
8 "cmd/go/internal/modload"
9 "errors"
10 "fmt"
11 "go/build"
12 "internal/godebugs"
13 "sort"
14 "strconv"
15 "strings"
16 )
17
18 var ErrNotGoDebug = errors.New("not //go:debug line")
19
20 func ParseGoDebug(text string) (key, value string, err error) {
21 if !strings.HasPrefix(text, "//go:debug") {
22 return "", "", ErrNotGoDebug
23 }
24 i := strings.IndexAny(text, " \t")
25 if i < 0 {
26 if strings.TrimSpace(text) == "//go:debug" {
27 return "", "", fmt.Errorf("missing key=value")
28 }
29 return "", "", ErrNotGoDebug
30 }
31 k, v, ok := strings.Cut(strings.TrimSpace(text[i:]), "=")
32 if !ok {
33 return "", "", fmt.Errorf("missing key=value")
34 }
35 if strings.ContainsAny(k, " \t") {
36 return "", "", fmt.Errorf("key contains space")
37 }
38 if strings.ContainsAny(v, " \t") {
39 return "", "", fmt.Errorf("value contains space")
40 }
41 if strings.ContainsAny(k, ",") {
42 return "", "", fmt.Errorf("key contains comma")
43 }
44 if strings.ContainsAny(v, ",") {
45 return "", "", fmt.Errorf("value contains comma")
46 }
47
48 for _, info := range godebugs.All {
49 if k == info.Name {
50 return k, v, nil
51 }
52 }
53 return "", "", fmt.Errorf("unknown //go:debug setting %q", k)
54 }
55
56
57
58
59 func defaultGODEBUG(p *Package, directives, testDirectives, xtestDirectives []build.Directive) string {
60 if p.Name != "main" {
61 return ""
62 }
63 goVersion := modload.MainModules.GoVersion()
64 if modload.RootMode == modload.NoRoot && p.Module != nil {
65
66
67
68 goVersion = p.Module.GoVersion
69 if goVersion == "" {
70 goVersion = "1.20"
71 }
72 }
73
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)
78 if err != nil {
79 continue
80 }
81 if m == nil {
82 m = make(map[string]string)
83 }
84 m[k] = v
85 }
86 }
87 var keys []string
88 for k := range m {
89 keys = append(keys, k)
90 }
91 sort.Strings(keys)
92 var b strings.Builder
93 for _, k := range keys {
94 if b.Len() > 0 {
95 b.WriteString(",")
96 }
97 b.WriteString(k)
98 b.WriteString("=")
99 b.WriteString(m[k])
100 }
101 return b.String()
102 }
103
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:], ".")
108 v = v[:j]
109 }
110
111 if !strings.HasPrefix(v, "1.") {
112 return nil
113 }
114 n, err := strconv.Atoi(v[len("1."):])
115 if err != nil {
116 return nil
117 }
118
119 def := make(map[string]string)
120 for _, info := range godebugs.All {
121 if n < info.Changed {
122 def[info.Name] = info.Old
123 }
124 }
125 return def
126 }
127
View as plain text