gen.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. b, err = format.Source(b)
  50. if err != nil {
  51. return err
  52. }
  53. zsys := "zsys_" + runtime.GOOS + ".go"
  54. switch runtime.GOOS {
  55. case "freebsd", "linux":
  56. zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
  57. }
  58. if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
  59. return err
  60. }
  61. return nil
  62. }
  63. var registries = []struct {
  64. url string
  65. parse func(io.Writer, io.Reader) error
  66. }{
  67. {
  68. "https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
  69. parseICMPv4Parameters,
  70. },
  71. }
  72. func geniana() error {
  73. var bb bytes.Buffer
  74. fmt.Fprintf(&bb, "// go generate gen.go\n")
  75. fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n")
  76. fmt.Fprintf(&bb, "package ipv4\n\n")
  77. for _, r := range registries {
  78. resp, err := http.Get(r.url)
  79. if err != nil {
  80. return err
  81. }
  82. defer resp.Body.Close()
  83. if resp.StatusCode != http.StatusOK {
  84. return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
  85. }
  86. if err := r.parse(&bb, resp.Body); err != nil {
  87. return err
  88. }
  89. fmt.Fprintf(&bb, "\n")
  90. }
  91. b, err := format.Source(bb.Bytes())
  92. if err != nil {
  93. return err
  94. }
  95. if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
  96. return err
  97. }
  98. return nil
  99. }
  100. func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
  101. dec := xml.NewDecoder(r)
  102. var icp icmpv4Parameters
  103. if err := dec.Decode(&icp); err != nil {
  104. return err
  105. }
  106. prs := icp.escape()
  107. fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
  108. fmt.Fprintf(w, "const (\n")
  109. for _, pr := range prs {
  110. if pr.Descr == "" {
  111. continue
  112. }
  113. fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
  114. fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
  115. }
  116. fmt.Fprintf(w, ")\n\n")
  117. fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
  118. fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
  119. for _, pr := range prs {
  120. if pr.Descr == "" {
  121. continue
  122. }
  123. fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
  124. }
  125. fmt.Fprintf(w, "}\n")
  126. return nil
  127. }
  128. type icmpv4Parameters struct {
  129. XMLName xml.Name `xml:"registry"`
  130. Title string `xml:"title"`
  131. Updated string `xml:"updated"`
  132. Registries []struct {
  133. Title string `xml:"title"`
  134. Records []struct {
  135. Value string `xml:"value"`
  136. Descr string `xml:"description"`
  137. } `xml:"record"`
  138. } `xml:"registry"`
  139. }
  140. type canonICMPv4ParamRecord struct {
  141. OrigDescr string
  142. Descr string
  143. Value int
  144. }
  145. func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
  146. id := -1
  147. for i, r := range icp.Registries {
  148. if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
  149. id = i
  150. break
  151. }
  152. }
  153. if id < 0 {
  154. return nil
  155. }
  156. prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
  157. sr := strings.NewReplacer(
  158. "Messages", "",
  159. "Message", "",
  160. "ICMP", "",
  161. "+", "P",
  162. "-", "",
  163. "/", "",
  164. ".", "",
  165. " ", "",
  166. )
  167. for i, pr := range icp.Registries[id].Records {
  168. if strings.Contains(pr.Descr, "Reserved") ||
  169. strings.Contains(pr.Descr, "Unassigned") ||
  170. strings.Contains(pr.Descr, "Deprecated") ||
  171. strings.Contains(pr.Descr, "Experiment") ||
  172. strings.Contains(pr.Descr, "experiment") {
  173. continue
  174. }
  175. ss := strings.Split(pr.Descr, "\n")
  176. if len(ss) > 1 {
  177. prs[i].Descr = strings.Join(ss, " ")
  178. } else {
  179. prs[i].Descr = ss[0]
  180. }
  181. s := strings.TrimSpace(prs[i].Descr)
  182. prs[i].OrigDescr = s
  183. prs[i].Descr = sr.Replace(s)
  184. prs[i].Value, _ = strconv.Atoi(pr.Value)
  185. }
  186. return prs
  187. }