1
2
3
4
5 package types
6
7 import (
8 "cmd/internal/obj"
9 "cmd/internal/objabi"
10 "fmt"
11 "sort"
12 "sync"
13 )
14
15
16 var pkgMap = make(map[string]*Pkg)
17
18
19 const MaxPkgHeight = 1e9
20
21 type Pkg struct {
22 Path string
23 Name string
24 Prefix string
25 Syms map[string]*Sym
26 Pathsym *obj.LSym
27
28
29
30
31
32 Height int
33
34 Direct bool
35 }
36
37
38
39
40 func NewPkg(path, name string) *Pkg {
41 if p := pkgMap[path]; p != nil {
42 if name != "" && p.Name != name {
43 panic(fmt.Sprintf("conflicting package names %s and %s for path %q", p.Name, name, path))
44 }
45 return p
46 }
47
48 p := new(Pkg)
49 p.Path = path
50 p.Name = name
51 if path == "go.shape" {
52
53
54
55
56 p.Prefix = path
57 } else {
58 p.Prefix = objabi.PathToPrefix(path)
59 }
60 p.Syms = make(map[string]*Sym)
61 pkgMap[path] = p
62
63 return p
64 }
65
66
67
68 func ImportedPkgList() []*Pkg {
69 var list []*Pkg
70 for _, p := range pkgMap {
71 if p.Direct {
72 list = append(list, p)
73 }
74 }
75 sort.Sort(byPath(list))
76 return list
77 }
78
79 type byPath []*Pkg
80
81 func (a byPath) Len() int { return len(a) }
82 func (a byPath) Less(i, j int) bool { return a[i].Path < a[j].Path }
83 func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
84
85 var nopkg = &Pkg{
86 Syms: make(map[string]*Sym),
87 }
88
89 func (pkg *Pkg) Lookup(name string) *Sym {
90 s, _ := pkg.LookupOK(name)
91 return s
92 }
93
94
95 func (pkg *Pkg) LookupOK(name string) (s *Sym, existed bool) {
96
97 if pkg == nil {
98 pkg = nopkg
99 }
100 if s := pkg.Syms[name]; s != nil {
101 return s, true
102 }
103
104 s = &Sym{
105 Name: name,
106 Pkg: pkg,
107 }
108 pkg.Syms[name] = s
109 return s, false
110 }
111
112 func (pkg *Pkg) LookupBytes(name []byte) *Sym {
113
114 if pkg == nil {
115 pkg = nopkg
116 }
117 if s := pkg.Syms[string(name)]; s != nil {
118 return s
119 }
120 str := InternString(name)
121 return pkg.Lookup(str)
122 }
123
124 var (
125 internedStringsmu sync.Mutex
126 internedStrings = map[string]string{}
127 )
128
129 func InternString(b []byte) string {
130 internedStringsmu.Lock()
131 s, ok := internedStrings[string(b)]
132 if !ok {
133 s = string(b)
134 internedStrings[s] = s
135 }
136 internedStringsmu.Unlock()
137 return s
138 }
139
140
141
142 func CleanroomDo(f func()) {
143 saved := pkgMap
144 pkgMap = make(map[string]*Pkg)
145 f()
146 pkgMap = saved
147 }
148
View as plain text