Rename to nswrap, put configuration in a toml file, allow imports
and sysimports.
This commit is contained in:
parent
ead1623d4b
commit
009a974a1a
187
main.go
187
main.go
|
@ -1,39 +1,27 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gitlab.wow.st/gmp/clast/ast"
|
"github.com/BurntSushi/toml"
|
||||||
"gitlab.wow.st/gmp/clast/wrap"
|
"gitlab.wow.st/gmp/nswrap/ast"
|
||||||
|
"gitlab.wow.st/gmp/nswrap/wrap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProgramArgs struct {
|
var Debug = false
|
||||||
verbose bool
|
|
||||||
ast bool
|
|
||||||
inputFiles []string
|
|
||||||
clangFlags []string
|
|
||||||
outputFile string
|
|
||||||
packageName string
|
|
||||||
|
|
||||||
// A private option to output the Go as a *_test.go file.
|
type conf struct {
|
||||||
outputAsTest bool
|
InputFiles []string
|
||||||
|
Classes []string
|
||||||
|
Imports []string
|
||||||
|
SysImports []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultProgramArgs default value of ProgramArgs
|
var Config conf
|
||||||
func DefaultProgramArgs() ProgramArgs {
|
|
||||||
return ProgramArgs{
|
|
||||||
verbose: false,
|
|
||||||
ast: false,
|
|
||||||
packageName: "main",
|
|
||||||
clangFlags: []string{},
|
|
||||||
outputAsTest: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readAST(data []byte) []string {
|
func readAST(data []byte) []string {
|
||||||
return strings.Split(string(data), "\n")
|
return strings.Split(string(data), "\n")
|
||||||
|
@ -143,17 +131,9 @@ func buildTree(nodes []treeNode, depth int) []ast.Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start begins transpiling an input file.
|
// Start begins transpiling an input file.
|
||||||
func Start(args ProgramArgs) (err error) {
|
func Start() (err error) {
|
||||||
if args.verbose {
|
|
||||||
fmt.Println("Start tanspiling ...")
|
|
||||||
}
|
|
||||||
|
|
||||||
if os.Getenv("GOPATH") == "" {
|
|
||||||
return fmt.Errorf("The $GOPATH must be set")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Compile it first (checking for errors)
|
// 1. Compile it first (checking for errors)
|
||||||
for _, in := range args.inputFiles {
|
for _, in := range Config.InputFiles {
|
||||||
_, err := os.Stat(in)
|
_, err := os.Stat(in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Input file %s is not found", in)
|
return fmt.Errorf("Input file %s is not found", in)
|
||||||
|
@ -163,12 +143,9 @@ func Start(args ProgramArgs) (err error) {
|
||||||
// 2. Preprocess NOT DONE
|
// 2. Preprocess NOT DONE
|
||||||
|
|
||||||
// 3. Generate JSON from AST
|
// 3. Generate JSON from AST
|
||||||
if args.verbose {
|
|
||||||
fmt.Println("Running clang for AST tree...")
|
|
||||||
}
|
|
||||||
cargs := []string{"-xobjective-c", "-Xclang", "-ast-dump",
|
cargs := []string{"-xobjective-c", "-Xclang", "-ast-dump",
|
||||||
"-fsyntax-only","-fno-color-diagnostics"}
|
"-fsyntax-only","-fno-color-diagnostics"}
|
||||||
cargs = append(cargs,args.inputFiles...)
|
cargs = append(cargs,Config.InputFiles...)
|
||||||
astPP, err := exec.Command("clang",cargs...).Output()
|
astPP, err := exec.Command("clang",cargs...).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If clang fails it still prints out the AST, so we have to run it
|
// If clang fails it still prints out the AST, so we have to run it
|
||||||
|
@ -178,32 +155,17 @@ func Start(args ProgramArgs) (err error) {
|
||||||
panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
|
panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.verbose {
|
|
||||||
fmt.Println("Reading clang AST tree...")
|
|
||||||
}
|
|
||||||
lines := readAST(astPP)
|
lines := readAST(astPP)
|
||||||
if args.ast {
|
|
||||||
for _, l := range lines {
|
|
||||||
fmt.Println(l)
|
|
||||||
}
|
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converting to nodes
|
// Converting to nodes
|
||||||
if args.verbose {
|
|
||||||
fmt.Println("Converting to nodes...")
|
|
||||||
}
|
|
||||||
nodes := convertLinesToNodesParallel(lines)
|
nodes := convertLinesToNodesParallel(lines)
|
||||||
|
|
||||||
// build tree
|
// build tree
|
||||||
if args.verbose {
|
|
||||||
fmt.Println("Building tree...")
|
|
||||||
}
|
|
||||||
tree := buildTree(nodes, 0)
|
tree := buildTree(nodes, 0)
|
||||||
unit := tree[0]
|
unit := tree[0]
|
||||||
w := wrap.NewWrapper(*debugFlag)
|
w := wrap.NewWrapper(Debug)
|
||||||
|
w.Import(Config.Imports)
|
||||||
|
w.SysImport(Config.SysImports)
|
||||||
for _, n := range(unit.Children()) {
|
for _, n := range(unit.Children()) {
|
||||||
switch x := n.(type) {
|
switch x := n.(type) {
|
||||||
case *ast.ObjCInterfaceDecl:
|
case *ast.ObjCInterfaceDecl:
|
||||||
|
@ -212,122 +174,17 @@ func Start(args ProgramArgs) (err error) {
|
||||||
w.AddCategory(x)
|
w.AddCategory(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Wrap([]string{"NSString"})
|
w.Wrap(Config.Classes)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type inputDataFlags []string
|
|
||||||
|
|
||||||
func (i *inputDataFlags) String() (s string) {
|
|
||||||
for pos, item := range *i {
|
|
||||||
s += fmt.Sprintf("Flag %d. %s\n", pos, item)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *inputDataFlags) Set(value string) error {
|
|
||||||
*i = append(*i, value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var clangFlags inputDataFlags
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
wrapCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
|
|
||||||
astCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
versionFlag = flag.Bool("v", false, "print the version and exit")
|
|
||||||
wrapCommand = flag.NewFlagSet("wrap", flag.ContinueOnError)
|
|
||||||
verboseFlag = wrapCommand.Bool("V", false, "print progress as comments")
|
|
||||||
debugFlag = wrapCommand.Bool("d", false, "print debug information as comments")
|
|
||||||
outputFlag = wrapCommand.String("o", "", "output Go generated code to the specified file")
|
|
||||||
packageFlag = wrapCommand.String("p", "main", "set the name of the generated package")
|
|
||||||
wrapHelpFlag = wrapCommand.Bool("h", false, "print help information")
|
|
||||||
astCommand = flag.NewFlagSet("ast", flag.ContinueOnError)
|
|
||||||
astHelpFlag = astCommand.Bool("h", false, "print help information")
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
code := runCommand()
|
if _, err := toml.DecodeFile("conf.toml",&Config); err != nil {
|
||||||
if code != 0 {
|
fmt.Printf("Cannot open config file conf.toml.\n")
|
||||||
os.Exit(code)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
}
|
if err := Start(); err != nil {
|
||||||
|
|
||||||
func runCommand() int {
|
|
||||||
|
|
||||||
flag.Usage = func() {
|
|
||||||
usage := "Usage: %s [-v] [<command>] [<flags>] file1.c ...\n\n"
|
|
||||||
usage += "Commands:\n"
|
|
||||||
usage += " wrap\twrap an Objective-C interface for Go\n"
|
|
||||||
usage += " ast\t\tprint AST\n\n"
|
|
||||||
|
|
||||||
usage += "Flags:\n"
|
|
||||||
fmt.Printf(usage, os.Args[0])
|
|
||||||
flag.PrintDefaults()
|
|
||||||
}
|
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if *versionFlag {
|
|
||||||
// Simply print out the version and exit.
|
|
||||||
fmt.Println("version")
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if flag.NArg() < 1 {
|
|
||||||
flag.Usage()
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
args := DefaultProgramArgs()
|
|
||||||
|
|
||||||
switch os.Args[1] {
|
|
||||||
case "ast":
|
|
||||||
err := astCommand.Parse(os.Args[2:])
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("ast command cannot parse: %v", err)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if *astHelpFlag || astCommand.NArg() == 0 {
|
|
||||||
fmt.Printf("Usage: %s ast file.c\n", os.Args[0])
|
|
||||||
astCommand.PrintDefaults()
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
args.ast = true
|
|
||||||
args.inputFiles = astCommand.Args()
|
|
||||||
args.clangFlags = clangFlags
|
|
||||||
case "wrap":
|
|
||||||
err := wrapCommand.Parse(os.Args[2:])
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("wrap command cannot parse: %v", err)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if *wrapHelpFlag || wrapCommand.NArg() == 0 {
|
|
||||||
fmt.Printf("Usage: %s wrap [-V] [-o file.go] [-p package] file1.c ...\n", os.Args[0])
|
|
||||||
wrapCommand.PrintDefaults()
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
args.inputFiles = wrapCommand.Args()
|
|
||||||
args.outputFile = *outputFlag
|
|
||||||
args.packageName = *packageFlag
|
|
||||||
args.verbose = *verboseFlag
|
|
||||||
args.clangFlags = clangFlags
|
|
||||||
default:
|
|
||||||
flag.Usage()
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := Start(args); err != nil {
|
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return 1
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
40
wrap/main.go
40
wrap/main.go
|
@ -4,8 +4,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gitlab.wow.st/gmp/clast/ast"
|
"gitlab.wow.st/gmp/nswrap/ast"
|
||||||
"gitlab.wow.st/gmp/clast/types"
|
"gitlab.wow.st/gmp/nswrap/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -25,10 +25,31 @@ type Wrapper struct {
|
||||||
func NewWrapper(debug bool) *Wrapper {
|
func NewWrapper(debug bool) *Wrapper {
|
||||||
Debug = debug
|
Debug = debug
|
||||||
if Debug { fmt.Println("// Debug mode") }
|
if Debug { fmt.Println("// Debug mode") }
|
||||||
return &Wrapper{
|
ret := &Wrapper{
|
||||||
Interfaces: map[string]Interface{},
|
Interfaces: map[string]Interface{},
|
||||||
Processed: map[string]bool{},
|
Processed: map[string]bool{},
|
||||||
}
|
}
|
||||||
|
ret.cCode.WriteString(`/*
|
||||||
|
#cgo CFLAGS: -x objective-c
|
||||||
|
#cgo LDFLAGS: -framework Foundation
|
||||||
|
`)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) Import(ss []string) {
|
||||||
|
for _,s := range ss {
|
||||||
|
w.cCode.WriteString(`
|
||||||
|
#import "` + s + `"
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) SysImport(ss []string) {
|
||||||
|
for _,s := range ss {
|
||||||
|
w.cCode.WriteString(`
|
||||||
|
#import <` + s + `>
|
||||||
|
`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Property struct {
|
type Property struct {
|
||||||
|
@ -321,13 +342,6 @@ func (c *Char) String() string {
|
||||||
|
|
||||||
func (w *Wrapper) Wrap(toproc []string) {
|
func (w *Wrapper) Wrap(toproc []string) {
|
||||||
|
|
||||||
w.cCode.WriteString(`/*
|
|
||||||
#cgo CFLAGS: -x objective-c
|
|
||||||
#cgo LDFLAGS: -framework Foundation
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
`)
|
|
||||||
|
|
||||||
pInterfaces := map[string]Interface{}
|
pInterfaces := map[string]Interface{}
|
||||||
for _,iface := range toproc {
|
for _,iface := range toproc {
|
||||||
pInterfaces[iface] = w.Interfaces[iface]
|
pInterfaces[iface] = w.Interfaces[iface]
|
||||||
|
@ -339,11 +353,11 @@ func (w *Wrapper) Wrap(toproc []string) {
|
||||||
iname, len(i.Properties), len(i.Methods))
|
iname, len(i.Properties), len(i.Methods))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func New%s() *%s {
|
func New%s() *%s {
|
||||||
ret := &%s{}
|
ret := &%s{}
|
||||||
ret.ptr = unsafe.Pointer(C.New%s())
|
ret.ptr = unsafe.Pointer(C.New%s())
|
||||||
ret = ret.Init()
|
//ret = ret.Init()
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
`,i.Name,i.Name,i.Name,i.Name))
|
`,i.Name,i.Name,i.Name,i.Name))
|
||||||
|
@ -353,7 +367,7 @@ func New%s() *%s {
|
||||||
New%s() {
|
New%s() {
|
||||||
return [%s alloc];
|
return [%s alloc];
|
||||||
}
|
}
|
||||||
`, i.Name, i.Name, i.Name))*/
|
`, i.Name, i.Name, i.Name))
|
||||||
|
|
||||||
//FIXME: sort properties
|
//FIXME: sort properties
|
||||||
for _,p := range i.Properties {
|
for _,p := range i.Properties {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user