package main import "unsafe" //export write func cWrite(fd int32, buf unsafe.Pointer, count uint32) (n int32) //export mxc_readfile func cReadfile(path unsafe.Pointer, pathLen int32, buf unsafe.Pointer, bufCap int32) (n int32) //export mxc_filesize func cFilesize(path unsafe.Pointer, pathLen int32) (n int32) var nl = []byte{10} func out(s string) { if len(s) > 0 { cWrite(1, unsafe.Pointer(&[]byte(s)[0]), uint32(len(s))) } } func outln(s string) { out(s) cWrite(1, unsafe.Pointer(&nl[0]), 1) } func fatal(s string) { if len(s) > 0 { cWrite(2, unsafe.Pointer(&[]byte(s)[0]), uint32(len(s))) } cWrite(2, unsafe.Pointer(&nl[0]), 1) } func readFile(path string) (data []byte, ok bool) { sz := cFilesize(unsafe.Pointer(&[]byte(path)[0]), int32(len(path))) if sz < 0 { return nil, false } buf := []byte{:sz+1} n := cReadfile(unsafe.Pointer(&[]byte(path)[0]), int32(len(path)), unsafe.Pointer(&buf[0]), sz+1) if n < 0 { return nil, false } return buf[:n], true } func getArgs() (ss []string) { buf := []byte{:4096} n := cReadfile(unsafe.Pointer(&[]byte("/proc/self/cmdline")[0]), 18, unsafe.Pointer(&buf[0]), 4096) if n <= 0 { return nil } var args []string start := int32(0) for i := int32(0); i < n; i++ { if buf[i] == 0 { if i > start { args = append(args, string(buf[start:i])) } start = i + 1 } } return args } func main() { args := getArgs() if len(args) < 2 { fatal("usage: mxparse "); return } path := args[1] data, ok := readFile(path) if !ok { fatal("error: cannot read " | path); return } file := parseSource(path, data) if file == nil { fatal("parse failed"); return } outln("File " | path) if file.PkgName == nil { outln("PkgName: nil") } else { outln("Package " | file.PkgName.Value) } outln("Decls: " | ItoaU32(uint32(len(file.DeclList)))) for i := int32(0); i < int32(len(file.DeclList)); i++ { d := file.DeclList[i] if fd, ok := d.(*FuncDecl); ok && fd != nil { r := "" if fd.Recv != nil { r = "(method) " } name := "_" if fd.Name != nil { name = fd.Name.Value } outln("Func " | r | name) } else if td, ok := d.(*TypeDecl); ok && td != nil { outln("Type " | td.Name.Value) } else if _, ok := d.(*VarDecl); ok { outln("Var") } else if _, ok := d.(*ConstDecl); ok { outln("Const") } else if id, ok := d.(*ImportDecl); ok && id != nil { p := "" if id.Path != nil { p = id.Path.Value } outln("Import " | p) } else { outln("Decl?") } } }