mirror of git://gcc.gnu.org/git/gcc.git
libgo: Update to weekly.2012-03-27 aka go1 release.
From-SVN: r186029
This commit is contained in:
parent
99002f8366
commit
a1552fc3ec
|
|
@ -1,4 +1,4 @@
|
||||||
bce220d03774
|
dc5e410f0b4c
|
||||||
|
|
||||||
The first line of this file holds the Mercurial revision number of the
|
The first line of this file holds the Mercurial revision number of the
|
||||||
last merge done from the master library sources.
|
last merge done from the master library sources.
|
||||||
|
|
|
||||||
|
|
@ -60,21 +60,23 @@ FindCipherSuite:
|
||||||
for _, id := range clientHello.cipherSuites {
|
for _, id := range clientHello.cipherSuites {
|
||||||
for _, supported := range config.cipherSuites() {
|
for _, supported := range config.cipherSuites() {
|
||||||
if id == supported {
|
if id == supported {
|
||||||
suite = nil
|
var candidate *cipherSuite
|
||||||
|
|
||||||
for _, s := range cipherSuites {
|
for _, s := range cipherSuites {
|
||||||
if s.id == id {
|
if s.id == id {
|
||||||
suite = s
|
candidate = s
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if suite == nil {
|
if candidate == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Don't select a ciphersuite which we can't
|
// Don't select a ciphersuite which we can't
|
||||||
// support for this client.
|
// support for this client.
|
||||||
if suite.elliptic && !ellipticOk {
|
if candidate.elliptic && !ellipticOk {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
suite = candidate
|
||||||
break FindCipherSuite
|
break FindCipherSuite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,10 @@ Curve:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if curveid == 0 {
|
||||||
|
return nil, errors.New("tls: no supported elliptic curves offered")
|
||||||
|
}
|
||||||
|
|
||||||
var x, y *big.Int
|
var x, y *big.Int
|
||||||
var err error
|
var err error
|
||||||
ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
|
ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ func processFiles(filenames []string, allFiles bool) {
|
||||||
|
|
||||||
func processPackage(fset *token.FileSet, files map[string]*ast.File) {
|
func processPackage(fset *token.FileSet, files map[string]*ast.File) {
|
||||||
// make a package (resolve all identifiers)
|
// make a package (resolve all identifiers)
|
||||||
pkg, err := ast.NewPackage(fset, files, types.GcImporter, types.Universe)
|
pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
report(err)
|
report(err)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ func check(t *testing.T, testname string, testfiles []string) {
|
||||||
eliminate(t, errors, err)
|
eliminate(t, errors, err)
|
||||||
|
|
||||||
// verify errors returned after resolving identifiers
|
// verify errors returned after resolving identifiers
|
||||||
pkg, err := ast.NewPackage(fset, files, GcImporter, Universe)
|
pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
|
||||||
eliminate(t, errors, err)
|
eliminate(t, errors, err)
|
||||||
|
|
||||||
// verify errors returned by the typechecker
|
// verify errors returned by the typechecker
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// This file implements ExportData.
|
// This file implements FindGcExportData.
|
||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
|
@ -11,15 +11,14 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readGopackHeader(buf *bufio.Reader) (name string, size int, err error) {
|
func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
|
||||||
// See $GOROOT/include/ar.h.
|
// See $GOROOT/include/ar.h.
|
||||||
hdr := make([]byte, 16+12+6+6+8+10+2)
|
hdr := make([]byte, 16+12+6+6+8+10+2)
|
||||||
_, err = io.ReadFull(buf, hdr)
|
_, err = io.ReadFull(r, hdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -36,33 +35,14 @@ func readGopackHeader(buf *bufio.Reader) (name string, size int, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type dataReader struct {
|
// FindGcExportData positions the reader r at the beginning of the
|
||||||
*bufio.Reader
|
// export data section of an underlying GC-created object/archive
|
||||||
io.Closer
|
// file by reading from it. The reader must be positioned at the
|
||||||
}
|
// start of the file before calling this function.
|
||||||
|
|
||||||
// ExportData returns a readCloser positioned at the beginning of the
|
|
||||||
// export data section of the given object/archive file, or an error.
|
|
||||||
// It is the caller's responsibility to close the readCloser.
|
|
||||||
//
|
//
|
||||||
func ExportData(filename string) (rc io.ReadCloser, err error) {
|
func FindGcExportData(r *bufio.Reader) (err error) {
|
||||||
file, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
file.Close()
|
|
||||||
// Add file name to error.
|
|
||||||
err = fmt.Errorf("reading export data: %s: %v", filename, err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
buf := bufio.NewReader(file)
|
|
||||||
|
|
||||||
// Read first line to make sure this is an object file.
|
// Read first line to make sure this is an object file.
|
||||||
line, err := buf.ReadSlice('\n')
|
line, err := r.ReadSlice('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +54,7 @@ func ExportData(filename string) (rc io.ReadCloser, err error) {
|
||||||
|
|
||||||
// First entry should be __.SYMDEF.
|
// First entry should be __.SYMDEF.
|
||||||
// Read and discard.
|
// Read and discard.
|
||||||
if name, size, err = readGopackHeader(buf); err != nil {
|
if name, size, err = readGopackHeader(r); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if name != "__.SYMDEF" {
|
if name != "__.SYMDEF" {
|
||||||
|
|
@ -88,15 +68,14 @@ func ExportData(filename string) (rc io.ReadCloser, err error) {
|
||||||
if n > block {
|
if n > block {
|
||||||
n = block
|
n = block
|
||||||
}
|
}
|
||||||
_, err = io.ReadFull(buf, tmp[:n])
|
if _, err = io.ReadFull(r, tmp[:n]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
size -= n
|
size -= n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second entry should be __.PKGDEF.
|
// Second entry should be __.PKGDEF.
|
||||||
if name, size, err = readGopackHeader(buf); err != nil {
|
if name, size, err = readGopackHeader(r); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if name != "__.PKGDEF" {
|
if name != "__.PKGDEF" {
|
||||||
|
|
@ -106,8 +85,7 @@ func ExportData(filename string) (rc io.ReadCloser, err error) {
|
||||||
|
|
||||||
// Read first line of __.PKGDEF data, so that line
|
// Read first line of __.PKGDEF data, so that line
|
||||||
// is once again the first line of the input.
|
// is once again the first line of the input.
|
||||||
line, err = buf.ReadSlice('\n')
|
if line, err = r.ReadSlice('\n'); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -122,12 +100,10 @@ func ExportData(filename string) (rc io.ReadCloser, err error) {
|
||||||
// Skip over object header to export data.
|
// Skip over object header to export data.
|
||||||
// Begins after first line with $$.
|
// Begins after first line with $$.
|
||||||
for line[0] != '$' {
|
for line[0] != '$' {
|
||||||
line, err = buf.ReadSlice('\n')
|
if line, err = r.ReadSlice('\n'); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = &dataReader{buf, file}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// This file implements an ast.Importer for gc generated object files.
|
// This file implements an ast.Importer for gc-generated object files.
|
||||||
// TODO(gri) Eventually move this into a separate package outside types.
|
// TODO(gri) Eventually move this into a separate package outside types.
|
||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
|
@ -24,41 +25,40 @@ import (
|
||||||
|
|
||||||
const trace = false // set to true for debugging
|
const trace = false // set to true for debugging
|
||||||
|
|
||||||
var (
|
var pkgExts = [...]string{".a", ".5", ".6", ".8"}
|
||||||
pkgExts = [...]string{".a", ".5", ".6", ".8"}
|
|
||||||
)
|
|
||||||
|
|
||||||
// findPkg returns the filename and package id for an import path.
|
// FindPkg returns the filename and unique package id for an import
|
||||||
|
// path based on package information provided by build.Import (using
|
||||||
|
// the build.Default build.Context).
|
||||||
// If no file was found, an empty filename is returned.
|
// If no file was found, an empty filename is returned.
|
||||||
func findPkg(path string) (filename, id string) {
|
//
|
||||||
|
func FindPkg(path, srcDir string) (filename, id string) {
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id = path
|
id = path
|
||||||
var noext string
|
var noext string
|
||||||
switch path[0] {
|
switch {
|
||||||
default:
|
default:
|
||||||
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
|
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
|
||||||
bp, _ := build.Import(path, "", build.FindOnly)
|
bp, _ := build.Import(path, srcDir, build.FindOnly)
|
||||||
if bp.PkgObj == "" {
|
if bp.PkgObj == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
noext = bp.PkgObj
|
noext = bp.PkgObj
|
||||||
if strings.HasSuffix(noext, ".a") {
|
if strings.HasSuffix(noext, ".a") {
|
||||||
noext = noext[:len(noext)-2]
|
noext = noext[:len(noext)-len(".a")]
|
||||||
}
|
}
|
||||||
|
|
||||||
case '.':
|
case build.IsLocalImport(path):
|
||||||
// "./x" -> "/this/directory/x.ext", "/this/directory/x"
|
// "./x" -> "/this/directory/x.ext", "/this/directory/x"
|
||||||
cwd, err := os.Getwd()
|
noext = filepath.Join(srcDir, path)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
noext = filepath.Join(cwd, path)
|
|
||||||
id = noext
|
id = noext
|
||||||
|
|
||||||
case '/':
|
case filepath.IsAbs(path):
|
||||||
|
// for completeness only - go/build.Import
|
||||||
|
// does not support absolute imports
|
||||||
// "/x" -> "/x.ext", "/x"
|
// "/x" -> "/x.ext", "/x"
|
||||||
noext = path
|
noext = path
|
||||||
}
|
}
|
||||||
|
|
@ -75,6 +75,89 @@ func findPkg(path string) (filename, id string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GcImportData imports a package by reading the gc-generated export data,
|
||||||
|
// adds the corresponding package object to the imports map indexed by id,
|
||||||
|
// and returns the object.
|
||||||
|
//
|
||||||
|
// The imports map must contains all packages already imported, and no map
|
||||||
|
// entry with id as the key must be present. The data reader position must
|
||||||
|
// be the beginning of the export data section. The filename is only used
|
||||||
|
// in error messages.
|
||||||
|
//
|
||||||
|
func GcImportData(imports map[string]*ast.Object, filename, id string, data *bufio.Reader) (pkg *ast.Object, err error) {
|
||||||
|
if trace {
|
||||||
|
fmt.Printf("importing %s (%s)\n", id, filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
if imports[id] != nil {
|
||||||
|
panic(fmt.Sprintf("package %s already imported", id))
|
||||||
|
}
|
||||||
|
|
||||||
|
// support for gcParser error handling
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err = r.(importError) // will re-panic if r is not an importError
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var p gcParser
|
||||||
|
p.init(filename, id, data, imports)
|
||||||
|
pkg = p.parseExport()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GcImport imports a gc-generated package given its import path, adds the
|
||||||
|
// corresponding package object to the imports map, and returns the object.
|
||||||
|
// Local import paths are interpreted relative to the current working directory.
|
||||||
|
// The imports map must contains all packages already imported.
|
||||||
|
// GcImport satisfies the ast.Importer signature.
|
||||||
|
//
|
||||||
|
func GcImport(imports map[string]*ast.Object, path string) (pkg *ast.Object, err error) {
|
||||||
|
if path == "unsafe" {
|
||||||
|
return Unsafe, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
srcDir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
filename, id := FindPkg(path, srcDir)
|
||||||
|
if filename == "" {
|
||||||
|
err = errors.New("can't find import: " + id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if pkg = imports[id]; pkg != nil {
|
||||||
|
return // package was imported before
|
||||||
|
}
|
||||||
|
|
||||||
|
// open file
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
// Add file name to error.
|
||||||
|
err = fmt.Errorf("reading export data: %s: %v", filename, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
buf := bufio.NewReader(f)
|
||||||
|
if err = FindGcExportData(buf); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg, err = GcImportData(imports, filename, id, buf)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// gcParser
|
||||||
|
|
||||||
// gcParser parses the exports inside a gc compiler-produced
|
// gcParser parses the exports inside a gc compiler-produced
|
||||||
// object/archive file and populates its scope with the results.
|
// object/archive file and populates its scope with the results.
|
||||||
type gcParser struct {
|
type gcParser struct {
|
||||||
|
|
@ -109,47 +192,6 @@ func (p *gcParser) next() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GcImporter implements the ast.Importer signature.
|
|
||||||
func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, err error) {
|
|
||||||
if path == "unsafe" {
|
|
||||||
return Unsafe, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
err = r.(importError) // will re-panic if r is not an importError
|
|
||||||
if trace {
|
|
||||||
panic(err) // force a stack trace
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
filename, id := findPkg(path)
|
|
||||||
if filename == "" {
|
|
||||||
err = errors.New("can't find import: " + id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if pkg = imports[id]; pkg != nil {
|
|
||||||
return // package was imported before
|
|
||||||
}
|
|
||||||
|
|
||||||
buf, err := ExportData(filename)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer buf.Close()
|
|
||||||
|
|
||||||
if trace {
|
|
||||||
fmt.Printf("importing %s (%s)\n", id, filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
var p gcParser
|
|
||||||
p.init(filename, id, buf, imports)
|
|
||||||
pkg = p.parseExport()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Declare inserts a named object of the given kind in scope.
|
// Declare inserts a named object of the given kind in scope.
|
||||||
func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
|
func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
|
||||||
// the object may have been imported before - if it exists
|
// the object may have been imported before - if it exists
|
||||||
|
|
@ -707,7 +749,6 @@ func (p *gcParser) parseConstDecl() {
|
||||||
p.next()
|
p.next()
|
||||||
typ = String.Underlying
|
typ = String.Underlying
|
||||||
default:
|
default:
|
||||||
println(p.tok)
|
|
||||||
p.errorf("expected literal got %s", scanner.TokenString(p.tok))
|
p.errorf("expected literal got %s", scanner.TokenString(p.tok))
|
||||||
}
|
}
|
||||||
if obj.Type == nil {
|
if obj.Type == nil {
|
||||||
|
|
|
||||||
|
|
@ -17,23 +17,23 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var gcName, gcPath string // compiler name and path
|
var gcPath string // Go compiler path
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// determine compiler
|
// determine compiler
|
||||||
|
var gc string
|
||||||
switch runtime.GOARCH {
|
switch runtime.GOARCH {
|
||||||
case "386":
|
case "386":
|
||||||
gcName = "8g"
|
gc = "8g"
|
||||||
case "amd64":
|
case "amd64":
|
||||||
gcName = "6g"
|
gc = "6g"
|
||||||
case "arm":
|
case "arm":
|
||||||
gcName = "5g"
|
gc = "5g"
|
||||||
default:
|
default:
|
||||||
gcName = "unknown-GOARCH-compiler"
|
gcPath = "unknown-GOARCH-compiler"
|
||||||
gcPath = gcName
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gcPath = filepath.Join(build.ToolDir, gcName)
|
gcPath = filepath.Join(build.ToolDir, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func compile(t *testing.T, dirname, filename string) {
|
func compile(t *testing.T, dirname, filename string) {
|
||||||
|
|
@ -41,7 +41,7 @@ func compile(t *testing.T, dirname, filename string) {
|
||||||
cmd.Dir = dirname
|
cmd.Dir = dirname
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s %s failed: %s", gcName, filename, err)
|
t.Errorf("%s %s failed: %s", gcPath, filename, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Logf("%s", string(out))
|
t.Logf("%s", string(out))
|
||||||
|
|
@ -52,7 +52,7 @@ func compile(t *testing.T, dirname, filename string) {
|
||||||
var imports = make(map[string]*ast.Object)
|
var imports = make(map[string]*ast.Object)
|
||||||
|
|
||||||
func testPath(t *testing.T, path string) bool {
|
func testPath(t *testing.T, path string) bool {
|
||||||
_, err := GcImporter(imports, path)
|
_, err := GcImport(imports, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("testPath(%s): %s", path, err)
|
t.Errorf("testPath(%s): %s", path, err)
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,6 @@ func (ctxt *Context) SrcDirs() []string {
|
||||||
// if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
|
// if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
|
||||||
var Default Context = defaultContext()
|
var Default Context = defaultContext()
|
||||||
|
|
||||||
// This list is also known to ../../../cmd/dist/build.c.
|
|
||||||
var cgoEnabled = map[string]bool{
|
var cgoEnabled = map[string]bool{
|
||||||
"darwin/386": true,
|
"darwin/386": true,
|
||||||
"darwin/amd64": true,
|
"darwin/amd64": true,
|
||||||
|
|
@ -388,7 +387,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
|
||||||
// but check that using it wouldn't find something
|
// but check that using it wouldn't find something
|
||||||
// else first.
|
// else first.
|
||||||
if ctxt.GOROOT != "" {
|
if ctxt.GOROOT != "" {
|
||||||
if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) {
|
if dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", sub); ctxt.isDir(dir) {
|
||||||
goto Found
|
goto Found
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// initialization side effects.
|
// initialization side effects.
|
||||||
//
|
//
|
||||||
// See "The Go image package" for more details:
|
// See "The Go image package" for more details:
|
||||||
// http://blog.golang.org/2011/09/go-image-package.html
|
// http://golang.org/doc/articles/image_package.html
|
||||||
package image
|
package image
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -623,6 +623,10 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if err == syscall.ECONNABORTED {
|
||||||
|
// This means that a socket on the listen queue was closed
|
||||||
|
// before we Accept()ed it; it's a silly error, so try again.
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
return nil, &OpError{"accept", fd.net, fd.laddr, err}
|
return nil, &OpError{"accept", fd.net, fd.laddr, err}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ const (
|
||||||
|
|
||||||
func (m FileMode) String() string {
|
func (m FileMode) String() string {
|
||||||
const str = "dalTLDpSugct"
|
const str = "dalTLDpSugct"
|
||||||
var buf [20]byte
|
var buf [32]byte // Mode is uint32.
|
||||||
w := 0
|
w := 0
|
||||||
for i, c := range str {
|
for i, c := range str {
|
||||||
if m&(1<<uint(32-1-i)) != 0 {
|
if m&(1<<uint(32-1-i)) != 0 {
|
||||||
|
|
|
||||||
|
|
@ -814,6 +814,7 @@ type VolumeNameTest struct {
|
||||||
var volumenametests = []VolumeNameTest{
|
var volumenametests = []VolumeNameTest{
|
||||||
{`c:/foo/bar`, `c:`},
|
{`c:/foo/bar`, `c:`},
|
||||||
{`c:`, `c:`},
|
{`c:`, `c:`},
|
||||||
|
{`2:`, ``},
|
||||||
{``, ``},
|
{``, ``},
|
||||||
{`\\\host`, ``},
|
{`\\\host`, ``},
|
||||||
{`\\\host\`, ``},
|
{`\\\host\`, ``},
|
||||||
|
|
@ -845,3 +846,26 @@ func TestVolumeName(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDriveLetterInEvalSymlinks(t *testing.T) {
|
||||||
|
if runtime.GOOS != "windows" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wd, _ := os.Getwd()
|
||||||
|
if len(wd) < 3 {
|
||||||
|
t.Errorf("Current directory path %q is too short", wd)
|
||||||
|
}
|
||||||
|
lp := strings.ToLower(wd)
|
||||||
|
up := strings.ToUpper(wd)
|
||||||
|
flp, err := filepath.EvalSymlinks(lp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EvalSymlinks(%q) failed: %q", lp, err)
|
||||||
|
}
|
||||||
|
fup, err := filepath.EvalSymlinks(up)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EvalSymlinks(%q) failed: %q", up, err)
|
||||||
|
}
|
||||||
|
if flp != fup {
|
||||||
|
t.Errorf("Results of EvalSymlinks do not match: %q and %q", flp, fup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,7 @@ func VolumeName(path string) (v string) {
|
||||||
}
|
}
|
||||||
// with drive letter
|
// with drive letter
|
||||||
c := path[0]
|
c := path[0]
|
||||||
if path[1] == ':' &&
|
if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
|
||||||
('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
|
|
||||||
'A' <= c && c <= 'Z') {
|
|
||||||
return path[:2]
|
return path[:2]
|
||||||
}
|
}
|
||||||
// is it UNC
|
// is it UNC
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,24 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
func evalSymlinks(path string) (string, error) {
|
func toShort(path string) (string, error) {
|
||||||
|
p := syscall.StringToUTF16(path)
|
||||||
|
b := p // GetShortPathName says we can reuse buffer
|
||||||
|
n, err := syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if n > uint32(len(b)) {
|
||||||
|
b = make([]uint16, n)
|
||||||
|
n, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return syscall.UTF16ToString(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toLong(path string) (string, error) {
|
||||||
p := syscall.StringToUTF16(path)
|
p := syscall.StringToUTF16(path)
|
||||||
b := p // GetLongPathName says we can reuse buffer
|
b := p // GetLongPathName says we can reuse buffer
|
||||||
n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
|
n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
|
||||||
|
|
@ -23,5 +40,24 @@ func evalSymlinks(path string) (string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b = b[:n]
|
b = b[:n]
|
||||||
return Clean(syscall.UTF16ToString(b)), nil
|
return syscall.UTF16ToString(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func evalSymlinks(path string) (string, error) {
|
||||||
|
p, err := toShort(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
p, err = toLong(p)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// syscall.GetLongPathName does not change the case of the drive letter,
|
||||||
|
// but the result of EvalSymlinks must be unique, so we have
|
||||||
|
// EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`).
|
||||||
|
// Make drive letter upper case.
|
||||||
|
if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
|
||||||
|
p = string(p[0]+'A'-'a') + p[1:]
|
||||||
|
}
|
||||||
|
return Clean(p), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@ Functions
|
||||||
|
|
||||||
During execution functions are found in two function maps: first in the
|
During execution functions are found in two function maps: first in the
|
||||||
template, then in the global function map. By default, no functions are defined
|
template, then in the global function map. By default, no functions are defined
|
||||||
in the template but the Funcs methods can be used to add them.
|
in the template but the Funcs method can be used to add them.
|
||||||
|
|
||||||
Predefined global functions are named as follows.
|
Predefined global functions are named as follows.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -448,6 +448,11 @@ runtime_main(void)
|
||||||
// roots.
|
// roots.
|
||||||
mstats.enablegc = 1;
|
mstats.enablegc = 1;
|
||||||
|
|
||||||
|
// The deadlock detection has false negatives.
|
||||||
|
// Let scvg start up, to eliminate the false negative
|
||||||
|
// for the trivial program func main() { select{} }.
|
||||||
|
runtime_gosched();
|
||||||
|
|
||||||
main_main();
|
main_main();
|
||||||
runtime_exit(0);
|
runtime_exit(0);
|
||||||
for(;;)
|
for(;;)
|
||||||
|
|
@ -795,6 +800,20 @@ top:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for deadlock situation.
|
// Look for deadlock situation.
|
||||||
|
// There is a race with the scavenger that causes false negatives:
|
||||||
|
// if the scavenger is just starting, then we have
|
||||||
|
// scvg != nil && grunning == 0 && gwait == 0
|
||||||
|
// and we do not detect a deadlock. It is possible that we should
|
||||||
|
// add that case to the if statement here, but it is too close to Go 1
|
||||||
|
// to make such a subtle change. Instead, we work around the
|
||||||
|
// false negative in trivial programs by calling runtime.gosched
|
||||||
|
// from the main goroutine just before main.main.
|
||||||
|
// See runtime_main above.
|
||||||
|
//
|
||||||
|
// On a related note, it is also possible that the scvg == nil case is
|
||||||
|
// wrong and should include gwait, but that does not happen in
|
||||||
|
// standard Go programs, which all start the scavenger.
|
||||||
|
//
|
||||||
if((scvg == nil && runtime_sched.grunning == 0) ||
|
if((scvg == nil && runtime_sched.grunning == 0) ||
|
||||||
(scvg != nil && runtime_sched.grunning == 1 && runtime_sched.gwait == 0 &&
|
(scvg != nil && runtime_sched.grunning == 1 && runtime_sched.gwait == 0 &&
|
||||||
(scvg->status == Grunning || scvg->status == Gsyscall))) {
|
(scvg->status == Grunning || scvg->status == Gsyscall))) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue