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
5package objabi
6
7import (
8	"os"
9	"path/filepath"
10)
11
12// WorkingDir returns the current working directory
13// (or "/???" if the directory cannot be identified),
14// with "/" as separator.
15func WorkingDir() string {
16	var path string
17	path, _ = os.Getwd()
18	if path == "" {
19		path = "/???"
20	}
21	return filepath.ToSlash(path)
22}
23
24// AbsFile returns the absolute filename for file in the given directory.
25// It also removes a leading pathPrefix, or else rewrites a leading $GOROOT
26// prefix to the literal "$GOROOT".
27// If the resulting path is the empty string, the result is "??".
28func AbsFile(dir, file, pathPrefix string) string {
29	abs := file
30	if dir != "" && !filepath.IsAbs(file) {
31		abs = filepath.Join(dir, file)
32	}
33
34	if pathPrefix != "" && hasPathPrefix(abs, pathPrefix) {
35		if abs == pathPrefix {
36			abs = ""
37		} else {
38			abs = abs[len(pathPrefix)+1:]
39		}
40	} else if hasPathPrefix(abs, GOROOT) {
41		abs = "$GOROOT" + abs[len(GOROOT):]
42	}
43	if abs == "" {
44		abs = "??"
45	}
46
47	return abs
48}
49
50// Does s have t as a path prefix?
51// That is, does s == t or does s begin with t followed by a slash?
52// For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true.
53// Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true.
54// We do not allow full Unicode case folding, for fear of causing more confusion
55// or harm than good. (For an example of the kinds of things that can go wrong,
56// see http://article.gmane.org/gmane.linux.kernel/1853266.)
57func hasPathPrefix(s string, t string) bool {
58	if len(t) > len(s) {
59		return false
60	}
61	var i int
62	for i = 0; i < len(t); i++ {
63		cs := int(s[i])
64		ct := int(t[i])
65		if 'A' <= cs && cs <= 'Z' {
66			cs += 'a' - 'A'
67		}
68		if 'A' <= ct && ct <= 'Z' {
69			ct += 'a' - 'A'
70		}
71		if cs == '\\' {
72			cs = '/'
73		}
74		if ct == '\\' {
75			ct = '/'
76		}
77		if cs != ct {
78			return false
79		}
80	}
81	return i >= len(s) || s[i] == '/' || s[i] == '\\'
82}
83