Exemple #1
0
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
	}
}