func (j *Job) arrayType(n cc.Node, t cc.Type) { if ne := t.Elements(); ne >= 0 { j.body("[%v]", ne) j.typ(n, t.Element()) return } todo(n, t) }
func (j *Job) addTag(t cc.Type) { for t.Kind() == cc.Ptr || t.Kind() == cc.Array { t = t.Element() } tag := t.Tag() if tag == 0 { return } n := j.In.Declarations.Tags[tag].Node d := t.Declarator() if j.ImportPath(n) == 0 && j.tags[tag] == nil { j.tags[tag] = d } }
func (j *Job) cast(ot cc.Type, n *cc.Expression) { j.imports[idUnsafe] = struct{}{} if ot.Kind() == cc.Ptr && n.Type.Kind() == cc.Ptr && n.Type.Element().Kind() != cc.Function { j.body("(") j.typ(n, ot) j.body(")(unsafe.Pointer(") j.expression(nil, n) j.body("))") return } j.body("(*(*") j.typ(n, ot) j.body(")(unsafe.Pointer(&struct{f ") j.typ(n, n.Type) j.body("}{") j.expression(nil, n) j.body("})))") }
func (j *Job) union(n cc.Node, t cc.Type) { j.body("\n_ [0]struct{") m, _ := t.Members() for _, v := range m { j.body("\n%s", xc.Dict.S(v.Name)) j.typ(n, v.Type) if t := v.Type; t.Kind() != cc.Union && t.Kind() != cc.Struct { j.body(" // %s", v.Type) } } j.body("\n}") j.body("\nUnion [%v]byte", t.SizeOf()) }
func (j *Job) inc(ot cc.Type, n *cc.Expression, op string, post bool) { if ot != nil && ot.Kind() == cc.Void { todo(n, ot, n.Type) return } t := ot if t == nil { t = n.Type } j.body(" func() ") j.typ(n, t) j.body(" { p := &(") j.expression(nil, n.Expression) switch { case post: j.body("); r := *p; (*p)++; return r }()") default: j.body("); (*p)++; return *p }()") } }
func (j *Job) initializerList(st cc.Type, n *cc.InitializerList) { j.typ(n, st) j.body("{\n") defer j.body("\n}") if st.Kind() == cc.Union { return } if st.Kind() == cc.Array { t := st.Element() for ; n != nil; n = n.InitializerList { if n.DesignationOpt != nil { todo(n) } j.initializer(t, n.Initializer) j.body(",") j.body("\n") } return } var m []cc.Member if st != nil { m, _ = st.Members() } i := 0 for ; n != nil; n = n.InitializerList { if n.DesignationOpt != nil { todo(n) } var t cc.Type if i < len(m) { t = m[i].Type } j.initializer(t, n.Initializer) j.body(",") j.body("\n") i++ } }
func eqTypes(n cc.Node, a, b cc.Type) bool { if a.Kind() == cc.Ptr { if t := a.Element(); t.Kind() == cc.Function { a = t } } if b.Kind() == cc.Ptr { if t := b.Element(); t.Kind() == cc.Function { b = t } } return removeQualifiers(a.String()) == removeQualifiers(b.String()) }
func (j *Job) expression(ot cc.Type, n *cc.Expression) { if ot != nil { switch { case n.Case == 25 /* '(' TypeName')' Expression */ && !eqTypes(n.Expression, ot, n.Expression.Type): j.convert(ot, n.Expression) return case !eqTypes(n, ot, n.Type): j.convert(ot, n) return } } if n.Value != nil { j.constExpr(ot, n) return } switch n.Case { case 0: // IDENTIFIER id := n.Token.Val bn := n.IdentResolutionScope().Lookup(cc.NSIdentifiers, id).Node if j.ImportPath(bn) != 0 && id == idErrno { j.body(" 0/*TODO747*/") break } j.qualifier(bn) j.body(" %s", xc.Dict.S(mangleIdent(id, bn.(*cc.DirectDeclarator).TopDeclarator().Linkage == cc.External))) case 1: // CHARCONST // Case 1 todo(n) case 2: // FLOATCONST // Case 2 todo(n) case 3: // INTCONST // Case 3 todo(n) case 4: // LONGCHARCONST // Case 4 todo(n) case 5: // LONGSTRINGLITERAL // Case 5 todo(n) case 6: // STRINGLITERAL // Case 6 todo(n) case 7: // '(' ExpressionList ')' // Case 7 j.expressionList(n.Type, n.ExpressionList) case 8: // Expression '[' ExpressionList ']' // Case 8 switch n.Expression.Type.Kind() { case cc.Array: j.expression(nil, n.Expression) j.body("[") j.expressionList(nil, n.ExpressionList) j.body("]") case cc.Ptr: j.imports[idUnsafe] = struct{}{} j.body("(*(") j.typ(nil, n.Expression.Type) j.body(")(unsafe.Pointer(uintptr(unsafe.Pointer(") j.expression(nil, n.Expression) j.body(")) + uintptr(") j.expressionList(nil, n.ExpressionList) j.body("))))") default: todo(n, n.Expression.Type, n.Expression.Type.Kind(), ot, n.Type) } case 9: // Expression '(' ArgumentExpressionListOpt ')' // Case 9 e := n.Expression if e.Case == 0 /* IDENTIFIER */ && e.Token.Val == idGO { // __GO__() magic. for n := n.ArgumentExpressionListOpt.ArgumentExpressionList; n != nil; n = n.ArgumentExpressionList { switch n := n.Expression; n.Case { case 6: // STRINGLITERAL j.body("%s", xc.Dict.S(int(n.Value.(cc.StringLitID)))) default: panic("internal error") } } break } j.expression(n.Expression.Type, n.Expression) j.body("(") if o := n.ArgumentExpressionListOpt; o != nil { ps, _ := n.Expression.Type.Parameters() i := 0 for n := o.ArgumentExpressionList; n != nil; n = n.ArgumentExpressionList { j.expression(ps[i].Type, n.Expression) j.body(", ") i++ } } j.body(")") case 10: // Expression '.' IDENTIFIER // Case 10 fallthrough case 11: // Expression "->" IDENTIFIER // Case 11 j.selector(ot, n) case 12: // Expression "++" // Case 12 j.inc(ot, n, "++", true) case 13: // Expression "--" // Case 13 todo(n) case 14: // '(' TypeName ')' '{' InitializerList CommaOpt '}' // Case 14 todo(n) case 15: // "++" Expression // Case 15 j.inc(ot, n, "++", false) case 16: // "--" Expression // Case 16 todo(n) case 17: // '&' Expression // Case 17 j.body(" &") j.expression(nil, n.Expression) case 18: // '*' Expression // Case 18 j.body(" *") j.expression(n.Expression.Type, n.Expression) case 19: // '+' Expression // Case 19 todo(n) case 20: // '-' Expression // Case 20 todo(n) case 21: // '~' Expression // Case 21 j.body(" ^(") j.expression(ot, n.Expression) j.body(")") case 22: // '!' Expression // Case 22 switch t := n.Expression.Type; t.Kind() { case cc.Int: j.body(" libc.Not%s(", j.title(t.Kind())) j.expression(nil, n.Expression) j.body(")") default: todo(n, ot, t) } case 23: // "sizeof" Expression // Case 23 todo(n) case 24: // "sizeof" '(' TypeName ')' // Case 24 todo(n) case 25: // '(' TypeName')' Expression // Case 25 j.expression(ot, n.Expression) case 26: // Expression '*' Expression // Case 26 j.binary(ot, n, "*") case 27: // Expression '/' Expression // Case 27 j.binary(ot, n, "/") case 28: // Expression '%' Expression // Case 28 todo(n) case 29: // Expression '+' Expression // Case 29 j.add(ot, n, "+") case 30: // Expression '-' Expression // Case 30 j.add(ot, n, "-") case 31: // Expression "<<" Expression // Case 31 j.shift(ot, n, "<<") case 32: // Expression ">>" Expression // Case 32 todo(n) case 33: // Expression '<' Expression // Case 33 j.compare(ot, n, "Lt") case 34: // Expression '>' Expression // Case 34 j.compare(ot, n, "Gt") case 35: // Expression "<=" Expression // Case 35 todo(n) case 36: // Expression ">=" Expression // Case 36 todo(n) case 37: // Expression "==" Expression // Case 37 j.compare(ot, n, "Eq") case 38: // Expression "!=" Expression // Case 38 j.compare(ot, n, "Ne") case 39: // Expression '&' Expression // Case 39 j.binary(ot, n, "&") case 40: // Expression '^' Expression // Case 40 todo(n) case 41: // Expression '|' Expression // Case 41 j.binary(ot, n, "|") case 42: // Expression "&&" Expression // Case 42 j.boolean(ot, n, "&&") case 43: // Expression "||" Expression // Case 43 j.boolean(ot, n, "||") case 44: // Expression '?' ExpressionList ':' Expression // Case 44 switch { case ot != nil && ot.Kind() == cc.Void: todo(n, ot) default: j.body(" func()") j.typ(n, n.Type) j.body("{ if ") switch n.Expression.Type.Kind() { case cc.Int, cc.UInt, cc.UShort: j.body("(") j.expression(nil, n.Expression) j.body(") != 0 { return ") j.expressionList(n.Type, n.ExpressionList) j.body(" } else { return ") j.expression(n.Type, n.Expression2) case cc.Ptr: j.body("(") j.expression(nil, n.Expression) j.body(") != nil { return ") j.expressionList(n.Type, n.ExpressionList) j.body(" } else { return ") j.expression(n.Type, n.Expression2) default: todo(n, n.Expression.Type) } j.body(" }}()") } case 45: // Expression '=' Expression // Case 45 switch { case ot == nil: // Not an expression. switch { case n.Expression2.Case != 45: // Plain assignment. j.expression(nil, n.Expression) j.body(" = ") j.expression(n.Expression.Type, n.Expression2) default: todo(n) } default: j.body(" func() ") j.typ(n, n.Expression.Type) j.body(" { r := ") j.expression(n.Expression.Type, n.Expression2) j.body("; ") j.expression(nil, n.Expression) j.body(" = r; return r }()") } case 46: // Expression "*=" Expression // Case 46 todo(n) case 47: // Expression "/=" Expression // Case 47 todo(n) case 48: // Expression "%=" Expression // Case 48 todo(n) case 49: // Expression "+=" Expression // Case 49 todo(n) case 50: // Expression "-=" Expression // Case 50 todo(n) case 51: // Expression "<<=" Expression // Case 51 todo(n) case 52: // Expression ">>=" Expression // Case 52 todo(n) case 53: // Expression "&=" Expression // Case 53 todo(n) case 54: // Expression "^=" Expression // Case 54 todo(n) case 55: // Expression "|=" Expression // Case 55 todo(n) case 56: // "_Alignof" '(' TypeName ')' // Case 56 todo(n) default: panic("internal errro") } }
func (j *Job) convert(ot cc.Type, n *cc.Expression) { t := n.Type switch otk := ot.Kind(); otk { case cc.Ptr: switch t.Kind() { case cc.Int: if v := n.Value; v != nil && isZero(n, v) { j.body(" nil") return } todo(n, ot, t) } if ot.Element().Kind() == cc.Void { switch t.Kind() { case cc.Ptr: j.imports[idUnsafe] = struct{}{} j.body(" unsafe.Pointer(uintptr(0)/*TODO536*/)") break //TODO j.body(" unsafe.Pointer/*DBG536 %v %s */(", n.Case, n.Type) //TODO j.expression(nil, n) //TODO j.body("/*DBG538*/)") case cc.Array: switch { case t.Elements() > 0: j.imports[idUnsafe] = struct{}{} j.body(" unsafe.Pointer(&") j.expression(nil, n) j.body("[0])") default: todo(n, ot, t) } default: todo(n, ot, t) } break } switch t.Kind() { case cc.Ptr: switch t.Element().Kind() { case cc.Void: j.body("(") j.typ(n, ot) j.body(")(") j.expression(nil, n) j.body(")") default: j.cast(ot, n) } return case cc.Array: switch { case t.Elements() > 0: j.body(" &") j.expression(nil, n) j.body("[0]") default: todo(n, ot, t) } return } switch l := ot.Element(); l.Kind() { case cc.Function: switch t.Kind() { case cc.Function: j.cast(ot, n) default: todo(n, l, t) } case cc.Char: switch t.Kind() { case cc.Ptr: switch r := t.Element(); r.Kind() { case cc.Char: j.expression(nil, n) default: todo(n, l, r) } default: todo(n, l, t) } default: todo(n, ot, t) } case cc.Char, cc.Int, cc.LongLong, cc.SChar, cc.Short, cc.UChar, cc.UInt, cc.ULong, cc.ULongLong, cc.UShort: j.body(" %s(", j.Model.Items[otk].More) j.expression(nil, n) j.body(")") case cc.Void: if isLiteral(n) { break } j.expression(nil, n) default: todo(n, ot, t) } }
func (j *Job) signature(n cc.Node, t cc.Type) { ps, variadic := t.Parameters() j.body("(") names := false var groups [][]cc.Parameter var group []cc.Parameter var prevT cc.Type for i, p := range ps { if p.Name != 0 { names = true } if i == 0 { group = []cc.Parameter{p} prevT = p.Type continue } if !eqTypes(n, prevT, p.Type) { groups = append(groups, group) group = []cc.Parameter{p} prevT = p.Type continue } group = append(group, p) } if group != nil { groups = append(groups, group) } for _, g := range groups { switch { case names: for i, p := range g { j.body("%s", xc.Dict.S(mangleIdent(p.Name, false))) if i < len(g)-1 { j.body(", ") } } t := g[0].Type if t.Kind() == cc.Array { j.body("*") } j.typ(g[0].Declarator, t) j.body(", ") default: t := g[0].Type for range g { if t.Kind() == cc.Array { j.body("*") } j.typ(g[0].Declarator, t) j.body(", ") } } } if variadic { if names { j.body("args") } j.body("...interface{}") } j.body(")") if t := t.Result(); t.Kind() != cc.Void { if t.Kind() == cc.Array { j.body("*") } j.typ(n, t) } }
func (j *Job) typ(n cc.Node, t cc.Type) { if t.Declarator().RawSpecifier().TypedefName() == idVaList { j.body("[]interface{}") return } stars := 0 for t.Kind() == cc.Ptr { stars++ t = t.Element() } stars0 := stars if (t.Kind() == cc.Void || t.Kind() == cc.Function) && stars > 0 { stars-- } j.body("%s", strings.Repeat("*", stars)) switch k := t.Kind(); k { case cc.Char, cc.Double, cc.Int, cc.Long, cc.LongDouble, cc.LongLong, cc.SChar, cc.Short, cc.UChar, cc.ULong, cc.ULongLong, cc.UInt, cc.UShort: j.body(" %s", j.Model.Items[k].More) case cc.Void: if stars0 == 0 { todo(n) } j.body(" unsafe.Pointer") j.imports[idUnsafe] = struct{}{} case cc.Struct, cc.Union: // Use tag if available. if tag := t.Tag(); tag != 0 { nm := mangleTag(tag, true) j.qualifier(j.In.Declarations.Tags[tag].Node) j.body(" %s", xc.Dict.S(nm)) break } // Use typedef name if available. if tdn := t.Declarator().RawSpecifier().TypedefName(); tdn != 0 { nm := mangleIdent(tdn, true) j.qualifier(j.In.Declarations.Identifiers[tdn].Node) j.body(" %s", xc.Dict.S(nm)) break } j.body(" struct {") switch m, incomplete := t.Members(); { case incomplete: j.body("// Incomplete type\n_ byte") case t.Kind() == cc.Union: j.union(n, t) var f func(cc.Type) f = func(t cc.Type) { j.addTag(t) m, _ := t.Members() for _, v := range m { f(v.Type) } } default: for _, v := range m { if v.Bits != 0 { j.bits(n, v) continue } j.addTag(v.Type) id := v.Name nm := mangleIdent(id, true) j.body("\n%s", xc.Dict.S(nm)) j.typ(v.Declarator, v.Type) if t := v.Type; t.Kind() != cc.Union && t.Kind() != cc.Struct { j.body("// %s", v.Type) } } } j.body("\n}") case cc.Function: j.body(" func") j.signature(n, t) case cc.Array: j.arrayType(n, t) default: todo(n, t, t.Kind()) } }
func (j *Job) addTag2(t cc.Type) { for t.Kind() == cc.Ptr || t.Kind() == cc.Array { t = t.Element() } tag := t.Tag() var n cc.Node if tag != 0 { n = j.In.Declarations.Tags[tag].Node } d := t.Declarator() if (n != nil && j.ImportPath(n) != 0) || j.tags[tag] != nil { return } if tag != 0 { j.tags[tag] = d } m, _ := t.Members() for _, v := range m { j.addTag2(v.Type) } }