// Copyright 2018 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.

//go:build gc

package goroot

import (
	
	
	
	
	
)

// IsStandardPackage reports whether path is a standard package,
// given goroot and compiler.
func (, ,  string) bool {
	switch  {
	case "gc":
		 := filepath.Join(, "src", )
		,  := os.ReadDir()
		if  != nil {
			return false
		}
		for ,  := range  {
			if strings.HasSuffix(.Name(), ".go") {
				return true
			}
		}
		return false
	case "gccgo":
		return gccgoSearch.isStandard()
	default:
		panic("unknown compiler " + )
	}
}

// gccgoSearch holds the gccgo search directories.
type gccgoDirs struct {
	once sync.Once
	dirs []string
}

// gccgoSearch is used to check whether a gccgo package exists in the
// standard library.
var gccgoSearch gccgoDirs

// init finds the gccgo search directories. If this fails it leaves dirs == nil.
func ( *gccgoDirs) () {
	 := os.Getenv("GCCGO")
	if  == "" {
		 = "gccgo"
	}
	,  := exec.LookPath()
	if  != nil {
		return
	}

	,  := exec.Command(, "-print-search-dirs").Output()
	if  != nil {
		return
	}
	,  := exec.Command(, "-dumpversion").Output()
	if  != nil {
		return
	}
	 := strings.TrimSpace(string())
	,  := exec.Command(, "-dumpmachine").Output()
	if  != nil {
		return
	}
	 := strings.TrimSpace(string())

	 := strings.Split(string(), "\n")
	const  = "libraries: ="
	var  []string
	for ,  := range  {
		if strings.HasPrefix(, ) {
			 = filepath.SplitList(strings.TrimPrefix(, ))
			break
		}
	}
	if len() == 0 {
		return
	}

	var  []string
	for ,  := range  {
		 := filepath.Join(, "go", )
		if ,  := os.Stat();  == nil && .IsDir() {
			.dirs = append(.dirs, )
			 = filepath.Join(, )
			if ,  = os.Stat();  == nil && .IsDir() {
				.dirs = append(.dirs, )
			}
		}
		if ,  := os.Stat();  == nil && .IsDir() {
			 = append(, )
		}
	}
	.dirs = append(.dirs, ...)
}

// isStandard reports whether path is a standard library for gccgo.
func ( *gccgoDirs) ( string) bool {
	// Quick check: if the first path component has a '.', it's not
	// in the standard library. This skips most GOPATH directories.
	 := strings.Index(, "/")
	if  < 0 {
		 = len()
	}
	if strings.Contains([:], ".") {
		return false
	}

	if  == "unsafe" {
		// Special case.
		return true
	}

	.once.Do(.init)
	if .dirs == nil {
		// We couldn't find the gccgo search directories.
		// Best guess, since the first component did not contain
		// '.', is that this is a standard library package.
		return true
	}

	for ,  := range .dirs {
		 := filepath.Join(, ) + ".gox"
		if ,  := os.Stat();  == nil && !.IsDir() {
			return true
		}
	}

	return false
}