line.go 3.0 KB

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