github.com/bir3/gocompiler@v0.3.205/src/cmd/internal/objabi/line.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package objabi 6 7 import ( 8 "github.com/bir3/gocompiler/src/internal/buildcfg" 9 "os" 10 "path/filepath" 11 "strings" 12 ) 13 14 // WorkingDir returns the current working directory 15 // (or "/???" if the directory cannot be identified), 16 // with "/" as separator. 17 func WorkingDir() string { 18 var path string 19 path, _ = os.Getwd() 20 if path == "" { 21 path = "/???" 22 } 23 return filepath.ToSlash(path) 24 } 25 26 // AbsFile returns the absolute filename for file in the given directory, 27 // as rewritten by the rewrites argument. 28 // For unrewritten paths, AbsFile rewrites a leading $GOROOT prefix to the literal "$GOROOT". 29 // If the resulting path is the empty string, the result is "??". 30 // 31 // The rewrites argument is a ;-separated list of rewrites. 32 // Each rewrite is of the form "prefix" or "prefix=>replace", 33 // where prefix must match a leading sequence of path elements 34 // and is either removed entirely or replaced by the replacement. 35 func AbsFile(dir, file, rewrites string) string { 36 abs := file 37 if dir != "" && !filepath.IsAbs(file) { 38 abs = filepath.Join(dir, file) 39 } 40 41 abs, rewritten := ApplyRewrites(abs, rewrites) 42 if !rewritten && buildcfg.GOROOT != "" && hasPathPrefix(abs, buildcfg.GOROOT) { 43 abs = "$GOROOT" + abs[len(buildcfg.GOROOT):] 44 } 45 46 if abs == "" { 47 abs = "??" 48 } 49 return abs 50 } 51 52 // ApplyRewrites returns the filename for file in the given directory, 53 // as rewritten by the rewrites argument. 54 // 55 // The rewrites argument is a ;-separated list of rewrites. 56 // Each rewrite is of the form "prefix" or "prefix=>replace", 57 // where prefix must match a leading sequence of path elements 58 // and is either removed entirely or replaced by the replacement. 59 func ApplyRewrites(file, rewrites string) (string, bool) { 60 start := 0 61 for i := 0; i <= len(rewrites); i++ { 62 if i == len(rewrites) || rewrites[i] == ';' { 63 if new, ok := applyRewrite(file, rewrites[start:i]); ok { 64 return new, true 65 } 66 start = i + 1 67 } 68 } 69 70 return file, false 71 } 72 73 // applyRewrite applies the rewrite to the path, 74 // returning the rewritten path and a boolean 75 // indicating whether the rewrite applied at all. 76 func applyRewrite(path, rewrite string) (string, bool) { 77 prefix, replace := rewrite, "" 78 if j := strings.LastIndex(rewrite, "=>"); j >= 0 { 79 prefix, replace = rewrite[:j], rewrite[j+len("=>"):] 80 } 81 82 if prefix == "" || !hasPathPrefix(path, prefix) { 83 return path, false 84 } 85 if len(path) == len(prefix) { 86 return replace, true 87 } 88 if replace == "" { 89 return path[len(prefix)+1:], true 90 } 91 return replace + path[len(prefix):], true 92 } 93 94 // Does s have t as a path prefix? 95 // That is, does s == t or does s begin with t followed by a slash? 96 // For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true. 97 // Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true. 98 // We do not allow full Unicode case folding, for fear of causing more confusion 99 // or harm than good. (For an example of the kinds of things that can go wrong, 100 // see http://article.gmane.org/gmane.linux.kernel/1853266.) 101 func hasPathPrefix(s string, t string) bool { 102 if len(t) > len(s) { 103 return false 104 } 105 var i int 106 for i = 0; i < len(t); i++ { 107 cs := int(s[i]) 108 ct := int(t[i]) 109 if 'A' <= cs && cs <= 'Z' { 110 cs += 'a' - 'A' 111 } 112 if 'A' <= ct && ct <= 'Z' { 113 ct += 'a' - 'A' 114 } 115 if cs == '\\' { 116 cs = '/' 117 } 118 if ct == '\\' { 119 ct = '/' 120 } 121 if cs != ct { 122 return false 123 } 124 } 125 return i >= len(s) || s[i] == '/' || s[i] == '\\' 126 }