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]) }
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} }
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]); }
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 }
// 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 }
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() }
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...) }
// 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 }
// 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 }
// 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 }
// 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 }
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 }
func javaToGoIdentifier(s string) (z string) { if token.Lookup(s).IsKeyword() { return s + "_gen" } return s }
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 } }
func paramName(cparamName string) string { if token.Lookup(cparamName) != token.IDENT { return cparamName + "_" } return cparamName }