package main import ( "html/template" "os" ) var urls = map[string]string{} var names = map[string]string{} func (doc Document) URL() string { if doc.ID == "" { return "" } key := doc.Vendor.Name + "\000" + doc.ID if _, have := urls[key]; !have { urls[key] = doc.Vendor.GetURL(doc.ID) } return urls[key] } func (doc Document) Name() string { if doc.ID == "" { var names []string for _, full := range doc.Fulls() { names = append(names, full.Name()) } switch len(names) { case 0: return "???" case 1: return names[0] default: // BUG(lukeshu): Handle un-IDed Documents with // multiple IDed resellers. panic("TODO") } } key := doc.Vendor.Name + "\000" + doc.ID if _, have := names[key]; !have { names[key] = doc.Vendor.GetName(doc.ID, doc.URL()) } return names[key] } func (doc Document) Fulls() []Document { var ret []Document for _, reseller := range doc.Resellers { if doc.ID != "" && reseller.Vendor.Name == doc.Vendor.Name && reseller.ID == doc.ID { continue } if reseller.Type == Full { ret = append(ret, reseller) } } return ret } func (doc Document) Patches() []Document { var ret []Document for _, reseller := range doc.Resellers { if doc.ID != "" && reseller.Vendor.Name == doc.Vendor.Name && reseller.ID == doc.ID { continue } if reseller.Type == Patch { ret = append(ret, reseller) } } return ret } func (doc Document) AsFull() *Document { if doc.Vendor.Name == "" && doc.ID == "" { return nil } ret := doc ret.Resellers = ret.Fulls() switch doc.Type { case Full: // Nothing to do case Patch: if len(ret.Resellers) == 0 { return nil } ret.Type = Full ret.ID = func() string { var ids []string for _, reseller := range ret.Resellers { if reseller.Vendor.Name == doc.Vendor.Name { ids = append(ids, reseller.ID) } } switch len(ids) { case 0: return "" case 1: return ids[0] default: panic("wut") } }() if ret.ID != "" { ret.Resellers = ret.Fulls() } default: panic("uhh") } return &ret } func (doc Document) AsPatch() *Document { if doc.Vendor.Name == "" && doc.ID == "" { return nil } ret := doc switch doc.Type { case Full: return nil case Patch: ret.Resellers = doc.Patches() default: panic("no") } return &ret } func (ed Edition) DocsOrdered() []Document { // This chould be O(n), but this niaeve implementation is // O(n^2). It's OK, n is small. s := make([]Document, len(Vendors)) for i, vnd := range Vendors { for _, doc := range ed.Docs { if doc.Vendor.Name == vnd.Name { s[i] = doc } } } return s } var tmpl = `{{define "document"}}{{if .}} {{if .URL}}{{.Name}}{{else}}{{.Name}}{{end}} {{range .Resellers}} ({{.Vendor.Name}}) {{end}} {{end}}{{end}} POSIX Editions

There's a typo in the "standardNumber" in IEEE Xplore's records forfor the 2004 edition of 1003.1; it says 2014 instead or 2004. The actual document says 2004 though.

{{range .Vendors}}{{end}}{{range .Vendors}}{{end}} {{range .Editions}} {{range .DocsOrdered}} {{end}} {{end}}

POSIX: C & Shell (1997-present)

{{.Name}}
FullPatch
{{.Name}}{{template "document" .AsFull}}{{template "document" .AsPatch}}
` func main() { err := template.Must(template.New("page").Parse(tmpl)).Execute(os.Stdout, map[string]interface{}{ "Vendors": Vendors, "Editions": Editions, }) if err != nil { panic(err) } }