//go:build ignore
// +build ignore

// const_generate.go parses pkcs11t.h and generates zconst.go.
// zconst.go is meant to be checked into git.

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"go/format"
	"log"
	"os"
	"strings"
)

func main() {
	file, err := os.Open("pkcs11t.h")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	out := &bytes.Buffer{}
	fmt.Fprintf(out, header)

	scanner := bufio.NewScanner(file)
	fmt.Fprintln(out, "const (")
	for scanner.Scan() {
		// Fairly simple parsing, any line starting with '#define' will output
		// $2 = $3 and drop any UL (unsigned long) suffixes
		fields := strings.Fields(scanner.Text())
		if len(fields) < 3 {
			continue
		}
		if fields[0] != "#define" {
			continue
		}
		// fields[1] (const name) needs to be 3 chars, starting with CK
		if !strings.HasPrefix(fields[1], "CK") {
			continue
		}
		value := strings.TrimSuffix(fields[2], "UL")
		// special case for things like: (CKF_ARRAY_ATTRIBUTE|0x00000211UL)
		if strings.HasSuffix(value, "UL)") {
			value = strings.Replace(value, "UL)", ")", 1)
		}
		// CK_UNAVAILABLE_INFORMATION is encoded as (~0) (with UL) removed, this needs to be ^uint(0) in Go.
		// Special case that here.
		if value == "(~0)" {
			value = "^uint(0)"
		}

		// check for /* deprecated */ comment
		if len(fields) == 6 && fields[4] == "Deprecated" {
			fmt.Fprintln(out, fields[1], " = ", value, "// Deprecated")
			continue
		}

		fmt.Fprintln(out, fields[1], " = ", value)
	}

	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
	fmt.Fprintln(out, ")")
	res, err := format.Source(out.Bytes())
	if err != nil {
		fmt.Fprintf(os.Stderr, out.String())
		log.Fatal(err)
	}
	f, err := os.Create("zconst.go")
	if err != nil {
		log.Fatal(err)
	}
	f.Write(res)

}

const header = `// Copyright 2013 Miek Gieben. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

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


package pkcs11

`
