gen.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build ignore
  5. //go:generate go run gen.go
  6. // This program generates system adaptation constants and types,
  7. // internet protocol constants and tables by reading template files
  8. // and IANA protocol registries.
  9. package main
  10. import (
  11. "bytes"
  12. "encoding/xml"
  13. "fmt"
  14. "go/format"
  15. "io"
  16. "io/ioutil"
  17. "net/http"
  18. "os"
  19. "os/exec"
  20. "runtime"
  21. "strconv"
  22. "strings"
  23. )
  24. func main() {
  25. if err := genzsys(); err != nil {
  26. fmt.Fprintln(os.Stderr, err)
  27. os.Exit(1)
  28. }
  29. if err := geniana(); err != nil {
  30. fmt.Fprintln(os.Stderr, err)
  31. os.Exit(1)
  32. }
  33. }
  34. func genzsys() error {
  35. defs := "defs_" + runtime.GOOS + ".go"
  36. f, err := os.Open(defs)
  37. if err != nil {
  38. if os.IsNotExist(err) {
  39. return nil
  40. }
  41. return err
  42. }
  43. f.Close()
  44. cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
  45. b, err := cmd.Output()
  46. if err != nil {
  47. return err
  48. }
  49. switch runtime.GOOS {
  50. case "dragonfly", "solaris":
  51. // The ipv4 pacakge still supports go1.2, and so we
  52. // need to take care of additional platforms in go1.3
  53. // and above for working with go1.2.
  54. b = bytes.Replace(b, []byte("package ipv4\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv4\n"), 1)
  55. }
  56. b, err = format.Source(b)
  57. if err != nil {
  58. return err
  59. }
  60. if err := ioutil.WriteFile("zsys_"+runtime.GOOS+".go", b, 0644); err != nil {
  61. return err
  62. }
  63. return nil
  64. }
  65. var registries = []struct {
  66. url string
  67. parse func(io.Writer, io.Reader) error
  68. }{
  69. {
  70. "http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
  71. parseICMPv4Parameters,
  72. },
  73. }
  74. func geniana() error {
  75. var bb bytes.Buffer
  76. fmt.Fprintf(&bb, "// go generate gen.go\n")
  77. fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
  78. fmt.Fprintf(&bb, "package ipv4\n\n")
  79. for _, r := range registries {
  80. resp, err := http.Get(r.url)
  81. if err != nil {
  82. return err
  83. }
  84. defer resp.Body.Close()
  85. if resp.StatusCode != http.StatusOK {
  86. return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
  87. }
  88. if err := r.parse(&bb, resp.Body); err != nil {
  89. return err
  90. }
  91. fmt.Fprintf(&bb, "\n")
  92. }
  93. b, err := format.Source(bb.Bytes())
  94. if err != nil {
  95. return err
  96. }
  97. if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
  98. return err
  99. }
  100. return nil
  101. }
  102. func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
  103. dec := xml.NewDecoder(r)
  104. var icp icmpv4Parameters
  105. if err := dec.Decode(&icp); err != nil {
  106. return err
  107. }
  108. prs := icp.escape()
  109. fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
  110. fmt.Fprintf(w, "const (\n")
  111. for _, pr := range prs {
  112. if pr.Descr == "" {
  113. continue
  114. }
  115. fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
  116. fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
  117. }
  118. fmt.Fprintf(w, ")\n\n")
  119. fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
  120. fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
  121. for _, pr := range prs {
  122. if pr.Descr == "" {
  123. continue
  124. }
  125. fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
  126. }
  127. fmt.Fprintf(w, "}\n")
  128. return nil
  129. }
  130. type icmpv4Parameters struct {
  131. XMLName xml.Name `xml:"registry"`
  132. Title string `xml:"title"`
  133. Updated string `xml:"updated"`
  134. Registries []struct {
  135. Title string `xml:"title"`
  136. Records []struct {
  137. Value string `xml:"value"`
  138. Descr string `xml:"description"`
  139. } `xml:"record"`
  140. } `xml:"registry"`
  141. }
  142. type canonICMPv4ParamRecord struct {
  143. OrigDescr string
  144. Descr string
  145. Value int
  146. }
  147. func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
  148. id := -1
  149. for i, r := range icp.Registries {
  150. if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
  151. id = i
  152. break
  153. }
  154. }
  155. if id < 0 {
  156. return nil
  157. }
  158. prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
  159. sr := strings.NewReplacer(
  160. "Messages", "",
  161. "Message", "",
  162. "ICMP", "",
  163. "+", "P",
  164. "-", "",
  165. "/", "",
  166. ".", "",
  167. " ", "",
  168. )
  169. for i, pr := range icp.Registries[id].Records {
  170. if strings.Contains(pr.Descr, "Reserved") ||
  171. strings.Contains(pr.Descr, "Unassigned") ||
  172. strings.Contains(pr.Descr, "Deprecated") ||
  173. strings.Contains(pr.Descr, "Experiment") ||
  174. strings.Contains(pr.Descr, "experiment") {
  175. continue
  176. }
  177. ss := strings.Split(pr.Descr, "\n")
  178. if len(ss) > 1 {
  179. prs[i].Descr = strings.Join(ss, " ")
  180. } else {
  181. prs[i].Descr = ss[0]
  182. }
  183. s := strings.TrimSpace(prs[i].Descr)
  184. prs[i].OrigDescr = s
  185. prs[i].Descr = sr.Replace(s)
  186. prs[i].Value, _ = strconv.Atoi(pr.Value)
  187. }
  188. return prs
  189. }