/* Copyright (c) 2016, 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 (
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
)

var (
	boringsslDir = flag.String("boringssl", ".", "The path to the BoringSSL checkout.")
	opensslDir   = flag.String("openssl", filepath.Join("..", "openssl"), "The path to the OpenSSL checkout.")
)

func mapName(path string) string {
	switch filepath.ToSlash(path) {
	case "crypto/rand/asm/rdrand-x86_64.pl":
		return ""
	case "crypto/ec/asm/p256-x86_64-asm.pl":
		return filepath.FromSlash("crypto/ec/asm/ecp_nistz256-x86_64.pl")
	}
	return path
}

func diff(from, to string) error {
	cmd := exec.Command("diff", "-u", "--", from, to)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	// diff returns exit code 1 if the files differ but it was otherwise
	// successful.
	if exitError, ok := err.(*exec.ExitError); ok && exitError.Sys().(syscall.WaitStatus).ExitStatus() == 1 {
		return nil
	}
	return err
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: diff_asm [flag...] [filter...]\n")
		fmt.Fprintf(os.Stderr, "Filter arguments limit to assembly files which match arguments.\n")
		fmt.Fprintf(os.Stderr, "If not using a filter, piping to `diffstat` may be useful.\n\n")
		flag.PrintDefaults()
	}
	flag.Parse()

	// Find all the assembly files.
	var files []string
	err := filepath.Walk(*boringsslDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil
		}

		path, err = filepath.Rel(*boringsslDir, path)
		if err != nil {
			return err
		}

		dir := filepath.Base(filepath.Dir(path))
		if !info.IsDir() && (dir == "asm" || dir == "perlasm") && strings.HasSuffix(filepath.Base(path), ".pl") {
			files = append(files, path)
		}

		return nil
	})
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error finding assembly: %s\n", err)
		os.Exit(1)
	}

	for _, file := range files {
		opensslFile := mapName(file)
		if len(opensslFile) == 0 {
			continue
		}

		if flag.NArg() > 0 {
			var found bool
			for _, arg := range flag.Args() {
				if strings.Contains(file, arg) {
					found = true
					break
				}
			}
			if !found {
				continue
			}
		}

		if err := diff(filepath.Join(*opensslDir, opensslFile), filepath.Join(*boringsslDir, file)); err != nil {
			fmt.Fprintf(os.Stderr, "Error comparing %s: %s\n", file, err)
			os.Exit(1)
		}
	}
}
