diff options
| author | Pietro Gagliardi <[email protected]> | 2014-07-10 21:42:16 -0400 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-07-10 21:42:16 -0400 |
| commit | cf64176fe0326cd370bedb607333875cd23e9b4c (patch) | |
| tree | 503387e522e3b81ae965aab2256168fa578801c5 /redo/zwinconstgen.go | |
| parent | ff1a5d73a1ce1abe9ec574b47b7209fa676cd1d1 (diff) | |
Moved winconstgen.go into a tools/ folder because blah more than one package found.
Diffstat (limited to 'redo/zwinconstgen.go')
| -rw-r--r-- | redo/zwinconstgen.go | 230 |
1 files changed, 0 insertions, 230 deletions
diff --git a/redo/zwinconstgen.go b/redo/zwinconstgen.go deleted file mode 100644 index f4f0e9f..0000000 --- a/redo/zwinconstgen.go +++ /dev/null @@ -1,230 +0,0 @@ -// +build ignore - -// 24 may 2014 -package main - -import ( - "fmt" - "os" - "strings" - "go/token" - "go/ast" - "go/parser" - "sort" - "io/ioutil" - "path/filepath" - "os/exec" -) - -func getPackage(path string) (pkg *ast.Package) { - fileset := token.NewFileSet() // parser.ParseDir() actually writes to this; not sure why it doesn't return one instead - filter := func(i os.FileInfo) bool { - return strings.HasSuffix(i.Name(), "_windows.go") - } - pkgs, err := parser.ParseDir(fileset, path, filter, parser.AllErrors) - if err != nil { - panic(err) - } - if len(pkgs) != 1 { - panic("more than one package found") - } - for k, _ := range pkgs { // get the sole key - pkg = pkgs[k] - } - return pkg -} - -type walker struct { - desired func(string) bool -} - -var known = map[string]string{} -var unknown = map[string]struct{}{} - -func (w *walker) Visit(node ast.Node) ast.Visitor { - switch n := node.(type) { - case *ast.Ident: // constant or structure? - if w.desired(n.Name) { - if n.Obj != nil { - delete(unknown, n.Name) - kind := n.Obj.Kind.String() - if known[n.Name] != "" && known[n.Name] != kind { - panic(n.Name + "(" + kind + ") already known to be a " + known[n.Name]) - } - known[n.Name] = kind - } else if _, ok := known[n.Name]; !ok { // only if not known - unknown[n.Name] = struct{}{} - } - } - case *ast.Comment: // function? - // TODO - } - return w -} - -func gatherNames(pkg *ast.Package) { - desired := func(name string) bool { - return strings.HasPrefix(name, "c_") || // constants - strings.HasPrefix(name, "s_") // structs - } - for _, f := range pkg.Files { - for _, d := range f.Decls { - ast.Walk(&walker{desired}, d) - } - } -} - -// for backwards compatibiilty reasons, Windows defines GetWindowLongPtr()/SetWindowLongPtr() as a macro which expands to GetWindowLong()/SetWindowLong() on 32-bit systems -// we'll just simulate that here -var gwlpNames = map[string]string{ - "386": "etWindowLongW", - "amd64": "etWindowLongPtrW", -} - -func writeLine(f *os.File, line string) { - fmt.Fprintf(f, "%s\n", line) -} - -const cgopreamble = ` -#define UNICODE -#define _UNICODE -#define STRICT -#define STRICT_TYPED_ITEMIDS -/* get Windows version right; right now Windows XP */ -#define WINVER 0x0501 -#define _WIN32_WINNT 0x0501 -#define _WIN32_WINDOWS 0x0501 /* according to Microsoft's winperf.h */ -#define _WIN32_IE 0x0600 /* according to Microsoft's sdkddkver.h */ -#define NTDDI_VERSION 0x05010000 /* according to Microsoft's sdkddkver.h */ -#include <windows.h> -#include <commctrl.h> -#include <stdint.h> -` - -func writeConstCast(f *os.File, c string) { - cc := c[2:] // strip leading c_ - fmt.Fprintf(f, "uintptr_t %s = (uintptr_t) (%s);\n", c, cc) -} - -func writeConstPrint(f *os.File, c string) { - fmt.Fprintf(f, "\tfmt.Fprintf(buf, \"const %%s = %%d\\n\", %q, C.%s)\n", c, c) -} - -func writeStructPrint(f *os.File, s string) { - cs := s[2:] // strip leading s_ - fmt.Fprintf(f, "\tt = reflect.TypeOf(C.%s{})\n", cs) - // TODO -} - -func main() { - if len(os.Args) < 3 { - panic("usage: " + os.Args[0] + " path goarch [go-command-options...]") - } - pkgpath := os.Args[1] - targetarch := os.Args[2] - if _, ok := gwlpNames[targetarch]; !ok { - panic("unknown target windows/" + targetarch) - } - goopts := os.Args[3:] // valid if len(os.Args) == 3; in that case this will just be a slice of length zero - - pkg := getPackage(pkgpath) - gatherNames(pkg) - - // if we still have some known, I didn't clean things up completely - if len(known) > 0 { - knowns := "" - for ident, kind := range known { - if kind != "var" && kind != "const" { - continue - } - knowns += "\n" + ident + " (" + kind + ")" - } - panic("error: the following are still known!" + knowns) // has a newline already - } - - // keep sorted for git - consts := make([]string, 0, len(unknown)) - structs := make([]string, 0, len(unknown)) - for ident, _ := range unknown { - if strings.HasPrefix(ident, "s_") { - structs = append(structs, ident) - continue - } - consts = append(consts, ident) - } - sort.Strings(consts) - sort.Strings(structs) - - // thanks to james4k in irc.freenode.net/#go-nuts - tmpdir, err := ioutil.TempDir("", "windowsconstgen") - if err != nil { - panic(err) - } - genoutname := filepath.Join(tmpdir, "gen.go") - f, err := os.Create(genoutname) - if err != nil { - panic(err) - } - - writeLine(f, "package main") - writeLine(f, "import \"fmt\"") - writeLine(f, "import \"bytes\"") - writeLine(f, "import \"runtime\"") - writeLine(f, "import \"go/format\"") - writeLine(f, "/*") - writeLine(f, cgopreamble) - for _, c := range consts { - writeConstCast(f, c) - } - writeLine(f, "*/") - writeLine(f, "import \"C\"") - writeLine(f, "func main() {") - writeLine(f, "\tbuf := new(bytes.Buffer)") - writeLine(f, "\tfmt.Fprintln(buf, \"package main\")") - writeLine(f, "\tfmt.Fprintln(buf, \"func main() {\")") - for _, c := range consts { - writeConstPrint(f, c) - } - writeLine(f, "\tfmt.Fprintln(buf, \"var t reflect.Type\")") - writeLine(f, "\tfmt.Fprintln(buf, \"var s string\")") - for _, s := range structs { - writeStructPrint(f, s) - } - writeLine(f, "\tfmt.Fprintln(buf, \"}\")") - writeLine(f, "\tres, err := format.Source(buf.Bytes())") - writeLine(f, "\tif err != nil { panic(err) }") - writeLine(f, "\tfmt.Printf(\"%s\", res)") - writeLine(f, "}") - - cmd := exec.Command("go", "run") - cmd.Args = append(cmd.Args, goopts...) // valid if len(goopts) == 0; in that case this will just be a no-op - cmd.Args = append(cmd.Args, genoutname) - f, err = os.Create(filepath.Join(pkgpath, "zconstants_windows_" + targetarch + ".go")) - if err != nil { - panic(err) - } - defer f.Close() - cmd.Stdout = f - cmd.Stderr = os.Stderr - // we need to preserve the environment EXCEPT FOR the variables we're overriding - // thanks to raggi and smw in irc.freenode.net/#go-nuts - for _, ev := range os.Environ() { - if strings.HasPrefix(ev, "GOOS=") || - strings.HasPrefix(ev, "GOARCH=") || - strings.HasPrefix(ev, "CGO_ENABLED=") { - continue - } - cmd.Env = append(cmd.Env, ev) - } - cmd.Env = append(cmd.Env, - "GOOS=windows", - "GOARCH=" + targetarch, - "CGO_ENABLED=1") // needed as it's not set by default in cross-compiles - err = cmd.Run() - if err != nil { - // TODO find a way to get the exit code - os.Exit(1) - } - - // TODO remove the temporary directory -} |
