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