gen.go 4.6 KB

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