func rewriteTypes(cfg *Config, prog cc.Syntax) {
	cache := make(map[*cc.Type]*cc.Type)
	cc.Postorder(prog, func(x cc.Syntax) {
		if t, ok := x.(*cc.Type); ok {
			if t.Kind == cc.Struct || t.Kind == cc.Enum {
				for _, d := range t.Decls {
					d.OuterType = t
				}
			}
			if t.Kind == cc.Func && len(t.Decls) == 1 && t.Decls[0].Type.Is(cc.Void) {
				t.Decls = nil
			}
		}
		if d, ok := x.(*cc.Decl); ok {
			if d.Type != nil && d.Type.Kind == cc.Func {
				for _, d1 := range d.Type.Decls {
					d1.CurFn = d
				}
				if d.Body != nil {
					for _, s := range d.Body.Block {
						if s.Op == cc.StmtDecl {
							s.Decl.CurFn = d
						}
					}
				}
			}
		}
	})
	cc.Postorder(prog, func(x cc.Syntax) {
		switch x := x.(type) {
		case *cc.Decl:
			d := x
			if d.Name == "..." || d.Type == nil {
				return
			}
			if d.Name == "" && d.Type.Is(cc.Enum) && len(d.Type.Decls) > 0 {
				for _, dd := range d.Type.Decls {
					dd.Type = idealType
				}
				return
			}
			if d.Init != nil && len(d.Init.Braced) > 0 && d.Type != nil && d.Type.Kind == cc.Array {
				d.Type.Base = toGoType(cfg, nil, d.Type.Base, cache)
				if d.Type.Width == nil {
					d.Type.Kind = Slice
				}
				return
			}
			d.Type = toGoType(cfg, d, d.Type, cache)
		case *cc.Expr:
			if x.Type != nil {
				t := toGoType(cfg, nil, x.Type, cache)
				if t == nil {
					fprintf(x.Span, "cannot convert %v to go type\n", GoString(x.Type))
				}
				x.Type = t
			}
		}
	})
}
rewriteTypes rewrites C types appearing in the program to equivalent Go types.
package main
import (
	"fmt"
	"os"
	"strings"
	"rsc.io/c2go/cc"
)