xgbgen: process <doc> elements
Most of XCB documentation now ends up in Go sources, although the end result is of mixed quality.
This commit is contained in:
		@@ -6,6 +6,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Context represents the protocol we're converting to Go, and a writer
 | 
					// Context represents the protocol we're converting to Go, and a writer
 | 
				
			||||||
@@ -34,6 +35,13 @@ func (c *Context) Put(format string, v ...interface{}) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PutComment writes each line of comment commented out to 'out'.
 | 
				
			||||||
 | 
					func (c *Context) PutComment(comment string) {
 | 
				
			||||||
 | 
						for _, line := range strings.Split(comment, "\n") {
 | 
				
			||||||
 | 
							c.Putln("// %s", line)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Morph is the big daddy of them all. It takes in an XML byte slice,
 | 
					// Morph is the big daddy of them all. It takes in an XML byte slice,
 | 
				
			||||||
// parse it, transforms the XML types into more usable types,
 | 
					// parse it, transforms the XML types into more usable types,
 | 
				
			||||||
// and writes Go code to the 'out' buffer.
 | 
					// and writes Go code to the 'out' buffer.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,6 +105,7 @@ type SingleField struct {
 | 
				
			|||||||
	srcName string
 | 
						srcName string
 | 
				
			||||||
	xmlName string
 | 
						xmlName string
 | 
				
			||||||
	Type    Type
 | 
						Type    Type
 | 
				
			||||||
 | 
						Comment string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SingleField) Initialize(p *Protocol) {
 | 
					func (f *SingleField) Initialize(p *Protocol) {
 | 
				
			||||||
@@ -259,6 +260,8 @@ type ValueField struct {
 | 
				
			|||||||
	MaskType    Type
 | 
						MaskType    Type
 | 
				
			||||||
	MaskName    string
 | 
						MaskName    string
 | 
				
			||||||
	ListName    string
 | 
						ListName    string
 | 
				
			||||||
 | 
						MaskComment string
 | 
				
			||||||
 | 
						ListComment string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *ValueField) SrcName() string {
 | 
					func (f *ValueField) SrcName() string {
 | 
				
			||||||
@@ -324,6 +327,7 @@ type SwitchField struct {
 | 
				
			|||||||
	MaskName string
 | 
						MaskName string
 | 
				
			||||||
	Expr     Expression
 | 
						Expr     Expression
 | 
				
			||||||
	Bitcases []*Bitcase
 | 
						Bitcases []*Bitcase
 | 
				
			||||||
 | 
						Comment  string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SwitchField) SrcName() string {
 | 
					func (f *SwitchField) SrcName() string {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -168,7 +168,13 @@ func (f *ExprField) Write(c *Context, prefix string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Value field
 | 
					// Value field
 | 
				
			||||||
func (f *ValueField) Define(c *Context) {
 | 
					func (f *ValueField) Define(c *Context) {
 | 
				
			||||||
 | 
						if f.MaskComment != "" {
 | 
				
			||||||
 | 
							c.PutComment(f.MaskComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	c.Putln("%s %s", f.MaskName, f.SrcType())
 | 
						c.Putln("%s %s", f.MaskName, f.SrcType())
 | 
				
			||||||
 | 
						if f.ListComment != "" {
 | 
				
			||||||
 | 
							c.PutComment(f.ListComment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	c.Putln("%s []uint32", f.ListName)
 | 
						c.Putln("%s []uint32", f.ListName)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -197,6 +203,9 @@ func (f *ValueField) Write(c *Context, prefix string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Switch field
 | 
					// Switch field
 | 
				
			||||||
func (f *SwitchField) Define(c *Context) {
 | 
					func (f *SwitchField) Define(c *Context) {
 | 
				
			||||||
 | 
						if f.Comment != "" {
 | 
				
			||||||
 | 
							c.PutComment(f.Comment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	c.Putln("%s []uint32", f.Name)
 | 
						c.Putln("%s []uint32", f.Name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,6 +13,33 @@ func (r *Request) Define(c *Context) {
 | 
				
			|||||||
	c.Putln("*xgb.Cookie")
 | 
						c.Putln("*xgb.Cookie")
 | 
				
			||||||
	c.Putln("}")
 | 
						c.Putln("}")
 | 
				
			||||||
	c.Putln("")
 | 
						c.Putln("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.Doc.Description != "" {
 | 
				
			||||||
 | 
							c.PutComment(r.Doc.Description)
 | 
				
			||||||
 | 
							c.Putln("//")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allErrors := make([]string, 0, len(r.Doc.Errors))
 | 
				
			||||||
 | 
						for kind := range r.Doc.Errors {
 | 
				
			||||||
 | 
							allErrors = append(allErrors, kind)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sort.Strings(allErrors)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						undocErrors := make([]string, 0)
 | 
				
			||||||
 | 
						for _, kind := range allErrors {
 | 
				
			||||||
 | 
							if desc := r.Doc.Errors[kind]; desc == "" {
 | 
				
			||||||
 | 
								undocErrors = append(undocErrors, kind)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								c.PutComment(fmt.Sprintf("May return a %s error if %s%s", kind,
 | 
				
			||||||
 | 
									strings.ToLower(desc[:1]), desc[1:]))
 | 
				
			||||||
 | 
								c.Putln("//")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(undocErrors) > 0 {
 | 
				
			||||||
 | 
							c.Putln("// May return %s errors.", strings.Join(undocErrors, ", "))
 | 
				
			||||||
 | 
							c.Putln("//")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if r.Reply != nil {
 | 
						if r.Reply != nil {
 | 
				
			||||||
		c.Putln("// %s sends a checked request.", r.SrcName())
 | 
							c.Putln("// %s sends a checked request.", r.SrcName())
 | 
				
			||||||
		c.Putln("// If an error occurs, it will be returned with the reply "+
 | 
							c.Putln("// If an error occurs, it will be returned with the reply "+
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,9 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *SingleField) Define(c *Context) {
 | 
					func (f *SingleField) Define(c *Context) {
 | 
				
			||||||
 | 
						if f.Comment != "" {
 | 
				
			||||||
 | 
							c.PutComment(f.Comment)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	c.Putln("%s %s", f.SrcName(), f.Type.SrcName())
 | 
						c.Putln("%s %s", f.SrcName(), f.Type.SrcName())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,22 @@ import (
 | 
				
			|||||||
	"unicode"
 | 
						"unicode"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Doc contains any documentation, if present. Example C code is excluded.
 | 
				
			||||||
 | 
					type Doc struct {
 | 
				
			||||||
 | 
						Brief       string            // short description
 | 
				
			||||||
 | 
						Description string            // long description
 | 
				
			||||||
 | 
						Fields      map[string]string // from field name to description
 | 
				
			||||||
 | 
						Errors      map[string]string // from error type to description
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DescribeField is an accessor that supports nil receivers.
 | 
				
			||||||
 | 
					func (d *Doc) DescribeField(name string) string {
 | 
				
			||||||
 | 
						if d == nil {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return d.Fields[name]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Request represents all XML 'request' nodes.
 | 
					// Request represents all XML 'request' nodes.
 | 
				
			||||||
// If the request doesn't have a reply, Reply is nil.
 | 
					// If the request doesn't have a reply, Reply is nil.
 | 
				
			||||||
type Request struct {
 | 
					type Request struct {
 | 
				
			||||||
@@ -15,6 +31,7 @@ type Request struct {
 | 
				
			|||||||
	Combine bool    // Not currently used.
 | 
						Combine bool    // Not currently used.
 | 
				
			||||||
	Fields  []Field // All fields in the request.
 | 
						Fields  []Field // All fields in the request.
 | 
				
			||||||
	Reply   *Reply  // A reply, if one exists for this request.
 | 
						Reply   *Reply  // A reply, if one exists for this request.
 | 
				
			||||||
 | 
						Doc     Doc     // Documentation.
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Requests []*Request
 | 
					type Requests []*Request
 | 
				
			||||||
@@ -126,6 +143,7 @@ func (r *Request) Size(c *Context) Size {
 | 
				
			|||||||
// Reply encapsulates the fields associated with a 'reply' element.
 | 
					// Reply encapsulates the fields associated with a 'reply' element.
 | 
				
			||||||
type Reply struct {
 | 
					type Reply struct {
 | 
				
			||||||
	Fields []Field
 | 
						Fields []Field
 | 
				
			||||||
 | 
						Doc    Doc
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Size gets the number of bytes in this request's reply.
 | 
					// Size gets the number of bytes in this request's reply.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,13 +7,11 @@ the XML type into our "better" representation.
 | 
				
			|||||||
i.e., the representation of Fields and Expressions is just too general.
 | 
					i.e., the representation of Fields and Expressions is just too general.
 | 
				
			||||||
We end up losing a lot of the advantages of static typing if we keep
 | 
					We end up losing a lot of the advantages of static typing if we keep
 | 
				
			||||||
the types that encoding/xml forces us into.
 | 
					the types that encoding/xml forces us into.
 | 
				
			||||||
 | 
					 | 
				
			||||||
Please see 'representation.go' for the type definitions that we're
 | 
					 | 
				
			||||||
translating to.
 | 
					 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -138,12 +136,10 @@ func (x *XMLEvent) Translate() *Event {
 | 
				
			|||||||
		Number:     x.Number,
 | 
							Number:     x.Number,
 | 
				
			||||||
		NoSequence: x.NoSequence,
 | 
							NoSequence: x.NoSequence,
 | 
				
			||||||
		Fields:     make([]Field, 0, len(x.Fields)),
 | 
							Fields:     make([]Field, 0, len(x.Fields)),
 | 
				
			||||||
 | 
							Doc:        x.Doc.Translate(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, field := range x.Fields {
 | 
						for _, field := range x.Fields {
 | 
				
			||||||
		if field.XMLName.Local == "doc" {
 | 
							ev.Fields = append(ev.Fields, field.Translate(ev, &ev.Doc))
 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ev.Fields = append(ev.Fields, field.Translate(ev))
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return ev
 | 
						return ev
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -163,7 +159,7 @@ func (x *XMLError) Translate() *Error {
 | 
				
			|||||||
		Fields:  make([]Field, len(x.Fields)),
 | 
							Fields:  make([]Field, len(x.Fields)),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i, field := range x.Fields {
 | 
						for i, field := range x.Fields {
 | 
				
			||||||
		err.Fields[i] = field.Translate(err)
 | 
							err.Fields[i] = field.Translate(err, nil)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -176,13 +172,82 @@ func (x *XMLErrorCopy) Translate() *ErrorCopy {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// XCB documentation is positively stuffed with TODOs. We'd like to make it
 | 
				
			||||||
 | 
					// look a bit less shitty, so remove those as they don't convey information.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//  ^TODO
 | 
				
			||||||
 | 
					//  ^TODO:
 | 
				
			||||||
 | 
					//  ^TODO: question?
 | 
				
			||||||
 | 
					//  ^TODO: Some words
 | 
				
			||||||
 | 
					//  ^TODO: some words
 | 
				
			||||||
 | 
					//  ^TODO: some words with full stop.
 | 
				
			||||||
 | 
					//  ^TODO: some words with full stop. and a question?
 | 
				
			||||||
 | 
					//  ... (TODO),
 | 
				
			||||||
 | 
					//  ... (TODO).
 | 
				
			||||||
 | 
					//  ... (TODO: a question?).
 | 
				
			||||||
 | 
					//  ... TODO: a question?
 | 
				
			||||||
 | 
					//  ... (word TODO) ...
 | 
				
			||||||
 | 
					var todoRE = regexp.MustCompile(`(?m:^TODO.*| \([^)]*TODO[^)]*\)| TODO:.*)`)
 | 
				
			||||||
 | 
					var paraRE = regexp.MustCompile(`\n{3,}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var backticksRE = regexp.MustCompile("`(?:xcb_|XCB_)?(.*?)(?:_t)?`")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// fixDocumentation tries to translate XCB documentation to match XGB.
 | 
				
			||||||
 | 
					// Note that <doc> blocks only appear in xproto, so this doesn't have that much
 | 
				
			||||||
 | 
					// of a value--users still need to read Xlib or X11 protocol docs.
 | 
				
			||||||
 | 
					// Despite that, it's better to have something than nothing.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// We don't attempt to add proper prefixes to enum values or guess at
 | 
				
			||||||
 | 
					// specific XCB_NONE types (the latter is undecidable).
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// We can't decide whether `fields_len` should be converted to len(Fields)
 | 
				
			||||||
 | 
					// or FieldsLen because e.g. StringLen is retained in ImageText8/16 but
 | 
				
			||||||
 | 
					// PointsLen is implied by the length of the Points slice in PolyLine.
 | 
				
			||||||
 | 
					func fixDocumentation(xcb string) string {
 | 
				
			||||||
 | 
						last, result := 0, make([]byte, 0, len(xcb))
 | 
				
			||||||
 | 
						for _, m := range backticksRE.FindAllStringSubmatchIndex(xcb, -1) {
 | 
				
			||||||
 | 
							result = append(result, xcb[last:m[0]]...)
 | 
				
			||||||
 | 
							inner := xcb[m[2]:m[3]]
 | 
				
			||||||
 | 
							last = m[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Do not convert atom names to identifiers, mainly _NET_WM_*.
 | 
				
			||||||
 | 
							if strings.Contains(inner, "WM_") {
 | 
				
			||||||
 | 
								result = append(result, inner...)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								result = append(result, splitAndTitle(inner)...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						result = todoRE.ReplaceAllLiteral(append(result, xcb[last:]...), nil)
 | 
				
			||||||
 | 
						result = paraRE.ReplaceAllLiteral(result, []byte("\n\n"))
 | 
				
			||||||
 | 
						return strings.TrimSpace(string(result))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (x *XMLDoc) Translate() Doc {
 | 
				
			||||||
 | 
						if x == nil {
 | 
				
			||||||
 | 
							return Doc{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						d := Doc{
 | 
				
			||||||
 | 
							Brief:       fixDocumentation(x.Brief),
 | 
				
			||||||
 | 
							Description: fixDocumentation(x.Description),
 | 
				
			||||||
 | 
							Fields:      make(map[string]string),
 | 
				
			||||||
 | 
							Errors:      make(map[string]string),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, x := range x.Fields {
 | 
				
			||||||
 | 
							d.Fields[x.Name] = fixDocumentation(x.Description)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, x := range x.Errors {
 | 
				
			||||||
 | 
							d.Errors[x.Type] = fixDocumentation(x.Description)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return d
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *XMLStruct) Translate() *Struct {
 | 
					func (x *XMLStruct) Translate() *Struct {
 | 
				
			||||||
	s := &Struct{
 | 
						s := &Struct{
 | 
				
			||||||
		xmlName: x.Name,
 | 
							xmlName: x.Name,
 | 
				
			||||||
		Fields:  make([]Field, len(x.Fields)),
 | 
							Fields:  make([]Field, len(x.Fields)),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i, field := range x.Fields {
 | 
						for i, field := range x.Fields {
 | 
				
			||||||
		s.Fields[i] = field.Translate(s)
 | 
							s.Fields[i] = field.Translate(s, nil)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return s
 | 
						return s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -193,7 +258,7 @@ func (x *XMLUnion) Translate() *Union {
 | 
				
			|||||||
		Fields:  make([]Field, len(x.Fields)),
 | 
							Fields:  make([]Field, len(x.Fields)),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i, field := range x.Fields {
 | 
						for i, field := range x.Fields {
 | 
				
			||||||
		u.Fields[i] = field.Translate(u)
 | 
							u.Fields[i] = field.Translate(u, nil)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return u
 | 
						return u
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -205,12 +270,13 @@ func (x *XMLRequest) Translate() *Request {
 | 
				
			|||||||
		Combine: x.Combine,
 | 
							Combine: x.Combine,
 | 
				
			||||||
		Fields:  make([]Field, 0, len(x.Fields)),
 | 
							Fields:  make([]Field, 0, len(x.Fields)),
 | 
				
			||||||
		Reply:   x.Reply.Translate(),
 | 
							Reply:   x.Reply.Translate(),
 | 
				
			||||||
 | 
							Doc:     x.Doc.Translate(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, field := range x.Fields {
 | 
						for _, field := range x.Fields {
 | 
				
			||||||
		if field.XMLName.Local == "doc" || field.XMLName.Local == "fd" {
 | 
							if field.XMLName.Local == "fd" {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		r.Fields = append(r.Fields, field.Translate(r))
 | 
							r.Fields = append(r.Fields, field.Translate(r, &r.Doc))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Address bug (or legacy code) in QueryTextExtents.
 | 
						// Address bug (or legacy code) in QueryTextExtents.
 | 
				
			||||||
@@ -236,12 +302,13 @@ func (x *XMLReply) Translate() *Reply {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	r := &Reply{
 | 
						r := &Reply{
 | 
				
			||||||
		Fields: make([]Field, 0, len(x.Fields)),
 | 
							Fields: make([]Field, 0, len(x.Fields)),
 | 
				
			||||||
 | 
							Doc:    x.Doc.Translate(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, field := range x.Fields {
 | 
						for _, field := range x.Fields {
 | 
				
			||||||
		if field.XMLName.Local == "doc" || field.XMLName.Local == "fd" {
 | 
							if field.XMLName.Local == "fd" {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		r.Fields = append(r.Fields, field.Translate(r))
 | 
							r.Fields = append(r.Fields, field.Translate(r, &r.Doc))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r
 | 
						return r
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -320,7 +387,7 @@ func (x *XMLExpression) Translate() Expression {
 | 
				
			|||||||
	panic("unreachable")
 | 
						panic("unreachable")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (x *XMLField) Translate(parent interface{}) Field {
 | 
					func (x *XMLField) Translate(parent interface{}, doc *Doc) Field {
 | 
				
			||||||
	switch x.XMLName.Local {
 | 
						switch x.XMLName.Local {
 | 
				
			||||||
	case "pad":
 | 
						case "pad":
 | 
				
			||||||
		return &PadField{
 | 
							return &PadField{
 | 
				
			||||||
@@ -331,6 +398,7 @@ func (x *XMLField) Translate(parent interface{}) Field {
 | 
				
			|||||||
		s := &SingleField{
 | 
							s := &SingleField{
 | 
				
			||||||
			xmlName: x.Name,
 | 
								xmlName: x.Name,
 | 
				
			||||||
			Type:    newTranslation(x.Type),
 | 
								Type:    newTranslation(x.Type),
 | 
				
			||||||
 | 
								Comment: doc.DescribeField(x.Name),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return s
 | 
							return s
 | 
				
			||||||
	case "list":
 | 
						case "list":
 | 
				
			||||||
@@ -356,12 +424,15 @@ func (x *XMLField) Translate(parent interface{}) Field {
 | 
				
			|||||||
			MaskType:    newTranslation(x.ValueMaskType),
 | 
								MaskType:    newTranslation(x.ValueMaskType),
 | 
				
			||||||
			MaskName:    x.ValueMaskName,
 | 
								MaskName:    x.ValueMaskName,
 | 
				
			||||||
			ListName:    x.ValueListName,
 | 
								ListName:    x.ValueListName,
 | 
				
			||||||
 | 
								MaskComment: doc.DescribeField(x.ValueMaskName),
 | 
				
			||||||
 | 
								ListComment: doc.DescribeField(x.ValueListName),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case "switch":
 | 
						case "switch":
 | 
				
			||||||
		swtch := &SwitchField{
 | 
							swtch := &SwitchField{
 | 
				
			||||||
			Name:     x.Name,
 | 
								Name:     x.Name,
 | 
				
			||||||
			Expr:     x.Expr.Translate(),
 | 
								Expr:     x.Expr.Translate(),
 | 
				
			||||||
			Bitcases: make([]*Bitcase, len(x.Bitcases)),
 | 
								Bitcases: make([]*Bitcase, len(x.Bitcases)),
 | 
				
			||||||
 | 
								Comment:  doc.DescribeField(x.Name),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for i, bitcase := range x.Bitcases {
 | 
							for i, bitcase := range x.Bitcases {
 | 
				
			||||||
			swtch.Bitcases[i] = bitcase.Translate()
 | 
								swtch.Bitcases[i] = bitcase.Translate()
 | 
				
			||||||
@@ -381,7 +452,7 @@ func (x *XMLBitcase) Translate() *Bitcase {
 | 
				
			|||||||
		Fields: make([]Field, len(x.Fields)),
 | 
							Fields: make([]Field, len(x.Fields)),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i, field := range x.Fields {
 | 
						for i, field := range x.Fields {
 | 
				
			||||||
		b.Fields[i] = field.Translate(b)
 | 
							b.Fields[i] = field.Translate(b, nil)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return b
 | 
						return b
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -190,6 +190,7 @@ type Event struct {
 | 
				
			|||||||
	Number     int
 | 
						Number     int
 | 
				
			||||||
	NoSequence bool
 | 
						NoSequence bool
 | 
				
			||||||
	Fields     []Field
 | 
						Fields     []Field
 | 
				
			||||||
 | 
						Doc        Doc
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (e *Event) SrcName() string {
 | 
					func (e *Event) SrcName() string {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,6 +92,24 @@ type XMLErrorCopy struct {
 | 
				
			|||||||
	Ref    string `xml:"ref,attr"`
 | 
						Ref    string `xml:"ref,attr"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type XMLDocField struct {
 | 
				
			||||||
 | 
						Name        string `xml:"name,attr"`
 | 
				
			||||||
 | 
						Description string `xml:",chardata"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type XMLDocError struct {
 | 
				
			||||||
 | 
						Type        string `xml:"type,attr"`
 | 
				
			||||||
 | 
						Description string `xml:",chardata"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type XMLDoc struct {
 | 
				
			||||||
 | 
						Brief       string         `xml:"brief"`
 | 
				
			||||||
 | 
						Description string         `xml:"description"`
 | 
				
			||||||
 | 
						Example     string         `xml:"example"`
 | 
				
			||||||
 | 
						Fields      []*XMLDocField `xml:"field"`
 | 
				
			||||||
 | 
						Errors      []*XMLDocError `xml:"error"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type XMLStruct struct {
 | 
					type XMLStruct struct {
 | 
				
			||||||
	Name   string      `xml:"name,attr"`
 | 
						Name   string      `xml:"name,attr"`
 | 
				
			||||||
	Fields []*XMLField `xml:",any"`
 | 
						Fields []*XMLField `xml:",any"`
 | 
				
			||||||
@@ -108,10 +126,12 @@ type XMLRequest struct {
 | 
				
			|||||||
	Combine bool        `xml:"combine-adjacent,attr"`
 | 
						Combine bool        `xml:"combine-adjacent,attr"`
 | 
				
			||||||
	Fields  []*XMLField `xml:",any"`
 | 
						Fields  []*XMLField `xml:",any"`
 | 
				
			||||||
	Reply   *XMLReply   `xml:"reply"`
 | 
						Reply   *XMLReply   `xml:"reply"`
 | 
				
			||||||
 | 
						Doc     *XMLDoc     `xml:"doc"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type XMLReply struct {
 | 
					type XMLReply struct {
 | 
				
			||||||
	Fields []*XMLField `xml:",any"`
 | 
						Fields []*XMLField `xml:",any"`
 | 
				
			||||||
 | 
						Doc    *XMLDoc     `xml:"doc"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type XMLEvent struct {
 | 
					type XMLEvent struct {
 | 
				
			||||||
@@ -119,6 +139,7 @@ type XMLEvent struct {
 | 
				
			|||||||
	Number     int         `xml:"number,attr"`
 | 
						Number     int         `xml:"number,attr"`
 | 
				
			||||||
	NoSequence bool        `xml:"no-sequence-number,attr"`
 | 
						NoSequence bool        `xml:"no-sequence-number,attr"`
 | 
				
			||||||
	Fields     []*XMLField `xml:",any"`
 | 
						Fields     []*XMLField `xml:",any"`
 | 
				
			||||||
 | 
						Doc        *XMLDoc     `xml:"doc"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type XMLError struct {
 | 
					type XMLError struct {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user