Skip to content

Commit

Permalink
generate: Further progress on function and struct support
Browse files Browse the repository at this point in the history
  • Loading branch information
tmc committed Sep 3, 2023
1 parent 6ced417 commit ad3f5c6
Show file tree
Hide file tree
Showing 10 changed files with 12,715 additions and 83 deletions.
31 changes: 22 additions & 9 deletions generate/codegen/gen_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var reservedWords = map[string]bool{
"string": true,
}

var typeMap = map[string]string{
var goTypeFixupMap = map[string]string{
"*kernel.Boolean_t": "*int",
"*kernel.UniChar": "*uint16",
"kernel.Boolean_t": "int",
Expand All @@ -47,6 +47,12 @@ var typeMap = map[string]string{
"uint8_t": "byte",
}

var objCtoCMap = map[string]string{
"NSInteger": "int",
"NSUInteger": "uint",
"BOOL": "bool",
}

// GoArgs return go function args
func (f *Function) GoArgs(currentModule *modules.Module) string {
// log.Println("rendering function", f.Name)
Expand All @@ -64,7 +70,7 @@ func (f *Function) GoArgs(currentModule *modules.Module) string {
p.Name = p.Name + "_"
}
typ := p.Type.GoName(currentModule, true)
if v, ok := typeMap[typ]; ok {
if v, ok := goTypeFixupMap[typ]; ok {
typ = v
}
args = append(args, fmt.Sprintf("%s %s", p.Name, typ))
Expand All @@ -79,7 +85,7 @@ func (f *Function) GoReturn(currentModule *modules.Module) string {
}
// log.Printf("rendering GoReturn function return: %s %T", f.ReturnType, f.ReturnType)
typ := f.ReturnType.GoName(currentModule, true)
if v, ok := typeMap[typ]; ok {
if v, ok := goTypeFixupMap[typ]; ok {
typ = v
}
return typ
Expand All @@ -93,6 +99,7 @@ func (f *Function) CArgs(currentModule *modules.Module) string {
// log.Printf("rendering cfunction arg: %s %s %T", p.Name, p.Type, p.Type)
typ := p.Type.CName()
if cs, ok := p.Type.(CSignatureer); ok {
fmt.Printf("has CSignatureer: %T %v -> %v\n", p.Type, typ, cs.CSignature())
typ = cs.CSignature()
}
// check reserved words
Expand Down Expand Up @@ -174,7 +181,12 @@ func (f *Function) WriteGoCallCode(currentModule *modules.Module, cw *CodeWriter
case *typing.PrimitiveType:
sb.WriteString(cw.IndentStr + fmt.Sprintf(" C.%s(%s)", tt.CName(), p.GoName()))
case *typing.PointerType:
sb.WriteString(cw.IndentStr + fmt.Sprintf(" (*C.%s)(unsafe.Pointer(%s))", tt.Type.ObjcName(), p.GoName()))
cTyp := tt.Type.CName()
if v, ok := objCtoCMap[cTyp]; ok {
// note: we should drive use of this branch down
cTyp = v
}
sb.WriteString(cw.IndentStr + fmt.Sprintf(" (*C.%s)(unsafe.Pointer(%s))", cTyp, p.GoName()))
default:
sb.WriteString(cw.IndentStr + p.GoName())
}
Expand All @@ -192,6 +204,8 @@ func (f *Function) WriteGoCallCode(currentModule *modules.Module, cw *CodeWriter
switch tt := f.ReturnType.(type) {
case *typing.StructType, *typing.PointerType:
cw.WriteLineF("return *(*%s)(unsafe.Pointer(&%s))", tt.GoName(currentModule, true), resultName)
case *typing.CStringType:
cw.WriteLineF("return C.GoString(%s)", resultName)
default:
cw.WriteLineF("return %s(%s)", returnTypeStr, resultName)
}
Expand Down Expand Up @@ -253,7 +267,10 @@ func (f *Function) WriteObjcWrapper(currentModule *modules.Module, cw *CodeWrite
var conv string
switch tt := p.Type.(type) {
case *typing.PointerType:
cw.WriteLineF("// -> %T", tt.Type)
conv = tt.ObjcName()
// case *typing.AliasType:
// conv = tt.ObjcName() + "*"
default:
conv = tt.ObjcName()
}
Expand All @@ -279,11 +296,7 @@ func (f *Function) WriteCSignature(currentModule *modules.Module, cw *CodeWriter
var returnTypeStr string
rt := f.Type.ReturnType
returnTypeStr = rt.CName()
if v, ok := map[string]string{
"NSInteger": "int",
"NSUInteger": "uint",
"BOOL": "bool",
}[returnTypeStr]; ok {
if v, ok := objCtoCMap[returnTypeStr]; ok {
returnTypeStr = v
}
if hasBlockParam(f.Parameters) {
Expand Down
51 changes: 17 additions & 34 deletions generate/declparse/declparse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1014,16 +1014,16 @@ var tests = []struct {
},
},
},
{
ParseOnly: true,
s: `typedef struct objc_object { ... } id;`,
n: &Statement{
Typedef: "id",
Struct: &StructDecl{
Name: "objc_object",
},
},
},
// {
// ParseOnly: true,
// s: `typedef struct objc_object { ... } id;`,
// n: &Statement{
// Typedef: "id",
// Struct: &StructDecl{
// Name: "objc_object",
// },
// },
// },
{
ParseOnly: true,
s: `typedef const void *(*CFDictionaryRetainCallBack)(CFAllocatorRef allocator, const void *value);`,
Expand Down Expand Up @@ -1155,31 +1155,14 @@ var tests = []struct {
},
{
ParseOnly: true,
s: "bool CGPDFDocumentUnlockWithPassword(CGPDFDocumentRef document, const char *password);",
Hint: HintFunction,
s: "typedef struct CGPDFArray *CGPDFArrayRef",
n: &Statement{
Function: &FunctionDecl{
ReturnType: TypeInfo{
Name: "bool",
},
Name: "CGPDFDocumentUnlockWithPassword",
Args: FuncArgs{
ArgInfo{
Name: "document",
Type: TypeInfo{
Name: "CGPDFDocumentRef",
},
},
ArgInfo{
Name: "password",
Type: TypeInfo{
Name: "char",
IsPtr: true,
Annots: map[TypeAnnotation]bool{
TypeAnnotConst: true,
},
},
},
Typedef: "CGPDFArrayRef",
TypeAlias: &TypeInfo{
Name: "CGPDFArray",
IsPtr: true,
Annots: map[TypeAnnotation]bool{
TypeAnnotStruct: true,
},
},
},
Expand Down
12 changes: 12 additions & 0 deletions generate/declparse/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ func (p *Parser) Parse() (*Statement, error) {
}
return &Statement{Enum: decl.(*EnumDecl), Typedef: p.finishTypedef()}, nil
case keywords.STRUCT:
if p.typedef {
ti, err := p.expectType(false)
if err != nil {
return nil, err
}
typedef := p.finishTypedef()
if typedef == "" && ti.Func != nil {
typedef = ti.Func.Name
ti.Func.Name = ""
}
return &Statement{TypeAlias: ti, Typedef: typedef}, nil
}
decl, err := p.parse(parseStruct)
if err != nil {
return nil, err
Expand Down
24 changes: 16 additions & 8 deletions generate/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,15 @@ func (db *Generator) ToFunction(fw string, sym Symbol) *codegen.Function {
"CFSetRemoveValue": true,
"CFSetReplaceValue": true,
"CFSetSetValue": true,
"CFSocketCopyRegisteredValue": true,
"CFTreeApplyFunctionToChildren": true,
"CFTreeSortChildren": true,
"CFURLCopyResourcePropertyForKey": true,
"CFXMLNodeCreate": true,
"CGBitmapContextCreate": true,
"CGPDFScannerPopName": true,
"CGBitmapContextCreateWithData": true,
"CGColorSpaceCreateIndexed": true,
"CGColorSpaceCreateWithPlatformColorSpace": true,
"CGConvertColorDataWithFormat": true,
"CGDataConsumerCreate": true,
Expand All @@ -138,11 +141,14 @@ func (db *Generator) ToFunction(fw string, sym Symbol) *codegen.Function {
"CGEventTapCreate": true,
"CGEventTapCreateForPSN": true,
"CGEventTapCreateForPid": true,
"CGEventTapPostEvent": true,
"CGFontCreateWithPlatformFont": true,
"CGFunctionCreate": true,
"CGPDFArrayApplyBlock": true,
"CGPDFArrayGetName": true,
"CGPDFDictionaryApplyBlock": true,
"CGPDFDictionaryApplyFunction": true,
"CGPDFDictionaryGetName": true,
"CGPDFObjectGetValue": true,
"CGPDFScannerCreate": true,
"CGPSConverterCreate": true,
Expand Down Expand Up @@ -240,13 +246,6 @@ func (db *Generator) ToFunction(fw string, sym Symbol) *codegen.Function {
"OBEXSessionSetPath": true,
"OBEXSessionSetPathResponse": true,
"OBEXSessionSetServerCallback": true,
"CFSocketCopyRegisteredValue": true,
}
if _, ok := map[string]bool{
//"CGColorSpaceCreateCalibratedGray": true,
"CGPDFDocumentUnlockWithPassword": true,
}[sym.Name]; !ok {
return nil
}
if knownIssues[sym.Name] {
_, err := sym.Parse()
Expand Down Expand Up @@ -277,13 +276,22 @@ func (db *Generator) ToFunction(fw string, sym Symbol) *codegen.Function {
// populate params:
log.Printf("decl: %v %s\n", sym.Name, sym.Declaration)
for i, p := range fntyp.Parameters {
log.Printf(" param %#v: %v %+v\n", i, p.Name, p.Type.ObjcName())
if p.Type != nil {
log.Printf(" param %#v: %v %+v\n", i, p.Name, p.Type.ObjcName())
}
}
for _, p := range fntyp.Parameters {
if p.Type == nil {
fmt.Printf("skipping %s: %s because of nil type\n", sym.Name, p.Name)
return nil
}
// skip pointers to ref types (for now)
if pt, ok := p.Type.(*typing.PointerType); ok {
if _, ok := pt.Type.(*typing.RefType); ok {
fmt.Printf("skipping %s: %s because of pointer to ref type\n", sym.Name, p.Name)
return nil
}
}
fn.Parameters = append(fn.Parameters, &codegen.Param{
Name: p.Name,
Type: p.Type,
Expand Down
43 changes: 33 additions & 10 deletions generate/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"log"
"os"
"strings"

"github.com/progrium/macdriver/generate/declparse"
Expand Down Expand Up @@ -63,6 +64,8 @@ func (db *Generator) TypeFromSymbol(sym Symbol) typing.Type {
fmt.Printf("TypeFromSymbol: name=%s declaration=%s\n", sym.Name, sym.Declaration)
panic("unknown type")
}

// special handling of Ref structs
if (strings.HasSuffix(sym.Name, "Ref") && strings.Contains(sym.Declaration, "struct")) ||
sym.Name == "AudioComponent" ||
// sym.Name == "NSZone" ||
Expand Down Expand Up @@ -92,13 +95,22 @@ func (db *Generator) TypeFromSymbol(sym Symbol) typing.Type {
fmt.Printf("TypeFromSymbol: name=%s declaration=%s\n", sym.Name, sym.Declaration)
panic("unable to parse type")
}
return &typing.AliasType{
typ = &typing.AliasType{
Name: sym.Name,
GName: modules.TrimPrefix(sym.Name),
Module: modules.Get(module),
Type: typ,
}

j, _ := json.Marshal(typ)
fmt.Println(string(j))
if sym.Name == "CGPDFArrayRef" {
os.Exit(1)
}

return typ
case "Struct":
fmt.Println("STURCT AHDNLE:", sym.Name)
if strings.HasSuffix(sym.Name, "Ref") {
return &typing.RefType{
Name: sym.Name,
Expand Down Expand Up @@ -197,13 +209,21 @@ func (db *Generator) ParseType(ti declparse.TypeInfo) (typ typing.Type) {
// objc type
typ = typing.Class
case "off_t":
j, _ := json.Marshal(ti)
fmt.Println(string(j))

// to kernel type
typ = typing.Int
case "float", "CGFloat", "Float64":
case "CGFloat", "Float64":
typ = typing.Float
case "float":
typ = &typing.PrimitiveType{
GoName_: "float32",
ObjcName_: "float",
CName_: "float",
}
case "int":
typ = &typing.PrimitiveType{
GoName_: "int",
ObjcName_: "int",
CName_: "int",
}
case "char":
j, _ := json.Marshal(ti)
fmt.Println(string(j))
Expand Down Expand Up @@ -250,6 +270,7 @@ func (db *Generator) ParseType(ti declparse.TypeInfo) (typ typing.Type) {
}
ref = true
default:

var ok bool
typ, ok = typing.GetPrimitiveType(ti.Name)
// log.Println("primitive", ti.Name, ok)
Expand All @@ -263,12 +284,13 @@ func (db *Generator) ParseType(ti declparse.TypeInfo) (typ typing.Type) {
// log.Println("kernel", ti.Name, ok)
if !ok {
typ = db.TypeFromSymbolName(ti.Name)
log.Println("symbol", ti.Name, typ, ok)
j, _ := json.Marshal(ti)
log.Printf("symbol %v %T %v - %v", ti.Name, typ, ok, string(j))
switch typ.(type) {
case *typing.ClassType:
ref = true
// case *typing.StructType:
// ref = true
case *typing.StructType:
//ref = true
case *typing.ProtocolType:
panic("standalone proto type")
}
Expand All @@ -279,7 +301,8 @@ func (db *Generator) ParseType(ti declparse.TypeInfo) (typ typing.Type) {
return typ
}

if ti.IsPtr && !ref {
//fmt.Printf("ParseType: %s %s %s\n", ti.Name, typ, ti)
if (ti.IsPtr || ti.IsPtrPtr) && !ref {
if _, ok := typ.(*typing.VoidType); ok {
typ = &typing.VoidPointerType{}
} else {
Expand Down
Loading

0 comments on commit ad3f5c6

Please sign in to comment.