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