73 lines
1.7 KiB
Odin
73 lines
1.7 KiB
Odin
// jnigen -- generates JNI binding boilerplate from an annotated Odin spec.
|
|
//
|
|
// odin run jnigen -- [spec.odin] [out.odin] [package]
|
|
//
|
|
// The spec is never compiled (it carries `#+build ignore`), so it needs no
|
|
// -custom-attribute flags and cannot collide with the generated procs.
|
|
package jnigen
|
|
|
|
import "core:fmt"
|
|
import "core:odin/ast"
|
|
import "core:odin/parser"
|
|
import "core:os"
|
|
|
|
main :: proc() {
|
|
spec_path := "jni_spec.odin"
|
|
out_path := "jni_generated.odin"
|
|
package_name := "main"
|
|
|
|
args := os.args[1:]
|
|
if len(args) > 0 {
|
|
spec_path = args[0]
|
|
}
|
|
if len(args) > 1 {
|
|
out_path = args[1]
|
|
}
|
|
if len(args) > 2 {
|
|
package_name = args[2]
|
|
}
|
|
|
|
src, read_err := os.read_entire_file(spec_path, context.allocator)
|
|
if read_err != nil {
|
|
fmt.eprintfln("jnigen: cannot read %s: %v", spec_path, read_err)
|
|
os.exit(1)
|
|
}
|
|
|
|
p := parser.default_parser()
|
|
f := ast.File{
|
|
src = string(src),
|
|
fullpath = spec_path,
|
|
}
|
|
if !parser.parse_file(&p, &f) {
|
|
fmt.eprintfln("jnigen: failed to parse %s", spec_path)
|
|
os.exit(1)
|
|
}
|
|
|
|
g: Gen
|
|
g.classes = make(map[string]string)
|
|
|
|
collect_classes(&g, &f)
|
|
collect_bindings(&g, &f)
|
|
|
|
if len(g.errors) > 0 {
|
|
for e in g.errors {
|
|
fmt.eprintfln("jnigen: %s", e)
|
|
}
|
|
os.exit(1)
|
|
}
|
|
|
|
out := emit_file(&g, package_name)
|
|
if werr := os.write_entire_file(out_path, transmute([]byte)out); werr != nil {
|
|
fmt.eprintfln("jnigen: cannot write %s: %v", out_path, werr)
|
|
os.exit(1)
|
|
}
|
|
|
|
fmt.printfln(
|
|
"jnigen: %s -> %s (%d classes, %d bindings)",
|
|
spec_path,
|
|
out_path,
|
|
len(g.class_decls),
|
|
len(g.bindings),
|
|
)
|
|
}
|