Performance improvements (do not parse addresses or locations unless

location tracking is enabled). Allow profiling option. Add some
comments and clean-ups to types/*.go.
This commit is contained in:
Greg 2019-05-11 23:03:56 -04:00
parent 49fd749fe3
commit 8de87cddb7
24 changed files with 132 additions and 219 deletions

View File

@ -8,6 +8,8 @@ import (
"github.com/elliotchance/c2go/util"
)
var TrackPositions bool = false
// Node represents any node in the AST.
type Node interface {
Address() Address
@ -27,6 +29,9 @@ type Address uint64
// ParseAddress returns the integer representation of the hexadecimal address
// (like 0x7f8a1d8ccfd0). If the address cannot be parsed, 0 is returned.
func ParseAddress(address string) Address {
if !TrackPositions {
return 0
}
addr, _ := strconv.ParseUint(address, 0, 64)
return Address(addr)
@ -318,7 +323,6 @@ func groupsFromRegex(rx, line string) map[string]string {
rx = fullRegexp + "[\\s]*$"
re := util.GetRegex(rx)
match := re.FindStringSubmatch(line)
if len(match) == 0 {
panic("could not match regexp with string\n" + rx + "\n" + line + "\n")

View File

@ -20,7 +20,7 @@ func parseBinaryOperator(line string) *BinaryOperator {
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type1"],
Type2: groups["type2"],
//Type2: groups["type2"],
Operator: groups["operator"],
ChildNodes: []Node{},
}

View File

@ -26,7 +26,7 @@ func parseCStyleCastExpr(line string) *CStyleCastExpr {
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type1"],
Type2: groups["type2"],
//Type2: groups["type2"],
Kind: groups["kind"],
ChildNodes: []Node{},
}

View File

@ -27,19 +27,19 @@ func parseEnumConstantDecl(line string) *EnumConstantDecl {
line,
)
type2 := groups["type2"]
/*type2 := groups["type2"]
if type2 != "" {
type2 = type2[2 : len(type2)-1]
}
}*/
return &EnumConstantDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: groups["position2"],
//Position2: groups["position2"],
Referenced: len(groups["referenced"]) > 0,
Name: strings.TrimSpace(groups["name"]),
Type: removeQuotes(groups["type"]),
Type2: type2,
//Type2: type2,
ChildNodes: []Node{},
}
}

View File

@ -26,18 +26,18 @@ func parseEnumDecl(line string) *EnumDecl {
line,
)
type2 := groups["type2"]
/*type2 := groups["type2"]
if type2 != "" {
type2 = type2[2 : len(type2)-1]
}
}*/
return &EnumDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: groups["position2"],
//Position2: groups["position2"],
Name: strings.TrimSpace(groups["name"]),
Type: removeQuotes(groups["type"]),
Type2: type2,
//Type2: type2,
ChildNodes: []Node{},
}
}

View File

@ -26,7 +26,7 @@ func parseObjCCategoryDecl(line string) *ObjCCategoryDecl {
return &ObjCCategoryDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
//Position2: strings.TrimSpace(groups["position2"]),
Name: strings.TrimSpace(groups["name"]),
ChildNodes: []Node{},
}

View File

@ -25,17 +25,10 @@ func parseObjCInterfaceDecl(line string) *ObjCInterfaceDecl {
line,
)
/*fmt.Println(line)
fmt.Println("prev = ",groups["prev"])
fmt.Println("position = ",groups["position"])
fmt.Println("position2 = ",groups["position2"])
fmt.Println("implicit = ",len(groups["implicit"])>0)
fmt.Println("name = ",groups["name"])*/
return &ObjCInterfaceDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
//Position2: strings.TrimSpace(groups["position2"]),
Name: strings.TrimSpace(groups["name"]),
Implicit: len(groups["implicit"])>0,
ChildNodes: []Node{},

View File

@ -42,13 +42,13 @@ func parseObjCMethodDecl(line string) *ObjCMethodDecl {
return &ObjCMethodDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
Implicit: len(groups["implicit"])>0,
//Position2: strings.TrimSpace(groups["position2"]),
Implicit: len(groups["implicit"]) > 0,
ClassMethod: groups["methodtype"] == " +",
Name: parts[0],
Parameters: params,
Type: strings.TrimSpace(groups["type"]),
Type2: strings.TrimSpace(groups["type2"]),
//Type2: strings.TrimSpace(groups["type2"]),
Attr: strings.TrimSpace(groups["attr"]),
ChildNodes: []Node{},
}

View File

@ -33,8 +33,8 @@ func parseObjCPropertyDecl(line string) *ObjCPropertyDecl {
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
Name: strings.TrimSpace(groups["name"]),
Type: strings.TrimSpace(groups["type"]),
Type2: strings.TrimSpace(groups["type2"]),
Type: groups["type"],
//Type2: strings.TrimSpace(groups["type2"]),
Attr: strings.TrimSpace(groups["attr"]),
ChildNodes: []Node{},
}

View File

@ -25,7 +25,7 @@ func parseObjCProtocolDecl(line string) *ObjCProtocolDecl {
return &ObjCProtocolDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
//Position2: strings.TrimSpace(groups["position2"]),
Name: strings.TrimSpace(groups["name"]),
ChildNodes: []Node{},
}

View File

@ -32,10 +32,10 @@ func parseObjCTypeParamDecl(line string) *ObjCTypeParamDecl {
line,
)
type2 := groups["type2"]
/*type2 := groups["type2"]
if type2 != "" {
type2 = type2[2 : len(type2)-1]
}
}*/
if strings.Index(groups["position"], "<invalid sloc>") > -1 {
groups["position"] = "<invalid sloc>"
@ -45,10 +45,10 @@ func parseObjCTypeParamDecl(line string) *ObjCTypeParamDecl {
return &ObjCTypeParamDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
//Position2: strings.TrimSpace(groups["position2"]),
Name: strings.TrimSpace(groups["name"]),
Type: groups["type"],
Type2: type2,
//Type2: type2,
IsReferenced: len(groups["referenced"]) > 0,
IsCovariant: len(groups["covariant"]) > 0,
IsBounded : len(groups["bounded"]) > 0,

View File

@ -32,23 +32,23 @@ func parseParmVarDecl(line string) *ParmVarDecl {
line,
)
type2 := groups["type2"]
/*type2 := groups["type2"]
if type2 != "" {
type2 = type2[2 : len(type2)-1]
}
}*/
if strings.Index(groups["position"], "<invalid sloc>") > -1 {
/*if strings.Index(groups["position"], "<invalid sloc>") > -1 {
groups["position"] = "<invalid sloc>"
groups["position2"] = "<invalid sloc>"
}
}*/
return &ParmVarDecl{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
//Position2: strings.TrimSpace(groups["position2"]),
Name: strings.TrimSpace(groups["name"]),
Type: groups["type"],
Type2: type2,
//Type2: type2,
IsUsed: len(groups["used"]) > 0,
IsReferenced: len(groups["referenced"]) > 0,
IsRegister: len(groups["register"]) > 0,

View File

@ -33,6 +33,9 @@ func (p Position) GetSimpleLocation() (loc string) {
}
func NewPositionFromString(s string) Position {
if !TrackPositions {
return Position{}
}
re := util.GetRegex(`<invalid sloc>|<scratch space>|<built-in>`)
if re.MatchString(s) || s == "" {
return Position{}

View File

@ -25,7 +25,7 @@ func parseUnavailableAttr(line string) *UnavailableAttr {
return &UnavailableAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
//Position2: strings.TrimSpace(groups["position2"]),
Content: strings.TrimSpace(groups["content"]),
ChildNodes: []Node{},
}

View File

@ -1,7 +1,7 @@
package ast
import (
"strings"
//"strings"
)
// Unknown is node represents an unknown node.
@ -30,7 +30,7 @@ func parseUnknown(name, line string) *Unknown {
Name: name,
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Position2: strings.TrimSpace(groups["position2"]),
//Position2: strings.TrimSpace(groups["position2"]),
Content: groups["content"],
ChildNodes: []Node{},
}

View File

@ -3,10 +3,12 @@ package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"regexp"
"runtime"
"runtime/pprof"
"strings"
"gopkg.in/yaml.v2"
@ -16,8 +18,10 @@ import (
)
var Debug = false
var Profile = false
type conf struct {
Positions bool
Package string
Inputfiles []string
Classes []string
@ -158,9 +162,7 @@ func Start() (err error) {
}
}
// 2. Preprocess NOT DONE
// 3. Generate AST
// Generate AST
cargs := []string{"-xobjective-c", "-Xclang", "-ast-dump",
"-fsyntax-only","-fno-color-diagnostics"}
cargs = append(cargs,Config.Inputfiles...)
@ -185,7 +187,12 @@ func Start() (err error) {
// Converting to nodes
fmt.Printf("Building nodes\n")
nodes := convertLinesToNodesParallel(lines)
if Config.Positions {
ast.TrackPositions = true
}
//NOTE: converting in parallel is slower on my system
//nodes := convertLinesToNodesParallel(lines)
nodes := convertLinesToNodes(lines)
// build tree
fmt.Printf("Assembling tree\n")
@ -231,6 +238,18 @@ func Start() (err error) {
}
func main() {
if Profile {
f1, err := os.Create("cpuprofile.pprof")
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
defer f1.Close()
if err := pprof.StartCPUProfile(f1); err != nil {
log.Fatal("could not start CPU profile: ", err)
}
defer pprof.StopCPUProfile()
}
confbytes, err := ioutil.ReadFile("nswrap.yaml")
if err != nil {
fmt.Printf("Cannot open config file nswrap.yaml. %s\n",err)
@ -244,4 +263,15 @@ func main() {
fmt.Printf("Error: %v\n", err)
os.Exit(-1)
}
if Profile {
f2, err := os.Create("memprofile.pprof")
if err != nil {
log.Fatal("could not create memory profile: ", err)
}
defer f2.Close()
runtime.GC() // get up-to-date statistics
if err := pprof.WriteHeapProfile(f2); err != nil {
log.Fatal("could not write memory profile: ", err)
}
}
}

View File

@ -89,7 +89,7 @@ func app() {
func main() {
//Run our app in an autorelease pool just for fun
go ns.Autorelease(app)
go ns.Autoreleasepool(app)
select { }
}

View File

@ -30,9 +30,12 @@ func updateState(c *ns.CBCentralManager) {
func discoverPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral, d *ns.NSDictionary, rssi *ns.NSNumber) {
fmt.Printf("Did discover peripheral\n")
c.StopScan()
if peripheral != nil {
peripheral.Release()
}
peripheral = p
peripheral.Retain()
c.ConnectPeripheral(p,nil)
c.ConnectPeripheral(peripheral,nil)
}
func connectPeripheral(c *ns.CBCentralManager, p *ns.CBPeripheral) {
@ -106,6 +109,7 @@ func main() {
queue := ns.DispatchQueueCreate(ns.CharWithGoString("st.wow.gitlab.ble"),nil)
cd = ns.BleDelegateAlloc()
cd.CentralManagerDidUpdateStateCallback(updateState)
cd.CentralManagerDidDiscoverPeripheralCallback(discoverPeripheral)
cd.CentralManagerDidConnectPeripheralCallback(connectPeripheral)

View File

@ -1,7 +1,6 @@
package types
import (
//"fmt"
"regexp"
)
@ -17,26 +16,12 @@ func init() {
reservedwords = regexp.MustCompile("^(void|char|short|int|long|float|double|signed|unsigned|_Bool|_Complex|const|restrict|volatile|struct|union|enum)$")
}
//Parser is a function that takes the string to be parsed plus an input Node
//and returns a new Node and the unparsed remainder string. If the parser fails
//to parse anything in the input, it should return a nil Node.
type Parser func(string, *Node) (string, *Node)
// Adders
//Child takes a parser and adds its output node (if non-nil) to the tree.
//FIXME -- broken?
func Child(p Parser) Parser {
return func(s string, n *Node) (string, *Node) {
dbg("Child(%s %p)\n",n.Kind,n)
s2,n2 := p(s,n)
if n2 == nil {
return s,nil
}
if n2 != n {
dbg("Child(%p): AddChild()\n",p)
n.AddChild(n2)
}
return s2,n
}
}
// Adders -- add elements to the Node tree
//ChildOf takes a node and adds results of a parser to it as a child
func ChildOf(ret *Node, p Parser) Parser {
@ -100,9 +85,10 @@ func NodeNamed(k string, p Parser) Parser {
}
}
// Combinators
// Combinators -- combine one or more Parsers into a new Parser.
//Opt optionally runs a Parser, returning the input node if it fails
//Opt optionally runs a Parser, returning the input Node (instead of nil)
//if it fails
func Opt(p Parser) Parser {
return func(s string, n *Node) (string, *Node) {
s2,n2 := p(s,n)
@ -127,29 +113,6 @@ func OneOf(ps ...Parser) Parser {
}
}
//Doesn't work? May have side effects that do not get unwound.
func Longest(ps ...Parser) Parser {
dbg("Longest(%p)\n",ps)
return func(s string, n *Node) (string, *Node) {
ss := make([]string,len(ps))
ns := make([]*Node,len(ps))
//An arbitrarily large number so I don't have to import "math"
minrem := 10000
mini := 0
for i,p := range ps {
ss[i],ns[i] = p(s,n)
if ns[i] != nil && len(ss[i]) < minrem {
minrem = len(ss[i])
mini = i
}
}
if minrem < 10000 {
return ss[mini],ns[mini]
}
return s,nil
}
}
//Seq applies parsers in sequence, adding results as children to the input
//node. Returns nil and the input string unless the entire sequence succeeds
func Seq(ps ...Parser) Parser {
@ -172,7 +135,8 @@ func Seq(ps ...Parser) Parser {
return Children(p)
}
//Like Seq but subsequent children are nested inside their earlier siblings.
//Nest is like Seq but subsequent children are nested inside their earlier
//siblings.
func Nest(ps ...Parser) Parser {
dbg("Nest(%p)\n",ps)
p := func(s string, n *Node) (string, *Node) {
@ -212,32 +176,41 @@ func ZeroOrMore(p Parser) Parser {
return Children(ret)
}
//OneOrMore is ZeroOrMore, but fails (returns nil) if the input parser does
//not match any elements.
func OneOrMore(p Parser) Parser {
return Seq(p,ZeroOrMore(p))
}
//Parenthesized matches the input parser surrounded by literal parenthesis.
func Parenthesized(p Parser) Parser {
return Children(Seq(Lit("("),p,Lit(")")))
}
//Bracketed matches the input parser surrounded by literal square brackets.
func Bracketed(p Parser) Parser {
return Seq(Lit("["),p,Lit("]"))
}
//AngBracketed matches the input parser surrounded by literal angled brackets.
func AngBracketed(p Parser) Parser {
return Children(Seq(Lit("<"),p,Lit(">")))
}
//CurlyBracketed matches the input parser surrounded by literal curly brackets.
func CurlyBracketed(p Parser) Parser {
return Children(Seq(Lit("{"),p,Lit("}")))
}
// Recognizers
// Recognizers -- these functions return parsers that match tokens in the input
// stream. There is no separate tokenizer.
//Word matches an element with a word boundary after its end
func Word(f string) Parser {
return Lit(f,true)
}
//Lit matches a literal string
func Lit(f string, ws ...bool) Parser {
word := false
if len(ws) > 0 {
@ -261,6 +234,7 @@ func Lit(f string, ws ...bool) Parser {
}
}
//Regexp matches a regular expression at the beginning of the input string
func Regexp(f string) Parser {
f = "^" + f
r := regexp.MustCompile(f)

View File

@ -33,7 +33,6 @@ var TypeParameters map[string]map[string]string
var typedefs map[string]*Type
func (t *Type) Typedef() *Type {
//return typedefs[t.BaseType().CType()]
return typedefs[t.CType()]
}
@ -78,7 +77,6 @@ func AddTypedef(n,t string) {
type Type struct {
Node *Node
Class string
ctype string
Variadic bool
}
@ -96,7 +94,7 @@ func clean(n *Node,c string) (*Node,bool) {
}
ret := NewNode(n.Kind,n.Content)
ret.Children = n.Children
//fmt.Printf("clean(%s,%s)\n",n.Ctype(),c)
//fmt.Printf("clean(%s,%s)\n",n.CType(),c)
recur := false
if TypeParameters[c] != nil {
for k,v := range TypeParameters[c] {
@ -127,7 +125,7 @@ func NewTypeFromString(t,c string) *Type {
}
if n2,ok := clean(n, c); ok {
//found type parameters, re-parse
return NewTypeFromString(n2.Ctype(),c)
return NewTypeFromString(n2.CType(),c)
}
return &Type{
Node: n,
@ -216,24 +214,16 @@ func (t *Type) _CType(attrib bool) string {
//fmt.Println("nil sent to _CType()")
return ""
}
//if !attrib && t.ctype != "" { // cache
// return t.ctype
//}
var ct string
if attrib {
ignore := map[string]bool { "GenericList": true }
ct = t.Node._Ctype(ignore)
ct = t.Node._CType(ignore)
} else {
ct = t.Node.CtypeSimplified()
ct = t.Node.CTypeSimplified()
}
ct = r_id.ReplaceAllString(ct,"NSObject*")
ct = r_instancename.ReplaceAllString(ct,t.Class)
ct = r_instancetype.ReplaceAllString(ct,t.Class + "*")
if attrib {
t._CType(false)
} else {
t.ctype = ct
}
return ct
}
@ -295,7 +285,7 @@ func (t *Type) IsFunctionPtr() bool {
if td := t.Typedef(); td != nil {
return td.IsFunctionPtr()
}
for pt := t.PointsTo(); pt != nil; pt = pt.PointsTo() {
if pt := t.PointsTo(); pt != nil {
return pt.IsFunction()
}
return false
@ -326,7 +316,8 @@ func (t *Type) IsPointer() bool {
return t.Node.IsPointer()
}
func (t *Type) CToGo(cval string) string { // cast C value to CGo
// cast C value to CGo
func (t *Type) CToGo(cval string) string {
if t.IsPointer() {
cval = "unsafe.Pointer(" + cval + ")"
}
@ -334,7 +325,7 @@ func (t *Type) CToGo(cval string) string { // cast C value to CGo
}
// Call a C function from Go with a given return type and parameter types
func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type, fun bool) string {
if rtype == nil {
fmt.Println("nil sent to GoToC")
return ""
@ -367,7 +358,7 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
switch {
case pt.Variadic:
p = "unsafe.Pointer(&" + p + ")"
case pt.IsPointer():
case pt.IsPointer() && !fun:
p = "unsafe.Pointer(" + pn + ")"
default:
p = "(" + pt.CGoType() + ")(" + pn + ")"

View File

@ -1,85 +1,6 @@
package types
/* Parsers for recognizing type names in C/Objective-C
type-name:
specifier-qualifier-list abstract-declarator<opt>
abstract-declarator:
pointer
pointer<opt> direct-abstract-declarator
direct-abstract-declarator:
( abstract-declarator )
direct-abstract-declarator<opt> [ type-qualifier-list<opt> assignment-expression<opt> ]
direct-abstract-declarator<opt> [ static type-qualifier-list<opt> assignment-expression ]
direct-abstract-declarator<opt> [ type-qualifier-list static assignment-expression ]
direct-abstract-declarator<opt> [ * ]
direct-abstract-declarator<opt> ( parameter-type-list<opt> )
pointer:
* type-qualifier-list<opt>
* type-qualifier-list<opt> pointer
parameter-type-list:
parameter-list
parameter-list , ...
parameter-list:
parameter-declaration
parameter-list , parameter-declaration
parameter-declaration:
declaration-specifiers declarator
declaration-specifiers abstract-declarator<opt>
type-qualifier-list:
type-qualifier
type-qualifier-list type-qualifier
specifier-qualifier-list:
type-specifier specifier-qualifier-list<opt>
type-qualifier specifier-qualifier-list<opt>
type-specifier:
void
char
short
int
long
float
double
signed
unsigned
_Bool
_Complex
struct-or-union-specifier
enum-specifier
typedef-name
type-qualifier:
const
restrict
volatile
struct-or-union-specifier:
// DON'T DO struct-or-union identifier<opt> { struct-declaration-list }
struct-or-union identifier
struct-or-union:
struct
union
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
struct-declarator-list:
struct-declarator
struct-declarator-list , struct-declarator
struct-declarator:
declarator
declarator<opt>: constant-expression
identifier:
identifier-non-digit
identifier identifier-nondigit
identifier digit
identifier-nondigit:
nondigit
universal-character-name
nondigit:
_ [a-zA-Z]
digit:
[0-9]
*/
// A parser to recognize type names in C/Objective-C
import (
"regexp"
@ -94,6 +15,7 @@ func init() {
return !instancetype.MatchString(s) && !instancename.MatchString(s)
}
//memoize the TypeName function for performance
cache := map[string]*Node{}
TypeName = func(s string, n *Node) (string, *Node) {
if n2,ok := cache[s]; ok {
@ -105,6 +27,8 @@ func init() {
}
return s2,n2
}
//for debug purposes, the following line can be uncommented, which will
//memoization memoization
//TypeName = _TypeName
}
@ -120,7 +44,6 @@ func AbstractDeclarator(s string, n *Node) (string, *Node) {
Opt(Pointer),
OneOrMore(DirectAbstractDeclarator)),
Pointer,
//Id,
Block,
)(s,n)
}
@ -227,14 +150,6 @@ func NullableAnnotation(s string, n *Node) (string, *Node) {
))(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) {
return Seq(
NodeNamed("Pointer",Lit("*")),
@ -280,9 +195,7 @@ func TypeSpecifier(s string, n *Node) (string, *Node) {
Word("unsigned"),
Word("_Bool"),
Word("_Complex"),
//StructOrUnionSpecifier,
EnumSpecifier,
//TypedefName,
))(s,n)
}

View File

@ -36,15 +36,15 @@ func Parse(s string) (*Node, error) {
}
//Evaluate a node to determine if it is a pointer or array
func (n *Node) isAbstract(k string) bool {
if n.stripAbstract(k) == nil {
func (n *Node) isIndirect(k string) bool {
if n.stripIndirect(k) == nil {
return false
}
return true
}
//Strip one level of pointer or array indirection from a node
func (n *Node) stripAbstract(k string) *Node {
func (n *Node) stripIndirect(k string) *Node {
if n == nil {
return nil
}
@ -55,14 +55,14 @@ func (n *Node) stripAbstract(k string) *Node {
ret := NewNode(n.Kind)
cs := append([]*Node{},n.Children...)
dbg("stripAbstract(): i = %d\n",i)
dbg("stripIndirect(): i = %d\n",i)
//Scan backwords skipping TypeQualifier and NullableAnnotation tags
for ;i > 0 &&
(cs[i].Kind == "TypeQualifier" ||
cs[i].Kind == "NullableAnnotation") ; i-- { }
if cs[i].Kind == k {
dbg("stripAbstract(): last node is %s\n",k)
dbg("stripIndirect(): last node is %s\n",k)
ret.Children = cs[:i]
return ret
}
@ -92,7 +92,7 @@ func (n *Node) stripAbstract(k string) *Node {
//pointed to. Otherwise returns nil when called on non-pointer types.
func (n *Node) PointsTo() *Node {
dbg("PointsTo()\n")
return n.stripAbstract("Pointer")
return n.stripIndirect("Pointer")
}
//IsPointer returns true if the node is a pointer
@ -108,7 +108,7 @@ func (n *Node) IsPointer() bool {
//non-array types.
func (n *Node) ArrayOf() *Node {
dbg("ArrayOf()\n")
return n.stripAbstract("Array")
return n.stripIndirect("Array")
}
//IsArray returns true if the node is an array

View File

@ -13,6 +13,8 @@ type Node struct {
Children []*Node
}
//NewNode returns a new node of kind k with an optional content string as its
//second parameter.
func NewNode(k string,cs ...string) *Node {
c := ""
if len(cs) > 0 {
@ -56,7 +58,6 @@ func (n *Node) AddChild(c *Node) *Node {
// Skip literals
if c.Kind == "Lit" { return n }
// Do we already have this child? (FIXME: Not needed?)
for _,d := range n.Children {
if c == d {
return n
@ -85,21 +86,21 @@ func (n *Node) renameTypedefs(a,b string) (ret bool) {
return
}
func (n *Node) CtypeSimplified() string {
func (n *Node) CTypeSimplified() string {
ignore := map[string]bool{
"NullableAnnotation": true,
"KindQualifier": true,
"TypeQualifier": true,
"GenericList": true,
}
return n._Ctype(ignore)
return n._CType(ignore)
}
func (n *Node) Ctype() string {
return n._Ctype(map[string]bool{})
func (n *Node) CType() string {
return n._CType(map[string]bool{})
}
func (n *Node) _Ctype(ignore map[string]bool) string {
func (n *Node) _CType(ignore map[string]bool) string {
if n == nil || ignore[n.Kind] {
return ""
}
@ -108,7 +109,7 @@ func (n *Node) _Ctype(ignore map[string]bool) string {
ret := []string{}
if n == nil { return ret }
for _,c := range n.Children {
if x := c._Ctype(ignore); x != "" {
if x := c._CType(ignore); x != "" {
ret = append(ret, x)
}
}

View File

@ -659,7 +659,7 @@ func (o *NSAutoreleasePool) Init() *NSAutoreleasePool {
return (*NSAutoreleasePool)(unsafe.Pointer(C.NSAutoreleasePool_init(o.Ptr())))
}
func Autorelease(f func()) {
func Autoreleasepool(f func()) {
pool := NSAutoreleasePoolAlloc().Init()
f()
pool.Drain()
@ -777,7 +777,7 @@ func %s%s(%s) %s {
`,vn,w.Vaargs,vn,vn))
}
w.goCode.WriteString(` ` +
types.GoToC(cname,ns,m.Type,tps) + "\n}\n")
types.GoToC(cname,ns,m.Type,tps,fun) + "\n}\n")
cret := ""
if !m.isVoid() {
@ -936,7 +936,7 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
} else {
pm := m.Parameters[0]
w.processType(pm.Type)
parms = fmt.Sprintf(":(%s)%s",pm.Type.Node.Ctype(),pm.Vname)
parms = fmt.Sprintf(":(%s)%s",pm.Type.Node.CType(),pm.Vname)
vnames[i][1] = pm.Vname
gtypes[i][0] = pm.Type.GoType()
if pm.Type.IsPointer() {
@ -948,7 +948,7 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
for j := 1; j < len(m.Parameters); j++ {
pm := m.Parameters[j]
w.processType(pm.Type)
parms = parms + fmt.Sprintf(" %s:(%s)%s",pm.Pname,pm.Type.Node.Ctype(),pm.Vname)
parms = parms + fmt.Sprintf(" %s:(%s)%s",pm.Pname,pm.Type.Node.CType(),pm.Vname)
vnames[i][j+1] = pm.Vname
gtypes[i][j] = pm.Type.GoType()
var getp string
@ -960,7 +960,7 @@ func (w *Wrapper) ProcessDelegate(dname string, ps []string) {
getypes[i][j+1] = getp
}
methprotos[i] = fmt.Sprintf(
`- (%s)%s%s;`,m.Type.Node.Ctype(),m.Name,parms)
`- (%s)%s%s;`,m.Type.Node.CType(),m.Name,parms)
if x := m.Type.GoType(); x == "Void" {
grtypes[i] = ""
} else {