mirror of
https://github.com/golang/go.git
synced 2026-01-29 07:02:05 +03:00
Compare commits
181 Commits
0f72aff835
...
go1.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb6c6570b7 | ||
|
|
d0eabe2bbf | ||
|
|
75fff72d44 | ||
|
|
5d333a6de5 | ||
|
|
596e6f390b | ||
|
|
96ab6e4a84 | ||
|
|
4a0549ffc6 | ||
|
|
95c8f44f3a | ||
|
|
687e047b14 | ||
|
|
2117541627 | ||
|
|
1ddbfeedae | ||
|
|
e819613d08 | ||
|
|
ef902f8c8e | ||
|
|
2c396a8f4a | ||
|
|
5169191e96 | ||
|
|
a2f13c8cf2 | ||
|
|
0d5061ac95 | ||
|
|
61364c1b97 | ||
|
|
a56e41d518 | ||
|
|
4bc9ddf82f | ||
|
|
dc0f7d6fde | ||
|
|
cec2715018 | ||
|
|
24ee3e4eef | ||
|
|
0db7bc2ed8 | ||
|
|
2ed8b2011d | ||
|
|
d261dc39aa | ||
|
|
d4a15ab8ca | ||
|
|
3a9bd603ed | ||
|
|
9f0345c4ec | ||
|
|
0508326926 | ||
|
|
1ba00e32da | ||
|
|
4c35c0b498 | ||
|
|
0a6b1d66f6 | ||
|
|
f384564778 | ||
|
|
47c317c50b | ||
|
|
c30e746666 | ||
|
|
01faffd009 | ||
|
|
8da546a3cf | ||
|
|
95cffc1227 | ||
|
|
c558dc787d | ||
|
|
5fc093e3c0 | ||
|
|
19af0b28c5 | ||
|
|
56ef99d910 | ||
|
|
39c6f00c9a | ||
|
|
f12183ff6a | ||
|
|
c8ba37cf37 | ||
|
|
d0176e77e7 | ||
|
|
35a1aa0420 | ||
|
|
4fcdfe1eb6 | ||
|
|
90f1a852dc | ||
|
|
71b3ca0817 | ||
|
|
6835ec91dd | ||
|
|
920ebab03c | ||
|
|
dfb11495b5 | ||
|
|
73052c1d6c | ||
|
|
c8e2ccdc9c | ||
|
|
ce85383682 | ||
|
|
f5ef888ce9 | ||
|
|
84d3dc5a93 | ||
|
|
ea2a0ad508 | ||
|
|
b260999d4c | ||
|
|
536be05e32 | ||
|
|
7de2fc41a2 | ||
|
|
0d814d213e | ||
|
|
88c11420a3 | ||
|
|
3c10f29757 | ||
|
|
40960a55c3 | ||
|
|
cee42ca53b | ||
|
|
adb732b5fd | ||
|
|
b503008c9d | ||
|
|
03fab00ed0 | ||
|
|
b7250b205a | ||
|
|
603ace6f8a | ||
|
|
aea18fe74b | ||
|
|
eae44968e3 | ||
|
|
f5a5f17847 | ||
|
|
6a87464709 | ||
|
|
ed3ffb7013 | ||
|
|
3d8275cc3a | ||
|
|
8516b743a8 | ||
|
|
c7b02ba811 | ||
|
|
31ccae9af8 | ||
|
|
dcd49f5eaf | ||
|
|
2f89bfbf8e | ||
|
|
0c2ee38a0a | ||
|
|
9fdd043517 | ||
|
|
fd2dfebd88 | ||
|
|
bd0227bbec | ||
|
|
ff5f88f214 | ||
|
|
dc2889c57e | ||
|
|
237b087af6 | ||
|
|
aceb23ef83 | ||
|
|
52b822298e | ||
|
|
a53a74c204 | ||
|
|
87372e839e | ||
|
|
a340c2a131 | ||
|
|
1927afba99 | ||
|
|
cc52fe30c1 | ||
|
|
c60564f59b | ||
|
|
778529bd58 | ||
|
|
3cbadbd631 | ||
|
|
5ccc50c8d6 | ||
|
|
fcfedc0117 | ||
|
|
c08ef1339e | ||
|
|
db26f2a473 | ||
|
|
7a4e18dbe6 | ||
|
|
43f2be4f4b | ||
|
|
2555bbfdd8 | ||
|
|
0b4c5d7946 | ||
|
|
3a3d8826b4 | ||
|
|
ec1cbabbac | ||
|
|
fd30163bdb | ||
|
|
8ac275bb01 | ||
|
|
763858faca | ||
|
|
e983ddae2f | ||
|
|
2cdf371346 | ||
|
|
2a9009f417 | ||
|
|
50be632ee4 | ||
|
|
2fffba7fe1 | ||
|
|
1c15a46489 | ||
|
|
318b29d661 | ||
|
|
c7a1baf1f0 | ||
|
|
19b11c49a9 | ||
|
|
6b8d891e4e | ||
|
|
cbffaffa6d | ||
|
|
8f2d48993a | ||
|
|
a8cea4cda0 | ||
|
|
342f4bf288 | ||
|
|
b4ea696b49 | ||
|
|
c619931610 | ||
|
|
bff1a8a3b1 | ||
|
|
cb6f9ce4c7 | ||
|
|
01dce10cbf | ||
|
|
86990145a6 | ||
|
|
8b5350b8e4 | ||
|
|
802ac98ffc | ||
|
|
554316495f | ||
|
|
69a8369b87 | ||
|
|
56612a5dc8 | ||
|
|
78bf569018 | ||
|
|
5fe252d191 | ||
|
|
dd58503eaf | ||
|
|
5c69520377 | ||
|
|
85a2bbe135 | ||
|
|
65904a75bc | ||
|
|
ad0c81b124 | ||
|
|
30f431fe2e | ||
|
|
e4806c2a18 | ||
|
|
cd73d696d0 | ||
|
|
18a71beb07 | ||
|
|
bde649ca89 | ||
|
|
ec0b7b7de4 | ||
|
|
a200931cae | ||
|
|
01479df5b6 | ||
|
|
610fc6598b | ||
|
|
8f72d82b63 | ||
|
|
4df8143754 | ||
|
|
70e139f3bc | ||
|
|
9b1d0910e1 | ||
|
|
54fc7ef5ad | ||
|
|
41848f960c | ||
|
|
c3882041a9 | ||
|
|
d98b9dac03 | ||
|
|
ca246227a8 | ||
|
|
02c38a83b9 | ||
|
|
6b68716f85 | ||
|
|
eacdcccb9e | ||
|
|
efcd0d5bd8 | ||
|
|
7510885c4d | ||
|
|
b4f17bdf98 | ||
|
|
879f5d9007 | ||
|
|
c50da29f00 | ||
|
|
465aef6f86 | ||
|
|
d9b3c09097 | ||
|
|
931e05acde | ||
|
|
78b1980875 | ||
|
|
8af4ac6444 | ||
|
|
0c34a28d85 | ||
|
|
6d62c5c99a | ||
|
|
6174b5e21e | ||
|
|
4081aa1277 |
14
AUTHORS
14
AUTHORS
@@ -10,6 +10,7 @@
|
||||
|
||||
Abhinav Gupta <abhinav.g90@gmail.com>
|
||||
Adrian O'Grady <elpollouk@gmail.com>
|
||||
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
@@ -30,8 +31,11 @@ Anthony Starks <ajstarks@gmail.com>
|
||||
Aron Nopanen <aron.nopanen@gmail.com>
|
||||
Arvindh Rajesh Tamilmani <art@a-30.net>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
Benny Siegert <bsiegert@gmail.com>
|
||||
Berengar Lehr <berengar.lehr@gmx.de>
|
||||
Brian Dellisanti <briandellisanti@gmail.com>
|
||||
Bjorn Tillenius <bjorn@tillenius.me>
|
||||
Bjorn Tipling <bjorn.tipling@gmail.com>
|
||||
Blake Mizerany <blake.mizerany@gmail.com>
|
||||
Bobby Powers <bobbypowers@gmail.com>
|
||||
@@ -53,6 +57,7 @@ Damian Gryski <dgryski@gmail.com>
|
||||
Dan Sinclair <dan.sinclair@gmail.com>
|
||||
Daniel Fleischman <danielfleischman@gmail.com>
|
||||
Daniel Krech <eikeon@eikeon.com>
|
||||
Daniel Morsing <daniel.morsing@gmail.com>
|
||||
Daniel Theophanes <kardianos@gmail.com>
|
||||
Darren Elwood <darren@textnode.com>
|
||||
Dave Cheney <dave@cheney.net>
|
||||
@@ -93,6 +98,7 @@ Icarus Sparry <golang@icarus.freeuk.com>
|
||||
Ingo Oeser <nightlyone@googlemail.com>
|
||||
Isaac Wagner <ibw@isaacwagner.me>
|
||||
James Fysh <james.fysh@gmail.com>
|
||||
James Gray <james@james4k.com>
|
||||
James Meneghello <rawrz0r@gmail.com>
|
||||
James P. Cooper <jamespcooper@gmail.com>
|
||||
James Toy <nil@opensesame.st>
|
||||
@@ -100,6 +106,7 @@ James Whitehead <jnwhiteh@gmail.com>
|
||||
Jan H. Hosang <jan.hosang@gmail.com>
|
||||
Jan Mercl <befelemepeseveze@gmail.com>
|
||||
Jan Newmarch <jan.newmarch@gmail.com>
|
||||
Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
|
||||
Jani Monoses <jani.monoses@ubuntu.com>
|
||||
Jaroslavas Počepko <jp@webmaster.ms>
|
||||
Jeff Hodges <jeff@somethingsimilar.com>
|
||||
@@ -129,13 +136,18 @@ Luca Greco <luca.greco@alcacoop.it>
|
||||
Lucio De Re <lucio.dere@gmail.com>
|
||||
Luit van Drongelen <luitvd@gmail.com>
|
||||
Markus Duft <markus.duft@salomon.at>
|
||||
Markus Sonderegger <marraison@gmail.com>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Mateusz Czapliński <czapkofan@gmail.com>
|
||||
Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
|
||||
Mats Lidell <mats.lidell@cag.se>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Micah Stetson <micah.stetson@gmail.com>
|
||||
Michael Chaten <mchaten@gmail.com>
|
||||
Michael Elkins <michael.elkins@gmail.com>
|
||||
Michael Gehring <mg@ebfe.org>
|
||||
Michael Hoisie <hoisie@gmail.com>
|
||||
Michael Lewis <mikelikespie@gmail.com>
|
||||
Michał Derkacz <ziutek@lnet.pl>
|
||||
Miek Gieben <miek@miek.nl>
|
||||
Mikael Tillenius <mikti42@gmail.com>
|
||||
@@ -159,6 +171,7 @@ Paul Lalonde <paul.a.lalonde@gmail.com>
|
||||
Paul Sbarra <Sbarra.Paul@gmail.com>
|
||||
Petar Maymounkov <petarm@gmail.com>
|
||||
Peter Froehlich <peter.hans.froehlich@gmail.com>
|
||||
Peter Kleiweg <pkleiweg@xs4all.nl>
|
||||
Peter Mundy <go.peter.90@gmail.com>
|
||||
Peter Williams <pwil3058@gmail.com>
|
||||
Pieter Droogendijk <pieter@binky.org.uk>
|
||||
@@ -183,6 +196,7 @@ Sergio Luis O. B. Correia <sergio@larces.uece.br>
|
||||
Shenghou Ma <minux.ma@gmail.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
|
||||
Stéphane Travostino <stephane.travostino@gmail.com>
|
||||
Stephen Weinberg <stephen@q5comm.com>
|
||||
Sven Almgren <sven@tras.se>
|
||||
Szabolcs Nagy <nsz@port70.net>
|
||||
|
||||
20
CONTRIBUTORS
20
CONTRIBUTORS
@@ -31,9 +31,11 @@
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Aaron Kemp <kemp.aaron@gmail.com>
|
||||
Abhinav Gupta <abhinav.g90@gmail.com>
|
||||
Adam Langley <agl@golang.org>
|
||||
Adrian O'Grady <elpollouk@gmail.com>
|
||||
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
@@ -62,13 +64,17 @@ Ben Eitzen <eitzenb@golang.org>
|
||||
Ben Fried <ben.fried@gmail.com>
|
||||
Ben Lynn <benlynn@gmail.com>
|
||||
Ben Olive <sionide21@gmail.com>
|
||||
Benjamin Black <b@b3k.us>
|
||||
Benny Siegert <bsiegert@gmail.com>
|
||||
Berengar Lehr <Berengar.Lehr@gmx.de>
|
||||
Bill Neubauer <wcn@golang.org> <wcn@google.com>
|
||||
Bill Thiede <couchmoney@gmail.com>
|
||||
Bjorn Tillenius <bjorn@tillenius.me>
|
||||
Bjorn Tipling <bjorn.tipling@gmail.com>
|
||||
Blake Mizerany <blake.mizerany@gmail.com>
|
||||
Bobby Powers <bobbypowers@gmail.com>
|
||||
Brad Fitzpatrick <bradfitz@golang.org> <bradfitz@gmail.com>
|
||||
Brian Dellisanti <briandellisanti@gmail.com>
|
||||
Brendan O'Dea <bod@golang.org>
|
||||
Caine Tighe <arctanofyourface@gmail.com>
|
||||
Cary Hull <chull@google.com>
|
||||
@@ -84,12 +90,14 @@ Christopher Nielsen <m4dh4tt3r@gmail.com>
|
||||
Christopher Redden <christopher.redden@gmail.com>
|
||||
Christopher Wedgwood <cw@f00f.org>
|
||||
Clement Skau <clementskau@gmail.com>
|
||||
Colby Ranger <cranger@google.com>
|
||||
Conrad Meyer <cemeyer@cs.washington.edu>
|
||||
Corey Thomasson <cthom.lists@gmail.com>
|
||||
Damian Gryski <dgryski@gmail.com>
|
||||
Dan Sinclair <dan.sinclair@gmail.com>
|
||||
Daniel Fleischman <danielfleischman@gmail.com>
|
||||
Daniel Krech <eikeon@eikeon.com>
|
||||
Daniel Morsing <daniel.morsing@gmail.com>
|
||||
Daniel Nadasi <dnadasi@google.com>
|
||||
Daniel Theophanes <kardianos@gmail.com>
|
||||
Darren Elwood <darren@textnode.com>
|
||||
@@ -141,6 +149,7 @@ Ivan Krasin <krasin@golang.org>
|
||||
Jacob Baskin <jbaskin@google.com>
|
||||
James Aguilar <jaguilar@google.com>
|
||||
James Fysh <james.fysh@gmail.com>
|
||||
James Gray <james@james4k.com>
|
||||
James Meneghello <rawrz0r@gmail.com>
|
||||
James P. Cooper <jamespcooper@gmail.com>
|
||||
James Toy <nil@opensesame.st>
|
||||
@@ -149,8 +158,10 @@ Jamie Gennis <jgennis@google.com> <jgennis@gmail.com>
|
||||
Jan H. Hosang <jan.hosang@gmail.com>
|
||||
Jan Mercl <befelemepeseveze@gmail.com>
|
||||
Jan Newmarch <jan.newmarch@gmail.com>
|
||||
Jan Ziak <0xe2.0x9a.0x9b@gmail.com>
|
||||
Jani Monoses <jani.monoses@ubuntu.com> <jani.monoses@gmail.com>
|
||||
Jaroslavas Počepko <jp@webmaster.ms>
|
||||
Jean-Marc Eurin <jmeurin@google.com>
|
||||
Jeff Hodges <jeff@somethingsimilar.com>
|
||||
Jeff R. Allen <jra@nella.org> <jeff.allen@gmail.com>
|
||||
Jeremy Jackins <jeremyjackins@gmail.com>
|
||||
@@ -192,16 +203,21 @@ Luuk van Dijk <lvd@golang.org> <lvd@google.com>
|
||||
Marcel van Lohuizen <mpvl@golang.org>
|
||||
Mark Zavislak <zavislak@google.com>
|
||||
Markus Duft <markus.duft@salomon.at>
|
||||
Markus Sonderegger <marraison@gmail.com>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Mateusz Czapliński <czapkofan@gmail.com>
|
||||
Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
|
||||
Mats Lidell <mats.lidell@cag.se> <mats.lidell@gmail.com>
|
||||
Matt Jones <mrjones@google.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Maxim Pimenov <mpimenov@google.com>
|
||||
Maxim Ushakov <ushakov@google.com>
|
||||
Micah Stetson <micah.stetson@gmail.com>
|
||||
Michael Chaten <mchaten@gmail.com>
|
||||
Michael Elkins <michael.elkins@gmail.com>
|
||||
Michael Gehring <mg@ebfe.org>
|
||||
Michael Hoisie <hoisie@gmail.com>
|
||||
Michael Lewis <mikelikespie@gmail.com>
|
||||
Michael Shields <mshields@google.com>
|
||||
Michael T. Jones <mtj@google.com> <michael.jones@gmail.com>
|
||||
Michał Derkacz <ziutek@lnet.pl>
|
||||
@@ -230,9 +246,11 @@ Paul Lalonde <paul.a.lalonde@gmail.com>
|
||||
Paul Sbarra <Sbarra.Paul@gmail.com>
|
||||
Petar Maymounkov <petarm@gmail.com>
|
||||
Peter Froehlich <peter.hans.froehlich@gmail.com>
|
||||
Peter Kleiweg <pkleiweg@xs4all.nl>
|
||||
Peter McKenzie <petermck@google.com>
|
||||
Peter Mundy <go.peter.90@gmail.com>
|
||||
Péter Szabó <pts@google.com>
|
||||
Peter Weinberger <pjw@golang.org>
|
||||
Peter Williams <pwil3058@gmail.com>
|
||||
Phil Pennock <pdp@golang.org>
|
||||
Pieter Droogendijk <pieter@binky.org.uk>
|
||||
@@ -250,6 +268,7 @@ Roger Peppe <rogpeppe@gmail.com>
|
||||
Ron Minnich <rminnich@gmail.com>
|
||||
Ross Light <rlight2@gmail.com>
|
||||
Russ Cox <rsc@golang.org>
|
||||
Ryan Barrett <ryanb@google.com>
|
||||
Ryan Hitchman <hitchmanr@gmail.com>
|
||||
Sam Thorogood <thorogood@google.com> <sam.thorogood@gmail.com>
|
||||
Sameer Ajmani <sameer@golang.org> <ajmani@gmail.com>
|
||||
@@ -264,6 +283,7 @@ Sergio Luis O. B. Correia <sergio@larces.uece.br>
|
||||
Shenghou Ma <minux.ma@gmail.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
|
||||
Stéphane Travostino <stephane.travostino@gmail.com>
|
||||
Stephen Ma <stephenm@golang.org>
|
||||
Stephen Weinberg <stephen@q5comm.com>
|
||||
Sugu Sougoumarane <ssougou@gmail.com>
|
||||
|
||||
11
api/README
Normal file
11
api/README
Normal file
@@ -0,0 +1,11 @@
|
||||
Files in this directory are data for Go's API checker ("go tool api", in src/cmd/api).
|
||||
|
||||
Each file is a list of of API features, one per line.
|
||||
|
||||
go1.txt (and similarly named files) are frozen once a version has been
|
||||
shipped. Each file adds new lines but does not remove any.
|
||||
|
||||
next.txt is the only file intended to be mutated. It's a list of
|
||||
features that may be added to the next version. It only affects
|
||||
warning output from the go api tool.
|
||||
|
||||
6296
api/go1.txt
6296
api/go1.txt
File diff suppressed because it is too large
Load Diff
428
api/next.txt
Normal file
428
api/next.txt
Normal file
@@ -0,0 +1,428 @@
|
||||
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16
|
||||
pkg crypto/tls, const TLS_RSA_WITH_AES_256_CBC_SHA uint16
|
||||
pkg crypto/x509, const ECDSA PublicKeyAlgorithm
|
||||
pkg crypto/x509, const ECDSAWithSHA1 SignatureAlgorithm
|
||||
pkg crypto/x509, const ECDSAWithSHA256 SignatureAlgorithm
|
||||
pkg crypto/x509, const ECDSAWithSHA384 SignatureAlgorithm
|
||||
pkg crypto/x509, const ECDSAWithSHA512 SignatureAlgorithm
|
||||
pkg debug/elf, type FileHeader struct, Entry uint64
|
||||
pkg go/doc, var IllegalPrefixes []string
|
||||
pkg math/big, method (*Int) MarshalJSON() ([]byte, error)
|
||||
pkg math/big, method (*Int) UnmarshalJSON([]byte) error
|
||||
pkg regexp/syntax, const ErrUnexpectedParen ErrorCode
|
||||
pkg syscall (darwin-386), const B0 ideal-int
|
||||
pkg syscall (darwin-386), const B110 ideal-int
|
||||
pkg syscall (darwin-386), const B115200 ideal-int
|
||||
pkg syscall (darwin-386), const B1200 ideal-int
|
||||
pkg syscall (darwin-386), const B134 ideal-int
|
||||
pkg syscall (darwin-386), const B14400 ideal-int
|
||||
pkg syscall (darwin-386), const B150 ideal-int
|
||||
pkg syscall (darwin-386), const B1800 ideal-int
|
||||
pkg syscall (darwin-386), const B19200 ideal-int
|
||||
pkg syscall (darwin-386), const B200 ideal-int
|
||||
pkg syscall (darwin-386), const B230400 ideal-int
|
||||
pkg syscall (darwin-386), const B2400 ideal-int
|
||||
pkg syscall (darwin-386), const B28800 ideal-int
|
||||
pkg syscall (darwin-386), const B300 ideal-int
|
||||
pkg syscall (darwin-386), const B38400 ideal-int
|
||||
pkg syscall (darwin-386), const B4800 ideal-int
|
||||
pkg syscall (darwin-386), const B50 ideal-int
|
||||
pkg syscall (darwin-386), const B57600 ideal-int
|
||||
pkg syscall (darwin-386), const B600 ideal-int
|
||||
pkg syscall (darwin-386), const B7200 ideal-int
|
||||
pkg syscall (darwin-386), const B75 ideal-int
|
||||
pkg syscall (darwin-386), const B76800 ideal-int
|
||||
pkg syscall (darwin-386), const B9600 ideal-int
|
||||
pkg syscall (darwin-386), const BRKINT ideal-int
|
||||
pkg syscall (darwin-386), const CFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const CLOCAL ideal-int
|
||||
pkg syscall (darwin-386), const CREAD ideal-int
|
||||
pkg syscall (darwin-386), const CS5 ideal-int
|
||||
pkg syscall (darwin-386), const CS6 ideal-int
|
||||
pkg syscall (darwin-386), const CS7 ideal-int
|
||||
pkg syscall (darwin-386), const CS8 ideal-int
|
||||
pkg syscall (darwin-386), const CSIZE ideal-int
|
||||
pkg syscall (darwin-386), const CSTART ideal-int
|
||||
pkg syscall (darwin-386), const CSTATUS ideal-int
|
||||
pkg syscall (darwin-386), const CSTOP ideal-int
|
||||
pkg syscall (darwin-386), const CSTOPB ideal-int
|
||||
pkg syscall (darwin-386), const CSUSP ideal-int
|
||||
pkg syscall (darwin-386), const FLUSHO ideal-int
|
||||
pkg syscall (darwin-386), const HUPCL ideal-int
|
||||
pkg syscall (darwin-386), const ICANON ideal-int
|
||||
pkg syscall (darwin-386), const ICRNL ideal-int
|
||||
pkg syscall (darwin-386), const IEXTEN ideal-int
|
||||
pkg syscall (darwin-386), const IGNBRK ideal-int
|
||||
pkg syscall (darwin-386), const IGNCR ideal-int
|
||||
pkg syscall (darwin-386), const IGNPAR ideal-int
|
||||
pkg syscall (darwin-386), const IMAXBEL ideal-int
|
||||
pkg syscall (darwin-386), const INLCR ideal-int
|
||||
pkg syscall (darwin-386), const INPCK ideal-int
|
||||
pkg syscall (darwin-386), const ISIG ideal-int
|
||||
pkg syscall (darwin-386), const ISTRIP ideal-int
|
||||
pkg syscall (darwin-386), const IUTF8 ideal-int
|
||||
pkg syscall (darwin-386), const IXANY ideal-int
|
||||
pkg syscall (darwin-386), const IXOFF ideal-int
|
||||
pkg syscall (darwin-386), const IXON ideal-int
|
||||
pkg syscall (darwin-386), const NOFLSH ideal-int
|
||||
pkg syscall (darwin-386), const OCRNL ideal-int
|
||||
pkg syscall (darwin-386), const OFDEL ideal-int
|
||||
pkg syscall (darwin-386), const OFILL ideal-int
|
||||
pkg syscall (darwin-386), const ONLCR ideal-int
|
||||
pkg syscall (darwin-386), const ONLRET ideal-int
|
||||
pkg syscall (darwin-386), const ONOCR ideal-int
|
||||
pkg syscall (darwin-386), const ONOEOT ideal-int
|
||||
pkg syscall (darwin-386), const OPOST ideal-int
|
||||
pkg syscall (darwin-386), const PARENB ideal-int
|
||||
pkg syscall (darwin-386), const PARMRK ideal-int
|
||||
pkg syscall (darwin-386), const PARODD ideal-int
|
||||
pkg syscall (darwin-386), const PENDIN ideal-int
|
||||
pkg syscall (darwin-386), const TCIFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const TCIOFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const TCOFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const TCSAFLUSH ideal-int
|
||||
pkg syscall (darwin-386), const TOSTOP ideal-int
|
||||
pkg syscall (darwin-386), const VDISCARD ideal-int
|
||||
pkg syscall (darwin-386), const VDSUSP ideal-int
|
||||
pkg syscall (darwin-386), const VEOF ideal-int
|
||||
pkg syscall (darwin-386), const VEOL ideal-int
|
||||
pkg syscall (darwin-386), const VEOL2 ideal-int
|
||||
pkg syscall (darwin-386), const VERASE ideal-int
|
||||
pkg syscall (darwin-386), const VINTR ideal-int
|
||||
pkg syscall (darwin-386), const VKILL ideal-int
|
||||
pkg syscall (darwin-386), const VLNEXT ideal-int
|
||||
pkg syscall (darwin-386), const VMIN ideal-int
|
||||
pkg syscall (darwin-386), const VQUIT ideal-int
|
||||
pkg syscall (darwin-386), const VREPRINT ideal-int
|
||||
pkg syscall (darwin-386), const VSTART ideal-int
|
||||
pkg syscall (darwin-386), const VSTATUS ideal-int
|
||||
pkg syscall (darwin-386), const VSTOP ideal-int
|
||||
pkg syscall (darwin-386), const VSUSP ideal-int
|
||||
pkg syscall (darwin-386), const VT0 ideal-int
|
||||
pkg syscall (darwin-386), const VT1 ideal-int
|
||||
pkg syscall (darwin-386), const VTDLY ideal-int
|
||||
pkg syscall (darwin-386), const VTIME ideal-int
|
||||
pkg syscall (darwin-386), const VWERASE ideal-int
|
||||
pkg syscall (darwin-386), type Termios struct
|
||||
pkg syscall (darwin-386), type Termios struct, Cc [20]uint8
|
||||
pkg syscall (darwin-386), type Termios struct, Cflag uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Iflag uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Ispeed uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Lflag uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Oflag uint32
|
||||
pkg syscall (darwin-386), type Termios struct, Ospeed uint32
|
||||
pkg syscall (darwin-386-cgo), const B0 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B110 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B115200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B1200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B134 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B14400 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B150 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B1800 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B19200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B230400 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B2400 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B28800 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B300 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B38400 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B4800 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B50 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B57600 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B600 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B7200 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B75 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B76800 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const B9600 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const BRKINT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CLOCAL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CREAD ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CS5 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CS6 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CS7 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CS8 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSIZE ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSTART ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSTATUS ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSTOP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSTOPB ideal-int
|
||||
pkg syscall (darwin-386-cgo), const CSUSP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const FLUSHO ideal-int
|
||||
pkg syscall (darwin-386-cgo), const HUPCL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ICANON ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ICRNL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IEXTEN ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IGNBRK ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IGNCR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IGNPAR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IMAXBEL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const INLCR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const INPCK ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ISIG ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ISTRIP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IUTF8 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IXANY ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IXOFF ideal-int
|
||||
pkg syscall (darwin-386-cgo), const IXON ideal-int
|
||||
pkg syscall (darwin-386-cgo), const NOFLSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const OCRNL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const OFDEL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const OFILL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ONLCR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ONLRET ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ONOCR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const ONOEOT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const OPOST ideal-int
|
||||
pkg syscall (darwin-386-cgo), const PARENB ideal-int
|
||||
pkg syscall (darwin-386-cgo), const PARMRK ideal-int
|
||||
pkg syscall (darwin-386-cgo), const PARODD ideal-int
|
||||
pkg syscall (darwin-386-cgo), const PENDIN ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TCIFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TCIOFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TCOFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TCSAFLUSH ideal-int
|
||||
pkg syscall (darwin-386-cgo), const TOSTOP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VDISCARD ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VDSUSP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VEOF ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VEOL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VEOL2 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VERASE ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VINTR ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VKILL ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VLNEXT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VMIN ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VQUIT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VREPRINT ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VSTART ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VSTATUS ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VSTOP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VSUSP ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VT0 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VT1 ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VTDLY ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VTIME ideal-int
|
||||
pkg syscall (darwin-386-cgo), const VWERASE ideal-int
|
||||
pkg syscall (darwin-386-cgo), type Termios struct
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Cc [20]uint8
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Cflag uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Iflag uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Ispeed uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Lflag uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Oflag uint32
|
||||
pkg syscall (darwin-386-cgo), type Termios struct, Ospeed uint32
|
||||
pkg syscall (darwin-amd64), const B0 ideal-int
|
||||
pkg syscall (darwin-amd64), const B110 ideal-int
|
||||
pkg syscall (darwin-amd64), const B115200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B1200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B134 ideal-int
|
||||
pkg syscall (darwin-amd64), const B14400 ideal-int
|
||||
pkg syscall (darwin-amd64), const B150 ideal-int
|
||||
pkg syscall (darwin-amd64), const B1800 ideal-int
|
||||
pkg syscall (darwin-amd64), const B19200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B230400 ideal-int
|
||||
pkg syscall (darwin-amd64), const B2400 ideal-int
|
||||
pkg syscall (darwin-amd64), const B28800 ideal-int
|
||||
pkg syscall (darwin-amd64), const B300 ideal-int
|
||||
pkg syscall (darwin-amd64), const B38400 ideal-int
|
||||
pkg syscall (darwin-amd64), const B4800 ideal-int
|
||||
pkg syscall (darwin-amd64), const B50 ideal-int
|
||||
pkg syscall (darwin-amd64), const B57600 ideal-int
|
||||
pkg syscall (darwin-amd64), const B600 ideal-int
|
||||
pkg syscall (darwin-amd64), const B7200 ideal-int
|
||||
pkg syscall (darwin-amd64), const B75 ideal-int
|
||||
pkg syscall (darwin-amd64), const B76800 ideal-int
|
||||
pkg syscall (darwin-amd64), const B9600 ideal-int
|
||||
pkg syscall (darwin-amd64), const BRKINT ideal-int
|
||||
pkg syscall (darwin-amd64), const CFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const CLOCAL ideal-int
|
||||
pkg syscall (darwin-amd64), const CREAD ideal-int
|
||||
pkg syscall (darwin-amd64), const CS5 ideal-int
|
||||
pkg syscall (darwin-amd64), const CS6 ideal-int
|
||||
pkg syscall (darwin-amd64), const CS7 ideal-int
|
||||
pkg syscall (darwin-amd64), const CS8 ideal-int
|
||||
pkg syscall (darwin-amd64), const CSIZE ideal-int
|
||||
pkg syscall (darwin-amd64), const CSTART ideal-int
|
||||
pkg syscall (darwin-amd64), const CSTATUS ideal-int
|
||||
pkg syscall (darwin-amd64), const CSTOP ideal-int
|
||||
pkg syscall (darwin-amd64), const CSTOPB ideal-int
|
||||
pkg syscall (darwin-amd64), const CSUSP ideal-int
|
||||
pkg syscall (darwin-amd64), const FLUSHO ideal-int
|
||||
pkg syscall (darwin-amd64), const HUPCL ideal-int
|
||||
pkg syscall (darwin-amd64), const ICANON ideal-int
|
||||
pkg syscall (darwin-amd64), const ICRNL ideal-int
|
||||
pkg syscall (darwin-amd64), const IEXTEN ideal-int
|
||||
pkg syscall (darwin-amd64), const IGNBRK ideal-int
|
||||
pkg syscall (darwin-amd64), const IGNCR ideal-int
|
||||
pkg syscall (darwin-amd64), const IGNPAR ideal-int
|
||||
pkg syscall (darwin-amd64), const IMAXBEL ideal-int
|
||||
pkg syscall (darwin-amd64), const INLCR ideal-int
|
||||
pkg syscall (darwin-amd64), const INPCK ideal-int
|
||||
pkg syscall (darwin-amd64), const ISIG ideal-int
|
||||
pkg syscall (darwin-amd64), const ISTRIP ideal-int
|
||||
pkg syscall (darwin-amd64), const IUTF8 ideal-int
|
||||
pkg syscall (darwin-amd64), const IXANY ideal-int
|
||||
pkg syscall (darwin-amd64), const IXOFF ideal-int
|
||||
pkg syscall (darwin-amd64), const IXON ideal-int
|
||||
pkg syscall (darwin-amd64), const NOFLSH ideal-int
|
||||
pkg syscall (darwin-amd64), const OCRNL ideal-int
|
||||
pkg syscall (darwin-amd64), const OFDEL ideal-int
|
||||
pkg syscall (darwin-amd64), const OFILL ideal-int
|
||||
pkg syscall (darwin-amd64), const ONLCR ideal-int
|
||||
pkg syscall (darwin-amd64), const ONLRET ideal-int
|
||||
pkg syscall (darwin-amd64), const ONOCR ideal-int
|
||||
pkg syscall (darwin-amd64), const ONOEOT ideal-int
|
||||
pkg syscall (darwin-amd64), const OPOST ideal-int
|
||||
pkg syscall (darwin-amd64), const PARENB ideal-int
|
||||
pkg syscall (darwin-amd64), const PARMRK ideal-int
|
||||
pkg syscall (darwin-amd64), const PARODD ideal-int
|
||||
pkg syscall (darwin-amd64), const PENDIN ideal-int
|
||||
pkg syscall (darwin-amd64), const TCIFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const TCIOFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const TCOFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const TCSAFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64), const TOSTOP ideal-int
|
||||
pkg syscall (darwin-amd64), const VDISCARD ideal-int
|
||||
pkg syscall (darwin-amd64), const VDSUSP ideal-int
|
||||
pkg syscall (darwin-amd64), const VEOF ideal-int
|
||||
pkg syscall (darwin-amd64), const VEOL ideal-int
|
||||
pkg syscall (darwin-amd64), const VEOL2 ideal-int
|
||||
pkg syscall (darwin-amd64), const VERASE ideal-int
|
||||
pkg syscall (darwin-amd64), const VINTR ideal-int
|
||||
pkg syscall (darwin-amd64), const VKILL ideal-int
|
||||
pkg syscall (darwin-amd64), const VLNEXT ideal-int
|
||||
pkg syscall (darwin-amd64), const VMIN ideal-int
|
||||
pkg syscall (darwin-amd64), const VQUIT ideal-int
|
||||
pkg syscall (darwin-amd64), const VREPRINT ideal-int
|
||||
pkg syscall (darwin-amd64), const VSTART ideal-int
|
||||
pkg syscall (darwin-amd64), const VSTATUS ideal-int
|
||||
pkg syscall (darwin-amd64), const VSTOP ideal-int
|
||||
pkg syscall (darwin-amd64), const VSUSP ideal-int
|
||||
pkg syscall (darwin-amd64), const VT0 ideal-int
|
||||
pkg syscall (darwin-amd64), const VT1 ideal-int
|
||||
pkg syscall (darwin-amd64), const VTDLY ideal-int
|
||||
pkg syscall (darwin-amd64), const VTIME ideal-int
|
||||
pkg syscall (darwin-amd64), const VWERASE ideal-int
|
||||
pkg syscall (darwin-amd64), type Termios struct
|
||||
pkg syscall (darwin-amd64), type Termios struct, Cc [20]uint8
|
||||
pkg syscall (darwin-amd64), type Termios struct, Cflag uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Iflag uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Ispeed uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Lflag uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Oflag uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Ospeed uint64
|
||||
pkg syscall (darwin-amd64), type Termios struct, Pad_cgo_0 [4]byte
|
||||
pkg syscall (darwin-amd64-cgo), const B0 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B110 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B115200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B1200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B134 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B14400 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B150 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B1800 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B19200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B230400 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B2400 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B28800 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B300 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B38400 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B4800 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B50 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B57600 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B600 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B7200 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B75 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B76800 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const B9600 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const BRKINT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CLOCAL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CREAD ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CS5 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CS6 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CS7 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CS8 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSIZE ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSTART ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSTATUS ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSTOP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSTOPB ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const CSUSP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const FLUSHO ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const HUPCL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ICANON ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ICRNL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IEXTEN ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IGNBRK ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IGNCR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IGNPAR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IMAXBEL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const INLCR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const INPCK ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ISIG ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ISTRIP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IUTF8 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IXANY ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IXOFF ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const IXON ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const NOFLSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const OCRNL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const OFDEL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const OFILL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ONLCR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ONLRET ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ONOCR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const ONOEOT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const OPOST ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const PARENB ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const PARMRK ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const PARODD ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const PENDIN ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TCIFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TCIOFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TCOFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TCSAFLUSH ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const TOSTOP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VDISCARD ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VDSUSP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VEOF ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VEOL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VEOL2 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VERASE ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VINTR ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VKILL ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VLNEXT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VMIN ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VQUIT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VREPRINT ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VSTART ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VSTATUS ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VSTOP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VSUSP ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VT0 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VT1 ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VTDLY ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VTIME ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), const VWERASE ideal-int
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Cc [20]uint8
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Cflag uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Iflag uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Ispeed uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Lflag uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Oflag uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Ospeed uint64
|
||||
pkg syscall (darwin-amd64-cgo), type Termios struct, Pad_cgo_0 [4]byte
|
||||
pkg syscall (windows-386), const CREATE_NEW_PROCESS_GROUP ideal-int
|
||||
pkg syscall (windows-386), const CTRL_BREAK_EVENT ideal-int
|
||||
pkg syscall (windows-386), const CTRL_C_EVENT ideal-int
|
||||
pkg syscall (windows-386), func GetCurrentProcessId() uint32
|
||||
pkg syscall (windows-386), type SysProcAttr struct, CreationFlags uint32
|
||||
pkg syscall (windows-amd64), const CREATE_NEW_PROCESS_GROUP ideal-int
|
||||
pkg syscall (windows-amd64), const CTRL_BREAK_EVENT ideal-int
|
||||
pkg syscall (windows-amd64), const CTRL_C_EVENT ideal-int
|
||||
pkg syscall (windows-amd64), func GetCurrentProcessId() uint32
|
||||
pkg syscall (windows-amd64), type SysProcAttr struct, CreationFlags uint32
|
||||
@@ -89,7 +89,7 @@ interface which has a <code>Set</code> method.
|
||||
|
||||
<p>
|
||||
To fill a rectangle with a solid color, use an <code>image.Uniform</code>
|
||||
source. The <code>ColorImage</code> type re-interprets a <code>Color</code> as a
|
||||
source. The <code>Uniform</code> type re-interprets a <code>Color</code> as a
|
||||
practically infinite-sized <code>Image</code> of that color. For those
|
||||
familiar with the design of Plan 9's draw library, there is no need
|
||||
for an explicit "repeat bit" in Go's slice-based image types; the
|
||||
@@ -189,7 +189,7 @@ To draw an image through a circular mask with center <code>p</code> and radius
|
||||
|
||||
<p>
|
||||
To draw a font glyph in blue starting from a point <code>p</code>, draw with
|
||||
an <code>image.ColorImage</code> source and an <code>image.Alpha mask</code>. For
|
||||
an <code>image.Uniform</code> source and an <code>image.Alpha mask</code>. For
|
||||
simplicity, we aren't performing any sub-pixel positioning or
|
||||
rendering, or correcting for a font's height above a baseline.
|
||||
</p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<h1>Editing {{.Title |html}}</h1>
|
||||
<h1>Editing {{.Title}}</h1>
|
||||
|
||||
<form action="/save/{{.Title |html}}" method="POST">
|
||||
<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body |html}}</textarea></div>
|
||||
<form action="/save/{{.Title}}" method="POST">
|
||||
<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body}}</textarea></div>
|
||||
<div><input type="submit" value="Save"></div>
|
||||
</form>
|
||||
|
||||
@@ -359,10 +359,10 @@ First, we must add <code>html/template</code> to the list of imports:
|
||||
|
||||
<pre>
|
||||
import (
|
||||
<b>"html/template"</b>
|
||||
"http"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
<b>"html/template"</b>
|
||||
)
|
||||
</pre>
|
||||
|
||||
@@ -397,10 +397,11 @@ Template directives are enclosed in double curly braces.
|
||||
The <code>printf "%s" .Body</code> instruction is a function call
|
||||
that outputs <code>.Body</code> as a string instead of a stream of bytes,
|
||||
the same as a call to <code>fmt.Printf</code>.
|
||||
The <code>|html</code> part of each directive pipes the value through the
|
||||
<code>html</code> formatter before outputting it, which escapes HTML
|
||||
characters (such as replacing <code>></code> with <code>&gt;</code>),
|
||||
preventing user data from corrupting the form HTML.
|
||||
The <code>html/template</code> package helps guarantee that only safe and
|
||||
correct-looking HTML is generated by template actions. For instance, it
|
||||
automatically escapes any greater than sign (<code>></code>), replacing it
|
||||
with <code>&gt;</code>, to make sure user data does not corrupt the form
|
||||
HTML.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<h1>{{.Title |html}}</h1>
|
||||
<h1>{{.Title}}</h1>
|
||||
|
||||
<p>[<a href="/edit/{{.Title |html}}">edit</a>]</p>
|
||||
<p>[<a href="/edit/{{.Title}}">edit</a>]</p>
|
||||
|
||||
<div>{{printf "%s" .Body |html}}</div>
|
||||
<div>{{printf "%s" .Body}}</div>
|
||||
|
||||
@@ -236,7 +236,7 @@ are built and installed correctly.
|
||||
<p>
|
||||
As a convenience, the <code>go</code> command will assume the current directory
|
||||
if no import path is specified on the command line. This sequence of commands
|
||||
has the same affect as the one above:
|
||||
has the same effect as the one above:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -300,7 +300,8 @@ func main() {
|
||||
|
||||
<p>
|
||||
Next, run <code>go install</code>, which builds and installs the binary to
|
||||
<code>$GOPATH/bin</code>:
|
||||
<code>$GOPATH/bin</code> (or <code>$GOBIN</code>, if set; to simplify
|
||||
presentation, this document assumes <code>GOBIN</code> is unset):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -384,7 +385,7 @@ package newmath
|
||||
import "testing"
|
||||
|
||||
func TestSqrt(t *testing.T) {
|
||||
const in, out = 9, 3
|
||||
const in, out = 4, 2
|
||||
if x := Sqrt(in); x != out {
|
||||
t.Errorf("Sqrt(%v) = %v, want %v", in, x, out)
|
||||
}
|
||||
@@ -397,7 +398,7 @@ Now run the test with <code>go test</code>:
|
||||
|
||||
<pre>
|
||||
$ go test example/newmath
|
||||
ok example/newmath
|
||||
ok example/newmath 0.165s
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -475,8 +476,8 @@ import "code.google.com/p/go.example/newmath"
|
||||
<p>
|
||||
This convention is the easiest way to make your Go packages available for
|
||||
others to use.
|
||||
The <a href="http://godashboard.appspot.com/package">Go Package Dashboard</a>
|
||||
displays a list of packages recently installed with the <code>go</code> command.
|
||||
The <a href="http://godashboard.appspot.com">Go Project Dashboard</a>
|
||||
is a list of external Go projects including programs and libraries.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -215,7 +215,7 @@ p[len(p)-1] = suffix
|
||||
|
||||
<step title="Choosing a suffix at random" src="doc/codewalk/markov.go:/next := choices/,/Shift/">
|
||||
To choose a suffix we use the
|
||||
<code><a href="/pkg/rand/#Intn">rand.Intn</a></code> function.
|
||||
<code><a href="/pkg/math/rand/#Intn">rand.Intn</a></code> function.
|
||||
It returns a random integer up to (but not including) the provided
|
||||
value. Passing in <code>len(choices)</code> gives us a random index
|
||||
into the full length of the list.
|
||||
@@ -287,11 +287,11 @@ a plan a man a plan a canal panama</pre>
|
||||
Here's a transcript of generating some text using the Go distribution's
|
||||
README file as source material:
|
||||
<pre>
|
||||
$ ./markov -words=10 < $GOROOT/go/README
|
||||
$ ./markov -words=10 < $GOROOT/README
|
||||
This is the source code repository for the Go source
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/go/README
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/README
|
||||
This is the go directory (the one containing this README).
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/go/README
|
||||
$ ./markov -prefix=1 -words=10 < $GOROOT/README
|
||||
This is the variable if you have just untarred a</pre>
|
||||
</step>
|
||||
|
||||
|
||||
@@ -35,6 +35,28 @@ The go1 release corresponds to
|
||||
<code><a href="weekly.html#2012-03-27">weekly.2012-03-27</a></code>.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.0.1 (released 2012/04/25) was issued to
|
||||
<a href="https://code.google.com/p/go/source/detail?r=a890477d3dfb">fix</a> an
|
||||
<a href="https://code.google.com/p/go/issues/detail?id=3545">escape analysis
|
||||
bug</a> that can lead to memory corruption.
|
||||
It also includes several minor code and documentation fixes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.0.2 (released 2012/06/13) was issued to fix two bugs in the implementation
|
||||
of maps using struct or array keys:
|
||||
<a href="http://code.google.com/p/go/issues/detail?id=3695">issue 3695</a> and
|
||||
<a href="http://code.google.com/p/go/issues/detail?id=3573">issue 3573</a>.
|
||||
It also includes many minor code and documentation fixes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
See the <a href="http://code.google.com/p/go/source/list?name=release-branch.go1">go1 release branch history</a> for the complete list of changes.
|
||||
</p>
|
||||
|
||||
<h2 id="r60">r60 (released 2011/09/07)</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -2291,7 +2291,7 @@ This would be useful if we wanted to refine the methods of <code>Logger</code>.
|
||||
</p>
|
||||
<pre>
|
||||
func (job *Job) Logf(format string, args ...interface{}) {
|
||||
job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args))
|
||||
job.Logger.Logf("%q: %s", job.Command, fmt.Sprintf(format, args...))
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
@@ -2479,7 +2479,7 @@ func handle(queue chan *Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func Serve(clientRequests chan *clientRequests, quit chan bool) {
|
||||
func Serve(clientRequests chan *Request, quit chan bool) {
|
||||
// Start handlers
|
||||
for i := 0; i < MaxOutstanding; i++ {
|
||||
go handle(clientRequests)
|
||||
|
||||
@@ -1253,7 +1253,7 @@ Since the package's functionality is new, no updating is necessary.
|
||||
<p>
|
||||
In Go 1 the <a href="/pkg/net/http/"><code>http</code></a> package is refactored,
|
||||
putting some of the utilities into a
|
||||
<a href="/pkg/net/httputil/"><code>httputil</code></a> subdirectory.
|
||||
<a href="/pkg/net/http/httputil/"><code>httputil</code></a> subdirectory.
|
||||
These pieces are only rarely needed by HTTP clients.
|
||||
The affected items are:
|
||||
</p>
|
||||
@@ -1261,7 +1261,6 @@ The affected items are:
|
||||
<ul>
|
||||
<li>ClientConn</li>
|
||||
<li>DumpRequest</li>
|
||||
<li>DumpRequest</li>
|
||||
<li>DumpRequestOut</li>
|
||||
<li>DumpResponse</li>
|
||||
<li>NewChunkedReader</li>
|
||||
@@ -1789,7 +1788,7 @@ for full details.
|
||||
<td colspan="2"><hr></td>
|
||||
</tr>
|
||||
<tr><td>Atoui(x)</td> <td>ParseUint(x, 10, 0)§</td></tr>
|
||||
<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
|
||||
<tr><td>Atoui64(x)</td> <td>ParseUint(x, 10, 64)</td></tr>
|
||||
<tr>
|
||||
<td colspan="2"><hr></td>
|
||||
</tr>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of March 17, 2012",
|
||||
"Subtitle": "Version of June 4, 2012",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
@@ -684,6 +684,8 @@ consists of all methods with receiver type <code>T</code>.
|
||||
The method set of the corresponding pointer type <code>*T</code>
|
||||
is the set of all methods with receiver <code>*T</code> or <code>T</code>
|
||||
(that is, it also contains the method set of <code>T</code>).
|
||||
Further rules apply to structs containing anonymous fields, as described
|
||||
in the section on <a href="#Struct_types">struct types</a>.
|
||||
Any other type has an empty method set.
|
||||
In a method set, each method must have a
|
||||
<a href="#Uniqueness_of_identifiers">unique</a> <a href="#MethodName">method name</a>.
|
||||
@@ -955,28 +957,39 @@ struct {
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Fields and methods (§<a href="#Method_declarations">Method declarations</a>) of an anonymous field are
|
||||
promoted to be ordinary fields and methods of the struct (§<a href="#Selectors">Selectors</a>).
|
||||
The following rules apply for a struct type <code>S</code> and
|
||||
a type named <code>T</code>:
|
||||
A field or <a href="#Method_declarations">method</a> <code>f</code> of an
|
||||
anonymous field in a struct <code>x</code> is called <i>promoted</i> if
|
||||
<code>x.f</code> is a legal <a href="#Selectors">selector</a> that denotes
|
||||
that field or method <code>f</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Promoted fields act like ordinary fields
|
||||
of a struct except that they cannot be used as field names in
|
||||
<a href="#Composite_literals">composite literals</a> of the struct.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Given a struct type <code>S</code> and a type named <code>T</code>,
|
||||
promoted methods are included in the method set of the struct as follows:
|
||||
</p>
|
||||
<ul>
|
||||
<li>If <code>S</code> contains an anonymous field <code>T</code>, the
|
||||
<a href="#Method_sets">method set</a> of <code>S</code> includes the
|
||||
method set of <code>T</code>.
|
||||
<li>
|
||||
If <code>S</code> contains an anonymous field <code>T</code>,
|
||||
the <a href="#Method_sets">method sets</a> of <code>S</code>
|
||||
and <code>*S</code> both include promoted methods with receiver
|
||||
<code>T</code>. The method set of <code>*S</code> also
|
||||
includes promoted methods with receiver <code>*T</code>.
|
||||
</li>
|
||||
|
||||
<li>If <code>S</code> contains an anonymous field <code>*T</code>, the
|
||||
method set of <code>S</code> includes the method set of <code>*T</code>
|
||||
(which itself includes the method set of <code>T</code>).
|
||||
</li>
|
||||
|
||||
<li>If <code>S</code> contains an anonymous field <code>T</code> or
|
||||
<code>*T</code>, the method set of <code>*S</code> includes the
|
||||
method set of <code>*T</code> (which itself includes the method
|
||||
set of <code>T</code>).
|
||||
|
||||
<li>
|
||||
If <code>S</code> contains an anonymous field <code>*T</code>,
|
||||
the method sets of <code>S</code> and <code>*S</code> both
|
||||
include promoted methods with receiver <code>T</code> or
|
||||
<code>*T</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
A field declaration may be followed by an optional string literal <i>tag</i>,
|
||||
which becomes an attribute for all the fields in the corresponding
|
||||
@@ -1598,7 +1611,7 @@ Given a set of identifiers, an identifier is called <i>unique</i> if it is
|
||||
<i>different</i> from every other in the set.
|
||||
Two identifiers are different if they are spelled differently, or if they
|
||||
appear in different <a href="#Packages">packages</a> and are not
|
||||
<a href="Exported_identifiers">exported</a>. Otherwise, they are the same.
|
||||
<a href="#Exported_identifiers">exported</a>. Otherwise, they are the same.
|
||||
</p>
|
||||
|
||||
<h3 id="Constant_declarations">Constant declarations</h3>
|
||||
@@ -2396,7 +2409,7 @@ type T2 struct {
|
||||
|
||||
func (recv *T2) M2()
|
||||
|
||||
var p *T2 // with p != nil and p.T1 != nil
|
||||
var p *T2 // with p != nil and p.T0 != nil
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -2659,7 +2672,7 @@ back to the calling function when the function returns.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Calling a <code>nil</code> function value
|
||||
Calling a <code>nil</code> function value
|
||||
causes a <a href="#Run_time_panics">run-time panic</a>.
|
||||
</p>
|
||||
|
||||
@@ -3030,29 +3043,29 @@ These terms and the result of the comparisons are defined as follows:
|
||||
<li>
|
||||
Integer values are comparable and ordered, in the usual way.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Floating point values are comparable and ordered,
|
||||
as defined by the IEEE-754 standard.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Complex values are comparable.
|
||||
Two complex values <code>u</code> and <code>v</code> are
|
||||
equal if both <code>real(u) == real(v)</code> and
|
||||
<code>imag(u) == imag(v)</code>.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
String values are comparable and ordered, lexically byte-wise.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Pointer values are comparable.
|
||||
Two pointer values are equal if they point to the same variable or if both have value <code>nil</code>.
|
||||
Pointers to distinct <a href="#Size_and_alignment_guarantees">zero-size</a> variables may or may not be equal.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Channel values are comparable.
|
||||
Two channel values are equal if they were created by the same call to <code>make</code>
|
||||
@@ -3065,7 +3078,7 @@ These terms and the result of the comparisons are defined as follows:
|
||||
Two interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types
|
||||
and equal dynamic values or if both have value <code>nil</code>.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
A value <code>x</code> of non-interface type <code>X</code> and
|
||||
a value <code>t</code> of interface type <code>T</code> are comparable when values
|
||||
@@ -3080,7 +3093,7 @@ These terms and the result of the comparisons are defined as follows:
|
||||
Two struct values are equal if their corresponding
|
||||
non-<a href="#Blank_identifier">blank</a> fields are equal.
|
||||
</li>
|
||||
|
||||
|
||||
<li>
|
||||
Array values are comparable if values of the array element type are comparable.
|
||||
Two array values are equal if their corresponding elements are equal.
|
||||
@@ -3866,7 +3879,11 @@ x, _ = f() // ignore second value returned by f()
|
||||
In the second form, the number of operands on the left must equal the number
|
||||
of expressions on the right, each of which must be single-valued, and the
|
||||
<i>n</i>th expression on the right is assigned to the <i>n</i>th
|
||||
operand on the left. The assignment proceeds in two phases.
|
||||
operand on the left.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The assignment proceeds in two phases.
|
||||
First, the operands of <a href="#Indexes">index expressions</a>
|
||||
and <a href="#Address_operators">pointer indirections</a>
|
||||
(including implicit pointer indirections in <a href="#Selectors">selectors</a>)
|
||||
@@ -3885,13 +3902,20 @@ i, x[i] = 1, 2 // set i = 1, x[0] = 2
|
||||
i = 0
|
||||
x[i], i = 2, 1 // set x[0] = 2, i = 1
|
||||
|
||||
x[0], x[0] = 1, 2 // set x[0] = 1, then x[0] = 2 (so x[0] = 2 at end)
|
||||
x[0], x[0] = 1, 2 // set x[0] = 1, then x[0] = 2 (so x[0] == 2 at end)
|
||||
|
||||
x[1], x[3] = 4, 5 // set x[1] = 4, then panic setting x[3] = 5.
|
||||
|
||||
type Point struct { x, y int }
|
||||
var p *Point
|
||||
x[2], p.x = 6, 7 // set x[2] = 6, then panic setting p.x = 7
|
||||
|
||||
i = 2
|
||||
x = []int{3, 5, 7}
|
||||
for i, x[i] = range x { // set i, x[2] = 0, x[0]
|
||||
break
|
||||
}
|
||||
// after this loop, i == 0 and x == []int{3, 5, 3}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -5401,7 +5425,7 @@ type ArbitraryType int // shorthand for an arbitrary Go type; it is not a real
|
||||
type Pointer *ArbitraryType
|
||||
|
||||
func Alignof(variable ArbitraryType) uintptr
|
||||
func Offsetof(selector ArbitraryType) uinptr
|
||||
func Offsetof(selector ArbitraryType) uintptr
|
||||
func Sizeof(variable ArbitraryType) uintptr
|
||||
</pre>
|
||||
|
||||
|
||||
@@ -106,26 +106,13 @@ On Windows, install <code>gcc</code> with
|
||||
|
||||
<p>
|
||||
To perform the next step you must have Mercurial installed. (Check that you
|
||||
have an <code>hg</code> command.) This suffices to install Mercurial on most
|
||||
Unix systems:
|
||||
have an <code>hg</code> command.)
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
sudo easy_install mercurial==2.0
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
On Ubuntu/Debian, the Mercurial in your distribution's
|
||||
package repository is most likely old and broken.
|
||||
You might try this first:
|
||||
</p>
|
||||
|
||||
<pre>apt-get install python-setuptools python-dev build-essential</pre>
|
||||
|
||||
<p>
|
||||
If that fails, or if you use Windows, install manually from the
|
||||
<a href="http://mercurial.selenic.com/wiki/Download">Mercurial Download</a>
|
||||
page.
|
||||
If you do not have a working Mercurial installation,
|
||||
follow the instructions on the
|
||||
<a href="http://mercurial.selenic.com/downloads/">Mercurial downloads</a> page.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -183,7 +170,6 @@ ALL TESTS PASSED
|
||||
Installed Go for linux/amd64 in /home/you/go.
|
||||
Installed commands in /home/you/go/bin.
|
||||
*** You need to add /home/you/go/bin to your $PATH. ***
|
||||
The compiler is 6g.
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -24,6 +24,32 @@ For information about installing <code>gccgo</code>, see
|
||||
<a href="/doc/install/gccgo">Setting up and using gccgo</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="requirements">System requirements</h2>
|
||||
<p>
|
||||
The <code>gc</code> compiler supports the following operating systems and
|
||||
architectures. Please ensure your system meets these requirements before
|
||||
proceeding. If your OS or architecture is not on the list, it's possible that
|
||||
<code>gccgo</code> might support your setup; see
|
||||
<a href="/doc/install/gccgo">Setting up and using gccgo</a> for details.
|
||||
</p>
|
||||
|
||||
<table class="codetable" frame="border" summary="requirements">
|
||||
<tr>
|
||||
<th align="middle">Operating system</th>
|
||||
<th align="middle">Architectures</th>
|
||||
<th align="middle">Notes</th>
|
||||
</tr>
|
||||
<tr><td colspan="3"><hr></td></tr>
|
||||
<tr><td>FreeBSD 7 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
||||
<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</tr>
|
||||
<tr><td>Mac OS X 10.6/10.7</td> <td>amd64, 386</td> <td>use the gcc<sup>†</sup> that comes with Xcode</td></tr>
|
||||
<tr><td>Windows 2000 or later</td> <td>amd64, 386</td> <td>use mingw gcc<sup>†</sup>; cygwin or msys is not needed</td></tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<sup>†</sup><code>gcc</code> is required only if you plan to use <a href="/cmd/cgo">cgo</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="download">Download the Go tools</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
// codeEl - code editor element
|
||||
// outputEl - program output element
|
||||
// runEl - run button element
|
||||
// fmtEl - fmt button element (optional)
|
||||
// shareEl - share button element (optional)
|
||||
// shareURLEl - share URL text input element (optional)
|
||||
// shareRedirect - base URL to redirect to on share (optional)
|
||||
// preCompile - callback to mutate request data before compiling
|
||||
// postCompile - callback to read response data after compiling
|
||||
// simple - use plain textarea instead of CodeMirror.
|
||||
// toysEl - select element with a list of toys.
|
||||
// preCompile - callback to mutate request data before compiling (optional)
|
||||
// postCompile - callback to read response data after compiling (optional)
|
||||
// simple - use plain textarea instead of CodeMirror. (optional)
|
||||
// toysEl - select element with a list of toys. (optional)
|
||||
function playground(opts) {
|
||||
var simple = opts['simple'];
|
||||
var code = $(opts['codeEl']);
|
||||
@@ -97,7 +98,7 @@ function playground(opts) {
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
var errorRe = /[a-z]+\.go:([0-9]+): /g;
|
||||
var errorRe = /[a-z]+\.go:([0-9]+):/g;
|
||||
var result;
|
||||
while ((result = errorRe.exec(text)) != null) {
|
||||
var line = result[1]*1-1;
|
||||
@@ -120,13 +121,23 @@ function playground(opts) {
|
||||
function origin(href) {
|
||||
return (""+href).split("/").slice(0, 3).join("/");
|
||||
}
|
||||
function loading() {
|
||||
output.removeClass("error").html(
|
||||
'<div class="loading">Waiting for remote server...</div>'
|
||||
);
|
||||
}
|
||||
function setOutput(text, error) {
|
||||
output.empty();
|
||||
if (error) {
|
||||
output.addClass("error");
|
||||
}
|
||||
$("<pre/>").text(text).appendTo(output);
|
||||
}
|
||||
|
||||
var seq = 0;
|
||||
function run() {
|
||||
clearErrors();
|
||||
output.removeClass("error").html(
|
||||
'<div class="loading">Waiting for remote server...</div>'
|
||||
);
|
||||
loading();
|
||||
seq++;
|
||||
var cur = seq;
|
||||
var data = {"body": body()};
|
||||
@@ -141,8 +152,6 @@ function playground(opts) {
|
||||
if (seq != cur) {
|
||||
return;
|
||||
}
|
||||
pre = $("<pre/>");
|
||||
output.empty().append(pre);
|
||||
if (opts['postCompile']) {
|
||||
opts['postCompile'](data);
|
||||
}
|
||||
@@ -150,8 +159,7 @@ function playground(opts) {
|
||||
return;
|
||||
}
|
||||
if (data.compile_errors != "") {
|
||||
pre.text(data.compile_errors);
|
||||
output.addClass("error");
|
||||
setOutput(data.compile_errors, true);
|
||||
highlightErrors(data.compile_errors);
|
||||
return;
|
||||
}
|
||||
@@ -164,11 +172,10 @@ function playground(opts) {
|
||||
output.empty().append(img);
|
||||
return;
|
||||
}
|
||||
pre.text(out);
|
||||
setOutput(out, false);
|
||||
},
|
||||
error: function(xhr) {
|
||||
var text = "Error communicating with remote server.";
|
||||
console.log(xhr.status);
|
||||
if (xhr.status == 501) {
|
||||
text = xhr.responseText;
|
||||
}
|
||||
@@ -178,6 +185,41 @@ function playground(opts) {
|
||||
}
|
||||
$(opts['runEl']).click(run);
|
||||
|
||||
$(opts['fmtEl']).click(function() {
|
||||
loading();
|
||||
$.ajax("/fmt", {
|
||||
data: {"body": body()},
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if (data.Error) {
|
||||
setOutput(data.Error, true);
|
||||
highlightErrors(data.Error);
|
||||
return;
|
||||
}
|
||||
setBody(data.Body);
|
||||
setOutput("", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(opts['toysEl']).bind('change', function() {
|
||||
var toy = $(this).val();
|
||||
loading();
|
||||
$.ajax("/doc/play/"+toy, {
|
||||
processData: false,
|
||||
type: "GET",
|
||||
complete: function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
setOutput("Server error; try again.", true);
|
||||
return;
|
||||
}
|
||||
setBody(xhr.responseText);
|
||||
setOutput("", false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (opts['shareEl'] != null && (opts['shareURLEl'] != null || opts['shareRedirect'] != null)) {
|
||||
var shareURL;
|
||||
if (opts['shareURLEl']) {
|
||||
@@ -213,22 +255,5 @@ function playground(opts) {
|
||||
});
|
||||
}
|
||||
|
||||
if (opts['toysEl'] != null) {
|
||||
$(opts['toysEl']).bind('change', function() {
|
||||
var toy = $(this).val();
|
||||
$.ajax("/doc/play/"+toy, {
|
||||
processData: false,
|
||||
type: "GET",
|
||||
complete: function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
alert("Server error; try again.")
|
||||
return;
|
||||
}
|
||||
setBody(xhr.responseText);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ func ConvAndCircle() {
|
||||
|
||||
// CONV OMIT
|
||||
b := src.Bounds()
|
||||
m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
||||
draw.Draw(m, m.Bounds(), src, b.Min, draw.Src)
|
||||
m := image.NewRGBA(b)
|
||||
draw.Draw(m, b, src, b.Min, draw.Src)
|
||||
// STOP OMIT
|
||||
|
||||
p := image.Point{100, 100}
|
||||
|
||||
@@ -108,7 +108,9 @@ table.dir td {
|
||||
word-wrap: break-word;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
div#page.wide table.dir td.name {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.alert {
|
||||
color: #AA0000;
|
||||
}
|
||||
@@ -371,6 +373,7 @@ div#blog .read {
|
||||
.toggleVisible .expanded { display: block; }
|
||||
|
||||
table.codetable { margin-left: auto; margin-right: auto; border-style: none; }
|
||||
table.codetable td { padding-right: 10px; }
|
||||
hr { border-style: none; border-top: 1px solid black; }
|
||||
|
||||
img.gopher {
|
||||
@@ -388,4 +391,3 @@ img.gopher {
|
||||
margin-bottom: -120px;
|
||||
}
|
||||
h2 { clear: right; }
|
||||
|
||||
|
||||
@@ -192,14 +192,14 @@
|
||||
{{if $.DirFlat}}
|
||||
{{if .HasPkg}}
|
||||
<tr>
|
||||
<td><a href="{{html .Path}}">{{html .Path}}</a></td>
|
||||
<td class="name"><a href="{{html .Path}}">{{html .Path}}</a></td>
|
||||
<td> </td>
|
||||
<td style="width: auto">{{html .Synopsis}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<tr>
|
||||
<td>{{repeat ` ` .Depth}}<a href="{{html .Path}}">{{html .Name}}</a></td>
|
||||
<td class="name">{{repeat ` ` .Depth}}<a href="{{html .Path}}">{{html .Name}}</a></td>
|
||||
<td> </td>
|
||||
<td style="width: auto">{{html .Synopsis}}</td>
|
||||
</tr>
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
;; Operators (punctuation)
|
||||
(modify-syntax-entry ?+ "." st)
|
||||
(modify-syntax-entry ?- "." st)
|
||||
(modify-syntax-entry ?* "." st)
|
||||
(modify-syntax-entry ?/ "." st)
|
||||
(modify-syntax-entry ?* ". 23" st) ; also part of comments
|
||||
(modify-syntax-entry ?/ (if (featurep 'xemacs) ". 1456" ". 124b") st) ; ditto
|
||||
(modify-syntax-entry ?% "." st)
|
||||
(modify-syntax-entry ?& "." st)
|
||||
(modify-syntax-entry ?| "." st)
|
||||
@@ -50,6 +50,9 @@
|
||||
(modify-syntax-entry ?` "." st)
|
||||
(modify-syntax-entry ?\\ "." st)
|
||||
|
||||
;; Newline is a comment-ender.
|
||||
(modify-syntax-entry ?\n "> b" st)
|
||||
|
||||
st)
|
||||
"Syntax table for Go mode.")
|
||||
|
||||
@@ -179,6 +182,10 @@ to and including character (1- go-mode-mark-comment-end)).")
|
||||
marked from the beginning up to this point.")
|
||||
(make-variable-buffer-local 'go-mode-mark-nesting-end)
|
||||
|
||||
(defun go-mode-mark-clear-cs (b e l)
|
||||
"An after-change-function that removes the go-mode-cs text property"
|
||||
(remove-text-properties b e '(go-mode-cs)))
|
||||
|
||||
(defun go-mode-mark-clear-cache (b e)
|
||||
"A before-change-function that clears the comment/string and
|
||||
nesting caches from the modified point on."
|
||||
@@ -243,8 +250,8 @@ comment or string."
|
||||
|
||||
(unless pos
|
||||
(setq pos (point)))
|
||||
(when (> pos go-mode-mark-cs-end)
|
||||
(go-mode-mark-cs pos))
|
||||
(when (>= pos go-mode-mark-cs-end)
|
||||
(go-mode-mark-cs (1+ pos)))
|
||||
(get-text-property pos 'go-mode-cs))
|
||||
|
||||
(defun go-mode-mark-cs (end)
|
||||
@@ -435,7 +442,7 @@ if no further tokens of the type exist."
|
||||
(when (search-forward "\n" (cdr cs) t)
|
||||
(put-text-property
|
||||
(car cs) (cdr cs) 'font-lock-multline t))
|
||||
(set-match-data (list (car cs) (cdr cs) (current-buffer)))
|
||||
(set-match-data (list (car cs) (copy-marker (cdr cs))))
|
||||
(goto-char (cdr cs))
|
||||
(setq result t))
|
||||
;; Wrong type. Look for next comment/string after this one.
|
||||
@@ -545,8 +552,9 @@ token on the line."
|
||||
(not (looking-at go-mode-non-terminating-keywords-regexp)))))))
|
||||
|
||||
(defun go-mode-whitespace-p (char)
|
||||
"Is char whitespace in the syntax table for go."
|
||||
(eq 32 (char-syntax char)))
|
||||
"Is newline, or char whitespace in the syntax table for go."
|
||||
(or (eq char ?\n)
|
||||
(= (char-syntax char) ?\ )))
|
||||
|
||||
(defun go-mode-backward-skip-comments ()
|
||||
"Skip backward over comments and whitespace."
|
||||
@@ -589,7 +597,7 @@ indented one level."
|
||||
(cond
|
||||
((and cs (save-excursion
|
||||
(goto-char (car cs))
|
||||
(looking-at "\\s\"")))
|
||||
(looking-at "`")))
|
||||
;; Inside a multi-line string. Don't mess with indentation.
|
||||
nil)
|
||||
(cs
|
||||
@@ -698,13 +706,18 @@ functions, and some types. It also provides indentation that is
|
||||
;; Remove stale text properties
|
||||
(save-restriction
|
||||
(widen)
|
||||
(remove-text-properties 1 (point-max)
|
||||
'(go-mode-cs nil go-mode-nesting nil)))
|
||||
(let ((modified (buffer-modified-p)))
|
||||
(remove-text-properties 1 (point-max)
|
||||
'(go-mode-cs nil go-mode-nesting nil))
|
||||
;; remove-text-properties marks the buffer modified. undo that if it
|
||||
;; wasn't originally marked modified.
|
||||
(set-buffer-modified-p modified)))
|
||||
|
||||
;; Reset the syntax mark caches
|
||||
(setq go-mode-mark-cs-end 1
|
||||
go-mode-mark-nesting-end 1)
|
||||
(add-hook 'before-change-functions #'go-mode-mark-clear-cache nil t)
|
||||
(add-hook 'after-change-functions #'go-mode-mark-clear-cs nil t)
|
||||
|
||||
;; Indentation
|
||||
(set (make-local-variable 'indent-line-function)
|
||||
@@ -716,7 +729,20 @@ functions, and some types. It also provides indentation that is
|
||||
(set (make-local-variable 'comment-end) "")
|
||||
|
||||
;; Go style
|
||||
(setq indent-tabs-mode t))
|
||||
(setq indent-tabs-mode t)
|
||||
|
||||
;; Handle unit test failure output in compilation-mode
|
||||
;;
|
||||
;; Note the final t argument to add-to-list for append, ie put these at the
|
||||
;; *ends* of compilation-error-regexp-alist[-alist]. We want go-test to be
|
||||
;; handled first, otherwise other elements will match that don't work, and
|
||||
;; those alists are traversed in *reverse* order:
|
||||
;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2001-12/msg00674.html
|
||||
(when (and (boundp 'compilation-error-regexp-alist)
|
||||
(boundp 'compilation-error-regexp-alist-alist))
|
||||
(add-to-list 'compilation-error-regexp-alist 'go-test t)
|
||||
(add-to-list 'compilation-error-regexp-alist-alist
|
||||
'(go-test . ("^\t+\\([^()\t\n]+\\):\\([0-9]+\\):? .*$" 1 2)) t)))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist (cons "\\.go$" #'go-mode))
|
||||
@@ -737,36 +763,79 @@ Replace the current buffer on success; display errors on failure."
|
||||
|
||||
(interactive)
|
||||
(let ((currconf (current-window-configuration)))
|
||||
(let ((srcbuf (current-buffer)))
|
||||
(with-temp-buffer
|
||||
(let ((outbuf (current-buffer))
|
||||
(errbuf (get-buffer-create "*Gofmt Errors*"))
|
||||
(coding-system-for-read 'utf-8) ;; use utf-8 with subprocesses
|
||||
(coding-system-for-write 'utf-8))
|
||||
(with-current-buffer errbuf (erase-buffer))
|
||||
(with-current-buffer srcbuf
|
||||
(save-restriction
|
||||
(let (deactivate-mark)
|
||||
(widen)
|
||||
(if (= 0 (shell-command-on-region (point-min) (point-max) "gofmt"
|
||||
outbuf nil errbuf))
|
||||
;; restore window config
|
||||
;; gofmt succeeded: replace the current buffer with outbuf,
|
||||
;; restore the mark and point, and discard errbuf.
|
||||
(let ((old-mark (mark t)) (old-point (point)))
|
||||
(set-window-configuration currconf)
|
||||
(erase-buffer)
|
||||
(insert-buffer-substring outbuf)
|
||||
(goto-char (min old-point (point-max)))
|
||||
(if old-mark (push-mark (min old-mark (point-max)) t))
|
||||
(kill-buffer errbuf))
|
||||
(let ((srcbuf (current-buffer))
|
||||
(filename buffer-file-name)
|
||||
(patchbuf (get-buffer-create "*Gofmt patch*")))
|
||||
(with-current-buffer patchbuf
|
||||
(let ((errbuf (get-buffer-create "*Gofmt Errors*"))
|
||||
(coding-system-for-read 'utf-8) ;; use utf-8 with subprocesses
|
||||
(coding-system-for-write 'utf-8))
|
||||
(with-current-buffer errbuf
|
||||
(toggle-read-only 0)
|
||||
(erase-buffer))
|
||||
(with-current-buffer srcbuf
|
||||
(save-restriction
|
||||
(let (deactivate-mark)
|
||||
(widen)
|
||||
; If this is a new file, diff-mode can't apply a
|
||||
; patch to a non-exisiting file, so replace the buffer
|
||||
; completely with the output of 'gofmt'.
|
||||
; If the file exists, patch it to keep the 'undo' list happy.
|
||||
(let* ((newfile (not (file-exists-p filename)))
|
||||
(flag (if newfile "" " -d")))
|
||||
(if (= 0 (shell-command-on-region (point-min) (point-max)
|
||||
(concat "gofmt" flag)
|
||||
patchbuf nil errbuf))
|
||||
; gofmt succeeded: replace buffer or apply patch hunks.
|
||||
(let ((old-point (point))
|
||||
(old-mark (mark t)))
|
||||
(kill-buffer errbuf)
|
||||
(if newfile
|
||||
; New file, replace it (diff-mode won't work)
|
||||
(gofmt-replace-buffer srcbuf patchbuf)
|
||||
; Existing file, patch it
|
||||
(gofmt-apply-patch filename srcbuf patchbuf))
|
||||
(goto-char (min old-point (point-max)))
|
||||
;; Restore the mark and point
|
||||
(if old-mark (push-mark (min old-mark (point-max)) t))
|
||||
(set-window-configuration currconf))
|
||||
|
||||
;; gofmt failed: display the errors
|
||||
(display-buffer errbuf)))))
|
||||
;; gofmt failed: display the errors
|
||||
(gofmt-process-errors filename errbuf))))))
|
||||
|
||||
;; Collapse any window opened on outbuf if shell-command-on-region
|
||||
;; displayed it.
|
||||
(delete-windows-on outbuf))))))
|
||||
;; Collapse any window opened on outbuf if shell-command-on-region
|
||||
;; displayed it.
|
||||
(delete-windows-on patchbuf)))
|
||||
(kill-buffer patchbuf))))
|
||||
|
||||
(defun gofmt-replace-buffer (srcbuf patchbuf)
|
||||
(with-current-buffer srcbuf
|
||||
(erase-buffer)
|
||||
(insert-buffer-substring patchbuf)))
|
||||
|
||||
(defconst gofmt-stdin-tag "<standard input>")
|
||||
|
||||
(defun gofmt-apply-patch (filename srcbuf patchbuf)
|
||||
(require 'diff-mode)
|
||||
;; apply all the patch hunks
|
||||
(with-current-buffer patchbuf
|
||||
(replace-regexp "^--- /tmp/gofmt[0-9]*" (concat "--- " filename)
|
||||
nil (point-min) (point-max))
|
||||
(condition-case nil
|
||||
(while t
|
||||
(diff-hunk-next)
|
||||
(diff-apply-hunk))
|
||||
;; When there's no more hunks, diff-hunk-next signals an error, ignore it
|
||||
(error nil))))
|
||||
|
||||
(defun gofmt-process-errors (filename errbuf)
|
||||
;; Convert the gofmt stderr to something understood by the compilation mode.
|
||||
(with-current-buffer errbuf
|
||||
(beginning-of-buffer)
|
||||
(insert "gofmt errors:\n")
|
||||
(replace-string gofmt-stdin-tag (file-name-nondirectory filename) nil (point-min) (point-max))
|
||||
(display-buffer errbuf)
|
||||
(compilation-mode)))
|
||||
|
||||
;;;###autoload
|
||||
(defun gofmt-before-save ()
|
||||
|
||||
@@ -8,6 +8,8 @@ if [ ! -f make.bash ]; then
|
||||
echo 'all.bash must be run from $GOROOT/src' 1>&2
|
||||
exit 1
|
||||
fi
|
||||
OLDPATH="$PATH"
|
||||
. ./make.bash --no-banner
|
||||
bash run.bash --no-rebuild --banner
|
||||
bash run.bash --no-rebuild
|
||||
PATH="$OLDPATH"
|
||||
$GOTOOLDIR/dist banner # print build info
|
||||
|
||||
@@ -11,10 +11,12 @@ echo all.bat must be run from go\src
|
||||
goto end
|
||||
:ok
|
||||
|
||||
set OLDPATH=%PATH%
|
||||
call make.bat --no-banner --no-local
|
||||
if %GOBUILDFAIL%==1 goto end
|
||||
call run.bat --no-rebuild --no-local
|
||||
if %GOBUILDFAIL%==1 goto end
|
||||
set PATH=%OLDPATH%
|
||||
go tool dist banner
|
||||
|
||||
:end
|
||||
|
||||
@@ -140,7 +140,7 @@ Dconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Adr *a;
|
||||
char *op;
|
||||
const char *op;
|
||||
int v;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
@@ -169,7 +169,7 @@ Dconv(Fmt *fp)
|
||||
|
||||
case D_SHIFT:
|
||||
v = a->offset;
|
||||
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
||||
op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
|
||||
if(v & (1<<4))
|
||||
sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
|
||||
else
|
||||
|
||||
@@ -198,7 +198,8 @@ dumpfuncs(void)
|
||||
if(isblank(pl->name))
|
||||
continue;
|
||||
|
||||
if(debug['S']) {
|
||||
// -S prints code; -SS prints code and data
|
||||
if(debug['S'] && (pl->name || debug['S']>1)) {
|
||||
s = S;
|
||||
if(pl->name != N)
|
||||
s = pl->name->sym;
|
||||
|
||||
@@ -83,7 +83,7 @@ int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
char *op;
|
||||
const char *op;
|
||||
Addr *a;
|
||||
int i;
|
||||
int32 v;
|
||||
@@ -119,7 +119,7 @@ Dconv(Fmt *fp)
|
||||
|
||||
case D_SHIFT:
|
||||
v = a->offset;
|
||||
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
||||
op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
|
||||
if(v & (1<<4))
|
||||
sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
|
||||
else
|
||||
|
||||
@@ -695,8 +695,8 @@ brk:
|
||||
}
|
||||
}
|
||||
}
|
||||
if(r1 != R) {
|
||||
r1->link = freer;
|
||||
if(lastr != R) {
|
||||
lastr->link = freer;
|
||||
freer = firstr;
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
char *op;
|
||||
const char *op;
|
||||
Adr *a;
|
||||
int32 v;
|
||||
|
||||
@@ -191,7 +191,7 @@ Dconv(Fmt *fp)
|
||||
|
||||
case D_SHIFT:
|
||||
v = a->offset;
|
||||
op = "<<>>->@>" + (((v>>5) & 3) << 1);
|
||||
op = &"<<>>->@>"[(((v>>5) & 3) << 1)];
|
||||
if(v & (1<<4))
|
||||
snprint(str, sizeof str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15);
|
||||
else
|
||||
|
||||
@@ -244,7 +244,8 @@ dumpfuncs(void)
|
||||
if(isblank(pl->name))
|
||||
continue;
|
||||
|
||||
if(debug['S']) {
|
||||
// -S prints code; -SS prints code and data
|
||||
if(debug['S'] && (pl->name || debug['S']>1)) {
|
||||
s = S;
|
||||
if(pl->name != N)
|
||||
s = pl->name->sym;
|
||||
|
||||
@@ -780,8 +780,8 @@ brk:
|
||||
p->to.branch = p->to.branch->link;
|
||||
}
|
||||
|
||||
if(r1 != R) {
|
||||
r1->link = freer;
|
||||
if(lastr != R) {
|
||||
lastr->link = freer;
|
||||
freer = firstr;
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,8 @@ dumpfuncs(void)
|
||||
if(isblank(pl->name))
|
||||
continue;
|
||||
|
||||
if(debug['S']) {
|
||||
// -S prints code; -SS prints code and data
|
||||
if(debug['S'] && (pl->name || debug['S']>1)) {
|
||||
s = S;
|
||||
if(pl->name != N)
|
||||
s = pl->name->sym;
|
||||
|
||||
@@ -677,8 +677,8 @@ brk:
|
||||
p->to.branch = p->to.branch->link;
|
||||
}
|
||||
|
||||
if(r1 != R) {
|
||||
r1->link = freer;
|
||||
if(lastr != R) {
|
||||
lastr->link = freer;
|
||||
freer = firstr;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -35,27 +36,31 @@ import (
|
||||
|
||||
// Flags
|
||||
var (
|
||||
// TODO(bradfitz): once Go 1.1 comes out, allow the -c flag to take a comma-separated
|
||||
// list of files, rather than just one.
|
||||
checkFile = flag.String("c", "", "optional filename to check API against")
|
||||
verbose = flag.Bool("v", false, "Verbose debugging")
|
||||
allowNew = flag.Bool("allow_new", true, "allow API additions")
|
||||
nextFile = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.")
|
||||
verbose = flag.Bool("v", false, "verbose debugging")
|
||||
forceCtx = flag.String("contexts", "", "optional comma-separated list of <goos>-<goarch>[-cgo] to override default contexts.")
|
||||
)
|
||||
|
||||
// contexts are the default contexts which are scanned, unless
|
||||
// overridden by the -contexts flag.
|
||||
var contexts = []*build.Context{
|
||||
{GOOS: "linux", GOARCH: "386", CgoEnabled: true},
|
||||
{GOOS: "linux", GOARCH: "386"},
|
||||
{GOOS: "linux", GOARCH: "amd64", CgoEnabled: true},
|
||||
{GOOS: "linux", GOARCH: "amd64"},
|
||||
{GOOS: "linux", GOARCH: "arm"},
|
||||
{GOOS: "darwin", GOARCH: "386", CgoEnabled: true},
|
||||
{GOOS: "darwin", GOARCH: "386"},
|
||||
{GOOS: "darwin", GOARCH: "amd64", CgoEnabled: true},
|
||||
{GOOS: "darwin", GOARCH: "amd64"},
|
||||
{GOOS: "windows", GOARCH: "amd64"},
|
||||
{GOOS: "windows", GOARCH: "386"},
|
||||
}
|
||||
|
||||
func init() {
|
||||
for _, c := range contexts {
|
||||
c.Compiler = build.Default.Compiler
|
||||
}
|
||||
{GOOS: "freebsd", GOARCH: "amd64"},
|
||||
{GOOS: "freebsd", GOARCH: "386"},
|
||||
}
|
||||
|
||||
func contextName(c *build.Context) string {
|
||||
@@ -66,9 +71,49 @@ func contextName(c *build.Context) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func parseContext(c string) *build.Context {
|
||||
parts := strings.Split(c, "-")
|
||||
if len(parts) < 2 {
|
||||
log.Fatalf("bad context: %q", c)
|
||||
}
|
||||
bc := &build.Context{
|
||||
GOOS: parts[0],
|
||||
GOARCH: parts[1],
|
||||
}
|
||||
if len(parts) == 3 {
|
||||
if parts[2] == "cgo" {
|
||||
bc.CgoEnabled = true
|
||||
} else {
|
||||
log.Fatalf("bad context: %q", c)
|
||||
}
|
||||
}
|
||||
return bc
|
||||
}
|
||||
|
||||
func setContexts() {
|
||||
contexts = []*build.Context{}
|
||||
for _, c := range strings.Split(*forceCtx, ",") {
|
||||
contexts = append(contexts, parseContext(c))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if !strings.Contains(runtime.Version(), "weekly") {
|
||||
if *nextFile != "" {
|
||||
fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile)
|
||||
*nextFile = ""
|
||||
}
|
||||
}
|
||||
|
||||
if *forceCtx != "" {
|
||||
setContexts()
|
||||
}
|
||||
for _, c := range contexts {
|
||||
c.Compiler = build.Default.Compiler
|
||||
}
|
||||
|
||||
var pkgs []string
|
||||
if flag.NArg() > 0 {
|
||||
pkgs = flag.Args()
|
||||
@@ -123,45 +168,86 @@ func main() {
|
||||
}
|
||||
sort.Strings(features)
|
||||
|
||||
fail := false
|
||||
defer func() {
|
||||
if fail {
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
bw := bufio.NewWriter(os.Stdout)
|
||||
defer bw.Flush()
|
||||
|
||||
if *checkFile != "" {
|
||||
bs, err := ioutil.ReadFile(*checkFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file %s: %v", *checkFile, err)
|
||||
}
|
||||
v1 := strings.Split(strings.TrimSpace(string(bs)), "\n")
|
||||
sort.Strings(v1)
|
||||
v2 := features
|
||||
take := func(sl *[]string) string {
|
||||
s := (*sl)[0]
|
||||
*sl = (*sl)[1:]
|
||||
return s
|
||||
}
|
||||
changes := false
|
||||
for len(v1) > 0 || len(v2) > 0 {
|
||||
switch {
|
||||
case len(v2) == 0 || v1[0] < v2[0]:
|
||||
fmt.Fprintf(bw, "-%s\n", take(&v1))
|
||||
changes = true
|
||||
case len(v1) == 0 || v1[0] > v2[0]:
|
||||
fmt.Fprintf(bw, "+%s\n", take(&v2))
|
||||
changes = true
|
||||
default:
|
||||
take(&v1)
|
||||
take(&v2)
|
||||
}
|
||||
}
|
||||
if changes {
|
||||
bw.Flush()
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
if *checkFile == "" {
|
||||
for _, f := range features {
|
||||
fmt.Fprintf(bw, "%s\n", f)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var required []string
|
||||
for _, filename := range []string{*checkFile} {
|
||||
required = append(required, fileFeatures(filename)...)
|
||||
}
|
||||
sort.Strings(required)
|
||||
|
||||
var optional = make(map[string]bool) // feature => true
|
||||
if *nextFile != "" {
|
||||
for _, feature := range fileFeatures(*nextFile) {
|
||||
optional[feature] = true
|
||||
}
|
||||
}
|
||||
|
||||
take := func(sl *[]string) string {
|
||||
s := (*sl)[0]
|
||||
*sl = (*sl)[1:]
|
||||
return s
|
||||
}
|
||||
|
||||
for len(required) > 0 || len(features) > 0 {
|
||||
switch {
|
||||
case len(features) == 0 || required[0] < features[0]:
|
||||
fmt.Fprintf(bw, "-%s\n", take(&required))
|
||||
fail = true // broke compatibility
|
||||
case len(required) == 0 || required[0] > features[0]:
|
||||
newFeature := take(&features)
|
||||
if optional[newFeature] {
|
||||
// Known added feature to the upcoming release.
|
||||
// Delete it from the map so we can detect any upcoming features
|
||||
// which were never seen. (so we can clean up the nextFile)
|
||||
delete(optional, newFeature)
|
||||
} else {
|
||||
fmt.Fprintf(bw, "+%s\n", newFeature)
|
||||
if !*allowNew {
|
||||
fail = true // we're in lock-down mode for next release
|
||||
}
|
||||
}
|
||||
default:
|
||||
take(&required)
|
||||
take(&features)
|
||||
}
|
||||
}
|
||||
|
||||
var missing []string
|
||||
for feature := range optional {
|
||||
missing = append(missing, feature)
|
||||
}
|
||||
sort.Strings(missing)
|
||||
for _, feature := range missing {
|
||||
fmt.Fprintf(bw, "(in next file, but not in API) -%s\n", feature)
|
||||
}
|
||||
}
|
||||
|
||||
func fileFeatures(filename string) []string {
|
||||
bs, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file %s: %v", filename, err)
|
||||
}
|
||||
text := strings.TrimSpace(string(bs))
|
||||
if text == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(text, "\n")
|
||||
}
|
||||
|
||||
// pkgSymbol represents a symbol in a package
|
||||
|
||||
@@ -175,7 +175,10 @@ evconst(Node *n)
|
||||
break;
|
||||
|
||||
case OLSHR:
|
||||
v = (uvlong)l->vconst >> r->vconst;
|
||||
if(l->type->width != sizeof(uvlong))
|
||||
v = ((uvlong)l->vconst & 0xffffffffULL) >> r->vconst;
|
||||
else
|
||||
v = (uvlong)l->vconst >> r->vconst;
|
||||
break;
|
||||
|
||||
case OASHR:
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -33,9 +34,8 @@ type Package struct {
|
||||
GccOptions []string
|
||||
CgoFlags map[string]string // #cgo flags (CFLAGS, LDFLAGS)
|
||||
Written map[string]bool
|
||||
Name map[string]*Name // accumulated Name from Files
|
||||
Typedef map[string]ast.Expr // accumulated Typedef from Files
|
||||
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
|
||||
Name map[string]*Name // accumulated Name from Files
|
||||
ExpFunc []*ExpFunc // accumulated ExpFunc from Files
|
||||
Decl []ast.Decl
|
||||
GoFiles []string // list of Go files
|
||||
GccFiles []string // list of gcc output files
|
||||
@@ -51,7 +51,15 @@ type File struct {
|
||||
Ref []*Ref // all references to C.xxx in AST
|
||||
ExpFunc []*ExpFunc // exported functions for this file
|
||||
Name map[string]*Name // map from Go name to Name
|
||||
Typedef map[string]ast.Expr // translations of all necessary types from C
|
||||
}
|
||||
|
||||
func nameKeys(m map[string]*Name) []string {
|
||||
var ks []string
|
||||
for k := range m {
|
||||
ks = append(ks, k)
|
||||
}
|
||||
sort.Strings(ks)
|
||||
return ks
|
||||
}
|
||||
|
||||
// A Ref refers to an expression of the form C.xxx in the AST.
|
||||
|
||||
@@ -71,7 +71,8 @@ func (p *Package) writeDefs() {
|
||||
}
|
||||
|
||||
cVars := make(map[string]bool)
|
||||
for _, n := range p.Name {
|
||||
for _, key := range nameKeys(p.Name) {
|
||||
n := p.Name[key]
|
||||
if n.Kind != "var" {
|
||||
continue
|
||||
}
|
||||
@@ -94,14 +95,16 @@ func (p *Package) writeDefs() {
|
||||
}
|
||||
fmt.Fprintf(fc, "\n")
|
||||
|
||||
for _, n := range p.Name {
|
||||
for _, key := range nameKeys(p.Name) {
|
||||
n := p.Name[key]
|
||||
if n.Const != "" {
|
||||
fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(fgo2, "\n")
|
||||
|
||||
for _, n := range p.Name {
|
||||
for _, key := range nameKeys(p.Name) {
|
||||
n := p.Name[key]
|
||||
if n.FuncType != nil {
|
||||
p.writeDefsFunc(fc, fgo2, n)
|
||||
}
|
||||
@@ -372,7 +375,8 @@ func (p *Package) writeOutput(f *File, srcfile string) {
|
||||
fmt.Fprintf(fgcc, "%s\n", f.Preamble)
|
||||
fmt.Fprintf(fgcc, "%s\n", gccProlog)
|
||||
|
||||
for _, n := range f.Name {
|
||||
for _, key := range nameKeys(f.Name) {
|
||||
n := f.Name[key]
|
||||
if n.FuncType != nil {
|
||||
p.writeOutputFunc(fgcc, n)
|
||||
}
|
||||
@@ -736,25 +740,23 @@ func c(repr string, args ...interface{}) *TypeRepr {
|
||||
|
||||
// Map predeclared Go types to Type.
|
||||
var goTypes = map[string]*Type{
|
||||
"bool": {Size: 1, Align: 1, C: c("uchar")},
|
||||
"byte": {Size: 1, Align: 1, C: c("uchar")},
|
||||
"int": {Size: 4, Align: 4, C: c("int")},
|
||||
"uint": {Size: 4, Align: 4, C: c("uint")},
|
||||
"rune": {Size: 4, Align: 4, C: c("int")},
|
||||
"int8": {Size: 1, Align: 1, C: c("schar")},
|
||||
"uint8": {Size: 1, Align: 1, C: c("uchar")},
|
||||
"int16": {Size: 2, Align: 2, C: c("short")},
|
||||
"uint16": {Size: 2, Align: 2, C: c("ushort")},
|
||||
"int32": {Size: 4, Align: 4, C: c("int")},
|
||||
"uint32": {Size: 4, Align: 4, C: c("uint")},
|
||||
"int64": {Size: 8, Align: 8, C: c("int64")},
|
||||
"uint64": {Size: 8, Align: 8, C: c("uint64")},
|
||||
"float": {Size: 4, Align: 4, C: c("float")},
|
||||
"float32": {Size: 4, Align: 4, C: c("float")},
|
||||
"float64": {Size: 8, Align: 8, C: c("double")},
|
||||
"complex": {Size: 8, Align: 8, C: c("__complex float")},
|
||||
"complex64": {Size: 8, Align: 8, C: c("__complex float")},
|
||||
"complex128": {Size: 16, Align: 16, C: c("__complex double")},
|
||||
"bool": {Size: 1, Align: 1, C: c("GoUint8")},
|
||||
"byte": {Size: 1, Align: 1, C: c("GoUint8")},
|
||||
"int": {Size: 4, Align: 4, C: c("GoInt")},
|
||||
"uint": {Size: 4, Align: 4, C: c("GoUint")},
|
||||
"rune": {Size: 4, Align: 4, C: c("GoInt32")},
|
||||
"int8": {Size: 1, Align: 1, C: c("GoInt8")},
|
||||
"uint8": {Size: 1, Align: 1, C: c("GoUint8")},
|
||||
"int16": {Size: 2, Align: 2, C: c("GoInt16")},
|
||||
"uint16": {Size: 2, Align: 2, C: c("GoUint16")},
|
||||
"int32": {Size: 4, Align: 4, C: c("GoInt32")},
|
||||
"uint32": {Size: 4, Align: 4, C: c("GoUint32")},
|
||||
"int64": {Size: 8, Align: 8, C: c("GoInt64")},
|
||||
"uint64": {Size: 8, Align: 8, C: c("GoUint64")},
|
||||
"float32": {Size: 4, Align: 4, C: c("GoFloat32")},
|
||||
"float64": {Size: 8, Align: 8, C: c("GoFloat64")},
|
||||
"complex64": {Size: 8, Align: 8, C: c("GoComplex64")},
|
||||
"complex128": {Size: 16, Align: 16, C: c("GoComplex128")},
|
||||
}
|
||||
|
||||
// Map an ast type to a Type.
|
||||
@@ -799,7 +801,7 @@ func (p *Package) cgoType(e ast.Expr) *Type {
|
||||
return def
|
||||
}
|
||||
if t.Name == "uintptr" {
|
||||
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("uintptr")}
|
||||
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")}
|
||||
}
|
||||
if t.Name == "string" {
|
||||
return &Type{Size: p.PtrSize + 4, Align: p.PtrSize, C: c("GoString")}
|
||||
@@ -930,13 +932,21 @@ Slice GoBytes(char *p, int n) {
|
||||
`
|
||||
|
||||
const gccExportHeaderProlog = `
|
||||
typedef unsigned int uint;
|
||||
typedef signed char schar;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
typedef __SIZE_TYPE__ uintptr;
|
||||
typedef int GoInt;
|
||||
typedef unsigned int GoUint;
|
||||
typedef signed char GoInt8;
|
||||
typedef unsigned char GoUint8;
|
||||
typedef short GoInt16;
|
||||
typedef unsigned short GoUint16;
|
||||
typedef int GoInt32;
|
||||
typedef unsigned int GoUint32;
|
||||
typedef long long GoInt64;
|
||||
typedef unsigned long long GoUint64;
|
||||
typedef __SIZE_TYPE__ GoUintptr;
|
||||
typedef float GoFloat32;
|
||||
typedef double GoFloat64;
|
||||
typedef __complex float GoComplex64;
|
||||
typedef __complex double GoComplex128;
|
||||
|
||||
typedef struct { char *p; int n; } GoString;
|
||||
typedef void *GoMap;
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# 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.
|
||||
|
||||
include ../../Make.dist
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2009 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.
|
||||
|
||||
/*
|
||||
|
||||
Cov is a rudimentary code coverage tool.
|
||||
|
||||
Usage:
|
||||
go tool cov [-lsv] [-g substring] [-m minlines] [6.out args]
|
||||
|
||||
Given a command to run, it runs the command while tracking which
|
||||
sections of code have been executed. When the command finishes,
|
||||
cov prints the line numbers of sections of code in the binary that
|
||||
were not executed. With no arguments it assumes the command "6.out".
|
||||
|
||||
|
||||
The options are:
|
||||
|
||||
-l
|
||||
print full path names instead of paths relative to the current directory
|
||||
-s
|
||||
show the source code that didn't execute, in addition to the line numbers.
|
||||
-v
|
||||
print debugging information during the run.
|
||||
-g substring
|
||||
restrict the coverage analysis to functions or files whose names contain substring
|
||||
-m minlines
|
||||
only report uncovered sections of code larger than minlines lines
|
||||
|
||||
The program is the same for all architectures: 386, amd64, and arm.
|
||||
|
||||
*/
|
||||
package documentation
|
||||
@@ -1,480 +0,0 @@
|
||||
// Copyright 2009 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.
|
||||
|
||||
/*
|
||||
* code coverage
|
||||
*/
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "tree.h"
|
||||
|
||||
#include <ureg_amd64.h>
|
||||
#include <mach.h>
|
||||
typedef struct Ureg Ureg;
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: cov [-lsv] [-g substring] [-m minlines] [6.out args...]\n");
|
||||
fprint(2, "-g specifies pattern of interesting functions or files\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
typedef struct Range Range;
|
||||
struct Range
|
||||
{
|
||||
uvlong pc;
|
||||
uvlong epc;
|
||||
};
|
||||
|
||||
int chatty;
|
||||
int fd;
|
||||
int longnames;
|
||||
int pid;
|
||||
int doshowsrc;
|
||||
Map *mem;
|
||||
Map *text;
|
||||
Fhdr fhdr;
|
||||
char *substring;
|
||||
char cwd[1000];
|
||||
int ncwd;
|
||||
int minlines = -1000;
|
||||
|
||||
Tree breakpoints; // code ranges not run
|
||||
|
||||
/*
|
||||
* comparison for Range structures
|
||||
* they are "equal" if they overlap, so
|
||||
* that a search for [pc, pc+1) finds the
|
||||
* Range containing pc.
|
||||
*/
|
||||
int
|
||||
rangecmp(void *va, void *vb)
|
||||
{
|
||||
Range *a = va, *b = vb;
|
||||
if(a->epc <= b->pc)
|
||||
return 1;
|
||||
if(b->epc <= a->pc)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* remember that we ran the section of code [pc, epc).
|
||||
*/
|
||||
void
|
||||
ran(uvlong pc, uvlong epc)
|
||||
{
|
||||
Range key;
|
||||
Range *r;
|
||||
uvlong oldepc;
|
||||
|
||||
if(chatty)
|
||||
print("run %#llux-%#llux\n", pc, epc);
|
||||
|
||||
key.pc = pc;
|
||||
key.epc = pc+1;
|
||||
r = treeget(&breakpoints, &key);
|
||||
if(r == nil)
|
||||
sysfatal("unchecked breakpoint at %#llux+%d", pc, (int)(epc-pc));
|
||||
|
||||
// Might be that the tail of the sequence
|
||||
// was run already, so r->epc is before the end.
|
||||
// Adjust len.
|
||||
if(epc > r->epc)
|
||||
epc = r->epc;
|
||||
|
||||
if(r->pc == pc) {
|
||||
r->pc = epc;
|
||||
} else {
|
||||
// Chop r to before pc;
|
||||
// add new entry for after if needed.
|
||||
// Changing r->epc does not affect r's position in the tree.
|
||||
oldepc = r->epc;
|
||||
r->epc = pc;
|
||||
if(epc < oldepc) {
|
||||
Range *n;
|
||||
n = malloc(sizeof *n);
|
||||
n->pc = epc;
|
||||
n->epc = oldepc;
|
||||
treeput(&breakpoints, n, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
showsrc(char *file, int line1, int line2)
|
||||
{
|
||||
Biobuf *b;
|
||||
char *p;
|
||||
int n, stop;
|
||||
|
||||
if((b = Bopen(file, OREAD)) == nil) {
|
||||
print("\topen %s: %r\n", file);
|
||||
return;
|
||||
}
|
||||
|
||||
for(n=1; n<line1 && (p = Brdstr(b, '\n', 1)) != nil; n++)
|
||||
free(p);
|
||||
|
||||
// print up to five lines (this one and 4 more).
|
||||
// if there are more than five lines, print 4 and "..."
|
||||
stop = n+4;
|
||||
if(stop > line2)
|
||||
stop = line2;
|
||||
if(stop < line2)
|
||||
stop--;
|
||||
for(; n<=stop && (p = Brdstr(b, '\n', 1)) != nil; n++) {
|
||||
print(" %d %s\n", n, p);
|
||||
free(p);
|
||||
}
|
||||
if(n < line2)
|
||||
print(" ...\n");
|
||||
Bterm(b);
|
||||
}
|
||||
|
||||
/*
|
||||
* if s is in the current directory or below,
|
||||
* return the relative path.
|
||||
*/
|
||||
char*
|
||||
shortname(char *s)
|
||||
{
|
||||
if(!longnames && strlen(s) > ncwd && memcmp(s, cwd, ncwd) == 0 && s[ncwd] == '/')
|
||||
return s+ncwd+1;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* we've decided that [pc, epc) did not run.
|
||||
* do something about it.
|
||||
*/
|
||||
void
|
||||
missing(uvlong pc, uvlong epc)
|
||||
{
|
||||
char file[1000];
|
||||
int line1, line2;
|
||||
char buf[100];
|
||||
Symbol s;
|
||||
char *p;
|
||||
uvlong uv;
|
||||
|
||||
if(!findsym(pc, CTEXT, &s) || !fileline(file, sizeof file, pc)) {
|
||||
notfound:
|
||||
print("%#llux-%#llux\n", pc, epc);
|
||||
return;
|
||||
}
|
||||
p = strrchr(file, ':');
|
||||
*p++ = 0;
|
||||
line1 = atoi(p);
|
||||
for(uv=pc; uv<epc; ) {
|
||||
if(!fileline(file, sizeof file, epc-2))
|
||||
goto notfound;
|
||||
uv += machdata->instsize(text, uv);
|
||||
}
|
||||
p = strrchr(file, ':');
|
||||
*p++ = 0;
|
||||
line2 = atoi(p);
|
||||
|
||||
if(line2+1-line2 < minlines)
|
||||
return;
|
||||
|
||||
if(pc == s.value) {
|
||||
// never entered function
|
||||
print("%s:%d %s never called (%#llux-%#llux)\n", shortname(file), line1, s.name, pc, epc);
|
||||
return;
|
||||
}
|
||||
if(pc <= s.value+13) {
|
||||
// probably stub for stack growth.
|
||||
// check whether last instruction is call to morestack.
|
||||
// the -5 below is the length of
|
||||
// CALL sys.morestack.
|
||||
buf[0] = 0;
|
||||
machdata->das(text, epc-5, 0, buf, sizeof buf);
|
||||
if(strstr(buf, "morestack"))
|
||||
return;
|
||||
}
|
||||
|
||||
if(epc - pc == 5) {
|
||||
// check for CALL sys.panicindex
|
||||
buf[0] = 0;
|
||||
machdata->das(text, pc, 0, buf, sizeof buf);
|
||||
if(strstr(buf, "panicindex"))
|
||||
return;
|
||||
}
|
||||
|
||||
if(epc - pc == 2 || epc -pc == 3) {
|
||||
// check for XORL inside shift.
|
||||
// (on x86 have to implement large left or unsigned right shift with explicit zeroing).
|
||||
// f+90 0x00002c9f CMPL CX,$20
|
||||
// f+93 0x00002ca2 JCS f+97(SB)
|
||||
// f+95 0x00002ca4 XORL AX,AX <<<
|
||||
// f+97 0x00002ca6 SHLL CL,AX
|
||||
// f+99 0x00002ca8 MOVL $1,CX
|
||||
//
|
||||
// f+c8 0x00002cd7 CMPL CX,$40
|
||||
// f+cb 0x00002cda JCS f+d0(SB)
|
||||
// f+cd 0x00002cdc XORQ AX,AX <<<
|
||||
// f+d0 0x00002cdf SHLQ CL,AX
|
||||
// f+d3 0x00002ce2 MOVQ $1,CX
|
||||
buf[0] = 0;
|
||||
machdata->das(text, pc, 0, buf, sizeof buf);
|
||||
if(strncmp(buf, "XOR", 3) == 0) {
|
||||
machdata->das(text, epc, 0, buf, sizeof buf);
|
||||
if(strncmp(buf, "SHL", 3) == 0 || strncmp(buf, "SHR", 3) == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(epc - pc == 3) {
|
||||
// check for SAR inside shift.
|
||||
// (on x86 have to implement large signed right shift as >>31).
|
||||
// f+36 0x00016216 CMPL CX,$20
|
||||
// f+39 0x00016219 JCS f+3e(SB)
|
||||
// f+3b 0x0001621b SARL $1f,AX <<<
|
||||
// f+3e 0x0001621e SARL CL,AX
|
||||
// f+40 0x00016220 XORL CX,CX
|
||||
// f+42 0x00016222 CMPL CX,AX
|
||||
buf[0] = 0;
|
||||
machdata->das(text, pc, 0, buf, sizeof buf);
|
||||
if(strncmp(buf, "SAR", 3) == 0) {
|
||||
machdata->das(text, epc, 0, buf, sizeof buf);
|
||||
if(strncmp(buf, "SAR", 3) == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// show first instruction to make clear where we were.
|
||||
machdata->das(text, pc, 0, buf, sizeof buf);
|
||||
|
||||
if(line1 != line2)
|
||||
print("%s:%d,%d %#llux-%#llux %s\n",
|
||||
shortname(file), line1, line2, pc, epc, buf);
|
||||
else
|
||||
print("%s:%d %#llux-%#llux %s\n",
|
||||
shortname(file), line1, pc, epc, buf);
|
||||
if(doshowsrc)
|
||||
showsrc(file, line1, line2);
|
||||
}
|
||||
|
||||
/*
|
||||
* walk the tree, calling missing for each non-empty
|
||||
* section of missing code.
|
||||
*/
|
||||
void
|
||||
walktree(TreeNode *t)
|
||||
{
|
||||
Range *n;
|
||||
|
||||
if(t == nil)
|
||||
return;
|
||||
walktree(t->left);
|
||||
n = t->key;
|
||||
if(n->pc < n->epc)
|
||||
missing(n->pc, n->epc);
|
||||
walktree(t->right);
|
||||
}
|
||||
|
||||
/*
|
||||
* set a breakpoint all over [pc, epc)
|
||||
* and remember that we did.
|
||||
*/
|
||||
void
|
||||
breakpoint(uvlong pc, uvlong epc)
|
||||
{
|
||||
Range *r;
|
||||
|
||||
r = malloc(sizeof *r);
|
||||
r->pc = pc;
|
||||
r->epc = epc;
|
||||
treeput(&breakpoints, r, r);
|
||||
|
||||
for(; pc < epc; pc+=machdata->bpsize)
|
||||
put1(mem, pc, machdata->bpinst, machdata->bpsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* install breakpoints over all text symbols
|
||||
* that match the pattern.
|
||||
*/
|
||||
void
|
||||
cover(void)
|
||||
{
|
||||
Symbol s;
|
||||
char *lastfn;
|
||||
uvlong lastpc;
|
||||
int i;
|
||||
char buf[200];
|
||||
|
||||
lastfn = nil;
|
||||
lastpc = 0;
|
||||
for(i=0; textsym(&s, i); i++) {
|
||||
switch(s.type) {
|
||||
case 'T':
|
||||
case 't':
|
||||
if(lastpc != 0) {
|
||||
breakpoint(lastpc, s.value);
|
||||
lastpc = 0;
|
||||
}
|
||||
// Ignore second entry for a given name;
|
||||
// that's the debugging blob.
|
||||
if(lastfn && strcmp(s.name, lastfn) == 0)
|
||||
break;
|
||||
lastfn = s.name;
|
||||
buf[0] = 0;
|
||||
fileline(buf, sizeof buf, s.value);
|
||||
if(substring == nil || strstr(buf, substring) || strstr(s.name, substring))
|
||||
lastpc = s.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uvlong
|
||||
rgetzero(Map *map, char *reg)
|
||||
{
|
||||
USED(map);
|
||||
USED(reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove the breakpoints at pc and successive instructions,
|
||||
* up to and including the first jump or other control flow transfer.
|
||||
*/
|
||||
void
|
||||
uncover(uvlong pc)
|
||||
{
|
||||
uchar buf[1000];
|
||||
int n, n1, n2;
|
||||
uvlong foll[2];
|
||||
|
||||
// Double-check that we stopped at a breakpoint.
|
||||
if(get1(mem, pc, buf, machdata->bpsize) < 0)
|
||||
sysfatal("read mem inst at %#llux: %r", pc);
|
||||
if(memcmp(buf, machdata->bpinst, machdata->bpsize) != 0)
|
||||
sysfatal("stopped at %#llux; not at breakpoint %d", pc, machdata->bpsize);
|
||||
|
||||
// Figure out how many bytes of straight-line code
|
||||
// there are in the text starting at pc.
|
||||
n = 0;
|
||||
while(n < sizeof buf) {
|
||||
n1 = machdata->instsize(text, pc+n);
|
||||
if(n+n1 > sizeof buf)
|
||||
break;
|
||||
n2 = machdata->foll(text, pc+n, rgetzero, foll);
|
||||
n += n1;
|
||||
if(n2 != 1 || foll[0] != pc+n)
|
||||
break;
|
||||
}
|
||||
|
||||
// Record that this section of code ran.
|
||||
ran(pc, pc+n);
|
||||
|
||||
// Put original instructions back.
|
||||
if(get1(text, pc, buf, n) < 0)
|
||||
sysfatal("get1: %r");
|
||||
if(put1(mem, pc, buf, n) < 0)
|
||||
sysfatal("put1: %r");
|
||||
}
|
||||
|
||||
int
|
||||
startprocess(char **argv)
|
||||
{
|
||||
int pid;
|
||||
|
||||
if((pid = fork()) < 0)
|
||||
sysfatal("fork: %r");
|
||||
if(pid == 0) {
|
||||
pid = getpid();
|
||||
if(ctlproc(pid, "hang") < 0)
|
||||
sysfatal("ctlproc hang: %r");
|
||||
exec(argv[0], argv);
|
||||
sysfatal("exec %s: %r", argv[0]);
|
||||
}
|
||||
if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0)
|
||||
sysfatal("attach %d %s: %r", pid, argv[0]);
|
||||
return pid;
|
||||
}
|
||||
|
||||
int
|
||||
go(void)
|
||||
{
|
||||
uvlong pc;
|
||||
char buf[100];
|
||||
int n;
|
||||
|
||||
for(n = 0;; n++) {
|
||||
ctlproc(pid, "startstop");
|
||||
if(get8(mem, offsetof(Ureg, ip), &pc) < 0) {
|
||||
rerrstr(buf, sizeof buf);
|
||||
if(strstr(buf, "exited") || strstr(buf, "No such process"))
|
||||
return n;
|
||||
sysfatal("cannot read pc: %r");
|
||||
}
|
||||
pc--;
|
||||
if(put8(mem, offsetof(Ureg, ip), pc) < 0)
|
||||
sysfatal("cannot write pc: %r");
|
||||
uncover(pc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int n;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'g':
|
||||
substring = EARGF(usage());
|
||||
break;
|
||||
case 'l':
|
||||
longnames++;
|
||||
break;
|
||||
case 'n':
|
||||
minlines = atoi(EARGF(usage()));
|
||||
break;
|
||||
case 's':
|
||||
doshowsrc = 1;
|
||||
break;
|
||||
case 'v':
|
||||
chatty++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
getwd(cwd, sizeof cwd);
|
||||
ncwd = strlen(cwd);
|
||||
|
||||
if(argc == 0) {
|
||||
*--argv = "6.out";
|
||||
}
|
||||
fd = open(argv[0], OREAD);
|
||||
if(fd < 0)
|
||||
sysfatal("open %s: %r", argv[0]);
|
||||
if(crackhdr(fd, &fhdr) <= 0)
|
||||
sysfatal("crackhdr: %r");
|
||||
machbytype(fhdr.type);
|
||||
if(syminit(fd, &fhdr) <= 0)
|
||||
sysfatal("syminit: %r");
|
||||
text = loadmap(nil, fd, &fhdr);
|
||||
if(text == nil)
|
||||
sysfatal("loadmap: %r");
|
||||
pid = startprocess(argv);
|
||||
mem = attachproc(pid, &fhdr);
|
||||
if(mem == nil)
|
||||
sysfatal("attachproc: %r");
|
||||
breakpoints.cmp = rangecmp;
|
||||
cover();
|
||||
n = go();
|
||||
walktree(breakpoints.root);
|
||||
if(chatty)
|
||||
print("%d breakpoints\n", n);
|
||||
detachproc(mem);
|
||||
exits(0);
|
||||
}
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
// Renamed from Map to Tree to avoid conflict with libmach.
|
||||
|
||||
/*
|
||||
Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
|
||||
Massachusetts Institute of Technology
|
||||
Portions Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Mutable map structure, but still based on
|
||||
// Okasaki, Red Black Trees in a Functional Setting, JFP 1999,
|
||||
// which is a lot easier than the traditional red-black
|
||||
// and plenty fast enough for me. (Also I could copy
|
||||
// and edit fmap.c.)
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include "tree.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Red = 0,
|
||||
Black = 1
|
||||
};
|
||||
|
||||
|
||||
// Red-black trees are binary trees with this property:
|
||||
// 1. No red node has a red parent.
|
||||
// 2. Every path from the root to a leaf contains the
|
||||
// same number of black nodes.
|
||||
|
||||
static TreeNode*
|
||||
rwTreeNode(TreeNode *p, int color, TreeNode *left, void *key, void *value, TreeNode *right)
|
||||
{
|
||||
if(p == nil)
|
||||
p = malloc(sizeof *p);
|
||||
p->color = color;
|
||||
p->left = left;
|
||||
p->key = key;
|
||||
p->value = value;
|
||||
p->right = right;
|
||||
return p;
|
||||
}
|
||||
|
||||
static TreeNode*
|
||||
balance(TreeNode *m0)
|
||||
{
|
||||
void *xk, *xv, *yk, *yv, *zk, *zv;
|
||||
TreeNode *a, *b, *c, *d;
|
||||
TreeNode *m1, *m2;
|
||||
int color;
|
||||
TreeNode *left, *right;
|
||||
void *key, *value;
|
||||
|
||||
color = m0->color;
|
||||
left = m0->left;
|
||||
key = m0->key;
|
||||
value = m0->value;
|
||||
right = m0->right;
|
||||
|
||||
// Okasaki notation: (T is mkTreeNode, B is Black, R is Red, x, y, z are key-value.
|
||||
//
|
||||
// balance B (T R (T R a x b) y c) z d
|
||||
// balance B (T R a x (T R b y c)) z d
|
||||
// balance B a x (T R (T R b y c) z d)
|
||||
// balance B a x (T R b y (T R c z d))
|
||||
//
|
||||
// = T R (T B a x b) y (T B c z d)
|
||||
|
||||
if(color == Black){
|
||||
if(left && left->color == Red){
|
||||
if(left->left && left->left->color == Red){
|
||||
a = left->left->left;
|
||||
xk = left->left->key;
|
||||
xv = left->left->value;
|
||||
b = left->left->right;
|
||||
yk = left->key;
|
||||
yv = left->value;
|
||||
c = left->right;
|
||||
zk = key;
|
||||
zv = value;
|
||||
d = right;
|
||||
m1 = left;
|
||||
m2 = left->left;
|
||||
goto hard;
|
||||
}else if(left->right && left->right->color == Red){
|
||||
a = left->left;
|
||||
xk = left->key;
|
||||
xv = left->value;
|
||||
b = left->right->left;
|
||||
yk = left->right->key;
|
||||
yv = left->right->value;
|
||||
c = left->right->right;
|
||||
zk = key;
|
||||
zv = value;
|
||||
d = right;
|
||||
m1 = left;
|
||||
m2 = left->right;
|
||||
goto hard;
|
||||
}
|
||||
}else if(right && right->color == Red){
|
||||
if(right->left && right->left->color == Red){
|
||||
a = left;
|
||||
xk = key;
|
||||
xv = value;
|
||||
b = right->left->left;
|
||||
yk = right->left->key;
|
||||
yv = right->left->value;
|
||||
c = right->left->right;
|
||||
zk = right->key;
|
||||
zv = right->value;
|
||||
d = right->right;
|
||||
m1 = right;
|
||||
m2 = right->left;
|
||||
goto hard;
|
||||
}else if(right->right && right->right->color == Red){
|
||||
a = left;
|
||||
xk = key;
|
||||
xv = value;
|
||||
b = right->left;
|
||||
yk = right->key;
|
||||
yv = right->value;
|
||||
c = right->right->left;
|
||||
zk = right->right->key;
|
||||
zv = right->right->value;
|
||||
d = right->right->right;
|
||||
m1 = right;
|
||||
m2 = right->right;
|
||||
goto hard;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rwTreeNode(m0, color, left, key, value, right);
|
||||
|
||||
hard:
|
||||
return rwTreeNode(m0, Red, rwTreeNode(m1, Black, a, xk, xv, b),
|
||||
yk, yv, rwTreeNode(m2, Black, c, zk, zv, d));
|
||||
}
|
||||
|
||||
static TreeNode*
|
||||
ins0(TreeNode *p, void *k, void *v, TreeNode *rw)
|
||||
{
|
||||
if(p == nil)
|
||||
return rwTreeNode(rw, Red, nil, k, v, nil);
|
||||
if(p->key == k){
|
||||
if(rw)
|
||||
return rwTreeNode(rw, p->color, p->left, k, v, p->right);
|
||||
p->value = v;
|
||||
return p;
|
||||
}
|
||||
if(p->key < k)
|
||||
p->left = ins0(p->left, k, v, rw);
|
||||
else
|
||||
p->right = ins0(p->right, k, v, rw);
|
||||
return balance(p);
|
||||
}
|
||||
|
||||
static TreeNode*
|
||||
ins1(Tree *m, TreeNode *p, void *k, void *v, TreeNode *rw)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(p == nil)
|
||||
return rwTreeNode(rw, Red, nil, k, v, nil);
|
||||
i = m->cmp(p->key, k);
|
||||
if(i == 0){
|
||||
if(rw)
|
||||
return rwTreeNode(rw, p->color, p->left, k, v, p->right);
|
||||
p->value = v;
|
||||
return p;
|
||||
}
|
||||
if(i < 0)
|
||||
p->left = ins1(m, p->left, k, v, rw);
|
||||
else
|
||||
p->right = ins1(m, p->right, k, v, rw);
|
||||
return balance(p);
|
||||
}
|
||||
|
||||
void
|
||||
treeputelem(Tree *m, void *key, void *val, TreeNode *rw)
|
||||
{
|
||||
if(m->cmp)
|
||||
m->root = ins1(m, m->root, key, val, rw);
|
||||
else
|
||||
m->root = ins0(m->root, key, val, rw);
|
||||
}
|
||||
|
||||
void
|
||||
treeput(Tree *m, void *key, void *val)
|
||||
{
|
||||
treeputelem(m, key, val, nil);
|
||||
}
|
||||
|
||||
void*
|
||||
treeget(Tree *m, void *key)
|
||||
{
|
||||
int i;
|
||||
TreeNode *p;
|
||||
|
||||
p = m->root;
|
||||
if(m->cmp){
|
||||
for(;;){
|
||||
if(p == nil)
|
||||
return nil;
|
||||
i = m->cmp(p->key, key);
|
||||
if(i < 0)
|
||||
p = p->left;
|
||||
else if(i > 0)
|
||||
p = p->right;
|
||||
else
|
||||
return p->value;
|
||||
}
|
||||
}else{
|
||||
for(;;){
|
||||
if(p == nil)
|
||||
return nil;
|
||||
if(p->key == key)
|
||||
return p->value;
|
||||
if(p->key < key)
|
||||
p = p->left;
|
||||
else
|
||||
p = p->right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// Renamed from Map to Tree to avoid conflict with libmach.
|
||||
|
||||
/*
|
||||
Copyright (c) 2003-2007 Russ Cox, Tom Bergan, Austin Clements,
|
||||
Massachusetts Institute of Technology
|
||||
Portions Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
typedef struct Tree Tree;
|
||||
typedef struct TreeNode TreeNode;
|
||||
struct Tree
|
||||
{
|
||||
int (*cmp)(void*, void*);
|
||||
TreeNode *root;
|
||||
};
|
||||
|
||||
struct TreeNode
|
||||
{
|
||||
int color;
|
||||
TreeNode *left;
|
||||
void *key;
|
||||
void *value;
|
||||
TreeNode *right;
|
||||
};
|
||||
|
||||
void *treeget(Tree*, void*);
|
||||
void treeput(Tree*, void*, void*);
|
||||
void treeputelem(Tree*, void*, void*, TreeNode*);
|
||||
22
src/cmd/dist/build.c
vendored
22
src/cmd/dist/build.c
vendored
@@ -19,7 +19,7 @@ char *goos;
|
||||
char *goroot = GOROOT_FINAL;
|
||||
char *goroot_final = GOROOT_FINAL;
|
||||
char *workdir;
|
||||
char *tooldir;
|
||||
char *tooldir;
|
||||
char *gochar;
|
||||
char *goversion;
|
||||
char *slash; // / for unix, \ for windows
|
||||
@@ -1230,6 +1230,15 @@ clean(void)
|
||||
xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
|
||||
}
|
||||
|
||||
// remove src/pkg/runtime/z* unconditionally
|
||||
vreset(&dir);
|
||||
bpathf(&path, "%s/src/pkg/runtime", goroot);
|
||||
xreaddir(&dir, bstr(&path));
|
||||
for(j=0; j<dir.len; j++) {
|
||||
if(hasprefix(dir.p[j], "z"))
|
||||
xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
|
||||
}
|
||||
|
||||
if(rebuildall) {
|
||||
// Remove object tree.
|
||||
xremoveall(bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch));
|
||||
@@ -1462,7 +1471,7 @@ void
|
||||
cmdbanner(int argc, char **argv)
|
||||
{
|
||||
char *pathsep;
|
||||
Buf b, b1, search;
|
||||
Buf b, b1, search, path;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'v':
|
||||
@@ -1478,6 +1487,7 @@ cmdbanner(int argc, char **argv)
|
||||
binit(&b);
|
||||
binit(&b1);
|
||||
binit(&search);
|
||||
binit(&path);
|
||||
|
||||
xprintf("\n");
|
||||
xprintf("---\n");
|
||||
@@ -1495,9 +1505,10 @@ cmdbanner(int argc, char **argv)
|
||||
xprintf("*** You need to add %s to your PATH.\n", gobin);
|
||||
|
||||
if(streq(gohostos, "darwin")) {
|
||||
xprintf("\n"
|
||||
"On OS X the debuggers must be installed setgid procmod.\n"
|
||||
"Read and run ./sudo.bash to install the debuggers.\n");
|
||||
if(isfile(bpathf(&path, "%s/cov", tooldir)))
|
||||
xprintf("\n"
|
||||
"On OS X the debuggers must be installed setgid procmod.\n"
|
||||
"Read and run ./sudo.bash to install the debuggers.\n");
|
||||
}
|
||||
|
||||
if(!streq(goroot_final, goroot)) {
|
||||
@@ -1509,6 +1520,7 @@ cmdbanner(int argc, char **argv)
|
||||
bfree(&b);
|
||||
bfree(&b1);
|
||||
bfree(&search);
|
||||
bfree(&path);
|
||||
}
|
||||
|
||||
// Version prints the Go version.
|
||||
|
||||
@@ -432,21 +432,6 @@ oldname(Sym *s)
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* same for types
|
||||
*/
|
||||
Type*
|
||||
newtype(Sym *s)
|
||||
{
|
||||
Type *t;
|
||||
|
||||
t = typ(TFORW);
|
||||
t->sym = s;
|
||||
t->type = T;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* := declarations
|
||||
*/
|
||||
@@ -1311,7 +1296,7 @@ addmethod(Sym *sf, Type *t, int local)
|
||||
}
|
||||
// Should have picked off all the reasons above,
|
||||
// but just in case, fall back to generic error.
|
||||
yyerror("invalid receiver type %T", pa);
|
||||
yyerror("invalid receiver type %T (%lT / %lT)", pa, pa, t);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,9 @@ Flags:
|
||||
-N
|
||||
disable optimizations
|
||||
-S
|
||||
write assembly language text to standard output
|
||||
write assembly language text to standard output (code only)
|
||||
-SS
|
||||
write assembly language text to standard output (code and data)
|
||||
-u
|
||||
disallow importing packages not marked as safe
|
||||
-V
|
||||
|
||||
@@ -131,7 +131,12 @@ escfunc(Node *func)
|
||||
}
|
||||
|
||||
// walk will take the address of cvar->closure later and assign it to cvar.
|
||||
// handle that here by linking a fake oaddr node directly to the closure.
|
||||
// linking a fake oaddr node directly to the closure handles the case
|
||||
// of the closure itself leaking. Following the flow of the value to th
|
||||
// paramref is done in escflow, because if we did that here, it would look
|
||||
// like the original is assigned out of its loop depth, whereas it's just
|
||||
// assigned to something in an inner function. A paramref itself is never
|
||||
// moved to the heap, only its original.
|
||||
for(ll=curfn->cvars; ll; ll=ll->next) {
|
||||
if(ll->n->op == OXXX) // see dcl.c:398
|
||||
continue;
|
||||
@@ -221,16 +226,19 @@ esc(Node *n)
|
||||
if(n->op == OFOR || n->op == ORANGE)
|
||||
loopdepth++;
|
||||
|
||||
esc(n->left);
|
||||
esc(n->right);
|
||||
esc(n->ntest);
|
||||
esc(n->nincr);
|
||||
esclist(n->ninit);
|
||||
esclist(n->nbody);
|
||||
esclist(n->nelse);
|
||||
esclist(n->list);
|
||||
esclist(n->rlist);
|
||||
|
||||
if(n->op == OCLOSURE) {
|
||||
escfunc(n);
|
||||
} else {
|
||||
esc(n->left);
|
||||
esc(n->right);
|
||||
esc(n->ntest);
|
||||
esc(n->nincr);
|
||||
esclist(n->ninit);
|
||||
esclist(n->nbody);
|
||||
esclist(n->nelse);
|
||||
esclist(n->list);
|
||||
esclist(n->rlist);
|
||||
}
|
||||
if(n->op == OFOR || n->op == ORANGE)
|
||||
loopdepth--;
|
||||
|
||||
@@ -379,8 +387,8 @@ esc(Node *n)
|
||||
}
|
||||
break;
|
||||
|
||||
case OADDR:
|
||||
case OCLOSURE:
|
||||
case OADDR:
|
||||
case OMAKECHAN:
|
||||
case OMAKEMAP:
|
||||
case OMAKESLICE:
|
||||
@@ -407,8 +415,8 @@ escassign(Node *dst, Node *src)
|
||||
return;
|
||||
|
||||
if(debug['m'] > 1)
|
||||
print("%L:[%d] %S escassign: %hN = %hN\n", lineno, loopdepth,
|
||||
(curfn && curfn->nname) ? curfn->nname->sym : S, dst, src);
|
||||
print("%L:[%d] %S escassign: %hN(%hJ) = %hN(%hJ)\n", lineno, loopdepth,
|
||||
(curfn && curfn->nname) ? curfn->nname->sym : S, dst, dst, src, src);
|
||||
|
||||
setlineno(dst);
|
||||
|
||||
@@ -467,7 +475,11 @@ escassign(Node *dst, Node *src)
|
||||
case OARRAYLIT:
|
||||
case OMAPLIT:
|
||||
case OSTRUCTLIT:
|
||||
// loopdepth was set in the defining statement or function header
|
||||
case OMAKECHAN:
|
||||
case OMAKEMAP:
|
||||
case OMAKESLICE:
|
||||
case ONEW:
|
||||
case OCLOSURE:
|
||||
escflows(dst, src);
|
||||
break;
|
||||
|
||||
@@ -500,18 +512,6 @@ escassign(Node *dst, Node *src)
|
||||
escassign(dst, src->left);
|
||||
break;
|
||||
|
||||
case OMAKECHAN:
|
||||
case OMAKEMAP:
|
||||
case OMAKESLICE:
|
||||
case ONEW:
|
||||
escflows(dst, src);
|
||||
break;
|
||||
|
||||
case OCLOSURE:
|
||||
escflows(dst, src);
|
||||
escfunc(src);
|
||||
break;
|
||||
|
||||
case OADD:
|
||||
case OSUB:
|
||||
case OOR:
|
||||
@@ -543,7 +543,7 @@ escassign(Node *dst, Node *src)
|
||||
// This is a bit messier than fortunate, pulled out of escassign's big
|
||||
// switch for clarity. We either have the paramnodes, which may be
|
||||
// connected to other things throug flows or we have the parameter type
|
||||
// nodes, which may be marked 'n(ofloworescape)'. Navigating the ast is slightly
|
||||
// nodes, which may be marked "noescape". Navigating the ast is slightly
|
||||
// different for methods vs plain functions and for imported vs
|
||||
// this-package
|
||||
static void
|
||||
@@ -711,8 +711,8 @@ escwalk(int level, Node *dst, Node *src)
|
||||
src->walkgen = walkgen;
|
||||
|
||||
if(debug['m']>1)
|
||||
print("escwalk: level:%d depth:%d %.*s %hN scope:%S[%d]\n",
|
||||
level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src,
|
||||
print("escwalk: level:%d depth:%d %.*s %hN(%hJ) scope:%S[%d]\n",
|
||||
level, pdepth, pdepth, "\t\t\t\t\t\t\t\t\t\t", src, src,
|
||||
(src->curfn && src->curfn->nname) ? src->curfn->nname->sym : S, src->escloopdepth);
|
||||
|
||||
pdepth++;
|
||||
@@ -726,6 +726,16 @@ escwalk(int level, Node *dst, Node *src)
|
||||
if(debug['m'])
|
||||
warnl(src->lineno, "leaking param: %hN", src);
|
||||
}
|
||||
// handle the missing flow ref <- orig
|
||||
// a paramref is automagically dereferenced, and taking its
|
||||
// address produces the address of the original, so all we have to do here
|
||||
// is keep track of the value flow, so level is unchanged.
|
||||
// alternatively, we could have substituted PPARAMREFs with their ->closure in esc/escassign/flow,
|
||||
if(src->class == PPARAMREF) {
|
||||
if(leaks && debug['m'])
|
||||
warnl(src->lineno, "leaking closure reference %hN", src);
|
||||
escwalk(level, dst, src->closure);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTRLIT:
|
||||
|
||||
@@ -647,6 +647,9 @@ cgen_as(Node *nl, Node *nr)
|
||||
dump("cgen_as = ", nr);
|
||||
}
|
||||
|
||||
while(nr != N && nr->op == OCONVNOP)
|
||||
nr = nr->left;
|
||||
|
||||
if(nl == N || isblank(nl)) {
|
||||
cgen_discard(nr);
|
||||
return;
|
||||
|
||||
@@ -182,6 +182,9 @@ struct Type
|
||||
|
||||
int32 maplineno; // first use of TFORW as map key
|
||||
int32 embedlineno; // first use of TFORW as embedded type
|
||||
|
||||
// for TFORW, where to copy the eventual value to
|
||||
NodeList *copyto;
|
||||
};
|
||||
#define T ((Type*)0)
|
||||
|
||||
@@ -940,7 +943,6 @@ Node* methodname(Node *n, Type *t);
|
||||
Node* methodname1(Node *n, Node *t);
|
||||
Sym* methodsym(Sym *nsym, Type *t0, int iface);
|
||||
Node* newname(Sym *s);
|
||||
Type* newtype(Sym *s);
|
||||
Node* oldname(Sym *s);
|
||||
void popdcl(void);
|
||||
void poptodcl(void);
|
||||
@@ -1248,9 +1250,7 @@ int islvalue(Node *n);
|
||||
Node* typecheck(Node **np, int top);
|
||||
void typechecklist(NodeList *l, int top);
|
||||
Node* typecheckdef(Node *n);
|
||||
void resumetypecopy(void);
|
||||
void copytype(Node *n, Type *t);
|
||||
void defertypecopy(Node *n, Type *t);
|
||||
void queuemethod(Node *n);
|
||||
|
||||
/*
|
||||
|
||||
@@ -506,6 +506,19 @@ mkinlcall(Node **np, Node *fn)
|
||||
mkinlcall1(np, fn);
|
||||
safemode = save_safemode;
|
||||
}
|
||||
|
||||
static Node*
|
||||
tinlvar(Type *t)
|
||||
{
|
||||
if(t->nname && !isblank(t->nname)) {
|
||||
if(!t->nname->inlvar)
|
||||
fatal("missing inlvar for %N\n", t->nname);
|
||||
return t->nname->inlvar;
|
||||
}
|
||||
typecheck(&nblank, Erv | Easgn);
|
||||
return nblank;
|
||||
}
|
||||
|
||||
// if *np is a call, and fn is a function with an inlinable body, substitute *np with an OINLCALL.
|
||||
// On return ninit has the parameter assignments, the nbody is the
|
||||
// inlined function body and list, rlist contain the input, output
|
||||
@@ -579,15 +592,12 @@ mkinlcall1(Node **np, Node *fn)
|
||||
fatal("method call without receiver: %+N", n);
|
||||
if(t == T)
|
||||
fatal("method call unknown receiver type: %+N", n);
|
||||
if(t->nname != N && !isblank(t->nname))
|
||||
as = nod(OAS, t->nname->inlvar, n->left->left);
|
||||
else
|
||||
as = nod(OAS, temp(t->type), n->left->left);
|
||||
as = nod(OAS, tinlvar(t), n->left->left);
|
||||
} else { // non-method call to method
|
||||
if (!n->list)
|
||||
if(!n->list)
|
||||
fatal("non-method call to method without first arg: %+N", n);
|
||||
if(t != T && t->nname != N && !isblank(t->nname))
|
||||
as = nod(OAS, t->nname->inlvar, n->list->n);
|
||||
if(t != T)
|
||||
as = nod(OAS, tinlvar(t), n->list->n);
|
||||
}
|
||||
|
||||
if(as != N) {
|
||||
@@ -601,27 +611,16 @@ mkinlcall1(Node **np, Node *fn)
|
||||
// TODO check that n->list->n is a call?
|
||||
// TODO: non-method call to T.meth(f()) where f returns t, args...
|
||||
as->rlist = n->list;
|
||||
for(t = getinargx(fn->type)->type; t; t=t->down) {
|
||||
if(t->nname && !isblank(t->nname)) {
|
||||
if(!t->nname->inlvar)
|
||||
fatal("missing inlvar for %N\n", t->nname);
|
||||
as->list = list(as->list, t->nname->inlvar);
|
||||
} else {
|
||||
as->list = list(as->list, temp(t->type));
|
||||
}
|
||||
}
|
||||
for(t = getinargx(fn->type)->type; t; t=t->down)
|
||||
as->list = list(as->list, tinlvar(t));
|
||||
} else {
|
||||
ll = n->list;
|
||||
if(fn->type->thistuple && n->left->op != ODOTMETH) // non method call to method
|
||||
ll=ll->next; // was handled above in if(thistuple)
|
||||
|
||||
for(t = getinargx(fn->type)->type; t && ll; t=t->down) {
|
||||
if(t->nname && !isblank(t->nname)) {
|
||||
if(!t->nname->inlvar)
|
||||
fatal("missing inlvar for %N\n", t->nname);
|
||||
as->list = list(as->list, t->nname->inlvar);
|
||||
as->rlist = list(as->rlist, ll->n);
|
||||
}
|
||||
as->list = list(as->list, tinlvar(t));
|
||||
as->rlist = list(as->rlist, ll->n);
|
||||
ll=ll->next;
|
||||
}
|
||||
if(ll || t)
|
||||
|
||||
@@ -348,7 +348,6 @@ main(int argc, char *argv[])
|
||||
for(l=xtop; l; l=l->next)
|
||||
if(l->n->op == ODCL || l->n->op == OAS)
|
||||
typecheck(&l->n, Etop);
|
||||
resumetypecopy();
|
||||
resumecheckwidth();
|
||||
|
||||
// Phase 3: Type check function bodies.
|
||||
|
||||
@@ -152,9 +152,14 @@ walkrange(Node *n)
|
||||
n->ntest = nod(OLT, hv1, hn);
|
||||
n->nincr = nod(OASOP, hv1, nodintconst(1));
|
||||
n->nincr->etype = OADD;
|
||||
body = list1(nod(OAS, v1, hv1));
|
||||
if(v2) {
|
||||
body = list(body, nod(OAS, v2, nod(OIND, hp, N)));
|
||||
if(v2 == N)
|
||||
body = list1(nod(OAS, v1, hv1));
|
||||
else {
|
||||
a = nod(OAS2, N, N);
|
||||
a->list = list(list1(v1), v2);
|
||||
a->rlist = list(list1(hv1), nod(OIND, hp, N));
|
||||
body = list1(a);
|
||||
|
||||
tmp = nod(OADD, hp, nodintconst(t->type->width));
|
||||
tmp->type = hp->type;
|
||||
tmp->typecheck = 1;
|
||||
|
||||
@@ -629,6 +629,7 @@ typename(Type *t)
|
||||
n->ullman = 1;
|
||||
n->class = PEXTERN;
|
||||
n->xoffset = 0;
|
||||
n->typecheck = 1;
|
||||
s->def = n;
|
||||
|
||||
signatlist = list(signatlist, typenod(t));
|
||||
@@ -638,6 +639,7 @@ typename(Type *t)
|
||||
n->type = ptrto(s->def->type);
|
||||
n->addable = 1;
|
||||
n->ullman = 2;
|
||||
n->typecheck = 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
@@ -1945,6 +1945,12 @@ safeexpr(Node *n, NodeList **init)
|
||||
if(n == N)
|
||||
return N;
|
||||
|
||||
if(n->ninit) {
|
||||
walkstmtlist(n->ninit);
|
||||
*init = concat(*init, n->ninit);
|
||||
n->ninit = nil;
|
||||
}
|
||||
|
||||
switch(n->op) {
|
||||
case ONAME:
|
||||
case OLITERAL:
|
||||
@@ -2673,7 +2679,7 @@ genhash(Sym *sym, Type *t)
|
||||
first = T;
|
||||
for(t1=t->type;; t1=t1->down) {
|
||||
if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) {
|
||||
if(first == T)
|
||||
if(first == T && !isblanksym(t1->sym))
|
||||
first = t1;
|
||||
continue;
|
||||
}
|
||||
@@ -2890,7 +2896,7 @@ geneq(Sym *sym, Type *t)
|
||||
first = T;
|
||||
for(t1=t->type;; t1=t1->down) {
|
||||
if(t1 != T && (isblanksym(t1->sym) || algtype1(t1->type, nil) == AMEM)) {
|
||||
if(first == T)
|
||||
if(first == T && !isblanksym(t1->sym))
|
||||
first = t1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ static void checkassign(Node*);
|
||||
static void checkassignlist(NodeList*);
|
||||
static void stringtoarraylit(Node**);
|
||||
static Node* resolve(Node*);
|
||||
static Type* getforwtype(Node*);
|
||||
|
||||
static NodeList* typecheckdefstack;
|
||||
|
||||
@@ -237,7 +236,7 @@ typecheck1(Node **np, int top)
|
||||
Node *n, *l, *r;
|
||||
NodeList *args;
|
||||
int ok, ntop;
|
||||
Type *t, *tp, *ft, *missing, *have, *badtype;
|
||||
Type *t, *tp, *missing, *have, *badtype;
|
||||
Val v;
|
||||
char *why;
|
||||
|
||||
@@ -249,10 +248,6 @@ typecheck1(Node **np, int top)
|
||||
goto error;
|
||||
}
|
||||
|
||||
// a dance to handle forward-declared recursive pointer types.
|
||||
if(n->op == OTYPE && (ft = getforwtype(n->ntype)) != T)
|
||||
defertypecopy(n, ft);
|
||||
|
||||
typecheckdef(n);
|
||||
n->realtype = n->type;
|
||||
if(n->op == ONONAME)
|
||||
@@ -1140,6 +1135,10 @@ reswitch:
|
||||
goto error;
|
||||
n->type = t;
|
||||
if(!isslice(t)) {
|
||||
if(isconst(args->n, CTNIL)) {
|
||||
yyerror("first argument to append must be typed slice; have untyped nil", t);
|
||||
goto error;
|
||||
}
|
||||
yyerror("first argument to append must be slice; have %lT", t);
|
||||
goto error;
|
||||
}
|
||||
@@ -2612,26 +2611,6 @@ stringtoarraylit(Node **np)
|
||||
*np = nn;
|
||||
}
|
||||
|
||||
static Type*
|
||||
getforwtype(Node *n)
|
||||
{
|
||||
Node *f1, *f2;
|
||||
|
||||
for(f2=n; ; n=n->ntype) {
|
||||
if((n = resolve(n)) == N || n->op != OTYPE)
|
||||
return T;
|
||||
|
||||
if(n->type != T && n->type->etype == TFORW)
|
||||
return n->type;
|
||||
|
||||
// Check for ntype cycle.
|
||||
if((f2 = resolve(f2)) != N && (f1 = resolve(f2->ntype)) != N) {
|
||||
f2 = resolve(f1->ntype);
|
||||
if(f1 == n || f2 == n)
|
||||
return T;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ntypecheckdeftype;
|
||||
static NodeList *methodqueue;
|
||||
@@ -2669,49 +2648,24 @@ domethod(Node *n)
|
||||
checkwidth(n->type);
|
||||
}
|
||||
|
||||
typedef struct NodeTypeList NodeTypeList;
|
||||
struct NodeTypeList {
|
||||
Node *n;
|
||||
Type *t;
|
||||
NodeTypeList *next;
|
||||
};
|
||||
|
||||
static NodeTypeList *dntq;
|
||||
static NodeTypeList *dntend;
|
||||
|
||||
void
|
||||
defertypecopy(Node *n, Type *t)
|
||||
{
|
||||
NodeTypeList *ntl;
|
||||
|
||||
if(n == N || t == T)
|
||||
return;
|
||||
|
||||
ntl = mal(sizeof *ntl);
|
||||
ntl->n = n;
|
||||
ntl->t = t;
|
||||
ntl->next = nil;
|
||||
|
||||
if(dntq == nil)
|
||||
dntq = ntl;
|
||||
else
|
||||
dntend->next = ntl;
|
||||
|
||||
dntend = ntl;
|
||||
}
|
||||
|
||||
void
|
||||
resumetypecopy(void)
|
||||
{
|
||||
NodeTypeList *l;
|
||||
|
||||
for(l=dntq; l; l=l->next)
|
||||
copytype(l->n, l->t);
|
||||
}
|
||||
static NodeList *mapqueue;
|
||||
|
||||
void
|
||||
copytype(Node *n, Type *t)
|
||||
{
|
||||
int maplineno, embedlineno, lno;
|
||||
NodeList *l;
|
||||
|
||||
if(t->etype == TFORW) {
|
||||
// This type isn't computed yet; when it is, update n.
|
||||
t->copyto = list(t->copyto, n);
|
||||
return;
|
||||
}
|
||||
|
||||
maplineno = n->type->maplineno;
|
||||
embedlineno = n->type->embedlineno;
|
||||
|
||||
l = n->type->copyto;
|
||||
*n->type = *t;
|
||||
|
||||
t = n->type;
|
||||
@@ -2724,12 +2678,32 @@ copytype(Node *n, Type *t)
|
||||
t->nod = N;
|
||||
t->printed = 0;
|
||||
t->deferwidth = 0;
|
||||
t->copyto = nil;
|
||||
|
||||
// Update nodes waiting on this type.
|
||||
for(; l; l=l->next)
|
||||
copytype(l->n, t);
|
||||
|
||||
// Double-check use of type as embedded type.
|
||||
lno = lineno;
|
||||
if(embedlineno) {
|
||||
lineno = embedlineno;
|
||||
if(isptr[t->etype])
|
||||
yyerror("embedded type cannot be a pointer");
|
||||
}
|
||||
lineno = lno;
|
||||
|
||||
// Queue check for map until all the types are done settling.
|
||||
if(maplineno) {
|
||||
t->maplineno = maplineno;
|
||||
mapqueue = list(mapqueue, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
typecheckdeftype(Node *n)
|
||||
{
|
||||
int maplineno, embedlineno, lno;
|
||||
int lno;
|
||||
Type *t;
|
||||
NodeList *l;
|
||||
|
||||
@@ -2748,26 +2722,12 @@ typecheckdeftype(Node *n)
|
||||
goto ret;
|
||||
}
|
||||
|
||||
maplineno = n->type->maplineno;
|
||||
embedlineno = n->type->embedlineno;
|
||||
|
||||
// copy new type and clear fields
|
||||
// that don't come along.
|
||||
// anything zeroed here must be zeroed in
|
||||
// typedcl2 too.
|
||||
copytype(n, t);
|
||||
|
||||
// double-check use of type as map key.
|
||||
if(maplineno) {
|
||||
lineno = maplineno;
|
||||
maptype(n->type, types[TBOOL]);
|
||||
}
|
||||
if(embedlineno) {
|
||||
lineno = embedlineno;
|
||||
if(isptr[t->etype])
|
||||
yyerror("embedded type cannot be a pointer");
|
||||
}
|
||||
|
||||
ret:
|
||||
lineno = lno;
|
||||
|
||||
@@ -2780,6 +2740,11 @@ ret:
|
||||
for(; l; l=l->next)
|
||||
domethod(l->n);
|
||||
}
|
||||
for(l=mapqueue; l; l=l->next) {
|
||||
lineno = l->n->type->maplineno;
|
||||
maptype(l->n->type, types[TBOOL]);
|
||||
}
|
||||
lineno = lno;
|
||||
}
|
||||
ntypecheckdeftype--;
|
||||
}
|
||||
|
||||
@@ -846,11 +846,13 @@ walkexpr(Node **np, NodeList **init)
|
||||
// if range of type cannot exceed static array bound,
|
||||
// disable bounds check
|
||||
if(isfixedarray(n->left->type))
|
||||
if(!issigned[n->right->type->etype])
|
||||
if(n->right->type->width < 4)
|
||||
if((1<<(8*n->right->type->width)) <= n->left->type->bound)
|
||||
n->etype = 1;
|
||||
|
||||
if(isconst(n->left, CTSTR))
|
||||
if(!issigned[n->right->type->etype])
|
||||
if(n->right->type->width < 4)
|
||||
if((1<<(8*n->right->type->width)) <= n->left->val.u.sval->len)
|
||||
n->etype = 1;
|
||||
|
||||
@@ -152,6 +152,11 @@ func addBuildFlags(cmd *Command) {
|
||||
cmd.Flag.Var(buildCompiler{}, "compiler", "")
|
||||
}
|
||||
|
||||
func addBuildFlagsNX(cmd *Command) {
|
||||
cmd.Flag.BoolVar(&buildN, "n", false, "")
|
||||
cmd.Flag.BoolVar(&buildX, "x", false, "")
|
||||
}
|
||||
|
||||
type stringsFlag []string
|
||||
|
||||
func (v *stringsFlag) Set(s string) error {
|
||||
|
||||
@@ -145,7 +145,7 @@ Run godoc on package sources
|
||||
|
||||
Usage:
|
||||
|
||||
go doc [packages]
|
||||
go doc [-n] [-x] [packages]
|
||||
|
||||
Doc runs the godoc command on the packages named by the
|
||||
import paths.
|
||||
@@ -153,6 +153,9 @@ import paths.
|
||||
For more about godoc, see 'godoc godoc'.
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
|
||||
The -n flag prints commands that would be executed.
|
||||
The -x flag prints commands as they are executed.
|
||||
|
||||
To run godoc with specific options, run godoc itself.
|
||||
|
||||
See also: go fix, go fmt, go vet.
|
||||
@@ -192,7 +195,7 @@ Run gofmt on package sources
|
||||
|
||||
Usage:
|
||||
|
||||
go fmt [packages]
|
||||
go fmt [-n] [-x] [packages]
|
||||
|
||||
Fmt runs the command 'gofmt -l -w' on the packages named
|
||||
by the import paths. It prints the names of the files that are modified.
|
||||
@@ -200,6 +203,9 @@ by the import paths. It prints the names of the files that are modified.
|
||||
For more about gofmt, see 'godoc gofmt'.
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
|
||||
The -n flag prints commands that would be executed.
|
||||
The -x flag prints commands as they are executed.
|
||||
|
||||
To run gofmt with specific options, run gofmt itself.
|
||||
|
||||
See also: go doc, go fix, go vet.
|
||||
@@ -227,15 +233,11 @@ The -u flag instructs get to use the network to update the named packages
|
||||
and their dependencies. By default, get uses the network to check out
|
||||
missing packages but does not use it to look for updates to existing packages.
|
||||
|
||||
When checking out or updating a package, get looks for a branch or
|
||||
tag that matches the locally installed version of Go. If the local
|
||||
version "is release.rNN", it searches for "go.rNN". (For an
|
||||
installation using Go version "weekly.YYYY-MM-DD", it searches for a
|
||||
package version labeled "go.YYYY-MM-DD".) If the desired version
|
||||
cannot be found but others exist with labels in the correct format,
|
||||
get retrieves the most recent version before the desired label.
|
||||
Finally, if all else fails it retrieves the most recent version of
|
||||
the package.
|
||||
When checking out or updating a package, get looks for a branch or tag
|
||||
that matches the locally installed version of Go. The most important
|
||||
rule is that if the local installation is running version "go1", get
|
||||
searches for a branch or tag named "go1". If no such version exists it
|
||||
retrieves the most recent version of the package.
|
||||
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
|
||||
@@ -418,7 +420,7 @@ Run go tool vet on packages
|
||||
|
||||
Usage:
|
||||
|
||||
go vet [packages]
|
||||
go vet [-n] [-x] [packages]
|
||||
|
||||
Vet runs the Go vet command on the packages named by the import paths.
|
||||
|
||||
@@ -427,6 +429,9 @@ For more about specifying packages, see 'go help packages'.
|
||||
|
||||
To run the vet tool with specific options, run 'go tool vet'.
|
||||
|
||||
The -n flag prints commands that would be executed.
|
||||
The -x flag prints commands as they are executed.
|
||||
|
||||
See also: go fmt, go fix.
|
||||
|
||||
|
||||
@@ -541,7 +546,7 @@ in those files and ignoring any other files in the directory.
|
||||
|
||||
Remote import path syntax
|
||||
|
||||
An import path (see 'go help importpath') denotes a package
|
||||
An import path (see 'go help packages') denotes a package
|
||||
stored in the local file system. Certain import paths also
|
||||
describe how to obtain the source code for the package using
|
||||
a revision control system.
|
||||
|
||||
@@ -4,9 +4,14 @@
|
||||
|
||||
package main
|
||||
|
||||
func init() {
|
||||
addBuildFlagsNX(cmdFmt)
|
||||
addBuildFlagsNX(cmdDoc)
|
||||
}
|
||||
|
||||
var cmdFmt = &Command{
|
||||
Run: runFmt,
|
||||
UsageLine: "fmt [packages]",
|
||||
UsageLine: "fmt [-n] [-x] [packages]",
|
||||
Short: "run gofmt on package sources",
|
||||
Long: `
|
||||
Fmt runs the command 'gofmt -l -w' on the packages named
|
||||
@@ -15,6 +20,9 @@ by the import paths. It prints the names of the files that are modified.
|
||||
For more about gofmt, see 'godoc gofmt'.
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
|
||||
The -n flag prints commands that would be executed.
|
||||
The -x flag prints commands as they are executed.
|
||||
|
||||
To run gofmt with specific options, run gofmt itself.
|
||||
|
||||
See also: go doc, go fix, go vet.
|
||||
@@ -32,7 +40,7 @@ func runFmt(cmd *Command, args []string) {
|
||||
|
||||
var cmdDoc = &Command{
|
||||
Run: runDoc,
|
||||
UsageLine: "doc [packages]",
|
||||
UsageLine: "doc [-n] [-x] [packages]",
|
||||
Short: "run godoc on package sources",
|
||||
Long: `
|
||||
Doc runs the godoc command on the packages named by the
|
||||
@@ -41,6 +49,9 @@ import paths.
|
||||
For more about godoc, see 'godoc godoc'.
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
|
||||
The -n flag prints commands that would be executed.
|
||||
The -x flag prints commands as they are executed.
|
||||
|
||||
To run godoc with specific options, run godoc itself.
|
||||
|
||||
See also: go fix, go fmt, go vet.
|
||||
@@ -53,6 +64,10 @@ func runDoc(cmd *Command, args []string) {
|
||||
errorf("go doc: cannot use package file list")
|
||||
continue
|
||||
}
|
||||
run("godoc", pkg.Dir)
|
||||
if pkg.local {
|
||||
run("godoc", pkg.Dir)
|
||||
} else {
|
||||
run("godoc", pkg.ImportPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,15 +37,11 @@ The -u flag instructs get to use the network to update the named packages
|
||||
and their dependencies. By default, get uses the network to check out
|
||||
missing packages but does not use it to look for updates to existing packages.
|
||||
|
||||
When checking out or updating a package, get looks for a branch or
|
||||
tag that matches the locally installed version of Go. If the local
|
||||
version "is release.rNN", it searches for "go.rNN". (For an
|
||||
installation using Go version "weekly.YYYY-MM-DD", it searches for a
|
||||
package version labeled "go.YYYY-MM-DD".) If the desired version
|
||||
cannot be found but others exist with labels in the correct format,
|
||||
get retrieves the most recent version before the desired label.
|
||||
Finally, if all else fails it retrieves the most recent version of
|
||||
the package.
|
||||
When checking out or updating a package, get looks for a branch or tag
|
||||
that matches the locally installed version of Go. The most important
|
||||
rule is that if the local installation is running version "go1", get
|
||||
searches for a branch or tag named "go1". If no such version exists it
|
||||
retrieves the most recent version of the package.
|
||||
|
||||
For more about specifying packages, see 'go help packages'.
|
||||
|
||||
@@ -339,56 +335,32 @@ var goTag = regexp.MustCompile(
|
||||
// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
|
||||
// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).
|
||||
// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
|
||||
//
|
||||
// NOTE(rsc): Eventually we will need to decide on some logic here.
|
||||
// For now, there is only "go1". This matches the docs in go help get.
|
||||
func selectTag(goVersion string, tags []string) (match string) {
|
||||
const rPrefix = "release.r"
|
||||
if strings.HasPrefix(goVersion, rPrefix) {
|
||||
p := "go.r"
|
||||
v, err := strconv.ParseFloat(goVersion[len(rPrefix):], 64)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
var matchf float64
|
||||
for _, t := range tags {
|
||||
if !strings.HasPrefix(t, p) {
|
||||
continue
|
||||
}
|
||||
tf, err := strconv.ParseFloat(t[len(p):], 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if matchf < tf && tf <= v {
|
||||
match, matchf = t, tf
|
||||
}
|
||||
for _, t := range tags {
|
||||
if t == "go1" {
|
||||
return "go1"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
|
||||
const wPrefix = "weekly."
|
||||
if strings.HasPrefix(goVersion, wPrefix) {
|
||||
p := "go.weekly."
|
||||
v := goVersion[len(wPrefix):]
|
||||
for _, t := range tags {
|
||||
if !strings.HasPrefix(t, p) {
|
||||
continue
|
||||
}
|
||||
if match < t && t[len(p):] <= v {
|
||||
match = t
|
||||
/*
|
||||
if goTag.MatchString(goVersion) {
|
||||
v := goVersion
|
||||
for _, t := range tags {
|
||||
if !goTag.MatchString(t) {
|
||||
continue
|
||||
}
|
||||
if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
|
||||
match = t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if goTag.MatchString(goVersion) {
|
||||
v := goVersion
|
||||
for _, t := range tags {
|
||||
if !goTag.MatchString(t) {
|
||||
continue
|
||||
}
|
||||
if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
|
||||
match = t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match
|
||||
return match
|
||||
*/
|
||||
}
|
||||
|
||||
// cmpGoVersion returns -1, 0, +1 reporting whether
|
||||
|
||||
@@ -61,7 +61,7 @@ var helpRemote = &Command{
|
||||
Short: "remote import path syntax",
|
||||
Long: `
|
||||
|
||||
An import path (see 'go help importpath') denotes a package
|
||||
An import path (see 'go help packages') denotes a package
|
||||
stored in the local file system. Certain import paths also
|
||||
describe how to obtain the source code for the package using
|
||||
a revision control system.
|
||||
@@ -138,7 +138,7 @@ The meta tag has the form:
|
||||
|
||||
<meta name="go-import" content="import-prefix vcs repo-root">
|
||||
|
||||
The import-prefix is the import path correponding to the repository
|
||||
The import-prefix is the import path corresponding to the repository
|
||||
root. It must be a prefix or an exact match of the package being
|
||||
fetched with "go get". If it's not an exact match, another http
|
||||
request is made at the prefix to verify the <meta> tags match.
|
||||
|
||||
@@ -144,8 +144,9 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Unknown command %#q\n\n", args[0])
|
||||
usage()
|
||||
fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0])
|
||||
setExitStatus(2)
|
||||
exit()
|
||||
}
|
||||
|
||||
var usageTemplate = `Go is a tool for managing Go source code.
|
||||
@@ -339,6 +340,13 @@ func exitIfErrors() {
|
||||
|
||||
func run(cmdargs ...interface{}) {
|
||||
cmdline := stringList(cmdargs...)
|
||||
if buildN || buildV {
|
||||
fmt.Printf("%s\n", strings.Join(cmdline, " "))
|
||||
if buildN {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command(cmdline[0], cmdline[1:]...)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
@@ -500,13 +508,25 @@ func matchPackagesInFS(pattern string) []string {
|
||||
|
||||
var pkgs []string
|
||||
filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() || path == dir {
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if path == dir {
|
||||
// filepath.Walk starts at dir and recurses. For the recursive case,
|
||||
// the path is the result of filepath.Join, which calls filepath.Clean.
|
||||
// The initial case is not Cleaned, though, so we do this explicitly.
|
||||
//
|
||||
// This converts a path like "./io/" to "io". Without this step, running
|
||||
// "cd $GOROOT/src/pkg; go list ./io/..." would incorrectly skip the io
|
||||
// package, because prepending the prefix "./" to the unclean path would
|
||||
// result in "././io", and match("././io") returns false.
|
||||
path = filepath.Clean(path)
|
||||
}
|
||||
|
||||
// Avoid .foo, _foo, and testdata directory trees.
|
||||
// Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
|
||||
_, elem := filepath.Split(path)
|
||||
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
|
||||
if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@ func runRun(cmd *Command, args []string) {
|
||||
if p.Error != nil {
|
||||
fatalf("%s", p.Error)
|
||||
}
|
||||
for _, err := range p.DepsErrors {
|
||||
errorf("%s", err)
|
||||
}
|
||||
exitIfErrors()
|
||||
if p.Name != "main" {
|
||||
fatalf("go run: cannot run non-main package")
|
||||
}
|
||||
|
||||
@@ -50,41 +50,44 @@ var selectTagTests = []struct {
|
||||
version string
|
||||
selected string
|
||||
}{
|
||||
{"release.r57", ""},
|
||||
{"release.r58.2", "go.r58.1"},
|
||||
{"release.r59", "go.r59"},
|
||||
{"release.r59.1", "go.r59.1"},
|
||||
{"release.r60", "go.r59.1"},
|
||||
{"release.r60.1", "go.r59.1"},
|
||||
{"release.r61", "go.r61"},
|
||||
{"release.r66", "go.r61.1"},
|
||||
{"weekly.2010-01-01", ""},
|
||||
{"weekly.2010-01-02", "go.weekly.2010-01-02"},
|
||||
{"weekly.2010-01-02.1", "go.weekly.2010-01-02"},
|
||||
{"weekly.2010-01-03", "go.weekly.2010-01-02"},
|
||||
{"weekly.2011-10-12", "go.weekly.2011-10-12"},
|
||||
{"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"},
|
||||
{"weekly.2011-10-13", "go.weekly.2011-10-12.1"},
|
||||
{"weekly.2011-10-14", "go.weekly.2011-10-14"},
|
||||
{"weekly.2011-10-14.1", "go.weekly.2011-10-14"},
|
||||
{"weekly.2011-11-01", "go.weekly.2011-11-01"},
|
||||
{"weekly.2014-01-01", "go.weekly.2011-11-01"},
|
||||
{"weekly.3000-01-01", "go.weekly.2011-11-01"},
|
||||
{"go1", "go1"},
|
||||
{"go1.1", "go1.0.1"},
|
||||
{"go1.998", "go1.9.2"},
|
||||
{"go1.1000", "go1.999"},
|
||||
{"go6", "go5"},
|
||||
/*
|
||||
{"release.r57", ""},
|
||||
{"release.r58.2", "go.r58.1"},
|
||||
{"release.r59", "go.r59"},
|
||||
{"release.r59.1", "go.r59.1"},
|
||||
{"release.r60", "go.r59.1"},
|
||||
{"release.r60.1", "go.r59.1"},
|
||||
{"release.r61", "go.r61"},
|
||||
{"release.r66", "go.r61.1"},
|
||||
{"weekly.2010-01-01", ""},
|
||||
{"weekly.2010-01-02", "go.weekly.2010-01-02"},
|
||||
{"weekly.2010-01-02.1", "go.weekly.2010-01-02"},
|
||||
{"weekly.2010-01-03", "go.weekly.2010-01-02"},
|
||||
{"weekly.2011-10-12", "go.weekly.2011-10-12"},
|
||||
{"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"},
|
||||
{"weekly.2011-10-13", "go.weekly.2011-10-12.1"},
|
||||
{"weekly.2011-10-14", "go.weekly.2011-10-14"},
|
||||
{"weekly.2011-10-14.1", "go.weekly.2011-10-14"},
|
||||
{"weekly.2011-11-01", "go.weekly.2011-11-01"},
|
||||
{"weekly.2014-01-01", "go.weekly.2011-11-01"},
|
||||
{"weekly.3000-01-01", "go.weekly.2011-11-01"},
|
||||
{"go1", "go1"},
|
||||
{"go1.1", "go1.0.1"},
|
||||
{"go1.998", "go1.9.2"},
|
||||
{"go1.1000", "go1.999"},
|
||||
{"go6", "go5"},
|
||||
|
||||
// faulty versions:
|
||||
{"release.f00", ""},
|
||||
{"weekly.1999-01-01", ""},
|
||||
{"junk", ""},
|
||||
{"", ""},
|
||||
{"go2x", ""},
|
||||
{"go200000000000", ""},
|
||||
{"go2.", ""},
|
||||
{"go2.0", ""},
|
||||
// faulty versions:
|
||||
{"release.f00", ""},
|
||||
{"weekly.1999-01-01", ""},
|
||||
{"junk", ""},
|
||||
{"", ""},
|
||||
{"go2x", ""},
|
||||
{"go200000000000", ""},
|
||||
{"go2.", ""},
|
||||
{"go2.0", ""},
|
||||
*/
|
||||
{"anything", "go1"},
|
||||
}
|
||||
|
||||
func TestSelectTag(t *testing.T) {
|
||||
|
||||
@@ -422,11 +422,15 @@ func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) {
|
||||
func repoRootForImportDynamic(importPath string) (*repoRoot, error) {
|
||||
slash := strings.Index(importPath, "/")
|
||||
if slash < 0 {
|
||||
return nil, fmt.Errorf("missing / in import %q", importPath)
|
||||
return nil, errors.New("import path doesn't contain a slash")
|
||||
}
|
||||
host := importPath[:slash]
|
||||
if !strings.Contains(host, ".") {
|
||||
return nil, errors.New("import path doesn't contain a hostname")
|
||||
}
|
||||
urlStr, body, err := httpsOrHTTP(importPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("http/https fetch for import %q: %v", importPath, err)
|
||||
return nil, fmt.Errorf("http/https fetch: %v", err)
|
||||
}
|
||||
defer body.Close()
|
||||
metaImport, err := matchGoImport(parseMetaGoImports(body), importPath)
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
|
||||
package main
|
||||
|
||||
func init() {
|
||||
addBuildFlagsNX(cmdVet)
|
||||
}
|
||||
|
||||
var cmdVet = &Command{
|
||||
Run: runVet,
|
||||
UsageLine: "vet [packages]",
|
||||
UsageLine: "vet [-n] [-x] [packages]",
|
||||
Short: "run go tool vet on packages",
|
||||
Long: `
|
||||
Vet runs the Go vet command on the packages named by the import paths.
|
||||
@@ -16,6 +20,9 @@ For more about specifying packages, see 'go help packages'.
|
||||
|
||||
To run the vet tool with specific options, run 'go tool vet'.
|
||||
|
||||
The -n flag prints commands that would be executed.
|
||||
The -x flag prints commands as they are executed.
|
||||
|
||||
See also: go fmt, go fix.
|
||||
`,
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ godoc on appengine
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
* Go appengine SDK 1.5.5 - 2011-10-11
|
||||
http://code.google.com/appengine/downloads.html#Google_App_Engine_SDK_for_Go
|
||||
* Go appengine SDK
|
||||
https://developers.google.com/appengine/downloads#Google_App_Engine_SDK_for_Go
|
||||
|
||||
* Go sources at tip under $GOROOT
|
||||
|
||||
@@ -23,10 +23,6 @@ Directory structure
|
||||
* $APPDIR contains the following entries (this may change depending on
|
||||
app-engine release and version of godoc):
|
||||
|
||||
alt/
|
||||
encoding/binary/
|
||||
go/*
|
||||
index/suffixarray/
|
||||
app.yaml
|
||||
godoc.zip
|
||||
godoc/
|
||||
@@ -36,31 +32,16 @@ Directory structure
|
||||
For instance:
|
||||
|
||||
application: godoc-app
|
||||
version: 1-5-5
|
||||
version: 1
|
||||
runtime: go
|
||||
api_version: 3
|
||||
api_version: go1
|
||||
|
||||
handlers:
|
||||
- url: /.*
|
||||
script: _go_app
|
||||
|
||||
* The godoc/ directory contains a copy of the files under $GOROOT/src/cmd/godoc
|
||||
with modifications:
|
||||
|
||||
- doc.go is excluded (it belongs to pseudo-package <20>documentation<6F>)
|
||||
- main.go is excluded (appinit.go is taking its place)
|
||||
|
||||
Additional manual modifications are required to refer to the alt/ packages
|
||||
where the app-engine library is not up-to-date with the godoc version.
|
||||
|
||||
* The alt/ directory contains up-to-date copies of Go packages that a tip-based
|
||||
godoc is dependent on but which do not yet exist in the current app-engine SDK.
|
||||
At the time of this writing (10/14/2011) this is the entire go directory tree
|
||||
(for the missing FileSet serialization code in go/token) as well as the
|
||||
index/suffixarray package (for the missing suffix array serialization code).
|
||||
The latest (alt/)index/suffixarray package internally requires the latest
|
||||
version of encoding/binary, which is why it also needs to be present under
|
||||
alt/.
|
||||
with doc.go excluded (it belongs to pseudo-package "documentation")
|
||||
|
||||
|
||||
Configuring and running godoc
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
// godoc crypto/block Cipher NewCMAC
|
||||
// - prints doc for Cipher and NewCMAC in package crypto/block
|
||||
|
||||
// +build !appengine
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -44,8 +44,8 @@ getArgs() {
|
||||
if [ ! -d $GOROOT ]; then
|
||||
error "$GOROOT is not a directory"
|
||||
fi
|
||||
if [ ! -x $GOROOT/src/cmd/godoc/godoc ]; then
|
||||
error "$GOROOT/src/cmd/godoc/godoc does not exist or is not executable"
|
||||
if [ ! -x $GOROOT/bin/godoc ]; then
|
||||
error "$GOROOT/bin/godoc does not exist or is not executable"
|
||||
fi
|
||||
if [ ! -d $APPDIR ]; then
|
||||
error "$APPDIR is not a directory"
|
||||
@@ -72,15 +72,15 @@ cleanup() {
|
||||
|
||||
makeZipfile() {
|
||||
echo "*** make $APPDIR/$ZIPFILE"
|
||||
zip -q -r $APPDIR/$ZIPFILE $GOROOT -i \*.go -i \*.html -i \*.css -i \*.js -i \*.txt -i \*.c -i \*.h -i \*.s -i \*.png -i \*.jpg -i \*.sh -i \*.ico
|
||||
zip -q -r $APPDIR/$ZIPFILE $GOROOT -i \*.go -i \*.html -i \*.xml -i \*.css -i \*.js -i \*.txt -i \*.c -i \*.h -i \*.s -i \*.png -i \*.jpg -i \*.sh -i \*.ico
|
||||
}
|
||||
|
||||
makeIndexfile() {
|
||||
echo "*** make $APPDIR/$INDEXFILE"
|
||||
OUT=/tmp/godoc.out
|
||||
$GOROOT/src/cmd/godoc/godoc -write_index -index_files=$APPDIR/$INDEXFILE -zip=$APPDIR/$ZIPFILE 2> $OUT
|
||||
$GOROOT/bin/godoc -write_index -index_files=$APPDIR/$INDEXFILE -zip=$APPDIR/$ZIPFILE 2> $OUT
|
||||
if [ $? != 0 ]; then
|
||||
error "$GOROOT/src/cmd/godoc/godoc failed - see $OUT for details"
|
||||
error "$GOROOT/bin/godoc failed - see $OUT for details"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# 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.
|
||||
|
||||
include ../../Make.dist
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright 2009 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.
|
||||
|
||||
/*
|
||||
|
||||
Prof is a rudimentary real-time profiler.
|
||||
|
||||
Given a command to run or the process id (pid) of a command already
|
||||
running, it samples the program's state at regular intervals and reports
|
||||
on its behavior. With no options, it prints a histogram of the locations
|
||||
in the code that were sampled during execution.
|
||||
|
||||
Since it is a real-time profiler, unlike a traditional profiler it samples
|
||||
the program's state even when it is not running, such as when it is
|
||||
asleep or waiting for I/O. Each thread contributes equally to the
|
||||
statistics.
|
||||
|
||||
Usage:
|
||||
go tool prof -p pid [-t total_secs] [-d delta_msec] [6.out args ...]
|
||||
|
||||
The output modes (default -h) are:
|
||||
|
||||
-P file.prof:
|
||||
Write the profile information to file.prof, in the format used by pprof.
|
||||
At the moment, this only works on Linux amd64 binaries and requires that the
|
||||
binary be written using 6l -e to produce ELF debug info.
|
||||
See http://code.google.com/p/google-perftools for details.
|
||||
-h: histograms
|
||||
How many times a sample occurred at each location.
|
||||
-f: dynamic functions
|
||||
At each sample period, print the name of the executing function.
|
||||
-l: dynamic file and line numbers
|
||||
At each sample period, print the file and line number of the executing instruction.
|
||||
-r: dynamic registers
|
||||
At each sample period, print the register contents.
|
||||
-s: dynamic function stack traces
|
||||
At each sample period, print the symbolic stack trace.
|
||||
|
||||
Flag -t sets the maximum real time to sample, in seconds, and -d
|
||||
sets the sampling interval in milliseconds. The default is to sample
|
||||
every 100ms until the program completes.
|
||||
|
||||
It is installed as go tool prof and is architecture-independent.
|
||||
|
||||
*/
|
||||
package documentation
|
||||
@@ -1,899 +0,0 @@
|
||||
// Copyright 2009 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.
|
||||
|
||||
#include <u.h>
|
||||
#include <time.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define Ureg Ureg_amd64
|
||||
#include <ureg_amd64.h>
|
||||
#undef Ureg
|
||||
#define Ureg Ureg_x86
|
||||
#include <ureg_x86.h>
|
||||
#undef Ureg
|
||||
#include <mach.h>
|
||||
|
||||
char* file = "6.out";
|
||||
static Fhdr fhdr;
|
||||
int have_syms;
|
||||
int fd;
|
||||
struct Ureg_amd64 ureg_amd64;
|
||||
struct Ureg_x86 ureg_x86;
|
||||
int total_sec = 0;
|
||||
int delta_msec = 100;
|
||||
int nsample;
|
||||
int nsamplethread;
|
||||
|
||||
// pprof data, stored as sequences of N followed by N PC values.
|
||||
// See http://code.google.com/p/google-perftools .
|
||||
uvlong *ppdata; // traces
|
||||
Biobuf* pproffd; // file descriptor to write trace info
|
||||
long ppstart; // start position of current trace
|
||||
long nppdata; // length of data
|
||||
long ppalloc; // size of allocated data
|
||||
char ppmapdata[10*1024]; // the map information for the output file
|
||||
|
||||
// output formats
|
||||
int pprof; // print pprof output to named file
|
||||
int functions; // print functions
|
||||
int histograms; // print histograms
|
||||
int linenums; // print file and line numbers rather than function names
|
||||
int registers; // print registers
|
||||
int stacks; // print stack traces
|
||||
|
||||
int pid; // main process pid
|
||||
|
||||
int nthread; // number of threads
|
||||
int thread[32]; // thread pids
|
||||
Map *map[32]; // thread maps
|
||||
|
||||
void
|
||||
Usage(void)
|
||||
{
|
||||
fprint(2, "Usage: prof -p pid [-t total_secs] [-d delta_msec]\n");
|
||||
fprint(2, " prof [-t total_secs] [-d delta_msec] 6.out args ...\n");
|
||||
fprint(2, "\tformats (default -h):\n");
|
||||
fprint(2, "\t\t-P file.prof: write [c]pprof output to file.prof\n");
|
||||
fprint(2, "\t\t-h: histograms\n");
|
||||
fprint(2, "\t\t-f: dynamic functions\n");
|
||||
fprint(2, "\t\t-l: dynamic file and line numbers\n");
|
||||
fprint(2, "\t\t-r: dynamic registers\n");
|
||||
fprint(2, "\t\t-s: dynamic function stack traces\n");
|
||||
fprint(2, "\t\t-hs: include stack info in histograms\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
typedef struct PC PC;
|
||||
struct PC {
|
||||
uvlong pc;
|
||||
uvlong callerpc;
|
||||
unsigned int count;
|
||||
PC* next;
|
||||
};
|
||||
|
||||
enum {
|
||||
Ncounters = 256
|
||||
};
|
||||
|
||||
PC *counters[Ncounters];
|
||||
|
||||
// Set up by setarch() to make most of the code architecture-independent.
|
||||
typedef struct Arch Arch;
|
||||
struct Arch {
|
||||
char* name;
|
||||
void (*regprint)(void);
|
||||
int (*getregs)(Map*);
|
||||
int (*getPC)(Map*);
|
||||
int (*getSP)(Map*);
|
||||
uvlong (*uregPC)(void);
|
||||
uvlong (*uregSP)(void);
|
||||
void (*ppword)(uvlong w);
|
||||
};
|
||||
|
||||
void
|
||||
amd64_regprint(void)
|
||||
{
|
||||
fprint(2, "ax\t0x%llux\n", ureg_amd64.ax);
|
||||
fprint(2, "bx\t0x%llux\n", ureg_amd64.bx);
|
||||
fprint(2, "cx\t0x%llux\n", ureg_amd64.cx);
|
||||
fprint(2, "dx\t0x%llux\n", ureg_amd64.dx);
|
||||
fprint(2, "si\t0x%llux\n", ureg_amd64.si);
|
||||
fprint(2, "di\t0x%llux\n", ureg_amd64.di);
|
||||
fprint(2, "bp\t0x%llux\n", ureg_amd64.bp);
|
||||
fprint(2, "r8\t0x%llux\n", ureg_amd64.r8);
|
||||
fprint(2, "r9\t0x%llux\n", ureg_amd64.r9);
|
||||
fprint(2, "r10\t0x%llux\n", ureg_amd64.r10);
|
||||
fprint(2, "r11\t0x%llux\n", ureg_amd64.r11);
|
||||
fprint(2, "r12\t0x%llux\n", ureg_amd64.r12);
|
||||
fprint(2, "r13\t0x%llux\n", ureg_amd64.r13);
|
||||
fprint(2, "r14\t0x%llux\n", ureg_amd64.r14);
|
||||
fprint(2, "r15\t0x%llux\n", ureg_amd64.r15);
|
||||
fprint(2, "ds\t0x%llux\n", ureg_amd64.ds);
|
||||
fprint(2, "es\t0x%llux\n", ureg_amd64.es);
|
||||
fprint(2, "fs\t0x%llux\n", ureg_amd64.fs);
|
||||
fprint(2, "gs\t0x%llux\n", ureg_amd64.gs);
|
||||
fprint(2, "type\t0x%llux\n", ureg_amd64.type);
|
||||
fprint(2, "error\t0x%llux\n", ureg_amd64.error);
|
||||
fprint(2, "pc\t0x%llux\n", ureg_amd64.ip);
|
||||
fprint(2, "cs\t0x%llux\n", ureg_amd64.cs);
|
||||
fprint(2, "flags\t0x%llux\n", ureg_amd64.flags);
|
||||
fprint(2, "sp\t0x%llux\n", ureg_amd64.sp);
|
||||
fprint(2, "ss\t0x%llux\n", ureg_amd64.ss);
|
||||
}
|
||||
|
||||
int
|
||||
amd64_getregs(Map *map)
|
||||
{
|
||||
int i;
|
||||
union {
|
||||
uvlong regs[1];
|
||||
struct Ureg_amd64 ureg;
|
||||
} u;
|
||||
|
||||
for(i = 0; i < sizeof ureg_amd64; i+=8) {
|
||||
if(get8(map, (uvlong)i, &u.regs[i/8]) < 0)
|
||||
return -1;
|
||||
}
|
||||
ureg_amd64 = u.ureg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
amd64_getPC(Map *map)
|
||||
{
|
||||
uvlong x;
|
||||
int r;
|
||||
|
||||
r = get8(map, offsetof(struct Ureg_amd64, ip), &x);
|
||||
ureg_amd64.ip = x;
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
amd64_getSP(Map *map)
|
||||
{
|
||||
uvlong x;
|
||||
int r;
|
||||
|
||||
r = get8(map, offsetof(struct Ureg_amd64, sp), &x);
|
||||
ureg_amd64.sp = x;
|
||||
return r;
|
||||
}
|
||||
|
||||
uvlong
|
||||
amd64_uregPC(void)
|
||||
{
|
||||
return ureg_amd64.ip;
|
||||
}
|
||||
|
||||
uvlong
|
||||
amd64_uregSP(void) {
|
||||
return ureg_amd64.sp;
|
||||
}
|
||||
|
||||
void
|
||||
amd64_ppword(uvlong w)
|
||||
{
|
||||
uchar buf[8];
|
||||
|
||||
buf[0] = w;
|
||||
buf[1] = w >> 8;
|
||||
buf[2] = w >> 16;
|
||||
buf[3] = w >> 24;
|
||||
buf[4] = w >> 32;
|
||||
buf[5] = w >> 40;
|
||||
buf[6] = w >> 48;
|
||||
buf[7] = w >> 56;
|
||||
Bwrite(pproffd, buf, 8);
|
||||
}
|
||||
|
||||
void
|
||||
x86_regprint(void)
|
||||
{
|
||||
fprint(2, "ax\t0x%ux\n", ureg_x86.ax);
|
||||
fprint(2, "bx\t0x%ux\n", ureg_x86.bx);
|
||||
fprint(2, "cx\t0x%ux\n", ureg_x86.cx);
|
||||
fprint(2, "dx\t0x%ux\n", ureg_x86.dx);
|
||||
fprint(2, "si\t0x%ux\n", ureg_x86.si);
|
||||
fprint(2, "di\t0x%ux\n", ureg_x86.di);
|
||||
fprint(2, "bp\t0x%ux\n", ureg_x86.bp);
|
||||
fprint(2, "ds\t0x%ux\n", ureg_x86.ds);
|
||||
fprint(2, "es\t0x%ux\n", ureg_x86.es);
|
||||
fprint(2, "fs\t0x%ux\n", ureg_x86.fs);
|
||||
fprint(2, "gs\t0x%ux\n", ureg_x86.gs);
|
||||
fprint(2, "cs\t0x%ux\n", ureg_x86.cs);
|
||||
fprint(2, "flags\t0x%ux\n", ureg_x86.flags);
|
||||
fprint(2, "pc\t0x%ux\n", ureg_x86.pc);
|
||||
fprint(2, "sp\t0x%ux\n", ureg_x86.sp);
|
||||
fprint(2, "ss\t0x%ux\n", ureg_x86.ss);
|
||||
}
|
||||
|
||||
int
|
||||
x86_getregs(Map *map)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < sizeof ureg_x86; i+=4) {
|
||||
if(get4(map, (uvlong)i, &((uint32*)&ureg_x86)[i/4]) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
x86_getPC(Map* map)
|
||||
{
|
||||
return get4(map, offsetof(struct Ureg_x86, pc), &ureg_x86.pc);
|
||||
}
|
||||
|
||||
int
|
||||
x86_getSP(Map* map)
|
||||
{
|
||||
return get4(map, offsetof(struct Ureg_x86, sp), &ureg_x86.sp);
|
||||
}
|
||||
|
||||
uvlong
|
||||
x86_uregPC(void)
|
||||
{
|
||||
return (uvlong)ureg_x86.pc;
|
||||
}
|
||||
|
||||
uvlong
|
||||
x86_uregSP(void)
|
||||
{
|
||||
return (uvlong)ureg_x86.sp;
|
||||
}
|
||||
|
||||
void
|
||||
x86_ppword(uvlong w)
|
||||
{
|
||||
uchar buf[4];
|
||||
|
||||
buf[0] = w;
|
||||
buf[1] = w >> 8;
|
||||
buf[2] = w >> 16;
|
||||
buf[3] = w >> 24;
|
||||
Bwrite(pproffd, buf, 4);
|
||||
}
|
||||
|
||||
Arch archtab[] = {
|
||||
{
|
||||
"amd64",
|
||||
amd64_regprint,
|
||||
amd64_getregs,
|
||||
amd64_getPC,
|
||||
amd64_getSP,
|
||||
amd64_uregPC,
|
||||
amd64_uregSP,
|
||||
amd64_ppword,
|
||||
},
|
||||
{
|
||||
"386",
|
||||
x86_regprint,
|
||||
x86_getregs,
|
||||
x86_getPC,
|
||||
x86_getSP,
|
||||
x86_uregPC,
|
||||
x86_uregSP,
|
||||
x86_ppword,
|
||||
},
|
||||
{
|
||||
nil
|
||||
}
|
||||
};
|
||||
|
||||
Arch *arch;
|
||||
|
||||
int
|
||||
setarch(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(mach != nil) {
|
||||
for(i = 0; archtab[i].name != nil; i++) {
|
||||
if (strcmp(mach->name, archtab[i].name) == 0) {
|
||||
arch = &archtab[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
getthreads(void)
|
||||
{
|
||||
int i, j, curn, found;
|
||||
Map *curmap[nelem(map)];
|
||||
int curthread[nelem(map)];
|
||||
static int complained = 0;
|
||||
|
||||
curn = procthreadpids(pid, curthread, nelem(curthread));
|
||||
if(curn <= 0)
|
||||
return curn;
|
||||
|
||||
if(curn > nelem(map)) {
|
||||
if(complained == 0) {
|
||||
fprint(2, "prof: too many threads; limiting to %d\n", nthread, nelem(map));
|
||||
complained = 1;
|
||||
}
|
||||
curn = nelem(map);
|
||||
}
|
||||
if(curn == nthread && memcmp(thread, curthread, curn*sizeof(*thread)) == 0)
|
||||
return curn; // no changes
|
||||
|
||||
// Number of threads has changed (might be the init case).
|
||||
// A bit expensive but rare enough not to bother being clever.
|
||||
for(i = 0; i < curn; i++) {
|
||||
found = 0;
|
||||
for(j = 0; j < nthread; j++) {
|
||||
if(curthread[i] == thread[j]) {
|
||||
found = 1;
|
||||
curmap[i] = map[j];
|
||||
map[j] = nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
continue;
|
||||
|
||||
// map new thread
|
||||
curmap[i] = attachproc(curthread[i], &fhdr);
|
||||
if(curmap[i] == nil) {
|
||||
fprint(2, "prof: can't attach to %d: %r\n", curthread[i]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for(j = 0; j < nthread; j++)
|
||||
if(map[j] != nil)
|
||||
detachproc(map[j]);
|
||||
|
||||
nthread = curn;
|
||||
memmove(thread, curthread, nthread*sizeof thread[0]);
|
||||
memmove(map, curmap, sizeof map);
|
||||
return nthread;
|
||||
}
|
||||
|
||||
int
|
||||
sample(Map *map)
|
||||
{
|
||||
static int n;
|
||||
|
||||
n++;
|
||||
if(registers) {
|
||||
if(arch->getregs(map) < 0)
|
||||
goto bad;
|
||||
} else {
|
||||
// we need only two registers
|
||||
if(arch->getPC(map) < 0)
|
||||
goto bad;
|
||||
if(arch->getSP(map) < 0)
|
||||
goto bad;
|
||||
}
|
||||
return 1;
|
||||
bad:
|
||||
if(n == 1)
|
||||
fprint(2, "prof: can't read registers: %r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
addtohistogram(uvlong pc, uvlong callerpc, uvlong sp)
|
||||
{
|
||||
int h;
|
||||
PC *x;
|
||||
|
||||
USED(sp);
|
||||
|
||||
h = (pc + callerpc*101) % Ncounters;
|
||||
for(x = counters[h]; x != NULL; x = x->next) {
|
||||
if(x->pc == pc && x->callerpc == callerpc) {
|
||||
x->count++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
x = malloc(sizeof(PC));
|
||||
x->pc = pc;
|
||||
x->callerpc = callerpc;
|
||||
x->count = 1;
|
||||
x->next = counters[h];
|
||||
counters[h] = x;
|
||||
}
|
||||
|
||||
void
|
||||
addppword(uvlong pc)
|
||||
{
|
||||
if(pc == 0) {
|
||||
return;
|
||||
}
|
||||
if(nppdata == ppalloc) {
|
||||
ppalloc = (1000+nppdata)*2;
|
||||
ppdata = realloc(ppdata, ppalloc * sizeof ppdata[0]);
|
||||
if(ppdata == nil) {
|
||||
fprint(2, "prof: realloc failed: %r\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
ppdata[nppdata++] = pc;
|
||||
}
|
||||
|
||||
void
|
||||
startpptrace()
|
||||
{
|
||||
ppstart = nppdata;
|
||||
addppword(~0);
|
||||
}
|
||||
|
||||
void
|
||||
endpptrace()
|
||||
{
|
||||
ppdata[ppstart] = nppdata-ppstart-1;
|
||||
}
|
||||
|
||||
uvlong nextpc;
|
||||
|
||||
void
|
||||
xptrace(Map *map, uvlong pc, uvlong sp, Symbol *sym)
|
||||
{
|
||||
USED(map);
|
||||
|
||||
char buf[1024];
|
||||
if(sym == nil){
|
||||
fprint(2, "syms\n");
|
||||
return;
|
||||
}
|
||||
if(histograms)
|
||||
addtohistogram(nextpc, pc, sp);
|
||||
if(!histograms || stacks > 1 || pprof) {
|
||||
if(nextpc == 0)
|
||||
nextpc = sym->value;
|
||||
if(stacks){
|
||||
fprint(2, "%s(", sym->name);
|
||||
fprint(2, ")");
|
||||
if(nextpc != sym->value)
|
||||
fprint(2, "+%#llux ", nextpc - sym->value);
|
||||
if(have_syms && linenums && fileline(buf, sizeof buf, pc)) {
|
||||
fprint(2, " %s", buf);
|
||||
}
|
||||
fprint(2, "\n");
|
||||
}
|
||||
if (pprof) {
|
||||
addppword(nextpc);
|
||||
}
|
||||
}
|
||||
nextpc = pc;
|
||||
}
|
||||
|
||||
void
|
||||
stacktracepcsp(Map *map, uvlong pc, uvlong sp)
|
||||
{
|
||||
nextpc = pc;
|
||||
if(pprof){
|
||||
startpptrace();
|
||||
}
|
||||
if(machdata->ctrace==nil)
|
||||
fprint(2, "no machdata->ctrace\n");
|
||||
else if(machdata->ctrace(map, pc, sp, 0, xptrace) <= 0)
|
||||
fprint(2, "no stack frame: pc=%#p sp=%#p\n", pc, sp);
|
||||
else {
|
||||
addtohistogram(nextpc, 0, sp);
|
||||
if(stacks)
|
||||
fprint(2, "\n");
|
||||
}
|
||||
if(pprof){
|
||||
endpptrace();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printpc(Map *map, uvlong pc, uvlong sp)
|
||||
{
|
||||
char buf[1024];
|
||||
if(registers)
|
||||
arch->regprint();
|
||||
if(have_syms > 0 && linenums && fileline(buf, sizeof buf, pc))
|
||||
fprint(2, "%s\n", buf);
|
||||
if(have_syms > 0 && functions) {
|
||||
symoff(buf, sizeof(buf), pc, CANY);
|
||||
fprint(2, "%s\n", buf);
|
||||
}
|
||||
if(stacks || pprof){
|
||||
stacktracepcsp(map, pc, sp);
|
||||
}
|
||||
else if(histograms){
|
||||
addtohistogram(pc, 0, sp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ppmaps(void)
|
||||
{
|
||||
int fd, n;
|
||||
char tmp[100];
|
||||
Seg *seg;
|
||||
|
||||
// If it's Linux, the info is in /proc/$pid/maps
|
||||
snprint(tmp, sizeof tmp, "/proc/%d/maps", pid);
|
||||
fd = open(tmp, 0);
|
||||
if(fd >= 0) {
|
||||
n = read(fd, ppmapdata, sizeof ppmapdata - 1);
|
||||
close(fd);
|
||||
if(n < 0) {
|
||||
fprint(2, "prof: can't read %s: %r\n", tmp);
|
||||
exit(2);
|
||||
}
|
||||
ppmapdata[n] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// It's probably a mac. Synthesize an entry for the text file.
|
||||
// The register segment may come first but it has a zero offset, so grab the first non-zero offset segment.
|
||||
for(n = 0; n < 3; n++){
|
||||
seg = &map[0]->seg[n];
|
||||
if(seg->b == 0) {
|
||||
continue;
|
||||
}
|
||||
snprint(ppmapdata, sizeof ppmapdata,
|
||||
"%.16x-%.16x r-xp %d 00:00 34968549 %s\n",
|
||||
seg->b, seg->e, seg->f, "/home/r/6.out"
|
||||
);
|
||||
return;
|
||||
}
|
||||
fprint(2, "prof: no text segment in maps for %s\n", file);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void
|
||||
samples(void)
|
||||
{
|
||||
int i, pid, msec;
|
||||
struct timespec req;
|
||||
int getmaps;
|
||||
|
||||
req.tv_sec = delta_msec/1000;
|
||||
req.tv_nsec = 1000000*(delta_msec % 1000);
|
||||
getmaps = 0;
|
||||
if(pprof)
|
||||
getmaps= 1;
|
||||
for(msec = 0; total_sec <= 0 || msec < 1000*total_sec; msec += delta_msec) {
|
||||
nsample++;
|
||||
nsamplethread += nthread;
|
||||
for(i = 0; i < nthread; i++) {
|
||||
pid = thread[i];
|
||||
if(ctlproc(pid, "stop") < 0)
|
||||
return;
|
||||
if(!sample(map[i])) {
|
||||
ctlproc(pid, "start");
|
||||
return;
|
||||
}
|
||||
printpc(map[i], arch->uregPC(), arch->uregSP());
|
||||
ctlproc(pid, "start");
|
||||
}
|
||||
nanosleep(&req, NULL);
|
||||
getthreads();
|
||||
if(nthread == 0)
|
||||
break;
|
||||
if(getmaps) {
|
||||
getmaps = 0;
|
||||
ppmaps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct Func Func;
|
||||
struct Func
|
||||
{
|
||||
Func *next;
|
||||
Symbol s;
|
||||
uint onstack;
|
||||
uint leaf;
|
||||
};
|
||||
|
||||
Func *func[257];
|
||||
int nfunc;
|
||||
|
||||
Func*
|
||||
findfunc(uvlong pc)
|
||||
{
|
||||
Func *f;
|
||||
uint h;
|
||||
Symbol s;
|
||||
|
||||
if(pc == 0)
|
||||
return nil;
|
||||
|
||||
if(!findsym(pc, CTEXT, &s))
|
||||
return nil;
|
||||
|
||||
h = s.value % nelem(func);
|
||||
for(f = func[h]; f != NULL; f = f->next)
|
||||
if(f->s.value == s.value)
|
||||
return f;
|
||||
|
||||
f = malloc(sizeof *f);
|
||||
memset(f, 0, sizeof *f);
|
||||
f->s = s;
|
||||
f->next = func[h];
|
||||
func[h] = f;
|
||||
nfunc++;
|
||||
return f;
|
||||
}
|
||||
|
||||
int
|
||||
compareleaf(const void *va, const void *vb)
|
||||
{
|
||||
Func *a, *b;
|
||||
|
||||
a = *(Func**)va;
|
||||
b = *(Func**)vb;
|
||||
if(a->leaf != b->leaf)
|
||||
return b->leaf - a->leaf;
|
||||
if(a->onstack != b->onstack)
|
||||
return b->onstack - a->onstack;
|
||||
return strcmp(a->s.name, b->s.name);
|
||||
}
|
||||
|
||||
void
|
||||
dumphistogram()
|
||||
{
|
||||
int i, h, n;
|
||||
PC *x;
|
||||
Func *f, **ff;
|
||||
|
||||
if(!histograms)
|
||||
return;
|
||||
|
||||
// assign counts to functions.
|
||||
for(h = 0; h < Ncounters; h++) {
|
||||
for(x = counters[h]; x != NULL; x = x->next) {
|
||||
f = findfunc(x->pc);
|
||||
if(f) {
|
||||
f->onstack += x->count;
|
||||
f->leaf += x->count;
|
||||
}
|
||||
f = findfunc(x->callerpc);
|
||||
if(f)
|
||||
f->leaf -= x->count;
|
||||
}
|
||||
}
|
||||
|
||||
// build array
|
||||
ff = malloc(nfunc*sizeof ff[0]);
|
||||
n = 0;
|
||||
for(h = 0; h < nelem(func); h++)
|
||||
for(f = func[h]; f != NULL; f = f->next)
|
||||
ff[n++] = f;
|
||||
|
||||
// sort by leaf counts
|
||||
qsort(ff, nfunc, sizeof ff[0], compareleaf);
|
||||
|
||||
// print.
|
||||
fprint(2, "%d samples (avg %.1g threads)\n", nsample, (double)nsamplethread/nsample);
|
||||
for(i = 0; i < nfunc; i++) {
|
||||
f = ff[i];
|
||||
fprint(2, "%6.2f%%\t", 100.0*(double)f->leaf/nsample);
|
||||
if(stacks)
|
||||
fprint(2, "%6.2f%%\t", 100.0*(double)f->onstack/nsample);
|
||||
fprint(2, "%s\n", f->s.name);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct Trace Trace;
|
||||
struct Trace {
|
||||
int count;
|
||||
int npc;
|
||||
uvlong *pc;
|
||||
Trace *next;
|
||||
};
|
||||
|
||||
void
|
||||
dumppprof()
|
||||
{
|
||||
uvlong i, n, *p, *e;
|
||||
int ntrace;
|
||||
Trace *trace, *tp, *up, *prev;
|
||||
|
||||
if(!pprof)
|
||||
return;
|
||||
e = ppdata + nppdata;
|
||||
// Create list of traces. First, count the traces
|
||||
ntrace = 0;
|
||||
for(p = ppdata; p < e;) {
|
||||
n = *p++;
|
||||
p += n;
|
||||
if(n == 0)
|
||||
continue;
|
||||
ntrace++;
|
||||
}
|
||||
if(ntrace <= 0)
|
||||
return;
|
||||
// Allocate and link the traces together.
|
||||
trace = malloc(ntrace * sizeof(Trace));
|
||||
tp = trace;
|
||||
for(p = ppdata; p < e;) {
|
||||
n = *p++;
|
||||
if(n == 0)
|
||||
continue;
|
||||
tp->count = 1;
|
||||
tp->npc = n;
|
||||
tp->pc = p;
|
||||
tp->next = tp+1;
|
||||
tp++;
|
||||
p += n;
|
||||
}
|
||||
trace[ntrace-1].next = nil;
|
||||
// Eliminate duplicates. Lousy algorithm, although not as bad as it looks because
|
||||
// the list collapses fast.
|
||||
for(tp = trace; tp != nil; tp = tp->next) {
|
||||
prev = tp;
|
||||
for(up = tp->next; up != nil; up = up->next) {
|
||||
if(up->npc == tp->npc && memcmp(up->pc, tp->pc, up->npc*sizeof up->pc[0]) == 0) {
|
||||
tp->count++;
|
||||
prev->next = up->next;
|
||||
} else {
|
||||
prev = up;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Write file.
|
||||
// See http://code.google.com/p/google-perftools/source/browse/trunk/doc/cpuprofile-fileformat.html
|
||||
// 1) Header
|
||||
arch->ppword(0); // must be zero
|
||||
arch->ppword(3); // 3 words follow in header
|
||||
arch->ppword(0); // must be zero
|
||||
arch->ppword(delta_msec * 1000); // sampling period in microseconds
|
||||
arch->ppword(0); // must be zero (padding)
|
||||
// 2) One record for each trace.
|
||||
for(tp = trace; tp != nil; tp = tp->next) {
|
||||
arch->ppword(tp->count);
|
||||
arch->ppword(tp->npc);
|
||||
for(i = 0; i < tp->npc; i++) {
|
||||
arch->ppword(tp->pc[i]);
|
||||
}
|
||||
}
|
||||
// 3) Binary trailer
|
||||
arch->ppword(0); // must be zero
|
||||
arch->ppword(1); // must be one
|
||||
arch->ppword(0); // must be zero
|
||||
// 4) Mapped objects.
|
||||
Bwrite(pproffd, ppmapdata, strlen(ppmapdata));
|
||||
// 5) That's it.
|
||||
Bterm(pproffd);
|
||||
}
|
||||
|
||||
int
|
||||
startprocess(char **argv)
|
||||
{
|
||||
int pid;
|
||||
|
||||
if((pid = fork()) == 0) {
|
||||
pid = getpid();
|
||||
if(ctlproc(pid, "hang") < 0){
|
||||
fprint(2, "prof: child process could not hang\n");
|
||||
exits(0);
|
||||
}
|
||||
execv(argv[0], argv);
|
||||
fprint(2, "prof: could not exec %s: %r\n", argv[0]);
|
||||
exits(0);
|
||||
}
|
||||
|
||||
if(pid == -1) {
|
||||
fprint(2, "prof: could not fork\n");
|
||||
exit(1);
|
||||
}
|
||||
if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0) {
|
||||
fprint(2, "prof: could not attach to child process: %r\n");
|
||||
exit(1);
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
void
|
||||
detach(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nthread; i++)
|
||||
detachproc(map[i]);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
char *ppfile;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'P':
|
||||
pprof =1;
|
||||
ppfile = EARGF(Usage());
|
||||
pproffd = Bopen(ppfile, OWRITE);
|
||||
if(pproffd == nil) {
|
||||
fprint(2, "prof: cannot open %s: %r\n", ppfile);
|
||||
exit(2);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
delta_msec = atoi(EARGF(Usage()));
|
||||
break;
|
||||
case 't':
|
||||
total_sec = atoi(EARGF(Usage()));
|
||||
break;
|
||||
case 'p':
|
||||
pid = atoi(EARGF(Usage()));
|
||||
break;
|
||||
case 'f':
|
||||
functions = 1;
|
||||
break;
|
||||
case 'h':
|
||||
histograms = 1;
|
||||
break;
|
||||
case 'l':
|
||||
linenums = 1;
|
||||
break;
|
||||
case 'r':
|
||||
registers = 1;
|
||||
break;
|
||||
case 's':
|
||||
stacks++;
|
||||
break;
|
||||
default:
|
||||
Usage();
|
||||
}ARGEND
|
||||
if(pid <= 0 && argc == 0)
|
||||
Usage();
|
||||
if(functions+linenums+registers+stacks+pprof == 0)
|
||||
histograms = 1;
|
||||
if(!machbyname("amd64")) {
|
||||
fprint(2, "prof: no amd64 support\n", pid);
|
||||
exit(1);
|
||||
}
|
||||
if(argc > 0)
|
||||
file = argv[0];
|
||||
else if(pid) {
|
||||
file = proctextfile(pid);
|
||||
if (file == NULL) {
|
||||
fprint(2, "prof: can't find file for pid %d: %r\n", pid);
|
||||
fprint(2, "prof: on Darwin, need to provide file name explicitly\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
fd = open(file, 0);
|
||||
if(fd < 0) {
|
||||
fprint(2, "prof: can't open %s: %r\n", file);
|
||||
exit(1);
|
||||
}
|
||||
if(crackhdr(fd, &fhdr)) {
|
||||
have_syms = syminit(fd, &fhdr);
|
||||
if(!have_syms) {
|
||||
fprint(2, "prof: no symbols for %s: %r\n", file);
|
||||
}
|
||||
} else {
|
||||
fprint(2, "prof: crack header for %s: %r\n", file);
|
||||
exit(1);
|
||||
}
|
||||
if(pid <= 0)
|
||||
pid = startprocess(argv);
|
||||
attachproc(pid, &fhdr); // initializes thread list
|
||||
if(setarch() < 0) {
|
||||
detach();
|
||||
fprint(2, "prof: can't identify binary architecture for pid %d\n", pid);
|
||||
exit(1);
|
||||
}
|
||||
if(getthreads() <= 0) {
|
||||
detach();
|
||||
fprint(2, "prof: can't find threads for pid %d\n", pid);
|
||||
exit(1);
|
||||
}
|
||||
for(i = 0; i < nthread; i++)
|
||||
ctlproc(thread[i], "start");
|
||||
samples();
|
||||
detach();
|
||||
dumphistogram();
|
||||
dumppprof();
|
||||
exit(0);
|
||||
}
|
||||
@@ -16,8 +16,8 @@ p9ctime(long t)
|
||||
tt = t;
|
||||
tm = localtime(&tt);
|
||||
snprint(buf, sizeof buf, "%3.3s %3.3s %02d %02d:%02d:%02d %3.3s %d\n",
|
||||
"SunMonTueWedThuFriSat"+(tm->tm_wday*3),
|
||||
"JanFebMarAprMayJunJulAugSepOctNovDec"+(tm->tm_mon*3),
|
||||
&"SunMonTueWedThuFriSat"[tm->tm_wday*3],
|
||||
&"JanFebMarAprMayJunJulAugSepOctNovDec"[tm->tm_mon*3],
|
||||
tm->tm_mday,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
|
||||
@@ -32,6 +32,7 @@ const (
|
||||
hashSize = 1 << hashBits
|
||||
hashMask = (1 << hashBits) - 1
|
||||
hashShift = (hashBits + minMatchLength - 1) / minMatchLength
|
||||
maxHashOffset = 1 << 24
|
||||
|
||||
skipNever = math.MaxInt32
|
||||
)
|
||||
@@ -106,6 +107,25 @@ func (d *compressor) fillDeflate(b []byte) int {
|
||||
d.blockStart = math.MaxInt32
|
||||
}
|
||||
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)
|
||||
d.windowEnd += n
|
||||
|
||||
@@ -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 {
|
||||
buf bytes.Buffer
|
||||
mu sync.RWMutex
|
||||
|
||||
@@ -11,11 +11,11 @@ package aes
|
||||
// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
|
||||
// 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.
|
||||
// Reducing mod poly corresponds to binary xor with poly every
|
||||
// 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).
|
||||
var powx = [16]byte{
|
||||
|
||||
@@ -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
|
||||
// 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
|
||||
// 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 {
|
||||
orderBits := c.Params().N.BitLen()
|
||||
orderBytes := (orderBits + 7) / 8
|
||||
@@ -75,7 +77,7 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
|
||||
}
|
||||
|
||||
ret := new(big.Int).SetBytes(hash)
|
||||
excess := orderBytes*8 - orderBits
|
||||
excess := len(hash)*8 - orderBits
|
||||
if excess > 0 {
|
||||
ret.Rsh(ret, uint(excess))
|
||||
}
|
||||
|
||||
@@ -151,6 +151,7 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
|
||||
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.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.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},
|
||||
|
||||
@@ -23,8 +23,8 @@ type keyAgreement interface {
|
||||
// In the case that the key agreement protocol doesn't use a
|
||||
// ServerKeyExchange message, generateServerKeyExchange can return nil,
|
||||
// nil.
|
||||
generateServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
|
||||
processClientKeyExchange(*Config, *clientKeyExchangeMsg, uint16) ([]byte, error)
|
||||
generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
|
||||
processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
|
||||
|
||||
// On the client side, the next two methods are called in order.
|
||||
|
||||
|
||||
@@ -563,7 +563,7 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
|
||||
if len(d) < 4 {
|
||||
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 {
|
||||
return false
|
||||
}
|
||||
@@ -575,7 +575,7 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
|
||||
m.certificates = make([][]byte, numCerts)
|
||||
d = data[7:]
|
||||
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]
|
||||
d = d[3+certLen:]
|
||||
}
|
||||
|
||||
@@ -112,37 +112,38 @@ FindCipherSuite:
|
||||
hello.nextProtoNeg = true
|
||||
hello.nextProtos = config.NextProtos
|
||||
}
|
||||
if clientHello.ocspStapling && len(config.Certificates[0].OCSPStaple) > 0 {
|
||||
|
||||
if len(config.Certificates) == 0 {
|
||||
return c.sendAlert(alertInternalError)
|
||||
}
|
||||
cert := &config.Certificates[0]
|
||||
if len(clientHello.serverName) > 0 {
|
||||
c.serverName = clientHello.serverName
|
||||
cert = config.getCertificateForName(clientHello.serverName)
|
||||
}
|
||||
|
||||
if clientHello.ocspStapling && len(cert.OCSPStaple) > 0 {
|
||||
hello.ocspStapling = true
|
||||
}
|
||||
|
||||
finishedHash.Write(hello.marshal())
|
||||
c.writeRecord(recordTypeHandshake, hello.marshal())
|
||||
|
||||
if len(config.Certificates) == 0 {
|
||||
return c.sendAlert(alertInternalError)
|
||||
}
|
||||
|
||||
certMsg := new(certificateMsg)
|
||||
if len(clientHello.serverName) > 0 {
|
||||
c.serverName = clientHello.serverName
|
||||
certMsg.certificates = config.getCertificateForName(clientHello.serverName).Certificate
|
||||
} else {
|
||||
certMsg.certificates = config.Certificates[0].Certificate
|
||||
}
|
||||
certMsg.certificates = cert.Certificate
|
||||
finishedHash.Write(certMsg.marshal())
|
||||
c.writeRecord(recordTypeHandshake, certMsg.marshal())
|
||||
|
||||
if hello.ocspStapling {
|
||||
certStatus := new(certificateStatusMsg)
|
||||
certStatus.statusType = statusTypeOCSP
|
||||
certStatus.response = config.Certificates[0].OCSPStaple
|
||||
certStatus.response = cert.OCSPStaple
|
||||
finishedHash.Write(certStatus.marshal())
|
||||
c.writeRecord(recordTypeHandshake, certStatus.marshal())
|
||||
}
|
||||
|
||||
keyAgreement := suite.ka()
|
||||
skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
|
||||
skx, err := keyAgreement.generateServerKeyExchange(config, cert, clientHello, hello)
|
||||
if err != nil {
|
||||
c.sendAlert(alertHandshakeFailure)
|
||||
return err
|
||||
@@ -288,7 +289,7 @@ FindCipherSuite:
|
||||
finishedHash.Write(certVerify.marshal())
|
||||
}
|
||||
|
||||
preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx, c.vers)
|
||||
preMasterSecret, err := keyAgreement.processClientKeyExchange(config, cert, ckx, c.vers)
|
||||
if err != nil {
|
||||
c.sendAlert(alertHandshakeFailure)
|
||||
return err
|
||||
|
||||
@@ -37,9 +37,12 @@ func init() {
|
||||
testConfig = new(Config)
|
||||
testConfig.Time = func() time.Time { return time.Unix(0, 0) }
|
||||
testConfig.Rand = zeroSource{}
|
||||
testConfig.Certificates = make([]Certificate, 1)
|
||||
testConfig.Certificates = make([]Certificate, 2)
|
||||
testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
|
||||
testConfig.Certificates[0].PrivateKey = testPrivateKey
|
||||
testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate}
|
||||
testConfig.Certificates[1].PrivateKey = testPrivateKey
|
||||
testConfig.BuildNameToCertificate()
|
||||
testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
|
||||
testConfig.InsecureSkipVerify = true
|
||||
}
|
||||
@@ -176,6 +179,13 @@ func TestHandshakeServerSSLv3(t *testing.T) {
|
||||
testServerScript(t, "SSLv3", sslv3ServerScript, testConfig, nil)
|
||||
}
|
||||
|
||||
// TestHandshakeServerSNI involves a client sending an SNI extension of
|
||||
// "snitest.com", which happens to match the CN of testSNICertificate. The test
|
||||
// verifies that the server correctly selects that certificate.
|
||||
func TestHandshakeServerSNI(t *testing.T) {
|
||||
testServerScript(t, "SNI", selectCertificateBySNIScript, testConfig, nil)
|
||||
}
|
||||
|
||||
type clientauthTest struct {
|
||||
name string
|
||||
clientauth ClientAuthType
|
||||
@@ -258,6 +268,8 @@ func fromHex(s string) []byte {
|
||||
|
||||
var testCertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9")
|
||||
|
||||
var testSNICertificate = fromHex("308201f23082015da003020102020100300b06092a864886f70d01010530283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d301e170d3132303431313137343033355a170d3133303431313137343533355a30283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d30819d300b06092a864886f70d01010103818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a3323030300e0603551d0f0101ff0404030200a0300d0603551d0e0406040401020304300f0603551d2304083006800401020304300b06092a864886f70d0101050381810089c6455f1c1f5ef8eb1ab174ee2439059f5c4259bb1a8d86cdb1d056f56a717da40e95ab90f59e8deaf627c157995094db0802266eb34fc6842dea8a4b68d9c1389103ab84fb9e1f85d9b5d23ff2312c8670fbb540148245a4ebafe264d90c8a4cf4f85b0fac12ac2fc4a3154bad52462868af96c62c6525d652b6e31845bdcc")
|
||||
|
||||
var testPrivateKey = &rsa.PrivateKey{
|
||||
PublicKey: rsa.PublicKey{
|
||||
N: bigFromString("131650079503776001033793877885499001334664249354723305978524647182322416328664556247316495448366990052837680518067798333412266673813370895702118944398081598789828837447552603077848001020611640547221687072142537202428102790818451901395596882588063427854225330436740647715202971973145151161964464812406232198521"),
|
||||
@@ -947,6 +959,142 @@ var sslv3ServerScript = [][]byte{
|
||||
},
|
||||
}
|
||||
|
||||
var selectCertificateBySNIScript = [][]byte{
|
||||
{
|
||||
0x16, 0x03, 0x01, 0x00, 0x6e, 0x01, 0x00, 0x00,
|
||||
0x6a, 0x03, 0x01, 0x4f, 0x85, 0xc4, 0xc2, 0xb9,
|
||||
0x39, 0x80, 0x91, 0x66, 0x65, 0x56, 0x8e, 0xdd,
|
||||
0x48, 0xe9, 0xca, 0x34, 0x02, 0x3c, 0xaf, 0x0d,
|
||||
0x73, 0xb5, 0x2a, 0x05, 0x6e, 0xbd, 0x5e, 0x8f,
|
||||
0x38, 0xf9, 0xe5, 0x00, 0x00, 0x28, 0x00, 0x39,
|
||||
0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13,
|
||||
0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f,
|
||||
0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12,
|
||||
0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08,
|
||||
0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01,
|
||||
0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00,
|
||||
0x0e, 0x00, 0x00, 0x0b, 0x73, 0x6e, 0x69, 0x74,
|
||||
0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
|
||||
0x23, 0x00, 0x00,
|
||||
},
|
||||
{
|
||||
0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
|
||||
0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
|
||||
0x03, 0x01, 0x02, 0x00, 0x0b, 0x00, 0x01, 0xfc,
|
||||
0x00, 0x01, 0xf9, 0x00, 0x01, 0xf6, 0x30, 0x82,
|
||||
0x01, 0xf2, 0x30, 0x82, 0x01, 0x5d, 0xa0, 0x03,
|
||||
0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0b,
|
||||
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x01, 0x05, 0x30, 0x28, 0x31, 0x10, 0x30,
|
||||
0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07,
|
||||
0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, 0x31,
|
||||
0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x0b, 0x73, 0x6e, 0x69, 0x74, 0x65, 0x73,
|
||||
0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17,
|
||||
0x0d, 0x31, 0x32, 0x30, 0x34, 0x31, 0x31, 0x31,
|
||||
0x37, 0x34, 0x30, 0x33, 0x35, 0x5a, 0x17, 0x0d,
|
||||
0x31, 0x33, 0x30, 0x34, 0x31, 0x31, 0x31, 0x37,
|
||||
0x34, 0x35, 0x33, 0x35, 0x5a, 0x30, 0x28, 0x31,
|
||||
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a,
|
||||
0x13, 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43,
|
||||
0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x13, 0x0b, 0x73, 0x6e, 0x69, 0x74,
|
||||
0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
|
||||
0x81, 0x9d, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x03,
|
||||
0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81,
|
||||
0x81, 0x00, 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5,
|
||||
0xe5, 0xbf, 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe,
|
||||
0xe6, 0x2b, 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d,
|
||||
0x8a, 0x7a, 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7,
|
||||
0xa5, 0x65, 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c,
|
||||
0xb5, 0xb4, 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b,
|
||||
0x7e, 0x62, 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe,
|
||||
0x12, 0x5c, 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf,
|
||||
0xfa, 0x58, 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04,
|
||||
0xd3, 0xd0, 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4,
|
||||
0x54, 0x9f, 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00,
|
||||
0xfe, 0x18, 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d,
|
||||
0x7d, 0xf1, 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb,
|
||||
0x51, 0xc9, 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32,
|
||||
0x66, 0x01, 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71,
|
||||
0x9a, 0x1d, 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda,
|
||||
0x2d, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
|
||||
0x32, 0x30, 0x30, 0x30, 0x0e, 0x06, 0x03, 0x55,
|
||||
0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
|
||||
0x02, 0x00, 0xa0, 0x30, 0x0d, 0x06, 0x03, 0x55,
|
||||
0x1d, 0x0e, 0x04, 0x06, 0x04, 0x04, 0x01, 0x02,
|
||||
0x03, 0x04, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
|
||||
0x23, 0x04, 0x08, 0x30, 0x06, 0x80, 0x04, 0x01,
|
||||
0x02, 0x03, 0x04, 0x30, 0x0b, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
|
||||
0x03, 0x81, 0x81, 0x00, 0x89, 0xc6, 0x45, 0x5f,
|
||||
0x1c, 0x1f, 0x5e, 0xf8, 0xeb, 0x1a, 0xb1, 0x74,
|
||||
0xee, 0x24, 0x39, 0x05, 0x9f, 0x5c, 0x42, 0x59,
|
||||
0xbb, 0x1a, 0x8d, 0x86, 0xcd, 0xb1, 0xd0, 0x56,
|
||||
0xf5, 0x6a, 0x71, 0x7d, 0xa4, 0x0e, 0x95, 0xab,
|
||||
0x90, 0xf5, 0x9e, 0x8d, 0xea, 0xf6, 0x27, 0xc1,
|
||||
0x57, 0x99, 0x50, 0x94, 0xdb, 0x08, 0x02, 0x26,
|
||||
0x6e, 0xb3, 0x4f, 0xc6, 0x84, 0x2d, 0xea, 0x8a,
|
||||
0x4b, 0x68, 0xd9, 0xc1, 0x38, 0x91, 0x03, 0xab,
|
||||
0x84, 0xfb, 0x9e, 0x1f, 0x85, 0xd9, 0xb5, 0xd2,
|
||||
0x3f, 0xf2, 0x31, 0x2c, 0x86, 0x70, 0xfb, 0xb5,
|
||||
0x40, 0x14, 0x82, 0x45, 0xa4, 0xeb, 0xaf, 0xe2,
|
||||
0x64, 0xd9, 0x0c, 0x8a, 0x4c, 0xf4, 0xf8, 0x5b,
|
||||
0x0f, 0xac, 0x12, 0xac, 0x2f, 0xc4, 0xa3, 0x15,
|
||||
0x4b, 0xad, 0x52, 0x46, 0x28, 0x68, 0xaf, 0x96,
|
||||
0xc6, 0x2c, 0x65, 0x25, 0xd6, 0x52, 0xb6, 0xe3,
|
||||
0x18, 0x45, 0xbd, 0xcc, 0x16, 0x03, 0x01, 0x00,
|
||||
0x04, 0x0e, 0x00, 0x00, 0x00,
|
||||
},
|
||||
{
|
||||
0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
|
||||
0x82, 0x00, 0x80, 0x70, 0x1d, 0x34, 0x75, 0xa2,
|
||||
0xe7, 0xe3, 0x2f, 0x3d, 0xc1, 0x1d, 0xca, 0x0b,
|
||||
0xe3, 0x64, 0xb9, 0x1a, 0x00, 0x69, 0xc4, 0x14,
|
||||
0x05, 0x07, 0x7e, 0xc3, 0x51, 0x43, 0x52, 0x66,
|
||||
0xe3, 0xbd, 0xff, 0x1b, 0x1a, 0x6a, 0x84, 0xf2,
|
||||
0x07, 0x24, 0xd7, 0x12, 0xa8, 0x58, 0xcf, 0x8a,
|
||||
0x50, 0x30, 0xe8, 0xc8, 0xb2, 0xf9, 0x58, 0x1c,
|
||||
0x56, 0x53, 0x76, 0x21, 0xe0, 0x03, 0x7f, 0x77,
|
||||
0xa7, 0xf1, 0xad, 0x67, 0xd4, 0xe2, 0x8f, 0xa0,
|
||||
0x58, 0x6c, 0xe0, 0x28, 0x59, 0xf3, 0xd1, 0x53,
|
||||
0x2b, 0x21, 0xbd, 0xa3, 0x84, 0x31, 0x73, 0xbf,
|
||||
0x84, 0x0f, 0x83, 0xf4, 0xc4, 0xd0, 0xe5, 0x3c,
|
||||
0x2d, 0x3e, 0xf2, 0x8a, 0x1e, 0xe7, 0xe9, 0x1f,
|
||||
0x12, 0x13, 0xad, 0x29, 0xd6, 0x0c, 0xc7, 0xc6,
|
||||
0x05, 0x53, 0x7d, 0x5e, 0xc6, 0x92, 0x72, 0xba,
|
||||
0xd2, 0x93, 0x8f, 0x53, 0x84, 0x87, 0x44, 0x05,
|
||||
0x9f, 0x5d, 0x66, 0x14, 0x03, 0x01, 0x00, 0x01,
|
||||
0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xfc, 0x71,
|
||||
0xaa, 0xa8, 0x37, 0xa8, 0xbd, 0x63, 0xb7, 0xbc,
|
||||
0x95, 0xef, 0x0c, 0xcf, 0x39, 0x31, 0x93, 0xe6,
|
||||
0x86, 0xbd, 0x3f, 0x56, 0x9d, 0xf0, 0xb2, 0xb5,
|
||||
0xd1, 0xa7, 0xc6, 0x45, 0x89, 0x18, 0xfb, 0xa0,
|
||||
0x7f, 0xc1,
|
||||
},
|
||||
{
|
||||
0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
|
||||
0x01, 0x00, 0x24, 0xb8, 0x6d, 0x9a, 0x90, 0x3c,
|
||||
0x45, 0xe0, 0xff, 0x63, 0xba, 0xab, 0x3d, 0x7a,
|
||||
0xa6, 0x49, 0x5a, 0x13, 0xdc, 0x0e, 0xa3, 0xba,
|
||||
0x7f, 0x04, 0x19, 0x45, 0xfd, 0xfb, 0xbd, 0x00,
|
||||
0xa3, 0xa7, 0x78, 0x81, 0x38, 0x9f, 0x10, 0x17,
|
||||
0x03, 0x01, 0x00, 0x21, 0x43, 0xc3, 0x91, 0xb7,
|
||||
0xbf, 0x50, 0x0b, 0x04, 0xb4, 0x5d, 0xc6, 0x20,
|
||||
0x64, 0xb8, 0x01, 0x09, 0x25, 0x2c, 0x03, 0x30,
|
||||
0xc0, 0x77, 0xc9, 0x5e, 0xe6, 0xe0, 0x99, 0xdc,
|
||||
0xcd, 0x75, 0x9d, 0x51, 0x82, 0x15, 0x03, 0x01,
|
||||
0x00, 0x16, 0x2d, 0x7a, 0x89, 0x7b, 0x36, 0x85,
|
||||
0x2a, 0x93, 0xcb, 0x83, 0xa7, 0x2f, 0x9e, 0x91,
|
||||
0xfc, 0xad, 0x57, 0xca, 0xf5, 0xbc, 0x13, 0x2f,
|
||||
},
|
||||
}
|
||||
|
||||
var clientauthTests = []clientauthTest{
|
||||
// Server doesn't asks for cert
|
||||
// go test -run "TestRunServer" -serve -clientauth 0
|
||||
@@ -1285,7 +1433,7 @@ var clientauthTests = []clientauthTest{
|
||||
// go test -run "TestRunServer" -serve -clientauth 1
|
||||
// gnutls-cli --insecure --debug 100 -p 10443 localhost
|
||||
{"RequestClientCert, client gives it", RequestClientCert,
|
||||
[]*x509.Certificate{clicert},
|
||||
[]*x509.Certificate{clientCertificate},
|
||||
[][]byte{{
|
||||
0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
|
||||
0x76, 0x03, 0x02, 0x4e, 0xe7, 0x44, 0xda, 0x58,
|
||||
@@ -1528,14 +1676,16 @@ var clientauthTests = []clientauthTest{
|
||||
0x00, 0x16, 0x53, 0xf5, 0xff, 0xe0, 0xa1, 0x6c,
|
||||
0x33, 0xf4, 0x4e, 0x89, 0x68, 0xe1, 0xf7, 0x61,
|
||||
0x13, 0xb3, 0x12, 0xa1, 0x8e, 0x5a, 0x7a, 0x02,
|
||||
}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// cert.pem and key.pem were generated with generate_cert.go
|
||||
// Thus, they have no ExtKeyUsage fields and trigger an error
|
||||
// when verification is turned on.
|
||||
|
||||
var clicert = loadPEMCert(`
|
||||
var clientCertificate = loadPEMCert(`
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
|
||||
bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
|
||||
|
||||
@@ -20,11 +20,11 @@ import (
|
||||
// encrypts the pre-master secret to the server's public key.
|
||||
type rsaKeyAgreement struct{}
|
||||
|
||||
func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
||||
func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
||||
func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
||||
preMasterSecret := make([]byte, 48)
|
||||
_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
|
||||
if err != nil {
|
||||
@@ -44,7 +44,7 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKe
|
||||
ciphertext = ckx.ciphertext[2:]
|
||||
}
|
||||
|
||||
err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
|
||||
err = rsa.DecryptPKCS1v15SessionKey(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), ciphertext, preMasterSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -109,7 +109,7 @@ type ecdheRSAKeyAgreement struct {
|
||||
x, y *big.Int
|
||||
}
|
||||
|
||||
func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
||||
func (ka *ecdheRSAKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
||||
var curveid uint16
|
||||
|
||||
Curve:
|
||||
@@ -151,7 +151,7 @@ Curve:
|
||||
copy(serverECDHParams[4:], ecdhePublic)
|
||||
|
||||
md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
|
||||
sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
|
||||
sig, err := rsa.SignPKCS1v15(config.rand(), cert.PrivateKey.(*rsa.PrivateKey), crypto.MD5SHA1, md5sha1)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
|
||||
}
|
||||
@@ -167,7 +167,7 @@ Curve:
|
||||
return skx, nil
|
||||
}
|
||||
|
||||
func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
||||
func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
||||
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
|
||||
return nil, errors.New("bad ClientKeyExchange")
|
||||
}
|
||||
|
||||
@@ -388,10 +388,10 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
|
||||
h := hashType.New()
|
||||
if h == nil {
|
||||
if !hashType.Available() {
|
||||
return ErrUnsupportedAlgorithm
|
||||
}
|
||||
h := hashType.New()
|
||||
|
||||
h.Write(signed)
|
||||
digest := h.Sum(nil)
|
||||
|
||||
@@ -327,6 +327,9 @@ func (db *DB) prepare(query string) (stmt *Stmt, err error) {
|
||||
// Exec executes a query without returning any rows.
|
||||
func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
|
||||
sargs, err := subsetTypeArgs(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res Result
|
||||
for i := 0; i < 10; i++ {
|
||||
res, err = db.exec(query, sargs)
|
||||
|
||||
@@ -7,14 +7,19 @@ package gosym
|
||||
import (
|
||||
"debug/elf"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var pclinetestBinary string
|
||||
var (
|
||||
pclineTempDir string
|
||||
pclinetestBinary string
|
||||
)
|
||||
|
||||
func dotest() bool {
|
||||
// For now, only works on ELF platforms.
|
||||
@@ -24,10 +29,18 @@ func dotest() bool {
|
||||
if pclinetestBinary != "" {
|
||||
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;
|
||||
// the resulting binary looks like it was built from pclinetest.s,
|
||||
// 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",
|
||||
pclinetestBinary, pclinetestBinary, pclinetestBinary)
|
||||
cmd := exec.Command("sh", "-c", command)
|
||||
@@ -170,6 +183,7 @@ func TestPCLine(t *testing.T) {
|
||||
if !dotest() {
|
||||
return
|
||||
}
|
||||
defer os.RemoveAll(pclineTempDir)
|
||||
|
||||
f, tab := crack(pclinetestBinary, t)
|
||||
text := f.Section(".text")
|
||||
|
||||
@@ -57,6 +57,7 @@ func Encode(dst, src []byte) int {
|
||||
if v == 0 && len(src) >= 4 {
|
||||
dst[0] = 'z'
|
||||
dst = dst[1:]
|
||||
src = src[4:]
|
||||
n++
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -28,6 +28,11 @@ var pairs = []testpair{
|
||||
"l(DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G\n" +
|
||||
">uD.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c\n",
|
||||
},
|
||||
// Special case when shortening !!!!! to z.
|
||||
{
|
||||
"\000\000\000\000",
|
||||
"z",
|
||||
},
|
||||
}
|
||||
|
||||
var bigtest = pairs[len(pairs)-1]
|
||||
|
||||
@@ -377,11 +377,6 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
|
||||
} else {
|
||||
// Bottom 7 bits give the number of length bytes to follow.
|
||||
numBytes := int(b & 0x7f)
|
||||
// We risk overflowing a signed 32-bit number if we accept more than 3 bytes.
|
||||
if numBytes > 3 {
|
||||
err = StructuralError{"length too large"}
|
||||
return
|
||||
}
|
||||
if numBytes == 0 {
|
||||
err = SyntaxError{"indefinite length found (not DER)"}
|
||||
return
|
||||
@@ -394,8 +389,19 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
|
||||
}
|
||||
b = bytes[offset]
|
||||
offset++
|
||||
if ret.length >= 1<<23 {
|
||||
// We can't shift ret.length up without
|
||||
// overflowing.
|
||||
err = StructuralError{"length too large"}
|
||||
return
|
||||
}
|
||||
ret.length <<= 8
|
||||
ret.length |= int(b)
|
||||
if ret.length == 0 {
|
||||
// DER requires that lengths be minimal.
|
||||
err = StructuralError{"superfluous leading zeros in length"}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -283,6 +283,12 @@ var tagAndLengthData = []tagAndLengthTest{
|
||||
{[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}},
|
||||
{[]byte{0x1f, 0x85}, false, tagAndLength{}},
|
||||
{[]byte{0x30, 0x80}, false, tagAndLength{}},
|
||||
// Superfluous zeros in the length should be an error.
|
||||
{[]byte{0xa0, 0x82, 0x00, 0x01}, false, tagAndLength{}},
|
||||
// Lengths up to the maximum size of an int should work.
|
||||
{[]byte{0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff}, true, tagAndLength{2, 0, 0x7fffffff, true}},
|
||||
// Lengths that would overflow an int should be rejected.
|
||||
{[]byte{0xa0, 0x84, 0x80, 0x00, 0x00, 0x00}, false, tagAndLength{}},
|
||||
}
|
||||
|
||||
func TestParseTagAndLength(t *testing.T) {
|
||||
|
||||
@@ -230,7 +230,12 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
|
||||
if in == '=' && j >= 2 && len(src) < 4 {
|
||||
// We've reached the end and there's
|
||||
// padding
|
||||
if len(src) == 0 && j == 2 {
|
||||
// not enough padding
|
||||
return n, false, CorruptInputError(len(osrc))
|
||||
}
|
||||
if len(src) > 0 && src[0] != '=' {
|
||||
// incorrect padding
|
||||
return n, false, CorruptInputError(len(osrc) - len(src) - 1)
|
||||
}
|
||||
dlen = j
|
||||
@@ -313,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)
|
||||
d.nbuf += nn
|
||||
if d.nbuf < 4 {
|
||||
if d.err != nil || d.nbuf < 4 {
|
||||
return 0, d.err
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ package base64
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type testpair struct {
|
||||
@@ -151,6 +153,9 @@ func TestDecodeCorrupt(t *testing.T) {
|
||||
{"AAA=AAAA", 3},
|
||||
{"AAAAA", 4},
|
||||
{"AAAAAA", 4},
|
||||
{"A=", 1},
|
||||
{"AA=", 3},
|
||||
{"AAAAAA=", 7},
|
||||
}
|
||||
|
||||
for _, e := range examples {
|
||||
@@ -223,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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ uninterpreted bytes of the value.
|
||||
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.
|
||||
|
||||
Maps are sent as an unsigned count followed by that man key, element
|
||||
Maps are sent as an unsigned count followed by that many key, element
|
||||
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
|
||||
transmitted.
|
||||
|
||||
@@ -273,9 +273,14 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (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() {
|
||||
v = iv.Elem()
|
||||
continue
|
||||
e := iv.Elem()
|
||||
if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) {
|
||||
v = e
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
pv := v
|
||||
@@ -588,6 +593,11 @@ func (d *decodeState) literal(v reflect.Value) {
|
||||
// produce more helpful error messages.
|
||||
func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) {
|
||||
// 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
|
||||
unmarshaler, pv := d.indirect(v, wantptr)
|
||||
if unmarshaler != nil {
|
||||
|
||||
@@ -638,3 +638,68 @@ func TestAnonymous(t *testing.T) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
@@ -95,7 +96,7 @@ import (
|
||||
//
|
||||
// Channel, complex, and function values cannot be encoded in JSON.
|
||||
// Attempting to encode such a value causes Marshal to return
|
||||
// an InvalidTypeError.
|
||||
// an UnsupportedTypeError.
|
||||
//
|
||||
// JSON cannot represent cyclic data structures and Marshal does not
|
||||
// handle them. Passing cyclic structures to Marshal will result in
|
||||
@@ -156,6 +157,8 @@ type Marshaler interface {
|
||||
MarshalJSON() ([]byte, error)
|
||||
}
|
||||
|
||||
// An UnsupportedTypeError is returned by Marshal when attempting
|
||||
// to encode an unsupported value type.
|
||||
type UnsupportedTypeError struct {
|
||||
Type reflect.Type
|
||||
}
|
||||
@@ -415,9 +418,11 @@ func isValidTag(s string) bool {
|
||||
return false
|
||||
}
|
||||
for _, c := range s {
|
||||
switch c {
|
||||
case '$', '-', '_', '/', '%':
|
||||
// Acceptable
|
||||
switch {
|
||||
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~", c):
|
||||
// Backslash and quote chars are reserved, but
|
||||
// otherwise any punctuation chars are allowed
|
||||
// in a tag name.
|
||||
default:
|
||||
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
|
||||
return false
|
||||
|
||||
@@ -40,6 +40,10 @@ type percentSlashTag struct {
|
||||
V string `json:"text/html%"` // http://golang.org/issue/2718
|
||||
}
|
||||
|
||||
type punctuationTag struct {
|
||||
V string `json:"!#$%&()*+-./:<=>?@[]^_{|}~"` // http://golang.org/issue/3546
|
||||
}
|
||||
|
||||
type emptyTag struct {
|
||||
W string
|
||||
}
|
||||
@@ -73,6 +77,7 @@ var structTagObjectKeyTests = []struct {
|
||||
{badFormatTag{"Orfevre"}, "Orfevre", "Y"},
|
||||
{badCodeTag{"Reliable Man"}, "Reliable Man", "Z"},
|
||||
{percentSlashTag{"brut"}, "brut", "text/html%"},
|
||||
{punctuationTag{"Union Rags"}, "Union Rags", "!#$%&()*+-./:<=>?@[]^_{|}~"},
|
||||
}
|
||||
|
||||
func TestStructTagObjectKey(t *testing.T) {
|
||||
|
||||
@@ -28,9 +28,10 @@ type Block struct {
|
||||
}
|
||||
|
||||
// getLine results the first \r\n or \n delineated line from the given byte
|
||||
// array. The line does not include the \r\n or \n. The remainder of the byte
|
||||
// array (also not including the new line bytes) is also returned and this will
|
||||
// always be smaller than the original argument.
|
||||
// array. The line does not include trailing whitespace or the trailing new
|
||||
// line bytes. The remainder of the byte array (also not including the new line
|
||||
// bytes) is also returned and this will always be smaller than the original
|
||||
// argument.
|
||||
func getLine(data []byte) (line, rest []byte) {
|
||||
i := bytes.Index(data, []byte{'\n'})
|
||||
var j int
|
||||
@@ -43,7 +44,7 @@ func getLine(data []byte) (line, rest []byte) {
|
||||
i--
|
||||
}
|
||||
}
|
||||
return data[0:i], data[j:]
|
||||
return bytes.TrimRight(data[0:i], " \t"), data[j:]
|
||||
}
|
||||
|
||||
// removeWhitespace returns a copy of its input with all spaces, tab and
|
||||
|
||||
@@ -127,13 +127,13 @@ Certificate chain
|
||||
-----BEGIN CERTIFICATE-----
|
||||
testing
|
||||
-----BEGIN CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID6TCCA1ICAQEwDQYJKoZIhvcNAQEFBQAwgYsxCzAJBgNVBAYTAlVTMRMwEQYD
|
||||
VQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQK
|
||||
EwtHb29nbGUgSW5jLjEMMAoGA1UECxMDRW5nMQwwCgYDVQQDEwNhZ2wxHTAbBgkq
|
||||
hkiG9w0BCQEWDmFnbEBnb29nbGUuY29tMB4XDTA5MDkwOTIyMDU0M1oXDTEwMDkw
|
||||
OTIyMDU0M1owajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAf
|
||||
BgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMaZXVyb3Bh
|
||||
EwtHb29nbGUgSW5jLjEMMAoGA1UECxMDRW5nMQwwCgYDVQQDEwNhZ2wxHTAbBgkq
|
||||
hkiG9w0BCQEWDmFnbEBnb29nbGUuY29tMB4XDTA5MDkwOTIyMDU0M1oXDTEwMDkw
|
||||
OTIyMDU0M1owajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAf
|
||||
BgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMaZXVyb3Bh
|
||||
LnNmby5jb3JwLmdvb2dsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
|
||||
AoICAQC6pgYt7/EibBDumASF+S0qvqdL/f+nouJw2T1Qc8GmXF/iiUcrsgzh/Fd8
|
||||
pDhz/T96Qg9IyR4ztuc2MXrmPra+zAuSf5bevFReSqvpIt8Duv0HbDbcqs/XKPfB
|
||||
@@ -149,15 +149,15 @@ Pomjn71GNTtDeWAXibjCgdL6iHACCF6Htbl0zGlG0OAK+bdn0QIDAQABMA0GCSqG
|
||||
SIb3DQEBBQUAA4GBAOKnQDtqBV24vVqvesL5dnmyFpFPXBn3WdFfwD6DzEb21UVG
|
||||
5krmJiu+ViipORJPGMkgoL6BjU21XI95VQbun5P8vvg8Z+FnFsvRFY3e1CCzAVQY
|
||||
ZsUkLw2I7zI/dNlWdB8Xp7v+3w9sX5N3J/WuJ1KOO5m26kRlHQo7EzT3974g
|
||||
-----END CERTIFICATE-----
|
||||
-----END CERTIFICATE-----
|
||||
1 s:/C=ZA/O=Ca Inc./CN=CA Inc
|
||||
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,80C7C7A09690757A
|
||||
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,80C7C7A09690757A
|
||||
|
||||
eQp5ZkH6CyHBz7BZfUPxyLCCmftsBJ7HlqGb8Ld21cSwnzWZ4/SIlhyrUtsfw7VR
|
||||
2TTwA+odo9ex7GdxOTaH8oZFumIRoiEjHsk8U7Bhntp+ekkPP79xunnN7hb7hkhr
|
||||
2TTwA+odo9ex7GdxOTaH8oZFumIRoiEjHsk8U7Bhntp+ekkPP79xunnN7hb7hkhr
|
||||
yGDQZgA7s2cQHQ71v3gwT2BACAft26jCjbM1wgNzBnJ8M0Rzn68YWqaPtdBu8qb/
|
||||
zVR5JB1mnqvTSbFsfF5yMc6o2WQ9jJCl6KypnMl+BpL+dlvdjYVK4l9lYsB1Hs3d
|
||||
+zDBbWxos818zzhS8/y6eIfiSG27cqrbhURbmgiSfDXjncK4m/pLcQ7mmBL6mFOr
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
This directory tree contains experimental packages and
|
||||
unfinished code that is subject to even more change than the
|
||||
rest of the Go tree.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user