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