// Copyright (c) 2014, 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"
	"errors"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

// ssl.h reserves values 1000 and above for error codes corresponding to
// alerts. If automatically assigned reason codes exceed this value, this script
// will error. This must be kept in sync with SSL_AD_REASON_OFFSET in ssl.h.
const reservedReasonCode = 1000

var resetFlag *bool = flag.Bool("reset", false, "If true, ignore current assignments and reassign from scratch")

type libraryInfo struct {
	sourceDirs []string
	headerName string
}

func getLibraryInfo(lib string) libraryInfo {
	var info libraryInfo
	if lib == "ssl" {
		info.sourceDirs = []string{"ssl"}
	} else {
		info.sourceDirs = []string{
			filepath.Join("crypto", lib),
			filepath.Join("crypto", lib+"_extra"),
			filepath.Join("crypto", "fipsmodule", lib),
		}
	}
	info.headerName = lib + ".h"

	if lib == "evp" {
		info.headerName = "evp_errors.h"
		info.sourceDirs = append(info.sourceDirs, filepath.Join("crypto", "hpke"))
	}

	return info
}

func makeErrors(lib string, reset bool) error {
	topLevelPath, err := findToplevel()
	if err != nil {
		return err
	}

	info := getLibraryInfo(lib)

	headerPath := filepath.Join(topLevelPath, "include", "openssl", info.headerName)
	errDir := filepath.Join(topLevelPath, "crypto", "err")
	dataPath := filepath.Join(errDir, lib+".errordata")

	headerFile, err := os.Open(headerPath)
	if err != nil {
		if os.IsNotExist(err) {
			return fmt.Errorf("No header %s. Run in the right directory or touch the file.", headerPath)
		}

		return err
	}

	prefix := strings.ToUpper(lib)
	reasons, err := parseHeader(prefix, headerFile)
	headerFile.Close()

	if reset {
		err = nil
		// Retain any reason codes above reservedReasonCode.
		newReasons := make(map[string]int)
		for key, value := range reasons {
			if value >= reservedReasonCode {
				newReasons[key] = value
			}
		}
		reasons = newReasons
	}

	if err != nil {
		return err
	}

	for _, sourceDir := range info.sourceDirs {
		fullPath := filepath.Join(topLevelPath, sourceDir)
		dir, err := os.Open(fullPath)
		if err != nil {
			if os.IsNotExist(err) {
				// Some directories in the search path may not exist.
				continue
			}
			return err
		}
		defer dir.Close()
		filenames, err := dir.Readdirnames(-1)
		if err != nil {
			return err
		}

		for _, name := range filenames {
			if !strings.HasSuffix(name, ".c") && !strings.HasSuffix(name, ".cc") {
				continue
			}

			if err := addReasons(reasons, filepath.Join(fullPath, name), prefix); err != nil {
				return err
			}
		}
	}

	assignNewValues(reasons, reservedReasonCode)

	headerFile, err = os.Open(headerPath)
	if err != nil {
		return err
	}
	defer headerFile.Close()

	newHeaderFile, err := os.OpenFile(headerPath+".tmp", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
	if err != nil {
		return err
	}
	defer newHeaderFile.Close()

	if err := writeHeaderFile(newHeaderFile, headerFile, prefix, reasons); err != nil {
		return err
	}
	// Windows forbids renaming an open file.
	headerFile.Close()
	newHeaderFile.Close()
	if err := os.Rename(headerPath+".tmp", headerPath); err != nil {
		return err
	}

	dataFile, err := os.OpenFile(dataPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}

	outputStrings(dataFile, lib, reasons)
	dataFile.Close()

	return nil
}

func findToplevel() (path string, err error) {
	path = "."
	buildingPath := filepath.Join(path, "BUILDING.md")

	_, err = os.Stat(buildingPath)
	for i := 0; i < 2 && err != nil && os.IsNotExist(err); i++ {
		if i == 0 {
			path = ".."
		} else {
			path = filepath.Join("..", path)
		}
		buildingPath = filepath.Join(path, "BUILDING.md")
		_, err = os.Stat(buildingPath)
	}
	if err != nil {
		return "", errors.New("Cannot find BUILDING.md file at the top-level")
	}
	return path, nil
}

type assignment struct {
	key   string
	value int
}

func outputAssignments(w io.Writer, assignments map[string]int) {
	sorted := make([]assignment, 0, len(assignments))
	for key, value := range assignments {
		sorted = append(sorted, assignment{key, value})
	}

	sort.Slice(sorted, func(i, j int) bool { return sorted[i].value < sorted[j].value })

	for _, assignment := range sorted {
		fmt.Fprintf(w, "#define %s %d\n", assignment.key, assignment.value)
	}
}

func parseDefineLine(line, lib string) (key string, value int, ok bool) {
	if !strings.HasPrefix(line, "#define ") {
		return
	}

	fields := strings.Fields(line)
	if len(fields) != 3 {
		return
	}

	key = fields[1]
	if !strings.HasPrefix(key, lib+"_R_") {
		return
	}

	var err error
	if value, err = strconv.Atoi(fields[2]); err != nil {
		return
	}

	ok = true
	return
}

func writeHeaderFile(w io.Writer, headerFile io.Reader, lib string, reasons map[string]int) error {
	var last []byte
	var haveLast, sawDefine bool
	newLine := []byte("\n")

	scanner := bufio.NewScanner(headerFile)
	for scanner.Scan() {
		line := scanner.Text()
		_, _, ok := parseDefineLine(line, lib)
		if ok {
			sawDefine = true
			continue
		}

		if haveLast {
			w.Write(last)
			w.Write(newLine)
		}

		if len(line) > 0 || !sawDefine {
			last = []byte(line)
			haveLast = true
		} else {
			haveLast = false
		}
		sawDefine = false
	}

	if err := scanner.Err(); err != nil {
		return err
	}

	outputAssignments(w, reasons)
	w.Write(newLine)

	if haveLast {
		w.Write(last)
		w.Write(newLine)
	}

	return nil
}

func outputStrings(w io.Writer, lib string, assignments map[string]int) {
	lib = strings.ToUpper(lib)
	prefixLen := len(lib + "_R_")

	keys := make([]string, 0, len(assignments))
	for key := range assignments {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	for _, key := range keys {
		fmt.Fprintf(w, "%s,%d,%s\n", lib, assignments[key], key[prefixLen:])
	}
}

func assignNewValues(assignments map[string]int, reserved int) {
	// Needs to be in sync with the reason limit in
	// |ERR_reason_error_string|.
	max := 99

	for _, value := range assignments {
		if reserved >= 0 && value >= reserved {
			continue
		}
		if value > max {
			max = value
		}
	}

	max++

	// Sort the keys, so this script is reproducible.
	keys := make([]string, 0, len(assignments))
	for key, value := range assignments {
		if value == -1 {
			keys = append(keys, key)
		}
	}
	sort.Strings(keys)

	for _, key := range keys {
		if reserved >= 0 && max >= reserved {
			// If this happens, try passing -reset. Otherwise bump
			// up reservedReasonCode.
			panic("Automatically-assigned values exceeded limit!")
		}
		assignments[key] = max
		max++
	}
}

func handleDeclareMacro(line, join, macroName string, m map[string]int) {
	if i := strings.Index(line, macroName); i >= 0 {
		contents := line[i+len(macroName):]
		if i := strings.Index(contents, ")"); i >= 0 {
			contents = contents[:i]
			args := strings.Split(contents, ",")
			for i := range args {
				args[i] = strings.TrimSpace(args[i])
			}
			if len(args) != 2 {
				panic("Bad macro line: " + line)
			}
			token := args[0] + join + args[1]
			if _, ok := m[token]; !ok {
				m[token] = -1
			}
		}
	}
}

func addReasons(reasons map[string]int, filename, prefix string) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	reasonPrefix := prefix + "_R_"

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()

		handleDeclareMacro(line, "_R_", "OPENSSL_DECLARE_ERROR_REASON(", reasons)

		for len(line) > 0 {
			i := strings.Index(line, prefix+"_")
			if i == -1 {
				break
			}

			line = line[i:]
			end := strings.IndexFunc(line, func(r rune) bool {
				return !(r == '_' || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9'))
			})
			if end == -1 {
				end = len(line)
			}

			var token string
			token, line = line[:end], line[end:]

			switch {
			case strings.HasPrefix(token, reasonPrefix):
				if _, ok := reasons[token]; !ok {
					reasons[token] = -1
				}
			}
		}
	}

	return scanner.Err()
}

func parseHeader(lib string, file io.Reader) (reasons map[string]int, err error) {
	reasons = make(map[string]int)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		key, value, ok := parseDefineLine(scanner.Text(), lib)
		if !ok {
			continue
		}

		reasons[key] = value
	}

	err = scanner.Err()
	return
}

func main() {
	flag.Parse()
	if flag.NArg() == 0 {
		fmt.Fprintf(os.Stderr, "Usage: make_errors.go LIB [LIB2...]\n")
		os.Exit(1)
	}

	for _, lib := range flag.Args() {
		if err := makeErrors(lib, *resetFlag); err != nil {
			fmt.Fprintf(os.Stderr, "Error generating errors for %q: %s\n", lib, err)
			os.Exit(1)
		}
	}
}
