//go:build ignore
// +build ignore

// mklinkmodes is a Go script which generates the linkModes lookup table using
// a ztypes_linux.go from x/sys as input.
package main

import (
	"bufio"
	"bytes"
	"fmt"
	"go/format"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

func main() {
	// Assume a local GOPATH checkout of x/sys.
	f, err := os.Open(filepath.Join(os.Getenv("GOPATH"), "src/golang.org/x/sys/unix/ztypes_linux.go"))
	if err != nil {
		log.Fatalf("failed to open ztypes_linux.go: %v", err)
	}
	defer f.Close()

	b := bytes.NewBuffer(nil)

	pf(b, `//go:build linux
// +build linux

// Code generated by "go run mklinkmodes.go"; DO NOT EDIT.

package ethtool

import "golang.org/x/sys/unix"

var linkModes = [...]struct{
	bit uint32
	str string
}{`)

	s := bufio.NewScanner(f)
	for s.Scan() {
		if !bytes.HasPrefix(s.Bytes(), []byte("\tETHTOOL_LINK_MODE")) {
			continue
		}

		// Found a link mode, we only care about the name.
		ss := strings.Fields(s.Text())
		if len(ss) != 3 {
			continue
		}

		// The constant and a stringified name like 1000baseT/Full is written
		// for each line found.
		bit := ss[0]

		str := strings.TrimPrefix(ss[0], "ETHTOOL_LINK_MODE_")
		str = strings.TrimSuffix(str, "_BIT")
		str = strings.Replace(str, "_", "/", -1)

		pf(b, `{bit: unix.%s, str: %q},`, bit, str)
	}

	pf(b, `}`)

	if err := s.Err(); err != nil {
		log.Fatalf("failed to scan: %v", err)
	}

	out, err := format.Source(b.Bytes())
	if err != nil {
		log.Fatalf("failed to format: %v", err)
	}

	if err := ioutil.WriteFile("linkmodes_linux.go", out, 0o644); err != nil {
		log.Fatalf("failed to write output file: %v", err)
	}
}

func pf(w io.Writer, format string, args ...interface{}) {
	fmt.Fprintf(w, format+"\n", args...)
}
