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
210 func readComments(f io.Reader) ([]byte, error) {
211 r := &importReader{b: bufio.NewReader(f)}
212 r.peekByte(true)
213 if r.err == nil && !r.eof {
214
215 r.buf = r.buf[:len(r.buf)-1]
216 }
217 return r.buf, r.err
218 }
219
220
221 func readimports(file string) []string {
222 var imports []string
223 r := &importReader{b: bufio.NewReader(strings.NewReader(readfile(file)))}
224 r.readKeyword("package")
225 r.readIdent()
226 for r.peekByte(true) == 'i' {
227 r.readKeyword("import")
228 if r.peekByte(true) == '(' {
229 r.nextByte(false)
230 for r.peekByte(true) != ')' && r.err == nil {
231 r.readImport(&imports)
232 }
233 r.nextByte(false)
234 } else {
235 r.readImport(&imports)
236 }
237 }
238
239 for i := range imports {
240 unquoted, err := strconv.Unquote(imports[i])
241 if err != nil {
242 fatalf("reading imports from %s: %v", file, err)
243 }
244 imports[i] = unquoted
245 }
246
247 return imports
248 }
249
250
251
252
253
254
255
256
257 func resolveVendor(imp, srcDir string) string {
258 var first string
259 if i := strings.Index(imp, "/"); i < 0 {
260 first = imp
261 } else {
262 first = imp[:i]
263 }
264 isStandard := !strings.Contains(first, ".")
265 if isStandard {
266 return imp
267 }
268
269 if strings.HasPrefix(srcDir, filepath.Join(goroot, "src", "cmd")) {
270 return path.Join("cmd", "vendor", imp)
271 } else if strings.HasPrefix(srcDir, filepath.Join(goroot, "src")) {
272 return path.Join("vendor", imp)
273 } else {
274 panic(fmt.Sprintf("srcDir %q not in GOOROT/src", srcDir))
275 }
276 }
277
View as plain text