| // 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 |
| |
| } |