// Copyright 2026 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 sgutil import ( "flag" "fmt" "os" "path/filepath" "strings" ) type PathList struct { paths []string fromShell bool // if false, perform our own shell var expansion } func FlagPathList(name string, usage string, value ...string) *PathList { p := &PathList{paths: value, fromShell: false} flag.Var(p, name, usage) return p } func (l *PathList) String() string { return strings.Join(l.paths, string(filepath.ListSeparator)) } func (l *PathList) Set(val string) error { l.paths = filepath.SplitList(val) l.fromShell = true return nil } // Find returns the first element of l containing a file by the given name. If // file is not found in the path list, it returns a descriptive error. func (l *PathList) Find(file string) (string, error) { for _, path := range l.paths { if !l.fromShell { path = os.ExpandEnv(path) } if path == "" { // Probably an unknown shell variable. Ignore. continue } if _, err := os.Stat(filepath.Join(path, file)); err == nil { return filepath.Abs(path) } } var errMsg strings.Builder fmt.Fprintf(&errMsg, "%q not found in any of:", file) for _, path := range l.paths { errMsg.WriteString("\n\t") errMsg.WriteString(path) } return "", fmt.Errorf("%s", errMsg.String()) } // FlagXEDPath registers and returns a global -xedPath flag. func FlagXEDPath(genRoot string) *PathList { return FlagPathList("xedPath", "`list` of directories to search for XED data (must be an XED obj/dgen directory)", "$XEDPATH", genRoot+"/extern/xed/obj/dgen", "$HOME/xed/obj/dgen") } func ResolveXEDPath(flag *PathList) (string, error) { xedPath, err := flag.Find("all-dec-instructions.txt") if err != nil { return "", fmt.Errorf(`%s Could not find XED data. Use fetch-xed.sh to download it, or set $XEDPATH or -xedPath to the XED obj/dgen directory.`, err) } return xedPath, nil } // FlagARM64Path registers and returns a global -arm64Path flag. func FlagARM64Path(genRoot string) *PathList { const isaDir = "ISA_A64_xml_A_profile_2026-03_96-2026-03_rel" return FlagPathList("arm64Path", "`list` of directories to search for ARM64 ISA data", "$ARM64_ISA_PATH", genRoot+"/extern/"+isaDir, "$HOME/Downloads/"+isaDir) } func ResolveARM64Path(flag *PathList) (string, error) { arm64Path, err := flag.Find("abs_advsimd.xml") if err != nil { return "", fmt.Errorf(`%s Could not find ARM64 ISA data. Use fetch-arm64.sh to download it, or set $ARM64_ISA_PATH or -arm64Path to the ARM64 ISA specification directory.`, err) } return arm64Path, nil }