...
1 package main
2
3 import (
4 "bytes"
5 "encoding/xml"
6 "fmt"
7 "log"
8 "sort"
9 )
10
11
12
13 type Context struct {
14 protocol *Protocol
15 out *bytes.Buffer
16 }
17
18 func newContext() *Context {
19 return &Context{
20 out: bytes.NewBuffer([]byte{}),
21 }
22 }
23
24
25 func (c *Context) Putln(format string, v ...interface{}) {
26 c.Put(format+"\n", v...)
27 }
28
29
30 func (c *Context) Put(format string, v ...interface{}) {
31 _, err := c.out.WriteString(fmt.Sprintf(format, v...))
32 if err != nil {
33 log.Fatalf("There was an error writing to context buffer: %s", err)
34 }
35 }
36
37
38
39
40 func (c *Context) Morph(xmlBytes []byte) {
41 parsedXml := &XML{}
42 err := xml.Unmarshal(xmlBytes, parsedXml)
43 if err != nil {
44 log.Fatal(err)
45 }
46
47
48 parsedXml.Imports.Eval()
49
50
51 c.protocol = parsedXml.Translate(nil)
52
53 c.protocol.AddAlignGaps()
54
55
56 c.Putln("// Package %s is the X client API for the %s extension.",
57 c.protocol.PkgName(), c.protocol.ExtXName)
58 c.Putln("package %s", c.protocol.PkgName())
59 c.Putln("")
60 c.Putln("// This file is automatically generated from %s.xml. "+
61 "Edit at your peril!", c.protocol.Name)
62 c.Putln("")
63
64
65
66 c.Putln("import (")
67 c.Putln("\"github.com/jezek/xgb\"")
68 c.Putln("")
69 if c.protocol.isExt() {
70 c.Putln("\"github.com/jezek/xgb/xproto\"")
71 }
72
73 sort.Sort(Protocols(c.protocol.Imports))
74 for _, imp := range c.protocol.Imports {
75
76 if imp.Name == "xproto" {
77 continue
78 }
79 c.Putln("\"github.com/jezek/xgb/%s\"", imp.Name)
80 }
81 c.Putln(")")
82 c.Putln("")
83
84
85
86 if c.protocol.isExt() {
87 xname := c.protocol.ExtXName
88
89 c.Putln("// Init must be called before using the %s extension.",
90 xname)
91 c.Putln("func Init(c *xgb.Conn) error {")
92 c.Putln("reply, err := xproto.QueryExtension(c, %d, \"%s\").Reply()",
93 len(xname), xname)
94 c.Putln("switch {")
95 c.Putln("case err != nil:")
96 c.Putln("return err")
97 c.Putln("case !reply.Present:")
98 c.Putln("return xgb.Errorf(\"No extension named %s could be found on "+
99 "on the server.\")", xname)
100 c.Putln("}")
101 c.Putln("")
102 c.Putln("c.ExtLock.Lock()")
103 c.Putln("c.Extensions[\"%s\"] = reply.MajorOpcode", xname)
104 c.Putln("c.ExtLock.Unlock()")
105 c.Putln("for evNum, fun := range xgb.NewExtEventFuncs[\"%s\"] {",
106 xname)
107 c.Putln("xgb.NewEventFuncs[int(reply.FirstEvent) + evNum] = fun")
108 c.Putln("}")
109 c.Putln("for errNum, fun := range xgb.NewExtErrorFuncs[\"%s\"] {",
110 xname)
111 c.Putln("xgb.NewErrorFuncs[int(reply.FirstError) + errNum] = fun")
112 c.Putln("}")
113 c.Putln("return nil")
114 c.Putln("}")
115 c.Putln("")
116
117
118
119 c.Putln("func init() {")
120 c.Putln("xgb.NewExtEventFuncs[\"%s\"] = make(map[int]xgb.NewEventFun)",
121 xname)
122 c.Putln("xgb.NewExtErrorFuncs[\"%s\"] = make(map[int]xgb.NewErrorFun)",
123 xname)
124 c.Putln("}")
125 c.Putln("")
126 } else {
127
128
129 c.Putln("// Setup parses the setup bytes retrieved when")
130 c.Putln("// connecting into a SetupInfo struct.")
131 c.Putln("func Setup(c *xgb.Conn) *SetupInfo {")
132 c.Putln("setup := new(SetupInfo)")
133 c.Putln("SetupInfoRead(c.SetupBytes, setup)")
134 c.Putln("return setup")
135 c.Putln("}")
136 c.Putln("")
137 c.Putln("// DefaultScreen gets the default screen info from SetupInfo.")
138 c.Putln("func (s *SetupInfo) DefaultScreen(c *xgb.Conn) *ScreenInfo {")
139 c.Putln("return &s.Roots[c.DefaultScreen]")
140 c.Putln("}")
141 c.Putln("")
142 }
143
144
145 sort.Sort(Types(c.protocol.Types))
146 sort.Sort(Requests(c.protocol.Requests))
147 for _, typ := range c.protocol.Types {
148 typ.Define(c)
149 }
150 for _, req := range c.protocol.Requests {
151 req.Define(c)
152 }
153 }
154
View as plain text