func toGoType(cfg *Config, x cc.Syntax, typ *cc.Type, cache map[*cc.Type]*cc.Type) *cc.Type { if typ == nil { return nil } if cache[typ] != nil { return cache[typ] } switch typ.Kind { default: panic(fmt.Sprintf("unexpected C type %s", typ)) case Ideal: return typ case cc.Void: return &cc.Type{Kind: cc.Struct} // struct{} case cc.Char, cc.Uchar, cc.Short, cc.Ushort, cc.Int, cc.Uint, cc.Long, cc.Ulong, cc.Longlong, cc.Ulonglong, cc.Float, cc.Double, cc.Enum: t := &cc.Type{Kind: c2goKind[typ.Kind]} if d, ok := x.(*cc.Decl); ok { if cfg.bool[declKey(d)] { t.Kind = Bool } else if strings.HasPrefix(d.Name, "no") { println("not bool", d.Name, declKey(d)) } } return t case cc.TypedefType: if cfg.typeMap[typ.Name] != "" { t := &cc.Type{Kind: cc.TypedefType, Name: cfg.typeMap[typ.Name], TypeDecl: typ.TypeDecl} cache[typ] = t return t } // If this is a typedef like uchar, translate the type by name. // Otherwise fall back to base. def := typ.Base if cc.Char <= def.Kind && def.Kind <= cc.Enum { var t *cc.Type if c2goName[typ.Name] != 0 { t = &cc.Type{Kind: c2goName[typ.Name]} } else { t = &cc.Type{Kind: c2goKind[typ.Base.Kind]} } if d, ok := x.(*cc.Decl); ok { if cfg.bool[declKey(d)] { t.Kind = Bool } else if strings.HasPrefix(d.Name, "no") { println("not bool", d.Name, declKey(d)) } } return t } if typ.Name == "va_list" { return &cc.Type{Kind: cc.TypedefType, Name: "[]interface{}"} } // Otherwise assume it is a struct or some such, // and preserve the name but translate the base. t := &cc.Type{Kind: cc.TypedefType, Name: typ.Name, TypeDecl: typ.TypeDecl} cache[typ] = t t.Base = toGoType(cfg, nil, typ.Base, cache) return t case cc.Array: if typ.Base.Def().Kind == cc.Char { return &cc.Type{Kind: String} } t := &cc.Type{Kind: cc.Array, Width: typ.Width} cache[typ] = t t.Base = toGoType(cfg, nil, typ.Base, cache) return t case cc.Ptr: t := &cc.Type{Kind: cc.Ptr} cache[typ] = t base := x if typ.Base.Kind != cc.Func { base = nil } t.Base = toGoType(cfg, base, typ.Base, cache) // Convert void* to interface{}. if typ.Base.Kind == cc.Void { t.Base = nil t.Kind = cc.TypedefType t.Name = "interface{}" return t } if typ.Base.Kind == cc.Char { t.Kind = String t.Base = nil return t } d, ok := x.(*cc.Decl) if typ.Base.Def().Kind == cc.Uchar && (!ok || !cfg.ptr[declKey(d)]) { t.Kind = Slice t.Base = byteType } if ok && cfg.slice[declKey(d)] { t.Kind = Slice } return t case cc.Func: // A func Type contains Decls, and we don't fork the Decls, so don't fork the Type. // The Decls themselves appear in the group lists, so they'll be handled by rewriteTypes. // The return value has no Decl and needs to be converted. if !typ.Base.Is(cc.Void) { if d, ok := x.(*cc.Decl); ok { x = &cc.Decl{ Name: "return", CurFn: d, } } else { x = nil } typ.Base = toGoType(cfg, x, typ.Base, cache) } // Check for array passed as parameter. Doesn't translate well. for _, d := range typ.Decls { if d.Type.Is(cc.Array) { fprintf(d.Span, "function taking array parameter!") } } return typ case cc.Struct: // A struct Type contains Decls, and we don't fork the Decls, so don't fork the Type. // The Decls themselves appear in the group lists, so they'll be handled by rewriteTypes. return typ } }