Struct conversion: return Go and (gc) C syntax for type.
(dt *dwarf.StructType, pos token.Pos)
| 2868 | |
| 2869 | // Struct conversion: return Go and (gc) C syntax for type. |
| 2870 | func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) { |
| 2871 | // Minimum alignment for a struct is 1 byte. |
| 2872 | align = 1 |
| 2873 | |
| 2874 | var buf bytes.Buffer |
| 2875 | buf.WriteString("struct {") |
| 2876 | fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field |
| 2877 | sizes := make([]int64, 0, 2*len(dt.Field)+1) |
| 2878 | off := int64(0) |
| 2879 | |
| 2880 | // Rename struct fields that happen to be named Go keywords into |
| 2881 | // _{keyword}. Create a map from C ident -> Go ident. The Go ident will |
| 2882 | // be mangled. Any existing identifier that already has the same name on |
| 2883 | // the C-side will cause the Go-mangled version to be prefixed with _. |
| 2884 | // (e.g. in a struct with fields '_type' and 'type', the latter would be |
| 2885 | // rendered as '__type' in Go). |
| 2886 | ident := make(map[string]string) |
| 2887 | used := make(map[string]bool) |
| 2888 | for _, f := range dt.Field { |
| 2889 | ident[f.Name] = f.Name |
| 2890 | used[f.Name] = true |
| 2891 | } |
| 2892 | |
| 2893 | if !*godefs { |
| 2894 | for cid, goid := range ident { |
| 2895 | if token.Lookup(goid).IsKeyword() { |
| 2896 | // Avoid keyword |
| 2897 | goid = "_" + goid |
| 2898 | |
| 2899 | // Also avoid existing fields |
| 2900 | for _, exist := used[goid]; exist; _, exist = used[goid] { |
| 2901 | goid = "_" + goid |
| 2902 | } |
| 2903 | |
| 2904 | used[goid] = true |
| 2905 | ident[cid] = goid |
| 2906 | } |
| 2907 | } |
| 2908 | } |
| 2909 | |
| 2910 | anon := 0 |
| 2911 | for _, f := range dt.Field { |
| 2912 | name := f.Name |
| 2913 | ft := f.Type |
| 2914 | |
| 2915 | // In godefs mode, if this field is a C11 |
| 2916 | // anonymous union then treat the first field in the |
| 2917 | // union as the field in the struct. This handles |
| 2918 | // cases like the glibc <sys/resource.h> file; see |
| 2919 | // issue 6677. |
| 2920 | if *godefs { |
| 2921 | if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] { |
| 2922 | name = st.Field[0].Name |
| 2923 | ident[name] = name |
| 2924 | ft = st.Field[0].Type |
| 2925 | } |
| 2926 | } |
| 2927 |