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
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"gitlab.wow.st/gmp/clast/ast"
|
||||
"gitlab.wow.st/gmp/clast/wrap"
|
||||
"github.com/BurntSushi/toml"
|
||||
"gitlab.wow.st/gmp/nswrap/ast"
|
||||
"gitlab.wow.st/gmp/nswrap/wrap"
|
||||
)
|
||||
|
||||
type ProgramArgs struct {
|
||||
verbose bool
|
||||
ast bool
|
||||
inputFiles []string
|
||||
clangFlags []string
|
||||
outputFile string
|
||||
packageName string
|
||||
var Debug = false
|
||||
|
||||
// A private option to output the Go as a *_test.go file.
|
||||
outputAsTest bool
|
||||
type conf struct {
|
||||
InputFiles []string
|
||||
Classes []string
|
||||
Imports []string
|
||||
SysImports []string
|
||||
}
|
||||
|
||||
// DefaultProgramArgs default value of ProgramArgs
|
||||
func DefaultProgramArgs() ProgramArgs {
|
||||
return ProgramArgs{
|
||||
verbose: false,
|
||||
ast: false,
|
||||
packageName: "main",
|
||||
clangFlags: []string{},
|
||||
outputAsTest: false,
|
||||
}
|
||||
}
|
||||
var Config conf
|
||||
|
||||
func readAST(data []byte) []string {
|
||||
return strings.Split(string(data), "\n")
|
||||
|
@ -143,17 +131,9 @@ func buildTree(nodes []treeNode, depth int) []ast.Node {
|
|||
}
|
||||
|
||||
// Start begins transpiling an input file.
|
||||
func Start(args ProgramArgs) (err error) {
|
||||
if args.verbose {
|
||||
fmt.Println("Start tanspiling ...")
|
||||
}
|
||||
|
||||
if os.Getenv("GOPATH") == "" {
|
||||
return fmt.Errorf("The $GOPATH must be set")
|
||||
}
|
||||
|
||||
func Start() (err error) {
|
||||
// 1. Compile it first (checking for errors)
|
||||
for _, in := range args.inputFiles {
|
||||
for _, in := range Config.InputFiles {
|
||||
_, err := os.Stat(in)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Input file %s is not found", in)
|
||||
|
@ -163,12 +143,9 @@ func Start(args ProgramArgs) (err error) {
|
|||
// 2. Preprocess NOT DONE
|
||||
|
||||
// 3. Generate JSON from AST
|
||||
if args.verbose {
|
||||
fmt.Println("Running clang for AST tree...")
|
||||
}
|
||||
cargs := []string{"-xobjective-c", "-Xclang", "-ast-dump",
|
||||
"-fsyntax-only","-fno-color-diagnostics"}
|
||||
cargs = append(cargs,args.inputFiles...)
|
||||
cargs = append(cargs,Config.InputFiles...)
|
||||
astPP, err := exec.Command("clang",cargs...).Output()
|
||||
if err != nil {
|
||||
// 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))
|
||||
}
|
||||
|
||||
if args.verbose {
|
||||
fmt.Println("Reading clang AST tree...")
|
||||
}
|
||||
lines := readAST(astPP)
|
||||
if args.ast {
|
||||
for _, l := range lines {
|
||||
fmt.Println(l)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Converting to nodes
|
||||
if args.verbose {
|
||||
fmt.Println("Converting to nodes...")
|
||||
}
|
||||
nodes := convertLinesToNodesParallel(lines)
|
||||
|
||||
// build tree
|
||||
if args.verbose {
|
||||
fmt.Println("Building tree...")
|
||||
}
|
||||
tree := buildTree(nodes, 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()) {
|
||||
switch x := n.(type) {
|
||||
case *ast.ObjCInterfaceDecl:
|
||||
|
@ -212,122 +174,17 @@ func Start(args ProgramArgs) (err error) {
|
|||
w.AddCategory(x)
|
||||
}
|
||||
}
|
||||
w.Wrap([]string{"NSString"})
|
||||
w.Wrap(Config.Classes)
|
||||
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() {
|
||||
code := runCommand()
|
||||
if code != 0 {
|
||||
os.Exit(code)
|
||||
if _, err := toml.DecodeFile("conf.toml",&Config); err != nil {
|
||||
fmt.Printf("Cannot open config file conf.toml.\n")
|
||||
os.Exit(-1)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if err := Start(); err != nil {
|
||||
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"
|
||||
"strings"
|
||||
|
||||
"gitlab.wow.st/gmp/clast/ast"
|
||||
"gitlab.wow.st/gmp/clast/types"
|
||||
"gitlab.wow.st/gmp/nswrap/ast"
|
||||
"gitlab.wow.st/gmp/nswrap/types"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -25,10 +25,31 @@ type Wrapper struct {
|
|||
func NewWrapper(debug bool) *Wrapper {
|
||||
Debug = debug
|
||||
if Debug { fmt.Println("// Debug mode") }
|
||||
return &Wrapper{
|
||||
ret := &Wrapper{
|
||||
Interfaces: map[string]Interface{},
|
||||
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 {
|
||||
|
@ -321,13 +342,6 @@ func (c *Char) String() 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{}
|
||||
for _,iface := range toproc {
|
||||
pInterfaces[iface] = w.Interfaces[iface]
|
||||
|
@ -339,11 +353,11 @@ func (w *Wrapper) Wrap(toproc []string) {
|
|||
iname, len(i.Properties), len(i.Methods))
|
||||
}
|
||||
|
||||
/*w.goCode.WriteString(fmt.Sprintf(`
|
||||
w.goCode.WriteString(fmt.Sprintf(`
|
||||
func New%s() *%s {
|
||||
ret := &%s{}
|
||||
ret.ptr = unsafe.Pointer(C.New%s())
|
||||
ret = ret.Init()
|
||||
//ret = ret.Init()
|
||||
return ret
|
||||
}
|
||||
`,i.Name,i.Name,i.Name,i.Name))
|
||||
|
@ -353,7 +367,7 @@ func New%s() *%s {
|
|||
New%s() {
|
||||
return [%s alloc];
|
||||
}
|
||||
`, i.Name, i.Name, i.Name))*/
|
||||
`, i.Name, i.Name, i.Name))
|
||||
|
||||
//FIXME: sort properties
|
||||
for _,p := range i.Properties {
|
||||
|
|
Loading…
Reference in New Issue
Block a user