mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	* Changes to make vendored packages accept new home. * Fix go2idl to import vendored packages.
		
			
				
	
	
		
			247 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2012 The Go Authors.  All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package build
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"errors"
 | |
| 	"io"
 | |
| )
 | |
| 
 | |
| type importReader struct {
 | |
| 	b    *bufio.Reader
 | |
| 	buf  []byte
 | |
| 	peek byte
 | |
| 	err  error
 | |
| 	eof  bool
 | |
| 	nerr int
 | |
| }
 | |
| 
 | |
| func isIdent(c byte) bool {
 | |
| 	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= 0x80
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	errSyntax = errors.New("syntax error")
 | |
| 	errNUL    = errors.New("unexpected NUL in input")
 | |
| )
 | |
| 
 | |
| // syntaxError records a syntax error, but only if an I/O error has not already been recorded.
 | |
| func (r *importReader) syntaxError() {
 | |
| 	if r.err == nil {
 | |
| 		r.err = errSyntax
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // readByte reads the next byte from the input, saves it in buf, and returns it.
 | |
| // If an error occurs, readByte records the error in r.err and returns 0.
 | |
| func (r *importReader) readByte() byte {
 | |
| 	c, err := r.b.ReadByte()
 | |
| 	if err == nil {
 | |
| 		r.buf = append(r.buf, c)
 | |
| 		if c == 0 {
 | |
| 			err = errNUL
 | |
| 		}
 | |
| 	}
 | |
| 	if err != nil {
 | |
| 		if err == io.EOF {
 | |
| 			r.eof = true
 | |
| 		} else if r.err == nil {
 | |
| 			r.err = err
 | |
| 		}
 | |
| 		c = 0
 | |
| 	}
 | |
| 	return c
 | |
| }
 | |
| 
 | |
| // peekByte returns the next byte from the input reader but does not advance beyond it.
 | |
| // If skipSpace is set, peekByte skips leading spaces and comments.
 | |
| func (r *importReader) peekByte(skipSpace bool) byte {
 | |
| 	if r.err != nil {
 | |
| 		if r.nerr++; r.nerr > 10000 {
 | |
| 			panic("go/build: import reader looping")
 | |
| 		}
 | |
| 		return 0
 | |
| 	}
 | |
| 
 | |
| 	// Use r.peek as first input byte.
 | |
| 	// Don't just return r.peek here: it might have been left by peekByte(false)
 | |
| 	// and this might be peekByte(true).
 | |
| 	c := r.peek
 | |
| 	if c == 0 {
 | |
| 		c = r.readByte()
 | |
| 	}
 | |
| 	for r.err == nil && !r.eof {
 | |
| 		if skipSpace {
 | |
| 			// For the purposes of this reader, semicolons are never necessary to
 | |
| 			// understand the input and are treated as spaces.
 | |
| 			switch c {
 | |
| 			case ' ', '\f', '\t', '\r', '\n', ';':
 | |
| 				c = r.readByte()
 | |
| 				continue
 | |
| 
 | |
| 			case '/':
 | |
| 				c = r.readByte()
 | |
| 				if c == '/' {
 | |
| 					for c != '\n' && r.err == nil && !r.eof {
 | |
| 						c = r.readByte()
 | |
| 					}
 | |
| 				} else if c == '*' {
 | |
| 					var c1 byte
 | |
| 					for (c != '*' || c1 != '/') && r.err == nil {
 | |
| 						if r.eof {
 | |
| 							r.syntaxError()
 | |
| 						}
 | |
| 						c, c1 = c1, r.readByte()
 | |
| 					}
 | |
| 				} else {
 | |
| 					r.syntaxError()
 | |
| 				}
 | |
| 				c = r.readByte()
 | |
| 				continue
 | |
| 			}
 | |
| 		}
 | |
| 		break
 | |
| 	}
 | |
| 	r.peek = c
 | |
| 	return r.peek
 | |
| }
 | |
| 
 | |
| // nextByte is like peekByte but advances beyond the returned byte.
 | |
| func (r *importReader) nextByte(skipSpace bool) byte {
 | |
| 	c := r.peekByte(skipSpace)
 | |
| 	r.peek = 0
 | |
| 	return c
 | |
| }
 | |
| 
 | |
| // readKeyword reads the given keyword from the input.
 | |
| // If the keyword is not present, readKeyword records a syntax error.
 | |
| func (r *importReader) readKeyword(kw string) {
 | |
| 	r.peekByte(true)
 | |
| 	for i := 0; i < len(kw); i++ {
 | |
| 		if r.nextByte(false) != kw[i] {
 | |
| 			r.syntaxError()
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 	if isIdent(r.peekByte(false)) {
 | |
| 		r.syntaxError()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // readIdent reads an identifier from the input.
 | |
| // If an identifier is not present, readIdent records a syntax error.
 | |
| func (r *importReader) readIdent() {
 | |
| 	c := r.peekByte(true)
 | |
| 	if !isIdent(c) {
 | |
| 		r.syntaxError()
 | |
| 		return
 | |
| 	}
 | |
| 	for isIdent(r.peekByte(false)) {
 | |
| 		r.peek = 0
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // readString reads a quoted string literal from the input.
 | |
| // If an identifier is not present, readString records a syntax error.
 | |
| func (r *importReader) readString(save *[]string) {
 | |
| 	switch r.nextByte(true) {
 | |
| 	case '`':
 | |
| 		start := len(r.buf) - 1
 | |
| 		for r.err == nil {
 | |
| 			if r.nextByte(false) == '`' {
 | |
| 				if save != nil {
 | |
| 					*save = append(*save, string(r.buf[start:]))
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 			if r.eof {
 | |
| 				r.syntaxError()
 | |
| 			}
 | |
| 		}
 | |
| 	case '"':
 | |
| 		start := len(r.buf) - 1
 | |
| 		for r.err == nil {
 | |
| 			c := r.nextByte(false)
 | |
| 			if c == '"' {
 | |
| 				if save != nil {
 | |
| 					*save = append(*save, string(r.buf[start:]))
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 			if r.eof || c == '\n' {
 | |
| 				r.syntaxError()
 | |
| 			}
 | |
| 			if c == '\\' {
 | |
| 				r.nextByte(false)
 | |
| 			}
 | |
| 		}
 | |
| 	default:
 | |
| 		r.syntaxError()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // readImport reads an import clause - optional identifier followed by quoted string -
 | |
| // from the input.
 | |
| func (r *importReader) readImport(imports *[]string) {
 | |
| 	c := r.peekByte(true)
 | |
| 	if c == '.' {
 | |
| 		r.peek = 0
 | |
| 	} else if isIdent(c) {
 | |
| 		r.readIdent()
 | |
| 	}
 | |
| 	r.readString(imports)
 | |
| }
 | |
| 
 | |
| // readComments is like ioutil.ReadAll, except that it only reads the leading
 | |
| // block of comments in the file.
 | |
| func readComments(f io.Reader) ([]byte, error) {
 | |
| 	r := &importReader{b: bufio.NewReader(f)}
 | |
| 	r.peekByte(true)
 | |
| 	if r.err == nil && !r.eof {
 | |
| 		// Didn't reach EOF, so must have found a non-space byte. Remove it.
 | |
| 		r.buf = r.buf[:len(r.buf)-1]
 | |
| 	}
 | |
| 	return r.buf, r.err
 | |
| }
 | |
| 
 | |
| // readImports is like ioutil.ReadAll, except that it expects a Go file as input
 | |
| // and stops reading the input once the imports have completed.
 | |
| func readImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) {
 | |
| 	r := &importReader{b: bufio.NewReader(f)}
 | |
| 
 | |
| 	r.readKeyword("package")
 | |
| 	r.readIdent()
 | |
| 	for r.peekByte(true) == 'i' {
 | |
| 		r.readKeyword("import")
 | |
| 		if r.peekByte(true) == '(' {
 | |
| 			r.nextByte(false)
 | |
| 			for r.peekByte(true) != ')' && r.err == nil {
 | |
| 				r.readImport(imports)
 | |
| 			}
 | |
| 			r.nextByte(false)
 | |
| 		} else {
 | |
| 			r.readImport(imports)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// If we stopped successfully before EOF, we read a byte that told us we were done.
 | |
| 	// Return all but that last byte, which would cause a syntax error if we let it through.
 | |
| 	if r.err == nil && !r.eof {
 | |
| 		return r.buf[:len(r.buf)-1], nil
 | |
| 	}
 | |
| 
 | |
| 	// If we stopped for a syntax error, consume the whole file so that
 | |
| 	// we are sure we don't change the errors that go/parser returns.
 | |
| 	if r.err == errSyntax && !reportSyntaxError {
 | |
| 		r.err = nil
 | |
| 		for r.err == nil && !r.eof {
 | |
| 			r.readByte()
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return r.buf, r.err
 | |
| }
 |