...

Source file src/pkg/cmd/internal/objabi/line.go

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

View as plain text