200 lines
4.3 KiB
Go
200 lines
4.3 KiB
Go
// 15 april 2015
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"flag"
|
|
"github.com/andlabs/pgidl"
|
|
)
|
|
|
|
var extern = flag.String("extern", "extern", "name for extern")
|
|
var guard = flag.String("guard", "", "#define name for include guards")
|
|
|
|
var pkgtypes = map[string]string{}
|
|
|
|
func typedecl(t *pgidl.Type, name string) string {
|
|
if t == nil {
|
|
return "void " + name
|
|
}
|
|
if t.IsFuncPtr {
|
|
return cfuncptrdecl(t.FuncType, name)
|
|
}
|
|
s := t.Name + " "
|
|
if pkgtypes[t.Name] != "" {
|
|
s = pkgtypes[t.Name] + " "
|
|
}
|
|
for i := uint(0); i < t.NumPtrs; i++ {
|
|
s += "*"
|
|
}
|
|
return s + name
|
|
}
|
|
|
|
func arglist(a []*pgidl.Arg) string {
|
|
if len(a) == 0 {
|
|
return "void"
|
|
}
|
|
s := typedecl(a[0].Type, a[0].Name)
|
|
for i := 1; i < len(a); i++ {
|
|
s += ", " + typedecl(a[i].Type, a[i].Name)
|
|
}
|
|
return s
|
|
}
|
|
|
|
func cfuncdecl(f *pgidl.Func, name string) string {
|
|
fd := name + "(" + arglist(f.Args) + ")"
|
|
return *extern + " " + typedecl(f.Ret, fd) + ";"
|
|
}
|
|
|
|
func cfuncptrdecl(f *pgidl.Func, name string) string {
|
|
name = "(*" + name + ")"
|
|
fd := name + "(" + arglist(f.Args) + ")"
|
|
return typedecl(f.Ret, fd)
|
|
}
|
|
|
|
func cmethodmacro(f *pgidl.Func, typename string) string {
|
|
s := "#define " + typename + f.Name + "("
|
|
first := true
|
|
for _, a := range f.Args {
|
|
if !first {
|
|
s += ", "
|
|
}
|
|
s += a.Name
|
|
first = false
|
|
}
|
|
s += ") ("
|
|
s += "(*((this)->" + f.Name + "))"
|
|
s += "("
|
|
first = true
|
|
for _, a := range f.Args {
|
|
if !first {
|
|
s += ", "
|
|
}
|
|
s += "(" + a.Name + ")"
|
|
first = false
|
|
}
|
|
s += ")"
|
|
s += ")"
|
|
return s
|
|
}
|
|
|
|
func genpkgfunc(f *pgidl.Func, prefix string) {
|
|
fmt.Printf("%s\n", cfuncdecl(f, prefix + f.Name))
|
|
}
|
|
|
|
func genstruct(s *pgidl.Struct, prefix string) {
|
|
fmt.Printf("struct %s%s {\n", prefix, s.Name)
|
|
for _, f := range s.Fields {
|
|
fmt.Printf("\t%s;\n", typedecl(f.Type, f.Name))
|
|
}
|
|
fmt.Printf("};\n")
|
|
}
|
|
|
|
func geniface(i *pgidl.Interface, prefix string) {
|
|
fmt.Printf("struct %s%s {\n", prefix, i.Name)
|
|
if i.From != "" {
|
|
fmt.Printf("\t%s%s base;\n", prefix, i.From)
|
|
} else {
|
|
fmt.Printf("\tuintmax_t Type;\n")
|
|
}
|
|
for _, f := range i.Fields {
|
|
fmt.Printf("\t%s;\n", typedecl(f.Type, f.Name))
|
|
}
|
|
for _, m := range i.Methods {
|
|
// hack our this pointer in
|
|
m.Args = append([]*pgidl.Arg{
|
|
&pgidl.Arg{
|
|
Name: "this",
|
|
Type: &pgidl.Type{
|
|
Name: prefix + i.Name,
|
|
NumPtrs: 1,
|
|
},
|
|
},
|
|
}, m.Args...)
|
|
fmt.Printf("\t%s;\n", cfuncptrdecl(m, m.Name))
|
|
fmt.Printf("%s\n", cmethodmacro(m, prefix + i.Name))
|
|
}
|
|
fmt.Printf("};\n")
|
|
fmt.Printf("%s uintmax_t %sType%s(void);\n",
|
|
*extern,
|
|
prefix, i.Name)
|
|
fmt.Printf("#define %s%s(this) ((%s%s *) %sIsA((this), %sType%s(), 1))\n",
|
|
prefix, i.Name,
|
|
prefix, i.Name,
|
|
prefix,
|
|
prefix, i.Name)
|
|
fmt.Printf("#define %sIs%s(this) (%sIsA((this), %sType%s(), 0) != NULL)\n",
|
|
prefix, i.Name,
|
|
prefix,
|
|
prefix, i.Name)
|
|
}
|
|
|
|
func genenum(e *pgidl.Enum, prefix string) {
|
|
fmt.Printf("enum %s%s {\n", prefix, e.Name)
|
|
for _, m := range e.Members {
|
|
fmt.Printf("\t%s%s%s,\n", prefix, e.Name, m)
|
|
}
|
|
fmt.Printf("};\n")
|
|
}
|
|
|
|
func genpkg(p *pgidl.Package) {
|
|
for _, s := range p.Structs {
|
|
fmt.Printf("typedef struct %s%s %s%s;\n",
|
|
p.Name, s.Name,
|
|
p.Name, s.Name)
|
|
pkgtypes[s.Name] = p.Name + s.Name
|
|
}
|
|
for _, i := range p.Interfaces {
|
|
fmt.Printf("typedef struct %s%s %s%s;\n",
|
|
p.Name, i.Name,
|
|
p.Name, i.Name)
|
|
pkgtypes[i.Name] = p.Name + i.Name
|
|
}
|
|
for _, e := range p.Enums {
|
|
fmt.Printf("typedef enum %s%s %s%s;\n",
|
|
p.Name, e.Name,
|
|
p.Name, e.Name)
|
|
pkgtypes[e.Name] = p.Name + e.Name
|
|
}
|
|
// apparently we have to fully define C enumerations before we can use them...
|
|
for _, e := range p.Enums {
|
|
genenum(e, p.Name)
|
|
}
|
|
for _, o := range p.Order {
|
|
switch o.Which {
|
|
case pgidl.Funcs:
|
|
genpkgfunc(p.Funcs[o.Index], p.Name)
|
|
case pgidl.Structs:
|
|
genstruct(p.Structs[o.Index], p.Name)
|
|
case pgidl.Interfaces:
|
|
geniface(p.Interfaces[o.Index], p.Name)
|
|
case pgidl.Raws:
|
|
fmt.Printf("%s\n", p.Raws[o.Index])
|
|
case pgidl.Enums:
|
|
// we did them already; see above
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
idl, errs := pgidl.Parse(os.Stdin, "<stdin>")
|
|
if len(errs) != 0 {
|
|
for _, e := range errs {
|
|
fmt.Fprintf(os.Stderr, "%s\n", e)
|
|
}
|
|
os.Exit(1)
|
|
}
|
|
fmt.Printf("// generated by idl2h; do not edit\n")
|
|
if *guard != "" {
|
|
fmt.Printf("#ifndef %s\n", *guard)
|
|
fmt.Printf("#define %s\n", *guard)
|
|
}
|
|
for _, p := range idl {
|
|
genpkg(p)
|
|
}
|
|
if *guard != "" {
|
|
fmt.Printf("#endif\n")
|
|
}
|
|
}
|