libgo: Update to weekly.2012-03-22.

From-SVN: r186026
This commit is contained in:
Ian Lance Taylor 2012-03-30 22:09:55 +00:00
parent 57c7433fdc
commit 9a18821cfc
51 changed files with 612 additions and 168 deletions

View File

@ -1,4 +1,4 @@
3cdba7b0650c
bce220d03774
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.

View File

@ -7,10 +7,12 @@ package zip
import (
"bytes"
"encoding/binary"
"encoding/hex"
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"testing"
"time"
)
@ -62,13 +64,14 @@ var tests = []ZipTest{
},
},
{
Name: "r.zip",
Name: "r.zip",
Source: returnRecursiveZip,
File: []ZipTestFile{
{
Name: "r/r.zip",
File: "r.zip",
Mtime: "03-04-10 00:24:16",
Mode: 0666,
Name: "r/r.zip",
Content: rZipBytes(),
Mtime: "03-04-10 00:24:16",
Mode: 0666,
},
},
},
@ -415,3 +418,49 @@ func returnCorruptNotStreamedZip() (r io.ReaderAt, size int64) {
// is what matters.
})
}
// rZipBytes returns the bytes of a recursive zip file, without
// putting it on disk and triggering certain virus scanners.
func rZipBytes() []byte {
s := `
0000000 50 4b 03 04 14 00 00 00 08 00 08 03 64 3c f9 f4
0000010 89 64 48 01 00 00 b8 01 00 00 07 00 00 00 72 2f
0000020 72 2e 7a 69 70 00 25 00 da ff 50 4b 03 04 14 00
0000030 00 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00
0000040 b8 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00
0000050 2f 00 d0 ff 00 25 00 da ff 50 4b 03 04 14 00 00
0000060 00 08 00 08 03 64 3c f9 f4 89 64 48 01 00 00 b8
0000070 01 00 00 07 00 00 00 72 2f 72 2e 7a 69 70 00 2f
0000080 00 d0 ff c2 54 8e 57 39 00 05 00 fa ff c2 54 8e
0000090 57 39 00 05 00 fa ff 00 05 00 fa ff 00 14 00 eb
00000a0 ff c2 54 8e 57 39 00 05 00 fa ff 00 05 00 fa ff
00000b0 00 14 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42
00000c0 88 21 c4 00 00 14 00 eb ff 42 88 21 c4 00 00 14
00000d0 00 eb ff 42 88 21 c4 00 00 14 00 eb ff 42 88 21
00000e0 c4 00 00 00 00 ff ff 00 00 00 ff ff 00 34 00 cb
00000f0 ff 42 88 21 c4 00 00 00 00 ff ff 00 00 00 ff ff
0000100 00 34 00 cb ff 42 e8 21 5e 0f 00 00 00 ff ff 0a
0000110 f0 66 64 12 61 c0 15 dc e8 a0 48 bf 48 af 2a b3
0000120 20 c0 9b 95 0d c4 67 04 42 53 06 06 06 40 00 06
0000130 00 f9 ff 6d 01 00 00 00 00 42 e8 21 5e 0f 00 00
0000140 00 ff ff 0a f0 66 64 12 61 c0 15 dc e8 a0 48 bf
0000150 48 af 2a b3 20 c0 9b 95 0d c4 67 04 42 53 06 06
0000160 06 40 00 06 00 f9 ff 6d 01 00 00 00 00 50 4b 01
0000170 02 14 00 14 00 00 00 08 00 08 03 64 3c f9 f4 89
0000180 64 48 01 00 00 b8 01 00 00 07 00 00 00 00 00 00
0000190 00 00 00 00 00 00 00 00 00 00 00 72 2f 72 2e 7a
00001a0 69 70 50 4b 05 06 00 00 00 00 01 00 01 00 35 00
00001b0 00 00 6d 01 00 00 00 00`
s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "")
s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "")
b, err := hex.DecodeString(s)
if err != nil {
panic(err)
}
return b
}
func returnRecursiveZip() (r io.ReaderAt, size int64) {
b := rZipBytes()
return bytes.NewReader(b), int64(len(b))
}

View File

@ -166,8 +166,11 @@ func (c *Conn) clientHandshake() error {
}
var certToSend *Certificate
var certRequested bool
certReq, ok := msg.(*certificateRequestMsg)
if ok {
certRequested = true
// RFC 4346 on the certificateAuthorities field:
// A list of the distinguished names of acceptable certificate
// authorities. These distinguished names may specify a desired
@ -238,9 +241,14 @@ func (c *Conn) clientHandshake() error {
}
finishedHash.Write(shd.marshal())
if certToSend != nil {
// If the server requested a certificate then we have to send a
// Certificate message, even if it's empty because we don't have a
// certificate to send.
if certRequested {
certMsg = new(certificateMsg)
certMsg.certificates = certToSend.Certificate
if certToSend != nil {
certMsg.certificates = certToSend.Certificate
}
finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
}

View File

@ -226,7 +226,7 @@ where * signifies zero or more repetitions and the type id of a value must
be predefined or be defined before the value in the stream.
See "Gobs of data" for a design discussion of the gob wire format:
http://blog.golang.org/2011/03/gobs-of-data.html
http://golang.org/doc/articles/gobs_of_data.html
*/
package gob

View File

@ -6,7 +6,7 @@
// RFC 4627.
//
// See "JSON and Go" for an introduction to this package:
// http://blog.golang.org/2011/01/json-and-go.html
// http://golang.org/doc/articles/json_and_go.html
package json
import (

View File

@ -356,7 +356,7 @@ func lastBoundary(fd *formInfo, b []byte) int {
return -1
}
if info.size == 0 { // ends with incomplete rune
if p == 0 { // starts wtih incomplete rune
if p == 0 { // starts with incomplete rune
return -1
}
i = p

View File

@ -102,11 +102,6 @@ func init() {
defType("Pointer")
defFun("Alignof")
defFun("New")
defFun("NewArray")
defFun("Offsetof")
defFun("Reflect")
defFun("Sizeof")
defFun("Typeof")
defFun("Unreflect")
}

View File

@ -0,0 +1,83 @@
// Copyright 2012 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.
// These examples demonstrate more intricate uses of the flag package.
package flag_test
import (
"errors"
"flag"
"fmt"
"strings"
"time"
)
// Example 1: A single string flag called "species" with default value "gopher".
var species = flag.String("species", "gopher", "the species we are studying")
// Example 2: Two flags sharing a variable, so we can have a shorthand.
// The order of initialization is undefined, so make sure both use the
// same default value. They must be set up with an init function.
var gopherType string
func init() {
const (
defaultGopher = "pocket"
usage = "the variety of gopher"
)
flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)")
}
// Example 3: A user-defined flag type, a slice of durations.
type interval []time.Duration
// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (i *interval) String() string {
return fmt.Sprint(*i)
}
// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (i *interval) Set(value string) error {
// If we wanted to allow the flag to be set multiple times,
// accumulating values, we would delete this if statement.
// That would permit usages such as
// -deltaT 10s -deltaT 15s
// and other combinations.
if len(*i) > 0 {
return errors.New("interval flag already set")
}
for _, dt := range strings.Split(value, ",") {
duration, err := time.ParseDuration(dt)
if err != nil {
return err
}
*i = append(*i, duration)
}
return nil
}
// Define a flag to accumulate durations. Because it has a special type,
// we need to use the Var function and therefore create the flag during
// init.
var intervalFlag interval
func init() {
// Tie the command-line flag to the intervalFlag variable and
// set a usage message.
flag.Var(&intervalFlag, "deltaT", "comma-separated list of intervals to use between events")
}
func Example() {
// All the interesting pieces are with the variables declared above, but
// to enable the flag package to see the flags defined there, one must
// execute, typically at the start of main (not init!):
// flag.Parse()
// We don't run it here because this is not a main function and
// the testing suite has already parsed the flags.
}

View File

@ -810,7 +810,7 @@ func TestMultiLine(t *testing.T) {
}
}
// RecursiveInt accepts an string matching %d.%d.%d....
// RecursiveInt accepts a string matching %d.%d.%d....
// and parses it into a linked list.
// It allows us to benchmark recursive descent style scanners.
type RecursiveInt struct {
@ -826,7 +826,7 @@ func (r *RecursiveInt) Scan(state ScanState, verb rune) (err error) {
next := new(RecursiveInt)
_, err = Fscanf(state, ".%v", next)
if err != nil {
if err == errors.New("input does not match format") || err == io.ErrUnexpectedEOF {
if err == io.ErrUnexpectedEOF {
err = nil
}
return

View File

@ -328,22 +328,22 @@ func (e *NoGoError) Error() string {
}
// Import returns details about the Go package named by the import path,
// interpreting local import paths relative to the src directory. If the path
// is a local import path naming a package that can be imported using a
// standard import path, the returned package will set p.ImportPath to
// that path.
// interpreting local import paths relative to the srcDir directory.
// If the path is a local import path naming a package that can be imported
// using a standard import path, the returned package will set p.ImportPath
// to that path.
//
// In the directory containing the package, .go, .c, .h, and .s files are
// considered part of the package except for:
//
// - .go files in package documentation
// - files starting with _ or .
// - files starting with _ or . (likely editor temporary files)
// - files with build constraints not satisfied by the context
//
// If an error occurs, Import returns a non-nil error also returns a non-nil
// *Package containing partial information.
//
func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package, error) {
func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) {
p := &Package{
ImportPath: path,
}
@ -363,11 +363,12 @@ func (ctxt *Context) Import(path string, src string, mode ImportMode) (*Package,
binaryOnly := false
if IsLocalImport(path) {
if src == "" {
pkga = "" // local imports have no installed path
if srcDir == "" {
return p, fmt.Errorf("import %q: import relative to unknown directory", path)
}
if !ctxt.isAbsPath(path) {
p.Dir = ctxt.joinPath(src, path)
p.Dir = ctxt.joinPath(srcDir, path)
}
// Determine canonical import path, if any.
if ctxt.GOROOT != "" {
@ -640,8 +641,8 @@ func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.P
}
// Import is shorthand for Default.Import.
func Import(path, src string, mode ImportMode) (*Package, error) {
return Default.Import(path, src, mode)
func Import(path, srcDir string, mode ImportMode) (*Package, error) {
return Default.Import(path, srcDir, mode)
}
// ImportDir is shorthand for Default.ImportDir.
@ -874,7 +875,7 @@ func splitQuoted(s string) (r []string, err error) {
// !cgo (if cgo is disabled)
// tag (if tag is listed in ctxt.BuildTags)
// !tag (if tag is not listed in ctxt.BuildTags)
// a slash-separated list of any of these
// a comma-separated list of any of these
//
func (ctxt *Context) match(name string) bool {
if name == "" {
@ -888,11 +889,11 @@ func (ctxt *Context) match(name string) bool {
return false
}
if strings.HasPrefix(name, "!") { // negation
return !ctxt.match(name[1:])
return len(name) > 1 && !ctxt.match(name[1:])
}
// Tags must be letters, digits, underscores.
// Unlike in Go identifiers, all digits is fine (e.g., "386").
// Unlike in Go identifiers, all digits are fine (e.g., "386").
for _, c := range name {
if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' {
return false

View File

@ -36,6 +36,7 @@ func TestMatch(t *testing.T) {
nomatch(runtime.GOOS + "," + runtime.GOARCH + ",!foo")
match(runtime.GOOS + "," + runtime.GOARCH + ",!bar")
nomatch(runtime.GOOS + "," + runtime.GOARCH + ",bar")
nomatch("!")
}
func TestDotSlashImport(t *testing.T) {

View File

@ -365,7 +365,7 @@ func (p *printer) setLineComment(text string) {
}
func (p *printer) isMultiLine(n ast.Node) bool {
return p.lineFor(n.End())-p.lineFor(n.Pos()) > 1
return p.lineFor(n.End())-p.lineFor(n.Pos()) > 0
}
func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) {

View File

@ -500,7 +500,7 @@ type _ struct {
type _ struct {
a, b,
c, d int // this line should be indented
c, d int // this line should be indented
u, v, w, x float // this line should be indented
p, q,
r, s float // this line should be indented
@ -562,10 +562,21 @@ var a2, b2,
var (
a3, b3,
c3, d3 int // this line should be indented
c3, d3 int // this line should be indented
a4, b4, c4 int // this line should be indented
)
// Test case from issue 3304: multi-line declarations must end
// a formatting section and not influence indentation of the
// next line.
var (
minRefreshTimeSec = flag.Int64("min_refresh_time_sec", 604800,
"minimum time window between two refreshes for a given user.")
x = flag.Int64("refresh_user_rollout_percent", 100,
"temporary flag to ramp up the refresh user rpc")
aVeryLongVariableName = stats.GetVarInt("refresh-user-count")
)
func _() {
var privateKey2 = &Block{Type: "RSA PRIVATE KEY",
Headers: map[string]string{},

View File

@ -577,6 +577,16 @@ c3, d3 int // this line should be indented
a4, b4, c4 int // this line should be indented
)
// Test case from issue 3304: multi-line declarations must end
// a formatting section and not influence indentation of the
// next line.
var (
minRefreshTimeSec = flag.Int64("min_refresh_time_sec", 604800,
"minimum time window between two refreshes for a given user.")
x = flag.Int64("refresh_user_rollout_percent", 100,
"temporary flag to ramp up the refresh user rpc")
aVeryLongVariableName = stats.GetVarInt("refresh-user-count")
)
func _() {
var privateKey2 = &Block{Type: "RSA PRIVATE KEY",

View File

@ -113,3 +113,36 @@ func TestClone(t *testing.T) {
t.Errorf("t3: got %q want %q", got, want)
}
}
func TestTemplates(t *testing.T) {
names := []string{"t0", "a", "lhs", "rhs"}
// Some template definitions borrowed from TestClone.
const tmpl = `
{{define "a"}}{{template "lhs"}}{{.}}{{template "rhs"}}{{end}}
{{define "lhs"}} <a href=" {{end}}
{{define "rhs"}} "></a> {{end}}`
t0 := Must(New("t0").Parse(tmpl))
templates := t0.Templates()
if len(templates) != len(names) {
t.Errorf("expected %d templates; got %d", len(names), len(templates))
}
for _, name := range names {
found := false
for _, tmpl := range templates {
if name == tmpl.text.Name() {
found = true
break
}
}
if !found {
t.Error("could not find template", name)
}
}
}
// This used to crash; http://golang.org/issue/3281
func TestCloneCrash(t *testing.T) {
t1 := New("all")
Must(t1.New("t1").Parse(`{{define "foo"}}foo{{end}}`))
t1.Clone()
}

View File

@ -26,10 +26,10 @@ type (
HTML string
// HTMLAttr encapsulates an HTML attribute from a trusted source,
// for example: ` dir="ltr"`.
// for example, ` dir="ltr"`.
HTMLAttr string
// JS encapsulates a known safe EcmaScript5 Expression, or example,
// JS encapsulates a known safe EcmaScript5 Expression, for example,
// `(x + y * z())`.
// Template authors are responsible for ensuring that typed expressions
// do not break the intended precedence and that there is no

View File

@ -8,6 +8,7 @@ import (
"bytes"
"fmt"
"html"
"io"
"text/template"
"text/template/parse"
)
@ -751,3 +752,44 @@ func (e *escaper) template(name string) *template.Template {
}
return t
}
// Forwarding functions so that clients need only import this package
// to reach the general escaping functions of text/template.
// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
func HTMLEscape(w io.Writer, b []byte) {
template.HTMLEscape(w, b)
}
// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
func HTMLEscapeString(s string) string {
return template.HTMLEscapeString(s)
}
// HTMLEscaper returns the escaped HTML equivalent of the textual
// representation of its arguments.
func HTMLEscaper(args ...interface{}) string {
return template.HTMLEscaper(args...)
}
// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
func JSEscape(w io.Writer, b []byte) {
template.JSEscape(w, b)
}
// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
func JSEscapeString(s string) string {
return template.JSEscapeString(s)
}
// JSEscaper returns the escaped JavaScript equivalent of the textual
// representation of its arguments.
func JSEscaper(args ...interface{}) string {
return template.JSEscaper(args...)
}
// URLQueryEscaper returns the escaped value of the textual representation of
// its arguments in a form suitable for embedding in a URL query.
func URLQueryEscaper(args ...interface{}) string {
return template.URLQueryEscaper(args...)
}

View File

@ -8,6 +8,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"os"
"strings"
"testing"
"text/template"
@ -1637,6 +1638,14 @@ func TestIndirectPrint(t *testing.T) {
}
}
// This is a test for issue 3272.
func TestEmptyTemplate(t *testing.T) {
page := Must(New("page").ParseFiles(os.DevNull))
if err := page.ExecuteTemplate(os.Stdout, "page", "nothing"); err == nil {
t.Fatal("expected error")
}
}
func BenchmarkEscapedExecute(b *testing.B) {
tmpl := Must(New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`))
var buf bytes.Buffer

View File

@ -31,6 +31,20 @@ type nameSpace struct {
set map[string]*Template
}
// Templates returns a slice of the templates associated with t, including t
// itself.
func (t *Template) Templates() []*Template {
ns := t.nameSpace
ns.mu.Lock()
defer ns.mu.Unlock()
// Return a slice so we don't expose the map.
m := make([]*Template, 0, len(ns.set))
for _, v := range ns.set {
m = append(m, v)
}
return m
}
// Execute applies a parsed template to the specified data object,
// writing the output to wr.
func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
@ -64,7 +78,13 @@ func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err err
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
tmpl = t.set[name]
if (tmpl == nil) != (t.text.Lookup(name) == nil) {
if tmpl == nil {
return nil, fmt.Errorf("html/template: %q is undefined", name)
}
if tmpl.text.Tree == nil || tmpl.text.Root == nil {
return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
}
if t.text.Lookup(name) == nil {
panic("html/template internal error: template escaping out of sync")
}
if tmpl != nil && !tmpl.escaped {
@ -160,9 +180,11 @@ func (t *Template) Clone() (*Template, error) {
if src == nil || src.escaped {
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
}
x.Tree = &parse.Tree{
Name: x.Tree.Name,
Root: x.Tree.Root.CopyList(),
if x.Tree != nil {
x.Tree = &parse.Tree{
Name: x.Tree.Name,
Root: x.Tree.Root.CopyList(),
}
}
ret.set[name] = &Template{
false,
@ -274,7 +296,7 @@ func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
func parseFiles(t *Template, filenames ...string) (*Template, error) {
if len(filenames) == 0 {
// Not really a problem, but be consistent.
return nil, fmt.Errorf("template: no files named in call to ParseFiles")
return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
}
for _, filename := range filenames {
b, err := ioutil.ReadFile(filename)
@ -331,7 +353,7 @@ func parseGlob(t *Template, pattern string) (*Template, error) {
return nil, err
}
if len(filenames) == 0 {
return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
}
return parseFiles(t, filenames...)
}

View File

@ -5,7 +5,7 @@
// Package draw provides image composition functions.
//
// See "The Go image/draw package" for an introduction to this package:
// http://blog.golang.org/2011/09/go-imagedraw-package.html
// http://golang.org/doc/articles/image_draw.html
package draw
import (

View File

@ -11,7 +11,7 @@
// Consecutive groups of suffixes in sa are labeled as sorted groups or
// unsorted groups. For a given pass of the sorter, all suffixes are ordered
// up to their first h characters, and sa is h-ordered. Suffixes in their
// final positions and unambiguouly sorted in h-order are in a sorted group.
// final positions and unambiguously sorted in h-order are in a sorted group.
// Consecutive groups of suffixes with identical first h characters are an
// unsorted group. In each pass of the algorithm, unsorted groups are sorted
// according to the group number of their following suffix.
@ -78,7 +78,7 @@ func sortedByFirstByte(data []byte) []int {
for _, b := range data {
count[b]++
}
// make count[b] equal index of first occurence of b in sorted array
// make count[b] equal index of first occurrence of b in sorted array
sum := 0
for b := range count {
count[b], sum = sum, count[b]+sum

View File

@ -53,10 +53,13 @@ func ReadFile(filename string) ([]byte, error) {
defer f.Close()
// It's a good but not certain bet that FileInfo will tell us exactly how much to
// read, so let's try it but be prepared for the answer to be wrong.
fi, err := f.Stat()
var n int64
if size := fi.Size(); err == nil && size < 2e9 { // Don't preallocate a huge buffer, just in case.
n = size
if fi, err := f.Stat(); err == nil {
// Don't preallocate a huge buffer, just in case.
if size := fi.Size(); size < 1e9 {
n = size
}
}
// As initial capacity for readAll, use n + a little extra in case Size is zero,
// and to avoid another allocation after Read has filled the buffer. The readAll

View File

@ -0,0 +1,8 @@
// Copyright 2012 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 syslog provides a simple interface to the system log service.
package syslog
// BUG(brainman): This package is not implemented on Windows yet.

View File

@ -826,7 +826,7 @@ func (x nat) string(charset string) string {
// iterative approach. This threshold is represented by leafSize. Benchmarking of leafSize in the
// range 2..64 shows that values of 8 and 16 work well, with a 4x speedup at medium lengths and
// ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
// specfic hardware.
// specific hardware.
//
func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
// split larger blocks recursively

View File

@ -248,7 +248,7 @@ func Erf(x float64) float64 {
R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6)))))
S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))))
}
z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precison x
z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precision x
r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S)
if sign {
return r/x - 1
@ -321,7 +321,7 @@ func Erfc(x float64) float64 {
R = rb0 + s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*rb6)))))
S = 1 + s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))))
}
z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precison x
z := Float64frombits(Float64bits(x) & 0xffffffff00000000) // pseudo-single (20-bit) precision x
r := Exp(-z*z-0.5625) * Exp((z-x)*(z+x)+R/S)
if sign {
return 2 - r/x

View File

@ -15,7 +15,9 @@ import (
"log"
"net/http"
"os"
"os/exec"
"strconv"
"sync"
)
// hello world, the web server
@ -28,14 +30,21 @@ func HelloServer(w http.ResponseWriter, req *http.Request) {
// Simple counter server. POSTing to it will set the value.
type Counter struct {
n int
mu sync.Mutex // protects n
n int
}
// This makes Counter satisfy the expvar.Var interface, so we can export
// it directly.
func (ctr *Counter) String() string { return fmt.Sprintf("%d", ctr.n) }
func (ctr *Counter) String() string {
ctr.mu.Lock()
defer ctr.mu.Unlock()
return fmt.Sprintf("%d", ctr.n)
}
func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctr.mu.Lock()
defer ctr.mu.Unlock()
switch req.Method {
case "GET":
ctr.n++
@ -95,54 +104,36 @@ func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// exec a program, redirecting output
func DateServer(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
r, w, err := os.Pipe()
if err != nil {
fmt.Fprintf(rw, "pipe: %s\n", err)
return
}
p, err := os.StartProcess("/bin/date", []string{"date"}, &os.ProcAttr{Files: []*os.File{nil, w, w}})
defer r.Close()
w.Close()
date, err := exec.Command("/bin/date").Output()
if err != nil {
fmt.Fprintf(rw, "fork/exec: %s\n", err)
return
}
io.Copy(rw, r)
wait, err := p.Wait(0)
if err != nil {
fmt.Fprintf(rw, "wait: %s\n", err)
return
}
if !wait.Exited() || wait.ExitStatus() != 0 {
fmt.Fprintf(rw, "date: %v\n", wait)
http.Error(rw, err.Error(), 500)
return
}
rw.Write(date)
}
func Logger(w http.ResponseWriter, req *http.Request) {
log.Print(req.URL.Raw)
w.WriteHeader(404)
w.Write([]byte("oops"))
log.Print(req.URL)
http.Error(w, "oops", 404)
}
var webroot = flag.String("root", "/home/rsc", "web root directory")
var webroot = flag.String("root", os.Getenv("HOME"), "web root directory")
func main() {
flag.Parse()
// The counter is published as a variable directly.
ctr := new(Counter)
http.Handle("/counter", ctr)
expvar.Publish("counter", ctr)
http.Handle("/counter", ctr)
http.Handle("/", http.HandlerFunc(Logger))
http.Handle("/go/", http.StripPrefix("/go/", http.FileServer(http.Dir(*webroot))))
http.Handle("/flags", http.HandlerFunc(FlagServer))
http.Handle("/args", http.HandlerFunc(ArgServer))
http.Handle("/go/hello", http.HandlerFunc(HelloServer))
http.Handle("/chan", ChanCreate())
http.Handle("/date", http.HandlerFunc(DateServer))
http.HandleFunc("/flags", FlagServer)
http.HandleFunc("/args", ArgServer)
http.HandleFunc("/go/hello", HelloServer)
http.HandleFunc("/date", DateServer)
err := http.ListenAndServe(":12345", nil)
if err != nil {
log.Panicln("ListenAndServe:", err)

View File

@ -13,7 +13,7 @@ import (
)
// If the ifindex is zero, interfaceTable returns mappings of all
// network interfaces. Otheriwse it returns a mapping of a specific
// network interfaces. Otherwise it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)

View File

@ -9,7 +9,7 @@
package net
// If the ifindex is zero, interfaceTable returns mappings of all
// network interfaces. Otheriwse it returns a mapping of a specific
// network interfaces. Otherwise it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
return nil, nil

View File

@ -56,7 +56,7 @@ func getInterfaceList() ([]syscall.InterfaceInfo, error) {
}
// If the ifindex is zero, interfaceTable returns mappings of all
// network interfaces. Otheriwse it returns a mapping of a specific
// network interfaces. Otherwise it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
ai, err := getAdapterList()

View File

@ -5,7 +5,6 @@
package net
import (
"io"
"runtime"
"syscall"
"testing"
@ -67,7 +66,7 @@ func TestTCPListener(t *testing.T) {
case syscall.AF_INET6:
testIPv6UnicastSocketOptions(t, fd)
}
l1.(io.Closer).Close()
l1.Close()
}
}
@ -112,7 +111,7 @@ func TestUDPListener(t *testing.T) {
case syscall.AF_INET6:
testIPv6UnicastSocketOptions(t, fd)
}
l1.(io.Closer).Close()
l1.Close()
}
}
@ -134,7 +133,7 @@ func TestSimpleTCPListener(t *testing.T) {
checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
l2, err := Listen(tt.net, tt.laddr+":"+port)
checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
l1.(io.Closer).Close()
l1.Close()
}
}
@ -169,7 +168,7 @@ func TestSimpleUDPListener(t *testing.T) {
checkFirstListener(t, tt.net, tt.laddr+":"+port, l1)
l2, err := ListenPacket(tt.net, tt.laddr+":"+port)
checkSecondListener(t, tt.net, tt.laddr+":"+port, err, l2)
l1.(io.Closer).Close()
l1.Close()
}
}
@ -530,8 +529,9 @@ func TestProhibitionaryDialArgs(t *testing.T) {
defer l.Close()
for _, tt := range prohibitionaryDialArgTests {
_, err := Dial(tt.net, tt.addr+":"+port)
c, err := Dial(tt.net, tt.addr+":"+port)
if err == nil {
c.Close()
t.Fatalf("Dial(%q, %q) should fail", tt.net, tt.addr)
}
}

View File

@ -42,3 +42,21 @@ func NewSyscallError(syscall string, err error) error {
}
return &SyscallError{syscall, err}
}
// IsExist returns whether the error is known to report that a file or directory
// already exists. It is satisfied by ErrExist as well as some syscall errors.
func IsExist(err error) bool {
return isExist(err)
}
// IsNotExist returns whether the error is known to report that a file or directory
// does not exist. It is satisfied by ErrNotExist as well as some syscall errors.
func IsNotExist(err error) bool {
return isNotExist(err)
}
// IsPermission returns whether the error is known to report that permission is denied.
// It is satisfied by ErrPermission as well as some syscall errors.
func IsPermission(err error) bool {
return isPermission(err)
}

View File

@ -4,24 +4,21 @@
package os
// IsExist returns whether the error is known to report that a file already exists.
func IsExist(err error) bool {
func isExist(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
return contains(err.Error(), " exists")
}
// IsNotExist returns whether the error is known to report that a file does not exist.
func IsNotExist(err error) bool {
func isNotExist(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
return contains(err.Error(), "does not exist")
}
// IsPermission returns whether the error is known to report that permission is denied.
func IsPermission(err error) bool {
func isPermission(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}

View File

@ -8,27 +8,21 @@ package os
import "syscall"
// IsExist returns whether the error is known to report that a file already exists.
// It is satisfied by ErrExist as well as some syscall errors.
func IsExist(err error) bool {
func isExist(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
return err == syscall.EEXIST || err == ErrExist
}
// IsNotExist returns whether the error is known to report that a file does not exist.
// It is satisfied by ErrNotExist as well as some syscall errors.
func IsNotExist(err error) bool {
func isNotExist(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
return err == syscall.ENOENT || err == ErrNotExist
}
// IsPermission returns whether the error is known to report that permission is denied.
// It is satisfied by ErrPermission as well as some syscall errors.
func IsPermission(err error) bool {
func isPermission(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}

View File

@ -5,8 +5,10 @@
package os_test
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
)
@ -24,8 +26,56 @@ func TestErrIsExist(t *testing.T) {
t.Fatal("Open should have failed")
return
}
if !os.IsExist(err) {
t.Fatalf("os.IsExist does not work as expected for %#v", err)
if s := checkErrorPredicate("os.IsExist", os.IsExist, err); s != "" {
t.Fatal(s)
return
}
}
func testErrNotExist(name string) string {
f, err := os.Open(name)
if err == nil {
f.Close()
return "Open should have failed"
}
if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" {
return s
}
err = os.Chdir(name)
if err == nil {
return "Chdir should have failed"
}
if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err); s != "" {
return s
}
return ""
}
func TestErrIsNotExist(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "_Go_ErrIsNotExist")
if err != nil {
t.Fatalf("create ErrIsNotExist tempdir: %s", err)
return
}
defer os.RemoveAll(tmpDir)
name := filepath.Join(tmpDir, "NotExists")
if s := testErrNotExist(name); s != "" {
t.Fatal(s)
return
}
name = filepath.Join(name, "NotExists2")
if s := testErrNotExist(name); s != "" {
t.Fatal(s)
return
}
}
func checkErrorPredicate(predName string, pred func(error) bool, err error) string {
if !pred(err) {
return fmt.Sprintf("%s does not work as expected for %#v", predName, err)
}
return ""
}

View File

@ -6,30 +6,25 @@ package os
import "syscall"
// IsExist returns whether the error is known to report that a file already exists.
// It is satisfied by ErrExist as well as some syscall errors.
func IsExist(err error) bool {
func isExist(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
return err == syscall.EEXIST || err == syscall.ERROR_ALREADY_EXISTS ||
return err == syscall.ERROR_ALREADY_EXISTS ||
err == syscall.ERROR_FILE_EXISTS || err == ErrExist
}
// IsNotExist returns whether the error is known to report that a file does not exist.
// It is satisfied by ErrNotExist as well as some syscall errors.
func IsNotExist(err error) bool {
func isNotExist(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
return err == syscall.ENOENT || err == ErrNotExist
return err == syscall.ERROR_FILE_NOT_FOUND ||
err == syscall.ERROR_PATH_NOT_FOUND || err == ErrNotExist
}
// IsPermission returns whether the error is known to report that permission is denied.
// It is satisfied by ErrPermission as well as some syscall errors.
func IsPermission(err error) bool {
func isPermission(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
return err == ErrPermission
}

View File

@ -179,7 +179,21 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
// write writes len(b) bytes to the File.
// It returns the number of bytes written and an error, if any.
func (f *File) write(b []byte) (n int, err error) {
return syscall.Write(f.fd, b)
for {
m, err := syscall.Write(f.fd, b)
n += m
// If the syscall wrote some data but not all (short write)
// or it returned EINTR, then assume it stopped early for
// reasons that are uninteresting to the caller, and try again.
if 0 < m && m < len(b) || err == syscall.EINTR {
b = b[m:]
continue
}
return n, err
}
panic("not reached")
}
// pwrite writes len(b) bytes to the File starting at byte offset off.

View File

@ -1045,3 +1045,22 @@ func TestSameFile(t *testing.T) {
t.Errorf("files should be different")
}
}
func TestDevNullFile(t *testing.T) {
f, err := Open(DevNull)
if err != nil {
t.Fatalf("Open(%s): %v", DevNull, err)
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
t.Fatalf("Stat(%s): %v", DevNull, err)
}
name := filepath.Base(DevNull)
if fi.Name() != name {
t.Fatalf("wrong file name have %v want %v", fi.Name(), name)
}
if fi.Size() != 0 {
t.Fatalf("wrong file size have %d want 0", fi.Size())
}
}

View File

@ -7,6 +7,7 @@ package filepath
import (
"errors"
"os"
"runtime"
"sort"
"strings"
"unicode/utf8"
@ -37,6 +38,9 @@ var ErrBadPattern = errors.New("syntax error in pattern")
// The only possible returned error is ErrBadPattern, when pattern
// is malformed.
//
// On Windows, escaping is disabled. Instead, '\\' is treated as
// path separator.
//
func Match(pattern, name string) (matched bool, err error) {
Pattern:
for len(pattern) > 0 {
@ -95,9 +99,11 @@ Scan:
for i = 0; i < len(pattern); i++ {
switch pattern[i] {
case '\\':
// error check handled in matchChunk: bad pattern.
if i+1 < len(pattern) {
i++
if runtime.GOOS != "windows" {
// error check handled in matchChunk: bad pattern.
if i+1 < len(pattern) {
i++
}
}
case '[':
inrange = true
@ -167,10 +173,12 @@ func matchChunk(chunk, s string) (rest string, ok bool, err error) {
chunk = chunk[1:]
case '\\':
chunk = chunk[1:]
if len(chunk) == 0 {
err = ErrBadPattern
return
if runtime.GOOS != "windows" {
chunk = chunk[1:]
if len(chunk) == 0 {
err = ErrBadPattern
return
}
}
fallthrough
@ -191,7 +199,7 @@ func getEsc(chunk string) (r rune, nchunk string, err error) {
err = ErrBadPattern
return
}
if chunk[0] == '\\' {
if chunk[0] == '\\' && runtime.GOOS != "windows" {
chunk = chunk[1:]
if len(chunk) == 0 {
err = ErrBadPattern

View File

@ -7,6 +7,7 @@ package filepath_test
import (
. "path/filepath"
"runtime"
"strings"
"testing"
)
@ -76,21 +77,26 @@ func errp(e error) string {
}
func TestMatch(t *testing.T) {
if runtime.GOOS == "windows" {
// XXX: Don't pass for windows.
return
}
for _, tt := range matchTests {
ok, err := Match(tt.pattern, tt.s)
pattern := tt.pattern
s := tt.s
if runtime.GOOS == "windows" {
if strings.Index(pattern, "\\") >= 0 {
// no escape allowed on windows.
continue
}
pattern = Clean(pattern)
s = Clean(s)
}
ok, err := Match(pattern, s)
if ok != tt.match || err != tt.err {
t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", tt.pattern, tt.s, ok, errp(err), tt.match, errp(tt.err))
t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err))
}
}
}
// contains returns true if vector contains the string s.
func contains(vector []string, s string) bool {
s = ToSlash(s)
for _, elem := range vector {
if elem == s {
return true
@ -110,18 +116,20 @@ var globTests = []struct {
}
func TestGlob(t *testing.T) {
if runtime.GOOS == "windows" {
// XXX: Don't pass for windows.
return
}
for _, tt := range globTests {
matches, err := Glob(tt.pattern)
pattern := tt.pattern
result := tt.result
if runtime.GOOS == "windows" {
pattern = Clean(pattern)
result = Clean(result)
}
matches, err := Glob(pattern)
if err != nil {
t.Errorf("Glob error for %q: %s", tt.pattern, err)
t.Errorf("Glob error for %q: %s", pattern, err)
continue
}
if !contains(matches, tt.result) {
t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result)
if !contains(matches, result) {
t.Errorf("Glob(%#q) = %#v want %v", pattern, matches, result)
}
}
for _, pattern := range []string{"no_match", "../*/no_match"} {

View File

@ -66,9 +66,10 @@ type Type interface {
// It returns an empty string for unnamed types.
Name() string
// PkgPath returns the type's package path.
// The package path is a full package import path like "encoding/base64".
// PkgPath returns an empty string for unnamed or predeclared types.
// PkgPath returns a named type's package path, that is, the import path
// that uniquely identifies the package, such as "encoding/base64".
// If the type was predeclared (string, error) or unnamed (*T, struct{}, []int),
// the package path will be the empty string.
PkgPath() string
// Size returns the number of bytes needed to store
@ -351,11 +352,18 @@ type structType struct {
// Method represents a single method.
type Method struct {
PkgPath string // empty for uppercase Name
// Name is the method name.
// PkgPath is the package path that qualifies a lower case (unexported)
// method name. It is empty for upper case (exported) method names.
// The combination of PkgPath and Name uniquely identifies a method
// in a method set.
// See http://golang.org/ref/spec#Uniqueness_of_identifiers
Name string
Type Type
Func Value
Index int
PkgPath string
Type Type // method type
Func Value // func with receiver as first argument
Index int // index for Type.Method
}
// High bit says whether type has
@ -695,14 +703,20 @@ func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
return
}
// A StructField describes a single field in a struct.
type StructField struct {
PkgPath string // empty for uppercase Name
Name string
Type Type
Tag StructTag
Offset uintptr
Index []int
Anonymous bool
// Name is the field name.
// PkgPath is the package path that qualifies a lower case (unexported)
// field name. It is empty for upper case (exported) field names.
// See http://golang.org/ref/spec#Uniqueness_of_identifiers
Name string
PkgPath string
Type Type // field type
Tag StructTag // field tag string
Offset uintptr // offset within struct, in bytes
Index []int // index sequence for Type.FieldByIndex
Anonymous bool // is an anonymous field
}
// A StructTag is the tag string in a struct field.

View File

@ -1624,6 +1624,15 @@ func MakeSlice(typ Type, len, cap int) Value {
if typ.Kind() != Slice {
panic("reflect.MakeSlice of non-slice type")
}
if len < 0 {
panic("reflect.MakeSlice: negative len")
}
if cap < 0 {
panic("reflect.MakeSlice: negative cap")
}
if len > cap {
panic("reflect.MakeSlice: len > cap")
}
// Declare slice so that gc can see the base pointer in it.
var x []byte

View File

@ -183,17 +183,21 @@ func quickSort(data Interface, a, b, maxDepth int) {
}
}
// Sort sorts data.
// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
// data.Less and data.Swap. The sort is not guaranteed to be stable.
func Sort(data Interface) {
// Switch to heapsort if depth of 2*ceil(lg(n)) is reached.
// Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached.
n := data.Len()
maxDepth := 0
for 1<<uint(maxDepth) < n {
for i := n; i > 0; i >>= 1 {
maxDepth++
}
maxDepth *= 2
quickSort(data, 0, n, maxDepth)
}
// IsSorted reports whether data is sorted.
func IsSorted(data Interface) bool {
n := data.Len()
for i := n - 1; i > 0; i-- {

View File

@ -369,6 +369,7 @@ func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args
// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
value := s.varValue(v.Ident[0])
if len(v.Ident) == 1 {
s.notAFunction(args, final)
return value
}
return s.evalFieldChain(dot, value, v.Ident[1:], args, final)

View File

@ -466,6 +466,10 @@ var execTests = []execTest{
{"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true},
{"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true},
{"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true},
// Legal parse but illegal execution: non-function should have no arguments.
{"bug7a", "{{3 2}}", "", tVal, false},
{"bug7b", "{{$x := 1}}{{$x 2}}", "", tVal, false},
{"bug7c", "{{$x := 1}}{{3 | $x}}", "", tVal, false},
}
func zeroArgs() string {

View File

@ -93,7 +93,7 @@ var multiExecTests = []execTest{
{"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
{"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
{"variable declared by template", `{{template "nested" $x=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
{"variable declared by template", `{{template "nested" $x:=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
// User-defined function: test argument evaluator.
{"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},

View File

@ -347,6 +347,9 @@ Loop:
default:
l.backup()
word := l.input[l.start:l.pos]
if !l.atTerminator() {
return l.errorf("unexpected character %+U", r)
}
switch {
case key[word] > itemKeyword:
l.emit(key[word])
@ -365,6 +368,28 @@ Loop:
return lexInsideAction
}
// atTerminator reports whether the input is at valid termination character to
// appear after an identifier. Mostly to catch cases like "$x+2" not being
// acceptable without a space, in case we decide one day to implement
// arithmetic.
func (l *lexer) atTerminator() bool {
r := l.peek()
if isSpace(r) {
return true
}
switch r {
case eof, ',', '|', ':':
return true
}
// Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
// succeed but should fail) but only in extremely rare cases caused by willfully
// bad choice of delimiter.
if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r {
return true
}
return false
}
// lexChar scans a character constant. The initial quote is already
// scanned. Syntax checking is done by the parse.
func lexChar(l *lexer) stateFn {

View File

@ -326,7 +326,7 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
for {
if v := t.peek(); v.typ == itemVariable {
t.next()
if next := t.peek(); next.typ == itemColonEquals || next.typ == itemChar {
if next := t.peek(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
t.next()
variable := newVariable(v.val)
if len(variable.Ident) != 1 {

View File

@ -201,6 +201,10 @@ var parseTests = []parseTest{
`{{range .X | .M}}"true"{{else}}"false"{{end}}`},
{"range []int", "{{range .SI}}{{.}}{{end}}", noError,
`{{range .SI}}{{.}}{{end}}`},
{"range 1 var", "{{range $x := .SI}}{{.}}{{end}}", noError,
`{{range $x := .SI}}{{.}}{{end}}`},
{"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
`{{range $x, $y := .SI}}{{.}}{{end}}`},
{"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError,
`{{range .SI 1 -3.2i true false 'a'}}{{end}}`},
{"template", "{{template `x`}}", noError,
@ -226,6 +230,17 @@ var parseTests = []parseTest{
{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
// Equals (and other chars) do not assignments make (yet).
{"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
{"bug0b", "{{$x = 1}}{{$x}}", hasError, ""},
{"bug0c", "{{$x ! 2}}{{$x}}", hasError, ""},
{"bug0d", "{{$x % 3}}{{$x}}", hasError, ""},
// Check the parse fails for := rather than comma.
{"bug0e", "{{range $x := $y := 3}}{{end}}", hasError, ""},
// Another bug: variable read must ignore following punctuation.
{"bug1a", "{{$x:=.}}{{$x!2}}", hasError, ""}, // ! is just illegal here.
{"bug1b", "{{$x:=.}}{{$x+2}}", hasError, ""}, // $x+2 should not parse as ($x) (+2).
{"bug1c", "{{$x:=.}}{{$x +2}}", noError, "{{$x := .}}{{$x +2}}"}, // It's OK with a space.
}
var builtins = map[string]interface{}{

View File

@ -163,7 +163,7 @@ done
done
done
runtime="chan.c cpuprof.c goc2c.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c proc.c runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
runtime="chan.c cpuprof.c lock_futex.c lock_sema.c mcache.c mcentral.c mfinal.c mfixalloc.c mgc0.c mheap.c msize.c proc.c runtime.c runtime.h signal_unix.c malloc.h malloc.goc mprof.goc runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
for f in $runtime; do
merge_c $f $f
done

View File

@ -966,6 +966,11 @@ runtime_mstart(void* mp)
}
#endif
// Install signal handlers; after minit so that minit can
// prepare the thread to be able to handle the signals.
if(m == &runtime_m0)
runtime_initsig();
schedule(nil);
return nil;
}

View File

@ -74,7 +74,7 @@ void
runtime_panicstring(const char *s)
{
Eface err;
if(runtime_m()->gcing) {
runtime_printf("panic: %s\n", s);
runtime_throw("panic during gc");
@ -101,7 +101,7 @@ runtime_goargs(void)
{
String *s;
int32 i;
// for windows implementation see "os" package
if(Windows)
return;
@ -119,7 +119,7 @@ runtime_goenvs_unix(void)
{
String *s;
int32 i, n;
for(n=0; argv[argc+1+n] != 0; n++)
;
@ -195,8 +195,6 @@ void
runtime_check(void)
{
__go_register_gc_roots(&runtime_roots);
runtime_initsig ();
}
int64