diff --git a/nexgb/xgbgen/context.go b/nexgb/xgbgen/context.go index d433531..35dd37e 100644 --- a/nexgb/xgbgen/context.go +++ b/nexgb/xgbgen/context.go @@ -5,6 +5,7 @@ import ( "encoding/xml" "fmt" "log" + "strings" "time" ) @@ -70,6 +71,43 @@ func (c *Context) Morph(xmlBytes []byte) { c.Putln("") } + // If this is an extension, create a function to initialize the extension + // before it can be used. + if c.protocol.isExt() { + name := strings.Title(c.protocol.Name) + "Init" + xname := c.protocol.ExtXName + + c.Putln("// %s must be called before using the %s extension.", + name, xname) + c.Putln("func (c *Conn) %s() error {", name) + c.Putln("reply, err := c.QueryExtension(%d, \"%s\").Reply()", + len(xname), xname) + c.Putln("switch {") + c.Putln("case err != nil:") + c.Putln("return err") + c.Putln("case !reply.Present:") + c.Putln("return newError(\"No extension named %s could be found on " + + "on the server.\")", xname) + c.Putln("}") + c.Putln("") + c.Putln("c.extLock.Lock()") + c.Putln("c.extensions[\"%s\"] = reply.MajorOpcode", xname) + c.Putln("for evNum, fun := range newExtEventFuncs[\"%s\"] {", xname) + c.Putln("newEventFuncs[int(reply.FirstEvent) + evNum] = fun") + c.Putln("}") + c.Putln("c.extLock.Unlock()") + c.Putln("") + c.Putln("return nil") + c.Putln("}") + c.Putln("") + + // Make sure newExtEventFuncs["EXT_NAME"] map is initialized. + c.Putln("func init() {") + c.Putln("newExtEventFuncs[\"%s\"] = make(map[int]newEventFun)", xname) + c.Putln("}") + c.Putln("") + } + // Now write Go source code for _, typ := range c.protocol.Types { typ.Define(c) diff --git a/nexgb/xgbgen/go_error.go b/nexgb/xgbgen/go_error.go index 152db8b..0222289 100644 --- a/nexgb/xgbgen/go_error.go +++ b/nexgb/xgbgen/go_error.go @@ -64,7 +64,7 @@ func (e *Error) ImplementsError(c *Context) { c.Putln("}") c.Putln("") c.Putln("func (err %s) BadId() Id {", e.ErrType()) - if c.protocol.Name == "xproto" { + if !c.protocol.isExt() { c.Putln("return Id(err.BadValue)") } else { c.Putln("return 0") diff --git a/nexgb/xgbgen/go_event.go b/nexgb/xgbgen/go_event.go index 9bc6dfe..ce54e19 100644 --- a/nexgb/xgbgen/go_event.go +++ b/nexgb/xgbgen/go_event.go @@ -47,7 +47,12 @@ func (e *Event) Define(c *Context) { // Let's the XGB event loop read this event. c.Putln("func init() {") - c.Putln("newEventFuncs[%d] = New%s", e.Number, e.EvType()) + if c.protocol.isExt() { + c.Putln("newExtEventFuncs[\"%s\"][%d] = New%s", + c.protocol.ExtXName, e.Number, e.EvType()) + } else { + c.Putln("newEventFuncs[%d] = New%s", e.Number, e.EvType()) + } c.Putln("}") c.Putln("") } @@ -130,7 +135,12 @@ func (e *EventCopy) Define(c *Context) { // Let's the XGB event loop read this event. c.Putln("func init() {") - c.Putln("newEventFuncs[%d] = New%s", e.Number, e.EvType()) + if c.protocol.isExt() { + c.Putln("newExtEventFuncs[\"%s\"][%d] = New%s", + c.protocol.ExtXName, e.Number, e.EvType()) + } else { + c.Putln("newEventFuncs[%d] = New%s", e.Number, e.EvType()) + } c.Putln("}") c.Putln("") } diff --git a/nexgb/xgbgen/go_request_reply.go b/nexgb/xgbgen/go_request_reply.go index e64e2a2..451667f 100644 --- a/nexgb/xgbgen/go_request_reply.go +++ b/nexgb/xgbgen/go_request_reply.go @@ -118,7 +118,7 @@ func (r *Request) WriteRequest(c *Context) { c.Putln("b := 0") c.Putln("buf := make([]byte, size)") c.Putln("") - if strings.ToLower(c.protocol.Name) != "xproto" { + if c.protocol.isExt() { c.Putln("buf[b] = c.extensions[\"%s\"]", strings.ToUpper(c.protocol.ExtXName)) c.Putln("b += 1") @@ -128,17 +128,17 @@ func (r *Request) WriteRequest(c *Context) { c.Putln("b += 1") c.Putln("") if len(r.Fields) == 0 { - if strings.ToLower(c.protocol.Name) == "xproto" { + if !c.protocol.isExt() { c.Putln("b += 1 // padding") } writeSize() - } else if strings.ToLower(c.protocol.Name) != "xproto" { + } else if c.protocol.isExt() { writeSize() } for i, field := range r.Fields { field.Write(c, "") c.Putln("") - if i == 0 && strings.ToLower(c.protocol.Name) == "xproto" { + if i == 0 && !c.protocol.isExt() { writeSize() } } diff --git a/nexgb/xgbgen/protocol.go b/nexgb/xgbgen/protocol.go index 505b400..e01bc17 100644 --- a/nexgb/xgbgen/protocol.go +++ b/nexgb/xgbgen/protocol.go @@ -36,6 +36,6 @@ func (p *Protocol) Initialize() { // isExt returns true if this protocol is an extension. // i.e., it's name isn't "xproto". func (p *Protocol) isExt() bool { - return strings.ToLower(p.Name) == "xproto" + return strings.ToLower(p.Name) != "xproto" } diff --git a/nexgb/xgbgen/request_reply.go b/nexgb/xgbgen/request_reply.go index 7cd2859..c7a4cf8 100644 --- a/nexgb/xgbgen/request_reply.go +++ b/nexgb/xgbgen/request_reply.go @@ -22,7 +22,7 @@ type Request struct { // It also initializes the reply if one exists, and all fields in this request. func (r *Request) Initialize(p *Protocol) { r.srcName = SrcName(p, r.xmlName) - if p.Name != "xproto" { + if p.isExt() { r.srcName = strings.Title(strings.ToLower(p.Name)) + r.srcName } @@ -93,7 +93,7 @@ func (r *Request) Size(c *Context) Size { // request. In an extension request, this byte is always occupied // by the opcode of the request (while the first byte is always occupied // by the opcode of the extension). - if c.protocol.Name == "xproto" { + if !c.protocol.isExt() { size = size.Add(newFixedSize(3)) } else { size = size.Add(newFixedSize(4)) diff --git a/nexgb/xgbgen/translation.go b/nexgb/xgbgen/translation.go index 90cd0f3..592c152 100644 --- a/nexgb/xgbgen/translation.go +++ b/nexgb/xgbgen/translation.go @@ -410,7 +410,7 @@ func TypeSrcName(p *Protocol, typ Type) string { // Since there is no namespace, we need to look for a namespace // in the current context. niceType := splitAndTitle(t) - if p.Name != "xproto" { + if p.isExt() { for _, typ2 := range p.Types { if t == typ2.XmlName() { return strings.Title(p.Name) + niceType