/* Copyright (c) 2015, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

package main

import (
	"bufio"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io"
	"os"
	"sort"
	"strconv"
	"strings"
)

var verbose = flag.Bool("verbose", false, "If true, prints a status message at the end.")

// libraryNames must be kept in sync with the enum in err.h. The generated code
// will contain static assertions to enforce this.
var libraryNames = []string{
	"NONE",
	"SYS",
	"BN",
	"RSA",
	"DH",
	"EVP",
	"BUF",
	"OBJ",
	"PEM",
	"DSA",
	"X509",
	"ASN1",
	"CONF",
	"CRYPTO",
	"EC",
	"SSL",
	"BIO",
	"PKCS7",
	"PKCS8",
	"X509V3",
	"RAND",
	"ENGINE",
	"OCSP",
	"UI",
	"COMP",
	"ECDSA",
	"ECDH",
	"HMAC",
	"DIGEST",
	"CIPHER",
	"HKDF",
	"USER",
}

// stringList is a map from uint32 -> string which can output data for a sorted
// list as C literals.
type stringList struct {
	// entries is an array of keys and offsets into |stringData|. The
	// offsets are in the bottom 15 bits of each uint32 and the key is the
	// top 17 bits.
	entries []uint32
	// internedStrings contains the same strings as are in |stringData|,
	// but allows for easy deduplication. It maps a string to its offset in
	// |stringData|.
	internedStrings map[string]uint32
	stringData      []byte
}

func newStringList() *stringList {
	return &stringList{
		internedStrings: make(map[string]uint32),
	}
}

// offsetMask is the bottom 15 bits. It's a mask that selects the offset from a
// uint32 in entries.
const offsetMask = 0x7fff

func (st *stringList) Add(key uint32, value string) error {
	if key&offsetMask != 0 {
		return errors.New("need bottom 15 bits of the key for the offset")
	}
	offset, ok := st.internedStrings[value]
	if !ok {
		offset = uint32(len(st.stringData))
		if offset&offsetMask != offset {
			return errors.New("stringList overflow")
		}
		st.stringData = append(st.stringData, []byte(value)...)
		st.stringData = append(st.stringData, 0)
		st.internedStrings[value] = offset
	}

	for _, existing := range st.entries {
		if existing>>15 == key>>15 {
			panic("duplicate entry")
		}
	}
	st.entries = append(st.entries, key|offset)
	return nil
}

// keySlice is a type that implements sorting of entries values.
type keySlice []uint32

func (ks keySlice) Len() int {
	return len(ks)
}

func (ks keySlice) Less(i, j int) bool {
	return (ks[i] >> 15) < (ks[j] >> 15)
}

func (ks keySlice) Swap(i, j int) {
	ks[i], ks[j] = ks[j], ks[i]
}

func (st *stringList) buildList() []uint32 {
	sort.Sort(keySlice(st.entries))
	return st.entries
}

type stringWriter interface {
	io.Writer
	WriteString(string) (int, error)
}

func (st *stringList) WriteTo(out stringWriter, name string) {
	list := st.buildList()
	if *verbose {
		fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData))
	}

	values := "kOpenSSL" + name + "Values"
	out.WriteString("const uint32_t " + values + "[] = {\n")
	for _, v := range list {
		fmt.Fprintf(out, "    0x%x,\n", v)
	}
	out.WriteString("};\n\n")
	out.WriteString("const size_t " + values + "Len = sizeof(" + values + ") / sizeof(" + values + "[0]);\n\n")

	stringData := "kOpenSSL" + name + "StringData"
	out.WriteString("const char " + stringData + "[] =\n    \"")
	for i, c := range st.stringData {
		if c == 0 {
			out.WriteString("\\0\"\n    \"")
			continue
		}
		out.Write(st.stringData[i : i+1])
	}
	out.WriteString("\";\n\n")
}

type errorData struct {
	reasons    *stringList
	libraryMap map[string]uint32
}

func (e *errorData) readErrorDataFile(filename string) error {
	inFile, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer inFile.Close()

	scanner := bufio.NewScanner(inFile)
	comma := []byte(",")

	lineNo := 0
	for scanner.Scan() {
		lineNo++

		line := scanner.Bytes()
		if len(line) == 0 {
			continue
		}
		parts := bytes.Split(line, comma)
		if len(parts) != 3 {
			return fmt.Errorf("bad line %d in %s: found %d values but want 3", lineNo, filename, len(parts))
		}
		libNum, ok := e.libraryMap[string(parts[0])]
		if !ok {
			return fmt.Errorf("bad line %d in %s: unknown library", lineNo, filename)
		}
		if libNum >= 64 {
			return fmt.Errorf("bad line %d in %s: library value too large", lineNo, filename)
		}
		key, err := strconv.ParseUint(string(parts[1]), 10 /* base */, 32 /* bit size */)
		if err != nil {
			return fmt.Errorf("bad line %d in %s: %s", lineNo, filename, err)
		}
		if key >= 2048 {
			return fmt.Errorf("bad line %d in %s: key too large", lineNo, filename)
		}
		value := string(parts[2])

		listKey := libNum<<26 | uint32(key)<<15

		err = e.reasons.Add(listKey, value)
		if err != nil {
			return err
		}
	}

	return scanner.Err()
}

func main() {
	flag.Parse()

	e := &errorData{
		reasons:    newStringList(),
		libraryMap: make(map[string]uint32),
	}
	for i, name := range libraryNames {
		e.libraryMap[name] = uint32(i) + 1
	}

	cwd, err := os.Open(".")
	if err != nil {
		panic(err)
	}
	names, err := cwd.Readdirnames(-1)
	if err != nil {
		panic(err)
	}

	sort.Strings(names)
	for _, name := range names {
		if !strings.HasSuffix(name, ".errordata") {
			continue
		}
		if err := e.readErrorDataFile(name); err != nil {
			panic(err)
		}
	}

	out := os.Stdout

	out.WriteString(`/* Copyright (c) 2015, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

 /* This file was generated by err_data_generate.go. */

#include <openssl/base.h>
#include <openssl/err.h>
#include <openssl/type_check.h>


`)

	for i, name := range libraryNames {
		fmt.Fprintf(out, "OPENSSL_COMPILE_ASSERT(ERR_LIB_%s == %d, library_values_changed_%d);\n", name, i+1, i+1)
	}
	fmt.Fprintf(out, "OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == %d, library_values_changed_num);\n", len(libraryNames)+1)
	out.WriteString("\n")

	e.reasons.WriteTo(out, "Reason")
}
