// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package gccgoimporter implements Import for gccgo-generated object files.
package gccgoimporter // import "go/internal/gccgoimporter"

import (
	"bytes"
	"debug/elf"
	"fmt"
	"go/types"
	"internal/xcoff"
	"io"
	"os"
	"path/filepath"
	"strings"
)

// A PackageInit describes an imported package that needs initialization.
type PackageInit struct {
	Name     string // short package name
	InitFunc string // name of init function
	Priority int    // priority of init function, see InitData.Priority
}

// The gccgo-specific init data for a package.
type InitData struct {
	// Initialization priority of this package relative to other packages.
	// This is based on the maximum depth of the package's dependency graph;
	// it is guaranteed to be greater than that of its dependencies.
	Priority int

	// The list of packages which this package depends on to be initialized,
	// including itself if needed. This is the subset of the transitive closure of
	// the package's dependencies that need initialization.
	Inits []PackageInit
}

// Locate the file from which to read export data.
// This is intended to replicate the logic in gofrontend.
func findExportFile(searchpaths []string, pkgpath string) (string, error) {
	for _, spath := range searchpaths {
		pkgfullpath := filepath.Join(spath, pkgpath)
		pkgdir, name := filepath.Split(pkgfullpath)

		for _, filepath := range [...]string{
			pkgfullpath,
			pkgfullpath + ".gox",
			pkgdir + "lib" + name + ".so",
			pkgdir + "lib" + name + ".a",
			pkgfullpath + ".o",
		} {
			fi, err := os.Stat(filepath)
			if err == nil && !fi.IsDir() {
				return filepath, nil
			}
		}
	}

	return "", fmt.Errorf("%s: could not find export data (tried %s)", pkgpath, strings.Join(searchpaths, ":"))
}

const (
	gccgov1Magic    = "v1;\n"
	gccgov2Magic    = "v2;\n"
	gccgov3Magic    = "v3;\n"
	goimporterMagic = "\n$$ "
	archiveMagic    = "!<ar"
	aixbigafMagic   = "<big"
)

// Opens the export data file at the given path. If this is an object file,
// searches for and opens the .go_export section. If this is an archive,
// reads the export data from the first member, which is assumed to be an object file.
// This is intended to replicate the logic in gofrontend.
func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
	f, err := os.Open(fpath)
	if err != nil {
		return
	}
	closer = f
	defer func() {
		if err != nil && closer != nil {
			f.Close()
		}
	}()

	var magic [4]byte
	_, err = f.ReadAt(magic[:], 0)
	if err != nil {
		return
	}

	var objreader io.ReaderAt
	switch string(magic[:]) {
	case gccgov1Magic, gccgov2Magic, gccgov3Magic, goimporterMagic:
		// Raw export data.
		reader = f
		return

	case archiveMagic, aixbigafMagic:
		reader, err = arExportData(f)
		return

	default:
		objreader = f
	}

	ef, err := elf.NewFile(objreader)
	if err == nil {
		sec := ef.Section(".go_export")
		if sec == nil {
			err = fmt.Errorf("%s: .go_export section not found", fpath)
			return
		}
		reader = sec.Open()
		return
	}

	xf, err := xcoff.NewFile(objreader)
	if err == nil {
		sdat := xf.CSect(".go_export")
		if sdat == nil {
			err = fmt.Errorf("%s: .go_export section not found", fpath)
			return
		}
		reader = bytes.NewReader(sdat)
		return
	}

	err = fmt.Errorf("%s: unrecognized file format", fpath)
	return
}

// An Importer resolves import paths to Packages. The imports map records
// packages already known, indexed by package path.
// An importer must determine the canonical package path and check imports
// to see if it is already present in the map. If so, the Importer can return
// the map entry. Otherwise, the importer must load the package data for the
// given path into a new *Package, record it in imports map, and return the
// package.
type Importer func(imports map[string]*types.Package, path, srcDir string, lookup func(string) (io.ReadCloser, error)) (*types.Package, error)

func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Importer {
	return func(imports map[string]*types.Package, pkgpath, srcDir string, lookup func(string) (io.ReadCloser, error)) (pkg *types.Package, err error) {
		// TODO(gri): Use srcDir.
		// Or not. It's possible that srcDir will fade in importance as
		// the go command and other tools provide a translation table
		// for relative imports (like ./foo or vendored imports).
		if pkgpath == "unsafe" {
			return types.Unsafe, nil
		}

		var reader io.ReadSeeker
		var fpath string
		var rc io.ReadCloser
		if lookup != nil {
			if p := imports[pkgpath]; p != nil && p.Complete() {
				return p, nil
			}
			rc, err = lookup(pkgpath)
			if err != nil {
				return nil, err
			}
		}
		if rc != nil {
			defer rc.Close()
			rs, ok := rc.(io.ReadSeeker)
			if !ok {
				return nil, fmt.Errorf("gccgo importer requires lookup to return an io.ReadSeeker, have %T", rc)
			}
			reader = rs
			fpath = "<lookup " + pkgpath + ">"
			// Take name from Name method (like on os.File) if present.
			if n, ok := rc.(interface{ Name() string }); ok {
				fpath = n.Name()
			}
		} else {
			fpath, err = findExportFile(searchpaths, pkgpath)
			if err != nil {
				return nil, err
			}

			r, closer, err := openExportFile(fpath)
			if err != nil {
				return nil, err
			}
			if closer != nil {
				defer closer.Close()
			}
			reader = r
		}

		var magics string
		magics, err = readMagic(reader)
		if err != nil {
			return
		}

		if magics == archiveMagic || magics == aixbigafMagic {
			reader, err = arExportData(reader)
			if err != nil {
				return
			}
			magics, err = readMagic(reader)
			if err != nil {
				return
			}
		}

		switch magics {
		case gccgov1Magic, gccgov2Magic, gccgov3Magic:
			var p parser
			p.init(fpath, reader, imports)
			pkg = p.parsePackage()
			if initmap != nil {
				initmap[pkg] = p.initdata
			}

		// Excluded for now: Standard gccgo doesn't support this import format currently.
		// case goimporterMagic:
		// 	var data []byte
		// 	data, err = ioutil.ReadAll(reader)
		// 	if err != nil {
		// 		return
		// 	}
		// 	var n int
		// 	n, pkg, err = importer.ImportData(imports, data)
		// 	if err != nil {
		// 		return
		// 	}

		// 	if initmap != nil {
		// 		suffixreader := bytes.NewReader(data[n:])
		// 		var p parser
		// 		p.init(fpath, suffixreader, nil)
		// 		p.parseInitData()
		// 		initmap[pkg] = p.initdata
		// 	}

		default:
			err = fmt.Errorf("unrecognized magic string: %q", magics)
		}

		return
	}
}

// readMagic reads the four bytes at the start of a ReadSeeker and
// returns them as a string.
func readMagic(reader io.ReadSeeker) (string, error) {
	var magic [4]byte
	if _, err := reader.Read(magic[:]); err != nil {
		return "", err
	}
	if _, err := reader.Seek(0, io.SeekStart); err != nil {
		return "", err
	}
	return string(magic[:]), nil
}
