Skip to content

Commit 762eb40

Browse files
committed
cmd/go: split out cmd/go/internal/str
This is one CL in a long sequence of changes to break up the go command from one package into a plausible group of packages. This sequence is concerned only with moving code, not changing or cleaning up code. There will still be more cleanup after this sequence. The entire sequence will be submitted together: it is not a goal for the tree to build at every step. For #18653. Change-Id: I63f578f5ac99c707b599ac5659293c46b275567d Reviewed-on: https://go-review.googlesource.com/36190 Reviewed-by: David Crawshaw <[email protected]>
1 parent d9e6835 commit 762eb40

File tree

11 files changed

+154
-126
lines changed

11 files changed

+154
-126
lines changed

src/cmd/go/build.go

+18-17
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package main
77
import (
88
"bufio"
99
"bytes"
10+
"cmd/go/internal/str"
1011
"container/heap"
1112
"debug/elf"
1213
"errors"
@@ -2091,7 +2092,7 @@ func (b *builder) run(dir string, desc string, env []string, cmdargs ...interfac
20912092
out, err := b.runOut(dir, desc, env, cmdargs...)
20922093
if len(out) > 0 {
20932094
if desc == "" {
2094-
desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " "))
2095+
desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " "))
20952096
}
20962097
b.showOutput(dir, desc, b.processOutput(out))
20972098
if err != nil {
@@ -2121,7 +2122,7 @@ func (b *builder) processOutput(out []byte) string {
21212122
// runOut runs the command given by cmdline in the directory dir.
21222123
// It returns the command output and any errors that occurred.
21232124
func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
2124-
cmdline := stringList(cmdargs...)
2125+
cmdline := str.StringList(cmdargs...)
21252126
if buildN || buildX {
21262127
var envcmdline string
21272128
for i := range env {
@@ -2450,7 +2451,7 @@ func toolVerify(b *builder, p *Package, newTool string, ofile string, args []int
24502451
return err
24512452
}
24522453
if !bytes.Equal(data1, data2) {
2453-
return fmt.Errorf("%s and %s produced different output files:\n%s\n%s", filepath.Base(args[1].(string)), newTool, strings.Join(stringList(args...), " "), strings.Join(stringList(newArgs...), " "))
2454+
return fmt.Errorf("%s and %s produced different output files:\n%s\n%s", filepath.Base(args[1].(string)), newTool, strings.Join(str.StringList(args...), " "), strings.Join(str.StringList(newArgs...), " "))
24542455
}
24552456
os.Remove(ofile + ".new")
24562457
return nil
@@ -2477,7 +2478,7 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
24772478
}
24782479

24792480
if buildN || buildX {
2480-
cmdline := stringList("pack", "r", absAfile, absOfiles)
2481+
cmdline := str.StringList("pack", "r", absAfile, absOfiles)
24812482
b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
24822483
}
24832484
if buildN {
@@ -2692,7 +2693,7 @@ func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmh
26922693
if p.localPrefix != "" {
26932694
gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
26942695
}
2695-
args := stringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
2696+
args := str.StringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
26962697
for _, f := range gofiles {
26972698
args = append(args, mkAbs(p.Dir, f))
26982699
}
@@ -2913,7 +2914,7 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
29132914
ldflags = append(ldflags, root.p.CgoLDFLAGS...)
29142915
}
29152916

2916-
ldflags = stringList("-Wl,-(", ldflags, "-Wl,-)")
2917+
ldflags = str.StringList("-Wl,-(", ldflags, "-Wl,-)")
29172918

29182919
for _, shlib := range shlibs {
29192920
ldflags = append(
@@ -3244,11 +3245,11 @@ func envList(key, def string) []string {
32443245
func (b *builder) cflags(p *Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
32453246
defaults := "-g -O2"
32463247

3247-
cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
3248-
cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
3249-
cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
3250-
fflags = stringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS)
3251-
ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
3248+
cppflags = str.StringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
3249+
cflags = str.StringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
3250+
cxxflags = str.StringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
3251+
fflags = str.StringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS)
3252+
ldflags = str.StringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
32523253
return
32533254
}
32543255

@@ -3354,7 +3355,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
33543355
outGo = append(outGo, gofiles...)
33553356

33563357
// gcc
3357-
cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
3358+
cflags := str.StringList(cgoCPPFLAGS, cgoCFLAGS)
33583359
for _, cfile := range cfiles {
33593360
ofile := obj + cfile[:len(cfile)-1] + "o"
33603361
if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil {
@@ -3372,7 +3373,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
33723373
outObj = append(outObj, ofile)
33733374
}
33743375

3375-
cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
3376+
cxxflags := str.StringList(cgoCPPFLAGS, cgoCXXFLAGS)
33763377
for _, file := range gxxfiles {
33773378
// Append .o to the file, just in case the pkg has file.c and file.cpp
33783379
ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o"
@@ -3391,7 +3392,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
33913392
outObj = append(outObj, ofile)
33923393
}
33933394

3394-
fflags := stringList(cgoCPPFLAGS, cgoFFLAGS)
3395+
fflags := str.StringList(cgoCPPFLAGS, cgoFFLAGS)
33953396
for _, file := range ffiles {
33963397
// Append .o to the file, just in case the pkg has file.c and file.f
33973398
ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o"
@@ -3440,7 +3441,7 @@ func (b *builder) dynimport(p *Package, obj, importGo, cgoExe string, cflags, cg
34403441
return err
34413442
}
34423443

3443-
linkobj := stringList(ofile, outObj, p.SysoFiles)
3444+
linkobj := str.StringList(ofile, outObj, p.SysoFiles)
34443445
dynobj := obj + "_cgo_.o"
34453446

34463447
// we need to use -pie for Linux/ARM to get accurate imported sym
@@ -3672,9 +3673,9 @@ func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx b
36723673
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.cflags(p)
36733674
var cflags []string
36743675
if cxx {
3675-
cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
3676+
cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
36763677
} else {
3677-
cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
3678+
cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
36783679
}
36793680

36803681
n := 5 // length of ".swig"

src/cmd/go/fix.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
package main
66

7+
import "cmd/go/internal/str"
8+
79
var cmdFix = &Command{
810
Run: runFix,
911
UsageLine: "fix [packages]",
@@ -25,6 +27,6 @@ func runFix(cmd *Command, args []string) {
2527
// Use pkg.gofiles instead of pkg.Dir so that
2628
// the command only applies to this package,
2729
// not to packages in subdirectories.
28-
run(stringList(buildToolExec, tool("fix"), relPaths(pkg.allgofiles)))
30+
run(str.StringList(buildToolExec, tool("fix"), relPaths(pkg.allgofiles)))
2931
}
3032
}

src/cmd/go/fmt.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package main
66

77
import (
8+
"cmd/go/internal/str"
89
"os"
910
"path/filepath"
1011
)
@@ -39,7 +40,7 @@ func runFmt(cmd *Command, args []string) {
3940
// Use pkg.gofiles instead of pkg.Dir so that
4041
// the command only applies to this package,
4142
// not to packages in subdirectories.
42-
run(stringList(gofmt, "-l", "-w", relPaths(pkg.allgofiles)))
43+
run(str.StringList(gofmt, "-l", "-w", relPaths(pkg.allgofiles)))
4344
}
4445
}
4546

src/cmd/go/get.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package main
66

77
import (
8+
"cmd/go/internal/str"
89
"fmt"
910
"go/build"
1011
"os"
@@ -302,7 +303,7 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
302303
// due to wildcard expansion.
303304
for _, p := range pkgs {
304305
if *getFix {
305-
run(buildToolExec, stringList(tool("fix"), relPaths(p.allgofiles)))
306+
run(buildToolExec, str.StringList(tool("fix"), relPaths(p.allgofiles)))
306307

307308
// The imports might have changed, so reload again.
308309
p = reloadPackage(arg, stk)
@@ -324,7 +325,7 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
324325
// Process test dependencies when -t is specified.
325326
// (But don't get test dependencies for test dependencies:
326327
// we always pass mode 0 to the recursive calls below.)
327-
imports = stringList(imports, p.TestImports, p.XTestImports)
328+
imports = str.StringList(imports, p.TestImports, p.XTestImports)
328329
}
329330
for i, path := range imports {
330331
if path == "C" {

src/cmd/go/internal/str/str.go

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2017 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 str provides string manipulation utilities.
6+
package str
7+
8+
import (
9+
"bytes"
10+
"fmt"
11+
"unicode"
12+
"unicode/utf8"
13+
)
14+
15+
// StringList flattens its arguments into a single []string.
16+
// Each argument in args must have type string or []string.
17+
func StringList(args ...interface{}) []string {
18+
var x []string
19+
for _, arg := range args {
20+
switch arg := arg.(type) {
21+
case []string:
22+
x = append(x, arg...)
23+
case string:
24+
x = append(x, arg)
25+
default:
26+
panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
27+
}
28+
}
29+
return x
30+
}
31+
32+
// toFold returns a string with the property that
33+
// strings.EqualFold(s, t) iff toFold(s) == toFold(t)
34+
// This lets us test a large set of strings for fold-equivalent
35+
// duplicates without making a quadratic number of calls
36+
// to EqualFold. Note that strings.ToUpper and strings.ToLower
37+
// do not have the desired property in some corner cases.
38+
func toFold(s string) string {
39+
// Fast path: all ASCII, no upper case.
40+
// Most paths look like this already.
41+
for i := 0; i < len(s); i++ {
42+
c := s[i]
43+
if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' {
44+
goto Slow
45+
}
46+
}
47+
return s
48+
49+
Slow:
50+
var buf bytes.Buffer
51+
for _, r := range s {
52+
// SimpleFold(x) cycles to the next equivalent rune > x
53+
// or wraps around to smaller values. Iterate until it wraps,
54+
// and we've found the minimum value.
55+
for {
56+
r0 := r
57+
r = unicode.SimpleFold(r0)
58+
if r <= r0 {
59+
break
60+
}
61+
}
62+
// Exception to allow fast path above: A-Z => a-z
63+
if 'A' <= r && r <= 'Z' {
64+
r += 'a' - 'A'
65+
}
66+
buf.WriteRune(r)
67+
}
68+
return buf.String()
69+
}
70+
71+
// FoldDup reports a pair of strings from the list that are
72+
// equal according to strings.EqualFold.
73+
// It returns "", "" if there are no such strings.
74+
func FoldDup(list []string) (string, string) {
75+
clash := map[string]string{}
76+
for _, s := range list {
77+
fold := toFold(s)
78+
if t := clash[fold]; t != "" {
79+
if s > t {
80+
s, t = t, s
81+
}
82+
return s, t
83+
}
84+
clash[fold] = s
85+
}
86+
return "", ""
87+
}
88+
89+
// Contains reports whether x contains s.
90+
func Contains(x []string, s string) bool {
91+
for _, t := range x {
92+
if t == s {
93+
return true
94+
}
95+
}
96+
return false
97+
}

src/cmd/go/main.go

+2-75
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package main
77
import (
88
"bufio"
99
"bytes"
10+
"cmd/go/internal/str"
1011
"flag"
1112
"fmt"
1213
"go/build"
@@ -453,7 +454,7 @@ func exitIfErrors() {
453454
}
454455

455456
func run(cmdargs ...interface{}) {
456-
cmdline := stringList(cmdargs...)
457+
cmdline := str.StringList(cmdargs...)
457458
if buildN || buildX {
458459
fmt.Printf("%s\n", strings.Join(cmdline, " "))
459460
if buildN {
@@ -730,77 +731,3 @@ func matchPackagesInFS(pattern string) []string {
730731
})
731732
return pkgs
732733
}
733-
734-
// stringList's arguments should be a sequence of string or []string values.
735-
// stringList flattens them into a single []string.
736-
func stringList(args ...interface{}) []string {
737-
var x []string
738-
for _, arg := range args {
739-
switch arg := arg.(type) {
740-
case []string:
741-
x = append(x, arg...)
742-
case string:
743-
x = append(x, arg)
744-
default:
745-
panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
746-
}
747-
}
748-
return x
749-
}
750-
751-
// toFold returns a string with the property that
752-
// strings.EqualFold(s, t) iff toFold(s) == toFold(t)
753-
// This lets us test a large set of strings for fold-equivalent
754-
// duplicates without making a quadratic number of calls
755-
// to EqualFold. Note that strings.ToUpper and strings.ToLower
756-
// have the desired property in some corner cases.
757-
func toFold(s string) string {
758-
// Fast path: all ASCII, no upper case.
759-
// Most paths look like this already.
760-
for i := 0; i < len(s); i++ {
761-
c := s[i]
762-
if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' {
763-
goto Slow
764-
}
765-
}
766-
return s
767-
768-
Slow:
769-
var buf bytes.Buffer
770-
for _, r := range s {
771-
// SimpleFold(x) cycles to the next equivalent rune > x
772-
// or wraps around to smaller values. Iterate until it wraps,
773-
// and we've found the minimum value.
774-
for {
775-
r0 := r
776-
r = unicode.SimpleFold(r0)
777-
if r <= r0 {
778-
break
779-
}
780-
}
781-
// Exception to allow fast path above: A-Z => a-z
782-
if 'A' <= r && r <= 'Z' {
783-
r += 'a' - 'A'
784-
}
785-
buf.WriteRune(r)
786-
}
787-
return buf.String()
788-
}
789-
790-
// foldDup reports a pair of strings from the list that are
791-
// equal according to strings.EqualFold.
792-
// It returns "", "" if there are no such strings.
793-
func foldDup(list []string) (string, string) {
794-
clash := map[string]string{}
795-
for _, s := range list {
796-
fold := toFold(s)
797-
if t := clash[fold]; t != "" {
798-
if s > t {
799-
s, t = t, s
800-
}
801-
return s, t
802-
}
803-
clash[fold] = s
804-
}
805-
return "", ""
806-
}

0 commit comments

Comments
 (0)