mirror of
https://github.com/golang/go.git
synced 2026-01-30 23:52:05 +03:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e809658d77 | ||
|
|
504a104a2c | ||
|
|
29cfbcfef4 | ||
|
|
55b9234023 | ||
|
|
d6d493fc56 | ||
|
|
4bc85b2eb8 | ||
|
|
83153e7f37 | ||
|
|
7a8201b924 | ||
|
|
38d52ef0c4 | ||
|
|
f82bd3cc7d | ||
|
|
3c72ed3bfa | ||
|
|
a17ec6b30c | ||
|
|
0d8ac5ecf1 | ||
|
|
573afbcdb6 | ||
|
|
a6a4701053 | ||
|
|
81839a93a9 | ||
|
|
3a7da56582 | ||
|
|
f363ad2a55 | ||
|
|
fe52bcc8e6 | ||
|
|
f50329534a | ||
|
|
1d8cdaf6ce | ||
|
|
49fb8d3cdb | ||
|
|
9be3d08e6a | ||
|
|
b3efd7d6e8 | ||
|
|
1a5acb4b3a | ||
|
|
4b1cc51518 | ||
|
|
4f989a487d | ||
|
|
d5bb1db3ec | ||
|
|
c7cc983097 | ||
|
|
a85b9c5467 |
10
.github/ISSUE_TEMPLATE
vendored
10
.github/ISSUE_TEMPLATE
vendored
@@ -1,20 +1,20 @@
|
||||
Please answer these questions before submitting your issue. Thanks!
|
||||
|
||||
### What version of Go are you using (`go version`)?
|
||||
1. What version of Go are you using (`go version`)?
|
||||
|
||||
|
||||
### What operating system and processor architecture are you using (`go env`)?
|
||||
2. What operating system and processor architecture are you using (`go env`)?
|
||||
|
||||
|
||||
### What did you do?
|
||||
3. What did you do?
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
A link on play.golang.org is best.
|
||||
|
||||
|
||||
### What did you expect to see?
|
||||
4. What did you expect to see?
|
||||
|
||||
|
||||
### What did you see instead?
|
||||
5. What did you see instead?
|
||||
|
||||
|
||||
|
||||
76
AUTHORS
76
AUTHORS
@@ -27,7 +27,6 @@ Ainar Garipov <gugl.zadolbal@gmail.com>
|
||||
Akihiro Suda <suda.kyoto@gmail.com>
|
||||
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
Alan Shreve <alan@inconshreveable.com>
|
||||
Albert Nigmatzianov <albertnigma@gmail.com>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Alberto Bertogli <albertito@blitiri.com.ar>
|
||||
Alberto Donizetti <alb.donizetti@gmail.com>
|
||||
@@ -36,14 +35,11 @@ Aleksandar Dezelin <dezelin@gmail.com>
|
||||
Alessandro Arzilli <alessandro.arzilli@gmail.com>
|
||||
Alex A Skinner <alex@lx.lc>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
Alex Browne <stephenalexbrowne@gmail.com>
|
||||
Alex Carol <alex.carol.c@gmail.com>
|
||||
Alex Jin <toalexjin@gmail.com>
|
||||
Alex Plugaru <alex@plugaru.org> <alexandru.plugaru@gmail.com>
|
||||
Alex Schroeder <alex@gnu.org>
|
||||
Alex Sergeyev <abc@alexsergeyev.com>
|
||||
Alexander Demakin <alexander.demakin@gmail.com>
|
||||
Alexander Döring <email@alexd.ch>
|
||||
Alexander Larsson <alexander.larsson@gmail.com>
|
||||
Alexander Morozov <lk4d4math@gmail.com>
|
||||
Alexander Neumann <alexander@bumpern.de>
|
||||
@@ -59,14 +55,10 @@ Alexey Borzenkov <snaury@gmail.com>
|
||||
Alexey Palazhchenko <alexey.palazhchenko@gmail.com>
|
||||
Aliaksandr Valialkin <valyala@gmail.com>
|
||||
Alif Rachmawadi <subosito@gmail.com>
|
||||
Allan Simon <allan.simon@supinfo.com>
|
||||
Alok Menghrajani <alok.menghrajani@gmail.com>
|
||||
Amazon.com, Inc
|
||||
Amir Mohammad Saied <amir@gluegadget.com>
|
||||
Amrut Joshi <amrut.joshi@gmail.com>
|
||||
Andre Nathan <andrenth@gmail.com>
|
||||
Andreas Auernhammer <aead@mail.de>
|
||||
Andreas Litt <andreas.litt@gmail.com>
|
||||
Andrei Korzhevskii <a.korzhevskiy@gmail.com>
|
||||
Andrei Vieru <euvieru@gmail.com>
|
||||
Andrew Balholm <andybalholm@gmail.com>
|
||||
@@ -76,7 +68,6 @@ Andrew Ekstedt <andrew.ekstedt@gmail.com>
|
||||
Andrew Etter <andrew.etter@gmail.com>
|
||||
Andrew Harding <andrew@spacemonkey.com>
|
||||
Andrew Lutomirski <andy@luto.us>
|
||||
Andrew Pogrebnoy <absourd.noise@gmail.com>
|
||||
Andrew Pritchard <awpritchard@gmail.com>
|
||||
Andrew Radev <andrey.radev@gmail.com>
|
||||
Andrew Skiba <skibaa@gmail.com>
|
||||
@@ -109,7 +100,6 @@ Arnout Engelen <arnout@bzzt.net>
|
||||
Aron Nopanen <aron.nopanen@gmail.com>
|
||||
Artyom Pervukhin <artyom.pervukhin@gmail.com>
|
||||
Arvindh Rajesh Tamilmani <art@a-30.net>
|
||||
Atin Malaviya <amalaviy@akamai.com>
|
||||
Ato Araki <ato.araki@gmail.com>
|
||||
Audrey Lim <audreylh@gmail.com>
|
||||
Augusto Roman <aroman@gmail.com>
|
||||
@@ -128,9 +118,7 @@ Bjorn Tillenius <bjorn@tillenius.me>
|
||||
Bjorn Tipling <bjorn.tipling@gmail.com>
|
||||
Blake Gentry <blakesgentry@gmail.com>
|
||||
Blake Mizerany <blake.mizerany@gmail.com>
|
||||
Blixt <me@blixt.nyc>
|
||||
Bobby Powers <bobbypowers@gmail.com>
|
||||
Bolt
|
||||
Brady Catherman <brady@gmail.com>
|
||||
Brady Sullivan <brady@bsull.com>
|
||||
Brendan Daniel Tracey <tracey.brendan@gmail.com>
|
||||
@@ -138,15 +126,12 @@ Brett Cannon <bcannon@gmail.com>
|
||||
Brian Dellisanti <briandellisanti@gmail.com>
|
||||
Brian G. Merrell <bgmerrell@gmail.com>
|
||||
Brian Gitonga Marete <marete@toshnix.com> <bgmarete@gmail.com>
|
||||
Brian Kennedy <btkennedy@gmail.com>
|
||||
Brian Ketelsen <bketelsen@gmail.com>
|
||||
Brian Smith <ohohvi@gmail.com>
|
||||
Bryan Alexander <Kozical@msn.com>
|
||||
Bryan Ford <brynosaurus@gmail.com>
|
||||
Caine Tighe <arctanofyourface@gmail.com>
|
||||
Caleb Spare <cespare@gmail.com>
|
||||
Carl Chatfield <carlchatfield@gmail.com>
|
||||
Carl Johnson <me@carlmjohnson.net>
|
||||
Carlos Castillo <cookieo9@gmail.com>
|
||||
Carlos Cirello <uldericofilho@gmail.com>
|
||||
Case Nelson <case.nelson@gmail.com>
|
||||
@@ -185,7 +170,6 @@ CoreOS, Inc.
|
||||
Corey Thomasson <cthom.lists@gmail.com>
|
||||
Cristian Staretu <unclejacksons@gmail.com>
|
||||
Currant
|
||||
Cyrill Schumacher <cyrill@schumacher.fm>
|
||||
Damian Gryski <dgryski@gmail.com>
|
||||
Dan Caddigan <goldcaddy77@gmail.com>
|
||||
Dan Callahan <dan.callahan@gmail.com>
|
||||
@@ -196,7 +180,6 @@ Daniel Johansson <dajo2002@gmail.com>
|
||||
Daniel Kerwin <d.kerwin@gini.net>
|
||||
Daniel Krech <eikeon@eikeon.com>
|
||||
Daniel Lidén <daniel.liden.87@gmail.com>
|
||||
Daniel Martí <mvdan@mvdan.cc>
|
||||
Daniel Morsing <daniel.morsing@gmail.com>
|
||||
Daniel Ortiz Pereira da Silva <daniel.particular@gmail.com>
|
||||
Daniel Skinner <daniel@dasa.cc>
|
||||
@@ -216,12 +199,10 @@ David Jakob Fritz <david.jakob.fritz@gmail.com>
|
||||
David Leon Gil <coruus@gmail.com>
|
||||
David R. Jenni <david.r.jenni@gmail.com>
|
||||
David Sansome <me@davidsansome.com>
|
||||
David Stainton <dstainton415@gmail.com>
|
||||
David Thomas <davidthomas426@gmail.com>
|
||||
David Titarenco <david.titarenco@gmail.com>
|
||||
Davies Liu <davies.liu@gmail.com>
|
||||
Dean Prichard <dean.prichard@gmail.com>
|
||||
Deepak Jois <deepak.jois@gmail.com>
|
||||
Denis Bernard <db047h@gmail.com>
|
||||
Denis Brandolini <denis.brandolini@gmail.com>
|
||||
Denys Honsiorovskyi <honsiorovskyi@gmail.com>
|
||||
@@ -230,13 +211,11 @@ Derek Parker <parkerderek86@gmail.com>
|
||||
Derek Shockey <derek.shockey@gmail.com>
|
||||
Develer SRL
|
||||
Devon H. O'Dell <devon.odell@gmail.com>
|
||||
Dhaivat Pandit <dhaivatpandit@gmail.com>
|
||||
Dhiru Kholia <dhiru.kholia@gmail.com>
|
||||
Didier Spezia <didier.06@gmail.com>
|
||||
Dimitri Tcaciuc <dtcaciuc@gmail.com>
|
||||
Dirk Gadsden <dirk@esherido.com>
|
||||
Diwaker Gupta <diwakergupta@gmail.com>
|
||||
Dmitri Popov <operator@cv.dp-net.com>
|
||||
Dmitri Shuralyov <shurcooL@gmail.com>
|
||||
Dmitriy Dudkin <dudkin.dmitriy@gmail.com>
|
||||
Dmitriy Shelenin <deemok@googlemail.com> <deemok@gmail.com>
|
||||
@@ -278,12 +257,10 @@ Evan Shaw <chickencha@gmail.com>
|
||||
Ewan Chou <coocood@gmail.com>
|
||||
Fabian Wickborn <fabian@wickborn.net>
|
||||
Fabrizio Milo <mistobaan@gmail.com>
|
||||
Faiyaz Ahmed <ahmedf@vmware.com>
|
||||
Fan Hongjian <fan.howard@gmail.com>
|
||||
Fastly, Inc.
|
||||
Fatih Arslan <fatih@arslan.io>
|
||||
Fazlul Shahriar <fshahriar@gmail.com>
|
||||
Fedor Indutny <fedor@indutny.com>
|
||||
Felix Geisendörfer <haimuiba@gmail.com>
|
||||
Filippo Valsorda <hi@filippo.io>
|
||||
Firmansyah Adiputra <frm.adiputra@gmail.com>
|
||||
@@ -298,20 +275,16 @@ Fredrik Enestad <fredrik.enestad@soundtrackyourbrand.com>
|
||||
Frithjof Schulze <schulze@math.uni-hannover.de> <sfrithjof@gmail.com>
|
||||
Frits van Bommel <fvbommel@gmail.com>
|
||||
Gabriel Aszalos <gabriel.aszalos@gmail.com>
|
||||
Gabriel Russell <gabriel.russell@gmail.com>
|
||||
Gareth Paul Jones <gpj@foursquare.com>
|
||||
Gary Burd <gary@beagledreams.com>
|
||||
Gaurish Sharma <contact@gaurishsharma.com>
|
||||
Gautham Thambidorai <gautham.dorai@gmail.com>
|
||||
Geert-Johan Riemer <gjr19912@gmail.com>
|
||||
Geoffroy Lorieux <lorieux.g@gmail.com>
|
||||
Georg Reinke <guelfey@gmail.com>
|
||||
George Shammas <george@shamm.as> <georgyo@gmail.com>
|
||||
Gerasimos Dimitriadis <gedimitr@gmail.com>
|
||||
Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
|
||||
Giles Lean <giles.lean@pobox.com>
|
||||
Giulio Iotti <dullgiulio@gmail.com>
|
||||
Gleb Stepanov <glebstepanov1992@gmail.com>
|
||||
Google Inc.
|
||||
Gordon Klaus <gordon.klaus@gmail.com>
|
||||
Graham King <graham4king@gmail.com>
|
||||
@@ -334,7 +307,6 @@ Hector Chu <hectorchu@gmail.com>
|
||||
Hector Martin Cantero <hector@marcansoft.com>
|
||||
Henning Schmiedehausen <henning@schmiedehausen.org>
|
||||
Henrik Edwards <henrik.edwards@gmail.com>
|
||||
Henrik Hodne <henrik@hodne.io>
|
||||
Herbert Georg Fischer <herbert.fischer@gmail.com>
|
||||
Hironao OTSUBO <motemen@gmail.com>
|
||||
Hiroshi Ioka <hirochachacha@gmail.com>
|
||||
@@ -355,14 +327,12 @@ Ingo Oeser <nightlyone@googlemail.com>
|
||||
Intel Corporation
|
||||
Irieda Noboru <irieda@gmail.com>
|
||||
Isaac Wagner <ibw@isaacwagner.me>
|
||||
Ivan Babrou <ivan@cloudflare.com>
|
||||
Ivan Ukhov <ivan.ukhov@gmail.com>
|
||||
Jacob Hoffman-Andrews <github@hoffman-andrews.com>
|
||||
Jae Kwon <jae@tendermint.com>
|
||||
Jakob Borg <jakob@nym.se>
|
||||
Jakub Ryszard Czarnowicz <j.czarnowicz@gmail.com>
|
||||
James Bardin <j.bardin@gmail.com>
|
||||
James Clarke <jrtc27@jrtc27.com>
|
||||
James David Chalfant <james.chalfant@gmail.com>
|
||||
James Fysh <james.fysh@gmail.com>
|
||||
James Gray <james@james4k.com>
|
||||
@@ -372,7 +342,6 @@ James Schofield <james@shoeboxapp.com>
|
||||
James Sweet <james.sweet88@googlemail.com>
|
||||
James Toy <nil@opensesame.st>
|
||||
James Whitehead <jnwhiteh@gmail.com>
|
||||
Jamie Beverly <jamie.r.beverly@gmail.com>
|
||||
Jamil Djadala <djadala@gmail.com>
|
||||
Jan H. Hosang <jan.hosang@gmail.com>
|
||||
Jan Mercl <0xjnml@gmail.com>
|
||||
@@ -383,17 +352,14 @@ Jani Monoses <jani.monoses@ubuntu.com>
|
||||
Jaroslavas Počepko <jp@webmaster.ms>
|
||||
Jason Barnett <jason.w.barnett@gmail.com>
|
||||
Jason Del Ponte <delpontej@gmail.com>
|
||||
Jason Smale <jsmale@zendesk.com>
|
||||
Jason Travis <infomaniac7@gmail.com>
|
||||
Jay Weisskopf <jay@jayschwa.net>
|
||||
Jean-Nicolas Moal <jn.moal@gmail.com>
|
||||
Jeff Hodges <jeff@somethingsimilar.com>
|
||||
Jeff R. Allen <jra@nella.org>
|
||||
Jeff Sickel <jas@corpus-callosum.com>
|
||||
Jeff Wendling <jeff@spacemonkey.com>
|
||||
Jens Frederich <jfrederich@gmail.com>
|
||||
Jeremy Jackins <jeremyjackins@gmail.com>
|
||||
Jeroen Bobbeldijk <jerbob92@gmail.com>
|
||||
Jess Frazelle <me@jessfraz.com>
|
||||
Jihyun Yu <yjh0502@gmail.com>
|
||||
Jim McGrath <jimmc2@gmail.com>
|
||||
@@ -401,7 +367,6 @@ Jimmy Zelinskie <jimmyzelinskie@gmail.com>
|
||||
Jingcheng Zhang <diogin@gmail.com>
|
||||
Jingguo Yao <yaojingguo@gmail.com>
|
||||
Jiong Du <londevil@gmail.com>
|
||||
Jirka Daněk <dnk@mail.muni.cz>
|
||||
Joakim Sernbrant <serbaut@gmail.com>
|
||||
Joe Farrell <joe2farrell@gmail.com>
|
||||
Joe Harrison <joehazzers@gmail.com>
|
||||
@@ -428,11 +393,9 @@ Jonathan Mark <jhmark@xenops.com>
|
||||
Jonathan Rudenberg <jonathan@titanous.com>
|
||||
Jonathan Wills <runningwild@gmail.com>
|
||||
Jongmin Kim <atomaths@gmail.com>
|
||||
Joonas Kuorilehto <joneskoo@derbian.fi>
|
||||
Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Joseph Holsten <joseph@josephholsten.com>
|
||||
Josh Bleecher Snyder <josharian@gmail.com>
|
||||
Josh Chorlton <jchorlton@gmail.com>
|
||||
Josh Goebel <dreamer3@gmail.com>
|
||||
Josh Holland <jrh@joshh.co.uk>
|
||||
Joshua Chase <jcjoshuachase@gmail.com>
|
||||
@@ -443,9 +406,7 @@ Julian Kornberger <jk+github@digineo.de>
|
||||
Julian Phillips <julian@quantumfyre.co.uk>
|
||||
Julien Schmidt <google@julienschmidt.com>
|
||||
Justin Nuß <nuss.justin@gmail.com>
|
||||
Justyn Temme <justyntemme@gmail.com>
|
||||
Kai Backman <kaib@golang.org>
|
||||
Kale Blankenship <kale@lemnisys.com>
|
||||
Kamil Kisiel <kamil@kamilkisiel.net> <kamil.kisiel@gmail.com>
|
||||
Kang Hu <hukangustc@gmail.com>
|
||||
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
|
||||
@@ -476,7 +437,6 @@ Kyle Lemons <kyle@kylelemons.net>
|
||||
L Campbell <unpantsu@gmail.com>
|
||||
Lai Jiangshan <eag0628@gmail.com>
|
||||
Larz Conwell <larzconwell@gmail.com>
|
||||
LE Manh Cuong <cuong.manhle.vn@gmail.com>
|
||||
Lee Hinman <hinman@gmail.com>
|
||||
Lee Packham <lpackham@gmail.com>
|
||||
Lewin Bormann <lewin.bormann@gmail.com>
|
||||
@@ -488,12 +448,10 @@ Luan Santos <cfcluan@gmail.com>
|
||||
Luca Greco <luca.greco@alcacoop.it>
|
||||
Lucien Stuker <lucien.stuker@gmail.com>
|
||||
Lucio De Re <lucio.dere@gmail.com>
|
||||
Luigi Riefolo <luigi.riefolo@gmail.com>
|
||||
Luit van Drongelen <luitvd@gmail.com>
|
||||
Luka Zakrajšek <tr00.g33k@gmail.com>
|
||||
Luke Curley <qpingu@gmail.com>
|
||||
Mal Curtis <mal@mal.co.nz>
|
||||
Manfred Touron <m@42.am>
|
||||
Manu S Ajith <neo@codingarena.in>
|
||||
Manuel Mendez <mmendez534@gmail.com>
|
||||
Marc Weistroff <marc@weistroff.net>
|
||||
@@ -507,9 +465,7 @@ Markover Inc. DBA Poptip
|
||||
Markus Duft <markus.duft@salomon.at>
|
||||
Markus Sonderegger <marraison@gmail.com>
|
||||
Markus Zimmermann <zimmski@gmail.com>
|
||||
Martin Bertschler <mbertschler@gmail.com>
|
||||
Martin Garton <garton@gmail.com>
|
||||
Martin Hamrle <martin.hamrle@gmail.com>
|
||||
Martin Möhrmann <martisch@uos.de>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Martin Olsson <martin@minimum.se>
|
||||
@@ -531,13 +487,10 @@ Matt T. Proud <matt.proud@gmail.com>
|
||||
Matt Williams <gh@mattyw.net>
|
||||
Matthew Brennan <matty.brennan@gmail.com>
|
||||
Matthew Cottingham <mattcottingham@gmail.com>
|
||||
Matthew Denton <mdenton@skyportsystems.com>
|
||||
Matthew Holt <Matthew.Holt+git@gmail.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
|
||||
Maxim Khitrov <max@mxcrypt.com>
|
||||
Maxwell Krohn <themax@gmail.com>
|
||||
MediaMath, Inc
|
||||
Meir Fischer <meirfischer@gmail.com>
|
||||
Meng Zhuo <mengzhuo1203@gmail.com>
|
||||
Meteor Development Group
|
||||
@@ -564,8 +517,6 @@ Miguel Mendez <stxmendez@gmail.com>
|
||||
Mihai Borobocea <MihaiBorobocea@gmail.com>
|
||||
Mikael Tillenius <mikti42@gmail.com>
|
||||
Mike Andrews <mra@xoba.com>
|
||||
Mike Appleby <mike@app.leby.org>
|
||||
Mike Houston <mike@kothar.net>
|
||||
Mike Rosset <mike.rosset@gmail.com>
|
||||
Mikhail Gusarov <dottedmag@dottedmag.net>
|
||||
Mikhail Panchenko <m@mihasya.com>
|
||||
@@ -573,9 +524,7 @@ Miki Tebeka <miki.tebeka@gmail.com>
|
||||
Mikio Hara <mikioh.mikioh@gmail.com>
|
||||
Mikkel Krautz <mikkel@krautz.dk>
|
||||
Miquel Sabaté Solà <mikisabate@gmail.com>
|
||||
Miroslav Genov <mgenov@gmail.com>
|
||||
Mohit Agarwal <mohit@sdf.org>
|
||||
Momchil Velikov <momchil.velikov@gmail.com>
|
||||
Monty Taylor <mordred@inaugust.com>
|
||||
Moov Corporation
|
||||
Moriyoshi Koizumi <mozo@mozo.jp>
|
||||
@@ -610,7 +559,6 @@ Niko Dziemba <niko@dziemba.com>
|
||||
Nikolay Turpitko <nikolay@turpitko.com>
|
||||
Noah Campbell <noahcampbell@gmail.com>
|
||||
Norberto Lopes <nlopes.ml@gmail.com>
|
||||
Oleg Vakheta <helginet@gmail.com>
|
||||
Oleku Konko <oleku.konko@gmail.com>
|
||||
Oling Cat <olingcat@gmail.com>
|
||||
Oliver Hookins <ohookins@gmail.com>
|
||||
@@ -625,7 +573,6 @@ Padraig Kitterick <padraigkitterick@gmail.com>
|
||||
Palm Stone Games
|
||||
Paolo Giarrusso <p.giarrusso@gmail.com>
|
||||
Paolo Martini <mrtnpaolo@gmail.com>
|
||||
Parker Moore <parkrmoore@gmail.com>
|
||||
Pascal S. de Kloe <pascal@quies.net>
|
||||
Patrick Crosby <patrick@stathat.com>
|
||||
Patrick Gavlin <pgavlin@gmail.com>
|
||||
@@ -672,7 +619,6 @@ Quan Yong Zhai <qyzhai@gmail.com>
|
||||
Quentin Perez <qperez@ocs.online.net>
|
||||
Quoc-Viet Nguyen <afelion@gmail.com>
|
||||
RackTop Systems Inc.
|
||||
Radu Berinde <radu@cockroachlabs.com>
|
||||
Raif S. Naffah <go@naffah-raif.name>
|
||||
Rajat Goel <rajat.goel2010@gmail.com>
|
||||
Ralph Corderoy <ralph@inputplus.co.uk>
|
||||
@@ -683,7 +629,6 @@ Ricardo Padilha <ricardospadilha@gmail.com>
|
||||
Richard Barnes <rlb@ipv.sx>
|
||||
Richard Crowley <r@rcrowley.org>
|
||||
Richard Eric Gavaletz <gavaletz@gmail.com>
|
||||
Richard Gibson <richard.gibson@gmail.com>
|
||||
Richard Miller <miller.research@gmail.com>
|
||||
Richard Musiol <mail@richard-musiol.de>
|
||||
Rick Arnold <rickarnoldjr@gmail.com>
|
||||
@@ -714,14 +659,12 @@ S.Çağlar Onur <caglar@10ur.org>
|
||||
Salmān Aljammāz <s@0x65.net>
|
||||
Sam Hug <samuel.b.hug@gmail.com>
|
||||
Sam Whited <sam@samwhited.com>
|
||||
Samuele Pedroni <pedronis@lucediurna.net>
|
||||
Sanjay Menakuru <balasanjay@gmail.com>
|
||||
Sasha Sobol <sasha@scaledinference.com>
|
||||
Scott Barron <scott.barron@github.com>
|
||||
Scott Bell <scott@sctsm.com>
|
||||
Scott Ferguson <scottwferg@gmail.com>
|
||||
Scott Lawrence <bytbox@gmail.com>
|
||||
Sean Rees <sean@erifax.org>
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
Sébastien Paolacci <sebastien.paolacci@gmail.com>
|
||||
Sergei Skorobogatov <skorobo@rambler.ru>
|
||||
@@ -738,12 +681,9 @@ Shinji Tanaka <shinji.tanaka@gmail.com>
|
||||
Shivakumar GN <shivakumar.gn@gmail.com>
|
||||
Silvan Jegen <s.jegen@gmail.com>
|
||||
Simon Jefford <simon.jefford@gmail.com>
|
||||
Simon Rawet <simon@rawet.se>
|
||||
Simon Thulbourn <simon+github@thulbourn.com>
|
||||
Simon Whitehead <chemnova@gmail.com>
|
||||
Sina Siadat <siadat@gmail.com>
|
||||
Sokolov Yura <funny.falcon@gmail.com>
|
||||
Song Gao <song@gao.io>
|
||||
Spencer Nelson <s@spenczar.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Square, Inc.
|
||||
@@ -760,9 +700,7 @@ Steve Streeting <steve@stevestreeting.com>
|
||||
Steven Elliot Harris <seharris@gmail.com>
|
||||
Steven Hartland <steven.hartland@multiplay.co.uk>
|
||||
Stripe, Inc.
|
||||
Suyash <dextrous93@gmail.com>
|
||||
Sven Almgren <sven@tras.se>
|
||||
Syohei YOSHIDA <syohex@gmail.com>
|
||||
Szabolcs Nagy <nsz@port70.net>
|
||||
Tad Glines <tad.glines@gmail.com>
|
||||
Taj Khattra <taj.khattra@gmail.com>
|
||||
@@ -772,18 +710,15 @@ Tamir Duberstein <tamird@gmail.com>
|
||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||
Taru Karttunen <taruti@taruti.net>
|
||||
Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
|
||||
Terrel Shumway <gopher@shumway.us>
|
||||
Tetsuo Kiso <tetsuokiso9@gmail.com>
|
||||
Thiago Fransosi Farina <thiago.farina@gmail.com>
|
||||
Thomas Alan Copeland <talan.copeland@gmail.com>
|
||||
Thomas de Zeeuw <thomasdezeeuw@gmail.com>
|
||||
Thomas Desrosiers <thomasdesr@gmail.com>
|
||||
Thomas Kappler <tkappler@gmail.com>
|
||||
Thorben Krueger <thorben.krueger@gmail.com>
|
||||
Tilman Dilo <tilman.dilo@gmail.com>
|
||||
Tim Cooijmans <timcooijmans@gmail.com>
|
||||
Tim Ebringer <tim.ebringer@gmail.com>
|
||||
Tim Henderson <tim.tadh@gmail.com>
|
||||
Timo Savola <timo.savola@gmail.com>
|
||||
Timo Truyts <alkaloid.btx@gmail.com>
|
||||
Timothy Studd <tim@timstudd.com>
|
||||
@@ -796,11 +731,8 @@ Tor Andersson <tor.andersson@gmail.com>
|
||||
Tormod Erevik Lea <tormodlea@gmail.com>
|
||||
Totoro W <tw19881113@gmail.com>
|
||||
Travis Cline <travis.cline@gmail.com>
|
||||
Trey Lawrence <lawrence.trey@gmail.com>
|
||||
Trey Tacon <ttacon@gmail.com>
|
||||
Tristan Ooohry <ooohry@gmail.com>
|
||||
Tudor Golubenco <tudor.g@gmail.com>
|
||||
Tuo Shan <sturbo89@gmail.com>
|
||||
Tyler Bunnell <tylerbunnell@gmail.com>
|
||||
Tyler Treat <ttreat31@gmail.com>
|
||||
Ugorji Nwoke <ugorji@gmail.com>
|
||||
@@ -810,18 +742,13 @@ Upthere, Inc.
|
||||
Uriel Mangado <uriel@berlinblue.org>
|
||||
Vadim Grek <vadimprog@gmail.com>
|
||||
Vadim Vygonets <unixdj@gmail.com>
|
||||
Vendasta
|
||||
Vincent Ambo <tazjin@googlemail.com>
|
||||
Vincent Batts <vbatts@hashbangbash.com> <vbatts@gmail.com>
|
||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||
Vinu Rajashekhar <vinutheraj@gmail.com>
|
||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||
Vitor De Mario <vitordemario@gmail.com>
|
||||
Vladimir Mihailenco <vladimir.webdev@gmail.com>
|
||||
Vladimir Nikishenko <vova616@gmail.com>
|
||||
Vladimir Stefanovic <vladimir.stefanovic@imgtec.com>
|
||||
Volker Dobler <dr.volker.dobler@gmail.com>
|
||||
Weaveworks
|
||||
Wei Guangjing <vcc.163@gmail.com>
|
||||
Willem van der Schyff <willemvds@gmail.com>
|
||||
William Josephson <wjosephson@gmail.com>
|
||||
@@ -830,7 +757,6 @@ Wisdom Omuya <deafgoat@gmail.com>
|
||||
Xia Bin <snyh@snyh.org>
|
||||
Xing Xing <mikespook@gmail.com>
|
||||
Xudong Zhang <felixmelon@gmail.com>
|
||||
Xuyang Kang <xuyangkang@gmail.com>
|
||||
Yahoo Inc.
|
||||
Yann Kerhervé <yann.kerherve@gmail.com>
|
||||
Yao Zhang <lunaria21@gmail.com>
|
||||
@@ -840,13 +766,11 @@ Yesudeep Mangalapilly <yesudeep@google.com>
|
||||
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
|
||||
Yo-An Lin <yoanlin93@gmail.com>
|
||||
Yongjian Xu <i3dmaster@gmail.com>
|
||||
Yorman Arias <cixtords@gmail.com>
|
||||
Yoshiyuki Kanno <nekotaroh@gmail.com> <yoshiyuki.kanno@stoic.co.jp>
|
||||
Yusuke Kagiwada <block.rxckin.beats@gmail.com>
|
||||
Yuusei Kuwana <kuwana@kumama.org>
|
||||
Yuval Pavel Zholkover <paulzhol@gmail.com>
|
||||
Zemanta d.o.o.
|
||||
Zev Goldstein <zev.goldstein@gmail.com>
|
||||
Ziad Hatahet <hatahet@gmail.com>
|
||||
Zorion Arrizabalaga <zorionk@gmail.com>
|
||||
申习之 <bronze1man@gmail.com>
|
||||
|
||||
103
CONTRIBUTORS
103
CONTRIBUTORS
@@ -53,7 +53,6 @@ Akihiro Suda <suda.kyoto@gmail.com>
|
||||
Akshat Kumar <seed@mail.nanosouffle.net>
|
||||
Alan Donovan <adonovan@google.com>
|
||||
Alan Shreve <alan@inconshreveable.com>
|
||||
Albert Nigmatzianov <albertnigma@gmail.com>
|
||||
Albert Strasheim <fullung@gmail.com>
|
||||
Alberto Bertogli <albertito@blitiri.com.ar>
|
||||
Alberto Donizetti <alb.donizetti@gmail.com>
|
||||
@@ -63,15 +62,12 @@ Alessandro Arzilli <alessandro.arzilli@gmail.com>
|
||||
Alex A Skinner <alex@lx.lc>
|
||||
Alex Brainman <alex.brainman@gmail.com>
|
||||
Alex Bramley <abramley@google.com>
|
||||
Alex Browne <stephenalexbrowne@gmail.com>
|
||||
Alex Carol <alex.carol.c@gmail.com>
|
||||
Alex Jin <toalexjin@gmail.com>
|
||||
Alex Plugaru <alex@plugaru.org> <alexandru.plugaru@gmail.com>
|
||||
Alex Schroeder <alex@gnu.org>
|
||||
Alex Sergeyev <abc@alexsergeyev.com>
|
||||
Alex Vaghin <crhyme@google.com>
|
||||
Alexander Demakin <alexander.demakin@gmail.com>
|
||||
Alexander Döring <email@alexd.ch>
|
||||
Alexander Larsson <alexander.larsson@gmail.com>
|
||||
Alexander Morozov <lk4d4math@gmail.com>
|
||||
Alexander Neumann <alexander@bumpern.de>
|
||||
@@ -89,15 +85,11 @@ Alexey Palazhchenko <alexey.palazhchenko@gmail.com>
|
||||
Alexis Imperial-Legrand <ail@google.com>
|
||||
Aliaksandr Valialkin <valyala@gmail.com>
|
||||
Alif Rachmawadi <subosito@gmail.com>
|
||||
Allan Simon <allan.simon@supinfo.com>
|
||||
Alok Menghrajani <alok.menghrajani@gmail.com>
|
||||
Amir Mohammad Saied <amir@gluegadget.com>
|
||||
Amrut Joshi <amrut.joshi@gmail.com>
|
||||
Andre Nathan <andrenth@gmail.com>
|
||||
Andrea Spadaccini <spadaccio@google.com>
|
||||
Andreas Auernhammer <aead@mail.de>
|
||||
Andreas Jellinghaus <andreas@ionisiert.de> <anj@google.com>
|
||||
Andreas Litt <andreas.litt@gmail.com>
|
||||
Andrei Korzhevskii <a.korzhevskiy@gmail.com>
|
||||
Andrei Vieru <euvieru@gmail.com>
|
||||
Andres Erbsen <andreser@google.com>
|
||||
@@ -110,7 +102,6 @@ Andrew Gerrand <adg@golang.org>
|
||||
Andrew Harding <andrew@spacemonkey.com>
|
||||
Andrew Lutomirski <andy@luto.us>
|
||||
Andrew Pilloud <andrewpilloud@igneoussystems.com>
|
||||
Andrew Pogrebnoy <absourd.noise@gmail.com>
|
||||
Andrew Pritchard <awpritchard@gmail.com>
|
||||
Andrew Radev <andrey.radev@gmail.com>
|
||||
Andrew Skiba <skibaa@gmail.com>
|
||||
@@ -133,7 +124,6 @@ Anthony Canino <anthony.canino1@gmail.com>
|
||||
Anthony Eufemio <anthony.eufemio@gmail.com>
|
||||
Anthony Martin <ality@pbrane.org>
|
||||
Anthony Starks <ajstarks@gmail.com>
|
||||
Antonio Murdaca <runcom@redhat.com>
|
||||
Apisak Darakananda <pongad@gmail.com>
|
||||
Aram Hăvărneanu <aram@mgk.ro>
|
||||
Areski Belaid <areski@gmail.com>
|
||||
@@ -146,7 +136,6 @@ Aron Nopanen <aron.nopanen@gmail.com>
|
||||
Artyom Pervukhin <artyom.pervukhin@gmail.com>
|
||||
Arvindh Rajesh Tamilmani <art@a-30.net>
|
||||
Asim Shankar <asimshankar@gmail.com>
|
||||
Atin Malaviya <amalaviy@akamai.com>
|
||||
Ato Araki <ato.araki@gmail.com>
|
||||
Audrey Lim <audreylh@gmail.com>
|
||||
Augusto Roman <aroman@gmail.com>
|
||||
@@ -171,17 +160,13 @@ Bill Neubauer <wcn@golang.org> <wcn@google.com> <bill.neubauer@gmail.com>
|
||||
Bill O'Farrell <billo@ca.ibm.com>
|
||||
Bill Thiede <couchmoney@gmail.com>
|
||||
Billie Harold Cleek <bhcleek@gmail.com>
|
||||
Billy Lynch <wlynch@google.com>
|
||||
Bjorn Tillenius <bjorn@tillenius.me>
|
||||
Bjorn Tipling <bjorn.tipling@gmail.com>
|
||||
Blake Gentry <blakesgentry@gmail.com>
|
||||
Blake Mizerany <blake.mizerany@gmail.com>
|
||||
Blixt <me@blixt.nyc>
|
||||
Bobby Powers <bobbypowers@gmail.com>
|
||||
Boris Nagaev <nagaev@google.com>
|
||||
Brad Fitzpatrick <bradfitz@golang.org> <bradfitz@gmail.com>
|
||||
Brad Garcia <bgarcia@golang.org>
|
||||
Braden Bassingthwaite <bbassingthwaite@vendasta.com>
|
||||
Brady Catherman <brady@gmail.com>
|
||||
Brady Sullivan <brady@bsull.com>
|
||||
Brandon Gilmore <varz@google.com>
|
||||
@@ -191,11 +176,9 @@ Brett Cannon <bcannon@gmail.com>
|
||||
Brian Dellisanti <briandellisanti@gmail.com>
|
||||
Brian G. Merrell <bgmerrell@gmail.com>
|
||||
Brian Gitonga Marete <marete@toshnix.com> <bgmarete@gmail.com> <bgm@google.com>
|
||||
Brian Kennedy <btkennedy@gmail.com>
|
||||
Brian Ketelsen <bketelsen@gmail.com>
|
||||
Brian Slesinsky <skybrian@google.com>
|
||||
Brian Smith <ohohvi@gmail.com>
|
||||
Bryan Alexander <Kozical@msn.com>
|
||||
Bryan C. Mills <bcmills@google.com>
|
||||
Bryan Chan <bryan.chan@ca.ibm.com>
|
||||
Bryan Ford <brynosaurus@gmail.com>
|
||||
@@ -204,12 +187,10 @@ Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
|
||||
Caleb Spare <cespare@gmail.com>
|
||||
Carl Chatfield <carlchatfield@gmail.com>
|
||||
Carl Jackson <carl@stripe.com>
|
||||
Carl Johnson <me@carlmjohnson.net>
|
||||
Carl Mastrangelo <notcarl@google.com>
|
||||
Carl Shapiro <cshapiro@google.com> <cshapiro@golang.org>
|
||||
Carlos Castillo <cookieo9@gmail.com>
|
||||
Carlos Cirello <uldericofilho@gmail.com>
|
||||
Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>
|
||||
Cary Hull <chull@google.com>
|
||||
Case Nelson <case.nelson@gmail.com>
|
||||
Casey Marshall <casey.marshall@gmail.com>
|
||||
@@ -259,12 +240,10 @@ Corey Thomasson <cthom.lists@gmail.com>
|
||||
Cosmos Nicolaou <cnicolaou@google.com>
|
||||
Cristian Staretu <unclejacksons@gmail.com>
|
||||
Cuihtlauac ALVARADO <cuihtlauac.alvarado@orange.com>
|
||||
Cyrill Schumacher <cyrill@schumacher.fm>
|
||||
Damian Gryski <dgryski@gmail.com>
|
||||
Damien Neil <dneil@google.com>
|
||||
Dan Caddigan <goldcaddy77@gmail.com>
|
||||
Dan Callahan <dan.callahan@gmail.com>
|
||||
Dan Harrington <harringtond@google.com>
|
||||
Dan Jacques <dnj@google.com>
|
||||
Dan Peterson <dpiddy@gmail.com>
|
||||
Dan Pupius <dan@medium.com>
|
||||
@@ -274,14 +253,12 @@ Daniel Johansson <dajo2002@gmail.com>
|
||||
Daniel Kerwin <d.kerwin@gini.net>
|
||||
Daniel Krech <eikeon@eikeon.com>
|
||||
Daniel Lidén <daniel.liden.87@gmail.com>
|
||||
Daniel Martí <mvdan@mvdan.cc>
|
||||
Daniel Morsing <daniel.morsing@gmail.com>
|
||||
Daniel Nadasi <dnadasi@google.com>
|
||||
Daniel Ortiz Pereira da Silva <daniel.particular@gmail.com>
|
||||
Daniel Skinner <daniel@dasa.cc>
|
||||
Daniel Speichert <daniel@speichert.pl>
|
||||
Daniel Theophanes <kardianos@gmail.com>
|
||||
Daria Kolistratova <daria.kolistratova@intel.com>
|
||||
Darren Elwood <darren@textnode.com>
|
||||
Datong Sun <dndx@idndx.com>
|
||||
Dave Borowitz <dborowitz@google.com>
|
||||
@@ -303,37 +280,30 @@ David Forsythe <dforsythe@gmail.com>
|
||||
David G. Andersen <dave.andersen@gmail.com>
|
||||
David Glasser <glasser@meteor.com>
|
||||
David Howden <dhowden@gmail.com>
|
||||
David Hubbard <dsp@google.com>
|
||||
David Jakob Fritz <david.jakob.fritz@gmail.com>
|
||||
David Leon Gil <coruus@gmail.com>
|
||||
David McLeish <davemc@google.com>
|
||||
David Presotto <presotto@gmail.com>
|
||||
David R. Jenni <david.r.jenni@gmail.com>
|
||||
David Sansome <me@davidsansome.com>
|
||||
David Stainton <dstainton415@gmail.com>
|
||||
David Symonds <dsymonds@golang.org>
|
||||
David Thomas <davidthomas426@gmail.com>
|
||||
David Titarenco <david.titarenco@gmail.com>
|
||||
Davies Liu <davies.liu@gmail.com>
|
||||
Dean Prichard <dean.prichard@gmail.com>
|
||||
Deepak Jois <deepak.jois@gmail.com>
|
||||
Denis Bernard <db047h@gmail.com>
|
||||
Denis Brandolini <denis.brandolini@gmail.com>
|
||||
Denis Nagorny <denis.nagorny@intel.com>
|
||||
Denys Honsiorovskyi <honsiorovskyi@gmail.com>
|
||||
Derek Buitenhuis <derek.buitenhuis@gmail.com>
|
||||
Derek Che <drc@yahoo-inc.com>
|
||||
Derek Parker <parkerderek86@gmail.com>
|
||||
Derek Shockey <derek.shockey@gmail.com>
|
||||
Devon H. O'Dell <devon.odell@gmail.com>
|
||||
Dhaivat Pandit <dhaivatpandit@gmail.com>
|
||||
Dhananjay Nakrani <dhananjayn@google.com>
|
||||
Dhiru Kholia <dhiru.kholia@gmail.com>
|
||||
Didier Spezia <didier.06@gmail.com>
|
||||
Dimitri Tcaciuc <dtcaciuc@gmail.com>
|
||||
Dirk Gadsden <dirk@esherido.com>
|
||||
Diwaker Gupta <diwakergupta@gmail.com>
|
||||
Dmitri Popov <operator@cv.dp-net.com>
|
||||
Dmitri Shuralyov <shurcooL@gmail.com>
|
||||
Dmitriy Dudkin <dudkin.dmitriy@gmail.com>
|
||||
Dmitriy Shelenin <deemok@googlemail.com> <deemok@gmail.com>
|
||||
@@ -373,12 +343,10 @@ Eric Roshan-Eisner <eric.d.eisner@gmail.com>
|
||||
Erik Aigner <aigner.erik@gmail.com>
|
||||
Erik Dubbelboer <erik@dubbelboer.com>
|
||||
Erik St. Martin <alakriti@gmail.com>
|
||||
Erik Staab <estaab@google.com>
|
||||
Erik Westrup <erik.westrup@gmail.com>
|
||||
Ernest Chiang <ernest_chiang@htc.com>
|
||||
Esko Luontola <esko.luontola@gmail.com>
|
||||
Ethan Burns <eaburns@google.com>
|
||||
Ethan Miller <eamiller@us.ibm.com>
|
||||
Evan Broder <evan@stripe.com>
|
||||
Evan Brown <evanbrown@google.com>
|
||||
Evan Kroske <evankroske@google.com>
|
||||
@@ -388,12 +356,10 @@ Evan Shaw <chickencha@gmail.com>
|
||||
Ewan Chou <coocood@gmail.com>
|
||||
Fabian Wickborn <fabian@wickborn.net>
|
||||
Fabrizio Milo <mistobaan@gmail.com>
|
||||
Faiyaz Ahmed <ahmedf@vmware.com>
|
||||
Fan Hongjian <fan.howard@gmail.com>
|
||||
Fatih Arslan <fatih@arslan.io>
|
||||
Fazlul Shahriar <fshahriar@gmail.com>
|
||||
Federico Simoncelli <fsimonce@redhat.com>
|
||||
Fedor Indutny <fedor@indutny.com>
|
||||
Felix Geisendörfer <haimuiba@gmail.com>
|
||||
Filippo Valsorda <hi@filippo.io>
|
||||
Firmansyah Adiputra <frm.adiputra@gmail.com>
|
||||
@@ -412,15 +378,12 @@ Frits van Bommel <fvbommel@gmail.com>
|
||||
Fumitoshi Ukai <ukai@google.com>
|
||||
Gaal Yahas <gaal@google.com>
|
||||
Gabriel Aszalos <gabriel.aszalos@gmail.com>
|
||||
Gabriel Russell <gabriel.russell@gmail.com>
|
||||
Gareth Paul Jones <gpj@foursquare.com>
|
||||
Garrick Evans <garrick@google.com>
|
||||
Gary Burd <gary@beagledreams.com> <gary.burd@gmail.com>
|
||||
Gary Elliott <garyelliott@google.com>
|
||||
Gaurish Sharma <contact@gaurishsharma.com>
|
||||
Gautham Thambidorai <gautham.dorai@gmail.com>
|
||||
Geert-Johan Riemer <gjr19912@gmail.com>
|
||||
Geoffroy Lorieux <lorieux.g@gmail.com>
|
||||
Georg Reinke <guelfey@gmail.com>
|
||||
George Shammas <george@shamm.as> <georgyo@gmail.com>
|
||||
Gerasimos Dimitriadis <gedimitr@gmail.com>
|
||||
@@ -428,7 +391,6 @@ Gideon Jan-Wessel Redelinghuys <gjredelinghuys@gmail.com>
|
||||
Giles Lean <giles.lean@pobox.com>
|
||||
Giovanni Bajo <rasky@develer.com>
|
||||
Giulio Iotti <dullgiulio@gmail.com>
|
||||
Gleb Stepanov <glebstepanov1992@gmail.com>
|
||||
Glenn Brown <glennb@google.com>
|
||||
Glenn Lewis <gmlewis@google.com>
|
||||
Gordon Klaus <gordon.klaus@gmail.com>
|
||||
@@ -455,7 +417,6 @@ Hector Chu <hectorchu@gmail.com>
|
||||
Hector Martin Cantero <hector@marcansoft.com>
|
||||
Henning Schmiedehausen <henning@schmiedehausen.org>
|
||||
Henrik Edwards <henrik.edwards@gmail.com>
|
||||
Henrik Hodne <henrik@hodne.io>
|
||||
Herbert Georg Fischer <herbert.fischer@gmail.com>
|
||||
Hironao OTSUBO <motemen@gmail.com>
|
||||
Hiroshi Ioka <hirochachacha@gmail.com>
|
||||
@@ -477,11 +438,9 @@ Ingo Krabbe <ikrabbe.ask@gmail.com>
|
||||
Ingo Oeser <nightlyone@googlemail.com> <nightlyone@gmail.com>
|
||||
Irieda Noboru <irieda@gmail.com>
|
||||
Isaac Wagner <ibw@isaacwagner.me>
|
||||
Ivan Babrou <ivan@cloudflare.com>
|
||||
Ivan Krasin <krasin@golang.org>
|
||||
Ivan Ukhov <ivan.ukhov@gmail.com>
|
||||
Jaana Burcu Dogan <jbd@google.com> <jbd@golang.org> <burcujdogan@gmail.com>
|
||||
Jack Lindamood <jlindamo@justin.tv>
|
||||
Jacob Baskin <jbaskin@google.com>
|
||||
Jacob H. Haven <jacob@cloudflare.com>
|
||||
Jacob Hoffman-Andrews <github@hoffman-andrews.com>
|
||||
@@ -492,7 +451,6 @@ Jakub Ryszard Czarnowicz <j.czarnowicz@gmail.com>
|
||||
James Aguilar <jaguilar@google.com>
|
||||
James Bardin <j.bardin@gmail.com>
|
||||
James Chacon <jchacon@google.com>
|
||||
James Clarke <jrtc27@jrtc27.com>
|
||||
James David Chalfant <james.chalfant@gmail.com>
|
||||
James Fysh <james.fysh@gmail.com>
|
||||
James Gray <james@james4k.com>
|
||||
@@ -504,7 +462,6 @@ James Sweet <james.sweet88@googlemail.com>
|
||||
James Toy <nil@opensesame.st>
|
||||
James Tucker <raggi@google.com>
|
||||
James Whitehead <jnwhiteh@gmail.com>
|
||||
Jamie Beverly <jamie.r.beverly@gmail.com>
|
||||
Jamie Gennis <jgennis@google.com> <jgennis@gmail.com>
|
||||
Jamie Turner <jamwt@dropbox.com>
|
||||
Jamie Wilkinson <jaq@spacepants.org>
|
||||
@@ -520,11 +477,9 @@ Jaroslavas Počepko <jp@webmaster.ms>
|
||||
Jason Barnett <jason.w.barnett@gmail.com>
|
||||
Jason Del Ponte <delpontej@gmail.com>
|
||||
Jason Hall <jasonhall@google.com>
|
||||
Jason Smale <jsmale@zendesk.com>
|
||||
Jason Travis <infomaniac7@gmail.com>
|
||||
Jay Weisskopf <jay@jayschwa.net>
|
||||
Jean-Marc Eurin <jmeurin@google.com>
|
||||
Jean-Nicolas Moal <jn.moal@gmail.com>
|
||||
Jed Denlea <jed@fastly.com>
|
||||
Jeff Craig <jeffcraig@google.com>
|
||||
Jeff Hodges <jeff@somethingsimilar.com>
|
||||
@@ -535,17 +490,14 @@ Jens Frederich <jfrederich@gmail.com>
|
||||
Jeremiah Harmsen <jeremiah@google.com>
|
||||
Jeremy Jackins <jeremyjackins@gmail.com>
|
||||
Jeremy Schlatter <jeremy.schlatter@gmail.com>
|
||||
Jeroen Bobbeldijk <jerbob92@gmail.com>
|
||||
Jess Frazelle <me@jessfraz.com>
|
||||
Jihyun Yu <yjh0502@gmail.com>
|
||||
Jim Cote <jfcote87@gmail.com>
|
||||
Jim Kingdon <jim@bolt.me>
|
||||
Jim McGrath <jimmc2@gmail.com>
|
||||
Jimmy Zelinskie <jimmyzelinskie@gmail.com>
|
||||
Jingcheng Zhang <diogin@gmail.com>
|
||||
Jingguo Yao <yaojingguo@gmail.com>
|
||||
Jiong Du <londevil@gmail.com>
|
||||
Jirka Daněk <dnk@mail.muni.cz>
|
||||
Joakim Sernbrant <serbaut@gmail.com>
|
||||
Joe Farrell <joe2farrell@gmail.com>
|
||||
Joe Harrison <joehazzers@gmail.com>
|
||||
@@ -572,7 +524,6 @@ John Potocny <johnp@vividcortex.com>
|
||||
John Schnake <schnake.john@gmail.com>
|
||||
John Shahid <jvshahid@gmail.com>
|
||||
John Tuley <john@tuley.org>
|
||||
Jon Chen <jchen@justin.tv>
|
||||
Jonathan Allie <jonallie@google.com>
|
||||
Jonathan Amsterdam <jba@google.com>
|
||||
Jonathan Boulle <jonathanboulle@gmail.com>
|
||||
@@ -585,17 +536,14 @@ Jonathan Pittman <jmpittman@google.com> <jonathan.mark.pittman@gmail.com>
|
||||
Jonathan Rudenberg <jonathan@titanous.com>
|
||||
Jonathan Wills <runningwild@gmail.com>
|
||||
Jongmin Kim <atomaths@gmail.com>
|
||||
Joonas Kuorilehto <joneskoo@derbian.fi>
|
||||
Jos Visser <josv@google.com>
|
||||
Jose Luis Vázquez González <josvazg@gmail.com>
|
||||
Joseph Bonneau <jcb@google.com>
|
||||
Joseph Holsten <joseph@josephholsten.com>
|
||||
Josh Bleecher Snyder <josharian@gmail.com>
|
||||
Josh Chorlton <jchorlton@gmail.com>
|
||||
Josh Goebel <dreamer3@gmail.com>
|
||||
Josh Hoak <jhoak@google.com>
|
||||
Josh Holland <jrh@joshh.co.uk>
|
||||
Joshua Boelter <joshua.boelter@intel.com>
|
||||
Joshua Chase <jcjoshuachase@gmail.com>
|
||||
Jostein Stuhaug <js@solidsystem.no>
|
||||
JP Sugarbroad <jpsugar@google.com>
|
||||
@@ -608,9 +556,7 @@ Julien Schmidt <google@julienschmidt.com>
|
||||
Jungho Ahn <jhahn@google.com>
|
||||
Jure Ham <jure.ham@zemanta.com>
|
||||
Justin Nuß <nuss.justin@gmail.com>
|
||||
Justyn Temme <justyntemme@gmail.com>
|
||||
Kai Backman <kaib@golang.org>
|
||||
Kale Blankenship <kale@lemnisys.com>
|
||||
Kamal Aboul-Hosn <aboulhosn@google.com>
|
||||
Kamil Kisiel <kamil@kamilkisiel.net> <kamil.kisiel@gmail.com>
|
||||
Kang Hu <hukangustc@gmail.com>
|
||||
@@ -652,7 +598,6 @@ L Campbell <unpantsu@gmail.com>
|
||||
Lai Jiangshan <eag0628@gmail.com>
|
||||
Larry Hosken <lahosken@golang.org>
|
||||
Larz Conwell <larzconwell@gmail.com>
|
||||
LE Manh Cuong <cuong.manhle.vn@gmail.com>
|
||||
Lee Hinman <hinman@gmail.com>
|
||||
Lee Packham <lpackham@gmail.com>
|
||||
Lewin Bormann <lewin.bormann@gmail.com>
|
||||
@@ -663,7 +608,6 @@ Luan Santos <cfcluan@gmail.com>
|
||||
Luca Greco <luca.greco@alcacoop.it>
|
||||
Lucien Stuker <lucien.stuker@gmail.com>
|
||||
Lucio De Re <lucio.dere@gmail.com>
|
||||
Luigi Riefolo <luigi.riefolo@gmail.com>
|
||||
Luit van Drongelen <luitvd@gmail.com>
|
||||
Luka Zakrajšek <tr00.g33k@gmail.com>
|
||||
Luke Curley <qpingu@gmail.com>
|
||||
@@ -671,7 +615,6 @@ Luna Duclos <luna.duclos@palmstonegames.com>
|
||||
Luuk van Dijk <lvd@golang.org> <lvd@google.com>
|
||||
Lynn Boger <laboger@linux.vnet.ibm.com>
|
||||
Mal Curtis <mal@mal.co.nz>
|
||||
Manfred Touron <m@42.am>
|
||||
Manoj Dayaram <platform-dev@moovweb.com> <manoj.dayaram@moovweb.com>
|
||||
Manu Garg <manugarg@google.com>
|
||||
Manu S Ajith <neo@codingarena.in>
|
||||
@@ -692,10 +635,8 @@ Marko Tiikkaja <marko@joh.to>
|
||||
Markus Duft <markus.duft@salomon.at>
|
||||
Markus Sonderegger <marraison@gmail.com>
|
||||
Markus Zimmermann <zimmski@gmail.com>
|
||||
Martin Bertschler <mbertschler@gmail.com>
|
||||
Martin Garton <garton@gmail.com>
|
||||
Martin Hamrle <martin.hamrle@gmail.com>
|
||||
Martin Möhrmann <moehrmann@google.com> <martisch@uos.de>
|
||||
Martin Möhrmann <martisch@uos.de>
|
||||
Martin Neubauer <m.ne@gmx.net>
|
||||
Martin Olsson <martin@minimum.se>
|
||||
Marvin Stenger <marvin.stenger94@gmail.com>
|
||||
@@ -719,10 +660,8 @@ Matt Williams <gh@mattyw.net> <mattyjwilliams@gmail.com>
|
||||
Matthew Brennan <matty.brennan@gmail.com>
|
||||
Matthew Cottingham <mattcottingham@gmail.com>
|
||||
Matthew Dempsky <mdempsky@google.com>
|
||||
Matthew Denton <mdenton@skyportsystems.com>
|
||||
Matthew Holt <Matthew.Holt+git@gmail.com>
|
||||
Matthew Horsnell <matthew.horsnell@gmail.com>
|
||||
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
|
||||
Maxim Khitrov <max@mxcrypt.com>
|
||||
Maxim Pimenov <mpimenov@google.com>
|
||||
Maxim Ushakov <ushakov@google.com>
|
||||
@@ -732,7 +671,6 @@ Meng Zhuo <mengzhuo1203@gmail.com>
|
||||
Mhd Sulhan <m.shulhan@gmail.com>
|
||||
Micah Stetson <micah.stetson@gmail.com>
|
||||
Michael Chaten <mchaten@gmail.com>
|
||||
Michael Darakananda <pongad@google.com>
|
||||
Michael Elkins <michael.elkins@gmail.com>
|
||||
Michael Fraenkel <michael.fraenkel@gmail.com>
|
||||
Michael Gehring <mg@ebfe.org> <gnirheg.leahcim@gmail.com>
|
||||
@@ -766,22 +704,17 @@ Miguel Mendez <stxmendez@gmail.com>
|
||||
Mihai Borobocea <MihaiBorobocea@gmail.com>
|
||||
Mikael Tillenius <mikti42@gmail.com>
|
||||
Mike Andrews <mra@xoba.com>
|
||||
Mike Appleby <mike@app.leby.org>
|
||||
Mike Danese <mikedanese@google.com>
|
||||
Mike Houston <mike@kothar.net>
|
||||
Mike Rosset <mike.rosset@gmail.com>
|
||||
Mike Samuel <mikesamuel@gmail.com>
|
||||
Mike Solomon <msolo@gmail.com>
|
||||
Mike Strosaker <strosake@us.ibm.com>
|
||||
Mikhail Gusarov <dottedmag@dottedmag.net>
|
||||
Mikhail Panchenko <m@mihasya.com>
|
||||
Miki Tebeka <miki.tebeka@gmail.com>
|
||||
Mikio Hara <mikioh.mikioh@gmail.com>
|
||||
Mikkel Krautz <mikkel@krautz.dk> <krautz@gmail.com>
|
||||
Miquel Sabaté Solà <mikisabate@gmail.com>
|
||||
Miroslav Genov <mgenov@gmail.com>
|
||||
Mohit Agarwal <mohit@sdf.org>
|
||||
Momchil Velikov <momchil.velikov@gmail.com>
|
||||
Monty Taylor <mordred@inaugust.com>
|
||||
Moriyoshi Koizumi <mozo@mozo.jp>
|
||||
Morten Siebuhr <sbhr@sbhr.dk>
|
||||
@@ -805,7 +738,6 @@ Nicholas Sullivan <nicholas.sullivan@gmail.com>
|
||||
Nicholas Waples <nwaples@gmail.com>
|
||||
Nick Cooper <nmvc@google.com>
|
||||
Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
|
||||
Nick Harper <nharper@google.com>
|
||||
Nick Patavalis <nick.patavalis@gmail.com>
|
||||
Nick Petroni <npetroni@cs.umd.edu>
|
||||
Nicolas Kaiser <nikai@nikai.net>
|
||||
@@ -819,7 +751,6 @@ Nikolay Turpitko <nikolay@turpitko.com>
|
||||
Noah Campbell <noahcampbell@gmail.com>
|
||||
Nodir Turakulov <nodir@google.com>
|
||||
Norberto Lopes <nlopes.ml@gmail.com>
|
||||
Oleg Vakheta <helginet@gmail.com>
|
||||
Oleku Konko <oleku.konko@gmail.com>
|
||||
Oling Cat <olingcat@gmail.com>
|
||||
Oliver Hookins <ohookins@gmail.com>
|
||||
@@ -832,7 +763,6 @@ Omar Jarjur <ojarjur@google.com>
|
||||
Padraig Kitterick <padraigkitterick@gmail.com>
|
||||
Paolo Giarrusso <p.giarrusso@gmail.com>
|
||||
Paolo Martini <mrtnpaolo@gmail.com>
|
||||
Parker Moore <parkrmoore@gmail.com>
|
||||
Pascal S. de Kloe <pascal@quies.net>
|
||||
Patrick Crosby <patrick@stathat.com>
|
||||
Patrick Gavlin <pgavlin@gmail.com>
|
||||
@@ -887,7 +817,6 @@ Pierre Durand <pierredurand@gmail.com>
|
||||
Pierre Roullon <pierre.roullon@gmail.com>
|
||||
Pieter Droogendijk <pieter@binky.org.uk>
|
||||
Pietro Gagliardi <pietro10@mac.com>
|
||||
Prasanna Swaminathan <prasanna@mediamath.com>
|
||||
Prashant Varanasi <prashant@prashantv.com>
|
||||
Preetam Jinka <pj@preet.am>
|
||||
Quan Tran <qeed.quan@gmail.com>
|
||||
@@ -895,12 +824,10 @@ Quan Yong Zhai <qyzhai@gmail.com>
|
||||
Quentin Perez <qperez@ocs.online.net>
|
||||
Quentin Smith <quentin@golang.org>
|
||||
Quoc-Viet Nguyen <afelion@gmail.com>
|
||||
Radu Berinde <radu@cockroachlabs.com>
|
||||
Rahul Chaudhry <rahulchaudhry@chromium.org>
|
||||
Raif S. Naffah <go@naffah-raif.name>
|
||||
Rajat Goel <rajat.goel2010@gmail.com>
|
||||
Ralph Corderoy <ralph@inputplus.co.uk>
|
||||
Ramesh Dharan <dharan@google.com>
|
||||
Raph Levien <raph@google.com>
|
||||
Raul Silvera <rsilvera@google.com>
|
||||
Reinaldo de Souza Jr <juniorz@gmail.com>
|
||||
@@ -910,7 +837,6 @@ Ricardo Padilha <ricardospadilha@gmail.com>
|
||||
Richard Barnes <rlb@ipv.sx>
|
||||
Richard Crowley <r@rcrowley.org>
|
||||
Richard Eric Gavaletz <gavaletz@gmail.com>
|
||||
Richard Gibson <richard.gibson@gmail.com>
|
||||
Richard Miller <miller.research@gmail.com>
|
||||
Richard Musiol <mail@richard-musiol.de> <neelance@gmail.com>
|
||||
Rick Arnold <rickarnoldjr@gmail.com>
|
||||
@@ -958,10 +884,7 @@ Sam Thorogood <thorogood@google.com> <sam.thorogood@gmail.com>
|
||||
Sam Whited <sam@samwhited.com>
|
||||
Sameer Ajmani <sameer@golang.org> <ajmani@gmail.com>
|
||||
Sami Commerot <samic@google.com>
|
||||
Samuel Tan <samueltan@google.com>
|
||||
Samuele Pedroni <pedronis@lucediurna.net>
|
||||
Sanjay Menakuru <balasanjay@gmail.com>
|
||||
Sarah Adams <shadams@google.com>
|
||||
Sasha Lionheart <lionhearts@google.com>
|
||||
Sasha Sobol <sasha@scaledinference.com>
|
||||
Scott Barron <scott.barron@github.com>
|
||||
@@ -974,7 +897,6 @@ Scott Van Woudenberg <scottvw@google.com>
|
||||
Sean Burford <sburford@google.com>
|
||||
Sean Dolphin <Sean.Dolphin@kpcompass.com>
|
||||
Sean Harger <sharger@google.com>
|
||||
Sean Rees <sean@erifax.org>
|
||||
Sebastien Binet <seb.binet@gmail.com>
|
||||
Sébastien Paolacci <sebastien.paolacci@gmail.com>
|
||||
Sergei Skorobogatov <skorobo@rambler.ru>
|
||||
@@ -995,12 +917,9 @@ Shivakumar GN <shivakumar.gn@gmail.com>
|
||||
Shun Fan <sfan@google.com>
|
||||
Silvan Jegen <s.jegen@gmail.com>
|
||||
Simon Jefford <simon.jefford@gmail.com>
|
||||
Simon Rawet <simon@rawet.se>
|
||||
Simon Thulbourn <simon+github@thulbourn.com>
|
||||
Simon Whitehead <chemnova@gmail.com>
|
||||
Sina Siadat <siadat@gmail.com>
|
||||
Sokolov Yura <funny.falcon@gmail.com>
|
||||
Song Gao <song@gao.io>
|
||||
Spencer Nelson <s@spenczar.com>
|
||||
Spring Mc <heresy.mc@gmail.com>
|
||||
Srdjan Petrovic <spetrovic@google.com>
|
||||
@@ -1020,10 +939,7 @@ Steven Elliot Harris <seharris@gmail.com>
|
||||
Steven Hartland <steven.hartland@multiplay.co.uk>
|
||||
Sugu Sougoumarane <ssougou@gmail.com>
|
||||
Suharsh Sivakumar <suharshs@google.com>
|
||||
Suyash <dextrous93@gmail.com>
|
||||
Sven Almgren <sven@tras.se>
|
||||
Sven Blumenstein <svbl@google.com>
|
||||
Syohei YOSHIDA <syohex@gmail.com>
|
||||
Szabolcs Nagy <nsz@port70.net>
|
||||
Tad Glines <tad.glines@gmail.com>
|
||||
Taj Khattra <taj.khattra@gmail.com>
|
||||
@@ -1034,12 +950,9 @@ Tamir Duberstein <tamird@gmail.com>
|
||||
Tarmigan Casebolt <tarmigan@gmail.com>
|
||||
Taru Karttunen <taruti@taruti.net>
|
||||
Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
|
||||
Terrel Shumway <gopher@shumway.us>
|
||||
Tetsuo Kiso <tetsuokiso9@gmail.com>
|
||||
Than McIntosh <thanm@google.com>
|
||||
Thiago Fransosi Farina <thiago.farina@gmail.com> <tfarina@chromium.org>
|
||||
Thomas Alan Copeland <talan.copeland@gmail.com>
|
||||
Thomas de Zeeuw <thomasdezeeuw@gmail.com>
|
||||
Thomas Desrosiers <thomasdesr@gmail.com>
|
||||
Thomas Habets <habets@google.com>
|
||||
Thomas Kappler <tkappler@gmail.com>
|
||||
@@ -1047,7 +960,6 @@ Thorben Krueger <thorben.krueger@gmail.com>
|
||||
Tilman Dilo <tilman.dilo@gmail.com>
|
||||
Tim Cooijmans <timcooijmans@gmail.com>
|
||||
Tim Ebringer <tim.ebringer@gmail.com>
|
||||
Tim Henderson <tim.tadh@gmail.com>
|
||||
Tim Hockin <thockin@google.com>
|
||||
Tim Swast <swast@google.com>
|
||||
Timo Savola <timo.savola@gmail.com>
|
||||
@@ -1062,19 +974,15 @@ Tom Bergan <tombergan@google.com>
|
||||
Tom Heng <zhm20070928@gmail.com>
|
||||
Tom Linford <tomlinford@gmail.com>
|
||||
Tom Szymanski <tgs@google.com>
|
||||
Tom Wilkie <tom@weave.works>
|
||||
Tommy Schaefer <tommy.schaefer@teecom.com>
|
||||
Tor Andersson <tor.andersson@gmail.com>
|
||||
Tormod Erevik Lea <tormodlea@gmail.com>
|
||||
Totoro W <tw19881113@gmail.com>
|
||||
Travis Cline <travis.cline@gmail.com>
|
||||
Trevor Strohman <trevor.strohman@gmail.com>
|
||||
Trey Lawrence <lawrence.trey@gmail.com>
|
||||
Trey Tacon <ttacon@gmail.com>
|
||||
Tristan Amini <tamini01@ca.ibm.com>
|
||||
Tristan Ooohry <ooohry@gmail.com>
|
||||
Tudor Golubenco <tudor.g@gmail.com>
|
||||
Tuo Shan <sturbo89@gmail.com> <shantuo@google.com>
|
||||
Tyler Bunnell <tylerbunnell@gmail.com>
|
||||
Tyler Treat <ttreat31@gmail.com>
|
||||
Tzu-Jung Lee <roylee17@currant.com>
|
||||
@@ -1086,21 +994,15 @@ Uttam C Pawar <uttam.c.pawar@intel.com>
|
||||
Vadim Grek <vadimprog@gmail.com>
|
||||
Vadim Vygonets <unixdj@gmail.com>
|
||||
Vega Garcia Luis Alfonso <vegacom@gmail.com>
|
||||
Victor Chudnovsky <vchudnov@google.com>
|
||||
Vincent Ambo <tazjin@googlemail.com>
|
||||
Vincent Batts <vbatts@hashbangbash.com> <vbatts@gmail.com>
|
||||
Vincent Vanackere <vincent.vanackere@gmail.com>
|
||||
Vinu Rajashekhar <vinutheraj@gmail.com>
|
||||
Vish Subramanian <vish@google.com>
|
||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||
Vitor De Mario <vitordemario@gmail.com>
|
||||
Vlad Krasnov <vlad@cloudflare.com>
|
||||
Vladimir Mihailenco <vladimir.webdev@gmail.com>
|
||||
Vladimir Nikishenko <vova616@gmail.com>
|
||||
Vladimir Stefanovic <vladimir.stefanovic@imgtec.com>
|
||||
Volker Dobler <dr.volker.dobler@gmail.com>
|
||||
Volodymyr Paprotski <vpaprots@ca.ibm.com>
|
||||
Walter Poupore <wpoupore@google.com>
|
||||
Wedson Almeida Filho <wedsonaf@google.com>
|
||||
Wei Guangjing <vcc.163@gmail.com>
|
||||
Will Chan <willchan@google.com>
|
||||
@@ -1113,7 +1015,6 @@ Wisdom Omuya <deafgoat@gmail.com>
|
||||
Xia Bin <snyh@snyh.org>
|
||||
Xing Xing <mikespook@gmail.com>
|
||||
Xudong Zhang <felixmelon@gmail.com>
|
||||
Xuyang Kang <xuyangkang@gmail.com>
|
||||
Yan Zou <yzou@google.com>
|
||||
Yann Kerhervé <yann.kerherve@gmail.com>
|
||||
Yao Zhang <lunaria21@gmail.com>
|
||||
@@ -1123,7 +1024,6 @@ Yesudeep Mangalapilly <yesudeep@google.com>
|
||||
Yissakhar Z. Beck <yissakhar.beck@gmail.com>
|
||||
Yo-An Lin <yoanlin93@gmail.com>
|
||||
Yongjian Xu <i3dmaster@gmail.com>
|
||||
Yorman Arias <cixtords@gmail.com>
|
||||
Yoshiyuki Kanno <nekotaroh@gmail.com> <yoshiyuki.kanno@stoic.co.jp>
|
||||
Yu Heng Zhang <annita.zhang@cn.ibm.com>
|
||||
Yu Xuan Zhang <zyxsh@cn.ibm.com>
|
||||
@@ -1132,7 +1032,6 @@ Yusuke Kagiwada <block.rxckin.beats@gmail.com>
|
||||
Yuusei Kuwana <kuwana@kumama.org>
|
||||
Yuval Pavel Zholkover <paulzhol@gmail.com>
|
||||
Yves Junqueira <yvesj@google.com> <yves.junqueira@gmail.com>
|
||||
Zev Goldstein <zev.goldstein@gmail.com>
|
||||
Zhongwei Yao <zhongwei.yao@arm.com>
|
||||
Ziad Hatahet <hatahet@gmail.com>
|
||||
Zorion Arrizabalaga <zorionk@gmail.com>
|
||||
|
||||
194
api/except.txt
194
api/except.txt
@@ -1,107 +1,23 @@
|
||||
pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
|
||||
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
|
||||
pkg syscall (darwin-386), func Fchflags(string, int) error
|
||||
pkg syscall (darwin-386-cgo), func Fchflags(string, int) error
|
||||
pkg syscall (darwin-amd64), func Fchflags(string, int) error
|
||||
pkg syscall (darwin-amd64-cgo), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-386), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-amd64), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-arm), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-arm-cgo), func Fchflags(string, int) error
|
||||
pkg syscall (netbsd-arm), func Fchflags(string, int) error
|
||||
pkg syscall (netbsd-arm-cgo), func Fchflags(string, int) error
|
||||
pkg testing, func RegisterCover(Cover)
|
||||
pkg text/template/parse, type DotNode bool
|
||||
pkg text/template/parse, type Node interface { Copy, String, Type }
|
||||
pkg os (linux-arm), const O_SYNC = 4096
|
||||
pkg os (linux-arm-cgo), const O_SYNC = 4096
|
||||
pkg syscall (darwin-386), const ImplementsGetwd = false
|
||||
pkg syscall (darwin-386), func Fchflags(string, int) error
|
||||
pkg syscall (darwin-386-cgo), const ImplementsGetwd = false
|
||||
pkg syscall (darwin-386-cgo), func Fchflags(string, int) error
|
||||
pkg syscall (darwin-amd64), const ImplementsGetwd = false
|
||||
pkg syscall (darwin-amd64), func Fchflags(string, int) error
|
||||
pkg syscall (darwin-amd64-cgo), const ImplementsGetwd = false
|
||||
pkg syscall (darwin-amd64-cgo), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-386), const AF_MAX = 38
|
||||
pkg syscall (freebsd-386), const DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-386), const ELAST = 94
|
||||
pkg syscall (freebsd-386), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-386), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-386-cgo), const AF_MAX = 38
|
||||
pkg syscall (freebsd-386-cgo), const DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-386-cgo), const ELAST = 94
|
||||
pkg syscall (freebsd-386-cgo), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-amd64), const AF_MAX = 38
|
||||
pkg syscall (freebsd-amd64), const DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-amd64), const ELAST = 94
|
||||
pkg syscall (freebsd-amd64), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-amd64), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-amd64-cgo), const AF_MAX = 38
|
||||
pkg syscall (freebsd-amd64-cgo), const DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-amd64-cgo), const ELAST = 94
|
||||
pkg syscall (freebsd-amd64-cgo), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-arm), const AF_MAX = 38
|
||||
pkg syscall (freebsd-arm), const BIOCGRTIMEOUT = 1074545262
|
||||
pkg syscall (freebsd-arm), const BIOCSRTIMEOUT = 2148287085
|
||||
pkg syscall (freebsd-arm), const ELAST = 94
|
||||
pkg syscall (freebsd-arm), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-arm), const SIOCAIFADDR = 2151967019
|
||||
pkg syscall (freebsd-arm), const SIOCGIFSTATUS = 3274991931
|
||||
pkg syscall (freebsd-arm), const SIOCSIFPHYADDR = 2151967046
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_FCNTLS_GET = 537
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_FCNTLS_GET ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_FCNTLS_LIMIT = 536
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_FCNTLS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_IOCTLS_GET = 535
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_IOCTLS_GET ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_IOCTLS_LIMIT = 534
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_IOCTLS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_RIGHTS_GET = 515
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_RIGHTS_GET ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_RIGHTS_LIMIT = 533
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_RIGHTS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm), const SizeofBpfHdr = 24
|
||||
pkg syscall (freebsd-arm), const SizeofIfData = 88
|
||||
pkg syscall (freebsd-arm), const SizeofIfMsghdr = 104
|
||||
pkg syscall (freebsd-arm), const SizeofSockaddrDatalink = 56
|
||||
pkg syscall (freebsd-arm), const SizeofSockaddrUnix = 108
|
||||
pkg syscall (freebsd-arm), const TIOCTIMESTAMP = 1074558041
|
||||
pkg syscall (freebsd-arm), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-arm), type BpfHdr struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm), type Stat_t struct, Pad_cgo_0 [4]uint8
|
||||
pkg syscall (freebsd-arm-cgo), const AF_MAX = 38
|
||||
pkg syscall (freebsd-arm-cgo), const BIOCGRTIMEOUT = 1074545262
|
||||
pkg syscall (freebsd-arm-cgo), const BIOCSRTIMEOUT = 2148287085
|
||||
pkg syscall (freebsd-arm-cgo), const ELAST = 94
|
||||
pkg syscall (freebsd-arm-cgo), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-arm-cgo), const SIOCAIFADDR = 2151967019
|
||||
pkg syscall (freebsd-arm-cgo), const SIOCGIFSTATUS = 3274991931
|
||||
pkg syscall (freebsd-arm-cgo), const SIOCSIFPHYADDR = 2151967046
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_FCNTLS_GET = 537
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_FCNTLS_GET ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_FCNTLS_LIMIT = 536
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_FCNTLS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_IOCTLS_GET = 535
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_IOCTLS_GET ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_IOCTLS_LIMIT = 534
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_IOCTLS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_RIGHTS_GET = 515
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_RIGHTS_GET ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_RIGHTS_LIMIT = 533
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_RIGHTS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofBpfHdr = 24
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofIfData = 88
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofIfMsghdr = 104
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofSockaddrDatalink = 56
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofSockaddrUnix = 108
|
||||
pkg syscall (freebsd-arm-cgo), const TIOCTIMESTAMP = 1074558041
|
||||
pkg syscall (freebsd-arm-cgo), func Fchflags(string, int) error
|
||||
pkg syscall (freebsd-arm-cgo), type BpfHdr struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm-cgo), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm-cgo), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Pad_cgo_0 [4]uint8
|
||||
pkg syscall (linux-386), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||
pkg syscall (linux-386-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||
pkg syscall (linux-amd64), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||
pkg syscall (linux-amd64-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||
pkg syscall (linux-arm), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||
pkg syscall (linux-arm-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||
pkg syscall (netbsd-arm), const SizeofIfData = 132
|
||||
pkg syscall (netbsd-arm), func Fchflags(string, int) error
|
||||
pkg syscall (netbsd-arm), type IfMsghdr struct, Pad_cgo_1 [4]uint8
|
||||
pkg syscall (netbsd-arm-cgo), const SizeofIfData = 132
|
||||
pkg syscall (netbsd-arm-cgo), func Fchflags(string, int) error
|
||||
pkg syscall (netbsd-arm-cgo), type IfMsghdr struct, Pad_cgo_1 [4]uint8
|
||||
pkg syscall (openbsd-386), const BIOCGRTIMEOUT = 1074283118
|
||||
pkg syscall (openbsd-386), const BIOCSRTIMEOUT = 2148024941
|
||||
pkg syscall (openbsd-386), const RTF_FMASK = 63496
|
||||
@@ -330,11 +246,87 @@ pkg syscall (openbsd-amd64-cgo), type Statfs_t struct, F_spare [3]uint32
|
||||
pkg syscall (openbsd-amd64-cgo), type Statfs_t struct, Pad_cgo_1 [4]uint8
|
||||
pkg syscall (openbsd-amd64-cgo), type Timespec struct, Pad_cgo_0 [4]uint8
|
||||
pkg syscall (openbsd-amd64-cgo), type Timespec struct, Sec int32
|
||||
pkg testing, func RegisterCover(Cover)
|
||||
pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M
|
||||
pkg text/template/parse, type DotNode bool
|
||||
pkg text/template/parse, type Node interface { Copy, String, Type }
|
||||
pkg unicode, const Version = "6.2.0"
|
||||
pkg syscall (freebsd-386), const AF_MAX = 38
|
||||
pkg syscall (freebsd-386), const DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-386), const ELAST = 94
|
||||
pkg syscall (freebsd-386), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-386-cgo), const AF_MAX = 38
|
||||
pkg syscall (freebsd-386-cgo), const DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-386-cgo), const ELAST = 94
|
||||
pkg syscall (freebsd-386-cgo), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-amd64), const AF_MAX = 38
|
||||
pkg syscall (freebsd-amd64), const DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-amd64), const ELAST = 94
|
||||
pkg syscall (freebsd-amd64), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-amd64-cgo), const AF_MAX = 38
|
||||
pkg syscall (freebsd-amd64-cgo), const DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-amd64-cgo), const ELAST = 94
|
||||
pkg syscall (freebsd-amd64-cgo), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-arm), const AF_MAX = 38
|
||||
pkg syscall (freebsd-arm), const BIOCGRTIMEOUT = 1074545262
|
||||
pkg syscall (freebsd-arm), const BIOCSRTIMEOUT = 2148287085
|
||||
pkg syscall (freebsd-arm), const ELAST = 94
|
||||
pkg syscall (freebsd-arm), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-arm), const SIOCAIFADDR = 2151967019
|
||||
pkg syscall (freebsd-arm), const SIOCGIFSTATUS = 3274991931
|
||||
pkg syscall (freebsd-arm), const SIOCSIFPHYADDR = 2151967046
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_FCNTLS_GET = 537
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_FCNTLS_GET ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_FCNTLS_LIMIT = 536
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_FCNTLS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_IOCTLS_GET = 535
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_IOCTLS_GET ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_IOCTLS_LIMIT = 534
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_IOCTLS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_RIGHTS_GET = 515
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_RIGHTS_GET ideal-int
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_RIGHTS_LIMIT = 533
|
||||
pkg syscall (freebsd-arm), const SYS_CAP_RIGHTS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm), const SizeofBpfHdr = 24
|
||||
pkg syscall (freebsd-arm), const SizeofIfData = 88
|
||||
pkg syscall (freebsd-arm), const SizeofIfMsghdr = 104
|
||||
pkg syscall (freebsd-arm), const SizeofSockaddrDatalink = 56
|
||||
pkg syscall (freebsd-arm), const SizeofSockaddrUnix = 108
|
||||
pkg syscall (freebsd-arm), const TIOCTIMESTAMP = 1074558041
|
||||
pkg syscall (freebsd-arm), type BpfHdr struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm), type Stat_t struct, Pad_cgo_0 [4]uint8
|
||||
pkg syscall (freebsd-arm-cgo), const AF_MAX = 38
|
||||
pkg syscall (freebsd-arm-cgo), const BIOCGRTIMEOUT = 1074545262
|
||||
pkg syscall (freebsd-arm-cgo), const BIOCSRTIMEOUT = 2148287085
|
||||
pkg syscall (freebsd-arm-cgo), const ELAST = 94
|
||||
pkg syscall (freebsd-arm-cgo), const O_CLOEXEC = 0
|
||||
pkg syscall (freebsd-arm-cgo), const SIOCAIFADDR = 2151967019
|
||||
pkg syscall (freebsd-arm-cgo), const SIOCGIFSTATUS = 3274991931
|
||||
pkg syscall (freebsd-arm-cgo), const SIOCSIFPHYADDR = 2151967046
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_FCNTLS_GET = 537
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_FCNTLS_GET ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_FCNTLS_LIMIT = 536
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_FCNTLS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_IOCTLS_GET = 535
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_IOCTLS_GET ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_IOCTLS_LIMIT = 534
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_IOCTLS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_RIGHTS_GET = 515
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_RIGHTS_GET ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_RIGHTS_LIMIT = 533
|
||||
pkg syscall (freebsd-arm-cgo), const SYS_CAP_RIGHTS_LIMIT ideal-int
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofBpfHdr = 24
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofIfData = 88
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofIfMsghdr = 104
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofSockaddrDatalink = 56
|
||||
pkg syscall (freebsd-arm-cgo), const SizeofSockaddrUnix = 108
|
||||
pkg syscall (freebsd-arm-cgo), const TIOCTIMESTAMP = 1074558041
|
||||
pkg syscall (freebsd-arm-cgo), type BpfHdr struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm-cgo), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm-cgo), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8
|
||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Pad_cgo_0 [4]uint8
|
||||
pkg syscall (netbsd-arm), const SizeofIfData = 132
|
||||
pkg syscall (netbsd-arm), type IfMsghdr struct, Pad_cgo_1 [4]uint8
|
||||
pkg syscall (netbsd-arm-cgo), const SizeofIfData = 132
|
||||
pkg syscall (netbsd-arm-cgo), type IfMsghdr struct, Pad_cgo_1 [4]uint8
|
||||
pkg unicode, const Version = "6.3.0"
|
||||
pkg unicode, const Version = "7.0.0"
|
||||
pkg unicode, const Version = "8.0.0"
|
||||
|
||||
193
api/next.txt
193
api/next.txt
@@ -1,193 +0,0 @@
|
||||
pkg compress/gzip, const HuffmanOnly = -2
|
||||
pkg compress/gzip, const HuffmanOnly ideal-int
|
||||
pkg compress/zlib, const HuffmanOnly = -2
|
||||
pkg compress/zlib, const HuffmanOnly ideal-int
|
||||
pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 49187
|
||||
pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16
|
||||
pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = 52393
|
||||
pkg crypto/tls, const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 uint16
|
||||
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 49191
|
||||
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16
|
||||
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = 52392
|
||||
pkg crypto/tls, const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 uint16
|
||||
pkg crypto/tls, const TLS_RSA_WITH_AES_128_CBC_SHA256 = 60
|
||||
pkg crypto/tls, const TLS_RSA_WITH_AES_128_CBC_SHA256 uint16
|
||||
pkg crypto/tls, const X25519 = 29
|
||||
pkg crypto/tls, const X25519 CurveID
|
||||
pkg crypto/tls, method (*Config) Clone() *Config
|
||||
pkg crypto/tls, type ClientHelloInfo struct, Conn net.Conn
|
||||
pkg crypto/tls, type ClientHelloInfo struct, SignatureSchemes []uint16
|
||||
pkg crypto/tls, type ClientHelloInfo struct, SupportedProtos []string
|
||||
pkg crypto/tls, type ClientHelloInfo struct, SupportedVersions []uint16
|
||||
pkg crypto/tls, type Config struct, GetConfigForClient func(*ClientHelloInfo) (*Config, error)
|
||||
pkg crypto/tls, type Config struct, KeyLogWriter io.Writer
|
||||
pkg crypto/tls, type Config struct, VerifyPeerCertificate func([][]uint8, [][]*x509.Certificate) error
|
||||
pkg crypto/x509, const NameMismatch = 5
|
||||
pkg crypto/x509, const NameMismatch InvalidReason
|
||||
pkg crypto/x509, const SHA256WithRSAPSS = 13
|
||||
pkg crypto/x509, const SHA256WithRSAPSS SignatureAlgorithm
|
||||
pkg crypto/x509, const SHA384WithRSAPSS = 14
|
||||
pkg crypto/x509, const SHA384WithRSAPSS SignatureAlgorithm
|
||||
pkg crypto/x509, const SHA512WithRSAPSS = 15
|
||||
pkg crypto/x509, const SHA512WithRSAPSS SignatureAlgorithm
|
||||
pkg database/sql, func Param(string, interface{}) NamedParam
|
||||
pkg database/sql, method (*ColumnType) DatabaseTypeName() string
|
||||
pkg database/sql, method (*ColumnType) DecimalSize() (int64, int64, bool)
|
||||
pkg database/sql, method (*ColumnType) Length() (int64, bool)
|
||||
pkg database/sql, method (*ColumnType) Name() string
|
||||
pkg database/sql, method (*ColumnType) Nullable() (bool, bool)
|
||||
pkg database/sql, method (*ColumnType) ScanType() reflect.Type
|
||||
pkg database/sql, method (*DB) BeginContext(context.Context) (*Tx, error)
|
||||
pkg database/sql, method (*DB) ExecContext(context.Context, string, ...interface{}) (Result, error)
|
||||
pkg database/sql, method (*DB) PingContext(context.Context) error
|
||||
pkg database/sql, method (*DB) PrepareContext(context.Context, string) (*Stmt, error)
|
||||
pkg database/sql, method (*DB) QueryContext(context.Context, string, ...interface{}) (*Rows, error)
|
||||
pkg database/sql, method (*DB) QueryRowContext(context.Context, string, ...interface{}) *Row
|
||||
pkg database/sql, method (*Rows) ColumnTypes() ([]*ColumnType, error)
|
||||
pkg database/sql, method (*Rows) NextResultSet() bool
|
||||
pkg database/sql, method (*Stmt) ExecContext(context.Context, ...interface{}) (Result, error)
|
||||
pkg database/sql, method (*Stmt) QueryContext(context.Context, ...interface{}) (*Rows, error)
|
||||
pkg database/sql, method (*Stmt) QueryRowContext(context.Context, ...interface{}) *Row
|
||||
pkg database/sql, method (*Tx) ExecContext(context.Context, string, ...interface{}) (Result, error)
|
||||
pkg database/sql, method (*Tx) PrepareContext(context.Context, string) (*Stmt, error)
|
||||
pkg database/sql, method (*Tx) QueryContext(context.Context, string, ...interface{}) (*Rows, error)
|
||||
pkg database/sql, method (*Tx) QueryRowContext(context.Context, string, ...interface{}) *Row
|
||||
pkg database/sql, method (*Tx) StmtContext(context.Context, *Stmt) *Stmt
|
||||
pkg database/sql, type ColumnType struct
|
||||
pkg database/sql, type NamedParam struct
|
||||
pkg database/sql, type NamedParam struct, Name string
|
||||
pkg database/sql, type NamedParam struct, Value interface{}
|
||||
pkg database/sql/driver, type ConnBeginContext interface { BeginContext }
|
||||
pkg database/sql/driver, type ConnBeginContext interface, BeginContext(context.Context) (Tx, error)
|
||||
pkg database/sql/driver, type ConnPrepareContext interface { PrepareContext }
|
||||
pkg database/sql/driver, type ConnPrepareContext interface, PrepareContext(context.Context, string) (Stmt, error)
|
||||
pkg database/sql/driver, type ExecerContext interface { ExecContext }
|
||||
pkg database/sql/driver, type ExecerContext interface, ExecContext(context.Context, string, []NamedValue) (Result, error)
|
||||
pkg database/sql/driver, type NamedValue struct
|
||||
pkg database/sql/driver, type NamedValue struct, Name string
|
||||
pkg database/sql/driver, type NamedValue struct, Ordinal int
|
||||
pkg database/sql/driver, type NamedValue struct, Value Value
|
||||
pkg database/sql/driver, type QueryerContext interface { QueryContext }
|
||||
pkg database/sql/driver, type QueryerContext interface, QueryContext(context.Context, string, []NamedValue) (Rows, error)
|
||||
pkg database/sql/driver, type RowsColumnTypeDatabaseTypeName interface { Close, ColumnTypeDatabaseTypeName, Columns, Next }
|
||||
pkg database/sql/driver, type RowsColumnTypeDatabaseTypeName interface, Close() error
|
||||
pkg database/sql/driver, type RowsColumnTypeDatabaseTypeName interface, ColumnTypeDatabaseTypeName(int) string
|
||||
pkg database/sql/driver, type RowsColumnTypeDatabaseTypeName interface, Columns() []string
|
||||
pkg database/sql/driver, type RowsColumnTypeDatabaseTypeName interface, Next([]Value) error
|
||||
pkg database/sql/driver, type RowsColumnTypeLength interface { Close, ColumnTypeLength, Columns, Next }
|
||||
pkg database/sql/driver, type RowsColumnTypeLength interface, Close() error
|
||||
pkg database/sql/driver, type RowsColumnTypeLength interface, ColumnTypeLength(int) (int64, bool)
|
||||
pkg database/sql/driver, type RowsColumnTypeLength interface, Columns() []string
|
||||
pkg database/sql/driver, type RowsColumnTypeLength interface, Next([]Value) error
|
||||
pkg database/sql/driver, type RowsColumnTypeNullable interface { Close, ColumnTypeNullable, Columns, Next }
|
||||
pkg database/sql/driver, type RowsColumnTypeNullable interface, Close() error
|
||||
pkg database/sql/driver, type RowsColumnTypeNullable interface, ColumnTypeNullable(int) (bool, bool)
|
||||
pkg database/sql/driver, type RowsColumnTypeNullable interface, Columns() []string
|
||||
pkg database/sql/driver, type RowsColumnTypeNullable interface, Next([]Value) error
|
||||
pkg database/sql/driver, type RowsColumnTypePrecisionScale interface { Close, ColumnTypePrecisionScale, Columns, Next }
|
||||
pkg database/sql/driver, type RowsColumnTypePrecisionScale interface, Close() error
|
||||
pkg database/sql/driver, type RowsColumnTypePrecisionScale interface, ColumnTypePrecisionScale(int) (int64, int64, bool)
|
||||
pkg database/sql/driver, type RowsColumnTypePrecisionScale interface, Columns() []string
|
||||
pkg database/sql/driver, type RowsColumnTypePrecisionScale interface, Next([]Value) error
|
||||
pkg database/sql/driver, type RowsColumnTypeScanType interface { Close, ColumnTypeScanType, Columns, Next }
|
||||
pkg database/sql/driver, type RowsColumnTypeScanType interface, Close() error
|
||||
pkg database/sql/driver, type RowsColumnTypeScanType interface, ColumnTypeScanType(int) reflect.Type
|
||||
pkg database/sql/driver, type RowsColumnTypeScanType interface, Columns() []string
|
||||
pkg database/sql/driver, type RowsColumnTypeScanType interface, Next([]Value) error
|
||||
pkg database/sql/driver, type RowsNextResultSet interface { Close, Columns, HasNextResultSet, Next, NextResultSet }
|
||||
pkg database/sql/driver, type RowsNextResultSet interface, Close() error
|
||||
pkg database/sql/driver, type RowsNextResultSet interface, Columns() []string
|
||||
pkg database/sql/driver, type RowsNextResultSet interface, HasNextResultSet() bool
|
||||
pkg database/sql/driver, type RowsNextResultSet interface, Next([]Value) error
|
||||
pkg database/sql/driver, type RowsNextResultSet interface, NextResultSet() error
|
||||
pkg database/sql/driver, type StmtExecContext interface { ExecContext }
|
||||
pkg database/sql/driver, type StmtExecContext interface, ExecContext(context.Context, []NamedValue) (Result, error)
|
||||
pkg database/sql/driver, type StmtQueryContext interface { QueryContext }
|
||||
pkg database/sql/driver, type StmtQueryContext interface, QueryContext(context.Context, []NamedValue) (Rows, error)
|
||||
pkg debug/gosym, func PCValue([]uint8, uint64, int) int
|
||||
pkg debug/pe, method (*COFFSymbol) FullName(StringTable) (string, error)
|
||||
pkg debug/pe, method (StringTable) String(uint32) (string, error)
|
||||
pkg debug/pe, type File struct, COFFSymbols []COFFSymbol
|
||||
pkg debug/pe, type File struct, StringTable StringTable
|
||||
pkg debug/pe, type Reloc struct
|
||||
pkg debug/pe, type Reloc struct, SymbolTableIndex uint32
|
||||
pkg debug/pe, type Reloc struct, Type uint16
|
||||
pkg debug/pe, type Reloc struct, VirtualAddress uint32
|
||||
pkg debug/pe, type Section struct, Relocs []Reloc
|
||||
pkg debug/pe, type StringTable []uint8
|
||||
pkg encoding/base64, method (Encoding) Strict() *Encoding
|
||||
pkg encoding/json, type UnmarshalTypeError struct, Field string
|
||||
pkg encoding/json, type UnmarshalTypeError struct, Struct string
|
||||
pkg expvar, func Handler() http.Handler
|
||||
pkg expvar, method (*Float) Value() float64
|
||||
pkg expvar, method (*Int) Value() int64
|
||||
pkg expvar, method (*String) Value() string
|
||||
pkg expvar, method (Func) Value() interface{}
|
||||
pkg go/ast, method (*AliasSpec) End() token.Pos
|
||||
pkg go/ast, method (*AliasSpec) Pos() token.Pos
|
||||
pkg go/ast, type AliasSpec struct
|
||||
pkg go/ast, type AliasSpec struct, Comment *CommentGroup
|
||||
pkg go/ast, type AliasSpec struct, Doc *CommentGroup
|
||||
pkg go/ast, type AliasSpec struct, Name *Ident
|
||||
pkg go/ast, type AliasSpec struct, Orig Expr
|
||||
pkg go/build, type NoGoError struct, Ignored bool
|
||||
pkg go/doc, func IsPredeclared(string) bool
|
||||
pkg go/token, const ALIAS = 87
|
||||
pkg go/token, const ALIAS Token
|
||||
pkg go/types, func Default(Type) Type
|
||||
pkg go/types, func IdenticalIgnoreTags(Type, Type) bool
|
||||
pkg math/big, method (*Float) Scan(fmt.ScanState, int32) error
|
||||
pkg math/big, method (*Int) Sqrt(*Int) *Int
|
||||
pkg math/rand, func Uint64() uint64
|
||||
pkg math/rand, method (*Rand) Uint64() uint64
|
||||
pkg net, method (*Buffers) Read([]uint8) (int, error)
|
||||
pkg net, method (*Buffers) WriteTo(io.Writer) (int64, error)
|
||||
pkg net, method (*Resolver) LookupAddr(context.Context, string) ([]string, error)
|
||||
pkg net, method (*Resolver) LookupCNAME(context.Context, string) (string, error)
|
||||
pkg net, method (*Resolver) LookupHost(context.Context, string) ([]string, error)
|
||||
pkg net, method (*Resolver) LookupIPAddr(context.Context, string) ([]IPAddr, error)
|
||||
pkg net, method (*Resolver) LookupMX(context.Context, string) ([]*MX, error)
|
||||
pkg net, method (*Resolver) LookupNS(context.Context, string) ([]*NS, error)
|
||||
pkg net, method (*Resolver) LookupPort(context.Context, string, string) (int, error)
|
||||
pkg net, method (*Resolver) LookupSRV(context.Context, string, string, string) (string, []*SRV, error)
|
||||
pkg net, method (*Resolver) LookupTXT(context.Context, string) ([]string, error)
|
||||
pkg net, type Buffers [][]uint8
|
||||
pkg net, type Dialer struct, Resolver *Resolver
|
||||
pkg net, type Resolver struct
|
||||
pkg net, type Resolver struct, PreferGo bool
|
||||
pkg net, var DefaultResolver *Resolver
|
||||
pkg net/http, type PushOptions struct
|
||||
pkg net/http, type PushOptions struct, Header Header
|
||||
pkg net/http, type PushOptions struct, Method string
|
||||
pkg net/http, type Pusher interface { Push }
|
||||
pkg net/http, type Pusher interface, Push(string, *PushOptions) error
|
||||
pkg net/http, type Request struct, GetBody func() (io.ReadCloser, error)
|
||||
pkg net/http, var NoBody noBody
|
||||
pkg net/http/httptrace, type ClientTrace struct, TLSHandshakeDone func(tls.ConnectionState, error)
|
||||
pkg net/http/httptrace, type ClientTrace struct, TLSHandshakeStart func()
|
||||
pkg net/mail, func ParseDate(string) (time.Time, error)
|
||||
pkg net/url, func PathEscape(string) string
|
||||
pkg net/url, func PathUnescape(string) (string, error)
|
||||
pkg net/url, method (*URL) Hostname() string
|
||||
pkg net/url, method (*URL) MarshalBinary() ([]uint8, error)
|
||||
pkg net/url, method (*URL) Port() string
|
||||
pkg net/url, method (*URL) UnmarshalBinary([]uint8) error
|
||||
pkg os, var ErrClosed error
|
||||
pkg plugin, func Open(string) (*Plugin, error)
|
||||
pkg plugin, method (*Plugin) Lookup(string) (Symbol, error)
|
||||
pkg plugin, type Plugin struct
|
||||
pkg plugin, type Symbol interface {}
|
||||
pkg reflect, func Swapper(interface{}) func(int, int)
|
||||
pkg sort, func Slice(interface{}, func(int, int) bool)
|
||||
pkg sort, func SliceIsSorted(interface{}, func(int, int) bool) bool
|
||||
pkg sort, func SliceStable(interface{}, func(int, int) bool)
|
||||
pkg syscall (linux-arm), func TimevalToNsec(Timeval) int64
|
||||
pkg syscall (linux-arm-cgo), func TimevalToNsec(Timeval) int64
|
||||
pkg syscall (windows-386), const ERROR_DIR_NOT_EMPTY = 145
|
||||
pkg syscall (windows-386), const ERROR_DIR_NOT_EMPTY Errno
|
||||
pkg syscall (windows-amd64), const ERROR_DIR_NOT_EMPTY = 145
|
||||
pkg syscall (windows-amd64), const ERROR_DIR_NOT_EMPTY Errno
|
||||
pkg testing, method (*B) Name() string
|
||||
pkg testing, method (*T) Name() string
|
||||
pkg testing, type TB interface, Name() string
|
||||
pkg time, func Until(Time) Duration
|
||||
|
||||
@@ -164,14 +164,14 @@ red-black tree. We can install both with the "<code>go get</code>"
|
||||
subcommand:</p>
|
||||
|
||||
<pre>
|
||||
$ go get github.com/google/codesearch/index
|
||||
$ go get code.google.com/p/codesearch/index
|
||||
$ go get github.com/petar/GoLLRB/llrb
|
||||
$
|
||||
</pre>
|
||||
|
||||
<p>Both of these projects are now downloaded and installed into our
|
||||
<code>$GOPATH</code> directory. The one tree now contains the two directories
|
||||
<code>src/github.com/google/codesearch/index/</code> and
|
||||
<code>src/code.google.com/p/codesearch/index/</code> and
|
||||
<code>src/github.com/petar/GoLLRB/llrb/</code>, along with the compiled
|
||||
packages (in <code>pkg/</code>) for those libraries and their dependencies.</p>
|
||||
|
||||
@@ -185,12 +185,12 @@ the pattern "<code>./...</code>" means start in the current directory
|
||||
|
||||
<pre>
|
||||
$ go list ./...
|
||||
github.com/google/codesearch/cmd/cgrep
|
||||
github.com/google/codesearch/cmd/cindex
|
||||
github.com/google/codesearch/cmd/csearch
|
||||
github.com/google/codesearch/index
|
||||
github.com/google/codesearch/regexp
|
||||
github.com/google/codesearch/sparse
|
||||
code.google.com/p/codesearch/cmd/cgrep
|
||||
code.google.com/p/codesearch/cmd/cindex
|
||||
code.google.com/p/codesearch/cmd/csearch
|
||||
code.google.com/p/codesearch/index
|
||||
code.google.com/p/codesearch/regexp
|
||||
code.google.com/p/codesearch/sparse
|
||||
github.com/petar/GoLLRB/example
|
||||
github.com/petar/GoLLRB/llrb
|
||||
$
|
||||
@@ -200,12 +200,12 @@ $
|
||||
|
||||
<pre>
|
||||
$ go test ./...
|
||||
? github.com/google/codesearch/cmd/cgrep [no test files]
|
||||
? github.com/google/codesearch/cmd/cindex [no test files]
|
||||
? github.com/google/codesearch/cmd/csearch [no test files]
|
||||
ok github.com/google/codesearch/index 0.203s
|
||||
ok github.com/google/codesearch/regexp 0.017s
|
||||
? github.com/google/codesearch/sparse [no test files]
|
||||
? code.google.com/p/codesearch/cmd/cgrep [no test files]
|
||||
? code.google.com/p/codesearch/cmd/cindex [no test files]
|
||||
? code.google.com/p/codesearch/cmd/csearch [no test files]
|
||||
ok code.google.com/p/codesearch/index 0.239s
|
||||
ok code.google.com/p/codesearch/regexp 0.021s
|
||||
? code.google.com/p/codesearch/sparse [no test files]
|
||||
? github.com/petar/GoLLRB/example [no test files]
|
||||
ok github.com/petar/GoLLRB/llrb 0.231s
|
||||
$
|
||||
@@ -215,18 +215,18 @@ $
|
||||
current directory:</p>
|
||||
|
||||
<pre>
|
||||
$ cd $GOPATH/src/github.com/google/codesearch/regexp
|
||||
$ cd $GOPATH/src/code.google.com/p/codesearch/regexp
|
||||
$ go list
|
||||
github.com/google/codesearch/regexp
|
||||
code.google.com/p/codesearch/regexp
|
||||
$ go test -v
|
||||
=== RUN TestNstateEnc
|
||||
--- PASS: TestNstateEnc (0.00s)
|
||||
=== RUN TestMatch
|
||||
--- PASS: TestMatch (0.00s)
|
||||
=== RUN TestGrep
|
||||
--- PASS: TestGrep (0.00s)
|
||||
=== RUN TestNstateEnc
|
||||
--- PASS: TestNstateEnc (0.00 seconds)
|
||||
=== RUN TestMatch
|
||||
--- PASS: TestMatch (0.01 seconds)
|
||||
=== RUN TestGrep
|
||||
--- PASS: TestGrep (0.00 seconds)
|
||||
PASS
|
||||
ok github.com/google/codesearch/regexp 0.018s
|
||||
ok code.google.com/p/codesearch/regexp 0.021s
|
||||
$ go install
|
||||
$
|
||||
</pre>
|
||||
@@ -255,7 +255,8 @@ In particular, it does not have any facility for generating Go
|
||||
source files <em>during</em> a build, although it does provide
|
||||
<a href="/cmd/go/#hdr-Generate_Go_files_by_processing_source"><code>go</code>
|
||||
<code>generate</code></a>,
|
||||
which can automate the creation of Go files <em>before</em> the build.
|
||||
which can automate the creation of Go files <em>before</em>
|
||||
the build, such as by running <code>yacc</code>.
|
||||
For more advanced build setups, you may need to write a
|
||||
makefile (or a configuration file for the build tool of your choice)
|
||||
to run whatever tool creates the Go files and then check those generated source files
|
||||
|
||||
@@ -149,7 +149,7 @@ $ <b>export PATH=$PATH:$GOPATH/bin</b>
|
||||
<p>
|
||||
To learn more about setting up the <code>GOPATH</code> environment variable,
|
||||
please see
|
||||
<a href="/cmd/go/#hdr-GOPATH_environment_variable"><code>'go help gopath'</code></a>
|
||||
<a href="/cmd/go/#hdr-GOPATH_environment_variable"><code>go help gopath</code></a>
|
||||
</p>
|
||||
|
||||
<h3 id="ImportPaths">Import paths</h3>
|
||||
|
||||
@@ -20,8 +20,8 @@ ul ul {
|
||||
<p>
|
||||
Online communities include people from many different backgrounds.
|
||||
The Go contributors are committed to providing a friendly, safe and welcoming
|
||||
environment for all, regardless of age, disability, gender, nationality,
|
||||
ethnicity, religion, sexuality, or similar personal characteristic.
|
||||
environment for all, regardless of age, disability, gender, nationality, race,
|
||||
religion, sexuality, or similar personal characteristic.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -37,26 +37,6 @@ Go 1.7 is a major release of Go.
|
||||
Read the <a href="/doc/go1.7">Go 1.7 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.7.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.7.1 (released 2016/09/07) includes fixes to the compiler, runtime,
|
||||
documentation, and the <code>compress/flate</code>, <code>hash/crc32</code>,
|
||||
<code>io</code>, <code>net</code>, <code>net/http</code>,
|
||||
<code>path/filepath</code>, <code>reflect</code>, and <code>syscall</code>
|
||||
packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.1">Go
|
||||
1.7.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.7.2 (released 2016/10/17) includes fixes to the compiler, runtime,
|
||||
and the <code>crypto/cipher</code>, <code>crypto/tls</code>,
|
||||
<code>net/http</code>, and <code>strings</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.2">Go
|
||||
1.7.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.6">go1.6 (released 2016/02/17)</h2>
|
||||
|
||||
<p>
|
||||
@@ -83,7 +63,7 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.2">Go
|
||||
<p>
|
||||
go1.6.3 (released 2016/07/17) includes security fixes to the
|
||||
<code>net/http/cgi</code> package and <code>net/http</code> package when used in
|
||||
a CGI environment.
|
||||
a CGI environment. This release also adds support for macOS Sierra.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.3">Go
|
||||
1.6.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
@@ -40,13 +40,7 @@ The first section covers basic syntax and data structures; the second discusses
|
||||
methods and interfaces; and the third introduces Go's concurrency primitives.
|
||||
Each section concludes with a few exercises so you can practice what you've
|
||||
learned. You can <a href="//tour.golang.org/">take the tour online</a> or
|
||||
install it locally with:
|
||||
</p>
|
||||
<p>
|
||||
<pre>
|
||||
$ go get golang.org/x/tour/gotour
|
||||
</pre>
|
||||
This will place the <code>gotour</code> binary in your workspace's <code>bin</code> directory.
|
||||
<a href="//code.google.com/p/go-tour/">install it locally</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="code"><a href="code.html">How to write Go code</a></h3>
|
||||
|
||||
@@ -245,15 +245,15 @@ func Compile(str string) (*Regexp, error) {
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If every doc comment begins with the name of the item it describes,
|
||||
the output of <code>godoc</code> can usefully be run through <code>grep</code>.
|
||||
If the name always begins the comment, the output of <code>godoc</code>
|
||||
can usefully be run through <code>grep</code>.
|
||||
Imagine you couldn't remember the name "Compile" but were looking for
|
||||
the parsing function for regular expressions, so you ran
|
||||
the command,
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ godoc regexp | grep -i parse
|
||||
$ godoc regexp | grep parse
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -2409,7 +2409,7 @@ The <code>http</code> package contains this code:
|
||||
// Handler object that calls f.
|
||||
type HandlerFunc func(ResponseWriter, *Request)
|
||||
|
||||
// ServeHTTP calls f(w, req).
|
||||
// ServeHTTP calls f(c, req).
|
||||
func (f HandlerFunc) ServeHTTP(w ResponseWriter, req *Request) {
|
||||
f(w, req)
|
||||
}
|
||||
@@ -2447,7 +2447,7 @@ the handler installed at that page has value <code>ArgServer</code>
|
||||
and type <code>HandlerFunc</code>.
|
||||
The HTTP server will invoke the method <code>ServeHTTP</code>
|
||||
of that type, with <code>ArgServer</code> as the receiver, which will in turn call
|
||||
<code>ArgServer</code> (via the invocation <code>f(w, req)</code>
|
||||
<code>ArgServer</code> (via the invocation <code>f(c, req)</code>
|
||||
inside <code>HandlerFunc.ServeHTTP</code>).
|
||||
The arguments will then be displayed.
|
||||
</p>
|
||||
|
||||
@@ -12,7 +12,7 @@ information on building gccgo for yourself,
|
||||
see <a href="/doc/gccgo_install.html">Setting up and using gccgo</a>.
|
||||
For more of the gritty details on the process of doing development
|
||||
with the gccgo frontend,
|
||||
see <a href="https://go.googlesource.com/gofrontend/+/master/HACKING">the
|
||||
see <a href="https://code.google.com/p/gofrontend/source/browse/HACKING">the
|
||||
file HACKING</a> in the gofrontend repository.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ includes the <a href="#context">context package</a>, promoted from the
|
||||
and now used in the standard library;
|
||||
and <a href="#testing">adds support in the testing package</a> for
|
||||
creating hierarchies of tests and benchmarks.
|
||||
The release also <a href="#cmd_go">finalizes the vendoring support</a>
|
||||
The release also <a href="#cmd/go">finalizes the vendoring support</a>
|
||||
started in Go 1.5, making it a standard feature.
|
||||
</p>
|
||||
|
||||
@@ -67,7 +67,8 @@ This change has no effect on the correctness of existing programs.
|
||||
|
||||
<p>
|
||||
Go 1.7 adds support for macOS 10.12 Sierra.
|
||||
Binaries built with versions of Go before 1.7 will not work
|
||||
This support was backported to Go 1.6.3.
|
||||
Binaries built with versions of Go before 1.6.3 will not work
|
||||
correctly on Sierra.
|
||||
</p>
|
||||
|
||||
@@ -394,9 +395,9 @@ This allows the use of contexts for cancelation, timeouts, and passing
|
||||
request-scoped data in other standard library packages,
|
||||
including
|
||||
<a href="#net">net</a>,
|
||||
<a href="#net_http">net/http</a>,
|
||||
<a href="#net/http">net/http</a>,
|
||||
and
|
||||
<a href="#os_exec">os/exec</a>,
|
||||
<a href="#os/exec">os/exec</a>,
|
||||
as noted below.
|
||||
</p>
|
||||
|
||||
@@ -908,7 +909,7 @@ For example, the address on which a request received is
|
||||
<p>
|
||||
The server's <a href="/pkg/net/http/#Server.Serve"><code>Serve</code></a> method
|
||||
now only enables HTTP/2 support if the <code>Server.TLSConfig</code> field is <code>nil</code>
|
||||
or includes <code>"h2"</code> in its <code>TLSConfig.NextProtos</code>.
|
||||
or includes <code>"h2"</code> in its <code>TLSConfig.NextProto</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
443
doc/go1.8.txt
443
doc/go1.8.txt
@@ -1,443 +0,0 @@
|
||||
Overall:
|
||||
|
||||
plugin build mode & package (many CLs)
|
||||
Many ppc64, s390x, arm, arm64 optimizations
|
||||
New frontend
|
||||
Improvements to binary size, runtime speed, compile speed.
|
||||
Hybrid barrier. <100us GC pauses.
|
||||
|
||||
Language:
|
||||
|
||||
Alias declarations?
|
||||
|
||||
Tools:
|
||||
|
||||
compile: SSA for 386, nacl, arm, arm64, ppc64, ppc64le, s390x ... (many CLs)
|
||||
yacc: "go tool yacc" is removed. now at golang.org/x/tools/cmd/goyacc (CL 27324, CL 27325)
|
||||
go: -buildmode=c-archive now builds PIC on ELF (CL 24180)
|
||||
go: mobile pkg dir change, recommend using go list in scripts (CL 24930, CL 27929)
|
||||
go, dist: can set default pkg-config tool using PKG_CONFIG env var (CL 29991)
|
||||
go: can set secure/insecure GIT schemes using GIT_ALLOW_PROTOCOL env var (CL 30135)
|
||||
|
||||
Ports:
|
||||
|
||||
dragonfly: go1.8 requires DragonFly BSD 4.4.4 or above (CL 29491)
|
||||
plan9: various fixes (Close unblocks Read, I/O deadline maybe?)
|
||||
mips, mipsle
|
||||
|
||||
API additions and behavior changes:
|
||||
|
||||
all: freeze net/rpc and reword the 'frozen' message in other frozen packages (CL 32112)
|
||||
archive/tar: fix and cleanup readOldGNUSparseMap (CL 28471)
|
||||
archive/tar: fix parsePAX to be POSIX.1-2001 compliant (CL 31440)
|
||||
archive/tar: fix parsePAXTime (CL 31441)
|
||||
archive/tar: make Reader handle GNU format properly (CL 31444)
|
||||
archive/tar: reapply Header.Size to regFileReader after merging (CL 28418)
|
||||
archive/tar: validate sparse headers in parsePAX (CL 31439)
|
||||
archive/zip: handle mtime in NTFS/UNIX/ExtendedTS extra fields (CL 18274)
|
||||
archive/zip: only use Extended Timestamp on non-zero MS-DOS timestamps (CL 30811)
|
||||
cmd/cgo: add -srcdir option (CL 32354)
|
||||
cmd/cgo: fix line info in _cgo_gotypes.go (CL 29713)
|
||||
cmd/cgo: throw if C.malloc returns nil (CL 31768)
|
||||
cmd/compile, runtime, etc: get rid of constant FP registers (CL 28095)
|
||||
cmd/compile, runtime: add go:yeswritebarrierrec pragma (CL 30938)
|
||||
cmd/compile/internal/gc: add runtime/trace support (CL 25354)
|
||||
cmd/compile/internal/gc: enable new parser by default (CL 27203)
|
||||
cmd/compile/internal/syntax: fast Go syntax trees, initial commit (CL 27195)
|
||||
cmd/compile: add SSA backend for s390x and enable by default (CL 28978)
|
||||
cmd/compile: add compiler phase timing (CL 24462)
|
||||
cmd/compile: add go:notinheap type pragma (CL 30939)
|
||||
cmd/compile: add inline explainer (CL 22782)
|
||||
cmd/compile: args no longer live until end of function - use runtime.KeepAlive instead (CL 28310)
|
||||
cmd/compile: enable flag-specified dump of specific phase+function (CL 23044)
|
||||
cmd/compile: fail gracefully on export format skew (CL 27814)
|
||||
cmd/compile: import/export of alias declarations (CL 32090)
|
||||
cmd/compile: inline convI2E (CL 31260)
|
||||
cmd/compile: make ssa compilation unconditional (CL 29155)
|
||||
cmd/compile: remove -A flag (CL 31497)
|
||||
cmd/compile: remove old lexer and parser (CL 32020)
|
||||
cmd/compile: remove support for textual export format (CL 27171)
|
||||
cmd/cover: Fix compiler directives handling (CL 30161)
|
||||
cmd/cover: handle gotos (CL 30977)
|
||||
cmd/dist, go/build: make CGO_ENABLED during make.bash sticky (CL 31141)
|
||||
cmd/dist: enable plugin test on darwin/amd64 (CL 29396)
|
||||
cmd/dist: test PIE internal linking on linux/amd64 (CL 28545)
|
||||
cmd/doc: ensure summaries truly are only one line (CL 25420)
|
||||
cmd/doc: perform type grouping for constants and variables (CL 25419)
|
||||
cmd/doc: show documentation for interface methods when requested explicitly (CL 31852)
|
||||
cmd/fix: add golang.org/x/net/context fix (CL 28872)
|
||||
cmd/go, testing: indicate when no tests are run (CL 22341)
|
||||
cmd/go: add bug command (CL 28485)
|
||||
cmd/go: add distribution-specific info for Linux to bug command (CL 28581)
|
||||
cmd/go: apply import restrictions to test code too (CL 31821)
|
||||
cmd/go: diagnose non-canonical import paths before compilation (CL 31668)
|
||||
cmd/go: enable -buildmode=plugin on darwin/amd64 (CL 29395)
|
||||
cmd/go: for -msan build runtime/cgo with -fsanitize=memory (CL 24855)
|
||||
cmd/go: make bug subcommand open the browser (CL 29210)
|
||||
cmd/go: make go test -i -o x.test actually write x.test (CL 31352)
|
||||
cmd/go: print more env variables in "go env" (CL 31330)
|
||||
cmd/go: referee another vendor vs symlink fight (CL 31665)
|
||||
cmd/internal/obj, cmd/link: darwin dynlink support (CL 29393)
|
||||
cmd/internal/objfile: add ppc64/ppc64le disassembler support (CL 9682)
|
||||
cmd/link, cmd/go: delay linking of mingwex and mingw32 until very end (CL 26670)
|
||||
cmd/link: R_ADDR dynamic relocs for internal PIE (CL 29118)
|
||||
cmd/link: add trampolines for too far calls in ppc64x (CL 30850)
|
||||
cmd/link: allow internal PIE linking (CL 28543)
|
||||
cmd/link: fix -X importpath.name=value when import path needs escaping (CL 31970)
|
||||
cmd/link: fix -buildmode=pie / -linkshared combination (CL 28996)
|
||||
cmd/link: insert trampolines for too-far jumps on ARM (CL 29397)
|
||||
cmd/link: non-executable stack support for Solaris (CL 24142)
|
||||
cmd/link: plugin support on darwin/amd64 (CL 29394)
|
||||
cmd/link: put text at address 0x1000000 on darwin/amd64 (CL 32185)
|
||||
cmd/link: remove the -shared flag (CL 28852)
|
||||
cmd/link: split large elf text sections on ppc64x (CL 27790)
|
||||
cmd/link: trampoline support for external linking on ARM (CL 31143)
|
||||
cmd/objdump: implement objdump of .o files (CL 24818)
|
||||
cmd/pprof: instruction-level granularity in callgrind output (CL 23781)
|
||||
cmd/trace: add option to output pprof files (CL 23324)
|
||||
cmd/trace: fix a runnable goroutine count bug (CL 25552)
|
||||
cmd/trace: move process-wide GC events to their own row (CL 30017)
|
||||
cmd/vet: accept space-separated tag lists for compatibility with cmd/go (CL 32030)
|
||||
cmd/vet: allow ^& uintptr arithmetic (CL 27156)
|
||||
cmd/vet: allow any printf verb with any interface (CL 27127)
|
||||
cmd/vet: check for copying of array of locks (CL 24340)
|
||||
cmd/vet: check for duplicate json, xml struct field tags (CL 16704)
|
||||
cmd/vet: diagnose non-space-separated struct tag like `json:"x",xml:"y"` (CL 32031)
|
||||
cmd/vet: improve asmdecl parameter handling (CL 27150)
|
||||
cmd/vet: properly handle indexed arguments in printf (CL 24391)
|
||||
cmd/vet: skip printf check for non-constant format string during failed import (CL 29014)
|
||||
compress/flate: always return uncompressed data in the event of error (CL 28216)
|
||||
compress/flate: level 1 (best speed) match across blocks (CL 31640)
|
||||
compress/flate: make compression level 0 consistent (CL 31174)
|
||||
compress/flate: tighten the BestSpeed max match offset bound. (CL 32149)
|
||||
compress/gzip, compress/zlib: add HuffmanOnly as compression levels. (CL 31186)
|
||||
compress/gzip: only encode MTIME if it is valid (CL 32325)
|
||||
context: make DeadlineExceeded implement net.Error (CL 30370)
|
||||
crypto/cipher: enforce message size limits for GCM (CL 28410)
|
||||
crypto/rsa: ensure that generating toy RSA keys doesn't loop (CL 28969)
|
||||
crypto/tls: add CloseWrite method to Conn (CL 25159)
|
||||
crypto/tls: add CloseWrite method to Conn (CL 31318)
|
||||
crypto/tls: add Config.Clone (CL 28075)
|
||||
crypto/tls: add Config.GetConfigForClient (CL 30790)
|
||||
crypto/tls: add GetClientCertificate callback (CL 32115)
|
||||
crypto/tls: add KeyLogWriter for debugging (CL 27434)
|
||||
crypto/tls: add VerifyPeerCertificate to tls.Config (CL 26654)
|
||||
crypto/tls: add a SignatureScheme type. (CL 32119)
|
||||
crypto/tls: don't generate random ticket keys if already set (CL 27317)
|
||||
crypto/tls: enable ChaCha20-Poly1305 cipher suites by default. (CL 30958)
|
||||
crypto/tls: expand ClientHelloInfo (CL 31391)
|
||||
crypto/tls: fix deadlock when racing to complete handshake (CL 29164)
|
||||
crypto/tls: flush the buffer on handshake errors (CL 28818)
|
||||
crypto/tls: implement countermeasures against CBC padding oracles (CL 18130)
|
||||
crypto/tls: set Conn.ConnectionState.ServerName unconditionally (CL 22862)
|
||||
crypto/tls: support AES-128-CBC cipher suites with SHA-256 (CL 27315)
|
||||
crypto/tls: support ChaCha20-Poly1305. (CL 30957)
|
||||
crypto/tls: support X25519 (CL 30824, CL 30825)
|
||||
crypto/x509: Fix bug in UnknownAuthorityError.Error (CL 27992)
|
||||
crypto/x509: allow a leaf certificate to be specified directly as root (CL 27393)
|
||||
crypto/x509: check that the issuer name matches the issuer's subject name (CL 23571)
|
||||
crypto/x509: don't accept a root that already appears in a chain. (CL 32121)
|
||||
crypto/x509: fix name constraints handling (CL 30155)
|
||||
crypto/x509: implement SystemCertPool on Windows (CL 30578)
|
||||
crypto/x509: parse all names in an RDN (CL 30810)
|
||||
crypto/x509: recognise ISO OID for RSA+SHA1 (CL 27394)
|
||||
crypto/x509: require a NULL parameters for RSA public keys (CL 16166)
|
||||
crypto/x509: require a NULL parameters for RSA public keys (CL 27312)
|
||||
crypto/x509: return error for missing SerialNumber (CL 27238)
|
||||
crypto/x509: support PSS signatures (CL 24743)
|
||||
crypto/x509: support RHEL 7 cert bundle (CL 30375)
|
||||
database/sql: accept nil pointers to Valuers implemented on value receivers (CL 31259)
|
||||
database/sql: add Pinger interface to driver Conn (CL 32136)
|
||||
database/sql: add context helper methods and transaction types (CL 31258)
|
||||
database/sql: add context methods (CL 29381)
|
||||
database/sql: add option to use named parameter in query arguments (CL 30166)
|
||||
database/sql: add support for multiple result sets (CL 30592)
|
||||
database/sql: don't hang if the driver Exec method panics (CL 23576)
|
||||
database/sql: support returning query database types (CL 29961)
|
||||
debug/elf: add sparc64 relocations (CL 30870)
|
||||
debug/pe: revert CL 22720 (CL 27212)
|
||||
doc: document minimum OS X version as 10.8 (CL 28870)
|
||||
encoding/base64: add Encoding.Strict (CL 24964)
|
||||
encoding/binary: add bool support (CL 28514)
|
||||
encoding/json: add struct and field name to UnmarshalTypeError message (CL 18692)
|
||||
encoding/json: fix decoding of null into Unmarshaler, TextUnmarshaler (CL 30944)
|
||||
encoding/json: marshal the RawMessage value type the same as its pointer type (CL 21811)
|
||||
encoding/json: use standard ES6 formatting for numbers during marshal (CL 30371)
|
||||
encoding/pem: be stricter about the ending line (CL 27391)
|
||||
encoding/xml: add wildcard support for collecting all attributes (CL 30946)
|
||||
encoding/xml: prevent omitempty from omitting non-nil pointers to empty values (CL 15684)
|
||||
expvar: add Value methods (CL 30917)
|
||||
expvar: export http.Handler (CL 24722)
|
||||
flag: arrange for FlagSet.Usage to be non-nil by default (CL 31576)
|
||||
fmt: document and adjust Scanf space handling to eliminate a few paradoxes (CL 30611)
|
||||
go/ast, go/parser: parse alias declarations (CL 30211)
|
||||
go/build: allow % in ${SRCDIR} expansion for Jenkins (CL 31611)
|
||||
go/build: do not record go:binary-only-package if build tags not satisfied (CL 31577)
|
||||
go/doc: add IsPredeclared function (CL 29870)
|
||||
go/doc: allow ToHTML to properly handle URLs containing semicolons (CL 25385)
|
||||
go/internal/gcimporter: fail gracefully on export format skew (CL 27816)
|
||||
go/token: fix race in FileSet.PositionFor. (CL 25345)
|
||||
go/types: expose Default function, which converts untyped T to T (CL 30715)
|
||||
go/types: handle imported aliases (CL 32534)
|
||||
go/types: match cmd/compile's alignment for complex64 (CL 31939)
|
||||
go/types: minimal support for alias declarations: don't crash (CL 30213)
|
||||
html/template: check "type" attribute in <script> (CL 14336)
|
||||
image/color: tweak the formula for converting to gray. (CL 31538)
|
||||
image/png: implement grayscale transparency. (CL 32143)
|
||||
image/png: implement truecolor transparency. (CL 32140)
|
||||
image/png: improve compression by skipping filter for paletted images (CL 29872)
|
||||
internal/trace: fix analysis of EvGoWaiting/EvGoInSyscall events (CL 25572)
|
||||
io: fix infinite loop bug in MultiReader (CL 27397)
|
||||
io: make MultiReader nil exhausted Readers for earlier GC (CL 28533)
|
||||
math/big: Rat.SetString to report error if input is not consumed entirely (CL 30472)
|
||||
math/big: add (*Int).Sqrt (CL 30706)
|
||||
math/big: implement Float.Scan, type assert fmt interfaces to enforce docs (CL 30723)
|
||||
math/big: support negative numbers in ModInverse (CL 29299)
|
||||
math/big: test and optimize Exp(2, y, n) for large y, odd n (CL 30708)
|
||||
math/cmplx: prevent infinite loop in tanSeries (CL 31952)
|
||||
math/rand: add Rand.Uint64 (CL 27253)
|
||||
math: fix Gamma(-171.5) on all platforms (CL 30540)
|
||||
mime/quotedprintable: accept = not followed by 2 hex digits as literal equals (CL 32174)
|
||||
mime/quotedprintable: accept trailing soft line-break at the end of message (CL 27530)
|
||||
mime: preserve unnecessary backslash escapes as literals (CL 32175)
|
||||
net/http, net/http/httptest: make http2's TrailerPrefix work for http1 (CL 32479)
|
||||
net/http/httptest: fill ContentLength in recorded Response (CL 28302)
|
||||
net/http/httptrace: add ClientTrace.TLSHandshakeStart & TLSHandshakeDone (CL 30359)
|
||||
net/http/httputil: add ModifyResponse to reverseProxy (CL 32356)
|
||||
net/http/httputil: copy header map if necessary in ReverseProxy (CL 28493)
|
||||
net/http/httputil: log err encountered during reverseproxy body copying (CL 30692)
|
||||
net/http/httputil: make ReverseProxy send nil Body requests when possible (CL 28412)
|
||||
net/http/httputil: remove custom hop-by-hop headers from response in ReverseProxy (CL 28810)
|
||||
net/http/httputil: remove proxied headers mentioned in connection-tokens (CL 27970)
|
||||
net/http/internal: don't block unnecessarily in ChunkedReader (CL 31329)
|
||||
net/http: add NoBody, don't return nil from NewRequest on zero bodies (CL 31726)
|
||||
net/http: add Request.GetBody func for 307/308 redirects (CL 31733)
|
||||
net/http: add Server.Close & Server.Shutdown for forced & graceful shutdown (CL 32329)
|
||||
net/http: add Server.ReadHeaderTimeout, IdleTimeout, document WriteTimeout (CL 32024)
|
||||
net/http: add Transport.ProxyConnectHeader to control headers to proxies (CL 32481)
|
||||
net/http: add an interface for HTTP/2 server push (CL 32012)
|
||||
net/http: allow Handlers to test Hijacked conn without spamming error log (CL 30812)
|
||||
net/http: don't sniff Request.Body on 100-continue requests in Transport (CL 30151)
|
||||
net/http: handle 3xx redirects properly (CL 29852)
|
||||
net/http: make Client copy headers on redirect (CL 28930)
|
||||
net/http: make DefaultTransport's Dialer enable DualStack ("Happy Eyeballs") (CL 28077)
|
||||
net/http: make NewRequest set empty Body nil, don't peek Read Body in Transport (CL 31445)
|
||||
net/http: make Redirect escape non-ASCII in Location header (CL 31732)
|
||||
net/http: make Server Handler's Request.Context be done on conn errors (CL 31173)
|
||||
net/http: make Transport reject URLs with bogus ports with non-digits (CL 32482)
|
||||
net/http: make Transport retry non-idempotent requests if no bytes written (CL 27117)
|
||||
net/http: make Transport support international domain names (CL 29072)
|
||||
net/http: omit Content-Length in Response.Write for 1xx or 204 status (CL 28351)
|
||||
net/http: returned typed error on Transport proxy dial (CL 30750)
|
||||
net/http: send Content-Range if no byte range overlaps (CL 24212)
|
||||
net/http: skip test needing good DNS in short mode, except on builders (CL 28782)
|
||||
net/http: support multiple identical Content-Length headers (CL 31252)
|
||||
net/http: update bundled http2, add h2 Transport.IdleConnTimeout tests (CL 30078)
|
||||
net/mail: allow empty quoted string name in address again (CL 32176)
|
||||
net/mail: expose ParseDate, for use parsing Resent-Date headers (CL 31581)
|
||||
net/url: add PathEscape, PathUnescape (CL 31322)
|
||||
net/url: add URL.Hostname and URL.Port accessors (CL 28933)
|
||||
net/url: handle escaped paths in ResolveReference (CL 28343)
|
||||
net/url: make URL implement encoding.BinaryMarshaler, BinaryUnmarshaler (CL 31467)
|
||||
net/url: prefix relative paths containing ":" in the first segment with "./" (CL 29610)
|
||||
net/url: reject colon in first segment of relative path in Parse (CL 31582)
|
||||
net: add (*UnixListener).SetUnlinkOnClose (CL 32099)
|
||||
net: add Buffers type, do writev on unix (CL 29951)
|
||||
net: add Resolver type, Dialer.Resolver, and DefaultResolver (CL 29440)
|
||||
net: always wake up the readers on close on Plan 9 (CL 31390)
|
||||
net: break up >1GB reads and writes on stream connections (CL 31584)
|
||||
net: close the connection gracefully on Plan 9 (CL 31271)
|
||||
net: implement network interface API for Plan 9 (CL 29963)
|
||||
net: implement network interface API for Solaris (CL 29892)
|
||||
net: make LookupPort and lookupProtocol work on nacl (CL 28951)
|
||||
net: make lookupPort case-insensitive on Plan 9 (CL 29051)
|
||||
net: only remove Unix domain socket file on the first call to Close (CL 32098)
|
||||
net: remove parsing of negative decimals in IPv4 literal (CL 28414)
|
||||
net: respect resolv.conf rotate option (CL 29233)
|
||||
net: support "option ndots:0" in resolv.conf (CL 24901)
|
||||
net: there are no invalid domain names anymore (CL 31468)
|
||||
net: use libresolv rules for ndots range and validation (CL 24901)
|
||||
os, syscall: fix incorrect offset calculation in Readlink on windows (CL 31118)
|
||||
os: add ErrClosed, return for use of closed File (CL 30614)
|
||||
os: add Executable() (CL 16551)
|
||||
os: consider only files from #M as regular on Plan 9 (CL 32152)
|
||||
os: don't let File.Readdir return an empty slice and nil error (CL 28056)
|
||||
os: make IsExist report true on ERROR_DIR_NOT_EMPTY on Windows (CL 29753)
|
||||
os: make Windows readConsole handle input and output correctly (CL 29493)
|
||||
os: prevent infinite symlink loop of Stat on Windows (CL 27580)
|
||||
os: reject Rename("old", "new") where new is a directory (CL 31358)
|
||||
os: use GetConsoleCP() instead of GetACP() (CL 27575)
|
||||
path/filepath: don't return SkipDir at top (CL 24780)
|
||||
path/filepath: fix Abs on Windows (CL 32292)
|
||||
path/filepath: fix match of \\?\c:\* on Windows (CL 31460)
|
||||
path/filepath: handle ".." in normalizing a path on Windows (CL 27410)
|
||||
path/filepath: handle "C:." correctly in EvalSymlinks on Windows (CL 28214)
|
||||
plugin: darwin support (CL 29392)
|
||||
plugin: mention OS X support and concurrency (CL 31463)
|
||||
plugin: new package for loading plugins (CL 27823)
|
||||
reflect: add Swapper func (CL 30088)
|
||||
reflect: fix DeepEqual for some cyclic corner cases (CL 31588)
|
||||
reflect: ignore struct tags when converting structs (CL 30191)
|
||||
runtime, cmd/trace: annotate different mark worker types (CL 30702)
|
||||
runtime, runtime/cgo: revert CL 18814; don't drop signal stack in new thread on dragonfly (CL 29971)
|
||||
runtime/pprof: write profiles in protobuf format. (CL 32257)
|
||||
runtime/race: don't crash on invalid PCs (CL 29714)
|
||||
runtime/race: update race runtime (CL 32160)
|
||||
runtime: Profile goroutines holding contended mutexes. (CL 29650)
|
||||
runtime: assume 64kB physical pages on ARM (CL 25021)
|
||||
runtime: disable stack rescanning by default (CL 31766)
|
||||
runtime: don't call cgocallback from signal handler (CL 30218)
|
||||
runtime: fetch physical page size from the OS (CL 25050)
|
||||
runtime: fix check for vacuous page boundary rounding (CL 27230)
|
||||
runtime: fix map iterator concurrent map check (CL 24749)
|
||||
runtime: fix newextram PC passed to race detector (CL 29712)
|
||||
runtime: implement unconditional hybrid barrier (CL 31765)
|
||||
runtime: limit the number of map overflow buckets (CL 25049)
|
||||
runtime: pass windows float syscall args via XMM (CL 32173)
|
||||
runtime: print sigcode on signal crash (CL 32183)
|
||||
runtime: record current PC for SIGPROF on non-Go thread (CL 30252)
|
||||
runtime: report GCSys and OtherSys in heap profile (CL 29276)
|
||||
runtime: sleep on CLOCK_MONOTONIC in futexsleep1 on freebsd (CL 30154)
|
||||
runtime: use RtlGenRandom instead of CryptGenRandom (CL 29700)
|
||||
runtime: use clock_gettime(CLOCK_REALTIME) for nanosecond-precision time.now on arm64, mips64x (CL 32177)
|
||||
runtime: use correct system page size on all arches (CL 25022)
|
||||
sort: add Slice, SliceStable, and SliceIsSorted (CL 27321)
|
||||
spec: add new language for alias declarations (CL 30601)
|
||||
spec: ignore struct tags when converting structs (CL 24190)
|
||||
spec: require 16 bit minimum exponent in constants rather than 32 (CL 17711)
|
||||
spec: update language on type switches to match implementations (CL 27356)
|
||||
strconv: strip \r in raw strings passed to Unquote (CL 31210)
|
||||
strings, bytes: panic if Repeat overflows or if given a negative count (CL 29954)
|
||||
sync: enable Pool when using race detector (CL 31589)
|
||||
sync: throw, not panic, for unlock of unlocked mutex (CL 31359)
|
||||
syscall: add bounds checking and error returns to ParseNetlinkMessage (CL 26990)
|
||||
syscall: fix Send{msg,msgN}, Recvmsg and control message handling on solaris (CL 30171)
|
||||
syscall: make Getpagesize return system-reported page size (CL 25051)
|
||||
syscall: make Utimes on Solaris match all the other geese (CL 31446)
|
||||
syscall: remove X__cmsg_data from Cmsghdr (CL 32319)
|
||||
syscall: unify NsecToTime{spec,val}, fix for times < 1970 (CL 30826)
|
||||
syscall: validate ParseDirent inputs (CL 23780)
|
||||
testing/quick, text/tabwriter: freeze packages (CL 31910)
|
||||
testing: add Name method to *T and *B (CL 29970)
|
||||
testing: add a method testing.CoverMode (CL 32483)
|
||||
testing: respect benchtime on very fast benchmarks (CL 26664)
|
||||
text/template: add support for reflect.Value args, results in funcs (CL 31462)
|
||||
time: add Until helper function (CL 20118)
|
||||
time: allow long fractions in ParseDuration (CL 29338)
|
||||
time: be consistent about representation of UTC location in Time struct (CL 31144)
|
||||
unicode: change SimpleFold to handle invalid runes (CL 30935)
|
||||
website: recreate 16px and 32px favicon (CL 26850)
|
||||
|
||||
Optimizations:
|
||||
|
||||
bytes, strings: optimize for ASCII sets (CL 31593)
|
||||
bytes, strings: optimize multi-byte index operations on s390x (CL 32447)
|
||||
bytes,strings: use IndexByte more often in Index on AMD64 (CL 31690)
|
||||
bytes: Use the same algorithm as strings for Index (CL 22550)
|
||||
bytes: improve WriteRune performance (CL 28816)
|
||||
bytes: improve performance for bytes.Compare on ppc64x (CL 30949)
|
||||
bytes: make IndexRune faster (CL 28537)
|
||||
cmd/asm, go/build: invoke cmd/asm only once per package (CL 27636)
|
||||
cmd/compile, cmd/link: more efficient typelink generation (CL 31772)
|
||||
cmd/compile, cmd/link: stop generating unused go.string.hdr symbols. (CL 31030)
|
||||
cmd/compile,runtime: redo how map assignments work (CL 30815)
|
||||
cmd/compile/internal/obj/x86: eliminate some function prologues (CL 24814)
|
||||
cmd/compile: accept literals in samesafeexpr (CL 26666)
|
||||
cmd/compile: add more non-returning runtime calls (CL 28965)
|
||||
cmd/compile: add size hint to map literal allocations (CL 23558)
|
||||
cmd/compile: be more aggressive in tighten pass for booleans (CL 28390)
|
||||
cmd/compile: directly construct Fields instead of ODCLFIELD nodes (CL 31670)
|
||||
cmd/compile: don't reserve X15 for float sub/div any more (CL 28272)
|
||||
cmd/compile: don’t generate pointless gotos during inlining (CL 27461)
|
||||
cmd/compile: fold negation into comparison operators (CL 28232)
|
||||
cmd/compile: generate makeslice calls with int arguments (CL 27851)
|
||||
cmd/compile: handle e == T comparison more efficiently (CL 26660)
|
||||
cmd/compile: improve s390x SSA rules for logical ops (CL 31754)
|
||||
cmd/compile: improve s390x rules for folding ADDconst into loads/stores (CL 30616)
|
||||
cmd/compile: improve string iteration performance (CL 27853)
|
||||
cmd/compile: improve tighten pass (CL 28712)
|
||||
cmd/compile: inline _, ok = i.(T) (CL 26658)
|
||||
cmd/compile: inline atomics from runtime/internal/atomic on amd64 (CL 27641, CL 27813)
|
||||
cmd/compile: inline convT2{I,E} when result doesn't escape (CL 29373)
|
||||
cmd/compile: inline x, ok := y.(T) where T is a scalar (CL 26659)
|
||||
cmd/compile: intrinsify atomic operations on s390x (CL 31614)
|
||||
cmd/compile: intrinsify math/big.mulWW, divWW on AMD64 (CL 30542)
|
||||
cmd/compile: intrinsify runtime/internal/atomic.Xaddint64 (CL 29274)
|
||||
cmd/compile: intrinsify slicebytetostringtmp when not instrumenting (CL 29017)
|
||||
cmd/compile: intrinsify sync/atomic for amd64 (CL 28076)
|
||||
cmd/compile: make [0]T and [1]T SSAable types (CL 32416)
|
||||
cmd/compile: make link register allocatable in non-leaf functions (CL 30597)
|
||||
cmd/compile: missing float indexed loads/stores on amd64 (CL 28273)
|
||||
cmd/compile: move stringtoslicebytetmp to the backend (CL 32158)
|
||||
cmd/compile: only generate ·f symbols when necessary (CL 31031)
|
||||
cmd/compile: optimize bool to int conversion (CL 22711)
|
||||
cmd/compile: optimize integer "in range" expressions (CL 27652)
|
||||
cmd/compile: remove Zero and NilCheck for newobject (CL 27930)
|
||||
cmd/compile: remove duplicate nilchecks (CL 29952)
|
||||
cmd/compile: remove some write barriers for stack writes (CL 30290)
|
||||
cmd/compile: simplify div/mod on ARM (CL 29390)
|
||||
cmd/compile: statically initialize some interface values (CL 26668)
|
||||
cmd/compile: unroll comparisons to short constant strings (CL 26758)
|
||||
cmd/compile: use 2-result divide op (CL 25004)
|
||||
cmd/compile: use masks instead of branches for slicing (CL 32022)
|
||||
cmd/compile: when inlining ==, don’t take the address of the values (CL 22277)
|
||||
container/heap: remove one unnecessary comparison in Fix (CL 24273)
|
||||
crypto/sha256: improve performance for sha256.block on ppc64le (CL 32318)
|
||||
crypto/sha512: improve performance for sha512.block on ppc64le (CL 32320)
|
||||
crypto/{aes,cipher}: add optimized implementation of AES-GCM for s390x (CL 30361)
|
||||
encoding/asn1: reduce allocations in Marshal (CL 27030)
|
||||
encoding/csv: avoid allocations when reading records (CL 24723)
|
||||
encoding/hex: change lookup table from string to array (CL 27254)
|
||||
encoding/json: Use a lookup table for safe characters (CL 24466)
|
||||
hash/crc32: improve the AMD64 implementation using SSE4.2 (CL 24471)
|
||||
hash/crc32: improve the AMD64 implementation using SSE4.2 (CL 27931)
|
||||
hash/crc32: improve the processing of the last bytes in the SSE4.2 code for AMD64 (CL 24470)
|
||||
image/color: improve speed of RGBA methods (CL 31773)
|
||||
image/draw: optimize drawFillOver as drawFillSrc for opaque fills (CL 28790)
|
||||
math/big: avoid allocation in float.{Add, Sub} when there's no aliasing (CL 23568)
|
||||
math/big: make division faster (CL 30613)
|
||||
math/big: slightly faster float->decimal conversion (CL 31250)
|
||||
math/big: use array instead of slice for deBruijn lookups (CL 26663)
|
||||
math/big: uses SIMD for some math big functions on s390x (CL 32211)
|
||||
math: speed up Gamma(+Inf) (CL 31370)
|
||||
math: speed up bessel functions on AMD64 (CL 28086)
|
||||
reflect: avoid zeroing memory that will be overwritten (CL 28011)
|
||||
regexp: avoid alloc in QuoteMeta when not quoting (CL 31395)
|
||||
regexp: reduce mallocs in Regexp.Find* and Regexp.ReplaceAll* (CL 23030)
|
||||
runtime: cgo calls are about 100ns faster (CL 29656, CL 30080)
|
||||
runtime: defer is now 2X faster (CL 29656)
|
||||
runtime: implement getcallersp in Go (CL 29655)
|
||||
runtime: improve memmove for amd64 (CL 22515, CL 29590)
|
||||
runtime: increase malloc size classes (CL 24493)
|
||||
runtime: large objects no longer cause significant goroutine pauses (CL 23540)
|
||||
runtime: make append only clear uncopied memory (CL 30192)
|
||||
runtime: make assists perform root jobs (CL 32432)
|
||||
runtime: memclr perf improvements on ppc64x (CL 30373)
|
||||
runtime: minor string/rune optimizations (CL 27460)
|
||||
runtime: optimize defer code (CL 29656)
|
||||
runtime: remove a load and shift from scanobject (CL 22712)
|
||||
runtime: remove defer from standard cgo call (CL 30080)
|
||||
runtime: speed up StartTrace with lots of blocked goroutines (CL 25573)
|
||||
runtime: speed up non-ASCII rune decoding (CL 28490)
|
||||
strconv: make FormatFloat slowpath a little faster (CL 30099)
|
||||
strings: add special cases for Join of 2 and 3 strings (CL 25005)
|
||||
strings: make IndexRune faster (CL 28546)
|
||||
strings: use AVX2 for Index if available (CL 22551)
|
||||
strings: use Index in Count (CL 28586)
|
||||
syscall: avoid convT2I allocs for common Windows error values (CL 28484, CL 28990)
|
||||
text/template: improve lexer performance in finding left delimiters (CL 24863)
|
||||
unicode/utf8: optimize ValidRune (CL 32122)
|
||||
unicode/utf8: reduce bounds checks in EncodeRune (CL 28492)
|
||||
|
||||
Documentation:
|
||||
|
||||
all: many more examples in documentations (many CLs)
|
||||
runtime: runtime.MemStats has much more detailed documentation (CL 28972)
|
||||
|
||||
Binary Size:
|
||||
|
||||
cmd/link: more efficient encoding of DWARF line number information (CL 30577)
|
||||
cmd/compile: recognize integer ranges in switch statements (CL 26770)
|
||||
cmd/compile: use two tables for table-driven map inserts (CL 26669)
|
||||
cmd/link: when dynlinking, do not mangle short symbol names (CL 26890)
|
||||
cmd/compile, runtime: stop padding stackmaps to 4 bytes (CL 30817)
|
||||
@@ -271,27 +271,6 @@ you will need to abide by the guidelines at
|
||||
|
||||
<h2 id="Design">Design</h2>
|
||||
|
||||
<h3 id="runtime">
|
||||
Does Go have a runtime?</h3>
|
||||
|
||||
<p>
|
||||
Go does have an extensive library, called the <em>runtime</em>,
|
||||
that is part of every Go program.
|
||||
The runtime library implements garbage collection, concurrency,
|
||||
stack management, and other critical features of the Go language.
|
||||
Although it is more central to the language, Go's runtime is analogous
|
||||
to <code>libc</code>, the C library.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is important to understand, however, that Go's runtime does not
|
||||
include a virtual machine, such as is provided by the Java runtime.
|
||||
Go programs are compiled ahead of time to native machine code.
|
||||
Thus, although the term is often used to describe the virtual
|
||||
environment in which a program runs, in Go the word “runtime”
|
||||
is just the name given to the library providing critical language services.
|
||||
</p>
|
||||
|
||||
<h3 id="unicode_identifiers">
|
||||
What's up with Unicode identifiers?</h3>
|
||||
|
||||
@@ -889,7 +868,6 @@ Why does Go not have covariant result types?</h3>
|
||||
|
||||
<p>
|
||||
Covariant result types would mean that an interface like
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type Copyable interface {
|
||||
@@ -897,15 +875,13 @@ type Copyable interface {
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
would be satisfied by the method
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func (v Value) Copy() Value
|
||||
</pre>
|
||||
|
||||
<p>because <code>Value</code> implements the empty interface.
|
||||
because <code>Value</code> implements the empty interface.
|
||||
In Go method types must match exactly, so <code>Value</code> does not
|
||||
implement <code>Copyable</code>.
|
||||
Go separates the notion of what a
|
||||
@@ -1151,12 +1127,6 @@ struct. If the interface value holds a pointer, copying the interface value
|
||||
makes a copy of the pointer, but again not the data it points to.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that this discussion is about the semantics of the operations.
|
||||
Actual implementations may apply optimizations to avoid copying
|
||||
as long as the optimizations do not change the semantics.
|
||||
</p>
|
||||
|
||||
<h3 id="pointer_to_interface">
|
||||
When should I use a pointer to an interface?</h3>
|
||||
|
||||
@@ -1292,26 +1262,11 @@ size of value should use an explicitly sized type, like <code>int64</code>.
|
||||
Prior to Go 1.1, the 64-bit Go compilers (both gc and gccgo) used
|
||||
a 32-bit representation for <code>int</code>. As of Go 1.1 they use
|
||||
a 64-bit representation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
On the other hand, floating-point scalars and complex
|
||||
types are always sized (there are no <code>float</code> or <code>complex</code> basic types),
|
||||
because programmers should be aware of precision when using floating-point numbers.
|
||||
The default type used for an (untyped) floating-point constant is <code>float64</code>.
|
||||
Thus <code>foo</code> <code>:=</code> <code>3.0</code> declares a variable <code>foo</code>
|
||||
of type <code>float64</code>.
|
||||
For a <code>float32</code> variable initialized by an (untyped) constant, the variable type
|
||||
must be specified explicitly in the variable declaration:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var foo float32 = 3.0
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Alternatively, the constant must be given a type with a conversion as in
|
||||
<code>foo := float32(3.0)</code>.
|
||||
numbers are always sized: <code>float32</code>, <code>complex64</code>,
|
||||
etc., because programmers should be aware of precision when using
|
||||
floating-point numbers.
|
||||
The default size of a floating-point constant is <code>float64</code>.
|
||||
</p>
|
||||
|
||||
<h3 id="stack_or_heap">
|
||||
@@ -1715,7 +1670,8 @@ What compiler technology is used to build the compilers?</h3>
|
||||
|
||||
<p>
|
||||
<code>Gccgo</code> has a front end written in C++, with a recursive descent parser coupled to the
|
||||
standard GCC back end. <code>Gc</code> is written in Go with a recursive descent parser
|
||||
standard GCC back end. <code>Gc</code> is written in Go using
|
||||
<code>yacc</code>/<code>bison</code> for the parser
|
||||
and uses a custom loader, also written in Go but
|
||||
based on the Plan 9 loader, to generate ELF/Mach-O/PE binaries.
|
||||
</p>
|
||||
@@ -1776,7 +1732,7 @@ A simple C "hello, world" program compiled and linked statically using gcc
|
||||
on Linux is around 750 kB,
|
||||
including an implementation of <code>printf</code>.
|
||||
An equivalent Go program using <code>fmt.Printf</code>
|
||||
is around 1.5 MB, but
|
||||
is around 2.3 MB, but
|
||||
that includes more powerful run-time support and type information.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of November 4, 2016",
|
||||
"Subtitle": "Version of May 31, 2016",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
@@ -265,7 +265,7 @@ The following character sequences represent <a href="#Operators">operators</a>,
|
||||
* ^ *= ^= <- > >= { }
|
||||
/ << /= <<= ++ = := , ;
|
||||
% >> %= >>= -- ! ... . :
|
||||
&^ &^= =>
|
||||
&^ &^=
|
||||
</pre>
|
||||
|
||||
<h3 id="Integer_literals">Integer literals</h3>
|
||||
@@ -605,7 +605,7 @@ implementation must:
|
||||
|
||||
<li>Represent floating-point constants, including the parts of
|
||||
a complex constant, with a mantissa of at least 256 bits
|
||||
and a signed binary exponent of at least 16 bits.</li>
|
||||
and a signed exponent of at least 32 bits.</li>
|
||||
|
||||
<li>Give an error if unable to represent an integer constant
|
||||
precisely.</li>
|
||||
@@ -2286,10 +2286,8 @@ For array and slice literals the following rules apply:
|
||||
<li>Each element has an associated integer index marking
|
||||
its position in the array.
|
||||
</li>
|
||||
<li>An element with a key uses the key as its index. The
|
||||
key must be a non-negative constant representable by
|
||||
a value of type <code>int</code>; and if it is typed
|
||||
it must be of integer type.
|
||||
<li>An element with a key uses the key as its index; the
|
||||
key must be a constant integer expression.
|
||||
</li>
|
||||
<li>An element without a key uses the previous element's index plus one.
|
||||
If the first element has no key, its index is zero.
|
||||
@@ -2322,7 +2320,7 @@ days := [...]string{"Sat", "Sun"} // len(days) == 2
|
||||
|
||||
<p>
|
||||
A slice literal describes the entire underlying array literal.
|
||||
Thus the length and capacity of a slice literal are the maximum
|
||||
Thus, the length and capacity of a slice literal are the maximum
|
||||
element index plus one. A slice literal has the form
|
||||
</p>
|
||||
|
||||
@@ -2935,7 +2933,6 @@ used in an <a href="#Assignments">assignment</a> or initialization of the specia
|
||||
v, ok = a[x]
|
||||
v, ok := a[x]
|
||||
var v, ok = a[x]
|
||||
var v, ok T = a[x]
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -3116,16 +3113,13 @@ known to be <code>T</code> in a correct program.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var x interface{} = 7 // x has dynamic type int and value 7
|
||||
i := x.(int) // i has type int and value 7
|
||||
var x interface{} = 7 // x has dynamic type int and value 7
|
||||
i := x.(int) // i has type int and value 7
|
||||
|
||||
type I interface { m() }
|
||||
|
||||
func f(y I) {
|
||||
s := y.(string) // illegal: string does not implement I (missing method m)
|
||||
r := y.(io.Reader) // r has type io.Reader and the dynamic type of y must implement both I and io.Reader
|
||||
…
|
||||
}
|
||||
var y I
|
||||
s := y.(string) // illegal: string does not implement I (missing method m)
|
||||
r := y.(io.Reader) // r has type io.Reader and y must implement both I and io.Reader
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -3136,7 +3130,6 @@ A type assertion used in an <a href="#Assignments">assignment</a> or initializat
|
||||
v, ok = x.(T)
|
||||
v, ok := x.(T)
|
||||
var v, ok = x.(T)
|
||||
var v, ok T1 = x.(T)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -3744,7 +3737,6 @@ A receive expression used in an <a href="#Assignments">assignment</a> or initial
|
||||
x, ok = <-ch
|
||||
x, ok := <-ch
|
||||
var x, ok = <-ch
|
||||
var x, ok T = <-ch
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
@@ -3842,12 +3834,10 @@ in any of these cases:
|
||||
to <code>T</code>.
|
||||
</li>
|
||||
<li>
|
||||
ignoring struct tags (see below),
|
||||
<code>x</code>'s type and <code>T</code> have <a href="#Type_identity">identical</a>
|
||||
<code>x</code>'s type and <code>T</code> have identical
|
||||
<a href="#Types">underlying types</a>.
|
||||
</li>
|
||||
<li>
|
||||
ignoring struct tags (see below),
|
||||
<code>x</code>'s type and <code>T</code> are unnamed pointer types
|
||||
and their pointer base types have identical underlying types.
|
||||
</li>
|
||||
@@ -3867,31 +3857,6 @@ in any of these cases:
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<a href="#Struct_types">Struct tags</a> are ignored when comparing struct types
|
||||
for identity for the purpose of conversion:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type Person struct {
|
||||
Name string
|
||||
Address *struct {
|
||||
Street string
|
||||
City string
|
||||
}
|
||||
}
|
||||
|
||||
var data *struct {
|
||||
Name string `json:"name"`
|
||||
Address *struct {
|
||||
Street string `json:"street"`
|
||||
City string `json:"city"`
|
||||
} `json:"address"`
|
||||
}
|
||||
|
||||
var person = (*Person)(data) // ignoring tags, the underlying types are identical
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Specific rules apply to (non-constant) conversions between numeric types or
|
||||
to and from a string type.
|
||||
@@ -4722,8 +4687,8 @@ TypeList = Type { "," Type } .
|
||||
<p>
|
||||
The TypeSwitchGuard may include a
|
||||
<a href="#Short_variable_declarations">short variable declaration</a>.
|
||||
When that form is used, the variable is declared at the end of the
|
||||
TypeSwitchCase in the <a href="#Blocks">implicit block</a> of each clause.
|
||||
When that form is used, the variable is declared at the beginning of
|
||||
the <a href="#Blocks">implicit block</a> in each clause.
|
||||
In clauses with a case listing exactly one type, the variable
|
||||
has that type; otherwise, the variable has the type of the expression
|
||||
in the TypeSwitchGuard.
|
||||
@@ -5758,12 +5723,12 @@ var a = complex(2, -2) // complex128
|
||||
const b = complex(1.0, -1.4) // untyped complex constant 1 - 1.4i
|
||||
x := float32(math.Cos(math.Pi/2)) // float32
|
||||
var c64 = complex(5, -x) // complex64
|
||||
var s uint = complex(1, 0) // untyped complex constant 1 + 0i can be converted to uint
|
||||
_ = complex(1, 2<<s) // illegal: 2 assumes floating-point type, cannot shift
|
||||
const s uint = complex(1, 0) // untyped complex constant 1 + 0i can be converted to uint
|
||||
_ = complex(1, 2<<s) // illegal: 2 has floating-point type, cannot shift
|
||||
var rl = real(c64) // float32
|
||||
var im = imag(a) // float64
|
||||
const c = imag(b) // untyped constant -1.4
|
||||
_ = imag(3 << s) // illegal: 3 assumes complex type, cannot shift
|
||||
_ = imag(3 << s) // illegal: 3 has complex type, cannot shift
|
||||
</pre>
|
||||
|
||||
<h3 id="Handling_panics">Handling panics</h3>
|
||||
@@ -6194,10 +6159,9 @@ func init() { … }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Multiple such functions may be defined per package, even within a single
|
||||
source file. In the package block, the <code>init</code> identifier can
|
||||
be used only to declare <code>init</code> functions, yet the identifier
|
||||
itself is not <a href="#Declarations_and_scope">declared</a>. Thus
|
||||
Multiple such functions may be defined, even within a single
|
||||
source file. The <code>init</code> identifier is not
|
||||
<a href="#Declarations_and_scope">declared</a> and thus
|
||||
<code>init</code> functions cannot be referred to from anywhere
|
||||
in a program.
|
||||
</p>
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32.000001"
|
||||
id="svg4416"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="favicon.svg"
|
||||
inkscape:export-filename="../../favicon.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4418" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="15.839192"
|
||||
inkscape:cx="17.966652"
|
||||
inkscape:cy="9.2991824"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-bbox-edge-midpoints="false"
|
||||
inkscape:bbox-nodes="true"
|
||||
showguides="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1018"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-global="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid5148" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4421">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="icon"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<ellipse
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#384e54;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="ellipse4216"
|
||||
cx="-907.35657"
|
||||
cy="479.90009"
|
||||
rx="3.5793996"
|
||||
ry="3.8207953"
|
||||
transform="matrix(-0.49169095,-0.87076978,-0.87076978,0.49169095,0,0)"
|
||||
inkscape:transform-center-x="0.67794294"
|
||||
inkscape:transform-center-y="-2.3634048" />
|
||||
<ellipse
|
||||
inkscape:transform-center-y="-2.3633882"
|
||||
inkscape:transform-center-x="-0.67793718"
|
||||
transform="matrix(0.49169095,-0.87076978,0.87076978,0.49169095,0,0)"
|
||||
ry="3.8207953"
|
||||
rx="3.5793996"
|
||||
cy="507.8461"
|
||||
cx="-891.57654"
|
||||
id="ellipse4463"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#384e54;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#384e54;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 16.091693,1021.3642 c -1.105749,0.01 -2.210341,0.049 -3.31609,0.09 C 6.8422558,1021.6738 2,1026.3942 2,1032.3622 c 0,2.9786 0,13 0,20 l 28,0 c 0,-8 0,-16 0,-20 0,-5.9683 -4.667345,-10.4912 -10.59023,-10.908 -1.10575,-0.078 -2.212328,-0.099 -3.318077,-0.09 z"
|
||||
id="path4465"
|
||||
sodipodi:nodetypes="ccsccscc" />
|
||||
<path
|
||||
inkscape:transform-center-y="-1.3604657"
|
||||
inkscape:transform-center-x="-0.98424303"
|
||||
sodipodi:nodetypes="sssssss"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4469"
|
||||
d="m 4.6078867,1025.0462 c 0.459564,0.2595 1.818262,1.2013 1.980983,1.648 0.183401,0.5035 0.159385,1.0657 -0.114614,1.551 -0.346627,0.6138 -1.005341,0.9487 -1.696421,0.9365 -0.339886,-0.01 -1.720283,-0.6372 -2.042561,-0.8192 -0.97754,-0.5519 -1.350795,-1.7418 -0.833686,-2.6576 0.517109,-0.9158 1.728749,-1.2107 2.706299,-0.6587 z"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#76e1fe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.32850246;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4473"
|
||||
width="3.0866659"
|
||||
height="3.5313663"
|
||||
x="14.406213"
|
||||
y="1035.6842"
|
||||
ry="0.62426329" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#76e1fe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 16,1023.3622 c -9,0 -12,3.7153 -12,9 l 0,20 24,0 c -0.04889,-7.3562 0,-18 0,-20 0,-5.2848 -3,-9 -12,-9 z"
|
||||
id="path4471"
|
||||
sodipodi:nodetypes="zsccsz" />
|
||||
<path
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#76e1fe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 27.074073,1025.0462 c -0.45957,0.2595 -1.818257,1.2013 -1.980979,1.648 -0.183401,0.5035 -0.159384,1.0657 0.114614,1.551 0.346627,0.6138 1.005335,0.9487 1.696415,0.9365 0.33988,-0.01 1.72029,-0.6372 2.04256,-0.8192 0.97754,-0.5519 1.35079,-1.7418 0.83369,-2.6576 -0.51711,-0.9158 -1.72876,-1.2107 -2.7063,-0.6587 z"
|
||||
id="path4481"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sssssss"
|
||||
inkscape:transform-center-x="0.98424094"
|
||||
inkscape:transform-center-y="-1.3604657" />
|
||||
<circle
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="circle4477"
|
||||
cx="21.175734"
|
||||
cy="1030.3542"
|
||||
r="4.6537542"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<circle
|
||||
r="4.8316345"
|
||||
cy="1030.3542"
|
||||
cx="10.339486"
|
||||
id="circle4483"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<rect
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.32941176;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4246"
|
||||
width="3.6673687"
|
||||
height="4.1063409"
|
||||
x="14.115863"
|
||||
y="1035.9174"
|
||||
ry="0.72590536" />
|
||||
<rect
|
||||
ry="0.72590536"
|
||||
y="1035.2253"
|
||||
x="14.115863"
|
||||
height="4.1063409"
|
||||
width="3.6673687"
|
||||
id="rect4485"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#fffcfb;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<path
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.32941176;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 19.999735,1036.5289 c 0,0.838 -0.871228,1.2682 -2.144766,1.1659 -0.02366,0 -0.04795,-0.6004 -0.254147,-0.5832 -0.503669,0.042 -1.095902,-0.02 -1.685964,-0.02 -0.612939,0 -1.206342,0.1826 -1.68549,0.017 -0.110233,-0.038 -0.178298,0.5838 -0.261532,0.5816 -1.243685,-0.033 -2.078803,-0.3383 -2.078803,-1.1618 0,-1.2118 1.815635,-2.1941 4.055351,-2.1941 2.239704,0 4.055351,0.9823 4.055351,2.1941 z"
|
||||
id="path4487"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sssssssss"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<path
|
||||
sodipodi:nodetypes="sssssssss"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4489"
|
||||
d="m 19.977414,1035.7004 c 0,0.5685 -0.433659,0.8554 -1.138091,1.0001 -0.291933,0.06 -0.630371,0.096 -1.003719,0.1166 -0.56405,0.032 -1.207782,0.031 -1.89122,0.031 -0.672834,0 -1.307182,0 -1.864904,-0.029 -0.306268,-0.017 -0.589429,-0.043 -0.843164,-0.084 -0.813833,-0.1318 -1.324962,-0.417 -1.324962,-1.0344 0,-1.1601 1.805642,-2.1006 4.03303,-2.1006 2.227377,0 4.03303,0.9405 4.03303,2.1006 z"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c38c74;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<ellipse
|
||||
cy="1033.8501"
|
||||
cx="15.944382"
|
||||
id="ellipse4491"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#23201f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
rx="2.0801733"
|
||||
ry="1.343747"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<circle
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#171311;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="circle4493"
|
||||
cx="12.414201"
|
||||
cy="1030.3542"
|
||||
r="1.9630634"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<circle
|
||||
r="1.9630634"
|
||||
cy="1030.3542"
|
||||
cx="23.110121"
|
||||
id="circle4495"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#171311;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:export-filename=".\rect4485.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4497"
|
||||
d="m 5.0055377,1027.2727 c -1.170435,-1.0835 -2.026973,-0.7721 -2.044172,-0.7463"
|
||||
style="display:inline;fill:none;fill-rule:evenodd;stroke:#384e54;stroke-width:0.39730874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="display:inline;fill:none;fill-rule:evenodd;stroke:#384e54;stroke-width:0.39730874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 4.3852457,1026.9152 c -1.158557,0.036 -1.346704,0.6303 -1.33881,0.6523"
|
||||
id="path4499"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="display:inline;fill:none;fill-rule:evenodd;stroke:#384e54;stroke-width:0.39730874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 26.630533,1027.1724 c 1.17043,-1.0835 2.02697,-0.7721 2.04417,-0.7463"
|
||||
id="path4501"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4503"
|
||||
d="m 27.321773,1026.673 c 1.15856,0.036 1.3467,0.6302 1.3388,0.6522"
|
||||
style="display:inline;fill:none;fill-rule:evenodd;stroke:#384e54;stroke-width:0.39730874;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 17 KiB |
@@ -43,13 +43,17 @@ architectures.
|
||||
<code>amd64</code> (also known as <code>x86-64</code>)
|
||||
</dt>
|
||||
<dd>
|
||||
A mature implementation.
|
||||
A mature implementation. New in 1.7 is its SSA-based back end
|
||||
that generates compact, efficient code.
|
||||
</dd>
|
||||
<dt>
|
||||
<code>386</code> (<code>x86</code> or <code>x86-32</code>)
|
||||
</dt>
|
||||
<dd>
|
||||
Comparable to the <code>amd64</code> port.
|
||||
Comparable to the <code>amd64</code> port, but does
|
||||
not yet use the SSA-based back end. It has an effective
|
||||
optimizer (registerizer) and generates good code (although
|
||||
<code>gccgo</code> can do noticeably better sometimes).
|
||||
</dd>
|
||||
<dt>
|
||||
<code>arm</code> (<code>ARM</code>)
|
||||
@@ -115,39 +119,27 @@ Go does not support CentOS 6 on these systems.
|
||||
<p>
|
||||
The Go tool chain is written in Go. To build it, you need a Go compiler installed.
|
||||
The scripts that do the initial build of the tools look for an existing Go tool
|
||||
chain in <code>$GOROOT_BOOTSTRAP</code>.
|
||||
If unset, the default value of <code>GOROOT_BOOTSTRAP</code>
|
||||
is <code>$HOME/go1.4</code>.
|
||||
chain in <code>$HOME/go1.4</code>.
|
||||
(This path may be overridden by setting the <code>GOROOT_BOOTSTRAP</code>
|
||||
environment variable.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are many options for the bootstrap tool chain.
|
||||
After obtaining one, set <code>GOROOT_BOOTSTRAP</code> to the
|
||||
directory containing the unpacked tree.
|
||||
For example, <code>$GOROOT_BOOTSTRAP/bin/go</code> should be
|
||||
the <code>go</code> command binary for the bootstrap tool chain.
|
||||
Build the tools with Go version 1.4 or a point release (1.4.1, 1.4.2 etc.).
|
||||
Go 1.4 binaries can be found at <a href="/dl/">the downloads page</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To use a binary release as a bootstrap tool chain, see
|
||||
<a href="/dl/">the downloads page</a> or use any other
|
||||
packaged Go distribution.
|
||||
Download the zip or tarball of Go 1.4 for your platform and extract it to
|
||||
<code>$HOME/go1.4</code> (or your nominated <code>GOROOT_BOOTSTRAP</code>
|
||||
location).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To build a bootstrap tool chain from source, use
|
||||
either the git branch <code>release-branch.go1.4</code> or
|
||||
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20161024.tar.gz">go1.4-bootstrap-20161024.tar.gz</a>,
|
||||
which contains the Go 1.4 source code plus accumulated fixes
|
||||
to keep the tools running on newer operating systems.
|
||||
(Go 1.4 was the last distribution in which the tool chain was written in C.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To cross-compile a bootstrap tool chain from source, which is
|
||||
necessary on systems Go 1.4 did not target (for
|
||||
example, <code>linux/ppc64le</code>), install Go on a different system
|
||||
and run <a href="/src/bootstrap.bash">bootstrap.bash</a>.
|
||||
If you want to install Go 1.5 on a system that is not supported by Go 1.4 (such
|
||||
as <code>linux/ppc64</code> and <code>linux/mips64le</code>) you can either use
|
||||
<a href="/src/bootstrap.bash">bootstrap.bash</a> on a system that can bootstrap Go
|
||||
1.5 normally, or bootstrap with gccgo 5.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -166,9 +158,8 @@ and used as <code>GOROOT_BOOTSTRAP</code> to bootstrap a local build.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To use gccgo as the bootstrap toolchain, you need to arrange
|
||||
for <code>$GOROOT_BOOTSTRAP/bin/go</code> to be the go tool that comes
|
||||
as part of gccgo 5. For example on Ubuntu Vivid:
|
||||
To use gccgo, you need to arrange for <code>$GOROOT_BOOTSTRAP/bin/go</code> to be
|
||||
the go tool that comes as part of gccgo 5. For example on Ubuntu Vivid:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -212,7 +203,7 @@ To build without <code>cgo</code>, set the environment variable
|
||||
Change to the directory that will be its parent
|
||||
and make sure the <code>go</code> directory does not exist.
|
||||
Then clone the repository and check out the latest release tag
|
||||
(<code class="versionTag">go1.7.2</code>, for example):</p>
|
||||
(<code class="versionTag">go1.7</code>, for example):</p>
|
||||
|
||||
<pre>
|
||||
$ git clone https://go.googlesource.com/go
|
||||
@@ -400,7 +391,7 @@ New releases are announced on the
|
||||
<a href="//groups.google.com/group/golang-announce">golang-announce</a>
|
||||
mailing list.
|
||||
Each announcement mentions the latest release tag, for instance,
|
||||
<code class="versionTag">go1.7.2</code>.
|
||||
<code class="versionTag">go1.7</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -455,7 +446,7 @@ These default to the values of <code>$GOHOSTOS</code> and
|
||||
|
||||
<p>
|
||||
Choices for <code>$GOOS</code> are
|
||||
<code>darwin</code> (Mac OS X 10.8 and above and iOS), <code>dragonfly</code>, <code>freebsd</code>,
|
||||
<code>darwin</code> (Mac OS X 10.7 and above and iOS), <code>dragonfly</code>, <code>freebsd</code>,
|
||||
<code>linux</code>, <code>netbsd</code>, <code>openbsd</code>,
|
||||
<code>plan9</code>, <code>solaris</code> and <code>windows</code>.
|
||||
Choices for <code>$GOARCH</code> are
|
||||
|
||||
@@ -49,12 +49,12 @@ If your OS or architecture is not on the list, you may be able to
|
||||
<tr><td colspan="3"><hr></td></tr>
|
||||
<tr><td>FreeBSD 8-STABLE or later</td> <td>amd64</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</td></tr>
|
||||
<tr><td>Mac OS X 10.8 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
||||
<tr><td>Mac OS X 10.7 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
||||
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<sup>†</sup>A C compiler is required only if you plan to use
|
||||
<sup>†</sup><code>gcc</code> is required only if you plan to use
|
||||
<a href="/cmd/cgo">cgo</a>.<br/>
|
||||
<sup>‡</sup>You only need to install the command line tools for
|
||||
<a href="http://developer.apple.com/Xcode/">Xcode</a>. If you have already
|
||||
|
||||
BIN
favicon.ico
BIN
favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -8,8 +8,8 @@
|
||||
# Consult http://www.iana.org/time-zones for the latest versions.
|
||||
|
||||
# Versions to use.
|
||||
CODE=2016i
|
||||
DATA=2016i
|
||||
CODE=2016f
|
||||
DATA=2016f
|
||||
|
||||
set -e
|
||||
rm -rf work
|
||||
|
||||
Binary file not shown.
@@ -1,17 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// Issue 16591: Test that we detect an invalid call that was being
|
||||
// hidden by a type conversion inserted by cgo checking.
|
||||
|
||||
package p
|
||||
|
||||
// void f(int** p) { }
|
||||
import "C"
|
||||
|
||||
type x *C.int
|
||||
|
||||
func F(p *x) {
|
||||
C.f(p) // ERROR HERE
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// Test that C.malloc does not return nil.
|
||||
|
||||
package main
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var size C.size_t
|
||||
size--
|
||||
|
||||
// The Dragonfly libc succeeds when asked to allocate
|
||||
// 0xffffffffffffffff bytes, so pass a different value that
|
||||
// causes it to fail.
|
||||
if runtime.GOOS == "dragonfly" {
|
||||
size = C.size_t(0x7fffffff << (32 * (^uintptr(0) >> 63)))
|
||||
}
|
||||
|
||||
p := C.malloc(size)
|
||||
if p == nil {
|
||||
fmt.Println("malloc: C.malloc returned nil")
|
||||
// Just exit normally--the test script expects this
|
||||
// program to crash, so exiting normally indicates failure.
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,6 @@ check issue13423.go
|
||||
expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulonglong C.complexfloat C.complexdouble
|
||||
check issue13830.go
|
||||
check issue16116.go
|
||||
check issue16591.go
|
||||
|
||||
if ! go build issue14669.go; then
|
||||
exit 1
|
||||
@@ -59,15 +58,5 @@ if ! go run ptr.go; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The malloc.go test should crash.
|
||||
rm -f malloc.out
|
||||
if go run malloc.go >malloc.out 2>&1; then
|
||||
echo '`go run malloc.go` succeeded unexpectedly'
|
||||
cat malloc.out
|
||||
rm -f malloc.out
|
||||
exit 1
|
||||
fi
|
||||
rm -f malloc.out
|
||||
|
||||
rm -rf errs _obj
|
||||
exit 0
|
||||
|
||||
@@ -7,11 +7,6 @@
|
||||
package cgotest
|
||||
|
||||
// #include <stdlib.h>
|
||||
//
|
||||
// // Test for issue 17723.
|
||||
// typedef char *cstring_pointer;
|
||||
// static void cstring_pointer_fun(cstring_pointer dummy) { }
|
||||
//
|
||||
// const char *api_hello = "hello!";
|
||||
import "C"
|
||||
import "unsafe"
|
||||
@@ -26,5 +21,4 @@ func testAPI() {
|
||||
var b []byte
|
||||
b = C.GoBytes(unsafe.Pointer(C.api_hello), C.int(6))
|
||||
_, _ = s, b
|
||||
C.cstring_pointer_fun(nil)
|
||||
}
|
||||
|
||||
@@ -162,6 +162,3 @@ func testUnsignedInt(t *testing.T) {
|
||||
func sliceOperands(array [2000]int) {
|
||||
_ = array[C.KILO:C.KILO:C.KILO] // no type error
|
||||
}
|
||||
|
||||
// set in cgo_thread_lock.go init
|
||||
var testThreadLockFunc = func(*testing.T) {}
|
||||
|
||||
@@ -186,7 +186,6 @@ func testCallbackCallers(t *testing.T) {
|
||||
"runtime.asmcgocall",
|
||||
"runtime.cgocall",
|
||||
"test._Cfunc_callback",
|
||||
"test.nestedCall.func1",
|
||||
"test.nestedCall",
|
||||
"test.testCallbackCallers",
|
||||
"test.TestCallbackCallers",
|
||||
|
||||
@@ -70,9 +70,5 @@ func Test12030(t *testing.T) { test12030(t) }
|
||||
func TestGCC68255(t *testing.T) { testGCC68255(t) }
|
||||
func TestCallGoWithString(t *testing.T) { testCallGoWithString(t) }
|
||||
func Test14838(t *testing.T) { test14838(t) }
|
||||
func Test8756(t *testing.T) { test8756(t) }
|
||||
func Test17065(t *testing.T) { test17065(t) }
|
||||
func TestThreadLock(t *testing.T) { testThreadLockFunc(t) }
|
||||
func TestCheckConst(t *testing.T) { testCheckConst(t) }
|
||||
|
||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// +build linux,freebsd,openbsd
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
void Gosched(void);
|
||||
static int Ctid(void) { Gosched(); return syscall(SYS_gettid); }
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
//export Gosched
|
||||
func Gosched() {
|
||||
runtime.Gosched()
|
||||
}
|
||||
|
||||
func init() {
|
||||
testThreadLockFunc = testThreadLock
|
||||
}
|
||||
|
||||
func testThreadLock(t *testing.T) {
|
||||
stop := make(chan int)
|
||||
go func() {
|
||||
// We need the G continue running,
|
||||
// so the M has a chance to run this G.
|
||||
for {
|
||||
select {
|
||||
case <-stop:
|
||||
return
|
||||
case <-time.After(time.Millisecond * 100):
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer close(stop)
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
if C.int(syscall.Gettid()) != C.Ctid() {
|
||||
t.Fatalf("cgo has not locked OS thread")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// Test a constant in conjunction with pointer checking.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CheckConstVal 0
|
||||
|
||||
typedef struct {
|
||||
int *p;
|
||||
} CheckConstStruct;
|
||||
|
||||
static void CheckConstFunc(CheckConstStruct *p, int e) {
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func testCheckConst(t *testing.T) {
|
||||
// The test is that this compiles successfully.
|
||||
p := C.malloc(C.size_t(unsafe.Sizeof(C.int(0))))
|
||||
defer C.free(p)
|
||||
C.CheckConstFunc(&C.CheckConstStruct{(*C.int)(p)}, C.CheckConstVal)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
struct {
|
||||
float x;
|
||||
_Complex float y;
|
||||
} cplxAlign = { 3.14, 2.17 };
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestComplexAlign(t *testing.T) {
|
||||
if C.cplxAlign.x != 3.14 {
|
||||
t.Errorf("got %v, expected 3.14", C.cplxAlign.x)
|
||||
}
|
||||
if C.cplxAlign.y != 2.17 {
|
||||
t.Errorf("got %v, expected 2.17", C.cplxAlign.y)
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
// Test that C symbols larger than a page play nicely with the race detector.
|
||||
// See issue 17065.
|
||||
|
||||
int ii[65537];
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var sink C.int
|
||||
|
||||
func test17065(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
t.Skip("broken on darwin; issue 17065")
|
||||
}
|
||||
for i := range C.ii {
|
||||
sink = C.ii[i]
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lm
|
||||
#include <math.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"./issue8756"
|
||||
)
|
||||
|
||||
func test8756(t *testing.T) {
|
||||
issue8756.Pow()
|
||||
C.pow(1, 2)
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package issue8756
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lm
|
||||
#include <math.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func Pow() {
|
||||
C.pow(1, 2)
|
||||
}
|
||||
@@ -6,7 +6,6 @@ package carchive_test
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"debug/elf"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -35,9 +34,13 @@ var GOOS, GOARCH string
|
||||
var libgodir string
|
||||
|
||||
func init() {
|
||||
bin = []string{"./testp"}
|
||||
GOOS = goEnv("GOOS")
|
||||
GOARCH = goEnv("GOARCH")
|
||||
bin = cmdToRun("./testp")
|
||||
execScript := "go_" + GOOS + "_" + GOARCH + "_exec"
|
||||
if executor, err := exec.LookPath(execScript); err == nil {
|
||||
bin = []string{executor, "./testp"}
|
||||
}
|
||||
|
||||
ccOut := goEnv("CC")
|
||||
cc = []string{string(ccOut)}
|
||||
@@ -81,13 +84,8 @@ func init() {
|
||||
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
|
||||
}
|
||||
libgodir = GOOS + "_" + GOARCH
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
if GOARCH == "arm" || GOARCH == "arm64" {
|
||||
libgodir += "_shared"
|
||||
}
|
||||
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||
libgodir += "_shared"
|
||||
if GOOS == "darwin" && (GOARCH == "arm" || GOARCH == "arm64") {
|
||||
libgodir = GOOS + "_" + GOARCH + "_shared"
|
||||
}
|
||||
cc = append(cc, "-I", filepath.Join("pkg", libgodir))
|
||||
|
||||
@@ -122,62 +120,81 @@ func goEnv(key string) string {
|
||||
return strings.TrimSpace(string(out))
|
||||
}
|
||||
|
||||
func cmdToRun(name string) []string {
|
||||
execScript := "go_" + goEnv("GOOS") + "_" + goEnv("GOARCH") + "_exec"
|
||||
executor, err := exec.LookPath(execScript)
|
||||
if err != nil {
|
||||
return []string{name}
|
||||
}
|
||||
return []string{executor, name}
|
||||
}
|
||||
|
||||
func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
||||
cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
|
||||
cmd.Env = gopathEnv
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
os.Remove(libgoa)
|
||||
os.Remove(libgoh)
|
||||
}()
|
||||
|
||||
ccArgs := append(cc, "-o", exe, "main.c")
|
||||
func compilemain(t *testing.T, libgo string) {
|
||||
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main.c")
|
||||
if GOOS == "windows" {
|
||||
ccArgs = append(ccArgs, "main_windows.c", libgoa, "-lntdll", "-lws2_32", "-lwinmm")
|
||||
ccArgs = append(ccArgs, "main_windows.c", libgo, "-lntdll", "-lws2_32", "-lwinmm")
|
||||
} else {
|
||||
ccArgs = append(ccArgs, "main_unix.c", libgoa)
|
||||
ccArgs = append(ccArgs, "main_unix.c", libgo)
|
||||
}
|
||||
t.Log(ccArgs)
|
||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(exe)
|
||||
|
||||
binArgs := append(cmdToRun(exe), "arg1", "arg2")
|
||||
if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
|
||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstall(t *testing.T) {
|
||||
defer os.RemoveAll("pkg")
|
||||
defer func() {
|
||||
os.Remove("libgo.a")
|
||||
os.Remove("libgo.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll("pkg")
|
||||
}()
|
||||
|
||||
testInstall(t, "./testp1"+exeSuffix,
|
||||
filepath.Join("pkg", libgodir, "libgo.a"),
|
||||
filepath.Join("pkg", libgodir, "libgo.h"),
|
||||
"go", "install", "-buildmode=c-archive", "libgo")
|
||||
cmd := exec.Command("go", "install", "-buildmode=c-archive", "libgo")
|
||||
cmd.Env = gopathEnv
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
compilemain(t, filepath.Join("pkg", libgodir, "libgo.a"))
|
||||
|
||||
binArgs := append(bin, "arg1", "arg2")
|
||||
if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
os.Remove("libgo.a")
|
||||
os.Remove("libgo.h")
|
||||
os.Remove("testp")
|
||||
|
||||
// Test building libgo other than installing it.
|
||||
// Header files are now present.
|
||||
testInstall(t, "./testp2"+exeSuffix, "libgo.a", "libgo.h",
|
||||
"go", "build", "-buildmode=c-archive", filepath.Join("src", "libgo", "libgo.go"))
|
||||
cmd = exec.Command("go", "build", "-buildmode=c-archive", filepath.Join("src", "libgo", "libgo.go"))
|
||||
cmd.Env = gopathEnv
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testInstall(t, "./testp3"+exeSuffix, "libgo.a", "libgo.h",
|
||||
"go", "build", "-buildmode=c-archive", "-o", "libgo.a", "libgo")
|
||||
compilemain(t, "libgo.a")
|
||||
|
||||
if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
os.Remove("libgo.a")
|
||||
os.Remove("libgo.h")
|
||||
os.Remove("testp")
|
||||
|
||||
cmd = exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo.a", "libgo")
|
||||
cmd.Env = gopathEnv
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
compilemain(t, "libgo.a")
|
||||
|
||||
if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEarlySignalHandler(t *testing.T) {
|
||||
@@ -470,71 +487,3 @@ func TestExtar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPIE(t *testing.T) {
|
||||
switch GOOS {
|
||||
case "windows", "darwin", "plan9":
|
||||
t.Skipf("skipping PIE test on %s", GOOS)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("testp" + exeSuffix)
|
||||
os.RemoveAll("pkg")
|
||||
}()
|
||||
|
||||
cmd := exec.Command("go", "install", "-buildmode=c-archive", "libgo")
|
||||
cmd.Env = gopathEnv
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join("pkg", libgodir, "libgo.a"))
|
||||
if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
binArgs := append(bin, "arg1", "arg2")
|
||||
if out, err := exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
f, err := elf.Open("testp" + exeSuffix)
|
||||
if err != nil {
|
||||
t.Fatal("elf.Open failed: ", err)
|
||||
}
|
||||
defer f.Close()
|
||||
if hasDynTag(t, f, elf.DT_TEXTREL) {
|
||||
t.Errorf("%s has DT_TEXTREL flag", "testp"+exeSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool {
|
||||
ds := f.SectionByType(elf.SHT_DYNAMIC)
|
||||
if ds == nil {
|
||||
t.Error("no SHT_DYNAMIC section")
|
||||
return false
|
||||
}
|
||||
d, err := ds.Data()
|
||||
if err != nil {
|
||||
t.Errorf("can't read SHT_DYNAMIC contents: %v", err)
|
||||
return false
|
||||
}
|
||||
for len(d) > 0 {
|
||||
var t elf.DynTag
|
||||
switch f.Class {
|
||||
case elf.ELFCLASS32:
|
||||
t = elf.DynTag(f.ByteOrder.Uint32(d[:4]))
|
||||
d = d[8:]
|
||||
case elf.ELFCLASS64:
|
||||
t = elf.DynTag(f.ByteOrder.Uint64(d[:8]))
|
||||
d = d[16:]
|
||||
}
|
||||
if t == tag {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -7,10 +7,8 @@
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
@@ -48,22 +46,11 @@ static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
|
||||
static jmp_buf jmp;
|
||||
static char* nullPointer;
|
||||
|
||||
// An arbitrary function which requires proper stack alignment; see
|
||||
// http://golang.org/issue/17641.
|
||||
static void callWithVarargs(void* dummy, ...) {
|
||||
va_list args;
|
||||
va_start(args, dummy);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// Signal handler for SIGSEGV on a C thread.
|
||||
static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
|
||||
sigset_t mask;
|
||||
int i;
|
||||
|
||||
// Call an arbitrary function that requires the stack to be properly aligned.
|
||||
callWithVarargs("dummy arg", 3.1415);
|
||||
|
||||
if (sigemptyset(&mask) < 0) {
|
||||
die("sigemptyset");
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ FILE_PREFIXES="anonunion issue8478"
|
||||
RM=
|
||||
for FP in $FILE_PREFIXES
|
||||
do
|
||||
go tool cgo -godefs -srcdir . ${FP}.go > ${FP}_defs.go
|
||||
go tool cgo -godefs ${FP}.go > ${FP}_defs.go
|
||||
RM="${RM} ${FP}_defs.go"
|
||||
done
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package common
|
||||
|
||||
var X int
|
||||
|
||||
func init() {
|
||||
X = 3
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
|
||||
"common"
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.X *= 5
|
||||
}
|
||||
|
||||
func main() {
|
||||
if got, want := common.X, 3*5; got != want {
|
||||
log.Fatalf("before plugin load common.X=%d, want %d", got, want)
|
||||
}
|
||||
|
||||
p, err := plugin.Open("plugin1.so")
|
||||
if err != nil {
|
||||
log.Fatalf("plugin.Open failed: %v", err)
|
||||
}
|
||||
|
||||
const wantX = 3 * 5 * 7
|
||||
if got := common.X; got != wantX {
|
||||
log.Fatalf("after plugin load common.X=%d, want %d", got, wantX)
|
||||
}
|
||||
|
||||
seven, err := p.Lookup("Seven")
|
||||
if err != nil {
|
||||
log.Fatalf(`Lookup("Seven") failed: %v`, err)
|
||||
}
|
||||
if got, want := *seven.(*int), 7; got != want {
|
||||
log.Fatalf("plugin1.Seven=%d, want %d", got, want)
|
||||
}
|
||||
|
||||
readFunc, err := p.Lookup("ReadCommonX")
|
||||
if err != nil {
|
||||
log.Fatalf(`plugin1.Lookup("ReadCommonX") failed: %v`, err)
|
||||
}
|
||||
if got := readFunc.(func() int)(); got != wantX {
|
||||
log.Fatalf("plugin1.ReadCommonX()=%d, want %d", got, wantX)
|
||||
}
|
||||
|
||||
// sub/plugin1.so is a different plugin with the same name as
|
||||
// the already loaded plugin. It also depends on common. Test
|
||||
// that we can load the different plugin, it is actually
|
||||
// different, and that it sees the same common package.
|
||||
subpPath, err := filepath.Abs("sub/plugin1.so")
|
||||
if err != nil {
|
||||
log.Fatalf("filepath.Abs(%q) failed: %v", subpPath, err)
|
||||
}
|
||||
subp, err := plugin.Open(subpPath)
|
||||
if err != nil {
|
||||
log.Fatalf("plugin.Open(%q) failed: %v", subpPath, err)
|
||||
}
|
||||
|
||||
funcVar, err := subp.Lookup("FuncVar")
|
||||
if err != nil {
|
||||
log.Fatalf(`sub/plugin1.Lookup("FuncVar") failed: %v`, err)
|
||||
}
|
||||
called := false
|
||||
*funcVar.(*func()) = func() {
|
||||
called = true
|
||||
}
|
||||
|
||||
readFunc, err = subp.Lookup("ReadCommonX")
|
||||
if err != nil {
|
||||
log.Fatalf(`sub/plugin1.Lookup("ReadCommonX") failed: %v`, err)
|
||||
}
|
||||
if got := readFunc.(func() int)(); got != wantX {
|
||||
log.Fatalf("sub/plugin1.ReadCommonX()=%d, want %d", got, wantX)
|
||||
}
|
||||
if !called {
|
||||
log.Fatal("calling ReadCommonX did not call FuncVar")
|
||||
}
|
||||
|
||||
subf, err := subp.Lookup("F")
|
||||
if err != nil {
|
||||
log.Fatalf(`sub/plugin1.Lookup("F") failed: %v`, err)
|
||||
}
|
||||
if gotf := subf.(func() int)(); gotf != 17 {
|
||||
log.Fatalf(`sub/plugin1.F()=%d, want 17`, gotf)
|
||||
}
|
||||
f, err := p.Lookup("F")
|
||||
if err != nil {
|
||||
log.Fatalf(`plugin1.Lookup("F") failed: %v`, err)
|
||||
}
|
||||
if gotf := f.(func() int)(); gotf != 3 {
|
||||
log.Fatalf(`plugin1.F()=%d, want 17`, gotf)
|
||||
}
|
||||
|
||||
// plugin2 has no exported symbols, only an init function.
|
||||
if _, err := plugin.Open("plugin2.so"); err != nil {
|
||||
log.Fatalf("plugin.Open failed: %v", err)
|
||||
}
|
||||
if got, want := common.X, 2; got != want {
|
||||
log.Fatalf("after loading plugin2, common.X=%d, want %d", got, want)
|
||||
}
|
||||
|
||||
fmt.Println("PASS")
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// // No C code required.
|
||||
import "C"
|
||||
|
||||
import "common"
|
||||
|
||||
func F() int { return 3 }
|
||||
|
||||
func ReadCommonX() int {
|
||||
return common.X
|
||||
}
|
||||
|
||||
var Seven int
|
||||
|
||||
func init() {
|
||||
Seven = 7
|
||||
common.X *= Seven
|
||||
}
|
||||
|
||||
func main() {
|
||||
panic("plugin1.main called")
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// // No C code required.
|
||||
import "C"
|
||||
|
||||
import "common"
|
||||
|
||||
func init() {
|
||||
common.X = 2
|
||||
}
|
||||
|
||||
func main() {
|
||||
panic("plugin1.main called")
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// // No C code required.
|
||||
import "C"
|
||||
|
||||
import "common"
|
||||
|
||||
func F() int { return 17 }
|
||||
|
||||
var FuncVar = func() {}
|
||||
|
||||
func ReadCommonX() int {
|
||||
FuncVar()
|
||||
return common.X
|
||||
}
|
||||
|
||||
func main() {
|
||||
panic("plugin1.main called")
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2016 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.
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -f src/host/host.go ]; then
|
||||
cwd=$(pwd)
|
||||
echo "misc/cgo/testplugin/test.bash is running in $cwd" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
goos=$(go env GOOS)
|
||||
goarch=$(go env GOARCH)
|
||||
|
||||
function cleanup() {
|
||||
rm -rf plugin1.so host pkg sub
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
rm -rf pkg sub
|
||||
mkdir sub
|
||||
|
||||
GOPATH=$(pwd) go build -buildmode=plugin plugin1
|
||||
GOPATH=$(pwd) go build -buildmode=plugin plugin2
|
||||
GOPATH=$(pwd) go build -buildmode=plugin -o=sub/plugin1.so sub/plugin1
|
||||
GOPATH=$(pwd) go build host
|
||||
|
||||
LD_LIBRARY_PATH=$(pwd) ./host
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// Using reflect to set a value was not seen by msan.
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
extern void Go1(int*);
|
||||
extern void Go2(char*);
|
||||
|
||||
// Use weak as a hack to permit defining a function even though we use export.
|
||||
void C1() __attribute__ ((weak));
|
||||
void C2() __attribute__ ((weak));
|
||||
|
||||
void C1() {
|
||||
int i;
|
||||
Go1(&i);
|
||||
if (i != 42) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void C2() {
|
||||
char a[2];
|
||||
a[1] = 42;
|
||||
Go2(a);
|
||||
if (a[0] != 42) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//export Go1
|
||||
func Go1(p *C.int) {
|
||||
reflect.ValueOf(p).Elem().Set(reflect.ValueOf(C.int(42)))
|
||||
}
|
||||
|
||||
//export Go2
|
||||
func Go2(p *C.char) {
|
||||
a := (*[2]byte)(unsafe.Pointer(p))
|
||||
reflect.Copy(reflect.ValueOf(a[:1]), reflect.ValueOf(a[1:]))
|
||||
}
|
||||
|
||||
func main() {
|
||||
C.C1()
|
||||
C.C2()
|
||||
}
|
||||
@@ -15,11 +15,6 @@ if test -x "$(type -p clang)"; then
|
||||
fi
|
||||
export CC
|
||||
|
||||
if [ "$(sysctl -n vm.overcommit_memory)" = 2 ]; then
|
||||
echo "skipping msan/tsan tests: vm.overcommit_memory=2" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
msan=yes
|
||||
|
||||
TMPDIR=${TMPDIR:-/tmp}
|
||||
@@ -93,11 +88,6 @@ if test "$msan" = "yes"; then
|
||||
status=1
|
||||
fi
|
||||
|
||||
if ! go run -msan msan5.go; then
|
||||
echo "FAIL: msan5"
|
||||
status=1
|
||||
fi
|
||||
|
||||
if go run -msan msan_fail.go 2>/dev/null; then
|
||||
echo "FAIL: msan_fail"
|
||||
status=1
|
||||
@@ -166,9 +156,6 @@ if test "$tsan" = "yes"; then
|
||||
|
||||
# This test requires rebuilding runtime/cgo with -fsanitize=thread.
|
||||
testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
||||
|
||||
# This test requires rebuilding runtime/cgo with -fsanitize=thread.
|
||||
testtsan tsan7.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// Setting an environment variable in a cgo program changes the C
|
||||
// environment. Test that this does not confuse the race detector.
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -fsanitize=thread
|
||||
#cgo LDFLAGS: -fsanitize=thread
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
f := func() {
|
||||
defer wg.Done()
|
||||
for i := 0; i < 100; i++ {
|
||||
time.Sleep(time.Microsecond)
|
||||
mu.Lock()
|
||||
s := fmt.Sprint(i)
|
||||
os.Setenv("TSAN_TEST"+s, s)
|
||||
mu.Unlock()
|
||||
}
|
||||
}
|
||||
wg.Add(2)
|
||||
go f()
|
||||
go f()
|
||||
wg.Wait()
|
||||
}
|
||||
@@ -43,7 +43,7 @@ func run(t *testing.T, msg string, args ...string) {
|
||||
}
|
||||
|
||||
// goCmd invokes the go tool with the installsuffix set up by TestMain. It calls
|
||||
// t.Fatalf if the command fails.
|
||||
// t.Errorf if the command fails.
|
||||
func goCmd(t *testing.T, args ...string) {
|
||||
newargs := []string{args[0], "-installsuffix=" + suffix}
|
||||
if testing.Verbose() {
|
||||
@@ -63,7 +63,7 @@ func goCmd(t *testing.T, args ...string) {
|
||||
}
|
||||
if err != nil {
|
||||
if t != nil {
|
||||
t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
|
||||
t.Errorf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
|
||||
} else {
|
||||
log.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, output)
|
||||
}
|
||||
@@ -97,9 +97,6 @@ func testMain(m *testing.M) (int, error) {
|
||||
if gorootInstallDir == "" {
|
||||
return 0, errors.New("could not create temporary directory after 10000 tries")
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ mkdir -p %s\n", gorootInstallDir)
|
||||
}
|
||||
defer os.RemoveAll(gorootInstallDir)
|
||||
|
||||
// Some tests need to edit the source in GOPATH, so copy this directory to a
|
||||
@@ -108,9 +105,6 @@ func testMain(m *testing.M) (int, error) {
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("TempDir failed: %v", err)
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ mkdir -p %s\n", scratchDir)
|
||||
}
|
||||
defer os.RemoveAll(scratchDir)
|
||||
err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
|
||||
scratchPath := filepath.Join(scratchDir, path)
|
||||
@@ -118,18 +112,12 @@ func testMain(m *testing.M) (int, error) {
|
||||
if path == "." {
|
||||
return nil
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ mkdir -p %s\n", scratchPath)
|
||||
}
|
||||
return os.Mkdir(scratchPath, info.Mode())
|
||||
} else {
|
||||
fromBytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ cp %s %s\n", path, scratchPath)
|
||||
}
|
||||
return ioutil.WriteFile(scratchPath, fromBytes, info.Mode())
|
||||
}
|
||||
})
|
||||
@@ -137,13 +125,7 @@ func testMain(m *testing.M) (int, error) {
|
||||
return 0, fmt.Errorf("walk failed: %v", err)
|
||||
}
|
||||
os.Setenv("GOPATH", scratchDir)
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ export GOPATH=%s\n", scratchDir)
|
||||
}
|
||||
myContext.GOPATH = scratchDir
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ cd %s\n", scratchDir)
|
||||
}
|
||||
os.Chdir(scratchDir)
|
||||
|
||||
// All tests depend on runtime being built into a shared library. Because
|
||||
@@ -394,14 +376,6 @@ func TestTrivialExecutable(t *testing.T) {
|
||||
AssertHasRPath(t, "./bin/trivial", gorootInstallDir)
|
||||
}
|
||||
|
||||
// Build a trivial program in PIE mode that links against the shared runtime and check it runs.
|
||||
func TestTrivialExecutablePIE(t *testing.T) {
|
||||
goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "trivial")
|
||||
run(t, "trivial executable", "./trivial.pie")
|
||||
AssertIsLinkedTo(t, "./trivial.pie", soname)
|
||||
AssertHasRPath(t, "./trivial.pie", gorootInstallDir)
|
||||
}
|
||||
|
||||
// Build an executable that uses cgo linked against the shared runtime and check it
|
||||
// runs.
|
||||
func TestCgoExecutable(t *testing.T) {
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
package depBase
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var V int = 1
|
||||
|
||||
var HasMask []string = []string{"hi"}
|
||||
@@ -18,10 +13,6 @@ type Dep struct {
|
||||
}
|
||||
|
||||
func (d *Dep) Method() int {
|
||||
// This code below causes various go.itab.* symbols to be generated in
|
||||
// the shared library. Similar code in ../exe/exe.go results in
|
||||
// exercising https://github.com/golang/go/issues/17594
|
||||
reflect.TypeOf(os.Stdout).Elem()
|
||||
return 10
|
||||
}
|
||||
|
||||
|
||||
@@ -2,17 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"depBase"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
defer depBase.ImplementedInAsm()
|
||||
// This code below causes various go.itab.* symbols to be generated in
|
||||
// the executable. Similar code in ../depBase/dep.go results in
|
||||
// exercising https://github.com/golang/go/issues/17594
|
||||
reflect.TypeOf(os.Stdout).Elem()
|
||||
runtime.GC()
|
||||
depBase.V = depBase.F() + 1
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ static void iohandler(int signum) {
|
||||
|
||||
static void* sigioThread(void* arg __attribute__ ((unused))) {
|
||||
raise(SIGIO);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sigioOnThread() {
|
||||
|
||||
@@ -48,10 +48,6 @@ go src=..
|
||||
x86asm
|
||||
testdata
|
||||
+
|
||||
ppc64
|
||||
ppc64asm
|
||||
testdata
|
||||
+
|
||||
archive
|
||||
tar
|
||||
testdata
|
||||
|
||||
@@ -30,10 +30,6 @@ if [ "$GOARM" != "7" ]; then
|
||||
echo "android only supports GOARM=7, got GOARM=$GOARM" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$GOARCH" = "" ]; then
|
||||
echo "GOARCH must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export CGO_ENABLED=1
|
||||
unset GOBIN
|
||||
@@ -47,12 +43,6 @@ GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH go build \
|
||||
-o ../bin/go_android_${GOARCH}_exec \
|
||||
../misc/android/go_android_exec.go
|
||||
|
||||
export pkgdir=$(dirname $(go list -f '{{.Target}}' runtime))
|
||||
if [ "$pkgdir" = "" ]; then
|
||||
echo "could not find android pkg dir" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export ANDROID_TEST_DIR=/tmp/androidtest-$$
|
||||
|
||||
function cleanup() {
|
||||
@@ -74,7 +64,15 @@ mkdir -p $FAKE_GOROOT/pkg
|
||||
cp -a "${GOROOT}/src" "${FAKE_GOROOT}/"
|
||||
cp -a "${GOROOT}/test" "${FAKE_GOROOT}/"
|
||||
cp -a "${GOROOT}/lib" "${FAKE_GOROOT}/"
|
||||
cp -a "${pkgdir}" "${FAKE_GOROOT}/pkg/"
|
||||
|
||||
# For android, the go tool will install the compiled package in
|
||||
# pkg/android_${GOARCH}_shared directory by default, not in
|
||||
# the usual pkg/${GOOS}_${GOARCH}. Some tests in src/go/* assume
|
||||
# the compiled packages were installed in the usual places.
|
||||
# Instead of reflecting this exception into the go/* packages,
|
||||
# we copy the compiled packages into the usual places.
|
||||
cp -a "${GOROOT}/pkg/android_${GOARCH}_shared" "${FAKE_GOROOT}/pkg/"
|
||||
mv "${FAKE_GOROOT}/pkg/android_${GOARCH}_shared" "${FAKE_GOROOT}/pkg/android_${GOARCH}"
|
||||
|
||||
echo '# Syncing test files to android device'
|
||||
adb shell mkdir -p /data/local/tmp/goroot
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
package tar
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -20,10 +21,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// BUG: Use of the Uid and Gid fields in Header could overflow on 32-bit
|
||||
// architectures. If a large value is encountered when decoding, the result
|
||||
// stored in Header will be the truncated version.
|
||||
|
||||
// Header type flags.
|
||||
const (
|
||||
TypeReg = '0' // regular file
|
||||
@@ -274,6 +271,28 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func isASCII(s string) bool {
|
||||
for _, c := range s {
|
||||
if c >= 0x80 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func toASCII(s string) string {
|
||||
if isASCII(s) {
|
||||
return s
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
for _, c := range s {
|
||||
if c < 0x80 {
|
||||
buf.WriteByte(byte(c))
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// isHeaderOnlyType checks if the given type flag is of the type that has no
|
||||
// data section even if a size is specified.
|
||||
func isHeaderOnlyType(flag byte) bool {
|
||||
|
||||
@@ -22,20 +22,22 @@ var (
|
||||
ErrHeader = errors.New("archive/tar: invalid tar header")
|
||||
)
|
||||
|
||||
const maxNanoSecondIntSize = 9
|
||||
|
||||
// A Reader provides sequential access to the contents of a tar archive.
|
||||
// A tar archive consists of a sequence of files.
|
||||
// The Next method advances to the next file in the archive (including the first),
|
||||
// and then it can be treated as an io.Reader to access the file's data.
|
||||
type Reader struct {
|
||||
r io.Reader
|
||||
err error
|
||||
pad int64 // amount of padding (ignored) after current file entry
|
||||
curr numBytesReader // reader for current file entry
|
||||
blk block // buffer to use as temporary local storage
|
||||
}
|
||||
|
||||
// err is a persistent error.
|
||||
// It is only the responsibility of every exported method of Reader to
|
||||
// ensure that this error is sticky.
|
||||
err error
|
||||
type parser struct {
|
||||
err error // Last error seen
|
||||
}
|
||||
|
||||
// A numBytesReader is an io.Reader with a numBytes method, returning the number
|
||||
@@ -106,12 +108,8 @@ func (tr *Reader) Next() (*Header, error) {
|
||||
if tr.err != nil {
|
||||
return nil, tr.err
|
||||
}
|
||||
hdr, err := tr.next()
|
||||
tr.err = err
|
||||
return hdr, err
|
||||
}
|
||||
|
||||
func (tr *Reader) next() (*Header, error) {
|
||||
var hdr *Header
|
||||
var extHdrs map[string]string
|
||||
|
||||
// Externally, Next iterates through the tar archive as if it is a series of
|
||||
@@ -121,29 +119,29 @@ func (tr *Reader) next() (*Header, error) {
|
||||
// one or more "header files" until it finds a "normal file".
|
||||
loop:
|
||||
for {
|
||||
if err := tr.skipUnread(); err != nil {
|
||||
return nil, err
|
||||
tr.err = tr.skipUnread()
|
||||
if tr.err != nil {
|
||||
return nil, tr.err
|
||||
}
|
||||
hdr, rawHdr, err := tr.readHeader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := tr.handleRegularFile(hdr); err != nil {
|
||||
return nil, err
|
||||
|
||||
hdr = tr.readHeader()
|
||||
if tr.err != nil {
|
||||
return nil, tr.err
|
||||
}
|
||||
|
||||
// Check for PAX/GNU special headers and files.
|
||||
switch hdr.Typeflag {
|
||||
case TypeXHeader:
|
||||
extHdrs, err = parsePAX(tr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
extHdrs, tr.err = parsePAX(tr)
|
||||
if tr.err != nil {
|
||||
return nil, tr.err
|
||||
}
|
||||
continue loop // This is a meta header affecting the next header
|
||||
case TypeGNULongName, TypeGNULongLink:
|
||||
realname, err := ioutil.ReadAll(tr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var realname []byte
|
||||
realname, tr.err = ioutil.ReadAll(tr)
|
||||
if tr.err != nil {
|
||||
return nil, tr.err
|
||||
}
|
||||
|
||||
// Convert GNU extensions to use PAX headers.
|
||||
@@ -158,73 +156,31 @@ loop:
|
||||
extHdrs[paxLinkpath] = p.parseString(realname)
|
||||
}
|
||||
if p.err != nil {
|
||||
return nil, p.err
|
||||
tr.err = p.err
|
||||
return nil, tr.err
|
||||
}
|
||||
continue loop // This is a meta header affecting the next header
|
||||
default:
|
||||
// The old GNU sparse format is handled here since it is technically
|
||||
// just a regular file with additional attributes.
|
||||
mergePAX(hdr, extHdrs)
|
||||
|
||||
if err := mergePAX(hdr, extHdrs); err != nil {
|
||||
// Check for a PAX format sparse file
|
||||
sp, err := tr.checkForGNUSparsePAXHeaders(hdr, extHdrs)
|
||||
if err != nil {
|
||||
tr.err = err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The extended headers may have updated the size.
|
||||
// Thus, setup the regFileReader again after merging PAX headers.
|
||||
if err := tr.handleRegularFile(hdr); err != nil {
|
||||
return nil, err
|
||||
if sp != nil {
|
||||
// Current file is a PAX format GNU sparse file.
|
||||
// Set the current file reader to a sparse file reader.
|
||||
tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size)
|
||||
if tr.err != nil {
|
||||
return nil, tr.err
|
||||
}
|
||||
}
|
||||
|
||||
// Sparse formats rely on being able to read from the logical data
|
||||
// section; there must be a preceding call to handleRegularFile.
|
||||
if err := tr.handleSparseFile(hdr, rawHdr, extHdrs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hdr, nil // This is a file, so stop
|
||||
break loop // This is a file, so stop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleRegularFile sets up the current file reader and padding such that it
|
||||
// can only read the following logical data section. It will properly handle
|
||||
// special headers that contain no data section.
|
||||
func (tr *Reader) handleRegularFile(hdr *Header) error {
|
||||
nb := hdr.Size
|
||||
if isHeaderOnlyType(hdr.Typeflag) {
|
||||
nb = 0
|
||||
}
|
||||
if nb < 0 {
|
||||
return ErrHeader
|
||||
}
|
||||
|
||||
tr.pad = -nb & (blockSize - 1) // blockSize is a power of two
|
||||
tr.curr = ®FileReader{r: tr.r, nb: nb}
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleSparseFile checks if the current file is a sparse format of any type
|
||||
// and sets the curr reader appropriately.
|
||||
func (tr *Reader) handleSparseFile(hdr *Header, rawHdr *block, extHdrs map[string]string) error {
|
||||
var sp []sparseEntry
|
||||
var err error
|
||||
if hdr.Typeflag == TypeGNUSparse {
|
||||
sp, err = tr.readOldGNUSparseMap(hdr, rawHdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
sp, err = tr.checkForGNUSparsePAXHeaders(hdr, extHdrs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If sp is non-nil, then this is a sparse file.
|
||||
// Note that it is possible for len(sp) to be zero.
|
||||
if sp != nil {
|
||||
tr.curr, err = newSparseFileReader(tr.curr, sp, hdr.Size)
|
||||
}
|
||||
return err
|
||||
return hdr, nil
|
||||
}
|
||||
|
||||
// checkForGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. If they are found, then
|
||||
@@ -263,13 +219,13 @@ func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]st
|
||||
hdr.Name = sparseName
|
||||
}
|
||||
if sparseSizeOk {
|
||||
realSize, err := strconv.ParseInt(sparseSize, 10, 64)
|
||||
realSize, err := strconv.ParseInt(sparseSize, 10, 0)
|
||||
if err != nil {
|
||||
return nil, ErrHeader
|
||||
}
|
||||
hdr.Size = realSize
|
||||
} else if sparseRealSizeOk {
|
||||
realSize, err := strconv.ParseInt(sparseRealSize, 10, 64)
|
||||
realSize, err := strconv.ParseInt(sparseRealSize, 10, 0)
|
||||
if err != nil {
|
||||
return nil, ErrHeader
|
||||
}
|
||||
@@ -293,32 +249,53 @@ func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]st
|
||||
// in the header struct overwrite those found in the header
|
||||
// struct with higher precision or longer values. Esp. useful
|
||||
// for name and linkname fields.
|
||||
func mergePAX(hdr *Header, headers map[string]string) (err error) {
|
||||
var id64 int64
|
||||
func mergePAX(hdr *Header, headers map[string]string) error {
|
||||
for k, v := range headers {
|
||||
switch k {
|
||||
case paxPath:
|
||||
hdr.Name = v
|
||||
case paxLinkpath:
|
||||
hdr.Linkname = v
|
||||
case paxUname:
|
||||
hdr.Uname = v
|
||||
case paxGname:
|
||||
hdr.Gname = v
|
||||
case paxUname:
|
||||
hdr.Uname = v
|
||||
case paxUid:
|
||||
id64, err = strconv.ParseInt(v, 10, 64)
|
||||
hdr.Uid = int(id64) // Integer overflow possible
|
||||
uid, err := strconv.ParseInt(v, 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr.Uid = int(uid)
|
||||
case paxGid:
|
||||
id64, err = strconv.ParseInt(v, 10, 64)
|
||||
hdr.Gid = int(id64) // Integer overflow possible
|
||||
gid, err := strconv.ParseInt(v, 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr.Gid = int(gid)
|
||||
case paxAtime:
|
||||
hdr.AccessTime, err = parsePAXTime(v)
|
||||
t, err := parsePAXTime(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr.AccessTime = t
|
||||
case paxMtime:
|
||||
hdr.ModTime, err = parsePAXTime(v)
|
||||
t, err := parsePAXTime(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr.ModTime = t
|
||||
case paxCtime:
|
||||
hdr.ChangeTime, err = parsePAXTime(v)
|
||||
t, err := parsePAXTime(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr.ChangeTime = t
|
||||
case paxSize:
|
||||
hdr.Size, err = strconv.ParseInt(v, 10, 64)
|
||||
size, err := strconv.ParseInt(v, 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr.Size = size
|
||||
default:
|
||||
if strings.HasPrefix(k, paxXattr) {
|
||||
if hdr.Xattrs == nil {
|
||||
@@ -327,13 +304,46 @@ func mergePAX(hdr *Header, headers map[string]string) (err error) {
|
||||
hdr.Xattrs[k[len(paxXattr):]] = v
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return ErrHeader
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parsePAXTime takes a string of the form %d.%d as described in
|
||||
// the PAX specification.
|
||||
func parsePAXTime(t string) (time.Time, error) {
|
||||
buf := []byte(t)
|
||||
pos := bytes.IndexByte(buf, '.')
|
||||
var seconds, nanoseconds int64
|
||||
var err error
|
||||
if pos == -1 {
|
||||
seconds, err = strconv.ParseInt(t, 10, 0)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
} else {
|
||||
seconds, err = strconv.ParseInt(string(buf[:pos]), 10, 0)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
nanoBuf := string(buf[pos+1:])
|
||||
// Pad as needed before converting to a decimal.
|
||||
// For example .030 -> .030000000 -> 30000000 nanoseconds
|
||||
if len(nanoBuf) < maxNanoSecondIntSize {
|
||||
// Right pad
|
||||
nanoBuf += strings.Repeat("0", maxNanoSecondIntSize-len(nanoBuf))
|
||||
} else if len(nanoBuf) > maxNanoSecondIntSize {
|
||||
// Right truncate
|
||||
nanoBuf = nanoBuf[:maxNanoSecondIntSize]
|
||||
}
|
||||
nanoseconds, err = strconv.ParseInt(nanoBuf, 10, 0)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
}
|
||||
ts := time.Unix(seconds, nanoseconds)
|
||||
return ts, nil
|
||||
}
|
||||
|
||||
// parsePAX parses PAX headers.
|
||||
// If an extended header (type 'x') is invalid, ErrHeader is returned
|
||||
func parsePAX(r io.Reader) (map[string]string, error) {
|
||||
@@ -344,11 +354,12 @@ func parsePAX(r io.Reader) (map[string]string, error) {
|
||||
sbuf := string(buf)
|
||||
|
||||
// For GNU PAX sparse format 0.0 support.
|
||||
// This function transforms the sparse format 0.0 headers into format 0.1
|
||||
// headers since 0.0 headers were not PAX compliant.
|
||||
var sparseMap []string
|
||||
// This function transforms the sparse format 0.0 headers into sparse format 0.1 headers.
|
||||
var sparseMap bytes.Buffer
|
||||
|
||||
extHdrs := make(map[string]string)
|
||||
headers := make(map[string]string)
|
||||
// Each record is constructed as
|
||||
// "%d %s=%s\n", length, keyword, value
|
||||
for len(sbuf) > 0 {
|
||||
key, value, residual, err := parsePAXRecord(sbuf)
|
||||
if err != nil {
|
||||
@@ -356,29 +367,127 @@ func parsePAX(r io.Reader) (map[string]string, error) {
|
||||
}
|
||||
sbuf = residual
|
||||
|
||||
switch key {
|
||||
case paxGNUSparseOffset, paxGNUSparseNumBytes:
|
||||
// Validate sparse header order and value.
|
||||
if (len(sparseMap)%2 == 0 && key != paxGNUSparseOffset) ||
|
||||
(len(sparseMap)%2 == 1 && key != paxGNUSparseNumBytes) ||
|
||||
strings.Contains(value, ",") {
|
||||
return nil, ErrHeader
|
||||
}
|
||||
sparseMap = append(sparseMap, value)
|
||||
default:
|
||||
// According to PAX specification, a value is stored only if it is
|
||||
// non-empty. Otherwise, the key is deleted.
|
||||
if len(value) > 0 {
|
||||
extHdrs[key] = value
|
||||
} else {
|
||||
delete(extHdrs, key)
|
||||
}
|
||||
keyStr := key
|
||||
if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes {
|
||||
// GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map.
|
||||
sparseMap.WriteString(value)
|
||||
sparseMap.Write([]byte{','})
|
||||
} else {
|
||||
// Normal key. Set the value in the headers map.
|
||||
headers[keyStr] = value
|
||||
}
|
||||
}
|
||||
if len(sparseMap) > 0 {
|
||||
extHdrs[paxGNUSparseMap] = strings.Join(sparseMap, ",")
|
||||
if sparseMap.Len() != 0 {
|
||||
// Add sparse info to headers, chopping off the extra comma
|
||||
sparseMap.Truncate(sparseMap.Len() - 1)
|
||||
headers[paxGNUSparseMap] = sparseMap.String()
|
||||
}
|
||||
return extHdrs, nil
|
||||
return headers, nil
|
||||
}
|
||||
|
||||
// parsePAXRecord parses the input PAX record string into a key-value pair.
|
||||
// If parsing is successful, it will slice off the currently read record and
|
||||
// return the remainder as r.
|
||||
//
|
||||
// A PAX record is of the following form:
|
||||
// "%d %s=%s\n" % (size, key, value)
|
||||
func parsePAXRecord(s string) (k, v, r string, err error) {
|
||||
// The size field ends at the first space.
|
||||
sp := strings.IndexByte(s, ' ')
|
||||
if sp == -1 {
|
||||
return "", "", s, ErrHeader
|
||||
}
|
||||
|
||||
// Parse the first token as a decimal integer.
|
||||
n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int
|
||||
if perr != nil || n < 5 || int64(len(s)) < n {
|
||||
return "", "", s, ErrHeader
|
||||
}
|
||||
|
||||
// Extract everything between the space and the final newline.
|
||||
rec, nl, rem := s[sp+1:n-1], s[n-1:n], s[n:]
|
||||
if nl != "\n" {
|
||||
return "", "", s, ErrHeader
|
||||
}
|
||||
|
||||
// The first equals separates the key from the value.
|
||||
eq := strings.IndexByte(rec, '=')
|
||||
if eq == -1 {
|
||||
return "", "", s, ErrHeader
|
||||
}
|
||||
return rec[:eq], rec[eq+1:], rem, nil
|
||||
}
|
||||
|
||||
// parseString parses bytes as a NUL-terminated C-style string.
|
||||
// If a NUL byte is not found then the whole slice is returned as a string.
|
||||
func (*parser) parseString(b []byte) string {
|
||||
n := 0
|
||||
for n < len(b) && b[n] != 0 {
|
||||
n++
|
||||
}
|
||||
return string(b[0:n])
|
||||
}
|
||||
|
||||
// parseNumeric parses the input as being encoded in either base-256 or octal.
|
||||
// This function may return negative numbers.
|
||||
// If parsing fails or an integer overflow occurs, err will be set.
|
||||
func (p *parser) parseNumeric(b []byte) int64 {
|
||||
// Check for base-256 (binary) format first.
|
||||
// If the first bit is set, then all following bits constitute a two's
|
||||
// complement encoded number in big-endian byte order.
|
||||
if len(b) > 0 && b[0]&0x80 != 0 {
|
||||
// Handling negative numbers relies on the following identity:
|
||||
// -a-1 == ^a
|
||||
//
|
||||
// If the number is negative, we use an inversion mask to invert the
|
||||
// data bytes and treat the value as an unsigned number.
|
||||
var inv byte // 0x00 if positive or zero, 0xff if negative
|
||||
if b[0]&0x40 != 0 {
|
||||
inv = 0xff
|
||||
}
|
||||
|
||||
var x uint64
|
||||
for i, c := range b {
|
||||
c ^= inv // Inverts c only if inv is 0xff, otherwise does nothing
|
||||
if i == 0 {
|
||||
c &= 0x7f // Ignore signal bit in first byte
|
||||
}
|
||||
if (x >> 56) > 0 {
|
||||
p.err = ErrHeader // Integer overflow
|
||||
return 0
|
||||
}
|
||||
x = x<<8 | uint64(c)
|
||||
}
|
||||
if (x >> 63) > 0 {
|
||||
p.err = ErrHeader // Integer overflow
|
||||
return 0
|
||||
}
|
||||
if inv == 0xff {
|
||||
return ^int64(x)
|
||||
}
|
||||
return int64(x)
|
||||
}
|
||||
|
||||
// Normal case is base-8 (octal) format.
|
||||
return p.parseOctal(b)
|
||||
}
|
||||
|
||||
func (p *parser) parseOctal(b []byte) int64 {
|
||||
// Because unused fields are filled with NULs, we need
|
||||
// to skip leading NULs. Fields may also be padded with
|
||||
// spaces or NULs.
|
||||
// So we remove leading and trailing NULs and spaces to
|
||||
// be sure.
|
||||
b = bytes.Trim(b, " \x00")
|
||||
|
||||
if len(b) == 0 {
|
||||
return 0
|
||||
}
|
||||
x, perr := strconv.ParseUint(p.parseString(b), 8, 64)
|
||||
if perr != nil {
|
||||
p.err = ErrHeader
|
||||
}
|
||||
return int64(x)
|
||||
}
|
||||
|
||||
// skipUnread skips any unread bytes in the existing file entry, as well as any
|
||||
@@ -407,46 +516,51 @@ func (tr *Reader) skipUnread() error {
|
||||
// Seek seems supported, so perform the real Seek.
|
||||
pos2, err := sr.Seek(dataSkip-1, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
tr.err = err
|
||||
return tr.err
|
||||
}
|
||||
seekSkipped = pos2 - pos1
|
||||
}
|
||||
}
|
||||
|
||||
copySkipped, err := io.CopyN(ioutil.Discard, tr.r, totalSkip-seekSkipped)
|
||||
if err == io.EOF && seekSkipped+copySkipped < dataSkip {
|
||||
err = io.ErrUnexpectedEOF
|
||||
var copySkipped int64 // Number of bytes skipped via CopyN
|
||||
copySkipped, tr.err = io.CopyN(ioutil.Discard, tr.r, totalSkip-seekSkipped)
|
||||
if tr.err == io.EOF && seekSkipped+copySkipped < dataSkip {
|
||||
tr.err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return err
|
||||
return tr.err
|
||||
}
|
||||
|
||||
// readHeader reads the next block header and assumes that the underlying reader
|
||||
// is already aligned to a block boundary. It returns the raw block of the
|
||||
// header in case further processing is required.
|
||||
// is already aligned to a block boundary.
|
||||
//
|
||||
// The err will be set to io.EOF only when one of the following occurs:
|
||||
// * Exactly 0 bytes are read and EOF is hit.
|
||||
// * Exactly 1 block of zeros is read and EOF is hit.
|
||||
// * At least 2 blocks of zeros are read.
|
||||
func (tr *Reader) readHeader() (*Header, *block, error) {
|
||||
// Two blocks of zero bytes marks the end of the archive.
|
||||
if _, err := io.ReadFull(tr.r, tr.blk[:]); err != nil {
|
||||
return nil, nil, err // EOF is okay here; exactly 0 bytes read
|
||||
func (tr *Reader) readHeader() *Header {
|
||||
if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
|
||||
return nil // io.EOF is okay here
|
||||
}
|
||||
|
||||
// Two blocks of zero bytes marks the end of the archive.
|
||||
if bytes.Equal(tr.blk[:], zeroBlock[:]) {
|
||||
if _, err := io.ReadFull(tr.r, tr.blk[:]); err != nil {
|
||||
return nil, nil, err // EOF is okay here; exactly 1 block of zeros read
|
||||
if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
|
||||
return nil // io.EOF is okay here
|
||||
}
|
||||
if bytes.Equal(tr.blk[:], zeroBlock[:]) {
|
||||
return nil, nil, io.EOF // normal EOF; exactly 2 block of zeros read
|
||||
tr.err = io.EOF
|
||||
} else {
|
||||
tr.err = ErrHeader // zero block and then non-zero block
|
||||
}
|
||||
return nil, nil, ErrHeader // Zero block and then non-zero block
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify the header matches a known format.
|
||||
format := tr.blk.GetFormat()
|
||||
if format == formatUnknown {
|
||||
return nil, nil, ErrHeader
|
||||
tr.err = ErrHeader
|
||||
return nil
|
||||
}
|
||||
|
||||
var p parser
|
||||
@@ -463,26 +577,6 @@ func (tr *Reader) readHeader() (*Header, *block, error) {
|
||||
hdr.Typeflag = v7.TypeFlag()[0]
|
||||
hdr.Linkname = p.parseString(v7.LinkName())
|
||||
|
||||
// The atime and ctime fields are often left unused. Some versions of Go
|
||||
// had a bug in the tar.Writer where it would output an invalid tar file
|
||||
// in certain rare situations because the logic incorrectly believed that
|
||||
// the old GNU format had a prefix field. This is wrong and leads to
|
||||
// an outputted file that actually mangles the atime and ctime fields.
|
||||
//
|
||||
// In order to continue reading tar files created by a buggy writer, we
|
||||
// try to parse the atime and ctime fields, but just return the zero value
|
||||
// of time.Time when we cannot parse them.
|
||||
//
|
||||
// See https://golang.org/issues/12594
|
||||
tryParseTime := func(b []byte) time.Time {
|
||||
var p parser
|
||||
n := p.parseNumeric(b)
|
||||
if b[0] != 0x00 && p.err == nil {
|
||||
return time.Unix(n, 0)
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// Unpack format specific fields.
|
||||
if format > formatV7 {
|
||||
ustar := tr.blk.USTAR()
|
||||
@@ -495,7 +589,9 @@ func (tr *Reader) readHeader() (*Header, *block, error) {
|
||||
|
||||
var prefix string
|
||||
switch format {
|
||||
case formatUSTAR:
|
||||
case formatUSTAR, formatGNU:
|
||||
// TODO(dsnet): Do not use the prefix field for the GNU format!
|
||||
// See golang.org/issues/12594
|
||||
ustar := tr.blk.USTAR()
|
||||
prefix = p.parseString(ustar.Prefix())
|
||||
case formatSTAR:
|
||||
@@ -503,68 +599,97 @@ func (tr *Reader) readHeader() (*Header, *block, error) {
|
||||
prefix = p.parseString(star.Prefix())
|
||||
hdr.AccessTime = time.Unix(p.parseNumeric(star.AccessTime()), 0)
|
||||
hdr.ChangeTime = time.Unix(p.parseNumeric(star.ChangeTime()), 0)
|
||||
case formatGNU:
|
||||
gnu := tr.blk.GNU()
|
||||
hdr.AccessTime = tryParseTime(gnu.AccessTime())
|
||||
hdr.ChangeTime = tryParseTime(gnu.ChangeTime())
|
||||
}
|
||||
if len(prefix) > 0 {
|
||||
hdr.Name = prefix + "/" + hdr.Name
|
||||
}
|
||||
}
|
||||
return hdr, &tr.blk, p.err
|
||||
|
||||
nb := hdr.Size
|
||||
if isHeaderOnlyType(hdr.Typeflag) {
|
||||
nb = 0
|
||||
}
|
||||
if nb < 0 {
|
||||
tr.err = ErrHeader
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set the current file reader.
|
||||
tr.pad = -nb & (blockSize - 1) // blockSize is a power of two
|
||||
tr.curr = ®FileReader{r: tr.r, nb: nb}
|
||||
|
||||
// Check for old GNU sparse format entry.
|
||||
if hdr.Typeflag == TypeGNUSparse {
|
||||
// Get the real size of the file.
|
||||
hdr.Size = p.parseNumeric(tr.blk.GNU().RealSize())
|
||||
if p.err != nil {
|
||||
tr.err = p.err
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read the sparse map.
|
||||
sp := tr.readOldGNUSparseMap(&tr.blk)
|
||||
if tr.err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Current file is a GNU sparse file. Update the current file reader.
|
||||
tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size)
|
||||
if tr.err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if p.err != nil {
|
||||
tr.err = p.err
|
||||
return nil
|
||||
}
|
||||
|
||||
return hdr
|
||||
}
|
||||
|
||||
// readOldGNUSparseMap reads the sparse map from the old GNU sparse format.
|
||||
// The sparse map is stored in the tar header if it's small enough.
|
||||
// If it's larger than four entries, then one or more extension headers are used
|
||||
// to store the rest of the sparse map.
|
||||
//
|
||||
// The Header.Size does not reflect the size of any extended headers used.
|
||||
// Thus, this function will read from the raw io.Reader to fetch extra headers.
|
||||
// This method mutates blk in the process.
|
||||
func (tr *Reader) readOldGNUSparseMap(hdr *Header, blk *block) ([]sparseEntry, error) {
|
||||
// Make sure that the input format is GNU.
|
||||
// Unfortunately, the STAR format also has a sparse header format that uses
|
||||
// the same type flag but has a completely different layout.
|
||||
if blk.GetFormat() != formatGNU {
|
||||
return nil, ErrHeader
|
||||
}
|
||||
|
||||
// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format.
|
||||
// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries,
|
||||
// then one or more extension headers are used to store the rest of the sparse map.
|
||||
func (tr *Reader) readOldGNUSparseMap(blk *block) []sparseEntry {
|
||||
var p parser
|
||||
hdr.Size = p.parseNumeric(blk.GNU().RealSize())
|
||||
if p.err != nil {
|
||||
return nil, p.err
|
||||
}
|
||||
var s sparseArray = blk.GNU().Sparse()
|
||||
var sp = make([]sparseEntry, 0, s.MaxEntries())
|
||||
for {
|
||||
for i := 0; i < s.MaxEntries(); i++ {
|
||||
offset := p.parseOctal(s.Entry(i).Offset())
|
||||
numBytes := p.parseOctal(s.Entry(i).NumBytes())
|
||||
if p.err != nil {
|
||||
tr.err = p.err
|
||||
return nil
|
||||
}
|
||||
if offset == 0 && numBytes == 0 {
|
||||
break
|
||||
}
|
||||
sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
|
||||
}
|
||||
|
||||
for s.IsExtended()[0] > 0 {
|
||||
// There are more entries. Read an extension header and parse its entries.
|
||||
var blk block
|
||||
if _, tr.err = io.ReadFull(tr.r, blk[:]); tr.err != nil {
|
||||
return nil
|
||||
}
|
||||
s = blk.Sparse()
|
||||
|
||||
for i := 0; i < s.MaxEntries(); i++ {
|
||||
// This termination condition is identical to GNU and BSD tar.
|
||||
if s.Entry(i).Offset()[0] == 0x00 {
|
||||
break // Don't return, need to process extended headers (even if empty)
|
||||
}
|
||||
offset := p.parseNumeric(s.Entry(i).Offset())
|
||||
numBytes := p.parseNumeric(s.Entry(i).NumBytes())
|
||||
offset := p.parseOctal(s.Entry(i).Offset())
|
||||
numBytes := p.parseOctal(s.Entry(i).NumBytes())
|
||||
if p.err != nil {
|
||||
return nil, p.err
|
||||
tr.err = p.err
|
||||
return nil
|
||||
}
|
||||
if offset == 0 && numBytes == 0 {
|
||||
break
|
||||
}
|
||||
sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
|
||||
}
|
||||
|
||||
if s.IsExtended()[0] > 0 {
|
||||
// There are more entries. Read an extension header and parse its entries.
|
||||
if _, err := io.ReadFull(tr.r, blk[:]); err != nil {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
s = blk.Sparse()
|
||||
continue
|
||||
}
|
||||
return sp, nil // Done
|
||||
}
|
||||
return sp
|
||||
}
|
||||
|
||||
// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format
|
||||
@@ -692,7 +817,7 @@ func (tr *Reader) numBytes() int64 {
|
||||
// Calling Read on special types like TypeLink, TypeSymLink, TypeChar,
|
||||
// TypeBlock, TypeDir, and TypeFifo returns 0, io.EOF regardless of what
|
||||
// the Header.Size claims.
|
||||
func (tr *Reader) Read(b []byte) (int, error) {
|
||||
func (tr *Reader) Read(b []byte) (n int, err error) {
|
||||
if tr.err != nil {
|
||||
return 0, tr.err
|
||||
}
|
||||
@@ -700,11 +825,11 @@ func (tr *Reader) Read(b []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n, err := tr.curr.Read(b)
|
||||
n, err = tr.curr.Read(b)
|
||||
if err != nil && err != io.EOF {
|
||||
tr.err = err
|
||||
}
|
||||
return n, err
|
||||
return
|
||||
}
|
||||
|
||||
func (rfr *regFileReader) Read(b []byte) (n int, err error) {
|
||||
|
||||
@@ -18,15 +18,17 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
vectors := []struct {
|
||||
file string // Test input file
|
||||
headers []*Header // Expected output headers
|
||||
chksums []string // MD5 checksum of files, leave as nil if not checked
|
||||
err error // Expected error to occur
|
||||
}{{
|
||||
file: "testdata/gnu.tar",
|
||||
headers: []*Header{{
|
||||
type untarTest struct {
|
||||
file string // Test input file
|
||||
headers []*Header // Expected output headers
|
||||
chksums []string // MD5 checksum of files, leave as nil if not checked
|
||||
err error // Expected error to occur
|
||||
}
|
||||
|
||||
var gnuTarTest = &untarTest{
|
||||
file: "testdata/gnu.tar",
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "small.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
@@ -36,7 +38,8 @@ func TestReader(t *testing.T) {
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
}, {
|
||||
},
|
||||
{
|
||||
Name: "small2.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
@@ -46,14 +49,18 @@ func TestReader(t *testing.T) {
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
}},
|
||||
chksums: []string{
|
||||
"e38b27eaccb4391bdec553a7f3ae6b2f",
|
||||
"c65bd2e50a56a2138bf1716f2fd56fe9",
|
||||
},
|
||||
}, {
|
||||
file: "testdata/sparse-formats.tar",
|
||||
headers: []*Header{{
|
||||
},
|
||||
chksums: []string{
|
||||
"e38b27eaccb4391bdec553a7f3ae6b2f",
|
||||
"c65bd2e50a56a2138bf1716f2fd56fe9",
|
||||
},
|
||||
}
|
||||
|
||||
var sparseTarTest = &untarTest{
|
||||
file: "testdata/sparse-formats.tar",
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "sparse-gnu",
|
||||
Mode: 420,
|
||||
Uid: 1000,
|
||||
@@ -66,7 +73,8 @@ func TestReader(t *testing.T) {
|
||||
Gname: "david",
|
||||
Devmajor: 0,
|
||||
Devminor: 0,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
Name: "sparse-posix-0.0",
|
||||
Mode: 420,
|
||||
Uid: 1000,
|
||||
@@ -79,7 +87,8 @@ func TestReader(t *testing.T) {
|
||||
Gname: "david",
|
||||
Devmajor: 0,
|
||||
Devminor: 0,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
Name: "sparse-posix-0.1",
|
||||
Mode: 420,
|
||||
Uid: 1000,
|
||||
@@ -92,7 +101,8 @@ func TestReader(t *testing.T) {
|
||||
Gname: "david",
|
||||
Devmajor: 0,
|
||||
Devminor: 0,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
Name: "sparse-posix-1.0",
|
||||
Mode: 420,
|
||||
Uid: 1000,
|
||||
@@ -105,7 +115,8 @@ func TestReader(t *testing.T) {
|
||||
Gname: "david",
|
||||
Devmajor: 0,
|
||||
Devminor: 0,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
Name: "end",
|
||||
Mode: 420,
|
||||
Uid: 1000,
|
||||
@@ -118,237 +129,209 @@ func TestReader(t *testing.T) {
|
||||
Gname: "david",
|
||||
Devmajor: 0,
|
||||
Devminor: 0,
|
||||
}},
|
||||
chksums: []string{
|
||||
"6f53234398c2449fe67c1812d993012f",
|
||||
"6f53234398c2449fe67c1812d993012f",
|
||||
"6f53234398c2449fe67c1812d993012f",
|
||||
"6f53234398c2449fe67c1812d993012f",
|
||||
"b0061974914468de549a2af8ced10316",
|
||||
},
|
||||
}, {
|
||||
},
|
||||
chksums: []string{
|
||||
"6f53234398c2449fe67c1812d993012f",
|
||||
"6f53234398c2449fe67c1812d993012f",
|
||||
"6f53234398c2449fe67c1812d993012f",
|
||||
"6f53234398c2449fe67c1812d993012f",
|
||||
"b0061974914468de549a2af8ced10316",
|
||||
},
|
||||
}
|
||||
|
||||
var untarTests = []*untarTest{
|
||||
gnuTarTest,
|
||||
sparseTarTest,
|
||||
{
|
||||
file: "testdata/star.tar",
|
||||
headers: []*Header{{
|
||||
Name: "small.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 5,
|
||||
ModTime: time.Unix(1244592783, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
AccessTime: time.Unix(1244592783, 0),
|
||||
ChangeTime: time.Unix(1244592783, 0),
|
||||
}, {
|
||||
Name: "small2.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 11,
|
||||
ModTime: time.Unix(1244592783, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
AccessTime: time.Unix(1244592783, 0),
|
||||
ChangeTime: time.Unix(1244592783, 0),
|
||||
}},
|
||||
}, {
|
||||
file: "testdata/v7.tar",
|
||||
headers: []*Header{{
|
||||
Name: "small.txt",
|
||||
Mode: 0444,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 5,
|
||||
ModTime: time.Unix(1244593104, 0),
|
||||
Typeflag: '\x00',
|
||||
}, {
|
||||
Name: "small2.txt",
|
||||
Mode: 0444,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 11,
|
||||
ModTime: time.Unix(1244593104, 0),
|
||||
Typeflag: '\x00',
|
||||
}},
|
||||
}, {
|
||||
file: "testdata/pax.tar",
|
||||
headers: []*Header{{
|
||||
Name: "a/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
|
||||
Mode: 0664,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Uname: "shane",
|
||||
Gname: "shane",
|
||||
Size: 7,
|
||||
ModTime: time.Unix(1350244992, 23960108),
|
||||
ChangeTime: time.Unix(1350244992, 23960108),
|
||||
AccessTime: time.Unix(1350244992, 23960108),
|
||||
Typeflag: TypeReg,
|
||||
}, {
|
||||
Name: "a/b",
|
||||
Mode: 0777,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Uname: "shane",
|
||||
Gname: "shane",
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1350266320, 910238425),
|
||||
ChangeTime: time.Unix(1350266320, 910238425),
|
||||
AccessTime: time.Unix(1350266320, 910238425),
|
||||
Typeflag: TypeSymlink,
|
||||
Linkname: "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
|
||||
}},
|
||||
}, {
|
||||
file: "testdata/pax-bad-hdr-file.tar",
|
||||
err: ErrHeader,
|
||||
}, {
|
||||
file: "testdata/pax-bad-mtime-file.tar",
|
||||
err: ErrHeader,
|
||||
}, {
|
||||
file: "testdata/pax-pos-size-file.tar",
|
||||
headers: []*Header{{
|
||||
Name: "foo",
|
||||
Mode: 0640,
|
||||
Uid: 319973,
|
||||
Gid: 5000,
|
||||
Size: 999,
|
||||
ModTime: time.Unix(1442282516, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "joetsai",
|
||||
Gname: "eng",
|
||||
}},
|
||||
chksums: []string{
|
||||
"0afb597b283fe61b5d4879669a350556",
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "small.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 5,
|
||||
ModTime: time.Unix(1244592783, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
AccessTime: time.Unix(1244592783, 0),
|
||||
ChangeTime: time.Unix(1244592783, 0),
|
||||
},
|
||||
{
|
||||
Name: "small2.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 11,
|
||||
ModTime: time.Unix(1244592783, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
AccessTime: time.Unix(1244592783, 0),
|
||||
ChangeTime: time.Unix(1244592783, 0),
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
file: "testdata/v7.tar",
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "small.txt",
|
||||
Mode: 0444,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 5,
|
||||
ModTime: time.Unix(1244593104, 0),
|
||||
Typeflag: '\x00',
|
||||
},
|
||||
{
|
||||
Name: "small2.txt",
|
||||
Mode: 0444,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 11,
|
||||
ModTime: time.Unix(1244593104, 0),
|
||||
Typeflag: '\x00',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
file: "testdata/pax.tar",
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "a/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
|
||||
Mode: 0664,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Uname: "shane",
|
||||
Gname: "shane",
|
||||
Size: 7,
|
||||
ModTime: time.Unix(1350244992, 23960108),
|
||||
ChangeTime: time.Unix(1350244992, 23960108),
|
||||
AccessTime: time.Unix(1350244992, 23960108),
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
{
|
||||
Name: "a/b",
|
||||
Mode: 0777,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Uname: "shane",
|
||||
Gname: "shane",
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1350266320, 910238425),
|
||||
ChangeTime: time.Unix(1350266320, 910238425),
|
||||
AccessTime: time.Unix(1350266320, 910238425),
|
||||
Typeflag: TypeSymlink,
|
||||
Linkname: "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
file: "testdata/nil-uid.tar", // golang.org/issue/5290
|
||||
headers: []*Header{{
|
||||
Name: "P1050238.JPG.log",
|
||||
Mode: 0664,
|
||||
Uid: 0,
|
||||
Gid: 0,
|
||||
Size: 14,
|
||||
ModTime: time.Unix(1365454838, 0),
|
||||
Typeflag: TypeReg,
|
||||
Linkname: "",
|
||||
Uname: "eyefi",
|
||||
Gname: "eyefi",
|
||||
Devmajor: 0,
|
||||
Devminor: 0,
|
||||
}},
|
||||
}, {
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "P1050238.JPG.log",
|
||||
Mode: 0664,
|
||||
Uid: 0,
|
||||
Gid: 0,
|
||||
Size: 14,
|
||||
ModTime: time.Unix(1365454838, 0),
|
||||
Typeflag: TypeReg,
|
||||
Linkname: "",
|
||||
Uname: "eyefi",
|
||||
Gname: "eyefi",
|
||||
Devmajor: 0,
|
||||
Devminor: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
file: "testdata/xattrs.tar",
|
||||
headers: []*Header{{
|
||||
Name: "small.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 10,
|
||||
Size: 5,
|
||||
ModTime: time.Unix(1386065770, 448252320),
|
||||
Typeflag: '0',
|
||||
Uname: "alex",
|
||||
Gname: "wheel",
|
||||
AccessTime: time.Unix(1389782991, 419875220),
|
||||
ChangeTime: time.Unix(1389782956, 794414986),
|
||||
Xattrs: map[string]string{
|
||||
"user.key": "value",
|
||||
"user.key2": "value2",
|
||||
// Interestingly, selinux encodes the terminating null inside the xattr
|
||||
"security.selinux": "unconfined_u:object_r:default_t:s0\x00",
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "small.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 10,
|
||||
Size: 5,
|
||||
ModTime: time.Unix(1386065770, 448252320),
|
||||
Typeflag: '0',
|
||||
Uname: "alex",
|
||||
Gname: "wheel",
|
||||
AccessTime: time.Unix(1389782991, 419875220),
|
||||
ChangeTime: time.Unix(1389782956, 794414986),
|
||||
Xattrs: map[string]string{
|
||||
"user.key": "value",
|
||||
"user.key2": "value2",
|
||||
// Interestingly, selinux encodes the terminating null inside the xattr
|
||||
"security.selinux": "unconfined_u:object_r:default_t:s0\x00",
|
||||
},
|
||||
},
|
||||
}, {
|
||||
Name: "small2.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 10,
|
||||
Size: 11,
|
||||
ModTime: time.Unix(1386065770, 449252304),
|
||||
Typeflag: '0',
|
||||
Uname: "alex",
|
||||
Gname: "wheel",
|
||||
AccessTime: time.Unix(1389782991, 419875220),
|
||||
ChangeTime: time.Unix(1386065770, 449252304),
|
||||
Xattrs: map[string]string{
|
||||
"security.selinux": "unconfined_u:object_r:default_t:s0\x00",
|
||||
{
|
||||
Name: "small2.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 10,
|
||||
Size: 11,
|
||||
ModTime: time.Unix(1386065770, 449252304),
|
||||
Typeflag: '0',
|
||||
Uname: "alex",
|
||||
Gname: "wheel",
|
||||
AccessTime: time.Unix(1389782991, 419875220),
|
||||
ChangeTime: time.Unix(1386065770, 449252304),
|
||||
Xattrs: map[string]string{
|
||||
"security.selinux": "unconfined_u:object_r:default_t:s0\x00",
|
||||
},
|
||||
},
|
||||
}},
|
||||
}, {
|
||||
},
|
||||
},
|
||||
{
|
||||
// Matches the behavior of GNU, BSD, and STAR tar utilities.
|
||||
file: "testdata/gnu-multi-hdrs.tar",
|
||||
headers: []*Header{{
|
||||
Name: "GNU2/GNU2/long-path-name",
|
||||
Linkname: "GNU4/GNU4/long-linkpath-name",
|
||||
ModTime: time.Unix(0, 0),
|
||||
Typeflag: '2',
|
||||
}},
|
||||
}, {
|
||||
// GNU tar file with atime and ctime fields set.
|
||||
// Created with the GNU tar v1.27.1.
|
||||
// tar --incremental -S -cvf gnu-incremental.tar test2
|
||||
file: "testdata/gnu-incremental.tar",
|
||||
headers: []*Header{{
|
||||
Name: "test2/",
|
||||
Mode: 16877,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Size: 14,
|
||||
ModTime: time.Unix(1441973427, 0),
|
||||
Typeflag: 'D',
|
||||
Uname: "rawr",
|
||||
Gname: "dsnet",
|
||||
AccessTime: time.Unix(1441974501, 0),
|
||||
ChangeTime: time.Unix(1441973436, 0),
|
||||
}, {
|
||||
Name: "test2/foo",
|
||||
Mode: 33188,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Size: 64,
|
||||
ModTime: time.Unix(1441973363, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "rawr",
|
||||
Gname: "dsnet",
|
||||
AccessTime: time.Unix(1441974501, 0),
|
||||
ChangeTime: time.Unix(1441973436, 0),
|
||||
}, {
|
||||
Name: "test2/sparse",
|
||||
Mode: 33188,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Size: 536870912,
|
||||
ModTime: time.Unix(1441973427, 0),
|
||||
Typeflag: 'S',
|
||||
Uname: "rawr",
|
||||
Gname: "dsnet",
|
||||
AccessTime: time.Unix(1441991948, 0),
|
||||
ChangeTime: time.Unix(1441973436, 0),
|
||||
}},
|
||||
}, {
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "GNU2/GNU2/long-path-name",
|
||||
Linkname: "GNU4/GNU4/long-linkpath-name",
|
||||
ModTime: time.Unix(0, 0),
|
||||
Typeflag: '2',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Matches the behavior of GNU and BSD tar utilities.
|
||||
file: "testdata/pax-multi-hdrs.tar",
|
||||
headers: []*Header{{
|
||||
Name: "bar",
|
||||
Linkname: "PAX4/PAX4/long-linkpath-name",
|
||||
ModTime: time.Unix(0, 0),
|
||||
Typeflag: '2',
|
||||
}},
|
||||
}, {
|
||||
headers: []*Header{
|
||||
{
|
||||
Name: "bar",
|
||||
Linkname: "PAX4/PAX4/long-linkpath-name",
|
||||
ModTime: time.Unix(0, 0),
|
||||
Typeflag: '2',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
file: "testdata/neg-size.tar",
|
||||
err: ErrHeader,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
file: "testdata/issue10968.tar",
|
||||
err: ErrHeader,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
file: "testdata/issue11169.tar",
|
||||
err: ErrHeader,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
file: "testdata/issue12435.tar",
|
||||
err: ErrHeader,
|
||||
}}
|
||||
},
|
||||
}
|
||||
|
||||
for i, v := range vectors {
|
||||
func TestReader(t *testing.T) {
|
||||
for i, v := range untarTests {
|
||||
f, err := os.Open(v.file)
|
||||
if err != nil {
|
||||
t.Errorf("file %s, test %d: unexpected error: %v", v.file, i, err)
|
||||
@@ -457,8 +440,83 @@ func TestPartialRead(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePAXHeader(t *testing.T) {
|
||||
paxTests := [][3]string{
|
||||
{"a", "a=name", "10 a=name\n"}, // Test case involving multiple acceptable lengths
|
||||
{"a", "a=name", "9 a=name\n"}, // Test case involving multiple acceptable length
|
||||
{"mtime", "mtime=1350244992.023960108", "30 mtime=1350244992.023960108\n"}}
|
||||
for _, test := range paxTests {
|
||||
key, expected, raw := test[0], test[1], test[2]
|
||||
reader := bytes.NewReader([]byte(raw))
|
||||
headers, err := parsePAX(reader)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't parse correctly formatted headers: %v", err)
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(headers[key], expected) {
|
||||
t.Errorf("mtime header incorrectly parsed: got %s, wanted %s", headers[key], expected)
|
||||
continue
|
||||
}
|
||||
trailer := make([]byte, 100)
|
||||
n, err := reader.Read(trailer)
|
||||
if err != io.EOF || n != 0 {
|
||||
t.Error("Buffer wasn't consumed")
|
||||
}
|
||||
}
|
||||
badHeaderTests := [][]byte{
|
||||
[]byte("3 somelongkey=\n"),
|
||||
[]byte("50 tooshort=\n"),
|
||||
}
|
||||
for _, test := range badHeaderTests {
|
||||
if _, err := parsePAX(bytes.NewReader(test)); err != ErrHeader {
|
||||
t.Fatal("Unexpected success when parsing bad header")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePAXTime(t *testing.T) {
|
||||
// Some valid PAX time values
|
||||
timestamps := map[string]time.Time{
|
||||
"1350244992.023960108": time.Unix(1350244992, 23960108), // The common case
|
||||
"1350244992.02396010": time.Unix(1350244992, 23960100), // Lower precision value
|
||||
"1350244992.0239601089": time.Unix(1350244992, 23960108), // Higher precision value
|
||||
"1350244992": time.Unix(1350244992, 0), // Low precision value
|
||||
}
|
||||
for input, expected := range timestamps {
|
||||
ts, err := parsePAXTime(input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ts.Equal(expected) {
|
||||
t.Fatalf("Time parsing failure %s %s", ts, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePAX(t *testing.T) {
|
||||
hdr := new(Header)
|
||||
// Test a string, integer, and time based value.
|
||||
headers := map[string]string{
|
||||
"path": "a/b/c",
|
||||
"uid": "1000",
|
||||
"mtime": "1350244992.023960108",
|
||||
}
|
||||
err := mergePAX(hdr, headers)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := &Header{
|
||||
Name: "a/b/c",
|
||||
Uid: 1000,
|
||||
ModTime: time.Unix(1350244992, 23960108),
|
||||
}
|
||||
if !reflect.DeepEqual(hdr, want) {
|
||||
t.Errorf("incorrect merge: got %+v, want %+v", hdr, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSparseFileReader(t *testing.T) {
|
||||
vectors := []struct {
|
||||
var vectors = []struct {
|
||||
realSize int64 // Real size of the output file
|
||||
sparseMap []sparseEntry // Input sparse map
|
||||
sparseData string // Input compact data
|
||||
@@ -581,11 +639,9 @@ func TestSparseFileReader(t *testing.T) {
|
||||
r := bytes.NewReader([]byte(v.sparseData))
|
||||
rfr := ®FileReader{r: r, nb: int64(len(v.sparseData))}
|
||||
|
||||
var (
|
||||
sfr *sparseFileReader
|
||||
err error
|
||||
buf []byte
|
||||
)
|
||||
var sfr *sparseFileReader
|
||||
var err error
|
||||
var buf []byte
|
||||
|
||||
sfr, err = newSparseFileReader(rfr, v.sparseMap, v.realSize)
|
||||
if err != nil {
|
||||
@@ -612,64 +668,6 @@ func TestSparseFileReader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadOldGNUSparseMap(t *testing.T) {
|
||||
const (
|
||||
t00 = "00000000000\x0000000000000\x00"
|
||||
t11 = "00000000001\x0000000000001\x00"
|
||||
t12 = "00000000001\x0000000000002\x00"
|
||||
t21 = "00000000002\x0000000000001\x00"
|
||||
)
|
||||
|
||||
mkBlk := func(size, sp0, sp1, sp2, sp3, ext string, format int) *block {
|
||||
var blk block
|
||||
copy(blk.GNU().RealSize(), size)
|
||||
copy(blk.GNU().Sparse().Entry(0), sp0)
|
||||
copy(blk.GNU().Sparse().Entry(1), sp1)
|
||||
copy(blk.GNU().Sparse().Entry(2), sp2)
|
||||
copy(blk.GNU().Sparse().Entry(3), sp3)
|
||||
copy(blk.GNU().Sparse().IsExtended(), ext)
|
||||
if format != formatUnknown {
|
||||
blk.SetFormat(format)
|
||||
}
|
||||
return &blk
|
||||
}
|
||||
|
||||
vectors := []struct {
|
||||
data string // Input data
|
||||
rawHdr *block // Input raw header
|
||||
want []sparseEntry // Expected sparse entries to be outputted
|
||||
err error // Expected error to be returned
|
||||
}{
|
||||
{"", mkBlk("", "", "", "", "", "", formatUnknown), nil, ErrHeader},
|
||||
{"", mkBlk("1234", "fewa", "", "", "", "", formatGNU), nil, ErrHeader},
|
||||
{"", mkBlk("0031", "", "", "", "", "", formatGNU), nil, nil},
|
||||
{"", mkBlk("1234", t00, t11, "", "", "", formatGNU),
|
||||
[]sparseEntry{{0, 0}, {1, 1}}, nil},
|
||||
{"", mkBlk("1234", t11, t12, t21, t11, "", formatGNU),
|
||||
[]sparseEntry{{1, 1}, {1, 2}, {2, 1}, {1, 1}}, nil},
|
||||
{"", mkBlk("1234", t11, t12, t21, t11, "\x80", formatGNU),
|
||||
[]sparseEntry{}, io.ErrUnexpectedEOF},
|
||||
{t11 + t11,
|
||||
mkBlk("1234", t11, t12, t21, t11, "\x80", formatGNU),
|
||||
[]sparseEntry{}, io.ErrUnexpectedEOF},
|
||||
{t11 + t21 + strings.Repeat("\x00", 512),
|
||||
mkBlk("1234", t11, t12, t21, t11, "\x80", formatGNU),
|
||||
[]sparseEntry{{1, 1}, {1, 2}, {2, 1}, {1, 1}, {1, 1}, {2, 1}}, nil},
|
||||
}
|
||||
|
||||
for i, v := range vectors {
|
||||
tr := Reader{r: strings.NewReader(v.data)}
|
||||
hdr := new(Header)
|
||||
got, err := tr.readOldGNUSparseMap(hdr, v.rawHdr)
|
||||
if !reflect.DeepEqual(got, v.want) && !(len(got) == 0 && len(v.want) == 0) {
|
||||
t.Errorf("test %d, readOldGNUSparseMap(...): got %v, want %v", i, got, v.want)
|
||||
}
|
||||
if err != v.err {
|
||||
t.Errorf("test %d, unexpected error: got %v, want %v", i, err, v.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadGNUSparseMap0x1(t *testing.T) {
|
||||
const (
|
||||
maxUint = ^uint(0)
|
||||
@@ -681,7 +679,7 @@ func TestReadGNUSparseMap0x1(t *testing.T) {
|
||||
big3 = fmt.Sprintf("%d", (int64(maxInt) / 3))
|
||||
)
|
||||
|
||||
vectors := []struct {
|
||||
var vectors = []struct {
|
||||
extHdrs map[string]string // Input data
|
||||
sparseMap []sparseEntry // Expected sparse entries to be outputted
|
||||
err error // Expected errors that may be raised
|
||||
@@ -747,12 +745,12 @@ func TestReadGNUSparseMap0x1(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReadGNUSparseMap1x0(t *testing.T) {
|
||||
sp := []sparseEntry{{1, 2}, {3, 4}}
|
||||
var sp = []sparseEntry{{1, 2}, {3, 4}}
|
||||
for i := 0; i < 98; i++ {
|
||||
sp = append(sp, sparseEntry{54321, 12345})
|
||||
}
|
||||
|
||||
vectors := []struct {
|
||||
var vectors = []struct {
|
||||
input string // Input data
|
||||
sparseMap []sparseEntry // Expected sparse entries to be outputted
|
||||
cnt int // Expected number of bytes read
|
||||
@@ -827,7 +825,8 @@ func TestReadGNUSparseMap1x0(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUninitializedRead(t *testing.T) {
|
||||
f, err := os.Open("testdata/gnu.tar")
|
||||
test := gnuTarTest
|
||||
f, err := os.Open(test.file)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
@@ -869,7 +868,7 @@ func TestReadTruncation(t *testing.T) {
|
||||
data2 += strings.Repeat("\x00", 10*512)
|
||||
trash := strings.Repeat("garbage ", 64) // Exactly 512 bytes
|
||||
|
||||
vectors := []struct {
|
||||
var vectors = []struct {
|
||||
input string // Input stream
|
||||
cnt int // Expected number of headers read
|
||||
err error // Expected error outcome
|
||||
@@ -905,7 +904,8 @@ func TestReadTruncation(t *testing.T) {
|
||||
{pax + trash[:1], 0, io.ErrUnexpectedEOF},
|
||||
{pax + trash[:511], 0, io.ErrUnexpectedEOF},
|
||||
{sparse[:511], 0, io.ErrUnexpectedEOF},
|
||||
{sparse[:512], 0, io.ErrUnexpectedEOF},
|
||||
// TODO(dsnet): This should pass, but currently fails.
|
||||
// {sparse[:512], 0, io.ErrUnexpectedEOF},
|
||||
{sparse[:3584], 1, io.EOF},
|
||||
{sparse[:9200], 1, io.EOF}, // Terminate in padding of sparse header
|
||||
{sparse[:9216], 1, io.EOF},
|
||||
@@ -1002,7 +1002,7 @@ func TestReadHeaderOnly(t *testing.T) {
|
||||
t.Fatalf("len(hdrs): got %d, want %d", len(hdrs), 16)
|
||||
}
|
||||
for i := 0; i < 8; i++ {
|
||||
hdr1, hdr2 := hdrs[i+0], hdrs[i+8]
|
||||
var hdr1, hdr2 = hdrs[i+0], hdrs[i+8]
|
||||
hdr1.Size, hdr2.Size = 0, 0
|
||||
if !reflect.DeepEqual(*hdr1, *hdr2) {
|
||||
t.Errorf("incorrect header:\ngot %+v\nwant %+v", *hdr1, *hdr2)
|
||||
@@ -1010,87 +1010,116 @@ func TestReadHeaderOnly(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergePAX(t *testing.T) {
|
||||
vectors := []struct {
|
||||
in map[string]string
|
||||
want *Header
|
||||
ok bool
|
||||
}{{
|
||||
in: map[string]string{
|
||||
"path": "a/b/c",
|
||||
"uid": "1000",
|
||||
"mtime": "1350244992.023960108",
|
||||
},
|
||||
want: &Header{
|
||||
Name: "a/b/c",
|
||||
Uid: 1000,
|
||||
ModTime: time.Unix(1350244992, 23960108),
|
||||
},
|
||||
ok: true,
|
||||
}, {
|
||||
in: map[string]string{
|
||||
"gid": "gtgergergersagersgers",
|
||||
},
|
||||
}, {
|
||||
in: map[string]string{
|
||||
"missing": "missing",
|
||||
"SCHILY.xattr.key": "value",
|
||||
},
|
||||
want: &Header{
|
||||
Xattrs: map[string]string{"key": "value"},
|
||||
},
|
||||
ok: true,
|
||||
}}
|
||||
func TestParsePAXRecord(t *testing.T) {
|
||||
var medName = strings.Repeat("CD", 50)
|
||||
var longName = strings.Repeat("AB", 100)
|
||||
|
||||
for i, v := range vectors {
|
||||
got := new(Header)
|
||||
err := mergePAX(got, v.in)
|
||||
if v.ok && !reflect.DeepEqual(*got, *v.want) {
|
||||
t.Errorf("test %d, mergePAX(...):\ngot %+v\nwant %+v", i, *got, *v.want)
|
||||
}
|
||||
if ok := err == nil; ok != v.ok {
|
||||
t.Errorf("test %d, mergePAX(...): got %v, want %v", i, ok, v.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePAX(t *testing.T) {
|
||||
vectors := []struct {
|
||||
in string
|
||||
want map[string]string
|
||||
ok bool
|
||||
var vectors = []struct {
|
||||
input string
|
||||
residual string
|
||||
outputKey string
|
||||
outputVal string
|
||||
ok bool
|
||||
}{
|
||||
{"", nil, true},
|
||||
{"6 k=1\n", map[string]string{"k": "1"}, true},
|
||||
{"10 a=name\n", map[string]string{"a": "name"}, true},
|
||||
{"9 a=name\n", map[string]string{"a": "name"}, true},
|
||||
{"30 mtime=1350244992.023960108\n", map[string]string{"mtime": "1350244992.023960108"}, true},
|
||||
{"3 somelongkey=\n", nil, false},
|
||||
{"50 tooshort=\n", nil, false},
|
||||
{"13 key1=haha\n13 key2=nana\n13 key3=kaka\n",
|
||||
map[string]string{"key1": "haha", "key2": "nana", "key3": "kaka"}, true},
|
||||
{"13 key1=val1\n13 key2=val2\n8 key1=\n",
|
||||
map[string]string{"key2": "val2"}, true},
|
||||
{"22 GNU.sparse.size=10\n26 GNU.sparse.numblocks=2\n" +
|
||||
"23 GNU.sparse.offset=1\n25 GNU.sparse.numbytes=2\n" +
|
||||
"23 GNU.sparse.offset=3\n25 GNU.sparse.numbytes=4\n",
|
||||
map[string]string{paxGNUSparseSize: "10", paxGNUSparseNumBlocks: "2", paxGNUSparseMap: "1,2,3,4"}, true},
|
||||
{"22 GNU.sparse.size=10\n26 GNU.sparse.numblocks=1\n" +
|
||||
"25 GNU.sparse.numbytes=2\n23 GNU.sparse.offset=1\n",
|
||||
nil, false},
|
||||
{"22 GNU.sparse.size=10\n26 GNU.sparse.numblocks=1\n" +
|
||||
"25 GNU.sparse.offset=1,2\n25 GNU.sparse.numbytes=2\n",
|
||||
nil, false},
|
||||
{"6 k=v\n\n", "\n", "k", "v", true},
|
||||
{"19 path=/etc/hosts\n", "", "path", "/etc/hosts", true},
|
||||
{"210 path=" + longName + "\nabc", "abc", "path", longName, true},
|
||||
{"110 path=" + medName + "\n", "", "path", medName, true},
|
||||
{"9 foo=ba\n", "", "foo", "ba", true},
|
||||
{"11 foo=bar\n\x00", "\x00", "foo", "bar", true},
|
||||
{"18 foo=b=\nar=\n==\x00\n", "", "foo", "b=\nar=\n==\x00", true},
|
||||
{"27 foo=hello9 foo=ba\nworld\n", "", "foo", "hello9 foo=ba\nworld", true},
|
||||
{"27 ☺☻☹=日a本b語ç\nmeow mix", "meow mix", "☺☻☹", "日a本b語ç", true},
|
||||
{"17 \x00hello=\x00world\n", "", "\x00hello", "\x00world", true},
|
||||
{"1 k=1\n", "1 k=1\n", "", "", false},
|
||||
{"6 k~1\n", "6 k~1\n", "", "", false},
|
||||
{"6_k=1\n", "6_k=1\n", "", "", false},
|
||||
{"6 k=1 ", "6 k=1 ", "", "", false},
|
||||
{"632 k=1\n", "632 k=1\n", "", "", false},
|
||||
{"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
|
||||
{"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
|
||||
{"50 tooshort=\n", "50 tooshort=\n", "", "", false},
|
||||
}
|
||||
|
||||
for i, v := range vectors {
|
||||
r := strings.NewReader(v.in)
|
||||
got, err := parsePAX(r)
|
||||
if !reflect.DeepEqual(got, v.want) && !(len(got) == 0 && len(v.want) == 0) {
|
||||
t.Errorf("test %d, parsePAX(...):\ngot %v\nwant %v", i, got, v.want)
|
||||
for _, v := range vectors {
|
||||
key, val, res, err := parsePAXRecord(v.input)
|
||||
ok := (err == nil)
|
||||
if v.ok != ok {
|
||||
if v.ok {
|
||||
t.Errorf("parsePAXRecord(%q): got parsing failure, want success", v.input)
|
||||
} else {
|
||||
t.Errorf("parsePAXRecord(%q): got parsing success, want failure", v.input)
|
||||
}
|
||||
}
|
||||
if ok := err == nil; ok != v.ok {
|
||||
t.Errorf("test %d, parsePAX(...): got %v, want %v", i, ok, v.ok)
|
||||
if ok && (key != v.outputKey || val != v.outputVal) {
|
||||
t.Errorf("parsePAXRecord(%q): got (%q: %q), want (%q: %q)",
|
||||
v.input, key, val, v.outputKey, v.outputVal)
|
||||
}
|
||||
if res != v.residual {
|
||||
t.Errorf("parsePAXRecord(%q): got residual %q, want residual %q",
|
||||
v.input, res, v.residual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseNumeric(t *testing.T) {
|
||||
var vectors = []struct {
|
||||
input string
|
||||
output int64
|
||||
ok bool
|
||||
}{
|
||||
// Test base-256 (binary) encoded values.
|
||||
{"", 0, true},
|
||||
{"\x80", 0, true},
|
||||
{"\x80\x00", 0, true},
|
||||
{"\x80\x00\x00", 0, true},
|
||||
{"\xbf", (1 << 6) - 1, true},
|
||||
{"\xbf\xff", (1 << 14) - 1, true},
|
||||
{"\xbf\xff\xff", (1 << 22) - 1, true},
|
||||
{"\xff", -1, true},
|
||||
{"\xff\xff", -1, true},
|
||||
{"\xff\xff\xff", -1, true},
|
||||
{"\xc0", -1 * (1 << 6), true},
|
||||
{"\xc0\x00", -1 * (1 << 14), true},
|
||||
{"\xc0\x00\x00", -1 * (1 << 22), true},
|
||||
{"\x87\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
|
||||
{"\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
|
||||
{"\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
|
||||
{"\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
|
||||
{"\x80\x7f\xff\xff\xff\xff\xff\xff\xff", math.MaxInt64, true},
|
||||
{"\x80\x80\x00\x00\x00\x00\x00\x00\x00", 0, false},
|
||||
{"\xff\x80\x00\x00\x00\x00\x00\x00\x00", math.MinInt64, true},
|
||||
{"\xff\x7f\xff\xff\xff\xff\xff\xff\xff", 0, false},
|
||||
{"\xf5\xec\xd1\xc7\x7e\x5f\x26\x48\x81\x9f\x8f\x9b", 0, false},
|
||||
|
||||
// Test base-8 (octal) encoded values.
|
||||
{"0000000\x00", 0, true},
|
||||
{" \x0000000\x00", 0, true},
|
||||
{" \x0000003\x00", 3, true},
|
||||
{"00000000227\x00", 0227, true},
|
||||
{"032033\x00 ", 032033, true},
|
||||
{"320330\x00 ", 0320330, true},
|
||||
{"0000660\x00 ", 0660, true},
|
||||
{"\x00 0000660\x00 ", 0660, true},
|
||||
{"0123456789abcdef", 0, false},
|
||||
{"0123456789\x00abcdef", 0, false},
|
||||
{"01234567\x0089abcdef", 342391, true},
|
||||
{"0123\x7e\x5f\x264123", 0, false},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
var p parser
|
||||
num := p.parseNumeric([]byte(v.input))
|
||||
ok := (p.err == nil)
|
||||
if v.ok != ok {
|
||||
if v.ok {
|
||||
t.Errorf("parseNumeric(%q): got parsing failure, want success", v.input)
|
||||
} else {
|
||||
t.Errorf("parseNumeric(%q): got parsing success, want failure", v.input)
|
||||
}
|
||||
}
|
||||
if ok && num != v.output {
|
||||
t.Errorf("parseNumeric(%q): got %d, want %d", v.input, num, v.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package tar
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func isASCII(s string) bool {
|
||||
for _, c := range s {
|
||||
if c >= 0x80 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func toASCII(s string) string {
|
||||
if isASCII(s) {
|
||||
return s
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
for _, c := range s {
|
||||
if c < 0x80 {
|
||||
buf.WriteByte(byte(c))
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
err error // Last error seen
|
||||
}
|
||||
|
||||
type formatter struct {
|
||||
err error // Last error seen
|
||||
}
|
||||
|
||||
// parseString parses bytes as a NUL-terminated C-style string.
|
||||
// If a NUL byte is not found then the whole slice is returned as a string.
|
||||
func (*parser) parseString(b []byte) string {
|
||||
n := 0
|
||||
for n < len(b) && b[n] != 0 {
|
||||
n++
|
||||
}
|
||||
return string(b[0:n])
|
||||
}
|
||||
|
||||
// Write s into b, terminating it with a NUL if there is room.
|
||||
func (f *formatter) formatString(b []byte, s string) {
|
||||
if len(s) > len(b) {
|
||||
f.err = ErrFieldTooLong
|
||||
return
|
||||
}
|
||||
ascii := toASCII(s)
|
||||
copy(b, ascii)
|
||||
if len(ascii) < len(b) {
|
||||
b[len(ascii)] = 0
|
||||
}
|
||||
}
|
||||
|
||||
// fitsInBase256 reports whether x can be encoded into n bytes using base-256
|
||||
// encoding. Unlike octal encoding, base-256 encoding does not require that the
|
||||
// string ends with a NUL character. Thus, all n bytes are available for output.
|
||||
//
|
||||
// If operating in binary mode, this assumes strict GNU binary mode; which means
|
||||
// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is
|
||||
// equivalent to the sign bit in two's complement form.
|
||||
func fitsInBase256(n int, x int64) bool {
|
||||
var binBits = uint(n-1) * 8
|
||||
return n >= 9 || (x >= -1<<binBits && x < 1<<binBits)
|
||||
}
|
||||
|
||||
// parseNumeric parses the input as being encoded in either base-256 or octal.
|
||||
// This function may return negative numbers.
|
||||
// If parsing fails or an integer overflow occurs, err will be set.
|
||||
func (p *parser) parseNumeric(b []byte) int64 {
|
||||
// Check for base-256 (binary) format first.
|
||||
// If the first bit is set, then all following bits constitute a two's
|
||||
// complement encoded number in big-endian byte order.
|
||||
if len(b) > 0 && b[0]&0x80 != 0 {
|
||||
// Handling negative numbers relies on the following identity:
|
||||
// -a-1 == ^a
|
||||
//
|
||||
// If the number is negative, we use an inversion mask to invert the
|
||||
// data bytes and treat the value as an unsigned number.
|
||||
var inv byte // 0x00 if positive or zero, 0xff if negative
|
||||
if b[0]&0x40 != 0 {
|
||||
inv = 0xff
|
||||
}
|
||||
|
||||
var x uint64
|
||||
for i, c := range b {
|
||||
c ^= inv // Inverts c only if inv is 0xff, otherwise does nothing
|
||||
if i == 0 {
|
||||
c &= 0x7f // Ignore signal bit in first byte
|
||||
}
|
||||
if (x >> 56) > 0 {
|
||||
p.err = ErrHeader // Integer overflow
|
||||
return 0
|
||||
}
|
||||
x = x<<8 | uint64(c)
|
||||
}
|
||||
if (x >> 63) > 0 {
|
||||
p.err = ErrHeader // Integer overflow
|
||||
return 0
|
||||
}
|
||||
if inv == 0xff {
|
||||
return ^int64(x)
|
||||
}
|
||||
return int64(x)
|
||||
}
|
||||
|
||||
// Normal case is base-8 (octal) format.
|
||||
return p.parseOctal(b)
|
||||
}
|
||||
|
||||
// Write x into b, as binary (GNUtar/star extension).
|
||||
func (f *formatter) formatNumeric(b []byte, x int64) {
|
||||
if fitsInBase256(len(b), x) {
|
||||
for i := len(b) - 1; i >= 0; i-- {
|
||||
b[i] = byte(x)
|
||||
x >>= 8
|
||||
}
|
||||
b[0] |= 0x80 // Highest bit indicates binary format
|
||||
return
|
||||
}
|
||||
|
||||
f.formatOctal(b, 0) // Last resort, just write zero
|
||||
f.err = ErrFieldTooLong
|
||||
}
|
||||
|
||||
func (p *parser) parseOctal(b []byte) int64 {
|
||||
// Because unused fields are filled with NULs, we need
|
||||
// to skip leading NULs. Fields may also be padded with
|
||||
// spaces or NULs.
|
||||
// So we remove leading and trailing NULs and spaces to
|
||||
// be sure.
|
||||
b = bytes.Trim(b, " \x00")
|
||||
|
||||
if len(b) == 0 {
|
||||
return 0
|
||||
}
|
||||
x, perr := strconv.ParseUint(p.parseString(b), 8, 64)
|
||||
if perr != nil {
|
||||
p.err = ErrHeader
|
||||
}
|
||||
return int64(x)
|
||||
}
|
||||
|
||||
func (f *formatter) formatOctal(b []byte, x int64) {
|
||||
s := strconv.FormatInt(x, 8)
|
||||
// Add leading zeros, but leave room for a NUL.
|
||||
if n := len(b) - len(s) - 1; n > 0 {
|
||||
s = strings.Repeat("0", n) + s
|
||||
}
|
||||
f.formatString(b, s)
|
||||
}
|
||||
|
||||
// parsePAXTime takes a string of the form %d.%d as described in the PAX
|
||||
// specification. Note that this implementation allows for negative timestamps,
|
||||
// which is allowed for by the PAX specification, but not always portable.
|
||||
func parsePAXTime(s string) (time.Time, error) {
|
||||
const maxNanoSecondDigits = 9
|
||||
|
||||
// Split string into seconds and sub-seconds parts.
|
||||
ss, sn := s, ""
|
||||
if pos := strings.IndexByte(s, '.'); pos >= 0 {
|
||||
ss, sn = s[:pos], s[pos+1:]
|
||||
}
|
||||
|
||||
// Parse the seconds.
|
||||
secs, err := strconv.ParseInt(ss, 10, 64)
|
||||
if err != nil {
|
||||
return time.Time{}, ErrHeader
|
||||
}
|
||||
if len(sn) == 0 {
|
||||
return time.Unix(secs, 0), nil // No sub-second values
|
||||
}
|
||||
|
||||
// Parse the nanoseconds.
|
||||
if strings.Trim(sn, "0123456789") != "" {
|
||||
return time.Time{}, ErrHeader
|
||||
}
|
||||
if len(sn) < maxNanoSecondDigits {
|
||||
sn += strings.Repeat("0", maxNanoSecondDigits-len(sn)) // Right pad
|
||||
} else {
|
||||
sn = sn[:maxNanoSecondDigits] // Right truncate
|
||||
}
|
||||
nsecs, _ := strconv.ParseInt(sn, 10, 64) // Must succeed
|
||||
if len(ss) > 0 && ss[0] == '-' {
|
||||
return time.Unix(secs, -1*int64(nsecs)), nil // Negative correction
|
||||
}
|
||||
return time.Unix(secs, int64(nsecs)), nil
|
||||
}
|
||||
|
||||
// TODO(dsnet): Implement formatPAXTime.
|
||||
|
||||
// parsePAXRecord parses the input PAX record string into a key-value pair.
|
||||
// If parsing is successful, it will slice off the currently read record and
|
||||
// return the remainder as r.
|
||||
//
|
||||
// A PAX record is of the following form:
|
||||
// "%d %s=%s\n" % (size, key, value)
|
||||
func parsePAXRecord(s string) (k, v, r string, err error) {
|
||||
// The size field ends at the first space.
|
||||
sp := strings.IndexByte(s, ' ')
|
||||
if sp == -1 {
|
||||
return "", "", s, ErrHeader
|
||||
}
|
||||
|
||||
// Parse the first token as a decimal integer.
|
||||
n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int
|
||||
if perr != nil || n < 5 || int64(len(s)) < n {
|
||||
return "", "", s, ErrHeader
|
||||
}
|
||||
|
||||
// Extract everything between the space and the final newline.
|
||||
rec, nl, rem := s[sp+1:n-1], s[n-1:n], s[n:]
|
||||
if nl != "\n" {
|
||||
return "", "", s, ErrHeader
|
||||
}
|
||||
|
||||
// The first equals separates the key from the value.
|
||||
eq := strings.IndexByte(rec, '=')
|
||||
if eq == -1 {
|
||||
return "", "", s, ErrHeader
|
||||
}
|
||||
return rec[:eq], rec[eq+1:], rem, nil
|
||||
}
|
||||
|
||||
// formatPAXRecord formats a single PAX record, prefixing it with the
|
||||
// appropriate length.
|
||||
func formatPAXRecord(k, v string) string {
|
||||
const padding = 3 // Extra padding for ' ', '=', and '\n'
|
||||
size := len(k) + len(v) + padding
|
||||
size += len(strconv.Itoa(size))
|
||||
record := fmt.Sprintf("%d %s=%s\n", size, k, v)
|
||||
|
||||
// Final adjustment if adding size field increased the record size.
|
||||
if len(record) != size {
|
||||
size = len(record)
|
||||
record = fmt.Sprintf("%d %s=%s\n", size, k, v)
|
||||
}
|
||||
return record
|
||||
}
|
||||
@@ -1,319 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package tar
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFitsInBase256(t *testing.T) {
|
||||
vectors := []struct {
|
||||
in int64
|
||||
width int
|
||||
ok bool
|
||||
}{
|
||||
{+1, 8, true},
|
||||
{0, 8, true},
|
||||
{-1, 8, true},
|
||||
{1 << 56, 8, false},
|
||||
{(1 << 56) - 1, 8, true},
|
||||
{-1 << 56, 8, true},
|
||||
{(-1 << 56) - 1, 8, false},
|
||||
{121654, 8, true},
|
||||
{-9849849, 8, true},
|
||||
{math.MaxInt64, 9, true},
|
||||
{0, 9, true},
|
||||
{math.MinInt64, 9, true},
|
||||
{math.MaxInt64, 12, true},
|
||||
{0, 12, true},
|
||||
{math.MinInt64, 12, true},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
ok := fitsInBase256(v.width, v.in)
|
||||
if ok != v.ok {
|
||||
t.Errorf("fitsInBase256(%d, %d): got %v, want %v", v.in, v.width, ok, v.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseNumeric(t *testing.T) {
|
||||
vectors := []struct {
|
||||
in string
|
||||
want int64
|
||||
ok bool
|
||||
}{
|
||||
// Test base-256 (binary) encoded values.
|
||||
{"", 0, true},
|
||||
{"\x80", 0, true},
|
||||
{"\x80\x00", 0, true},
|
||||
{"\x80\x00\x00", 0, true},
|
||||
{"\xbf", (1 << 6) - 1, true},
|
||||
{"\xbf\xff", (1 << 14) - 1, true},
|
||||
{"\xbf\xff\xff", (1 << 22) - 1, true},
|
||||
{"\xff", -1, true},
|
||||
{"\xff\xff", -1, true},
|
||||
{"\xff\xff\xff", -1, true},
|
||||
{"\xc0", -1 * (1 << 6), true},
|
||||
{"\xc0\x00", -1 * (1 << 14), true},
|
||||
{"\xc0\x00\x00", -1 * (1 << 22), true},
|
||||
{"\x87\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
|
||||
{"\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
|
||||
{"\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
|
||||
{"\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
|
||||
{"\x80\x7f\xff\xff\xff\xff\xff\xff\xff", math.MaxInt64, true},
|
||||
{"\x80\x80\x00\x00\x00\x00\x00\x00\x00", 0, false},
|
||||
{"\xff\x80\x00\x00\x00\x00\x00\x00\x00", math.MinInt64, true},
|
||||
{"\xff\x7f\xff\xff\xff\xff\xff\xff\xff", 0, false},
|
||||
{"\xf5\xec\xd1\xc7\x7e\x5f\x26\x48\x81\x9f\x8f\x9b", 0, false},
|
||||
|
||||
// Test base-8 (octal) encoded values.
|
||||
{"0000000\x00", 0, true},
|
||||
{" \x0000000\x00", 0, true},
|
||||
{" \x0000003\x00", 3, true},
|
||||
{"00000000227\x00", 0227, true},
|
||||
{"032033\x00 ", 032033, true},
|
||||
{"320330\x00 ", 0320330, true},
|
||||
{"0000660\x00 ", 0660, true},
|
||||
{"\x00 0000660\x00 ", 0660, true},
|
||||
{"0123456789abcdef", 0, false},
|
||||
{"0123456789\x00abcdef", 0, false},
|
||||
{"01234567\x0089abcdef", 342391, true},
|
||||
{"0123\x7e\x5f\x264123", 0, false},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
var p parser
|
||||
got := p.parseNumeric([]byte(v.in))
|
||||
ok := (p.err == nil)
|
||||
if ok != v.ok {
|
||||
if v.ok {
|
||||
t.Errorf("parseNumeric(%q): got parsing failure, want success", v.in)
|
||||
} else {
|
||||
t.Errorf("parseNumeric(%q): got parsing success, want failure", v.in)
|
||||
}
|
||||
}
|
||||
if ok && got != v.want {
|
||||
t.Errorf("parseNumeric(%q): got %d, want %d", v.in, got, v.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatNumeric(t *testing.T) {
|
||||
vectors := []struct {
|
||||
in int64
|
||||
want string
|
||||
ok bool
|
||||
}{
|
||||
// Test base-256 (binary) encoded values.
|
||||
{-1, "\xff", true},
|
||||
{-1, "\xff\xff", true},
|
||||
{-1, "\xff\xff\xff", true},
|
||||
{(1 << 0), "0", false},
|
||||
{(1 << 8) - 1, "\x80\xff", true},
|
||||
{(1 << 8), "0\x00", false},
|
||||
{(1 << 16) - 1, "\x80\xff\xff", true},
|
||||
{(1 << 16), "00\x00", false},
|
||||
{-1 * (1 << 0), "\xff", true},
|
||||
{-1*(1<<0) - 1, "0", false},
|
||||
{-1 * (1 << 8), "\xff\x00", true},
|
||||
{-1*(1<<8) - 1, "0\x00", false},
|
||||
{-1 * (1 << 16), "\xff\x00\x00", true},
|
||||
{-1*(1<<16) - 1, "00\x00", false},
|
||||
{537795476381659745, "0000000\x00", false},
|
||||
{537795476381659745, "\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", true},
|
||||
{-615126028225187231, "0000000\x00", false},
|
||||
{-615126028225187231, "\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", true},
|
||||
{math.MaxInt64, "0000000\x00", false},
|
||||
{math.MaxInt64, "\x80\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff", true},
|
||||
{math.MinInt64, "0000000\x00", false},
|
||||
{math.MinInt64, "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
|
||||
{math.MaxInt64, "\x80\x7f\xff\xff\xff\xff\xff\xff\xff", true},
|
||||
{math.MinInt64, "\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
var f formatter
|
||||
got := make([]byte, len(v.want))
|
||||
f.formatNumeric(got, v.in)
|
||||
ok := (f.err == nil)
|
||||
if ok != v.ok {
|
||||
if v.ok {
|
||||
t.Errorf("formatNumeric(%d): got formatting failure, want success", v.in)
|
||||
} else {
|
||||
t.Errorf("formatNumeric(%d): got formatting success, want failure", v.in)
|
||||
}
|
||||
}
|
||||
if string(got) != v.want {
|
||||
t.Errorf("formatNumeric(%d): got %q, want %q", v.in, got, v.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePAXTime(t *testing.T) {
|
||||
vectors := []struct {
|
||||
in string
|
||||
want time.Time
|
||||
ok bool
|
||||
}{
|
||||
{"1350244992.023960108", time.Unix(1350244992, 23960108), true},
|
||||
{"1350244992.02396010", time.Unix(1350244992, 23960100), true},
|
||||
{"1350244992.0239601089", time.Unix(1350244992, 23960108), true},
|
||||
{"1350244992.3", time.Unix(1350244992, 300000000), true},
|
||||
{"1350244992", time.Unix(1350244992, 0), true},
|
||||
{"-1.000000001", time.Unix(-1, -1e0+0e0), true},
|
||||
{"-1.000001", time.Unix(-1, -1e3+0e0), true},
|
||||
{"-1.001000", time.Unix(-1, -1e6+0e0), true},
|
||||
{"-1", time.Unix(-1, -0e0+0e0), true},
|
||||
{"-1.999000", time.Unix(-1, -1e9+1e6), true},
|
||||
{"-1.999999", time.Unix(-1, -1e9+1e3), true},
|
||||
{"-1.999999999", time.Unix(-1, -1e9+1e0), true},
|
||||
{"0.000000001", time.Unix(0, 1e0+0e0), true},
|
||||
{"0.000001", time.Unix(0, 1e3+0e0), true},
|
||||
{"0.001000", time.Unix(0, 1e6+0e0), true},
|
||||
{"0", time.Unix(0, 0e0), true},
|
||||
{"0.999000", time.Unix(0, 1e9-1e6), true},
|
||||
{"0.999999", time.Unix(0, 1e9-1e3), true},
|
||||
{"0.999999999", time.Unix(0, 1e9-1e0), true},
|
||||
{"1.000000001", time.Unix(+1, +1e0-0e0), true},
|
||||
{"1.000001", time.Unix(+1, +1e3-0e0), true},
|
||||
{"1.001000", time.Unix(+1, +1e6-0e0), true},
|
||||
{"1", time.Unix(+1, +0e0-0e0), true},
|
||||
{"1.999000", time.Unix(+1, +1e9-1e6), true},
|
||||
{"1.999999", time.Unix(+1, +1e9-1e3), true},
|
||||
{"1.999999999", time.Unix(+1, +1e9-1e0), true},
|
||||
{"-1350244992.023960108", time.Unix(-1350244992, -23960108), true},
|
||||
{"-1350244992.02396010", time.Unix(-1350244992, -23960100), true},
|
||||
{"-1350244992.0239601089", time.Unix(-1350244992, -23960108), true},
|
||||
{"-1350244992.3", time.Unix(-1350244992, -300000000), true},
|
||||
{"-1350244992", time.Unix(-1350244992, 0), true},
|
||||
{"", time.Time{}, false},
|
||||
{"0", time.Unix(0, 0), true},
|
||||
{"1.", time.Unix(1, 0), true},
|
||||
{"0.0", time.Unix(0, 0), true},
|
||||
{".5", time.Time{}, false},
|
||||
{"-1.3", time.Unix(-1, -3e8), true},
|
||||
{"-1.0", time.Unix(-1, -0e0), true},
|
||||
{"-0.0", time.Unix(-0, -0e0), true},
|
||||
{"-0.1", time.Unix(-0, -1e8), true},
|
||||
{"-0.01", time.Unix(-0, -1e7), true},
|
||||
{"-0.99", time.Unix(-0, -99e7), true},
|
||||
{"-0.98", time.Unix(-0, -98e7), true},
|
||||
{"-1.1", time.Unix(-1, -1e8), true},
|
||||
{"-1.01", time.Unix(-1, -1e7), true},
|
||||
{"-2.99", time.Unix(-2, -99e7), true},
|
||||
{"-5.98", time.Unix(-5, -98e7), true},
|
||||
{"-", time.Time{}, false},
|
||||
{"+", time.Time{}, false},
|
||||
{"-1.-1", time.Time{}, false},
|
||||
{"99999999999999999999999999999999999999999999999", time.Time{}, false},
|
||||
{"0.123456789abcdef", time.Time{}, false},
|
||||
{"foo", time.Time{}, false},
|
||||
{"\x00", time.Time{}, false},
|
||||
{"𝟵𝟴𝟳𝟲𝟱.𝟰𝟯𝟮𝟭𝟬", time.Time{}, false}, // Unicode numbers (U+1D7EC to U+1D7F5)
|
||||
{"98765﹒43210", time.Time{}, false}, // Unicode period (U+FE52)
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
ts, err := parsePAXTime(v.in)
|
||||
ok := (err == nil)
|
||||
if v.ok != ok {
|
||||
if v.ok {
|
||||
t.Errorf("parsePAXTime(%q): got parsing failure, want success", v.in)
|
||||
} else {
|
||||
t.Errorf("parsePAXTime(%q): got parsing success, want failure", v.in)
|
||||
}
|
||||
}
|
||||
if ok && !ts.Equal(v.want) {
|
||||
t.Errorf("parsePAXTime(%q): got (%ds %dns), want (%ds %dns)",
|
||||
v.in, ts.Unix(), ts.Nanosecond(), v.want.Unix(), v.want.Nanosecond())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePAXRecord(t *testing.T) {
|
||||
medName := strings.Repeat("CD", 50)
|
||||
longName := strings.Repeat("AB", 100)
|
||||
|
||||
vectors := []struct {
|
||||
in string
|
||||
wantRes string
|
||||
wantKey string
|
||||
wantVal string
|
||||
ok bool
|
||||
}{
|
||||
{"6 k=v\n\n", "\n", "k", "v", true},
|
||||
{"19 path=/etc/hosts\n", "", "path", "/etc/hosts", true},
|
||||
{"210 path=" + longName + "\nabc", "abc", "path", longName, true},
|
||||
{"110 path=" + medName + "\n", "", "path", medName, true},
|
||||
{"9 foo=ba\n", "", "foo", "ba", true},
|
||||
{"11 foo=bar\n\x00", "\x00", "foo", "bar", true},
|
||||
{"18 foo=b=\nar=\n==\x00\n", "", "foo", "b=\nar=\n==\x00", true},
|
||||
{"27 foo=hello9 foo=ba\nworld\n", "", "foo", "hello9 foo=ba\nworld", true},
|
||||
{"27 ☺☻☹=日a本b語ç\nmeow mix", "meow mix", "☺☻☹", "日a本b語ç", true},
|
||||
{"17 \x00hello=\x00world\n", "", "\x00hello", "\x00world", true},
|
||||
{"1 k=1\n", "1 k=1\n", "", "", false},
|
||||
{"6 k~1\n", "6 k~1\n", "", "", false},
|
||||
{"6_k=1\n", "6_k=1\n", "", "", false},
|
||||
{"6 k=1 ", "6 k=1 ", "", "", false},
|
||||
{"632 k=1\n", "632 k=1\n", "", "", false},
|
||||
{"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
|
||||
{"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
|
||||
{"50 tooshort=\n", "50 tooshort=\n", "", "", false},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
key, val, res, err := parsePAXRecord(v.in)
|
||||
ok := (err == nil)
|
||||
if ok != v.ok {
|
||||
if v.ok {
|
||||
t.Errorf("parsePAXRecord(%q): got parsing failure, want success", v.in)
|
||||
} else {
|
||||
t.Errorf("parsePAXRecord(%q): got parsing success, want failure", v.in)
|
||||
}
|
||||
}
|
||||
if v.ok && (key != v.wantKey || val != v.wantVal) {
|
||||
t.Errorf("parsePAXRecord(%q): got (%q: %q), want (%q: %q)",
|
||||
v.in, key, val, v.wantKey, v.wantVal)
|
||||
}
|
||||
if res != v.wantRes {
|
||||
t.Errorf("parsePAXRecord(%q): got residual %q, want residual %q",
|
||||
v.in, res, v.wantRes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatPAXRecord(t *testing.T) {
|
||||
medName := strings.Repeat("CD", 50)
|
||||
longName := strings.Repeat("AB", 100)
|
||||
|
||||
vectors := []struct {
|
||||
inKey string
|
||||
inVal string
|
||||
want string
|
||||
}{
|
||||
{"k", "v", "6 k=v\n"},
|
||||
{"path", "/etc/hosts", "19 path=/etc/hosts\n"},
|
||||
{"path", longName, "210 path=" + longName + "\n"},
|
||||
{"path", medName, "110 path=" + medName + "\n"},
|
||||
{"foo", "ba", "9 foo=ba\n"},
|
||||
{"foo", "bar", "11 foo=bar\n"},
|
||||
{"foo", "b=\nar=\n==\x00", "18 foo=b=\nar=\n==\x00\n"},
|
||||
{"foo", "hello9 foo=ba\nworld", "27 foo=hello9 foo=ba\nworld\n"},
|
||||
{"☺☻☹", "日a本b語ç", "27 ☺☻☹=日a本b語ç\n"},
|
||||
{"\x00hello", "\x00world", "17 \x00hello=\x00world\n"},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
got := formatPAXRecord(v.inKey, v.inVal)
|
||||
if got != v.want {
|
||||
t.Errorf("formatPAXRecord(%q, %q): got %q, want %q",
|
||||
v.inKey, v.inVal, got, v.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,178 +135,190 @@ type headerRoundTripTest struct {
|
||||
}
|
||||
|
||||
func TestHeaderRoundTrip(t *testing.T) {
|
||||
vectors := []headerRoundTripTest{{
|
||||
golden := []headerRoundTripTest{
|
||||
// regular file.
|
||||
h: &Header{
|
||||
Name: "test.txt",
|
||||
Mode: 0644 | c_ISREG,
|
||||
Size: 12,
|
||||
ModTime: time.Unix(1360600916, 0),
|
||||
Typeflag: TypeReg,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "test.txt",
|
||||
Mode: 0644 | c_ISREG,
|
||||
Size: 12,
|
||||
ModTime: time.Unix(1360600916, 0),
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
fm: 0644,
|
||||
},
|
||||
fm: 0644,
|
||||
}, {
|
||||
// symbolic link.
|
||||
h: &Header{
|
||||
Name: "link.txt",
|
||||
Mode: 0777 | c_ISLNK,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360600852, 0),
|
||||
Typeflag: TypeSymlink,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "link.txt",
|
||||
Mode: 0777 | c_ISLNK,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360600852, 0),
|
||||
Typeflag: TypeSymlink,
|
||||
},
|
||||
fm: 0777 | os.ModeSymlink,
|
||||
},
|
||||
fm: 0777 | os.ModeSymlink,
|
||||
}, {
|
||||
// character device node.
|
||||
h: &Header{
|
||||
Name: "dev/null",
|
||||
Mode: 0666 | c_ISCHR,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360578951, 0),
|
||||
Typeflag: TypeChar,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "dev/null",
|
||||
Mode: 0666 | c_ISCHR,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360578951, 0),
|
||||
Typeflag: TypeChar,
|
||||
},
|
||||
fm: 0666 | os.ModeDevice | os.ModeCharDevice,
|
||||
},
|
||||
fm: 0666 | os.ModeDevice | os.ModeCharDevice,
|
||||
}, {
|
||||
// block device node.
|
||||
h: &Header{
|
||||
Name: "dev/sda",
|
||||
Mode: 0660 | c_ISBLK,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360578954, 0),
|
||||
Typeflag: TypeBlock,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "dev/sda",
|
||||
Mode: 0660 | c_ISBLK,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360578954, 0),
|
||||
Typeflag: TypeBlock,
|
||||
},
|
||||
fm: 0660 | os.ModeDevice,
|
||||
},
|
||||
fm: 0660 | os.ModeDevice,
|
||||
}, {
|
||||
// directory.
|
||||
h: &Header{
|
||||
Name: "dir/",
|
||||
Mode: 0755 | c_ISDIR,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360601116, 0),
|
||||
Typeflag: TypeDir,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "dir/",
|
||||
Mode: 0755 | c_ISDIR,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360601116, 0),
|
||||
Typeflag: TypeDir,
|
||||
},
|
||||
fm: 0755 | os.ModeDir,
|
||||
},
|
||||
fm: 0755 | os.ModeDir,
|
||||
}, {
|
||||
// fifo node.
|
||||
h: &Header{
|
||||
Name: "dev/initctl",
|
||||
Mode: 0600 | c_ISFIFO,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360578949, 0),
|
||||
Typeflag: TypeFifo,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "dev/initctl",
|
||||
Mode: 0600 | c_ISFIFO,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360578949, 0),
|
||||
Typeflag: TypeFifo,
|
||||
},
|
||||
fm: 0600 | os.ModeNamedPipe,
|
||||
},
|
||||
fm: 0600 | os.ModeNamedPipe,
|
||||
}, {
|
||||
// setuid.
|
||||
h: &Header{
|
||||
Name: "bin/su",
|
||||
Mode: 0755 | c_ISREG | c_ISUID,
|
||||
Size: 23232,
|
||||
ModTime: time.Unix(1355405093, 0),
|
||||
Typeflag: TypeReg,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "bin/su",
|
||||
Mode: 0755 | c_ISREG | c_ISUID,
|
||||
Size: 23232,
|
||||
ModTime: time.Unix(1355405093, 0),
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
fm: 0755 | os.ModeSetuid,
|
||||
},
|
||||
fm: 0755 | os.ModeSetuid,
|
||||
}, {
|
||||
// setguid.
|
||||
h: &Header{
|
||||
Name: "group.txt",
|
||||
Mode: 0750 | c_ISREG | c_ISGID,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360602346, 0),
|
||||
Typeflag: TypeReg,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "group.txt",
|
||||
Mode: 0750 | c_ISREG | c_ISGID,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1360602346, 0),
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
fm: 0750 | os.ModeSetgid,
|
||||
},
|
||||
fm: 0750 | os.ModeSetgid,
|
||||
}, {
|
||||
// sticky.
|
||||
h: &Header{
|
||||
Name: "sticky.txt",
|
||||
Mode: 0600 | c_ISREG | c_ISVTX,
|
||||
Size: 7,
|
||||
ModTime: time.Unix(1360602540, 0),
|
||||
Typeflag: TypeReg,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "sticky.txt",
|
||||
Mode: 0600 | c_ISREG | c_ISVTX,
|
||||
Size: 7,
|
||||
ModTime: time.Unix(1360602540, 0),
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
fm: 0600 | os.ModeSticky,
|
||||
},
|
||||
fm: 0600 | os.ModeSticky,
|
||||
}, {
|
||||
// hard link.
|
||||
h: &Header{
|
||||
Name: "hard.txt",
|
||||
Mode: 0644 | c_ISREG,
|
||||
Size: 0,
|
||||
Linkname: "file.txt",
|
||||
ModTime: time.Unix(1360600916, 0),
|
||||
Typeflag: TypeLink,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "hard.txt",
|
||||
Mode: 0644 | c_ISREG,
|
||||
Size: 0,
|
||||
Linkname: "file.txt",
|
||||
ModTime: time.Unix(1360600916, 0),
|
||||
Typeflag: TypeLink,
|
||||
},
|
||||
fm: 0644,
|
||||
},
|
||||
fm: 0644,
|
||||
}, {
|
||||
// More information.
|
||||
h: &Header{
|
||||
Name: "info.txt",
|
||||
Mode: 0600 | c_ISREG,
|
||||
Size: 0,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
ModTime: time.Unix(1360602540, 0),
|
||||
Uname: "slartibartfast",
|
||||
Gname: "users",
|
||||
Typeflag: TypeReg,
|
||||
{
|
||||
h: &Header{
|
||||
Name: "info.txt",
|
||||
Mode: 0600 | c_ISREG,
|
||||
Size: 0,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
ModTime: time.Unix(1360602540, 0),
|
||||
Uname: "slartibartfast",
|
||||
Gname: "users",
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
fm: 0600,
|
||||
},
|
||||
fm: 0600,
|
||||
}}
|
||||
}
|
||||
|
||||
for i, v := range vectors {
|
||||
fi := v.h.FileInfo()
|
||||
for i, g := range golden {
|
||||
fi := g.h.FileInfo()
|
||||
h2, err := FileInfoHeader(fi, "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
if strings.Contains(fi.Name(), "/") {
|
||||
t.Errorf("FileInfo of %q contains slash: %q", v.h.Name, fi.Name())
|
||||
t.Errorf("FileInfo of %q contains slash: %q", g.h.Name, fi.Name())
|
||||
}
|
||||
name := path.Base(v.h.Name)
|
||||
name := path.Base(g.h.Name)
|
||||
if fi.IsDir() {
|
||||
name += "/"
|
||||
}
|
||||
if got, want := h2.Name, name; got != want {
|
||||
t.Errorf("i=%d: Name: got %v, want %v", i, got, want)
|
||||
}
|
||||
if got, want := h2.Size, v.h.Size; got != want {
|
||||
if got, want := h2.Size, g.h.Size; got != want {
|
||||
t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
|
||||
}
|
||||
if got, want := h2.Uid, v.h.Uid; got != want {
|
||||
if got, want := h2.Uid, g.h.Uid; got != want {
|
||||
t.Errorf("i=%d: Uid: got %d, want %d", i, got, want)
|
||||
}
|
||||
if got, want := h2.Gid, v.h.Gid; got != want {
|
||||
if got, want := h2.Gid, g.h.Gid; got != want {
|
||||
t.Errorf("i=%d: Gid: got %d, want %d", i, got, want)
|
||||
}
|
||||
if got, want := h2.Uname, v.h.Uname; got != want {
|
||||
if got, want := h2.Uname, g.h.Uname; got != want {
|
||||
t.Errorf("i=%d: Uname: got %q, want %q", i, got, want)
|
||||
}
|
||||
if got, want := h2.Gname, v.h.Gname; got != want {
|
||||
if got, want := h2.Gname, g.h.Gname; got != want {
|
||||
t.Errorf("i=%d: Gname: got %q, want %q", i, got, want)
|
||||
}
|
||||
if got, want := h2.Linkname, v.h.Linkname; got != want {
|
||||
if got, want := h2.Linkname, g.h.Linkname; got != want {
|
||||
t.Errorf("i=%d: Linkname: got %v, want %v", i, got, want)
|
||||
}
|
||||
if got, want := h2.Typeflag, v.h.Typeflag; got != want {
|
||||
t.Logf("%#v %#v", v.h, fi.Sys())
|
||||
if got, want := h2.Typeflag, g.h.Typeflag; got != want {
|
||||
t.Logf("%#v %#v", g.h, fi.Sys())
|
||||
t.Errorf("i=%d: Typeflag: got %q, want %q", i, got, want)
|
||||
}
|
||||
if got, want := h2.Mode, v.h.Mode; got != want {
|
||||
if got, want := h2.Mode, g.h.Mode; got != want {
|
||||
t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
|
||||
}
|
||||
if got, want := fi.Mode(), v.fm; got != want {
|
||||
if got, want := fi.Mode(), g.fm; got != want {
|
||||
t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
|
||||
}
|
||||
if got, want := h2.AccessTime, v.h.AccessTime; got != want {
|
||||
if got, want := h2.AccessTime, g.h.AccessTime; got != want {
|
||||
t.Errorf("i=%d: AccessTime: got %v, want %v", i, got, want)
|
||||
}
|
||||
if got, want := h2.ChangeTime, v.h.ChangeTime; got != want {
|
||||
if got, want := h2.ChangeTime, g.h.ChangeTime; got != want {
|
||||
t.Errorf("i=%d: ChangeTime: got %v, want %v", i, got, want)
|
||||
}
|
||||
if got, want := h2.ModTime, v.h.ModTime; got != want {
|
||||
if got, want := h2.ModTime, g.h.ModTime; got != want {
|
||||
t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
|
||||
}
|
||||
if sysh, ok := fi.Sys().(*Header); !ok || sysh != v.h {
|
||||
if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h {
|
||||
t.Errorf("i=%d: Sys didn't return original *Header", i)
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/archive/tar/testdata/gnu-incremental.tar
vendored
BIN
src/archive/tar/testdata/gnu-incremental.tar
vendored
Binary file not shown.
BIN
src/archive/tar/testdata/pax-bad-hdr-file.tar
vendored
BIN
src/archive/tar/testdata/pax-bad-hdr-file.tar
vendored
Binary file not shown.
BIN
src/archive/tar/testdata/pax-bad-mtime-file.tar
vendored
BIN
src/archive/tar/testdata/pax-bad-mtime-file.tar
vendored
Binary file not shown.
BIN
src/archive/tar/testdata/pax-pos-size-file.tar
vendored
BIN
src/archive/tar/testdata/pax-pos-size-file.tar
vendored
Binary file not shown.
BIN
src/archive/tar/testdata/ustar.issue12594.tar
vendored
BIN
src/archive/tar/testdata/ustar.issue12594.tar
vendored
Binary file not shown.
BIN
src/archive/tar/testdata/writer-big-long.tar
vendored
BIN
src/archive/tar/testdata/writer-big-long.tar
vendored
Binary file not shown.
@@ -42,6 +42,10 @@ type Writer struct {
|
||||
paxHdrBuff block // buffer to use in writeHeader when writing a PAX header
|
||||
}
|
||||
|
||||
type formatter struct {
|
||||
err error // Last error seen
|
||||
}
|
||||
|
||||
// NewWriter creates a new Writer writing to w.
|
||||
func NewWriter(w io.Writer) *Writer { return &Writer{w: w} }
|
||||
|
||||
@@ -67,6 +71,56 @@ func (tw *Writer) Flush() error {
|
||||
return tw.err
|
||||
}
|
||||
|
||||
// Write s into b, terminating it with a NUL if there is room.
|
||||
func (f *formatter) formatString(b []byte, s string) {
|
||||
if len(s) > len(b) {
|
||||
f.err = ErrFieldTooLong
|
||||
return
|
||||
}
|
||||
ascii := toASCII(s)
|
||||
copy(b, ascii)
|
||||
if len(ascii) < len(b) {
|
||||
b[len(ascii)] = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Encode x as an octal ASCII string and write it into b with leading zeros.
|
||||
func (f *formatter) formatOctal(b []byte, x int64) {
|
||||
s := strconv.FormatInt(x, 8)
|
||||
// leading zeros, but leave room for a NUL.
|
||||
for len(s)+1 < len(b) {
|
||||
s = "0" + s
|
||||
}
|
||||
f.formatString(b, s)
|
||||
}
|
||||
|
||||
// fitsInBase256 reports whether x can be encoded into n bytes using base-256
|
||||
// encoding. Unlike octal encoding, base-256 encoding does not require that the
|
||||
// string ends with a NUL character. Thus, all n bytes are available for output.
|
||||
//
|
||||
// If operating in binary mode, this assumes strict GNU binary mode; which means
|
||||
// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is
|
||||
// equivalent to the sign bit in two's complement form.
|
||||
func fitsInBase256(n int, x int64) bool {
|
||||
var binBits = uint(n-1) * 8
|
||||
return n >= 9 || (x >= -1<<binBits && x < 1<<binBits)
|
||||
}
|
||||
|
||||
// Write x into b, as binary (GNUtar/star extension).
|
||||
func (f *formatter) formatNumeric(b []byte, x int64) {
|
||||
if fitsInBase256(len(b), x) {
|
||||
for i := len(b) - 1; i >= 0; i-- {
|
||||
b[i] = byte(x)
|
||||
x >>= 8
|
||||
}
|
||||
b[0] |= 0x80 // Highest bit indicates binary format
|
||||
return
|
||||
}
|
||||
|
||||
f.formatOctal(b, 0) // Last resort, just write zero
|
||||
f.err = ErrFieldTooLong
|
||||
}
|
||||
|
||||
var (
|
||||
minTime = time.Unix(0, 0)
|
||||
// There is room for 11 octal digits (33 bits) of mtime.
|
||||
@@ -170,41 +224,9 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
|
||||
formatNumeric(ustar.DevMajor(), hdr.Devmajor, paxNone)
|
||||
formatNumeric(ustar.DevMinor(), hdr.Devminor, paxNone)
|
||||
|
||||
// TODO(dsnet): The logic surrounding the prefix field is broken when trying
|
||||
// to encode the header as GNU format. The challenge with the current logic
|
||||
// is that we are unsure what format we are using at any given moment until
|
||||
// we have processed *all* of the fields. The problem is that by the time
|
||||
// all fields have been processed, some work has already been done to handle
|
||||
// each field under the assumption that it is for one given format or
|
||||
// another. In some situations, this causes the Writer to be confused and
|
||||
// encode a prefix field when the format being used is GNU. Thus, producing
|
||||
// an invalid tar file.
|
||||
//
|
||||
// As a short-term fix, we disable the logic to use the prefix field, which
|
||||
// will force the badly generated GNU files to become encoded as being
|
||||
// the PAX format.
|
||||
//
|
||||
// As an alternative fix, we could hard-code preferPax to be true. However,
|
||||
// this is problematic for the following reasons:
|
||||
// * The preferPax functionality is not tested at all.
|
||||
// * This can result in headers that try to use both the GNU and PAX
|
||||
// features at the same time, which is also wrong.
|
||||
//
|
||||
// The proper fix for this is to use a two-pass method:
|
||||
// * The first pass simply determines what set of formats can possibly
|
||||
// encode the given header.
|
||||
// * The second pass actually encodes the header as that given format
|
||||
// without worrying about violating the format.
|
||||
//
|
||||
// See the following:
|
||||
// https://golang.org/issue/12594
|
||||
// https://golang.org/issue/17630
|
||||
// https://golang.org/issue/9683
|
||||
const usePrefix = false
|
||||
|
||||
// try to use a ustar header when only the name is too long
|
||||
_, paxPathUsed := paxHeaders[paxPath]
|
||||
if usePrefix && !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
|
||||
if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
|
||||
prefix, suffix, ok := splitUSTARPath(hdr.Name)
|
||||
if ok {
|
||||
// Since we can encode in USTAR format, disable PAX header.
|
||||
@@ -318,6 +340,22 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
// formatPAXRecord formats a single PAX record, prefixing it with the
|
||||
// appropriate length.
|
||||
func formatPAXRecord(k, v string) string {
|
||||
const padding = 3 // Extra padding for ' ', '=', and '\n'
|
||||
size := len(k) + len(v) + padding
|
||||
size += len(strconv.Itoa(size))
|
||||
record := fmt.Sprintf("%d %s=%s\n", size, k, v)
|
||||
|
||||
// Final adjustment if adding size field increased the record size.
|
||||
if len(record) != size {
|
||||
size = len(record)
|
||||
record = fmt.Sprintf("%d %s=%s\n", size, k, v)
|
||||
}
|
||||
return record
|
||||
}
|
||||
|
||||
// Write writes to the current entry in the tar archive.
|
||||
// Write returns the error ErrWriteTooLong if more than
|
||||
// hdr.Size bytes are written after WriteHeader.
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
@@ -18,6 +19,176 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type writerTestEntry struct {
|
||||
header *Header
|
||||
contents string
|
||||
}
|
||||
|
||||
type writerTest struct {
|
||||
file string // filename of expected output
|
||||
entries []*writerTestEntry
|
||||
}
|
||||
|
||||
var writerTests = []*writerTest{
|
||||
// The writer test file was produced with this command:
|
||||
// tar (GNU tar) 1.26
|
||||
// ln -s small.txt link.txt
|
||||
// tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
|
||||
{
|
||||
file: "testdata/writer.tar",
|
||||
entries: []*writerTestEntry{
|
||||
{
|
||||
header: &Header{
|
||||
Name: "small.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 5,
|
||||
ModTime: time.Unix(1246508266, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
},
|
||||
contents: "Kilts",
|
||||
},
|
||||
{
|
||||
header: &Header{
|
||||
Name: "small2.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 11,
|
||||
ModTime: time.Unix(1245217492, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
},
|
||||
contents: "Google.com\n",
|
||||
},
|
||||
{
|
||||
header: &Header{
|
||||
Name: "link.txt",
|
||||
Mode: 0777,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1314603082, 0),
|
||||
Typeflag: '2',
|
||||
Linkname: "small.txt",
|
||||
Uname: "strings",
|
||||
Gname: "strings",
|
||||
},
|
||||
// no contents
|
||||
},
|
||||
},
|
||||
},
|
||||
// The truncated test file was produced using these commands:
|
||||
// dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
|
||||
// tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
|
||||
{
|
||||
file: "testdata/writer-big.tar",
|
||||
entries: []*writerTestEntry{
|
||||
{
|
||||
header: &Header{
|
||||
Name: "tmp/16gig.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 16 << 30,
|
||||
ModTime: time.Unix(1254699560, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
},
|
||||
// fake contents
|
||||
contents: strings.Repeat("\x00", 4<<10),
|
||||
},
|
||||
},
|
||||
},
|
||||
// The truncated test file was produced using these commands:
|
||||
// dd if=/dev/zero bs=1048576 count=16384 > (longname/)*15 /16gig.txt
|
||||
// tar -b 1 -c -f- (longname/)*15 /16gig.txt | dd bs=512 count=8 > writer-big-long.tar
|
||||
{
|
||||
file: "testdata/writer-big-long.tar",
|
||||
entries: []*writerTestEntry{
|
||||
{
|
||||
header: &Header{
|
||||
Name: strings.Repeat("longname/", 15) + "16gig.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Size: 16 << 30,
|
||||
ModTime: time.Unix(1399583047, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "guillaume",
|
||||
Gname: "guillaume",
|
||||
},
|
||||
// fake contents
|
||||
contents: strings.Repeat("\x00", 4<<10),
|
||||
},
|
||||
},
|
||||
},
|
||||
// This file was produced using gnu tar 1.17
|
||||
// gnutar -b 4 --format=ustar (longname/)*15 + file.txt
|
||||
{
|
||||
file: "testdata/ustar.tar",
|
||||
entries: []*writerTestEntry{
|
||||
{
|
||||
header: &Header{
|
||||
Name: strings.Repeat("longname/", 15) + "file.txt",
|
||||
Mode: 0644,
|
||||
Uid: 0765,
|
||||
Gid: 024,
|
||||
Size: 06,
|
||||
ModTime: time.Unix(1360135598, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "shane",
|
||||
Gname: "staff",
|
||||
},
|
||||
contents: "hello\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
// This file was produced using gnu tar 1.26
|
||||
// echo "Slartibartfast" > file.txt
|
||||
// ln file.txt hard.txt
|
||||
// tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt
|
||||
{
|
||||
file: "testdata/hardlink.tar",
|
||||
entries: []*writerTestEntry{
|
||||
{
|
||||
header: &Header{
|
||||
Name: "file.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 100,
|
||||
Size: 15,
|
||||
ModTime: time.Unix(1425484303, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "vbatts",
|
||||
Gname: "users",
|
||||
},
|
||||
contents: "Slartibartfast\n",
|
||||
},
|
||||
{
|
||||
header: &Header{
|
||||
Name: "hard.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 100,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1425484303, 0),
|
||||
Typeflag: '1',
|
||||
Linkname: "file.txt",
|
||||
Uname: "vbatts",
|
||||
Gname: "users",
|
||||
},
|
||||
// no contents
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
|
||||
func bytestr(offset int, b []byte) string {
|
||||
const rowLen = 32
|
||||
@@ -57,168 +228,9 @@ func bytediff(a []byte, b []byte) string {
|
||||
}
|
||||
|
||||
func TestWriter(t *testing.T) {
|
||||
type entry struct {
|
||||
header *Header
|
||||
contents string
|
||||
}
|
||||
|
||||
vectors := []struct {
|
||||
file string // filename of expected output
|
||||
entries []*entry
|
||||
}{{
|
||||
// The writer test file was produced with this command:
|
||||
// tar (GNU tar) 1.26
|
||||
// ln -s small.txt link.txt
|
||||
// tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
|
||||
file: "testdata/writer.tar",
|
||||
entries: []*entry{{
|
||||
header: &Header{
|
||||
Name: "small.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 5,
|
||||
ModTime: time.Unix(1246508266, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
},
|
||||
contents: "Kilts",
|
||||
}, {
|
||||
header: &Header{
|
||||
Name: "small2.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 11,
|
||||
ModTime: time.Unix(1245217492, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
},
|
||||
contents: "Google.com\n",
|
||||
}, {
|
||||
header: &Header{
|
||||
Name: "link.txt",
|
||||
Mode: 0777,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1314603082, 0),
|
||||
Typeflag: '2',
|
||||
Linkname: "small.txt",
|
||||
Uname: "strings",
|
||||
Gname: "strings",
|
||||
},
|
||||
// no contents
|
||||
}},
|
||||
}, {
|
||||
// The truncated test file was produced using these commands:
|
||||
// dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
|
||||
// tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
|
||||
file: "testdata/writer-big.tar",
|
||||
entries: []*entry{{
|
||||
header: &Header{
|
||||
Name: "tmp/16gig.txt",
|
||||
Mode: 0640,
|
||||
Uid: 73025,
|
||||
Gid: 5000,
|
||||
Size: 16 << 30,
|
||||
ModTime: time.Unix(1254699560, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "dsymonds",
|
||||
Gname: "eng",
|
||||
},
|
||||
// fake contents
|
||||
contents: strings.Repeat("\x00", 4<<10),
|
||||
}},
|
||||
}, {
|
||||
// This truncated file was produced using this library.
|
||||
// It was verified to work with GNU tar 1.27.1 and BSD tar 3.1.2.
|
||||
// dd if=/dev/zero bs=1G count=16 >> writer-big-long.tar
|
||||
// gnutar -xvf writer-big-long.tar
|
||||
// bsdtar -xvf writer-big-long.tar
|
||||
//
|
||||
// This file is in PAX format.
|
||||
file: "testdata/writer-big-long.tar",
|
||||
entries: []*entry{{
|
||||
header: &Header{
|
||||
Name: strings.Repeat("longname/", 15) + "16gig.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 1000,
|
||||
Size: 16 << 30,
|
||||
ModTime: time.Unix(1399583047, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "guillaume",
|
||||
Gname: "guillaume",
|
||||
},
|
||||
// fake contents
|
||||
contents: strings.Repeat("\x00", 4<<10),
|
||||
}},
|
||||
}, {
|
||||
// TODO(dsnet): The Writer output should match the following file.
|
||||
// To fix an issue (see https://golang.org/issue/12594), we disabled
|
||||
// prefix support, which alters the generated output.
|
||||
/*
|
||||
// This file was produced using gnu tar 1.17
|
||||
// gnutar -b 4 --format=ustar (longname/)*15 + file.txt
|
||||
file: "testdata/ustar.tar"
|
||||
*/
|
||||
file: "testdata/ustar.issue12594.tar", // This is a valid tar file, but not expected
|
||||
entries: []*entry{{
|
||||
header: &Header{
|
||||
Name: strings.Repeat("longname/", 15) + "file.txt",
|
||||
Mode: 0644,
|
||||
Uid: 0765,
|
||||
Gid: 024,
|
||||
Size: 06,
|
||||
ModTime: time.Unix(1360135598, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "shane",
|
||||
Gname: "staff",
|
||||
},
|
||||
contents: "hello\n",
|
||||
}},
|
||||
}, {
|
||||
// This file was produced using gnu tar 1.26
|
||||
// echo "Slartibartfast" > file.txt
|
||||
// ln file.txt hard.txt
|
||||
// tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt
|
||||
file: "testdata/hardlink.tar",
|
||||
entries: []*entry{{
|
||||
header: &Header{
|
||||
Name: "file.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 100,
|
||||
Size: 15,
|
||||
ModTime: time.Unix(1425484303, 0),
|
||||
Typeflag: '0',
|
||||
Uname: "vbatts",
|
||||
Gname: "users",
|
||||
},
|
||||
contents: "Slartibartfast\n",
|
||||
}, {
|
||||
header: &Header{
|
||||
Name: "hard.txt",
|
||||
Mode: 0644,
|
||||
Uid: 1000,
|
||||
Gid: 100,
|
||||
Size: 0,
|
||||
ModTime: time.Unix(1425484303, 0),
|
||||
Typeflag: '1',
|
||||
Linkname: "file.txt",
|
||||
Uname: "vbatts",
|
||||
Gname: "users",
|
||||
},
|
||||
// no contents
|
||||
}},
|
||||
}}
|
||||
|
||||
testLoop:
|
||||
for i, v := range vectors {
|
||||
expected, err := ioutil.ReadFile(v.file)
|
||||
for i, test := range writerTests {
|
||||
expected, err := ioutil.ReadFile(test.file)
|
||||
if err != nil {
|
||||
t.Errorf("test %d: Unexpected error: %v", i, err)
|
||||
continue
|
||||
@@ -227,7 +239,7 @@ testLoop:
|
||||
buf := new(bytes.Buffer)
|
||||
tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
|
||||
big := false
|
||||
for j, entry := range v.entries {
|
||||
for j, entry := range test.entries {
|
||||
big = big || entry.header.Size > 1<<10
|
||||
if err := tw.WriteHeader(entry.header); err != nil {
|
||||
t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err)
|
||||
@@ -564,9 +576,9 @@ func TestWriteAfterClose(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSplitUSTARPath(t *testing.T) {
|
||||
sr := strings.Repeat
|
||||
var sr = strings.Repeat
|
||||
|
||||
vectors := []struct {
|
||||
var vectors = []struct {
|
||||
input string // Input path
|
||||
prefix string // Expected output prefix
|
||||
suffix string // Expected output suffix
|
||||
@@ -597,51 +609,114 @@ func TestSplitUSTARPath(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestIssue12594 tests that the Writer does not attempt to populate the prefix
|
||||
// field when encoding a header in the GNU format. The prefix field is valid
|
||||
// in USTAR and PAX, but not GNU.
|
||||
func TestIssue12594(t *testing.T) {
|
||||
names := []string{
|
||||
"0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/file.txt",
|
||||
"0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/file.txt",
|
||||
"0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/333/file.txt",
|
||||
"0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/file.txt",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000/file.txt",
|
||||
"/home/support/.openoffice.org/3/user/uno_packages/cache/registry/com.sun.star.comp.deployment.executable.PackageRegistryBackend",
|
||||
func TestFormatPAXRecord(t *testing.T) {
|
||||
var medName = strings.Repeat("CD", 50)
|
||||
var longName = strings.Repeat("AB", 100)
|
||||
|
||||
var vectors = []struct {
|
||||
inputKey string
|
||||
inputVal string
|
||||
output string
|
||||
}{
|
||||
{"k", "v", "6 k=v\n"},
|
||||
{"path", "/etc/hosts", "19 path=/etc/hosts\n"},
|
||||
{"path", longName, "210 path=" + longName + "\n"},
|
||||
{"path", medName, "110 path=" + medName + "\n"},
|
||||
{"foo", "ba", "9 foo=ba\n"},
|
||||
{"foo", "bar", "11 foo=bar\n"},
|
||||
{"foo", "b=\nar=\n==\x00", "18 foo=b=\nar=\n==\x00\n"},
|
||||
{"foo", "hello9 foo=ba\nworld", "27 foo=hello9 foo=ba\nworld\n"},
|
||||
{"☺☻☹", "日a本b語ç", "27 ☺☻☹=日a本b語ç\n"},
|
||||
{"\x00hello", "\x00world", "17 \x00hello=\x00world\n"},
|
||||
}
|
||||
|
||||
for i, name := range names {
|
||||
var b bytes.Buffer
|
||||
|
||||
tw := NewWriter(&b)
|
||||
if err := tw.WriteHeader(&Header{
|
||||
Name: name,
|
||||
Uid: 1 << 25, // Prevent USTAR format
|
||||
}); err != nil {
|
||||
t.Errorf("test %d, unexpected WriteHeader error: %v", i, err)
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
t.Errorf("test %d, unexpected Close error: %v", i, err)
|
||||
}
|
||||
|
||||
// The prefix field should never appear in the GNU format.
|
||||
var blk block
|
||||
copy(blk[:], b.Bytes())
|
||||
prefix := string(blk.USTAR().Prefix())
|
||||
if i := strings.IndexByte(prefix, 0); i >= 0 {
|
||||
prefix = prefix[:i] // Truncate at the NUL terminator
|
||||
}
|
||||
if blk.GetFormat() == formatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) {
|
||||
t.Errorf("test %d, found prefix in GNU format: %s", i, prefix)
|
||||
}
|
||||
|
||||
tr := NewReader(&b)
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
t.Errorf("test %d, unexpected Next error: %v", i, err)
|
||||
}
|
||||
if hdr.Name != name {
|
||||
t.Errorf("test %d, hdr.Name = %s, want %s", i, hdr.Name, name)
|
||||
for _, v := range vectors {
|
||||
output := formatPAXRecord(v.inputKey, v.inputVal)
|
||||
if output != v.output {
|
||||
t.Errorf("formatPAXRecord(%q, %q): got %q, want %q",
|
||||
v.inputKey, v.inputVal, output, v.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFitsInBase256(t *testing.T) {
|
||||
var vectors = []struct {
|
||||
input int64
|
||||
width int
|
||||
ok bool
|
||||
}{
|
||||
{+1, 8, true},
|
||||
{0, 8, true},
|
||||
{-1, 8, true},
|
||||
{1 << 56, 8, false},
|
||||
{(1 << 56) - 1, 8, true},
|
||||
{-1 << 56, 8, true},
|
||||
{(-1 << 56) - 1, 8, false},
|
||||
{121654, 8, true},
|
||||
{-9849849, 8, true},
|
||||
{math.MaxInt64, 9, true},
|
||||
{0, 9, true},
|
||||
{math.MinInt64, 9, true},
|
||||
{math.MaxInt64, 12, true},
|
||||
{0, 12, true},
|
||||
{math.MinInt64, 12, true},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
ok := fitsInBase256(v.width, v.input)
|
||||
if ok != v.ok {
|
||||
t.Errorf("checkNumeric(%d, %d): got %v, want %v", v.input, v.width, ok, v.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatNumeric(t *testing.T) {
|
||||
var vectors = []struct {
|
||||
input int64
|
||||
output string
|
||||
ok bool
|
||||
}{
|
||||
// Test base-256 (binary) encoded values.
|
||||
{-1, "\xff", true},
|
||||
{-1, "\xff\xff", true},
|
||||
{-1, "\xff\xff\xff", true},
|
||||
{(1 << 0), "0", false},
|
||||
{(1 << 8) - 1, "\x80\xff", true},
|
||||
{(1 << 8), "0\x00", false},
|
||||
{(1 << 16) - 1, "\x80\xff\xff", true},
|
||||
{(1 << 16), "00\x00", false},
|
||||
{-1 * (1 << 0), "\xff", true},
|
||||
{-1*(1<<0) - 1, "0", false},
|
||||
{-1 * (1 << 8), "\xff\x00", true},
|
||||
{-1*(1<<8) - 1, "0\x00", false},
|
||||
{-1 * (1 << 16), "\xff\x00\x00", true},
|
||||
{-1*(1<<16) - 1, "00\x00", false},
|
||||
{537795476381659745, "0000000\x00", false},
|
||||
{537795476381659745, "\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", true},
|
||||
{-615126028225187231, "0000000\x00", false},
|
||||
{-615126028225187231, "\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", true},
|
||||
{math.MaxInt64, "0000000\x00", false},
|
||||
{math.MaxInt64, "\x80\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff", true},
|
||||
{math.MinInt64, "0000000\x00", false},
|
||||
{math.MinInt64, "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
|
||||
{math.MaxInt64, "\x80\x7f\xff\xff\xff\xff\xff\xff\xff", true},
|
||||
{math.MinInt64, "\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
|
||||
}
|
||||
|
||||
for _, v := range vectors {
|
||||
var f formatter
|
||||
output := make([]byte, len(v.output))
|
||||
f.formatNumeric(output, v.input)
|
||||
ok := (f.err == nil)
|
||||
if ok != v.ok {
|
||||
if v.ok {
|
||||
t.Errorf("formatNumeric(%d): got formatting failure, want success", v.input)
|
||||
} else {
|
||||
t.Errorf("formatNumeric(%d): got formatting success, want failure", v.input)
|
||||
}
|
||||
}
|
||||
if string(output) != v.output {
|
||||
t.Errorf("formatNumeric(%d): got %q, want %q", v.input, output, v.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -290,16 +289,13 @@ func readDirectoryHeader(f *File, r io.Reader) error {
|
||||
// Other zip authors might not even follow the basic format,
|
||||
// and we'll just ignore the Extra content in that case.
|
||||
b := readBuf(f.Extra)
|
||||
|
||||
Extras:
|
||||
for len(b) >= 4 { // need at least tag and size
|
||||
tag := b.uint16()
|
||||
size := b.uint16()
|
||||
if int(size) > len(b) {
|
||||
break
|
||||
}
|
||||
switch tag {
|
||||
case zip64ExtraId:
|
||||
if tag == zip64ExtraId {
|
||||
// update directory values from the zip64 extra block.
|
||||
// They should only be consulted if the sizes read earlier
|
||||
// are maxed out.
|
||||
@@ -327,42 +323,7 @@ func readDirectoryHeader(f *File, r io.Reader) error {
|
||||
}
|
||||
f.headerOffset = int64(eb.uint64())
|
||||
}
|
||||
break Extras
|
||||
|
||||
case ntfsExtraId:
|
||||
if size == 32 {
|
||||
eb := readBuf(b[:size])
|
||||
eb.uint32() // reserved
|
||||
eb.uint16() // tag1
|
||||
size1 := eb.uint16()
|
||||
if size1 == 24 {
|
||||
sub := readBuf(eb[:size1])
|
||||
lo := sub.uint32()
|
||||
hi := sub.uint32()
|
||||
tick := (uint64(uint64(lo)|uint64(hi)<<32) - 116444736000000000) / 10000000
|
||||
f.SetModTime(time.Unix(int64(tick), 0))
|
||||
}
|
||||
}
|
||||
break Extras
|
||||
|
||||
case unixExtraId:
|
||||
if size >= 12 {
|
||||
eb := readBuf(b[:size])
|
||||
eb.uint32() // AcTime
|
||||
epoch := eb.uint32() // ModTime
|
||||
f.SetModTime(time.Unix(int64(epoch), 0))
|
||||
break Extras
|
||||
}
|
||||
case exttsExtraId:
|
||||
if size >= 3 {
|
||||
eb := readBuf(b[:size])
|
||||
flags := eb.uint8() // Flags
|
||||
epoch := eb.uint32() // AcTime/ModTime/CrTime
|
||||
if flags&1 != 0 {
|
||||
f.SetModTime(time.Unix(int64(epoch), 0))
|
||||
}
|
||||
break Extras
|
||||
}
|
||||
break
|
||||
}
|
||||
b = b[size:]
|
||||
}
|
||||
@@ -547,12 +508,6 @@ func findSignatureInBlock(b []byte) int {
|
||||
|
||||
type readBuf []byte
|
||||
|
||||
func (b *readBuf) uint8() uint8 {
|
||||
v := uint8((*b)[0])
|
||||
*b = (*b)[1:]
|
||||
return v
|
||||
}
|
||||
|
||||
func (b *readBuf) uint16() uint16 {
|
||||
v := binary.LittleEndian.Uint16(*b)
|
||||
*b = (*b)[2:]
|
||||
|
||||
@@ -65,13 +65,13 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "test.txt",
|
||||
Content: []byte("This is a test text file.\n"),
|
||||
Mtime: "09-05-10 02:12:00",
|
||||
Mtime: "09-05-10 12:12:02",
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "gophercolor16x16.png",
|
||||
File: "gophercolor16x16.png",
|
||||
Mtime: "09-05-10 05:52:58",
|
||||
Mtime: "09-05-10 15:52:58",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
@@ -83,13 +83,13 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "test.txt",
|
||||
Content: []byte("This is a test text file.\n"),
|
||||
Mtime: "09-05-10 02:12:00",
|
||||
Mtime: "09-05-10 12:12:02",
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "gophercolor16x16.png",
|
||||
File: "gophercolor16x16.png",
|
||||
Mtime: "09-05-10 05:52:58",
|
||||
Mtime: "09-05-10 15:52:58",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
@@ -144,17 +144,6 @@ var tests = []ZipTest{
|
||||
Name: "unix.zip",
|
||||
File: crossPlatform,
|
||||
},
|
||||
{
|
||||
Name: "extra-timestamp.zip",
|
||||
File: []ZipTestFile{
|
||||
{
|
||||
Name: "hello.txt",
|
||||
Content: []byte(""),
|
||||
Mtime: "01-06-16 12:25:56",
|
||||
Mode: 0666,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// created by Go, before we wrote the "optional" data
|
||||
// descriptor signatures (which are required by OS X)
|
||||
@@ -163,13 +152,13 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "foo.txt",
|
||||
Content: []byte("foo\n"),
|
||||
Mtime: "03-09-12 00:59:10",
|
||||
Mtime: "03-08-12 16:59:10",
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "bar.txt",
|
||||
Content: []byte("bar\n"),
|
||||
Mtime: "03-09-12 00:59:12",
|
||||
Mtime: "03-08-12 16:59:12",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
@@ -216,13 +205,13 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "foo.txt",
|
||||
Content: []byte("foo\n"),
|
||||
Mtime: "03-09-12 00:59:10",
|
||||
Mtime: "03-08-12 16:59:10",
|
||||
Mode: 0644,
|
||||
},
|
||||
{
|
||||
Name: "bar.txt",
|
||||
Content: []byte("bar\n"),
|
||||
Mtime: "03-09-12 00:59:12",
|
||||
Mtime: "03-08-12 16:59:12",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
@@ -236,14 +225,14 @@ var tests = []ZipTest{
|
||||
{
|
||||
Name: "foo.txt",
|
||||
Content: []byte("foo\n"),
|
||||
Mtime: "03-09-12 00:59:10",
|
||||
Mtime: "03-08-12 16:59:10",
|
||||
Mode: 0644,
|
||||
ContentErr: ErrChecksum,
|
||||
},
|
||||
{
|
||||
Name: "bar.txt",
|
||||
Content: []byte("bar\n"),
|
||||
Mtime: "03-09-12 00:59:12",
|
||||
Mtime: "03-08-12 16:59:12",
|
||||
Mode: 0644,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -63,9 +63,6 @@ const (
|
||||
|
||||
// extra header id's
|
||||
zip64ExtraId = 0x0001 // zip64 Extended Information Extra Field
|
||||
ntfsExtraId = 0x000a // NTFS Extra Field
|
||||
unixExtraId = 0x000d // UNIX Extra Field
|
||||
exttsExtraId = 0x5455 // Extended Timestamp Extra Field
|
||||
)
|
||||
|
||||
// FileHeader describes a file within a zip file.
|
||||
|
||||
BIN
src/archive/zip/testdata/extra-timestamp.zip
vendored
BIN
src/archive/zip/testdata/extra-timestamp.zip
vendored
Binary file not shown.
@@ -98,19 +98,6 @@ func (w *Writer) Close() error {
|
||||
b.uint32(h.CompressedSize)
|
||||
b.uint32(h.UncompressedSize)
|
||||
}
|
||||
|
||||
// use Extended Timestamp Extra Field.
|
||||
if h.ModifiedTime != 0 || h.ModifiedDate != 0 {
|
||||
mt := uint32(h.ModTime().Unix())
|
||||
var mbuf [9]byte // 2x uint16 + uint8 + uint32
|
||||
eb := writeBuf(mbuf[:])
|
||||
eb.uint16(exttsExtraId)
|
||||
eb.uint16(5) // size = uint8 + uint32
|
||||
eb.uint8(1) // flags = modtime
|
||||
eb.uint32(mt) // ModTime
|
||||
h.Extra = append(h.Extra, mbuf[:]...)
|
||||
}
|
||||
|
||||
b.uint16(uint16(len(h.Name)))
|
||||
b.uint16(uint16(len(h.Extra)))
|
||||
b.uint16(uint16(len(h.Comment)))
|
||||
@@ -389,11 +376,6 @@ func (w nopCloser) Close() error {
|
||||
|
||||
type writeBuf []byte
|
||||
|
||||
func (b *writeBuf) uint8(v uint8) {
|
||||
(*b)[0] = v
|
||||
*b = (*b)[1:]
|
||||
}
|
||||
|
||||
func (b *writeBuf) uint16(v uint16) {
|
||||
binary.LittleEndian.PutUint16(*b, v)
|
||||
*b = (*b)[2:]
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TODO(adg): a more sophisticated test suite
|
||||
@@ -21,7 +20,6 @@ type WriteTest struct {
|
||||
Data []byte
|
||||
Method uint16
|
||||
Mode os.FileMode
|
||||
Mtime string
|
||||
}
|
||||
|
||||
var writeTests = []WriteTest{
|
||||
@@ -30,35 +28,30 @@ var writeTests = []WriteTest{
|
||||
Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."),
|
||||
Method: Store,
|
||||
Mode: 0666,
|
||||
Mtime: "02-01-08 00:01:02",
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
Data: nil, // large data set in the test
|
||||
Method: Deflate,
|
||||
Mode: 0644,
|
||||
Mtime: "03-02-08 01:02:03",
|
||||
},
|
||||
{
|
||||
Name: "setuid",
|
||||
Data: []byte("setuid file"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSetuid,
|
||||
Mtime: "04-03-08 02:03:04",
|
||||
},
|
||||
{
|
||||
Name: "setgid",
|
||||
Data: []byte("setgid file"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSetgid,
|
||||
Mtime: "05-04-08 03:04:04",
|
||||
},
|
||||
{
|
||||
Name: "symlink",
|
||||
Data: []byte("../link/target"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSymlink,
|
||||
Mtime: "03-02-08 11:22:33",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -155,11 +148,6 @@ func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
|
||||
if wt.Mode != 0 {
|
||||
header.SetMode(wt.Mode)
|
||||
}
|
||||
mtime, err := time.Parse("01-02-06 15:04:05", wt.Mtime)
|
||||
if err != nil {
|
||||
t.Fatal("time.Parse:", err)
|
||||
}
|
||||
header.SetModTime(mtime)
|
||||
f, err := w.CreateHeader(header)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -190,21 +178,6 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
|
||||
if !bytes.Equal(b, wt.Data) {
|
||||
t.Errorf("File contents %q, want %q", b, wt.Data)
|
||||
}
|
||||
|
||||
mtime, err := time.Parse("01-02-06 15:04:05", wt.Mtime)
|
||||
if err != nil {
|
||||
t.Fatal("time.Parse:", err)
|
||||
}
|
||||
|
||||
diff := mtime.Sub(f.ModTime())
|
||||
if diff < 0 {
|
||||
diff = -diff
|
||||
}
|
||||
|
||||
// allow several time span
|
||||
if diff > 5*time.Second {
|
||||
t.Errorf("File modtime %v, want %v", mtime, f.ModTime())
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompressedZipGarbage(b *testing.B) {
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -112,44 +111,6 @@ func TestFileHeaderRoundTrip64(t *testing.T) {
|
||||
testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t)
|
||||
}
|
||||
|
||||
func TestZeroFileRoundTrip(t *testing.T) {
|
||||
var b bytes.Buffer
|
||||
w := NewWriter(&b)
|
||||
if _, err := w.Create(""); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify that fields that should reasonably be the zero value stays
|
||||
// as the zero value.
|
||||
var want FileHeader
|
||||
if len(r.File) != 1 {
|
||||
t.Fatalf("len(r.File) = %d, want 1", len(r.File))
|
||||
}
|
||||
fh := r.File[0].FileHeader
|
||||
got := FileHeader{
|
||||
Name: fh.Name,
|
||||
ModifiedTime: fh.ModifiedTime,
|
||||
ModifiedDate: fh.ModifiedDate,
|
||||
UncompressedSize: fh.UncompressedSize,
|
||||
UncompressedSize64: fh.UncompressedSize64,
|
||||
ExternalAttrs: fh.ExternalAttrs,
|
||||
Comment: fh.Comment,
|
||||
}
|
||||
if len(fh.Extra) > 0 {
|
||||
got.Extra = fh.Extra
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("FileHeader mismatch:\ngot %#v\nwant %#v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type repeatedByte struct {
|
||||
off int64
|
||||
b byte
|
||||
|
||||
@@ -206,18 +206,10 @@ func (b *Reader) Read(p []byte) (n int, err error) {
|
||||
}
|
||||
return n, b.readErr()
|
||||
}
|
||||
// One read.
|
||||
// Do not use b.fill, which will loop.
|
||||
b.r = 0
|
||||
b.w = 0
|
||||
n, b.err = b.rd.Read(b.buf)
|
||||
if n < 0 {
|
||||
panic(errNegativeRead)
|
||||
}
|
||||
if n == 0 {
|
||||
b.fill() // buffer is empty
|
||||
if b.r == b.w {
|
||||
return 0, b.readErr()
|
||||
}
|
||||
b.w += n
|
||||
}
|
||||
|
||||
// copy as much as we can
|
||||
@@ -557,6 +549,11 @@ func (b *Writer) Reset(w io.Writer) {
|
||||
|
||||
// Flush writes any buffered data to the underlying io.Writer.
|
||||
func (b *Writer) Flush() error {
|
||||
err := b.flush()
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *Writer) flush() error {
|
||||
if b.err != nil {
|
||||
return b.err
|
||||
}
|
||||
@@ -599,7 +596,7 @@ func (b *Writer) Write(p []byte) (nn int, err error) {
|
||||
} else {
|
||||
n = copy(b.buf[b.n:], p)
|
||||
b.n += n
|
||||
b.Flush()
|
||||
b.flush()
|
||||
}
|
||||
nn += n
|
||||
p = p[n:]
|
||||
@@ -618,7 +615,7 @@ func (b *Writer) WriteByte(c byte) error {
|
||||
if b.err != nil {
|
||||
return b.err
|
||||
}
|
||||
if b.Available() <= 0 && b.Flush() != nil {
|
||||
if b.Available() <= 0 && b.flush() != nil {
|
||||
return b.err
|
||||
}
|
||||
b.buf[b.n] = c
|
||||
@@ -641,7 +638,7 @@ func (b *Writer) WriteRune(r rune) (size int, err error) {
|
||||
}
|
||||
n := b.Available()
|
||||
if n < utf8.UTFMax {
|
||||
if b.Flush(); b.err != nil {
|
||||
if b.flush(); b.err != nil {
|
||||
return 0, b.err
|
||||
}
|
||||
n = b.Available()
|
||||
@@ -666,7 +663,7 @@ func (b *Writer) WriteString(s string) (int, error) {
|
||||
b.n += n
|
||||
nn += n
|
||||
s = s[n:]
|
||||
b.Flush()
|
||||
b.flush()
|
||||
}
|
||||
if b.err != nil {
|
||||
return nn, b.err
|
||||
@@ -687,7 +684,7 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
var m int
|
||||
for {
|
||||
if b.Available() == 0 {
|
||||
if err1 := b.Flush(); err1 != nil {
|
||||
if err1 := b.flush(); err1 != nil {
|
||||
return n, err1
|
||||
}
|
||||
}
|
||||
@@ -711,7 +708,7 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
if err == io.EOF {
|
||||
// If we filled the buffer exactly, flush preemptively.
|
||||
if b.Available() == 0 {
|
||||
err = b.Flush()
|
||||
err = b.flush()
|
||||
} else {
|
||||
err = nil
|
||||
}
|
||||
|
||||
@@ -1236,27 +1236,6 @@ func TestWriterReadFromErrNoProgress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadZero(t *testing.T) {
|
||||
for _, size := range []int{100, 2} {
|
||||
t.Run(fmt.Sprintf("bufsize=%d", size), func(t *testing.T) {
|
||||
r := io.MultiReader(strings.NewReader("abc"), &emptyThenNonEmptyReader{r: strings.NewReader("def"), n: 1})
|
||||
br := NewReaderSize(r, size)
|
||||
want := func(s string, wantErr error) {
|
||||
p := make([]byte, 50)
|
||||
n, err := br.Read(p)
|
||||
if err != wantErr || n != len(s) || string(p[:n]) != s {
|
||||
t.Fatalf("read(%d) = %q, %v, want %q, %v", len(p), string(p[:n]), err, s, wantErr)
|
||||
}
|
||||
t.Logf("read(%d) = %q, %v", len(p), string(p[:n]), err)
|
||||
}
|
||||
want("abc", nil)
|
||||
want("", nil)
|
||||
want("def", nil)
|
||||
want("", io.EOF)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaderReset(t *testing.T) {
|
||||
r := NewReader(strings.NewReader("foo foo"))
|
||||
buf := make([]byte, 3)
|
||||
|
||||
@@ -199,6 +199,7 @@ func (s *Scanner) Scan() bool {
|
||||
s.buf = newBuf
|
||||
s.end -= s.start
|
||||
s.start = 0
|
||||
continue
|
||||
}
|
||||
// Finally we can read some input. Make sure we don't get stuck with
|
||||
// a misbehaving Reader. Officially we don't need to do this, but let's
|
||||
|
||||
@@ -173,8 +173,8 @@ func cap(v Type) int
|
||||
// specify a different capacity; it must be no smaller than the
|
||||
// length, so make([]int, 0, 10) allocates a slice of length 0 and
|
||||
// capacity 10.
|
||||
// Map: An empty map is allocated with enough space to hold the
|
||||
// specified number of elements. The size may be omitted, in which case
|
||||
// Map: An initial allocation is made according to the size but the
|
||||
// resulting map has length 0. The size may be omitted, in which case
|
||||
// a small starting size is allocated.
|
||||
// Channel: The channel's buffer is initialized with the specified
|
||||
// buffer capacity. If zero, or the size is omitted, the channel is
|
||||
|
||||
@@ -15,25 +15,22 @@ import (
|
||||
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
|
||||
// The zero value for Buffer is an empty buffer ready to use.
|
||||
type Buffer struct {
|
||||
buf []byte // contents are the bytes buf[off : len(buf)]
|
||||
off int // read at &buf[off], write at &buf[len(buf)]
|
||||
bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
|
||||
lastRead readOp // last read operation, so that Unread* can work correctly.
|
||||
buf []byte // contents are the bytes buf[off : len(buf)]
|
||||
off int // read at &buf[off], write at &buf[len(buf)]
|
||||
runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each call to WriteRune
|
||||
bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
|
||||
lastRead readOp // last read operation, so that Unread* can work correctly.
|
||||
}
|
||||
|
||||
// The readOp constants describe the last action performed on
|
||||
// the buffer, so that UnreadRune and UnreadByte can check for
|
||||
// invalid usage. opReadRuneX constants are choosen such that
|
||||
// converted to int they correspond to the rune size that was read.
|
||||
// the buffer, so that UnreadRune and UnreadByte can
|
||||
// check for invalid usage.
|
||||
type readOp int
|
||||
|
||||
const (
|
||||
opRead readOp = -1 // Any other read operation.
|
||||
opInvalid = 0 // Non-read operation.
|
||||
opReadRune1 = 1 // Read rune of size 1.
|
||||
opReadRune2 = 2 // Read rune of size 2.
|
||||
opReadRune3 = 3 // Read rune of size 3.
|
||||
opReadRune4 = 4 // Read rune of size 4.
|
||||
opInvalid readOp = iota // Non-read operation.
|
||||
opReadRune // Read rune.
|
||||
opRead // Any other read operation.
|
||||
)
|
||||
|
||||
// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
|
||||
@@ -249,10 +246,8 @@ func (b *Buffer) WriteRune(r rune) (n int, err error) {
|
||||
b.WriteByte(byte(r))
|
||||
return 1, nil
|
||||
}
|
||||
b.lastRead = opInvalid
|
||||
m := b.grow(utf8.UTFMax)
|
||||
n = utf8.EncodeRune(b.buf[m:m+utf8.UTFMax], r)
|
||||
b.buf = b.buf[:m+n]
|
||||
n = utf8.EncodeRune(b.runeBytes[0:], r)
|
||||
b.Write(b.runeBytes[0:n])
|
||||
return n, nil
|
||||
}
|
||||
|
||||
@@ -323,15 +318,14 @@ func (b *Buffer) ReadRune() (r rune, size int, err error) {
|
||||
b.Truncate(0)
|
||||
return 0, 0, io.EOF
|
||||
}
|
||||
b.lastRead = opReadRune
|
||||
c := b.buf[b.off]
|
||||
if c < utf8.RuneSelf {
|
||||
b.off++
|
||||
b.lastRead = opReadRune1
|
||||
return rune(c), 1, nil
|
||||
}
|
||||
r, n := utf8.DecodeRune(b.buf[b.off:])
|
||||
b.off += n
|
||||
b.lastRead = readOp(n)
|
||||
return r, n, nil
|
||||
}
|
||||
|
||||
@@ -341,13 +335,14 @@ func (b *Buffer) ReadRune() (r rune, size int, err error) {
|
||||
// it is stricter than UnreadByte, which will unread the last byte
|
||||
// from any read operation.)
|
||||
func (b *Buffer) UnreadRune() error {
|
||||
if b.lastRead <= opInvalid {
|
||||
if b.lastRead != opReadRune {
|
||||
return errors.New("bytes.Buffer: UnreadRune: previous operation was not ReadRune")
|
||||
}
|
||||
if b.off >= int(b.lastRead) {
|
||||
b.off -= int(b.lastRead)
|
||||
}
|
||||
b.lastRead = opInvalid
|
||||
if b.off > 0 {
|
||||
_, n := utf8.DecodeLastRune(b.buf[0:b.off])
|
||||
b.off -= n
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -355,7 +350,7 @@ func (b *Buffer) UnreadRune() error {
|
||||
// read operation. If write has happened since the last read, UnreadByte
|
||||
// returns an error.
|
||||
func (b *Buffer) UnreadByte() error {
|
||||
if b.lastRead == opInvalid {
|
||||
if b.lastRead != opReadRune && b.lastRead != opRead {
|
||||
return errors.New("bytes.Buffer: UnreadByte: previous operation was not a read")
|
||||
}
|
||||
b.lastRead = opInvalid
|
||||
|
||||
@@ -514,19 +514,6 @@ func TestBufferGrowth(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWriteRune(b *testing.B) {
|
||||
const n = 4 << 10
|
||||
const r = '☺'
|
||||
b.SetBytes(int64(n * utf8.RuneLen(r)))
|
||||
buf := NewBuffer(make([]byte, n*utf8.UTFMax))
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf.Reset()
|
||||
for i := 0; i < n; i++ {
|
||||
buf.WriteRune(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// From Issue 5154.
|
||||
func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {
|
||||
buf := make([]byte, 1024)
|
||||
|
||||
@@ -93,6 +93,37 @@ func ContainsRune(b []byte, r rune) bool {
|
||||
return IndexRune(b, r) >= 0
|
||||
}
|
||||
|
||||
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
||||
func Index(s, sep []byte) int {
|
||||
n := len(sep)
|
||||
if n == 0 {
|
||||
return 0
|
||||
}
|
||||
if n > len(s) {
|
||||
return -1
|
||||
}
|
||||
c := sep[0]
|
||||
if n == 1 {
|
||||
return IndexByte(s, c)
|
||||
}
|
||||
i := 0
|
||||
t := s[:len(s)-n+1]
|
||||
for i < len(t) {
|
||||
if t[i] != c {
|
||||
o := IndexByte(t[i:], c)
|
||||
if o < 0 {
|
||||
break
|
||||
}
|
||||
i += o
|
||||
}
|
||||
if Equal(s[i:i+n], sep) {
|
||||
return i
|
||||
}
|
||||
i++
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func indexBytePortable(s []byte, c byte) int {
|
||||
for i, b := range s {
|
||||
if b == c {
|
||||
@@ -130,28 +161,15 @@ func LastIndexByte(s []byte, c byte) int {
|
||||
// IndexRune interprets s as a sequence of UTF-8-encoded Unicode code points.
|
||||
// It returns the byte index of the first occurrence in s of the given rune.
|
||||
// It returns -1 if rune is not present in s.
|
||||
// If r is utf8.RuneError, it returns the first instance of any
|
||||
// invalid UTF-8 byte sequence.
|
||||
func IndexRune(s []byte, r rune) int {
|
||||
switch {
|
||||
case 0 <= r && r < utf8.RuneSelf:
|
||||
return IndexByte(s, byte(r))
|
||||
case r == utf8.RuneError:
|
||||
for i := 0; i < len(s); {
|
||||
r1, n := utf8.DecodeRune(s[i:])
|
||||
if r1 == utf8.RuneError {
|
||||
return i
|
||||
}
|
||||
i += n
|
||||
for i := 0; i < len(s); {
|
||||
r1, size := utf8.DecodeRune(s[i:])
|
||||
if r == r1 {
|
||||
return i
|
||||
}
|
||||
return -1
|
||||
case !utf8.ValidRune(r):
|
||||
return -1
|
||||
default:
|
||||
var b [utf8.UTFMax]byte
|
||||
n := utf8.EncodeRune(b[:], r)
|
||||
return Index(s, b[:n])
|
||||
i += size
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
|
||||
@@ -160,19 +178,10 @@ func IndexRune(s []byte, r rune) int {
|
||||
// point in common.
|
||||
func IndexAny(s []byte, chars string) int {
|
||||
if len(chars) > 0 {
|
||||
if len(s) > 8 {
|
||||
if as, isASCII := makeASCIISet(chars); isASCII {
|
||||
for i, c := range s {
|
||||
if as.contains(c) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
var r rune
|
||||
var width int
|
||||
for i := 0; i < len(s); i += width {
|
||||
r := rune(s[i])
|
||||
r = rune(s[i])
|
||||
if r < utf8.RuneSelf {
|
||||
width = 1
|
||||
} else {
|
||||
@@ -194,21 +203,11 @@ func IndexAny(s []byte, chars string) int {
|
||||
// there is no code point in common.
|
||||
func LastIndexAny(s []byte, chars string) int {
|
||||
if len(chars) > 0 {
|
||||
if len(s) > 8 {
|
||||
if as, isASCII := makeASCIISet(chars); isASCII {
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
if as.contains(s[i]) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
for i := len(s); i > 0; {
|
||||
r, size := utf8.DecodeLastRune(s[:i])
|
||||
r, size := utf8.DecodeLastRune(s[0:i])
|
||||
i -= size
|
||||
for _, c := range chars {
|
||||
if r == c {
|
||||
for _, ch := range chars {
|
||||
if r == ch {
|
||||
return i
|
||||
}
|
||||
}
|
||||
@@ -399,20 +398,7 @@ func Map(mapping func(r rune) rune, s []byte) []byte {
|
||||
}
|
||||
|
||||
// Repeat returns a new byte slice consisting of count copies of b.
|
||||
//
|
||||
// It panics if count is negative or if
|
||||
// the result of (len(b) * count) overflows.
|
||||
func Repeat(b []byte, count int) []byte {
|
||||
// Since we cannot return an error on overflow,
|
||||
// we should panic if the repeat will generate
|
||||
// an overflow.
|
||||
// See Issue golang.org/issue/16237.
|
||||
if count < 0 {
|
||||
panic("bytes: negative Repeat count")
|
||||
} else if count > 0 && len(b)*count/count != len(b) {
|
||||
panic("bytes: Repeat count causes overflow")
|
||||
}
|
||||
|
||||
nb := make([]byte, len(b)*count)
|
||||
bp := copy(nb, b)
|
||||
for bp < len(nb) {
|
||||
@@ -433,20 +419,20 @@ func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
|
||||
|
||||
// ToUpperSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
|
||||
// upper case, giving priority to the special casing rules.
|
||||
func ToUpperSpecial(c unicode.SpecialCase, s []byte) []byte {
|
||||
return Map(func(r rune) rune { return c.ToUpper(r) }, s)
|
||||
func ToUpperSpecial(_case unicode.SpecialCase, s []byte) []byte {
|
||||
return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
|
||||
}
|
||||
|
||||
// ToLowerSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
|
||||
// lower case, giving priority to the special casing rules.
|
||||
func ToLowerSpecial(c unicode.SpecialCase, s []byte) []byte {
|
||||
return Map(func(r rune) rune { return c.ToLower(r) }, s)
|
||||
func ToLowerSpecial(_case unicode.SpecialCase, s []byte) []byte {
|
||||
return Map(func(r rune) rune { return _case.ToLower(r) }, s)
|
||||
}
|
||||
|
||||
// ToTitleSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
|
||||
// title case, giving priority to the special casing rules.
|
||||
func ToTitleSpecial(c unicode.SpecialCase, s []byte) []byte {
|
||||
return Map(func(r rune) rune { return c.ToTitle(r) }, s)
|
||||
func ToTitleSpecial(_case unicode.SpecialCase, s []byte) []byte {
|
||||
return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
|
||||
}
|
||||
|
||||
// isSeparator reports whether the rune could mark a word boundary.
|
||||
@@ -592,43 +578,7 @@ func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
// asciiSet is a 32-byte value, where each bit represents the presence of a
|
||||
// given ASCII character in the set. The 128-bits of the lower 16 bytes,
|
||||
// starting with the least-significant bit of the lowest word to the
|
||||
// most-significant bit of the highest word, map to the full range of all
|
||||
// 128 ASCII characters. The 128-bits of the upper 16 bytes will be zeroed,
|
||||
// ensuring that any non-ASCII character will be reported as not in the set.
|
||||
type asciiSet [8]uint32
|
||||
|
||||
// makeASCIISet creates a set of ASCII characters and reports whether all
|
||||
// characters in chars are ASCII.
|
||||
func makeASCIISet(chars string) (as asciiSet, ok bool) {
|
||||
for i := 0; i < len(chars); i++ {
|
||||
c := chars[i]
|
||||
if c >= utf8.RuneSelf {
|
||||
return as, false
|
||||
}
|
||||
as[c>>5] |= 1 << uint(c&31)
|
||||
}
|
||||
return as, true
|
||||
}
|
||||
|
||||
// contains reports whether c is inside the set.
|
||||
func (as *asciiSet) contains(c byte) bool {
|
||||
return (as[c>>5] & (1 << uint(c&31))) != 0
|
||||
}
|
||||
|
||||
func makeCutsetFunc(cutset string) func(r rune) bool {
|
||||
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
|
||||
return func(r rune) bool {
|
||||
return r == rune(cutset[0])
|
||||
}
|
||||
}
|
||||
if as, isASCII := makeASCIISet(cutset); isASCII {
|
||||
return func(r rune) bool {
|
||||
return r < utf8.RuneSelf && as.contains(byte(r))
|
||||
}
|
||||
}
|
||||
return func(r rune) bool {
|
||||
for _, c := range cutset {
|
||||
if c == r {
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bytes
|
||||
|
||||
//go:noescape
|
||||
|
||||
// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s.
|
||||
// indexShortStr requires 2 <= len(c) <= shortStringLen
|
||||
func indexShortStr(s, c []byte) int // ../runtime/asm_$GOARCH.s
|
||||
func supportAVX2() bool // ../runtime/asm_$GOARCH.s
|
||||
|
||||
var shortStringLen int
|
||||
|
||||
func init() {
|
||||
if supportAVX2() {
|
||||
shortStringLen = 63
|
||||
} else {
|
||||
shortStringLen = 31
|
||||
}
|
||||
}
|
||||
|
||||
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
||||
func Index(s, sep []byte) int {
|
||||
n := len(sep)
|
||||
switch {
|
||||
case n == 0:
|
||||
return 0
|
||||
case n == 1:
|
||||
return IndexByte(s, sep[0])
|
||||
case n == len(s):
|
||||
if Equal(sep, s) {
|
||||
return 0
|
||||
}
|
||||
return -1
|
||||
case n > len(s):
|
||||
return -1
|
||||
case n <= shortStringLen:
|
||||
// Use brute force when s and sep both are small
|
||||
if len(s) <= 64 {
|
||||
return indexShortStr(s, sep)
|
||||
}
|
||||
c := sep[0]
|
||||
i := 0
|
||||
t := s[:len(s)-n+1]
|
||||
fails := 0
|
||||
for i < len(t) {
|
||||
if t[i] != c {
|
||||
// IndexByte skips 16/32 bytes per iteration,
|
||||
// so it's faster than indexShortStr.
|
||||
o := IndexByte(t[i:], c)
|
||||
if o < 0 {
|
||||
return -1
|
||||
}
|
||||
i += o
|
||||
}
|
||||
if Equal(s[i:i+n], sep) {
|
||||
return i
|
||||
}
|
||||
fails++
|
||||
i++
|
||||
// Switch to indexShortStr when IndexByte produces too many false positives.
|
||||
// Too many means more that 1 error per 8 characters.
|
||||
// Allow some errors in the beginning.
|
||||
if fails > (i+16)/8 {
|
||||
r := indexShortStr(s[i:], sep)
|
||||
if r >= 0 {
|
||||
return r + i
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
// Rabin-Karp search
|
||||
hashsep, pow := hashStr(sep)
|
||||
var h uint32
|
||||
for i := 0; i < n; i++ {
|
||||
h = h*primeRK + uint32(s[i])
|
||||
}
|
||||
if h == hashsep && Equal(s[:n], sep) {
|
||||
return 0
|
||||
}
|
||||
for i := n; i < len(s); {
|
||||
h *= primeRK
|
||||
h += uint32(s[i])
|
||||
h -= pow * uint32(s[i-n])
|
||||
i++
|
||||
if h == hashsep && Equal(s[i-n:i], sep) {
|
||||
return i - n
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// primeRK is the prime base used in Rabin-Karp algorithm.
|
||||
const primeRK = 16777619
|
||||
|
||||
// hashStr returns the hash and the appropriate multiplicative
|
||||
// factor for use in Rabin-Karp algorithm.
|
||||
func hashStr(sep []byte) (uint32, uint32) {
|
||||
hash := uint32(0)
|
||||
for i := 0; i < len(sep); i++ {
|
||||
hash = hash*primeRK + uint32(sep[i])
|
||||
}
|
||||
var pow, sq uint32 = 1, primeRK
|
||||
for i := len(sep); i > 0; i >>= 1 {
|
||||
if i&1 != 0 {
|
||||
pow *= sq
|
||||
}
|
||||
sq *= sq
|
||||
}
|
||||
return hash, pow
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build !amd64,!s390x
|
||||
|
||||
package bytes
|
||||
|
||||
// TODO: implements short string optimization on non amd64 platforms
|
||||
// and get rid of bytes_amd64.go
|
||||
|
||||
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
||||
func Index(s, sep []byte) int {
|
||||
n := len(sep)
|
||||
if n == 0 {
|
||||
return 0
|
||||
}
|
||||
if n > len(s) {
|
||||
return -1
|
||||
}
|
||||
c := sep[0]
|
||||
if n == 1 {
|
||||
return IndexByte(s, c)
|
||||
}
|
||||
i := 0
|
||||
t := s[:len(s)-n+1]
|
||||
for i < len(t) {
|
||||
if t[i] != c {
|
||||
o := IndexByte(t[i:], c)
|
||||
if o < 0 {
|
||||
break
|
||||
}
|
||||
i += o
|
||||
}
|
||||
if Equal(s[i:i+n], sep) {
|
||||
return i
|
||||
}
|
||||
i++
|
||||
}
|
||||
return -1
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bytes
|
||||
|
||||
//go:noescape
|
||||
|
||||
// indexShortStr returns the index of the first instance of sep in s,
|
||||
// or -1 if sep is not present in s.
|
||||
// indexShortStr requires 2 <= len(sep) <= shortStringLen
|
||||
func indexShortStr(s, c []byte) int // ../runtime/asm_s390x.s
|
||||
|
||||
// supportsVX reports whether the vector facility is available.
|
||||
// indexShortStr must not be called if the vector facility is not
|
||||
// available.
|
||||
func supportsVX() bool // ../runtime/asm_s390x.s
|
||||
|
||||
var shortStringLen = -1
|
||||
|
||||
func init() {
|
||||
if supportsVX() {
|
||||
shortStringLen = 64
|
||||
}
|
||||
}
|
||||
|
||||
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
|
||||
func Index(s, sep []byte) int {
|
||||
n := len(sep)
|
||||
switch {
|
||||
case n == 0:
|
||||
return 0
|
||||
case n == 1:
|
||||
return IndexByte(s, sep[0])
|
||||
case n == len(s):
|
||||
if Equal(sep, s) {
|
||||
return 0
|
||||
}
|
||||
return -1
|
||||
case n > len(s):
|
||||
return -1
|
||||
case n <= shortStringLen:
|
||||
// Use brute force when s and sep both are small
|
||||
if len(s) <= 64 {
|
||||
return indexShortStr(s, sep)
|
||||
}
|
||||
c := sep[0]
|
||||
i := 0
|
||||
t := s[:len(s)-n+1]
|
||||
fails := 0
|
||||
for i < len(t) {
|
||||
if t[i] != c {
|
||||
// IndexByte skips 16/32 bytes per iteration,
|
||||
// so it's faster than indexShortStr.
|
||||
o := IndexByte(t[i:], c)
|
||||
if o < 0 {
|
||||
return -1
|
||||
}
|
||||
i += o
|
||||
}
|
||||
if Equal(s[i:i+n], sep) {
|
||||
return i
|
||||
}
|
||||
fails++
|
||||
i++
|
||||
// Switch to indexShortStr when IndexByte produces too many false positives.
|
||||
// Too many means more that 1 error per 8 characters.
|
||||
// Allow some errors in the beginning.
|
||||
if fails > (i+16)/8 {
|
||||
r := indexShortStr(s[i:], sep)
|
||||
if r >= 0 {
|
||||
return r + i
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
// Rabin-Karp search
|
||||
hashsep, pow := hashStr(sep)
|
||||
var h uint32
|
||||
for i := 0; i < n; i++ {
|
||||
h = h*primeRK + uint32(s[i])
|
||||
}
|
||||
if h == hashsep && Equal(s[:n], sep) {
|
||||
return 0
|
||||
}
|
||||
for i := n; i < len(s); {
|
||||
h *= primeRK
|
||||
h += uint32(s[i])
|
||||
h -= pow * uint32(s[i-n])
|
||||
i++
|
||||
if h == hashsep && Equal(s[i-n:i], sep) {
|
||||
return i - n
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// primeRK is the prime base used in Rabin-Karp algorithm.
|
||||
const primeRK = 16777619
|
||||
|
||||
// hashStr returns the hash and the appropriate multiplicative
|
||||
// factor for use in Rabin-Karp algorithm.
|
||||
func hashStr(sep []byte) (uint32, uint32) {
|
||||
hash := uint32(0)
|
||||
for i := 0; i < len(sep); i++ {
|
||||
hash = hash*primeRK + uint32(sep[i])
|
||||
}
|
||||
var pow, sq uint32 = 1, primeRK
|
||||
for i := len(sep); i > 0; i >>= 1 {
|
||||
if i&1 != 0 {
|
||||
pow *= sq
|
||||
}
|
||||
sq *= sq
|
||||
}
|
||||
return hash, pow
|
||||
}
|
||||
@@ -7,10 +7,8 @@ package bytes_test
|
||||
import (
|
||||
. "bytes"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
@@ -167,12 +165,8 @@ var indexAnyTests = []BinOpTest{
|
||||
{"abc", "xyz", -1},
|
||||
{"abc", "xcz", 2},
|
||||
{"ab☺c", "x☺yz", 2},
|
||||
{"a☺b☻c☹d", "cx", len("a☺b☻")},
|
||||
{"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
|
||||
{"aRegExp*", ".(|)*+?^$[]", 7},
|
||||
{dots + dots + dots, " ", -1},
|
||||
{"012abcba210", "\xffb", 4},
|
||||
{"012\x80bcb\x80210", "\xffb", 3},
|
||||
}
|
||||
|
||||
var lastIndexAnyTests = []BinOpTest{
|
||||
@@ -184,13 +178,18 @@ var lastIndexAnyTests = []BinOpTest{
|
||||
{"aaa", "a", 2},
|
||||
{"abc", "xyz", -1},
|
||||
{"abc", "ab", 1},
|
||||
{"ab☺c", "x☺yz", 2},
|
||||
{"a☺b☻c☹d", "cx", len("a☺b☻")},
|
||||
{"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
|
||||
{"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
|
||||
{"a.RegExp*", ".(|)*+?^$[]", 8},
|
||||
{dots + dots + dots, " ", -1},
|
||||
{"012abcba210", "\xffb", 6},
|
||||
{"012\x80bcb\x80210", "\xffb", 7},
|
||||
}
|
||||
|
||||
var indexRuneTests = []BinOpTest{
|
||||
{"", "a", -1},
|
||||
{"", "☺", -1},
|
||||
{"foo", "☹", -1},
|
||||
{"foo", "o", 1},
|
||||
{"foo☺bar", "☺", 3},
|
||||
{"foo☺☻☹bar", "☹", 9},
|
||||
}
|
||||
|
||||
// Execute f on each test case. funcName should be the name of f; it's used
|
||||
@@ -347,53 +346,14 @@ func TestIndexByteSmall(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIndexRune(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
rune rune
|
||||
want int
|
||||
}{
|
||||
{"", 'a', -1},
|
||||
{"", '☺', -1},
|
||||
{"foo", '☹', -1},
|
||||
{"foo", 'o', 1},
|
||||
{"foo☺bar", '☺', 3},
|
||||
{"foo☺☻☹bar", '☹', 9},
|
||||
{"a A x", 'A', 2},
|
||||
{"some_text=some_value", '=', 9},
|
||||
{"☺a", 'a', 3},
|
||||
{"a☻☺b", '☺', 4},
|
||||
|
||||
// RuneError should match any invalid UTF-8 byte sequence.
|
||||
{"<22>", '<27>', 0},
|
||||
{"\xff", '<27>', 0},
|
||||
{"☻x<E298BB>", '<27>', len("☻x")},
|
||||
{"☻x\xe2\x98", '<27>', len("☻x")},
|
||||
{"☻x\xe2\x98<39>", '<27>', len("☻x")},
|
||||
{"☻x\xe2\x98x", '<27>', len("☻x")},
|
||||
|
||||
// Invalid rune values should never match.
|
||||
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", -1, -1},
|
||||
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", 0xD800, -1}, // Surrogate pair
|
||||
{"a☺b☻c☹d\xe2\x98<39>\xff<66>\xed\xa0\x80", utf8.MaxRune + 1, -1},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := IndexRune([]byte(tt.in), tt.rune); got != tt.want {
|
||||
t.Errorf("IndexRune(%q, %d) = %v; want %v", tt.in, tt.rune, got, tt.want)
|
||||
for _, tt := range indexRuneTests {
|
||||
a := []byte(tt.a)
|
||||
r, _ := utf8.DecodeRuneInString(tt.b)
|
||||
pos := IndexRune(a, r)
|
||||
if pos != tt.i {
|
||||
t.Errorf(`IndexRune(%q, '%c') = %v`, tt.a, r, pos)
|
||||
}
|
||||
}
|
||||
|
||||
haystack := []byte("test世界")
|
||||
allocs := testing.AllocsPerRun(1000, func() {
|
||||
if i := IndexRune(haystack, 's'); i != 2 {
|
||||
t.Fatalf("'s' at %d; want 2", i)
|
||||
}
|
||||
if i := IndexRune(haystack, '世'); i != 4 {
|
||||
t.Fatalf("'世' at %d; want 4", i)
|
||||
}
|
||||
})
|
||||
if allocs != 0 {
|
||||
t.Errorf("expected no allocations, got %f", allocs)
|
||||
}
|
||||
}
|
||||
|
||||
var bmbuf []byte
|
||||
@@ -410,9 +370,6 @@ func valName(x int) string {
|
||||
|
||||
func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
|
||||
for _, n := range sizes {
|
||||
if isRaceBuilder && n > 4<<10 {
|
||||
continue
|
||||
}
|
||||
b.Run(valName(n), func(b *testing.B) {
|
||||
if len(bmbuf) < n {
|
||||
bmbuf = make([]byte, n)
|
||||
@@ -425,8 +382,6 @@ func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
|
||||
|
||||
var indexSizes = []int{10, 32, 4 << 10, 4 << 20, 64 << 20}
|
||||
|
||||
var isRaceBuilder = strings.HasSuffix(testenv.Builder(), "-race")
|
||||
|
||||
func BenchmarkIndexByte(b *testing.B) {
|
||||
benchBytes(b, indexSizes, bmIndexByte(IndexByte))
|
||||
}
|
||||
@@ -449,44 +404,6 @@ func bmIndexByte(index func([]byte, byte) int) func(b *testing.B, n int) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexRune(b *testing.B) {
|
||||
benchBytes(b, indexSizes, bmIndexRune(IndexRune))
|
||||
}
|
||||
|
||||
func BenchmarkIndexRuneASCII(b *testing.B) {
|
||||
benchBytes(b, indexSizes, bmIndexRuneASCII(IndexRune))
|
||||
}
|
||||
|
||||
func bmIndexRuneASCII(index func([]byte, rune) int) func(b *testing.B, n int) {
|
||||
return func(b *testing.B, n int) {
|
||||
buf := bmbuf[0:n]
|
||||
buf[n-1] = 'x'
|
||||
for i := 0; i < b.N; i++ {
|
||||
j := index(buf, 'x')
|
||||
if j != n-1 {
|
||||
b.Fatal("bad index", j)
|
||||
}
|
||||
}
|
||||
buf[n-1] = '\x00'
|
||||
}
|
||||
}
|
||||
|
||||
func bmIndexRune(index func([]byte, rune) int) func(b *testing.B, n int) {
|
||||
return func(b *testing.B, n int) {
|
||||
buf := bmbuf[0:n]
|
||||
utf8.EncodeRune(buf[n-3:], '世')
|
||||
for i := 0; i < b.N; i++ {
|
||||
j := index(buf, '世')
|
||||
if j != n-3 {
|
||||
b.Fatal("bad index", j)
|
||||
}
|
||||
}
|
||||
buf[n-3] = '\x00'
|
||||
buf[n-2] = '\x00'
|
||||
buf[n-1] = '\x00'
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEqual(b *testing.B) {
|
||||
b.Run("0", func(b *testing.B) {
|
||||
var buf [4]byte
|
||||
@@ -927,54 +844,6 @@ func TestRepeat(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func repeat(b []byte, count int) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
switch v := r.(type) {
|
||||
case error:
|
||||
err = v
|
||||
default:
|
||||
err = fmt.Errorf("%s", v)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
Repeat(b, count)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// See Issue golang.org/issue/16237
|
||||
func TestRepeatCatchesOverflow(t *testing.T) {
|
||||
tests := [...]struct {
|
||||
s string
|
||||
count int
|
||||
errStr string
|
||||
}{
|
||||
0: {"--", -2147483647, "negative"},
|
||||
1: {"", int(^uint(0) >> 1), ""},
|
||||
2: {"-", 10, ""},
|
||||
3: {"gopher", 0, ""},
|
||||
4: {"-", -1, "negative"},
|
||||
5: {"--", -102, "negative"},
|
||||
6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
err := repeat([]byte(tt.s), tt.count)
|
||||
if tt.errStr == "" {
|
||||
if err != nil {
|
||||
t.Errorf("#%d panicked %v", i, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if err == nil || !strings.Contains(err.Error(), tt.errStr) {
|
||||
t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runesEqual(a, b []rune) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
@@ -1037,9 +906,6 @@ var trimTests = []TrimTest{
|
||||
{"Trim", "* listitem", " *", "listitem"},
|
||||
{"Trim", `"quote"`, `"`, "quote"},
|
||||
{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
|
||||
{"Trim", "\x80test\xff", "\xff", "test"},
|
||||
{"Trim", " Ġ ", " ", "Ġ"},
|
||||
{"Trim", " Ġİ0", "0 ", "Ġİ"},
|
||||
//empty string tests
|
||||
{"Trim", "abba", "", "abba"},
|
||||
{"Trim", "", "123", ""},
|
||||
@@ -1459,31 +1325,3 @@ func BenchmarkBytesCompare(b *testing.B) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexAnyASCII(b *testing.B) {
|
||||
x := Repeat([]byte{'#'}, 4096) // Never matches set
|
||||
cs := "0123456789abcdef"
|
||||
for k := 1; k <= 4096; k <<= 4 {
|
||||
for j := 1; j <= 16; j <<= 1 {
|
||||
b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IndexAny(x[:k], cs[:j])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTrimASCII(b *testing.B) {
|
||||
cs := "0123456789abcdef"
|
||||
for k := 1; k <= 4096; k <<= 4 {
|
||||
for j := 1; j <= 16; j <<= 1 {
|
||||
b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) {
|
||||
x := Repeat([]byte(cs[:j]), k) // Always matches set
|
||||
for i := 0; i < b.N; i++ {
|
||||
Trim(x[:k], cs[:j])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func loadSyms(t *testing.T) map[string]string {
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "nm", os.Args[0])
|
||||
cmd := exec.Command("go", "tool", "nm", os.Args[0])
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("go tool nm %v: %v\n%s", os.Args[0], err, string(out))
|
||||
@@ -98,7 +98,7 @@ func TestAddr2Line(t *testing.T) {
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
exepath := filepath.Join(tmpDir, "testaddr2line.exe")
|
||||
out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exepath, "cmd/addr2line").CombinedOutput()
|
||||
out, err := exec.Command("go", "build", "-o", exepath, "cmd/addr2line").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("go build -o %v cmd/addr2line: %v\n%s", exepath, err, string(out))
|
||||
}
|
||||
|
||||
@@ -59,14 +59,6 @@ func Set(GOARCH string) *Arch {
|
||||
return archArm()
|
||||
case "arm64":
|
||||
return archArm64()
|
||||
case "mips":
|
||||
a := archMips()
|
||||
a.LinkArch = &mips.Linkmips
|
||||
return a
|
||||
case "mipsle":
|
||||
a := archMips()
|
||||
a.LinkArch = &mips.Linkmipsle
|
||||
return a
|
||||
case "mips64":
|
||||
a := archMips64()
|
||||
a.LinkArch = &mips.Linkmips64
|
||||
@@ -327,12 +319,6 @@ func archPPC64() *Arch {
|
||||
for i := ppc64.REG_F0; i <= ppc64.REG_F31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
for i := ppc64.REG_V0; i <= ppc64.REG_V31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
for i := ppc64.REG_VS0; i <= ppc64.REG_VS63; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
for i := ppc64.REG_CR0; i <= ppc64.REG_CR7; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
@@ -382,62 +368,6 @@ func archPPC64() *Arch {
|
||||
}
|
||||
}
|
||||
|
||||
func archMips() *Arch {
|
||||
register := make(map[string]int16)
|
||||
// Create maps for easy lookup of instruction names etc.
|
||||
// Note that there is no list of names as there is for x86.
|
||||
for i := mips.REG_R0; i <= mips.REG_R31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
|
||||
for i := mips.REG_F0; i <= mips.REG_F31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
for i := mips.REG_M0; i <= mips.REG_M31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
|
||||
register[obj.Rconv(i)] = int16(i)
|
||||
}
|
||||
register["HI"] = mips.REG_HI
|
||||
register["LO"] = mips.REG_LO
|
||||
// Pseudo-registers.
|
||||
register["SB"] = RSB
|
||||
register["FP"] = RFP
|
||||
register["PC"] = RPC
|
||||
// Avoid unintentionally clobbering g using R30.
|
||||
delete(register, "R30")
|
||||
register["g"] = mips.REG_R30
|
||||
|
||||
registerPrefix := map[string]bool{
|
||||
"F": true,
|
||||
"FCR": true,
|
||||
"M": true,
|
||||
"R": true,
|
||||
}
|
||||
|
||||
instructions := make(map[string]obj.As)
|
||||
for i, s := range obj.Anames {
|
||||
instructions[s] = obj.As(i)
|
||||
}
|
||||
for i, s := range mips.Anames {
|
||||
if obj.As(i) >= obj.A_ARCHSPECIFIC {
|
||||
instructions[s] = obj.As(i) + obj.ABaseMIPS
|
||||
}
|
||||
}
|
||||
// Annoying alias.
|
||||
instructions["JAL"] = mips.AJAL
|
||||
|
||||
return &Arch{
|
||||
LinkArch: &mips.Linkmipsle,
|
||||
Instructions: instructions,
|
||||
Register: register,
|
||||
RegisterPrefix: registerPrefix,
|
||||
RegisterNumber: mipsRegisterNumber,
|
||||
IsJump: jumpMIPS,
|
||||
}
|
||||
}
|
||||
|
||||
func archMips64() *Arch {
|
||||
register := make(map[string]int16)
|
||||
// Create maps for easy lookup of instruction names etc.
|
||||
@@ -479,7 +409,7 @@ func archMips64() *Arch {
|
||||
}
|
||||
for i, s := range mips.Anames {
|
||||
if obj.As(i) >= obj.A_ARCHSPECIFIC {
|
||||
instructions[s] = obj.As(i) + obj.ABaseMIPS
|
||||
instructions[s] = obj.As(i) + obj.ABaseMIPS64
|
||||
}
|
||||
}
|
||||
// Annoying alias.
|
||||
@@ -491,7 +421,7 @@ func archMips64() *Arch {
|
||||
Register: register,
|
||||
RegisterPrefix: registerPrefix,
|
||||
RegisterNumber: mipsRegisterNumber,
|
||||
IsJump: jumpMIPS,
|
||||
IsJump: jumpMIPS64,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file encapsulates some of the odd characteristics of the
|
||||
// MIPS (MIPS64) instruction set, to minimize its interaction
|
||||
// 64-bit MIPS (MIPS64) instruction set, to minimize its interaction
|
||||
// with the core of the assembler.
|
||||
|
||||
package arch
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"cmd/internal/obj/mips"
|
||||
)
|
||||
|
||||
func jumpMIPS(word string) bool {
|
||||
func jumpMIPS64(word string) bool {
|
||||
switch word {
|
||||
case "BEQ", "BFPF", "BFPT", "BGEZ", "BGEZAL", "BGTZ", "BLEZ", "BLTZ", "BLTZAL", "BNE", "JMP", "JAL", "CALL":
|
||||
return true
|
||||
@@ -21,9 +21,9 @@ func jumpMIPS(word string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsMIPSCMP reports whether the op (as defined by an mips.A* constant) is
|
||||
// IsMIPS64CMP reports whether the op (as defined by an mips.A* constant) is
|
||||
// one of the CMP instructions that require special handling.
|
||||
func IsMIPSCMP(op obj.As) bool {
|
||||
func IsMIPS64CMP(op obj.As) bool {
|
||||
switch op {
|
||||
case mips.ACMPEQF, mips.ACMPEQD, mips.ACMPGEF, mips.ACMPGED,
|
||||
mips.ACMPGTF, mips.ACMPGTD:
|
||||
@@ -32,9 +32,9 @@ func IsMIPSCMP(op obj.As) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsMIPSMUL reports whether the op (as defined by an mips.A* constant) is
|
||||
// IsMIPS64MUL reports whether the op (as defined by an mips.A* constant) is
|
||||
// one of the MUL/DIV/REM instructions that require special handling.
|
||||
func IsMIPSMUL(op obj.As) bool {
|
||||
func IsMIPS64MUL(op obj.As) bool {
|
||||
switch op {
|
||||
case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU,
|
||||
mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU,
|
||||
@@ -39,10 +39,6 @@ func IsPPC64RLD(op obj.As) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func IsPPC64ISEL(op obj.As) bool {
|
||||
return op == ppc64.AISEL
|
||||
}
|
||||
|
||||
// IsPPC64CMP reports whether the op (as defined by an ppc64.A* constant) is
|
||||
// one of the CMP instructions that require special handling.
|
||||
func IsPPC64CMP(op obj.As) bool {
|
||||
@@ -77,14 +73,6 @@ func ppc64RegisterNumber(name string, n int16) (int16, bool) {
|
||||
if 0 <= n && n <= 7 {
|
||||
return ppc64.REG_CR0 + n, true
|
||||
}
|
||||
case "VS":
|
||||
if 0 <= n && n <= 63 {
|
||||
return ppc64.REG_VS0 + n, true
|
||||
}
|
||||
case "V":
|
||||
if 0 <= n && n <= 31 {
|
||||
return ppc64.REG_V0 + n, true
|
||||
}
|
||||
case "F":
|
||||
if 0 <= n && n <= 31 {
|
||||
return ppc64.REG_F0 + n, true
|
||||
|
||||
@@ -22,9 +22,7 @@ func jumpS390x(word string) bool {
|
||||
"BGT",
|
||||
"BL",
|
||||
"BLE",
|
||||
"BLEU",
|
||||
"BLT",
|
||||
"BLTU",
|
||||
"BNE",
|
||||
"BR",
|
||||
"BVC",
|
||||
@@ -80,7 +78,11 @@ func IsS390xCMP(op obj.As) bool {
|
||||
// one of the NEG-like instructions that require special handling.
|
||||
func IsS390xNEG(op obj.As) bool {
|
||||
switch op {
|
||||
case s390x.ANEG, s390x.ANEGW:
|
||||
case s390x.AADDME,
|
||||
s390x.AADDZE,
|
||||
s390x.ANEG,
|
||||
s390x.ASUBME,
|
||||
s390x.ASUBZE:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -108,8 +110,6 @@ func IsS390xWithIndex(op obj.As) bool {
|
||||
return true
|
||||
case s390x.AVLEIG, s390x.AVLEIF, s390x.AVLEIH, s390x.AVLEIB:
|
||||
return true
|
||||
case s390x.AVLEG, s390x.AVLEF, s390x.AVLEH, s390x.AVLEB:
|
||||
return true
|
||||
case s390x.AVPDI:
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -269,7 +269,17 @@ func (p *Parser) asmGlobl(word string, operands [][]lex.Token) {
|
||||
}
|
||||
|
||||
// log.Printf("GLOBL %s %d, $%d", name, flag, size)
|
||||
p.ctxt.Globl(nameAddr.Sym, addr.Offset, int(flag))
|
||||
prog := &obj.Prog{
|
||||
Ctxt: p.ctxt,
|
||||
As: obj.AGLOBL,
|
||||
Lineno: p.histLineNum,
|
||||
From: nameAddr,
|
||||
From3: &obj.Addr{
|
||||
Offset: flag,
|
||||
},
|
||||
To: addr,
|
||||
}
|
||||
p.append(prog, "", false)
|
||||
}
|
||||
|
||||
// asmPCData assembles a PCDATA pseudo-op.
|
||||
@@ -369,7 +379,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
|
||||
prog.Reg = reg
|
||||
break
|
||||
}
|
||||
if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 {
|
||||
if p.arch.Family == sys.MIPS64 {
|
||||
// 3-operand jumps.
|
||||
// First two must be registers
|
||||
target = &a[2]
|
||||
@@ -527,8 +537,8 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
break
|
||||
} else if p.arch.Family == sys.MIPS || p.arch.Family == sys.MIPS64 {
|
||||
if arch.IsMIPSCMP(op) || arch.IsMIPSMUL(op) {
|
||||
} else if p.arch.Family == sys.MIPS64 {
|
||||
if arch.IsMIPS64CMP(op) || arch.IsMIPS64MUL(op) {
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
break
|
||||
@@ -538,7 +548,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||
prog.To = a[1]
|
||||
case 3:
|
||||
switch p.arch.Family {
|
||||
case sys.MIPS, sys.MIPS64:
|
||||
case sys.MIPS64:
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.To = a[2]
|
||||
@@ -663,42 +673,15 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||
prog.To = a[3]
|
||||
break
|
||||
}
|
||||
if p.arch.Family == sys.PPC64 {
|
||||
if arch.IsPPC64RLD(op) {
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.From3 = newAddr(a[2])
|
||||
prog.To = a[3]
|
||||
break
|
||||
} else if arch.IsPPC64ISEL(op) {
|
||||
// ISEL BC,RB,RA,RT becomes isel rt,ra,rb,bc
|
||||
prog.From3 = newAddr(a[2]) // ra
|
||||
prog.From = a[0] // bc
|
||||
prog.Reg = p.getRegister(prog, op, &a[1]) // rb
|
||||
prog.To = a[3] // rt
|
||||
break
|
||||
}
|
||||
// Else, it is a VA-form instruction
|
||||
// reg reg reg reg
|
||||
// imm reg reg reg
|
||||
// Or a VX-form instruction
|
||||
// imm imm reg reg
|
||||
if a[1].Type == obj.TYPE_REG {
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.From3 = newAddr(a[2])
|
||||
prog.To = a[3]
|
||||
break
|
||||
} else if a[1].Type == obj.TYPE_CONST {
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[2])
|
||||
prog.From3 = newAddr(a[1])
|
||||
prog.To = a[3]
|
||||
break
|
||||
} else {
|
||||
p.errorf("invalid addressing modes for %s instruction", op)
|
||||
return
|
||||
}
|
||||
if p.arch.Family == sys.PPC64 && arch.IsPPC64RLD(op) {
|
||||
// 2nd operand must always be a register.
|
||||
// TODO: Do we need to guard this with the instruction type?
|
||||
// That is, are there 4-operand instructions without this property?
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.From3 = newAddr(a[2])
|
||||
prog.To = a[3]
|
||||
break
|
||||
}
|
||||
if p.arch.Family == sys.S390X {
|
||||
prog.From = a[1]
|
||||
|
||||
@@ -383,8 +383,7 @@ func TestAMD64Errors(t *testing.T) {
|
||||
testErrors(t, "amd64", "amd64error")
|
||||
}
|
||||
|
||||
func TestMIPSEndToEnd(t *testing.T) {
|
||||
testEndToEnd(t, "mips", "mips")
|
||||
func TestMIPS64EndToEnd(t *testing.T) {
|
||||
testEndToEnd(t, "mips64", "mips64")
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package asm
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"cmd/asm/internal/arch"
|
||||
@@ -15,8 +16,8 @@ import (
|
||||
// A simple in-out test: Do we print what we parse?
|
||||
|
||||
func setArch(goarch string) (*arch.Arch, *obj.Link) {
|
||||
obj.GOOS = "linux" // obj can handle this OS for all architectures.
|
||||
obj.GOARCH = goarch
|
||||
os.Setenv("GOOS", "linux") // obj can handle this OS for all architectures.
|
||||
os.Setenv("GOARCH", goarch)
|
||||
architecture := arch.Set(goarch)
|
||||
if architecture == nil {
|
||||
panic("asm: unrecognized architecture " + goarch)
|
||||
@@ -65,11 +66,6 @@ func TestPPC64OperandParser(t *testing.T) {
|
||||
testOperandParser(t, parser, ppc64OperandTests)
|
||||
}
|
||||
|
||||
func TestMIPSOperandParser(t *testing.T) {
|
||||
parser := newParser("mips")
|
||||
testOperandParser(t, parser, mipsOperandTests)
|
||||
}
|
||||
|
||||
func TestMIPS64OperandParser(t *testing.T) {
|
||||
parser := newParser("mips64")
|
||||
testOperandParser(t, parser, mips64OperandTests)
|
||||
@@ -345,102 +341,6 @@ var ppc64OperandTests = []operandTest{
|
||||
{"6(PC)", "6(PC)"},
|
||||
{"CR7", "CR7"},
|
||||
{"CTR", "CTR"},
|
||||
{"VS0", "VS0"},
|
||||
{"VS1", "VS1"},
|
||||
{"VS2", "VS2"},
|
||||
{"VS3", "VS3"},
|
||||
{"VS4", "VS4"},
|
||||
{"VS5", "VS5"},
|
||||
{"VS6", "VS6"},
|
||||
{"VS7", "VS7"},
|
||||
{"VS8", "VS8"},
|
||||
{"VS9", "VS9"},
|
||||
{"VS10", "VS10"},
|
||||
{"VS11", "VS11"},
|
||||
{"VS12", "VS12"},
|
||||
{"VS13", "VS13"},
|
||||
{"VS14", "VS14"},
|
||||
{"VS15", "VS15"},
|
||||
{"VS16", "VS16"},
|
||||
{"VS17", "VS17"},
|
||||
{"VS18", "VS18"},
|
||||
{"VS19", "VS19"},
|
||||
{"VS20", "VS20"},
|
||||
{"VS21", "VS21"},
|
||||
{"VS22", "VS22"},
|
||||
{"VS23", "VS23"},
|
||||
{"VS24", "VS24"},
|
||||
{"VS25", "VS25"},
|
||||
{"VS26", "VS26"},
|
||||
{"VS27", "VS27"},
|
||||
{"VS28", "VS28"},
|
||||
{"VS29", "VS29"},
|
||||
{"VS30", "VS30"},
|
||||
{"VS31", "VS31"},
|
||||
{"VS32", "VS32"},
|
||||
{"VS33", "VS33"},
|
||||
{"VS34", "VS34"},
|
||||
{"VS35", "VS35"},
|
||||
{"VS36", "VS36"},
|
||||
{"VS37", "VS37"},
|
||||
{"VS38", "VS38"},
|
||||
{"VS39", "VS39"},
|
||||
{"VS40", "VS40"},
|
||||
{"VS41", "VS41"},
|
||||
{"VS42", "VS42"},
|
||||
{"VS43", "VS43"},
|
||||
{"VS44", "VS44"},
|
||||
{"VS45", "VS45"},
|
||||
{"VS46", "VS46"},
|
||||
{"VS47", "VS47"},
|
||||
{"VS48", "VS48"},
|
||||
{"VS49", "VS49"},
|
||||
{"VS50", "VS50"},
|
||||
{"VS51", "VS51"},
|
||||
{"VS52", "VS52"},
|
||||
{"VS53", "VS53"},
|
||||
{"VS54", "VS54"},
|
||||
{"VS55", "VS55"},
|
||||
{"VS56", "VS56"},
|
||||
{"VS57", "VS57"},
|
||||
{"VS58", "VS58"},
|
||||
{"VS59", "VS59"},
|
||||
{"VS60", "VS60"},
|
||||
{"VS61", "VS61"},
|
||||
{"VS62", "VS62"},
|
||||
{"VS63", "VS63"},
|
||||
{"V0", "V0"},
|
||||
{"V1", "V1"},
|
||||
{"V2", "V2"},
|
||||
{"V3", "V3"},
|
||||
{"V4", "V4"},
|
||||
{"V5", "V5"},
|
||||
{"V6", "V6"},
|
||||
{"V7", "V7"},
|
||||
{"V8", "V8"},
|
||||
{"V9", "V9"},
|
||||
{"V10", "V10"},
|
||||
{"V11", "V11"},
|
||||
{"V12", "V12"},
|
||||
{"V13", "V13"},
|
||||
{"V14", "V14"},
|
||||
{"V15", "V15"},
|
||||
{"V16", "V16"},
|
||||
{"V17", "V17"},
|
||||
{"V18", "V18"},
|
||||
{"V19", "V19"},
|
||||
{"V20", "V20"},
|
||||
{"V21", "V21"},
|
||||
{"V22", "V22"},
|
||||
{"V23", "V23"},
|
||||
{"V24", "V24"},
|
||||
{"V25", "V25"},
|
||||
{"V26", "V26"},
|
||||
{"V27", "V27"},
|
||||
{"V28", "V28"},
|
||||
{"V29", "V29"},
|
||||
{"V30", "V30"},
|
||||
{"V31", "V31"},
|
||||
{"F14", "F14"},
|
||||
{"F15", "F15"},
|
||||
{"F16", "F16"},
|
||||
@@ -633,88 +533,6 @@ var mips64OperandTests = []operandTest{
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
var mipsOperandTests = []operandTest{
|
||||
{"$((1<<63)-1)", "$9223372036854775807"},
|
||||
{"$(-64*1024)", "$-65536"},
|
||||
{"$(1024 * 8)", "$8192"},
|
||||
{"$-1", "$-1"},
|
||||
{"$-24(R4)", "$-24(R4)"},
|
||||
{"$0", "$0"},
|
||||
{"$0(R1)", "$(R1)"},
|
||||
{"$0.5", "$(0.5)"},
|
||||
{"$0x7000", "$28672"},
|
||||
{"$0x88888eef", "$2290650863"},
|
||||
{"$1", "$1"},
|
||||
{"$_main<>(SB)", "$_main<>(SB)"},
|
||||
{"$argframe(FP)", "$argframe(FP)"},
|
||||
{"$~3", "$-4"},
|
||||
{"(-288-3*8)(R1)", "-312(R1)"},
|
||||
{"(16)(R7)", "16(R7)"},
|
||||
{"(8)(g)", "8(g)"},
|
||||
{"(R0)", "(R0)"},
|
||||
{"(R3)", "(R3)"},
|
||||
{"(R4)", "(R4)"},
|
||||
{"(R5)", "(R5)"},
|
||||
{"-1(R4)", "-1(R4)"},
|
||||
{"-1(R5)", "-1(R5)"},
|
||||
{"6(PC)", "6(PC)"},
|
||||
{"F14", "F14"},
|
||||
{"F15", "F15"},
|
||||
{"F16", "F16"},
|
||||
{"F17", "F17"},
|
||||
{"F18", "F18"},
|
||||
{"F19", "F19"},
|
||||
{"F20", "F20"},
|
||||
{"F21", "F21"},
|
||||
{"F22", "F22"},
|
||||
{"F23", "F23"},
|
||||
{"F24", "F24"},
|
||||
{"F25", "F25"},
|
||||
{"F26", "F26"},
|
||||
{"F27", "F27"},
|
||||
{"F28", "F28"},
|
||||
{"F29", "F29"},
|
||||
{"F30", "F30"},
|
||||
{"F31", "F31"},
|
||||
{"R0", "R0"},
|
||||
{"R1", "R1"},
|
||||
{"R11", "R11"},
|
||||
{"R12", "R12"},
|
||||
{"R13", "R13"},
|
||||
{"R14", "R14"},
|
||||
{"R15", "R15"},
|
||||
{"R16", "R16"},
|
||||
{"R17", "R17"},
|
||||
{"R18", "R18"},
|
||||
{"R19", "R19"},
|
||||
{"R2", "R2"},
|
||||
{"R20", "R20"},
|
||||
{"R21", "R21"},
|
||||
{"R22", "R22"},
|
||||
{"R23", "R23"},
|
||||
{"R24", "R24"},
|
||||
{"R25", "R25"},
|
||||
{"R26", "R26"},
|
||||
{"R27", "R27"},
|
||||
{"R29", "R29"},
|
||||
{"R3", "R3"},
|
||||
{"R31", "R31"},
|
||||
{"R4", "R4"},
|
||||
{"R5", "R5"},
|
||||
{"R6", "R6"},
|
||||
{"R7", "R7"},
|
||||
{"R8", "R8"},
|
||||
{"R9", "R9"},
|
||||
{"LO", "LO"},
|
||||
{"a(FP)", "a(FP)"},
|
||||
{"g", "g"},
|
||||
{"ret+8(FP)", "ret+8(FP)"},
|
||||
{"runtime·abort(SB)", "runtime.abort(SB)"},
|
||||
{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
|
||||
{"·trunc(SB)", "\"\".trunc(SB)"},
|
||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||
}
|
||||
|
||||
var s390xOperandTests = []operandTest{
|
||||
{"$((1<<63)-1)", "$9223372036854775807"},
|
||||
{"$(-64*1024)", "$-65536"},
|
||||
|
||||
@@ -941,6 +941,14 @@ func (p *Parser) atof(str string) float64 {
|
||||
return value
|
||||
}
|
||||
|
||||
func (p *Parser) atos(str string) string {
|
||||
value, err := strconv.Unquote(str)
|
||||
if err != nil {
|
||||
p.errorf("%s", err)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// EOF represents the end of input.
|
||||
var EOF = lex.Make(scanner.EOF, "EOF")
|
||||
|
||||
|
||||
192
src/cmd/asm/internal/asm/testdata/amd64enc.s
vendored
192
src/cmd/asm/internal/asm/testdata/amd64enc.s
vendored
@@ -2551,14 +2551,14 @@ TEXT asmtest(SB),7,$0
|
||||
MOVQ (R11), X11 // 66450f6e1b or 664d0f6e1b or f3450f7e1b
|
||||
MOVQ DX, X11 // 66440f6eda or 664c0f6eda
|
||||
MOVQ R11, X11 // 66450f6edb or 664d0f6edb
|
||||
MOVDDUP (BX), X2 // f20f1213
|
||||
MOVDDUP (R11), X2 // f2410f1213
|
||||
MOVDDUP X2, X2 // f20f12d2
|
||||
MOVDDUP X11, X2 // f2410f12d3
|
||||
MOVDDUP (BX), X11 // f2440f121b
|
||||
MOVDDUP (R11), X11 // f2450f121b
|
||||
MOVDDUP X2, X11 // f2440f12da
|
||||
MOVDDUP X11, X11 // f2450f12db
|
||||
//TODO: MOVDDUP (BX), X2 // f20f1213
|
||||
//TODO: MOVDDUP (R11), X2 // f2410f1213
|
||||
//TODO: MOVDDUP X2, X2 // f20f12d2
|
||||
//TODO: MOVDDUP X11, X2 // f2410f12d3
|
||||
//TODO: MOVDDUP (BX), X11 // f2440f121b
|
||||
//TODO: MOVDDUP (R11), X11 // f2450f121b
|
||||
//TODO: MOVDDUP X2, X11 // f2440f12da
|
||||
//TODO: MOVDDUP X11, X11 // f2450f12db
|
||||
MOVQ X2, M2 // f20fd6d2
|
||||
MOVQ X11, M2 // f2410fd6d3
|
||||
MOVQ X2, M3 // f20fd6da
|
||||
@@ -2697,22 +2697,22 @@ TEXT asmtest(SB),7,$0
|
||||
//TODO: MOVSD X11, (BX) // f2440f111b
|
||||
//TODO: MOVSD X2, (R11) // f2410f1113
|
||||
//TODO: MOVSD X11, (R11) // f2450f111b
|
||||
MOVSHDUP (BX), X2 // f30f1613
|
||||
MOVSHDUP (R11), X2 // f3410f1613
|
||||
MOVSHDUP X2, X2 // f30f16d2
|
||||
MOVSHDUP X11, X2 // f3410f16d3
|
||||
MOVSHDUP (BX), X11 // f3440f161b
|
||||
MOVSHDUP (R11), X11 // f3450f161b
|
||||
MOVSHDUP X2, X11 // f3440f16da
|
||||
MOVSHDUP X11, X11 // f3450f16db
|
||||
MOVSLDUP (BX), X2 // f30f1213
|
||||
MOVSLDUP (R11), X2 // f3410f1213
|
||||
MOVSLDUP X2, X2 // f30f12d2
|
||||
MOVSLDUP X11, X2 // f3410f12d3
|
||||
MOVSLDUP (BX), X11 // f3440f121b
|
||||
MOVSLDUP (R11), X11 // f3450f121b
|
||||
MOVSLDUP X2, X11 // f3440f12da
|
||||
MOVSLDUP X11, X11 // f3450f12db
|
||||
//TODO: MOVSHDUP (BX), X2 // f30f1613
|
||||
//TODO: MOVSHDUP (R11), X2 // f3410f1613
|
||||
//TODO: MOVSHDUP X2, X2 // f30f16d2
|
||||
//TODO: MOVSHDUP X11, X2 // f3410f16d3
|
||||
//TODO: MOVSHDUP (BX), X11 // f3440f161b
|
||||
//TODO: MOVSHDUP (R11), X11 // f3450f161b
|
||||
//TODO: MOVSHDUP X2, X11 // f3440f16da
|
||||
//TODO: MOVSHDUP X11, X11 // f3450f16db
|
||||
//TODO: MOVSLDUP (BX), X2 // f30f1213
|
||||
//TODO: MOVSLDUP (R11), X2 // f3410f1213
|
||||
//TODO: MOVSLDUP X2, X2 // f30f12d2
|
||||
//TODO: MOVSLDUP X11, X2 // f3410f12d3
|
||||
//TODO: MOVSLDUP (BX), X11 // f3440f121b
|
||||
//TODO: MOVSLDUP (R11), X11 // f3450f121b
|
||||
//TODO: MOVSLDUP X2, X11 // f3440f12da
|
||||
//TODO: MOVSLDUP X11, X11 // f3450f12db
|
||||
MOVSQ // 48a5
|
||||
MOVSS (BX), X2 // f30f1013
|
||||
MOVSS (R11), X2 // f3410f1013
|
||||
@@ -6116,30 +6116,30 @@ TEXT asmtest(SB),7,$0
|
||||
//TODO: VBROADCASTI128 (R11), Y2 // c4c27d5a13
|
||||
//TODO: VBROADCASTI128 (BX), Y11 // c4627d5a1b
|
||||
//TODO: VBROADCASTI128 (R11), Y11 // c4427d5a1b
|
||||
VBROADCASTSD (BX), Y2 // c4e27d1913
|
||||
VBROADCASTSD (R11), Y2 // c4c27d1913
|
||||
VBROADCASTSD (BX), Y11 // c4627d191b
|
||||
VBROADCASTSD (R11), Y11 // c4427d191b
|
||||
VBROADCASTSD X2, Y2 // c4e27d19d2
|
||||
VBROADCASTSD X11, Y2 // c4c27d19d3
|
||||
VBROADCASTSD X2, Y11 // c4627d19da
|
||||
VBROADCASTSD X11, Y11 // c4427d19db
|
||||
VBROADCASTSS (BX), X2 // c4e2791813
|
||||
VBROADCASTSS (R11), X2 // c4c2791813
|
||||
VBROADCASTSS (BX), X11 // c46279181b
|
||||
VBROADCASTSS (R11), X11 // c44279181b
|
||||
VBROADCASTSS X2, X2 // c4e27918d2
|
||||
VBROADCASTSS X11, X2 // c4c27918d3
|
||||
VBROADCASTSS X2, X11 // c4627918da
|
||||
VBROADCASTSS X11, X11 // c4427918db
|
||||
VBROADCASTSS (BX), Y2 // c4e27d1813
|
||||
VBROADCASTSS (R11), Y2 // c4c27d1813
|
||||
VBROADCASTSS (BX), Y11 // c4627d181b
|
||||
VBROADCASTSS (R11), Y11 // c4427d181b
|
||||
VBROADCASTSS X2, Y2 // c4e27d18d2
|
||||
VBROADCASTSS X11, Y2 // c4c27d18d3
|
||||
VBROADCASTSS X2, Y11 // c4627d18da
|
||||
VBROADCASTSS X11, Y11 // c4427d18db
|
||||
//TODO: VBROADCASTSD (BX), Y2 // c4e27d1913
|
||||
//TODO: VBROADCASTSD (R11), Y2 // c4c27d1913
|
||||
//TODO: VBROADCASTSD (BX), Y11 // c4627d191b
|
||||
//TODO: VBROADCASTSD (R11), Y11 // c4427d191b
|
||||
//TODO: VBROADCASTSD X2, Y2 // c4e27d19d2
|
||||
//TODO: VBROADCASTSD X11, Y2 // c4c27d19d3
|
||||
//TODO: VBROADCASTSD X2, Y11 // c4627d19da
|
||||
//TODO: VBROADCASTSD X11, Y11 // c4427d19db
|
||||
//TODO: VBROADCASTSS (BX), X2 // c4e2791813
|
||||
//TODO: VBROADCASTSS (R11), X2 // c4c2791813
|
||||
//TODO: VBROADCASTSS (BX), X11 // c46279181b
|
||||
//TODO: VBROADCASTSS (R11), X11 // c44279181b
|
||||
//TODO: VBROADCASTSS X2, X2 // c4e27918d2
|
||||
//TODO: VBROADCASTSS X11, X2 // c4c27918d3
|
||||
//TODO: VBROADCASTSS X2, X11 // c4627918da
|
||||
//TODO: VBROADCASTSS X11, X11 // c4427918db
|
||||
//TODO: VBROADCASTSS (BX), Y2 // c4e27d1813
|
||||
//TODO: VBROADCASTSS (R11), Y2 // c4c27d1813
|
||||
//TODO: VBROADCASTSS (BX), Y11 // c4627d181b
|
||||
//TODO: VBROADCASTSS (R11), Y11 // c4427d181b
|
||||
//TODO: VBROADCASTSS X2, Y2 // c4e27d18d2
|
||||
//TODO: VBROADCASTSS X11, Y2 // c4c27d18d3
|
||||
//TODO: VBROADCASTSS X2, Y11 // c4627d18da
|
||||
//TODO: VBROADCASTSS X11, Y11 // c4427d18db
|
||||
//TODO: VCMPPD $7, (BX), X9, X2 // c4e131c21307 or c5b1c21307
|
||||
//TODO: VCMPPD $7, (R11), X9, X2 // c4c131c21307
|
||||
//TODO: VCMPPD $7, X2, X9, X2 // c4e131c2d207 or c5b1c2d207
|
||||
@@ -7642,22 +7642,22 @@ TEXT asmtest(SB),7,$0
|
||||
//TODO: VMOVD (R11), X11 // c441796e1b
|
||||
//TODO: VMOVD DX, X11 // c461796eda or c5796eda
|
||||
//TODO: VMOVD R11, X11 // c441796edb
|
||||
VMOVDDUP (BX), X2 // c4e17b1213 or c5fb1213
|
||||
VMOVDDUP (R11), X2 // c4c17b1213
|
||||
VMOVDDUP X2, X2 // c4e17b12d2 or c5fb12d2
|
||||
VMOVDDUP X11, X2 // c4c17b12d3
|
||||
VMOVDDUP (BX), X11 // c4617b121b or c57b121b
|
||||
VMOVDDUP (R11), X11 // c4417b121b
|
||||
VMOVDDUP X2, X11 // c4617b12da or c57b12da
|
||||
VMOVDDUP X11, X11 // c4417b12db
|
||||
VMOVDDUP (BX), Y2 // c4e17f1213 or c5ff1213
|
||||
VMOVDDUP (R11), Y2 // c4c17f1213
|
||||
VMOVDDUP Y2, Y2 // c4e17f12d2 or c5ff12d2
|
||||
VMOVDDUP Y11, Y2 // c4c17f12d3
|
||||
VMOVDDUP (BX), Y11 // c4617f121b or c57f121b
|
||||
VMOVDDUP (R11), Y11 // c4417f121b
|
||||
VMOVDDUP Y2, Y11 // c4617f12da or c57f12da
|
||||
VMOVDDUP Y11, Y11 // c4417f12db
|
||||
//TODO: VMOVDDUP (BX), X2 // c4e17b1213 or c5fb1213
|
||||
//TODO: VMOVDDUP (R11), X2 // c4c17b1213
|
||||
//TODO: VMOVDDUP X2, X2 // c4e17b12d2 or c5fb12d2
|
||||
//TODO: VMOVDDUP X11, X2 // c4c17b12d3
|
||||
//TODO: VMOVDDUP (BX), X11 // c4617b121b or c57b121b
|
||||
//TODO: VMOVDDUP (R11), X11 // c4417b121b
|
||||
//TODO: VMOVDDUP X2, X11 // c4617b12da or c57b12da
|
||||
//TODO: VMOVDDUP X11, X11 // c4417b12db
|
||||
//TODO: VMOVDDUP (BX), Y2 // c4e17f1213 or c5ff1213
|
||||
//TODO: VMOVDDUP (R11), Y2 // c4c17f1213
|
||||
//TODO: VMOVDDUP Y2, Y2 // c4e17f12d2 or c5ff12d2
|
||||
//TODO: VMOVDDUP Y11, Y2 // c4c17f12d3
|
||||
//TODO: VMOVDDUP (BX), Y11 // c4617f121b or c57f121b
|
||||
//TODO: VMOVDDUP (R11), Y11 // c4417f121b
|
||||
//TODO: VMOVDDUP Y2, Y11 // c4617f12da or c57f12da
|
||||
//TODO: VMOVDDUP Y11, Y11 // c4417f12db
|
||||
VMOVDQA (BX), X2 // c4e1796f13 or c5f96f13
|
||||
VMOVDQA (R11), X2 // c4c1796f13
|
||||
VMOVDQA X2, X2 // c4e1796fd2 or c5f96fd2 or c4e1797fd2 or c5f97fd2
|
||||
@@ -7826,38 +7826,38 @@ TEXT asmtest(SB),7,$0
|
||||
//TODO: VMOVSD X11, X9, X2 // c4c13310d3 or c4613311da or c53311da
|
||||
//TODO: VMOVSD X2, X9, X11 // c4613310da or c53310da or c4c13311d3
|
||||
//TODO: VMOVSD X11, X9, X11 // c4413310db or c4413311db
|
||||
VMOVSHDUP (BX), X2 // c4e17a1613 or c5fa1613
|
||||
VMOVSHDUP (R11), X2 // c4c17a1613
|
||||
VMOVSHDUP X2, X2 // c4e17a16d2 or c5fa16d2
|
||||
VMOVSHDUP X11, X2 // c4c17a16d3
|
||||
VMOVSHDUP (BX), X11 // c4617a161b or c57a161b
|
||||
VMOVSHDUP (R11), X11 // c4417a161b
|
||||
VMOVSHDUP X2, X11 // c4617a16da or c57a16da
|
||||
VMOVSHDUP X11, X11 // c4417a16db
|
||||
VMOVSHDUP (BX), Y2 // c4e17e1613 or c5fe1613
|
||||
VMOVSHDUP (R11), Y2 // c4c17e1613
|
||||
VMOVSHDUP Y2, Y2 // c4e17e16d2 or c5fe16d2
|
||||
VMOVSHDUP Y11, Y2 // c4c17e16d3
|
||||
VMOVSHDUP (BX), Y11 // c4617e161b or c57e161b
|
||||
VMOVSHDUP (R11), Y11 // c4417e161b
|
||||
VMOVSHDUP Y2, Y11 // c4617e16da or c57e16da
|
||||
VMOVSHDUP Y11, Y11 // c4417e16db
|
||||
VMOVSLDUP (BX), X2 // c4e17a1213 or c5fa1213
|
||||
VMOVSLDUP (R11), X2 // c4c17a1213
|
||||
VMOVSLDUP X2, X2 // c4e17a12d2 or c5fa12d2
|
||||
VMOVSLDUP X11, X2 // c4c17a12d3
|
||||
VMOVSLDUP (BX), X11 // c4617a121b or c57a121b
|
||||
VMOVSLDUP (R11), X11 // c4417a121b
|
||||
VMOVSLDUP X2, X11 // c4617a12da or c57a12da
|
||||
VMOVSLDUP X11, X11 // c4417a12db
|
||||
VMOVSLDUP (BX), Y2 // c4e17e1213 or c5fe1213
|
||||
VMOVSLDUP (R11), Y2 // c4c17e1213
|
||||
VMOVSLDUP Y2, Y2 // c4e17e12d2 or c5fe12d2
|
||||
VMOVSLDUP Y11, Y2 // c4c17e12d3
|
||||
VMOVSLDUP (BX), Y11 // c4617e121b or c57e121b
|
||||
VMOVSLDUP (R11), Y11 // c4417e121b
|
||||
VMOVSLDUP Y2, Y11 // c4617e12da or c57e12da
|
||||
VMOVSLDUP Y11, Y11 // c4417e12db
|
||||
//TODO: VMOVSHDUP (BX), X2 // c4e17a1613 or c5fa1613
|
||||
//TODO: VMOVSHDUP (R11), X2 // c4c17a1613
|
||||
//TODO: VMOVSHDUP X2, X2 // c4e17a16d2 or c5fa16d2
|
||||
//TODO: VMOVSHDUP X11, X2 // c4c17a16d3
|
||||
//TODO: VMOVSHDUP (BX), X11 // c4617a161b or c57a161b
|
||||
//TODO: VMOVSHDUP (R11), X11 // c4417a161b
|
||||
//TODO: VMOVSHDUP X2, X11 // c4617a16da or c57a16da
|
||||
//TODO: VMOVSHDUP X11, X11 // c4417a16db
|
||||
//TODO: VMOVSHDUP (BX), Y2 // c4e17e1613 or c5fe1613
|
||||
//TODO: VMOVSHDUP (R11), Y2 // c4c17e1613
|
||||
//TODO: VMOVSHDUP Y2, Y2 // c4e17e16d2 or c5fe16d2
|
||||
//TODO: VMOVSHDUP Y11, Y2 // c4c17e16d3
|
||||
//TODO: VMOVSHDUP (BX), Y11 // c4617e161b or c57e161b
|
||||
//TODO: VMOVSHDUP (R11), Y11 // c4417e161b
|
||||
//TODO: VMOVSHDUP Y2, Y11 // c4617e16da or c57e16da
|
||||
//TODO: VMOVSHDUP Y11, Y11 // c4417e16db
|
||||
//TODO: VMOVSLDUP (BX), X2 // c4e17a1213 or c5fa1213
|
||||
//TODO: VMOVSLDUP (R11), X2 // c4c17a1213
|
||||
//TODO: VMOVSLDUP X2, X2 // c4e17a12d2 or c5fa12d2
|
||||
//TODO: VMOVSLDUP X11, X2 // c4c17a12d3
|
||||
//TODO: VMOVSLDUP (BX), X11 // c4617a121b or c57a121b
|
||||
//TODO: VMOVSLDUP (R11), X11 // c4417a121b
|
||||
//TODO: VMOVSLDUP X2, X11 // c4617a12da or c57a12da
|
||||
//TODO: VMOVSLDUP X11, X11 // c4417a12db
|
||||
//TODO: VMOVSLDUP (BX), Y2 // c4e17e1213 or c5fe1213
|
||||
//TODO: VMOVSLDUP (R11), Y2 // c4c17e1213
|
||||
//TODO: VMOVSLDUP Y2, Y2 // c4e17e12d2 or c5fe12d2
|
||||
//TODO: VMOVSLDUP Y11, Y2 // c4c17e12d3
|
||||
//TODO: VMOVSLDUP (BX), Y11 // c4617e121b or c57e121b
|
||||
//TODO: VMOVSLDUP (R11), Y11 // c4417e121b
|
||||
//TODO: VMOVSLDUP Y2, Y11 // c4617e12da or c57e12da
|
||||
//TODO: VMOVSLDUP Y11, Y11 // c4417e12db
|
||||
//TODO: VMOVSS X2, (BX) // c4e17a1113 or c5fa1113
|
||||
//TODO: VMOVSS X11, (BX) // c4617a111b or c57a111b
|
||||
//TODO: VMOVSS X2, (R11) // c4c17a1113
|
||||
|
||||
430
src/cmd/asm/internal/asm/testdata/mips.s
vendored
430
src/cmd/asm/internal/asm/testdata/mips.s
vendored
@@ -1,430 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// This input was created by taking the mips64 testcase and modified
|
||||
// by hand.
|
||||
|
||||
TEXT foo(SB),7,$0
|
||||
|
||||
//inst:
|
||||
//
|
||||
// load ints and bytes
|
||||
//
|
||||
// LMOVW rreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW R1, R2
|
||||
MOVW LO, R1
|
||||
MOVW HI, R1
|
||||
MOVW R1, LO
|
||||
MOVW R1, HI
|
||||
MOVW R1, R2
|
||||
MOVW LO, R1
|
||||
MOVW HI, R1
|
||||
MOVW R1, LO
|
||||
MOVW R1, HI
|
||||
|
||||
// LMOVW addr ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW foo<>+3(SB), R2
|
||||
MOVW 16(R1), R2
|
||||
MOVW (R1), R2
|
||||
MOVW foo<>+3(SB), R2
|
||||
MOVW 16(R1), R2
|
||||
MOVW (R1), R2
|
||||
LL (R1), R2
|
||||
|
||||
// LMOVB rreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVB R1, R2
|
||||
|
||||
// LMOVB addr ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVB foo<>+3(SB), R2
|
||||
MOVB 16(R1), R2
|
||||
MOVB (R1), R2
|
||||
|
||||
//
|
||||
// load floats
|
||||
//
|
||||
// LFMOV addr ',' freg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVF foo<>+3(SB), F2
|
||||
MOVF 16(R1), F2
|
||||
MOVF (R1), F2
|
||||
|
||||
// LFMOV fimm ',' freg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVF $0.1, F2 // MOVF $(0.10000000000000001), F2
|
||||
|
||||
// LFMOV freg ',' freg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVF F1, F2
|
||||
|
||||
// LFMOV freg ',' addr
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVF F2, foo<>+3(SB)
|
||||
MOVF F2, 16(R1)
|
||||
MOVF F2, (R1)
|
||||
|
||||
//
|
||||
// store ints and bytes
|
||||
//
|
||||
// LMOVW rreg ',' addr
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW R1, foo<>+3(SB)
|
||||
MOVW R1, 16(R2)
|
||||
MOVW R1, (R2)
|
||||
MOVW R1, foo<>+3(SB)
|
||||
MOVW R1, 16(R2)
|
||||
MOVW R1, (R2)
|
||||
SC R1, (R2)
|
||||
|
||||
// LMOVB rreg ',' addr
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVB R1, foo<>+3(SB)
|
||||
MOVB R1, 16(R2)
|
||||
MOVB R1, (R2)
|
||||
|
||||
//
|
||||
// store floats
|
||||
//
|
||||
// LMOVW freg ',' addr
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVD F1, foo<>+3(SB)
|
||||
MOVD F1, 16(R2)
|
||||
MOVD F1, (R2)
|
||||
|
||||
//
|
||||
// floating point status
|
||||
//
|
||||
// LMOVW fpscr ',' freg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW FCR0, R1
|
||||
|
||||
// LMOVW freg ',' fpscr
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW R1, FCR0
|
||||
|
||||
// LMOVW rreg ',' mreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW R1, M1
|
||||
MOVW R1, M1
|
||||
|
||||
// LMOVW mreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW M1, R1
|
||||
MOVW M1, R1
|
||||
|
||||
|
||||
//
|
||||
// integer operations
|
||||
// logical instructions
|
||||
// shift instructions
|
||||
// unary instructions
|
||||
//
|
||||
// LADDW rreg ',' sreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, int($4), &$6);
|
||||
// }
|
||||
ADD R1, R2, R3
|
||||
|
||||
// LADDW imm ',' sreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, int($4), &$6);
|
||||
// }
|
||||
ADD $1, R2, R3
|
||||
|
||||
// LADDW rreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
ADD R1, R2
|
||||
|
||||
// LADDW imm ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
ADD $4, R1
|
||||
|
||||
// LMUL rreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MUL R1, R2
|
||||
|
||||
// LSHW rreg ',' sreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, int($4), &$6);
|
||||
// }
|
||||
SLL R1, R2, R3
|
||||
|
||||
// LSHW rreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
SLL R1, R2
|
||||
|
||||
// LSHW imm ',' sreg ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, int($4), &$6);
|
||||
// }
|
||||
SLL $4, R1, R2
|
||||
|
||||
// LSHW imm ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
SLL $4, R1
|
||||
|
||||
//
|
||||
// move immediate: macro for lui+or, addi, addis, and other combinations
|
||||
//
|
||||
// LMOVW imm ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW $1, R1
|
||||
MOVW $1, R1
|
||||
|
||||
// LMOVW ximm ',' rreg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
MOVW $1, R1
|
||||
MOVW $foo(SB), R1
|
||||
MOVW $1, R1
|
||||
MOVW $foo(SB), R1
|
||||
|
||||
|
||||
//
|
||||
// branch
|
||||
//
|
||||
// LBRA rel
|
||||
// {
|
||||
// outcode(int($1), &nullgen, 0, &$2);
|
||||
// }
|
||||
BEQ R1, 2(PC)
|
||||
label0:
|
||||
JMP 1(PC)
|
||||
BEQ R1, 2(PC)
|
||||
JMP label0+0 // JMP 66
|
||||
BEQ R1, 2(PC)
|
||||
JAL 1(PC) // CALL 1(PC)
|
||||
BEQ R1, 2(PC)
|
||||
JAL label0+0 // CALL 66
|
||||
|
||||
// LBRA addr
|
||||
// {
|
||||
// outcode(int($1), &nullgen, 0, &$2);
|
||||
// }
|
||||
BEQ R1, 2(PC)
|
||||
JMP 0(R1) // JMP (R1)
|
||||
BEQ R1, 2(PC)
|
||||
JMP foo+0(SB) // JMP foo(SB)
|
||||
BEQ R1, 2(PC)
|
||||
JAL 0(R1) // CALL (R1)
|
||||
BEQ R1, 2(PC)
|
||||
JAL foo+0(SB) // CALL foo(SB)
|
||||
|
||||
//
|
||||
// BEQ/BNE
|
||||
//
|
||||
// LBRA rreg ',' rel
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
label1:
|
||||
BEQ R1, 1(PC)
|
||||
BEQ R1, label1 // BEQ R1, 81
|
||||
|
||||
// LBRA rreg ',' sreg ',' rel
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
label2:
|
||||
BEQ R1, R2, 1(PC)
|
||||
BEQ R1, R2, label2 // BEQ R1, R2, 83
|
||||
|
||||
//
|
||||
// other integer conditional branch
|
||||
//
|
||||
// LBRA rreg ',' rel
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
label3:
|
||||
BLTZ R1, 1(PC)
|
||||
BLTZ R1, label3 // BLTZ R1, 85
|
||||
|
||||
//
|
||||
// floating point conditional branch
|
||||
//
|
||||
// LBRA rel
|
||||
label4:
|
||||
BFPT 1(PC)
|
||||
BFPT label4 // BFPT 87
|
||||
|
||||
|
||||
//
|
||||
// floating point operate
|
||||
//
|
||||
// LFCONV freg ',' freg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
ABSD F1, F2
|
||||
|
||||
// LFADD freg ',' freg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
ADDD F1, F2
|
||||
|
||||
// LFADD freg ',' freg ',' freg
|
||||
// {
|
||||
// outcode(int($1), &$2, int($4.Reg), &$6);
|
||||
// }
|
||||
ADDD F1, F2, F3
|
||||
|
||||
// LFCMP freg ',' freg
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &$4);
|
||||
// }
|
||||
CMPEQD F1, F2
|
||||
|
||||
|
||||
//
|
||||
// WORD
|
||||
//
|
||||
WORD $1
|
||||
|
||||
//
|
||||
// NOP
|
||||
//
|
||||
// LNOP comma // asm doesn't support the trailing comma.
|
||||
// {
|
||||
// outcode(int($1), &nullgen, 0, &nullgen);
|
||||
// }
|
||||
NOP
|
||||
|
||||
// LNOP rreg comma // asm doesn't support the trailing comma.
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &nullgen);
|
||||
// }
|
||||
NOP R2
|
||||
|
||||
// LNOP freg comma // asm doesn't support the trailing comma.
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &nullgen);
|
||||
// }
|
||||
NOP F2
|
||||
|
||||
// LNOP ',' rreg // asm doesn't support the leading comma.
|
||||
// {
|
||||
// outcode(int($1), &nullgen, 0, &$3);
|
||||
// }
|
||||
NOP R2
|
||||
|
||||
// LNOP ',' freg // asm doesn't support the leading comma.
|
||||
// {
|
||||
// outcode(int($1), &nullgen, 0, &$3);
|
||||
// }
|
||||
NOP F2
|
||||
|
||||
// LNOP imm
|
||||
// {
|
||||
// outcode(int($1), &$2, 0, &nullgen);
|
||||
// }
|
||||
NOP $4
|
||||
|
||||
//
|
||||
// special
|
||||
//
|
||||
SYSCALL
|
||||
BREAK
|
||||
SYNC
|
||||
|
||||
//
|
||||
// conditional move on zero/nonzero gp value
|
||||
//
|
||||
CMOVN R1, R2, R3
|
||||
CMOVZ R1, R2, R3
|
||||
|
||||
//
|
||||
// conditional move on fp false/true
|
||||
//
|
||||
CMOVF R1, R2
|
||||
CMOVT R1, R2
|
||||
|
||||
//
|
||||
// conditional traps
|
||||
//
|
||||
TEQ $1, R1, R2
|
||||
TEQ $1, R1
|
||||
|
||||
|
||||
//
|
||||
// other
|
||||
//
|
||||
CLO R1, R2
|
||||
SQRTD F0, F1
|
||||
MUL R1, R2, R3
|
||||
|
||||
|
||||
//
|
||||
// RET
|
||||
//
|
||||
// LRETRN comma // asm doesn't support the trailing comma.
|
||||
// {
|
||||
// outcode(int($1), &nullgen, 0, &nullgen);
|
||||
// }
|
||||
SYSCALL
|
||||
BEQ R1, 2(PC)
|
||||
RET
|
||||
|
||||
|
||||
// More JMP/JAL cases, and canonical names JMP, CALL.
|
||||
|
||||
JAL foo(SB) // CALL foo(SB)
|
||||
BEQ R1, 2(PC)
|
||||
JMP foo(SB)
|
||||
CALL foo(SB)
|
||||
|
||||
// END
|
||||
//
|
||||
// LEND comma // asm doesn't support the trailing comma.
|
||||
// {
|
||||
// outcode(int($1), &nullgen, 0, &nullgen);
|
||||
// }
|
||||
END
|
||||
349
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
349
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
@@ -594,15 +594,6 @@ label1:
|
||||
// }
|
||||
RLWMI R1, R2, 4, 5, R3 // RLWMI R1, R2, $201326592, R3
|
||||
|
||||
|
||||
// opcodes added with constant shift counts, not masks
|
||||
|
||||
RLDICR $3, R2, $24, R4
|
||||
|
||||
RLDICL $1, R2, $61, R6
|
||||
|
||||
RLDIMI $7, R2, $52, R7
|
||||
|
||||
//
|
||||
// load/store multiple
|
||||
//
|
||||
@@ -673,346 +664,6 @@ label1:
|
||||
DCBF (R1)
|
||||
DCBF (R1+R2) // DCBF (R1)(R2*1)
|
||||
|
||||
// VMX instructions
|
||||
|
||||
// Described as:
|
||||
// <instruction type>, <instruction format>
|
||||
// <go asm operand order> produces
|
||||
// <Power ISA operand order>
|
||||
|
||||
// Vector load, VX-form
|
||||
// <MNEMONIC> (RB)(RA*1),VRT produces
|
||||
// <mnemonic> VRT,RA,RB
|
||||
LVEBX (R1)(R2*1), V0
|
||||
LVEHX (R3)(R4*1), V1
|
||||
LVEWX (R5)(R6*1), V2
|
||||
LVX (R7)(R8*1), V3
|
||||
LVXL (R9)(R10*1), V4
|
||||
LVSL (R11)(R12*1), V5
|
||||
LVSR (R14)(R15*1), V6
|
||||
|
||||
// Vector store, VX-form
|
||||
// <MNEMONIC> VRT,(RB)(RA*1) produces
|
||||
// <mnemonic> VRT,RA,RB
|
||||
STVEBX V31, (R1)(R2*1)
|
||||
STVEHX V30, (R2)(R3*1)
|
||||
STVEWX V29, (R4)(R5*1)
|
||||
STVX V28, (R6)(R7*1)
|
||||
STVXL V27, (R9)(R9*1)
|
||||
|
||||
// Vector AND, VX-form
|
||||
// <MNEMONIC> VRA,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB
|
||||
VANDL V10, V9, V8
|
||||
VANDC V15, V14, V13
|
||||
VNAND V19, V18, V17
|
||||
|
||||
// Vector OR, VX-form
|
||||
// <MNEMONIC> VRA,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB
|
||||
VORL V26, V25, V24
|
||||
VORC V23, V22, V21
|
||||
VNOR V20, V19, V18
|
||||
VXOR V17, V16, V15
|
||||
VEQV V14, V13, V12
|
||||
|
||||
// Vector ADD, VX-form
|
||||
// <MNEMONIC> VRA,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB
|
||||
VADDUBM V3, V2, V1
|
||||
VADDUHM V3, V2, V1
|
||||
VADDUWM V3, V2, V1
|
||||
VADDUDM V3, V2, V1
|
||||
VADDUQM V3, V2, V1
|
||||
VADDCUQ V3, V2, V1
|
||||
VADDCUW V3, V2, V1
|
||||
VADDUBS V3, V2, V1
|
||||
VADDUHS V3, V2, V1
|
||||
VADDUWS V3, V2, V1
|
||||
VADDSBS V3, V2, V1
|
||||
VADDSHS V3, V2, V1
|
||||
VADDSWS V3, V2, V1
|
||||
|
||||
// Vector ADD extended, VA-form
|
||||
// <MNEMONIC> VRA,VRB,VRC,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB,VRC
|
||||
VADDEUQM V4, V3, V2, V1
|
||||
VADDECUQ V4, V3, V2, V1
|
||||
|
||||
// Vector SUB, VX-form
|
||||
// <MNEMONIC> VRA,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB
|
||||
VSUBUBM V3, V2, V1
|
||||
VSUBUHM V3, V2, V1
|
||||
VSUBUWM V3, V2, V1
|
||||
VSUBUDM V3, V2, V1
|
||||
VSUBUQM V3, V2, V1
|
||||
VSUBCUQ V3, V2, V1
|
||||
VSUBCUW V3, V2, V1
|
||||
VSUBUBS V3, V2, V1
|
||||
VSUBUHS V3, V2, V1
|
||||
VSUBUWS V3, V2, V1
|
||||
VSUBSBS V3, V2, V1
|
||||
VSUBSHS V3, V2, V1
|
||||
VSUBSWS V3, V2, V1
|
||||
|
||||
// Vector SUB extended, VA-form
|
||||
// <MNEMONIC> VRA,VRB,VRC,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB,VRC
|
||||
VSUBEUQM V4, V3, V2, V1
|
||||
VSUBECUQ V4, V3, V2, V1
|
||||
|
||||
// Vector rotate, VX-form
|
||||
// <MNEMONIC> VRA,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB
|
||||
VRLB V2, V1, V0
|
||||
VRLH V2, V1, V0
|
||||
VRLW V2, V1, V0
|
||||
VRLD V2, V1, V0
|
||||
|
||||
// Vector shift, VX-form
|
||||
// <MNEMONIC> VRA,VRB,VRT
|
||||
// <mnemonic> VRT,VRA,VRB
|
||||
VSLB V2, V1, V0
|
||||
VSLH V2, V1, V0
|
||||
VSLW V2, V1, V0
|
||||
VSL V2, V1, V0
|
||||
VSLO V2, V1, V0
|
||||
VSRB V2, V1, V0
|
||||
VSRH V2, V1, V0
|
||||
VSRW V2, V1, V0
|
||||
VSR V2, V1, V0
|
||||
VSRO V2, V1, V0
|
||||
VSLD V2, V1, V0
|
||||
VSRD V2, V1, V0
|
||||
VSRAB V2, V1, V0
|
||||
VSRAH V2, V1, V0
|
||||
VSRAW V2, V1, V0
|
||||
VSRAD V2, V1, V0
|
||||
|
||||
// Vector shift by octect immediate, VA-form with SHB 4-bit field
|
||||
// <MNEMONIC> SHB,VRA,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB,SHB
|
||||
VSLDOI $4, V2, V1, V0
|
||||
|
||||
// Vector count, VX-form
|
||||
// <MNEMONIC> VRB,VRT produces
|
||||
// <mnemonic> VRT,VRB
|
||||
VCLZB V4, V5
|
||||
VCLZH V4, V5
|
||||
VCLZW V4, V5
|
||||
VCLZD V4, V5
|
||||
VPOPCNTB V4, V5
|
||||
VPOPCNTH V4, V5
|
||||
VPOPCNTW V4, V5
|
||||
VPOPCNTD V4, V5
|
||||
|
||||
// Vector compare, VC-form
|
||||
// <MNEMONIC> VRA,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB
|
||||
// * Note: 'CC' suffix denotes Rc=1
|
||||
// i.e. vcmpequb. v3,v1,v2 equals VCMPEQUBCC V1,V2,V3
|
||||
VCMPEQUB V3, V2, V1
|
||||
VCMPEQUBCC V3, V2, V1
|
||||
VCMPEQUH V3, V2, V1
|
||||
VCMPEQUHCC V3, V2, V1
|
||||
VCMPEQUW V3, V2, V1
|
||||
VCMPEQUWCC V3, V2, V1
|
||||
VCMPEQUD V3, V2, V1
|
||||
VCMPEQUDCC V3, V2, V1
|
||||
VCMPGTUB V3, V2, V1
|
||||
VCMPGTUBCC V3, V2, V1
|
||||
VCMPGTUH V3, V2, V1
|
||||
VCMPGTUHCC V3, V2, V1
|
||||
VCMPGTUW V3, V2, V1
|
||||
VCMPGTUWCC V3, V2, V1
|
||||
VCMPGTUD V3, V2, V1
|
||||
VCMPGTUDCC V3, V2, V1
|
||||
VCMPGTSB V3, V2, V1
|
||||
VCMPGTSBCC V3, V2, V1
|
||||
VCMPGTSH V3, V2, V1
|
||||
VCMPGTSHCC V3, V2, V1
|
||||
VCMPGTSW V3, V2, V1
|
||||
VCMPGTSWCC V3, V2, V1
|
||||
VCMPGTSD V3, V2, V1
|
||||
VCMPGTSDCC V3, V2, V1
|
||||
|
||||
// Vector permute, VA-form
|
||||
// <MNEMONIC> VRA,VRB,VRC,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB,VRC
|
||||
VPERM V3, V2, V1, V0
|
||||
|
||||
// Vector select, VA-form
|
||||
// <MNEMONIC> VRA,VRB,VRC,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB,VRC
|
||||
VSEL V3, V2, V1, V0
|
||||
|
||||
// Vector splat, VX-form with 4-bit UIM field
|
||||
// <MNEMONIC> UIM,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRB,UIM
|
||||
VSPLTB $15, V1, V0
|
||||
VSPLTH $7, V1, V0
|
||||
VSPLTW $3, V1, V0
|
||||
|
||||
// Vector splat immediate signed, VX-form with 5-bit SIM field
|
||||
// <MNEMONIC> SIM,VRT produces
|
||||
// <mnemonic> VRT,SIM
|
||||
VSPLTISB $31, V4
|
||||
VSPLTISH $31, V4
|
||||
VSPLTISW $31, V4
|
||||
|
||||
// Vector AES cipher, VX-form
|
||||
// <MNEMONIC> VRA,VRB,VRT produces
|
||||
// <mnemonic> VRT,VRA,VRB
|
||||
VCIPHER V3, V2, V1
|
||||
VCIPHERLAST V3, V2, V1
|
||||
VNCIPHER V3, V2, V1
|
||||
VNCIPHERLAST V3, V2, V1
|
||||
|
||||
// Vector AES subbytes, VX-form
|
||||
// <MNEMONIC> VRA,VRT produces
|
||||
// <mnemonic> VRT,VRA
|
||||
VSBOX V2, V1
|
||||
|
||||
// Vector SHA, VX-form with ST bit field and 4-bit SIX field
|
||||
// <MNEMONIC> SIX,VRA,ST,VRT produces
|
||||
// <mnemonic> VRT,VRA,ST,SIX
|
||||
VSHASIGMAW $15, V1, $1, V0
|
||||
VSHASIGMAD $15, V1, $1, V0
|
||||
|
||||
// VSX instructions
|
||||
// Described as:
|
||||
// <instruction type>, <instruction format>
|
||||
// <go asm operand order> produces
|
||||
// <Power ISA operand order>
|
||||
|
||||
// VSX load, XX1-form
|
||||
// <MNEMONIC> (RB)(RA*1),XT produces
|
||||
// <mnemonic> XT,RA,RB
|
||||
LXVD2X (R1)(R2*1), VS0
|
||||
LXVDSX (R1)(R2*1), VS0
|
||||
LXVW4X (R1)(R2*1), VS0
|
||||
LXSDX (R1)(R2*1), VS0
|
||||
LXSIWAX (R1)(R2*1), VS0
|
||||
LXSIWZX (R1)(R2*1), VS0
|
||||
|
||||
// VSX store, XX1-form
|
||||
// <MNEMONIC> XS,(RB)(RA*1) produces
|
||||
// <mnemonic> XS,RA,RB
|
||||
STXVD2X VS63, (R1)(R2*1)
|
||||
STXVW4X VS63, (R1)(R2*1)
|
||||
STXSDX VS63, (R1)(R2*1)
|
||||
STXSIWX VS63, (R1)(R2*1)
|
||||
|
||||
// VSX move from VSR, XX1-form
|
||||
// <MNEMONIC> XS,RA produces
|
||||
// <mnemonic> RA,XS
|
||||
MFVSRD VS0, R1
|
||||
MFVSRWZ VS33, R1
|
||||
|
||||
// VSX move to VSR, XX1-form
|
||||
// <MNEMONIC> RA,XT produces
|
||||
// <mnemonic> XT,RA
|
||||
MTVSRD R1, VS0
|
||||
MTVSRWA R1, VS31
|
||||
MTVSRWZ R1, VS63
|
||||
|
||||
// VSX AND, XX3-form
|
||||
// <MNEMONIC> XA,XB,XT produces
|
||||
// <mnemonic> XT,XA,XB
|
||||
XXLANDQ VS0,VS1,VS32
|
||||
XXLANDC VS0,VS1,VS32
|
||||
XXLEQV VS0,VS1,VS32
|
||||
XXLNAND VS0,VS1,VS32
|
||||
|
||||
// VSX OR, XX3-form
|
||||
// <MNEMONIC> XA,XB,XT produces
|
||||
// <mnemonic> XT,XA,XB
|
||||
XXLORC VS0,VS1,VS32
|
||||
XXLNOR VS0,VS1,VS32
|
||||
XXLORQ VS0,VS1,VS32
|
||||
XXLXOR VS0,VS1,VS32
|
||||
|
||||
// VSX select, XX4-form
|
||||
// <MNEMONIC> XA,XB,XC,XT produces
|
||||
// <mnemonic> XT,XA,XB,XC
|
||||
XXSEL VS0,VS1,VS3,VS32
|
||||
|
||||
// VSX merge, XX3-form
|
||||
// <MNEMONIC> XA,XB,XT produces
|
||||
// <mnemonic> XT,XA,XB
|
||||
XXMRGHW VS0,VS1,VS32
|
||||
XXMRGLW VS0,VS1,VS32
|
||||
|
||||
// VSX splat, XX2-form
|
||||
// <MNEMONIC> XB,UIM,XT produces
|
||||
// <mnemonic> XT,XB,UIM
|
||||
XXSPLTW VS0,$3,VS32
|
||||
|
||||
// VSX permute, XX3-form
|
||||
// <MNEMONIC> XA,XB,DM,XT produces
|
||||
// <mnemonic> XT,XA,XB,DM
|
||||
XXPERMDI VS0,VS1,$3,VS32
|
||||
|
||||
// VSX shift, XX3-form
|
||||
// <MNEMONIC> XA,XB,SHW,XT produces
|
||||
// <mnemonic> XT,XA,XB,SHW
|
||||
XXSLDWI VS0,VS1,$3,VS32
|
||||
|
||||
// VSX scalar FP-FP conversion, XX2-form
|
||||
// <MNEMONIC> XB,XT produces
|
||||
// <mnemonic> XT,XB
|
||||
XSCVDPSP VS0,VS32
|
||||
XSCVSPDP VS0,VS32
|
||||
XSCVDPSPN VS0,VS32
|
||||
XSCVSPDPN VS0,VS32
|
||||
|
||||
// VSX vector FP-FP conversion, XX2-form
|
||||
// <MNEMONIC> XB,XT produces
|
||||
// <mnemonic> XT,XB
|
||||
XVCVDPSP VS0,VS32
|
||||
XVCVSPDP VS0,VS32
|
||||
|
||||
// VSX scalar FP-integer conversion, XX2-form
|
||||
// <MNEMONIC> XB,XT produces
|
||||
// <mnemonic> XT,XB
|
||||
XSCVDPSXDS VS0,VS32
|
||||
XSCVDPSXWS VS0,VS32
|
||||
XSCVDPUXDS VS0,VS32
|
||||
XSCVDPUXWS VS0,VS32
|
||||
|
||||
// VSX scalar integer-FP conversion, XX2-form
|
||||
// <MNEMONIC> XB,XT produces
|
||||
// <mnemonic> XT,XB
|
||||
XSCVSXDDP VS0,VS32
|
||||
XSCVUXDDP VS0,VS32
|
||||
XSCVSXDSP VS0,VS32
|
||||
XSCVUXDSP VS0,VS32
|
||||
|
||||
// VSX vector FP-integer conversion, XX2-form
|
||||
// <MNEMONIC> XB,XT produces
|
||||
// <mnemonic> XT,XB
|
||||
XVCVDPSXDS VS0,VS32
|
||||
XVCVDPSXWS VS0,VS32
|
||||
XVCVDPUXDS VS0,VS32
|
||||
XVCVDPUXWS VS0,VS32
|
||||
XVCVSPSXDS VS0,VS32
|
||||
XVCVSPSXWS VS0,VS32
|
||||
XVCVSPUXDS VS0,VS32
|
||||
XVCVSPUXWS VS0,VS32
|
||||
|
||||
// VSX scalar integer-FP conversion, XX2-form
|
||||
// <MNEMONIC> XB,XT produces
|
||||
// <mnemonic> XT,XB
|
||||
XVCVSXDDP VS0,VS32
|
||||
XVCVSXWDP VS0,VS32
|
||||
XVCVUXDDP VS0,VS32
|
||||
XVCVUXWDP VS0,VS32
|
||||
XVCVSXDSP VS0,VS32
|
||||
XVCVSXWSP VS0,VS32
|
||||
XVCVUXDSP VS0,VS32
|
||||
XVCVUXWSP VS0,VS32
|
||||
|
||||
//
|
||||
// NOP
|
||||
//
|
||||
|
||||
148
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
148
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
@@ -13,13 +13,6 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
|
||||
MOVDBR R1, R2 // b90f0021
|
||||
MOVWBR R3, R4 // b91f0043
|
||||
|
||||
MOVDEQ R0, R1 // b9e28010
|
||||
MOVDGE R2, R3 // b9e2a032
|
||||
MOVDGT R4, R5 // b9e22054
|
||||
MOVDLE R6, R7 // b9e2c076
|
||||
MOVDLT R8, R9 // b9e24098
|
||||
MOVDNE R10, R11 // b9e270ba
|
||||
|
||||
MOVD (R15), R1 // e310f0000004
|
||||
MOVW (R15), R2 // e320f0000014
|
||||
MOVH (R15), R3 // e330f0000015
|
||||
@@ -52,34 +45,24 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
|
||||
|
||||
ADD R1, R2 // b9e81022
|
||||
ADD R1, R2, R3 // b9e81032
|
||||
ADD $8192, R1 // a71b2000
|
||||
ADD $8192, R1 // c21800002000
|
||||
ADD $8192, R1, R2 // ec21200000d9
|
||||
ADD $32768, R1 // c21800008000
|
||||
ADD $32768, R1, R2 // b9040021c22800008000
|
||||
ADDC R1, R2 // b9ea1022
|
||||
ADDC $1, R1, R2 // ec21000100db
|
||||
ADDC $1, R1, R2 // b9040021c22a00000001
|
||||
ADDC R1, R2, R3 // b9ea1032
|
||||
ADDW R1, R2 // 1a21
|
||||
ADDW R1, R2, R3 // b9f81032
|
||||
ADDW $8192, R1 // a71a2000
|
||||
ADDW $8192, R1, R2 // ec21200000d8
|
||||
SUB R3, R4 // b9090043
|
||||
SUB R3, R4, R5 // b9e93054
|
||||
SUB $8192, R3 // a73be000
|
||||
SUB $8192, R3 // c238ffffe000
|
||||
SUB $8192, R3, R4 // ec43e00000d9
|
||||
SUBC R1, R2 // b90b0021
|
||||
SUBC $1, R1, R2 // ec21ffff00db
|
||||
SUBC $1, R1, R2 // b9040021c22affffffff
|
||||
SUBC R2, R3, R4 // b9eb2043
|
||||
SUBW R3, R4 // 1b43
|
||||
SUBW R3, R4, R5 // b9f93054
|
||||
SUBW $8192, R1 // c21500002000
|
||||
SUBW $8192, R1, R2 // 1821c22500002000
|
||||
MULLW R6, R7 // b91c0076
|
||||
MULLW R6, R7, R8 // b9040087b91c0086
|
||||
MULLW $8192, R6 // a76c2000
|
||||
MULLW $8192, R6, R7 // 1876a77c2000
|
||||
MULLW $-32769, R8 // c281ffff7fff
|
||||
MULLW $-32769, R8, R9 // 1898c291ffff7fff
|
||||
MULLW $8192, R6 // a76d2000
|
||||
MULLW $8192, R6, R7 // b9040076a77d2000
|
||||
MULLW $-65537, R8 // c280fffeffff
|
||||
MULLW $-65537, R8, R9 // b9040098c290fffeffff
|
||||
MULLD $-2147483648, R1 // c21080000000
|
||||
MULLD $-2147483648, R1, R2 // b9040021c22080000000
|
||||
MULHD R9, R8 // b90400b8b98600a9ebb9003f000ab98000b8b90900abebb8003f000ab98000b9b9e9b08a
|
||||
@@ -90,99 +73,10 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
|
||||
DIVD R1, R2, R3 // b90400b2b90d00a1b904003b
|
||||
DIVW R4, R5 // b90400b5b91d00a4b904005b
|
||||
DIVW R4, R5, R6 // b90400b5b91d00a4b904006b
|
||||
DIVDU R7, R8 // a7a90000b90400b8b98700a7b904008b
|
||||
DIVDU R7, R8, R9 // a7a90000b90400b8b98700a7b904009b
|
||||
DIVWU R1, R2 // a7a90000b90400b2b99700a1b904002b
|
||||
DIVWU R1, R2, R3 // a7a90000b90400b2b99700a1b904003b
|
||||
MODD R1, R2 // b90400b2b90d00a1b904002a
|
||||
MODD R1, R2, R3 // b90400b2b90d00a1b904003a
|
||||
MODW R4, R5 // b90400b5b91d00a4b904005a
|
||||
MODW R4, R5, R6 // b90400b5b91d00a4b904006a
|
||||
MODDU R7, R8 // a7a90000b90400b8b98700a7b904008a
|
||||
MODDU R7, R8, R9 // a7a90000b90400b8b98700a7b904009a
|
||||
MODWU R1, R2 // a7a90000b90400b2b99700a1b904002a
|
||||
MODWU R1, R2, R3 // a7a90000b90400b2b99700a1b904003a
|
||||
NEG R1 // b9030011
|
||||
NEG R1, R2 // b9030021
|
||||
NEGW R1 // b9130011
|
||||
NEGW R1, R2 // b9130021
|
||||
FLOGR R2, R2 // b9830022
|
||||
|
||||
AND R1, R2 // b9800021
|
||||
AND R1, R2, R3 // b9e42031
|
||||
AND $-2, R1 // a517fffe
|
||||
AND $-65536, R1 // c01bffff0000
|
||||
AND $1, R1 // c0a100000001b980001a
|
||||
ANDW R1, R2 // 1421
|
||||
ANDW R1, R2, R3 // b9f42031
|
||||
ANDW $1, R1 // c01b00000001
|
||||
ANDW $131071, R1 // a5160001
|
||||
ANDW $65536, R1 // c01b00010000
|
||||
ANDW $-2, R1 // a517fffe
|
||||
OR R1, R2 // b9810021
|
||||
OR R1, R2, R3 // b9e62031
|
||||
OR $1, R1 // a51b0001
|
||||
OR $131071, R1 // c01d0001ffff
|
||||
OR $65536, R1 // c01d00010000
|
||||
OR $-2, R1 // c0a1fffffffeb981001a
|
||||
ORW R1, R2 // 1621
|
||||
ORW R1, R2, R3 // b9f62031
|
||||
ORW $1, R1 // a51b0001
|
||||
ORW $131071, R1 // c01d0001ffff
|
||||
ORW $65536, R1 // a51a0001
|
||||
ORW $-2, R1 // c01dfffffffe
|
||||
XOR R1, R2 // b9820021
|
||||
XOR R1, R2, R3 // b9e72031
|
||||
XOR $1, R1 // c01700000001
|
||||
XOR $131071, R1 // c0170001ffff
|
||||
XOR $65536, R1 // c01700010000
|
||||
XOR $-2, R1 // c0a1fffffffeb982001a
|
||||
XORW R1, R2 // 1721
|
||||
XORW R1, R2, R3 // b9f72031
|
||||
XORW $1, R1 // c01700000001
|
||||
XORW $131071, R1 // c0170001ffff
|
||||
XORW $65536, R1 // c01700010000
|
||||
XORW $-2, R1 // c017fffffffe
|
||||
|
||||
ADD -524288(R1), R2 // e32010008008
|
||||
ADD 524287(R3), R4 // e3403fff7f08
|
||||
ADD -524289(R1), R2 // c0a1fff7ffffe32a10000008
|
||||
ADD 524288(R3), R4 // c0a100080000e34a30000008
|
||||
ADD -524289(R1)(R2*1), R3 // c0a1fff7ffff41aa2000e33a10000008
|
||||
ADD 524288(R3)(R4*1), R5 // c0a10008000041aa4000e35a30000008
|
||||
ADDC (R1), R2 // e3201000000a
|
||||
ADDW (R5), R6 // 5a605000
|
||||
ADDW 4095(R7), R8 // 5a807fff
|
||||
ADDW -1(R1), R2 // e3201fffff5a
|
||||
ADDW 4096(R3), R4 // e3403000015a
|
||||
MULLD (R1)(R2*1), R3 // e3321000000c
|
||||
MULLW (R3)(R4*1), R5 // 71543000
|
||||
MULLW 4096(R3), R4 // e34030000151
|
||||
SUB (R1), R2 // e32010000009
|
||||
SUBC (R1), R2 // e3201000000b
|
||||
SUBE (R1), R2 // e32010000089
|
||||
SUBW (R1), R2 // 5b201000
|
||||
SUBW -1(R1), R2 // e3201fffff5b
|
||||
AND (R1), R2 // e32010000080
|
||||
ANDW (R1), R2 // 54201000
|
||||
ANDW -1(R1), R2 // e3201fffff54
|
||||
OR (R1), R2 // e32010000081
|
||||
ORW (R1), R2 // 56201000
|
||||
ORW -1(R1), R2 // e3201fffff56
|
||||
XOR (R1), R2 // e32010000082
|
||||
XORW (R1), R2 // 57201000
|
||||
XORW -1(R1), R2 // e3201fffff57
|
||||
|
||||
LAA R1, R2, 524287(R3) // eb213fff7ff8
|
||||
LAAG R4, R5, -524288(R6) // eb54600080e8
|
||||
LAAL R7, R8, 8192(R9) // eb87900002fa
|
||||
LAALG R10, R11, -8192(R12) // ebbac000feea
|
||||
LAN R1, R2, (R3) // eb21300000f4
|
||||
LANG R4, R5, (R6) // eb54600000e4
|
||||
LAX R7, R8, (R9) // eb87900000f7
|
||||
LAXG R10, R11, (R12) // ebbac00000e7
|
||||
LAO R1, R2, (R3) // eb21300000f6
|
||||
LAOG R4, R5, (R6) // eb54600000e6
|
||||
DIVDU R7, R8 // b90400a0b90400b8b98700a7b904008b
|
||||
DIVDU R7, R8, R9 // b90400a0b90400b8b98700a7b904009b
|
||||
DIVWU R1, R2 // b90400a0b90400b2b99700a1b904002b
|
||||
DIVWU R1, R2, R3 // b90400a0b90400b2b99700a1b904003b
|
||||
|
||||
XC $8, (R15), n-8(SP) // XC (R15), $8, n-8(SP) // d707f010f000
|
||||
NC $8, (R15), n-8(SP) // NC (R15), $8, n-8(SP) // d407f010f000
|
||||
@@ -193,14 +87,10 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
|
||||
MVC $256, 8192(R1), 8192(R2) // MVC 8192(R1), $256, 8192(R2) // b90400a2c2a800002000b90400b1c2b800002000d2ffa000b000
|
||||
|
||||
CMP R1, R2 // b9200012
|
||||
CMP R3, $32767 // a73f7fff
|
||||
CMP R3, $32768 // c23c00008000
|
||||
CMP R3, $-2147483648 // c23c80000000
|
||||
CMPU R4, R5 // b9210045
|
||||
CMPU R6, $4294967295 // c26effffffff
|
||||
CMPW R7, R8 // 1978
|
||||
CMPW R9, $-32768 // a79e8000
|
||||
CMPW R9, $-32769 // c29dffff7fff
|
||||
CMPW R9, $-2147483648 // c29d80000000
|
||||
CMPWU R1, R2 // 1512
|
||||
CMPWU R3, $4294967295 // c23fffffffff
|
||||
@@ -211,8 +101,6 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
|
||||
BLE 0(PC) // a7c40000
|
||||
BGT 0(PC) // a7240000
|
||||
BGE 0(PC) // a7a40000
|
||||
BLTU 0(PC) // a7540000
|
||||
BLEU 0(PC) // a7d40000
|
||||
|
||||
CMPBNE R1, R2, 0(PC) // ec1200007064
|
||||
CMPBEQ R3, R4, 0(PC) // ec3400008064
|
||||
@@ -279,8 +167,6 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
|
||||
FABS F1, F2 // b3100021
|
||||
FSQRTS F3, F4 // b3140043
|
||||
FSQRT F5, F15 // b31500f5
|
||||
FIEBR $0, F0, F1 // b3570010
|
||||
FIDBR $7, F2, F3 // b35f7032
|
||||
|
||||
VL (R15), V1 // e710f0000006
|
||||
VST V1, (R15) // e710f000000e
|
||||
@@ -323,17 +209,9 @@ TEXT main·foo(SB),7,$16-0 // TEXT main.foo(SB), 7, $16-0
|
||||
VERIMB $2, V31, V1, V2 // VERIMB V31, V1, $2, V2 // e72f10020472
|
||||
VSEL V1, V2, V3, V4 // VSEL V2, V3, V1, V4 // e7412000308d
|
||||
VGFMAH V21, V31, V24, V0 // VGFMAH V31, V24, V21, V0 // e705f10087bc
|
||||
VFMADB V16, V8, V9, V10 // VFMADB V8, V9, V16, V10 // e7a08300948f
|
||||
WFMADB V17, V18, V19, V20 // WFMADB V18, V19, V17, V20 // e74123083f8f
|
||||
VFMSDB V2, V25, V24, V31 // VFMSDB V25, V24, V2, V31 // e7f293008b8e
|
||||
WFMSDB V31, V2, V3, V4 // WFMSDB V2, V3, V31, V4 // e74f2308348e
|
||||
WFMSDB V2, V25, V24, V31 // WFMSDB V25, V24, V2, V31 // e7f298038b8e
|
||||
VPERM V31, V0, V2, V3 // VPERM V0, V2, V31, V3 // e73f0000248c
|
||||
VPDI $1, V2, V31, V1 // VPDI V2, V31, $1, V1 // e712f0001284
|
||||
VLEG $1, (R3), V1 // VLEG (R3), $1, V1 // e71030001002
|
||||
VLEF $2, (R0), V31 // VLEF (R0), $2, V31 // e7f000002803
|
||||
VLEH $3, (R12), V16 // VLEH (R12), $3, V16 // e700c0003801
|
||||
VLEB $15, 4095(R9), V15 // VLEB 4095(R9), $15, V15 // e7f09ffff000
|
||||
|
||||
|
||||
RET
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
var (
|
||||
Debug = flag.Bool("debug", false, "dump instructions as they are parsed")
|
||||
OutputFile = flag.String("o", "", "output file; default foo.o for /a/b/c/foo.s as first argument")
|
||||
OutputFile = flag.String("o", "", "output file; default foo.6 for /a/b/c/foo.s on amd64")
|
||||
PrintOut = flag.Bool("S", false, "print assembly and machine code")
|
||||
TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths")
|
||||
Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library")
|
||||
@@ -49,7 +49,7 @@ func (m *MultiFlag) Set(val string) error {
|
||||
}
|
||||
|
||||
func Usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: asm [options] file.s ...\n")
|
||||
fmt.Fprintf(os.Stderr, "usage: asm [options] file.s\n")
|
||||
fmt.Fprintf(os.Stderr, "Flags:\n")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(2)
|
||||
@@ -58,15 +58,12 @@ func Usage() {
|
||||
func Parse() {
|
||||
flag.Usage = Usage
|
||||
flag.Parse()
|
||||
if flag.NArg() == 0 {
|
||||
if flag.NArg() != 1 {
|
||||
flag.Usage()
|
||||
}
|
||||
|
||||
// Flag refinement.
|
||||
if *OutputFile == "" {
|
||||
if flag.NArg() != 1 {
|
||||
flag.Usage()
|
||||
}
|
||||
input := filepath.Base(flag.Arg(0))
|
||||
if strings.HasSuffix(input, ".s") {
|
||||
input = input[:len(input)-2]
|
||||
|
||||
@@ -24,7 +24,7 @@ func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("asm: ")
|
||||
|
||||
GOARCH := obj.GOARCH
|
||||
GOARCH := obj.Getgoarch()
|
||||
|
||||
architecture := arch.Set(GOARCH)
|
||||
if architecture == nil {
|
||||
@@ -51,36 +51,25 @@ func main() {
|
||||
defer bio.MustClose(out)
|
||||
buf := bufio.NewWriter(bio.MustWriter(out))
|
||||
|
||||
fmt.Fprintf(buf, "go object %s %s %s\n", obj.GOOS, obj.GOARCH, obj.Version)
|
||||
fmt.Fprintf(buf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion())
|
||||
fmt.Fprintf(buf, "!\n")
|
||||
|
||||
var ok, diag bool
|
||||
var failedFile string
|
||||
for _, f := range flag.Args() {
|
||||
lexer := lex.NewLexer(f, ctxt)
|
||||
parser := asm.NewParser(ctxt, architecture, lexer)
|
||||
ctxt.DiagFunc = func(format string, args ...interface{}) {
|
||||
diag = true
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
pList := obj.Linknewplist(ctxt)
|
||||
pList.Firstpc, ok = parser.Parse()
|
||||
if !ok {
|
||||
failedFile = f
|
||||
break
|
||||
}
|
||||
lexer := lex.NewLexer(flag.Arg(0), ctxt)
|
||||
parser := asm.NewParser(ctxt, architecture, lexer)
|
||||
diag := false
|
||||
ctxt.DiagFunc = func(format string, args ...interface{}) {
|
||||
diag = true
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
pList := obj.Linknewplist(ctxt)
|
||||
var ok bool
|
||||
pList.Firstpc, ok = parser.Parse()
|
||||
if ok {
|
||||
// reports errors to parser.Errorf
|
||||
obj.Writeobjdirect(ctxt, buf)
|
||||
}
|
||||
if !ok || diag {
|
||||
if failedFile != "" {
|
||||
log.Printf("assembly of %s failed", failedFile)
|
||||
} else {
|
||||
log.Print("assembly failed")
|
||||
}
|
||||
out.Close()
|
||||
log.Printf("assembly of %s failed", flag.Arg(0))
|
||||
os.Remove(*flags.OutputFile)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user