...

Source file src/golang.org/x/net/ipv6/gen.go

Documentation: golang.org/x/net/ipv6

     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  //go: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  	"net/http"
    21  	"os"
    22  	"os/exec"
    23  	"runtime"
    24  	"strconv"
    25  	"strings"
    26  )
    27  
    28  func main() {
    29  	if err := genzsys(); err != nil {
    30  		fmt.Fprintln(os.Stderr, err)
    31  		os.Exit(1)
    32  	}
    33  	if err := geniana(); err != nil {
    34  		fmt.Fprintln(os.Stderr, err)
    35  		os.Exit(1)
    36  	}
    37  }
    38  
    39  func genzsys() error {
    40  	defs := "defs_" + runtime.GOOS + ".go"
    41  	f, err := os.Open(defs)
    42  	if err != nil {
    43  		if os.IsNotExist(err) {
    44  			return nil
    45  		}
    46  		return err
    47  	}
    48  	f.Close()
    49  	cmd := exec.Command("go", "tool", "cgo", "-godefs", defs)
    50  	b, err := cmd.Output()
    51  	if err != nil {
    52  		return err
    53  	}
    54  	b, err = format.Source(b)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	zsys := "zsys_" + runtime.GOOS + ".go"
    59  	switch runtime.GOOS {
    60  	case "freebsd", "linux":
    61  		zsys = "zsys_" + runtime.GOOS + "_" + runtime.GOARCH + ".go"
    62  	}
    63  	if err := os.WriteFile(zsys, b, 0644); err != nil {
    64  		return err
    65  	}
    66  	return nil
    67  }
    68  
    69  var registries = []struct {
    70  	url   string
    71  	parse func(io.Writer, io.Reader) error
    72  }{
    73  	{
    74  		"https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml",
    75  		parseICMPv6Parameters,
    76  	},
    77  }
    78  
    79  func geniana() error {
    80  	var bb bytes.Buffer
    81  	fmt.Fprintf(&bb, "// go generate gen.go\n")
    82  	fmt.Fprintf(&bb, "// Code 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 := os.WriteFile("iana.go", b, 0644); err != nil {
   103  		return err
   104  	}
   105  	return nil
   106  }
   107  
   108  func parseICMPv6Parameters(w io.Writer, r io.Reader) error {
   109  	dec := xml.NewDecoder(r)
   110  	var icp icmpv6Parameters
   111  	if err := dec.Decode(&icp); err != nil {
   112  		return err
   113  	}
   114  	prs := icp.escape()
   115  	fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
   116  	fmt.Fprintf(w, "const (\n")
   117  	for _, pr := range prs {
   118  		if pr.Name == "" {
   119  			continue
   120  		}
   121  		fmt.Fprintf(w, "ICMPType%s ICMPType = %d", pr.Name, pr.Value)
   122  		fmt.Fprintf(w, "// %s\n", pr.OrigName)
   123  	}
   124  	fmt.Fprintf(w, ")\n\n")
   125  	fmt.Fprintf(w, "// %s, Updated: %s\n", icp.Title, icp.Updated)
   126  	fmt.Fprintf(w, "var icmpTypes = map[ICMPType]string{\n")
   127  	for _, pr := range prs {
   128  		if pr.Name == "" {
   129  			continue
   130  		}
   131  		fmt.Fprintf(w, "%d: %q,\n", pr.Value, strings.ToLower(pr.OrigName))
   132  	}
   133  	fmt.Fprintf(w, "}\n")
   134  	return nil
   135  }
   136  
   137  type icmpv6Parameters struct {
   138  	XMLName    xml.Name `xml:"registry"`
   139  	Title      string   `xml:"title"`
   140  	Updated    string   `xml:"updated"`
   141  	Registries []struct {
   142  		Title   string `xml:"title"`
   143  		Records []struct {
   144  			Value string `xml:"value"`
   145  			Name  string `xml:"name"`
   146  		} `xml:"record"`
   147  	} `xml:"registry"`
   148  }
   149  
   150  type canonICMPv6ParamRecord struct {
   151  	OrigName string
   152  	Name     string
   153  	Value    int
   154  }
   155  
   156  func (icp *icmpv6Parameters) escape() []canonICMPv6ParamRecord {
   157  	id := -1
   158  	for i, r := range icp.Registries {
   159  		if strings.Contains(r.Title, "Type") || strings.Contains(r.Title, "type") {
   160  			id = i
   161  			break
   162  		}
   163  	}
   164  	if id < 0 {
   165  		return nil
   166  	}
   167  	prs := make([]canonICMPv6ParamRecord, len(icp.Registries[id].Records))
   168  	sr := strings.NewReplacer(
   169  		"Messages", "",
   170  		"Message", "",
   171  		"ICMP", "",
   172  		"+", "P",
   173  		"-", "",
   174  		"/", "",
   175  		".", "",
   176  		" ", "",
   177  	)
   178  	for i, pr := range icp.Registries[id].Records {
   179  		if strings.Contains(pr.Name, "Reserved") ||
   180  			strings.Contains(pr.Name, "Unassigned") ||
   181  			strings.Contains(pr.Name, "Deprecated") ||
   182  			strings.Contains(pr.Name, "Experiment") ||
   183  			strings.Contains(pr.Name, "experiment") {
   184  			continue
   185  		}
   186  		ss := strings.Split(pr.Name, "\n")
   187  		if len(ss) > 1 {
   188  			prs[i].Name = strings.Join(ss, " ")
   189  		} else {
   190  			prs[i].Name = ss[0]
   191  		}
   192  		s := strings.TrimSpace(prs[i].Name)
   193  		prs[i].OrigName = s
   194  		prs[i].Name = sr.Replace(s)
   195  		prs[i].Value, _ = strconv.Atoi(pr.Value)
   196  	}
   197  	return prs
   198  }
   199  

View as plain text