1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
package program
import (
"fmt"
"strings"
"github.com/elliotchance/c2go/ast"
)
// Struct represents the definition for a C struct.
type Struct struct {
// The name of the struct.
Name string
// True if the struct kind is an union.
// This field is used to avoid to dupplicate code for union case the type is the same.
// Plus, this field is used in collaboration with the method "c2go/program".*Program.GetStruct()
IsUnion bool
// Each of the fields and their C type. The field may be a string or an
// instance of Struct for nested structures.
Fields map[string]interface{}
// Each of the field names in the order they were defined.
FieldNames []string
}
// NewStruct creates a new Struct definition from an ast.RecordDecl.
func NewStruct(n *ast.RecordDecl) *Struct {
fields := make(map[string]interface{})
fieldNames := make([]string, 0, len(n.Children()))
for _, field := range n.Children() {
switch f := field.(type) {
case *ast.FieldDecl:
fields[f.Name] = f.Type
fieldNames = append(fieldNames, f.Name)
case *ast.IndirectFieldDecl:
fields[f.Name] = f.Type
fieldNames = append(fieldNames, f.Name)
case *ast.RecordDecl:
fields[f.Name] = NewStruct(f)
fieldNames = append(fieldNames, f.Name)
case *ast.MaxFieldAlignmentAttr,
*ast.AlignedAttr,
*ast.TransparentUnionAttr,
*ast.FullComment:
// FIXME: Should these really be ignored?
default:
panic(fmt.Sprintf("cannot decode: %#v", f))
}
}
return &Struct{
Name: n.Name,
IsUnion: n.Kind == "union",
Fields: fields,
FieldNames: fieldNames,
}
}
// IsUnion - return true if the cType is 'union' or
// typedef of union
func (p *Program) IsUnion(cType string) bool {
if strings.HasPrefix(cType, "union ") {
return true
}
if _, ok := p.Unions[cType]; ok {
return true
}
if _, ok := p.Unions["union "+cType]; ok {
return true
}
if _, ok := p.GetBaseTypeOfTypedef("union " + cType); ok {
return true
}
if t, ok := p.GetBaseTypeOfTypedef(cType); ok {
if t == cType {
panic(fmt.Errorf("Cannot be same name: %s", t))
}
if strings.HasPrefix(t, "struct ") {
return false
}
if t == "" {
panic(fmt.Errorf("Type cannot be empty"))
}
return p.IsUnion(t)
}
return false
}
// GetBaseTypeOfTypedef - return typedef type
func (p *Program) GetBaseTypeOfTypedef(cTypedef string) (
cBase string, ok bool) {
cBase, ok = p.TypedefType[cTypedef]
if cBase == "" && ok {
panic(fmt.Errorf("Type cannot be empty"))
}
return
}
|