Changed xgbgen to support xcb-proto 1.12
* Added minimal support for switch fields. * Changed the way Size is calculated to accomodate for lists inside structs (added to randr) * Removed heuristic to place alignment gaps, they are now explicitly described in xml
This commit is contained in:
		@@ -1,120 +0,0 @@
 | 
				
			|||||||
package main
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (p *Protocol) AddAlignGaps() {
 | 
					 | 
				
			||||||
	for i := range p.Imports {
 | 
					 | 
				
			||||||
		p.Imports[i].AddAlignGaps()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i := range p.Types {
 | 
					 | 
				
			||||||
		switch t := p.Types[i].(type) {
 | 
					 | 
				
			||||||
		case *Struct:
 | 
					 | 
				
			||||||
			t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
 | 
					 | 
				
			||||||
		case *Event:
 | 
					 | 
				
			||||||
			t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
 | 
					 | 
				
			||||||
		case *Error:
 | 
					 | 
				
			||||||
			t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for i := range p.Requests {
 | 
					 | 
				
			||||||
		p.Requests[i].Fields = addAlignGapsToFields(
 | 
					 | 
				
			||||||
			p.Requests[i].xmlName, p.Requests[i].Fields)
 | 
					 | 
				
			||||||
		if p.Requests[i].Reply != nil {
 | 
					 | 
				
			||||||
			p.Requests[i].Reply.Fields = addAlignGapsToFields(
 | 
					 | 
				
			||||||
				p.Requests[i].xmlName, p.Requests[i].Reply.Fields)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func addAlignGapsToFields(name string, fields []Field) []Field {
 | 
					 | 
				
			||||||
	var i int
 | 
					 | 
				
			||||||
	for i = 0; i < len(fields); i++ {
 | 
					 | 
				
			||||||
		if _, ok := fields[i].(*ListField); ok {
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if i >= len(fields) {
 | 
					 | 
				
			||||||
		return fields
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	r := make([]Field, 0, len(fields)+2)
 | 
					 | 
				
			||||||
	r = append(r, fields[:i]...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	r = append(r, fields[i])
 | 
					 | 
				
			||||||
	for i = i + 1; i < len(fields); i++ {
 | 
					 | 
				
			||||||
		switch f := fields[i].(type) {
 | 
					 | 
				
			||||||
		case *ListField:
 | 
					 | 
				
			||||||
			// ok, add padding
 | 
					 | 
				
			||||||
			sz := xcbSizeOfType(f.Type)
 | 
					 | 
				
			||||||
			switch {
 | 
					 | 
				
			||||||
			case sz == 1:
 | 
					 | 
				
			||||||
				// nothing
 | 
					 | 
				
			||||||
			case sz == 2:
 | 
					 | 
				
			||||||
				r = append(r, &PadField{0, 2})
 | 
					 | 
				
			||||||
			case sz == 3:
 | 
					 | 
				
			||||||
				panic(fmt.Errorf("Alignment is not a power of 2"))
 | 
					 | 
				
			||||||
			case sz >= 4:
 | 
					 | 
				
			||||||
				r = append(r, &PadField{0, 4})
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		case *LocalField:
 | 
					 | 
				
			||||||
			// nothing
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			fmt.Fprintf(os.Stderr,
 | 
					 | 
				
			||||||
				"Can't add alignment gaps, mix of list and non-list "+
 | 
					 | 
				
			||||||
					"fields: %s\n", name)
 | 
					 | 
				
			||||||
			return fields
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		r = append(r, fields[i])
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return r
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func xcbSizeOfField(fld Field) int {
 | 
					 | 
				
			||||||
	switch f := fld.(type) {
 | 
					 | 
				
			||||||
	case *PadField:
 | 
					 | 
				
			||||||
		return int(f.Bytes)
 | 
					 | 
				
			||||||
	case *SingleField:
 | 
					 | 
				
			||||||
		return xcbSizeOfType(f.Type)
 | 
					 | 
				
			||||||
	case *ListField:
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	case *ExprField:
 | 
					 | 
				
			||||||
		return xcbSizeOfType(f.Type)
 | 
					 | 
				
			||||||
	case *ValueField:
 | 
					 | 
				
			||||||
		return xcbSizeOfType(f.MaskType)
 | 
					 | 
				
			||||||
	case *SwitchField:
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func xcbSizeOfType(typ Type) int {
 | 
					 | 
				
			||||||
	switch t := typ.(type) {
 | 
					 | 
				
			||||||
	case *Resource:
 | 
					 | 
				
			||||||
		return 4
 | 
					 | 
				
			||||||
	case *TypeDef:
 | 
					 | 
				
			||||||
		return t.Size().Eval()
 | 
					 | 
				
			||||||
	case *Base:
 | 
					 | 
				
			||||||
		return t.Size().Eval()
 | 
					 | 
				
			||||||
	case *Struct:
 | 
					 | 
				
			||||||
		sz := 0
 | 
					 | 
				
			||||||
		for i := range t.Fields {
 | 
					 | 
				
			||||||
			sz += xcbSizeOfField(t.Fields[i])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return sz
 | 
					 | 
				
			||||||
	case *Union:
 | 
					 | 
				
			||||||
		sz := 0
 | 
					 | 
				
			||||||
		for i := range t.Fields {
 | 
					 | 
				
			||||||
			csz := xcbSizeOfField(t.Fields[i])
 | 
					 | 
				
			||||||
			if csz > sz {
 | 
					 | 
				
			||||||
				sz = csz
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return sz
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -49,8 +49,23 @@ func (c *Context) Morph(xmlBytes []byte) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Translate XML types to nice types
 | 
						// Translate XML types to nice types
 | 
				
			||||||
	c.protocol = parsedXml.Translate(nil)
 | 
						c.protocol = parsedXml.Translate(nil)
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	c.protocol.AddAlignGaps()
 | 
						// For backwards compatibility we patch the type of the send_event field of
 | 
				
			||||||
 | 
						// PutImage to be byte
 | 
				
			||||||
 | 
						if c.protocol.Name == "shm" {
 | 
				
			||||||
 | 
							for _, req := range c.protocol.Requests {
 | 
				
			||||||
 | 
								if req.xmlName != "PutImage" {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								for _, ifield := range req.Fields {
 | 
				
			||||||
 | 
									field, ok := ifield.(*SingleField)
 | 
				
			||||||
 | 
									if !ok || field.xmlName != "send_event" {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									field.Type = &Base{ srcName: "byte", xmlName: "CARD8", size: newFixedSize(1, true) }
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Start with Go header.
 | 
						// Start with Go header.
 | 
				
			||||||
	c.Putln("// Package %s is the X client API for the %s extension.",
 | 
						c.Putln("// Package %s is the X client API for the %s extension.",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,9 @@ type Expression interface {
 | 
				
			|||||||
	// Initialize makes sure all names in this expression and any subexpressions
 | 
						// Initialize makes sure all names in this expression and any subexpressions
 | 
				
			||||||
	// have been translated to Go source names.
 | 
						// have been translated to Go source names.
 | 
				
			||||||
	Initialize(p *Protocol)
 | 
						Initialize(p *Protocol)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Makes all field references relative to path
 | 
				
			||||||
 | 
						Specialize(path string) Expression
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Function is a custom expression not found in the XML. It's simply used
 | 
					// Function is a custom expression not found in the XML. It's simply used
 | 
				
			||||||
@@ -62,6 +65,12 @@ func (e *Function) Initialize(p *Protocol) {
 | 
				
			|||||||
	e.Expr.Initialize(p)
 | 
						e.Expr.Initialize(p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Function) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						r := *e
 | 
				
			||||||
 | 
						r.Expr = r.Expr.Specialize(path)
 | 
				
			||||||
 | 
						return &r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BinaryOp is an expression that performs some operation (defined in the XML
 | 
					// BinaryOp is an expression that performs some operation (defined in the XML
 | 
				
			||||||
// file) with Expr1 and Expr2 as operands.
 | 
					// file) with Expr1 and Expr2 as operands.
 | 
				
			||||||
type BinaryOp struct {
 | 
					type BinaryOp struct {
 | 
				
			||||||
@@ -150,6 +159,13 @@ func (e *BinaryOp) Initialize(p *Protocol) {
 | 
				
			|||||||
	e.Expr2.Initialize(p)
 | 
						e.Expr2.Initialize(p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *BinaryOp) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						r := *e
 | 
				
			||||||
 | 
						r.Expr1 = r.Expr1.Specialize(path)
 | 
				
			||||||
 | 
						r.Expr2 = r.Expr2.Specialize(path)
 | 
				
			||||||
 | 
						return &r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UnaryOp is the same as BinaryOp, except it's a unary operator with only
 | 
					// UnaryOp is the same as BinaryOp, except it's a unary operator with only
 | 
				
			||||||
// one sub-expression.
 | 
					// one sub-expression.
 | 
				
			||||||
type UnaryOp struct {
 | 
					type UnaryOp struct {
 | 
				
			||||||
@@ -186,6 +202,12 @@ func (e *UnaryOp) Initialize(p *Protocol) {
 | 
				
			|||||||
	e.Expr.Initialize(p)
 | 
						e.Expr.Initialize(p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *UnaryOp) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						r := *e
 | 
				
			||||||
 | 
						r.Expr = r.Expr.Specialize(path)
 | 
				
			||||||
 | 
						return &r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Padding represents the application of the 'pad' function to some
 | 
					// Padding represents the application of the 'pad' function to some
 | 
				
			||||||
// sub-expression.
 | 
					// sub-expression.
 | 
				
			||||||
type Padding struct {
 | 
					type Padding struct {
 | 
				
			||||||
@@ -215,6 +237,12 @@ func (e *Padding) Initialize(p *Protocol) {
 | 
				
			|||||||
	e.Expr.Initialize(p)
 | 
						e.Expr.Initialize(p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Padding) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						r := *e
 | 
				
			||||||
 | 
						r.Expr = r.Expr.Specialize(path)
 | 
				
			||||||
 | 
						return &r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PopCount represents the application of the 'PopCount' function to
 | 
					// PopCount represents the application of the 'PopCount' function to
 | 
				
			||||||
// some sub-expression.
 | 
					// some sub-expression.
 | 
				
			||||||
type PopCount struct {
 | 
					type PopCount struct {
 | 
				
			||||||
@@ -244,6 +272,12 @@ func (e *PopCount) Initialize(p *Protocol) {
 | 
				
			|||||||
	e.Expr.Initialize(p)
 | 
						e.Expr.Initialize(p)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *PopCount) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						r := *e
 | 
				
			||||||
 | 
						r.Expr = r.Expr.Specialize(path)
 | 
				
			||||||
 | 
						return &r
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Value represents some constant integer.
 | 
					// Value represents some constant integer.
 | 
				
			||||||
type Value struct {
 | 
					type Value struct {
 | 
				
			||||||
	v int
 | 
						v int
 | 
				
			||||||
@@ -267,6 +301,10 @@ func (e *Value) String() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (e *Value) Initialize(p *Protocol) {}
 | 
					func (e *Value) Initialize(p *Protocol) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Value) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Bit represents some bit whose value is computed by '1 << bit'.
 | 
					// Bit represents some bit whose value is computed by '1 << bit'.
 | 
				
			||||||
type Bit struct {
 | 
					type Bit struct {
 | 
				
			||||||
	b int
 | 
						b int
 | 
				
			||||||
@@ -290,6 +328,10 @@ func (e *Bit) String() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (e *Bit) Initialize(p *Protocol) {}
 | 
					func (e *Bit) Initialize(p *Protocol) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Bit) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FieldRef represents a reference to some variable in the generated code
 | 
					// FieldRef represents a reference to some variable in the generated code
 | 
				
			||||||
// with name Name.
 | 
					// with name Name.
 | 
				
			||||||
type FieldRef struct {
 | 
					type FieldRef struct {
 | 
				
			||||||
@@ -321,6 +363,10 @@ func (e *FieldRef) Initialize(p *Protocol) {
 | 
				
			|||||||
	e.Name = SrcName(p, e.Name)
 | 
						e.Name = SrcName(p, e.Name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *FieldRef) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						return &FieldRef{Name: path + "." + e.Name}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnumRef represents a reference to some enumeration field.
 | 
					// EnumRef represents a reference to some enumeration field.
 | 
				
			||||||
// EnumKind is the "group" an EnumItem is the name of the specific enumeration
 | 
					// EnumKind is the "group" an EnumItem is the name of the specific enumeration
 | 
				
			||||||
// value inside that group.
 | 
					// value inside that group.
 | 
				
			||||||
@@ -351,6 +397,10 @@ func (e *EnumRef) Initialize(p *Protocol) {
 | 
				
			|||||||
	e.EnumItem = SrcName(p, e.EnumItem)
 | 
						e.EnumItem = SrcName(p, e.EnumItem)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *EnumRef) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SumOf represents a summation of the variable in the generated code named by
 | 
					// SumOf represents a summation of the variable in the generated code named by
 | 
				
			||||||
// Name. It is not currently used. (It's XKB voodoo.)
 | 
					// Name. It is not currently used. (It's XKB voodoo.)
 | 
				
			||||||
type SumOf struct {
 | 
					type SumOf struct {
 | 
				
			||||||
@@ -380,3 +430,7 @@ func (e *SumOf) String() string {
 | 
				
			|||||||
func (e *SumOf) Initialize(p *Protocol) {
 | 
					func (e *SumOf) Initialize(p *Protocol) {
 | 
				
			||||||
	e.Name = SrcName(p, e.Name)
 | 
						e.Name = SrcName(p, e.Name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *SumOf) Specialize(path string) Expression {
 | 
				
			||||||
 | 
						return e
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,6 +73,32 @@ func (p *PadField) Size() Size {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RequiredStartAlign struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *RequiredStartAlign) Initialize(p *Protocol) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *RequiredStartAlign) SrcName() string {
 | 
				
			||||||
 | 
						panic("illegal to take source name of a required_start_align field")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *RequiredStartAlign) XmlName() string {
 | 
				
			||||||
 | 
						panic("illegal to take XML name of a required_start_align field")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *RequiredStartAlign) SrcType() string {
 | 
				
			||||||
 | 
						panic("it is illegal to call SrcType on a required_start_align field")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *RequiredStartAlign) Size() Size {
 | 
				
			||||||
 | 
						return newFixedSize(0, true)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *RequiredStartAlign) Define(c *Context) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *RequiredStartAlign) Read(c *Context, prefix string) { }
 | 
				
			||||||
 | 
					func (f *RequiredStartAlign) Write(c *Context, prefix string) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SingleField represents most of the fields in an XML protocol description.
 | 
					// SingleField represents most of the fields in an XML protocol description.
 | 
				
			||||||
// It corresponds to any single value.
 | 
					// It corresponds to any single value.
 | 
				
			||||||
type SingleField struct {
 | 
					type SingleField struct {
 | 
				
			||||||
@@ -289,35 +315,72 @@ func (f *ValueField) Initialize(p *Protocol) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SwitchField represents a 'switch' element in the XML protocol description
 | 
					// SwitchField represents a 'switch' element in the XML protocol description
 | 
				
			||||||
// file. It is not currently used. (i.e., it is XKB voodoo.)
 | 
					// file.
 | 
				
			||||||
 | 
					// Currently we translate this to a slice of uint32 and let the user sort
 | 
				
			||||||
 | 
					// through it. 
 | 
				
			||||||
type SwitchField struct {
 | 
					type SwitchField struct {
 | 
				
			||||||
 | 
						xmlName string
 | 
				
			||||||
	Name     string
 | 
						Name     string
 | 
				
			||||||
 | 
						MaskName string
 | 
				
			||||||
	Expr     Expression
 | 
						Expr     Expression
 | 
				
			||||||
	Bitcases []*Bitcase
 | 
						Bitcases []*Bitcase
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SwitchField) SrcName() string {
 | 
					func (f *SwitchField) SrcName() string {
 | 
				
			||||||
	panic("it is illegal to call SrcName on a SwitchField field")
 | 
						return f.Name
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SwitchField) XmlName() string {
 | 
					func (f *SwitchField) XmlName() string {
 | 
				
			||||||
	panic("it is illegal to call XmlName on a SwitchField field")
 | 
						return f.xmlName
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SwitchField) SrcType() string {
 | 
					func (f *SwitchField) SrcType() string {
 | 
				
			||||||
	panic("it is illegal to call SrcType on a SwitchField field")
 | 
						return "[]uint32"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// XXX: This is a bit tricky. The size has to be represented as a non-concrete
 | 
					 | 
				
			||||||
// expression that finds *which* bitcase fields are included, and sums the
 | 
					 | 
				
			||||||
// sizes of those fields.
 | 
					 | 
				
			||||||
func (f *SwitchField) Size() Size {
 | 
					func (f *SwitchField) Size() Size {
 | 
				
			||||||
	return newFixedSize(0, true)
 | 
						// TODO: size expression used here is not correct unless every element of
 | 
				
			||||||
 | 
						// the switch is 32 bit long. This assumption holds for xproto but may not
 | 
				
			||||||
 | 
						// hold for other protocols (xkb?)
 | 
				
			||||||
 | 
						listSize := newExpressionSize(&Function{
 | 
				
			||||||
 | 
							Name: "xgb.Pad",
 | 
				
			||||||
 | 
							Expr: &BinaryOp{
 | 
				
			||||||
 | 
								Op:    "*",
 | 
				
			||||||
 | 
								Expr1: &Value{v: 4},
 | 
				
			||||||
 | 
								Expr2: &PopCount{
 | 
				
			||||||
 | 
									Expr: &Function{
 | 
				
			||||||
 | 
										Name: "int",
 | 
				
			||||||
 | 
										Expr: &FieldRef{
 | 
				
			||||||
 | 
											Name: f.MaskName,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}, true)
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return listSize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *SwitchField) ListLength() Size {
 | 
				
			||||||
 | 
						return newExpressionSize(&PopCount{
 | 
				
			||||||
 | 
							Expr: &Function{
 | 
				
			||||||
 | 
								Name: "int",
 | 
				
			||||||
 | 
								Expr: &FieldRef{
 | 
				
			||||||
 | 
									Name: f.MaskName,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SwitchField) Initialize(p *Protocol) {
 | 
					func (f *SwitchField) Initialize(p *Protocol) {
 | 
				
			||||||
 | 
						f.xmlName = f.Name
 | 
				
			||||||
	f.Name = SrcName(p, f.Name)
 | 
						f.Name = SrcName(p, f.Name)
 | 
				
			||||||
	f.Expr.Initialize(p)
 | 
						f.Expr.Initialize(p)
 | 
				
			||||||
 | 
						fieldref, ok := f.Expr.(*FieldRef)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							panic("switch field's expression not a fieldref")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						f.MaskName = SrcName(p, fieldref.Name)
 | 
				
			||||||
	for _, bitcase := range f.Bitcases {
 | 
						for _, bitcase := range f.Bitcases {
 | 
				
			||||||
		bitcase.Expr.Initialize(p)
 | 
							bitcase.Expr.Initialize(p)
 | 
				
			||||||
		for _, field := range bitcase.Fields {
 | 
							for _, field := range bitcase.Fields {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -186,11 +186,8 @@ func (f *ValueField) Read(c *Context, prefix string) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ValueField) Write(c *Context, prefix string) {
 | 
					func (f *ValueField) Write(c *Context, prefix string) {
 | 
				
			||||||
	// big time mofos
 | 
						WriteSimpleSingleField(c,
 | 
				
			||||||
	if rq, ok := f.Parent.(*Request); !ok || rq.SrcName() != "ConfigureWindow" {
 | 
							fmt.Sprintf("%s%s", prefix, f.MaskName), f.MaskType)
 | 
				
			||||||
		WriteSimpleSingleField(c,
 | 
					 | 
				
			||||||
			fmt.Sprintf("%s%s", prefix, f.MaskName), f.MaskType)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	c.Putln("for i := 0; i < %s; i++ {", f.ListLength().Reduce(prefix))
 | 
						c.Putln("for i := 0; i < %s; i++ {", f.ListLength().Reduce(prefix))
 | 
				
			||||||
	c.Putln("xgb.Put32(buf[b:], %s%s[i])", prefix, f.ListName)
 | 
						c.Putln("xgb.Put32(buf[b:], %s%s[i])", prefix, f.ListName)
 | 
				
			||||||
	c.Putln("b += 4")
 | 
						c.Putln("b += 4")
 | 
				
			||||||
@@ -200,16 +197,24 @@ func (f *ValueField) Write(c *Context, prefix string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Switch field
 | 
					// Switch field
 | 
				
			||||||
func (f *SwitchField) Define(c *Context) {
 | 
					func (f *SwitchField) Define(c *Context) {
 | 
				
			||||||
	c.Putln("// switch field: %s (%s)", f.Name, f.Expr)
 | 
						c.Putln("%s []uint32", f.Name)
 | 
				
			||||||
	panic("todo")
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SwitchField) Read(c *Context, prefix string) {
 | 
					func (f *SwitchField) Read(c *Context, prefix string) {
 | 
				
			||||||
	c.Putln("// reading switch field: %s (%s)", f.Name, f.Expr)
 | 
						c.Putln("")
 | 
				
			||||||
	panic("todo")
 | 
						c.Putln("%s%s = make([]uint32, %s)",
 | 
				
			||||||
 | 
							prefix, f.Name, f.ListLength().Reduce(prefix))
 | 
				
			||||||
 | 
						c.Putln("for i := 0; i < %s; i++ {", f.ListLength().Reduce(prefix))
 | 
				
			||||||
 | 
						c.Putln("%s%s[i] = xgb.Get32(buf[b:])", prefix, f.Name)
 | 
				
			||||||
 | 
						c.Putln("b += 4")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("b = xgb.Pad(b)")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SwitchField) Write(c *Context, prefix string) {
 | 
					func (f *SwitchField) Write(c *Context, prefix string) {
 | 
				
			||||||
	c.Putln("// writing switch field: %s (%s)", f.Name, f.Expr)
 | 
						c.Putln("for i := 0; i < %s; i++ {", f.ListLength().Reduce(prefix))
 | 
				
			||||||
	panic("todo")
 | 
						c.Putln("xgb.Put32(buf[b:], %s%s[i])", prefix, f.Name)
 | 
				
			||||||
 | 
						c.Putln("b += 4")
 | 
				
			||||||
 | 
						c.Putln("}")
 | 
				
			||||||
 | 
						c.Putln("b = xgb.Pad(b)")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -205,10 +205,7 @@ func (r *Request) ParamNames() string {
 | 
				
			|||||||
	for _, field := range r.Fields {
 | 
						for _, field := range r.Fields {
 | 
				
			||||||
		switch f := field.(type) {
 | 
							switch f := field.(type) {
 | 
				
			||||||
		case *ValueField:
 | 
							case *ValueField:
 | 
				
			||||||
			// mofos...
 | 
								names = append(names, f.MaskName)
 | 
				
			||||||
			if r.SrcName() != "ConfigureWindow" {
 | 
					 | 
				
			||||||
				names = append(names, f.MaskName)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			names = append(names, f.ListName)
 | 
								names = append(names, f.ListName)
 | 
				
			||||||
		case *PadField:
 | 
							case *PadField:
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
@@ -226,17 +223,16 @@ func (r *Request) ParamNameTypes() string {
 | 
				
			|||||||
	for _, field := range r.Fields {
 | 
						for _, field := range r.Fields {
 | 
				
			||||||
		switch f := field.(type) {
 | 
							switch f := field.(type) {
 | 
				
			||||||
		case *ValueField:
 | 
							case *ValueField:
 | 
				
			||||||
			// mofos...
 | 
								nameTypes = append(nameTypes,
 | 
				
			||||||
			if r.SrcName() != "ConfigureWindow" {
 | 
									fmt.Sprintf("%s %s", f.MaskName, f.MaskType.SrcName()))
 | 
				
			||||||
				nameTypes = append(nameTypes,
 | 
					 | 
				
			||||||
					fmt.Sprintf("%s %s", f.MaskName, f.MaskType.SrcName()))
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			nameTypes = append(nameTypes,
 | 
								nameTypes = append(nameTypes,
 | 
				
			||||||
				fmt.Sprintf("%s []uint32", f.ListName))
 | 
									fmt.Sprintf("%s []uint32", f.ListName))
 | 
				
			||||||
		case *PadField:
 | 
							case *PadField:
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		case *ExprField:
 | 
							case *ExprField:
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
 | 
							case *RequiredStartAlign:
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			nameTypes = append(nameTypes,
 | 
								nameTypes = append(nameTypes,
 | 
				
			||||||
				fmt.Sprintf("%s %s", field.SrcName(), field.SrcType()))
 | 
									fmt.Sprintf("%s %s", field.SrcName(), field.SrcType()))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,17 +105,15 @@ func (r *Request) Size(c *Context) Size {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, field := range r.Fields {
 | 
						for _, field := range r.Fields {
 | 
				
			||||||
		switch field.(type) {
 | 
							switch field := field.(type) {
 | 
				
			||||||
		case *LocalField: // local fields don't go over the wire
 | 
							case *LocalField: // local fields don't go over the wire
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		case *SingleField:
 | 
							case *SingleField:
 | 
				
			||||||
			// mofos!!!
 | 
								fsz := field.Size()
 | 
				
			||||||
			if r.SrcName() == "ConfigureWindow" &&
 | 
								if _, isstruct := field.Type.(*Struct); isstruct {
 | 
				
			||||||
				field.SrcName() == "ValueMask" {
 | 
									fsz.Expression = fsz.Expression.Specialize(field.SrcName())
 | 
				
			||||||
 | 
					 | 
				
			||||||
				continue
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			size = size.Add(field.Size())
 | 
								size = size.Add(fsz)
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			size = size.Add(field.Size())
 | 
								size = size.Add(field.Size())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -325,12 +325,14 @@ func (x *XMLField) Translate(parent interface{}) Field {
 | 
				
			|||||||
	case "pad":
 | 
						case "pad":
 | 
				
			||||||
		return &PadField{
 | 
							return &PadField{
 | 
				
			||||||
			Bytes: x.Bytes,
 | 
								Bytes: x.Bytes,
 | 
				
			||||||
 | 
								Align: x.Align,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case "field":
 | 
						case "field":
 | 
				
			||||||
		return &SingleField{
 | 
							s := &SingleField{
 | 
				
			||||||
			xmlName: x.Name,
 | 
								xmlName: x.Name,
 | 
				
			||||||
			Type:    newTranslation(x.Type),
 | 
								Type:    newTranslation(x.Type),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return s
 | 
				
			||||||
	case "list":
 | 
						case "list":
 | 
				
			||||||
		return &ListField{
 | 
							return &ListField{
 | 
				
			||||||
			xmlName:    x.Name,
 | 
								xmlName:    x.Name,
 | 
				
			||||||
@@ -365,6 +367,8 @@ func (x *XMLField) Translate(parent interface{}) Field {
 | 
				
			|||||||
			swtch.Bitcases[i] = bitcase.Translate()
 | 
								swtch.Bitcases[i] = bitcase.Translate()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return swtch
 | 
							return swtch
 | 
				
			||||||
 | 
						case "required_start_align":
 | 
				
			||||||
 | 
							return &RequiredStartAlign{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Panicf("Unrecognized field element: %s", x.XMLName.Local)
 | 
						log.Panicf("Unrecognized field element: %s", x.XMLName.Local)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@ type XMLField struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// For 'pad' element
 | 
						// For 'pad' element
 | 
				
			||||||
	Bytes uint `xml:"bytes,attr"`
 | 
						Bytes uint `xml:"bytes,attr"`
 | 
				
			||||||
 | 
						Align uint16 `xml:"align,attr"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// For 'field', 'list', 'localfield', 'exprfield' and 'switch' elements.
 | 
						// For 'field', 'list', 'localfield', 'exprfield' and 'switch' elements.
 | 
				
			||||||
	Name string `xml:"name,attr"`
 | 
						Name string `xml:"name,attr"`
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user