syncthing/vendor/github.com/calmh/xdr/cmd/genxdr/main.go

587 lines
13 KiB
Go
Raw Normal View History

2014-08-01 11:12:54 +00:00
// Copyright (C) 2014 Jakob Borg. All rights reserved. Use of this source code
// is governed by an MIT-style license that can be found in the LICENSE file.
2014-02-20 16:40:15 +00:00
package main
import (
"bytes"
"flag"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/token"
2014-12-06 13:20:49 +00:00
"io"
"log"
2014-02-20 16:40:15 +00:00
"os"
"regexp"
"strconv"
"strings"
"text/template"
)
2014-07-13 07:23:10 +00:00
type fieldInfo struct {
2014-02-20 16:40:15 +00:00
Name string
2014-07-13 07:23:10 +00:00
IsBasic bool // handled by one the native Read/WriteUint64 etc functions
IsSlice bool // field is a slice of FieldType
FieldType string // original type of field, i.e. "int"
Encoder string // the encoder name, i.e. "Uint64" for Read/WriteUint64
Convert string // what to convert to when encoding, i.e. "uint64"
Max int // max size for slices and strings
2015-10-06 23:37:08 +00:00
Submax int // max size for strings inside slices
2014-07-13 07:23:10 +00:00
}
type structInfo struct {
Name string
Fields []fieldInfo
2014-02-20 16:40:15 +00:00
}
2016-02-02 11:43:33 +00:00
func (i structInfo) SizeExpr() string {
var xdrSizes = map[string]int{
"int8": 4,
"uint8": 4,
"int16": 4,
"uint16": 4,
"int32": 4,
"uint32": 4,
"int64": 8,
"uint64": 8,
"int": 8,
"bool": 4,
}
var terms []string
nl := ""
for _, f := range i.Fields {
if size := xdrSizes[f.FieldType]; size > 0 {
if f.IsSlice {
terms = append(terms, nl+"4+len(o."+f.Name+")*"+strconv.Itoa(size))
} else {
terms = append(terms, strconv.Itoa(size))
}
} else {
switch f.FieldType {
case "string", "[]byte":
if f.IsSlice {
terms = append(terms, nl+"4+xdr.SizeOfSlice(o."+f.Name+")")
} else {
terms = append(terms, nl+"4+len(o."+f.Name+")+xdr.Padding(len(o."+f.Name+"))")
}
default:
if f.IsSlice {
terms = append(terms, nl+"4+xdr.SizeOfSlice(o."+f.Name+")")
} else {
terms = append(terms, nl+"o."+f.Name+".XDRSize()")
}
}
}
nl = "\n"
}
return strings.Join(terms, "+")
}
var headerData = `// ************************************************************
2014-07-13 07:23:10 +00:00
// This file is automatically generated by genxdr. Do not edit.
// ************************************************************
package {{.Package}}
2014-02-20 16:40:15 +00:00
import (
2014-08-01 11:12:54 +00:00
"github.com/calmh/xdr"
2014-02-20 16:40:15 +00:00
)
2016-02-02 11:43:33 +00:00
`
2014-02-20 16:40:15 +00:00
2016-02-02 11:43:33 +00:00
var encoderData = `
func (o {{.Name}}) XDRSize() int {
return {{.SizeExpr}}
2014-02-20 16:40:15 +00:00
}//+n
2016-02-02 11:43:33 +00:00
func (o {{.Name}}) MarshalXDR() ([]byte, error) {
buf:= make([]byte, o.XDRSize())
m := &xdr.Marshaller{Data: buf}
return buf, o.MarshalXDRInto(m)
}//+n
2016-02-02 11:43:33 +00:00
func (o {{.Name}}) MustMarshalXDR() []byte {
2014-10-21 06:40:05 +00:00
bs, err := o.MarshalXDR()
if err != nil {
panic(err)
}
return bs
}//+n
2016-02-02 11:43:33 +00:00
func (o {{.Name}}) MarshalXDRInto(m *xdr.Marshaller) error {
{{range $fi := .Fields}}
{{if $fi.IsSlice}}
{{template "marshalSlice" $fi}}
{{else}}
{{template "marshalValue" $fi}}
{{end}}
{{end}}
return m.Error
2014-02-20 16:40:15 +00:00
}//+n
2016-02-02 11:43:33 +00:00
{{define "marshalValue"}}
{{if ne .Convert ""}}
m.Marshal{{.Encoder}}({{.Convert}}(o.{{.Name}}))
{{else if .IsBasic}}
{{if ge .Max 1}}
if l := len(o.{{.Name}}); l > {{.Max}} {
return xdr.ElementSizeExceeded("{{.Name}}", l, {{.Max}})
2014-07-13 07:23:10 +00:00
}
2014-02-20 16:40:15 +00:00
{{end}}
2016-02-02 11:43:33 +00:00
m.Marshal{{.Encoder}}(o.{{.Name}})
{{else}}
if err := o.{{.Name}}.MarshalXDRInto(m); err != nil {
return err
}
2014-02-20 16:40:15 +00:00
{{end}}
2016-02-02 11:43:33 +00:00
{{end}}
2014-02-20 16:40:15 +00:00
2016-02-02 11:43:33 +00:00
{{define "marshalSlice"}}
{{if ge .Max 1}}
if l := len(o.{{.Name}}); l > {{.Max}} {
return xdr.ElementSizeExceeded("{{.Name}}", l, {{.Max}})
}
{{end}}
m.MarshalUint32(uint32(len(o.{{.Name}})))
for i := range o.{{.Name}} {
{{if ne .Convert ""}}
m.Marshal{{.Encoder}}({{.Convert}}(o.{{.Name}}[i]))
{{else if .IsBasic}}
m.Marshal{{.Encoder}}(o.{{.Name}}[i])
{{else}}
if err := o.{{.Name}}[i].MarshalXDRInto(m); err != nil {
return err
}
{{end}}
}
{{end}}
2014-02-20 16:40:15 +00:00
2016-02-02 11:43:33 +00:00
func (o *{{.Name}}) UnmarshalXDR(bs []byte) error {
u := &xdr.Unmarshaller{Data: bs}
return o.UnmarshalXDRFrom(u)
}
func (o *{{.Name}}) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
{{range $fi := .Fields}}
{{if $fi.IsSlice}}
{{template "unmarshalSlice" $fi}}
{{else}}
{{template "unmarshalValue" $fi}}
{{end}}
{{end}}
return u.Error
2014-02-20 16:40:15 +00:00
}//+n
2016-02-02 11:43:33 +00:00
{{define "unmarshalValue"}}
{{if ne .Convert ""}}
o.{{.Name}} = {{.FieldType}}(u.Unmarshal{{.Encoder}}())
{{else if .IsBasic}}
{{if ge .Max 1}}
o.{{.Name}} = u.Unmarshal{{.Encoder}}Max({{.Max}})
2014-02-20 16:40:15 +00:00
{{else}}
2016-02-02 11:43:33 +00:00
o.{{.Name}} = u.Unmarshal{{.Encoder}}()
{{end}}
{{else}}
(&o.{{.Name}}).UnmarshalXDRFrom(u)
{{end}}
{{end}}
{{define "unmarshalSlice"}}
_{{.Name}}Size := int(u.UnmarshalUint32())
if _{{.Name}}Size < 0 {
return xdr.ElementSizeExceeded("{{.Name}}", _{{.Name}}Size, {{.Max}})
} else if _{{.Name}}Size == 0 {
o.{{.Name}} = nil
} else {
{{if ge .Max 1}}
if _{{.Name}}Size > {{.Max}} {
return xdr.ElementSizeExceeded("{{.Name}}", _{{.Name}}Size, {{.Max}})
2015-04-08 12:44:47 +00:00
}
2016-02-02 11:43:33 +00:00
{{end}}
if _{{.Name}}Size <= len(o.{{.Name}}) {
{{if eq .FieldType "string"}}
for i := _{{.Name}}Size; i < len(o.{{.Name}}); i++ { o.{{.Name}}[i] = "" }
2014-07-13 07:23:10 +00:00
{{end}}
2016-02-02 11:43:33 +00:00
{{if eq .FieldType "[]byte"}}
for i := _{{.Name}}Size; i < len(o.{{.Name}}); i++ { o.{{.Name}}[i] = nil }
{{end}}
o.{{.Name}} = o.{{.Name}}[:_{{.Name}}Size]
} else {
o.{{.Name}} = make([]{{.FieldType}}, _{{.Name}}Size)
}
for i := range o.{{.Name}} {
{{if ne .Convert ""}}
o.{{.Name}}[i] = {{.FieldType}}(u.Unmarshal{{.Encoder}}())
{{else if .IsBasic}}
{{if ge .Submax 1}}
o.{{.Name}}[i] = u.Unmarshal{{.Encoder}}Max({{.Submax}})
2014-07-13 07:23:10 +00:00
{{else}}
2016-02-02 11:43:33 +00:00
o.{{.Name}}[i] = u.Unmarshal{{.Encoder}}()
2014-07-13 07:23:10 +00:00
{{end}}
2016-02-02 11:43:33 +00:00
{{else}}
(&o.{{.Name}}[i]).UnmarshalXDRFrom(u)
{{end}}
}
}
{{end}}
`
var (
encodeTpl = template.Must(template.New("encoder").Parse(encoderData))
headerTpl = template.Must(template.New("header").Parse(headerData))
)
2014-02-20 16:40:15 +00:00
2015-11-24 19:54:49 +00:00
var emptyTypeTpl = template.Must(template.New("encoder").Parse(`
2016-02-02 11:43:33 +00:00
func (o {{.Name}}) XDRSize() int {
return 0
}
2015-11-24 19:54:49 +00:00
2016-02-02 11:43:33 +00:00
func (o {{.Name}}) MarshalXDR() ([]byte, error) {
2015-11-24 19:54:49 +00:00
return nil, nil
}//+n
2016-02-02 11:43:33 +00:00
func (o {{.Name}}) MustMarshalXDR() []byte {
2015-11-24 19:54:49 +00:00
return nil
}//+n
2016-02-02 11:43:33 +00:00
func (o {{.Name}}) MarshalXDRInto(m *xdr.Marshaller) error {
return nil
2015-11-24 19:54:49 +00:00
}//+n
2016-02-02 11:43:33 +00:00
func (o *{{.Name}}) UnmarshalXDR(bs []byte) error {
2015-11-24 19:54:49 +00:00
return nil
}//+n
2016-02-02 11:43:33 +00:00
func (o *{{.Name}}) UnmarshalXDRFrom(u *xdr.Unmarshaller) error {
2015-11-24 19:54:49 +00:00
return nil
}//+n
2016-02-02 11:43:33 +00:00
`))
2015-11-24 19:54:49 +00:00
2015-10-06 23:37:08 +00:00
var maxRe = regexp.MustCompile(`(?:\Wmax:)(\d+)(?:\s*,\s*(\d+))?`)
2014-02-20 16:40:15 +00:00
type typeSet struct {
Type string
Encoder string
}
var xdrEncoders = map[string]typeSet{
2014-08-01 11:12:54 +00:00
"int8": typeSet{"uint8", "Uint8"},
"uint8": typeSet{"", "Uint8"},
2014-02-20 16:40:15 +00:00
"int16": typeSet{"uint16", "Uint16"},
"uint16": typeSet{"", "Uint16"},
"int32": typeSet{"uint32", "Uint32"},
"uint32": typeSet{"", "Uint32"},
"int64": typeSet{"uint64", "Uint64"},
"uint64": typeSet{"", "Uint64"},
"int": typeSet{"uint64", "Uint64"},
"string": typeSet{"", "String"},
"[]byte": typeSet{"", "Bytes"},
"bool": typeSet{"", "Bool"},
}
2014-07-13 07:23:10 +00:00
func handleStruct(t *ast.StructType) []fieldInfo {
var fs []fieldInfo
2014-02-20 16:40:15 +00:00
for _, sf := range t.Fields.List {
if len(sf.Names) == 0 {
// We don't handle anonymous fields
continue
}
fn := sf.Names[0].Name
2015-10-06 23:37:08 +00:00
var max1, max2 int
2014-02-20 16:40:15 +00:00
if sf.Comment != nil {
c := sf.Comment.List[0].Text
2015-10-06 23:37:08 +00:00
m := maxRe.FindStringSubmatch(c)
if len(m) >= 2 {
max1, _ = strconv.Atoi(m[1])
}
if len(m) >= 3 {
max2, _ = strconv.Atoi(m[2])
2014-02-20 16:40:15 +00:00
}
2014-07-12 21:06:48 +00:00
if strings.Contains(c, "noencode") {
continue
}
2014-02-20 16:40:15 +00:00
}
2014-07-13 07:23:10 +00:00
var f fieldInfo
2014-02-20 16:40:15 +00:00
switch ft := sf.Type.(type) {
case *ast.Ident:
tn := ft.Name
if enc, ok := xdrEncoders[tn]; ok {
2014-07-13 07:23:10 +00:00
f = fieldInfo{
2014-02-20 16:40:15 +00:00
Name: fn,
IsBasic: true,
FieldType: tn,
Encoder: enc.Encoder,
Convert: enc.Type,
2015-10-06 23:37:08 +00:00
Max: max1,
Submax: max2,
2014-02-20 16:40:15 +00:00
}
} else {
2014-07-13 07:23:10 +00:00
f = fieldInfo{
2014-02-20 16:40:15 +00:00
Name: fn,
IsBasic: false,
FieldType: tn,
2015-10-06 23:37:08 +00:00
Max: max1,
Submax: max2,
2014-02-20 16:40:15 +00:00
}
}
case *ast.ArrayType:
if ft.Len != nil {
// We don't handle arrays
continue
}
tn := ft.Elt.(*ast.Ident).Name
if enc, ok := xdrEncoders["[]"+tn]; ok {
2014-07-13 07:23:10 +00:00
f = fieldInfo{
2014-02-20 16:40:15 +00:00
Name: fn,
IsBasic: true,
2016-02-02 11:43:33 +00:00
FieldType: "[]" + tn,
2014-02-20 16:40:15 +00:00
Encoder: enc.Encoder,
Convert: enc.Type,
2015-10-06 23:37:08 +00:00
Max: max1,
Submax: max2,
2014-02-20 16:40:15 +00:00
}
} else if enc, ok := xdrEncoders[tn]; ok {
2014-07-13 07:23:10 +00:00
f = fieldInfo{
2014-02-20 16:40:15 +00:00
Name: fn,
IsBasic: true,
IsSlice: true,
FieldType: tn,
Encoder: enc.Encoder,
Convert: enc.Type,
2015-10-06 23:37:08 +00:00
Max: max1,
Submax: max2,
2014-02-20 16:40:15 +00:00
}
} else {
2014-07-13 07:23:10 +00:00
f = fieldInfo{
2014-02-20 16:40:15 +00:00
Name: fn,
IsSlice: true,
FieldType: tn,
2015-10-06 23:37:08 +00:00
Max: max1,
Submax: max2,
2014-02-20 16:40:15 +00:00
}
}
case *ast.SelectorExpr:
f = fieldInfo{
Name: fn,
FieldType: ft.Sel.Name,
2015-10-06 23:37:08 +00:00
Max: max1,
Submax: max2,
}
2014-02-20 16:40:15 +00:00
}
fs = append(fs, f)
}
2014-07-13 07:23:10 +00:00
return fs
2014-02-20 16:40:15 +00:00
}
2014-12-06 13:20:49 +00:00
func generateCode(output io.Writer, s structInfo) {
2014-02-20 16:40:15 +00:00
var buf bytes.Buffer
2015-11-24 19:54:49 +00:00
var err error
2016-02-02 11:43:33 +00:00
if len(s.Fields) == 0 {
2015-11-24 19:54:49 +00:00
// This is an empty type. We can create a quite simple codec for it.
2016-02-02 11:43:33 +00:00
err = emptyTypeTpl.Execute(&buf, s)
2015-11-24 19:54:49 +00:00
} else {
// Generate with the default template.
2016-02-02 11:43:33 +00:00
err = encodeTpl.Execute(&buf, s)
2015-11-24 19:54:49 +00:00
}
2014-02-20 16:40:15 +00:00
if err != nil {
panic(err)
}
bs := regexp.MustCompile(`(\s*\n)+`).ReplaceAll(buf.Bytes(), []byte("\n"))
bs = bytes.Replace(bs, []byte("//+n"), []byte("\n"), -1)
2016-02-02 11:43:33 +00:00
output.Write(bs)
2014-02-20 16:40:15 +00:00
}
2014-07-13 07:23:10 +00:00
func uncamelize(s string) string {
return regexp.MustCompile("[a-z][A-Z]").ReplaceAllStringFunc(s, func(camel string) string {
return camel[:1] + " " + camel[1:]
})
}
2014-12-06 13:20:49 +00:00
func generateDiagram(output io.Writer, s structInfo) {
2014-07-13 07:23:10 +00:00
sn := s.Name
fs := s.Fields
2014-12-06 13:20:49 +00:00
fmt.Fprintln(output, sn+" Structure:")
2015-11-24 19:54:49 +00:00
if len(fs) == 0 {
fmt.Fprintln(output, "(contains no fields)")
fmt.Fprintln(output)
fmt.Fprintln(output)
return
}
2014-12-06 13:20:49 +00:00
fmt.Fprintln(output)
fmt.Fprintln(output, " 0 1 2 3")
fmt.Fprintln(output, " 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1")
2014-02-20 16:40:15 +00:00
line := "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"
2014-12-06 13:20:49 +00:00
fmt.Fprintln(output, line)
2014-02-20 16:40:15 +00:00
for _, f := range fs {
tn := f.FieldType
2014-07-13 07:23:10 +00:00
name := uncamelize(f.Name)
2014-02-20 16:40:15 +00:00
2016-02-02 11:43:33 +00:00
suffix := ""
2015-03-25 21:35:05 +00:00
if f.IsSlice {
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "| %s |\n", center("Number of "+name, 61))
fmt.Fprintln(output, line)
2016-02-02 11:43:33 +00:00
suffix = " (n items)"
fmt.Fprintf(output, "/ %s /\n", center("", 61))
2014-02-20 16:40:15 +00:00
}
switch tn {
2014-07-13 07:23:10 +00:00
case "bool":
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "| %s |V|\n", center(name+" (V=0 or 1)", 59))
2015-01-22 20:53:10 +00:00
case "int16", "uint16":
2016-02-02 11:43:33 +00:00
fmt.Fprintf(output, "| %s | %s |\n", center("16 zero bits", 29), center(name, 29))
case "int8", "uint8":
fmt.Fprintf(output, "| %s | %s |\n", center("24 zero bits", 45), center(name, 13))
2015-01-22 20:53:10 +00:00
case "int32", "uint32":
2016-02-02 11:43:33 +00:00
fmt.Fprintf(output, "| %s |\n", center(name+suffix, 61))
2014-02-20 16:40:15 +00:00
case "int64", "uint64":
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "| %-61s |\n", "")
fmt.Fprintf(output, "+ %s +\n", center(name+" (64 bits)", 61))
fmt.Fprintf(output, "| %-61s |\n", "")
2016-02-02 11:43:33 +00:00
case "string", "[]byte":
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "/ %61s /\n", "")
2016-02-02 11:43:33 +00:00
fmt.Fprintf(output, "\\ %s \\\n", center(name+" (length + padded data)", 61))
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "/ %61s /\n", "")
2014-02-20 16:40:15 +00:00
default:
2015-03-25 21:35:05 +00:00
if f.IsSlice {
2014-02-20 16:40:15 +00:00
tn = "Zero or more " + tn + " Structures"
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "\\ %s \\\n", center(tn, 61))
2014-02-20 16:40:15 +00:00
} else {
tn = tn + " Structure"
fmt.Fprintf(output, "/ %s /\n", center("", 61))
fmt.Fprintf(output, "\\ %s \\\n", center(tn, 61))
fmt.Fprintf(output, "/ %s /\n", center("", 61))
2014-02-20 16:40:15 +00:00
}
}
2016-02-02 11:43:33 +00:00
if f.IsSlice {
fmt.Fprintf(output, "/ %s /\n", center("", 61))
}
fmt.Fprintln(output, line)
2014-02-20 16:40:15 +00:00
}
2014-12-06 13:20:49 +00:00
fmt.Fprintln(output)
fmt.Fprintln(output)
2014-02-20 16:40:15 +00:00
}
2014-12-06 13:20:49 +00:00
func generateXdr(output io.Writer, s structInfo) {
2014-07-13 07:23:10 +00:00
sn := s.Name
fs := s.Fields
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "struct %s {\n", sn)
2014-02-20 16:40:15 +00:00
for _, f := range fs {
tn := f.FieldType
fn := f.Name
suf := ""
2014-07-13 07:23:10 +00:00
l := ""
if f.Max > 0 {
l = strconv.Itoa(f.Max)
}
2014-02-20 16:40:15 +00:00
if f.IsSlice {
2014-07-13 07:23:10 +00:00
suf = "<" + l + ">"
2014-02-20 16:40:15 +00:00
}
switch tn {
2016-02-02 11:43:33 +00:00
case "int8", "int16", "int32":
2015-01-22 20:53:10 +00:00
fmt.Fprintf(output, "\tint %s%s;\n", fn, suf)
2016-02-02 11:43:33 +00:00
case "uint8", "uint16", "uint32":
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "\tunsigned int %s%s;\n", fn, suf)
2014-02-20 16:40:15 +00:00
case "int64":
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "\thyper %s%s;\n", fn, suf)
2014-02-20 16:40:15 +00:00
case "uint64":
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "\tunsigned hyper %s%s;\n", fn, suf)
2014-02-20 16:40:15 +00:00
case "string":
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "\tstring %s<%s>;\n", fn, l)
2016-02-02 11:43:33 +00:00
case "[]byte":
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "\topaque %s<%s>;\n", fn, l)
2014-02-20 16:40:15 +00:00
default:
2014-12-06 13:20:49 +00:00
fmt.Fprintf(output, "\t%s %s%s;\n", tn, fn, suf)
2014-02-20 16:40:15 +00:00
}
}
2014-12-06 13:20:49 +00:00
fmt.Fprintln(output, "}")
fmt.Fprintln(output)
2014-02-20 16:40:15 +00:00
}
func center(s string, w int) string {
w -= len(s)
l := w / 2
r := l
if l+r < w {
r++
}
return strings.Repeat(" ", l) + s + strings.Repeat(" ", r)
}
2014-07-13 07:23:10 +00:00
func inspector(structs *[]structInfo) func(ast.Node) bool {
2014-02-20 16:40:15 +00:00
return func(n ast.Node) bool {
switch n := n.(type) {
case *ast.TypeSpec:
switch t := n.Type.(type) {
case *ast.StructType:
name := n.Name.Name
2014-07-13 07:23:10 +00:00
fs := handleStruct(t)
*structs = append(*structs, structInfo{name, fs})
2014-02-20 16:40:15 +00:00
}
return false
default:
return true
}
}
}
func main() {
2014-12-06 13:20:49 +00:00
outputFile := flag.String("o", "", "Output file, blank for stdout")
2014-02-20 16:40:15 +00:00
flag.Parse()
fname := flag.Arg(0)
2014-07-13 07:23:10 +00:00
fset := token.NewFileSet()
2014-02-20 16:40:15 +00:00
f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments)
if err != nil {
2014-12-06 13:20:49 +00:00
log.Fatal(err)
2014-02-20 16:40:15 +00:00
}
2014-07-13 07:23:10 +00:00
var structs []structInfo
i := inspector(&structs)
ast.Inspect(f, i)
2014-02-20 16:40:15 +00:00
2016-02-02 11:43:33 +00:00
buf := new(bytes.Buffer)
headerTpl.Execute(buf, map[string]string{"Package": f.Name.Name})
for _, s := range structs {
fmt.Fprintf(buf, "\n/*\n\n")
generateDiagram(buf, s)
generateXdr(buf, s)
fmt.Fprintf(buf, "*/\n")
generateCode(buf, s)
}
bs, err := format.Source(buf.Bytes())
if err != nil {
log.Print(buf.String())
log.Fatal(err)
}
2014-12-06 13:20:49 +00:00
var output io.Writer = os.Stdout
if *outputFile != "" {
fd, err := os.Create(*outputFile)
if err != nil {
log.Fatal(err)
}
output = fd
}
2016-02-02 11:43:33 +00:00
output.Write(bs)
2014-02-20 16:40:15 +00:00
}