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