Skip to content

Commit ad3f5c6

Browse files
committed
generate: Further progress on function and struct support
1 parent 6ced417 commit ad3f5c6

File tree

10 files changed

+12715
-83
lines changed

10 files changed

+12715
-83
lines changed

generate/codegen/gen_function.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ var reservedWords = map[string]bool{
3838
"string": true,
3939
}
4040

41-
var typeMap = map[string]string{
41+
var goTypeFixupMap = map[string]string{
4242
"*kernel.Boolean_t": "*int",
4343
"*kernel.UniChar": "*uint16",
4444
"kernel.Boolean_t": "int",
@@ -47,6 +47,12 @@ var typeMap = map[string]string{
4747
"uint8_t": "byte",
4848
}
4949

50+
var objCtoCMap = map[string]string{
51+
"NSInteger": "int",
52+
"NSUInteger": "uint",
53+
"BOOL": "bool",
54+
}
55+
5056
// GoArgs return go function args
5157
func (f *Function) GoArgs(currentModule *modules.Module) string {
5258
// log.Println("rendering function", f.Name)
@@ -64,7 +70,7 @@ func (f *Function) GoArgs(currentModule *modules.Module) string {
6470
p.Name = p.Name + "_"
6571
}
6672
typ := p.Type.GoName(currentModule, true)
67-
if v, ok := typeMap[typ]; ok {
73+
if v, ok := goTypeFixupMap[typ]; ok {
6874
typ = v
6975
}
7076
args = append(args, fmt.Sprintf("%s %s", p.Name, typ))
@@ -79,7 +85,7 @@ func (f *Function) GoReturn(currentModule *modules.Module) string {
7985
}
8086
// log.Printf("rendering GoReturn function return: %s %T", f.ReturnType, f.ReturnType)
8187
typ := f.ReturnType.GoName(currentModule, true)
82-
if v, ok := typeMap[typ]; ok {
88+
if v, ok := goTypeFixupMap[typ]; ok {
8389
typ = v
8490
}
8591
return typ
@@ -93,6 +99,7 @@ func (f *Function) CArgs(currentModule *modules.Module) string {
9399
// log.Printf("rendering cfunction arg: %s %s %T", p.Name, p.Type, p.Type)
94100
typ := p.Type.CName()
95101
if cs, ok := p.Type.(CSignatureer); ok {
102+
fmt.Printf("has CSignatureer: %T %v -> %v\n", p.Type, typ, cs.CSignature())
96103
typ = cs.CSignature()
97104
}
98105
// check reserved words
@@ -174,7 +181,12 @@ func (f *Function) WriteGoCallCode(currentModule *modules.Module, cw *CodeWriter
174181
case *typing.PrimitiveType:
175182
sb.WriteString(cw.IndentStr + fmt.Sprintf(" C.%s(%s)", tt.CName(), p.GoName()))
176183
case *typing.PointerType:
177-
sb.WriteString(cw.IndentStr + fmt.Sprintf(" (*C.%s)(unsafe.Pointer(%s))", tt.Type.ObjcName(), p.GoName()))
184+
cTyp := tt.Type.CName()
185+
if v, ok := objCtoCMap[cTyp]; ok {
186+
// note: we should drive use of this branch down
187+
cTyp = v
188+
}
189+
sb.WriteString(cw.IndentStr + fmt.Sprintf(" (*C.%s)(unsafe.Pointer(%s))", cTyp, p.GoName()))
178190
default:
179191
sb.WriteString(cw.IndentStr + p.GoName())
180192
}
@@ -192,6 +204,8 @@ func (f *Function) WriteGoCallCode(currentModule *modules.Module, cw *CodeWriter
192204
switch tt := f.ReturnType.(type) {
193205
case *typing.StructType, *typing.PointerType:
194206
cw.WriteLineF("return *(*%s)(unsafe.Pointer(&%s))", tt.GoName(currentModule, true), resultName)
207+
case *typing.CStringType:
208+
cw.WriteLineF("return C.GoString(%s)", resultName)
195209
default:
196210
cw.WriteLineF("return %s(%s)", returnTypeStr, resultName)
197211
}
@@ -253,7 +267,10 @@ func (f *Function) WriteObjcWrapper(currentModule *modules.Module, cw *CodeWrite
253267
var conv string
254268
switch tt := p.Type.(type) {
255269
case *typing.PointerType:
270+
cw.WriteLineF("// -> %T", tt.Type)
256271
conv = tt.ObjcName()
272+
// case *typing.AliasType:
273+
// conv = tt.ObjcName() + "*"
257274
default:
258275
conv = tt.ObjcName()
259276
}
@@ -279,11 +296,7 @@ func (f *Function) WriteCSignature(currentModule *modules.Module, cw *CodeWriter
279296
var returnTypeStr string
280297
rt := f.Type.ReturnType
281298
returnTypeStr = rt.CName()
282-
if v, ok := map[string]string{
283-
"NSInteger": "int",
284-
"NSUInteger": "uint",
285-
"BOOL": "bool",
286-
}[returnTypeStr]; ok {
299+
if v, ok := objCtoCMap[returnTypeStr]; ok {
287300
returnTypeStr = v
288301
}
289302
if hasBlockParam(f.Parameters) {

generate/declparse/declparse_test.go

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,16 +1014,16 @@ var tests = []struct {
10141014
},
10151015
},
10161016
},
1017-
{
1018-
ParseOnly: true,
1019-
s: `typedef struct objc_object { ... } id;`,
1020-
n: &Statement{
1021-
Typedef: "id",
1022-
Struct: &StructDecl{
1023-
Name: "objc_object",
1024-
},
1025-
},
1026-
},
1017+
// {
1018+
// ParseOnly: true,
1019+
// s: `typedef struct objc_object { ... } id;`,
1020+
// n: &Statement{
1021+
// Typedef: "id",
1022+
// Struct: &StructDecl{
1023+
// Name: "objc_object",
1024+
// },
1025+
// },
1026+
// },
10271027
{
10281028
ParseOnly: true,
10291029
s: `typedef const void *(*CFDictionaryRetainCallBack)(CFAllocatorRef allocator, const void *value);`,
@@ -1155,31 +1155,14 @@ var tests = []struct {
11551155
},
11561156
{
11571157
ParseOnly: true,
1158-
s: "bool CGPDFDocumentUnlockWithPassword(CGPDFDocumentRef document, const char *password);",
1159-
Hint: HintFunction,
1158+
s: "typedef struct CGPDFArray *CGPDFArrayRef",
11601159
n: &Statement{
1161-
Function: &FunctionDecl{
1162-
ReturnType: TypeInfo{
1163-
Name: "bool",
1164-
},
1165-
Name: "CGPDFDocumentUnlockWithPassword",
1166-
Args: FuncArgs{
1167-
ArgInfo{
1168-
Name: "document",
1169-
Type: TypeInfo{
1170-
Name: "CGPDFDocumentRef",
1171-
},
1172-
},
1173-
ArgInfo{
1174-
Name: "password",
1175-
Type: TypeInfo{
1176-
Name: "char",
1177-
IsPtr: true,
1178-
Annots: map[TypeAnnotation]bool{
1179-
TypeAnnotConst: true,
1180-
},
1181-
},
1182-
},
1160+
Typedef: "CGPDFArrayRef",
1161+
TypeAlias: &TypeInfo{
1162+
Name: "CGPDFArray",
1163+
IsPtr: true,
1164+
Annots: map[TypeAnnotation]bool{
1165+
TypeAnnotStruct: true,
11831166
},
11841167
},
11851168
},

generate/declparse/parser.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ func (p *Parser) Parse() (*Statement, error) {
7777
}
7878
return &Statement{Enum: decl.(*EnumDecl), Typedef: p.finishTypedef()}, nil
7979
case keywords.STRUCT:
80+
if p.typedef {
81+
ti, err := p.expectType(false)
82+
if err != nil {
83+
return nil, err
84+
}
85+
typedef := p.finishTypedef()
86+
if typedef == "" && ti.Func != nil {
87+
typedef = ti.Func.Name
88+
ti.Func.Name = ""
89+
}
90+
return &Statement{TypeAlias: ti, Typedef: typedef}, nil
91+
}
8092
decl, err := p.parse(parseStruct)
8193
if err != nil {
8294
return nil, err

generate/function.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,15 @@ func (db *Generator) ToFunction(fw string, sym Symbol) *codegen.Function {
120120
"CFSetRemoveValue": true,
121121
"CFSetReplaceValue": true,
122122
"CFSetSetValue": true,
123+
"CFSocketCopyRegisteredValue": true,
123124
"CFTreeApplyFunctionToChildren": true,
124125
"CFTreeSortChildren": true,
125126
"CFURLCopyResourcePropertyForKey": true,
126127
"CFXMLNodeCreate": true,
127128
"CGBitmapContextCreate": true,
129+
"CGPDFScannerPopName": true,
128130
"CGBitmapContextCreateWithData": true,
131+
"CGColorSpaceCreateIndexed": true,
129132
"CGColorSpaceCreateWithPlatformColorSpace": true,
130133
"CGConvertColorDataWithFormat": true,
131134
"CGDataConsumerCreate": true,
@@ -138,11 +141,14 @@ func (db *Generator) ToFunction(fw string, sym Symbol) *codegen.Function {
138141
"CGEventTapCreate": true,
139142
"CGEventTapCreateForPSN": true,
140143
"CGEventTapCreateForPid": true,
144+
"CGEventTapPostEvent": true,
141145
"CGFontCreateWithPlatformFont": true,
142146
"CGFunctionCreate": true,
143147
"CGPDFArrayApplyBlock": true,
148+
"CGPDFArrayGetName": true,
144149
"CGPDFDictionaryApplyBlock": true,
145150
"CGPDFDictionaryApplyFunction": true,
151+
"CGPDFDictionaryGetName": true,
146152
"CGPDFObjectGetValue": true,
147153
"CGPDFScannerCreate": true,
148154
"CGPSConverterCreate": true,
@@ -240,13 +246,6 @@ func (db *Generator) ToFunction(fw string, sym Symbol) *codegen.Function {
240246
"OBEXSessionSetPath": true,
241247
"OBEXSessionSetPathResponse": true,
242248
"OBEXSessionSetServerCallback": true,
243-
"CFSocketCopyRegisteredValue": true,
244-
}
245-
if _, ok := map[string]bool{
246-
//"CGColorSpaceCreateCalibratedGray": true,
247-
"CGPDFDocumentUnlockWithPassword": true,
248-
}[sym.Name]; !ok {
249-
return nil
250249
}
251250
if knownIssues[sym.Name] {
252251
_, err := sym.Parse()
@@ -277,13 +276,22 @@ func (db *Generator) ToFunction(fw string, sym Symbol) *codegen.Function {
277276
// populate params:
278277
log.Printf("decl: %v %s\n", sym.Name, sym.Declaration)
279278
for i, p := range fntyp.Parameters {
280-
log.Printf(" param %#v: %v %+v\n", i, p.Name, p.Type.ObjcName())
279+
if p.Type != nil {
280+
log.Printf(" param %#v: %v %+v\n", i, p.Name, p.Type.ObjcName())
281+
}
281282
}
282283
for _, p := range fntyp.Parameters {
283284
if p.Type == nil {
284285
fmt.Printf("skipping %s: %s because of nil type\n", sym.Name, p.Name)
285286
return nil
286287
}
288+
// skip pointers to ref types (for now)
289+
if pt, ok := p.Type.(*typing.PointerType); ok {
290+
if _, ok := pt.Type.(*typing.RefType); ok {
291+
fmt.Printf("skipping %s: %s because of pointer to ref type\n", sym.Name, p.Name)
292+
return nil
293+
}
294+
}
287295
fn.Parameters = append(fn.Parameters, &codegen.Param{
288296
Name: p.Name,
289297
Type: p.Type,

generate/types.go

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"fmt"
66
"log"
7+
"os"
78
"strings"
89

910
"github.com/progrium/macdriver/generate/declparse"
@@ -63,6 +64,8 @@ func (db *Generator) TypeFromSymbol(sym Symbol) typing.Type {
6364
fmt.Printf("TypeFromSymbol: name=%s declaration=%s\n", sym.Name, sym.Declaration)
6465
panic("unknown type")
6566
}
67+
68+
// special handling of Ref structs
6669
if (strings.HasSuffix(sym.Name, "Ref") && strings.Contains(sym.Declaration, "struct")) ||
6770
sym.Name == "AudioComponent" ||
6871
// sym.Name == "NSZone" ||
@@ -92,13 +95,22 @@ func (db *Generator) TypeFromSymbol(sym Symbol) typing.Type {
9295
fmt.Printf("TypeFromSymbol: name=%s declaration=%s\n", sym.Name, sym.Declaration)
9396
panic("unable to parse type")
9497
}
95-
return &typing.AliasType{
98+
typ = &typing.AliasType{
9699
Name: sym.Name,
97100
GName: modules.TrimPrefix(sym.Name),
98101
Module: modules.Get(module),
99102
Type: typ,
100103
}
104+
105+
j, _ := json.Marshal(typ)
106+
fmt.Println(string(j))
107+
if sym.Name == "CGPDFArrayRef" {
108+
os.Exit(1)
109+
}
110+
111+
return typ
101112
case "Struct":
113+
fmt.Println("STURCT AHDNLE:", sym.Name)
102114
if strings.HasSuffix(sym.Name, "Ref") {
103115
return &typing.RefType{
104116
Name: sym.Name,
@@ -197,13 +209,21 @@ func (db *Generator) ParseType(ti declparse.TypeInfo) (typ typing.Type) {
197209
// objc type
198210
typ = typing.Class
199211
case "off_t":
200-
j, _ := json.Marshal(ti)
201-
fmt.Println(string(j))
202-
203-
// to kernel type
204212
typ = typing.Int
205-
case "float", "CGFloat", "Float64":
213+
case "CGFloat", "Float64":
206214
typ = typing.Float
215+
case "float":
216+
typ = &typing.PrimitiveType{
217+
GoName_: "float32",
218+
ObjcName_: "float",
219+
CName_: "float",
220+
}
221+
case "int":
222+
typ = &typing.PrimitiveType{
223+
GoName_: "int",
224+
ObjcName_: "int",
225+
CName_: "int",
226+
}
207227
case "char":
208228
j, _ := json.Marshal(ti)
209229
fmt.Println(string(j))
@@ -250,6 +270,7 @@ func (db *Generator) ParseType(ti declparse.TypeInfo) (typ typing.Type) {
250270
}
251271
ref = true
252272
default:
273+
253274
var ok bool
254275
typ, ok = typing.GetPrimitiveType(ti.Name)
255276
// log.Println("primitive", ti.Name, ok)
@@ -263,12 +284,13 @@ func (db *Generator) ParseType(ti declparse.TypeInfo) (typ typing.Type) {
263284
// log.Println("kernel", ti.Name, ok)
264285
if !ok {
265286
typ = db.TypeFromSymbolName(ti.Name)
266-
log.Println("symbol", ti.Name, typ, ok)
287+
j, _ := json.Marshal(ti)
288+
log.Printf("symbol %v %T %v - %v", ti.Name, typ, ok, string(j))
267289
switch typ.(type) {
268290
case *typing.ClassType:
269291
ref = true
270-
// case *typing.StructType:
271-
// ref = true
292+
case *typing.StructType:
293+
//ref = true
272294
case *typing.ProtocolType:
273295
panic("standalone proto type")
274296
}
@@ -279,7 +301,8 @@ func (db *Generator) ParseType(ti declparse.TypeInfo) (typ typing.Type) {
279301
return typ
280302
}
281303

282-
if ti.IsPtr && !ref {
304+
//fmt.Printf("ParseType: %s %s %s\n", ti.Name, typ, ti)
305+
if (ti.IsPtr || ti.IsPtrPtr) && !ref {
283306
if _, ok := typ.(*typing.VoidType); ok {
284307
typ = &typing.VoidPointerType{}
285308
} else {

0 commit comments

Comments
 (0)