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:
parent
49fd749fe3
commit
8de87cddb7
|
@ -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")
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
|
|
|
@ -42,13 +42,13 @@ func parseObjCMethodDecl(line string) *ObjCMethodDecl {
|
|||
return &ObjCMethodDecl{
|
||||
Addr: ParseAddress(groups["address"]),
|
||||
Pos: NewPositionFromString(groups["position"]),
|
||||
Position2: strings.TrimSpace(groups["position2"]),
|
||||
//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{},
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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{}
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
|
|
|
@ -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{},
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 { }
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 + ")"
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
10
wrap/main.go
10
wrap/main.go
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue
Block a user