github.com/Andyfoo/golang/x/net@v0.0.0-20190901054642-57c1bf301704/ipv6/gen.go (about) 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 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. 12 package main 13 14 import ( 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 29 func 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 40 func 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 70 var registries = []struct { 71 url string 72 parse func(io.Writer, io.Reader) error 73 }{ 74 { 75 "https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml", 76 parseICMPv6Parameters, 77 }, 78 } 79 80 func geniana() error { 81 var bb bytes.Buffer 82 fmt.Fprintf(&bb, "// go generate gen.go\n") 83 fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n") 84 fmt.Fprintf(&bb, "package ipv6\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 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 138 type icmpv6Parameters 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 Name string `xml:"name"` 147 } `xml:"record"` 148 } `xml:"registry"` 149 } 150 151 type canonICMPv6ParamRecord struct { 152 OrigName string 153 Name string 154 Value int 155 } 156 157 func (icp *icmpv6Parameters) escape() []canonICMPv6ParamRecord { 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([]canonICMPv6ParamRecord, 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.Name, "Reserved") || 181 strings.Contains(pr.Name, "Unassigned") || 182 strings.Contains(pr.Name, "Deprecated") || 183 strings.Contains(pr.Name, "Experiment") || 184 strings.Contains(pr.Name, "experiment") { 185 continue 186 } 187 ss := strings.Split(pr.Name, "\n") 188 if len(ss) > 1 { 189 prs[i].Name = strings.Join(ss, " ") 190 } else { 191 prs[i].Name = ss[0] 192 } 193 s := strings.TrimSpace(prs[i].Name) 194 prs[i].OrigName = s 195 prs[i].Name = sr.Replace(s) 196 prs[i].Value, _ = strconv.Atoi(pr.Value) 197 } 198 return prs 199 }