github.com/bir3/gocompiler@v0.9.2202/src/cmd/gocmd/internal/load/godebug.go (about) 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. 4 5 package load 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/gocmd/internal/modload" 9 "errors" 10 "fmt" 11 "github.com/bir3/gocompiler/src/go/build" 12 "github.com/bir3/gocompiler/src/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 // 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 { 60 if p.Name != "main" { 61 return "" 62 } 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 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 }