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