Пример #1
0
func (S *Scanner) scanIdentifier() token.Token {
	offs := S.offset
	for isLetter(S.ch) || isDigit(S.ch) {
		S.next()
	}
	return token.Lookup(S.src[offs:S.offset])
}
Пример #2
0
Файл: ast.go Проект: h12w/xsd
func (t *enumType) Decls() []ast.Decl {
	typeDecl := &ast.GenDecl{
		Tok: token.TYPE,
		Specs: []ast.Spec{
			&ast.TypeSpec{
				Name: &ast.Ident{Name: t.Name},
				Type: &ast.Ident{Name: t.Type},
			},
		},
		Doc: comment(t.Doc),
	}

	constDecl := &ast.GenDecl{
		Tok:    token.CONST,
		Lparen: 1,
	}
	kind := token.Lookup(t.Type)
	for _, kv := range t.KV {
		constDecl.Specs = append(constDecl.Specs,
			&ast.ValueSpec{
				Names:  []*ast.Ident{{Name: kv.Key}},
				Type:   &ast.Ident{Name: t.Name},
				Values: []ast.Expr{&ast.BasicLit{Kind: kind, Value: kv.Value}},
			})
	}
	return []ast.Decl{typeDecl, constDecl}
}
Пример #3
0
func (S *Scanner) scanIdentifier() token.Token {
	pos := S.pos.Offset;
	for isLetter(S.ch) || isDigit(S.ch) {
		S.next();
	}
	return token.Lookup(S.src[pos : S.pos.Offset]);
}
Пример #4
0
func (g *generator) Generate(pkg *model.Package, pkgName string) error {
	g.p("// Automatically generated by MockGen. DO NOT EDIT!")
	if g.filename != "" {
		g.p("// Source: %v", g.filename)
	} else {
		g.p("// Source: %v (interfaces: %v)", g.srcPackage, g.srcInterfaces)
	}
	g.p("")

	// Get all required imports, and generate unique names for them all.
	im := pkg.Imports()
	gomockPath := path.Join(*importPrefix, gomockImportPath)
	im[gomockPath] = true
	g.packageMap = make(map[string]string, len(im))
	localNames := make(map[string]bool, len(im))
	for pth := range im {
		base := sanitize(path.Base(pth))

		// Local names for an imported package can usually be the basename of the import path.
		// A couple of situations don't permit that, such as duplicate local names
		// (e.g. importing "html/template" and "text/template"), or where the basename is
		// a keyword (e.g. "foo/case").
		// try base0, base1, ...
		pkgName := base
		i := 0
		for localNames[pkgName] || token.Lookup(pkgName).IsKeyword() {
			pkgName = base + strconv.Itoa(i)
			i++
		}

		g.packageMap[pth] = pkgName
		localNames[pkgName] = true
	}

	g.p("package %v", pkgName)
	g.p("")
	g.p("import (")
	g.in()
	for path, pkg := range g.packageMap {
		if path == *selfPackage {
			continue
		}
		g.p("%v %q", pkg, path)
	}
	for _, path := range pkg.DotImports {
		g.p(". %q", path)
	}
	g.out()
	g.p(")")

	for _, intf := range pkg.Interfaces {
		if err := g.GenerateMockInterface(intf); err != nil {
			return err
		}
	}

	return nil
}
Пример #5
0
// NB: for renamings, blank is not considered valid.
func isValidIdentifier(id string) bool {
	if id == "" || id == "_" {
		return false
	}
	for i, r := range id {
		if !isLetter(r) && (i == 0 || !isDigit(r)) {
			return false
		}
	}
	return token.Lookup(id) == token.IDENT
}
Пример #6
0
func cmdName(val reflect.Value) string {
	mustBeStruct(val)
	typ := val.Type()
	for i := 0; i < typ.NumField(); i++ {
		field := typ.Field(i)
		tag := string(field.Tag)
		if field.Name == "name" &&
			field.Type.Kind() == reflect.String &&
			token.Lookup(tag) == token.IDENT {

			return tag
		}
	}
	return typ.Name()
}
Пример #7
0
func (self *BridgeFunc) ConvertParam(name, t string) {
	if tok := token.Lookup(name); tok.IsKeyword() {
		name = name + "_"
	}
	self.ParamNames = append(self.ParamNames, name)
	mapFunc, ok := PARAM_MAPPINGS[t]
	if !ok {
		mapFunc = tryDirectMapParam(t)
		if mapFunc == nil {
			log.Fatalf("no map for param type %s: %s", t, self.CFunc.Name)
		}
	}
	mappedName, mappedType, helperCodes := mapFunc(name)
	self.CgoArguments = append(self.CgoArguments, mappedName)
	self.ParamTypes = append(self.ParamTypes, mappedType)
	self.HelperCodes = append(self.HelperCodes, helperCodes...)
}
Пример #8
0
// Scan scans the next token and returns the token position, the token,
// and its literal string if applicable. The source end is indicated by
// token.EOF.
//
// If the returned token is a literal (token.IDENT, token.INT, token.FLOAT,
// token.IMAG, token.CHAR, token.STRING) or token.COMMENT, the literal string
// has the corresponding value.
//
// If the returned token is token.SEMICOLON, the corresponding
// literal string is ";" if the semicolon was present in the source,
// and "\n" if the semicolon was inserted because of a newline or
// at EOF.
//
// If the returned token is token.ILLEGAL, the literal string is the
// offending character.
//
// In all other cases, Scan returns an empty literal string.
//
// For more tolerant parsing, Scan will return a valid token if
// possible even if a syntax error was encountered. Thus, even
// if the resulting token sequence contains no illegal tokens,
// a client may not assume that no error occurred. Instead it
// must check the scanner's ErrorCount or the number of calls
// of the error handler, if there was one installed.
//
// Scan adds line information to the file added to the file
// set with Init. Token positions are relative to that file
// and thus relative to the file set.
//
func (s *Scanner) Scan() (pos token.Pos, tok token.Token, lit string) {
scanAgain:
	s.skipWhitespace()

	// current token start
	pos = s.file.Pos(s.offset)

	// determine token value
	insertSemi := false
	switch ch := s.ch; {
	case isLetter(ch):
		lit = s.scanIdentifier()
		tok = token.Lookup(lit)
		switch tok {
		case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
			insertSemi = true
		}
	case digitVal(ch) < 10:
		insertSemi = true
		tok, lit = s.scanNumber(false)
	default:
		s.next() // always make progress
		switch ch {
		case -1:
			if s.insertSemi {
				s.insertSemi = false // EOF consumed
				return pos, token.SEMICOLON, "\n"
			}
			tok = token.EOF
		case '\n':
			// we only reach here if s.insertSemi was
			// set in the first place and exited early
			// from s.skipWhitespace()
			s.insertSemi = false // newline consumed
			return pos, token.SEMICOLON, "\n"
		case '"':
			insertSemi = true
			tok = token.STRING
			lit = s.scanString()
		case '\'':
			insertSemi = true
			tok = token.CHAR
			lit = s.scanChar()
		case '`':
			insertSemi = true
			tok = token.STRING
			lit = s.scanRawString()
		case ':':
			tok = s.switch2(token.COLON, token.DEFINE)
		case '.':
			if digitVal(s.ch) < 10 {
				insertSemi = true
				tok, lit = s.scanNumber(true)
			} else if s.ch == '.' {
				s.next()
				if s.ch == '.' {
					s.next()
					tok = token.ELLIPSIS
				}
			} else {
				tok = token.PERIOD
			}
		case ',':
			tok = token.COMMA
		case ';':
			tok = token.SEMICOLON
			lit = ";"
		case '(':
			tok = token.LPAREN
		case ')':
			insertSemi = true
			tok = token.RPAREN
		case '[':
			tok = token.LBRACK
		case ']':
			insertSemi = true
			tok = token.RBRACK
		case '{':
			tok = token.LBRACE
		case '}':
			insertSemi = true
			tok = token.RBRACE
		case '+':
			tok = s.switch3(token.ADD, token.ADD_ASSIGN, '+', token.INC)
			if tok == token.INC {
				insertSemi = true
			}
		case '-':
			tok = s.switch3(token.SUB, token.SUB_ASSIGN, '-', token.DEC)
			if tok == token.DEC {
				insertSemi = true
			}
		case '*':
			tok = s.switch2(token.MUL, token.MUL_ASSIGN)
		case '/':
			if s.ch == '/' || s.ch == '*' {
				// comment
				if s.insertSemi && s.findLineEnd() {
					// reset position to the beginning of the comment
					s.ch = '/'
					s.offset = s.file.Offset(pos)
					s.rdOffset = s.offset + 1
					s.insertSemi = false // newline consumed
					return pos, token.SEMICOLON, "\n"
				}
				lit = s.scanComment()
				if s.mode&ScanComments == 0 {
					// skip comment
					s.insertSemi = false // newline consumed
					goto scanAgain
				}
				tok = token.COMMENT
			} else {
				tok = s.switch2(token.QUO, token.QUO_ASSIGN)
			}
		case '%':
			tok = s.switch2(token.REM, token.REM_ASSIGN)
		case '^':
			tok = s.switch2(token.XOR, token.XOR_ASSIGN)
		case '<':
			if s.ch == '-' {
				s.next()
				tok = token.ARROW
			} else {
				tok = s.switch4(token.LSS, token.LEQ, '<', token.SHL, token.SHL_ASSIGN)
			}
		case '>':
			tok = s.switch4(token.GTR, token.GEQ, '>', token.SHR, token.SHR_ASSIGN)
		case '=':
			tok = s.switch2(token.ASSIGN, token.EQL)
		case '!':
			tok = s.switch2(token.NOT, token.NEQ)
		case '&':
			if s.ch == '^' {
				s.next()
				tok = s.switch2(token.AND_NOT, token.AND_NOT_ASSIGN)
			} else {
				tok = s.switch3(token.AND, token.AND_ASSIGN, '&', token.LAND)
			}
		case '|':
			tok = s.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR)
		default:
			s.error(s.file.Offset(pos), fmt.Sprintf("illegal character %#U", ch))
			insertSemi = s.insertSemi // preserve insertSemi info
			tok = token.ILLEGAL
			lit = string(ch)
		}
	}
	if s.mode&dontInsertSemis == 0 {
		s.insertSemi = insertSemi
	}

	return
}
Пример #9
0
// Struct conversion: return Go and (gc) C syntax for type.
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
	// Minimum alignment for a struct is 1 byte.
	align = 1

	var buf bytes.Buffer
	buf.WriteString("struct {")
	fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
	off := int64(0)

	// Rename struct fields that happen to be named Go keywords into
	// _{keyword}.  Create a map from C ident -> Go ident.  The Go ident will
	// be mangled.  Any existing identifier that already has the same name on
	// the C-side will cause the Go-mangled version to be prefixed with _.
	// (e.g. in a struct with fields '_type' and 'type', the latter would be
	// rendered as '__type' in Go).
	ident := make(map[string]string)
	used := make(map[string]bool)
	for _, f := range dt.Field {
		ident[f.Name] = f.Name
		used[f.Name] = true
	}

	if !*godefs {
		for cid, goid := range ident {
			if token.Lookup(goid).IsKeyword() {
				// Avoid keyword
				goid = "_" + goid

				// Also avoid existing fields
				for _, exist := used[goid]; exist; _, exist = used[goid] {
					goid = "_" + goid
				}

				used[goid] = true
				ident[cid] = goid
			}
		}
	}

	anon := 0
	for _, f := range dt.Field {
		if f.ByteOffset > off {
			fld = c.pad(fld, f.ByteOffset-off)
			off = f.ByteOffset
		}

		name := f.Name
		ft := f.Type

		// In godefs mode, if this field is a C11
		// anonymous union then treat the first field in the
		// union as the field in the struct.  This handles
		// cases like the glibc <sys/resource.h> file; see
		// issue 6677.
		if *godefs {
			if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
				name = st.Field[0].Name
				ident[name] = name
				ft = st.Field[0].Type
			}
		}

		// TODO: Handle fields that are anonymous structs by
		// promoting the fields of the inner struct.

		t := c.Type(ft, pos)
		tgo := t.Go
		size := t.Size
		talign := t.Align
		if f.BitSize > 0 {
			if f.BitSize%8 != 0 {
				continue
			}
			size = f.BitSize / 8
			name := tgo.(*ast.Ident).String()
			if strings.HasPrefix(name, "int") {
				name = "int"
			} else {
				name = "uint"
			}
			tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
			talign = size
		}

		if talign > 0 && f.ByteOffset%talign != 0 {
			// Drop misaligned fields, the same way we drop integer bit fields.
			// The goal is to make available what can be made available.
			// Otherwise one bad and unneeded field in an otherwise okay struct
			// makes the whole program not compile. Much of the time these
			// structs are in system headers that cannot be corrected.
			continue
		}
		n := len(fld)
		fld = fld[0 : n+1]
		if name == "" {
			name = fmt.Sprintf("anon%d", anon)
			anon++
			ident[name] = name
		}
		fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
		off += size
		buf.WriteString(t.C.String())
		buf.WriteString(" ")
		buf.WriteString(name)
		buf.WriteString("; ")
		if talign > align {
			align = talign
		}
	}
	if off < dt.ByteSize {
		fld = c.pad(fld, dt.ByteSize-off)
		off = dt.ByteSize
	}
	if off != dt.ByteSize {
		fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
	}
	buf.WriteString("}")
	csyntax = buf.String()

	if *godefs {
		godefsFields(fld)
	}
	expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
	return
}
Пример #10
0
// Struct conversion: return Go and (6g) C syntax for type.
func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
	var buf bytes.Buffer
	buf.WriteString("struct {")
	fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
	off := int64(0)

	// Rename struct fields that happen to be named Go keywords into
	// _{keyword}.  Create a map from C ident -> Go ident.  The Go ident will
	// be mangled.  Any existing identifier that already has the same name on
	// the C-side will cause the Go-mangled version to be prefixed with _.
	// (e.g. in a struct with fields '_type' and 'type', the latter would be
	// rendered as '__type' in Go).
	ident := make(map[string]string)
	used := make(map[string]bool)
	for _, f := range dt.Field {
		ident[f.Name] = f.Name
		used[f.Name] = true
	}

	if !*godefs && !*cdefs {
		for cid, goid := range ident {
			if token.Lookup(goid).IsKeyword() {
				// Avoid keyword
				goid = "_" + goid

				// Also avoid existing fields
				for _, exist := used[goid]; exist; _, exist = used[goid] {
					goid = "_" + goid
				}

				used[goid] = true
				ident[cid] = goid
			}
		}
	}

	anon := 0
	for _, f := range dt.Field {
		if f.ByteOffset > off {
			fld = c.pad(fld, f.ByteOffset-off)
			off = f.ByteOffset
		}
		t := c.Type(f.Type, pos)
		tgo := t.Go
		size := t.Size

		if f.BitSize > 0 {
			if f.BitSize%8 != 0 {
				continue
			}
			size = f.BitSize / 8
			name := tgo.(*ast.Ident).String()
			if strings.HasPrefix(name, "int") {
				name = "int"
			} else {
				name = "uint"
			}
			tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
		}

		n := len(fld)
		fld = fld[0 : n+1]
		name := f.Name
		if name == "" {
			name = fmt.Sprintf("anon%d", anon)
			anon++
			ident[name] = name
		}
		fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
		off += size
		buf.WriteString(t.C.String())
		buf.WriteString(" ")
		buf.WriteString(name)
		buf.WriteString("; ")
		if t.Align > align {
			align = t.Align
		}
	}
	if off < dt.ByteSize {
		fld = c.pad(fld, dt.ByteSize-off)
		off = dt.ByteSize
	}
	if off != dt.ByteSize {
		fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
	}
	buf.WriteString("}")
	csyntax = buf.String()

	if *godefs || *cdefs {
		godefsFields(fld)
	}
	expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
	return
}
Пример #11
0
// Struct conversion: return Go and (6g) C syntax for type.
func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax string, align int64) {
	var buf bytes.Buffer
	buf.WriteString("struct {")
	fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
	off := int64(0)

	// Rename struct fields that happen to be named Go keywords into
	// _{keyword}.  Create a map from C ident -> Go ident.  The Go ident will
	// be mangled.  Any existing identifier that already has the same name on
	// the C-side will cause the Go-mangled version to be prefixed with _.
	// (e.g. in a struct with fields '_type' and 'type', the latter would be
	// rendered as '__type' in Go).
	ident := make(map[string]string)
	used := make(map[string]bool)
	for _, f := range dt.Field {
		ident[f.Name] = f.Name
		used[f.Name] = true
	}
	for cid, goid := range ident {
		if token.Lookup([]byte(goid)).IsKeyword() {
			// Avoid keyword
			goid = "_" + goid

			// Also avoid existing fields
			for _, exist := used[goid]; exist; _, exist = used[goid] {
				goid = "_" + goid
			}

			used[goid] = true
			ident[cid] = goid
		}
	}

	for _, f := range dt.Field {
		if f.BitSize > 0 && f.BitSize != f.ByteSize*8 {
			continue
		}
		if f.ByteOffset > off {
			fld = c.pad(fld, f.ByteOffset-off)
			off = f.ByteOffset
		}
		t := c.Type(f.Type)
		n := len(fld)
		fld = fld[0 : n+1]

		fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[f.Name])}, Type: t.Go}
		off += t.Size
		buf.WriteString(t.C.String())
		buf.WriteString(" ")
		buf.WriteString(f.Name)
		buf.WriteString("; ")
		if t.Align > align {
			align = t.Align
		}
	}
	if off < dt.ByteSize {
		fld = c.pad(fld, dt.ByteSize-off)
		off = dt.ByteSize
	}
	if off != dt.ByteSize {
		fatalf("struct size calculation error")
	}
	buf.WriteString("}")
	csyntax = buf.String()
	expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
	return
}
Пример #12
0
func prepareParam(f Func, pi int) Param {
	p := f.Param[pi]

	// Qt seems to have gratuitously changed some names.
	if name, ok := paramNameFixes[p.Name]; ok {
		p.Name = name
	}
	if pi > 0 && strings.HasPrefix(f.GoName, "Uniform") && p.Name != "count" && p.Name != "transpose" {
		if strings.HasSuffix(f.GoName, "v") {
			p.Name = "value"
		} else if f.Param[1].Name == "count" {
			p.Name = "v" + string('0'+pi-2)
		} else {
			p.Name = "v" + string('0'+pi-1)
		}
	}

	// Other names conflict with Go keywords.
	switch p.Name {
	case "type", "func", "map", "string":
		p.GoName = "gl" + p.Name
	default:
		if token.Lookup(p.Name) != token.IDENT {
			p.GoName = p.Name + "_"
		} else {
			p.GoName = p.Name
		}
	}

	// Some consistency. Those are a gl* function after all.
	switch p.Type {
	case "void":
		p.Type = "GLvoid"
	case "char":
		p.Type = "GLchar"
	case "qopengl_GLsizeiptr", "qopengl_GLintptr":
		p.Type = p.Type[8:]
	}

	// Prepare the parameter type.
	p.GoType = goTypeName(p.Type)
	switch p.GoType {
	case "uint32":
		switch p.GoName {
		case "program", "programs":
			p.GoType = "glbase.Program"
		case "shader", "shaders":
			p.GoType = "glbase.Shader"
		case "buffer", "buffers":
			p.GoType = "glbase.Buffer"
		case "texture", "textures":
			p.GoType = "glbase.Texture"
		case "framebuffer", "framebuffers":
			p.GoType = "glbase.Framebuffer"
		case "renderbuffer", "renderbuffers":
			p.GoType = "glbase.Renderbuffer"
		case "index":
			if strings.Contains(f.Name, "Attrib") {
				p.GoType = "glbase.Attrib"
			}
		}
	case "int32":
		switch p.GoName {
		case "size", "count", "stride", "offset", "xoffset", "yoffset", "order", "level":
			p.GoType = "int"
		case "n", "first", "width", "height", "border", "imageSize":
			p.GoType = "int"
		case "x", "y", "z", "w":
			if !strings.HasPrefix(f.GoName, "Uniform") {
				p.GoType = "int"
			}
		case "location":
			if strings.Contains(f.Name, "Uniform") {
				p.GoType = "glbase.Uniform"
			}
		}
	}

	// Save the original name so that future tweaks can still refer
	// to it, and apply the tweaks.
	p.GoNameOrig = p.GoName
	tweak := funcTweaks[f.GoName].params[p.GoNameOrig]
	if tweak.retype != "" {
		p.GoType = tweak.retype
	}
	if tweak.rename != "" {
		p.GoName = tweak.rename
	}

	return p
}
Пример #13
0
func javaToGoIdentifier(s string) (z string) {
	if token.Lookup(s).IsKeyword() {
		return s + "_gen"
	}
	return s
}
Пример #14
0
func prepareHeader(header *Header) {
	funcNameDocCount := make(map[string]int)

	for fi, f := range header.Func {
		docPrefix := funcNameDocPrefix(f.Name)
		if docPrefix != f.Name {
			funcNameDocCount[docPrefix]++
		}

		if !strings.HasPrefix(f.Name, "gl") || len(f.Name) < 3 {
			panic("unexpected C function name: " + f.Name)
		}
		f.GoName = f.Name[2:]
		if f.Type != "void" {
			f.GoType = goTypeName(f.Type)
		}

		for pi, p := range f.Param {
			switch p.Name {
			case "type", "func", "map":
				p.GoName = "gl" + p.Name
			default:
				if token.Lookup(p.Name) != token.IDENT {
					p.GoName = p.Name + "_"
				} else {
					p.GoName = p.Name
				}
			}
			p.GoType = goTypeName(p.Type)
			f.Param[pi] = p
		}
		header.Func[fi] = f
	}

	for fi, f := range header.Func {
		prefix := funcNameDocPrefix(f.Name)
		if funcNameDocCount[prefix] > 1 {
			f.DocName = prefix
		} else {
			f.DocName = f.Name
		}
		header.Func[fi] = f
	}

	for ti, t := range header.Type {
		t.GoName = goTypeName(t.Name)
		header.Type[ti] = t
	}

	for di, d := range header.Define {
		if !strings.HasPrefix(d.Name, "GL") || len(d.Name) < 3 {
			panic("unexpected C define name: " + d.Name)
		}
		if d.Name[3] >= '0' && d.Name[3] <= '9' {
			d.GoName = "N" + d.Name[3:]
		} else {
			d.GoName = d.Name[3:]
		}
		header.Define[di] = d
	}
}
Пример #15
0
func paramName(cparamName string) string {
	if token.Lookup(cparamName) != token.IDENT {
		return cparamName + "_"
	}
	return cparamName
}