blob: 09dcd0377c906e8061b0cf1d4a312dc9cadf4806 [file] [log] [blame]
Mikio Hara8108b4b2013-06-07 14:52:58 +09001// 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
Mikio Harae5dac172014-10-07 06:35:16 +09007//go:generate go run gen.go
8
Mikio Harabd815cb2014-10-24 17:37:57 +09009// This program generates system adaptation constants and types,
10// internet protocol constants and tables by reading template files
11// and IANA protocol registries.
Mikio Hara8108b4b2013-06-07 14:52:58 +090012package main
13
14import (
15 "bytes"
16 "encoding/xml"
17 "fmt"
18 "go/format"
19 "io"
Mikio Harae5dac172014-10-07 06:35:16 +090020 "io/ioutil"
Mikio Hara8108b4b2013-06-07 14:52:58 +090021 "net/http"
22 "os"
Mikio Harabd815cb2014-10-24 17:37:57 +090023 "os/exec"
24 "runtime"
Mikio Hara8108b4b2013-06-07 14:52:58 +090025 "strconv"
26 "strings"
27)
28
Mikio Harabd815cb2014-10-24 17:37:57 +090029func 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 switch runtime.GOOS {
56 case "dragonfly", "solaris":
57 // The ipv4 pacakge still supports go1.2, and so we
58 // need to take care of additional platforms in go1.3
59 // and above for working with go1.2.
60 b = bytes.Replace(b, []byte("package ipv4\n"), []byte("// +build "+runtime.GOOS+"\n\npackage ipv4\n"), 1)
61 }
62 b, err = format.Source(b)
63 if err != nil {
64 return err
65 }
Mikio Hara1d6af0d2014-11-13 07:19:40 +090066 zsys := "zsys_" + runtime.GOOS + ".go"
67 switch runtime.GOOS {
68 case "freebsd", "linux":
69 zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
70 }
71 if err := ioutil.WriteFile(zsys, b, 0644); err != nil {
Mikio Harabd815cb2014-10-24 17:37:57 +090072 return err
73 }
74 return nil
75}
76
Mikio Hara8108b4b2013-06-07 14:52:58 +090077var registries = []struct {
78 url string
79 parse func(io.Writer, io.Reader) error
80}{
81 {
Mikio Hara23139102013-06-29 10:25:14 +090082 "http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml",
Mikio Hara8108b4b2013-06-07 14:52:58 +090083 parseICMPv4Parameters,
84 },
Mikio Hara8108b4b2013-06-07 14:52:58 +090085}
86
Mikio Harabd815cb2014-10-24 17:37:57 +090087func geniana() error {
Mikio Hara8108b4b2013-06-07 14:52:58 +090088 var bb bytes.Buffer
Mikio Harae5dac172014-10-07 06:35:16 +090089 fmt.Fprintf(&bb, "// go generate gen.go\n")
Mikio Hara8108b4b2013-06-07 14:52:58 +090090 fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
91 fmt.Fprintf(&bb, "package ipv4\n\n")
92 for _, r := range registries {
93 resp, err := http.Get(r.url)
94 if err != nil {
Mikio Harabd815cb2014-10-24 17:37:57 +090095 return err
Mikio Hara8108b4b2013-06-07 14:52:58 +090096 }
97 defer resp.Body.Close()
98 if resp.StatusCode != http.StatusOK {
Mikio Harabd815cb2014-10-24 17:37:57 +090099 return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url)
Mikio Hara8108b4b2013-06-07 14:52:58 +0900100 }
101 if err := r.parse(&bb, resp.Body); err != nil {
Mikio Harabd815cb2014-10-24 17:37:57 +0900102 return err
Mikio Hara8108b4b2013-06-07 14:52:58 +0900103 }
104 fmt.Fprintf(&bb, "\n")
105 }
106 b, err := format.Source(bb.Bytes())
107 if err != nil {
Mikio Harabd815cb2014-10-24 17:37:57 +0900108 return err
Mikio Hara8108b4b2013-06-07 14:52:58 +0900109 }
Mikio Harae5dac172014-10-07 06:35:16 +0900110 if err := ioutil.WriteFile("iana.go", b, 0644); err != nil {
Mikio Harabd815cb2014-10-24 17:37:57 +0900111 return err
Mikio Harae5dac172014-10-07 06:35:16 +0900112 }
Mikio Harabd815cb2014-10-24 17:37:57 +0900113 return nil
Mikio Hara8108b4b2013-06-07 14:52:58 +0900114}
115
116func parseICMPv4Parameters(w io.Writer, r io.Reader) error {
117 dec := xml.NewDecoder(r)
118 var icp icmpv4Parameters
119 if err := dec.Decode(&icp); err != nil {
120 return err
121 }
Mikio Hara23139102013-06-29 10:25:14 +0900122 prs := icp.escape()
Mikio Hara8108b4b2013-06-07 14:52:58 +0900123 fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
124 fmt.Fprintf(w, "const (\n")
125 for _, pr := range prs {
126 if pr.Descr == "" {
127 continue
128 }
129 fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value)
130 fmt.Fprintf(w, "// %s\n", pr.OrigDescr)
131 }
132 fmt.Fprintf(w, ")\n\n")
133 fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
134 fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
135 for _, pr := range prs {
136 if pr.Descr == "" {
137 continue
138 }
139 fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr))
140 }
141 fmt.Fprintf(w, "}\n")
142 return nil
143}
144
145type icmpv4Parameters struct {
Mikio Hara36e5baf2013-10-14 09:29:40 +0900146 XMLName xml.Name `xml:"registry"`
147 Title string `xml:"title"`
148 Updated string `xml:"updated"`
149 Registries []struct {
150 Title string `xml:"title"`
151 Records []struct {
152 Value string `xml:"value"`
153 Descr string `xml:"description"`
154 } `xml:"record"`
155 } `xml:"registry"`
Mikio Hara8108b4b2013-06-07 14:52:58 +0900156}
157
158type canonICMPv4ParamRecord struct {
159 OrigDescr string
160 Descr string
161 Value int
162}
163
Mikio Hara23139102013-06-29 10:25:14 +0900164func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord {
165 id := -1
166 for i, r := range icp.Registries {
167 if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
168 id = i
169 break
170 }
171 }
172 if id < 0 {
173 return nil
174 }
Mikio Hara8108b4b2013-06-07 14:52:58 +0900175 prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records))
176 sr := strings.NewReplacer(
177 "Messages", "",
178 "Message", "",
179 "ICMP", "",
180 "+", "P",
181 "-", "",
182 "/", "",
183 ".", "",
184 " ", "",
185 )
186 for i, pr := range icp.Registries[id].Records {
187 if strings.Contains(pr.Descr, "Reserved") ||
188 strings.Contains(pr.Descr, "Unassigned") ||
189 strings.Contains(pr.Descr, "Deprecated") ||
190 strings.Contains(pr.Descr, "Experiment") ||
191 strings.Contains(pr.Descr, "experiment") {
192 continue
193 }
194 ss := strings.Split(pr.Descr, "\n")
195 if len(ss) > 1 {
196 prs[i].Descr = strings.Join(ss, " ")
197 } else {
198 prs[i].Descr = ss[0]
199 }
200 s := strings.TrimSpace(prs[i].Descr)
201 prs[i].OrigDescr = s
202 prs[i].Descr = sr.Replace(s)
203 prs[i].Value, _ = strconv.Atoi(pr.Value)
204 }
205 return prs
206}