Better handling of multiple classes and input files. Handle
Objective C type parameter declarations. Check Typedefs when determining if a Type is a pointer or a function.
This commit is contained in:
parent
6135381cc7
commit
977a09e77e
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,6 +1,8 @@
|
||||||
clast
|
clast
|
||||||
ast.txt
|
ast.txt
|
||||||
*.ast
|
*.ast
|
||||||
simple
|
|
||||||
complex
|
|
||||||
program
|
program
|
||||||
|
examples/foundation/foundation
|
||||||
|
examples/foundation/ns
|
||||||
|
examples/simple/simple
|
||||||
|
examples/simple/simple/ClassOne
|
||||||
|
|
|
@ -212,6 +212,8 @@ func Parse(fullline string) Node {
|
||||||
return parseObjCProtocol(line)
|
return parseObjCProtocol(line)
|
||||||
case "ObjCPropertyDecl":
|
case "ObjCPropertyDecl":
|
||||||
return parseObjCPropertyDecl(line)
|
return parseObjCPropertyDecl(line)
|
||||||
|
case "ObjCTypeParamDecl":
|
||||||
|
return parseObjCTypeParamDecl(line)
|
||||||
case "OffsetOfExpr":
|
case "OffsetOfExpr":
|
||||||
return parseOffsetOfExpr(line)
|
return parseOffsetOfExpr(line)
|
||||||
case "PackedAttr":
|
case "PackedAttr":
|
||||||
|
|
80
ast/objc_type_param_decl.go
Normal file
80
ast/objc_type_param_decl.go
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package ast
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ObjCTypeParamDecl is node represents a parameter of variable declaration.
|
||||||
|
type ObjCTypeParamDecl struct {
|
||||||
|
Addr Address
|
||||||
|
Pos Position
|
||||||
|
Position2 string
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
Type2 string
|
||||||
|
IsReferenced bool
|
||||||
|
IsCovariant bool
|
||||||
|
IsBounded bool
|
||||||
|
ChildNodes []Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseObjCTypeParamDecl(line string) *ObjCTypeParamDecl {
|
||||||
|
groups := groupsFromRegex(
|
||||||
|
`<(?P<position>.*)>
|
||||||
|
(?P<position2> [^ ]+:[\d:]+)?
|
||||||
|
(?P<referenced> referenced)?
|
||||||
|
(?P<name> \w+)?
|
||||||
|
(?P<covariant> covariant)?
|
||||||
|
(?P<bounded> bounded)?
|
||||||
|
'(?P<type>.*?)'
|
||||||
|
(?P<type2>:'.*?')?
|
||||||
|
`,
|
||||||
|
line,
|
||||||
|
)
|
||||||
|
|
||||||
|
type2 := groups["type2"]
|
||||||
|
if type2 != "" {
|
||||||
|
type2 = type2[2 : len(type2)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Index(groups["position"], "<invalid sloc>") > -1 {
|
||||||
|
groups["position"] = "<invalid sloc>"
|
||||||
|
groups["position2"] = "<invalid sloc>"
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ObjCTypeParamDecl{
|
||||||
|
Addr: ParseAddress(groups["address"]),
|
||||||
|
Pos: NewPositionFromString(groups["position"]),
|
||||||
|
Position2: strings.TrimSpace(groups["position2"]),
|
||||||
|
Name: strings.TrimSpace(groups["name"]),
|
||||||
|
Type: groups["type"],
|
||||||
|
Type2: type2,
|
||||||
|
IsReferenced: len(groups["referenced"]) > 0,
|
||||||
|
IsCovariant: len(groups["covariant"]) > 0,
|
||||||
|
IsBounded : len(groups["bounded"]) > 0,
|
||||||
|
ChildNodes: []Node{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChild adds a new child node. Child nodes can then be accessed with the
|
||||||
|
// Children attribute.
|
||||||
|
func (n *ObjCTypeParamDecl) AddChild(node Node) {
|
||||||
|
n.ChildNodes = append(n.ChildNodes, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address returns the numeric address of the node. See the documentation for
|
||||||
|
// the Address type for more information.
|
||||||
|
func (n *ObjCTypeParamDecl) Address() Address {
|
||||||
|
return n.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Children returns the child nodes. If this node does not have any children or
|
||||||
|
// this node does not support children it will always return an empty slice.
|
||||||
|
func (n *ObjCTypeParamDecl) Children() []Node {
|
||||||
|
return n.ChildNodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position returns the position in the original source code.
|
||||||
|
func (n *ObjCTypeParamDecl) Position() Position {
|
||||||
|
return n.Pos
|
||||||
|
}
|
18
examples/foundation/main.go
Normal file
18
examples/foundation/main.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gitlab.wow.st/gmp/nswrap/examples/foundation/ns"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("Started")
|
||||||
|
n := ns.StringWithUTF8String(ns.CharFromString("hi there"))
|
||||||
|
c := n.CapitalizedString()
|
||||||
|
gstring := c.UTF8String().String()
|
||||||
|
fmt.Println(gstring)
|
||||||
|
fmt.Println("ok")
|
||||||
|
}
|
||||||
|
|
10
examples/foundation/nswrap.toml
Normal file
10
examples/foundation/nswrap.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
InputFiles = [
|
||||||
|
"/System/Library/Frameworks/Foundation.framework/Headers/NSDictionary.h",
|
||||||
|
"/System/Library/Frameworks/Foundation.framework/Headers/NSString.h",
|
||||||
|
]
|
||||||
|
Classes = [
|
||||||
|
"NSString",
|
||||||
|
"NSDictionary",
|
||||||
|
]
|
||||||
|
SysImports = [ "Foundation/Foundation.h" ]
|
||||||
|
Pragma = [ 'clang diagnostic ignored "-Wformat-security"' ]
|
103
examples/simple/ClassOne/main.go
Normal file
103
examples/simple/ClassOne/main.go
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package ClassOne
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -x objective-c
|
||||||
|
#cgo LDFLAGS: -framework Foundation
|
||||||
|
|
||||||
|
#import "simple.h"
|
||||||
|
|
||||||
|
ClassOne*
|
||||||
|
NewClassOne() {
|
||||||
|
return [ClassOne alloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ClassOne_geti1(void* obj) {
|
||||||
|
return [(id)obj geti1];
|
||||||
|
}
|
||||||
|
int*
|
||||||
|
ClassOne_getp1(void* obj) {
|
||||||
|
return [(id)obj getp1];
|
||||||
|
}
|
||||||
|
int
|
||||||
|
ClassOne_hi1(void* obj, struct stru in) {
|
||||||
|
return [(id)obj hi1:in];
|
||||||
|
}
|
||||||
|
int
|
||||||
|
ClassOne_hi2(void* obj, void* in) {
|
||||||
|
return [(id)obj hi2:in];
|
||||||
|
}
|
||||||
|
struct stru
|
||||||
|
ClassOne_nstru1(void* obj) {
|
||||||
|
return [(id)obj nstru1];
|
||||||
|
}
|
||||||
|
struct stru*
|
||||||
|
ClassOne_nstru2(void* obj) {
|
||||||
|
return [(id)obj nstru2];
|
||||||
|
}
|
||||||
|
ClassOne*
|
||||||
|
ClassOne_init(void* obj) {
|
||||||
|
return [(id)obj init];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//ClassOne*
|
||||||
|
type ClassOne struct { NSObject }
|
||||||
|
|
||||||
|
//NSObject*
|
||||||
|
type NSObject struct { ptr unsafe.Pointer }
|
||||||
|
|
||||||
|
//int
|
||||||
|
type Int C.int
|
||||||
|
|
||||||
|
//struct stru
|
||||||
|
type Stru C.struct_stru
|
||||||
|
|
||||||
|
func NewClassOne() *ClassOne {
|
||||||
|
ret := &ClassOne{}
|
||||||
|
ret.ptr = unsafe.Pointer(C.NewClassOne())
|
||||||
|
//ret = ret.Init()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ClassOne) Geti1() Int {
|
||||||
|
return (Int)(C.ClassOne_geti1(o.ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (o *ClassOne) Getp1() *Int {
|
||||||
|
return (*Int)(unsafe.Pointer(C.ClassOne_getp1(o.ptr)))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (o *ClassOne) Hi1(in Stru) Int {
|
||||||
|
return (Int)(C.ClassOne_hi1(o.ptr, (C.struct_stru)(in)))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (o *ClassOne) Hi2(in *Stru) Int {
|
||||||
|
return (Int)(C.ClassOne_hi2(o.ptr, unsafe.Pointer(in)))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (o *ClassOne) Nstru1() Stru {
|
||||||
|
return (Stru)(C.ClassOne_nstru1(o.ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (o *ClassOne) Nstru2() *Stru {
|
||||||
|
return (*Stru)(unsafe.Pointer(C.ClassOne_nstru2(o.ptr)))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (o *ClassOne) Init() *ClassOne {
|
||||||
|
ret := &ClassOne{}
|
||||||
|
ret.ptr = unsafe.Pointer(C.ClassOne_init(o.ptr))
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
22
examples/simple/ClassOne/simple.h
Normal file
22
examples/simple/ClassOne/simple.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
struct stru {int a,b;};
|
||||||
|
|
||||||
|
@interface ClassOne : NSObject
|
||||||
|
{
|
||||||
|
int i1;
|
||||||
|
int *p1;
|
||||||
|
int a1[2];
|
||||||
|
int (*f)();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ClassOne*) init;
|
||||||
|
- (int) geti1;
|
||||||
|
- (int *) getp1;
|
||||||
|
- (int (*)()) getf1;
|
||||||
|
- (int) hi1:(struct stru)in;
|
||||||
|
- (int) hi2:(struct stru*)in;
|
||||||
|
- (struct stru) nstru1;
|
||||||
|
- (struct stru*) nstru2;
|
||||||
|
@end
|
||||||
|
|
59
examples/simple/ClassOne/simple.m
Normal file
59
examples/simple/ClassOne/simple.m
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#import "simple.h"
|
||||||
|
|
||||||
|
@implementation ClassOne
|
||||||
|
|
||||||
|
- (ClassOne*) init
|
||||||
|
{
|
||||||
|
ClassOne *ret;
|
||||||
|
ret = [ClassOne alloc];
|
||||||
|
ret->i1 = 12;
|
||||||
|
ret->p1 = malloc(sizeof(int));
|
||||||
|
*ret->p1 = 16;
|
||||||
|
ret->a1[0] = 4;
|
||||||
|
ret ->a1[1] = 5;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) geti1
|
||||||
|
{
|
||||||
|
return i1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int *) getp1
|
||||||
|
{
|
||||||
|
return p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int (*)()) getf1
|
||||||
|
{
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) hi1:(struct stru)in
|
||||||
|
{
|
||||||
|
return in.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) hi2:(struct stru*)in
|
||||||
|
{
|
||||||
|
return in->a;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (struct stru) nstru1
|
||||||
|
{
|
||||||
|
struct stru ret;
|
||||||
|
ret.a = 7;
|
||||||
|
ret.b = 8;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
- (struct stru*) nstru2
|
||||||
|
{
|
||||||
|
struct stru* ret;
|
||||||
|
ret = malloc(sizeof(struct stru));
|
||||||
|
ret->a = 9;
|
||||||
|
ret->b = 10;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
21
examples/simple/main.go
Normal file
21
examples/simple/main.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gitlab.wow.st/gmp/nswrap/examples/simple/ClassOne"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
o := ClassOne.NewClassOne().Init()
|
||||||
|
fmt.Println("i1 = ",o.Geti1())
|
||||||
|
fmt.Println("p1 = ",o.Getp1())
|
||||||
|
p1 := o.Getp1()
|
||||||
|
fmt.Println("*p1 = ", *p1)
|
||||||
|
*p1 = 17
|
||||||
|
fmt.Println("*p1 = ", *o.Getp1())
|
||||||
|
ns := o.Nstru1()
|
||||||
|
np := o.Nstru2()
|
||||||
|
fmt.Println(o.Hi1(ns))
|
||||||
|
fmt.Println(o.Hi2(np))
|
||||||
|
}
|
||||||
|
|
4
examples/simple/nswrap.toml
Normal file
4
examples/simple/nswrap.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Package = "ClassOne"
|
||||||
|
InputFiles = [ "ClassOne/simple.h" ]
|
||||||
|
Classes = [ "ClassOne" ]
|
||||||
|
Imports = [ "simple.h" ]
|
15
main.go
15
main.go
|
@ -9,12 +9,14 @@ import (
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"gitlab.wow.st/gmp/nswrap/ast"
|
"gitlab.wow.st/gmp/nswrap/ast"
|
||||||
|
"gitlab.wow.st/gmp/nswrap/types"
|
||||||
"gitlab.wow.st/gmp/nswrap/wrap"
|
"gitlab.wow.st/gmp/nswrap/wrap"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Debug = false
|
var Debug = false
|
||||||
|
|
||||||
type conf struct {
|
type conf struct {
|
||||||
|
Package string
|
||||||
InputFiles []string
|
InputFiles []string
|
||||||
Classes []string
|
Classes []string
|
||||||
Imports []string
|
Imports []string
|
||||||
|
@ -163,17 +165,22 @@ func Start() (err error) {
|
||||||
|
|
||||||
// build tree
|
// build tree
|
||||||
tree := buildTree(nodes, 0)
|
tree := buildTree(nodes, 0)
|
||||||
unit := tree[0]
|
//unit := tree[0]
|
||||||
w := wrap.NewWrapper(Debug)
|
w := wrap.NewWrapper(Debug)
|
||||||
|
w.Package = Config.Package
|
||||||
w.Import(Config.Imports)
|
w.Import(Config.Imports)
|
||||||
w.SysImport(Config.SysImports)
|
w.SysImport(Config.SysImports)
|
||||||
w.Pragma(Config.Pragma)
|
w.Pragma(Config.Pragma)
|
||||||
for _, n := range(unit.Children()) {
|
for _, u := range tree {
|
||||||
|
for _, n := range(u.Children()) {
|
||||||
switch x := n.(type) {
|
switch x := n.(type) {
|
||||||
case *ast.ObjCInterfaceDecl:
|
case *ast.ObjCInterfaceDecl:
|
||||||
w.AddInterface(x)
|
w.AddInterface(x)
|
||||||
case *ast.ObjCCategoryDecl:
|
case *ast.ObjCCategoryDecl:
|
||||||
w.AddCategory(x)
|
w.AddCategory(x)
|
||||||
|
case *ast.TypedefDecl:
|
||||||
|
types.AddTypedef(x.Name,x.Type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Wrap(Config.Classes)
|
w.Wrap(Config.Classes)
|
||||||
|
@ -181,8 +188,8 @@ func Start() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if _, err := toml.DecodeFile("conf.toml",&Config); err != nil {
|
if _, err := toml.DecodeFile("nswrap.toml",&Config); err != nil {
|
||||||
fmt.Printf("Cannot open config file conf.toml.\n")
|
fmt.Printf("Cannot open config file nswrap.toml.\n")
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
if err := Start(); err != nil {
|
if err := Start(); err != nil {
|
||||||
|
|
|
@ -102,11 +102,6 @@ func NodeNamed(k string, p Parser) Parser {
|
||||||
|
|
||||||
// Combinators
|
// Combinators
|
||||||
|
|
||||||
//Id is the identity parser
|
|
||||||
func Id(s string, n *Node) (string, *Node) {
|
|
||||||
return s,n
|
|
||||||
}
|
|
||||||
|
|
||||||
//Opt optionally runs a Parser, returning the input node if it fails
|
//Opt optionally runs a Parser, returning the input node if it fails
|
||||||
func Opt(p Parser) Parser {
|
func Opt(p Parser) Parser {
|
||||||
return func(s string, n *Node) (string, *Node) {
|
return func(s string, n *Node) (string, *Node) {
|
||||||
|
|
|
@ -12,6 +12,12 @@ var super map[string]string
|
||||||
//go struct.
|
//go struct.
|
||||||
var wrapped map[string]bool
|
var wrapped map[string]bool
|
||||||
|
|
||||||
|
//TypeParameters maps, for each class, a TypedefName to a type, representing
|
||||||
|
//the Objective-C type parameters for that class
|
||||||
|
var TypeParameters map[string]map[string]string
|
||||||
|
|
||||||
|
var Typedefs map[string]*Type
|
||||||
|
|
||||||
func Super(c string) string {
|
func Super(c string) string {
|
||||||
if super == nil {
|
if super == nil {
|
||||||
super = make(map[string]string)
|
super = make(map[string]string)
|
||||||
|
@ -26,6 +32,23 @@ func SetSuper(c, p string) {
|
||||||
super[c] = p
|
super[c] = p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetTypeParam(c, n, t string) {
|
||||||
|
if TypeParameters == nil {
|
||||||
|
TypeParameters = make(map[string]map[string]string)
|
||||||
|
}
|
||||||
|
if TypeParameters[c] == nil {
|
||||||
|
TypeParameters[c] = make(map[string]string)
|
||||||
|
}
|
||||||
|
TypeParameters[c][n] = t
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddTypedef(n,t string) {
|
||||||
|
if Typedefs == nil {
|
||||||
|
Typedefs = make(map[string]*Type)
|
||||||
|
}
|
||||||
|
Typedefs[n] = NewTypeFromString(t,"")
|
||||||
|
}
|
||||||
|
|
||||||
type Type struct {
|
type Type struct {
|
||||||
Node *Node
|
Node *Node
|
||||||
Class string
|
Class string
|
||||||
|
@ -42,12 +65,22 @@ func NewType(n *Node, c string) *Type {
|
||||||
|
|
||||||
func NewTypeFromString(t,c string) *Type {
|
func NewTypeFromString(t,c string) *Type {
|
||||||
n,err := Parse(t)
|
n,err := Parse(t)
|
||||||
if n.CtypeSimplified() == "id" {
|
if n.IsId() {
|
||||||
|
//if n.CtypeSimplified() == "id" {
|
||||||
n,err = Parse("NSObject*")
|
n,err = Parse("NSObject*")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Type{}
|
return &Type{}
|
||||||
}
|
}
|
||||||
|
if TypeParameters[c] != nil {
|
||||||
|
recur := false
|
||||||
|
for k,v := range TypeParameters[c] {
|
||||||
|
recur = n.renameTypedefs(k,v)
|
||||||
|
}
|
||||||
|
if recur {
|
||||||
|
return NewTypeFromString(n.Ctype(),c)
|
||||||
|
}
|
||||||
|
}
|
||||||
return &Type{
|
return &Type{
|
||||||
Node: n,
|
Node: n,
|
||||||
Class: c,
|
Class: c,
|
||||||
|
@ -117,19 +150,21 @@ func (t *Type) CTypeAttrib() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) _CType(attrib bool) string {
|
func (t *Type) _CType(attrib bool) string {
|
||||||
|
//if !attrib && c.ctype != "" ... FIXME?
|
||||||
if t.ctype != "" { // cache
|
if t.ctype != "" { // cache
|
||||||
return t.ctype
|
return t.ctype
|
||||||
}
|
}
|
||||||
var ct string
|
var ct string
|
||||||
if attrib {
|
if attrib {
|
||||||
ct = t.Node.Ctype()
|
ignore := map[string]bool { "GenericList": true }
|
||||||
|
ct = t.Node._Ctype(ignore)
|
||||||
} else {
|
} else {
|
||||||
ct = t.Node.CtypeSimplified()
|
ct = t.Node.CtypeSimplified()
|
||||||
}
|
}
|
||||||
ct = strings.ReplaceAll(ct,"instancename",t.Class)
|
ct = strings.ReplaceAll(ct,"instancename",t.Class)
|
||||||
ct = strings.ReplaceAll(ct,"instancetype",t.Class + " *")
|
ct = strings.ReplaceAll(ct,"instancetype",t.Class + " *")
|
||||||
if len(ct) > 1 && ct[:2] == "id" {
|
if len(ct) > 1 && ct[:2] == "id" {
|
||||||
ct = "NSObject *" + ct[2:]
|
ct = "NSObject*" + ct[2:]
|
||||||
}
|
}
|
||||||
if len(ct) > 11 {
|
if len(ct) > 11 {
|
||||||
if ct[:12] == "instancename" { ct = t.Class + ct[12:] }
|
if ct[:12] == "instancename" { ct = t.Class + ct[12:] }
|
||||||
|
@ -148,14 +183,18 @@ func (t *Type) GoTypeDecl() string {
|
||||||
return t.GoInterfaceDecl()
|
return t.GoInterfaceDecl()
|
||||||
}
|
}
|
||||||
tp := t.BaseType()
|
tp := t.BaseType()
|
||||||
|
if tp.Node.IsId() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
gt := tp.GoType()
|
gt := tp.GoType()
|
||||||
switch gt {
|
switch gt {
|
||||||
case "", "Void":
|
case "", "Void":
|
||||||
return ""
|
return ""
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
|
//%s
|
||||||
type %s %s
|
type %s %s
|
||||||
`,gt,tp.CGoType())
|
`,t.Node.CtypeSimplified(),gt,tp.CGoType())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,12 +209,27 @@ func (t *Type) GoInterfaceDecl() string {
|
||||||
super = "ptr unsafe.Pointer"
|
super = "ptr unsafe.Pointer"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
|
//%s
|
||||||
%stype %s struct { %s }
|
%stype %s struct { %s }
|
||||||
`,x,gt,super)
|
`,t.CTypeAttrib(),x,gt,super)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) IsFunction() bool {
|
||||||
|
if td,ok := Typedefs[t.BaseType().CType()]; ok {
|
||||||
|
return td.IsFunction()
|
||||||
|
}
|
||||||
|
return t.Node.IsFunction()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) IsPointer() bool {
|
||||||
|
if td,ok := Typedefs[t.BaseType().CType()]; ok {
|
||||||
|
return td.IsPointer()
|
||||||
|
}
|
||||||
|
return t.Node.IsPointer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) CToGo(cval string) string { // cast C value to CGo
|
func (t *Type) CToGo(cval string) string { // cast C value to CGo
|
||||||
if t.Node.IsPointer() {
|
if t.IsPointer() {
|
||||||
cval = "unsafe.Pointer(" + cval + ")"
|
cval = "unsafe.Pointer(" + cval + ")"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("(%s)(%s)",t.GoType(),cval)
|
return fmt.Sprintf("(%s)(%s)",t.GoType(),cval)
|
||||||
|
|
|
@ -30,6 +30,7 @@ func AbstractDeclarator(s string, n *Node) (string, *Node) {
|
||||||
Opt(Pointer),
|
Opt(Pointer),
|
||||||
OneOrMore(DirectAbstractDeclarator)),
|
OneOrMore(DirectAbstractDeclarator)),
|
||||||
Pointer,
|
Pointer,
|
||||||
|
Id,
|
||||||
Block,
|
Block,
|
||||||
)(s,n)
|
)(s,n)
|
||||||
}
|
}
|
||||||
|
@ -136,6 +137,14 @@ func NullableAnnotation(s string, n *Node) (string, *Node) {
|
||||||
))(s,n)
|
))(s,n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Id(s string, n *Node) (string, *Node) {
|
||||||
|
return Seq(
|
||||||
|
NodeNamed("Id",Lit("id")),
|
||||||
|
Opt(TypeQualifierList),
|
||||||
|
Opt(NullableAnnotation),
|
||||||
|
)(s,n)
|
||||||
|
}
|
||||||
|
|
||||||
func Pointer(s string, n *Node) (string, *Node) {
|
func Pointer(s string, n *Node) (string, *Node) {
|
||||||
return Seq(
|
return Seq(
|
||||||
NodeNamed("Pointer",Lit("*")),
|
NodeNamed("Pointer",Lit("*")),
|
||||||
|
|
|
@ -96,7 +96,7 @@ func (n *Node) PointsTo() *Node {
|
||||||
|
|
||||||
//IsPointer returns true if the node is a pointer
|
//IsPointer returns true if the node is a pointer
|
||||||
func (n *Node) IsPointer() bool {
|
func (n *Node) IsPointer() bool {
|
||||||
return n.PointsTo() != nil
|
return n.IsId() || n.PointsTo() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ArrayOf, when called on an array node returns a node describing the type
|
//ArrayOf, when called on an array node returns a node describing the type
|
||||||
|
@ -126,6 +126,13 @@ func (n *Node) IsFunction() bool {
|
||||||
return n.Children[len(n.Children)-1].Kind == "Function"
|
return n.Children[len(n.Children)-1].Kind == "Function"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Node) IsId() bool {
|
||||||
|
if n == nil || len(n.Children) < 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return n.Children[0].Kind == "TypedefName" && n.Children[0].Content == "id"
|
||||||
|
}
|
||||||
|
|
||||||
//BaseType strips off all layers of pointer indirection
|
//BaseType strips off all layers of pointer indirection
|
||||||
func (n *Node) BaseType() *Node {
|
func (n *Node) BaseType() *Node {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
|
|
|
@ -67,6 +67,24 @@ func (n *Node) AddChild(c *Node) *Node {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//returns true if anything gets renamed
|
||||||
|
func (n *Node) renameTypedefs(a,b string) (ret bool) {
|
||||||
|
ret = false
|
||||||
|
if n == nil { return }
|
||||||
|
for i,c := range n.Children {
|
||||||
|
if c.Kind == "TypedefName" && c.Content == a {
|
||||||
|
ret = true
|
||||||
|
n.Children[i] = NewNode("TypedefName", b)
|
||||||
|
n.Children[i].Children = c.Children
|
||||||
|
}
|
||||||
|
if len(c.Children) > 0 {
|
||||||
|
ret2 := c.renameTypedefs(a,b)
|
||||||
|
ret = ret || ret2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Node) CtypeSimplified() string {
|
func (n *Node) CtypeSimplified() string {
|
||||||
ignore := map[string]bool{
|
ignore := map[string]bool{
|
||||||
"NullableAnnotation": true,
|
"NullableAnnotation": true,
|
||||||
|
|
49
wrap/main.go
49
wrap/main.go
|
@ -2,6 +2,8 @@ package wrap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gitlab.wow.st/gmp/nswrap/ast"
|
"gitlab.wow.st/gmp/nswrap/ast"
|
||||||
|
@ -13,6 +15,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Wrapper struct {
|
type Wrapper struct {
|
||||||
|
Package string
|
||||||
Interfaces map[string]Interface
|
Interfaces map[string]Interface
|
||||||
|
|
||||||
cCode strings.Builder // put cGo code here
|
cCode strings.Builder // put cGo code here
|
||||||
|
@ -81,7 +84,7 @@ func (m Method) isVoid() bool {
|
||||||
//hasFunctionParam() returns true if a method has a function as a parameter.
|
//hasFunctionParam() returns true if a method has a function as a parameter.
|
||||||
func (m Method) hasFunctionParam() bool {
|
func (m Method) hasFunctionParam() bool {
|
||||||
for _,p := range m.Parameters {
|
for _,p := range m.Parameters {
|
||||||
if p.Type.Node.IsFunction() {
|
if p.Type.IsFunction() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,6 +227,9 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
//fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name)
|
//fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name)
|
||||||
types.SetSuper(name,x.Name)
|
types.SetSuper(name,x.Name)
|
||||||
}
|
}
|
||||||
|
case *ast.ObjCTypeParamDecl:
|
||||||
|
//fmt.Printf("ObjCTypeParamDecl: %s = %s\n",x.Name,x.Type)
|
||||||
|
types.SetTypeParam(name,x.Name,x.Type)
|
||||||
case *ast.Unknown:
|
case *ast.Unknown:
|
||||||
//fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content)
|
//fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content)
|
||||||
default:
|
default:
|
||||||
|
@ -312,7 +318,7 @@ func (w *Wrapper) processType(tp *types.Type) {
|
||||||
bt := tp.BaseType()
|
bt := tp.BaseType()
|
||||||
if w.Processed[bt.GoType()] { return }
|
if w.Processed[bt.GoType()] { return }
|
||||||
w.Processed[bt.GoType()] = true
|
w.Processed[bt.GoType()] = true
|
||||||
if bt.Node.IsFunction() {
|
if bt.IsFunction() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.goTypes.WriteString(tp.GoTypeDecl())
|
w.goTypes.WriteString(tp.GoTypeDecl())
|
||||||
|
@ -345,17 +351,26 @@ func (c *Char) String() string {
|
||||||
|
|
||||||
|
|
||||||
func (w *Wrapper) Wrap(toproc []string) {
|
func (w *Wrapper) Wrap(toproc []string) {
|
||||||
|
if w.Package == "" { w.Package = "ns" }
|
||||||
|
err := os.MkdirAll(w.Package,0755)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error creating directory '%s'\n%s\n",w.Package,err)
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
of,err := os.Create(path.Join(w.Package,"main.go"))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error opening file %s\n%s\n",path.Join(w.Package,"main.go"),err)
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
fmt.Printf("Writing output to %s\n",path.Join(w.Package,"main.go"))
|
||||||
pInterfaces := map[string]Interface{}
|
pInterfaces := map[string]Interface{}
|
||||||
for _,iface := range toproc {
|
for _,iface := range toproc {
|
||||||
pInterfaces[iface] = w.Interfaces[iface]
|
pInterfaces[iface] = w.Interfaces[iface]
|
||||||
}
|
}
|
||||||
//FIXME: sort pInterfaces
|
//FIXME: sort pInterfaces
|
||||||
for iname,i := range pInterfaces {
|
for _,i := range pInterfaces {
|
||||||
if Debug {
|
|
||||||
fmt.Printf("Interface %s: %d properties, %d methods\n",
|
fmt.Printf("Interface %s: %d properties, %d methods\n",
|
||||||
iname, len(i.Properties), len(i.Methods))
|
i.Name, len(i.Properties), len(i.Methods))
|
||||||
}
|
|
||||||
|
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func New%s() *%s {
|
func New%s() *%s {
|
||||||
|
@ -384,16 +399,14 @@ New%s() {
|
||||||
if Debug {
|
if Debug {
|
||||||
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
|
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
|
||||||
}
|
}
|
||||||
if m.Type.Node.IsFunction() {
|
if m.Type.IsFunction() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if m.hasFunctionParam() {
|
if m.hasFunctionParam() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
gname := strings.Title(m.Name)
|
gname := strings.Title(m.Name)
|
||||||
if m.ClassMethod {
|
if !m.ClassMethod {
|
||||||
gname = i.Name + gname
|
|
||||||
} else {
|
|
||||||
gname = "(o *" + i.Name + ") " + gname
|
gname = "(o *" + i.Name + ") " + gname
|
||||||
}
|
}
|
||||||
cname := i.Name + "_" + m.Name
|
cname := i.Name + "_" + m.Name
|
||||||
|
@ -429,10 +442,9 @@ func %s(%s) %s {
|
||||||
}`, cmtype, cname, w.cparamlist(m), cret, cobj, w.objcparamlist(m)))
|
}`, cmtype, cname, w.cparamlist(m), cret, cobj, w.objcparamlist(m)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println(`package main
|
of.WriteString("package " + w.Package + "\n\n")
|
||||||
`)
|
of.WriteString(w.cCode.String())
|
||||||
fmt.Println(w.cCode.String())
|
of.WriteString(`
|
||||||
fmt.Println(`
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
@ -440,7 +452,8 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
`)
|
`)
|
||||||
fmt.Println(w.goTypes.String())
|
of.WriteString(w.goTypes.String())
|
||||||
fmt.Println(w.goHelpers.String())
|
of.WriteString(w.goHelpers.String())
|
||||||
fmt.Println(w.goCode.String())
|
of.WriteString(w.goCode.String())
|
||||||
|
of.Close()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user