func exportDecl(d *cc.Decl) { d.Name = exportName(d.Name) if d.Storage&cc.Typedef != 0 && d.Type.Kind == cc.Struct { for _, dd := range d.Type.Decls { exportDecl(dd) // type became type_, became Type_. Drop underscore now that it's not needed. if strings.HasSuffix(dd.Name, "_") && goKeyword[strings.ToLower(dd.Name[:len(dd.Name)-1])] { dd.Name = dd.Name[:len(dd.Name)-1] } if dd.Name == "U" { for _, dd := range dd.Type.Decls { exportDecl(dd) } } } } }
func renameDecl(cfg *Config, d *cc.Decl) { key := declKey(d) if cfg.rename[key] != "" { d.Name = cfg.rename[key] } if d.Storage&cc.Typedef != 0 && d.Type.Kind == cc.Struct { for _, dd := range d.Type.Decls { renameDecl(cfg, dd) if dd.Name == "U" { for _, dd := range dd.Type.Decls { renameDecl(cfg, dd) } } } } if d.Type != nil && d.Type.Kind == cc.Func && d.Body != nil { for _, s := range d.Body.Block { if s.Op == cc.StmtDecl && s.Decl.Storage&cc.Static != 0 { renameDecl(cfg, s.Decl) } } } }
func fixQsortCmp(decl *cc.Decl) (*cc.Type, *cc.Decl) { ftyp := decl.Type if ftyp.Kind != cc.Func || len(ftyp.Decls) != 2 || !isEmptyInterface(ftyp.Decls[0].Type) || !isEmptyInterface(ftyp.Decls[1].Type) { fprintf(decl.Span, "invalid qsort cmp function %v - wrong args", GoString(ftyp)) return nil, nil } a1, a2 := ftyp.Decls[0], ftyp.Decls[1] var eq1, eq2, p1, p2 *cc.Expr var indir1, indir2 bool cc.Preorder(decl.Body, func(x cc.Syntax) { switch x := x.(type) { case *cc.Expr: if x.Op != cc.Eq { return } r := x.Right if r.Op == cc.Indir { r = r.Left } if (r.Op == TypeAssert || r.Op == cc.Cast) && r.Left.Op == cc.Name { if r.Left.XDecl == a1 && p1 == nil { p1 = x.Left eq1 = x indir1 = r != x.Right } if r.Left.XDecl == a2 && p2 == nil { p2 = x.Left eq2 = x indir2 = r != x.Right } } } }) if p1 == nil || p2 == nil { fprintf(decl.Span, "invalid qsort cmp function - cannot find arg extraction") return nil, nil } if !sameType(p1.XType, p2.XType) { fprintf(decl.Span, "invalid qsort cmp function - different arg types %v and %v", GoString(p1.XType), GoString(p2.XType)) return nil, nil } if indir1 != indir2 { fprintf(decl.Span, "invalid qsort cmp function - different arg indirection") return nil, nil } typ := p1.XType if !indir1 { if typ.Def().Kind != cc.Ptr { fprintf(decl.Span, "invalid qsort cmp function - arg ptr cast to non-ptr %v", GoString(typ)) return nil, nil } typ = typ.Def().Base } // Have all the information. Committed. // Rewrite to take x, i, j, use x[i] for p1, x[j] for p2, // take address of x[i], x[j] if there was no indirect, // replace all return z with return z < 0. newDecl := *decl decl.Body = nil decl = &newDecl cmp := decl.Name decl.Name = "(x " + cmp + ") Less" decl.Type = &cc.Type{ Kind: cc.Func, Base: boolType, Decls: []*cc.Decl{ {Name: "i", Type: &cc.Type{Kind: cc.TypedefType}}, {Name: "j", Type: intType}, }, } prefix := "" if !indir1 { prefix = "&" } eq1.Right = &cc.Expr{Op: cc.Name, Text: prefix + "x[i]", XType: p1.XType} eq2.Right = &cc.Expr{Op: cc.Name, Text: prefix + "x[j]", XType: p1.XType} cc.Preorder(decl.Body, func(x cc.Syntax) { switch x := x.(type) { case *cc.Stmt: if x.Op == cc.Return && x.Expr != nil { ret := x.Expr // Pick off 0, -1, +1. // Otherwise rewrite ret to ret < 0. switch ret.Op { case cc.Minus, cc.Plus: if ret.Left.Op == cc.Number && ret.Left.Text == "1" { if ret.Op == cc.Plus { ret.Text = "false" } else { ret.Text = "true" } ret.Op = cc.Name ret.Left = nil ret.XType = boolType return } case cc.Number: if ret.Text == "0" { ret.Op = cc.Name ret.Text = "false" ret.XType = boolType return } } x.Expr = &cc.Expr{Op: cc.Lt, Left: ret, Right: &cc.Expr{Op: cc.Number, Text: "0"}, XType: boolType} return } } }) return typ, decl }