gen.go 5.0 KB

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