Source file
src/cmd/dist/imports.go
1
2
3
4
5
6
7
8
9 package main
10
11 import (
12 "bufio"
13 "errors"
14 "fmt"
15 "io"
16 "path"
17 "path/filepath"
18 "strconv"
19 "strings"
20 "unicode/utf8"
21 )
22
23 type importReader struct {
24 b *bufio.Reader
25 buf []byte
26 peek byte
27 err error
28 eof bool
29 nerr int
30 }
31
32 func isIdent(c byte) bool {
33 return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf
34 }
35
36 var (
37 errSyntax = errors.New("syntax error")
38 errNUL = errors.New("unexpected NUL in input")
39 )
40
41
42 func (r *importReader) syntaxError() {
43 if r.err == nil {
44 r.err = errSyntax
45 }
46 }
47
48
49
50 func (r *importReader) readByte() byte {
51 c, err := r.b.ReadByte()
52 if err == nil {
53 r.buf = append(r.buf, c)
54 if c == 0 {
55 err = errNUL
56 }
57 }
58 if err != nil {
59 if err == io.EOF {
60 r.eof = true
61 } else if r.err == nil {
62 r.err = err
63 }
64 c = 0
65 }
66 return c
67 }
68
69
70
71 func (r *importReader) peekByte(skipSpace bool) byte {
72 if r.err != nil {
73 if r.nerr++; r.nerr > 10000 {
74 panic("go/build: import reader looping")
75 }
76 return 0
77 }
78
79
80
81
82 c := r.peek
83 if c == 0 {
84 c = r.readByte()
85 }
86 for r.err == nil && !r.eof {
87 if skipSpace {
88
89
90 switch c {
91 case ' ', '\f', '\t', '\r', '\n', ';':
92 c = r.readByte()
93 continue
94
95 case '/':
96 c = r.readByte()
97 if c == '/' {
98 for c != '\n' && r.err == nil && !r.eof {
99 c = r.readByte()
100 }
101 } else if c == '*' {
102 var c1 byte
103 for (c != '*' || c1 != '/') && r.err == nil {
104 if r.eof {
105 r.syntaxError()
106 }
107 c, c1 = c1, r.readByte()
108 }
109 } else {
110 r.syntaxError()
111 }
112 c = r.readByte()
113 continue
114 }
115 }
116 break
117 }
118 r.peek = c
119 return r.peek
120 }
121
122
123 func (r *importReader) nextByte(skipSpace bool) byte {
124 c := r.peekByte(skipSpace)
125 r.peek = 0
126 return c
127 }
128
129
130
131 func (r *importReader) readKeyword(kw string) {
132 r.peekByte(true)
133 for i := 0; i < len(kw); i++ {
134 if r.nextByte(false) != kw[i] {
135 r.syntaxError()
136 return
137 }
138 }
139 if isIdent(r.peekByte(false)) {
140 r.syntaxError()
141 }
142 }
143
144
145
146 func (r *importReader) readIdent() {
147 c := r.peekByte(true)
148 if !isIdent(c) {
149 r.syntaxError()
150 return
151 }
152 for isIdent(r.peekByte(false)) {
153 r.peek = 0
154 }
155 }
156
157
158
159 func (r *importReader) readString(save *[]string) {
160 switch r.nextByte(true) {
161 case '`':
162 start := len(r.buf) - 1
163 for r.err == nil {
164 if r.nextByte(false) == '`' {
165 if save != nil {
166 *save = append(*save, string(r.buf[start:]))
167 }
168 break
169 }
170 if r.eof {
171 r.syntaxError()
172 }
173 }
174 case '"':
175 start := len(r.buf) - 1
176 for r.err == nil {
177 c := r.nextByte(false)
178 if c == '"' {
179 if save != nil {
180 *save = append(*save, string(r.buf[start:]))
181 }
182 break
183 }
184 if r.eof || c == '\n' {
185 r.syntaxError()
186 }
187 if c == '\\' {
188 r.nextByte(false)
189 }
190 }
191 default:
192 r.syntaxError()
193 }
194 }
195
196
197
198 func (r *importReader) readImport(imports *[]string) {
199 c := r.peekByte(true)
200 if c == '.' {
201 r.peek = 0
202 } else if isIdent(c) {
203 r.readIdent()
204 }
205 r.readString(imports)
206 }
207
208
209 func readimports(file string) []string {
210 var imports []string
211 r := &importReader{b: bufio.NewReader(strings.NewReader(readfile(file)))}
212 r.readKeyword("package")
213 r.readIdent()
214 for r.peekByte(true) == 'i' {
215 r.readKeyword("import")
216 if r.peekByte(true) == '(' {
217 r.nextByte(false)
218 for r.peekByte(true) != ')' && r.err == nil {
219 r.readImport(&imports)
220 }
221 r.nextByte(false)
222 } else {
223 r.readImport(&imports)
224 }
225 }
226
227 for i := range imports {
228 unquoted, err := strconv.Unquote(imports[i])
229 if err != nil {
230 fatalf("reading imports from %s: %v", file, err)
231 }
232 imports[i] = unquoted
233 }
234
235 return imports
236 }
237
238
239
240
241
242
243
244
245 func resolveVendor(imp, srcDir string) string {
246 var first string
247 if i := strings.Index(imp, "/"); i < 0 {
248 first = imp
249 } else {
250 first = imp[:i]
251 }
252 isStandard := !strings.Contains(first, ".")
253 if isStandard {
254 return imp
255 }
256
257 if strings.HasPrefix(srcDir, filepath.Join(goroot, "src", "cmd")) {
258 return path.Join("cmd", "vendor", imp)
259 } else if strings.HasPrefix(srcDir, filepath.Join(goroot, "src")) {
260 return path.Join("vendor", imp)
261 } else {
262 panic(fmt.Sprintf("srcDir %q not in GOOROT/src", srcDir))
263 }
264 }
265
View as plain text