blob: ffb44fe681fe4332bff2b0eb0e3f6205f605cb1c [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// 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
5// +build ignore
6
7//go:generate go run gen.go
8
9// This program generates system adaptation constants and types,
10// internet protocol constants and tables by reading template files
11// and IANA protocol registries.
12package main
13
14import (
15 "bytes"
16 "encoding/xml"
17 "fmt"
18 "go/format"
19 "io"
20 "io/ioutil"
21 "net/http"
22 "os"
23 "os/exec"
24 "runtime"
25 "strconv"
26 "strings"
27)
28
29func main() {
30 if err := genzsys(); err != nil {
31 fmt.Fprintln(os.Stderr, err)
32 os.Exit(1)
33 }
34 if err := geniana(); err != nil {
35 fmt.Fprintln(os.Stderr, err)
36 os.Exit(1)
37 }
38}
39
40func genzsys() error {
41 defs := "defs_" + runtime.GOOS + ".go"
42 f, err := os.Open(defs)
43 if err != nil {
44 if os.IsNotExist(err) {
45 return nil
46 }
47 return err
48 }
49 f.Close()
50 cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
51 b, err := cmd.Output()
52 if err != nil {
53 return err
54 }
55 b, err = format.Source(b)
56 if err != nil {
57 return err
58 }
59 zsys := "zsys_" + runtime.GOOS + ".go"
60 switch runtime.GOOS {
61 case "freebsd", "linux":
62 zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
63 }
64 if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
65 return err
66 }
67 return nil
68}
69
70var registries = []struct {
71 url string
72 parse func(io.Writer, io.Reader) error
73}{
74 {
75 "http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
76 parseICMPv4Parameters,
77 },
78}
79
80func geniana() error {
81 var bb bytes.Buffer
82 fmt.Fprintf(&bb, "// go generate gen.go\n")
83 fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
84 fmt.Fprintf(&bb, "package ipv4\n\n")
85 for _, r := range registries {
86 resp, err := http.Get(r.url)
87 if err != nil {
88 return err
89 }
90 defer resp.Body.Close()
91 if resp.StatusCode != http.StatusOK {
92 return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
93 }
94 if err := r.parse(&bb, resp.Body); err != nil {
95 return err
96 }
97 fmt.Fprintf(&bb, "\n")
98 }
99 b, err := format.Source(bb.Bytes())
100 if err != nil {
101 return err
102 }
103 if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
104 return err
105 }
106 return nil
107}
108
109func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
110 dec := xml.NewDecoder(r)
111 var icp icmpv4Parameters
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.Descr == "" {
120 continue
121 }
122 fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
123 fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
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.Descr == "" {
130 continue
131 }
132 fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
133 }
134 fmt.Fprintf(w, "}\n")
135 return nil
136}
137
138type icmpv4Parameters struct {
139 XMLName xml.Name `xml:"registry"`
140 Title string `xml:"title"`
141 Updated string `xml:"updated"`
142 Registries []struct {
143 Title string `xml:"title"`
144 Records []struct {
145 Value string `xml:"value"`
146 Descr string `xml:"description"`
147 } `xml:"record"`
148 } `xml:"registry"`
149}
150
151type canonICMPv4ParamRecord struct {
152 OrigDescr string
153 Descr string
154 Value int
155}
156
157func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
158 id := -1
159 for i, r := range icp.Registries {
160 if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
161 id = i
162 break
163 }
164 }
165 if id < 0 {
166 return nil
167 }
168 prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
169 sr := strings.NewReplacer(
170 "Messages", "",
171 "Message", "",
172 "ICMP", "",
173 "+", "P",
174 "-", "",
175 "/", "",
176 ".", "",
177 " ", "",
178 )
179 for i, pr := range icp.Registries[id].Records {
180 if strings.Contains(pr.Descr, "Reserved") ||
181 strings.Contains(pr.Descr, "Unassigned") ||
182 strings.Contains(pr.Descr, "Deprecated") ||
183 strings.Contains(pr.Descr, "Experiment") ||
184 strings.Contains(pr.Descr, "experiment") {
185 continue
186 }
187 ss := strings.Split(pr.Descr, "\n")
188 if len(ss) > 1 {
189 prs[i].Descr = strings.Join(ss, " ")
190 } else {
191 prs[i].Descr = ss[0]
192 }
193 s := strings.TrimSpace(prs[i].Descr)
194 prs[i].OrigDescr = s
195 prs[i].Descr = sr.Replace(s)
196 prs[i].Value, _ = strconv.Atoi(pr.Value)
197 }
198 return prs
199}