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