| // Copyright 2013 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | // +build ignore | 
 |  | 
 | //go:generate go run gen.go | 
 |  | 
 | // This program generates system adaptation constants and types, | 
 | // internet protocol constants and tables by reading template files | 
 | // and IANA protocol registries. | 
 | package main | 
 |  | 
 | import ( | 
 | 	"bytes" | 
 | 	"encoding/xml" | 
 | 	"fmt" | 
 | 	"go/format" | 
 | 	"io" | 
 | 	"io/ioutil" | 
 | 	"net/http" | 
 | 	"os" | 
 | 	"os/exec" | 
 | 	"runtime" | 
 | 	"strconv" | 
 | 	"strings" | 
 | ) | 
 |  | 
 | func main() { | 
 | 	if err := genzsys(); err != nil { | 
 | 		fmt.Fprintln(os.Stderr, err) | 
 | 		os.Exit(1) | 
 | 	} | 
 | 	if err := geniana(); err != nil { | 
 | 		fmt.Fprintln(os.Stderr, err) | 
 | 		os.Exit(1) | 
 | 	} | 
 | } | 
 |  | 
 | func genzsys() error { | 
 | 	defs := "defs_" + runtime.GOOS + ".go" | 
 | 	f, err := os.Open(defs) | 
 | 	if err != nil { | 
 | 		if os.IsNotExist(err) { | 
 | 			return nil | 
 | 		} | 
 | 		return err | 
 | 	} | 
 | 	f.Close() | 
 | 	cmd := exec.Command("go", "tool", "cgo", "-godefs", defs) | 
 | 	b, err := cmd.Output() | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	b, err = format.Source(b) | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	zsys := "zsys_" + runtime.GOOS + ".go" | 
 | 	switch runtime.GOOS { | 
 | 	case "freebsd", "linux": | 
 | 		zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go" | 
 | 	} | 
 | 	if err := ioutil.WriteFile(zsys, b, 0644); err != nil { | 
 | 		return err | 
 | 	} | 
 | 	return nil | 
 | } | 
 |  | 
 | var registries = []struct { | 
 | 	url   string | 
 | 	parse func(io.Writer, io.Reader) error | 
 | }{ | 
 | 	{ | 
 | 		"http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml", | 
 | 		parseICMPv4Parameters, | 
 | 	}, | 
 | } | 
 |  | 
 | func geniana() error { | 
 | 	var bb bytes.Buffer | 
 | 	fmt.Fprintf(&bb, "// go generate gen.go\n") | 
 | 	fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n") | 
 | 	fmt.Fprintf(&bb, "package ipv4\n\n") | 
 | 	for _, r := range registries { | 
 | 		resp, err := http.Get(r.url) | 
 | 		if err != nil { | 
 | 			return err | 
 | 		} | 
 | 		defer resp.Body.Close() | 
 | 		if resp.StatusCode != http.StatusOK { | 
 | 			return fmt.Errorf("got HTTP status code %v for %v\n", resp.StatusCode, r.url) | 
 | 		} | 
 | 		if err := r.parse(&bb, resp.Body); err != nil { | 
 | 			return err | 
 | 		} | 
 | 		fmt.Fprintf(&bb, "\n") | 
 | 	} | 
 | 	b, err := format.Source(bb.Bytes()) | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	if err := ioutil.WriteFile("iana.go", b, 0644); err != nil { | 
 | 		return err | 
 | 	} | 
 | 	return nil | 
 | } | 
 |  | 
 | func parseICMPv4Parameters(w io.Writer, r io.Reader) error { | 
 | 	dec := xml.NewDecoder(r) | 
 | 	var icp icmpv4Parameters | 
 | 	if err := dec.Decode(&icp); err != nil { | 
 | 		return err | 
 | 	} | 
 | 	prs := icp.escape() | 
 | 	fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated) | 
 | 	fmt.Fprintf(w, "const (\n") | 
 | 	for _, pr := range prs { | 
 | 		if pr.Descr == "" { | 
 | 			continue | 
 | 		} | 
 | 		fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Descr, pr.Value) | 
 | 		fmt.Fprintf(w, "// %s\n", pr.OrigDescr) | 
 | 	} | 
 | 	fmt.Fprintf(w, ")\n\n") | 
 | 	fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated) | 
 | 	fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n") | 
 | 	for _, pr := range prs { | 
 | 		if pr.Descr == "" { | 
 | 			continue | 
 | 		} | 
 | 		fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigDescr)) | 
 | 	} | 
 | 	fmt.Fprintf(w, "}\n") | 
 | 	return nil | 
 | } | 
 |  | 
 | type icmpv4Parameters struct { | 
 | 	XMLName    xml.Name `xml:"registry"` | 
 | 	Title      string   `xml:"title"` | 
 | 	Updated    string   `xml:"updated"` | 
 | 	Registries []struct { | 
 | 		Title   string `xml:"title"` | 
 | 		Records []struct { | 
 | 			Value string `xml:"value"` | 
 | 			Descr string `xml:"description"` | 
 | 		} `xml:"record"` | 
 | 	} `xml:"registry"` | 
 | } | 
 |  | 
 | type canonICMPv4ParamRecord struct { | 
 | 	OrigDescr string | 
 | 	Descr     string | 
 | 	Value     int | 
 | } | 
 |  | 
 | func (icp *icmpv4Parameters) escape() []canonICMPv4ParamRecord { | 
 | 	id := -1 | 
 | 	for i, r := range icp.Registries { | 
 | 		if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") { | 
 | 			id = i | 
 | 			break | 
 | 		} | 
 | 	} | 
 | 	if id < 0 { | 
 | 		return nil | 
 | 	} | 
 | 	prs := make([]canonICMPv4ParamRecord, len(icp.Registries[id].Records)) | 
 | 	sr := strings.NewReplacer( | 
 | 		"Messages", "", | 
 | 		"Message", "", | 
 | 		"ICMP", "", | 
 | 		"+", "P", | 
 | 		"-", "", | 
 | 		"/", "", | 
 | 		".", "", | 
 | 		" ", "", | 
 | 	) | 
 | 	for i, pr := range icp.Registries[id].Records { | 
 | 		if strings.Contains(pr.Descr, "Reserved") || | 
 | 			strings.Contains(pr.Descr, "Unassigned") || | 
 | 			strings.Contains(pr.Descr, "Deprecated") || | 
 | 			strings.Contains(pr.Descr, "Experiment") || | 
 | 			strings.Contains(pr.Descr, "experiment") { | 
 | 			continue | 
 | 		} | 
 | 		ss := strings.Split(pr.Descr, "\n") | 
 | 		if len(ss) > 1 { | 
 | 			prs[i].Descr = strings.Join(ss, " ") | 
 | 		} else { | 
 | 			prs[i].Descr = ss[0] | 
 | 		} | 
 | 		s := strings.TrimSpace(prs[i].Descr) | 
 | 		prs[i].OrigDescr = s | 
 | 		prs[i].Descr = sr.Replace(s) | 
 | 		prs[i].Value, _ = strconv.Atoi(pr.Value) | 
 | 	} | 
 | 	return prs | 
 | } |