Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
08a680a8
Commit
08a680a8
authored
Jun 25, 2012
by
Ian Lance Taylor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
libgo: Update to Go 1.0.2 release.
From-SVN: r188943
parent
72de8622
Hide whitespace changes
Inline
Side-by-side
Showing
59 changed files
with
1088 additions
and
169 deletions
+1088
-169
libgo/MERGE
+1
-1
libgo/go/compress/flate/deflate.go
+20
-0
libgo/go/compress/flate/deflate_test.go
+44
-0
libgo/go/crypto/aes/const.go
+2
-2
libgo/go/crypto/ecdsa/ecdsa.go
+4
-2
libgo/go/crypto/rsa/pkcs1v15.go
+1
-0
libgo/go/crypto/tls/handshake_messages.go
+2
-2
libgo/go/crypto/x509/x509.go
+2
-2
libgo/go/debug/gosym/pclntab_test.go
+16
-2
libgo/go/encoding/base64/base64.go
+1
-1
libgo/go/encoding/base64/base64_test.go
+49
-0
libgo/go/encoding/gob/doc.go
+1
-1
libgo/go/encoding/json/decode.go
+12
-2
libgo/go/encoding/json/decode_test.go
+65
-0
libgo/go/encoding/json/encode.go
+3
-1
libgo/go/flag/flag.go
+3
-2
libgo/go/fmt/doc.go
+1
-1
libgo/go/go/ast/ast.go
+8
-6
libgo/go/go/ast/ast_test.go
+50
-0
libgo/go/go/build/build.go
+2
-2
libgo/go/go/parser/parser.go
+24
-18
libgo/go/go/parser/parser_test.go
+190
-5
libgo/go/go/printer/nodes.go
+12
-3
libgo/go/log/log.go
+1
-1
libgo/go/math/big/nat.go
+5
-5
libgo/go/math/big/nat_test.go
+18
-0
libgo/go/mime/multipart/multipart.go
+79
-36
libgo/go/mime/multipart/multipart_test.go
+213
-32
libgo/go/net/file.go
+2
-2
libgo/go/net/http/client.go
+5
-0
libgo/go/net/http/client_test.go
+25
-0
libgo/go/net/http/proxy_test.go
+30
-0
libgo/go/net/http/response.go
+6
-3
libgo/go/net/http/response_test.go
+15
-0
libgo/go/net/http/server.go
+1
-1
libgo/go/net/http/transfer.go
+4
-2
libgo/go/net/http/transport.go
+5
-1
libgo/go/net/mail/message.go
+6
-5
libgo/go/net/mail/message_test.go
+5
-0
libgo/go/net/url/url.go
+3
-2
libgo/go/net/url/url_test.go
+31
-0
libgo/go/os/exec/exec.go
+12
-6
libgo/go/path/filepath/path.go
+5
-2
libgo/go/path/filepath/path_plan9.go
+1
-1
libgo/go/path/filepath/path_test.go
+31
-0
libgo/go/regexp/regexp.go
+2
-2
libgo/go/regexp/syntax/parse.go
+5
-2
libgo/go/regexp/syntax/parse_test.go
+8
-0
libgo/go/runtime/extern.go
+3
-2
libgo/go/strconv/itoa.go
+6
-2
libgo/go/strings/example_test.go
+0
-1
libgo/go/text/template/exec.go
+7
-0
libgo/go/text/template/exec_test.go
+6
-0
libgo/go/time/sleep_test.go
+22
-0
libgo/go/unicode/tables.go
+3
-3
libgo/runtime/malloc.goc
+1
-0
libgo/runtime/mfinal.c
+1
-2
libgo/runtime/mgc0.c
+0
-1
libgo/runtime/time.goc
+8
-2
No files found.
libgo/MERGE
View file @
08a680a8
2ccfd4b451d3
5e806355a9e1
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.
libgo/go/compress/flate/deflate.go
View file @
08a680a8
...
@@ -32,6 +32,7 @@ const (
...
@@ -32,6 +32,7 @@ const (
hashSize
=
1
<<
hashBits
hashSize
=
1
<<
hashBits
hashMask
=
(
1
<<
hashBits
)
-
1
hashMask
=
(
1
<<
hashBits
)
-
1
hashShift
=
(
hashBits
+
minMatchLength
-
1
)
/
minMatchLength
hashShift
=
(
hashBits
+
minMatchLength
-
1
)
/
minMatchLength
maxHashOffset
=
1
<<
24
skipNever
=
math
.
MaxInt32
skipNever
=
math
.
MaxInt32
)
)
...
@@ -106,6 +107,25 @@ func (d *compressor) fillDeflate(b []byte) int {
...
@@ -106,6 +107,25 @@ func (d *compressor) fillDeflate(b []byte) int {
d
.
blockStart
=
math
.
MaxInt32
d
.
blockStart
=
math
.
MaxInt32
}
}
d
.
hashOffset
+=
windowSize
d
.
hashOffset
+=
windowSize
if
d
.
hashOffset
>
maxHashOffset
{
delta
:=
d
.
hashOffset
-
1
d
.
hashOffset
-=
delta
d
.
chainHead
-=
delta
for
i
,
v
:=
range
d
.
hashPrev
{
if
v
>
delta
{
d
.
hashPrev
[
i
]
-=
delta
}
else
{
d
.
hashPrev
[
i
]
=
0
}
}
for
i
,
v
:=
range
d
.
hashHead
{
if
v
>
delta
{
d
.
hashHead
[
i
]
-=
delta
}
else
{
d
.
hashHead
[
i
]
=
0
}
}
}
}
}
n
:=
copy
(
d
.
window
[
d
.
windowEnd
:
],
b
)
n
:=
copy
(
d
.
window
[
d
.
windowEnd
:
],
b
)
d
.
windowEnd
+=
n
d
.
windowEnd
+=
n
...
...
libgo/go/compress/flate/deflate_test.go
View file @
08a680a8
...
@@ -94,6 +94,50 @@ func TestDeflate(t *testing.T) {
...
@@ -94,6 +94,50 @@ func TestDeflate(t *testing.T) {
}
}
}
}
// A sparseReader returns a stream consisting of 0s followed by 1<<16 1s.
// This tests missing hash references in a very large input.
type
sparseReader
struct
{
l
int64
cur
int64
}
func
(
r
*
sparseReader
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
if
r
.
cur
>=
r
.
l
{
return
0
,
io
.
EOF
}
n
=
len
(
b
)
cur
:=
r
.
cur
+
int64
(
n
)
if
cur
>
r
.
l
{
n
-=
int
(
cur
-
r
.
l
)
cur
=
r
.
l
}
for
i
:=
range
b
[
0
:
n
]
{
if
r
.
cur
+
int64
(
i
)
>=
r
.
l
-
1
<<
16
{
b
[
i
]
=
1
}
else
{
b
[
i
]
=
0
}
}
r
.
cur
=
cur
return
}
func
TestVeryLongSparseChunk
(
t
*
testing
.
T
)
{
if
testing
.
Short
()
{
t
.
Logf
(
"skipping sparse chunk during short test"
)
return
}
w
,
err
:=
NewWriter
(
ioutil
.
Discard
,
1
)
if
err
!=
nil
{
t
.
Errorf
(
"NewWriter: %v"
,
err
)
return
}
if
_
,
err
=
io
.
Copy
(
w
,
&
sparseReader
{
l
:
23E8
});
err
!=
nil
{
t
.
Errorf
(
"Compress failed: %v"
,
err
)
return
}
}
type
syncBuffer
struct
{
type
syncBuffer
struct
{
buf
bytes
.
Buffer
buf
bytes
.
Buffer
mu
sync
.
RWMutex
mu
sync
.
RWMutex
...
...
libgo/go/crypto/aes/const.go
View file @
08a680a8
...
@@ -11,11 +11,11 @@ package aes
...
@@ -11,11 +11,11 @@ package aes
// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
// AES is based on the mathematical behavior of binary polynomials
// AES is based on the mathematical behavior of binary polynomials
// (polynomials over GF(2)) modulo the irreducible polynomial x⁸ + x⁴ + x
²
+ x + 1.
// (polynomials over GF(2)) modulo the irreducible polynomial x⁸ + x⁴ + x
³
+ x + 1.
// Addition of these binary polynomials corresponds to binary xor.
// Addition of these binary polynomials corresponds to binary xor.
// Reducing mod poly corresponds to binary xor with poly every
// Reducing mod poly corresponds to binary xor with poly every
// time a 0x100 bit appears.
// time a 0x100 bit appears.
const
poly
=
1
<<
8
|
1
<<
4
|
1
<<
3
|
1
<<
1
|
1
<<
0
// x⁸ + x⁴ + x
²
+ x + 1
const
poly
=
1
<<
8
|
1
<<
4
|
1
<<
3
|
1
<<
1
|
1
<<
0
// x⁸ + x⁴ + x
³
+ x + 1
// Powers of x mod poly in GF(2).
// Powers of x mod poly in GF(2).
var
powx
=
[
16
]
byte
{
var
powx
=
[
16
]
byte
{
...
...
libgo/go/crypto/ecdsa/ecdsa.go
View file @
08a680a8
...
@@ -66,7 +66,9 @@ func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error)
...
@@ -66,7 +66,9 @@ func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error)
// hashToInt converts a hash value to an integer. There is some disagreement
// hashToInt converts a hash value to an integer. There is some disagreement
// about how this is done. [NSA] suggests that this is done in the obvious
// about how this is done. [NSA] suggests that this is done in the obvious
// manner, but [SECG] truncates the hash to the bit-length of the curve order
// manner, but [SECG] truncates the hash to the bit-length of the curve order
// first. We follow [SECG] because that's what OpenSSL does.
// first. We follow [SECG] because that's what OpenSSL does. Additionally,
// OpenSSL right shifts excess bits from the number if the hash is too large
// and we mirror that too.
func
hashToInt
(
hash
[]
byte
,
c
elliptic
.
Curve
)
*
big
.
Int
{
func
hashToInt
(
hash
[]
byte
,
c
elliptic
.
Curve
)
*
big
.
Int
{
orderBits
:=
c
.
Params
()
.
N
.
BitLen
()
orderBits
:=
c
.
Params
()
.
N
.
BitLen
()
orderBytes
:=
(
orderBits
+
7
)
/
8
orderBytes
:=
(
orderBits
+
7
)
/
8
...
@@ -75,7 +77,7 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
...
@@ -75,7 +77,7 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
}
}
ret
:=
new
(
big
.
Int
)
.
SetBytes
(
hash
)
ret
:=
new
(
big
.
Int
)
.
SetBytes
(
hash
)
excess
:=
orderBytes
*
8
-
orderBits
excess
:=
len
(
hash
)
*
8
-
orderBits
if
excess
>
0
{
if
excess
>
0
{
ret
.
Rsh
(
ret
,
uint
(
excess
))
ret
.
Rsh
(
ret
,
uint
(
excess
))
}
}
...
...
libgo/go/crypto/rsa/pkcs1v15.go
View file @
08a680a8
...
@@ -151,6 +151,7 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
...
@@ -151,6 +151,7 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
var
hashPrefixes
=
map
[
crypto
.
Hash
][]
byte
{
var
hashPrefixes
=
map
[
crypto
.
Hash
][]
byte
{
crypto
.
MD5
:
{
0x30
,
0x20
,
0x30
,
0x0c
,
0x06
,
0x08
,
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x02
,
0x05
,
0x05
,
0x00
,
0x04
,
0x10
},
crypto
.
MD5
:
{
0x30
,
0x20
,
0x30
,
0x0c
,
0x06
,
0x08
,
0x2a
,
0x86
,
0x48
,
0x86
,
0xf7
,
0x0d
,
0x02
,
0x05
,
0x05
,
0x00
,
0x04
,
0x10
},
crypto
.
SHA1
:
{
0x30
,
0x21
,
0x30
,
0x09
,
0x06
,
0x05
,
0x2b
,
0x0e
,
0x03
,
0x02
,
0x1a
,
0x05
,
0x00
,
0x04
,
0x14
},
crypto
.
SHA1
:
{
0x30
,
0x21
,
0x30
,
0x09
,
0x06
,
0x05
,
0x2b
,
0x0e
,
0x03
,
0x02
,
0x1a
,
0x05
,
0x00
,
0x04
,
0x14
},
crypto
.
SHA224
:
{
0x30
,
0x2d
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x04
,
0x05
,
0x00
,
0x04
,
0x1c
},
crypto
.
SHA256
:
{
0x30
,
0x31
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x01
,
0x05
,
0x00
,
0x04
,
0x20
},
crypto
.
SHA256
:
{
0x30
,
0x31
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x01
,
0x05
,
0x00
,
0x04
,
0x20
},
crypto
.
SHA384
:
{
0x30
,
0x41
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x02
,
0x05
,
0x00
,
0x04
,
0x30
},
crypto
.
SHA384
:
{
0x30
,
0x41
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x02
,
0x05
,
0x00
,
0x04
,
0x30
},
crypto
.
SHA512
:
{
0x30
,
0x51
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x03
,
0x05
,
0x00
,
0x04
,
0x40
},
crypto
.
SHA512
:
{
0x30
,
0x51
,
0x30
,
0x0d
,
0x06
,
0x09
,
0x60
,
0x86
,
0x48
,
0x01
,
0x65
,
0x03
,
0x04
,
0x02
,
0x03
,
0x05
,
0x00
,
0x04
,
0x40
},
...
...
libgo/go/crypto/tls/handshake_messages.go
View file @
08a680a8
...
@@ -563,7 +563,7 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
...
@@ -563,7 +563,7 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
if
len
(
d
)
<
4
{
if
len
(
d
)
<
4
{
return
false
return
false
}
}
certLen
:=
uint32
(
d
[
0
])
<<
24
|
uint32
(
d
[
1
])
<<
8
|
uint32
(
d
[
2
])
certLen
:=
uint32
(
d
[
0
])
<<
16
|
uint32
(
d
[
1
])
<<
8
|
uint32
(
d
[
2
])
if
uint32
(
len
(
d
))
<
3
+
certLen
{
if
uint32
(
len
(
d
))
<
3
+
certLen
{
return
false
return
false
}
}
...
@@ -575,7 +575,7 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
...
@@ -575,7 +575,7 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
m
.
certificates
=
make
([][]
byte
,
numCerts
)
m
.
certificates
=
make
([][]
byte
,
numCerts
)
d
=
data
[
7
:
]
d
=
data
[
7
:
]
for
i
:=
0
;
i
<
numCerts
;
i
++
{
for
i
:=
0
;
i
<
numCerts
;
i
++
{
certLen
:=
uint32
(
d
[
0
])
<<
24
|
uint32
(
d
[
1
])
<<
8
|
uint32
(
d
[
2
])
certLen
:=
uint32
(
d
[
0
])
<<
16
|
uint32
(
d
[
1
])
<<
8
|
uint32
(
d
[
2
])
m
.
certificates
[
i
]
=
d
[
3
:
3
+
certLen
]
m
.
certificates
[
i
]
=
d
[
3
:
3
+
certLen
]
d
=
d
[
3
+
certLen
:
]
d
=
d
[
3
+
certLen
:
]
}
}
...
...
libgo/go/crypto/x509/x509.go
View file @
08a680a8
...
@@ -388,10 +388,10 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
...
@@ -388,10 +388,10 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
return
ErrUnsupportedAlgorithm
return
ErrUnsupportedAlgorithm
}
}
h
:=
hashType
.
New
()
if
!
hashType
.
Available
()
{
if
h
==
nil
{
return
ErrUnsupportedAlgorithm
return
ErrUnsupportedAlgorithm
}
}
h
:=
hashType
.
New
()
h
.
Write
(
signed
)
h
.
Write
(
signed
)
digest
:=
h
.
Sum
(
nil
)
digest
:=
h
.
Sum
(
nil
)
...
...
libgo/go/debug/gosym/pclntab_test.go
View file @
08a680a8
...
@@ -7,14 +7,19 @@ package gosym
...
@@ -7,14 +7,19 @@ package gosym
import
(
import
(
"debug/elf"
"debug/elf"
"fmt"
"fmt"
"io/ioutil"
"os"
"os"
"os/exec"
"os/exec"
"path/filepath"
"runtime"
"runtime"
"strings"
"strings"
"testing"
"testing"
)
)
var
pclinetestBinary
string
var
(
pclineTempDir
string
pclinetestBinary
string
)
func
dotest
()
bool
{
func
dotest
()
bool
{
// For now, only works on ELF platforms.
// For now, only works on ELF platforms.
...
@@ -24,10 +29,18 @@ func dotest() bool {
...
@@ -24,10 +29,18 @@ func dotest() bool {
if
pclinetestBinary
!=
""
{
if
pclinetestBinary
!=
""
{
return
true
return
true
}
}
var
err
error
pclineTempDir
,
err
=
ioutil
.
TempDir
(
""
,
"pclinetest"
)
if
err
!=
nil
{
panic
(
err
)
}
if
strings
.
Contains
(
pclineTempDir
,
" "
)
{
panic
(
"unexpected space in tempdir"
)
}
// This command builds pclinetest from pclinetest.asm;
// This command builds pclinetest from pclinetest.asm;
// the resulting binary looks like it was built from pclinetest.s,
// the resulting binary looks like it was built from pclinetest.s,
// but we have renamed it to keep it away from the go tool.
// but we have renamed it to keep it away from the go tool.
pclinetestBinary
=
os
.
TempDir
()
+
"/pclinetest"
pclinetestBinary
=
filepath
.
Join
(
pclineTempDir
,
"pclinetest"
)
command
:=
fmt
.
Sprintf
(
"go tool 6a -o %s.6 pclinetest.asm && go tool 6l -E main -o %s %s.6"
,
command
:=
fmt
.
Sprintf
(
"go tool 6a -o %s.6 pclinetest.asm && go tool 6l -E main -o %s %s.6"
,
pclinetestBinary
,
pclinetestBinary
,
pclinetestBinary
)
pclinetestBinary
,
pclinetestBinary
,
pclinetestBinary
)
cmd
:=
exec
.
Command
(
"sh"
,
"-c"
,
command
)
cmd
:=
exec
.
Command
(
"sh"
,
"-c"
,
command
)
...
@@ -170,6 +183,7 @@ func TestPCLine(t *testing.T) {
...
@@ -170,6 +183,7 @@ func TestPCLine(t *testing.T) {
if
!
dotest
()
{
if
!
dotest
()
{
return
return
}
}
defer
os
.
RemoveAll
(
pclineTempDir
)
f
,
tab
:=
crack
(
pclinetestBinary
,
t
)
f
,
tab
:=
crack
(
pclinetestBinary
,
t
)
text
:=
f
.
Section
(
".text"
)
text
:=
f
.
Section
(
".text"
)
...
...
libgo/go/encoding/base64/base64.go
View file @
08a680a8
...
@@ -318,7 +318,7 @@ func (d *decoder) Read(p []byte) (n int, err error) {
...
@@ -318,7 +318,7 @@ func (d *decoder) Read(p []byte) (n int, err error) {
}
}
nn
,
d
.
err
=
io
.
ReadAtLeast
(
d
.
r
,
d
.
buf
[
d
.
nbuf
:
nn
],
4
-
d
.
nbuf
)
nn
,
d
.
err
=
io
.
ReadAtLeast
(
d
.
r
,
d
.
buf
[
d
.
nbuf
:
nn
],
4
-
d
.
nbuf
)
d
.
nbuf
+=
nn
d
.
nbuf
+=
nn
if
d
.
nbuf
<
4
{
if
d
.
err
!=
nil
||
d
.
nbuf
<
4
{
return
0
,
d
.
err
return
0
,
d
.
err
}
}
...
...
libgo/go/encoding/base64/base64_test.go
View file @
08a680a8
...
@@ -6,9 +6,11 @@ package base64
...
@@ -6,9 +6,11 @@ package base64
import
(
import
(
"bytes"
"bytes"
"errors"
"io"
"io"
"io/ioutil"
"io/ioutil"
"testing"
"testing"
"time"
)
)
type
testpair
struct
{
type
testpair
struct
{
...
@@ -226,3 +228,50 @@ func TestNewLineCharacters(t *testing.T) {
...
@@ -226,3 +228,50 @@ func TestNewLineCharacters(t *testing.T) {
}
}
}
}
}
}
type
nextRead
struct
{
n
int
// bytes to return
err
error
// error to return
}
// faultInjectReader returns data from source, rate-limited
// and with the errors as written to nextc.
type
faultInjectReader
struct
{
source
string
nextc
<-
chan
nextRead
}
func
(
r
*
faultInjectReader
)
Read
(
p
[]
byte
)
(
int
,
error
)
{
nr
:=
<-
r
.
nextc
if
len
(
p
)
>
nr
.
n
{
p
=
p
[
:
nr
.
n
]
}
n
:=
copy
(
p
,
r
.
source
)
r
.
source
=
r
.
source
[
n
:
]
return
n
,
nr
.
err
}
// tests that we don't ignore errors from our underlying reader
func
TestDecoderIssue3577
(
t
*
testing
.
T
)
{
next
:=
make
(
chan
nextRead
,
10
)
wantErr
:=
errors
.
New
(
"my error"
)
next
<-
nextRead
{
5
,
nil
}
next
<-
nextRead
{
10
,
wantErr
}
d
:=
NewDecoder
(
StdEncoding
,
&
faultInjectReader
{
source
:
"VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw=="
,
// twas brillig...
nextc
:
next
,
})
errc
:=
make
(
chan
error
)
go
func
()
{
_
,
err
:=
ioutil
.
ReadAll
(
d
)
errc
<-
err
}()
select
{
case
err
:=
<-
errc
:
if
err
!=
wantErr
{
t
.
Errorf
(
"got error %v; want %v"
,
err
,
wantErr
)
}
case
<-
time
.
After
(
5
*
time
.
Second
)
:
t
.
Errorf
(
"timeout; Decoder blocked without returning an error"
)
}
}
libgo/go/encoding/gob/doc.go
View file @
08a680a8
...
@@ -116,7 +116,7 @@ uninterpreted bytes of the value.
...
@@ -116,7 +116,7 @@ uninterpreted bytes of the value.
All other slices and arrays are sent as an unsigned count followed by that many
All other slices and arrays are sent as an unsigned count followed by that many
elements using the standard gob encoding for their type, recursively.
elements using the standard gob encoding for their type, recursively.
Maps are sent as an unsigned count followed by that man key, element
Maps are sent as an unsigned count followed by that man
y
key, element
pairs. Empty but non-nil maps are sent, so if the sender has allocated
pairs. Empty but non-nil maps are sent, so if the sender has allocated
a map, the receiver will allocate a map even no elements are
a map, the receiver will allocate a map even no elements are
transmitted.
transmitted.
...
...
libgo/go/encoding/json/decode.go
View file @
08a680a8
...
@@ -273,9 +273,14 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
...
@@ -273,9 +273,14 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
_
,
isUnmarshaler
=
v
.
Interface
()
.
(
Unmarshaler
)
_
,
isUnmarshaler
=
v
.
Interface
()
.
(
Unmarshaler
)
}
}
// Load value from interface, but only if the result will be
// usefully addressable.
if
iv
:=
v
;
iv
.
Kind
()
==
reflect
.
Interface
&&
!
iv
.
IsNil
()
{
if
iv
:=
v
;
iv
.
Kind
()
==
reflect
.
Interface
&&
!
iv
.
IsNil
()
{
v
=
iv
.
Elem
()
e
:=
iv
.
Elem
()
continue
if
e
.
Kind
()
==
reflect
.
Ptr
&&
!
e
.
IsNil
()
&&
(
!
decodingNull
||
e
.
Elem
()
.
Kind
()
==
reflect
.
Ptr
)
{
v
=
e
continue
}
}
}
pv
:=
v
pv
:=
v
...
@@ -588,6 +593,11 @@ func (d *decodeState) literal(v reflect.Value) {
...
@@ -588,6 +593,11 @@ func (d *decodeState) literal(v reflect.Value) {
// produce more helpful error messages.
// produce more helpful error messages.
func
(
d
*
decodeState
)
literalStore
(
item
[]
byte
,
v
reflect
.
Value
,
fromQuoted
bool
)
{
func
(
d
*
decodeState
)
literalStore
(
item
[]
byte
,
v
reflect
.
Value
,
fromQuoted
bool
)
{
// Check for unmarshaler.
// Check for unmarshaler.
if
len
(
item
)
==
0
{
//Empty string given
d
.
saveError
(
fmt
.
Errorf
(
"json: invalid use of ,string struct tag, trying to unmarshal %q into %v"
,
item
,
v
.
Type
()))
return
}
wantptr
:=
item
[
0
]
==
'n'
// null
wantptr
:=
item
[
0
]
==
'n'
// null
unmarshaler
,
pv
:=
d
.
indirect
(
v
,
wantptr
)
unmarshaler
,
pv
:=
d
.
indirect
(
v
,
wantptr
)
if
unmarshaler
!=
nil
{
if
unmarshaler
!=
nil
{
...
...
libgo/go/encoding/json/decode_test.go
View file @
08a680a8
...
@@ -638,3 +638,68 @@ func TestAnonymous(t *testing.T) {
...
@@ -638,3 +638,68 @@ func TestAnonymous(t *testing.T) {
t
.
Fatal
(
"Unmarshal: did set T.Y"
)
t
.
Fatal
(
"Unmarshal: did set T.Y"
)
}
}
}
}
// Test that the empty string doesn't panic decoding when ,string is specified
// Issue 3450
func
TestEmptyString
(
t
*
testing
.
T
)
{
type
T2
struct
{
Number1
int
`json:",string"`
Number2
int
`json:",string"`
}
data
:=
`{"Number1":"1", "Number2":""}`
dec
:=
NewDecoder
(
strings
.
NewReader
(
data
))
var
t2
T2
err
:=
dec
.
Decode
(
&
t2
)
if
err
==
nil
{
t
.
Fatal
(
"Decode: did not return error"
)
}
if
t2
.
Number1
!=
1
{
t
.
Fatal
(
"Decode: did not set Number1"
)
}
}
func
intp
(
x
int
)
*
int
{
p
:=
new
(
int
)
*
p
=
x
return
p
}
func
intpp
(
x
*
int
)
**
int
{
pp
:=
new
(
*
int
)
*
pp
=
x
return
pp
}
var
interfaceSetTests
=
[]
struct
{
pre
interface
{}
json
string
post
interface
{}
}{
{
"foo"
,
`"bar"`
,
"bar"
},
{
"foo"
,
`2`
,
2.0
},
{
"foo"
,
`true`
,
true
},
{
"foo"
,
`null`
,
nil
},
{
nil
,
`null`
,
nil
},
{
new
(
int
),
`null`
,
nil
},
{(
*
int
)(
nil
),
`null`
,
nil
},
{
new
(
*
int
),
`null`
,
new
(
*
int
)},
{(
**
int
)(
nil
),
`null`
,
nil
},
{
intp
(
1
),
`null`
,
nil
},
{
intpp
(
nil
),
`null`
,
intpp
(
nil
)},
{
intpp
(
intp
(
1
)),
`null`
,
intpp
(
nil
)},
}
func
TestInterfaceSet
(
t
*
testing
.
T
)
{
for
_
,
tt
:=
range
interfaceSetTests
{
b
:=
struct
{
X
interface
{}
}{
tt
.
pre
}
blob
:=
`{"X":`
+
tt
.
json
+
`}`
if
err
:=
Unmarshal
([]
byte
(
blob
),
&
b
);
err
!=
nil
{
t
.
Errorf
(
"Unmarshal %#q: %v"
,
blob
,
err
)
continue
}
if
!
reflect
.
DeepEqual
(
b
.
X
,
tt
.
post
)
{
t
.
Errorf
(
"Unmarshal %#q into %#v: X=%#v, want %#v"
,
blob
,
tt
.
pre
,
b
.
X
,
tt
.
post
)
}
}
}
libgo/go/encoding/json/encode.go
View file @
08a680a8
...
@@ -96,7 +96,7 @@ import (
...
@@ -96,7 +96,7 @@ import (
//
//
// Channel, complex, and function values cannot be encoded in JSON.
// Channel, complex, and function values cannot be encoded in JSON.
// Attempting to encode such a value causes Marshal to return
// Attempting to encode such a value causes Marshal to return
// an
Invali
dTypeError.
// an
Unsupporte
dTypeError.
//
//
// JSON cannot represent cyclic data structures and Marshal does not
// JSON cannot represent cyclic data structures and Marshal does not
// handle them. Passing cyclic structures to Marshal will result in
// handle them. Passing cyclic structures to Marshal will result in
...
@@ -157,6 +157,8 @@ type Marshaler interface {
...
@@ -157,6 +157,8 @@ type Marshaler interface {
MarshalJSON
()
([]
byte
,
error
)
MarshalJSON
()
([]
byte
,
error
)
}
}
// An UnsupportedTypeError is returned by Marshal when attempting
// to encode an unsupported value type.
type
UnsupportedTypeError
struct
{
type
UnsupportedTypeError
struct
{
Type
reflect
.
Type
Type
reflect
.
Type
}
}
...
...
libgo/go/flag/flag.go
View file @
08a680a8
...
@@ -620,8 +620,9 @@ func (f *FlagSet) Var(value Value, name string, usage string) {
...
@@ -620,8 +620,9 @@ func (f *FlagSet) Var(value Value, name string, usage string) {
flag
:=
&
Flag
{
name
,
usage
,
value
,
value
.
String
()}
flag
:=
&
Flag
{
name
,
usage
,
value
,
value
.
String
()}
_
,
alreadythere
:=
f
.
formal
[
name
]
_
,
alreadythere
:=
f
.
formal
[
name
]
if
alreadythere
{
if
alreadythere
{
fmt
.
Fprintf
(
f
.
out
(),
"%s flag redefined: %s
\n
"
,
f
.
name
,
name
)
msg
:=
fmt
.
Sprintf
(
"%s flag redefined: %s"
,
f
.
name
,
name
)
panic
(
"flag redefinition"
)
// Happens only if flags are declared with identical names
fmt
.
Fprintln
(
f
.
out
(),
msg
)
panic
(
msg
)
// Happens only if flags are declared with identical names
}
}
if
f
.
formal
==
nil
{
if
f
.
formal
==
nil
{
f
.
formal
=
make
(
map
[
string
]
*
Flag
)
f
.
formal
=
make
(
map
[
string
]
*
Flag
)
...
...
libgo/go/fmt/doc.go
View file @
08a680a8
...
@@ -136,7 +136,7 @@
...
@@ -136,7 +136,7 @@
Fscanf and Fscanln read from a specified io.Reader; Sscan,
Fscanf and Fscanln read from a specified io.Reader; Sscan,
Sscanf and Sscanln read from an argument string. Scanln,
Sscanf and Sscanln read from an argument string. Scanln,
Fscanln and Sscanln stop scanning at a newline and require that
Fscanln and Sscanln stop scanning at a newline and require that
the items be followed by one; S
s
canf, Fscanf and Sscanf require
the items be followed by one; Scanf, Fscanf and Sscanf require
newlines in the input to match newlines in the format; the other
newlines in the input to match newlines in the format; the other
routines treat newlines as spaces.
routines treat newlines as spaces.
...
...
libgo/go/go/ast/ast.go
View file @
08a680a8
...
@@ -87,8 +87,12 @@ func stripTrailingWhitespace(s string) string {
...
@@ -87,8 +87,12 @@ func stripTrailingWhitespace(s string) string {
return
s
[
0
:
i
]
return
s
[
0
:
i
]
}
}
// Text returns the text of the comment,
// Text returns the text of the comment.
// with the comment markers - //, /*, and */ - removed.
// Comment markers (//, /*, and */), the first space of a line comment, and
// leading and trailing empty lines are removed. Multiple empty lines are
// reduced to one, and trailing space on lines is trimmed. Unless the result
// is empty, it is newline-terminated.
//
func
(
g
*
CommentGroup
)
Text
()
string
{
func
(
g
*
CommentGroup
)
Text
()
string
{
if
g
==
nil
{
if
g
==
nil
{
return
""
return
""
...
@@ -104,11 +108,9 @@ func (g *CommentGroup) Text() string {
...
@@ -104,11 +108,9 @@ func (g *CommentGroup) Text() string {
// The parser has given us exactly the comment text.
// The parser has given us exactly the comment text.
switch
c
[
1
]
{
switch
c
[
1
]
{
case
'/'
:
case
'/'
:
//-style comment
//-style comment
(no newline at the end)
c
=
c
[
2
:
]
c
=
c
[
2
:
]
// Remove leading space after //, if there is one.
// strip first space - required for Example tests
// TODO(gri) This appears to be necessary in isolated
// cases (bignum.RatFromString) - why?
if
len
(
c
)
>
0
&&
c
[
0
]
==
' '
{
if
len
(
c
)
>
0
&&
c
[
0
]
==
' '
{
c
=
c
[
1
:
]
c
=
c
[
1
:
]
}
}
...
...
libgo/go/go/ast/ast_test.go
0 → 100644
View file @
08a680a8
// 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
ast
import
(
"testing"
)
var
comments
=
[]
struct
{
list
[]
string
text
string
}{
{[]
string
{
"//"
},
""
},
{[]
string
{
"// "
},
""
},
{[]
string
{
"//"
,
"//"
,
"// "
},
""
},
{[]
string
{
"// foo "
},
"foo
\n
"
},
{[]
string
{
"//"
,
"//"
,
"// foo"
},
"foo
\n
"
},
{[]
string
{
"// foo bar "
},
"foo bar
\n
"
},
{[]
string
{
"// foo"
,
"// bar"
},
"foo
\n
bar
\n
"
},
{[]
string
{
"// foo"
,
"//"
,
"//"
,
"//"
,
"// bar"
},
"foo
\n\n
bar
\n
"
},
{[]
string
{
"// foo"
,
"/* bar */"
},
"foo
\n
bar
\n
"
},
{[]
string
{
"//"
,
"//"
,
"//"
,
"// foo"
,
"//"
,
"//"
,
"//"
},
"foo
\n
"
},
{[]
string
{
"/**/"
},
""
},
{[]
string
{
"/* */"
},
""
},
{[]
string
{
"/**/"
,
"/**/"
,
"/* */"
},
""
},
{[]
string
{
"/* Foo */"
},
" Foo
\n
"
},
{[]
string
{
"/* Foo Bar */"
},
" Foo Bar
\n
"
},
{[]
string
{
"/* Foo*/"
,
"/* Bar*/"
},
" Foo
\n
Bar
\n
"
},
{[]
string
{
"/* Foo*/"
,
"/**/"
,
"/**/"
,
"/**/"
,
"// Bar"
},
" Foo
\n\n
Bar
\n
"
},
{[]
string
{
"/* Foo*/"
,
"/*
\n
*/"
,
"//"
,
"/*
\n
*/"
,
"// Bar"
},
" Foo
\n\n
Bar
\n
"
},
{[]
string
{
"/* Foo*/"
,
"// Bar"
},
" Foo
\n
Bar
\n
"
},
{[]
string
{
"/* Foo
\n
Bar*/"
},
" Foo
\n
Bar
\n
"
},
}
func
TestCommentText
(
t
*
testing
.
T
)
{
for
i
,
c
:=
range
comments
{
list
:=
make
([]
*
Comment
,
len
(
c
.
list
))
for
i
,
s
:=
range
c
.
list
{
list
[
i
]
=
&
Comment
{
Text
:
s
}
}
text
:=
(
&
CommentGroup
{
list
})
.
Text
()
if
text
!=
c
.
text
{
t
.
Errorf
(
"case %d: got %q; expected %q"
,
i
,
text
,
c
.
text
)
}
}
}
libgo/go/go/build/build.go
View file @
08a680a8
...
@@ -68,7 +68,7 @@ type Context struct {
...
@@ -68,7 +68,7 @@ type Context struct {
// ReadDir returns a slice of os.FileInfo, sorted by Name,
// ReadDir returns a slice of os.FileInfo, sorted by Name,
// describing the content of the named directory.
// describing the content of the named directory.
// If ReadDir is nil, Import uses io.ReadDir.
// If ReadDir is nil, Import uses io
util
.ReadDir.
ReadDir
func
(
dir
string
)
(
fi
[]
os
.
FileInfo
,
err
error
)
ReadDir
func
(
dir
string
)
(
fi
[]
os
.
FileInfo
,
err
error
)
// OpenFile opens a file (not a directory) for reading.
// OpenFile opens a file (not a directory) for reading.
...
@@ -339,7 +339,7 @@ func (e *NoGoError) Error() string {
...
@@ -339,7 +339,7 @@ func (e *NoGoError) Error() string {
// - files starting with _ or . (likely editor temporary files)
// - files starting with _ or . (likely editor temporary files)
// - files with build constraints not satisfied by the context
// - files with build constraints not satisfied by the context
//
//
// If an error occurs, Import returns a non-nil error a
lso returns
a non-nil
// If an error occurs, Import returns a non-nil error a
nd
a non-nil
// *Package containing partial information.
// *Package containing partial information.
//
//
func
(
ctxt
*
Context
)
Import
(
path
string
,
srcDir
string
,
mode
ImportMode
)
(
*
Package
,
error
)
{
func
(
ctxt
*
Context
)
Import
(
path
string
,
srcDir
string
,
mode
ImportMode
)
(
*
Package
,
error
)
{
...
...
libgo/go/go/parser/parser.go
View file @
08a680a8
...
@@ -267,13 +267,13 @@ func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
...
@@ -267,13 +267,13 @@ func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
// Consume a group of adjacent comments, add it to the parser's
// Consume a group of adjacent comments, add it to the parser's
// comments list, and return it together with the line at which
// comments list, and return it together with the line at which
// the last comment in the group ends. A
n empty line or non-comment
// the last comment in the group ends. A
non-comment token or n
//
token terminates
a comment group.
//
empty lines terminate
a comment group.
//
//
func
(
p
*
parser
)
consumeCommentGroup
()
(
comments
*
ast
.
CommentGroup
,
endline
int
)
{
func
(
p
*
parser
)
consumeCommentGroup
(
n
int
)
(
comments
*
ast
.
CommentGroup
,
endline
int
)
{
var
list
[]
*
ast
.
Comment
var
list
[]
*
ast
.
Comment
endline
=
p
.
file
.
Line
(
p
.
pos
)
endline
=
p
.
file
.
Line
(
p
.
pos
)
for
p
.
tok
==
token
.
COMMENT
&&
endline
+
1
>=
p
.
file
.
Line
(
p
.
pos
)
{
for
p
.
tok
==
token
.
COMMENT
&&
p
.
file
.
Line
(
p
.
pos
)
<=
endline
+
n
{
var
comment
*
ast
.
Comment
var
comment
*
ast
.
Comment
comment
,
endline
=
p
.
consumeComment
()
comment
,
endline
=
p
.
consumeComment
()
list
=
append
(
list
,
comment
)
list
=
append
(
list
,
comment
)
...
@@ -314,7 +314,7 @@ func (p *parser) next() {
...
@@ -314,7 +314,7 @@ func (p *parser) next() {
if
p
.
file
.
Line
(
p
.
pos
)
==
line
{
if
p
.
file
.
Line
(
p
.
pos
)
==
line
{
// The comment is on same line as the previous token; it
// The comment is on same line as the previous token; it
// cannot be a lead comment but may be a line comment.
// cannot be a lead comment but may be a line comment.
comment
,
endline
=
p
.
consumeCommentGroup
()
comment
,
endline
=
p
.
consumeCommentGroup
(
0
)
if
p
.
file
.
Line
(
p
.
pos
)
!=
endline
{
if
p
.
file
.
Line
(
p
.
pos
)
!=
endline
{
// The next token is on a different line, thus
// The next token is on a different line, thus
// the last comment group is a line comment.
// the last comment group is a line comment.
...
@@ -325,7 +325,7 @@ func (p *parser) next() {
...
@@ -325,7 +325,7 @@ func (p *parser) next() {
// consume successor comments, if any
// consume successor comments, if any
endline
=
-
1
endline
=
-
1
for
p
.
tok
==
token
.
COMMENT
{
for
p
.
tok
==
token
.
COMMENT
{
comment
,
endline
=
p
.
consumeCommentGroup
()
comment
,
endline
=
p
.
consumeCommentGroup
(
1
)
}
}
if
endline
+
1
==
p
.
file
.
Line
(
p
.
pos
)
{
if
endline
+
1
==
p
.
file
.
Line
(
p
.
pos
)
{
...
@@ -627,10 +627,10 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
...
@@ -627,10 +627,10 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
doc
:=
p
.
leadComment
doc
:=
p
.
leadComment
//
fields
//
FieldDecl
list
,
typ
:=
p
.
parseVarList
(
false
)
list
,
typ
:=
p
.
parseVarList
(
false
)
//
optional t
ag
//
T
ag
var
tag
*
ast
.
BasicLit
var
tag
*
ast
.
BasicLit
if
p
.
tok
==
token
.
STRING
{
if
p
.
tok
==
token
.
STRING
{
tag
=
&
ast
.
BasicLit
{
ValuePos
:
p
.
pos
,
Kind
:
p
.
tok
,
Value
:
p
.
lit
}
tag
=
&
ast
.
BasicLit
{
ValuePos
:
p
.
pos
,
Kind
:
p
.
tok
,
Value
:
p
.
lit
}
...
@@ -645,7 +645,6 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
...
@@ -645,7 +645,6 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
}
else
{
}
else
{
// ["*"] TypeName (AnonymousField)
// ["*"] TypeName (AnonymousField)
typ
=
list
[
0
]
// we always have at least one element
typ
=
list
[
0
]
// we always have at least one element
p
.
resolve
(
typ
)
if
n
:=
len
(
list
);
n
>
1
||
!
isTypeName
(
deref
(
typ
))
{
if
n
:=
len
(
list
);
n
>
1
||
!
isTypeName
(
deref
(
typ
))
{
pos
:=
typ
.
Pos
()
pos
:=
typ
.
Pos
()
p
.
errorExpected
(
pos
,
"anonymous field"
)
p
.
errorExpected
(
pos
,
"anonymous field"
)
...
@@ -657,6 +656,7 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
...
@@ -657,6 +656,7 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
field
:=
&
ast
.
Field
{
Doc
:
doc
,
Names
:
idents
,
Type
:
typ
,
Tag
:
tag
,
Comment
:
p
.
lineComment
}
field
:=
&
ast
.
Field
{
Doc
:
doc
,
Names
:
idents
,
Type
:
typ
,
Tag
:
tag
,
Comment
:
p
.
lineComment
}
p
.
declare
(
field
,
nil
,
scope
,
ast
.
Var
,
idents
...
)
p
.
declare
(
field
,
nil
,
scope
,
ast
.
Var
,
idents
...
)
p
.
resolve
(
typ
)
return
field
return
field
}
}
...
@@ -699,12 +699,15 @@ func (p *parser) parsePointerType() *ast.StarExpr {
...
@@ -699,12 +699,15 @@ func (p *parser) parsePointerType() *ast.StarExpr {
return
&
ast
.
StarExpr
{
Star
:
star
,
X
:
base
}
return
&
ast
.
StarExpr
{
Star
:
star
,
X
:
base
}
}
}
// If the result is an identifier, it is not resolved.
func
(
p
*
parser
)
tryVarType
(
isParam
bool
)
ast
.
Expr
{
func
(
p
*
parser
)
tryVarType
(
isParam
bool
)
ast
.
Expr
{
if
isParam
&&
p
.
tok
==
token
.
ELLIPSIS
{
if
isParam
&&
p
.
tok
==
token
.
ELLIPSIS
{
pos
:=
p
.
pos
pos
:=
p
.
pos
p
.
next
()
p
.
next
()
typ
:=
p
.
tryIdentOrType
(
isParam
)
// don't use parseType so we can provide better error message
typ
:=
p
.
tryIdentOrType
(
isParam
)
// don't use parseType so we can provide better error message
if
typ
==
nil
{
if
typ
!=
nil
{
p
.
resolve
(
typ
)
}
else
{
p
.
error
(
pos
,
"'...' parameter is missing type"
)
p
.
error
(
pos
,
"'...' parameter is missing type"
)
typ
=
&
ast
.
BadExpr
{
From
:
pos
,
To
:
p
.
pos
}
typ
=
&
ast
.
BadExpr
{
From
:
pos
,
To
:
p
.
pos
}
}
}
...
@@ -713,6 +716,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
...
@@ -713,6 +716,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
return
p
.
tryIdentOrType
(
false
)
return
p
.
tryIdentOrType
(
false
)
}
}
// If the result is an identifier, it is not resolved.
func
(
p
*
parser
)
parseVarType
(
isParam
bool
)
ast
.
Expr
{
func
(
p
*
parser
)
parseVarType
(
isParam
bool
)
ast
.
Expr
{
typ
:=
p
.
tryVarType
(
isParam
)
typ
:=
p
.
tryVarType
(
isParam
)
if
typ
==
nil
{
if
typ
==
nil
{
...
@@ -724,6 +728,7 @@ func (p *parser) parseVarType(isParam bool) ast.Expr {
...
@@ -724,6 +728,7 @@ func (p *parser) parseVarType(isParam bool) ast.Expr {
return
typ
return
typ
}
}
// If any of the results are identifiers, they are not resolved.
func
(
p
*
parser
)
parseVarList
(
isParam
bool
)
(
list
[]
ast
.
Expr
,
typ
ast
.
Expr
)
{
func
(
p
*
parser
)
parseVarList
(
isParam
bool
)
(
list
[]
ast
.
Expr
,
typ
ast
.
Expr
)
{
if
p
.
trace
{
if
p
.
trace
{
defer
un
(
trace
(
p
,
"VarList"
))
defer
un
(
trace
(
p
,
"VarList"
))
...
@@ -744,9 +749,7 @@ func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
...
@@ -744,9 +749,7 @@ func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
}
}
// if we had a list of identifiers, it must be followed by a type
// if we had a list of identifiers, it must be followed by a type
if
typ
=
p
.
tryVarType
(
isParam
);
typ
!=
nil
{
typ
=
p
.
tryVarType
(
isParam
)
p
.
resolve
(
typ
)
}
return
return
}
}
...
@@ -756,7 +759,10 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
...
@@ -756,7 +759,10 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
defer
un
(
trace
(
p
,
"ParameterList"
))
defer
un
(
trace
(
p
,
"ParameterList"
))
}
}
// ParameterDecl
list
,
typ
:=
p
.
parseVarList
(
ellipsisOk
)
list
,
typ
:=
p
.
parseVarList
(
ellipsisOk
)
// analyze case
if
typ
!=
nil
{
if
typ
!=
nil
{
// IdentifierList Type
// IdentifierList Type
idents
:=
p
.
makeIdentList
(
list
)
idents
:=
p
.
makeIdentList
(
list
)
...
@@ -765,10 +771,10 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
...
@@ -765,10 +771,10 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
// Go spec: The scope of an identifier denoting a function
// Go spec: The scope of an identifier denoting a function
// parameter or result variable is the function body.
// parameter or result variable is the function body.
p
.
declare
(
field
,
nil
,
scope
,
ast
.
Var
,
idents
...
)
p
.
declare
(
field
,
nil
,
scope
,
ast
.
Var
,
idents
...
)
p
.
resolve
(
typ
)
if
p
.
tok
==
token
.
COMMA
{
if
p
.
tok
==
token
.
COMMA
{
p
.
next
()
p
.
next
()
}
}
for
p
.
tok
!=
token
.
RPAREN
&&
p
.
tok
!=
token
.
EOF
{
for
p
.
tok
!=
token
.
RPAREN
&&
p
.
tok
!=
token
.
EOF
{
idents
:=
p
.
parseIdentList
()
idents
:=
p
.
parseIdentList
()
typ
:=
p
.
parseVarType
(
ellipsisOk
)
typ
:=
p
.
parseVarType
(
ellipsisOk
)
...
@@ -777,18 +783,18 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
...
@@ -777,18 +783,18 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [
// Go spec: The scope of an identifier denoting a function
// Go spec: The scope of an identifier denoting a function
// parameter or result variable is the function body.
// parameter or result variable is the function body.
p
.
declare
(
field
,
nil
,
scope
,
ast
.
Var
,
idents
...
)
p
.
declare
(
field
,
nil
,
scope
,
ast
.
Var
,
idents
...
)
p
.
resolve
(
typ
)
if
!
p
.
atComma
(
"parameter list"
)
{
if
!
p
.
atComma
(
"parameter list"
)
{
break
break
}
}
p
.
next
()
p
.
next
()
}
}
}
else
{
}
else
{
// Type { "," Type } (anonymous parameters)
// Type { "," Type } (anonymous parameters)
params
=
make
([]
*
ast
.
Field
,
len
(
list
))
params
=
make
([]
*
ast
.
Field
,
len
(
list
))
for
i
,
x
:=
range
list
{
for
i
,
typ
:=
range
list
{
p
.
resolve
(
x
)
p
.
resolve
(
typ
)
params
[
i
]
=
&
ast
.
Field
{
Type
:
x
}
params
[
i
]
=
&
ast
.
Field
{
Type
:
typ
}
}
}
}
}
...
...
libgo/go/go/parser/parser_test.go
View file @
08a680a8
...
@@ -5,10 +5,12 @@
...
@@ -5,10 +5,12 @@
package
parser
package
parser
import
(
import
(
"bytes"
"fmt"
"fmt"
"go/ast"
"go/ast"
"go/token"
"go/token"
"os"
"os"
"strings"
"testing"
"testing"
)
)
...
@@ -25,7 +27,7 @@ func TestParse(t *testing.T) {
...
@@ -25,7 +27,7 @@ func TestParse(t *testing.T) {
for
_
,
filename
:=
range
validFiles
{
for
_
,
filename
:=
range
validFiles
{
_
,
err
:=
ParseFile
(
fset
,
filename
,
nil
,
DeclarationErrors
)
_
,
err
:=
ParseFile
(
fset
,
filename
,
nil
,
DeclarationErrors
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
f
(
"ParseFile(%s): %v"
,
filename
,
err
)
t
.
Fatal
f
(
"ParseFile(%s): %v"
,
filename
,
err
)
}
}
}
}
}
}
...
@@ -70,7 +72,7 @@ func TestParseExpr(t *testing.T) {
...
@@ -70,7 +72,7 @@ func TestParseExpr(t *testing.T) {
src
:=
"a + b"
src
:=
"a + b"
x
,
err
:=
ParseExpr
(
src
)
x
,
err
:=
ParseExpr
(
src
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
f
(
"ParseExpr(%s): %v"
,
src
,
err
)
t
.
Fatal
f
(
"ParseExpr(%s): %v"
,
src
,
err
)
}
}
// sanity check
// sanity check
if
_
,
ok
:=
x
.
(
*
ast
.
BinaryExpr
);
!
ok
{
if
_
,
ok
:=
x
.
(
*
ast
.
BinaryExpr
);
!
ok
{
...
@@ -81,7 +83,7 @@ func TestParseExpr(t *testing.T) {
...
@@ -81,7 +83,7 @@ func TestParseExpr(t *testing.T) {
src
=
"a + *"
src
=
"a + *"
_
,
err
=
ParseExpr
(
src
)
_
,
err
=
ParseExpr
(
src
)
if
err
==
nil
{
if
err
==
nil
{
t
.
Error
f
(
"ParseExpr(%s): %v"
,
src
,
err
)
t
.
Fatal
f
(
"ParseExpr(%s): %v"
,
src
,
err
)
}
}
// it must not crash
// it must not crash
...
@@ -93,7 +95,7 @@ func TestParseExpr(t *testing.T) {
...
@@ -93,7 +95,7 @@ func TestParseExpr(t *testing.T) {
func
TestColonEqualsScope
(
t
*
testing
.
T
)
{
func
TestColonEqualsScope
(
t
*
testing
.
T
)
{
f
,
err
:=
ParseFile
(
fset
,
""
,
`package p; func f() { x, y, z := x, y, z }`
,
0
)
f
,
err
:=
ParseFile
(
fset
,
""
,
`package p; func f() { x, y, z := x, y, z }`
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"parse: %s"
,
err
)
t
.
Fatal
(
err
)
}
}
// RHS refers to undefined globals; LHS does not.
// RHS refers to undefined globals; LHS does not.
...
@@ -115,7 +117,7 @@ func TestColonEqualsScope(t *testing.T) {
...
@@ -115,7 +117,7 @@ func TestColonEqualsScope(t *testing.T) {
func
TestVarScope
(
t
*
testing
.
T
)
{
func
TestVarScope
(
t
*
testing
.
T
)
{
f
,
err
:=
ParseFile
(
fset
,
""
,
`package p; func f() { var x, y, z = x, y, z }`
,
0
)
f
,
err
:=
ParseFile
(
fset
,
""
,
`package p; func f() { var x, y, z = x, y, z }`
,
0
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"parse: %s"
,
err
)
t
.
Fatal
(
err
)
}
}
// RHS refers to undefined globals; LHS does not.
// RHS refers to undefined globals; LHS does not.
...
@@ -133,6 +135,67 @@ func TestVarScope(t *testing.T) {
...
@@ -133,6 +135,67 @@ func TestVarScope(t *testing.T) {
}
}
}
}
func
TestUnresolved
(
t
*
testing
.
T
)
{
f
,
err
:=
ParseFile
(
fset
,
""
,
`
package p
//
func f1a(int)
func f2a(byte, int, float)
func f3a(a, b int, c float)
func f4a(...complex)
func f5a(a s1a, b ...complex)
//
func f1b(*int)
func f2b([]byte, (int), *float)
func f3b(a, b *int, c []float)
func f4b(...*complex)
func f5b(a s1a, b ...[]complex)
//
type s1a struct { int }
type s2a struct { byte; int; s1a }
type s3a struct { a, b int; c float }
//
type s1b struct { *int }
type s2b struct { byte; int; *float }
type s3b struct { a, b *s3b; c []float }
`
,
0
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
want
:=
"int "
+
// f1a
"byte int float "
+
// f2a
"int float "
+
// f3a
"complex "
+
// f4a
"complex "
+
// f5a
//
"int "
+
// f1b
"byte int float "
+
// f2b
"int float "
+
// f3b
"complex "
+
// f4b
"complex "
+
// f5b
//
"int "
+
// s1a
"byte int "
+
// s2a
"int float "
+
// s3a
//
"int "
+
// s1a
"byte int float "
+
// s2a
"float "
// s3a
// collect unresolved identifiers
var
buf
bytes
.
Buffer
for
_
,
u
:=
range
f
.
Unresolved
{
buf
.
WriteString
(
u
.
Name
)
buf
.
WriteByte
(
' '
)
}
got
:=
buf
.
String
()
if
got
!=
want
{
t
.
Errorf
(
"
\n
got: %s
\n
want: %s"
,
got
,
want
)
}
}
var
imports
=
map
[
string
]
bool
{
var
imports
=
map
[
string
]
bool
{
`"a"`
:
true
,
`"a"`
:
true
,
"`a`"
:
true
,
"`a`"
:
true
,
...
@@ -177,3 +240,125 @@ func TestImports(t *testing.T) {
...
@@ -177,3 +240,125 @@ func TestImports(t *testing.T) {
}
}
}
}
}
}
func
TestCommentGroups
(
t
*
testing
.
T
)
{
f
,
err
:=
ParseFile
(
fset
,
""
,
`
package p /* 1a */ /* 1b */ /* 1c */ // 1d
/* 2a
*/
// 2b
const pi = 3.1415
/* 3a */ // 3b
/* 3c */ const e = 2.7182
// Example from issue 3139
func ExampleCount() {
fmt.Println(strings.Count("cheese", "e"))
fmt.Println(strings.Count("five", "")) // before & after each rune
// Output:
// 3
// 5
}
`
,
ParseComments
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
expected
:=
[][]
string
{
{
"/* 1a */"
,
"/* 1b */"
,
"/* 1c */"
,
"// 1d"
},
{
"/* 2a
\n
*/"
,
"// 2b"
},
{
"/* 3a */"
,
"// 3b"
,
"/* 3c */"
},
{
"// Example from issue 3139"
},
{
"// before & after each rune"
},
{
"// Output:"
,
"// 3"
,
"// 5"
},
}
if
len
(
f
.
Comments
)
!=
len
(
expected
)
{
t
.
Fatalf
(
"got %d comment groups; expected %d"
,
len
(
f
.
Comments
),
len
(
expected
))
}
for
i
,
exp
:=
range
expected
{
got
:=
f
.
Comments
[
i
]
.
List
if
len
(
got
)
!=
len
(
exp
)
{
t
.
Errorf
(
"got %d comments in group %d; expected %d"
,
len
(
got
),
i
,
len
(
exp
))
continue
}
for
j
,
exp
:=
range
exp
{
got
:=
got
[
j
]
.
Text
if
got
!=
exp
{
t
.
Errorf
(
"got %q in group %d; expected %q"
,
got
,
i
,
exp
)
}
}
}
}
func
getField
(
file
*
ast
.
File
,
fieldname
string
)
*
ast
.
Field
{
parts
:=
strings
.
Split
(
fieldname
,
"."
)
for
_
,
d
:=
range
file
.
Decls
{
if
d
,
ok
:=
d
.
(
*
ast
.
GenDecl
);
ok
&&
d
.
Tok
==
token
.
TYPE
{
for
_
,
s
:=
range
d
.
Specs
{
if
s
,
ok
:=
s
.
(
*
ast
.
TypeSpec
);
ok
&&
s
.
Name
.
Name
==
parts
[
0
]
{
if
s
,
ok
:=
s
.
Type
.
(
*
ast
.
StructType
);
ok
{
for
_
,
f
:=
range
s
.
Fields
.
List
{
for
_
,
name
:=
range
f
.
Names
{
if
name
.
Name
==
parts
[
1
]
{
return
f
}
}
}
}
}
}
}
}
return
nil
}
// Don't use ast.CommentGroup.Text() - we want to see exact comment text.
func
commentText
(
c
*
ast
.
CommentGroup
)
string
{
var
buf
bytes
.
Buffer
if
c
!=
nil
{
for
_
,
c
:=
range
c
.
List
{
buf
.
WriteString
(
c
.
Text
)
}
}
return
buf
.
String
()
}
func
checkFieldComments
(
t
*
testing
.
T
,
file
*
ast
.
File
,
fieldname
,
lead
,
line
string
)
{
f
:=
getField
(
file
,
fieldname
)
if
f
==
nil
{
t
.
Fatalf
(
"field not found: %s"
,
fieldname
)
}
if
got
:=
commentText
(
f
.
Doc
);
got
!=
lead
{
t
.
Errorf
(
"got lead comment %q; expected %q"
,
got
,
lead
)
}
if
got
:=
commentText
(
f
.
Comment
);
got
!=
line
{
t
.
Errorf
(
"got line comment %q; expected %q"
,
got
,
line
)
}
}
func
TestLeadAndLineComments
(
t
*
testing
.
T
)
{
f
,
err
:=
ParseFile
(
fset
,
""
,
`
package p
type T struct {
/* F1 lead comment */
//
F1 int /* F1 */ // line comment
// F2 lead
// comment
F2 int // F2 line comment
// f3 lead comment
f3 int // f3 line comment
}
`
,
ParseComments
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
checkFieldComments
(
t
,
f
,
"T.F1"
,
"/* F1 lead comment *///"
,
"/* F1 */// line comment"
)
checkFieldComments
(
t
,
f
,
"T.F2"
,
"// F2 lead// comment"
,
"// F2 line comment"
)
checkFieldComments
(
t
,
f
,
"T.f3"
,
"// f3 lead comment"
,
"// f3 line comment"
)
ast
.
FileExports
(
f
)
checkFieldComments
(
t
,
f
,
"T.F1"
,
"/* F1 lead comment *///"
,
"/* F1 */// line comment"
)
checkFieldComments
(
t
,
f
,
"T.F2"
,
"// F2 lead// comment"
,
"// F2 line comment"
)
if
getField
(
f
,
"T.f3"
)
!=
nil
{
t
.
Error
(
"not expected to find T.f3"
)
}
}
libgo/go/go/printer/nodes.go
View file @
08a680a8
...
@@ -60,8 +60,8 @@ func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (prin
...
@@ -60,8 +60,8 @@ func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (prin
// setComment sets g as the next comment if g != nil and if node comments
// setComment sets g as the next comment if g != nil and if node comments
// are enabled - this mode is used when printing source code fragments such
// are enabled - this mode is used when printing source code fragments such
// as exports only. It assumes that there
are no other pending comments to
// as exports only. It assumes that there
is no pending comment in p.comments
//
interspers
e.
//
and at most one pending comment in the p.comment cach
e.
func
(
p
*
printer
)
setComment
(
g
*
ast
.
CommentGroup
)
{
func
(
p
*
printer
)
setComment
(
g
*
ast
.
CommentGroup
)
{
if
g
==
nil
||
!
p
.
useNodeComments
{
if
g
==
nil
||
!
p
.
useNodeComments
{
return
return
...
@@ -74,10 +74,19 @@ func (p *printer) setComment(g *ast.CommentGroup) {
...
@@ -74,10 +74,19 @@ func (p *printer) setComment(g *ast.CommentGroup) {
// should never happen - handle gracefully and flush
// should never happen - handle gracefully and flush
// all comments up to g, ignore anything after that
// all comments up to g, ignore anything after that
p
.
flush
(
p
.
posFor
(
g
.
List
[
0
]
.
Pos
()),
token
.
ILLEGAL
)
p
.
flush
(
p
.
posFor
(
g
.
List
[
0
]
.
Pos
()),
token
.
ILLEGAL
)
p
.
comments
=
p
.
comments
[
0
:
1
]
// in debug mode, report error
p
.
internalError
(
"setComment found pending comments"
)
}
}
p
.
comments
[
0
]
=
g
p
.
comments
[
0
]
=
g
p
.
cindex
=
0
p
.
cindex
=
0
p
.
nextComment
()
// get comment ready for use
// don't overwrite any pending comment in the p.comment cache
// (there may be a pending comment when a line comment is
// immediately followed by a lead comment with no other
// tokens inbetween)
if
p
.
commentOffset
==
infinity
{
p
.
nextComment
()
// get comment ready for use
}
}
}
type
exprListMode
uint
type
exprListMode
uint
...
...
libgo/go/log/log.go
View file @
08a680a8
...
@@ -26,7 +26,7 @@ const (
...
@@ -26,7 +26,7 @@ const (
// Bits or'ed together to control what's printed. There is no control over the
// Bits or'ed together to control what's printed. There is no control over the
// order they appear (the order listed here) or the format they present (as
// order they appear (the order listed here) or the format they present (as
// described in the comments). A colon appears after these items:
// described in the comments). A colon appears after these items:
// 2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
// 2009/01
/
23 01:23:23.123123 /a/b/c/d.go:23: message
Ldate
=
1
<<
iota
// the date: 2009/01/23
Ldate
=
1
<<
iota
// the date: 2009/01/23
Ltime
// the time: 01:23:23
Ltime
// the time: 01:23:23
Lmicroseconds
// microsecond resolution: 01:23:23.123123. assumes Ltime.
Lmicroseconds
// microsecond resolution: 01:23:23.123123. assumes Ltime.
...
...
libgo/go/math/big/nat.go
View file @
08a680a8
...
@@ -271,10 +271,10 @@ func karatsuba(z, x, y nat) {
...
@@ -271,10 +271,10 @@ func karatsuba(z, x, y nat) {
// xd = x1 - x0
// xd = x1 - x0
// yd = y0 - y1
// yd = y0 - y1
//
//
// z1 = xd*yd + z
1
+ z0
// z1 = xd*yd + z
2
+ z0
// = (x1-x0)*(y0 - y1) + z
1
+ z0
// = (x1-x0)*(y0 - y1) + z
2
+ z0
// = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z
1
+ z0
// = x1*y0 - x1*y1 - x0*y0 + x0*y1 + z
2
+ z0
// = x1*y0 - z
1 - z0 + x0*y1 + z1
+ z0
// = x1*y0 - z
2 - z0 + x0*y1 + z2
+ z0
// = x1*y0 + x0*y1
// = x1*y0 + x0*y1
// split x, y into "digits"
// split x, y into "digits"
...
@@ -318,7 +318,7 @@ func karatsuba(z, x, y nat) {
...
@@ -318,7 +318,7 @@ func karatsuba(z, x, y nat) {
// save original z2:z0
// save original z2:z0
// (ok to use upper half of z since we're done recursing)
// (ok to use upper half of z since we're done recursing)
r
:=
z
[
n
*
4
:
]
r
:=
z
[
n
*
4
:
]
copy
(
r
,
z
)
copy
(
r
,
z
[
:
n
*
2
]
)
// add up all partial products
// add up all partial products
//
//
...
...
libgo/go/math/big/nat_test.go
View file @
08a680a8
...
@@ -661,3 +661,21 @@ func TestExpNN(t *testing.T) {
...
@@ -661,3 +661,21 @@ func TestExpNN(t *testing.T) {
}
}
}
}
}
}
func
ExpHelper
(
b
*
testing
.
B
,
x
,
y
Word
)
{
var
z
nat
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
z
.
expWW
(
x
,
y
)
}
}
func
BenchmarkExp3Power0x10
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x10
)
}
func
BenchmarkExp3Power0x40
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x40
)
}
func
BenchmarkExp3Power0x100
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x100
)
}
func
BenchmarkExp3Power0x400
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x400
)
}
func
BenchmarkExp3Power0x1000
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x1000
)
}
func
BenchmarkExp3Power0x4000
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x4000
)
}
func
BenchmarkExp3Power0x10000
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x10000
)
}
func
BenchmarkExp3Power0x40000
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x40000
)
}
func
BenchmarkExp3Power0x100000
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x100000
)
}
func
BenchmarkExp3Power0x400000
(
b
*
testing
.
B
)
{
ExpHelper
(
b
,
3
,
0x400000
)
}
libgo/go/mime/multipart/multipart.go
View file @
08a680a8
...
@@ -22,11 +22,6 @@ import (
...
@@ -22,11 +22,6 @@ import (
"net/textproto"
"net/textproto"
)
)
// TODO(bradfitz): inline these once the compiler can inline them in
// read-only situation (such as bytes.HasSuffix)
var
lf
=
[]
byte
(
"
\n
"
)
var
crlf
=
[]
byte
(
"
\r\n
"
)
var
emptyParams
=
make
(
map
[
string
]
string
)
var
emptyParams
=
make
(
map
[
string
]
string
)
// A Part represents a single part in a multipart body.
// A Part represents a single part in a multipart body.
...
@@ -36,8 +31,9 @@ type Part struct {
...
@@ -36,8 +31,9 @@ type Part struct {
// i.e. "foo-bar" changes case to "Foo-Bar"
// i.e. "foo-bar" changes case to "Foo-Bar"
Header
textproto
.
MIMEHeader
Header
textproto
.
MIMEHeader
buffer
*
bytes
.
Buffer
buffer
*
bytes
.
Buffer
mr
*
Reader
mr
*
Reader
bytesRead
int
disposition
string
disposition
string
dispositionParams
map
[
string
]
string
dispositionParams
map
[
string
]
string
...
@@ -113,14 +109,26 @@ func (bp *Part) populateHeaders() error {
...
@@ -113,14 +109,26 @@ func (bp *Part) populateHeaders() error {
// Read reads the body of a part, after its headers and before the
// Read reads the body of a part, after its headers and before the
// next part (if any) begins.
// next part (if any) begins.
func
(
p
*
Part
)
Read
(
d
[]
byte
)
(
n
int
,
err
error
)
{
func
(
p
*
Part
)
Read
(
d
[]
byte
)
(
n
int
,
err
error
)
{
defer
func
()
{
p
.
bytesRead
+=
n
}()
if
p
.
buffer
.
Len
()
>=
len
(
d
)
{
if
p
.
buffer
.
Len
()
>=
len
(
d
)
{
// Internal buffer of unconsumed data is large enough for
// Internal buffer of unconsumed data is large enough for
// the read request. No need to parse more at the moment.
// the read request. No need to parse more at the moment.
return
p
.
buffer
.
Read
(
d
)
return
p
.
buffer
.
Read
(
d
)
}
}
peek
,
err
:=
p
.
mr
.
bufReader
.
Peek
(
4096
)
// TODO(bradfitz): add buffer size accessor
peek
,
err
:=
p
.
mr
.
bufReader
.
Peek
(
4096
)
// TODO(bradfitz): add buffer size accessor
unexpectedEof
:=
err
==
io
.
EOF
if
err
!=
nil
&&
!
unexpectedEof
{
// Look for an immediate empty part without a leading \r\n
// before the boundary separator. Some MIME code makes empty
// parts like this. Most browsers, however, write the \r\n
// before the subsequent boundary even for empty parts and
// won't hit this path.
if
p
.
bytesRead
==
0
&&
p
.
mr
.
peekBufferIsEmptyPart
(
peek
)
{
return
0
,
io
.
EOF
}
unexpectedEOF
:=
err
==
io
.
EOF
if
err
!=
nil
&&
!
unexpectedEOF
{
return
0
,
fmt
.
Errorf
(
"multipart: Part Read: %v"
,
err
)
return
0
,
fmt
.
Errorf
(
"multipart: Part Read: %v"
,
err
)
}
}
if
peek
==
nil
{
if
peek
==
nil
{
...
@@ -138,7 +146,7 @@ func (p *Part) Read(d []byte) (n int, err error) {
...
@@ -138,7 +146,7 @@ func (p *Part) Read(d []byte) (n int, err error) {
foundBoundary
=
true
foundBoundary
=
true
}
else
if
safeCount
:=
len
(
peek
)
-
len
(
p
.
mr
.
nlDashBoundary
);
safeCount
>
0
{
}
else
if
safeCount
:=
len
(
peek
)
-
len
(
p
.
mr
.
nlDashBoundary
);
safeCount
>
0
{
nCopy
=
safeCount
nCopy
=
safeCount
}
else
if
unexpectedE
of
{
}
else
if
unexpectedE
OF
{
// If we've run out of peek buffer and the boundary
// If we've run out of peek buffer and the boundary
// wasn't found (and can't possibly fit), we must have
// wasn't found (and can't possibly fit), we must have
// hit the end of the file unexpectedly.
// hit the end of the file unexpectedly.
...
@@ -172,7 +180,10 @@ type Reader struct {
...
@@ -172,7 +180,10 @@ type Reader struct {
currentPart
*
Part
currentPart
*
Part
partsRead
int
partsRead
int
nl
,
nlDashBoundary
,
dashBoundaryDash
,
dashBoundary
[]
byte
nl
[]
byte
// "\r\n" or "\n" (set after seeing first boundary line)
nlDashBoundary
[]
byte
// nl + "--boundary"
dashBoundaryDash
[]
byte
// "--boundary--"
dashBoundary
[]
byte
// "--boundary"
}
}
// NextPart returns the next part in the multipart or an error.
// NextPart returns the next part in the multipart or an error.
...
@@ -185,7 +196,7 @@ func (r *Reader) NextPart() (*Part, error) {
...
@@ -185,7 +196,7 @@ func (r *Reader) NextPart() (*Part, error) {
expectNewPart
:=
false
expectNewPart
:=
false
for
{
for
{
line
,
err
:=
r
.
bufReader
.
ReadSlice
(
'\n'
)
line
,
err
:=
r
.
bufReader
.
ReadSlice
(
'\n'
)
if
err
==
io
.
EOF
&&
bytes
.
Equal
(
line
,
r
.
dashBoundaryDash
)
{
if
err
==
io
.
EOF
&&
r
.
isFinalBoundary
(
line
)
{
// If the buffer ends in "--boundary--" without the
// If the buffer ends in "--boundary--" without the
// trailing "\r\n", ReadSlice will return an error
// trailing "\r\n", ReadSlice will return an error
// (since it's missing the '\n'), but this is a valid
// (since it's missing the '\n'), but this is a valid
...
@@ -207,7 +218,7 @@ func (r *Reader) NextPart() (*Part, error) {
...
@@ -207,7 +218,7 @@ func (r *Reader) NextPart() (*Part, error) {
return
bp
,
nil
return
bp
,
nil
}
}
if
hasPrefixThenNewline
(
line
,
r
.
dashBoundaryDash
)
{
if
r
.
isFinalBoundary
(
line
)
{
// Expected EOF
// Expected EOF
return
nil
,
io
.
EOF
return
nil
,
io
.
EOF
}
}
...
@@ -235,7 +246,19 @@ func (r *Reader) NextPart() (*Part, error) {
...
@@ -235,7 +246,19 @@ func (r *Reader) NextPart() (*Part, error) {
panic
(
"unreachable"
)
panic
(
"unreachable"
)
}
}
func
(
mr
*
Reader
)
isBoundaryDelimiterLine
(
line
[]
byte
)
bool
{
// isFinalBoundary returns whether line is the final boundary line
// indiciating that all parts are over.
// It matches `^--boundary--[ \t]*(\r\n)?$`
func
(
mr
*
Reader
)
isFinalBoundary
(
line
[]
byte
)
bool
{
if
!
bytes
.
HasPrefix
(
line
,
mr
.
dashBoundaryDash
)
{
return
false
}
rest
:=
line
[
len
(
mr
.
dashBoundaryDash
)
:
]
rest
=
skipLWSPChar
(
rest
)
return
len
(
rest
)
==
0
||
bytes
.
Equal
(
rest
,
mr
.
nl
)
}
func
(
mr
*
Reader
)
isBoundaryDelimiterLine
(
line
[]
byte
)
(
ret
bool
)
{
// http://tools.ietf.org/html/rfc2046#section-5.1
// http://tools.ietf.org/html/rfc2046#section-5.1
// The boundary delimiter line is then defined as a line
// The boundary delimiter line is then defined as a line
// consisting entirely of two hyphen characters ("-",
// consisting entirely of two hyphen characters ("-",
...
@@ -245,32 +268,52 @@ func (mr *Reader) isBoundaryDelimiterLine(line []byte) bool {
...
@@ -245,32 +268,52 @@ func (mr *Reader) isBoundaryDelimiterLine(line []byte) bool {
if
!
bytes
.
HasPrefix
(
line
,
mr
.
dashBoundary
)
{
if
!
bytes
.
HasPrefix
(
line
,
mr
.
dashBoundary
)
{
return
false
return
false
}
}
if
bytes
.
HasSuffix
(
line
,
mr
.
nl
)
{
rest
:=
line
[
len
(
mr
.
dashBoundary
)
:
]
return
onlyHorizontalWhitespace
(
line
[
len
(
mr
.
dashBoundary
)
:
len
(
line
)
-
len
(
mr
.
nl
)])
rest
=
skipLWSPChar
(
rest
)
// On the first part, see our lines are ending in \n instead of \r\n
// and switch into that mode if so. This is a violation of the spec,
// but occurs in practice.
if
mr
.
partsRead
==
0
&&
len
(
rest
)
==
1
&&
rest
[
0
]
==
'\n'
{
mr
.
nl
=
mr
.
nl
[
1
:
]
mr
.
nlDashBoundary
=
mr
.
nlDashBoundary
[
1
:
]
}
}
// Violate the spec and also support newlines without the
return
bytes
.
Equal
(
rest
,
mr
.
nl
)
// carriage return...
if
mr
.
partsRead
==
0
&&
bytes
.
HasSuffix
(
line
,
lf
)
{
if
onlyHorizontalWhitespace
(
line
[
len
(
mr
.
dashBoundary
)
:
len
(
line
)
-
1
])
{
mr
.
nl
=
mr
.
nl
[
1
:
]
mr
.
nlDashBoundary
=
mr
.
nlDashBoundary
[
1
:
]
return
true
}
}
return
false
}
}
func
onlyHorizontalWhitespace
(
s
[]
byte
)
bool
{
// peekBufferIsEmptyPart returns whether the provided peek-ahead
for
_
,
b
:=
range
s
{
// buffer represents an empty part. This is only called if we've not
if
b
!=
' '
&&
b
!=
'\t'
{
// already read any bytes in this part and checks for the case of MIME
return
false
// software not writing the \r\n on empty parts. Some does, some
}
// doesn't.
//
// This checks that what follows the "--boundary" is actually the end
// ("--boundary--" with optional whitespace) or optional whitespace
// and then a newline, so we don't catch "--boundaryFAKE", in which
// case the whole line is part of the data.
func
(
mr
*
Reader
)
peekBufferIsEmptyPart
(
peek
[]
byte
)
bool
{
// End of parts case.
// Test whether peek matches `^--boundary--[ \t]*(?:\r\n|$)`
if
bytes
.
HasPrefix
(
peek
,
mr
.
dashBoundaryDash
)
{
rest
:=
peek
[
len
(
mr
.
dashBoundaryDash
)
:
]
rest
=
skipLWSPChar
(
rest
)
return
bytes
.
HasPrefix
(
rest
,
mr
.
nl
)
||
len
(
rest
)
==
0
}
}
return
true
if
!
bytes
.
HasPrefix
(
peek
,
mr
.
dashBoundary
)
{
return
false
}
// Test whether rest matches `^[ \t]*\r\n`)
rest
:=
peek
[
len
(
mr
.
dashBoundary
)
:
]
rest
=
skipLWSPChar
(
rest
)
return
bytes
.
HasPrefix
(
rest
,
mr
.
nl
)
}
}
func
hasPrefixThenNewline
(
s
,
prefix
[]
byte
)
bool
{
// skipLWSPChar returns b with leading spaces and tabs removed.
return
bytes
.
HasPrefix
(
s
,
prefix
)
&&
// RFC 822 defines:
(
len
(
s
)
==
len
(
prefix
)
+
1
&&
s
[
len
(
s
)
-
1
]
==
'\n'
||
// LWSP-char = SPACE / HTAB
len
(
s
)
==
len
(
prefix
)
+
2
&&
bytes
.
HasSuffix
(
s
,
crlf
))
func
skipLWSPChar
(
b
[]
byte
)
[]
byte
{
for
len
(
b
)
>
0
&&
(
b
[
0
]
==
' '
||
b
[
0
]
==
'\t'
)
{
b
=
b
[
1
:
]
}
return
b
}
}
libgo/go/mime/multipart/multipart_test.go
View file @
08a680a8
...
@@ -10,20 +10,13 @@ import (
...
@@ -10,20 +10,13 @@ import (
"fmt"
"fmt"
"io"
"io"
"io/ioutil"
"io/ioutil"
"net/textproto"
"os"
"os"
"reflect"
"strings"
"strings"
"testing"
"testing"
)
)
func
TestHorizontalWhitespace
(
t
*
testing
.
T
)
{
if
!
onlyHorizontalWhitespace
([]
byte
(
"
\t
"
))
{
t
.
Error
(
"expected pass"
)
}
if
onlyHorizontalWhitespace
([]
byte
(
"foo bar"
))
{
t
.
Error
(
"expected failure"
)
}
}
func
TestBoundaryLine
(
t
*
testing
.
T
)
{
func
TestBoundaryLine
(
t
*
testing
.
T
)
{
mr
:=
NewReader
(
strings
.
NewReader
(
""
),
"myBoundary"
)
mr
:=
NewReader
(
strings
.
NewReader
(
""
),
"myBoundary"
)
if
!
mr
.
isBoundaryDelimiterLine
([]
byte
(
"--myBoundary
\r\n
"
))
{
if
!
mr
.
isBoundaryDelimiterLine
([]
byte
(
"--myBoundary
\r\n
"
))
{
...
@@ -319,29 +312,6 @@ Oh no, premature EOF!
...
@@ -319,29 +312,6 @@ Oh no, premature EOF!
}
}
}
}
func
TestZeroLengthBody
(
t
*
testing
.
T
)
{
testBody
:=
strings
.
Replace
(
`
This is a multi-part message. This line is ignored.
--MyBoundary
foo: bar
--MyBoundary--
`
,
"
\n
"
,
"
\r\n
"
,
-
1
)
r
:=
NewReader
(
strings
.
NewReader
(
testBody
),
"MyBoundary"
)
part
,
err
:=
r
.
NextPart
()
if
err
!=
nil
{
t
.
Fatalf
(
"didn't get a part"
)
}
n
,
err
:=
io
.
Copy
(
ioutil
.
Discard
,
part
)
if
err
!=
nil
{
t
.
Errorf
(
"error reading part: %v"
,
err
)
}
if
n
!=
0
{
t
.
Errorf
(
"read %d bytes; expected 0"
,
n
)
}
}
type
slowReader
struct
{
type
slowReader
struct
{
r
io
.
Reader
r
io
.
Reader
}
}
...
@@ -427,3 +397,214 @@ func TestNested(t *testing.T) {
...
@@ -427,3 +397,214 @@ func TestNested(t *testing.T) {
t
.
Fatalf
(
"final outer NextPart = %v; want io.EOF"
,
err
)
t
.
Fatalf
(
"final outer NextPart = %v; want io.EOF"
,
err
)
}
}
}
}
type
headerBody
struct
{
header
textproto
.
MIMEHeader
body
string
}
func
formData
(
key
,
value
string
)
headerBody
{
return
headerBody
{
textproto
.
MIMEHeader
{
"Content-Type"
:
{
"text/plain; charset=ISO-8859-1"
},
"Content-Disposition"
:
{
"form-data; name="
+
key
},
},
value
,
}
}
type
parseTest
struct
{
name
string
in
,
sep
string
want
[]
headerBody
}
var
parseTests
=
[]
parseTest
{
// Actual body from App Engine on a blob upload. The final part (the
// Content-Type: message/external-body) is what App Engine replaces
// the uploaded file with. The other form fields (prefixed with
// "other" in their form-data name) are unchanged. A bug was
// reported with blob uploads failing when the other fields were
// empty. This was the MIME POST body that previously failed.
{
name
:
"App Engine post"
,
sep
:
"00151757727e9583fd04bfbca4c6"
,
in
:
"--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=otherEmpty1
\r\n\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=otherFoo1
\r\n\r\n
foo
\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=otherFoo2
\r\n\r\n
foo
\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=otherEmpty2
\r\n\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=otherRepeatFoo
\r\n\r\n
foo
\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=otherRepeatFoo
\r\n\r\n
foo
\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=otherRepeatEmpty
\r\n\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=otherRepeatEmpty
\r\n\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: text/plain; charset=ISO-8859-1
\r\n
Content-Disposition: form-data; name=submit
\r\n\r\n
Submit
\r\n
--00151757727e9583fd04bfbca4c6
\r\n
Content-Type: message/external-body; charset=ISO-8859-1; blob-key=AHAZQqG84qllx7HUqO_oou5EvdYQNS3Mbbkb0RjjBoM_Kc1UqEN2ygDxWiyCPulIhpHRPx-VbpB6RX4MrsqhWAi_ZxJ48O9P2cTIACbvATHvg7IgbvZytyGMpL7xO1tlIvgwcM47JNfv_tGhy1XwyEUO8oldjPqg5Q
\r\n
Content-Disposition: form-data; name=file; filename=
\"
fall.png
\"\r\n\r\n
Content-Type: image/png
\r\n
Content-Length: 232303
\r\n
X-AppEngine-Upload-Creation: 2012-05-10 23:14:02.715173
\r\n
Content-MD5: MzRjODU1ZDZhZGU1NmRlOWEwZmMwMDdlODBmZTA0NzA=
\r\n
Content-Disposition: form-data; name=file; filename=
\"
fall.png
\"\r\n\r\n\r\n
--00151757727e9583fd04bfbca4c6--"
,
want
:
[]
headerBody
{
formData
(
"otherEmpty1"
,
""
),
formData
(
"otherFoo1"
,
"foo"
),
formData
(
"otherFoo2"
,
"foo"
),
formData
(
"otherEmpty2"
,
""
),
formData
(
"otherRepeatFoo"
,
"foo"
),
formData
(
"otherRepeatFoo"
,
"foo"
),
formData
(
"otherRepeatEmpty"
,
""
),
formData
(
"otherRepeatEmpty"
,
""
),
formData
(
"submit"
,
"Submit"
),
{
textproto
.
MIMEHeader
{
"Content-Type"
:
{
"message/external-body; charset=ISO-8859-1; blob-key=AHAZQqG84qllx7HUqO_oou5EvdYQNS3Mbbkb0RjjBoM_Kc1UqEN2ygDxWiyCPulIhpHRPx-VbpB6RX4MrsqhWAi_ZxJ48O9P2cTIACbvATHvg7IgbvZytyGMpL7xO1tlIvgwcM47JNfv_tGhy1XwyEUO8oldjPqg5Q"
},
"Content-Disposition"
:
{
"form-data; name=file; filename=
\"
fall.png
\"
"
},
},
"Content-Type: image/png
\r\n
Content-Length: 232303
\r\n
X-AppEngine-Upload-Creation: 2012-05-10 23:14:02.715173
\r\n
Content-MD5: MzRjODU1ZDZhZGU1NmRlOWEwZmMwMDdlODBmZTA0NzA=
\r\n
Content-Disposition: form-data; name=file; filename=
\"
fall.png
\"\r\n\r\n
"
},
},
},
// Single empty part, ended with --boundary immediately after headers.
{
name
:
"single empty part, --boundary"
,
sep
:
"abc"
,
in
:
"--abc
\r\n
Foo: bar
\r\n\r\n
--abc--"
,
want
:
[]
headerBody
{
{
textproto
.
MIMEHeader
{
"Foo"
:
{
"bar"
}},
""
},
},
},
// Single empty part, ended with \r\n--boundary immediately after headers.
{
name
:
"single empty part,
\r\n
--boundary"
,
sep
:
"abc"
,
in
:
"--abc
\r\n
Foo: bar
\r\n\r\n\r\n
--abc--"
,
want
:
[]
headerBody
{
{
textproto
.
MIMEHeader
{
"Foo"
:
{
"bar"
}},
""
},
},
},
// Final part empty.
{
name
:
"final part empty"
,
sep
:
"abc"
,
in
:
"--abc
\r\n
Foo: bar
\r\n\r\n
--abc
\r\n
Foo2: bar2
\r\n\r\n
--abc--"
,
want
:
[]
headerBody
{
{
textproto
.
MIMEHeader
{
"Foo"
:
{
"bar"
}},
""
},
{
textproto
.
MIMEHeader
{
"Foo2"
:
{
"bar2"
}},
""
},
},
},
// Final part empty with newlines after final separator.
{
name
:
"final part empty then crlf"
,
sep
:
"abc"
,
in
:
"--abc
\r\n
Foo: bar
\r\n\r\n
--abc--
\r\n
"
,
want
:
[]
headerBody
{
{
textproto
.
MIMEHeader
{
"Foo"
:
{
"bar"
}},
""
},
},
},
// Final part empty with lwsp-chars after final separator.
{
name
:
"final part empty then lwsp"
,
sep
:
"abc"
,
in
:
"--abc
\r\n
Foo: bar
\r\n\r\n
--abc--
\t
"
,
want
:
[]
headerBody
{
{
textproto
.
MIMEHeader
{
"Foo"
:
{
"bar"
}},
""
},
},
},
// No parts (empty form as submitted by Chrome)
{
name
:
"no parts"
,
sep
:
"----WebKitFormBoundaryQfEAfzFOiSemeHfA"
,
in
:
"------WebKitFormBoundaryQfEAfzFOiSemeHfA--
\r\n
"
,
want
:
[]
headerBody
{},
},
// Part containing data starting with the boundary, but with additional suffix.
{
name
:
"fake separator as data"
,
sep
:
"sep"
,
in
:
"--sep
\r\n
Foo: bar
\r\n\r\n
--sepFAKE
\r\n
--sep--"
,
want
:
[]
headerBody
{
{
textproto
.
MIMEHeader
{
"Foo"
:
{
"bar"
}},
"--sepFAKE"
},
},
},
// Part containing a boundary with whitespace following it.
{
name
:
"boundary with whitespace"
,
sep
:
"sep"
,
in
:
"--sep
\r\n
Foo: bar
\r\n\r\n
text
\r\n
--sep--"
,
want
:
[]
headerBody
{
{
textproto
.
MIMEHeader
{
"Foo"
:
{
"bar"
}},
"text"
},
},
},
// With ignored leading line.
{
name
:
"leading line"
,
sep
:
"MyBoundary"
,
in
:
strings
.
Replace
(
`This is a multi-part message. This line is ignored.
--MyBoundary
foo: bar
--MyBoundary--`
,
"
\n
"
,
"
\r\n
"
,
-
1
),
want
:
[]
headerBody
{
{
textproto
.
MIMEHeader
{
"Foo"
:
{
"bar"
}},
""
},
},
},
roundTripParseTest
(),
}
func
TestParse
(
t
*
testing
.
T
)
{
Cases
:
for
_
,
tt
:=
range
parseTests
{
r
:=
NewReader
(
strings
.
NewReader
(
tt
.
in
),
tt
.
sep
)
got
:=
[]
headerBody
{}
for
{
p
,
err
:=
r
.
NextPart
()
if
err
==
io
.
EOF
{
break
}
if
err
!=
nil
{
t
.
Errorf
(
"in test %q, NextPart: %v"
,
tt
.
name
,
err
)
continue
Cases
}
pbody
,
err
:=
ioutil
.
ReadAll
(
p
)
if
err
!=
nil
{
t
.
Errorf
(
"in test %q, error reading part: %v"
,
tt
.
name
,
err
)
continue
Cases
}
got
=
append
(
got
,
headerBody
{
p
.
Header
,
string
(
pbody
)})
}
if
!
reflect
.
DeepEqual
(
tt
.
want
,
got
)
{
t
.
Errorf
(
"test %q:
\n
got: %v
\n
want: %v"
,
tt
.
name
,
got
,
tt
.
want
)
if
len
(
tt
.
want
)
!=
len
(
got
)
{
t
.
Errorf
(
"test %q: got %d parts, want %d"
,
tt
.
name
,
len
(
got
),
len
(
tt
.
want
))
}
else
if
len
(
got
)
>
1
{
for
pi
,
wantPart
:=
range
tt
.
want
{
if
!
reflect
.
DeepEqual
(
wantPart
,
got
[
pi
])
{
t
.
Errorf
(
"test %q, part %d:
\n
got: %v
\n
want: %v"
,
tt
.
name
,
pi
,
got
[
pi
],
wantPart
)
}
}
}
}
}
}
func
roundTripParseTest
()
parseTest
{
t
:=
parseTest
{
name
:
"round trip"
,
want
:
[]
headerBody
{
formData
(
"empty"
,
""
),
formData
(
"lf"
,
"
\n
"
),
formData
(
"cr"
,
"
\r
"
),
formData
(
"crlf"
,
"
\r\n
"
),
formData
(
"foo"
,
"bar"
),
},
}
var
buf
bytes
.
Buffer
w
:=
NewWriter
(
&
buf
)
for
_
,
p
:=
range
t
.
want
{
pw
,
err
:=
w
.
CreatePart
(
p
.
header
)
if
err
!=
nil
{
panic
(
err
)
}
_
,
err
=
pw
.
Write
([]
byte
(
p
.
body
))
if
err
!=
nil
{
panic
(
err
)
}
}
w
.
Close
()
t
.
in
=
buf
.
String
()
t
.
sep
=
w
.
Boundary
()
return
t
}
libgo/go/net/file.go
View file @
08a680a8
...
@@ -89,8 +89,8 @@ func FileConn(f *os.File) (c Conn, err error) {
...
@@ -89,8 +89,8 @@ func FileConn(f *os.File) (c Conn, err error) {
// FileListener returns a copy of the network listener corresponding
// FileListener returns a copy of the network listener corresponding
// to the open file f. It is the caller's responsibility to close l
// to the open file f. It is the caller's responsibility to close l
// when finished. Closing
c does not affect l, and closing l
does not
// when finished. Closing
l does not affect f, and closing f
does not
// affect
c
.
// affect
l
.
func
FileListener
(
f
*
os
.
File
)
(
l
Listener
,
err
error
)
{
func
FileListener
(
f
*
os
.
File
)
(
l
Listener
,
err
error
)
{
fd
,
err
:=
newFileFD
(
f
)
fd
,
err
:=
newFileFD
(
f
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
libgo/go/net/http/client.go
View file @
08a680a8
...
@@ -278,6 +278,11 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response,
...
@@ -278,6 +278,11 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response,
return
nil
,
err
return
nil
,
err
}
}
req
.
Header
.
Set
(
"Content-Type"
,
bodyType
)
req
.
Header
.
Set
(
"Content-Type"
,
bodyType
)
if
c
.
Jar
!=
nil
{
for
_
,
cookie
:=
range
c
.
Jar
.
Cookies
(
req
.
URL
)
{
req
.
AddCookie
(
cookie
)
}
}
r
,
err
=
send
(
req
,
c
.
Transport
)
r
,
err
=
send
(
req
,
c
.
Transport
)
if
err
==
nil
&&
c
.
Jar
!=
nil
{
if
err
==
nil
&&
c
.
Jar
!=
nil
{
c
.
Jar
.
SetCookies
(
req
.
URL
,
r
.
Cookies
())
c
.
Jar
.
SetCookies
(
req
.
URL
,
r
.
Cookies
())
...
...
libgo/go/net/http/client_test.go
View file @
08a680a8
...
@@ -256,6 +256,31 @@ var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request)
...
@@ -256,6 +256,31 @@ var echoCookiesRedirectHandler = HandlerFunc(func(w ResponseWriter, r *Request)
}
}
})
})
func
TestClientSendsCookieFromJar
(
t
*
testing
.
T
)
{
tr
:=
&
recordingTransport
{}
client
:=
&
Client
{
Transport
:
tr
}
client
.
Jar
=
&
TestJar
{
perURL
:
make
(
map
[
string
][]
*
Cookie
)}
us
:=
"http://dummy.faketld/"
u
,
_
:=
url
.
Parse
(
us
)
client
.
Jar
.
SetCookies
(
u
,
expectedCookies
)
client
.
Get
(
us
)
// Note: doesn't hit network
matchReturnedCookies
(
t
,
expectedCookies
,
tr
.
req
.
Cookies
())
client
.
Head
(
us
)
// Note: doesn't hit network
matchReturnedCookies
(
t
,
expectedCookies
,
tr
.
req
.
Cookies
())
client
.
Post
(
us
,
"text/plain"
,
strings
.
NewReader
(
"body"
))
// Note: doesn't hit network
matchReturnedCookies
(
t
,
expectedCookies
,
tr
.
req
.
Cookies
())
client
.
PostForm
(
us
,
url
.
Values
{})
// Note: doesn't hit network
matchReturnedCookies
(
t
,
expectedCookies
,
tr
.
req
.
Cookies
())
req
,
_
:=
NewRequest
(
"GET"
,
us
,
nil
)
client
.
Do
(
req
)
// Note: doesn't hit network
matchReturnedCookies
(
t
,
expectedCookies
,
tr
.
req
.
Cookies
())
}
// Just enough correctness for our redirect tests. Uses the URL.Host as the
// Just enough correctness for our redirect tests. Uses the URL.Host as the
// scope of all cookies.
// scope of all cookies.
type
TestJar
struct
{
type
TestJar
struct
{
...
...
libgo/go/net/http/proxy_test.go
View file @
08a680a8
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
package
http
package
http
import
(
import
(
"net/url"
"os"
"os"
"testing"
"testing"
)
)
...
@@ -46,3 +47,32 @@ func TestUseProxy(t *testing.T) {
...
@@ -46,3 +47,32 @@ func TestUseProxy(t *testing.T) {
}
}
}
}
}
}
var
cacheKeysTests
=
[]
struct
{
proxy
string
scheme
string
addr
string
key
string
}{
{
""
,
"http"
,
"foo.com"
,
"|http|foo.com"
},
{
""
,
"https"
,
"foo.com"
,
"|https|foo.com"
},
{
"http://foo.com"
,
"http"
,
"foo.com"
,
"http://foo.com|http|"
},
{
"http://foo.com"
,
"https"
,
"foo.com"
,
"http://foo.com|https|foo.com"
},
}
func
TestCacheKeys
(
t
*
testing
.
T
)
{
for
_
,
tt
:=
range
cacheKeysTests
{
var
proxy
*
url
.
URL
if
tt
.
proxy
!=
""
{
u
,
err
:=
url
.
Parse
(
tt
.
proxy
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
proxy
=
u
}
cm
:=
connectMethod
{
proxy
,
tt
.
scheme
,
tt
.
addr
}
if
cm
.
String
()
!=
tt
.
key
{
t
.
Fatalf
(
"{%q, %q, %q} cache key %q; want %q"
,
tt
.
proxy
,
tt
.
scheme
,
tt
.
addr
,
cm
.
String
(),
tt
.
key
)
}
}
}
libgo/go/net/http/response.go
View file @
08a680a8
...
@@ -202,9 +202,12 @@ func (r *Response) Write(w io.Writer) error {
...
@@ -202,9 +202,12 @@ func (r *Response) Write(w io.Writer) error {
text
=
"status code "
+
strconv
.
Itoa
(
r
.
StatusCode
)
text
=
"status code "
+
strconv
.
Itoa
(
r
.
StatusCode
)
}
}
}
}
io
.
WriteString
(
w
,
"HTTP/"
+
strconv
.
Itoa
(
r
.
ProtoMajor
)
+
"."
)
protoMajor
,
protoMinor
:=
strconv
.
Itoa
(
r
.
ProtoMajor
),
strconv
.
Itoa
(
r
.
ProtoMinor
)
io
.
WriteString
(
w
,
strconv
.
Itoa
(
r
.
ProtoMinor
)
+
" "
)
statusCode
:=
strconv
.
Itoa
(
r
.
StatusCode
)
+
" "
io
.
WriteString
(
w
,
strconv
.
Itoa
(
r
.
StatusCode
)
+
" "
+
text
+
"
\r\n
"
)
if
strings
.
HasPrefix
(
text
,
statusCode
)
{
text
=
text
[
len
(
statusCode
)
:
]
}
io
.
WriteString
(
w
,
"HTTP/"
+
protoMajor
+
"."
+
protoMinor
+
" "
+
statusCode
+
text
+
"
\r\n
"
)
// Process Body,ContentLength,Close,Trailer
// Process Body,ContentLength,Close,Trailer
tw
,
err
:=
newTransferWriter
(
r
)
tw
,
err
:=
newTransferWriter
(
r
)
...
...
libgo/go/net/http/response_test.go
View file @
08a680a8
...
@@ -14,6 +14,7 @@ import (
...
@@ -14,6 +14,7 @@ import (
"io/ioutil"
"io/ioutil"
"net/url"
"net/url"
"reflect"
"reflect"
"strings"
"testing"
"testing"
)
)
...
@@ -444,3 +445,17 @@ func TestLocationResponse(t *testing.T) {
...
@@ -444,3 +445,17 @@ func TestLocationResponse(t *testing.T) {
}
}
}
}
}
}
func
TestResponseStatusStutter
(
t
*
testing
.
T
)
{
r
:=
&
Response
{
Status
:
"123 some status"
,
StatusCode
:
123
,
ProtoMajor
:
1
,
ProtoMinor
:
3
,
}
var
buf
bytes
.
Buffer
r
.
Write
(
&
buf
)
if
strings
.
Contains
(
buf
.
String
(),
"123 123"
)
{
t
.
Errorf
(
"stutter in status: %s"
,
buf
.
String
())
}
}
libgo/go/net/http/server.go
View file @
08a680a8
...
@@ -31,7 +31,7 @@ import (
...
@@ -31,7 +31,7 @@ import (
// Errors introduced by the HTTP server.
// Errors introduced by the HTTP server.
var
(
var
(
ErrWriteAfterFlush
=
errors
.
New
(
"Conn.Write called after Flush"
)
ErrWriteAfterFlush
=
errors
.
New
(
"Conn.Write called after Flush"
)
ErrBodyNotAllowed
=
errors
.
New
(
"http: response status code does not allow body"
)
ErrBodyNotAllowed
=
errors
.
New
(
"http: re
quest method or re
sponse status code does not allow body"
)
ErrHijacked
=
errors
.
New
(
"Conn has been hijacked"
)
ErrHijacked
=
errors
.
New
(
"Conn has been hijacked"
)
ErrContentLength
=
errors
.
New
(
"Conn.Write wrote more than the declared Content-Length"
)
ErrContentLength
=
errors
.
New
(
"Conn.Write wrote more than the declared Content-Length"
)
)
)
...
...
libgo/go/net/http/transfer.go
View file @
08a680a8
...
@@ -71,7 +71,9 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
...
@@ -71,7 +71,9 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
}
}
}
}
case
*
Response
:
case
*
Response
:
t
.
Method
=
rr
.
Request
.
Method
if
rr
.
Request
!=
nil
{
t
.
Method
=
rr
.
Request
.
Method
}
t
.
Body
=
rr
.
Body
t
.
Body
=
rr
.
Body
t
.
BodyCloser
=
rr
.
Body
t
.
BodyCloser
=
rr
.
Body
t
.
ContentLength
=
rr
.
ContentLength
t
.
ContentLength
=
rr
.
ContentLength
...
@@ -79,7 +81,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
...
@@ -79,7 +81,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
t
.
TransferEncoding
=
rr
.
TransferEncoding
t
.
TransferEncoding
=
rr
.
TransferEncoding
t
.
Trailer
=
rr
.
Trailer
t
.
Trailer
=
rr
.
Trailer
atLeastHTTP11
=
rr
.
ProtoAtLeast
(
1
,
1
)
atLeastHTTP11
=
rr
.
ProtoAtLeast
(
1
,
1
)
t
.
ResponseToHEAD
=
noBodyExpected
(
rr
.
Reques
t
.
Method
)
t
.
ResponseToHEAD
=
noBodyExpected
(
t
.
Method
)
}
}
// Sanitize Body,ContentLength,TransferEncoding
// Sanitize Body,ContentLength,TransferEncoding
...
...
libgo/go/net/http/transport.go
View file @
08a680a8
...
@@ -450,10 +450,14 @@ type connectMethod struct {
...
@@ -450,10 +450,14 @@ type connectMethod struct {
func
(
ck
*
connectMethod
)
String
()
string
{
func
(
ck
*
connectMethod
)
String
()
string
{
proxyStr
:=
""
proxyStr
:=
""
targetAddr
:=
ck
.
targetAddr
if
ck
.
proxyURL
!=
nil
{
if
ck
.
proxyURL
!=
nil
{
proxyStr
=
ck
.
proxyURL
.
String
()
proxyStr
=
ck
.
proxyURL
.
String
()
if
ck
.
targetScheme
==
"http"
{
targetAddr
=
""
}
}
}
return
strings
.
Join
([]
string
{
proxyStr
,
ck
.
targetScheme
,
ck
.
targetAddr
},
"|"
)
return
strings
.
Join
([]
string
{
proxyStr
,
ck
.
targetScheme
,
targetAddr
},
"|"
)
}
}
// addr returns the first hop "host:port" to which we need to TCP connect.
// addr returns the first hop "host:port" to which we need to TCP connect.
...
...
libgo/go/net/mail/message.go
View file @
08a680a8
...
@@ -69,11 +69,12 @@ var dateLayouts []string
...
@@ -69,11 +69,12 @@ var dateLayouts []string
func
init
()
{
func
init
()
{
// Generate layouts based on RFC 5322, section 3.3.
// Generate layouts based on RFC 5322, section 3.3.
dows
:=
[
...
]
string
{
""
,
"Mon, "
}
// day-of-week
dows
:=
[
...
]
string
{
""
,
"Mon, "
}
// day-of-week
days
:=
[
...
]
string
{
"2"
,
"02"
}
// day = 1*2DIGIT
days
:=
[
...
]
string
{
"2"
,
"02"
}
// day = 1*2DIGIT
years
:=
[
...
]
string
{
"2006"
,
"06"
}
// year = 4*DIGIT / 2*DIGIT
years
:=
[
...
]
string
{
"2006"
,
"06"
}
// year = 4*DIGIT / 2*DIGIT
seconds
:=
[
...
]
string
{
":05"
,
""
}
// second
seconds
:=
[
...
]
string
{
":05"
,
""
}
// second
zones
:=
[
...
]
string
{
"-0700"
,
"MST"
}
// zone = (("+" / "-") 4DIGIT) / "GMT" / ...
// "-0700 (MST)" is not in RFC 5322, but is common.
zones
:=
[
...
]
string
{
"-0700"
,
"MST"
,
"-0700 (MST)"
}
// zone = (("+" / "-") 4DIGIT) / "GMT" / ...
for
_
,
dow
:=
range
dows
{
for
_
,
dow
:=
range
dows
{
for
_
,
day
:=
range
days
{
for
_
,
day
:=
range
days
{
...
...
libgo/go/net/mail/message_test.go
View file @
08a680a8
...
@@ -95,6 +95,11 @@ func TestDateParsing(t *testing.T) {
...
@@ -95,6 +95,11 @@ func TestDateParsing(t *testing.T) {
"21 Nov 97 09:55:06 GMT"
,
"21 Nov 97 09:55:06 GMT"
,
time
.
Date
(
1997
,
11
,
21
,
9
,
55
,
6
,
0
,
time
.
FixedZone
(
"GMT"
,
0
)),
time
.
Date
(
1997
,
11
,
21
,
9
,
55
,
6
,
0
,
time
.
FixedZone
(
"GMT"
,
0
)),
},
},
// Commonly found format not specified by RFC 5322.
{
"Fri, 21 Nov 1997 09:55:06 -0600 (MDT)"
,
time
.
Date
(
1997
,
11
,
21
,
9
,
55
,
6
,
0
,
time
.
FixedZone
(
""
,
-
6
*
60
*
60
)),
},
}
}
for
_
,
test
:=
range
tests
{
for
_
,
test
:=
range
tests
{
hdr
:=
Header
{
hdr
:=
Header
{
...
...
libgo/go/net/url/url.go
View file @
08a680a8
...
@@ -401,11 +401,12 @@ Error:
...
@@ -401,11 +401,12 @@ Error:
}
}
func
parseAuthority
(
authority
string
)
(
user
*
Userinfo
,
host
string
,
err
error
)
{
func
parseAuthority
(
authority
string
)
(
user
*
Userinfo
,
host
string
,
err
error
)
{
if
strings
.
Index
(
authority
,
"@"
)
<
0
{
i
:=
strings
.
LastIndex
(
authority
,
"@"
)
if
i
<
0
{
host
=
authority
host
=
authority
return
return
}
}
userinfo
,
host
:=
split
(
authority
,
'@'
,
true
)
userinfo
,
host
:=
authority
[
:
i
],
authority
[
i
+
1
:
]
if
strings
.
Index
(
userinfo
,
":"
)
<
0
{
if
strings
.
Index
(
userinfo
,
":"
)
<
0
{
if
userinfo
,
err
=
unescape
(
userinfo
,
encodeUserPassword
);
err
!=
nil
{
if
userinfo
,
err
=
unescape
(
userinfo
,
encodeUserPassword
);
err
!=
nil
{
return
return
...
...
libgo/go/net/url/url_test.go
View file @
08a680a8
...
@@ -188,6 +188,37 @@ var urltests = []URLTest{
...
@@ -188,6 +188,37 @@ var urltests = []URLTest{
},
},
"http://user:password@google.com"
,
"http://user:password@google.com"
,
},
},
// unescaped @ in username should not confuse host
{
"http://j@ne:password@google.com"
,
&
URL
{
Scheme
:
"http"
,
User
:
UserPassword
(
"j@ne"
,
"password"
),
Host
:
"google.com"
,
},
"http://j%40ne:password@google.com"
,
},
// unescaped @ in password should not confuse host
{
"http://jane:p@ssword@google.com"
,
&
URL
{
Scheme
:
"http"
,
User
:
UserPassword
(
"jane"
,
"p@ssword"
),
Host
:
"google.com"
,
},
"http://jane:p%40ssword@google.com"
,
},
{
"http://j@ne:password@google.com/p@th?q=@go"
,
&
URL
{
Scheme
:
"http"
,
User
:
UserPassword
(
"j@ne"
,
"password"
),
Host
:
"google.com"
,
Path
:
"/p@th"
,
RawQuery
:
"q=@go"
,
},
"http://j%40ne:password@google.com/p@th?q=@go"
,
},
{
{
"http://www.google.com/?q=go+language#foo"
,
"http://www.google.com/?q=go+language#foo"
,
&
URL
{
&
URL
{
...
...
libgo/go/os/exec/exec.go
View file @
08a680a8
...
@@ -204,6 +204,12 @@ func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) {
...
@@ -204,6 +204,12 @@ func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) {
return
pw
,
nil
return
pw
,
nil
}
}
func
(
c
*
Cmd
)
closeDescriptors
(
closers
[]
io
.
Closer
)
{
for
_
,
fd
:=
range
closers
{
fd
.
Close
()
}
}
// Run starts the specified command and waits for it to complete.
// Run starts the specified command and waits for it to complete.
//
//
// The returned error is nil if the command runs, has no problems
// The returned error is nil if the command runs, has no problems
...
@@ -233,6 +239,8 @@ func (c *Cmd) Start() error {
...
@@ -233,6 +239,8 @@ func (c *Cmd) Start() error {
for
_
,
setupFd
:=
range
[]
F
{(
*
Cmd
)
.
stdin
,
(
*
Cmd
)
.
stdout
,
(
*
Cmd
)
.
stderr
}
{
for
_
,
setupFd
:=
range
[]
F
{(
*
Cmd
)
.
stdin
,
(
*
Cmd
)
.
stdout
,
(
*
Cmd
)
.
stderr
}
{
fd
,
err
:=
setupFd
(
c
)
fd
,
err
:=
setupFd
(
c
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
closeDescriptors
(
c
.
closeAfterStart
)
c
.
closeDescriptors
(
c
.
closeAfterWait
)
return
err
return
err
}
}
c
.
childFiles
=
append
(
c
.
childFiles
,
fd
)
c
.
childFiles
=
append
(
c
.
childFiles
,
fd
)
...
@@ -247,12 +255,12 @@ func (c *Cmd) Start() error {
...
@@ -247,12 +255,12 @@ func (c *Cmd) Start() error {
Sys
:
c
.
SysProcAttr
,
Sys
:
c
.
SysProcAttr
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
c
.
closeDescriptors
(
c
.
closeAfterStart
)
c
.
closeDescriptors
(
c
.
closeAfterWait
)
return
err
return
err
}
}
for
_
,
fd
:=
range
c
.
closeAfterStart
{
c
.
closeDescriptors
(
c
.
closeAfterStart
)
fd
.
Close
()
}
c
.
errch
=
make
(
chan
error
,
len
(
c
.
goroutine
))
c
.
errch
=
make
(
chan
error
,
len
(
c
.
goroutine
))
for
_
,
fn
:=
range
c
.
goroutine
{
for
_
,
fn
:=
range
c
.
goroutine
{
...
@@ -301,9 +309,7 @@ func (c *Cmd) Wait() error {
...
@@ -301,9 +309,7 @@ func (c *Cmd) Wait() error {
}
}
}
}
for
_
,
fd
:=
range
c
.
closeAfterWait
{
c
.
closeDescriptors
(
c
.
closeAfterWait
)
fd
.
Close
()
}
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
...
...
libgo/go/path/filepath/path.go
View file @
08a680a8
...
@@ -320,8 +320,11 @@ func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
...
@@ -320,8 +320,11 @@ func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
}
}
for
_
,
fileInfo
:=
range
list
{
for
_
,
fileInfo
:=
range
list
{
if
err
=
walk
(
Join
(
path
,
fileInfo
.
Name
()),
fileInfo
,
walkFn
);
err
!=
nil
{
err
=
walk
(
Join
(
path
,
fileInfo
.
Name
()),
fileInfo
,
walkFn
)
return
err
if
err
!=
nil
{
if
!
fileInfo
.
IsDir
()
||
err
!=
SkipDir
{
return
err
}
}
}
}
}
return
nil
return
nil
...
...
libgo/go/path/filepath/path_plan9.go
View file @
08a680a8
...
@@ -12,7 +12,7 @@ func IsAbs(path string) bool {
...
@@ -12,7 +12,7 @@ func IsAbs(path string) bool {
}
}
// VolumeName returns the leading volume name on Windows.
// VolumeName returns the leading volume name on Windows.
// It returns "" elsewhere
// It returns "" elsewhere
.
func
VolumeName
(
path
string
)
string
{
func
VolumeName
(
path
string
)
string
{
return
""
return
""
}
}
...
...
libgo/go/path/filepath/path_test.go
View file @
08a680a8
...
@@ -869,3 +869,34 @@ func TestDriveLetterInEvalSymlinks(t *testing.T) {
...
@@ -869,3 +869,34 @@ func TestDriveLetterInEvalSymlinks(t *testing.T) {
t
.
Errorf
(
"Results of EvalSymlinks do not match: %q and %q"
,
flp
,
fup
)
t
.
Errorf
(
"Results of EvalSymlinks do not match: %q and %q"
,
flp
,
fup
)
}
}
}
}
/* This test does not work gccgo, since the sources are arranged
differently.
func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486
root, err := filepath.EvalSymlinks(os.Getenv("GOROOT"))
if err != nil {
t.Fatal(err)
}
lib := filepath.Join(root, "lib")
src := filepath.Join(root, "src")
seenSrc := false
filepath.Walk(root, func(pth string, info os.FileInfo, err error) error {
if err != nil {
t.Fatal(err)
}
switch pth {
case lib:
return filepath.SkipDir
case src:
seenSrc = true
}
return nil
})
if !seenSrc {
t.Fatalf("%q not seen", src)
}
}
*/
libgo/go/regexp/regexp.go
View file @
08a680a8
...
@@ -512,7 +512,7 @@ func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst
...
@@ -512,7 +512,7 @@ func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst
}
}
// ReplaceAll returns a copy of src, replacing matches of the Regexp
// ReplaceAll returns a copy of src, replacing matches of the Regexp
// with the replacement
string
repl. Inside repl, $ signs are interpreted as
// with the replacement
text
repl. Inside repl, $ signs are interpreted as
// in Expand, so for instance $1 represents the text of the first submatch.
// in Expand, so for instance $1 represents the text of the first submatch.
func
(
re
*
Regexp
)
ReplaceAll
(
src
,
repl
[]
byte
)
[]
byte
{
func
(
re
*
Regexp
)
ReplaceAll
(
src
,
repl
[]
byte
)
[]
byte
{
n
:=
2
n
:=
2
...
@@ -726,7 +726,7 @@ func (re *Regexp) FindSubmatch(b []byte) [][]byte {
...
@@ -726,7 +726,7 @@ func (re *Regexp) FindSubmatch(b []byte) [][]byte {
// the submatch with the corresponding index; other names refer to
// the submatch with the corresponding index; other names refer to
// capturing parentheses named with the (?P<name>...) syntax. A
// capturing parentheses named with the (?P<name>...) syntax. A
// reference to an out of range or unmatched index or a name that is not
// reference to an out of range or unmatched index or a name that is not
// present in the regular expression is replaced with an empty s
tring
.
// present in the regular expression is replaced with an empty s
lice
.
//
//
// In the $name form, name is taken to be as long as possible: $1x is
// In the $name form, name is taken to be as long as possible: $1x is
// equivalent to ${1x}, not ${1}x, and, $10 is equivalent to ${10}, not ${1}0.
// equivalent to ${1x}, not ${1}x, and, $10 is equivalent to ${10}, not ${1}0.
...
...
libgo/go/regexp/syntax/parse.go
View file @
08a680a8
...
@@ -48,6 +48,9 @@ const (
...
@@ -48,6 +48,9 @@ const (
ErrTrailingBackslash
ErrorCode
=
"trailing backslash at end of expression"
ErrTrailingBackslash
ErrorCode
=
"trailing backslash at end of expression"
)
)
// TODO: Export for Go 1.1.
const
errUnexpectedParen
ErrorCode
=
"unexpected )"
func
(
e
ErrorCode
)
String
()
string
{
func
(
e
ErrorCode
)
String
()
string
{
return
string
(
e
)
return
string
(
e
)
}
}
...
@@ -1168,13 +1171,13 @@ func (p *parser) parseRightParen() error {
...
@@ -1168,13 +1171,13 @@ func (p *parser) parseRightParen() error {
n
:=
len
(
p
.
stack
)
n
:=
len
(
p
.
stack
)
if
n
<
2
{
if
n
<
2
{
return
&
Error
{
ErrInternalError
,
""
}
return
&
Error
{
errUnexpectedParen
,
p
.
wholeRegexp
}
}
}
re1
:=
p
.
stack
[
n
-
1
]
re1
:=
p
.
stack
[
n
-
1
]
re2
:=
p
.
stack
[
n
-
2
]
re2
:=
p
.
stack
[
n
-
2
]
p
.
stack
=
p
.
stack
[
:
n
-
2
]
p
.
stack
=
p
.
stack
[
:
n
-
2
]
if
re2
.
Op
!=
opLeftParen
{
if
re2
.
Op
!=
opLeftParen
{
return
&
Error
{
ErrMissing
Paren
,
p
.
wholeRegexp
}
return
&
Error
{
errUnexpected
Paren
,
p
.
wholeRegexp
}
}
}
// Restore flags at time of paren.
// Restore flags at time of paren.
p
.
flags
=
re2
.
Flags
p
.
flags
=
re2
.
Flags
...
...
libgo/go/regexp/syntax/parse_test.go
View file @
08a680a8
...
@@ -442,10 +442,18 @@ var invalidRegexps = []string{
...
@@ -442,10 +442,18 @@ var invalidRegexps = []string{
`(`
,
`(`
,
`)`
,
`)`
,
`(a`
,
`(a`
,
`a)`
,
`(a))`
,
`(a|b|`
,
`(a|b|`
,
`a|b|)`
,
`(a|b|))`
,
`(a|b`
,
`(a|b`
,
`a|b)`
,
`(a|b))`
,
`[a-z`
,
`[a-z`
,
`([a-z)`
,
`([a-z)`
,
`[a-z)`
,
`([a-z]))`
,
`x{1001}`
,
`x{1001}`
,
`x{9876543210}`
,
`x{9876543210}`
,
`x{2,1}`
,
`x{2,1}`
,
...
...
libgo/go/runtime/extern.go
View file @
08a680a8
...
@@ -20,7 +20,7 @@ func Goexit()
...
@@ -20,7 +20,7 @@ func Goexit()
// Caller reports file and line number information about function invocations on
// Caller reports file and line number information about function invocations on
// the calling goroutine's stack. The argument skip is the number of stack frames
// the calling goroutine's stack. The argument skip is the number of stack frames
// to ascend, with
1
identifying the caller of Caller. (For historical reasons the
// to ascend, with
0
identifying the caller of Caller. (For historical reasons the
// meaning of skip differs between Caller and Callers.) The return values report the
// meaning of skip differs between Caller and Callers.) The return values report the
// program counter, file name, and line number within the file of the corresponding
// program counter, file name, and line number within the file of the corresponding
// call. The boolean ok is false if it was not possible to recover the information.
// call. The boolean ok is false if it was not possible to recover the information.
...
@@ -28,7 +28,8 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool)
...
@@ -28,7 +28,8 @@ func Caller(skip int) (pc uintptr, file string, line int, ok bool)
// Callers fills the slice pc with the program counters of function invocations
// Callers fills the slice pc with the program counters of function invocations
// on the calling goroutine's stack. The argument skip is the number of stack frames
// on the calling goroutine's stack. The argument skip is the number of stack frames
// to skip before recording in pc, with 0 starting at the caller of Callers.
// to skip before recording in pc, with 0 identifying the frame for Callers itself and
// 1 identifying the caller of Callers.
// It returns the number of entries written to pc.
// It returns the number of entries written to pc.
func
Callers
(
skip
int
,
pc
[]
uintptr
)
int
func
Callers
(
skip
int
,
pc
[]
uintptr
)
int
...
...
libgo/go/strconv/itoa.go
View file @
08a680a8
...
@@ -4,13 +4,17 @@
...
@@ -4,13 +4,17 @@
package
strconv
package
strconv
// FormatUint returns the string representation of i in the given base.
// FormatUint returns the string representation of i in the given base,
// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
// for digit values >= 10.
func
FormatUint
(
i
uint64
,
base
int
)
string
{
func
FormatUint
(
i
uint64
,
base
int
)
string
{
_
,
s
:=
formatBits
(
nil
,
i
,
base
,
false
,
false
)
_
,
s
:=
formatBits
(
nil
,
i
,
base
,
false
,
false
)
return
s
return
s
}
}
// FormatInt returns the string representation of i in the given base.
// FormatInt returns the string representation of i in the given base,
// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
// for digit values >= 10.
func
FormatInt
(
i
int64
,
base
int
)
string
{
func
FormatInt
(
i
int64
,
base
int
)
string
{
_
,
s
:=
formatBits
(
nil
,
uint64
(
i
),
base
,
i
<
0
,
false
)
_
,
s
:=
formatBits
(
nil
,
uint64
(
i
),
base
,
i
<
0
,
false
)
return
s
return
s
...
...
libgo/go/strings/example_test.go
View file @
08a680a8
...
@@ -41,7 +41,6 @@ func ExampleContainsAny() {
...
@@ -41,7 +41,6 @@ func ExampleContainsAny() {
func
ExampleCount
()
{
func
ExampleCount
()
{
fmt
.
Println
(
strings
.
Count
(
"cheese"
,
"e"
))
fmt
.
Println
(
strings
.
Count
(
"cheese"
,
"e"
))
fmt
.
Println
(
strings
.
Count
(
"five"
,
""
))
// before & after each rune
fmt
.
Println
(
strings
.
Count
(
"five"
,
""
))
// before & after each rune
// Output:
// Output:
// 3
// 3
// 5
// 5
...
...
libgo/go/text/template/exec.go
View file @
08a680a8
...
@@ -518,6 +518,13 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
...
@@ -518,6 +518,13 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
}
}
}
}
if
!
value
.
Type
()
.
AssignableTo
(
typ
)
{
if
!
value
.
Type
()
.
AssignableTo
(
typ
)
{
if
value
.
Kind
()
==
reflect
.
Interface
&&
!
value
.
IsNil
()
{
value
=
value
.
Elem
()
if
value
.
Type
()
.
AssignableTo
(
typ
)
{
return
value
}
// fallthrough
}
// Does one dereference or indirection work? We could do more, as we
// Does one dereference or indirection work? We could do more, as we
// do with method receivers, but that gets messy and method receivers
// do with method receivers, but that gets messy and method receivers
// are much more constrained, so it makes more sense there than here.
// are much more constrained, so it makes more sense there than here.
...
...
libgo/go/text/template/exec_test.go
View file @
08a680a8
...
@@ -311,6 +311,7 @@ var execTests = []execTest{
...
@@ -311,6 +311,7 @@ var execTests = []execTest{
{
".VariadicFuncInt"
,
"{{call .VariadicFuncInt 33 `he` `llo`}}"
,
"33=<he+llo>"
,
tVal
,
true
},
{
".VariadicFuncInt"
,
"{{call .VariadicFuncInt 33 `he` `llo`}}"
,
"33=<he+llo>"
,
tVal
,
true
},
{
"if .BinaryFunc call"
,
"{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}"
,
"[1=2]"
,
tVal
,
true
},
{
"if .BinaryFunc call"
,
"{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}"
,
"[1=2]"
,
tVal
,
true
},
{
"if not .BinaryFunc call"
,
"{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}"
,
"No"
,
tVal
,
true
},
{
"if not .BinaryFunc call"
,
"{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}"
,
"No"
,
tVal
,
true
},
{
"Interface Call"
,
`{{stringer .S}}`
,
"foozle"
,
map
[
string
]
interface
{}{
"S"
:
bytes
.
NewBufferString
(
"foozle"
)},
true
},
// Erroneous function calls (check args).
// Erroneous function calls (check args).
{
".BinaryFuncTooFew"
,
"{{call .BinaryFunc `1`}}"
,
""
,
tVal
,
false
},
{
".BinaryFuncTooFew"
,
"{{call .BinaryFunc `1`}}"
,
""
,
tVal
,
false
},
...
@@ -507,6 +508,10 @@ func vfunc(V, *V) string {
...
@@ -507,6 +508,10 @@ func vfunc(V, *V) string {
return
"vfunc"
return
"vfunc"
}
}
func
stringer
(
s
fmt
.
Stringer
)
string
{
return
s
.
String
()
}
func
testExecute
(
execTests
[]
execTest
,
template
*
Template
,
t
*
testing
.
T
)
{
func
testExecute
(
execTests
[]
execTest
,
template
*
Template
,
t
*
testing
.
T
)
{
b
:=
new
(
bytes
.
Buffer
)
b
:=
new
(
bytes
.
Buffer
)
funcs
:=
FuncMap
{
funcs
:=
FuncMap
{
...
@@ -516,6 +521,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
...
@@ -516,6 +521,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
"typeOf"
:
typeOf
,
"typeOf"
:
typeOf
,
"vfunc"
:
vfunc
,
"vfunc"
:
vfunc
,
"zeroArgs"
:
zeroArgs
,
"zeroArgs"
:
zeroArgs
,
"stringer"
:
stringer
,
}
}
for
_
,
test
:=
range
execTests
{
for
_
,
test
:=
range
execTests
{
var
tmpl
*
Template
var
tmpl
*
Template
...
...
libgo/go/time/sleep_test.go
View file @
08a680a8
...
@@ -224,3 +224,25 @@ func TestTimerStopStress(t *testing.T) {
...
@@ -224,3 +224,25 @@ func TestTimerStopStress(t *testing.T) {
}
}
Sleep
(
3
*
Second
)
Sleep
(
3
*
Second
)
}
}
func
TestSleepZeroDeadlock
(
t
*
testing
.
T
)
{
// Sleep(0) used to hang, the sequence of events was as follows.
// Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
// Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
// After the GC nobody wakes up the goroutine from Gwaiting status.
defer
runtime
.
GOMAXPROCS
(
runtime
.
GOMAXPROCS
(
4
))
c
:=
make
(
chan
bool
)
go
func
()
{
for
i
:=
0
;
i
<
100
;
i
++
{
runtime
.
GC
()
}
c
<-
true
}()
for
i
:=
0
;
i
<
100
;
i
++
{
Sleep
(
0
)
tmp
:=
make
(
chan
bool
,
1
)
tmp
<-
true
<-
tmp
}
<-
c
}
libgo/go/unicode/tables.go
View file @
08a680a8
...
@@ -2701,7 +2701,7 @@ var _Zs = &RangeTable{
...
@@ -2701,7 +2701,7 @@ var _Zs = &RangeTable{
},
},
}
}
// The
following variables are of type *RangeTable:
// The
se variables have type *RangeTable.
var
(
var
(
Cc
=
_Cc
// Cc is the set of Unicode characters in category Cc.
Cc
=
_Cc
// Cc is the set of Unicode characters in category Cc.
Cf
=
_Cf
// Cf is the set of Unicode characters in category Cf.
Cf
=
_Cf
// Cf is the set of Unicode characters in category Cf.
...
@@ -4054,7 +4054,7 @@ var _Yi = &RangeTable{
...
@@ -4054,7 +4054,7 @@ var _Yi = &RangeTable{
},
},
}
}
// The
following variables are of type *RangeTable:
// The
se variables have type *RangeTable.
var
(
var
(
Arabic
=
_Arabic
// Arabic is the set of Unicode characters in script Arabic.
Arabic
=
_Arabic
// Arabic is the set of Unicode characters in script Arabic.
Armenian
=
_Armenian
// Armenian is the set of Unicode characters in script Armenian.
Armenian
=
_Armenian
// Armenian is the set of Unicode characters in script Armenian.
...
@@ -5116,7 +5116,7 @@ var _White_Space = &RangeTable{
...
@@ -5116,7 +5116,7 @@ var _White_Space = &RangeTable{
},
},
}
}
// The
following variables are of type *RangeTable:
// The
se variables have type *RangeTable.
var
(
var
(
ASCII_Hex_Digit
=
_ASCII_Hex_Digit
// ASCII_Hex_Digit is the set of Unicode characters with property ASCII_Hex_Digit.
ASCII_Hex_Digit
=
_ASCII_Hex_Digit
// ASCII_Hex_Digit is the set of Unicode characters with property ASCII_Hex_Digit.
Bidi_Control
=
_Bidi_Control
// Bidi_Control is the set of Unicode characters with property Bidi_Control.
Bidi_Control
=
_Bidi_Control
// Bidi_Control is the set of Unicode characters with property Bidi_Control.
...
...
libgo/runtime/malloc.goc
View file @
08a680a8
...
@@ -168,6 +168,7 @@ __go_free(void *v)
...
@@ -168,6 +168,7 @@ __go_free(void *v)
c->local_by_size[sizeclass].nfree++;
c->local_by_size[sizeclass].nfree++;
runtime_MCache_Free(c, v, sizeclass, size);
runtime_MCache_Free(c, v, sizeclass, size);
}
}
c->local_nfree++;
c->local_alloc -= size;
c->local_alloc -= size;
if(prof)
if(prof)
runtime_MProf_Free(v, size);
runtime_MProf_Free(v, size);
...
...
libgo/runtime/mfinal.c
View file @
08a680a8
...
@@ -150,8 +150,7 @@ runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft)
...
@@ -150,8 +150,7 @@ runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft)
tab
=
TAB
(
p
);
tab
=
TAB
(
p
);
runtime_lock
(
tab
);
runtime_lock
(
tab
);
if
(
f
==
nil
)
{
if
(
f
==
nil
)
{
if
(
lookfintab
(
tab
,
p
,
true
,
nil
))
lookfintab
(
tab
,
p
,
true
,
nil
);
runtime_setblockspecial
(
p
,
false
);
runtime_unlock
(
tab
);
runtime_unlock
(
tab
);
return
true
;
return
true
;
}
}
...
...
libgo/runtime/mgc0.c
View file @
08a680a8
...
@@ -1132,7 +1132,6 @@ runfinq(void* dummy __attribute__ ((unused)))
...
@@ -1132,7 +1132,6 @@ runfinq(void* dummy __attribute__ ((unused)))
f
=
&
fb
->
fin
[
i
];
f
=
&
fb
->
fin
[
i
];
params
[
0
]
=
&
f
->
arg
;
params
[
0
]
=
&
f
->
arg
;
runtime_setblockspecial
(
f
->
arg
,
false
);
reflect_call
(
f
->
ft
,
(
void
*
)
f
->
fn
,
0
,
0
,
params
,
nil
);
reflect_call
(
f
->
ft
,
(
void
*
)
f
->
fn
,
0
,
0
,
params
,
nil
);
f
->
fn
=
nil
;
f
->
fn
=
nil
;
f
->
arg
=
nil
;
f
->
arg
=
nil
;
...
...
libgo/runtime/time.goc
View file @
08a680a8
...
@@ -61,15 +61,21 @@ ready(int64 now, Eface e)
...
@@ -61,15 +61,21 @@ ready(int64 now, Eface e)
void
void
runtime_tsleep(int64 ns)
runtime_tsleep(int64 ns)
{
{
G* g;
Timer t;
Timer t;
if(ns <= 0)
g = runtime_g();
if(ns <= 0) {
g->status = Grunning;
g->waitreason = nil;
return;
return;
}
t.when = runtime_nanotime() + ns;
t.when = runtime_nanotime() + ns;
t.period = 0;
t.period = 0;
t.f = ready;
t.f = ready;
t.arg.__object =
runtime_g()
;
t.arg.__object =
g
;
addtimer(&t);
addtimer(&t);
runtime_gosched();
runtime_gosched();
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment