/* 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"
	"fmt"
	"io"
	"os"
	"sort"
	"strconv"
	"strings"
)

// 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()
	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() {
	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")
}
