Commit dc444418 authored by Todd Neal's avatar Todd Neal

cmd/internal: remove duplicate pathToPrefix function

goobj.importPathToPrefix is 3x faster than gc.pathToPrefix so rename and
move it to cmd/internal/objabi which is already imported by both goobj and
gc.

Change-Id: I10eda5bce95ef6d5d888818c5c47258c2833ea45
Reviewed-on: https://go-review.googlesource.com/40875
Run-TryBot: Todd Neal <todd@tneal.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarMatthew Dempsky <mdempsky@google.com>
parent eb40f062
......@@ -606,7 +606,6 @@ var knownFormats = map[string]string{
"[]cmd/compile/internal/ssa.ID %v": "",
"[]string %v": "",
"bool %v": "",
"byte %02x": "",
"byte %08b": "",
"byte %c": "",
"cmd/compile/internal/arm.shift %d": "",
......
......@@ -5,7 +5,6 @@
package gc
import (
"bytes"
"cmd/compile/internal/types"
"cmd/internal/objabi"
"cmd/internal/src"
......@@ -1958,33 +1957,6 @@ func ngotype(n *Node) *types.Sym {
return nil
}
// Convert raw string to the prefix that will be used in the symbol
// table. All control characters, space, '%' and '"', as well as
// non-7-bit clean bytes turn into %xx. The period needs escaping
// only in the last segment of the path, and it makes for happier
// users if we escape that as little as possible.
//
// If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
func pathtoprefix(s string) string {
slash := strings.LastIndex(s, "/")
for i := 0; i < len(s); i++ {
c := s[i]
if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
var buf bytes.Buffer
for i := 0; i < len(s); i++ {
c := s[i]
if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
fmt.Fprintf(&buf, "%%%02x", c)
continue
}
buf.WriteByte(c)
}
return buf.String()
}
}
return s
}
var pkgMap = make(map[string]*types.Pkg)
var pkgs []*types.Pkg
......@@ -1995,7 +1967,7 @@ func mkpkg(path string) *types.Pkg {
p := new(types.Pkg)
p.Path = path
p.Prefix = pathtoprefix(path)
p.Prefix = objabi.PathToPrefix(path)
p.Syms = make(map[string]*types.Sym)
pkgMap[path] = p
pkgs = append(pkgs, p)
......
......@@ -159,45 +159,6 @@ type objReader struct {
pkgprefix string
}
// importPathToPrefix returns the prefix that will be used in the
// final symbol table for the given import path.
// We escape '%', '"', all control characters and non-ASCII bytes,
// and any '.' after the final slash.
//
// See ../../../cmd/ld/lib.c:/^pathtoprefix and
// ../../../cmd/gc/subr.c:/^pathtoprefix.
func importPathToPrefix(s string) string {
// find index of last slash, if any, or else -1.
// used for determining whether an index is after the last slash.
slash := strings.LastIndex(s, "/")
// check for chars that need escaping
n := 0
for r := 0; r < len(s); r++ {
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
n++
}
}
// quick exit
if n == 0 {
return s
}
// escape
const hex = "0123456789abcdef"
p := make([]byte, 0, len(s)+2*n)
for r := 0; r < len(s); r++ {
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
p = append(p, '%', hex[c>>4], hex[c&0xF])
} else {
p = append(p, c)
}
}
return string(p)
}
// init initializes r to read package p from f.
func (r *objReader) init(f io.ReadSeeker, p *Package) {
r.f = f
......@@ -206,7 +167,7 @@ func (r *objReader) init(f io.ReadSeeker, p *Package) {
r.limit, _ = f.Seek(0, io.SeekEnd)
f.Seek(r.offset, io.SeekStart)
r.b = bufio.NewReader(f)
r.pkgprefix = importPathToPrefix(p.ImportPath) + "."
r.pkgprefix = objabi.PathToPrefix(p.ImportPath) + "."
}
// error records that an error occurred.
......
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package goobj
import "testing"
var importPathToPrefixTests = []struct {
in string
out string
}{
{"runtime", "runtime"},
{"sync/atomic", "sync/atomic"},
{"golang.org/x/tools/godoc", "golang.org/x/tools/godoc"},
{"foo.bar/baz.quux", "foo.bar/baz%2equux"},
{"", ""},
{"%foo%bar", "%25foo%25bar"},
{"\x01\x00\x7F☺", "%01%00%7f%e2%98%ba"},
}
func TestImportPathToPrefix(t *testing.T) {
for _, tt := range importPathToPrefixTests {
if out := importPathToPrefix(tt.in); out != tt.out {
t.Errorf("importPathToPrefix(%q) = %q, want %q", tt.in, out, tt.out)
}
}
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package objabi
import "strings"
// PathToPrefix converts raw string to the prefix that will be used in the
// symbol table. All control characters, space, '%' and '"', as well as
// non-7-bit clean bytes turn into %xx. The period needs escaping only in the
// last segment of the path, and it makes for happier users if we escape that as
// little as possible.
func PathToPrefix(s string) string {
slash := strings.LastIndex(s, "/")
// check for chars that need escaping
n := 0
for r := 0; r < len(s); r++ {
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
n++
}
}
// quick exit
if n == 0 {
return s
}
// escape
const hex = "0123456789abcdef"
p := make([]byte, 0, len(s)+2*n)
for r := 0; r < len(s); r++ {
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
p = append(p, '%', hex[c>>4], hex[c&0xF])
} else {
p = append(p, c)
}
}
return string(p)
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package objabi
import "testing"
func TestPathToPrefix(t *testing.T) {
tests := []struct {
Path string
Expected string
}{{"foo/bar/v1", "foo/bar/v1"},
{"foo/bar/v.1", "foo/bar/v%2e1"},
{"f.o.o/b.a.r/v1", "f.o.o/b.a.r/v1"},
{"f.o.o/b.a.r/v.1", "f.o.o/b.a.r/v%2e1"},
{"f.o.o/b.a.r/v..1", "f.o.o/b.a.r/v%2e%2e1"},
{"f.o.o/b.a.r/v..1.", "f.o.o/b.a.r/v%2e%2e1%2e"},
{"f.o.o/b.a.r/v%1", "f.o.o/b.a.r/v%251"},
{"runtime", "runtime"},
{"sync/atomic", "sync/atomic"},
{"golang.org/x/tools/godoc", "golang.org/x/tools/godoc"},
{"foo.bar/baz.quux", "foo.bar/baz%2equux"},
{"", ""},
{"%foo%bar", "%25foo%25bar"},
{"\x01\x00\x7F☺", "%01%00%7f%e2%98%ba"},
}
for _, tc := range tests {
if got := PathToPrefix(tc.Path); got != tc.Expected {
t.Errorf("expected PathToPrefix(%s) = %s, got %s", tc.Path, tc.Expected, got)
}
}
}
......@@ -1059,7 +1059,7 @@ func addstrdata1(ctxt *Link, arg string) {
if eq < 0 || dot < 0 {
Exitf("-X flag requires argument of the form importpath.name=value")
}
addstrdata(ctxt, pathtoprefix(arg[:dot])+arg[dot:eq], arg[eq+1:])
addstrdata(ctxt, objabi.PathToPrefix(arg[:dot])+arg[dot:eq], arg[eq+1:])
}
func addstrdata(ctxt *Link, name string, value string) {
......
......@@ -651,7 +651,7 @@ func (ctxt *Link) loadlib() {
// first containing package that the linker loads). canonicalize
// it here to the package with which it will be laid down
// in text.
s.File = pathtoprefix(lib.Pkg)
s.File = objabi.PathToPrefix(lib.Pkg)
}
}
}
......@@ -752,7 +752,7 @@ func genhash(ctxt *Link, lib *Library) {
}
func objfile(ctxt *Link, lib *Library) {
pkg := pathtoprefix(lib.Pkg)
pkg := objabi.PathToPrefix(lib.Pkg)
if ctxt.Debugvlog > 1 {
ctxt.Logf("%5.2f ldobj: %s (%s)\n", Cputime(), lib.File, pkg)
......@@ -1312,7 +1312,7 @@ func hostlinkArchArgs() []string {
// compiled by a non-Go compiler) it returns the Hostobj pointer. If
// it is a Go object, it returns nil.
func ldobj(ctxt *Link, f *bio.Reader, lib *Library, length int64, pn string, file string, whence int) *Hostobj {
pkg := pathtoprefix(lib.Pkg)
pkg := objabi.PathToPrefix(lib.Pkg)
eof := f.Offset() + length
start := f.Offset()
......@@ -1572,35 +1572,6 @@ func ldshlibsyms(ctxt *Link, shlib string) {
ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses})
}
// Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync.
/*
* Convert raw string to the prefix that will be used in the symbol table.
* Invalid bytes turn into %xx. Right now the only bytes that need
* escaping are %, ., and ", but we escape all control characters too.
*
* If you edit this, edit ../gc/subr.c:/^pathtoprefix too.
* If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
*/
func pathtoprefix(s string) string {
slash := strings.LastIndex(s, "/")
for i := 0; i < len(s); i++ {
c := s[i]
if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
var buf bytes.Buffer
for i := 0; i < len(s); i++ {
c := s[i]
if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
fmt.Fprintf(&buf, "%%%02x", c)
continue
}
buf.WriteByte(c)
}
return buf.String()
}
}
return s
}
func addsection(seg *Segment, name string, rwx int) *Section {
sect := new(Section)
sect.Rwx = uint8(rwx)
......
......@@ -68,7 +68,7 @@ func LoadObjFile(ctxt *Link, f *bio.Reader, lib *Library, length int64, pn strin
}
func (r *objReader) loadObjFile() {
pkg := pathtoprefix(r.lib.Pkg)
pkg := objabi.PathToPrefix(r.lib.Pkg)
// Magic header
var buf [8]uint8
......@@ -168,7 +168,7 @@ func (r *objReader) readSym() {
typ := r.readSymIndex()
data := r.readData()
nreloc := r.readInt()
pkg := pathtoprefix(r.lib.Pkg)
pkg := objabi.PathToPrefix(r.lib.Pkg)
isdup := false
var dup *Symbol
......@@ -345,7 +345,7 @@ func (r *objReader) patchDWARFName(s *Symbol) {
if p == -1 {
return
}
pkgprefix := []byte(pathtoprefix(r.lib.Pkg) + ".")
pkgprefix := []byte(objabi.PathToPrefix(r.lib.Pkg) + ".")
patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1)
s.P = append(patched, s.P[e:]...)
......@@ -478,7 +478,7 @@ func (r *objReader) readData() []byte {
// readSymName reads a symbol name, replacing all "". with pkg.
func (r *objReader) readSymName() string {
pkg := pathtoprefix(r.lib.Pkg)
pkg := objabi.PathToPrefix(r.lib.Pkg)
n := r.readInt()
if n == 0 {
r.readInt64()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment